4 * ReactOS Operating System
6 * --------------------------------------------------------------------
8 * This software is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
13 * This software is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this software; see the file COPYING.LIB. If not, write
20 * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
23 * --------------------------------------------------------------------
30 #define GIGABYTE (1024 * 1024 * 1024) /* One Gigabyte */
32 static NTSTATUS STDCALL
33 SmpPagingFilesQueryRoutine(PWSTR ValueName
,
40 UNICODE_STRING FileName
;
41 LARGE_INTEGER InitialSize
= {{0, 0}};
42 LARGE_INTEGER MaximumSize
= {{0, 0}};
43 NTSTATUS Status
= STATUS_SUCCESS
;
44 PWSTR p
, ValueString
= (PWSTR
)ValueData
;
45 WCHAR RootDriveLetter
[5] = {0};
47 if (ValueLength
> 3 * sizeof(WCHAR
) &&
48 (ValueLength
% sizeof(WCHAR
) != 0 ||
49 ValueString
[(ValueLength
/ sizeof(WCHAR
)) - 1] != L
'\0'))
51 return STATUS_INVALID_PARAMETER
;
54 if (ValueType
!= REG_SZ
)
56 return STATUS_INVALID_PARAMETER_2
;
60 * Format: "<path>[ <initial_size>[ <maximum_size>]]"
62 if ((p
= wcschr(ValueString
, L
' ')) != NULL
)
65 InitialSize
.QuadPart
= wcstoul(p
+ 1, &p
, 0) * 256 * 4096;
68 MaximumSize
.QuadPart
= wcstoul(p
+ 1, NULL
, 0) * 256 * 4096;
72 MaximumSize
= InitialSize
;
76 if (!RtlDosPathNameToNtPathName_U (ValueString
,
81 return STATUS_OBJECT_PATH_INVALID
;
84 /* If there is only a file name or if initial and max are both 0
85 * the system will pick the sizes. Then it makes intial the size of phyical memory
86 * and makes max the size of 1.5 * initial. If there isnt enough free space then it will
87 * fall back to intial 20% of free space and max 25%. There is a max of 1 gig before
88 * it doesnt make it bigger. */
89 if ((InitialSize
.QuadPart
== 0 && MaximumSize
.QuadPart
== 0) || p
== NULL
)
91 FILE_FS_SIZE_INFORMATION FileFsSize
;
92 IO_STATUS_BLOCK IoStatusBlock
;
94 SYSTEM_BASIC_INFORMATION SysBasicInfo
;
95 UNICODE_STRING NtPathU
;
96 LARGE_INTEGER FreeBytes
= {{0, 0}};
97 OBJECT_ATTRIBUTES ObjectAttributes
;
99 DPRINT("System managed pagefile...\n");
100 /* Make sure the path that is given for the file actually has the drive in it.
101 At this point if there is not file name, no sizes will be set therefore no page
102 file will be created */
103 if (wcslen(ValueString
) <= 3 ||
104 ValueString
[1] != L
':' ||
105 ValueString
[2] != L
'\\')
107 DPRINT1("Invalid path for pagefile.\n");
111 Status
= NtQuerySystemInformation(SystemBasicInformation
,
113 sizeof(SysBasicInfo
),
115 if (!NT_SUCCESS(Status
))
117 DPRINT1("Could not query for physical memory size.\n");
120 DPRINT("PageSize: %d, PhysicalPages: %d, TotalMem: %d\n", SysBasicInfo
.PageSize
, SysBasicInfo
.NumberOfPhysicalPages
, (SysBasicInfo
.NumberOfPhysicalPages
* SysBasicInfo
.PageSize
) / 1024);
122 InitialSize
.QuadPart
= SysBasicInfo
.NumberOfPhysicalPages
*
123 SysBasicInfo
.PageSize
;
124 MaximumSize
.QuadPart
= InitialSize
.QuadPart
* 2;
126 DPRINT("InitialSize: %I64d PhysicalPages: %lu PageSize: %lu\n",InitialSize
.QuadPart
,SysBasicInfo
.NumberOfPhysicalPages
,SysBasicInfo
.PageSize
);
128 /* copy the drive letter, the colon and the slash,
129 tack a null on the end */
130 RootDriveLetter
[0] = ValueString
[0];
131 RootDriveLetter
[1] = L
':';
132 RootDriveLetter
[2] = L
'\\';
133 RootDriveLetter
[3] = L
'\0';
134 DPRINT("Root drive X:\\...\"%S\"\n",RootDriveLetter
);
136 if (!RtlDosPathNameToNtPathName_U(RootDriveLetter
,
141 DPRINT1("Invalid path to root of drive\n");
142 Status
= STATUS_OBJECT_PATH_INVALID
;
146 InitializeObjectAttributes(&ObjectAttributes
,
148 OBJ_CASE_INSENSITIVE
,
152 /* Get a handle to the root to find the free space on the drive */
153 Status
= NtCreateFile(&hFile
,
159 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
165 RtlFreeUnicodeString(&NtPathU
);
167 if (!NT_SUCCESS(Status
))
169 DPRINT1("Could not open a handle to the volume.\n");
173 Status
= NtQueryVolumeInformationFile(hFile
,
176 sizeof(FILE_FS_SIZE_INFORMATION
),
177 FileFsSizeInformation
);
181 if (!NT_SUCCESS(Status
))
183 DPRINT1("Querying the volume free space failed!\n");
187 FreeBytes
.QuadPart
= FileFsSize
.BytesPerSector
*
188 FileFsSize
.SectorsPerAllocationUnit
*
189 FileFsSize
.AvailableAllocationUnits
.QuadPart
;
191 DPRINT("Free bytes: %I64d Inital Size based on memory: %I64d \n",FreeBytes
.QuadPart
,InitialSize
.QuadPart
);
194 if (InitialSize
.QuadPart
> (FreeBytes
.QuadPart
/ 4) || InitialSize
.QuadPart
== 0)
196 DPRINT("Inital Size took more then 25%% of free space\n");
197 /* Set by percentage of free space
198 * intial is 20%, and max is 25% */
199 InitialSize
.QuadPart
= FreeBytes
.QuadPart
/ 5;
200 MaximumSize
.QuadPart
= FreeBytes
.QuadPart
/ 4;
201 /* The page file is more then a gig, size it down */
202 if (InitialSize
.QuadPart
> GIGABYTE
)
204 InitialSize
.QuadPart
= GIGABYTE
;
205 MaximumSize
.QuadPart
= GIGABYTE
* 1.5;
212 /* Make sure that max is not smaller then initial */
213 if (InitialSize
.QuadPart
> MaximumSize
.QuadPart
)
215 DPRINT("Max page file size was bigger then inital.\n");
216 MaximumSize
.QuadPart
= InitialSize
.QuadPart
;
219 DPRINT("Creating paging file %wZ with size %I64d KB\n",
220 &FileName
, InitialSize
.QuadPart
/ 1024);
222 Status
= NtCreatePagingFile(&FileName
,
226 if (! NT_SUCCESS(Status
))
228 PrintString("Creation of paging file %wZ with size %I64d KB failed (status 0x%x)\n",
229 &FileName
, InitialSize
.QuadPart
/ 1024, Status
);
233 RtlFreeUnicodeString(&FileName
);
235 return STATUS_SUCCESS
;
240 SmCreatePagingFiles(VOID
)
242 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
245 DPRINT("creating system paging files\n");
247 * Disable paging file on MiniNT/Live CD.
249 if (RtlCheckRegistryKey(RTL_REGISTRY_CONTROL
, L
"MiniNT") == STATUS_SUCCESS
)
251 return STATUS_SUCCESS
;
254 RtlZeroMemory(&QueryTable
,
257 QueryTable
[0].Name
= L
"PagingFiles";
258 QueryTable
[0].QueryRoutine
= SmpPagingFilesQueryRoutine
;
260 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
261 L
"\\Session Manager\\Memory Management",