15
15
/* GLOBALS ********************************************************************/
16
16
17
17
//
18
- // Taken from ASSERTs
18
+ // Constants
19
19
//
20
20
#define STANDARD_PAGING_FILE_NAME L"\\??\\?:\\pagefile.sys"
21
21
#define STANDARD_DRIVE_LETTER_OFFSET 4
22
+ #define MEGABYTE 0x100000UL
23
+ #define MAXIMUM_PAGEFILE_SIZE (4095 * MEGABYTE)
24
+ /* This should be 32 MB, but we need more than that for 2nd stage setup */
25
+ #define MINIMUM_TO_KEEP_FREE (64 * MEGABYTE)
26
+ #define FUZZ_FACTOR (16 * MEGABYTE)
22
27
23
28
//
24
29
// Structure and flags describing each pagefile
@@ -83,9 +88,8 @@ SmpCreatePagingFileDescriptor(IN PUNICODE_STRING PageFileToken)
83
88
PSMP_PAGEFILE_DESCRIPTOR Descriptor , ListDescriptor ;
84
89
ULONG i ;
85
90
WCHAR c ;
86
- PWCHAR p , ArgBuffer ;
87
91
PLIST_ENTRY NextEntry ;
88
- UNICODE_STRING PageFileName , Arguments ;
92
+ UNICODE_STRING PageFileName , Arguments , SecondArgument ;
89
93
90
94
/* Make sure we don't have too many */
91
95
if (SmpNumberOfPagingFiles >= 16 )
@@ -131,7 +135,7 @@ SmpCreatePagingFileDescriptor(IN PUNICODE_STRING PageFileToken)
131
135
}
132
136
133
137
/* Was a pagefile not specified, or was it specified with no size? */
134
- if ((Arguments .Buffer ) || (ZeroSize ))
138
+ if (! (Arguments .Buffer ) || (ZeroSize ))
135
139
{
136
140
/* In this case, the system will manage its size */
137
141
SystemManaged = TRUE;
@@ -149,17 +153,18 @@ SmpCreatePagingFileDescriptor(IN PUNICODE_STRING PageFileToken)
149
153
}
150
154
151
155
/* Now advance to the next argument */
152
- ArgBuffer = Arguments .Buffer ;
153
- p = ArgBuffer ;
154
- while (* p ++ )
156
+ for (i = 0 ; i < Arguments .Length / sizeof (WCHAR ); i ++ )
155
157
{
156
- /* Which should be a space... */
157
- if (* p == L' ' )
158
+ /* Found a space -- second argument must start here */
159
+ if (Arguments . Buffer [ i ] == L' ' )
158
160
{
159
- /* And use the rest of the arguments as a maximum size */
160
- Arguments .Length -= ((PCHAR )p - (PCHAR )ArgBuffer );
161
- Arguments .Buffer = ArgBuffer ;
162
- Status = RtlUnicodeStringToInteger (& Arguments , 0 , & MaxSize );
161
+ /* Use the rest of the arguments as a maximum size */
162
+ SecondArgument .Buffer = & Arguments .Buffer [i ];
163
+ SecondArgument .Length = Arguments .Length -
164
+ i * sizeof (WCHAR );
165
+ SecondArgument .MaximumLength = Arguments .MaximumLength -
166
+ i * sizeof (WCHAR );
167
+ Status = RtlUnicodeStringToInteger (& SecondArgument , 0 , & MaxSize );
163
168
if (!NT_SUCCESS (Status ))
164
169
{
165
170
/* Fail */
@@ -168,8 +173,6 @@ SmpCreatePagingFileDescriptor(IN PUNICODE_STRING PageFileToken)
168
173
return Status ;
169
174
}
170
175
171
- /* We have both min and max, restore argument buffer */
172
- Arguments .Buffer = ArgBuffer ; // Actual Windows Bug in faillure case above.
173
176
break ;
174
177
}
175
178
}
@@ -192,8 +195,8 @@ SmpCreatePagingFileDescriptor(IN PUNICODE_STRING PageFileToken)
192
195
/* Capture all our data into the descriptor */
193
196
Descriptor -> Token = * PageFileToken ;
194
197
Descriptor -> Name = PageFileName ;
195
- Descriptor -> MinSize .QuadPart = MinSize * 0x100000 ;
196
- Descriptor -> MaxSize .QuadPart = MaxSize * 0x100000 ;
198
+ Descriptor -> MinSize .QuadPart = MinSize * MEGABYTE ;
199
+ Descriptor -> MaxSize .QuadPart = MaxSize * MEGABYTE ;
197
200
if (SystemManaged ) Descriptor -> Flags |= SMP_PAGEFILE_SYSTEM_MANAGED ;
198
201
Descriptor -> Name .Buffer [STANDARD_DRIVE_LETTER_OFFSET ] =
199
202
RtlUpcaseUnicodeChar (Descriptor -> Name .Buffer [STANDARD_DRIVE_LETTER_OFFSET ]);
@@ -271,8 +274,7 @@ SmpGetPagingFileSize(IN PUNICODE_STRING FileName,
271
274
}
272
275
273
276
NtClose (FileHandle );
274
- Size -> LowPart = StandardInfo .AllocationSize .LowPart ;
275
- Size -> HighPart = StandardInfo .AllocationSize .HighPart ;
277
+ Size -> QuadPart = StandardInfo .AllocationSize .QuadPart ;
276
278
return STATUS_SUCCESS ;
277
279
}
278
280
@@ -346,9 +348,7 @@ SmpGetVolumeFreeSpace(IN PSMP_VOLUME_DESCRIPTOR Volume)
346
348
347
349
/* Build the standard path */
348
350
wcscpy (PathString , L"\\??\\A:\\" );
349
- VolumeName .Buffer = PathString ;
350
- VolumeName .Length = wcslen (PathString ) * sizeof (WCHAR );
351
- VolumeName .MaximumLength = VolumeName .Length + sizeof (UNICODE_NULL );
351
+ RtlInitUnicodeString (& VolumeName , PathString );
352
352
VolumeName .Buffer [STANDARD_DRIVE_LETTER_OFFSET ] = Volume -> DriveLetter ;
353
353
DPRINT ("SMSS:PFILE: Querying volume `%wZ' for free space \n" , & VolumeName );
354
354
@@ -378,13 +378,12 @@ SmpGetVolumeFreeSpace(IN PSMP_VOLUME_DESCRIPTOR Volume)
378
378
FileFsSizeInformation );
379
379
if (!NT_SUCCESS (Status ))
380
380
{
381
- /* We failed -- keep going */
381
+ /* We failed */
382
382
DPRINT1 ("SMSS:PFILE: Query volume `%wZ' (handle %p) for size failed"
383
383
" with status %X \n" ,
384
384
& VolumeName ,
385
385
VolumeHandle ,
386
386
Status );
387
- RtlFreeHeap (RtlGetProcessHeap (), 0 , Volume );
388
387
NtClose (VolumeHandle );
389
388
return Status ;
390
389
}
@@ -394,18 +393,18 @@ SmpGetVolumeFreeSpace(IN PSMP_VOLUME_DESCRIPTOR Volume)
394
393
FreeSpace .QuadPart = SizeInfo .AvailableAllocationUnits .QuadPart *
395
394
SizeInfo .SectorsPerAllocationUnit ;
396
395
FinalFreeSpace .QuadPart = FreeSpace .QuadPart * SizeInfo .BytesPerSector ;
397
- Volume -> FreeSpace = FinalFreeSpace ;
398
396
399
397
/* Check if there's less than 32MB free so we don't starve the disk */
400
- if (FinalFreeSpace .QuadPart <= 0x2000000 )
398
+ if (FinalFreeSpace .QuadPart <= MINIMUM_TO_KEEP_FREE )
401
399
{
402
400
/* In this case, act as if there's no free space */
403
401
Volume -> FreeSpace .QuadPart = 0 ;
404
402
}
405
403
else
406
404
{
407
405
/* Trim off 32MB to give the disk a bit of breathing room */
408
- Volume -> FreeSpace .QuadPart = FinalFreeSpace .QuadPart - 0x2000000 ;
406
+ Volume -> FreeSpace .QuadPart = FinalFreeSpace .QuadPart -
407
+ MINIMUM_TO_KEEP_FREE ;
409
408
}
410
409
411
410
return STATUS_SUCCESS ;
@@ -540,7 +539,7 @@ SmpCreatePagingFileOnFixedDrive(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor,
540
539
541
540
/* Check how big we can make the pagefile */
542
541
Status = SmpGetPagingFileSize (& Descriptor -> Name , & PageFileSize );
543
- if (PageFileSize .QuadPart > 0 ) ShouldDelete = TRUE;
542
+ if (NT_SUCCESS ( Status ) && PageFileSize .QuadPart > 0 ) ShouldDelete = TRUE;
544
543
DPRINT ("SMSS:PFILE: Detected size %I64X for future paging file `%wZ'\n" ,
545
544
PageFileSize ,
546
545
& Descriptor -> Name );
@@ -588,7 +587,13 @@ SmpCreatePagingFileOnFixedDrive(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor,
588
587
if (Descriptor -> ActualMinSize .QuadPart < MinimumSize -> QuadPart )
589
588
{
590
589
/* Delete the current page file and fail */
591
- if (ShouldDelete ) SmpDeletePagingFile (& Descriptor -> Name );
590
+ if (ShouldDelete )
591
+ {
592
+ SmpDeletePagingFile (& Descriptor -> Name );
593
+
594
+ /* FIXFIX: Windows Vista does this, and it seems like we should too, so try to see if this fixes KVM */
595
+ Volume -> FreeSpace .QuadPart = PageFileSize .QuadPart ;
596
+ }
592
597
DPRINT1 ("SMSS:PFILE: Failing for min %I64X, max %I64X, real min %I64X \n" ,
593
598
Descriptor -> ActualMinSize .QuadPart ,
594
599
Descriptor -> ActualMaxSize .QuadPart ,
@@ -644,8 +649,8 @@ SmpMakeDefaultPagingFileDescriptor(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor)
644
649
{
645
650
/* The default descriptor uses 128MB as a pagefile size */
646
651
Descriptor -> Flags |= SMP_PAGEFILE_DEFAULT ;
647
- Descriptor -> MinSize .QuadPart = 0x8000000 ;
648
- Descriptor -> MaxSize .QuadPart = 0x8000000 ;
652
+ Descriptor -> MinSize .QuadPart = 128 * MEGABYTE ;
653
+ Descriptor -> MaxSize .QuadPart = 128 * MEGABYTE ;
649
654
}
650
655
651
656
VOID
@@ -674,7 +679,7 @@ SmpMakeSystemManagedPagingFileDescriptor(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor)
674
679
MaximumSize = 3 * Ram ;
675
680
676
681
/* If we have more than 1GB, use that as minimum, otherwise, use 1.5X RAM */
677
- MinimumSize = (Ram >= 0x40000000 ) ? Ram : MaximumSize / 2 ;
682
+ MinimumSize = (Ram >= 1024 * MEGABYTE ) ? Ram : MaximumSize / 2 ;
678
683
679
684
/* Write the new sizes in the descriptor and mark it as system managed */
680
685
Descriptor -> MinSize .QuadPart = MinimumSize ;
@@ -708,19 +713,19 @@ SmpValidatePagingFileSizes(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor)
708
713
else
709
714
{
710
715
/* Check if the minimum is more then 4095 MB */
711
- if (MinSize > 0xFFF00000 )
716
+ if (MinSize > MAXIMUM_PAGEFILE_SIZE )
712
717
{
713
718
/* Trim it, this isn't allowed */
714
719
WasTooBig = TRUE;
715
- MinSize = 0xFFF00000 ;
720
+ MinSize = MAXIMUM_PAGEFILE_SIZE ;
716
721
}
717
722
718
723
/* Check if the maximum is more then 4095 MB */
719
- if (MaxSize > 0xFFF00000 )
724
+ if (MaxSize > MAXIMUM_PAGEFILE_SIZE )
720
725
{
721
726
/* Trim it, this isn't allowed */
722
727
WasTooBig = TRUE;
723
- MaxSize = 0xFFF00000 ;
728
+ MaxSize = MAXIMUM_PAGEFILE_SIZE ;
724
729
}
725
730
}
726
731
@@ -752,14 +757,14 @@ SmpCreateSystemManagedPagingFile(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor,
752
757
ASSERT (Descriptor -> Flags & SMP_PAGEFILE_SYSTEM_MANAGED ); // Descriptor->SystemManaged == 1 in ASSERT.
753
758
754
759
/* Keep decreasing the pagefile by this amount if we run out of space */
755
- FuzzFactor .QuadPart = 0x1000000 ;
760
+ FuzzFactor .QuadPart = FUZZ_FACTOR ;
756
761
757
762
/* Create the descriptor for it (mainly the right sizes) and validate */
758
763
SmpMakeSystemManagedPagingFileDescriptor (Descriptor );
759
764
SmpValidatePagingFileSizes (Descriptor );
760
765
761
766
/* Use either the minimum size in the descriptor, or 16MB in minimal mode */
762
- Size .QuadPart = DecreaseSize ? 0x1000000 : Descriptor -> MinSize .QuadPart ;
767
+ Size .QuadPart = DecreaseSize ? 16 * MEGABYTE : Descriptor -> MinSize .QuadPart ;
763
768
764
769
/* Check if this should be a fixed pagefile or an any pagefile*/
765
770
if (Descriptor -> Name .Buffer [STANDARD_DRIVE_LETTER_OFFSET ] == '?' )
@@ -777,7 +782,6 @@ NTAPI
777
782
SmpCreateEmergencyPagingFile (VOID )
778
783
{
779
784
PSMP_PAGEFILE_DESCRIPTOR Descriptor ;
780
- ULONG Length ;
781
785
WCHAR Buffer [32 ];
782
786
783
787
/* Allocate a descriptor */
@@ -787,18 +791,14 @@ SmpCreateEmergencyPagingFile(VOID)
787
791
if (!Descriptor ) return STATUS_NO_MEMORY ;
788
792
789
793
/* Initialize it */
790
- RtlInitUnicodeString (& Descriptor -> Name , NULL );
791
794
RtlInitUnicodeString (& Descriptor -> Token , NULL );
792
795
793
796
/* Copy the default pagefile name */
797
+ ASSERT (sizeof (Buffer ) >= sizeof (STANDARD_PAGING_FILE_NAME ));
794
798
wcscpy (Buffer , STANDARD_PAGING_FILE_NAME );
795
- Length = wcslen (Buffer ) * sizeof (WCHAR );
796
- ASSERT (sizeof (Buffer ) > Length );
797
799
798
800
/* Fill the rest of the descriptor out */
799
- Descriptor -> Name .Buffer = Buffer ;
800
- Descriptor -> Name .Length = Length ;
801
- Descriptor -> Name .MaximumLength = Length + sizeof (UNICODE_NULL );
801
+ RtlInitUnicodeString (& Descriptor -> Name , Buffer );
802
802
Descriptor -> Name .Buffer [STANDARD_DRIVE_LETTER_OFFSET ] = '?' ;
803
803
Descriptor -> Flags |= SMP_PAGEFILE_SYSTEM_MANAGED |
804
804
SMP_PAGEFILE_EMERGENCY |
@@ -818,7 +818,6 @@ SmpCreateVolumeDescriptors(VOID)
818
818
{
819
819
NTSTATUS Status ;
820
820
UNICODE_STRING VolumePath ;
821
- ULONG Length ;
822
821
BOOLEAN BootVolumeFound = FALSE;
823
822
WCHAR StartChar , Drive , DriveDiff ;
824
823
HANDLE VolumeHandle ;
@@ -849,14 +848,11 @@ SmpCreateVolumeDescriptors(VOID)
849
848
850
849
/* Build the volume string, starting with A: (we'll edit this in place) */
851
850
wcscpy (Buffer , L"\\??\\A:\\" );
852
- Length = wcslen (Buffer );
853
- VolumePath .Buffer = Buffer ;
854
- VolumePath .Length = Length * sizeof (WCHAR );
855
- VolumePath .MaximumLength = Length * sizeof (WCHAR ) + sizeof (UNICODE_NULL );
851
+ RtlInitUnicodeString (& VolumePath , Buffer );
856
852
857
853
/* Start with the C drive except on weird Japanese NECs... */
858
854
StartChar = SharedUserData -> AlternativeArchitecture ? L'A' : L'C' ;
859
- for (Drive = StartChar , DriveDiff = StartChar - 'A' ; Drive <= L'Z' ; Drive ++ , DriveDiff ++ )
855
+ for (Drive = StartChar , DriveDiff = StartChar - L 'A' ; Drive <= L'Z' ; Drive ++ , DriveDiff ++ )
860
856
{
861
857
/* Skip the disk if it's not in the drive map */
862
858
if (!((1 << DriveDiff ) & ProcessInformation .Query .DriveMap )) continue ;
@@ -967,18 +963,18 @@ SmpCreateVolumeDescriptors(VOID)
967
963
FreeSpace .QuadPart = SizeInfo .AvailableAllocationUnits .QuadPart *
968
964
SizeInfo .SectorsPerAllocationUnit ;
969
965
FinalFreeSpace .QuadPart = FreeSpace .QuadPart * SizeInfo .BytesPerSector ;
970
- Volume -> FreeSpace = FinalFreeSpace ;
971
966
972
967
/* Check if there's less than 32MB free so we don't starve the disk */
973
- if (FinalFreeSpace .QuadPart <= 0x2000000 )
968
+ if (FinalFreeSpace .QuadPart <= MINIMUM_TO_KEEP_FREE )
974
969
{
975
970
/* In this case, act as if there's no free space */
976
971
Volume -> FreeSpace .QuadPart = 0 ;
977
972
}
978
973
else
979
974
{
980
975
/* Trim off 32MB to give the disk a bit of breathing room */
981
- Volume -> FreeSpace .QuadPart = FinalFreeSpace .QuadPart - 0x2000000 ;
976
+ Volume -> FreeSpace .QuadPart = FinalFreeSpace .QuadPart -
977
+ MINIMUM_TO_KEEP_FREE ;
982
978
}
983
979
984
980
/* All done, add this volume to our descriptor list */
@@ -1026,7 +1022,7 @@ SmpCreatePagingFiles(VOID)
1026
1022
}
1027
1023
1028
1024
/* If we fail creating pagefiles, try to reduce by this much each time */
1029
- FuzzFactor .QuadPart = 0x1000000 ;
1025
+ FuzzFactor .QuadPart = FUZZ_FACTOR ;
1030
1026
1031
1027
/* Loop the descriptor list */
1032
1028
NextEntry = SmpPagingFileDescriptorList .Flink ;
@@ -1068,7 +1064,7 @@ SmpCreatePagingFiles(VOID)
1068
1064
/* We failed to create it. Try again with a smaller size */
1069
1065
DPRINT1 ("SMSS:PFILE: Trying lower sizes for (`%wZ') \n" ,
1070
1066
& Descriptor -> Name );
1071
- Size .QuadPart = 0x1000000 ;
1067
+ Size .QuadPart = 16 * MEGABYTE ;
1072
1068
Status = SmpCreatePagingFileOnAnyDrive (Descriptor ,
1073
1069
& FuzzFactor ,
1074
1070
& Size );
@@ -1077,7 +1073,7 @@ SmpCreatePagingFiles(VOID)
1077
1073
else
1078
1074
{
1079
1075
/* It's a fixed pagefile: override the minimum and use ours */
1080
- Size .QuadPart = 0x1000000 ;
1076
+ Size .QuadPart = 16 * MEGABYTE ;
1081
1077
Status = SmpCreatePagingFileOnFixedDrive (Descriptor ,
1082
1078
& FuzzFactor ,
1083
1079
& Size );
0 commit comments