2 * PROJECT: ReactOS Session Manager
3 * LICENSE: GPL v2 or later - See COPYING in the top level directory
4 * FILE: base/system/smss/initpage.c
5 * PURPOSE: Paging file support.
6 * PROGRAMMERS: ReactOS Development Team
9 /* INCLUDES ******************************************************************/
15 #define GIGABYTE (1024 * 1024 * 1024) /* One Gigabyte */
18 SmpPagingFilesQueryRoutine(PWSTR ValueName
,
25 UNICODE_STRING FileName
;
26 LARGE_INTEGER InitialSize
= {{0, 0}};
27 LARGE_INTEGER MaximumSize
= {{0, 0}};
28 NTSTATUS Status
= STATUS_SUCCESS
;
29 PWSTR p
, ValueString
= (PWSTR
)ValueData
;
30 WCHAR RootDriveLetter
[5] = {0};
32 if (ValueLength
> 3 * sizeof(WCHAR
) &&
33 (ValueLength
% sizeof(WCHAR
) != 0 ||
34 ValueString
[(ValueLength
/ sizeof(WCHAR
)) - 1] != L
'\0'))
36 return STATUS_INVALID_PARAMETER
;
39 if (ValueType
!= REG_SZ
)
41 return STATUS_INVALID_PARAMETER_2
;
45 * Format: "<path>[ <initial_size>[ <maximum_size>]]"
47 if ((p
= wcschr(ValueString
, L
' ')) != NULL
)
50 InitialSize
.QuadPart
= wcstoul(p
+ 1, &p
, 0) * 256 * 4096;
53 MaximumSize
.QuadPart
= wcstoul(p
+ 1, NULL
, 0) * 256 * 4096;
57 MaximumSize
= InitialSize
;
61 if (!RtlDosPathNameToNtPathName_U (ValueString
,
66 return STATUS_OBJECT_PATH_INVALID
;
69 /* If there is only a file name or if initial and max are both 0
70 * the system will pick the sizes. Then it makes intial the size of phyical memory
71 * and makes max the size of 1.5 * initial. If there isnt enough free space then it will
72 * fall back to intial 20% of free space and max 25%. There is a max of 1 gig before
73 * it doesnt make it bigger. */
74 if ((InitialSize
.QuadPart
== 0 && MaximumSize
.QuadPart
== 0) || p
== NULL
)
76 FILE_FS_SIZE_INFORMATION FileFsSize
;
77 IO_STATUS_BLOCK IoStatusBlock
;
79 SYSTEM_BASIC_INFORMATION SysBasicInfo
;
80 UNICODE_STRING NtPathU
;
81 LARGE_INTEGER FreeBytes
= {{0, 0}};
82 OBJECT_ATTRIBUTES ObjectAttributes
;
84 DPRINT("System managed pagefile...\n");
85 /* Make sure the path that is given for the file actually has the drive in it.
86 At this point if there is not file name, no sizes will be set therefore no page
87 file will be created */
88 if (wcslen(ValueString
) <= 3 ||
89 ValueString
[1] != L
':' ||
90 ValueString
[2] != L
'\\')
92 DPRINT1("Invalid path for pagefile.\n");
96 Status
= NtQuerySystemInformation(SystemBasicInformation
,
100 if (!NT_SUCCESS(Status
))
102 DPRINT1("Could not query for physical memory size.\n");
105 DPRINT("PageSize: %d, PhysicalPages: %d, TotalMem: %d\n", SysBasicInfo
.PageSize
, SysBasicInfo
.NumberOfPhysicalPages
, (SysBasicInfo
.NumberOfPhysicalPages
* SysBasicInfo
.PageSize
) / 1024);
107 InitialSize
.QuadPart
= SysBasicInfo
.NumberOfPhysicalPages
*
108 SysBasicInfo
.PageSize
;
109 MaximumSize
.QuadPart
= InitialSize
.QuadPart
* 2;
111 DPRINT("InitialSize: %I64d PhysicalPages: %lu PageSize: %lu\n",InitialSize
.QuadPart
,SysBasicInfo
.NumberOfPhysicalPages
,SysBasicInfo
.PageSize
);
113 /* copy the drive letter, the colon and the slash,
114 tack a null on the end */
115 RootDriveLetter
[0] = ValueString
[0];
116 RootDriveLetter
[1] = L
':';
117 RootDriveLetter
[2] = L
'\\';
118 RootDriveLetter
[3] = L
'\0';
119 DPRINT("Root drive X:\\...\"%S\"\n",RootDriveLetter
);
121 if (!RtlDosPathNameToNtPathName_U(RootDriveLetter
,
126 DPRINT1("Invalid path to root of drive\n");
127 Status
= STATUS_OBJECT_PATH_INVALID
;
131 InitializeObjectAttributes(&ObjectAttributes
,
133 OBJ_CASE_INSENSITIVE
,
137 /* Get a handle to the root to find the free space on the drive */
138 Status
= NtCreateFile(&hFile
,
144 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
150 RtlFreeHeap(RtlGetProcessHeap(),
154 if (!NT_SUCCESS(Status
))
156 DPRINT1("Could not open a handle to the volume.\n");
160 Status
= NtQueryVolumeInformationFile(hFile
,
163 sizeof(FILE_FS_SIZE_INFORMATION
),
164 FileFsSizeInformation
);
168 if (!NT_SUCCESS(Status
))
170 DPRINT1("Querying the volume free space failed!\n");
174 FreeBytes
.QuadPart
= FileFsSize
.BytesPerSector
*
175 FileFsSize
.SectorsPerAllocationUnit
*
176 FileFsSize
.AvailableAllocationUnits
.QuadPart
;
178 DPRINT("Free bytes: %I64d Inital Size based on memory: %I64d \n",FreeBytes
.QuadPart
,InitialSize
.QuadPart
);
181 if (InitialSize
.QuadPart
> (FreeBytes
.QuadPart
/ 4) || InitialSize
.QuadPart
== 0)
183 DPRINT("Inital Size took more then 25%% of free space\n");
184 /* Set by percentage of free space
185 * intial is 20%, and max is 25% */
186 InitialSize
.QuadPart
= FreeBytes
.QuadPart
/ 5;
187 MaximumSize
.QuadPart
= FreeBytes
.QuadPart
/ 4;
188 /* The page file is more then a gig, size it down */
189 if (InitialSize
.QuadPart
> GIGABYTE
)
191 InitialSize
.QuadPart
= GIGABYTE
;
192 MaximumSize
.QuadPart
= GIGABYTE
* 1.5;
199 /* Make sure that max is not smaller then initial */
200 if (InitialSize
.QuadPart
> MaximumSize
.QuadPart
)
202 DPRINT("Max page file size was bigger then inital.\n");
203 MaximumSize
.QuadPart
= InitialSize
.QuadPart
;
206 DPRINT("Creating paging file %wZ with size %I64d KB\n",
207 &FileName
, InitialSize
.QuadPart
/ 1024);
209 Status
= NtCreatePagingFile(&FileName
,
213 if (! NT_SUCCESS(Status
))
215 PrintString("Creation of paging file %wZ with size %I64d KB failed (status 0x%x)\n",
216 &FileName
, InitialSize
.QuadPart
/ 1024, Status
);
220 RtlFreeHeap(RtlGetProcessHeap(),
224 return STATUS_SUCCESS
;
229 SmCreatePagingFiles(VOID
)
231 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
234 DPRINT("creating system paging files\n");
236 * Disable paging file on MiniNT/Live CD.
238 if (RtlCheckRegistryKey(RTL_REGISTRY_CONTROL
, L
"MiniNT") == STATUS_SUCCESS
)
240 return STATUS_SUCCESS
;
243 RtlZeroMemory(&QueryTable
,
246 QueryTable
[0].Name
= L
"PagingFiles";
247 QueryTable
[0].QueryRoutine
= SmpPagingFilesQueryRoutine
;
249 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
250 L
"\\Session Manager\\Memory Management",