+#include <Windows.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <stdint.h>\r
+#include <time.h>\r
+#include <resource.h>\r
+#include <vlnk.h>\r
+\r
+static WCHAR g_CurDirW[MAX_PATH];\r
+static CHAR g_CurDirA[MAX_PATH];\r
+static CHAR g_LogFile[MAX_PATH];\r
+static HWND g_create_button;\r
+static HWND g_parse_button;\r
+\r
+typedef enum MSGID\r
+{\r
+ MSGID_ERROR = 0,\r
+ MSGID_INFO,\r
+ MSGID_BTN_CREATE,\r
+ MSGID_BTN_PARSE,\r
+ MSGID_SRC_UNSUPPORTED,\r
+ MSGID_FS_UNSUPPORTED,\r
+ MSGID_SUFFIX_UNSUPPORTED,\r
+ MSGID_DISK_INFO_ERR,\r
+ MSGID_VLNK_SUCCESS,\r
+ MSGID_RUNNING_TIP,\r
+ MSGID_CREATE_FILE_ERR,\r
+ MSGID_ALREADY_VLNK,\r
+ MSGID_INVALID_VLNK,\r
+ MSGID_VLNK_POINT_TO,\r
+ MSGID_VLNK_NO_DST,\r
+ MSGID_FILE_NAME_TOO_LONG,\r
+\r
+ MSGID_BUTT\r
+}MSGID;\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
+};\r
+const WCHAR *g_msg_en[MSGID_BUTT] =\r
+{\r
+ L"Error",\r
+ L"Info", \r
+ L"Create",\r
+ L"Parse",\r
+ L"This file is not supported for vlnk",\r
+ L"Unsupported file system!", \r
+ L"Unsupported file suffix!",\r
+ L"Error when getting disk info",\r
+ L"Vlnk file successfully created!",\r
+ L"Please close another running VentoyVlnk instance!",\r
+ L"Failed to create file!",\r
+ L"This file is already a vlnk file!",\r
+ L"Invalid vlnk file!",\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
+};\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
+\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);
+}\r
+\r
+static int Utf8ToUtf16(const char* src, WCHAR * dst)\r
+{\r
+ int size = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, 0);\r
+ return MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size + 1);\r
+}\r
+\r
+static BOOL OnDestroyDialog()\r
+{ \r
+ return TRUE;\r
+}\r
+\r
+\r
+static BOOL InitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)\r
+{\r
+ HICON hIcon;\r
+\r
+ g_create_button = GetDlgItem(hWnd, IDC_BUTTON1);\r
+ g_parse_button = GetDlgItem(hWnd, IDC_BUTTON2);\r
+ \r
+ hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_ICON1));\r
+ SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);\r
+ SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);\r
+\r
+ SetWindowTextW(g_create_button, g_msg_lang[MSGID_BTN_CREATE]);\r
+ SetWindowTextW(g_parse_button, g_msg_lang[MSGID_BTN_PARSE]);\r
+\r
+ return TRUE;\r
+}\r
+\r
+static int GetPhyDiskInfo(const char LogicalDrive, UINT32 *DiskSig, DISK_EXTENT *DiskExtent)\r
+{\r
+ BOOL Ret;\r
+ DWORD dwSize;\r
+ HANDLE Handle;\r
+ VOLUME_DISK_EXTENTS DiskExtents;\r
+ CHAR PhyPath[128];\r
+ UINT8 SectorBuf[512];\r
+\r
+ LogA("GetPhyDiskInfo %C\n", LogicalDrive);\r
+\r
+ sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", LogicalDrive);\r
+ Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ LogA("Could not open the disk %C: error:%u\n", LogicalDrive, GetLastError());\r
+ return 1;\r
+ }\r
+\r
+ Ret = DeviceIoControl(Handle,\r
+ IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,\r
+ NULL,\r
+ 0,\r
+ &DiskExtents,\r
+ (DWORD)(sizeof(DiskExtents)),\r
+ (LPDWORD)&dwSize,\r
+ NULL);\r
+ if (!Ret || DiskExtents.NumberOfDiskExtents == 0)\r
+ {\r
+ LogA("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u\n", GetLastError());\r
+ CloseHandle(Handle);\r
+ return 1;\r
+ }\r
+ CloseHandle(Handle);\r
+\r
+ memcpy(DiskExtent, DiskExtents.Extents, sizeof(DISK_EXTENT));\r
+ LogA("%C: is in PhysicalDrive%d Offset:%llu\n", LogicalDrive, DiskExtents.Extents[0].DiskNumber,\r
+ (ULONGLONG)(DiskExtents.Extents[0].StartingOffset.QuadPart));\r
+\r
+ sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskExtents.Extents[0].DiskNumber);\r
+ Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ LogA("Could not open the disk<PhysicalDrive%d>, error:%u\n", DiskExtents.Extents[0].DiskNumber, GetLastError());\r
+ return 1;\r
+ }\r
+\r
+ if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))\r
+ {\r
+ LogA("ReadFile failed, dwSize:%u error:%u\n", dwSize, GetLastError());\r
+ CloseHandle(Handle);\r
+ return 1;\r
+ }\r
+\r
+ memcpy(DiskSig, SectorBuf + 0x1B8, 4);\r
+\r
+ CloseHandle(Handle);\r
+ return 0;\r
+}\r
+\r
+\r
+static int SaveBuffer2File(const WCHAR *Fullpath, void *Buffer, DWORD Length)\r
+{\r
+ int rc = 1;\r
+ DWORD dwSize;\r
+ HANDLE Handle;\r
+\r
+ LogW(L"SaveBuffer2File <%ls> len:%u\n", Fullpath, Length);\r
+\r
+ Handle = CreateFileW(Fullpath, GENERIC_READ | GENERIC_WRITE,\r
+ FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ LogA("Could not create new file, error:%u\n", GetLastError());\r
+ goto End;\r
+ }\r
+\r
+ WriteFile(Handle, Buffer, Length, &dwSize, NULL);\r
+\r
+ rc = 0;\r
+\r
+End:\r
+\r
+ if (Handle != INVALID_HANDLE_VALUE)\r
+ {\r
+ CloseHandle(Handle);\r
+ }\r
+\r
+\r
+ return rc;\r
+}\r
+\r
+static int DefaultVlnkDstFullPath(WCHAR *Src, WCHAR *Dir, WCHAR *Dst)\r
+{\r
+ int i, j;\r
+ int len;\r
+ int wrlen;\r
+ WCHAR C;\r
+\r
+ len = (int)lstrlen(Src);\r
+ for (i = len - 1; i >= 0; i--)\r
+ {\r
+ if (Src[i] == '.')\r
+ {\r
+ C = Src[i];\r
+ Src[i] = 0;\r
+ wrlen = swprintf_s(Dst, MAX_PATH, L"%ls\\%ls.vlnk.%ls", Dir, Src, Src + i + 1);\r
+ Src[i] = C;\r
+\r
+ for (j = wrlen - (len - i); j < wrlen; j++)\r
+ {\r
+ if (Dst[j] >= 'A' && Dst[j] <= 'Z')\r
+ {\r
+ Dst[j] = 'a' + (Dst[j] - 'A');\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static BOOL IsVlnkFile(WCHAR *path, ventoy_vlnk *outvlnk)\r
+{\r
+ BOOL bRet;\r
+ BOOL bVlnk = FALSE;\r
+ DWORD dwSize;\r
+ LARGE_INTEGER FileSize;\r
+ HANDLE Handle;\r
+ ventoy_vlnk vlnk;\r
+\r
+ Handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ LogA("Could not open this file, error:%u\n", GetLastError());\r
+ return FALSE;\r
+ }\r
+\r
+ if (!GetFileSizeEx(Handle, &FileSize))\r
+ {\r
+ LogA("Failed to get vlnk file size\n");\r
+ goto End;\r
+ }\r
+\r
+ if (FileSize.QuadPart != VLNK_FILE_LEN)\r
+ {\r
+ LogA("Invalid vlnk file length %llu\n", (unsigned long long)FileSize.QuadPart);\r
+ goto End;\r
+ }\r
+\r
+ memset(&vlnk, 0, sizeof(vlnk));\r
+ bRet = ReadFile(Handle, &vlnk, sizeof(vlnk), &dwSize, NULL);\r
+ if (bRet && CheckVlnkData(&vlnk))\r
+ {\r
+ if (outvlnk)\r
+ {\r
+ memcpy(outvlnk, &vlnk, sizeof(vlnk));\r
+ }\r
+\r
+ bVlnk = TRUE;\r
+ }\r
+\r
+End:\r
+\r
+ if (Handle != INVALID_HANDLE_VALUE)\r
+ {\r
+ CloseHandle(Handle);\r
+ }\r
+\r
+ return bVlnk;\r
+}\r
+\r
+\r
+static int CreateVlnk(HWND hWnd, WCHAR *Dir)\r
+{\r
+ int i;\r
+ int end;\r
+ int len;\r
+ UINT32 DiskSig;\r
+ DISK_EXTENT DiskExtend;\r
+ OPENFILENAME ofn = { 0 };\r
+ CHAR UTF8Path[MAX_PATH];\r
+ WCHAR DstFullPath[MAX_PATH];\r
+ WCHAR szFile[MAX_PATH] = { 0 };\r
+ CHAR suffix[8] = { 0 };\r
+ CHAR Drive[8] = { 0 };\r
+ CHAR FsName[64] = { 0 };\r
+ CHAR *Buf = NULL;\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
+ {\r
+ return 1;\r
+ }\r
+\r
+ LogW(L"Create vlnk for <%ls>\n", szFile);\r
+ \r
+ len = lstrlen(szFile);\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
+ return 1;\r
+ }\r
+ \r
+ Drive[0] = (CHAR)szFile[0];\r
+ Drive[1] = ':';\r
+ Drive[2] = '\\';\r
+ if (0 == GetVolumeInformationA(Drive, NULL, 0, NULL, NULL, NULL, FsName, sizeof(FsName) - 1))\r
+ {\r
+ LogA("GetVolumeInformationA failed %u\n", GetLastError());\r
+ return 1;\r
+ }\r
+\r
+ LogA("Partition filesystem of <%s> is <%s>\n", Drive, FsName);\r
+ if (_stricmp(FsName, "NTFS") == 0 ||\r
+ _stricmp(FsName, "exFAT") == 0 ||\r
+ _stricmp(FsName, "FAT") == 0 ||\r
+ _stricmp(FsName, "FAT32") == 0 ||\r
+ _stricmp(FsName, "FAT16") == 0 ||\r
+ _stricmp(FsName, "FAT12") == 0 ||\r
+ _stricmp(FsName, "UDF") == 0)\r
+ {\r
+ LogA("FS Check OK\n");\r
+ }\r
+ else\r
+ {\r
+ MessageBox(hWnd, g_msg_lang[MSGID_FS_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);\r
+ return 1;\r
+ }\r
+\r
+\r
+ end = (szFile[len - 5] == '.') ? 5 : 4;\r
+ for (i = 0; i < end; i++)\r
+ {\r
+ suffix[i] = (CHAR)szFile[len - (end - i)];\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
+ 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
+ return 1;\r
+ }\r
+\r
+ for (i = 0; i < MAX_PATH && szFile[i]; i++)\r
+ {\r
+ if (szFile[i] == '\\' || szFile[i] == '/')\r
+ {\r
+ Pos = szFile + i;\r
+ }\r
+ }\r
+\r
+ if (!Pos)\r
+ {\r
+ LogA("name part not found\n");\r
+ return 1;\r
+ }\r
+ LogW(L"File Name is <%ls>\n", Pos + 1);\r
+\r
+ memset(UTF8Path, 0, sizeof(UTF8Path));\r
+ WideCharToMultiByte(CP_UTF8, 0, szFile + 2, -1, UTF8Path, MAX_PATH, NULL, 0);\r
+\r
+ for (i = 0; i < MAX_PATH && UTF8Path[i]; i++)\r
+ {\r
+ if (UTF8Path[i] == '\\')\r
+ {\r
+ UTF8Path[i] = '/';\r
+ }\r
+ }\r
+\r
+ len = (int)strlen(UTF8Path);\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
+ 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
+ return 1;\r
+ }\r
+\r
+ Buf = malloc(VLNK_FILE_LEN);\r
+ if (Buf)\r
+ {\r
+ memset(Buf, 0, VLNK_FILE_LEN);\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
+ 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
+ MessageBox(hWnd, Msg, g_msg_lang[MSGID_INFO], MB_OK | MB_ICONINFORMATION);\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
+ }\r
+\r
+ free(Buf);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static CHAR GetDriveLetter(UINT32 disksig, UINT64 PartOffset)\r
+{\r
+ CHAR Letter;\r
+ DWORD Drives;\r
+ UINT32 Sig;\r
+ DISK_EXTENT DiskExtent;\r
+\r
+ Letter = 'A';\r
+ Drives = GetLogicalDrives();\r
+ LogA("Logic Drives: 0x%x", Drives);\r
+\r
+ while (Drives)\r
+ {\r
+ if (Drives & 0x01)\r
+ {\r
+ Sig = 0;\r
+ DiskExtent.StartingOffset.QuadPart = 0;\r
+ if (GetPhyDiskInfo(Letter, &Sig, &DiskExtent) == 0)\r
+ {\r
+ if (Sig == disksig && DiskExtent.StartingOffset.QuadPart == PartOffset)\r
+ {\r
+ return Letter;\r
+ }\r
+ }\r
+ }\r
+\r
+ Drives >>= 1;\r
+ Letter++;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+static int ParseVlnk(HWND hWnd)\r
+{\r
+ int i;\r
+ CHAR Letter;\r
+ ventoy_vlnk vlnk;\r
+ OPENFILENAME ofn = { 0 };\r
+ WCHAR szFile[MAX_PATH] = { 0 };\r
+ WCHAR szDst[MAX_PATH + 2] = { 0 };\r
+ WCHAR Msg[1024];\r
+ CHAR *suffix = NULL;\r
+ HANDLE hFile;\r
+\r
+ ofn.lStructSize = sizeof(ofn);\r
+ ofn.hwndOwner = hWnd;\r
+ ofn.lpstrFile = szFile;\r
+ ofn.nMaxFile = sizeof(szFile);\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.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
+ LogW(L"Parse vlnk for <%ls>\n", szFile);\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
+ return 1;\r
+ }\r
+\r
+ for (i = 0; i < sizeof(vlnk.filepath) && vlnk.filepath[i]; i++)\r
+ {\r
+ if (vlnk.filepath[i] == '.')\r
+ {\r
+ suffix = vlnk.filepath + i;\r
+ }\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
+ return 1;\r
+ }\r
+\r
+ Utf8ToUtf16(vlnk.filepath, szDst + 2);\r
+ for (i = 2; i < MAX_PATH && szDst[i]; i++)\r
+ {\r
+ if (szDst[i] == '/')\r
+ {\r
+ szDst[i] = '\\';\r
+ }\r
+ }\r
+ \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
+ return 1;\r
+ }\r
+\r
+ szDst[0] = toupper(Letter);\r
+ szDst[1] = ':';\r
+ LogW(L"vlnk dst is %ls\n", szDst);\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
+ 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
+\r
+ return 0;\r
+}\r
+\r
+INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ WORD NotifyCode;\r
+ WORD CtrlID;\r
+\r
+ switch (Message)\r
+ {\r
+ case WM_COMMAND:\r
+ {\r
+ NotifyCode = HIWORD(wParam);\r
+ CtrlID = LOWORD(wParam);\r
+\r
+ if (NotifyCode == BN_CLICKED)\r
+ {\r
+ if (CtrlID == IDC_BUTTON1)\r
+ {\r
+ EnableWindow(g_create_button, FALSE);\r
+ CreateVlnk(hWnd, g_CurDirW);\r
+ EnableWindow(g_create_button, TRUE);\r
+ }\r
+ else if (CtrlID == IDC_BUTTON2)\r
+ {\r
+ EnableWindow(g_parse_button, FALSE);\r
+ ParseVlnk(hWnd);\r
+ EnableWindow(g_parse_button, TRUE);\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ case WM_INITDIALOG:\r
+ {\r
+ InitDialog(hWnd, wParam, lParam);\r
+ break;\r
+ } \r
+ case WM_CLOSE:\r
+ {\r
+ OnDestroyDialog();\r
+ EndDialog(hWnd, 0);\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)\r
+{\r
+ int i;\r
+ HANDLE hMutex;\r
+\r
+ UNREFERENCED_PARAMETER(hPrevInstance);\r
+\r
+ if (GetUserDefaultUILanguage() == 0x0804)\r
+ {\r
+ g_msg_lang = g_msg_cn;\r
+ }\r
+ else\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
+\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
+ {\r
+ if (strncmp(__argv[i], "-Q", 2) == 0 ||\r
+ strncmp(__argv[i], "-q", 2) == 0)\r
+ {\r
+ g_LogFile[0] = 0;\r
+ break;\r
+ }\r
+ }\r
+ \r
+\r
+ LogA("========= VentoyVlnk =========\n");\r
+\r
+ g_hInst = hInstance;\r
+ DialogBoxA(hInstance, MAKEINTRESOURCEA(IDD_DIALOG1), NULL, DialogProc);\r
+\r
+ return 0;\r
+}\r