https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2969c28a273131c821057…
commit 2969c28a273131c82105753077402b6830ef42bb
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Fri Aug 10 07:50:16 2018 +0200
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Sat Aug 11 23:01:11 2018 +0200
[NTOSKRNL] Properly open a page file and set appropriate attributes
---
ntoskrnl/mm/pagefile.c | 66 ++++++++++++++++++++++++++++++++------------------
1 file changed, 43 insertions(+), 23 deletions(-)
diff --git a/ntoskrnl/mm/pagefile.c b/ntoskrnl/mm/pagefile.c
index 523422fcf5..1ea1f07302 100644
--- a/ntoskrnl/mm/pagefile.c
+++ b/ntoskrnl/mm/pagefile.c
@@ -46,6 +46,7 @@ typedef struct _PAGINGFILE
{
LIST_ENTRY PagingFileListEntry;
PFILE_OBJECT FileObject;
+ HANDLE FileHandle;
LARGE_INTEGER MaximumSize;
LARGE_INTEGER CurrentSize;
PFN_NUMBER FreePages;
@@ -502,7 +503,7 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
ULONG Size;
KPROCESSOR_MODE PreviousMode;
UNICODE_STRING CapturedFileName;
- LARGE_INTEGER SafeInitialSize, SafeMaximumSize;
+ LARGE_INTEGER SafeInitialSize, SafeMaximumSize, AllocationSize;
DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
FileName, InitialSize->QuadPart);
@@ -568,25 +569,56 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
NULL,
NULL);
+ /* Make sure we can at least store a complete page:
+ * If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is
+ * a problem if the paging file is fragmented. Suppose the first cluster
+ * of the paging file is cluster 3042 but cluster 3043 is NOT part of the
+ * paging file but of another file. We can't write a complete page (4096
+ * bytes) to the physical location of cluster 3042 then. */
+ AllocationSize.QuadPart = SafeInitialSize.QuadPart + PAGE_SIZE;
+
+ /* First, attempt to replace the page file, if existing */
Status = IoCreateFile(&FileHandle,
- FILE_ALL_ACCESS,
+ SYNCHRONIZE | WRITE_DAC | FILE_READ_DATA | FILE_WRITE_DATA,
&ObjectAttributes,
&IoStatus,
- NULL,
- 0,
- 0,
- FILE_OPEN_IF,
- FILE_SYNCHRONOUS_IO_NONALERT,
+ &AllocationSize,
+ FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
+ FILE_SHARE_WRITE,
+ FILE_SUPERSEDE,
+ FILE_DELETE_ON_CLOSE | FILE_NO_COMPRESSION |
FILE_NO_INTERMEDIATE_BUFFERING,
NULL,
0,
CreateFileTypeNone,
NULL,
SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING);
+ /* If we failed, relax a bit constraints, someone may be already holding the
+ * the file, so share write, don't attempt to replace and don't delete on
close
+ * (basically, don't do anything conflicting)
+ */
+ if (!NT_SUCCESS(Status))
+ {
+ Status = IoCreateFile(&FileHandle,
+ SYNCHRONIZE | FILE_WRITE_DATA,
+ &ObjectAttributes,
+ &IoStatus,
+ &AllocationSize,
+ FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ FILE_OPEN,
+ FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING,
+ NULL,
+ 0,
+ CreateFileTypeNone,
+ NULL,
+ SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING);
+ }
ReleaseCapturedUnicodeString(&CapturedFileName,
PreviousMode);
if (!NT_SUCCESS(Status))
{
+ DPRINT1("Failed creating page file: %lx\n", Status);
return(Status);
}
@@ -603,25 +635,14 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
BytesPerAllocationUnit = FsSizeInformation.SectorsPerAllocationUnit *
FsSizeInformation.BytesPerSector;
- /* FIXME: If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is
- * a problem if the paging file is fragmented. Suppose the first cluster
- * of the paging file is cluster 3042 but cluster 3043 is NOT part of the
- * paging file but of another file. We can't write a complete page (4096
- * bytes) to the physical location of cluster 3042 then. */
- if (BytesPerAllocationUnit % PAGE_SIZE)
- {
- DPRINT1("BytesPerAllocationUnit %lu is not a multiple of PAGE_SIZE
%d\n",
- BytesPerAllocationUnit, PAGE_SIZE);
- ZwClose(FileHandle);
- return STATUS_UNSUCCESSFUL;
- }
+ /* Set its end of file to initial size */
Status = ZwSetInformationFile(FileHandle,
&IoStatus,
&SafeInitialSize,
sizeof(LARGE_INTEGER),
- FileAllocationInformation);
- if (!NT_SUCCESS(Status))
+ FileEndOfFileInformation);
+ if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatus.Status))
{
ZwClose(FileHandle);
return(Status);
@@ -722,6 +743,7 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
RtlZeroMemory(PagingFile, sizeof(*PagingFile));
+ PagingFile->FileHandle = FileHandle;
PagingFile->FileObject = FileObject;
PagingFile->MaximumSize.QuadPart = SafeMaximumSize.QuadPart;
PagingFile->CurrentSize.QuadPart = SafeInitialSize.QuadPart;
@@ -817,8 +839,6 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
MmNumberOfPagingFiles++;
KeReleaseSpinLock(&PagingFileListLock, oldIrql);
- ZwClose(FileHandle);
-
MmSwapSpaceMessage = FALSE;
return(STATUS_SUCCESS);