/*++ Copyright (c) 1989-2001 Microsoft Corporation Module Name: lockmem.cpp Abstract: This utility locks the memory of all the modules currently mapped in the process address space. Author: Vijay Jayaseelan (vijayj@microsoft.com) 26'July'2001 Revision History: --*/ #include #include #include #include #include using namespace std; // // class abstracting the process with module // details // class Process { public: // // constructor // Process(ULONG Pid = 0) { // // enable the required privileges // if (!PrivilegeEnabled) { EnableRequiredPrivileges(); PrivilegeEnabled = TRUE; } if (Pid) { ProcessID = Pid; } else { ProcessID = GetCurrentProcessId(); } SelfProcess = (ProcessID == GetCurrentProcessId()); hProcess = 0; ::ZeroMemory(&hLoadedModules, sizeof(hLoadedModules)); // // Open the process // hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID); if (!hProcess) throw new InvalidProcessID(ProcessID, ::GetLastError()); DWORD cbNeeded = 0; // // Get the module details // if (!::EnumProcessModules(hProcess, hLoadedModules, sizeof(hLoadedModules), &cbNeeded)) { ::CloseHandle(hProcess); hProcess = 0; throw new EnumerationError(::GetLastError()); } } // // destructor // ~Process() { if (hProcess) { ::CloseHandle(hProcess); } } DWORD GetTotalWSSize(VOID) const { DWORD TotalSize = 0; for (int Index=0; ((Index < sizeof(hLoadedModules)/sizeof(HMODULE)) && hLoadedModules[Index]); Index++ ) { MODULEINFO ModuleInformation = {0}; if (GetModuleInformation(hProcess, hLoadedModules[Index], &ModuleInformation, sizeof(MODULEINFO))) { TotalSize += ModuleInformation.SizeOfImage; } } return TotalSize; } DWORD GetWSSizeLimits( SIZE_T &MinimumSize, SIZE_T &MaximumSize ) { GetProcessWorkingSetSize(hProcess, &MinimumSize, &MaximumSize); return ::GetLastError(); } DWORD LockMemory(DWORD &LockedMemorySize) { DWORD Result = ERROR_SUCCESS; DWORD TotalSize = GetTotalWSSize(); LockedMemorySize = 0; // // just make the WS limit twice the size of the // total module size // if (SetProcessWorkingSetSize(hProcess, TotalSize * 2, TotalSize * 2)) { if (SelfProcess) { for (int Index=0; ((Index < sizeof(hLoadedModules)/sizeof(HMODULE)) && hLoadedModules[Index]); Index++ ) { MODULEINFO ModuleInformation = {0}; if (GetModuleInformation(hProcess, hLoadedModules[Index], &ModuleInformation, sizeof(MODULEINFO))) { if (!IsBadCodePtr((FARPROC)ModuleInformation.lpBaseOfDll)) { if (!VirtualLock(ModuleInformation.lpBaseOfDll, ModuleInformation.SizeOfImage)) { Result = ::GetLastError(); } else { LockedMemorySize += ModuleInformation.SizeOfImage; } } else { Result = ERROR_ACCESS_DENIED; } } } } } else { Result = ::GetLastError(); } return Result; } // // dump utility // friend ostream& operator<<(ostream &os, const Process& rhs) { char ModuleName[MAX_PATH] = {0}; os << "Process ID: " << rhs.ProcessID << endl; os << "Loaded Modules: " << endl; for ( int Index=0; ((Index < sizeof(rhs.hLoadedModules)/sizeof(HMODULE)) && rhs.hLoadedModules[Index]); Index++ ) { if (::GetModuleFileNameExA(rhs.hProcess, rhs.hLoadedModules[Index], ModuleName, sizeof(ModuleName))) { MODULEINFO ModuleInformation = {0}; if (GetModuleInformation(rhs.hProcess, rhs.hLoadedModules[Index], &ModuleInformation, sizeof(MODULEINFO))) { os << ModuleName << " (" << ModuleInformation.lpBaseOfDll << "," << ModuleInformation.SizeOfImage << ")" << endl; } else { os << ModuleName << endl; } } } DWORD TotalSize = rhs.GetTotalWSSize(); os << "Total Size: " << dec << TotalSize << " Bytes = " << dec << TotalSize / 1024 << " KB = " << dec << TotalSize / (1024 * 1024) << " MB." << endl; return os; } protected: // // data members // HANDLE hProcess; HMODULE hLoadedModules[1024]; ULONG ProcessID; BOOLEAN SelfProcess; static BOOLEAN PrivilegeEnabled; public: // // exceptions // struct ProcessException{ ULONG ErrCode; virtual void dump(ostream &os) = 0; }; struct InvalidProcessID : public ProcessException { ULONG ProcessID; InvalidProcessID(ULONG Pid, ULONG Err) : ProcessID(Pid){ ErrCode = Err; } void dump(ostream &os) { os << *this; } friend ostream& operator<<(ostream& os, const InvalidProcessID& rhs) { os << "Invalid Process ID : " << rhs.ProcessID << " Error Code : " << rhs.ErrCode << endl; return os; } }; struct EnumerationError : public ProcessException { EnumerationError(ULONG Err) { ErrCode=Err; } void dump(ostream &os) { os << *this; } friend ostream& operator<<(ostream& os, const EnumerationError& rhs) { os << "Enumeration Error : " << rhs.ErrCode << endl; return os; } }; // // gives the process the required privileges // DWORD EnableRequiredPrivileges( VOID ) { HANDLE Token ; UCHAR Buf[ sizeof( TOKEN_PRIVILEGES ) + (sizeof( LUID_AND_ATTRIBUTES ) * 3) ] = {0}; PTOKEN_PRIVILEGES Privs; DWORD Result = ERROR_SUCCESS; if (::OpenProcessToken(hProcess, MAXIMUM_ALLOWED, &Token)) { Privs = (PTOKEN_PRIVILEGES) Buf ; Privs->PrivilegeCount = 3 ; LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &(Privs->Privileges[0].Luid)); Privs->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ; LookupPrivilegeValue(NULL, SE_INC_BASE_PRIORITY_NAME, &(Privs->Privileges[1].Luid)); Privs->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED ; LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(Privs->Privileges[2].Luid)); Privs->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED ; ::AdjustTokenPrivileges(Token, FALSE, Privs, NULL, NULL, NULL); Result = ::GetLastError(); ::CloseHandle(Token); } else { Result = ::GetLastError(); } return Result; } }; struct UsageException{}; // // static data member // BOOLEAN Process::PrivilegeEnabled = FALSE; DWORD LockModules( VOID ) { Process SelfProcess; DWORD LockedMemorySize = 0; return SelfProcess.LockMemory(LockedMemorySize); } #ifdef _CONOSOLE_VERSION // // global data // const string Usage = "Usage: lm.exe [process-to-execute]\n"; const int MinimumArgs = 2; const string ShowHelp1 = "/?"; const string ShowHelp2 = "-h"; const string SelfProcess = "-self"; /* /* main() entry point */ int __cdecl main( int Argc, char *Argv[] ) { int Result = 0; try { if (Argc == MinimumArgs) { char *EndPtr = 0; string Arg1(Argv[1]); // // verify arguments // if (Arg1 == ShowHelp1 || Arg1 == ShowHelp2) throw UsageException(); DWORD LastError = ERROR_SUCCESS; SIZE_T Min = 0, Max = 0; DWORD LockedMemorySize = 0; DWORD WSSize = 0; if (Arg1 != SelfProcess) { PROCESS_INFORMATION ProcessInfo = {0}; STARTUPINFOA StartupInfo = {0}; char ExecutableName[MAX_PATH]; strcpy(ExecutableName, Arg1.c_str()); BOOL CreateResult = CreateProcessA(NULL, ExecutableName, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo); if (CreateResult) { cout << "Waiting for : " << ExecutableName << "..." << endl; WaitForSingleObject(ProcessInfo.hProcess, 2000); Process ExecedProcess(ProcessInfo.dwProcessId); cout << ExecedProcess << endl; ExecedProcess.GetWSSizeLimits(Min, Max); cout << "Existing WS Limits : " << dec << Min << ", " << Max << endl; LastError = ExecedProcess.LockMemory(LockedMemorySize); ExecedProcess.GetWSSizeLimits(Min, Max); cout << "New WS Limits : " << dec << Min << ", " << Max << endl; cout << "Locked " << dec << LockedMemorySize << " / " << ExecedProcess.GetTotalWSSize() << " Bytes" << endl; } else { LastError = GetLastError(); } } else { Process SelfProcess; cout << SelfProcess << endl; SelfProcess.GetWSSizeLimits(Min, Max); cout << "Existing WS Limits : " << dec << Min << ", " << Max << endl; LastError = SelfProcess.LockMemory(LockedMemorySize); SelfProcess.GetWSSizeLimits(Min, Max); cout << "New WS Limits : " << dec << Min << ", " << Max << endl; cout << "Locked " << dec << LockedMemorySize << " / " << SelfProcess.GetTotalWSSize() << " Bytes" << endl; } if (ERROR_SUCCESS != LastError) { cout << "Error : " << dec << LastError << endl; } } else { cerr << Usage; Result = 1; } } catch(Process::ProcessException *pExp) { pExp->dump(cerr); delete pExp; } catch (...) { cerr << Usage; Result = 1; } return Result; } #endif // _CONSOLE_VERSION