]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - Vlnk/src/main_windows.c
Merge branch 'master' of https://github.com/Ventoy/Ventoy
[Ventoy.git] / Vlnk / src / main_windows.c
index 064604058723a847847cb375fc90aaa32382d232..bf9f8af402a0acfc9432e63e72e85b9b26b3cb49 100644 (file)
@@ -1,4 +1,4 @@
-#include <Windows.h>\r
+#include <Windows.h>\r
 #include <stdio.h>\r
 #include <stdlib.h>\r
 #include <string.h>\r
@@ -14,6 +14,7 @@ static HWND g_create_button;
 static HWND g_parse_button;\r
 \r
 static BOOL g_ShowHelp = FALSE;\r
+static BOOL g_SaveAs = FALSE;\r
 static WCHAR g_CmdInFile[MAX_PATH];\r
 static WCHAR g_CmdOutFile[MAX_PATH];\r
 \r
@@ -36,6 +37,7 @@ typedef enum MSGID
     MSGID_VLNK_POINT_TO,\r
     MSGID_VLNK_NO_DST,\r
     MSGID_FILE_NAME_TOO_LONG,\r
+    MSGID_INVALID_SUFFIX,\r
 \r
     MSGID_BUTT\r
 }MSGID;\r
@@ -43,23 +45,24 @@ typedef enum MSGID
 \r
 const WCHAR *g_msg_cn[MSGID_BUTT] =\r
 {\r
-    L"´íÎó",\r
-       L"ÌáÐÑ",\r
-       L"´´½¨",\r
-       L"½âÎö",        \r
-    L"Ö¸¶¨µÄÎļþ²»´æÔÚ", \r
-    L"²»Ö§³ÖΪ´ËÎļþ´´½¨vlnk",\r
-    L"²»Ö§³ÖµÄÎļþϵͳ",\r
-    L"²»Ö§³ÖµÄÎļþºó׺Ãû",\r
-    L"»ñÈ¡´ÅÅÌÐÅϢʱ·¢Éú´íÎó",\r
-    L"Vlnk Îļþ´´½¨³É¹¦¡£",\r
-    L"ÇëÏȹرÕÕýÔÚÔËÐеĠVentoyVlnk ³ÌÐò£¡",\r
-    L"´´½¨Îļþʧ°Ü",\r
-    L"´ËÎļþÒѾ­ÊÇÒ»¸övlnkÎļþÁË£¡",\r
-    L"·Ç·¨µÄvlnkÎļþ!",\r
-    L"´Ë vlnk ÎļþÖ¸Ïò ",\r
-    L"´Ë vlnk Ö¸ÏòµÄÎļþ²»´æÔÚ£¡",\r
-    L"Îļþ·¾¶Ì«³¤£¡",\r
+    L"错误",\r
+       L"提醒",\r
+       L"创建",\r
+       L"解析",      \r
+    L"指定的文件不存在", \r
+    L"不支持为此文件创建vlnk",\r
+    L"不支持的文件系统",\r
+    L"不支持的文件后缀名",\r
+    L"获取磁盘信息时发生错误",\r
+    L"Vlnk 文件创建成功。",\r
+    L"请先关闭正在运行的 VentoyVlnk 程序!",\r
+    L"创建文件失败",\r
+    L"此文件已经是一个vlnk文件了!",\r
+    L"非法的vlnk文件!",\r
+    L"此 vlnk 文件指向 ",\r
+    L"此 vlnk 指向的文件不存在!",\r
+    L"文件路径太长!",\r
+    L"非法的vlnk文件后缀名!",\r
 };\r
 const WCHAR *g_msg_en[MSGID_BUTT] =\r
 {\r
@@ -80,6 +83,7 @@ const WCHAR *g_msg_en[MSGID_BUTT] =
     L"The vlnk file point to ",\r
     L"The file pointed by the vlnk does NOT exist!",\r
     L"The file full path is too long!",\r
+    L"Invalid vlnk file suffix!",\r
 };\r
 \r
 const WCHAR **g_msg_lang = NULL;\r
@@ -101,62 +105,62 @@ static int VtoyMessageBox
 \r
     return MessageBox(hWnd, lpText, lpCaption, uType);\r
 }\r
-
-static void Log2File(const char *log)
-{
-    time_t stamp;
-    struct tm ttm;
-    FILE *fp;
-
-    time(&stamp);
-    localtime_s(&ttm, &stamp);
-
-    fopen_s(&fp, g_LogFile, "a+");
-    if (fp)
-    {
-        fprintf_s(fp, "[%04u/%02u/%02u %02u:%02u:%02u] %s",
-            ttm.tm_year + 1900, ttm.tm_mon + 1, ttm.tm_mday,
-            ttm.tm_hour, ttm.tm_min, ttm.tm_sec, log);
-        fclose(fp);
-    }
-}
-
-void LogW(const WCHAR *Fmt, ...)
-{
-    WCHAR log[512];
-    CHAR  alog[2048];
-    va_list arg;
-
-    if (g_LogFile[0] == 0)
-    {
-        return;
-    }
-
-    va_start(arg, Fmt);
-    vswprintf_s(log, 512, Fmt, arg);
-    va_end(arg);
-
-    WideCharToMultiByte(CP_UTF8, 0, log, -1, alog, 2048, 0, 0);
-
-    Log2File(alog);
+\r
+static void Log2File(const char *log)\r
+{\r
+    time_t stamp;\r
+    struct tm ttm;\r
+    FILE *fp;\r
+\r
+    time(&stamp);\r
+    localtime_s(&ttm, &stamp);\r
+\r
+    fopen_s(&fp, g_LogFile, "a+");\r
+    if (fp)\r
+    {\r
+        fprintf_s(fp, "[%04u/%02u/%02u %02u:%02u:%02u] %s",\r
+            ttm.tm_year + 1900, ttm.tm_mon + 1, ttm.tm_mday,\r
+            ttm.tm_hour, ttm.tm_min, ttm.tm_sec, log);\r
+        fclose(fp);\r
+    }\r
 }\r
 \r
-
-void LogA(const CHAR *Fmt, ...)
-{
-    CHAR log[512];
-    va_list arg;
-
-    if (g_LogFile[0] == 0)
-    {
-        return;
-    }
-
-    va_start(arg, Fmt);
-    vsprintf_s(log, 512, Fmt, arg);
-    va_end(arg);
-
-    Log2File(log);
+void LogW(const WCHAR *Fmt, ...)\r
+{\r
+    WCHAR log[512];\r
+    CHAR  alog[2048];\r
+    va_list arg;\r
+\r
+    if (g_LogFile[0] == 0)\r
+    {\r
+        return;\r
+    }\r
+\r
+    va_start(arg, Fmt);\r
+    vswprintf_s(log, 512, Fmt, arg);\r
+    va_end(arg);\r
+\r
+    WideCharToMultiByte(CP_UTF8, 0, log, -1, alog, 2048, 0, 0);\r
+\r
+    Log2File(alog);\r
+}\r
+\r
+\r
+void LogA(const CHAR *Fmt, ...)\r
+{\r
+    CHAR log[512];\r
+    va_list arg;\r
+\r
+    if (g_LogFile[0] == 0)\r
+    {\r
+        return;\r
+    }\r
+\r
+    va_start(arg, Fmt);\r
+    vsprintf_s(log, 512, Fmt, arg);\r
+    va_end(arg);\r
+\r
+    Log2File(log);\r
 }\r
 \r
 static int Utf8ToUtf16(const char* src, WCHAR * dst)\r
@@ -363,11 +367,62 @@ End:
 }\r
 \r
 \r
+static BOOL VentoyGetSaveFileName(HWND hWnd, WCHAR *szFile)\r
+{\r
+    OPENFILENAME ofn = { 0 };\r
+\r
+    ofn.lStructSize = sizeof(ofn);\r
+    ofn.hwndOwner = hWnd;\r
+    ofn.lpstrFilter = L"Vlnk File\0*.vlnk.iso;*.vlnk.img;*.vlnk.wim;*.vlnk.efi;*.vlnk.vhd;*.vlnk.vhdx;*.vlnk.vtoy;*.vlnk.dat\0";\r
+    ofn.nFilterIndex = 1;\r
+    ofn.lpstrFile = szFile;\r
+    ofn.nMaxFile = MAX_PATH;\r
+    ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;\r
+    ofn.lpstrFileTitle = NULL;\r
+    ofn.nMaxFileTitle = 0;\r
+    ofn.lpstrInitialDir = NULL;\r
+\r
+    return GetSaveFileName(&ofn);\r
+}\r
+\r
+static BOOL IsSupportedVlnkSuffix(WCHAR *FileName)\r
+{\r
+    int len;\r
+\r
+    len = lstrlen(FileName);\r
+\r
+    if (len > 9)\r
+    {\r
+        if (lstrcmp(FileName + len - 9, L".vlnk.iso") == 0 ||\r
+            lstrcmp(FileName + len - 9, L".vlnk.img") == 0 ||\r
+            lstrcmp(FileName + len - 9, L".vlnk.wim") == 0 ||\r
+            lstrcmp(FileName + len - 9, L".vlnk.vhd") == 0 ||\r
+            lstrcmp(FileName + len - 9, L".vlnk.efi") == 0 ||\r
+            lstrcmp(FileName + len - 9, L".vlnk.dat") == 0)\r
+        {\r
+            return TRUE;\r
+        }\r
+    }\r
+\r
+\r
+    if (len > 10)\r
+    {\r
+        if (lstrcmp(FileName + len - 10, L".vlnk.vhdx") == 0 ||\r
+            lstrcmp(FileName + len - 10, L".vlnk.vtoy") == 0)\r
+        {\r
+            return TRUE;\r
+        }\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
 static int CreateVlnk(HWND hWnd, WCHAR *Dir, WCHAR *InFile, WCHAR *OutFile)\r
 {\r
     int i;\r
     int end;\r
     int len;\r
+    BOOL SetOutFile = FALSE;\r
     UINT32 DiskSig;\r
     DISK_EXTENT DiskExtend;\r
     OPENFILENAME ofn = { 0 };\r
@@ -500,6 +555,7 @@ static int CreateVlnk(HWND hWnd, WCHAR *Dir, WCHAR *InFile, WCHAR *OutFile)
         return 1;\r
     }\r
 \r
+\r
     Buf = malloc(VLNK_FILE_LEN);\r
     if (Buf)\r
     {\r
@@ -510,10 +566,34 @@ static int CreateVlnk(HWND hWnd, WCHAR *Dir, WCHAR *InFile, WCHAR *OutFile)
         if (OutFile)\r
         {\r
             wcscpy_s(DstFullPath, MAX_PATH, OutFile);\r
+            SetOutFile = TRUE;\r
         }\r
         else\r
         {\r
             DefaultVlnkDstFullPath(Pos + 1, Dir, DstFullPath);\r
+\r
+            if (g_SaveAs)\r
+            {\r
+                wcscpy_s(szFile, MAX_PATH, DstFullPath);\r
+                if (VentoyGetSaveFileName(hWnd, szFile))\r
+                {\r
+                    if (IsSupportedVlnkSuffix(szFile))\r
+                    {\r
+                        wcscpy_s(DstFullPath, MAX_PATH, szFile);\r
+                        SetOutFile = TRUE;\r
+                    }\r
+                    else\r
+                    {\r
+                        VtoyMessageBox(hWnd, g_msg_lang[MSGID_INVALID_SUFFIX], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+                        LogA("Invalid vlnk suffix\n");\r
+                        goto end;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    LogA("User cancel the save as diaglog, use default name\n");\r
+                }\r
+            }\r
         }\r
 \r
         LogW(L"vlnk output file path is <%ls>\n", DstFullPath);\r
@@ -524,7 +604,7 @@ static int CreateVlnk(HWND hWnd, WCHAR *Dir, WCHAR *InFile, WCHAR *OutFile)
 \r
             LogW(L"Vlnk file create success <%ls>\n", DstFullPath);\r
 \r
-            if (OutFile)\r
+            if (SetOutFile)\r
             {\r
                 swprintf_s(Msg, 1024, L"%ls\r\n\r\n%ls", g_msg_lang[MSGID_VLNK_SUCCESS], DstFullPath);\r
                 VtoyMessageBox(hWnd, Msg, g_msg_lang[MSGID_INFO], MB_OK | MB_ICONINFORMATION);\r
@@ -541,6 +621,7 @@ static int CreateVlnk(HWND hWnd, WCHAR *Dir, WCHAR *InFile, WCHAR *OutFile)
             VtoyMessageBox(hWnd, g_msg_lang[MSGID_CREATE_FILE_ERR], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         }\r
 \r
+        end:\r
         free(Buf);\r
     }\r
 \r
@@ -580,7 +661,6 @@ static CHAR GetDriveLetter(UINT32 disksig, UINT64 PartOffset)
     return 0;\r
 }\r
 \r
-\r
 static int ParseVlnk(HWND hWnd)\r
 {\r
     int i;\r
@@ -728,6 +808,10 @@ static int ParseCmdLine(LPSTR lpCmdLine)
         {\r
             g_ShowHelp = TRUE;\r
         }\r
+        else if (lstrcmp(lpszArgv[i], L"-s") == 0 || lstrcmp(lpszArgv[i], L"-S") == 0)\r
+        {\r
+            g_SaveAs = TRUE;\r
+        }\r
         else if (lstrcmp(lpszArgv[i], L"-i") == 0 || lstrcmp(lpszArgv[i], L"-I") == 0)\r
         {\r
             if (i + 1 < argc)\r
@@ -747,6 +831,59 @@ static int ParseCmdLine(LPSTR lpCmdLine)
     return argc;\r
 }\r
 \r
+\r
+//\r
+//copy from Rufus\r
+//Copyright © 2011-2021 Pete Batard <pete@akeo.ie>\r
+//\r
+#include <delayimp.h>\r
+// For delay-loaded DLLs, use LOAD_LIBRARY_SEARCH_SYSTEM32 to avoid DLL search order hijacking.\r
+FARPROC WINAPI dllDelayLoadHook(unsigned dliNotify, PDelayLoadInfo pdli)\r
+{\r
+    if (dliNotify == dliNotePreLoadLibrary) {\r
+        // Windows 7 without KB2533623 does not support the LOAD_LIBRARY_SEARCH_SYSTEM32 flag.\r
+        // That is is OK, because the delay load handler will interrupt the NULL return value\r
+        // to mean that it should perform a normal LoadLibrary.\r
+        return (FARPROC)LoadLibraryExA(pdli->szDll, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);\r
+    }\r
+    return NULL;\r
+}\r
+\r
+#if defined(_MSC_VER)\r
+// By default the Windows SDK headers have a `const` while MinGW does not.\r
+const\r
+#endif\r
+PfnDliHook __pfnDliNotifyHook2 = dllDelayLoadHook;\r
+\r
+typedef BOOL(WINAPI *SetDefaultDllDirectories_t)(DWORD);\r
+static void DllProtect(void)\r
+{\r
+    SetDefaultDllDirectories_t pfSetDefaultDllDirectories = NULL;\r
+\r
+    // Disable loading system DLLs from the current directory (sideloading mitigation)\r
+    // PS: You know that official MSDN documentation for SetDllDirectory() that explicitly\r
+    // indicates that "If the parameter is an empty string (""), the call removes the current\r
+    // directory from the default DLL search order"? Yeah, that doesn't work. At all.\r
+    // Still, we invoke it, for platforms where the following call might actually work...\r
+    SetDllDirectoryA("");\r
+\r
+    // For libraries on the KnownDLLs list, the system will always load them from System32.\r
+    // For other DLLs we link directly to, we can delay load the DLL and use a delay load\r
+    // hook to load them from System32. Note that, for this to work, something like:\r
+    // 'somelib.dll;%(DelayLoadDLLs)' must be added to the 'Delay Loaded Dlls' option of\r
+    // the linker properties in Visual Studio (which means this won't work with MinGW).\r
+    // For all other DLLs, use SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32).\r
+    // Finally, we need to perform the whole gymkhana below, where we can't call on\r
+    // SetDefaultDllDirectories() directly, because Windows 7 doesn't have the API exposed.\r
+    // Also, no, Coverity, we never need to care about freeing kernel32 as a library.\r
+    // coverity[leaked_storage]\r
+\r
+    pfSetDefaultDllDirectories = (SetDefaultDllDirectories_t)\r
+        GetProcAddress(LoadLibraryW(L"kernel32.dll"), "SetDefaultDllDirectories");\r
+    if (pfSetDefaultDllDirectories != NULL)\r
+        pfSetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32);\r
+}\r
+\r
 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)\r
 {\r
     DWORD dwAttrib;\r
@@ -754,6 +891,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
 \r
     UNREFERENCED_PARAMETER(hPrevInstance);\r
 \r
+    DllProtect();\r
+\r
     if (GetUserDefaultUILanguage() == 0x0804)\r
     {\r
         g_msg_lang = g_msg_cn;\r
@@ -795,6 +934,13 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
             return 1;\r
         }\r
 \r
+        if (!IsSupportedVlnkSuffix(g_CmdOutFile))\r
+        {\r
+            LogW(L"File <<%ls>> contains invalid vlnk suffix!\n", g_CmdOutFile);\r
+            VtoyMessageBox(NULL, g_msg_lang[MSGID_INVALID_SUFFIX], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+            return 1;\r
+        }\r
+\r
         return CreateVlnk(NULL, g_CurDirW, g_CmdInFile, g_CmdOutFile);\r
     }\r
     else\r