ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pagefile.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Windows-Compatible Session Manager
00003  * LICENSE:         BSD 2-Clause License
00004  * FILE:            base/system/smss/smss.c
00005  * PURPOSE:         Main SMSS Code
00006  * PROGRAMMERS:     Alex Ionescu
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include "smss.h"
00012 #define NDEBUG
00013 #include "debug.h"
00014 
00015 /* GLOBALS ********************************************************************/
00016 
00017 //
00018 // Constants
00019 //
00020 #define STANDARD_PAGING_FILE_NAME       L"\\??\\?:\\pagefile.sys"
00021 #define STANDARD_DRIVE_LETTER_OFFSET    4
00022 #define MEGABYTE                        0x100000UL
00023 #define MAXIMUM_PAGEFILE_SIZE           (4095 * MEGABYTE)
00024 /* This should be 32 MB, but we need more than that for 2nd stage setup */
00025 #define MINIMUM_TO_KEEP_FREE            (64 * MEGABYTE)
00026 #define FUZZ_FACTOR                     (16 * MEGABYTE)
00027 
00028 //
00029 // Structure and flags describing each pagefile
00030 //
00031 #define SMP_PAGEFILE_CREATED            0x01
00032 #define SMP_PAGEFILE_DEFAULT            0x02
00033 #define SMP_PAGEFILE_SYSTEM_MANAGED     0x04
00034 #define SMP_PAGEFILE_WAS_TOO_BIG        0x08
00035 #define SMP_PAGEFILE_ON_ANY_DRIVE       0x10
00036 #define SMP_PAGEFILE_EMERGENCY          0x20
00037 #define SMP_PAGEFILE_DUMP_PROCESSED     0x40
00038 typedef struct _SMP_PAGEFILE_DESCRIPTOR
00039 {
00040     LIST_ENTRY Entry;
00041     UNICODE_STRING Name;
00042     UNICODE_STRING Token;
00043     LARGE_INTEGER MinSize;
00044     LARGE_INTEGER MaxSize;
00045     LARGE_INTEGER ActualMinSize;
00046     LARGE_INTEGER ActualMaxSize;
00047     ULONG Flags;
00048 } SMP_PAGEFILE_DESCRIPTOR, *PSMP_PAGEFILE_DESCRIPTOR;
00049 
00050 //
00051 // Structure and flags describing each volume
00052 //
00053 #define SMP_VOLUME_INSERTED             0x01
00054 #define SMP_VOLUME_PAGEFILE_CREATED     0x04
00055 #define SMP_VOLUME_IS_BOOT              0x08
00056 typedef struct _SMP_VOLUME_DESCRIPTOR
00057 {
00058     LIST_ENTRY Entry;
00059     USHORT Flags;
00060     USHORT PageFileCount;
00061     WCHAR DriveLetter;
00062     LARGE_INTEGER FreeSpace;
00063     FILE_FS_DEVICE_INFORMATION DeviceInfo;
00064 } SMP_VOLUME_DESCRIPTOR, *PSMP_VOLUME_DESCRIPTOR;
00065 
00066 LIST_ENTRY SmpPagingFileDescriptorList, SmpVolumeDescriptorList;
00067 BOOLEAN SmpRegistrySpecifierPresent;
00068 ULONG SmpNumberOfPagingFiles;
00069 
00070 /* FUNCTIONS ******************************************************************/
00071 
00072 VOID
00073 NTAPI
00074 SmpPagingFileInitialize(VOID)
00075 {
00076     /* Initialize the two lists */
00077     InitializeListHead(&SmpPagingFileDescriptorList);
00078     InitializeListHead(&SmpVolumeDescriptorList);
00079 }
00080 
00081 NTSTATUS
00082 NTAPI
00083 SmpCreatePagingFileDescriptor(IN PUNICODE_STRING PageFileToken)
00084 {
00085     NTSTATUS Status;
00086     ULONG MinSize = 0, MaxSize = 0;
00087     BOOLEAN SystemManaged = FALSE, ZeroSize = TRUE;
00088     PSMP_PAGEFILE_DESCRIPTOR Descriptor, ListDescriptor;
00089     ULONG i;
00090     WCHAR c;
00091     PLIST_ENTRY NextEntry;
00092     UNICODE_STRING PageFileName, Arguments, SecondArgument;
00093 
00094     /* Make sure we don't have too many */
00095     if (SmpNumberOfPagingFiles >= 16)
00096     {
00097         DPRINT1("SMSS:PFILE: Too many paging files specified - %d\n",
00098                 SmpNumberOfPagingFiles);
00099         return STATUS_TOO_MANY_PAGING_FILES;
00100     }
00101 
00102     /* Parse the specified and get the name and arguments out of it */
00103     DPRINT("SMSS:PFILE: Paging file specifier `%wZ' \n", PageFileToken);
00104     Status = SmpParseCommandLine(PageFileToken,
00105                                  NULL,
00106                                  &PageFileName,
00107                                  NULL,
00108                                  &Arguments);
00109     if (!NT_SUCCESS(Status))
00110     {
00111         /* Fail */
00112         DPRINT1("SMSS:PFILE: SmpParseCommandLine(%wZ) failed with status %X \n",
00113                 PageFileToken, Status);
00114         return Status;
00115     }
00116 
00117     /* Set the variable to let everyone know we have a pagefile token */
00118     SmpRegistrySpecifierPresent = TRUE;
00119 
00120     /* Parse the arguments, if any */
00121     if (Arguments.Buffer)
00122     {
00123         /* Parse the pagefile size */
00124         for (i = 0; i < Arguments.Length / sizeof(WCHAR); i++)
00125         {
00126             /* Check if it's zero */
00127             c = Arguments.Buffer[i];
00128             if ((c != L' ') && (c != L'\t') && (c != L'0'))
00129             {
00130                 /* It isn't, break out */
00131                 ZeroSize = FALSE;
00132                 break;
00133             }
00134         }
00135     }
00136 
00137     /* Was a pagefile not specified, or was it specified with no size? */
00138     if (!(Arguments.Buffer) || (ZeroSize))
00139     {
00140         /* In this case, the system will manage its size */
00141         SystemManaged = TRUE;
00142     }
00143     else
00144     {
00145         /* We do have a size, so convert the arguments into a number */
00146         Status = RtlUnicodeStringToInteger(&Arguments, 0, &MinSize);
00147         if (!NT_SUCCESS(Status))
00148         {
00149             /* Fail */
00150             RtlFreeUnicodeString(&PageFileName);
00151             RtlFreeUnicodeString(&Arguments);
00152             return Status;
00153         }
00154 
00155         /* Now advance to the next argument */
00156         for (i = 0; i < Arguments.Length / sizeof(WCHAR); i++)
00157         {
00158             /* Found a space -- second argument must start here */
00159             if (Arguments.Buffer[i] == L' ')
00160             {
00161                 /* Use the rest of the arguments as a maximum size */
00162                 SecondArgument.Buffer = &Arguments.Buffer[i];
00163                 SecondArgument.Length = Arguments.Length -
00164                                         i * sizeof(WCHAR);
00165                 SecondArgument.MaximumLength = Arguments.MaximumLength -
00166                                                i * sizeof(WCHAR);
00167                 Status = RtlUnicodeStringToInteger(&SecondArgument, 0, &MaxSize);
00168                 if (!NT_SUCCESS(Status))
00169                 {
00170                     /* Fail */
00171                     RtlFreeUnicodeString(&PageFileName);
00172                     RtlFreeUnicodeString(&Arguments);
00173                     return Status;
00174                 }
00175 
00176                 break;
00177             }
00178         }
00179     }
00180 
00181     /* We are done parsing arguments */
00182     RtlFreeUnicodeString(&Arguments);
00183 
00184     /* Now we can allocate our descriptor */
00185     Descriptor = RtlAllocateHeap(RtlGetProcessHeap(),
00186                                  HEAP_ZERO_MEMORY,
00187                                  sizeof(SMP_PAGEFILE_DESCRIPTOR));
00188     if (!Descriptor)
00189     {
00190         /* Fail if we couldn't */
00191         RtlFreeUnicodeString(&PageFileName);
00192         return STATUS_NO_MEMORY;
00193     }
00194 
00195     /* Capture all our data into the descriptor */
00196     Descriptor->Token = *PageFileToken;
00197     Descriptor->Name = PageFileName;
00198     Descriptor->MinSize.QuadPart = MinSize * MEGABYTE;
00199     Descriptor->MaxSize.QuadPart = MaxSize * MEGABYTE;
00200     if (SystemManaged) Descriptor->Flags |= SMP_PAGEFILE_SYSTEM_MANAGED;
00201     Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] =
00202     RtlUpcaseUnicodeChar(Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET]);
00203     if (Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] == '?')
00204     {
00205         Descriptor->Flags |= SMP_PAGEFILE_ON_ANY_DRIVE;
00206     }
00207 
00208     /* Now loop the existing descriptors */
00209     NextEntry = SmpPagingFileDescriptorList.Flink;
00210     do
00211     {
00212         /* Are there none, or have we looped back to the beginning? */
00213         if (NextEntry == &SmpPagingFileDescriptorList)
00214         {
00215             /* This means no duplicates exist, so insert our descriptor! */
00216             InsertTailList(&SmpPagingFileDescriptorList, &Descriptor->Entry);
00217             SmpNumberOfPagingFiles++;
00218             DPRINT("SMSS:PFILE: Created descriptor for `%wZ' (`%wZ') \n",
00219                     PageFileToken, &Descriptor->Name);
00220             return STATUS_SUCCESS;
00221         }
00222 
00223         /* Keep going until we find a duplicate, unless we are in "any" mode */
00224         ListDescriptor = CONTAINING_RECORD(NextEntry, SMP_PAGEFILE_DESCRIPTOR, Entry);
00225         NextEntry = NextEntry->Flink;
00226     } while (!(ListDescriptor->Flags & SMP_PAGEFILE_ON_ANY_DRIVE) ||
00227              !(Descriptor->Flags & SMP_PAGEFILE_ON_ANY_DRIVE));
00228 
00229     /* We found a duplicate, so skip this descriptor/pagefile and fail */
00230     DPRINT1("SMSS:PFILE: Skipping duplicate specifier `%wZ' \n", PageFileToken);
00231     RtlFreeUnicodeString(&PageFileName);
00232     RtlFreeHeap(RtlGetProcessHeap(), 0, Descriptor);
00233     return STATUS_INVALID_PARAMETER;
00234 }
00235 
00236 NTSTATUS
00237 NTAPI
00238 SmpGetPagingFileSize(IN PUNICODE_STRING FileName,
00239                      OUT PLARGE_INTEGER Size)
00240 {
00241     NTSTATUS Status;
00242     OBJECT_ATTRIBUTES ObjectAttributes;
00243     IO_STATUS_BLOCK IoStatusBlock;
00244     HANDLE FileHandle;
00245     FILE_STANDARD_INFORMATION StandardInfo;
00246 
00247     DPRINT("SMSS:PFILE: Trying to get size for `%wZ'\n", FileName);
00248     Size->QuadPart = 0;
00249 
00250     InitializeObjectAttributes(&ObjectAttributes,
00251                                FileName,
00252                                OBJ_CASE_INSENSITIVE,
00253                                NULL,
00254                                NULL);
00255     Status = NtOpenFile(&FileHandle,
00256                         FILE_READ_ATTRIBUTES | SYNCHRONIZE,
00257                         &ObjectAttributes,
00258                         &IoStatusBlock,
00259                         FILE_SHARE_READ | FILE_SHARE_WRITE,
00260                         FILE_SYNCHRONOUS_IO_NONALERT);
00261     if (!NT_SUCCESS(Status)) return Status;
00262 
00263     Status = NtQueryInformationFile(FileHandle,
00264                                     &IoStatusBlock,
00265                                     &StandardInfo,
00266                                     sizeof(StandardInfo),
00267                                     FileStandardInformation);
00268     if (!NT_SUCCESS(Status))
00269     {
00270         DPRINT1("SMSS:PFILE: Failed query for size potential pagefile `%wZ' with status %X \n",
00271                 FileName, Status);
00272         NtClose(FileHandle);
00273         return Status;
00274     }
00275 
00276     NtClose(FileHandle);
00277     Size->QuadPart = StandardInfo.AllocationSize.QuadPart;
00278     return STATUS_SUCCESS;
00279 }
00280 
00281 NTSTATUS
00282 NTAPI
00283 SmpDeletePagingFile(IN PUNICODE_STRING FileName)
00284 {
00285     NTSTATUS Status;
00286     OBJECT_ATTRIBUTES ObjectAttributes;
00287     IO_STATUS_BLOCK IoStatusBlock;
00288     HANDLE FileHandle;
00289     FILE_DISPOSITION_INFORMATION Disposition;
00290 
00291     /* Open the page file */
00292     InitializeObjectAttributes(&ObjectAttributes,
00293                                FileName,
00294                                OBJ_CASE_INSENSITIVE,
00295                                NULL,
00296                                NULL);
00297     Status = NtOpenFile(&FileHandle,
00298                         DELETE,
00299                         &ObjectAttributes,
00300                         &IoStatusBlock,
00301                         FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
00302                         FILE_NON_DIRECTORY_FILE);
00303     if (NT_SUCCESS(Status))
00304     {
00305         /* Delete it */
00306         Disposition.DeleteFile = TRUE;
00307         Status = NtSetInformationFile(FileHandle,
00308                                       &IoStatusBlock,
00309                                       &Disposition,
00310                                       sizeof(Disposition),
00311                                       FileDispositionInformation);
00312         if (!NT_SUCCESS(Status))
00313         {
00314             DPRINT1("SMSS:PFILE: Failed to delete page file `%wZ' (status %X)\n",
00315                     FileName, Status);
00316         }
00317         else
00318         {
00319             DPRINT1("SMSS:PFILE: Deleted stale paging file - %wZ\n", FileName);
00320         }
00321 
00322         /* Close the handle */
00323         NtClose(FileHandle);
00324     }
00325     else
00326     {
00327         DPRINT1("SMSS:PFILE: Failed to open for deletion page file `%wZ' (status %X)\n",
00328                 FileName, Status);
00329     }
00330 
00331     /* All done */
00332     return Status;
00333 }
00334 
00335 NTSTATUS
00336 NTAPI
00337 SmpGetVolumeFreeSpace(IN PSMP_VOLUME_DESCRIPTOR Volume)
00338 {
00339     NTSTATUS Status;
00340     LARGE_INTEGER FreeSpace, FinalFreeSpace;
00341     FILE_FS_SIZE_INFORMATION SizeInfo;
00342     IO_STATUS_BLOCK IoStatusBlock;
00343     OBJECT_ATTRIBUTES ObjectAttributes;
00344     UNICODE_STRING VolumeName;
00345     HANDLE VolumeHandle;
00346     WCHAR PathString[32];
00347     ASSERT(Volume->Flags & SMP_VOLUME_IS_BOOT); // ASSERT says "BootVolume == 1"
00348 
00349     /* Build the standard path */
00350     wcscpy(PathString, L"\\??\\A:\\");
00351     RtlInitUnicodeString(&VolumeName, PathString);
00352     VolumeName.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = Volume->DriveLetter;
00353     DPRINT("SMSS:PFILE: Querying volume `%wZ' for free space \n", &VolumeName);
00354 
00355     /* Open the volume */
00356     InitializeObjectAttributes(&ObjectAttributes,
00357                                &VolumeName,
00358                                OBJ_CASE_INSENSITIVE,
00359                                NULL,
00360                                NULL);
00361     Status = NtOpenFile(&VolumeHandle,
00362                         FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
00363                         &ObjectAttributes,
00364                         &IoStatusBlock,
00365                         FILE_SHARE_READ | FILE_SHARE_WRITE,
00366                         FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
00367     if (!NT_SUCCESS(Status))
00368     {
00369         DPRINT1("SMSS:PFILE: Open volume `%wZ' failed with status %X \n", &VolumeName, Status);
00370         return Status;
00371     }
00372 
00373     /* Now get size information on the volume */
00374     Status = NtQueryVolumeInformationFile(VolumeHandle,
00375                                           &IoStatusBlock,
00376                                           &SizeInfo,
00377                                           sizeof(SizeInfo),
00378                                           FileFsSizeInformation);
00379     if (!NT_SUCCESS(Status))
00380     {
00381         /* We failed */
00382         DPRINT1("SMSS:PFILE: Query volume `%wZ' (handle %p) for size failed"
00383                 " with status %X \n",
00384                 &VolumeName,
00385                 VolumeHandle,
00386                 Status);
00387         NtClose(VolumeHandle);
00388         return Status;
00389     }
00390     NtClose(VolumeHandle);
00391 
00392     /* Compute how much free space we have */
00393     FreeSpace.QuadPart = SizeInfo.AvailableAllocationUnits.QuadPart *
00394                          SizeInfo.SectorsPerAllocationUnit;
00395     FinalFreeSpace.QuadPart = FreeSpace.QuadPart * SizeInfo.BytesPerSector;
00396 
00397     /* Check if there's less than 32MB free so we don't starve the disk */
00398     if (FinalFreeSpace.QuadPart <= MINIMUM_TO_KEEP_FREE)
00399     {
00400         /* In this case, act as if there's no free space  */
00401         Volume->FreeSpace.QuadPart = 0;
00402     }
00403     else
00404     {
00405         /* Trim off 32MB to give the disk a bit of breathing room */
00406         Volume->FreeSpace.QuadPart = FinalFreeSpace.QuadPart -
00407                                      MINIMUM_TO_KEEP_FREE;
00408     }
00409 
00410     return STATUS_SUCCESS;
00411 }
00412 
00413 PSMP_VOLUME_DESCRIPTOR
00414 NTAPI
00415 SmpSearchVolumeDescriptor(IN WCHAR DriveLetter)
00416 {
00417     WCHAR UpLetter;
00418     PSMP_VOLUME_DESCRIPTOR Volume = NULL;
00419     PLIST_ENTRY NextEntry;
00420 
00421     /* Use upper case to reduce differences */
00422     UpLetter = RtlUpcaseUnicodeChar(DriveLetter);
00423 
00424     /* Loop each volume */
00425     NextEntry = SmpVolumeDescriptorList.Flink;
00426     while (NextEntry != &SmpVolumeDescriptorList)
00427     {
00428         /* Grab the entry */
00429         Volume = CONTAINING_RECORD(NextEntry, SMP_VOLUME_DESCRIPTOR, Entry);
00430 
00431         /* Make sure it's a valid entry with an uppcase drive letter */
00432         ASSERT(Volume->Flags & SMP_VOLUME_INSERTED); // Volume->Initialized in ASSERT
00433         ASSERT(Volume->DriveLetter >= L'A' && Volume->DriveLetter <= L'Z');
00434 
00435         /* Break if it matches, if not, keep going */
00436         if (Volume->DriveLetter == UpLetter) break;
00437         NextEntry = NextEntry->Flink;
00438     }
00439 
00440     /* Return the volume if one was found */
00441     if (NextEntry == &SmpVolumeDescriptorList) Volume = NULL;
00442     return Volume;
00443 }
00444 
00445 NTSTATUS
00446 NTAPI
00447 SmpCreatePagingFile(IN PUNICODE_STRING Name,
00448                     IN PLARGE_INTEGER MinSize,
00449                     IN PLARGE_INTEGER MaxSize,
00450                     IN ULONG Priority)
00451 {
00452     NTSTATUS Status;
00453 
00454     /* Tell the kernel to create the pagefile */
00455     Status = NtCreatePagingFile(Name, MinSize, MaxSize, Priority);
00456     if (NT_SUCCESS(Status))
00457     {
00458         DPRINT("SMSS:PFILE: NtCreatePagingFile (%wZ, %I64X, %I64X) succeeded. \n",
00459                 Name,
00460                 MinSize->QuadPart,
00461                 MaxSize->QuadPart);
00462     }
00463     else
00464     {
00465         DPRINT1("SMSS:PFILE: NtCreatePagingFile (%wZ, %I64X, %I64X) failed with %X \n",
00466                 Name,
00467                 MinSize->QuadPart,
00468                 MaxSize->QuadPart,
00469                 Status);
00470     }
00471 
00472     /* Return the status */
00473     return Status;
00474 }
00475 
00476 NTSTATUS
00477 NTAPI
00478 SmpCreatePagingFileOnFixedDrive(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor,
00479                                 IN PLARGE_INTEGER FuzzFactor,
00480                                 IN PLARGE_INTEGER MinimumSize)
00481 {
00482     PSMP_VOLUME_DESCRIPTOR Volume;
00483     BOOLEAN ShouldDelete;
00484     NTSTATUS Status;
00485     LARGE_INTEGER PageFileSize;
00486     ASSERT(Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] != L'?');
00487 
00488     /* Try to find the volume descriptor for this drive letter */
00489     ShouldDelete = FALSE;
00490     Volume = SmpSearchVolumeDescriptor(Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET]);
00491     if (!Volume)
00492     {
00493         /* Couldn't find it, fail */
00494         DPRINT1("SMSS:PFILE: No volume descriptor for `%wZ' \n",
00495                 &Descriptor->Name);
00496         return STATUS_INVALID_PARAMETER;
00497     }
00498 
00499     /* Check if this is the boot volume */
00500     if (Volume->Flags & SMP_VOLUME_IS_BOOT)
00501     {
00502         /* Check if we haven't yet processed a crash dump on this volume */
00503         if (!(Descriptor->Flags & SMP_PAGEFILE_DUMP_PROCESSED))
00504         {
00505             /* Try to find a crash dump and extract it */
00506             DPRINT("SMSS:PFILE: Checking for crash dump in `%wZ' on boot volume \n",
00507                     &Descriptor->Name);
00508             SmpCheckForCrashDump(&Descriptor->Name);
00509 
00510             /* Update how much free space we have now that we extracted a dump */
00511             Status = SmpGetVolumeFreeSpace(Volume);
00512             if (!NT_SUCCESS(Status))
00513             {
00514                 DPRINT1("SMSS:PFILE: Failed to query free space for boot volume `%wC'\n",
00515                         Volume->DriveLetter);
00516             }
00517             else
00518             {
00519                 DPRINT("Queried free space for boot volume `%wC: %I64x'\n",
00520                         Volume->DriveLetter, Volume->FreeSpace.QuadPart);
00521             }
00522 
00523             /* Don't process crashdump on this volume anymore */
00524             Descriptor->Flags |= SMP_PAGEFILE_DUMP_PROCESSED;
00525         }
00526     }
00527     else
00528     {
00529         /* Crashdumps can only be on the boot volume */
00530         DPRINT("SMSS:PFILE: Skipping crash dump checking for `%wZ' on non boot"
00531                 "volume `%wC' \n",
00532                 &Descriptor->Name,
00533                 Volume->DriveLetter);
00534     }
00535 
00536     /* Update the size after dump extraction */
00537     Descriptor->ActualMinSize = Descriptor->MinSize;
00538     Descriptor->ActualMaxSize = Descriptor->MaxSize;
00539 
00540     /* Check how big we can make the pagefile */
00541     Status = SmpGetPagingFileSize(&Descriptor->Name, &PageFileSize);
00542     if (NT_SUCCESS(Status) && PageFileSize.QuadPart > 0) ShouldDelete = TRUE;
00543     DPRINT("SMSS:PFILE: Detected size %I64X for future paging file `%wZ'\n",
00544             PageFileSize,
00545             &Descriptor->Name);
00546     DPRINT("SMSS:PFILE: Free space on volume `%wC' is %I64X \n",
00547             Volume->DriveLetter,
00548             Volume->FreeSpace.QuadPart);
00549 
00550     /* Now update our size and make sure none of these are too big */
00551     PageFileSize.QuadPart += Volume->FreeSpace.QuadPart;
00552     if (Descriptor->ActualMinSize.QuadPart > PageFileSize.QuadPart)
00553     {
00554         Descriptor->ActualMinSize = PageFileSize;
00555     }
00556     if (Descriptor->ActualMaxSize.QuadPart > PageFileSize.QuadPart)
00557     {
00558         Descriptor->ActualMaxSize = PageFileSize;
00559     }
00560     DPRINT("SMSS:PFILE: min %I64X, max %I64X, real min %I64X \n",
00561             Descriptor->ActualMinSize.QuadPart,
00562             Descriptor->ActualMaxSize.QuadPart,
00563             MinimumSize->QuadPart);
00564 
00565     /* Keep going until we've created a pagefile of the right size */
00566     while (Descriptor->ActualMinSize.QuadPart >= MinimumSize->QuadPart)
00567     {
00568         /* Call NT to do it */
00569         Status = SmpCreatePagingFile(&Descriptor->Name,
00570                                      &Descriptor->ActualMinSize,
00571                                      &Descriptor->ActualMaxSize,
00572                                      0);
00573         if (NT_SUCCESS(Status))
00574         {
00575             /* We're done, update flags and increase the count */
00576             Descriptor->Flags |= SMP_PAGEFILE_CREATED;
00577             Volume->Flags |= SMP_VOLUME_PAGEFILE_CREATED;
00578             Volume->PageFileCount++;
00579             break;
00580         }
00581 
00582         /* We failed, try a slighly smaller pagefile */
00583         Descriptor->ActualMinSize.QuadPart -= FuzzFactor->QuadPart;
00584     }
00585 
00586     /* Check if we weren't able to create it */
00587     if (Descriptor->ActualMinSize.QuadPart < MinimumSize->QuadPart)
00588     {
00589         /* Delete the current page file and fail */
00590         if (ShouldDelete)
00591         {
00592             SmpDeletePagingFile(&Descriptor->Name);
00593 
00594             /* FIXFIX: Windows Vista does this, and it seems like we should too, so try to see if this fixes KVM */
00595             Volume->FreeSpace.QuadPart = PageFileSize.QuadPart;
00596         }
00597         DPRINT1("SMSS:PFILE: Failing for min %I64X, max %I64X, real min %I64X \n",
00598                 Descriptor->ActualMinSize.QuadPart,
00599                 Descriptor->ActualMaxSize.QuadPart,
00600                 MinimumSize->QuadPart);
00601         Status = STATUS_DISK_FULL;
00602     }
00603 
00604     /* Return the status */
00605     return Status;
00606 }
00607 
00608 NTSTATUS
00609 NTAPI
00610 SmpCreatePagingFileOnAnyDrive(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor,
00611                               IN PLARGE_INTEGER FuzzFactor,
00612                               IN PLARGE_INTEGER MinimumSize)
00613 {
00614     PSMP_VOLUME_DESCRIPTOR Volume;
00615     NTSTATUS Status = STATUS_DISK_FULL;
00616     PLIST_ENTRY NextEntry;
00617     ASSERT(Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] == L'?');
00618 
00619     /* Loop the volume list */
00620     NextEntry = SmpVolumeDescriptorList.Flink;
00621     while (NextEntry != &SmpVolumeDescriptorList)
00622     {
00623         /* Get the volume */
00624         Volume = CONTAINING_RECORD(NextEntry, SMP_VOLUME_DESCRIPTOR, Entry);
00625 
00626         /* Make sure it's inserted and on a valid drive letter */
00627         ASSERT(Volume->Flags & SMP_VOLUME_INSERTED); // Volume->Initialized in ASSERT
00628         ASSERT(Volume->DriveLetter >= L'A' && Volume->DriveLetter <= L'Z');
00629 
00630         /* Write the drive letter to try creating it on this volume */
00631         Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = Volume->DriveLetter;
00632         Status = SmpCreatePagingFileOnFixedDrive(Descriptor,
00633                                                  FuzzFactor,
00634                                                  MinimumSize);
00635         if (NT_SUCCESS(Status)) break;
00636 
00637         /* It didn't work, make it an any pagefile again and keep going */
00638         Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = L'?';
00639         NextEntry = NextEntry->Flink;
00640     }
00641 
00642     /* Return disk full or success */
00643     return Status;
00644 }
00645 
00646 VOID
00647 NTAPI
00648 SmpMakeDefaultPagingFileDescriptor(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor)
00649 {
00650     /* The default descriptor uses 128MB as a pagefile size */
00651     Descriptor->Flags |= SMP_PAGEFILE_DEFAULT;
00652     Descriptor->MinSize.QuadPart = 128 * MEGABYTE;
00653     Descriptor->MaxSize.QuadPart = 128 * MEGABYTE;
00654 }
00655 
00656 VOID
00657 NTAPI
00658 SmpMakeSystemManagedPagingFileDescriptor(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor)
00659 {
00660     NTSTATUS Status;
00661     LONGLONG MinimumSize, MaximumSize, Ram;
00662     SYSTEM_BASIC_INFORMATION BasicInfo;
00663 
00664     /* Query the page size of the system, and the amount of RAM */
00665     Status = NtQuerySystemInformation(SystemBasicInformation,
00666                                       &BasicInfo,
00667                                       sizeof(BasicInfo),
00668                                       NULL);
00669     if (!NT_SUCCESS(Status))
00670     {
00671         /* If we failed, use defaults since we have no idea otherwise */
00672         DPRINT1("SMSS:PFILE: NtQuerySystemInformation failed with %x \n", Status);
00673         SmpMakeDefaultPagingFileDescriptor(Descriptor);
00674         return;
00675     }
00676 
00677     /* Chekc how much RAM we have and set three times this amount as maximum */
00678     Ram = BasicInfo.NumberOfPhysicalPages * BasicInfo.PageSize;
00679     MaximumSize = 3 * Ram;
00680 
00681     /* If we have more than 1GB, use that as minimum, otherwise, use 1.5X RAM */
00682     MinimumSize = (Ram >= 1024 * MEGABYTE) ? Ram : MaximumSize / 2;
00683 
00684     /* Write the new sizes in the descriptor and mark it as system managed */
00685     Descriptor->MinSize.QuadPart = MinimumSize;
00686     Descriptor->MaxSize.QuadPart = MaximumSize;
00687     Descriptor->Flags |= SMP_PAGEFILE_SYSTEM_MANAGED;
00688 }
00689 
00690 NTSTATUS
00691 NTAPI
00692 SmpValidatePagingFileSizes(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor)
00693 {
00694     NTSTATUS Status = STATUS_SUCCESS;
00695     ULONGLONG MinSize, MaxSize;
00696     BOOLEAN WasTooBig = FALSE;
00697 
00698     /* Capture the min and max */
00699     MinSize = Descriptor->MinSize.QuadPart;
00700     MaxSize = Descriptor->MaxSize.QuadPart;
00701     DPRINT("SMSS:PFILE: Validating sizes for `%wZ' %I64X %I64X\n",
00702              &Descriptor->Name, MinSize, MaxSize);
00703 
00704     /* Don't let minimum be bigger than maximum */
00705     if (MinSize > MaxSize) MaxSize = MinSize;
00706 
00707     /* On PAE we can have bigger pagefiles... */
00708     if (SharedUserData->ProcessorFeatures[PF_PAE_ENABLED])
00709     {
00710         /* But we don't support that yet */
00711         DPRINT1("ReactOS does not support PAE yet... assuming sizes OK\n");
00712     }
00713     else
00714     {
00715         /* Check if the minimum is more then 4095 MB */
00716         if (MinSize > MAXIMUM_PAGEFILE_SIZE)
00717         {
00718             /* Trim it, this isn't allowed */
00719             WasTooBig = TRUE;
00720             MinSize = MAXIMUM_PAGEFILE_SIZE;
00721         }
00722 
00723         /* Check if the maximum is more then 4095 MB */
00724         if (MaxSize > MAXIMUM_PAGEFILE_SIZE)
00725         {
00726             /* Trim it, this isn't allowed */
00727             WasTooBig = TRUE;
00728             MaxSize = MAXIMUM_PAGEFILE_SIZE;
00729         }
00730     }
00731 
00732     /* Did we trim? */
00733     if (WasTooBig)
00734     {
00735         /* Notify debugger output and write a flag in the descriptor */
00736         DPRINT("SMSS:PFILE: Trimmed size of `%wZ' to maximum allowed \n",
00737                 &Descriptor->Name);
00738         Descriptor->Flags |= SMP_PAGEFILE_WAS_TOO_BIG;
00739     }
00740 
00741     /* Now write the (possibly trimmed) sizes back */
00742     Descriptor->MinSize.QuadPart = MinSize;
00743     Descriptor->MaxSize.QuadPart = MaxSize;
00744     return Status;
00745 }
00746 
00747 NTSTATUS
00748 NTAPI
00749 SmpCreateSystemManagedPagingFile(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor,
00750                                  IN BOOLEAN DecreaseSize)
00751 {
00752     LARGE_INTEGER FuzzFactor, Size;
00753 
00754     /* Make sure there's at least 1 paging file and that we are system-managed */
00755     ASSERT(SmpNumberOfPagingFiles >= 1);
00756     ASSERT(!IsListEmpty(&SmpPagingFileDescriptorList));
00757     ASSERT(Descriptor->Flags & SMP_PAGEFILE_SYSTEM_MANAGED); // Descriptor->SystemManaged == 1 in ASSERT.
00758 
00759     /* Keep decreasing the pagefile by this amount if we run out of space */
00760     FuzzFactor.QuadPart = FUZZ_FACTOR;
00761 
00762     /* Create the descriptor for it (mainly the right sizes) and validate */
00763     SmpMakeSystemManagedPagingFileDescriptor(Descriptor);
00764     SmpValidatePagingFileSizes(Descriptor);
00765 
00766     /* Use either the minimum size in the descriptor, or 16MB in minimal mode */
00767     Size.QuadPart = DecreaseSize ? 16 * MEGABYTE : Descriptor->MinSize.QuadPart;
00768 
00769     /* Check if this should be a fixed pagefile or an any pagefile*/
00770     if (Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] == '?')
00771     {
00772         /* Find a disk for it */
00773         return SmpCreatePagingFileOnAnyDrive(Descriptor, &FuzzFactor, &Size);
00774     }
00775 
00776     /* Use the disk that was given */
00777     return SmpCreatePagingFileOnFixedDrive(Descriptor, &FuzzFactor, &Size);
00778 }
00779 
00780 NTSTATUS
00781 NTAPI
00782 SmpCreateEmergencyPagingFile(VOID)
00783 {
00784     PSMP_PAGEFILE_DESCRIPTOR Descriptor;
00785     WCHAR Buffer[32];
00786 
00787     /* Allocate a descriptor */
00788     Descriptor = RtlAllocateHeap(RtlGetProcessHeap(),
00789                                  HEAP_ZERO_MEMORY,
00790                                  sizeof(SMP_PAGEFILE_DESCRIPTOR));
00791     if (!Descriptor) return STATUS_NO_MEMORY;
00792 
00793     /* Initialize it */
00794     RtlInitUnicodeString(&Descriptor->Token, NULL);
00795 
00796     /* Copy the default pagefile name */
00797     ASSERT(sizeof(Buffer) >= sizeof(STANDARD_PAGING_FILE_NAME));
00798     wcscpy(Buffer, STANDARD_PAGING_FILE_NAME);
00799 
00800     /* Fill the rest of the descriptor out */
00801     RtlInitUnicodeString(&Descriptor->Name, Buffer);
00802     Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = '?';
00803     Descriptor->Flags |= SMP_PAGEFILE_SYSTEM_MANAGED |
00804                          SMP_PAGEFILE_EMERGENCY |
00805                          SMP_PAGEFILE_ON_ANY_DRIVE;
00806 
00807     /* Insert it into the descriptor list */
00808     InsertHeadList(&SmpPagingFileDescriptorList, &Descriptor->Entry);
00809     SmpNumberOfPagingFiles++;
00810 
00811     /* Go ahead and create it now, with the minimal size possible */
00812     return SmpCreateSystemManagedPagingFile(Descriptor, TRUE);
00813 }
00814 
00815 NTSTATUS
00816 NTAPI
00817 SmpCreateVolumeDescriptors(VOID)
00818 {
00819     NTSTATUS Status;
00820     UNICODE_STRING VolumePath;
00821     BOOLEAN BootVolumeFound = FALSE;
00822     WCHAR StartChar, Drive, DriveDiff;
00823     HANDLE VolumeHandle;
00824     OBJECT_ATTRIBUTES ObjectAttributes;
00825     IO_STATUS_BLOCK IoStatusBlock;
00826     PROCESS_DEVICEMAP_INFORMATION ProcessInformation;
00827     FILE_FS_DEVICE_INFORMATION DeviceInfo;
00828     FILE_FS_SIZE_INFORMATION SizeInfo;
00829     PSMP_VOLUME_DESCRIPTOR Volume;
00830     LARGE_INTEGER FreeSpace, FinalFreeSpace;
00831     WCHAR Buffer[32];
00832 
00833     /* We should be starting with an empty list */
00834     ASSERT(IsListEmpty(&SmpVolumeDescriptorList));
00835 
00836     /* Query the device map so we can get the drive letters */
00837     Status = NtQueryInformationProcess(NtCurrentProcess(),
00838                                        ProcessDeviceMap,
00839                                        &ProcessInformation,
00840                                        sizeof(ProcessInformation),
00841                                        NULL);
00842     if (!NT_SUCCESS(Status))
00843     {
00844         DPRINT1("SMSS:PFILE: Query(ProcessDeviceMap) failed with status %X \n",
00845                 Status);
00846         return Status;
00847     }
00848 
00849     /* Build the volume string, starting with A: (we'll edit this in place) */
00850     wcscpy(Buffer, L"\\??\\A:\\");
00851     RtlInitUnicodeString(&VolumePath, Buffer);
00852 
00853     /* Start with the C drive except on weird Japanese NECs... */
00854     StartChar = SharedUserData->AlternativeArchitecture ? L'A' : L'C';
00855     for (Drive = StartChar, DriveDiff = StartChar - L'A'; Drive <= L'Z'; Drive++, DriveDiff++)
00856     {
00857         /* Skip the disk if it's not in the drive map */
00858         if (!((1 << DriveDiff) & ProcessInformation.Query.DriveMap)) continue;
00859 
00860         /* Write the drive letter and try to open the volume */
00861         VolumePath.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = Drive;
00862         InitializeObjectAttributes(&ObjectAttributes,
00863                                    &VolumePath,
00864                                    OBJ_CASE_INSENSITIVE,
00865                                    NULL,
00866                                    NULL);
00867         Status = NtOpenFile(&VolumeHandle,
00868                             FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
00869                             &ObjectAttributes,
00870                             &IoStatusBlock,
00871                             FILE_SHARE_READ | FILE_SHARE_WRITE,
00872                             FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
00873         if (!NT_SUCCESS(Status))
00874         {
00875             /* Skip the volume if we failed */
00876             DPRINT1("SMSS:PFILE: Open volume `%wZ' failed with status %X \n",
00877                     &VolumePath, Status);
00878             continue;
00879         }
00880 
00881         /* Now query device information on the volume */
00882         Status = NtQueryVolumeInformationFile(VolumeHandle,
00883                                               &IoStatusBlock,
00884                                               &DeviceInfo,
00885                                               sizeof(DeviceInfo),
00886                                               FileFsDeviceInformation);
00887         if (!NT_SUCCESS(Status))
00888         {
00889             /* Move to the next volume if we failed */
00890             DPRINT1("SMSS:PFILE: Query volume `%wZ' (handle %p) for device info"
00891                     " failed with status %X \n",
00892                     &VolumePath,
00893                     VolumeHandle,
00894                     Status);
00895             NtClose(VolumeHandle);
00896             continue;
00897         }
00898 
00899         /* Check if this is a fixed disk */
00900         if (DeviceInfo.Characteristics & (FILE_FLOPPY_DISKETTE |
00901                                           FILE_READ_ONLY_DEVICE |
00902                                           FILE_REMOTE_DEVICE |
00903                                           FILE_REMOVABLE_MEDIA))
00904         {
00905             /* It isn't, so skip it */
00906             DPRINT1("SMSS:PFILE: Volume `%wZ' (%X) cannot store a paging file \n",
00907                     &VolumePath,
00908                     DeviceInfo.Characteristics);
00909             NtClose(VolumeHandle);
00910             continue;
00911         }
00912 
00913         /* We found a fixed volume, allocate a descriptor for it */
00914         Volume = RtlAllocateHeap(RtlGetProcessHeap(),
00915                                  HEAP_ZERO_MEMORY,
00916                                  sizeof(SMP_VOLUME_DESCRIPTOR));
00917         if (!Volume)
00918         {
00919             /* Failed to allocate memory, try the next disk */
00920             DPRINT1("SMSS:PFILE: Failed to allocate a volume descriptor (%u bytes) \n",
00921                     sizeof(SMP_VOLUME_DESCRIPTOR));
00922             NtClose(VolumeHandle);
00923             continue;
00924         }
00925 
00926         /* Save the drive letter and device information */
00927         Volume->DriveLetter = Drive;
00928         Volume->DeviceInfo = DeviceInfo;
00929 
00930         /* Check if this is the boot volume */
00931         if (RtlUpcaseUnicodeChar(Drive) ==
00932             RtlUpcaseUnicodeChar(SharedUserData->NtSystemRoot[0]))
00933         {
00934             /* Save it */
00935             ASSERT(BootVolumeFound == FALSE);
00936             Volume->Flags |= SMP_VOLUME_IS_BOOT;
00937             BootVolumeFound = TRUE;
00938         }
00939 
00940         /* Now get size information on the volume */
00941         Status = NtQueryVolumeInformationFile(VolumeHandle,
00942                                               &IoStatusBlock,
00943                                               &SizeInfo,
00944                                               sizeof(SizeInfo),
00945                                               FileFsSizeInformation);
00946         if (!NT_SUCCESS(Status))
00947         {
00948             /* We failed -- keep going */
00949             DPRINT1("SMSS:PFILE: Query volume `%wZ' (handle %p) for size failed"
00950                     " with status %X \n",
00951                     &VolumePath,
00952                     VolumeHandle,
00953                     Status);
00954             RtlFreeHeap(RtlGetProcessHeap(), 0, Volume);
00955             NtClose(VolumeHandle);
00956             continue;
00957         }
00958 
00959         /* Done querying volume information, close the handle */
00960         NtClose(VolumeHandle);
00961 
00962         /* Compute how much free space we have */
00963         FreeSpace.QuadPart = SizeInfo.AvailableAllocationUnits.QuadPart *
00964                              SizeInfo.SectorsPerAllocationUnit;
00965         FinalFreeSpace.QuadPart = FreeSpace.QuadPart * SizeInfo.BytesPerSector;
00966 
00967         /* Check if there's less than 32MB free so we don't starve the disk */
00968         if (FinalFreeSpace.QuadPart <= MINIMUM_TO_KEEP_FREE)
00969         {
00970             /* In this case, act as if there's no free space  */
00971             Volume->FreeSpace.QuadPart = 0;
00972         }
00973         else
00974         {
00975             /* Trim off 32MB to give the disk a bit of breathing room */
00976             Volume->FreeSpace.QuadPart = FinalFreeSpace.QuadPart -
00977                                          MINIMUM_TO_KEEP_FREE;
00978         }
00979 
00980         /* All done, add this volume to our descriptor list */
00981         InsertTailList(&SmpVolumeDescriptorList, &Volume->Entry);
00982         Volume->Flags |= SMP_VOLUME_INSERTED;
00983         DPRINT("SMSS:PFILE: Created volume descriptor for`%wZ' \n", &VolumePath);
00984     }
00985 
00986     /* We must've found at least the boot volume */
00987     ASSERT(BootVolumeFound == TRUE);
00988     ASSERT(!IsListEmpty(&SmpVolumeDescriptorList));
00989     if (!IsListEmpty(&SmpVolumeDescriptorList)) return STATUS_SUCCESS;
00990 
00991     /* Something is really messed up if we found no disks at all */
00992     return STATUS_UNEXPECTED_IO_ERROR;
00993 }
00994 
00995 NTSTATUS
00996 NTAPI
00997 SmpCreatePagingFiles(VOID)
00998 {
00999     NTSTATUS Status;
01000     PSMP_PAGEFILE_DESCRIPTOR Descriptor;
01001     LARGE_INTEGER Size, FuzzFactor;
01002     BOOLEAN Created = FALSE;
01003     PLIST_ENTRY NextEntry;
01004 
01005     /* Check if no paging files were requested */
01006     if (!(SmpNumberOfPagingFiles) && !(SmpRegistrySpecifierPresent))
01007     {
01008         /* The list should be empty -- nothign to do */
01009         ASSERT(IsListEmpty(&SmpPagingFileDescriptorList));
01010         DPRINT1("SMSS:PFILE: No paging file was requested \n");
01011         return STATUS_SUCCESS;
01012     }
01013 
01014     /* Initialize the volume descriptors so we can know what's available */
01015     Status = SmpCreateVolumeDescriptors();
01016     if (!NT_SUCCESS(Status))
01017     {
01018         /* We can't make decisions without this, so fail */
01019         DPRINT1("SMSS:PFILE: Failed to create volume descriptors (status %X)\n",
01020                 Status);
01021         return Status;
01022     }
01023 
01024     /* If we fail creating pagefiles, try to reduce by this much each time */
01025     FuzzFactor.QuadPart = FUZZ_FACTOR;
01026 
01027     /* Loop the descriptor list */
01028     NextEntry = SmpPagingFileDescriptorList.Flink;
01029     while (NextEntry != &SmpPagingFileDescriptorList)
01030     {
01031         /* Check what kind of descriptor this is */
01032         Descriptor = CONTAINING_RECORD(NextEntry, SMP_PAGEFILE_DESCRIPTOR, Entry);
01033         if (Descriptor->Flags & SMP_PAGEFILE_SYSTEM_MANAGED)
01034         {
01035             /* This is a system-managed descriptor. Create the correct file */
01036             DPRINT("SMSS:PFILE: Creating a system managed paging file (`%wZ')\n",
01037                     &Descriptor->Name);
01038             Status = SmpCreateSystemManagedPagingFile(Descriptor, FALSE);
01039             if (!NT_SUCCESS(Status))
01040             {
01041                 /* We failed -- try again, with size minimization this time */
01042                 DPRINT1("SMSS:PFILE: Trying lower sizes for (`%wZ') \n",
01043                         &Descriptor->Name);
01044                 Status = SmpCreateSystemManagedPagingFile(Descriptor, TRUE);
01045             }
01046         }
01047         else
01048         {
01049             /* This is a manually entered descriptor. Validate its size first */
01050             SmpValidatePagingFileSizes(Descriptor);
01051 
01052             /* Check if this is an ANY pagefile or a FIXED pagefile */
01053             DPRINT("SMSS:PFILE: Creating a normal paging file (`%wZ') \n",
01054                     &Descriptor->Name);
01055             if (Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] == L'?')
01056             {
01057                 /* It's an any pagefile, try to create it wherever possible */
01058                 Size = Descriptor->MinSize;
01059                 Status = SmpCreatePagingFileOnAnyDrive(Descriptor,
01060                                                        &FuzzFactor,
01061                                                        &Size);
01062                 if (!NT_SUCCESS(Status))
01063                 {
01064                     /* We failed to create it. Try again with a smaller size */
01065                     DPRINT1("SMSS:PFILE: Trying lower sizes for (`%wZ') \n",
01066                             &Descriptor->Name);
01067                     Size.QuadPart = 16 * MEGABYTE;
01068                     Status = SmpCreatePagingFileOnAnyDrive(Descriptor,
01069                                                            &FuzzFactor,
01070                                                            &Size);
01071                 }
01072             }
01073             else
01074             {
01075                 /* It's a fixed pagefile: override the minimum and use ours */
01076                 Size.QuadPart = 16 * MEGABYTE;
01077                 Status = SmpCreatePagingFileOnFixedDrive(Descriptor,
01078                                                          &FuzzFactor,
01079                                                          &Size);
01080             }
01081         }
01082 
01083         /* Go to the next descriptor */
01084         if (NT_SUCCESS(Status)) Created = TRUE;
01085         NextEntry = NextEntry->Flink;
01086     }
01087 
01088     /* Check if none of the code in our loops above was able to create it */
01089     if (!Created)
01090     {
01091         /* Build an emergency pagefile ourselves */
01092         DPRINT1("SMSS:PFILE: Creating emergency paging file. \n");
01093         Status = SmpCreateEmergencyPagingFile();
01094     }
01095 
01096     /* All done */
01097     return Status;
01098 }

Generated on Sat May 26 2012 04:17:44 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.