MmNumberOfPagingFiles = 0;
}
-static ULONG
-MiAllocPageFromPagingFile(PMMPAGING_FILE PagingFile)
-{
- KIRQL oldIrql;
- ULONG off;
-
- KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql);
- off = RtlFindClearBitsAndSet(PagingFile->AllocMap, 1, 0);
- KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql);
-
- return off;
-}
-
VOID
NTAPI
MmFreeSwapPage(SWAPENTRY Entry)
{
KeBugCheck(MEMORY_MANAGEMENT);
}
- KeAcquireSpinLockAtDpcLevel(&PagingFile->AllocMapLock);
RtlClearBit(PagingFile->AllocMap, off >> 5);
MiFreeSwapPages++;
MiUsedSwapPages--;
- KeReleaseSpinLockFromDpcLevel(&PagingFile->AllocMapLock);
KeReleaseSpinLock(&PagingFileListLock, oldIrql);
}
if (MmPagingFile[i] != NULL &&
MmPagingFile[i]->FreePages >= 1)
{
- off = MiAllocPageFromPagingFile(MmPagingFile[i]);
+ off = RtlFindClearBitsAndSet(MmPagingFile[i]->AllocMap, 1, 0);
if (off == 0xFFFFFFFF)
{
KeBugCheck(MEMORY_MANAGEMENT);
ULONG AllocMapSize;
ULONG Count;
KPROCESSOR_MODE PreviousMode;
- UNICODE_STRING CapturedFileName;
+ UNICODE_STRING PageFileName;
LARGE_INTEGER SafeInitialSize, SafeMaximumSize, AllocationSize;
FILE_FS_DEVICE_INFORMATION FsDeviceInfo;
SECURITY_DESCRIPTOR SecurityDescriptor;
PACL Dacl;
+ PWSTR Buffer;
DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
FileName, InitialSize->QuadPart);
{
SafeInitialSize = ProbeForReadLargeInteger(InitialSize);
SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
+
+ PageFileName.Length = FileName->Length;
+ PageFileName.MaximumLength = FileName->MaximumLength;
+ PageFileName.Buffer = FileName->Buffer;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
{
SafeInitialSize = *InitialSize;
SafeMaximumSize = *MaximumSize;
+
+ PageFileName.Length = FileName->Length;
+ PageFileName.MaximumLength = FileName->MaximumLength;
+ PageFileName.Buffer = FileName->Buffer;
}
/* Pagefiles can't be larger than 4GB and ofcourse the minimum should be
return STATUS_INVALID_PARAMETER_MIX;
}
- Status = ProbeAndCaptureUnicodeString(&CapturedFileName,
- PreviousMode,
- FileName);
- if (!NT_SUCCESS(Status))
+ /* Validate name length */
+ if (PageFileName.Length > 128 * sizeof(WCHAR))
{
- return(Status);
+ return STATUS_OBJECT_NAME_INVALID;
+ }
+
+ /* We won't care about any potential UNICODE_NULL */
+ PageFileName.MaximumLength = PageFileName.Length;
+ /* Allocate a buffer to keep name copy */
+ Buffer = ExAllocatePoolWithTag(PagedPool, PageFileName.Length, TAG_MM);
+ if (Buffer == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
}
+ /* Copy name */
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ if (PageFileName.Length != 0)
+ {
+ ProbeForRead(PageFileName.Buffer, PageFileName.Length, sizeof(WCHAR));
+ }
+
+ RtlCopyMemory(Buffer, PageFileName.Buffer, PageFileName.Length);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ExFreePoolWithTag(Buffer, TAG_MM);
+
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ RtlCopyMemory(Buffer, PageFileName.Buffer, PageFileName.Length);
+ }
+
+ /* Erase caller's buffer with ours */
+ PageFileName.Buffer = Buffer;
+
/* Create the security descriptor for the page file */
Status = RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(Status))
{
- ReleaseCapturedUnicodeString(&CapturedFileName,
- PreviousMode);
+ ExFreePoolWithTag(Buffer, TAG_MM);
return Status;
}
Dacl = ExAllocatePoolWithTag(PagedPool, Count, 'lcaD');
if (Dacl == NULL)
{
- ReleaseCapturedUnicodeString(&CapturedFileName,
- PreviousMode);
+ ExFreePoolWithTag(Buffer, TAG_MM);
return STATUS_INSUFFICIENT_RESOURCES;
}
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Dacl, 'lcaD');
- ReleaseCapturedUnicodeString(&CapturedFileName,
- PreviousMode);
+ ExFreePoolWithTag(Buffer, TAG_MM);
return Status;
}
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Dacl, 'lcaD');
- ReleaseCapturedUnicodeString(&CapturedFileName,
- PreviousMode);
+ ExFreePoolWithTag(Buffer, TAG_MM);
return Status;
}
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Dacl, 'lcaD');
- ReleaseCapturedUnicodeString(&CapturedFileName,
- PreviousMode);
+ ExFreePoolWithTag(Buffer, TAG_MM);
return Status;
}
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Dacl, 'lcaD');
- ReleaseCapturedUnicodeString(&CapturedFileName,
- PreviousMode);
+ ExFreePoolWithTag(Buffer, TAG_MM);
return Status;
}
InitializeObjectAttributes(&ObjectAttributes,
- &CapturedFileName,
+ &PageFileName,
OBJ_KERNEL_HANDLE,
NULL,
&SecurityDescriptor);
/* 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)
+ * This can happen if the caller attempts to extend a page file.
*/
if (!NT_SUCCESS(Status))
{
+ ULONG i;
+
Status = IoCreateFile(&FileHandle,
SYNCHRONIZE | FILE_WRITE_DATA,
&ObjectAttributes,
CreateFileTypeNone,
NULL,
SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(Dacl, 'lcaD');
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return Status;
+ }
+
+ /* We opened it! Check we are that "someone" ;-)
+ * First, get the opened file object.
+ */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ IoFileObjectType,
+ KernelMode,
+ (PVOID*)&FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ZwClose(FileHandle);
+ ExFreePoolWithTag(Dacl, 'lcaD');
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return Status;
+ }
+
+ /* Find if it matches a previous page file */
+ PagingFile = NULL;
+ if (MmNumberOfPagingFiles > 0)
+ {
+ i = 0;
+
+ while (MmPagingFile[i]->FileObject->SectionObjectPointer != FileObject->SectionObjectPointer)
+ {
+ ++i;
+ if (i >= MmNumberOfPagingFiles)
+ {
+ break;
+ }
+ }
+
+ /* This is the matching page file */
+ PagingFile = MmPagingFile[i];
+ }
+
+ /* If we didn't find the page file, fail */
+ if (PagingFile == NULL)
+ {
+ ObDereferenceObject(FileObject);
+ ZwClose(FileHandle);
+ ExFreePoolWithTag(Dacl, 'lcaD');
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return STATUS_NOT_FOUND;
+ }
+
+ /* FIXME: implement parameters checking and page file extension */
+ UNIMPLEMENTED;
+
+ ObDereferenceObject(FileObject);
+ ZwClose(FileHandle);
+ ExFreePoolWithTag(Dacl, 'lcaD');
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return STATUS_NOT_IMPLEMENTED;
}
- ReleaseCapturedUnicodeString(&CapturedFileName,
- PreviousMode);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed creating page file: %lx\n", Status);
ExFreePoolWithTag(Dacl, 'lcaD');
- return(Status);
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return Status;
}
/* Set the security descriptor */
{
ExFreePoolWithTag(Dacl, 'lcaD');
ZwClose(FileHandle);
+ ExFreePoolWithTag(Buffer, TAG_MM);
return Status;
}
}
if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatus.Status))
{
ZwClose(FileHandle);
- return(Status);
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return Status;
}
Status = ObReferenceObjectByHandle(FileHandle,
if (!NT_SUCCESS(Status))
{
ZwClose(FileHandle);
- return(Status);
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return Status;
}
/* Deny page file creation on a floppy disk */
{
ObDereferenceObject(FileObject);
ZwClose(FileHandle);
+ ExFreePoolWithTag(Buffer, TAG_MM);
return STATUS_FLOPPY_VOLUME;
}
- PagingFile = ExAllocatePool(NonPagedPool, sizeof(*PagingFile));
+ PagingFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(*PagingFile), TAG_MM);
if (PagingFile == NULL)
{
ObDereferenceObject(FileObject);
ZwClose(FileHandle);
- return(STATUS_NO_MEMORY);
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(PagingFile, sizeof(*PagingFile));
PagingFile->CurrentSize.QuadPart = SafeInitialSize.QuadPart;
PagingFile->FreePages = (ULONG)(SafeInitialSize.QuadPart / PAGE_SIZE);
PagingFile->UsedPages = 0;
- KeInitializeSpinLock(&PagingFile->AllocMapLock);
+ PagingFile->PageFileName = PageFileName;
AllocMapSize = sizeof(RTL_BITMAP) + (((PagingFile->FreePages + 31) / 32) * sizeof(ULONG));
PagingFile->AllocMap = ExAllocatePoolWithTag(NonPagedPool,
TAG_MM);
if (PagingFile->AllocMap == NULL)
{
- ExFreePool(PagingFile);
+ ExFreePoolWithTag(PagingFile, TAG_MM);
ObDereferenceObject(FileObject);
ZwClose(FileHandle);
- return(STATUS_NO_MEMORY);
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return STATUS_INSUFFICIENT_RESOURCES;
}
RtlInitializeBitMap(PagingFile->AllocMap,
MmSwapSpaceMessage = FALSE;
- return(STATUS_SUCCESS);
+ return STATUS_SUCCESS;
}
/* EOF */