ReactOS  0.4.14-dev-608-gd495a4f
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 
14 #define NDEBUG
15 #include <debug.h>
16 
17 
18 // ACHTUNG! HAXX FIXME!!
19 #define _SEH2_TRY
20 #define _SEH2_LEAVE goto __SEH2_FINALLY__label;
21 #define _SEH2_FINALLY __SEH2_FINALLY__label:
22 #define _SEH2_END
23 
24 
25 /* FUNCTIONS ****************************************************************/
26 
27 static
30  IN PCWSTR DirectoryName)
31 {
34  UNICODE_STRING PathName;
37 
38  if (!RtlCreateUnicodeString(&PathName, DirectoryName))
39  return STATUS_NO_MEMORY;
40 
41  if (PathName.Length > sizeof(WCHAR) &&
42  PathName.Buffer[PathName.Length / sizeof(WCHAR) - 2] == L'\\' &&
43  PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'.')
44  {
45  PathName.Length -= sizeof(WCHAR);
46  PathName.Buffer[PathName.Length / sizeof(WCHAR)] = UNICODE_NULL;
47  }
48 
49  if (PathName.Length > sizeof(WCHAR) &&
50  PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'\\')
51  {
52  PathName.Length -= sizeof(WCHAR);
53  PathName.Buffer[PathName.Length / sizeof(WCHAR)] = UNICODE_NULL;
54  }
55 
57  &PathName,
59  NULL,
60  NULL);
61 
66  NULL,
71  NULL,
72  0);
73  if (NT_SUCCESS(Status))
74  {
76  }
77 
78  RtlFreeUnicodeString(&PathName);
79 
80  return Status;
81 }
82 
85  IN PCWSTR PathName)
86 {
88  PWCHAR PathBuffer = NULL;
89  PWCHAR Ptr, EndPtr;
90  ULONG BackslashCount;
91  ULONG Size;
92 
93  Size = (wcslen(PathName) + 1) * sizeof(WCHAR);
94  PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Size);
95  if (PathBuffer == NULL)
97 
98  wcscpy(PathBuffer, PathName);
99  EndPtr = PathBuffer + wcslen(PathName);
100 
101  Ptr = PathBuffer;
102 
103  /* Skip the '\Device\HarddiskX\PartitionY\ part */
104  BackslashCount = 0;
105  while (Ptr < EndPtr && BackslashCount < 4)
106  {
107  if (*Ptr == L'\\')
108  BackslashCount++;
109 
110  Ptr++;
111  }
112 
113  while (Ptr < EndPtr)
114  {
115  if (*Ptr == L'\\')
116  {
117  *Ptr = 0;
118 
119  DPRINT("PathBuffer: %S\n", PathBuffer);
120  if (!DoesDirExist(NULL, PathBuffer))
121  {
122  DPRINT("Create: %S\n", PathBuffer);
123  Status = SetupCreateSingleDirectory(PathBuffer);
124  if (!NT_SUCCESS(Status))
125  goto done;
126  }
127 
128  *Ptr = L'\\';
129  }
130 
131  Ptr++;
132  }
133 
134  if (!DoesDirExist(NULL, PathBuffer))
135  {
136  DPRINT("Create: %S\n", PathBuffer);
137  Status = SetupCreateSingleDirectory(PathBuffer);
138  if (!NT_SUCCESS(Status))
139  goto done;
140  }
141 
142 done:
143  DPRINT("Done.\n");
144  if (PathBuffer != NULL)
145  RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
146 
147  return Status;
148 }
149 
150 NTSTATUS
153  IN BOOLEAN ForceDelete) // ForceDelete can be used to delete read-only files
154 {
156  UNICODE_STRING NtPathU;
160  FILE_DISPOSITION_INFORMATION FileDispInfo;
161  BOOLEAN RetryOnce = FALSE;
162 
163  /* Open the directory name that was passed in */
164  RtlInitUnicodeString(&NtPathU, FileName);
166  &NtPathU,
168  NULL,
169  NULL);
170 
171 Retry: // We go back there once if RetryOnce == TRUE
174  (RetryOnce ? FILE_WRITE_ATTRIBUTES : 0),
176  &IoStatusBlock,
179  if (!NT_SUCCESS(Status))
180  {
181  DPRINT1("NtOpenFile failed with Status 0x%08lx\n", Status);
182  return Status;
183  }
184 
185  if (RetryOnce)
186  {
188 
190  &IoStatusBlock,
192  sizeof(FILE_BASIC_INFORMATION),
194  if (!NT_SUCCESS(Status))
195  {
196  DPRINT1("NtQueryInformationFile failed with Status 0x%08lx\n", Status);
198  return Status;
199  }
200 
201  FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
203  &IoStatusBlock,
205  sizeof(FILE_BASIC_INFORMATION),
208  if (!NT_SUCCESS(Status))
209  {
210  DPRINT1("NtSetInformationFile failed with Status 0x%08lx\n", Status);
211  return Status;
212  }
213  }
214 
215  /* Ask for the file to be deleted */
216  FileDispInfo.DeleteFile = TRUE;
218  &IoStatusBlock,
219  &FileDispInfo,
223 
224  if (!NT_SUCCESS(Status))
225  DPRINT1("Deletion of file '%S' failed, Status 0x%08lx\n", FileName, Status);
226 
227  // FIXME: Check the precise value of Status!
228  if (!NT_SUCCESS(Status) && ForceDelete && !RetryOnce)
229  {
230  /* Retry once */
231  RetryOnce = TRUE;
232  goto Retry;
233  }
234 
235  /* Return result to the caller */
236  return Status;
237 }
238 
239 NTSTATUS
241  IN PCWSTR SourceFileName,
242  IN PCWSTR DestinationFileName,
243  IN BOOLEAN FailIfExists)
244 {
248  HANDLE FileHandleSource;
249  HANDLE FileHandleDest;
251  FILE_STANDARD_INFORMATION FileStandard;
252  FILE_BASIC_INFORMATION FileBasic;
254  HANDLE SourceFileSection;
255  PVOID SourceFileMap = NULL;
256  SIZE_T SourceSectionSize = 0;
258 
259  RtlInitUnicodeString(&FileName, SourceFileName);
261  &FileName,
263  NULL,
264  NULL);
265 
266  Status = NtOpenFile(&FileHandleSource,
267  GENERIC_READ,
269  &IoStatusBlock,
272  if (!NT_SUCCESS(Status))
273  {
274  DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName);
275  goto done;
276  }
277 
278  Status = NtQueryInformationFile(FileHandleSource,
279  &IoStatusBlock,
280  &FileStandard,
283  if (!NT_SUCCESS(Status))
284  {
285  DPRINT1("NtQueryInformationFile failed: %x\n", Status);
286  goto closesrc;
287  }
288 
289  Status = NtQueryInformationFile(FileHandleSource,
290  &IoStatusBlock,
291  &FileBasic,
292  sizeof(FILE_BASIC_INFORMATION),
294  if (!NT_SUCCESS(Status))
295  {
296  DPRINT1("NtQueryInformationFile failed: %x\n", Status);
297  goto closesrc;
298  }
299 
300  Status = NtCreateSection(&SourceFileSection,
302  NULL,
303  NULL,
305  SEC_COMMIT,
306  FileHandleSource);
307  if (!NT_SUCCESS(Status))
308  {
309  DPRINT1("NtCreateSection failed: %x, %S\n", Status, SourceFileName);
310  goto closesrc;
311  }
312 
313  Status = NtMapViewOfSection(SourceFileSection,
315  &SourceFileMap,
316  0,
317  0,
318  NULL,
319  &SourceSectionSize,
320  ViewUnmap,
321  0,
322  PAGE_READONLY);
323  if (!NT_SUCCESS(Status))
324  {
325  DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status, SourceFileName);
326  goto closesrcsec;
327  }
328 
329  RtlInitUnicodeString(&FileName, DestinationFileName);
331  &FileName,
333  NULL,
334  NULL);
335 
336  Status = NtCreateFile(&FileHandleDest,
339  &IoStatusBlock,
340  NULL,
341  FileBasic.FileAttributes, // FILE_ATTRIBUTE_NORMAL,
342  0,
343  FailIfExists ? FILE_CREATE : FILE_OVERWRITE_IF,
347  NULL,
348  0);
349  if (!NT_SUCCESS(Status))
350  {
351  /*
352  * Open may have failed because the file to overwrite
353  * is in readonly mode.
354  */
356  {
357  FILE_BASIC_INFORMATION FileBasicInfo;
358 
359  /* Reattempt to open it with limited access */
360  Status = NtCreateFile(&FileHandleDest,
363  &IoStatusBlock,
364  NULL,
366  0,
367  FILE_OPEN,
371  NULL,
372  0);
373  /* Fail for real if we cannot open it that way */
374  if (!NT_SUCCESS(Status))
375  {
376  DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName);
377  goto unmapsrcsec;
378  }
379 
380  /* Zero our basic info, just to set attributes */
381  RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
382  /* Reset attributes to normal, no read-only */
383  FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
384  /*
385  * We basically don't care about whether it succeed:
386  * if it didn't, later open will fail.
387  */
388  NtSetInformationFile(FileHandleDest, &IoStatusBlock, &FileBasicInfo,
389  sizeof(FileBasicInfo), FileBasicInformation);
390 
391  /* Close file */
392  NtClose(FileHandleDest);
393 
394  /* And re-attempt overwrite */
395  Status = NtCreateFile(&FileHandleDest,
398  &IoStatusBlock,
399  NULL,
401  0,
406  NULL,
407  0);
408  }
409 
410  /* We failed */
411  if (!NT_SUCCESS(Status))
412  {
413  DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName);
414  goto unmapsrcsec;
415  }
416  }
417 
418  RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
419  IoStatusBlock.Status = 0;
420  ByteOffset.QuadPart = 0ULL;
421  Status = NtWriteFile(FileHandleDest,
422  NULL,
423  NULL,
424  NULL,
425  &IoStatusBlock,
426  SourceFileMap,
427  RegionSize,
428  &ByteOffset,
429  NULL);
430  if (!NT_SUCCESS(Status))
431  {
432  DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n",
433  Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize);
434  goto closedest;
435  }
436 
437  /* Copy file date/time from source file */
438  Status = NtSetInformationFile(FileHandleDest,
439  &IoStatusBlock,
440  &FileBasic,
441  sizeof(FILE_BASIC_INFORMATION),
443  if (!NT_SUCCESS(Status))
444  {
445  DPRINT1("NtSetInformationFile failed: %x\n", Status);
446  goto closedest;
447  }
448 
449  /* Shorten the file back to its real size after completing the write */
450  Status = NtSetInformationFile(FileHandleDest,
451  &IoStatusBlock,
452  &FileStandard.EndOfFile,
455  if (!NT_SUCCESS(Status))
456  {
457  DPRINT1("NtSetInformationFile failed: %x\n", Status);
458  }
459 
460 closedest:
461  NtClose(FileHandleDest);
462 
463 unmapsrcsec:
464  NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap);
465 
466 closesrcsec:
467  NtClose(SourceFileSection);
468 
469 closesrc:
470  NtClose(FileHandleSource);
471 
472 done:
473  return Status;
474 }
475 
476 /*
477  * Synchronized with its kernel32 counterpart, but we don't manage reparse points here.
478  */
479 NTSTATUS
481  IN PCWSTR ExistingFileName,
482  IN PCWSTR NewFileName,
483  IN ULONG Flags)
484 {
488  PFILE_RENAME_INFORMATION RenameInfo;
489  UNICODE_STRING NewPathU, ExistingPathU;
491  BOOLEAN ReplaceIfExists;
492 
493  RtlInitUnicodeString(&ExistingPathU, ExistingFileName);
494  RtlInitUnicodeString(&NewPathU, NewFileName);
495 
496  _SEH2_TRY
497  {
498  ReplaceIfExists = !!(Flags & MOVEFILE_REPLACE_EXISTING);
499 
500  /* Unless we manage a proper opening, we'll attempt to reopen without reparse support */
502  &ExistingPathU,
504  NULL,
505  NULL);
506  /* Attempt to open source file */
510  &IoStatusBlock,
513  if (!NT_SUCCESS(Status))
514  {
516  {
517  _SEH2_LEAVE;
518  }
519  }
520 
521  /* At that point, we MUST have a source handle */
523 
524  /* Allocate renaming buffer and fill it */
525  RenameInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewPathU.Length + sizeof(FILE_RENAME_INFORMATION));
526  if (RenameInfo == NULL)
527  {
529  _SEH2_LEAVE;
530  }
531 
532  RtlCopyMemory(&RenameInfo->FileName, NewPathU.Buffer, NewPathU.Length);
533  RenameInfo->ReplaceIfExists = ReplaceIfExists;
534  RenameInfo->RootDirectory = NULL;
535  RenameInfo->FileNameLength = NewPathU.Length;
536 
537  /* Attempt to rename the file */
539  &IoStatusBlock,
540  RenameInfo,
541  NewPathU.Length + sizeof(FILE_RENAME_INFORMATION),
543  RtlFreeHeap(RtlGetProcessHeap(), 0, RenameInfo);
544  if (NT_SUCCESS(Status))
545  {
546  /* If it succeeded, all fine, quit */
547  _SEH2_LEAVE;
548  }
549  /*
550  * If we failed for any other reason than not the same device, fail.
551  * If we failed because of different devices, only allow renaming
552  * if user allowed copy.
553  */
555  {
556  /* ReactOS hack! To be removed once all FSD have proper renaming support
557  * Just leave status to error and leave
558  */
560  {
561  DPRINT1("Forcing copy, renaming not supported by FSD\n");
562  }
563  else
564  {
565  _SEH2_LEAVE;
566  }
567  }
568 
569  /* Close the source file */
571  SourceHandle = NULL;
572 
573  /* Perform the file copy */
574  Status = SetupCopyFile(ExistingFileName,
575  NewFileName,
576  !ReplaceIfExists);
577 
578  /* If it succeeded, delete the source file */
579  if (NT_SUCCESS(Status))
580  {
581  /* Force-delete files even if read-only */
582  SetupDeleteFile(ExistingFileName, TRUE);
583  }
584  }
586  {
587  if (SourceHandle)
589  }
590  _SEH2_END;
591 
592  return Status;
593 }
594 
595 NTSTATUS
597  IN OUT PWSTR PathBuffer,
598  IN SIZE_T cchPathSize,
599  IN ULONG NumberOfPathComponents,
600  IN va_list PathComponentsList)
601 {
603  SIZE_T cchPathLen;
605 
606  if (cchPathSize < 1)
607  return STATUS_SUCCESS;
608 
609  while (NumberOfPathComponents--)
610  {
611  PathComponent = va_arg(PathComponentsList, PCWSTR);
612  if (!PathComponent)
613  continue;
614 
615  cchPathLen = min(cchPathSize, wcslen(PathBuffer));
616  if (cchPathLen >= cchPathSize)
617  return STATUS_BUFFER_OVERFLOW;
618 
620  cchPathLen > 0 && PathBuffer[cchPathLen-1] != OBJ_NAME_PATH_SEPARATOR)
621  {
622  /* PathComponent does not start with '\' and PathBuffer does not end with '\' */
623  Status = RtlStringCchCatW(PathBuffer, cchPathSize, L"\\");
624  if (!NT_SUCCESS(Status))
625  return Status;
626  }
627  else if (PathComponent[0] == OBJ_NAME_PATH_SEPARATOR &&
628  cchPathLen > 0 && PathBuffer[cchPathLen-1] == OBJ_NAME_PATH_SEPARATOR)
629  {
630  /* PathComponent starts with '\' and PathBuffer ends with '\' */
632  ++PathComponent; // Skip any backslash
633  }
634  Status = RtlStringCchCatW(PathBuffer, cchPathSize, PathComponent);
635  if (!NT_SUCCESS(Status))
636  return Status;
637  }
638 
639  return Status;
640 }
641 
642 NTSTATUS
644  OUT PWSTR PathBuffer,
645  IN SIZE_T cchPathSize,
646  IN ULONG NumberOfPathComponents,
647  IN va_list PathComponentsList)
648 {
649  if (cchPathSize < 1)
650  return STATUS_SUCCESS;
651 
652  *PathBuffer = UNICODE_NULL;
653  return ConcatPathsV(PathBuffer, cchPathSize,
654  NumberOfPathComponents,
655  PathComponentsList);
656 }
657 
658 NTSTATUS
660  IN OUT PWSTR PathBuffer,
661  IN SIZE_T cchPathSize,
662  IN ULONG NumberOfPathComponents,
663  IN /* PCWSTR */ ...)
664 {
666  va_list PathComponentsList;
667 
668  if (cchPathSize < 1)
669  return STATUS_SUCCESS;
670 
671  va_start(PathComponentsList, NumberOfPathComponents);
672  Status = ConcatPathsV(PathBuffer, cchPathSize,
673  NumberOfPathComponents,
674  PathComponentsList);
675  va_end(PathComponentsList);
676 
677  return Status;
678 }
679 
680 NTSTATUS
682  OUT PWSTR PathBuffer,
683  IN SIZE_T cchPathSize,
684  IN ULONG NumberOfPathComponents,
685  IN /* PCWSTR */ ...)
686 {
688  va_list PathComponentsList;
689 
690  if (cchPathSize < 1)
691  return STATUS_SUCCESS;
692 
693  *PathBuffer = UNICODE_NULL;
694 
695  va_start(PathComponentsList, NumberOfPathComponents);
696  Status = CombinePathsV(PathBuffer, cchPathSize,
697  NumberOfPathComponents,
698  PathComponentsList);
699  va_end(PathComponentsList);
700 
701  return Status;
702 }
703 
704 BOOLEAN
707  IN PCWSTR PathName,
709 {
715 
716  RtlInitUnicodeString(&Name, PathName);
718  &Name,
721  NULL);
722 
725  : FILE_GENERIC_READ, // Contains SYNCHRONIZE
727  &IoStatusBlock,
732  if (NT_SUCCESS(Status))
733  {
735  }
736  else
737  {
738  DPRINT("Failed to open %s '%wZ', Status 0x%08lx\n",
739  IsDirectory ? "directory" : "file",
740  &Name, Status);
741  }
742 
743  return NT_SUCCESS(Status);
744 }
745 
746 // FIXME: DEPRECATED! HACKish function that needs to be deprecated!
747 BOOLEAN
749  IN PCWSTR PathName OPTIONAL,
751 {
754  return DoesFileExist(NULL, FullName);
755 }
756 
757 /*
758  * The format of NtPath should be:
759  * \Device\HarddiskXXX\PartitionYYY[\path] ,
760  * where XXX and YYY respectively represent the hard disk and partition numbers,
761  * and [\path] represent an optional path (separated by '\\').
762  *
763  * If a NT path of such a form is correctly parsed, the function returns respectively:
764  * - in pDiskNumber: the hard disk number XXX,
765  * - in pPartNumber: the partition number YYY,
766  * - in PathComponent: pointer value (inside NtPath) to the beginning of \path.
767  *
768  * NOTE: The function does not accept leading whitespace.
769  */
770 BOOLEAN
772  IN PCWSTR NtPath,
773  OUT PULONG pDiskNumber,
774  OUT PULONG pPartNumber,
776 {
777  ULONG DiskNumber, PartNumber;
778  PCWSTR Path;
779 
780  *pDiskNumber = 0;
781  *pPartNumber = 0;
783 
784  Path = NtPath;
785 
786  if (_wcsnicmp(Path, L"\\Device\\Harddisk", 16) != 0)
787  {
788  /* The NT path doesn't start with the prefix string, thus it cannot be a hard disk device path */
789  DPRINT1("'%S' : Not a possible hard disk device.\n", NtPath);
790  return FALSE;
791  }
792 
793  Path += 16;
794 
795  /* A number must be present now */
796  if (!iswdigit(*Path))
797  {
798  DPRINT1("'%S' : expected a number! Not a regular hard disk device.\n", Path);
799  return FALSE;
800  }
801  DiskNumber = wcstoul(Path, (PWSTR*)&Path, 10);
802 
803  /* Either NULL termination, or a path separator must be present now */
804  if (*Path && *Path != OBJ_NAME_PATH_SEPARATOR)
805  {
806  DPRINT1("'%S' : expected a path separator!\n", Path);
807  return FALSE;
808  }
809 
810  if (!*Path)
811  {
812  DPRINT1("The path only specified a hard disk (and nothing else, like a partition...), so we stop there.\n");
813  goto Quit;
814  }
815 
816  /* Here, *Path == L'\\' */
817 
818  if (_wcsnicmp(Path, L"\\Partition", 10) != 0)
819  {
820  /* Actually, \Partition is optional so, if we don't have it, we still return success. Or should we? */
821  DPRINT1("'%S' : unexpected format!\n", NtPath);
822  goto Quit;
823  }
824 
825  Path += 10;
826 
827  /* A number must be present now */
828  if (!iswdigit(*Path))
829  {
830  /* 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? */
831  DPRINT1("'%S' : expected a number!\n", Path);
832  goto Quit;
833  }
834  PartNumber = wcstoul(Path, (PWSTR*)&Path, 10);
835 
836  /* Either NULL termination, or a path separator must be present now */
837  if (*Path && *Path != OBJ_NAME_PATH_SEPARATOR)
838  {
839  /* We shouldn't fail here because it just means this part of path is actually not a partition specifier. Or should we? */
840  DPRINT1("'%S' : expected a path separator!\n", Path);
841  goto Quit;
842  }
843 
844  /* OK, here we really have a partition specifier: return its number */
845  *pPartNumber = PartNumber;
846 
847 Quit:
848  /* Return the disk number */
849  *pDiskNumber = DiskNumber;
850 
851  /* Return the path component also, if the user wants it */
853 
854  return TRUE;
855 }
856 
857 NTSTATUS
860  IN PCWSTR PathNameToFile,
861  OUT PHANDLE FileHandle, // IN OUT PHANDLE OPTIONAL
862  OUT PHANDLE SectionHandle,
865  IN BOOLEAN ReadWriteAccess)
866 {
873  PVOID ViewBase;
874 
875  /* Open the file */
876 
877  RtlInitUnicodeString(&FileName, PathNameToFile);
879  &FileName,
882  NULL);
883 
884  *FileHandle = NULL;
885  *SectionHandle = NULL;
886 
888  FILE_GENERIC_READ | // Contains SYNCHRONIZE
889  (ReadWriteAccess ? FILE_GENERIC_WRITE : 0),
891  &IoStatusBlock,
894  if (!NT_SUCCESS(Status))
895  {
896  DPRINT1("Failed to open file '%wZ', Status 0x%08lx\n", &FileName, Status);
897  return Status;
898  }
899 
900  if (FileSize)
901  {
902  /* Query the file size */
905  &IoStatusBlock,
906  &FileInfo,
907  sizeof(FileInfo),
909  if (!NT_SUCCESS(Status))
910  {
911  DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
913  *FileHandle = NULL;
914  return Status;
915  }
916 
917  if (FileInfo.EndOfFile.HighPart != 0)
918  DPRINT1("WARNING!! The file '%wZ' is too large!\n", &FileName);
919 
920  *FileSize = FileInfo.EndOfFile.LowPart;
921 
922  DPRINT("File size: %lu\n", *FileSize);
923  }
924 
925  /* Map the file in memory */
926 
927  SectionPageProtection = (ReadWriteAccess ? PAGE_READWRITE : PAGE_READONLY);
928 
929  /* Create the section */
930  Status = NtCreateSection(SectionHandle,
933  (ReadWriteAccess ? SECTION_MAP_WRITE : 0),
934  NULL,
935  NULL,
937  SEC_COMMIT /* | SEC_IMAGE (_NO_EXECUTE) */,
938  *FileHandle);
939  if (!NT_SUCCESS(Status))
940  {
941  DPRINT1("Failed to create a memory section for file '%wZ', Status 0x%08lx\n", &FileName, Status);
943  *FileHandle = NULL;
944  return Status;
945  }
946 
947  /* Map the section */
948  ViewSize = 0;
949  ViewBase = NULL;
950  Status = NtMapViewOfSection(*SectionHandle,
952  &ViewBase,
953  0, 0,
954  NULL,
955  &ViewSize,
956  ViewShare,
957  0,
959  if (!NT_SUCCESS(Status))
960  {
961  DPRINT1("Failed to map a view for file '%wZ', Status 0x%08lx\n", &FileName, Status);
962  NtClose(*SectionHandle);
963  *SectionHandle = NULL;
965  *FileHandle = NULL;
966  return Status;
967  }
968 
969  *BaseAddress = ViewBase;
970  return STATUS_SUCCESS;
971 }
972 
973 BOOLEAN
975  IN HANDLE SectionHandle,
977 {
979  BOOLEAN Success = TRUE;
980 
982  if (!NT_SUCCESS(Status))
983  {
984  DPRINT1("UnMapFile: NtUnmapViewOfSection(0x%p) failed with Status 0x%08lx\n",
986  Success = FALSE;
987  }
988  Status = NtClose(SectionHandle);
989  if (!NT_SUCCESS(Status))
990  {
991  DPRINT1("UnMapFile: NtClose(0x%p) failed with Status 0x%08lx\n",
992  SectionHandle, Status);
993  Success = FALSE;
994  }
995 
996  return Success;
997 }
998 
999 /* EOF */
struct _LARGE_INTEGER::@2220 u
#define FILE_GENERIC_READ
Definition: nt_native.h:653
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IN
Definition: typedefs.h:38
#define FILE_SEQUENTIAL_ONLY
Definition: from_kernel.h:27
NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN PVOID BaseAddress)
Definition: section.c:3782
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI NtSetInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass)
#define FILE_OPEN_IF
Definition: from_kernel.h:56
WCHAR RootDirectory[MAX_PATH]
Definition: format.c:74
#define STATUS_NOT_SAME_DEVICE
Definition: ntstatus.h:434
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:3373
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define MOVEFILE_REPLACE_EXISTING
Definition: filesup.h:28
BOOLEAN DoesPathExist(IN HANDLE RootDirectory OPTIONAL, IN PCWSTR PathName, IN BOOLEAN IsDirectory)
Definition: filesup.c:705
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint16_t * PWSTR
Definition: typedefs.h:54
BOOLEAN UnMapFile(IN HANDLE SectionHandle, IN PVOID BaseAddress)
Definition: filesup.c:974
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
BOOLEAN DoesFileExist_2(IN PCWSTR PathName OPTIONAL, IN PCWSTR FileName)
Definition: filesup.c:748
NTSTATUS SetupDeleteFile(IN PCWSTR FileName, IN BOOLEAN ForceDelete)
Definition: filesup.c:151
#define MOVEFILE_COPY_ALLOWED
Definition: filesup.h:29
#define SECTION_QUERY
Definition: nt_native.h:1287
#define iswdigit(_c)
Definition: ctype.h:667
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define FILE_CREATE
Definition: from_kernel.h:55
NTSTATUS SetupCopyFile(IN PCWSTR SourceFileName, IN PCWSTR DestinationFileName, IN BOOLEAN FailIfExists)
Definition: filesup.c:240
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
static HANDLE DirectoryHandle
Definition: ObType.c:48
static OUT PIO_STATUS_BLOCK OUT PVOID FileInformation
Definition: pipe.c:75
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
NTSTATUS ConcatPaths(IN OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN ...)
Definition: filesup.c:659
uint16_t * PWCHAR
Definition: typedefs.h:54
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
_In_ HANDLE SourceHandle
Definition: obfuncs.h:429
#define PAGE_ROUND_UP(x)
Definition: scsiport_int.h:13
NTSTATUS CombinePathsV(OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN va_list PathComponentsList)
Definition: filesup.c:643
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FILE_SHARE_READ
Definition: compat.h:125
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ PLARGE_INTEGER _In_ ULONG SectionPageProtection
Definition: mmfuncs.h:360
HANDLE FileHandle
Definition: stats.c:38
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FILE_NO_INTERMEDIATE_BUFFERING
Definition: from_kernel.h:28
#define SEC_COMMIT
Definition: mmtypes.h:99
#define va_end(ap)
Definition: acmsvcex.h:90
NTSTATUS SetupMoveFile(IN PCWSTR ExistingFileName, IN PCWSTR NewFileName, IN ULONG Flags)
Definition: filesup.c:480
#define UNICODE_NULL
#define MOVEFILE_WRITE_THROUGH
Definition: filesup.h:30
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
NTSTATUS SetupCreateDirectory(IN PCWSTR PathName)
Definition: filesup.c:84
#define _SEH2_FINALLY
Definition: filesup.c:21
#define GENERIC_WRITE
Definition: nt_native.h:90
struct NameRec_ * Name
Definition: cdprocs.h:464
NTSTATUS NTAPI NtMapViewOfSection(IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:3554
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
char * va_list
Definition: acmsvcex.h:78
void DPRINT(...)
Definition: polytest.cpp:61
#define _SEH2_END
Definition: filesup.c:22
#define DoesFileExist(RootDirectory, FileName)
Definition: filesup.h:77
NTSTATUS ConcatPathsV(IN OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN va_list PathComponentsList)
Definition: filesup.c:596
#define ULL(a, b)
Definition: format_msg.c:27
#define SECTION_MAP_WRITE
Definition: nt_native.h:1288
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
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
BOOLEAN NtPathToDiskPartComponents(IN PCWSTR NtPath, OUT PULONG pDiskNumber, OUT PULONG pPartNumber, OUT PCWSTR *PathComponent OPTIONAL)
Definition: filesup.c:771
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
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)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define OBJ_INHERIT
Definition: winternl.h:225
#define MAX_PATH
Definition: compat.h:26
NTSTRSAFEAPI RtlStringCchCatW(_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:601
_In_ PSTRING FullName
Definition: rtlfuncs.h:1649
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define DoesDirExist(RootDirectory, DirName)
Definition: filesup.h:74
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
static const WCHAR L[]
Definition: oid.c:1250
_Must_inspect_result_ _In_ PFLT_INSTANCE _Out_ PBOOLEAN IsDirectory
Definition: fltkernel.h:1139
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
#define SECTION_MAP_READ
Definition: compat.h:128
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_NON_DIRECTORY_FILE
Definition: constants.h:492
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
#define GENERIC_READ
Definition: compat.h:124
NTSTATUS NTAPI NtQueryInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass)
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define SYNCHRONIZE
Definition: nt_native.h:61
Status
Definition: gdiplustypes.h:24
#define FILE_GENERIC_WRITE
Definition: nt_native.h:660
#define FILE_OPEN
Definition: from_kernel.h:54
ULONG_PTR SIZE_T
Definition: typedefs.h:78
struct _FileName FileName
Definition: fatprocs.h:884
#define va_arg(ap, T)
Definition: acmsvcex.h:89
PRTL_UNICODE_STRING_BUFFER Path
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
static NTSTATUS SetupCreateSingleDirectory(IN PCWSTR DirectoryName)
Definition: filesup.c:29
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int * PULONG
Definition: retypes.h:1
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define min(a, b)
Definition: monoChain.cc:55
#define PAGE_READONLY
Definition: compat.h:127
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define DPRINT1
Definition: precomp.h:8
#define FileStandardInformation
Definition: propsheet.cpp:61
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define OUT
Definition: typedefs.h:39
struct FileInfo FileInfo
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:404
#define STANDARD_RIGHTS_REQUIRED
Definition: nt_native.h:63
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSTATUS OpenAndMapFile(IN HANDLE RootDirectory OPTIONAL, IN PCWSTR PathNameToFile, OUT PHANDLE FileHandle, OUT PHANDLE SectionHandle, OUT PVOID *BaseAddress, OUT PULONG FileSize OPTIONAL, IN BOOLEAN ReadWriteAccess)
Definition: filesup.c:858
#define _SEH2_LEAVE
Definition: filesup.c:20
return STATUS_SUCCESS
Definition: btrfs.c:2938
NTSTATUS CombinePaths(OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN ...)
Definition: filesup.c:681
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define DELETE
Definition: nt_native.h:57
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:716
#define PAGE_READWRITE
Definition: nt_native.h:1304
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68