Index: initpage.c =================================================================== --- initpage.c (revision 20275) +++ initpage.c (working copy) @@ -28,66 +28,184 @@ #define NDEBUG #include +#define GIGABYTE (1024 * 1024 * 1024) /* One Gigabyte */ + static NTSTATUS STDCALL SmpPagingFilesQueryRoutine(PWSTR ValueName, - ULONG ValueType, - PVOID ValueData, - ULONG ValueLength, - PVOID Context, - PVOID EntryContext) + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) { - UNICODE_STRING FileName; - LARGE_INTEGER InitialSize; - LARGE_INTEGER MaximumSize; - NTSTATUS Status; - LPWSTR p; + UNICODE_STRING FileName; + LARGE_INTEGER InitialSize = {{0, 0}}; + LARGE_INTEGER MaximumSize = {{0, 0}}; + NTSTATUS Status = STATUS_SUCCESS; + PWSTR p, ValueString = (PWSTR)ValueData; + WCHAR RootDriveLetter[5] = {0}; - DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); - DPRINT("ValueData '%S'\n", (PWSTR)ValueData); - - if (ValueType != REG_SZ) - { - return(STATUS_SUCCESS); - } - - /* + if(ValueLength > 3 * sizeof(WCHAR) && + (ValueLength % sizeof(WCHAR) != 0 || + ValueString[(ValueLength / sizeof(WCHAR)) - 1] != L'\0')) + { + return STATUS_INVALID_PARAMETER; + } + + DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueString, ValueType, ValueLength); + DPRINT("ValueData '%S'\n", ValueString); + + if (ValueType != REG_SZ) + { + return STATUS_INVALID_PARAMETER_2; + } + + /* * Format: "[ [ ]]" */ - if ((p = wcschr(ValueData, ' ')) != NULL) - { + if ((p = wcschr(ValueString, L' ')) != NULL) + { *p = L'\0'; InitialSize.QuadPart = wcstoul(p + 1, &p, 0) * 256 * 4096; if (*p == ' ') - { - MaximumSize.QuadPart = wcstoul(p + 1, NULL, 0) * 256 * 4096; - } + { + MaximumSize.QuadPart = wcstoul(p + 1, NULL, 0) * 256 * 4096; + } else - MaximumSize = InitialSize; - } - else - { - InitialSize.QuadPart = 50 * 4096; - MaximumSize.QuadPart = 80 * 4096; - } - - if (!RtlDosPathNameToNtPathName_U ((LPWSTR)ValueData, - &FileName, - NULL, - NULL)) - { - return (STATUS_SUCCESS); - } - - DPRINT("SMSS: Created paging file %wZ with size %dKB\n", - &FileName, InitialSize.QuadPart / 1024); - Status = NtCreatePagingFile(&FileName, - &InitialSize, - &MaximumSize, - 0); - - RtlFreeUnicodeString(&FileName); - - return(STATUS_SUCCESS); + MaximumSize = InitialSize; + } + + if (!RtlDosPathNameToNtPathName_U (ValueString, + &FileName, + NULL, + NULL)) + { + return STATUS_OBJECT_PATH_INVALID; + } + + /* If there is only a file name or if initial and max are both 0 + the system will pick the sizes. 10% and 20% for initial and max + respectivly. There is a max of 1 gig before it doesnt make it + bigger. */ + if((InitialSize.QuadPart == 0 && MaximumSize.QuadPart == 0) || p == NULL) + { + FILE_FS_SIZE_INFORMATION FileFsSize; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE hFile; + UNICODE_STRING NtPathU; + LARGE_INTEGER FreeBytes; + OBJECT_ATTRIBUTES ObjectAttributes; + + DPRINT("System managed pagefile...\n"); + /* Make sure the path that is given for the file actually has the drive in it. + At this point if there is not file name, no sizes will be set therefore no page + file will be created */ + if (wcslen(ValueString) > 2 && + ValueString[1] == L':' && + ValueString[2] == L'\\') + { + /* copy the drive letter, the colon and the slash, + tack a null on the end */ + RootDriveLetter[0] = ValueString[0]; + RootDriveLetter[1] = L':'; + RootDriveLetter[2] = L'\\'; + RootDriveLetter[3] = L'\0'; + DPRINT("Root drive X:\\...\"%S\"\n",RootDriveLetter); + + if (!RtlDosPathNameToNtPathName_U(RootDriveLetter, + &NtPathU, + NULL, + NULL)) + { + DPRINT("Invalid path\n"); + Status = STATUS_OBJECT_PATH_INVALID; + goto Cleanup; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + FILE_READ_ATTRIBUTES, + NULL, + NULL); + + /* Get a handle to the root to find the free space on the drive */ + Status = NtCreateFile (&hFile, + 0, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + 0, + NULL, + 0); + + RtlFreeUnicodeString(&NtPathU); + + if (!NT_SUCCESS(Status)) + { + DPRINT ("Invalid handle\n"); + goto Cleanup; + } + + Status = NtQueryVolumeInformationFile(hFile, + &IoStatusBlock, + &FileFsSize, + sizeof(FILE_FS_SIZE_INFORMATION), + FileFsSizeInformation); + + NtClose(hFile); + + if (!NT_SUCCESS(Status)) + { + DPRINT ("Querying the file size failed!\n"); + goto Cleanup; + } + + FreeBytes.QuadPart = FileFsSize.BytesPerSector * + FileFsSize.SectorsPerAllocationUnit * + FileFsSize.AvailableAllocationUnits.QuadPart; + + DPRINT ("Free bytes:%I64\n",FreeBytes.QuadPart); + + /* Set by percentage */ + InitialSize.QuadPart = FreeBytes.QuadPart / 10; + MaximumSize.QuadPart = FreeBytes.QuadPart / 5; + + /* The page file is more then a gig, size it down */ + if (InitialSize.QuadPart > GIGABYTE) + { + InitialSize.QuadPart = GIGABYTE; + MaximumSize.QuadPart = GIGABYTE; + } + } + else + { + /* No page file will be created, + but we return succes because that + is what the setting wants */ + goto Cleanup; + } + } + + /* Make sure that max is not smaller then initial */ + if(InitialSize.QuadPart > MaximumSize.QuadPart) + { + MaximumSize.QuadPart = InitialSize.QuadPart; + } + DPRINT("SMSS: Created paging file %wZ with size %I64 KB\n", + &FileName, InitialSize.QuadPart / 1024); + + Status = NtCreatePagingFile(&FileName, + &InitialSize, + &MaximumSize, + 0); + +Cleanup: + RtlFreeUnicodeString(&FileName); + + return Status; }