Author: ion
Date: Fri Feb 3 23:11:28 2012
New Revision: 55400
URL:
http://svn.reactos.org/svn/reactos?rev=55400&view=rev
Log:
[SMSS2]: Implement the rest of the code to create page files. All that's missing is
the actual call to NtCreatePagingFile.
Modified:
trunk/reactos/base/system/smss2/crashdmp.c
trunk/reactos/base/system/smss2/pagefile.c
trunk/reactos/base/system/smss2/smss.h
Modified: trunk/reactos/base/system/smss2/crashdmp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/crashdmp…
==============================================================================
--- trunk/reactos/base/system/smss2/crashdmp.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/crashdmp.c [iso-8859-1] Fri Feb 3 23:11:28 2012
@@ -15,3 +15,12 @@
/* GLOBALS ********************************************************************/
/* FUNCTIONS ******************************************************************/
+
+BOOLEAN
+NTAPI
+SmpCheckForCrashDump(IN PUNICODE_STRING FileName)
+{
+ return FALSE;
+}
+
+
Modified: trunk/reactos/base/system/smss2/pagefile.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/pagefile…
==============================================================================
--- trunk/reactos/base/system/smss2/pagefile.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/pagefile.c [iso-8859-1] Fri Feb 3 23:11:28 2012
@@ -46,11 +46,13 @@
// Structure and flags describing each volume
//
#define SMP_VOLUME_INSERTED 0x01
+#define SMP_VOLUME_PAGEFILE_CREATED 0x04
#define SMP_VOLUME_IS_BOOT 0x08
typedef struct _SMP_VOLUME_DESCRIPTOR
{
LIST_ENTRY Entry;
- ULONG Flags;
+ USHORT Flags;
+ USHORT PageFileCount;
WCHAR DriveLetter;
LARGE_INTEGER FreeSpace;
FILE_FS_DEVICE_INFORMATION DeviceInfo;
@@ -230,13 +232,369 @@
NTSTATUS
NTAPI
+SmpGetPagingFileSize(IN PUNICODE_STRING FileName,
+ OUT PLARGE_INTEGER Size)
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ FILE_STANDARD_INFORMATION StandardInfo;
+
+ DPRINT1("SMSS:PFILE: Trying to get size for `%wZ'\n", FileName);
+ Size->QuadPart = 0;
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Status = NtQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &StandardInfo,
+ sizeof(StandardInfo),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SMSS:PFILE: Failed query for size potential pagefile `%wZ' with
status %X \n",
+ FileName, Status);
+ NtClose(FileHandle);
+ return Status;
+ }
+
+ NtClose(FileHandle);
+ Size->LowPart = StandardInfo.AllocationSize.LowPart;
+ Size->HighPart = StandardInfo.AllocationSize.HighPart;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+SmpDeletePagingFile(IN PUNICODE_STRING FileName)
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ FILE_DISPOSITION_INFORMATION Disposition;
+
+ /* Open the page file */
+ InitializeObjectAttributes(&ObjectAttributes,
+ FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenFile(&FileHandle,
+ DELETE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_NON_DIRECTORY_FILE);
+ if (NT_SUCCESS(Status))
+ {
+ /* Delete it */
+ Disposition.DeleteFile = TRUE;
+ Status = NtSetInformationFile(FileHandle,
+ &IoStatusBlock,
+ &Disposition,
+ sizeof(Disposition),
+ FileDispositionInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SMSS:PFILE: Failed to delete page file `%wZ' (status
%X)\n",
+ FileName, Status);
+ }
+ else
+ {
+ DPRINT1("SMSS:PFILE: Deleted stale paging file - %wZ\n",
FileName);
+ }
+
+ /* Close the handle */
+ NtClose(FileHandle);
+ }
+ else
+ {
+ DPRINT1("SMSS:PFILE: Failed to open for deletion page file `%wZ' (status
%X)\n",
+ FileName, Status);
+ }
+
+ /* All done */
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+SmpGetVolumeFreeSpace(IN PSMP_VOLUME_DESCRIPTOR Volume)
+{
+ NTSTATUS Status;
+ LARGE_INTEGER FreeSpace, FinalFreeSpace;
+ FILE_FS_SIZE_INFORMATION SizeInfo;
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING VolumeName;
+ HANDLE VolumeHandle;
+ WCHAR PathString[32];
+ ASSERT(Volume->Flags & SMP_VOLUME_IS_BOOT); // ASSERT says "BootVolume ==
1"
+
+ /* Build the standard path */
+ wcscpy(PathString, L"\\??\\A:\\");
+ VolumeName.Buffer = PathString;
+ VolumeName.Length = wcslen(PathString) * sizeof(WCHAR);
+ VolumeName.MaximumLength = VolumeName.Length + sizeof(UNICODE_NULL);
+ VolumeName.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = Volume->DriveLetter;
+ DPRINT1("SMSS:PFILE: Querying volume `%wZ' for free space \n",
&VolumeName);
+
+ /* Open the volume */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &VolumeName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenFile(&VolumeHandle,
+ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SMSS:PFILE: Open volume `%wZ' failed with status %X \n",
&VolumeName, Status);
+ return Status;
+ }
+
+ /* Now get size information on the volume */
+ Status = NtQueryVolumeInformationFile(VolumeHandle,
+ &IoStatusBlock,
+ &SizeInfo,
+ sizeof(SizeInfo),
+ FileFsSizeInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ /* We failed -- keep going */
+ DPRINT1("SMSS:PFILE: Query volume `%wZ' (handle %p) for size
failed"
+ " with status %X \n",
+ &VolumeName,
+ VolumeHandle,
+ Status);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, Volume);
+ NtClose(VolumeHandle);
+ return Status;
+ }
+ NtClose(VolumeHandle);
+
+ /* Compute how much free space we have */
+ FreeSpace.QuadPart = SizeInfo.AvailableAllocationUnits.QuadPart *
+ SizeInfo.SectorsPerAllocationUnit;
+ FinalFreeSpace.QuadPart = FreeSpace.QuadPart * SizeInfo.BytesPerSector;
+ Volume->FreeSpace = FinalFreeSpace;
+
+ /* Check if there's less than 32MB free so we don't starve the disk */
+ if (FinalFreeSpace.QuadPart <= 0x2000000)
+ {
+ /* In this case, act as if there's no free space */
+ Volume->FreeSpace.QuadPart = 0;
+ }
+ else
+ {
+ /* Trim off 32MB to give the disk a bit of breathing room */
+ Volume->FreeSpace.QuadPart = FinalFreeSpace.QuadPart - 0x2000000;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+PSMP_VOLUME_DESCRIPTOR
+NTAPI
+SmpSearchVolumeDescriptor(IN WCHAR DriveLetter)
+{
+ WCHAR UpLetter;
+ PSMP_VOLUME_DESCRIPTOR Volume = NULL;
+ PLIST_ENTRY NextEntry;
+
+ /* Use upper case to reduce differences */
+ UpLetter = RtlUpcaseUnicodeChar(DriveLetter);
+
+ /* Loop each volume */
+ NextEntry = SmpVolumeDescriptorList.Flink;
+ while (NextEntry != &SmpVolumeDescriptorList)
+ {
+ /* Grab the entry */
+ Volume = CONTAINING_RECORD(NextEntry, SMP_VOLUME_DESCRIPTOR, Entry);
+
+ /* Make sure it's a valid entry with an uppcase drive letter */
+ ASSERT(Volume->Flags & SMP_VOLUME_INSERTED); // Volume->Initialized in
ASSERT
+ ASSERT(Volume->DriveLetter >= L'A' &&
Volume->DriveLetter <= L'Z');
+
+ /* Break if it matches, if not, keep going */
+ if (Volume->DriveLetter == UpLetter) break;
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Return the volume if one was found */
+ if (NextEntry == &SmpVolumeDescriptorList) Volume = NULL;
+ return Volume;
+}
+
+NTSTATUS
+NTAPI
+SmpCreatePagingFile(IN PUNICODE_STRING Name,
+ IN PLARGE_INTEGER MinSize,
+ IN PLARGE_INTEGER MaxSize,
+ IN ULONG Priority)
+{
+ NTSTATUS Status;
+ DPRINT1("Should request pagefile: %wZ with size %I64x and %I64x\n", Name,
MinSize->QuadPart, MaxSize->QuadPart);
+
+ /* Tell the kernel to create the pagefile */
+ Status = STATUS_SUCCESS;
+ //Status = NtCreatePagingFile(Name, MinSize, MaxSize, Priority);
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT1("SMSS:PFILE: NtCreatePagingFile (%wZ, %I64X, %I64X) succeeded.
\n",
+ Name,
+ MinSize->QuadPart,
+ MaxSize->QuadPart);
+ }
+ else
+ {
+ DPRINT1("SMSS:PFILE: NtCreatePagingFile (%wZ, %I64X, %I64X) failed with %X
\n",
+ Name,
+ MinSize->QuadPart,
+ MaxSize->QuadPart,
+ Status);
+ }
+
+ /* Return the status */
+ return Status;
+}
+
+NTSTATUS
+NTAPI
SmpCreatePagingFileOnFixedDrive(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor,
IN PLARGE_INTEGER FuzzFactor,
IN PLARGE_INTEGER MinimumSize)
{
- DPRINT1("Should create fixed pagefile of sizes: %I64d %I64d\n",
- FuzzFactor->QuadPart, MinimumSize->QuadPart);
- return STATUS_SUCCESS;
+ PSMP_VOLUME_DESCRIPTOR Volume;
+ BOOLEAN ShouldDelete;
+ NTSTATUS Status;
+ LARGE_INTEGER PageFileSize;
+ ASSERT(Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] != L'?');
+
+ /* Try to find the volume descriptor for this drive letter */
+ ShouldDelete = FALSE;
+ Volume =
SmpSearchVolumeDescriptor(Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET]);
+ if (!Volume)
+ {
+ /* Couldn't find it, fail */
+ DPRINT1("SMSS:PFILE: No volume descriptor for `%wZ' \n",
+ &Descriptor->Name);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Check if this is the boot volume */
+ if (Volume->Flags & SMP_VOLUME_IS_BOOT)
+ {
+ /* Check if we haven't yet processed a crash dump on this volume */
+ if (!(Descriptor->Flags & SMP_PAGEFILE_DUMP_PROCESSED))
+ {
+ /* Try to find a crash dump and extract it */
+ DPRINT1("SMSS:PFILE: Checking for crash dump in `%wZ' on boot volume
\n",
+ &Descriptor->Name);
+ SmpCheckForCrashDump(&Descriptor->Name);
+
+ /* Update how much free space we have now that we extracted a dump */
+ Status = SmpGetVolumeFreeSpace(Volume);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SMSS:PFILE: Failed to query free space for boot volume
`%wC'\n",
+ Volume->DriveLetter);
+ }
+
+ /* Don't process crashdump on this volume anymore */
+ Descriptor->Flags |= SMP_PAGEFILE_DUMP_PROCESSED;
+ }
+ }
+ else
+ {
+ /* Crashdumps can only be on the boot volume */
+ DPRINT1("SMSS:PFILE: Skipping crash dump checking for `%wZ' on non
boot"
+ "volume `%wC' \n",
+ &Descriptor->Name,
+ Volume->DriveLetter);
+ }
+
+ /* Update the size after dump extraction */
+ Descriptor->ActualMinSize = Descriptor->MinSize;
+ Descriptor->ActualMaxSize = Descriptor->MaxSize;
+
+ /* Check how big we can make the pagefile */
+ Status = SmpGetPagingFileSize(&Descriptor->Name, &PageFileSize);
+ if (PageFileSize.QuadPart > 0) ShouldDelete = TRUE;
+ DPRINT1("SMSS:PFILE: Detected size %I64X for future paging file
`%wZ'\n",
+ PageFileSize,
+ &Descriptor->Name);
+ DPRINT1("SMSS:PFILE: Free space on volume `%wC' is %I64X \n",
+ Volume->DriveLetter,
+ Volume->FreeSpace.QuadPart);
+
+ /* Now update our size and make sure none of these are too big */
+ PageFileSize.QuadPart += Volume->FreeSpace.QuadPart;
+ if (Descriptor->ActualMinSize.QuadPart > PageFileSize.QuadPart)
+ {
+ Descriptor->ActualMinSize = PageFileSize;
+ }
+ if (Descriptor->ActualMaxSize.QuadPart > PageFileSize.QuadPart)
+ {
+ Descriptor->ActualMaxSize = PageFileSize;
+ }
+ DPRINT1("SMSS:PFILE: min %I64X, max %I64X, real min %I64X \n",
+ Descriptor->ActualMinSize.QuadPart,
+ Descriptor->ActualMaxSize.QuadPart,
+ MinimumSize->QuadPart);
+
+ /* Keep going until we've created a pagefile of the right size */
+ while (Descriptor->ActualMinSize.QuadPart >= MinimumSize->QuadPart)
+ {
+ /* Call NT to do it */
+ Status = SmpCreatePagingFile(&Descriptor->Name,
+ &Descriptor->ActualMinSize,
+ &Descriptor->ActualMaxSize,
+ 0);
+ if (NT_SUCCESS(Status))
+ {
+ /* We're done, update flags and increase the count */
+ Descriptor->Flags |= SMP_PAGEFILE_CREATED;
+ Volume->Flags |= SMP_VOLUME_PAGEFILE_CREATED;
+ Volume->PageFileCount++;
+ break;
+ }
+
+ /* We failed, try a slighly smaller pagefile */
+ Descriptor->ActualMinSize.QuadPart -= FuzzFactor->QuadPart;
+ }
+
+ /* Check if we weren't able to create it */
+ if (Descriptor->ActualMinSize.QuadPart < MinimumSize->QuadPart)
+ {
+ /* Delete the current page file and fail */
+ if (ShouldDelete) SmpDeletePagingFile(&Descriptor->Name);
+ DPRINT1("SMSS:PFILE: Failing for min %I64X, max %I64X, real min %I64X
\n",
+ Descriptor->ActualMinSize.QuadPart,
+ Descriptor->ActualMaxSize.QuadPart,
+ MinimumSize->QuadPart);
+ Status = STATUS_DISK_FULL;
+ }
+
+ /* Return the status */
+ return Status;
}
NTSTATUS
@@ -245,9 +603,36 @@
IN PLARGE_INTEGER FuzzFactor,
IN PLARGE_INTEGER MinimumSize)
{
- DPRINT1("Should create 'any' pagefile of sizes: %I64d %I64d\n",
- FuzzFactor->QuadPart, MinimumSize->QuadPart);
- return STATUS_SUCCESS;
+ PSMP_VOLUME_DESCRIPTOR Volume;
+ NTSTATUS Status = STATUS_DISK_FULL;
+ PLIST_ENTRY NextEntry;
+ ASSERT(Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] == L'?');
+
+ /* Loop the volume list */
+ NextEntry = SmpVolumeDescriptorList.Flink;
+ while (NextEntry != &SmpVolumeDescriptorList)
+ {
+ /* Get the volume */
+ Volume = CONTAINING_RECORD(NextEntry, SMP_VOLUME_DESCRIPTOR, Entry);
+
+ /* Make sure it's inserted and on a valid drive letter */
+ ASSERT(Volume->Flags & SMP_VOLUME_INSERTED); // Volume->Initialized in
ASSERT
+ ASSERT(Volume->DriveLetter >= L'A' &&
Volume->DriveLetter <= L'Z');
+
+ /* Write the drive letter to try creating it on this volume */
+ Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] =
Volume->DriveLetter;
+ Status = SmpCreatePagingFileOnFixedDrive(Descriptor,
+ FuzzFactor,
+ MinimumSize);
+ if (NT_SUCCESS(Status)) break;
+
+ /* It didn't work, make it an any pagefile again and keep going */
+ Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = L'?';
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Return disk full or success */
+ return Status;
}
VOID
Modified: trunk/reactos/base/system/smss2/smss.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/smss.h?r…
==============================================================================
--- trunk/reactos/base/system/smss2/smss.h [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/smss.h [iso-8859-1] Fri Feb 3 23:11:28 2012
@@ -181,4 +181,10 @@
IN BOOLEAN ShutdownOkay
);
+BOOLEAN
+NTAPI
+SmpCheckForCrashDump(
+ IN PUNICODE_STRING FileName
+);
+