Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602/* * COPYRIGHT: See COPYING in the top level directory * LICENSE: See LGPL.txt in the top level directory * PROJECT: ReactOS system libraries * FILE: reactos/lib/psapi/misc/win32.c * PURPOSE: Win32 interfaces for PSAPI * PROGRAMMER: KJK::Hyperion <noog@libero.it> * Thomas Weidenmueller <w3seek@reactos.com> * Pierre Schweitzer <pierre@reactos.org> * UPDATE HISTORY: * 10/06/2002: Created */
#include <stdarg.h>
#define WIN32_NO_STATUS#include <windef.h>#include <winbase.h>#include <winnls.h>#define NTOS_MODE_USER#include <ndk/exfuncs.h>#include <ndk/mmfuncs.h>#include <ndk/psfuncs.h>#include <ndk/rtlfuncs.h>
#include <psapi.h>
#include <pseh/pseh2.h>
#define NDEBUG#include <debug.h>
#define MAX_MODULES 0x2710 // Matches 10.000 modules#define INIT_MEMORY_SIZE 0x1000 // Matches 4kB
/* INTERNAL *******************************************************************/
/* * @implemented */static BOOL NTAPIFindDeviceDriver(IN PVOID ImageBase, OUT PRTL_PROCESS_MODULE_INFORMATION MatchingModule){ NTSTATUS Status; DWORD i, RequiredSize; PRTL_PROCESS_MODULES Information; RTL_PROCESS_MODULE_INFORMATION Module; /* By default, to prevent too many reallocations, we already make room for 4 modules */ DWORD Size = sizeof(RTL_PROCESS_MODULES) + 3 * sizeof(RTL_PROCESS_MODULE_INFORMATION);
while (TRUE) { /* Allocate a buffer to hold modules information */ Information = LocalAlloc(LMEM_FIXED, Size); if (!Information) { SetLastError(ERROR_NO_SYSTEM_RESOURCES); return FALSE; }
/* Query information */ Status = NtQuerySystemInformation(SystemModuleInformation, Information, Size, &RequiredSize); if (!NT_SUCCESS(Status)) { /* Free the current buffer */ LocalFree(Information);
/* If it was not a length mismatch (ie, buffer too small), just leave */ if (Status != STATUS_INFO_LENGTH_MISMATCH) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
/* Try again with the required size */ Size = RequiredSize; continue; }
/* No modules returned? Leave */ if (Information->NumberOfModules == 0) { break; }
/* Try to find which module matches the base address given */ for (i = 0; i < Information->NumberOfModules; ++i) { Module = Information->Modules[i]; if (Module.ImageBase == ImageBase) { /* Copy the matching module and leave */ memcpy(MatchingModule, &Module, sizeof(Module)); LocalFree(Information); return TRUE; } }
/* If we arrive here, it means we were not able to find matching base address */ break; }
/* Release and leave */ LocalFree(Information); SetLastError(ERROR_INVALID_HANDLE);
return FALSE;}
/* * @implemented */static BOOL NTAPIFindModule(IN HANDLE hProcess, IN HMODULE hModule OPTIONAL, OUT PLDR_DATA_TABLE_ENTRY Module){ DWORD Count; NTSTATUS Status; PPEB_LDR_DATA LoaderData; PLIST_ENTRY ListHead, ListEntry; PROCESS_BASIC_INFORMATION ProcInfo;
/* Query the process information to get its PEB address */ Status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &ProcInfo, sizeof(ProcInfo), NULL); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
/* If no module was provided, get base as module */ if (hModule == NULL) { if (!ReadProcessMemory(hProcess, &ProcInfo.PebBaseAddress->ImageBaseAddress, &hModule, sizeof(hModule), NULL)) { return FALSE; } }
/* Read loader data address from PEB */ if (!ReadProcessMemory(hProcess, &ProcInfo.PebBaseAddress->Ldr, &LoaderData, sizeof(LoaderData), NULL)) { return FALSE; }
if (LoaderData == NULL) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; }
/* Store list head address */ ListHead = &(LoaderData->InMemoryOrderModuleList);
/* Read first element in the modules list */ if (!ReadProcessMemory(hProcess, &(LoaderData->InMemoryOrderModuleList.Flink), &ListEntry, sizeof(ListEntry), NULL)) { return FALSE; }
Count = 0;
/* Loop on the modules */ while (ListEntry != ListHead) { /* Load module data */ if (!ReadProcessMemory(hProcess, CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks), Module, sizeof(*Module), NULL)) { return FALSE; }
/* Does that match the module we're looking for? */ if (Module->DllBase == hModule) { return TRUE; }
++Count; if (Count > MAX_MODULES) { break; }
/* Get to next listed module */ ListEntry = Module->InMemoryOrderLinks.Flink; }
SetLastError(ERROR_INVALID_HANDLE); return FALSE;}
typedef struct _INTERNAL_ENUM_PAGE_FILES_CONTEXT{ LPVOID lpContext; PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine; DWORD dwErrCode;} INTERNAL_ENUM_PAGE_FILES_CONTEXT, *PINTERNAL_ENUM_PAGE_FILES_CONTEXT;
/* * @implemented */static BOOL CALLBACKCallBackConvertToAscii(LPVOID pContext, PENUM_PAGE_FILE_INFORMATION pPageFileInfo, LPCWSTR lpFilename){ BOOL Ret; SIZE_T Len; LPSTR AnsiFileName; PINTERNAL_ENUM_PAGE_FILES_CONTEXT Context = (PINTERNAL_ENUM_PAGE_FILES_CONTEXT)pContext;
Len = wcslen(lpFilename);
/* Alloc space for the ANSI string */ AnsiFileName = LocalAlloc(LMEM_FIXED, (Len * sizeof(CHAR)) + sizeof(ANSI_NULL)); if (AnsiFileName == NULL) { Context->dwErrCode = RtlNtStatusToDosError(STATUS_INSUFFICIENT_RESOURCES); return FALSE; }
/* Convert string to ANSI */ if (WideCharToMultiByte(CP_ACP, 0, lpFilename, -1, AnsiFileName, (Len * sizeof(CHAR)) + sizeof(ANSI_NULL), NULL, NULL) == 0) { Context->dwErrCode = GetLastError(); LocalFree(AnsiFileName); return FALSE; }
/* And finally call "real" callback */ Ret = Context->pCallbackRoutine(Context->lpContext, pPageFileInfo, AnsiFileName); LocalFree(AnsiFileName);
return Ret;}
/* * @implemented */BOOLWINAPIEmptyWorkingSet(HANDLE hProcess){ SYSTEM_INFO SystemInfo; QUOTA_LIMITS QuotaLimits; NTSTATUS Status;
GetSystemInfo(&SystemInfo);
/* Query the working set */ Status = NtQueryInformationProcess(hProcess, ProcessQuotaLimits, &QuotaLimits, sizeof(QuotaLimits), NULL);
if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
/* Empty the working set */ QuotaLimits.MinimumWorkingSetSize = -1; QuotaLimits.MaximumWorkingSetSize = -1;
/* Set the working set */ Status = NtSetInformationProcess(hProcess, ProcessQuotaLimits, &QuotaLimits, sizeof(QuotaLimits)); if (!NT_SUCCESS(Status) && Status != STATUS_PRIVILEGE_NOT_HELD) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
return TRUE;}
/* * @implemented */BOOLWINAPIEnumDeviceDrivers(LPVOID *lpImageBase, DWORD cb, LPDWORD lpcbNeeded){ NTSTATUS Status; DWORD NewSize, Count; PRTL_PROCESS_MODULES Information; /* By default, to prevent too many reallocations, we already make room for 4 modules */ DWORD Size = sizeof(RTL_PROCESS_MODULES) + 3 * sizeof(RTL_PROCESS_MODULE_INFORMATION);
do { /* Allocate a buffer to hold modules information */ Information = LocalAlloc(LMEM_FIXED, Size); if (!Information) { SetLastError(ERROR_NO_SYSTEM_RESOURCES); return FALSE; }
/* Query information */ Status = NtQuerySystemInformation(SystemModuleInformation, Information, Size, &Count); /* In case of an error */ if (!NT_SUCCESS(Status)) { /* Save the amount of output modules */ NewSize = Information->NumberOfModules; /* And free buffer */ LocalFree(Information);
/* If it was not a length mismatch (ie, buffer too small), just leave */ if (Status != STATUS_INFO_LENGTH_MISMATCH) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
/* Compute new size length */ ASSERT(Size >= sizeof(RTL_PROCESS_MODULES)); NewSize *= sizeof(RTL_PROCESS_MODULE_INFORMATION); NewSize += sizeof(ULONG); ASSERT(NewSize >= sizeof(RTL_PROCESS_MODULES)); /* Check whether it is really bigger - otherwise, leave */ if (NewSize < Size) { ASSERT(NewSize > Size); SetLastError(RtlNtStatusToDosError(STATUS_INFO_LENGTH_MISMATCH)); return FALSE; }
/* Loop again with that new buffer */ Size = NewSize; continue; }
/* End of allocation loop */ break; } while (TRUE);
_SEH2_TRY { for (Count = 0; Count < Information->NumberOfModules && Count < cb / sizeof(LPVOID); ++Count) { lpImageBase[Count] = Information->Modules[Count].ImageBase; }
*lpcbNeeded = Information->NumberOfModules * sizeof(LPVOID); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); _SEH2_YIELD(return FALSE); } _SEH2_END;
return TRUE;}
/* * @implemented */BOOLWINAPIEnumProcesses(DWORD *lpidProcess, DWORD cb, LPDWORD lpcbNeeded){ NTSTATUS Status; DWORD Size = MAXSHORT, Count; PSYSTEM_PROCESS_INFORMATION ProcInfo; PSYSTEM_PROCESS_INFORMATION ProcInfoArray;
/* First of all, query all the processes */ do { ProcInfoArray = LocalAlloc(LMEM_FIXED, Size); if (ProcInfoArray == NULL) { return FALSE; }
Status = NtQuerySystemInformation(SystemProcessInformation, ProcInfoArray, Size, NULL); if (Status == STATUS_INFO_LENGTH_MISMATCH) { LocalFree(ProcInfoArray); Size += MAXSHORT; continue; }
break; } while (TRUE);
if (!NT_SUCCESS(Status)) { LocalFree(ProcInfoArray); SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
/* Then, loop to output data */ Count = 0; ProcInfo = ProcInfoArray;
_SEH2_TRY { do { /* It may sound weird, but actually MS only updated Count on * successful write. So, it cannot measure the amount of space needed! * This is really tricky. */ if (Count < cb / sizeof(DWORD)) { lpidProcess[Count] = HandleToUlong(ProcInfo->UniqueProcessId); Count++; }
if (ProcInfo->NextEntryOffset == 0) { break; }
ProcInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcInfo + ProcInfo->NextEntryOffset); } while (TRUE);
*lpcbNeeded = Count * sizeof(DWORD); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); LocalFree(ProcInfoArray); _SEH2_YIELD(return FALSE); } _SEH2_END;
LocalFree(ProcInfoArray); return TRUE;}
/* * @implemented */BOOLWINAPIEnumProcessModules(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded){ NTSTATUS Status; DWORD NbOfModules, Count; PPEB_LDR_DATA LoaderData; PLIST_ENTRY ListHead, ListEntry; PROCESS_BASIC_INFORMATION ProcInfo; LDR_DATA_TABLE_ENTRY CurrentModule;
/* Query the process information to get its PEB address */ Status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &ProcInfo, sizeof(ProcInfo), NULL); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
if (ProcInfo.PebBaseAddress == NULL) { SetLastError(RtlNtStatusToDosError(STATUS_PARTIAL_COPY)); return FALSE; }
/* Read loader data address from PEB */ if (!ReadProcessMemory(hProcess, &ProcInfo.PebBaseAddress->Ldr, &LoaderData, sizeof(LoaderData), NULL)) { return FALSE; }
/* Store list head address */ ListHead = &LoaderData->InLoadOrderModuleList;
/* Read first element in the modules list */ if (!ReadProcessMemory(hProcess, &LoaderData->InLoadOrderModuleList.Flink, &ListEntry, sizeof(ListEntry), NULL)) { return FALSE; }
NbOfModules = cb / sizeof(HMODULE); Count = 0;
/* Loop on the modules */ while (ListEntry != ListHead) { /* Load module data */ if (!ReadProcessMemory(hProcess, CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks), &CurrentModule, sizeof(CurrentModule), NULL)) { return FALSE; }
/* Check if we can output module, do it if so */ if (Count < NbOfModules) { _SEH2_TRY { lphModule[Count] = CurrentModule.DllBase; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); _SEH2_YIELD(return FALSE); } _SEH2_END; }
++Count; if (Count > MAX_MODULES) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; }
/* Get to next listed module */ ListEntry = CurrentModule.InLoadOrderLinks.Flink; }
_SEH2_TRY { *lpcbNeeded = Count * sizeof(HMODULE); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); _SEH2_YIELD(return FALSE); } _SEH2_END;
return TRUE;}
/* * @implemented */DWORDWINAPIGetDeviceDriverBaseNameA(LPVOID ImageBase, LPSTR lpBaseName, DWORD nSize){ SIZE_T Len, LenWithNull; RTL_PROCESS_MODULE_INFORMATION Module;
/* Get the associated device driver to the base address */ if (!FindDeviceDriver(ImageBase, &Module)) { return 0; }
/* And copy as much as possible to output buffer. * Try to add 1 to the len, to copy the null char as well. */ Len = LenWithNull = strlen(&Module.FullPathName[Module.OffsetToFileName]) + 1; if (Len > nSize) { Len = nSize; }
memcpy(lpBaseName, &Module.FullPathName[Module.OffsetToFileName], Len); /* In case we copied null char, remove it from final len */ if (Len == LenWithNull) { --Len; }
return Len;}
/* * @implemented */DWORDWINAPIGetDeviceDriverFileNameA(LPVOID ImageBase, LPSTR lpFilename, DWORD nSize){ SIZE_T Len, LenWithNull; RTL_PROCESS_MODULE_INFORMATION Module;
/* Get the associated device driver to the base address */ if (!FindDeviceDriver(ImageBase, &Module)) { return 0; }
/* And copy as much as possible to output buffer. * Try to add 1 to the len, to copy the null char as well. */ Len = LenWithNull = strlen(Module.FullPathName) + 1; if (Len > nSize) { Len = nSize; }
memcpy(lpFilename, Module.FullPathName, Len); /* In case we copied null char, remove it from final len */ if (Len == LenWithNull) { --Len; }
return Len;}
/* * @implemented */DWORDWINAPIGetDeviceDriverBaseNameW(LPVOID ImageBase, LPWSTR lpBaseName, DWORD nSize){ DWORD Len; LPSTR BaseName;
/* Allocate internal buffer for conversion */ BaseName = LocalAlloc(LMEM_FIXED, nSize); if (BaseName == 0) { return 0; }
/* Call A API */ Len = GetDeviceDriverBaseNameA(ImageBase, BaseName, nSize); if (Len == 0) { LocalFree(BaseName); return 0; }
/* And convert output */ if (MultiByteToWideChar(CP_ACP, 0, BaseName, (Len < nSize) ? Len + 1 : Len, lpBaseName, nSize) == 0) { LocalFree(BaseName); return 0; }
LocalFree(BaseName); return Len;}
/* * @implemented */DWORDWINAPIGetDeviceDriverFileNameW(LPVOID ImageBase, LPWSTR lpFilename, DWORD nSize){ DWORD Len; LPSTR FileName;
/* Allocate internal buffer for conversion */ FileName = LocalAlloc(LMEM_FIXED, nSize); if (FileName == 0) { return 0; }
/* Call A API */ Len = GetDeviceDriverFileNameA(ImageBase, FileName, nSize); if (Len == 0) { LocalFree(FileName); return 0; }
/* And convert output */ if (MultiByteToWideChar(CP_ACP, 0, FileName, (Len < nSize) ? Len + 1 : Len, lpFilename, nSize) == 0) { LocalFree(FileName); return 0; }
LocalFree(FileName); return Len;}
/* * @implemented */DWORDWINAPIGetMappedFileNameA(HANDLE hProcess, LPVOID lpv, LPSTR lpFilename, DWORD nSize){ DWORD Len; LPWSTR FileName;
DPRINT("GetMappedFileNameA(%p, %p, %p, %lu)\n", hProcess, lpv, lpFilename, nSize);
/* Allocate internal buffer for conversion */ FileName = LocalAlloc(LMEM_FIXED, nSize * sizeof(WCHAR)); if (FileName == NULL) { return 0; }
/* Call W API */ Len = GetMappedFileNameW(hProcess, lpv, FileName, nSize);
/* And convert output */ if (WideCharToMultiByte(CP_ACP, 0, FileName, (Len < nSize) ? Len + 1 : Len, lpFilename, nSize, NULL, NULL) == 0) { Len = 0; }
LocalFree(FileName); return Len;}
/* * @implemented */DWORDWINAPIGetMappedFileNameW(HANDLE hProcess, LPVOID lpv, LPWSTR lpFilename, DWORD nSize){ DWORD Len; SIZE_T OutSize; NTSTATUS Status; struct { MEMORY_SECTION_NAME; WCHAR CharBuffer[MAX_PATH]; } SectionName;
DPRINT("GetMappedFileNameW(%p, %p, %p, %lu)\n", hProcess, lpv, lpFilename, nSize);
/* If no buffer, no need to keep going on */ if (nSize == 0) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return 0; }
/* Query section name */ Status = NtQueryVirtualMemory(hProcess, lpv, MemorySectionName, &SectionName, sizeof(SectionName), &OutSize); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return 0; }
/* Prepare to copy file name */ Len = OutSize = SectionName.SectionFileName.Length / sizeof(WCHAR); if (OutSize + 1 > nSize) { Len = nSize - 1; OutSize = nSize; SetLastError(ERROR_INSUFFICIENT_BUFFER); } else { SetLastError(ERROR_SUCCESS); }
/* Copy, zero and return */ memcpy(lpFilename, SectionName.SectionFileName.Buffer, Len * sizeof(WCHAR)); lpFilename[Len] = 0;
return OutSize;}
/* * @implemented */DWORDWINAPIGetModuleBaseNameA(HANDLE hProcess, HMODULE hModule, LPSTR lpBaseName, DWORD nSize){ DWORD Len; PWSTR BaseName;
/* Allocate internal buffer for conversion */ BaseName = LocalAlloc(LMEM_FIXED, nSize * sizeof(WCHAR)); if (BaseName == NULL) { return 0; }
/* Call W API */ Len = GetModuleBaseNameW(hProcess, hModule, BaseName, nSize); /* And convert output */ if (WideCharToMultiByte(CP_ACP, 0, BaseName, (Len < nSize) ? Len + 1 : Len, lpBaseName, nSize, NULL, NULL) == 0) { Len = 0; }
LocalFree(BaseName);
return Len;}
/* * @implemented */DWORDWINAPIGetModuleBaseNameW(HANDLE hProcess, HMODULE hModule, LPWSTR lpBaseName, DWORD nSize){ DWORD Len; LDR_DATA_TABLE_ENTRY Module;
/* Get the matching module */ if (!FindModule(hProcess, hModule, &Module)) { return 0; }
/* Get the maximum len we have/can write in given size */ Len = Module.BaseDllName.Length + sizeof(UNICODE_NULL); if (nSize * sizeof(WCHAR) < Len) { Len = nSize * sizeof(WCHAR); }
/* Read string */ if (!ReadProcessMemory(hProcess, (&Module.BaseDllName)->Buffer, lpBaseName, Len, NULL)) { return 0; }
/* If we are at the end of the string, prepare to override to nullify string */ if (Len == Module.BaseDllName.Length + sizeof(UNICODE_NULL)) { Len -= sizeof(UNICODE_NULL); }
/* Nullify at the end if needed */ if (Len >= nSize * sizeof(WCHAR)) { if (nSize) { ASSERT(nSize >= sizeof(UNICODE_NULL)); lpBaseName[nSize - 1] = UNICODE_NULL; } } /* Otherwise, nullify at last written char */ else { ASSERT(Len + sizeof(UNICODE_NULL) <= nSize * sizeof(WCHAR)); lpBaseName[Len / sizeof(WCHAR)] = UNICODE_NULL; }
return Len / sizeof(WCHAR);}
/* * @implemented */DWORDWINAPIGetModuleFileNameExA(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize){ DWORD Len; PWSTR Filename;
/* Allocate internal buffer for conversion */ Filename = LocalAlloc(LMEM_FIXED, nSize * sizeof(WCHAR)); if (Filename == NULL) { return 0; }
/* Call W API */ Len = GetModuleFileNameExW(hProcess, hModule, Filename, nSize); /* And convert output */ if (WideCharToMultiByte(CP_ACP, 0, Filename, (Len < nSize) ? Len + 1 : Len, lpFilename, nSize, NULL, NULL) == 0) { Len = 0; }
LocalFree(Filename);
return Len;}
/* * @implemented */DWORDWINAPIGetModuleFileNameExW(HANDLE hProcess, HMODULE hModule, LPWSTR lpFilename, DWORD nSize){ DWORD Len; LDR_DATA_TABLE_ENTRY Module;
/* Get the matching module */ if (!FindModule(hProcess, hModule, &Module)) { return 0; }
/* Get the maximum len we have/can write in given size */ Len = Module.FullDllName.Length + sizeof(UNICODE_NULL); if (nSize * sizeof(WCHAR) < Len) { Len = nSize * sizeof(WCHAR); }
/* Read string */ if (!ReadProcessMemory(hProcess, (&Module.FullDllName)->Buffer, lpFilename, Len, NULL)) { return 0; }
/* If we are at the end of the string, prepare to override to nullify string */ if (Len == Module.FullDllName.Length + sizeof(UNICODE_NULL)) { Len -= sizeof(UNICODE_NULL); }
/* Nullify at the end if needed */ if (Len >= nSize * sizeof(WCHAR)) { if (nSize) { ASSERT(nSize >= sizeof(UNICODE_NULL)); lpFilename[nSize - 1] = UNICODE_NULL; } } /* Otherwise, nullify at last written char */ else { ASSERT(Len + sizeof(UNICODE_NULL) <= nSize * sizeof(WCHAR)); lpFilename[Len / sizeof(WCHAR)] = UNICODE_NULL; }
return Len / sizeof(WCHAR);}
/* * @implemented */BOOLWINAPIGetModuleInformation(HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, DWORD cb){ MODULEINFO LocalInfo; LDR_DATA_TABLE_ENTRY Module;
/* Check output size */ if (cb < sizeof(MODULEINFO)) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; }
/* Get the matching module */ if (!FindModule(hProcess, hModule, &Module)) { return FALSE; }
/* Get a local copy first, to check for valid pointer once */ LocalInfo.lpBaseOfDll = hModule; LocalInfo.SizeOfImage = Module.SizeOfImage; LocalInfo.EntryPoint = Module.EntryPoint;
/* Attempt to copy to output */ _SEH2_TRY { memcpy(lpmodinfo, &LocalInfo, sizeof(LocalInfo)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); _SEH2_YIELD(return FALSE); } _SEH2_END;
return TRUE;}
/* * @implemented */BOOLWINAPIInitializeProcessForWsWatch(HANDLE hProcess){ NTSTATUS Status;
/* Simply forward the call */ Status = NtSetInformationProcess(hProcess, ProcessWorkingSetWatch, NULL, 0); /* In case the function returns this, MS considers the call as a success */ if (NT_SUCCESS(Status) || Status == STATUS_PORT_ALREADY_SET || Status == STATUS_ACCESS_DENIED) { return TRUE; }
SetLastError(RtlNtStatusToDosError(Status)); return FALSE;}
/* * @implemented */BOOLWINAPIGetWsChanges(HANDLE hProcess, PPSAPI_WS_WATCH_INFORMATION lpWatchInfo, DWORD cb){ NTSTATUS Status;
/* Simply forward the call */ Status = NtQueryInformationProcess(hProcess, ProcessWorkingSetWatch, lpWatchInfo, cb, NULL); if(!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
return TRUE;}
/* * @implemented */DWORDWINAPIGetProcessImageFileNameW(HANDLE hProcess, LPWSTR lpImageFileName, DWORD nSize){ PUNICODE_STRING ImageFileName; SIZE_T BufferSize; NTSTATUS Status; DWORD Len;
/* Allocate string big enough to hold name */ BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR)); ImageFileName = LocalAlloc(LMEM_FIXED, BufferSize); if (ImageFileName == NULL) { return 0; }
/* Query name */ Status = NtQueryInformationProcess(hProcess, ProcessImageFileName, ImageFileName, BufferSize, NULL); /* Len mismatch => buffer too small */ if (Status == STATUS_INFO_LENGTH_MISMATCH) { Status = STATUS_BUFFER_TOO_SMALL; } if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); LocalFree(ImageFileName); return 0; }
/* Copy name and null-terminate if possible */ memcpy(lpImageFileName, ImageFileName->Buffer, ImageFileName->Length); Len = ImageFileName->Length / sizeof(WCHAR); if (Len < nSize) { lpImageFileName[Len] = UNICODE_NULL; }
LocalFree(ImageFileName); return Len;}
/* * @implemented */DWORDWINAPIGetProcessImageFileNameA(HANDLE hProcess, LPSTR lpImageFileName, DWORD nSize){ PUNICODE_STRING ImageFileName; SIZE_T BufferSize; NTSTATUS Status; DWORD Len;
/* Allocate string big enough to hold name */ BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR)); ImageFileName = LocalAlloc(LMEM_FIXED, BufferSize); if (ImageFileName == NULL) { return 0; }
/* Query name */ Status = NtQueryInformationProcess(hProcess, ProcessImageFileName, ImageFileName, BufferSize, NULL); /* Len mismatch => buffer too small */ if (Status == STATUS_INFO_LENGTH_MISMATCH) { Status = STATUS_BUFFER_TOO_SMALL; } if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); LocalFree(ImageFileName); return 0; }
/* Copy name */ Len = WideCharToMultiByte(CP_ACP, 0, ImageFileName->Buffer, ImageFileName->Length, lpImageFileName, nSize, NULL, NULL); /* If conversion was successful, don't return len with added \0 */ if (Len != 0) { Len -= sizeof(ANSI_NULL); }
LocalFree(ImageFileName); return Len;}
/* * @implemented */BOOLWINAPIEnumPageFilesA(PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine, LPVOID lpContext){ BOOL Ret; INTERNAL_ENUM_PAGE_FILES_CONTEXT Context;
Context.dwErrCode = ERROR_SUCCESS; Context.lpContext = lpContext; Context.pCallbackRoutine = pCallbackRoutine;
/* Call W with our own callback for W -> A conversions */ Ret = EnumPageFilesW(CallBackConvertToAscii, &Context); /* If we succeed but we have error code, fail and set error */ if (Ret && Context.dwErrCode != ERROR_SUCCESS) { Ret = FALSE; SetLastError(Context.dwErrCode); }
return Ret;}
/* * @implemented */BOOLWINAPIEnumPageFilesW(PENUM_PAGE_FILE_CALLBACKW pCallbackRoutine, LPVOID lpContext){ PWSTR Colon; NTSTATUS Status; DWORD Size = INIT_MEMORY_SIZE, Needed; ENUM_PAGE_FILE_INFORMATION Information; PSYSTEM_PAGEFILE_INFORMATION PageFileInfoArray, PageFileInfo;
/* First loop till we have all the information about page files */ do { PageFileInfoArray = LocalAlloc(LMEM_FIXED, Size); if (PageFileInfoArray == NULL) { SetLastError(RtlNtStatusToDosError(STATUS_INSUFFICIENT_RESOURCES)); return FALSE; }
Status = NtQuerySystemInformation(SystemPageFileInformation, PageFileInfoArray, Size, &Needed); if (NT_SUCCESS(Status)) { break; }
LocalFree(PageFileInfoArray);
/* In case we have unexpected status, quit */ if (Status != STATUS_INFO_LENGTH_MISMATCH) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
/* If needed size is smaller than actual size, guess it's something to add to our current size */ if (Needed <= Size) { Size += Needed; } /* Otherwise, take it as size to allocate */ else { Size = Needed; } } while (TRUE);
/* Start browsing all our entries */ PageFileInfo = PageFileInfoArray; do { /* Ensure we really have an entry */ if (Needed < sizeof(SYSTEM_PAGEFILE_INFORMATION)) { break; }
/* Prepare structure to hand to the user */ Information.Reserved = 0; Information.cb = sizeof(Information); Information.TotalSize = PageFileInfo->TotalSize; Information.TotalInUse = PageFileInfo->TotalInUse; Information.PeakUsage = PageFileInfo->PeakUsage;
/* Search for colon */ Colon = wcschr(PageFileInfo->PageFileName.Buffer, L':'); /* If it's found and not at the begin of the string */ if (Colon != 0 && Colon != PageFileInfo->PageFileName.Buffer) { /* We can call the user callback routine with the colon */ --Colon; pCallbackRoutine(lpContext, &Information, Colon); }
/* If no next entry, then, it's over */ if (PageFileInfo->NextEntryOffset == 0 || PageFileInfo->NextEntryOffset > Needed) { break; }
/* Jump to next entry while keeping accurate bytes left count */ Needed -= PageFileInfo->NextEntryOffset; PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)((ULONG_PTR)PageFileInfo + PageFileInfo->NextEntryOffset); } while (TRUE);
LocalFree(PageFileInfoArray); return TRUE;}
/* * @implemented */BOOLWINAPIGetPerformanceInfo(PPERFORMANCE_INFORMATION pPerformanceInformation, DWORD cb){ NTSTATUS Status; SYSTEM_BASIC_INFORMATION SystemBasicInfo; SYSTEM_PERFORMANCE_INFORMATION SystemPerfInfo; SYSTEM_FILECACHE_INFORMATION SystemFileCacheInfo; PSYSTEM_PROCESS_INFORMATION ProcInfoArray, SystemProcInfo; DWORD Size = INIT_MEMORY_SIZE, Needed, ProcCount, ThreadsCount, HandleCount;
/* Validate output buffer */ if (cb < sizeof(PERFORMANCE_INFORMATION)) { SetLastError(RtlNtStatusToDosError(STATUS_INFO_LENGTH_MISMATCH)); return FALSE; }
/* First, gather as many information about the system as possible */ Status = NtQuerySystemInformation(SystemBasicInformation, &SystemBasicInfo, sizeof(SystemBasicInfo), NULL); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
Status = NtQuerySystemInformation(SystemPerformanceInformation, &SystemPerfInfo, sizeof(SystemPerfInfo), NULL); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
Status = NtQuerySystemInformation(SystemFileCacheInformation, &SystemFileCacheInfo, sizeof(SystemFileCacheInfo), NULL); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
/* Then loop till we have all the information about processes */ do { ProcInfoArray = LocalAlloc(LMEM_FIXED, Size); if (ProcInfoArray == NULL) { SetLastError(RtlNtStatusToDosError(STATUS_INSUFFICIENT_RESOURCES)); return FALSE; }
Status = NtQuerySystemInformation(SystemProcessInformation, ProcInfoArray, Size, &Needed); if (NT_SUCCESS(Status)) { break; }
LocalFree(ProcInfoArray);
/* In case we have unexpected status, quit */ if (Status != STATUS_INFO_LENGTH_MISMATCH) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
/* If needed size is smaller than actual size, guess it's something to add to our current size */ if (Needed <= Size) { Size += Needed; } /* Otherwise, take it as size to allocate */ else { Size = Needed; } } while (TRUE);
/* Start browsing all our entries */ ProcCount = 0; HandleCount = 0; ThreadsCount = 0; SystemProcInfo = ProcInfoArray; do { /* Ensure we really have an entry */ if (Needed < sizeof(SYSTEM_PROCESS_INFORMATION)) { break; }
/* Sum procs, threads and handles */ ++ProcCount; ThreadsCount += SystemProcInfo->NumberOfThreads; HandleCount += SystemProcInfo->HandleCount;
/* If no next entry, then, it's over */ if (SystemProcInfo->NextEntryOffset == 0 || SystemProcInfo->NextEntryOffset > Needed) { break; }
/* Jump to next entry while keeping accurate bytes left count */ Needed -= SystemProcInfo->NextEntryOffset; SystemProcInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)SystemProcInfo + SystemProcInfo->NextEntryOffset); } while (TRUE);
LocalFree(ProcInfoArray);
/* Output data */ pPerformanceInformation->CommitTotal = SystemPerfInfo.CommittedPages; pPerformanceInformation->CommitLimit = SystemPerfInfo.CommitLimit; pPerformanceInformation->CommitPeak = SystemPerfInfo.PeakCommitment; pPerformanceInformation->PhysicalTotal = SystemBasicInfo.NumberOfPhysicalPages; pPerformanceInformation->PhysicalAvailable = SystemPerfInfo.AvailablePages; pPerformanceInformation->SystemCache = SystemFileCacheInfo.CurrentSizeIncludingTransitionInPages; pPerformanceInformation->KernelNonpaged = SystemPerfInfo.NonPagedPoolPages; pPerformanceInformation->PageSize = SystemBasicInfo.PageSize; pPerformanceInformation->cb = sizeof(PERFORMANCE_INFORMATION); pPerformanceInformation->KernelTotal = SystemPerfInfo.PagedPoolPages + SystemPerfInfo.NonPagedPoolPages; pPerformanceInformation->KernelPaged = SystemPerfInfo.PagedPoolPages; pPerformanceInformation->HandleCount = HandleCount; pPerformanceInformation->ProcessCount = ProcCount; pPerformanceInformation->ThreadCount = ThreadsCount;
return TRUE;}
/* * @implemented */BOOLWINAPIGetProcessMemoryInfo(HANDLE Process, PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb){ NTSTATUS Status; VM_COUNTERS_EX Counters;
/* Validate output size * It can be either PROCESS_MEMORY_COUNTERS or PROCESS_MEMORY_COUNTERS_EX */ if (cb < sizeof(PROCESS_MEMORY_COUNTERS)) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; }
_SEH2_TRY { ppsmemCounters->PeakPagefileUsage = 0;
/* Query counters */ Status = NtQueryInformationProcess(Process, ProcessVmCounters, &Counters, sizeof(Counters), NULL); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); _SEH2_YIELD(return FALSE); }
/* Properly set cb, according to what we received */ if (cb >= sizeof(PROCESS_MEMORY_COUNTERS_EX)) { ppsmemCounters->cb = sizeof(PROCESS_MEMORY_COUNTERS_EX); } else { ppsmemCounters->cb = sizeof(PROCESS_MEMORY_COUNTERS); }
/* Output data */ ppsmemCounters->PageFaultCount = Counters.PageFaultCount; ppsmemCounters->PeakWorkingSetSize = Counters.PeakWorkingSetSize; ppsmemCounters->WorkingSetSize = Counters.WorkingSetSize; ppsmemCounters->QuotaPeakPagedPoolUsage = Counters.QuotaPeakPagedPoolUsage; ppsmemCounters->QuotaPagedPoolUsage = Counters.QuotaPagedPoolUsage; ppsmemCounters->QuotaPeakNonPagedPoolUsage = Counters.QuotaPeakNonPagedPoolUsage; ppsmemCounters->QuotaNonPagedPoolUsage = Counters.QuotaNonPagedPoolUsage; ppsmemCounters->PagefileUsage = Counters.PagefileUsage; ppsmemCounters->PeakPagefileUsage = Counters.PeakPagefileUsage; /* And if needed, additional field for _EX version */ if (cb >= sizeof(PROCESS_MEMORY_COUNTERS_EX)) { ((PPROCESS_MEMORY_COUNTERS_EX)ppsmemCounters)->PrivateUsage = Counters.PrivateUsage; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); _SEH2_YIELD(return FALSE); } _SEH2_END;
return TRUE;}
/* * @implemented */BOOLWINAPIQueryWorkingSet(HANDLE hProcess, PVOID pv, DWORD cb){ NTSTATUS Status;
/* Simply forward the call */ Status = NtQueryVirtualMemory(hProcess, NULL, MemoryWorkingSetList, pv, cb, NULL); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
return TRUE;}
/* * @implemented */BOOLWINAPIQueryWorkingSetEx(IN HANDLE hProcess, IN OUT PVOID pv, IN DWORD cb){ NTSTATUS Status;
/* Simply forward the call */ Status = NtQueryVirtualMemory(hProcess, NULL, MemoryWorkingSetExList, pv, cb, NULL); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; }
return TRUE;}
/* EOF */