]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Plugson/src/Core/ventoy_util_windows.c
language.json: Update Tamil translation (#2009)
[Ventoy.git] / Plugson / src / Core / ventoy_util_windows.c
1 /******************************************************************************
2 * ventoy_util.c ---- ventoy util
3 * Copyright (c) 2021, longpanda <admin@ventoy.net>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <ventoy_define.h>
23 #include <ventoy_util.h>
24 #include <ventoy_disk.h>
25 #include "fat_filelib.h"
26
27 static void TrimString(CHAR *String)
28 {
29 CHAR *Pos1 = String;
30 CHAR *Pos2 = String;
31 size_t Len = strlen(String);
32
33 while (Len > 0)
34 {
35 if (String[Len - 1] != ' ' && String[Len - 1] != '\t')
36 {
37 break;
38 }
39 String[Len - 1] = 0;
40 Len--;
41 }
42
43 while (*Pos1 == ' ' || *Pos1 == '\t')
44 {
45 Pos1++;
46 }
47
48 while (*Pos1)
49 {
50 *Pos2++ = *Pos1++;
51 }
52 *Pos2++ = 0;
53
54 return;
55 }
56
57 void ventoy_gen_preudo_uuid(void *uuid)
58 {
59 CoCreateGuid((GUID *)uuid);
60 }
61
62 static int IsUTF8Encode(const char *src)
63 {
64 int i;
65 const UCHAR *Byte = (const UCHAR *)src;
66
67 for (i = 0; i < MAX_PATH && Byte[i]; i++)
68 {
69 if (Byte[i] > 127)
70 {
71 return 1;
72 }
73 }
74
75 return 0;
76 }
77
78 static int Utf8ToUtf16(const char* src, WCHAR * dst)
79 {
80 return MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, MAX_PATH * sizeof(WCHAR));
81 }
82
83 static int Utf16ToUtf8(const WCHAR* src, CHAR * dst)
84 {
85 int size = WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, MAX_PATH, NULL, 0);
86 dst[size] = 0;
87 return size;
88 }
89
90
91 int ventoy_path_case(char *path, int slash)
92 {
93 int i;
94 int j = 0;
95 int count = 0;
96 int isUTF8 = 0;
97 BOOL bRet;
98 HANDLE handle = INVALID_HANDLE_VALUE;
99 WCHAR Buffer[MAX_PATH + 16];
100 WCHAR FilePathW[MAX_PATH];
101 CHAR FilePathA[MAX_PATH];
102 FILE_NAME_INFO *pInfo = NULL;
103
104 if (g_sysinfo.pathcase == 0)
105 {
106 return 0;
107 }
108
109 if (path == NULL || path[0] == '/' || path[0] == '\\')
110 {
111 return 0;
112 }
113
114 isUTF8 = IsUTF8Encode(path);
115 if (isUTF8)
116 {
117 Utf8ToUtf16(path, FilePathW);
118 handle = CreateFileW(FilePathW, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
119 }
120 else
121 {
122 handle = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
123 }
124
125 if (handle != INVALID_HANDLE_VALUE)
126 {
127 bRet = GetFileInformationByHandleEx(handle, FileNameInfo, Buffer, sizeof(Buffer));
128 if (bRet)
129 {
130 pInfo = (FILE_NAME_INFO *)Buffer;
131
132 if (slash)
133 {
134 for (i = 0; i < (int)(pInfo->FileNameLength / sizeof(WCHAR)); i++)
135 {
136 if (pInfo->FileName[i] == L'\\')
137 {
138 pInfo->FileName[i] = L'/';
139 }
140 }
141 }
142
143 pInfo->FileName[(pInfo->FileNameLength / sizeof(WCHAR))] = 0;
144
145 memset(FilePathA, 0, sizeof(FilePathA));
146 Utf16ToUtf8(pInfo->FileName, FilePathA);
147
148 if (FilePathA[1] == ':')
149 {
150 j = 3;
151 }
152 else
153 {
154 j = 1;
155 }
156
157 for (i = 0; i < MAX_PATH && j < MAX_PATH; i++, j++)
158 {
159 if (FilePathA[j] == 0)
160 {
161 break;
162 }
163
164 if (path[i] != FilePathA[j])
165 {
166 path[i] = FilePathA[j];
167 count++;
168 }
169 }
170 }
171
172 CHECK_CLOSE_HANDLE(handle);
173 }
174
175 return count;
176 }
177
178
179
180 int ventoy_is_directory_exist(const char *Fmt, ...)
181 {
182 va_list Arg;
183 DWORD Attr;
184 int UTF8 = 0;
185 CHAR FilePathA[MAX_PATH];
186 WCHAR FilePathW[MAX_PATH];
187
188 va_start(Arg, Fmt);
189 vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);
190 va_end(Arg);
191
192 UTF8 = IsUTF8Encode(FilePathA);
193
194 if (UTF8)
195 {
196 Utf8ToUtf16(FilePathA, FilePathW);
197 Attr = GetFileAttributesW(FilePathW);
198 }
199 else
200 {
201 Attr = GetFileAttributesA(FilePathA);
202 }
203
204 if (Attr != INVALID_FILE_ATTRIBUTES && (Attr & FILE_ATTRIBUTE_DIRECTORY))
205 {
206 return TRUE;
207 }
208
209 return FALSE;
210 }
211
212 int ventoy_is_file_exist(const char *Fmt, ...)
213 {
214 va_list Arg;
215 HANDLE hFile;
216 DWORD Attr;
217 int UTF8 = 0;
218 CHAR FilePathA[MAX_PATH];
219 WCHAR FilePathW[MAX_PATH];
220
221 va_start(Arg, Fmt);
222 vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);
223 va_end(Arg);
224
225 UTF8 = IsUTF8Encode(FilePathA);
226 if (UTF8)
227 {
228 Utf8ToUtf16(FilePathA, FilePathW);
229 hFile = CreateFileW(FilePathW, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
230 Attr = GetFileAttributesW(FilePathW);
231 }
232 else
233 {
234 hFile = CreateFileA(FilePathA, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
235 Attr = GetFileAttributesA(FilePathA);
236 }
237
238 if (INVALID_HANDLE_VALUE == hFile)
239 {
240 return 0;
241 }
242 CloseHandle(hFile);
243
244 if (Attr & FILE_ATTRIBUTE_DIRECTORY)
245 {
246 return 0;
247 }
248
249 return 1;
250 }
251
252 const char * ventoy_get_os_language(void)
253 {
254 if (GetUserDefaultUILanguage() == 0x0804)
255 {
256 return "cn";
257 }
258 else
259 {
260 return "en";
261 }
262 }
263
264
265 int GetPhyDriveByLogicalDrive(int DriveLetter, UINT64 *Offset)
266 {
267 BOOL Ret;
268 DWORD dwSize;
269 HANDLE Handle;
270 VOLUME_DISK_EXTENTS DiskExtents;
271 CHAR PhyPath[128];
272
273 scnprintf(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", (CHAR)DriveLetter);
274
275 Handle = CreateFileA(PhyPath, 0, 0, 0, OPEN_EXISTING, 0, 0);
276 if (Handle == INVALID_HANDLE_VALUE)
277 {
278 vlog("CreateFileA %s failed %u\n", PhyPath, LASTERR);
279 return -1;
280 }
281
282 Ret = DeviceIoControl(Handle,
283 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
284 NULL,
285 0,
286 &DiskExtents,
287 (DWORD)(sizeof(DiskExtents)),
288 (LPDWORD)&dwSize,
289 NULL);
290
291 if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
292 {
293 vlog("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTSfailed %u\n", LASTERR);
294 CHECK_CLOSE_HANDLE(Handle);
295 return -1;
296 }
297 CHECK_CLOSE_HANDLE(Handle);
298
299 if (Offset)
300 {
301 *Offset = (UINT64)(DiskExtents.Extents[0].StartingOffset.QuadPart);
302 }
303
304 return (int)DiskExtents.Extents[0].DiskNumber;
305 }
306
307 int GetPhyDriveInfo(int PhyDrive, UINT64 *Size, CHAR *Vendor, CHAR *Product)
308 {
309 int ret = 1;
310 BOOL bRet;
311 DWORD dwBytes;
312 CHAR Drive[64];
313 HANDLE Handle = INVALID_HANDLE_VALUE;
314 GET_LENGTH_INFORMATION LengthInfo;
315 STORAGE_PROPERTY_QUERY Query;
316 STORAGE_DESCRIPTOR_HEADER DevDescHeader;
317 STORAGE_DEVICE_DESCRIPTOR *pDevDesc = NULL;
318
319 sprintf_s(Drive, sizeof(Drive), "\\\\.\\PhysicalDrive%d", PhyDrive);
320 Handle = CreateFileA(Drive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
321 if (Handle == INVALID_HANDLE_VALUE)
322 {
323 vlog("CreateFileA %s failed %u\n", Drive, LASTERR);
324 goto out;
325 }
326
327
328 bRet = DeviceIoControl(Handle,
329 IOCTL_DISK_GET_LENGTH_INFO, NULL,
330 0,
331 &LengthInfo,
332 sizeof(LengthInfo),
333 &dwBytes,
334 NULL);
335 if (!bRet)
336 {
337 vlog("IOCTL_DISK_GET_LENGTH_INFO failed %u\n", LASTERR);
338 return 1;
339 }
340
341 if (Size)
342 {
343 *Size = (UINT64)LengthInfo.Length.QuadPart;
344 }
345
346 Query.PropertyId = StorageDeviceProperty;
347 Query.QueryType = PropertyStandardQuery;
348
349 bRet = DeviceIoControl(Handle,
350 IOCTL_STORAGE_QUERY_PROPERTY,
351 &Query,
352 sizeof(Query),
353 &DevDescHeader,
354 sizeof(STORAGE_DESCRIPTOR_HEADER),
355 &dwBytes,
356 NULL);
357 if (!bRet)
358 {
359 vlog("IOCTL_STORAGE_QUERY_PROPERTY failed %u\n", LASTERR);
360 goto out;
361 }
362
363 if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))
364 {
365 vlog("DevDescHeader.size invalid %u\n", DevDescHeader.Size);
366 goto out;
367 }
368
369 pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size);
370 if (!pDevDesc)
371 {
372 vlog("malloc failed\n");
373 goto out;
374 }
375
376 bRet = DeviceIoControl(Handle,
377 IOCTL_STORAGE_QUERY_PROPERTY,
378 &Query,
379 sizeof(Query),
380 pDevDesc,
381 DevDescHeader.Size,
382 &dwBytes,
383 NULL);
384 if (!bRet)
385 {
386 vlog("IOCTL_STORAGE_QUERY_PROPERTY failed %u\n", LASTERR);
387 goto out;
388 }
389
390 if (pDevDesc->VendorIdOffset && Vendor)
391 {
392 strcpy_s(Vendor, 128, (char *)pDevDesc + pDevDesc->VendorIdOffset);
393 TrimString(Vendor);
394 }
395
396 if (pDevDesc->ProductIdOffset && Product)
397 {
398 strcpy_s(Product, 128, (char *)pDevDesc + pDevDesc->ProductIdOffset);
399 TrimString(Product);
400 }
401
402 ret = 0;
403
404 out:
405 CHECK_FREE(pDevDesc);
406 CHECK_CLOSE_HANDLE(Handle);
407 return ret;
408 }
409
410
411 int ventoy_get_file_size(const char *file)
412 {
413 int Size = -1;
414 HANDLE hFile;
415
416 hFile = CreateFileA(file, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
417 if (hFile != INVALID_HANDLE_VALUE)
418 {
419 Size = (int)GetFileSize(hFile, NULL);
420 CHECK_CLOSE_HANDLE(hFile);
421 }
422
423 return Size;
424 }
425
426
427 static HANDLE g_FatPhyDrive;
428 static UINT64 g_Part2StartSec;
429
430 const CHAR* ParseVentoyVersionFromString(CHAR *Buf)
431 {
432 CHAR *Pos = NULL;
433 CHAR *End = NULL;
434 static CHAR LocalVersion[64] = { 0 };
435
436 Pos = strstr(Buf, "VENTOY_VERSION=");
437 if (Pos)
438 {
439 Pos += strlen("VENTOY_VERSION=");
440 if (*Pos == '"')
441 {
442 Pos++;
443 }
444
445 End = Pos;
446 while (*End != 0 && *End != '"' && *End != '\r' && *End != '\n')
447 {
448 End++;
449 }
450
451 *End = 0;
452
453 sprintf_s(LocalVersion, sizeof(LocalVersion), "%s", Pos);
454 return LocalVersion;
455 }
456
457 return "";
458 }
459 static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen)
460 {
461 int rc = 1;
462 int size = 0;
463 char *buf = NULL;
464 void *flfile = NULL;
465
466 flfile = fl_fopen("/grub/grub.cfg", "rb");
467 if (flfile)
468 {
469 fl_fseek(flfile, 0, SEEK_END);
470 size = (int)fl_ftell(flfile);
471
472 fl_fseek(flfile, 0, SEEK_SET);
473
474 buf = (char *)malloc(size + 1);
475 if (buf)
476 {
477 fl_fread(buf, 1, size, flfile);
478 buf[size] = 0;
479
480 rc = 0;
481 sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf));
482 free(buf);
483 }
484
485 fl_fclose(flfile);
486 }
487
488 return rc;
489 }
490
491 static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
492 {
493 DWORD dwSize;
494 BOOL bRet;
495 DWORD ReadSize;
496 LARGE_INTEGER liCurrentPosition;
497
498 liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
499 liCurrentPosition.QuadPart *= 512;
500 SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
501
502 ReadSize = (DWORD)(SectorCount * 512);
503
504 bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
505 if (bRet == FALSE || dwSize != ReadSize)
506 {
507
508 }
509
510 return 1;
511 }
512
513 static int GetVentoyVersion(int PhyDrive, ventoy_disk *disk)
514 {
515 int ret = 1;
516 BOOL bRet;
517 DWORD dwBytes;
518 UINT64 Part2Offset;
519 HANDLE Handle = INVALID_HANDLE_VALUE;
520 VTOY_GPT_INFO *pGPT = NULL;
521 CHAR Drive[64];
522 void *flfile = NULL;
523 UCHAR MbrData[] =
524 {
525 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
529 };
530
531 sprintf_s(Drive, sizeof(Drive), "\\\\.\\PhysicalDrive%d", PhyDrive);
532 Handle = CreateFileA(Drive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
533 if (Handle == INVALID_HANDLE_VALUE)
534 {
535 vlog("CreateFileA %s failed %u\n", Drive, LASTERR);
536 goto out;
537 }
538
539 pGPT = zalloc(sizeof(VTOY_GPT_INFO));
540 if (!pGPT)
541 {
542 goto out;
543 }
544
545 bRet = ReadFile(Handle, pGPT, sizeof(VTOY_GPT_INFO), &dwBytes, NULL);
546 if (!bRet || dwBytes != sizeof(VTOY_GPT_INFO))
547 {
548 vlog("ReadFile failed %u\n", LASTERR);
549 goto out;
550 }
551
552 if (memcmp(pGPT->MBR.BootCode, MbrData, 0x30) || memcmp(pGPT->MBR.BootCode + 0x190, MbrData + 0x30, 0x10))
553 {
554 vlog("Invalid MBR Code %u\n", LASTERR);
555 goto out;
556 }
557
558 if (pGPT->MBR.PartTbl[0].FsFlag == 0xEE)
559 {
560 if (memcmp(pGPT->Head.Signature, "EFI PART", 8))
561 {
562 vlog("Invalid GPT Signature\n");
563 goto out;
564 }
565
566 Part2Offset = pGPT->PartTbl[1].StartLBA;
567 disk->cur_part_style = 1;
568 }
569 else
570 {
571 Part2Offset = pGPT->MBR.PartTbl[1].StartSectorId;
572 disk->cur_part_style = 0;
573 }
574
575
576 g_FatPhyDrive = Handle;
577 g_Part2StartSec = Part2Offset;
578
579 fl_init();
580
581 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
582 {
583 ret = GetVentoyVersionFromFatFile(disk->cur_ventoy_ver, sizeof(disk->cur_ventoy_ver));
584 if (ret == 0)
585 {
586 flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
587 if (flfile)
588 {
589 disk->cur_secureboot = 1;
590 fl_fclose(flfile);
591 }
592 }
593 }
594
595 fl_shutdown();
596
597 out:
598 CHECK_FREE(pGPT);
599 CHECK_CLOSE_HANDLE(Handle);
600 return ret;
601 }
602
603 int CheckRuntimeEnvironment(char Letter, ventoy_disk *disk)
604 {
605 int PhyDrive;
606 UINT64 Offset = 0;
607 char Drive[32];
608 DWORD FsFlag;
609 CHAR Vendor[128] = { 0 };
610 CHAR Product[128] = { 0 };
611 CHAR FsName[MAX_PATH];
612
613 PhyDrive = GetPhyDriveByLogicalDrive(Letter, &Offset);
614 if (PhyDrive < 0)
615 {
616 vlog("GetPhyDriveByLogicalDrive failed %d %llu\n", PhyDrive, (ULONGLONG)Offset);
617 return 1;
618 }
619 if (Offset != 1048576)
620 {
621 vlog("Partition offset is NOT 1MB. This is NOT ventoy image partition (%llu)\n", (ULONGLONG)Offset);
622 return 1;
623 }
624
625 if (GetPhyDriveInfo(PhyDrive, &Offset, Vendor, Product) != 0)
626 {
627 vlog("GetPhyDriveInfo failed\n");
628 return 1;
629 }
630
631 sprintf_s(disk->cur_capacity, sizeof(disk->cur_capacity), "%dGB", (int)ventoy_get_human_readable_gb(Offset));
632 sprintf_s(disk->cur_model, sizeof(disk->cur_model), "%s %s", Vendor, Product);
633
634 scnprintf(Drive, sizeof(Drive), "%C:\\", Letter);
635 if (0 == GetVolumeInformationA(Drive, NULL, 0, NULL, NULL, &FsFlag, FsName, MAX_PATH))
636 {
637 vlog("GetVolumeInformationA failed %u\n", LASTERR);
638 return 1;
639 }
640
641 if (_stricmp(FsName, "NTFS") == 0)
642 {
643 disk->pathcase = 1;
644 }
645
646 strlcpy(disk->cur_fsname, FsName);
647
648 if (GetVentoyVersion(PhyDrive, disk) != 0)
649 {
650 vlog("GetVentoyVersion failed %u\n", LASTERR);
651 return 1;
652 }
653
654 return 0;
655 }
656
657
658
659 static volatile int g_thread_stop = 0;
660 static HANDLE g_writeback_thread;
661 static HANDLE g_writeback_event;
662
663 DWORD WINAPI ventoy_local_thread_run(LPVOID lpParameter)
664 {
665 ventoy_http_writeback_pf callback = (ventoy_http_writeback_pf)lpParameter;
666
667 while (1)
668 {
669 WaitForSingleObject(g_writeback_event, INFINITE);
670 if (g_thread_stop)
671 {
672 break;
673 }
674 else
675 {
676 callback();
677 }
678 }
679
680 return 0;
681 }
682
683
684 void ventoy_set_writeback_event(void)
685 {
686 SetEvent(g_writeback_event);
687 }
688
689
690 int ventoy_start_writeback_thread(ventoy_http_writeback_pf callback)
691 {
692 g_thread_stop = 0;
693 g_writeback_event = CreateEventA(NULL, FALSE, FALSE, "VTOYWRBK");
694 g_writeback_thread = CreateThread(NULL, 0, ventoy_local_thread_run, callback, 0, NULL);
695
696 return 0;
697 }
698
699
700 void ventoy_stop_writeback_thread(void)
701 {
702 g_thread_stop = 1;
703 ventoy_set_writeback_event();
704
705 WaitForSingleObject(g_writeback_thread, INFINITE);
706
707 CHECK_CLOSE_HANDLE(g_writeback_thread);
708 CHECK_CLOSE_HANDLE(g_writeback_event);
709 }
710
711 int ventoy_read_file_to_buf(const char *FileName, int ExtLen, void **Bufer, int *BufLen)
712 {
713 int UTF8 = 0;
714 int Size = 0;
715 BOOL bRet;
716 DWORD dwBytes;
717 HANDLE hFile;
718 char *buffer = NULL;
719 WCHAR FilePathW[MAX_PATH];
720
721 UTF8 = IsUTF8Encode(FileName);
722 if (UTF8)
723 {
724 Utf8ToUtf16(FileName, FilePathW);
725 hFile = CreateFileW(FilePathW, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
726 }
727 else
728 {
729 hFile = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
730 }
731
732 if (hFile == INVALID_HANDLE_VALUE)
733 {
734 vlog("Failed to open %s %u\n", FileName, LASTERR);
735 return 1;
736 }
737
738 Size = (int)GetFileSize(hFile, NULL);
739 buffer = malloc(Size + ExtLen);
740 if (!buffer)
741 {
742 vlog("Failed to alloc file buffer\n");
743 CloseHandle(hFile);
744 return 1;
745 }
746
747 bRet = ReadFile(hFile, buffer, (DWORD)Size, &dwBytes, NULL);
748 if ((!bRet) || ((DWORD)Size != dwBytes))
749 {
750 vlog("Failed to read file <%s> %u err:%u", FileName, dwBytes, LASTERR);
751 CloseHandle(hFile);
752 free(buffer);
753 return 1;
754 }
755
756 *Bufer = buffer;
757 *BufLen = Size;
758
759 CloseHandle(hFile);
760 return 0;
761 }
762
763 int ventoy_write_buf_to_file(const char *FileName, void *Bufer, int BufLen)
764 {
765 BOOL bRet;
766 DWORD dwBytes;
767 HANDLE hFile;
768
769 hFile = CreateFileA(FileName, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
770 if (hFile == INVALID_HANDLE_VALUE)
771 {
772 vlog("CreateFile %s failed %u\n", FileName, LASTERR);
773 return 1;
774 }
775
776 bRet = WriteFile(hFile, Bufer, (DWORD)BufLen, &dwBytes, NULL);
777
778 if ((!bRet) || ((DWORD)BufLen != dwBytes))
779 {
780 vlog("Failed to write file <%s> %u err:%u", FileName, dwBytes, LASTERR);
781 CloseHandle(hFile);
782 return 1;
783 }
784
785 FlushFileBuffers(hFile);
786 CloseHandle(hFile);
787
788 return 0;
789 }
790
791 int ventoy_copy_file(const char *a, const char *b)
792 {
793 CopyFileA(a, b, FALSE);
794 return 0;
795 }
796