ReactOS 0.4.17-dev-966-gf06eace
filesup.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Setup Library
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: File support functions.
5 * COPYRIGHT: Casper S. Hornstrup (chorns@users.sourceforge.net)
6 * Copyright 2017-2018 Hermes Belusca-Maito
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include "precomp.h"
12#include "filesup.h"
13#include <pseh/pseh2.h>
14#include <ndk/umfuncs.h> // Ldr* functions
15
16#define NDEBUG
17#include <debug.h>
18
19/* FUNCTIONS ****************************************************************/
20
21static
24 _In_ PCUNICODE_STRING DirectoryName)
25{
27 UNICODE_STRING PathName = *DirectoryName;
31
32 /* Remove the trailing separator if needed */
33 if (PathName.Length >= 2 * sizeof(WCHAR) &&
34 PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
35 {
36 PathName.Length -= sizeof(WCHAR);
37 }
38
40 &PathName,
42 NULL,
43 NULL);
44
49 NULL,
54 NULL,
55 0);
56 if (NT_SUCCESS(Status))
58
59 return Status;
60}
61
74 _In_ PCWSTR PathName)
75{
77 UNICODE_STRING PathNameU;
79 PCWCH Ptr, End;
80
81 RtlInitUnicodeString(&PathNameU, PathName);
82 Buffer = PathNameU.Buffer;
83 End = Buffer + (PathNameU.Length / sizeof(WCHAR));
84
85 /* Find the deepest existing sub-directory: start from the
86 * end and go back, verifying each sub-directory in turn */
87 for (Ptr = End; Ptr > Buffer;)
88 {
89 BOOLEAN bExists;
90
91 /* If we are on a separator, truncate at the next character.
92 * The trailing separator is kept for the existence check. */
93 if ((Ptr < End) && (*Ptr == OBJ_NAME_PATH_SEPARATOR))
94 PathNameU.Length = (ULONG_PTR)(Ptr+1) - (ULONG_PTR)Buffer;
95
96 /* Check if the sub-directory exists and stop
97 * if so: this is the deepest existing one */
98 DPRINT("PathName: %wZ\n", &PathNameU);
99 bExists = DoesPathExist_UStr(NULL, &PathNameU, TRUE);
100 if (bExists)
101 break;
102
103 /* Skip back any consecutive path separators */
104 while ((Ptr > Buffer) && (*Ptr == OBJ_NAME_PATH_SEPARATOR))
105 --Ptr;
106 /* Go to the beginning of the path component, stop at the separator */
107 while ((Ptr > Buffer) && (*Ptr != OBJ_NAME_PATH_SEPARATOR))
108 --Ptr;
109 }
110
111 /* Skip any consecutive path separators */
112 while ((Ptr < End) && (*Ptr == OBJ_NAME_PATH_SEPARATOR))
113 ++Ptr;
114
115 /* Create all the remaining sub-directories */
116 for (; Ptr < End; ++Ptr)
117 {
118 /* Go to the end of the current path component, stop at
119 * the separator or terminating NUL and truncate it */
120 while ((Ptr < End) && (*Ptr != OBJ_NAME_PATH_SEPARATOR))
121 ++Ptr;
122 PathNameU.Length = (ULONG_PTR)Ptr - (ULONG_PTR)Buffer;
123
124 DPRINT("Create: %wZ\n", &PathNameU);
126 if (!NT_SUCCESS(Status))
127 break;
128 }
129
130 DPRINT("Done.\n");
131 return Status;
132}
133
137 IN BOOLEAN ForceDelete) // ForceDelete can be used to delete read-only files
138{
140 UNICODE_STRING NtPathU;
144 FILE_DISPOSITION_INFORMATION FileDispInfo;
145 BOOLEAN RetryOnce = FALSE;
146
147 /* Open the directory name that was passed in */
150 &NtPathU,
152 NULL,
153 NULL);
154
155Retry: // We go back there once if RetryOnce == TRUE
158 (RetryOnce ? FILE_WRITE_ATTRIBUTES : 0),
163 if (!NT_SUCCESS(Status))
164 {
165 DPRINT1("NtOpenFile failed with Status 0x%08lx\n", Status);
166 return Status;
167 }
168
169 if (RetryOnce)
170 {
172
178 if (!NT_SUCCESS(Status))
179 {
180 DPRINT1("NtQueryInformationFile failed with Status 0x%08lx\n", Status);
182 return Status;
183 }
184
185 FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
192 if (!NT_SUCCESS(Status))
193 {
194 DPRINT1("NtSetInformationFile failed with Status 0x%08lx\n", Status);
195 return Status;
196 }
197 }
198
199 /* Ask for the file to be deleted */
200 FileDispInfo.DeleteFile = TRUE;
203 &FileDispInfo,
207
208 if (!NT_SUCCESS(Status))
209 DPRINT1("Deletion of file '%S' failed, Status 0x%08lx\n", FileName, Status);
210
211 // FIXME: Check the precise value of Status!
212 if (!NT_SUCCESS(Status) && ForceDelete && !RetryOnce)
213 {
214 /* Retry once */
215 RetryOnce = TRUE;
216 goto Retry;
217 }
218
219 /* Return result to the caller */
220 return Status;
221}
222
225 IN PCWSTR SourceFileName,
226 IN PCWSTR DestinationFileName,
227 IN BOOLEAN FailIfExists)
228{
232 HANDLE FileHandleSource;
233 HANDLE FileHandleDest;
235 FILE_STANDARD_INFORMATION FileStandard;
236 FILE_BASIC_INFORMATION FileBasic;
238 HANDLE SourceFileSection;
239 PVOID SourceFileMap = NULL;
240 SIZE_T SourceSectionSize = 0;
242
243 RtlInitUnicodeString(&FileName, SourceFileName);
245 &FileName,
247 NULL,
248 NULL);
249
250 Status = NtOpenFile(&FileHandleSource,
256 if (!NT_SUCCESS(Status))
257 {
258 DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName);
259 goto done;
260 }
261
262 Status = NtQueryInformationFile(FileHandleSource,
264 &FileStandard,
267 if (!NT_SUCCESS(Status))
268 {
269 DPRINT1("NtQueryInformationFile failed: %x\n", Status);
270 goto closesrc;
271 }
272
273 Status = NtQueryInformationFile(FileHandleSource,
275 &FileBasic,
278 if (!NT_SUCCESS(Status))
279 {
280 DPRINT1("NtQueryInformationFile failed: %x\n", Status);
281 goto closesrc;
282 }
283
284 Status = NtCreateSection(&SourceFileSection,
286 NULL,
287 NULL,
290 FileHandleSource);
291 if (!NT_SUCCESS(Status))
292 {
293 DPRINT1("NtCreateSection failed: %x, %S\n", Status, SourceFileName);
294 goto closesrc;
295 }
296
297 Status = NtMapViewOfSection(SourceFileSection,
299 &SourceFileMap,
300 0,
301 0,
302 NULL,
303 &SourceSectionSize,
304 ViewUnmap,
305 0,
307 if (!NT_SUCCESS(Status))
308 {
309 DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status, SourceFileName);
310 goto closesrcsec;
311 }
312
313 RtlInitUnicodeString(&FileName, DestinationFileName);
315 &FileName,
317 NULL,
318 NULL);
319
320 Status = NtCreateFile(&FileHandleDest,
324 NULL,
325 FileBasic.FileAttributes, // FILE_ATTRIBUTE_NORMAL,
326 0,
327 FailIfExists ? FILE_CREATE : FILE_OVERWRITE_IF,
331 NULL,
332 0);
333 if (!NT_SUCCESS(Status))
334 {
335 /*
336 * Open may have failed because the file to overwrite
337 * is in readonly mode.
338 */
340 {
342
343 /* Reattempt to open it with limited access */
344 Status = NtCreateFile(&FileHandleDest,
348 NULL,
350 0,
351 FILE_OPEN,
355 NULL,
356 0);
357 /* Fail for real if we cannot open it that way */
358 if (!NT_SUCCESS(Status))
359 {
360 DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName);
361 goto unmapsrcsec;
362 }
363
364 /* Zero our basic info, just to set attributes */
366 /* Reset attributes to normal, no read-only */
367 FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
368 /*
369 * We basically don't care about whether it succeed:
370 * if it didn't, later open will fail.
371 */
374
375 /* Close file */
376 NtClose(FileHandleDest);
377
378 /* And re-attempt overwrite */
379 Status = NtCreateFile(&FileHandleDest,
383 NULL,
385 0,
390 NULL,
391 0);
392 }
393
394 /* We failed */
395 if (!NT_SUCCESS(Status))
396 {
397 DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName);
398 goto unmapsrcsec;
399 }
400 }
401
402 RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
403 IoStatusBlock.Status = 0;
404 ByteOffset.QuadPart = 0ULL;
405 Status = NtWriteFile(FileHandleDest,
406 NULL,
407 NULL,
408 NULL,
410 SourceFileMap,
412 &ByteOffset,
413 NULL);
414 if (!NT_SUCCESS(Status))
415 {
416 DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n",
417 Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize);
418 goto closedest;
419 }
420
421 /* Copy file date/time from source file */
422 Status = NtSetInformationFile(FileHandleDest,
424 &FileBasic,
427 if (!NT_SUCCESS(Status))
428 {
429 DPRINT1("NtSetInformationFile failed: %x\n", Status);
430 goto closedest;
431 }
432
433 /* Shorten the file back to its real size after completing the write */
434 Status = NtSetInformationFile(FileHandleDest,
436 &FileStandard.EndOfFile,
439 if (!NT_SUCCESS(Status))
440 {
441 DPRINT1("NtSetInformationFile failed: %x\n", Status);
442 }
443
444closedest:
445 NtClose(FileHandleDest);
446
447unmapsrcsec:
448 NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap);
449
450closesrcsec:
451 NtClose(SourceFileSection);
452
453closesrc:
454 NtClose(FileHandleSource);
455
456done:
457 return Status;
458}
459
460/*
461 * Synchronized with its kernel32 counterpart, but we don't manage reparse points here.
462 */
465 IN PCWSTR ExistingFileName,
466 IN PCWSTR NewFileName,
467 IN ULONG Flags)
468{
472 PFILE_RENAME_INFORMATION RenameInfo;
473 UNICODE_STRING NewPathU, ExistingPathU;
475 BOOLEAN ReplaceIfExists;
476
477 RtlInitUnicodeString(&ExistingPathU, ExistingFileName);
478 RtlInitUnicodeString(&NewPathU, NewFileName);
479
481 {
482 ReplaceIfExists = !!(Flags & MOVEFILE_REPLACE_EXISTING);
483
484 /* Unless we manage a proper opening, we'll attempt to reopen without reparse support */
486 &ExistingPathU,
488 NULL,
489 NULL);
490 /* Attempt to open source file */
497 if (!NT_SUCCESS(Status))
498 {
500 {
502 }
503 }
504
505 /* At that point, we MUST have a source handle */
507
508 /* Allocate renaming buffer and fill it */
509 RenameInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewPathU.Length + sizeof(FILE_RENAME_INFORMATION));
510 if (RenameInfo == NULL)
511 {
514 }
515
516 RtlCopyMemory(&RenameInfo->FileName, NewPathU.Buffer, NewPathU.Length);
517 RenameInfo->ReplaceIfExists = ReplaceIfExists;
518 RenameInfo->RootDirectory = NULL;
519 RenameInfo->FileNameLength = NewPathU.Length;
520
521 /* Attempt to rename the file */
524 RenameInfo,
525 NewPathU.Length + sizeof(FILE_RENAME_INFORMATION),
527 RtlFreeHeap(RtlGetProcessHeap(), 0, RenameInfo);
528 if (NT_SUCCESS(Status))
529 {
530 /* If it succeeded, all fine, quit */
532 }
533 /*
534 * If we failed for any other reason than not the same device, fail.
535 * If we failed because of different devices, only allow renaming
536 * if user allowed copy.
537 */
539 {
540 /* ReactOS hack! To be removed once all FSD have proper renaming support
541 * Just leave status to error and leave
542 */
544 {
545 DPRINT1("Forcing copy, renaming not supported by FSD\n");
546 }
547 else
548 {
550 }
551 }
552
553 /* Close the source file */
556
557 /* Perform the file copy */
558 Status = SetupCopyFile(ExistingFileName,
559 NewFileName,
560 !ReplaceIfExists);
561
562 /* If it succeeded, delete the source file */
563 if (NT_SUCCESS(Status))
564 {
565 /* Force-delete files even if read-only */
566 SetupDeleteFile(ExistingFileName, TRUE);
567 }
568 }
570 {
571 if (SourceHandle)
573 }
574 _SEH2_END;
575
576 return Status;
577}
578
581 IN OUT PWSTR PathBuffer,
582 IN SIZE_T cchPathSize,
583 IN ULONG NumberOfPathComponents,
584 IN va_list PathComponentsList)
585{
587 SIZE_T cchPathLen;
589
590 if (cchPathSize < 1)
591 return STATUS_SUCCESS;
592
593 while (NumberOfPathComponents--)
594 {
595 PathComponent = va_arg(PathComponentsList, PCWSTR);
596 if (!PathComponent)
597 continue;
598
599 cchPathLen = min(cchPathSize, wcslen(PathBuffer));
600 if (cchPathLen >= cchPathSize)
602
604 cchPathLen > 0 && PathBuffer[cchPathLen-1] != OBJ_NAME_PATH_SEPARATOR)
605 {
606 /* PathComponent does not start with '\' and PathBuffer does not end with '\' */
607 Status = RtlStringCchCatW(PathBuffer, cchPathSize, L"\\");
608 if (!NT_SUCCESS(Status))
609 return Status;
610 }
611 else if (PathComponent[0] == OBJ_NAME_PATH_SEPARATOR &&
612 cchPathLen > 0 && PathBuffer[cchPathLen-1] == OBJ_NAME_PATH_SEPARATOR)
613 {
614 /* PathComponent starts with '\' and PathBuffer ends with '\' */
616 ++PathComponent; // Skip any backslash
617 }
618 Status = RtlStringCchCatW(PathBuffer, cchPathSize, PathComponent);
619 if (!NT_SUCCESS(Status))
620 return Status;
621 }
622
623 return Status;
624}
625
628 OUT PWSTR PathBuffer,
629 IN SIZE_T cchPathSize,
630 IN ULONG NumberOfPathComponents,
631 IN va_list PathComponentsList)
632{
633 if (cchPathSize < 1)
634 return STATUS_SUCCESS;
635
636 *PathBuffer = UNICODE_NULL;
637 return ConcatPathsV(PathBuffer, cchPathSize,
638 NumberOfPathComponents,
639 PathComponentsList);
640}
641
644 IN OUT PWSTR PathBuffer,
645 IN SIZE_T cchPathSize,
646 IN ULONG NumberOfPathComponents,
647 IN /* PCWSTR */ ...)
648{
650 va_list PathComponentsList;
651
652 if (cchPathSize < 1)
653 return STATUS_SUCCESS;
654
655 va_start(PathComponentsList, NumberOfPathComponents);
656 Status = ConcatPathsV(PathBuffer, cchPathSize,
657 NumberOfPathComponents,
658 PathComponentsList);
659 va_end(PathComponentsList);
660
661 return Status;
662}
663
666 OUT PWSTR PathBuffer,
667 IN SIZE_T cchPathSize,
668 IN ULONG NumberOfPathComponents,
669 IN /* PCWSTR */ ...)
670{
672 va_list PathComponentsList;
673
674 if (cchPathSize < 1)
675 return STATUS_SUCCESS;
676
677 *PathBuffer = UNICODE_NULL;
678
679 va_start(PathComponentsList, NumberOfPathComponents);
680 Status = CombinePathsV(PathBuffer, cchPathSize,
681 NumberOfPathComponents,
682 PathComponentsList);
683 va_end(PathComponentsList);
684
685 return Status;
686}
687
691 _In_ PCUNICODE_STRING PathName,
693{
698
700 (PUNICODE_STRING)PathName,
703 NULL);
704
707 : FILE_GENERIC_READ, // Contains SYNCHRONIZE
714 if (NT_SUCCESS(Status))
715 {
717 }
718 else
719 {
720 DPRINT("Failed to open %s '%wZ', Status 0x%08lx\n",
721 IsDirectory ? "directory" : "file",
722 PathName, Status);
723 }
724
725 return NT_SUCCESS(Status);
726}
727
731 _In_ PCWSTR PathName,
733{
734 UNICODE_STRING PathNameU;
735 RtlInitUnicodeString(&PathNameU, PathName);
736 return DoesPathExist_UStr(RootDirectory, &PathNameU, IsDirectory);
737}
738
739// FIXME: DEPRECATED! HACKish function that needs to be deprecated!
742 IN PCWSTR PathName OPTIONAL,
744{
747 return DoesFileExist(NULL, FullName);
748}
749
750/*
751 * The format of NtPath should be:
752 * \Device\HarddiskXXX\PartitionYYY[\path] ,
753 * where XXX and YYY respectively represent the hard disk and partition numbers,
754 * and [\path] represent an optional path (separated by '\\').
755 *
756 * If a NT path of such a form is correctly parsed, the function returns respectively:
757 * - in pDiskNumber: the hard disk number XXX,
758 * - in pPartNumber: the partition number YYY,
759 * - in PathComponent: pointer value (inside NtPath) to the beginning of \path.
760 *
761 * NOTE: The function does not accept leading whitespace.
762 */
765 IN PCWSTR NtPath,
766 OUT PULONG pDiskNumber,
767 OUT PULONG pPartNumber,
769{
770 ULONG DiskNumber, PartNumber;
771 PCWSTR Path;
772
773 *pDiskNumber = 0;
774 *pPartNumber = 0;
776
777 Path = NtPath;
778
779 if (_wcsnicmp(Path, L"\\Device\\Harddisk", 16) != 0)
780 {
781 /* The NT path doesn't start with the prefix string, thus it cannot be a hard disk device path */
782 DPRINT1("'%S' : Not a possible hard disk device.\n", NtPath);
783 return FALSE;
784 }
785
786 Path += 16;
787
788 /* A number must be present now */
789 if (!iswdigit(*Path))
790 {
791 DPRINT1("'%S' : expected a number! Not a regular hard disk device.\n", Path);
792 return FALSE;
793 }
794 DiskNumber = wcstoul(Path, (PWSTR*)&Path, 10);
795
796 /* Either NULL termination, or a path separator must be present now */
798 {
799 DPRINT1("'%S' : expected a path separator!\n", Path);
800 return FALSE;
801 }
802
803 if (!*Path)
804 {
805 DPRINT1("The path only specified a hard disk (and nothing else, like a partition...), so we stop there.\n");
806 goto Quit;
807 }
808
809 /* Here, *Path == L'\\' */
810
811 if (_wcsnicmp(Path, L"\\Partition", 10) != 0)
812 {
813 /* Actually, \Partition is optional so, if we don't have it, we still return success. Or should we? */
814 DPRINT1("'%S' : unexpected format!\n", NtPath);
815 goto Quit;
816 }
817
818 Path += 10;
819
820 /* A number must be present now */
821 if (!iswdigit(*Path))
822 {
823 /* If we don't have a number it means this part of path is actually not a partition specifier, so we shouldn't fail either. Or should we? */
824 DPRINT1("'%S' : expected a number!\n", Path);
825 goto Quit;
826 }
827 PartNumber = wcstoul(Path, (PWSTR*)&Path, 10);
828
829 /* Either NULL termination, or a path separator must be present now */
831 {
832 /* We shouldn't fail here because it just means this part of path is actually not a partition specifier. Or should we? */
833 DPRINT1("'%S' : expected a path separator!\n", Path);
834 goto Quit;
835 }
836
837 /* OK, here we really have a partition specifier: return its number */
838 *pPartNumber = PartNumber;
839
840Quit:
841 /* Return the disk number */
842 *pDiskNumber = DiskNumber;
843
844 /* Return the path component also, if the user wants it */
846
847 return TRUE;
848}
849
882 _In_ PCWSTR PathNameToFile,
885 _Out_ PHANDLE SectionHandle,
887 _In_ BOOLEAN ReadWriteAccess)
888{
893 HANDLE LocalFileHandle;
894
895 /* Open the file */
896 RtlInitUnicodeString(&FileName, PathNameToFile);
898 &FileName,
901 NULL);
902
903 if (FileHandle) *FileHandle = NULL;
904 Status = NtOpenFile(&LocalFileHandle,
905 FILE_GENERIC_READ | // Contains SYNCHRONIZE
906 (ReadWriteAccess ? FILE_GENERIC_WRITE : 0),
911 if (!NT_SUCCESS(Status))
912 {
913 DPRINT1("Failed to open file '%wZ' (Status 0x%08lx)\n", &FileName, Status);
914 return Status;
915 }
916
917 if (FileSize)
918 {
919 /* Query the file size */
921 Status = NtQueryInformationFile(LocalFileHandle,
923 &FileInfo,
924 sizeof(FileInfo),
926 if (!NT_SUCCESS(Status))
927 {
928 DPRINT("NtQueryInformationFile() failed (Status 0x%08lx)\n", Status);
929 goto Quit;
930 }
931
932 if (FileInfo.EndOfFile.HighPart != 0)
933 DPRINT1("WARNING!! The file '%wZ' is too large!\n", &FileName);
934
935 *FileSize = FileInfo.EndOfFile.LowPart;
936 DPRINT("File size: %lu\n", *FileSize);
937 }
938
939 /* Map the whole file into memory */
940 Status = MapFile(LocalFileHandle,
941 SectionHandle,
943 ReadWriteAccess);
944 if (!NT_SUCCESS(Status))
945 {
946 DPRINT1("Failed to map file '%wZ' (Status 0x%08lx)\n", &FileName, Status);
947 goto Quit;
948 }
949
950Quit:
951 /* If we succeeded, return the opened file handle if needed.
952 * If we failed or the caller does not need the handle, close it now. */
954 *FileHandle = LocalFileHandle;
955 else
956 NtClose(LocalFileHandle);
957
958 return Status;
959}
960
984 _Out_ PHANDLE SectionHandle,
986 _In_ BOOLEAN ReadWriteAccess)
987{
991 PVOID ViewBase;
992
993 SectionPageProtection = (ReadWriteAccess ? PAGE_READWRITE : PAGE_READONLY);
994
995 /* Create the section */
996 *SectionHandle = NULL;
997 Status = NtCreateSection(SectionHandle,
1000 (ReadWriteAccess ? SECTION_MAP_WRITE : 0),
1001 NULL,
1002 NULL,
1004 SEC_COMMIT /* | SEC_IMAGE (_NO_EXECUTE) */,
1005 FileHandle);
1006 if (!NT_SUCCESS(Status))
1007 {
1008 DPRINT1("Failed to create a memory section for file 0x%p (Status 0x%08lx)\n",
1010 return Status;
1011 }
1012
1013 /* Map the section */
1014 ViewSize = 0;
1015 ViewBase = NULL;
1016 Status = NtMapViewOfSection(*SectionHandle,
1018 &ViewBase,
1019 0, 0,
1020 NULL,
1021 &ViewSize,
1022 ViewShare,
1023 0,
1025 if (!NT_SUCCESS(Status))
1026 {
1027 DPRINT1("Failed to map a view for file 0x%p (Status 0x%08lx)\n",
1029 NtClose(*SectionHandle);
1030 *SectionHandle = NULL;
1031 return Status;
1032 }
1033
1034 *BaseAddress = ViewBase;
1035 return STATUS_SUCCESS;
1036}
1037
1051BOOLEAN
1053 _In_ HANDLE SectionHandle,
1055{
1058
1060 if (!NT_SUCCESS(Status))
1061 {
1062 DPRINT1("NtUnmapViewOfSection(0x%p) failed (Status 0x%08lx)\n",
1064 Success = FALSE;
1065 }
1066 Status = NtClose(SectionHandle);
1067 if (!NT_SUCCESS(Status))
1068 {
1069 DPRINT1("NtClose(0x%p) failed (Status 0x%08lx)\n",
1070 SectionHandle, Status);
1071 Success = FALSE;
1072 }
1073
1074 return Success;
1075}
1076
1077static UCHAR
1079 _In_ USHORT DriveNumber)
1080{
1083
1086 &DeviceMap.Query,
1087 sizeof(DeviceMap.Query),
1088 NULL);
1089 if (NT_SUCCESS(Status) && (DeviceMap.Query.DriveMap & (1 << DriveNumber)) != 0)
1090 {
1091 UCHAR Type = DeviceMap.Query.DriveType[DriveNumber];
1092 if (Type <= DRIVE_RAMDISK)
1093 return Type;
1094 }
1095 return DRIVE_UNKNOWN;
1096}
1097
1098UCHAR
1100 _In_ USHORT DriveNumber,
1102{
1103 WCHAR szDosDevPath[] = {'\\','?','?','\\', 'A'+DriveNumber,':', UNICODE_NULL};
1104 UCHAR Type;
1105 ULONG (WINAPI *pfnQueryDosDeviceW)(PCWSTR, PWSTR, ULONG) = NULL;
1111
1112 /* Retrieve the drive type; if we fail, bail out early */
1113 Type = GetWin32DriveTypeOfDriveNumber(DriveNumber);
1114 if (Type <= DRIVE_NO_ROOT_DIR)
1115 return Type;
1116
1117 /* Lookup the drive. Use Win32 directly if available so we match UAC, etc. */
1118 RtlInitUnicodeString(&String, L"kernel32");
1120 if (NT_SUCCESS(Status))
1121 {
1122 ANSI_STRING AnsiString = RTL_CONSTANT_STRING("QueryDosDeviceW");
1123 Status = LdrGetProcedureAddress(hKernel32, &AnsiString, 0, (PVOID*)&pfnQueryDosDeviceW);
1124 }
1125 if (NT_SUCCESS(Status))
1126 {
1127 /* "+ 4" to start at the drive letter itself */
1128 ULONG cch = pfnQueryDosDeviceW(szDosDevPath + 4, DevicePath->Buffer,
1129 DevicePath->MaximumLength / sizeof(WCHAR));
1130 if (cch)
1131 {
1132 DevicePath->Length = (cch - 1) * sizeof(WCHAR);
1133 return Type;
1134 }
1135 }
1136
1137 /* Retrieve the DOS device symlink target */
1138 RtlInitUnicodeString(&String, szDosDevPath);
1141 if (NT_SUCCESS(Status))
1142 {
1146 }
1147
1148 /* Return the drive type if success, or unknown if failure */
1149 return (NT_SUCCESS(Status) ? Type : DRIVE_UNKNOWN);
1150}
1151
1152/* EOF */
NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN PVOID BaseAddress)
Definition: section.c:3498
NTSTATUS NTAPI NtCreateSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG SectionPageProtection OPTIONAL, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL)
Definition: section.c:3090
NTSTATUS NTAPI NtMapViewOfSection(_In_ HANDLE SectionHandle, _In_ HANDLE ProcessHandle, _Outptr_result_bytebuffer_(*ViewSize) _Pre_valid_ PVOID *BaseAddress, _In_ ULONG_PTR ZeroBits, _In_ SIZE_T CommitSize, _Inout_opt_ PLARGE_INTEGER SectionOffset, _Inout_ PSIZE_T ViewSize, _In_range_(ViewShare, ViewUnmap) SECTION_INHERIT InheritDisposition, _In_ ULONG AllocationType, _In_ ULONG Win32Protect)
Definition: section.c:3271
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG ReturnLength
static HANDLE DirectoryHandle
Definition: ObType.cpp:48
PRTL_UNICODE_STRING_BUFFER Path
Type
Definition: Type.h:7
unsigned char BOOLEAN
Definition: actypes.h:127
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define DPRINT1
Definition: precomp.h:8
WCHAR RootDirectory[MAX_PATH]
Definition: format.c:73
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:616
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
#define ARRAYSIZE(a)
Definition: cat.c:25
Definition: bufpool.h:45
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
_In_ PIO_STATUS_BLOCK IoStatusBlock
Definition: dispmprt.h:608
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define PAGE_READONLY
Definition: compat.h:138
#define SECTION_MAP_READ
Definition: compat.h:139
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
#define SYMBOLIC_LINK_QUERY
Definition: volume.c:47
_ACRTIMP __msvcrt_ulong __cdecl wcstoul(const wchar_t *, wchar_t **, int)
Definition: wcs.c:2917
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
_ACRTIMP int __cdecl _wcsnicmp(const wchar_t *, const wchar_t *, size_t)
Definition: wcs.c:200
#define va_end(v)
Definition: stdarg.h:28
#define va_arg(v, l)
Definition: stdarg.h:27
#define va_start(v, l)
Definition: stdarg.h:26
char * va_list
Definition: vadefs.h:50
@ AnsiString
Definition: dnslib.h:19
#define L(x)
Definition: resources.c:13
#define ULONG_PTR
Definition: config.h:101
@ Success
Definition: eventcreate.c:712
#define IsDirectory(Fcb)
Definition: ext2fs.h:283
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:732
struct _FileName FileName
Definition: fatprocs.h:897
BOOLEAN DoesPathExist(_In_opt_ HANDLE RootDirectory, _In_ PCWSTR PathName, _In_ BOOLEAN IsDirectory)
Definition: filesup.c:729
NTSTATUS CombinePaths(OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN ...)
Definition: filesup.c:665
NTSTATUS MapFile(_In_ HANDLE FileHandle, _Out_ PHANDLE SectionHandle, _Out_ PVOID *BaseAddress, _In_ BOOLEAN ReadWriteAccess)
Maps an opened file in memory.
Definition: filesup.c:982
UCHAR GetNtDevicePathOfDriveNumber(_In_ USHORT DriveNumber, _Out_ PUNICODE_STRING DevicePath)
Definition: filesup.c:1099
static NTSTATUS SetupCreateSingleDirectory(_In_ PCUNICODE_STRING DirectoryName)
Definition: filesup.c:23
BOOLEAN DoesFileExist_2(IN PCWSTR PathName OPTIONAL, IN PCWSTR FileName)
Definition: filesup.c:741
BOOLEAN NtPathToDiskPartComponents(IN PCWSTR NtPath, OUT PULONG pDiskNumber, OUT PULONG pPartNumber, OUT PCWSTR *PathComponent OPTIONAL)
Definition: filesup.c:764
NTSTATUS OpenAndMapFile(_In_opt_ HANDLE RootDirectory, _In_ PCWSTR PathNameToFile, _Out_opt_ PHANDLE FileHandle, _Out_opt_ PULONG FileSize, _Out_ PHANDLE SectionHandle, _Out_ PVOID *BaseAddress, _In_ BOOLEAN ReadWriteAccess)
Opens and maps a file in memory.
Definition: filesup.c:880
NTSTATUS ConcatPathsV(IN OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN va_list PathComponentsList)
Definition: filesup.c:580
NTSTATUS CombinePathsV(OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN va_list PathComponentsList)
Definition: filesup.c:627
NTSTATUS SetupMoveFile(IN PCWSTR ExistingFileName, IN PCWSTR NewFileName, IN ULONG Flags)
Definition: filesup.c:464
NTSTATUS SetupCreateDirectory(_In_ PCWSTR PathName)
Create a new directory, specified by the given path. Any intermediate non-existing directory is creat...
Definition: filesup.c:73
NTSTATUS ConcatPaths(IN OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN ...)
Definition: filesup.c:643
BOOLEAN UnMapFile(_In_ HANDLE SectionHandle, _In_ PVOID BaseAddress)
Unmaps a mapped file by section.
Definition: filesup.c:1052
static UCHAR GetWin32DriveTypeOfDriveNumber(_In_ USHORT DriveNumber)
Definition: filesup.c:1078
NTSTATUS SetupCopyFile(IN PCWSTR SourceFileName, IN PCWSTR DestinationFileName, IN BOOLEAN FailIfExists)
Definition: filesup.c:224
NTSTATUS SetupDeleteFile(IN PCWSTR FileName, IN BOOLEAN ForceDelete)
Definition: filesup.c:135
BOOLEAN DoesPathExist_UStr(_In_opt_ HANDLE RootDirectory, _In_ PCUNICODE_STRING PathName, _In_ BOOLEAN IsDirectory)
Definition: filesup.c:689
#define MOVEFILE_WRITE_THROUGH
Definition: filesup.h:30
#define MOVEFILE_REPLACE_EXISTING
Definition: filesup.h:28
#define DoesFileExist(RootDirectory, FileName)
Definition: filesup.h:83
#define MOVEFILE_COPY_ALLOWED
Definition: filesup.h:29
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
@ FileEndOfFileInformation
Definition: from_kernel.h:81
@ FileRenameInformation
Definition: from_kernel.h:71
@ FileBasicInformation
Definition: from_kernel.h:65
@ FileDispositionInformation
Definition: from_kernel.h:74
#define FILE_OPEN
Definition: from_kernel.h:54
#define FILE_CREATE
Definition: from_kernel.h:55
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define FILE_NO_INTERMEDIATE_BUFFERING
Definition: from_kernel.h:28
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define FILE_SEQUENTIAL_ONLY
Definition: from_kernel.h:27
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI LdrGetDllHandle(_In_opt_ PWSTR DllPath, _In_opt_ PULONG DllCharacteristics, _In_ PUNICODE_STRING DllName, _Out_ PVOID *DllHandle)
Definition: ldrapi.c:770
NTSTATUS NTAPI LdrGetProcedureAddress(_In_ PVOID BaseAddress, _In_opt_ _When_(Ordinal==0, _Notnull_) PANSI_STRING Name, _In_opt_ _When_(Name==NULL, _In_range_(>, 0)) ULONG Ordinal, _Out_ PVOID *ProcedureAddress)
Definition: ldrapi.c:789
@ FileBasicInfo
Definition: minwinbase.h:304
#define ASSERT(a)
Definition: mode.c:44
HANDLE hKernel32
Definition: locale.c:13
#define ULL(a, b)
Definition: format_msg.c:27
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
#define min(a, b)
Definition: monoChain.cc:55
_In_ PIOMMU_DEVICE_PATH _In_ PIOMMU_SVM_CAPABILITIES _Out_ PVOID * DeviceHandle
Definition: haltypes.h:1826
_In_ PIOMMU_DEVICE_PATH DevicePath
Definition: haltypes.h:1823
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG SectionPageProtection
Definition: mmfuncs.h:367
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID * BaseAddress
Definition: mmfuncs.h:408
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:412
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:176
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
#define SEC_COMMIT
Definition: mmtypes.h:100
_In_ HANDLE SourceHandle
Definition: obfuncs.h:438
#define _Out_opt_
Definition: no_sal2.h:214
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3951
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define SECTION_MAP_WRITE
Definition: nt_native.h:1291
#define PAGE_READWRITE
Definition: nt_native.h:1307
NTSYSAPI NTSTATUS NTAPI NtWriteFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID WriteBuffer, IN ULONG WriteBufferLength, IN PLARGE_INTEGER FileOffset OPTIONAL, IN PULONG LockOperationKey OPTIONAL)
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
#define SECTION_QUERY
Definition: nt_native.h:1290
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define NtCurrentProcess()
Definition: nt_native.h:1660
NTSYSAPI NTSTATUS NTAPI NtSetInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
Definition: iofunc.c:3096
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
@ ViewUnmap
Definition: nt_native.h:1282
@ ViewShare
Definition: nt_native.h:1281
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3429
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define DELETE
Definition: nt_native.h:57
NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength)
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FILE_GENERIC_READ
Definition: nt_native.h:653
#define FILE_GENERIC_WRITE
Definition: nt_native.h:660
#define STANDARD_RIGHTS_REQUIRED
Definition: nt_native.h:63
CONST WCHAR * PCWCH
Definition: ntbasedef.h:423
#define UNICODE_NULL
static OUT PIO_STATUS_BLOCK OUT PVOID FileInformation
Definition: pipe.c:100
NTSTATUS NTAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_writes_bytes_to_opt_(ProcessInformationLength, *ReturnLength) PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:211
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_NOT_SAME_DEVICE
Definition: ntstatus.h:542
NTSTRSAFEAPI RtlStringCchCatW(_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:601
short WCHAR
Definition: pedump.c:58
unsigned short USHORT
Definition: pedump.c:61
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define _SEH2_FINALLY
Definition: pseh2_64.h:153
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define _SEH2_LEAVE
Definition: pseh2_64.h:206
#define iswdigit(_c)
Definition: ctype.h:667
_In_ UINT _In_ UINT cch
Definition: shellapi.h:432
#define FileStandardInformation
Definition: propsheet.cpp:61
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
struct _PROCESS_DEVICEMAP_INFORMATION::@5116::@5118 Query
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
unsigned char UCHAR
Definition: typedefs.h:53
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
struct _LARGE_INTEGER::@2736 u
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2439
#define DRIVE_UNKNOWN
Definition: winbase.h:281
#define DRIVE_NO_ROOT_DIR
Definition: winbase.h:282
#define DRIVE_RAMDISK
Definition: winbase.h:280
#define WINAPI
Definition: msvc.h:6
@ ProcessDeviceMap
Definition: winternl.h:1905
_In_ PSTRING FullName
Definition: rtlfuncs.h:1665