10 static WCHAR g_CurDirW
[MAX_PATH
];
11 static CHAR g_CurDirA
[MAX_PATH
];
12 static CHAR g_LogFile
[MAX_PATH
];
13 static HWND g_create_button
;
14 static HWND g_parse_button
;
16 static BOOL g_ShowHelp
= FALSE
;
17 static BOOL g_SaveAs
= FALSE
;
18 static WCHAR g_CmdInFile
[MAX_PATH
];
19 static WCHAR g_CmdOutFile
[MAX_PATH
];
28 MSGID_SRC_UNSUPPORTED
,
30 MSGID_SUFFIX_UNSUPPORTED
,
34 MSGID_CREATE_FILE_ERR
,
39 MSGID_FILE_NAME_TOO_LONG
,
46 const WCHAR
*g_msg_cn
[MSGID_BUTT
] =
53 L
"²»Ö§³ÖΪ´ËÎļþ´´½¨vlnk",
55 L
"²»Ö§³ÖµÄÎļþºó׺Ãû",
56 L
"»ñÈ¡´ÅÅÌÐÅϢʱ·¢Éú´íÎó",
57 L
"Vlnk Îļþ´´½¨³É¹¦¡£",
58 L
"ÇëÏȹرÕÕýÔÚÔËÐÐµÄ VentoyVlnk ³ÌÐò£¡",
60 L
"´ËÎļþÒѾÊÇÒ»¸övlnkÎļþÁË£¡",
63 L
"´Ë vlnk Ö¸ÏòµÄÎļþ²»´æÔÚ£¡",
65 L
"·Ç·¨µÄvlnkÎļþºó׺Ãû!",
67 const WCHAR
*g_msg_en
[MSGID_BUTT
] =
73 L
"The specified file is not exist!",
74 L
"This file is not supported for vlnk",
75 L
"Unsupported file system!",
76 L
"Unsupported file suffix!",
77 L
"Error when getting disk info",
78 L
"Vlnk file successfully created!",
79 L
"Please close another running VentoyVlnk instance!",
80 L
"Failed to create file!",
81 L
"This file is already a vlnk file!",
82 L
"Invalid vlnk file!",
83 L
"The vlnk file point to ",
84 L
"The file pointed by the vlnk does NOT exist!",
85 L
"The file full path is too long!",
86 L
"Invalid vlnk file suffix!",
89 const WCHAR
**g_msg_lang
= NULL
;
93 static int VtoyMessageBox
96 _In_opt_ LPCWSTR lpText
,
97 _In_opt_ LPCWSTR lpCaption
,
101 if (g_CmdInFile
[0] && g_CmdOutFile
[0])
106 return MessageBox(hWnd
, lpText
, lpCaption
, uType
);
109 static void Log2File(const char *log
)
116 localtime_s(&ttm
, &stamp
);
118 fopen_s(&fp
, g_LogFile
, "a+");
121 fprintf_s(fp
, "[%04u/%02u/%02u %02u:%02u:%02u] %s",
122 ttm
.tm_year
+ 1900, ttm
.tm_mon
+ 1, ttm
.tm_mday
,
123 ttm
.tm_hour
, ttm
.tm_min
, ttm
.tm_sec
, log
);
128 void LogW(const WCHAR
*Fmt
, ...)
134 if (g_LogFile
[0] == 0)
140 vswprintf_s(log
, 512, Fmt
, arg
);
143 WideCharToMultiByte(CP_UTF8
, 0, log
, -1, alog
, 2048, 0, 0);
149 void LogA(const CHAR
*Fmt
, ...)
154 if (g_LogFile
[0] == 0)
160 vsprintf_s(log
, 512, Fmt
, arg
);
166 static int Utf8ToUtf16(const char* src
, WCHAR
* dst
)
168 int size
= MultiByteToWideChar(CP_UTF8
, 0, src
, -1, dst
, 0);
169 return MultiByteToWideChar(CP_UTF8
, 0, src
, -1, dst
, size
+ 1);
172 static BOOL
OnDestroyDialog()
178 static BOOL
InitDialog(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
182 g_create_button
= GetDlgItem(hWnd
, IDC_BUTTON1
);
183 g_parse_button
= GetDlgItem(hWnd
, IDC_BUTTON2
);
185 hIcon
= LoadIcon(g_hInst
, MAKEINTRESOURCE(IDI_ICON1
));
186 SendMessage(hWnd
, WM_SETICON
, ICON_BIG
, (LPARAM
)hIcon
);
187 SendMessage(hWnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)hIcon
);
189 SetWindowTextW(g_create_button
, g_msg_lang
[MSGID_BTN_CREATE
]);
190 SetWindowTextW(g_parse_button
, g_msg_lang
[MSGID_BTN_PARSE
]);
195 static int GetPhyDiskInfo(const char LogicalDrive
, UINT32
*DiskSig
, DISK_EXTENT
*DiskExtent
)
200 VOLUME_DISK_EXTENTS DiskExtents
;
202 UINT8 SectorBuf
[512];
204 LogA("GetPhyDiskInfo %C\n", LogicalDrive
);
206 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\%C:", LogicalDrive
);
207 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
208 if (Handle
== INVALID_HANDLE_VALUE
)
210 LogA("Could not open the disk %C: error:%u\n", LogicalDrive
, GetLastError());
214 Ret
= DeviceIoControl(Handle
,
215 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
219 (DWORD
)(sizeof(DiskExtents
)),
222 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
224 LogA("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u\n", GetLastError());
230 memcpy(DiskExtent
, DiskExtents
.Extents
, sizeof(DISK_EXTENT
));
231 LogA("%C: is in PhysicalDrive%d Offset:%llu\n", LogicalDrive
, DiskExtents
.Extents
[0].DiskNumber
,
232 (ULONGLONG
)(DiskExtents
.Extents
[0].StartingOffset
.QuadPart
));
234 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", DiskExtents
.Extents
[0].DiskNumber
);
235 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
236 if (Handle
== INVALID_HANDLE_VALUE
)
238 LogA("Could not open the disk<PhysicalDrive%d>, error:%u\n", DiskExtents
.Extents
[0].DiskNumber
, GetLastError());
242 if (!ReadFile(Handle
, SectorBuf
, sizeof(SectorBuf
), &dwSize
, NULL
))
244 LogA("ReadFile failed, dwSize:%u error:%u\n", dwSize
, GetLastError());
249 memcpy(DiskSig
, SectorBuf
+ 0x1B8, 4);
256 static int SaveBuffer2File(const WCHAR
*Fullpath
, void *Buffer
, DWORD Length
)
262 LogW(L
"SaveBuffer2File <%ls> len:%u\n", Fullpath
, Length
);
264 Handle
= CreateFileW(Fullpath
, GENERIC_READ
| GENERIC_WRITE
,
265 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, CREATE_ALWAYS
, 0, 0);
266 if (Handle
== INVALID_HANDLE_VALUE
)
268 LogA("Could not create new file, error:%u\n", GetLastError());
272 WriteFile(Handle
, Buffer
, Length
, &dwSize
, NULL
);
278 if (Handle
!= INVALID_HANDLE_VALUE
)
287 static int DefaultVlnkDstFullPath(WCHAR
*Src
, WCHAR
*Dir
, WCHAR
*Dst
)
294 len
= (int)lstrlen(Src
);
295 for (i
= len
- 1; i
>= 0; i
--)
301 wrlen
= swprintf_s(Dst
, MAX_PATH
, L
"%ls\\%ls.vlnk.%ls", Dir
, Src
, Src
+ i
+ 1);
304 for (j
= wrlen
- (len
- i
); j
< wrlen
; j
++)
306 if (Dst
[j
] >= 'A' && Dst
[j
] <= 'Z')
308 Dst
[j
] = 'a' + (Dst
[j
] - 'A');
319 static BOOL
IsVlnkFile(WCHAR
*path
, ventoy_vlnk
*outvlnk
)
324 LARGE_INTEGER FileSize
;
328 Handle
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
329 if (Handle
== INVALID_HANDLE_VALUE
)
331 LogA("Could not open this file, error:%u\n", GetLastError());
335 if (!GetFileSizeEx(Handle
, &FileSize
))
337 LogA("Failed to get vlnk file size\n");
341 if (FileSize
.QuadPart
!= VLNK_FILE_LEN
)
343 LogA("Invalid vlnk file length %llu\n", (unsigned long long)FileSize
.QuadPart
);
347 memset(&vlnk
, 0, sizeof(vlnk
));
348 bRet
= ReadFile(Handle
, &vlnk
, sizeof(vlnk
), &dwSize
, NULL
);
349 if (bRet
&& CheckVlnkData(&vlnk
))
353 memcpy(outvlnk
, &vlnk
, sizeof(vlnk
));
361 if (Handle
!= INVALID_HANDLE_VALUE
)
370 static BOOL
VentoyGetSaveFileName(HWND hWnd
, WCHAR
*szFile
)
372 OPENFILENAME ofn
= { 0 };
374 ofn
.lStructSize
= sizeof(ofn
);
375 ofn
.hwndOwner
= hWnd
;
376 ofn
.lpstrFilter
= L
"Vlnk File\0*.vlnk.iso;*.vlnk.img;*.vlnk.wim;*.vlnk.efi;*.vlnk.vhd;*.vlnk.vhdx;*.vlnk.vtoy;*.vlnk.dat\0";
377 ofn
.nFilterIndex
= 1;
378 ofn
.lpstrFile
= szFile
;
379 ofn
.nMaxFile
= MAX_PATH
;
380 ofn
.Flags
= OFN_EXPLORER
| OFN_PATHMUSTEXIST
| OFN_HIDEREADONLY
| OFN_OVERWRITEPROMPT
;
381 ofn
.lpstrFileTitle
= NULL
;
382 ofn
.nMaxFileTitle
= 0;
383 ofn
.lpstrInitialDir
= NULL
;
385 return GetSaveFileName(&ofn
);
388 static BOOL
IsSupportedVlnkSuffix(WCHAR
*FileName
)
392 len
= lstrlen(FileName
);
396 if (lstrcmp(FileName
+ len
- 9, L
".vlnk.iso") == 0 ||
397 lstrcmp(FileName
+ len
- 9, L
".vlnk.img") == 0 ||
398 lstrcmp(FileName
+ len
- 9, L
".vlnk.wim") == 0 ||
399 lstrcmp(FileName
+ len
- 9, L
".vlnk.vhd") == 0 ||
400 lstrcmp(FileName
+ len
- 9, L
".vlnk.efi") == 0 ||
401 lstrcmp(FileName
+ len
- 9, L
".vlnk.dat") == 0)
410 if (lstrcmp(FileName
+ len
- 10, L
".vlnk.vhdx") == 0 ||
411 lstrcmp(FileName
+ len
- 10, L
".vlnk.vtoy") == 0)
420 static int CreateVlnk(HWND hWnd
, WCHAR
*Dir
, WCHAR
*InFile
, WCHAR
*OutFile
)
425 BOOL SetOutFile
= FALSE
;
427 DISK_EXTENT DiskExtend
;
428 OPENFILENAME ofn
= { 0 };
429 CHAR UTF8Path
[MAX_PATH
];
430 WCHAR DstFullPath
[MAX_PATH
];
431 WCHAR szFile
[MAX_PATH
] = { 0 };
432 CHAR suffix
[8] = { 0 };
433 CHAR Drive
[8] = { 0 };
434 CHAR FsName
[64] = { 0 };
437 ventoy_vlnk
*vlnk
= NULL
;
441 wcscpy_s(szFile
, MAX_PATH
, InFile
);
445 ofn
.lStructSize
= sizeof(ofn
);
446 ofn
.hwndOwner
= hWnd
;
447 ofn
.lpstrFile
= szFile
;
448 ofn
.nMaxFile
= sizeof(szFile
);
449 ofn
.lpstrFilter
= L
"Vlnk Source File\0*.iso;*.img;*.wim;*.vhd;*.vhdx;*.vtoy;*.efi;*.dat\0";
450 ofn
.nFilterIndex
= 1;
451 ofn
.lpstrFileTitle
= NULL
;
452 ofn
.nMaxFileTitle
= 0;
453 ofn
.lpstrInitialDir
= NULL
;
454 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_FILEMUSTEXIST
;
456 if (GetOpenFileName(&ofn
) != TRUE
)
462 LogW(L
"Create vlnk for <%ls>\n", szFile
);
464 len
= lstrlen(szFile
);
466 if (len
< 5 || szFile
[0] == '.' || szFile
[1] != ':')
468 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_SRC_UNSUPPORTED
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
472 Drive
[0] = (CHAR
)szFile
[0];
475 if (0 == GetVolumeInformationA(Drive
, NULL
, 0, NULL
, NULL
, NULL
, FsName
, sizeof(FsName
) - 1))
477 LogA("GetVolumeInformationA failed %u\n", GetLastError());
481 LogA("Partition filesystem of <%s> is <%s>\n", Drive
, FsName
);
482 if (_stricmp(FsName
, "NTFS") == 0 ||
483 _stricmp(FsName
, "exFAT") == 0 ||
484 _stricmp(FsName
, "FAT") == 0 ||
485 _stricmp(FsName
, "FAT32") == 0 ||
486 _stricmp(FsName
, "FAT16") == 0 ||
487 _stricmp(FsName
, "FAT12") == 0 ||
488 _stricmp(FsName
, "UDF") == 0)
490 LogA("FS Check OK\n");
494 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_FS_UNSUPPORTED
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
499 end
= (szFile
[len
- 5] == '.') ? 5 : 4;
500 for (i
= 0; i
< end
; i
++)
502 suffix
[i
] = (CHAR
)szFile
[len
- (end
- i
)];
505 if (!IsSupportedImgSuffix(suffix
))
507 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_SUFFIX_UNSUPPORTED
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
511 if (IsVlnkFile(szFile
, NULL
))
513 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_ALREADY_VLNK
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
517 for (i
= 0; i
< MAX_PATH
&& szFile
[i
]; i
++)
519 if (szFile
[i
] == '\\' || szFile
[i
] == '/')
527 LogA("name part not found\n");
530 LogW(L
"File Name is <%ls>\n", Pos
+ 1);
532 memset(UTF8Path
, 0, sizeof(UTF8Path
));
533 WideCharToMultiByte(CP_UTF8
, 0, szFile
+ 2, -1, UTF8Path
, MAX_PATH
, NULL
, 0);
535 for (i
= 0; i
< MAX_PATH
&& UTF8Path
[i
]; i
++)
537 if (UTF8Path
[i
] == '\\')
543 len
= (int)strlen(UTF8Path
);
544 if (len
>= VLNK_NAME_MAX
)
546 LogA("File name length %d overflow\n", len
);
547 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_FILE_NAME_TOO_LONG
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
551 DiskExtend
.StartingOffset
.QuadPart
= 0;
552 if (GetPhyDiskInfo((char)szFile
[0], &DiskSig
, &DiskExtend
))
554 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_DISK_INFO_ERR
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
559 Buf
= malloc(VLNK_FILE_LEN
);
562 memset(Buf
, 0, VLNK_FILE_LEN
);
563 vlnk
= (ventoy_vlnk
*)Buf
;
564 ventoy_create_vlnk(DiskSig
, (uint64_t)DiskExtend
.StartingOffset
.QuadPart
, UTF8Path
, vlnk
);
568 wcscpy_s(DstFullPath
, MAX_PATH
, OutFile
);
573 DefaultVlnkDstFullPath(Pos
+ 1, Dir
, DstFullPath
);
577 wcscpy_s(szFile
, MAX_PATH
, DstFullPath
);
578 if (VentoyGetSaveFileName(hWnd
, szFile
))
580 if (IsSupportedVlnkSuffix(szFile
))
582 wcscpy_s(DstFullPath
, MAX_PATH
, szFile
);
587 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_INVALID_SUFFIX
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
588 LogA("Invalid vlnk suffix\n");
594 LogA("User cancel the save as diaglog, use default name\n");
599 LogW(L
"vlnk output file path is <%ls>\n", DstFullPath
);
601 if (SaveBuffer2File(DstFullPath
, Buf
, VLNK_FILE_LEN
) == 0)
605 LogW(L
"Vlnk file create success <%ls>\n", DstFullPath
);
609 swprintf_s(Msg
, 1024, L
"%ls\r\n\r\n%ls", g_msg_lang
[MSGID_VLNK_SUCCESS
], DstFullPath
);
610 VtoyMessageBox(hWnd
, Msg
, g_msg_lang
[MSGID_INFO
], MB_OK
| MB_ICONINFORMATION
);
614 swprintf_s(Msg
, 1024, L
"%ls\r\n\r\n%ls", g_msg_lang
[MSGID_VLNK_SUCCESS
], DstFullPath
+ lstrlen(Dir
) + 1);
615 VtoyMessageBox(hWnd
, Msg
, g_msg_lang
[MSGID_INFO
], MB_OK
| MB_ICONINFORMATION
);
620 LogA("Vlnk file save failed\n");
621 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_CREATE_FILE_ERR
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
631 static CHAR
GetDriveLetter(UINT32 disksig
, UINT64 PartOffset
)
636 DISK_EXTENT DiskExtent
;
639 Drives
= GetLogicalDrives();
640 LogA("Logic Drives: 0x%x", Drives
);
647 DiskExtent
.StartingOffset
.QuadPart
= 0;
648 if (GetPhyDiskInfo(Letter
, &Sig
, &DiskExtent
) == 0)
650 if (Sig
== disksig
&& DiskExtent
.StartingOffset
.QuadPart
== PartOffset
)
664 static int ParseVlnk(HWND hWnd
)
669 OPENFILENAME ofn
= { 0 };
670 WCHAR szFile
[MAX_PATH
] = { 0 };
671 WCHAR szDst
[MAX_PATH
+ 2] = { 0 };
676 ofn
.lStructSize
= sizeof(ofn
);
677 ofn
.hwndOwner
= hWnd
;
678 ofn
.lpstrFile
= szFile
;
679 ofn
.nMaxFile
= sizeof(szFile
);
680 ofn
.lpstrFilter
= L
"Vlnk File\0*.vlnk.iso;*.vlnk.img;*.vlnk.wim;*.vlnk.efi;*.vlnk.vhd;*.vlnk.vhdx;*.vlnk.vtoy;*.vlnk.dat\0";
681 ofn
.nFilterIndex
= 1;
682 ofn
.lpstrFileTitle
= NULL
;
683 ofn
.nMaxFileTitle
= 0;
684 ofn
.lpstrInitialDir
= NULL
;
685 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_FILEMUSTEXIST
;
687 if (GetOpenFileName(&ofn
) != TRUE
)
692 LogW(L
"Parse vlnk for <%ls>\n", szFile
);
694 if (!IsVlnkFile(szFile
, &vlnk
))
696 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_INVALID_VLNK
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
700 for (i
= 0; i
< sizeof(vlnk
.filepath
) && vlnk
.filepath
[i
]; i
++)
702 if (vlnk
.filepath
[i
] == '.')
704 suffix
= vlnk
.filepath
+ i
;
708 if (!IsSupportedImgSuffix(suffix
))
710 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_SUFFIX_UNSUPPORTED
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
714 Utf8ToUtf16(vlnk
.filepath
, szDst
+ 2);
715 for (i
= 2; i
< MAX_PATH
&& szDst
[i
]; i
++)
724 Letter
= GetDriveLetter(vlnk
.disk_signature
, vlnk
.part_offset
);
727 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_VLNK_NO_DST
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
731 szDst
[0] = toupper(Letter
);
733 LogW(L
"vlnk dst is %ls\n", szDst
);
735 hFile
= CreateFileW(szDst
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
736 if (INVALID_HANDLE_VALUE
== hFile
)
738 VtoyMessageBox(hWnd
, g_msg_lang
[MSGID_VLNK_NO_DST
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
743 swprintf_s(Msg
, 1024, L
"%ls %ls", g_msg_lang
[MSGID_VLNK_POINT_TO
], szDst
);
744 VtoyMessageBox(hWnd
, Msg
, g_msg_lang
[MSGID_INFO
], MB_OK
| MB_ICONINFORMATION
);
749 INT_PTR CALLBACK
DialogProc(HWND hWnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
)
758 NotifyCode
= HIWORD(wParam
);
759 CtrlID
= LOWORD(wParam
);
761 if (NotifyCode
== BN_CLICKED
)
763 if (CtrlID
== IDC_BUTTON1
)
765 EnableWindow(g_create_button
, FALSE
);
766 CreateVlnk(hWnd
, g_CurDirW
, NULL
, NULL
);
767 EnableWindow(g_create_button
, TRUE
);
769 else if (CtrlID
== IDC_BUTTON2
)
771 EnableWindow(g_parse_button
, FALSE
);
773 EnableWindow(g_parse_button
, TRUE
);
780 InitDialog(hWnd
, wParam
, lParam
);
793 static int ParseCmdLine(LPSTR lpCmdLine
)
797 LPWSTR
*lpszArgv
= NULL
;
799 lpszArgv
= CommandLineToArgvW(GetCommandLineW(), &argc
);
801 for (i
= 0; i
< argc
; i
++)
803 if (lstrcmp(lpszArgv
[i
], L
"-q") == 0 || lstrcmp(lpszArgv
[i
], L
"-Q") == 0)
807 else if (lstrcmp(lpszArgv
[i
], L
"-h") == 0 || lstrcmp(lpszArgv
[i
], L
"-H") == 0)
811 else if (lstrcmp(lpszArgv
[i
], L
"-s") == 0 || lstrcmp(lpszArgv
[i
], L
"-S") == 0)
815 else if (lstrcmp(lpszArgv
[i
], L
"-i") == 0 || lstrcmp(lpszArgv
[i
], L
"-I") == 0)
819 wcscpy_s(g_CmdInFile
, MAX_PATH
, lpszArgv
[i
+ 1]);
822 else if (lstrcmp(lpszArgv
[i
], L
"-o") == 0 || lstrcmp(lpszArgv
[i
], L
"-O") == 0)
826 wcscpy_s(g_CmdOutFile
, MAX_PATH
, lpszArgv
[i
+ 1]);
834 int APIENTRY
WinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, INT nCmdShow
)
839 UNREFERENCED_PARAMETER(hPrevInstance
);
841 if (GetUserDefaultUILanguage() == 0x0804)
843 g_msg_lang
= g_msg_cn
;
847 g_msg_lang
= g_msg_en
;
850 hMutex
= CreateMutexA(NULL
, TRUE
, "VtoyVlnkMUTEX");
851 if ((hMutex
!= NULL
) && (GetLastError() == ERROR_ALREADY_EXISTS
))
853 MessageBoxW(NULL
, g_msg_lang
[MSGID_RUNNING_TIP
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
857 GetCurrentDirectoryA(MAX_PATH
, g_CurDirA
);
858 GetCurrentDirectoryW(MAX_PATH
, g_CurDirW
);
859 sprintf_s(g_LogFile
, sizeof(g_LogFile
), "%s\\VentoyVlnk.log", g_CurDirA
);
861 ParseCmdLine(lpCmdLine
);
867 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
);
870 else if (g_CmdInFile
[0] && g_CmdOutFile
[0])
872 LogA("========= VentoyVlnk Cmdline Mode =========\n");
874 dwAttrib
= GetFileAttributesW(g_CmdInFile
);
875 if (dwAttrib
== INVALID_FILE_ATTRIBUTES
|| (dwAttrib
& FILE_ATTRIBUTE_DIRECTORY
))
877 LogW(L
"File <<%ls>> does not exist!\n", g_CmdInFile
);
878 VtoyMessageBox(NULL
, g_msg_lang
[MSGID_SRC_NONEXIST
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
882 if (!IsSupportedVlnkSuffix(g_CmdOutFile
))
884 LogW(L
"File <<%ls>> contains invalid vlnk suffix!\n", g_CmdOutFile
);
885 VtoyMessageBox(NULL
, g_msg_lang
[MSGID_INVALID_SUFFIX
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
889 return CreateVlnk(NULL
, g_CurDirW
, g_CmdInFile
, g_CmdOutFile
);
893 LogA("========= VentoyVlnk GUI Mode =========\n");
895 DialogBoxA(hInstance
, MAKEINTRESOURCEA(IDD_DIALOG1
), NULL
, DialogProc
);