]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - Vlnk/src/main_windows.c
1.1.07 release
[Ventoy.git] / Vlnk / src / main_windows.c
index 6596c29bec158f9692b0e5d008985265048f77b5..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
 #include <stdio.h>\r
 #include <stdlib.h>\r
 #include <string.h>\r
@@ -13,12 +13,18 @@ static CHAR g_LogFile[MAX_PATH];
 static HWND g_create_button;\r
 static HWND g_parse_button;\r
 \r
 static HWND g_create_button;\r
 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
 typedef enum MSGID\r
 {\r
     MSGID_ERROR = 0,\r
        MSGID_INFO,\r
        MSGID_BTN_CREATE,\r
        MSGID_BTN_PARSE,\r
 typedef enum MSGID\r
 {\r
     MSGID_ERROR = 0,\r
        MSGID_INFO,\r
        MSGID_BTN_CREATE,\r
        MSGID_BTN_PARSE,\r
+    MSGID_SRC_NONEXIST,\r
     MSGID_SRC_UNSUPPORTED,\r
     MSGID_FS_UNSUPPORTED,\r
     MSGID_SUFFIX_UNSUPPORTED,\r
     MSGID_SRC_UNSUPPORTED,\r
     MSGID_FS_UNSUPPORTED,\r
     MSGID_SUFFIX_UNSUPPORTED,\r
@@ -31,6 +37,7 @@ typedef enum MSGID
     MSGID_VLNK_POINT_TO,\r
     MSGID_VLNK_NO_DST,\r
     MSGID_FILE_NAME_TOO_LONG,\r
     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
 \r
     MSGID_BUTT\r
 }MSGID;\r
@@ -38,22 +45,24 @@ typedef enum MSGID
 \r
 const WCHAR *g_msg_cn[MSGID_BUTT] =\r
 {\r
 \r
 const WCHAR *g_msg_cn[MSGID_BUTT] =\r
 {\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
 };\r
 const WCHAR *g_msg_en[MSGID_BUTT] =\r
 {\r
@@ -61,6 +70,7 @@ const WCHAR *g_msg_en[MSGID_BUTT] =
        L"Info",   \r
        L"Create",\r
        L"Parse",\r
        L"Info",   \r
        L"Create",\r
        L"Parse",\r
+    L"The specified file is not exist!",\r
     L"This file is not supported for vlnk",\r
     L"Unsupported file system!", \r
     L"Unsupported file suffix!",\r
     L"This file is not supported for vlnk",\r
     L"Unsupported file system!", \r
     L"Unsupported file suffix!",\r
@@ -73,67 +83,84 @@ 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"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
 \r
 HINSTANCE g_hInst;\r
 };\r
 \r
 const WCHAR **g_msg_lang = NULL;\r
 \r
 HINSTANCE g_hInst;\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 int VtoyMessageBox\r
+(\r
+    _In_opt_ HWND hWnd,\r
+    _In_opt_ LPCWSTR lpText,\r
+    _In_opt_ LPCWSTR lpCaption,\r
+    _In_ UINT uType\r
+)\r
+{\r
+    if (g_CmdInFile[0] && g_CmdOutFile[0])\r
+    {\r
+        return 0;\r
+    }\r
+\r
+    return MessageBox(hWnd, lpText, lpCaption, uType);\r
+}\r
+\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
 }\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
 }\r
 \r
 static int Utf8ToUtf16(const char* src, WCHAR * dst)\r
@@ -340,11 +367,62 @@ End:
 }\r
 \r
 \r
 }\r
 \r
 \r
-static int CreateVlnk(HWND hWnd, WCHAR *Dir)\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
 {\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
     UINT32 DiskSig;\r
     DISK_EXTENT DiskExtend;\r
     OPENFILENAME ofn = { 0 };\r
@@ -358,20 +436,27 @@ static int CreateVlnk(HWND hWnd, WCHAR *Dir)
     WCHAR *Pos = NULL;\r
     ventoy_vlnk *vlnk = NULL;\r
 \r
     WCHAR *Pos = NULL;\r
     ventoy_vlnk *vlnk = NULL;\r
 \r
-    ofn.lStructSize = sizeof(ofn);\r
-    ofn.hwndOwner = hWnd;\r
-    ofn.lpstrFile = szFile;\r
-    ofn.nMaxFile = sizeof(szFile);\r
-    ofn.lpstrFilter = L"Vlnk Source File\0*.iso;*.img;*.wim;*.vhd;*.vhdx;*.vtoy;*.efi;*.dat\0";\r
-    ofn.nFilterIndex = 1;\r
-    ofn.lpstrFileTitle = NULL;\r
-    ofn.nMaxFileTitle = 0;\r
-    ofn.lpstrInitialDir = NULL;\r
-    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;\r
-\r
-    if (GetOpenFileName(&ofn) != TRUE)\r
+    if (InFile)\r
     {\r
     {\r
-        return 1;\r
+        wcscpy_s(szFile, MAX_PATH, InFile);\r
+    }\r
+    else\r
+    {\r
+        ofn.lStructSize = sizeof(ofn);\r
+        ofn.hwndOwner = hWnd;\r
+        ofn.lpstrFile = szFile;\r
+        ofn.nMaxFile = sizeof(szFile);\r
+        ofn.lpstrFilter = L"Vlnk Source File\0*.iso;*.img;*.wim;*.vhd;*.vhdx;*.vtoy;*.efi;*.dat\0";\r
+        ofn.nFilterIndex = 1;\r
+        ofn.lpstrFileTitle = NULL;\r
+        ofn.nMaxFileTitle = 0;\r
+        ofn.lpstrInitialDir = NULL;\r
+        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;\r
+\r
+        if (GetOpenFileName(&ofn) != TRUE)\r
+        {\r
+            return 1;\r
+        }\r
     }\r
 \r
     LogW(L"Create vlnk for <%ls>\n", szFile);\r
     }\r
 \r
     LogW(L"Create vlnk for <%ls>\n", szFile);\r
@@ -380,7 +465,7 @@ static int CreateVlnk(HWND hWnd, WCHAR *Dir)
 \r
     if (len < 5 || szFile[0] == '.' || szFile[1] != ':')\r
     {\r
 \r
     if (len < 5 || szFile[0] == '.' || szFile[1] != ':')\r
     {\r
-        MessageBox(hWnd, g_msg_lang[MSGID_SRC_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        VtoyMessageBox(hWnd, g_msg_lang[MSGID_SRC_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         return 1;\r
     }\r
     \r
         return 1;\r
     }\r
     \r
@@ -406,7 +491,7 @@ static int CreateVlnk(HWND hWnd, WCHAR *Dir)
     }\r
     else\r
     {\r
     }\r
     else\r
     {\r
-        MessageBox(hWnd, g_msg_lang[MSGID_FS_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        VtoyMessageBox(hWnd, g_msg_lang[MSGID_FS_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         return 1;\r
     }\r
 \r
         return 1;\r
     }\r
 \r
@@ -419,13 +504,13 @@ static int CreateVlnk(HWND hWnd, WCHAR *Dir)
 \r
     if (!IsSupportedImgSuffix(suffix))\r
     {\r
 \r
     if (!IsSupportedImgSuffix(suffix))\r
     {\r
-        MessageBox(hWnd, g_msg_lang[MSGID_SUFFIX_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        VtoyMessageBox(hWnd, g_msg_lang[MSGID_SUFFIX_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         return 1;\r
     }\r
 \r
     if (IsVlnkFile(szFile, NULL))\r
     {\r
         return 1;\r
     }\r
 \r
     if (IsVlnkFile(szFile, NULL))\r
     {\r
-        MessageBox(hWnd, g_msg_lang[MSGID_ALREADY_VLNK], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        VtoyMessageBox(hWnd, g_msg_lang[MSGID_ALREADY_VLNK], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         return 1;\r
     }\r
 \r
         return 1;\r
     }\r
 \r
@@ -459,17 +544,18 @@ static int CreateVlnk(HWND hWnd, WCHAR *Dir)
     if (len >= VLNK_NAME_MAX)\r
     {\r
         LogA("File name length %d overflow\n", len);\r
     if (len >= VLNK_NAME_MAX)\r
     {\r
         LogA("File name length %d overflow\n", len);\r
-        MessageBox(hWnd, g_msg_lang[MSGID_FILE_NAME_TOO_LONG], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        VtoyMessageBox(hWnd, g_msg_lang[MSGID_FILE_NAME_TOO_LONG], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         return 1;\r
     }\r
 \r
     DiskExtend.StartingOffset.QuadPart = 0;\r
     if (GetPhyDiskInfo((char)szFile[0], &DiskSig, &DiskExtend))\r
     {\r
         return 1;\r
     }\r
 \r
     DiskExtend.StartingOffset.QuadPart = 0;\r
     if (GetPhyDiskInfo((char)szFile[0], &DiskSig, &DiskExtend))\r
     {\r
-        MessageBox(hWnd, g_msg_lang[MSGID_DISK_INFO_ERR], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        VtoyMessageBox(hWnd, g_msg_lang[MSGID_DISK_INFO_ERR], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         return 1;\r
     }\r
 \r
         return 1;\r
     }\r
 \r
+\r
     Buf = malloc(VLNK_FILE_LEN);\r
     if (Buf)\r
     {\r
     Buf = malloc(VLNK_FILE_LEN);\r
     if (Buf)\r
     {\r
@@ -477,24 +563,65 @@ static int CreateVlnk(HWND hWnd, WCHAR *Dir)
         vlnk = (ventoy_vlnk *)Buf;\r
         ventoy_create_vlnk(DiskSig, (uint64_t)DiskExtend.StartingOffset.QuadPart, UTF8Path, vlnk);\r
 \r
         vlnk = (ventoy_vlnk *)Buf;\r
         ventoy_create_vlnk(DiskSig, (uint64_t)DiskExtend.StartingOffset.QuadPart, UTF8Path, vlnk);\r
 \r
-        DefaultVlnkDstFullPath(Pos + 1, Dir, DstFullPath);\r
+        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
 \r
         if (SaveBuffer2File(DstFullPath, Buf, VLNK_FILE_LEN) == 0)\r
         {\r
             WCHAR Msg[1024];\r
 \r
         LogW(L"vlnk output file path is <%ls>\n", DstFullPath);\r
 \r
         if (SaveBuffer2File(DstFullPath, Buf, VLNK_FILE_LEN) == 0)\r
         {\r
             WCHAR Msg[1024];\r
 \r
-            swprintf_s(Msg, 1024, L"%ls\r\n\r\n%ls", g_msg_lang[MSGID_VLNK_SUCCESS], DstFullPath + lstrlen(Dir) + 1);\r
-\r
             LogW(L"Vlnk file create success <%ls>\n", DstFullPath);\r
             LogW(L"Vlnk file create success <%ls>\n", DstFullPath);\r
-            MessageBox(hWnd, Msg, g_msg_lang[MSGID_INFO], MB_OK | MB_ICONINFORMATION);\r
+\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
+            }\r
+            else\r
+            {\r
+                swprintf_s(Msg, 1024, L"%ls\r\n\r\n%ls", g_msg_lang[MSGID_VLNK_SUCCESS], DstFullPath + lstrlen(Dir) + 1);\r
+                VtoyMessageBox(hWnd, Msg, g_msg_lang[MSGID_INFO], MB_OK | MB_ICONINFORMATION);\r
+            }\r
         }\r
         else\r
         {\r
             LogA("Vlnk file save failed\n");\r
         }\r
         else\r
         {\r
             LogA("Vlnk file save failed\n");\r
-            MessageBox(hWnd, g_msg_lang[MSGID_CREATE_FILE_ERR], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+            VtoyMessageBox(hWnd, g_msg_lang[MSGID_CREATE_FILE_ERR], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         }\r
 \r
         }\r
 \r
+        end:\r
         free(Buf);\r
     }\r
 \r
         free(Buf);\r
     }\r
 \r
@@ -534,7 +661,6 @@ static CHAR GetDriveLetter(UINT32 disksig, UINT64 PartOffset)
     return 0;\r
 }\r
 \r
     return 0;\r
 }\r
 \r
-\r
 static int ParseVlnk(HWND hWnd)\r
 {\r
     int i;\r
 static int ParseVlnk(HWND hWnd)\r
 {\r
     int i;\r
@@ -567,7 +693,7 @@ static int ParseVlnk(HWND hWnd)
 \r
     if (!IsVlnkFile(szFile, &vlnk))\r
     {\r
 \r
     if (!IsVlnkFile(szFile, &vlnk))\r
     {\r
-        MessageBox(hWnd, g_msg_lang[MSGID_INVALID_VLNK], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        VtoyMessageBox(hWnd, g_msg_lang[MSGID_INVALID_VLNK], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         return 1;\r
     }\r
 \r
         return 1;\r
     }\r
 \r
@@ -581,7 +707,7 @@ static int ParseVlnk(HWND hWnd)
 \r
     if (!IsSupportedImgSuffix(suffix))\r
     {\r
 \r
     if (!IsSupportedImgSuffix(suffix))\r
     {\r
-        MessageBox(hWnd, g_msg_lang[MSGID_SUFFIX_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        VtoyMessageBox(hWnd, g_msg_lang[MSGID_SUFFIX_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         return 1;\r
     }\r
 \r
         return 1;\r
     }\r
 \r
@@ -598,7 +724,7 @@ static int ParseVlnk(HWND hWnd)
     Letter = GetDriveLetter(vlnk.disk_signature, vlnk.part_offset);\r
     if (Letter == 0)\r
     {\r
     Letter = GetDriveLetter(vlnk.disk_signature, vlnk.part_offset);\r
     if (Letter == 0)\r
     {\r
-        MessageBox(hWnd, g_msg_lang[MSGID_VLNK_NO_DST], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        VtoyMessageBox(hWnd, g_msg_lang[MSGID_VLNK_NO_DST], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         return 1;\r
     }\r
 \r
         return 1;\r
     }\r
 \r
@@ -609,13 +735,13 @@ static int ParseVlnk(HWND hWnd)
     hFile = CreateFileW(szDst, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);\r
     if (INVALID_HANDLE_VALUE == hFile)\r
     {\r
     hFile = CreateFileW(szDst, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);\r
     if (INVALID_HANDLE_VALUE == hFile)\r
     {\r
-        MessageBox(hWnd, g_msg_lang[MSGID_VLNK_NO_DST], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        VtoyMessageBox(hWnd, g_msg_lang[MSGID_VLNK_NO_DST], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
         return 1;\r
     }\r
     CloseHandle(hFile);\r
 \r
     swprintf_s(Msg, 1024, L"%ls %ls", g_msg_lang[MSGID_VLNK_POINT_TO], szDst);\r
         return 1;\r
     }\r
     CloseHandle(hFile);\r
 \r
     swprintf_s(Msg, 1024, L"%ls %ls", g_msg_lang[MSGID_VLNK_POINT_TO], szDst);\r
-    MessageBox(hWnd, Msg, g_msg_lang[MSGID_INFO], MB_OK | MB_ICONINFORMATION);\r
+    VtoyMessageBox(hWnd, Msg, g_msg_lang[MSGID_INFO], MB_OK | MB_ICONINFORMATION);\r
 \r
     return 0;\r
 }\r
 \r
     return 0;\r
 }\r
@@ -637,7 +763,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lPara
                                if (CtrlID == IDC_BUTTON1)\r
                                {\r
                     EnableWindow(g_create_button, FALSE);\r
                                if (CtrlID == IDC_BUTTON1)\r
                                {\r
                     EnableWindow(g_create_button, FALSE);\r
-                    CreateVlnk(hWnd, g_CurDirW);\r
+                    CreateVlnk(hWnd, g_CurDirW, NULL, NULL);\r
                     EnableWindow(g_create_button, TRUE);\r
                                }\r
                                else if (CtrlID == IDC_BUTTON2)\r
                     EnableWindow(g_create_button, TRUE);\r
                                }\r
                                else if (CtrlID == IDC_BUTTON2)\r
@@ -664,13 +790,109 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lPara
     return 0;\r
 }\r
 \r
     return 0;\r
 }\r
 \r
-int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)\r
+static int ParseCmdLine(LPSTR lpCmdLine)\r
 {\r
     int i;\r
 {\r
     int i;\r
+    int argc = 0;\r
+    LPWSTR *lpszArgv = NULL;\r
+    \r
+    lpszArgv = CommandLineToArgvW(GetCommandLineW(), &argc);\r
+\r
+    for (i = 0; i < argc; i++)\r
+    {\r
+        if (lstrcmp(lpszArgv[i], L"-q") == 0 || lstrcmp(lpszArgv[i], L"-Q") == 0)\r
+        {\r
+            g_LogFile[0] = 0;\r
+        }\r
+        else if (lstrcmp(lpszArgv[i], L"-h") == 0 || lstrcmp(lpszArgv[i], L"-H") == 0)\r
+        {\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
+            {\r
+                wcscpy_s(g_CmdInFile, MAX_PATH, lpszArgv[i + 1]);\r
+            }\r
+        }\r
+        else if (lstrcmp(lpszArgv[i], L"-o") == 0 || lstrcmp(lpszArgv[i], L"-O") == 0)\r
+        {\r
+            if (i + 1 < argc)\r
+            {\r
+                wcscpy_s(g_CmdOutFile, MAX_PATH, lpszArgv[i + 1]);\r
+            }\r
+        }\r
+    }\r
+\r
+    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
        HANDLE hMutex;\r
 \r
     UNREFERENCED_PARAMETER(hPrevInstance);\r
 \r
        HANDLE hMutex;\r
 \r
     UNREFERENCED_PARAMETER(hPrevInstance);\r
 \r
+    DllProtect();\r
+\r
     if (GetUserDefaultUILanguage() == 0x0804)\r
     {\r
         g_msg_lang = g_msg_cn;\r
     if (GetUserDefaultUILanguage() == 0x0804)\r
     {\r
         g_msg_lang = g_msg_cn;\r
@@ -680,32 +902,52 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
         g_msg_lang = g_msg_en;\r
     }\r
 \r
         g_msg_lang = g_msg_en;\r
     }\r
 \r
-       hMutex = CreateMutexA(NULL, TRUE, "VtoyVlnkMUTEX");\r
-       if ((hMutex != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))\r
-       {\r
-               MessageBoxW(NULL, g_msg_lang[MSGID_RUNNING_TIP], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
-               return 1;\r
-       }\r
+    hMutex = CreateMutexA(NULL, TRUE, "VtoyVlnkMUTEX");\r
+    if ((hMutex != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))\r
+    {\r
+        MessageBoxW(NULL, g_msg_lang[MSGID_RUNNING_TIP], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+        return 1;\r
+    }\r
 \r
     GetCurrentDirectoryA(MAX_PATH, g_CurDirA);\r
     GetCurrentDirectoryW(MAX_PATH, g_CurDirW);\r
     sprintf_s(g_LogFile, sizeof(g_LogFile), "%s\\VentoyVlnk.log", g_CurDirA);\r
 \r
 \r
     GetCurrentDirectoryA(MAX_PATH, g_CurDirA);\r
     GetCurrentDirectoryW(MAX_PATH, g_CurDirW);\r
     sprintf_s(g_LogFile, sizeof(g_LogFile), "%s\\VentoyVlnk.log", g_CurDirA);\r
 \r
-    for (i = 0; i < __argc; i++)\r
+    ParseCmdLine(lpCmdLine);\r
+    \r
+    g_hInst = hInstance;\r
+\r
+    if (g_ShowHelp)\r
+    {\r
+        VtoyMessageBox(NULL, L"VentoyVlnk.exe  CMD\r\n  -i  Input file path\r\n  -o  Output vlnk file path\r\n  -q  Quite mode (no log)", L"Tip", MB_OK);\r
+        return 0;\r
+    }\r
+    else if (g_CmdInFile[0] && g_CmdOutFile[0])\r
     {\r
     {\r
-        if (strncmp(__argv[i], "-Q", 2) == 0 ||\r
-            strncmp(__argv[i], "-q", 2) == 0)\r
+        LogA("========= VentoyVlnk Cmdline Mode =========\n");\r
+\r
+        dwAttrib = GetFileAttributesW(g_CmdInFile);\r
+        if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))\r
         {\r
         {\r
-            g_LogFile[0] = 0;\r
-            break;\r
+            LogW(L"File <<%ls>> does not exist!\n", g_CmdInFile);\r
+            VtoyMessageBox(NULL, g_msg_lang[MSGID_SRC_NONEXIST], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+            return 1;\r
         }\r
         }\r
-    }\r
-    \r
 \r
 \r
-    LogA("========= VentoyVlnk =========\n");\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
 \r
-    g_hInst = hInstance;\r
-    DialogBoxA(hInstance, MAKEINTRESOURCEA(IDD_DIALOG1), NULL, DialogProc);\r
+        return CreateVlnk(NULL, g_CurDirW, g_CmdInFile, g_CmdOutFile);\r
+    }\r
+    else\r
+    {\r
+        LogA("========= VentoyVlnk GUI Mode =========\n");\r
 \r
 \r
-    return 0;\r
+        DialogBoxA(hInstance, MAKEINTRESOURCEA(IDD_DIALOG1), NULL, DialogProc);\r
+        return 0;\r
+    }\r
 }\r
 }\r