Files
zodiacon-WindowsInternals/MemLimit/MemLimit.cpp
T
2018-01-21 10:40:34 +02:00

193 lines
12 KiB
C++

#include "stdafx.h"
#pragma comment(lib, "ntdll")
extern "C" {
#include "ntndk.h"
}
typedef enum _MI_SYSTEM_VA_TYPE {
MiVaUnused = 0,
MiVaSessionSpace = 1,
MiVaProcessSpace = 2,
MiVaBootLoaded = 3,
MiVaPfnDatabase = 4,
MiVaNonPagedPool = 5,
MiVaPagedPool = 6,
MiVaSpecialPool = 7,
MiVaSystemCache = 8,
MiVaSystemPtes = 9,
MiVaHal = 10,
MiVaSessionGlobalSpace = 11,
MiVaDriverImageSpace = 12,
MiVaMaximumType = 13
} MI_SYSTEM_VA_TYPE;
typedef struct _MM_SYSTEM_VA_LIST_ENTRY {
ULONG Number;
ULONG Peak;
ULONG Limit;
ULONG Failures;
} MM_SYSTEM_VA_LIST_ENTRY, *PMM_SYSTEM_VA_LIST_ENTRY;
typedef struct _MM_SYSTEM_VA_LIST {
ULONG AvailableVa;
ULONG AvailableVaLow;
ULONG Reserved;
ULONG TotalFailures;
MM_SYSTEM_VA_LIST_ENTRY Entry[5];
} MM_SYSTEM_VA_LIST, *PMM_SYSTEM_VA_LIST;
int main(int argc, const char* argv[]) {
NTSTATUS ntStatus;
BOOLEAN old;
ULONG resultLength;
MM_SYSTEM_VA_LIST systemVaInfo = { 0 };
ULONG i;
ULONG SetNonPaged = 0, SetPaged = 0, SetSession = 0, SetSystem = 0, SetCache = 0, SetQuery = 0, SetRegistry = 0;
//
// Print header
//
printf("\nMemLimit v1.00 - Query and set hard limits on system VA space consumption\n");
printf("Copyright (C) 2008 Alex Ionescu\n");
printf("www.alex-ionescu.com\n\n");
//
// Check if no parameters given
//
if (argc == 1)
{
//
// Display usage
//
printf("usage: memlimit [-q|-r][-n size] [-p size] [-s size] [-c size] [-t size]\n");
printf("%6s Queries the current consumption, peak, and maximums on system VA for this system and does not set any limits\n", "-q");
printf("%6s Specifies that the limits being set should be written to the registry, making them persistent\n", "-r");
printf("%6s Specifies the maximum amount of system VA space that can be used by the nonpaged pool\n"
" Under certain conditions, this limit may be exceeded by a small amount\n", "-n");
printf("%6s Specifies the maximum amount of system VA space that can be used by the paged pool\n", "-p");
printf("%6s Specifies the maximum amount of system VA space that can be used by session space allocations\n", "-s");
printf("%6s Specifies the maximum amount of system VA space that can be used by the system cache\n"
" Under certain conditions, this limit may be exceeded by a small amount\n", "-c");
printf("%6s Specifies the maximum amount of system VA space that can be used by I/O mappings\n"
" and other resources that consume system page table entries (PTEs)\n", "-t");
printf("\nThe default is 0, which means no limit is enforced.\n"
"Sizes are in MB automatically rounded up to the next system VA allocation boundary,\n"
"which is 2 MB on 32-bit systems that have Physical Address Extension (PAE) enabled\n"
"and 4 MB on 32-bit systems that do not have PAE enabled.\n");
return -1;
}
//
// Get increase working set privilege
//
ntStatus = RtlAdjustPrivilege(SE_INCREASE_QUOTA_PRIVILEGE, TRUE, FALSE, &old);
if (!NT_SUCCESS(ntStatus))
{
//
// Display error
//
printf("Failed to get required privilege.\n");
printf("Make sure that you are running with administrative privileges\n"
"and that your account has the increase quota privilege\n");
return -1;
}
//
// Check what we should do
//
for (i = 0; i < (ULONG)argc; i++)
{
//
// Check what the user wants
//
if (strstr(argv[i], "-q")) SetQuery = i + 1;
if (strstr(argv[i], "-r")) SetRegistry = i + 1;
if (strstr(argv[i], "-n")) SetNonPaged = i + 1;
if (strstr(argv[i], "-p")) SetPaged = i + 1;
if (strstr(argv[i], "-s")) SetSession = i + 1;
if (strstr(argv[i], "-c")) SetCache = i + 1;
if (strstr(argv[i], "-t")) SetSystem = i + 1;
}
//
// Do a query to get current limits
//
ntStatus = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS) 106,
&systemVaInfo,
sizeof(systemVaInfo),
&resultLength);
if (!NT_SUCCESS(ntStatus))
{
//
// Shouldn't really happen
//
printf("Failed to query memory limits. This tool only supports Vista SP1/Server 08 and higher!\n");
return -1;
}
//
// Check if this is only a query
//
if (SetQuery)
{
doQuery:
//
// Tell the user
//
printf("System Va Consumption:\n\nType\t\t\tCurrent\t\t Peak\t\t Limit \n"
"Non Paged Pool\t\t%7d KB\t%7d KB\t%7d KB\n"
"Paged Pool\t\t%7d KB\t%7d KB\t%7d KB\n"
"System Cache\t\t%7d KB\t%7d KB\t%7d KB\n"
"System PTEs\t\t%7d KB\t%7d KB\t%7d KB\n"
"Session Space\t\t%7d KB\t%7d KB\t%7d KB\n",
systemVaInfo.Entry[0].Number / 1024,
systemVaInfo.Entry[0].Peak / 1024,
systemVaInfo.Entry[0].Limit / 1024,
systemVaInfo.Entry[1].Number / 1024,
systemVaInfo.Entry[1].Peak / 1024,
systemVaInfo.Entry[1].Limit / 1024,
systemVaInfo.Entry[2].Number / 1024,
systemVaInfo.Entry[2].Peak / 1024,
systemVaInfo.Entry[2].Limit / 1024,
systemVaInfo.Entry[3].Number / 1024,
systemVaInfo.Entry[3].Peak / 1024,
systemVaInfo.Entry[3].Limit / 1024,
systemVaInfo.Entry[4].Number / 1024,
systemVaInfo.Entry[4].Peak / 1024,
systemVaInfo.Entry[4].Limit / 1024);
return 0;
}
//
// Now get the limits
//
if (SetNonPaged) systemVaInfo.Entry[0].Limit = atol(argv[SetNonPaged]) * 1024 * 1024;
if (SetPaged) systemVaInfo.Entry[1].Limit = atol(argv[SetPaged]) * 1024 * 1024;
if (SetCache) systemVaInfo.Entry[2].Limit = atol(argv[SetCache]) * 1024 * 1024;
if (SetSystem) systemVaInfo.Entry[3].Limit = atol(argv[SetSystem]) * 1024 * 1024;
if (SetSession) systemVaInfo.Entry[4].Limit = atol(argv[SetSession]) * 1024 * 1024;
//
// And set them!
//
ntStatus = NtSetSystemInformation((SYSTEM_INFORMATION_CLASS) 106,
&systemVaInfo,
sizeof(systemVaInfo));
if (!NT_SUCCESS(ntStatus))
{
//
// Shouldn't really happen
//
printf("Failed to set memory limits. This tool only supports Vista SP1/Server 08 and higher!\n");
return -1;
}
//
// Print current state
//
printf("Limits set succesfully!\n\n");
goto doQuery;
}