Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpsapi.c
Go to the documentation of this file.
00001 /* $Id: psapi.c 44602 2009-12-15 15:16:01Z tkreuzer $ 00002 */ 00003 /* 00004 * COPYRIGHT: See COPYING in the top level directory 00005 * LICENSE: See LGPL.txt in the top level directory 00006 * PROJECT: ReactOS system libraries 00007 * FILE: reactos/lib/psapi/misc/win32.c 00008 * PURPOSE: Win32 interfaces for PSAPI 00009 * PROGRAMMER: KJK::Hyperion <noog@libero.it> 00010 * Thomas Weidenmueller <w3seek@reactos.com> 00011 * UPDATE HISTORY: 00012 * 10/06/2002: Created 00013 */ 00014 00015 #include "precomp.h" 00016 00017 #define NDEBUG 00018 #include <debug.h> 00019 00020 BOOLEAN 00021 WINAPI 00022 DllMain(HINSTANCE hDllHandle, 00023 DWORD nReason, 00024 LPVOID Reserved) 00025 { 00026 switch(nReason) 00027 { 00028 case DLL_PROCESS_ATTACH: 00029 DisableThreadLibraryCalls(hDllHandle); 00030 break; 00031 } 00032 00033 return TRUE; 00034 } 00035 00036 /* INTERNAL *******************************************************************/ 00037 00038 typedef struct _ENUM_DEVICE_DRIVERS_CONTEXT 00039 { 00040 LPVOID *lpImageBase; 00041 DWORD nCount; 00042 DWORD nTotal; 00043 } ENUM_DEVICE_DRIVERS_CONTEXT, *PENUM_DEVICE_DRIVERS_CONTEXT; 00044 00045 NTSTATUS WINAPI 00046 EnumDeviceDriversCallback(IN PRTL_PROCESS_MODULE_INFORMATION CurrentModule, 00047 IN OUT PVOID CallbackContext) 00048 { 00049 PENUM_DEVICE_DRIVERS_CONTEXT Context = (PENUM_DEVICE_DRIVERS_CONTEXT)CallbackContext; 00050 00051 /* check if more buffer space is available */ 00052 if(Context->nCount != 0) 00053 { 00054 /* return current module */ 00055 *Context->lpImageBase = CurrentModule->ImageBase; 00056 00057 /* go to next array slot */ 00058 Context->lpImageBase++; 00059 Context->nCount--; 00060 } 00061 00062 Context->nTotal++; 00063 return STATUS_SUCCESS; 00064 } 00065 00066 00067 typedef struct _ENUM_PROCESSES_CONTEXT 00068 { 00069 DWORD *lpidProcess; 00070 DWORD nCount; 00071 } ENUM_PROCESSES_CONTEXT, *PENUM_PROCESSES_CONTEXT; 00072 00073 NTSTATUS WINAPI 00074 EnumProcessesCallback(IN PSYSTEM_PROCESS_INFORMATION CurrentProcess, 00075 IN OUT PVOID CallbackContext) 00076 { 00077 PENUM_PROCESSES_CONTEXT Context = (PENUM_PROCESSES_CONTEXT)CallbackContext; 00078 00079 /* no more buffer space */ 00080 if(Context->nCount == 0) 00081 { 00082 return STATUS_INFO_LENGTH_MISMATCH; 00083 } 00084 00085 /* return current process */ 00086 *Context->lpidProcess = (DWORD_PTR)CurrentProcess->UniqueProcessId; 00087 00088 /* go to next array slot */ 00089 Context->lpidProcess++; 00090 Context->nCount--; 00091 00092 return STATUS_SUCCESS; 00093 } 00094 00095 00096 typedef struct _ENUM_PROCESS_MODULES_CONTEXT 00097 { 00098 HMODULE *lphModule; 00099 DWORD nCount; 00100 DWORD nTotal; 00101 } ENUM_PROCESS_MODULES_CONTEXT, *PENUM_PROCESS_MODULES_CONTEXT; 00102 00103 NTSTATUS WINAPI 00104 EnumProcessModulesCallback(IN HANDLE ProcessHandle, 00105 IN PLDR_DATA_TABLE_ENTRY CurrentModule, 00106 IN OUT PVOID CallbackContext) 00107 { 00108 PENUM_PROCESS_MODULES_CONTEXT Context = (PENUM_PROCESS_MODULES_CONTEXT)CallbackContext; 00109 00110 /* check if more buffer space is available */ 00111 if(Context->nCount != 0) 00112 { 00113 /* return current process */ 00114 *Context->lphModule = CurrentModule->DllBase; 00115 00116 /* go to next array slot */ 00117 Context->lphModule++; 00118 Context->nCount--; 00119 } 00120 00121 Context->nTotal++; 00122 return STATUS_SUCCESS; 00123 } 00124 00125 00126 typedef struct _GET_DEVICE_DRIVER_NAME_CONTEXT 00127 { 00128 LPVOID ImageBase; 00129 struct 00130 { 00131 ULONG bFullName : sizeof(ULONG) * 8 / 2; 00132 ULONG bUnicode : sizeof(ULONG) * 8 / 2; 00133 }; 00134 DWORD nSize; 00135 union 00136 { 00137 LPVOID lpName; 00138 LPSTR lpAnsiName; 00139 LPWSTR lpUnicodeName; 00140 }; 00141 } GET_DEVICE_DRIVER_NAME_CONTEXT, *PGET_DEVICE_DRIVER_NAME_CONTEXT; 00142 00143 NTSTATUS WINAPI 00144 GetDeviceDriverNameCallback(IN PRTL_PROCESS_MODULE_INFORMATION CurrentModule, 00145 IN OUT PVOID CallbackContext) 00146 { 00147 PGET_DEVICE_DRIVER_NAME_CONTEXT Context = (PGET_DEVICE_DRIVER_NAME_CONTEXT)CallbackContext; 00148 00149 /* module found */ 00150 if(Context->ImageBase == CurrentModule->ImageBase) 00151 { 00152 PCHAR pcModuleName; 00153 ULONG l; 00154 00155 /* get the full name or just the filename part */ 00156 if(Context->bFullName) 00157 pcModuleName = &CurrentModule->FullPathName[0]; 00158 else 00159 pcModuleName = &CurrentModule->FullPathName[CurrentModule->OffsetToFileName]; 00160 00161 /* get the length of the name */ 00162 l = strlen(pcModuleName); 00163 00164 if(Context->nSize <= l) 00165 { 00166 /* use the user buffer's length */ 00167 l = Context->nSize; 00168 } 00169 else 00170 { 00171 /* enough space for the null terminator */ 00172 Context->nSize = ++l; 00173 } 00174 00175 /* copy the string */ 00176 if(Context->bUnicode) 00177 { 00178 ANSI_STRING AnsiString; 00179 UNICODE_STRING UnicodeString; 00180 00181 UnicodeString.Length = 0; 00182 UnicodeString.MaximumLength = l * sizeof(WCHAR); 00183 UnicodeString.Buffer = Context->lpUnicodeName; 00184 00185 RtlInitAnsiString(&AnsiString, pcModuleName); 00186 /* driver names should always be in language-neutral ASCII, so we don't 00187 bother calling AreFileApisANSI() */ 00188 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); 00189 } 00190 else 00191 { 00192 memcpy(Context->lpAnsiName, pcModuleName, l); 00193 } 00194 00195 /* terminate the enumeration */ 00196 return STATUS_NO_MORE_FILES; 00197 } 00198 else 00199 { 00200 /* continue searching */ 00201 return STATUS_SUCCESS; 00202 } 00203 } 00204 00205 00206 static DWORD 00207 InternalGetDeviceDriverName(BOOLEAN bUnicode, 00208 BOOLEAN bFullName, 00209 LPVOID ImageBase, 00210 LPVOID lpName, 00211 DWORD nSize) 00212 { 00213 GET_DEVICE_DRIVER_NAME_CONTEXT Context; 00214 NTSTATUS Status; 00215 00216 if(lpName == NULL || nSize == 0) 00217 { 00218 return 0; 00219 } 00220 00221 if(ImageBase == NULL) 00222 { 00223 SetLastError(ERROR_INVALID_HANDLE); 00224 return 0; 00225 } 00226 00227 Context.ImageBase = ImageBase; 00228 Context.bFullName = bFullName; 00229 Context.bUnicode = bUnicode; 00230 Context.nSize = nSize; 00231 Context.lpName = lpName; 00232 00233 /* start the enumeration */ 00234 Status = PsaEnumerateSystemModules(GetDeviceDriverNameCallback, &Context); 00235 00236 if(Status == STATUS_NO_MORE_FILES) 00237 { 00238 /* module was found, return string size */ 00239 return Context.nSize; 00240 } 00241 else if(NT_SUCCESS(Status)) 00242 { 00243 /* module was not found */ 00244 SetLastError(ERROR_INVALID_HANDLE); 00245 } 00246 else 00247 { 00248 /* an error occurred */ 00249 SetLastErrorByStatus(Status); 00250 } 00251 return 0; 00252 } 00253 00254 00255 static DWORD 00256 InternalGetMappedFileName(BOOLEAN bUnicode, 00257 HANDLE hProcess, 00258 LPVOID lpv, 00259 LPVOID lpName, 00260 DWORD nSize) 00261 { 00262 PMEMORY_SECTION_NAME pmsnName; 00263 ULONG nBufSize; 00264 NTSTATUS Status; 00265 00266 if(nSize == 0 || lpName == NULL) 00267 { 00268 return 0; 00269 } 00270 00271 if(nSize > (0xFFFF / sizeof(WCHAR))) 00272 { 00273 /* if the user buffer contains more characters than would fit in an 00274 UNICODE_STRING, limit the buffer size. RATIONALE: we don't limit buffer 00275 size elsewhere because here superfluous buffer size will mean a larger 00276 temporary buffer */ 00277 nBufSize = 0xFFFF / sizeof(WCHAR); 00278 } 00279 else 00280 { 00281 nBufSize = nSize * sizeof(WCHAR); 00282 } 00283 00284 /* allocate the memory */ 00285 pmsnName = PsaiMalloc(nBufSize + sizeof(MEMORY_SECTION_NAME)); 00286 00287 if(pmsnName == NULL) 00288 { 00289 SetLastError(ERROR_OUTOFMEMORY); 00290 return 0; 00291 } 00292 00293 /* initialize the destination buffer */ 00294 pmsnName->SectionFileName.Length = 0; 00295 pmsnName->SectionFileName.Length = nBufSize; 00296 00297 #if 0 00298 __try 00299 { 00300 #endif 00301 /* query the name */ 00302 Status = NtQueryVirtualMemory(hProcess, 00303 lpv, 00304 MemorySectionName, 00305 pmsnName, 00306 nBufSize, 00307 NULL); 00308 if(!NT_SUCCESS(Status)) 00309 { 00310 PsaiFree(pmsnName); 00311 SetLastErrorByStatus(Status); 00312 return 0; 00313 } 00314 00315 if(bUnicode) 00316 { 00317 /* destination is an Unicode string: direct copy */ 00318 memcpy((LPWSTR)lpName, pmsnName + 1, pmsnName->SectionFileName.Length); 00319 00320 PsaiFree(pmsnName); 00321 00322 if(pmsnName->SectionFileName.Length < nSize) 00323 { 00324 /* null-terminate the string */ 00325 ((LPWSTR)lpName)[pmsnName->SectionFileName.Length] = 0; 00326 return pmsnName->SectionFileName.Length + 1; 00327 } 00328 00329 return pmsnName->SectionFileName.Length; 00330 } 00331 else 00332 { 00333 ANSI_STRING AnsiString; 00334 00335 AnsiString.Length = 0; 00336 AnsiString.MaximumLength = nSize; 00337 AnsiString.Buffer = (LPSTR)lpName; 00338 00339 if(AreFileApisANSI()) 00340 RtlUnicodeStringToAnsiString(&AnsiString, &pmsnName->SectionFileName, FALSE); 00341 else 00342 RtlUnicodeStringToOemString(&AnsiString, &pmsnName->SectionFileName, FALSE); 00343 00344 PsaiFree(pmsnName); 00345 00346 if(AnsiString.Length < nSize) 00347 { 00348 /* null-terminate the string */ 00349 ((LPSTR)lpName)[AnsiString.Length] = 0; 00350 return AnsiString.Length + 1; 00351 } 00352 00353 return AnsiString.Length; 00354 } 00355 00356 #if 0 00357 } 00358 __finally 00359 { 00360 PsaiFree(pmsnName); 00361 } 00362 #endif 00363 } 00364 00365 00366 typedef struct _GET_MODULE_INFORMATION_FLAGS 00367 { 00368 ULONG bWantName : sizeof(ULONG) * 8 / 4; 00369 ULONG bUnicode : sizeof(ULONG) * 8 / 4; 00370 ULONG bFullName : sizeof(ULONG) * 8 / 4; 00371 } GET_MODULE_INFORMATION_FLAGS, *PGET_MODULE_INFORMATION_FLAGS; 00372 00373 typedef struct _GET_MODULE_INFORMATION_CONTEXT 00374 { 00375 HMODULE hModule; 00376 GET_MODULE_INFORMATION_FLAGS Flags; 00377 DWORD nBufSize; 00378 union 00379 { 00380 LPWSTR lpUnicodeName; 00381 LPSTR lpAnsiName; 00382 LPMODULEINFO lpmodinfo; 00383 LPVOID lpBuffer; 00384 }; 00385 } GET_MODULE_INFORMATION_CONTEXT, *PGET_MODULE_INFORMATION_CONTEXT; 00386 00387 NTSTATUS WINAPI 00388 GetModuleInformationCallback(IN HANDLE ProcessHandle, 00389 IN PLDR_DATA_TABLE_ENTRY CurrentModule, 00390 IN OUT PVOID CallbackContext) 00391 { 00392 PGET_MODULE_INFORMATION_CONTEXT Context = (PGET_MODULE_INFORMATION_CONTEXT)CallbackContext; 00393 00394 /* found the module we were looking for */ 00395 if(CurrentModule->DllBase == Context->hModule) 00396 { 00397 /* we want the module name */ 00398 if(Context->Flags.bWantName) 00399 { 00400 PUNICODE_STRING SourceString; 00401 ULONG l; 00402 NTSTATUS Status; 00403 00404 if(Context->Flags.bFullName) 00405 SourceString = &(CurrentModule->FullDllName); 00406 else 00407 SourceString = &(CurrentModule->BaseDllName); 00408 00409 SourceString->Length -= SourceString->Length % sizeof(WCHAR); 00410 00411 /* l is the byte size of the user buffer */ 00412 l = Context->nBufSize * sizeof(WCHAR); 00413 00414 /* if the user buffer has room for the string and a null terminator */ 00415 if(l >= (SourceString->Length + sizeof(WCHAR))) 00416 { 00417 /* limit the buffer size */ 00418 l = SourceString->Length; 00419 00420 /* null-terminate the string */ 00421 if(Context->Flags.bUnicode) 00422 Context->lpUnicodeName[l / sizeof(WCHAR)] = 0; 00423 else 00424 Context->lpAnsiName[l / sizeof(WCHAR)] = 0; 00425 } 00426 00427 if(Context->Flags.bUnicode) 00428 { 00429 /* Unicode: direct copy */ 00430 /* NOTE: I've chosen not to check for ProcessHandle == NtCurrentProcess(), 00431 this function is complicated enough as it is */ 00432 Status = NtReadVirtualMemory(ProcessHandle, 00433 SourceString->Buffer, 00434 Context->lpUnicodeName, 00435 l, 00436 NULL); 00437 00438 if(!NT_SUCCESS(Status)) 00439 { 00440 Context->nBufSize = 0; 00441 return Status; 00442 } 00443 00444 Context->nBufSize = l / sizeof(WCHAR); 00445 } 00446 else 00447 { 00448 /* ANSI/OEM: convert and copy */ 00449 LPWSTR pwcUnicodeBuf; 00450 ANSI_STRING AnsiString; 00451 UNICODE_STRING UnicodeString; 00452 00453 AnsiString.Length = 0; 00454 AnsiString.MaximumLength = Context->nBufSize; 00455 AnsiString.Buffer = Context->lpAnsiName; 00456 00457 /* allocate the local buffer */ 00458 pwcUnicodeBuf = PsaiMalloc(SourceString->Length); 00459 00460 #if 0 00461 __try 00462 { 00463 #endif 00464 if(pwcUnicodeBuf == NULL) 00465 { 00466 Status = STATUS_NO_MEMORY; 00467 goto exitWithStatus; 00468 } 00469 00470 /* copy the string in the local buffer */ 00471 Status = NtReadVirtualMemory(ProcessHandle, 00472 SourceString->Buffer, 00473 pwcUnicodeBuf, 00474 l, 00475 NULL); 00476 00477 if(!NT_SUCCESS(Status)) 00478 { 00479 goto exitWithStatus; 00480 } 00481 00482 /* initialize Unicode string buffer */ 00483 UnicodeString.Length = UnicodeString.MaximumLength = l; 00484 UnicodeString.Buffer = pwcUnicodeBuf; 00485 00486 /* convert and copy */ 00487 if(AreFileApisANSI()) 00488 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE); 00489 else 00490 RtlUnicodeStringToOemString(&AnsiString, &UnicodeString, FALSE); 00491 00492 /* return the string size */ 00493 Context->nBufSize = AnsiString.Length; 00494 #if 0 00495 } 00496 __finally 00497 { 00498 /* free the buffer */ 00499 PsaiFree(pwcUnicodeBuf); 00500 } 00501 #else 00502 Status = STATUS_NO_MORE_FILES; 00503 00504 exitWithStatus: 00505 /* free the buffer */ 00506 PsaiFree(pwcUnicodeBuf); 00507 return Status; 00508 #endif 00509 } 00510 } 00511 else 00512 { 00513 /* we want other module information */ 00514 ULONG nSize = Context->nBufSize; 00515 00516 /* base address */ 00517 if(nSize >= sizeof(CurrentModule->DllBase)) 00518 { 00519 Context->lpmodinfo->lpBaseOfDll = CurrentModule->DllBase; 00520 nSize -= sizeof(CurrentModule->DllBase); 00521 } 00522 00523 /* image size */ 00524 if(nSize >= sizeof(CurrentModule->SizeOfImage)) 00525 { 00526 Context->lpmodinfo->SizeOfImage = CurrentModule->SizeOfImage; 00527 nSize -= sizeof(CurrentModule->SizeOfImage); 00528 } 00529 00530 /* entry point */ 00531 if(nSize >= sizeof(CurrentModule->EntryPoint)) 00532 { 00533 /* ??? FIXME? is "EntryPoint" just the offset, or the real address? */ 00534 Context->lpmodinfo->EntryPoint = (PVOID)CurrentModule->EntryPoint; 00535 } 00536 00537 Context->nBufSize = TRUE; 00538 } 00539 00540 return STATUS_NO_MORE_FILES; 00541 } 00542 00543 return STATUS_SUCCESS; 00544 } 00545 00546 00547 static DWORD 00548 InternalGetModuleInformation(HANDLE hProcess, 00549 HMODULE hModule, 00550 GET_MODULE_INFORMATION_FLAGS Flags, 00551 LPVOID lpBuffer, 00552 DWORD nBufSize) 00553 { 00554 GET_MODULE_INFORMATION_CONTEXT Context; 00555 NTSTATUS Status; 00556 00557 Context.hModule = hModule; 00558 Context.Flags = Flags; 00559 Context.nBufSize = nBufSize; 00560 Context.lpBuffer = lpBuffer; 00561 00562 Status = PsaEnumerateProcessModules(hProcess, GetModuleInformationCallback, &Context); 00563 00564 if(Status == STATUS_NO_MORE_FILES) 00565 { 00566 /* module was found, return string size */ 00567 return Context.nBufSize; 00568 } 00569 else if(NT_SUCCESS(Status)) 00570 { 00571 /* module was not found */ 00572 SetLastError(ERROR_INVALID_HANDLE); 00573 } 00574 else 00575 { 00576 /* an error occurred */ 00577 SetLastErrorByStatus(Status); 00578 } 00579 return 0; 00580 } 00581 00582 00583 typedef struct _INTERNAL_ENUM_PAGE_FILES_CONTEXT 00584 { 00585 PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine; 00586 LPVOID lpContext; 00587 } INTERNAL_ENUM_PAGE_FILES_CONTEXT, *PINTERNAL_ENUM_PAGE_FILES_CONTEXT; 00588 00589 00590 static BOOL CALLBACK 00591 InternalAnsiPageFileCallback(LPVOID pContext, 00592 PENUM_PAGE_FILE_INFORMATION pPageFileInfo, 00593 LPCWSTR lpFilename) 00594 { 00595 size_t slen; 00596 LPSTR AnsiFileName; 00597 PINTERNAL_ENUM_PAGE_FILES_CONTEXT Context = (PINTERNAL_ENUM_PAGE_FILES_CONTEXT)pContext; 00598 00599 slen = wcslen(lpFilename); 00600 00601 AnsiFileName = (LPSTR)LocalAlloc(LMEM_FIXED, (slen + 1) * sizeof(CHAR)); 00602 if(AnsiFileName != NULL) 00603 { 00604 BOOL Ret; 00605 00606 WideCharToMultiByte(CP_ACP, 00607 0, 00608 lpFilename, 00609 -1, /* only works if the string is NULL-terminated!!! */ 00610 AnsiFileName, 00611 (slen + 1) * sizeof(CHAR), 00612 NULL, 00613 NULL); 00614 00615 Ret = Context->pCallbackRoutine(Context->lpContext, pPageFileInfo, AnsiFileName); 00616 00617 LocalFree((HLOCAL)AnsiFileName); 00618 00619 return Ret; 00620 } 00621 00622 return FALSE; 00623 } 00624 00625 /* PUBLIC *********************************************************************/ 00626 00627 /* 00628 * @implemented 00629 */ 00630 BOOL 00631 WINAPI 00632 EmptyWorkingSet(HANDLE hProcess) 00633 { 00634 QUOTA_LIMITS QuotaLimits; 00635 NTSTATUS Status; 00636 00637 /* query the working set */ 00638 Status = NtQueryInformationProcess(hProcess, 00639 ProcessQuotaLimits, 00640 &QuotaLimits, 00641 sizeof(QuotaLimits), 00642 NULL); 00643 00644 if(!NT_SUCCESS(Status)) 00645 { 00646 SetLastErrorByStatus(Status); 00647 return FALSE; 00648 } 00649 00650 /* empty the working set */ 00651 QuotaLimits.MinimumWorkingSetSize = -1; 00652 QuotaLimits.MaximumWorkingSetSize = -1; 00653 00654 /* set the working set */ 00655 Status = NtSetInformationProcess(hProcess, 00656 ProcessQuotaLimits, 00657 &QuotaLimits, 00658 sizeof(QuotaLimits)); 00659 if(!NT_SUCCESS(Status)) 00660 { 00661 SetLastErrorByStatus(Status); 00662 return FALSE; 00663 } 00664 00665 return TRUE; 00666 } 00667 00668 00669 /* 00670 * @implemented 00671 */ 00672 BOOL 00673 WINAPI 00674 EnumDeviceDrivers(LPVOID *lpImageBase, 00675 DWORD cb, 00676 LPDWORD lpcbNeeded) 00677 { 00678 ENUM_DEVICE_DRIVERS_CONTEXT Context; 00679 NTSTATUS Status; 00680 00681 cb /= sizeof(PVOID); 00682 00683 Context.lpImageBase = lpImageBase; 00684 Context.nCount = cb; 00685 Context.nTotal = 0; 00686 00687 Status = PsaEnumerateSystemModules(EnumDeviceDriversCallback, &Context); 00688 00689 /* return the count of bytes that would be needed for a complete enumeration */ 00690 *lpcbNeeded = Context.nTotal * sizeof(PVOID); 00691 00692 if(!NT_SUCCESS(Status)) 00693 { 00694 SetLastErrorByStatus(Status); 00695 return FALSE; 00696 } 00697 00698 return TRUE; 00699 } 00700 00701 00702 /* 00703 * @implemented 00704 */ 00705 BOOL 00706 WINAPI 00707 EnumProcesses(DWORD *lpidProcess, 00708 DWORD cb, 00709 LPDWORD lpcbNeeded) 00710 { 00711 ENUM_PROCESSES_CONTEXT Context; 00712 NTSTATUS Status; 00713 00714 cb /= sizeof(DWORD); 00715 00716 if(cb == 0 || lpidProcess == NULL) 00717 { 00718 *lpcbNeeded = 0; 00719 return TRUE; 00720 } 00721 00722 Context.lpidProcess = lpidProcess; 00723 Context.nCount = cb; 00724 00725 /* enumerate the process ids */ 00726 Status = PsaEnumerateProcesses(EnumProcessesCallback, &Context); 00727 00728 *lpcbNeeded = (cb - Context.nCount) * sizeof(DWORD); 00729 00730 if(!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH)) 00731 { 00732 SetLastErrorByStatus(Status); 00733 return FALSE; 00734 } 00735 00736 return TRUE; 00737 } 00738 00739 00740 /* 00741 * @implemented 00742 */ 00743 BOOL 00744 WINAPI 00745 EnumProcessModules(HANDLE hProcess, 00746 HMODULE *lphModule, 00747 DWORD cb, 00748 LPDWORD lpcbNeeded) 00749 { 00750 ENUM_PROCESS_MODULES_CONTEXT Context; 00751 NTSTATUS Status; 00752 00753 cb /= sizeof(HMODULE); 00754 00755 Context.lphModule = lphModule; 00756 Context.nCount = cb; 00757 Context.nTotal = 0; 00758 00759 /* enumerate the process modules */ 00760 Status = PsaEnumerateProcessModules(hProcess, EnumProcessModulesCallback, &Context); 00761 00762 *lpcbNeeded = Context.nTotal * sizeof(HMODULE); 00763 00764 if(!NT_SUCCESS(Status)) 00765 { 00766 SetLastErrorByStatus(Status); 00767 return FALSE; 00768 } 00769 00770 return TRUE; 00771 } 00772 00773 00774 /* 00775 * @implemented 00776 */ 00777 DWORD 00778 WINAPI 00779 GetDeviceDriverBaseNameA(LPVOID ImageBase, 00780 LPSTR lpBaseName, 00781 DWORD nSize) 00782 { 00783 return InternalGetDeviceDriverName(FALSE, FALSE, ImageBase, lpBaseName, nSize); 00784 } 00785 00786 00787 /* 00788 * @implemented 00789 */ 00790 DWORD 00791 WINAPI 00792 GetDeviceDriverFileNameA(LPVOID ImageBase, 00793 LPSTR lpFilename, 00794 DWORD nSize) 00795 { 00796 return InternalGetDeviceDriverName(FALSE, TRUE, ImageBase, lpFilename, nSize); 00797 } 00798 00799 00800 /* 00801 * @implemented 00802 */ 00803 DWORD 00804 WINAPI 00805 GetDeviceDriverBaseNameW(LPVOID ImageBase, 00806 LPWSTR lpBaseName, 00807 DWORD nSize) 00808 { 00809 return InternalGetDeviceDriverName(TRUE, FALSE, ImageBase, lpBaseName, nSize); 00810 } 00811 00812 00813 /* 00814 * @implemented 00815 */ 00816 DWORD 00817 WINAPI 00818 GetDeviceDriverFileNameW(LPVOID ImageBase, 00819 LPWSTR lpFilename, 00820 DWORD nSize) 00821 { 00822 return InternalGetDeviceDriverName(TRUE, TRUE, ImageBase, lpFilename, nSize); 00823 } 00824 00825 00826 /* 00827 * @implemented 00828 */ 00829 DWORD 00830 WINAPI 00831 GetMappedFileNameA(HANDLE hProcess, 00832 LPVOID lpv, 00833 LPSTR lpFilename, 00834 DWORD nSize) 00835 { 00836 return InternalGetMappedFileName(FALSE, hProcess, lpv, lpFilename, nSize); 00837 } 00838 00839 00840 /* 00841 * @implemented 00842 */ 00843 DWORD 00844 WINAPI 00845 GetMappedFileNameW(HANDLE hProcess, 00846 LPVOID lpv, 00847 LPWSTR lpFilename, 00848 DWORD nSize) 00849 { 00850 return InternalGetMappedFileName(TRUE, hProcess, lpv, lpFilename, nSize); 00851 } 00852 00853 00854 /* 00855 * @implemented 00856 */ 00857 DWORD 00858 WINAPI 00859 GetModuleBaseNameA(HANDLE hProcess, 00860 HMODULE hModule, 00861 LPSTR lpBaseName, 00862 DWORD nSize) 00863 { 00864 GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, FALSE, FALSE}; 00865 return InternalGetModuleInformation(hProcess, hModule, Flags, lpBaseName, nSize); 00866 } 00867 00868 00869 /* 00870 * @implemented 00871 */ 00872 DWORD 00873 WINAPI 00874 GetModuleBaseNameW(HANDLE hProcess, 00875 HMODULE hModule, 00876 LPWSTR lpBaseName, 00877 DWORD nSize) 00878 { 00879 GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, TRUE, FALSE}; 00880 return InternalGetModuleInformation(hProcess, hModule, Flags, lpBaseName, nSize); 00881 } 00882 00883 00884 /* 00885 * @implemented 00886 */ 00887 DWORD 00888 WINAPI 00889 GetModuleFileNameExA(HANDLE hProcess, 00890 HMODULE hModule, 00891 LPSTR lpFilename, 00892 DWORD nSize) 00893 { 00894 GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, FALSE, TRUE}; 00895 return InternalGetModuleInformation(hProcess, hModule, Flags, lpFilename, nSize); 00896 } 00897 00898 00899 /* 00900 * @implemented 00901 */ 00902 DWORD 00903 WINAPI 00904 GetModuleFileNameExW(HANDLE hProcess, 00905 HMODULE hModule, 00906 LPWSTR lpFilename, 00907 DWORD nSize) 00908 { 00909 GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, TRUE, TRUE}; 00910 return InternalGetModuleInformation(hProcess, hModule, Flags, lpFilename, nSize); 00911 } 00912 00913 00914 /* 00915 * @implemented 00916 */ 00917 BOOL 00918 WINAPI 00919 GetModuleInformation(HANDLE hProcess, 00920 HMODULE hModule, 00921 LPMODULEINFO lpmodinfo, 00922 DWORD cb) 00923 { 00924 GET_MODULE_INFORMATION_FLAGS Flags = {FALSE, FALSE, FALSE}; 00925 00926 if (cb < sizeof(MODULEINFO)) 00927 { 00928 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00929 return FALSE; 00930 } 00931 return (BOOL)InternalGetModuleInformation(hProcess, hModule, Flags, lpmodinfo, cb); 00932 } 00933 00934 00935 /* 00936 * @implemented 00937 */ 00938 BOOL 00939 WINAPI 00940 InitializeProcessForWsWatch(HANDLE hProcess) 00941 { 00942 NTSTATUS Status; 00943 00944 Status = NtSetInformationProcess(hProcess, 00945 ProcessWorkingSetWatch, 00946 NULL, 00947 0); 00948 if(!NT_SUCCESS(Status)) 00949 { 00950 SetLastErrorByStatus(Status); 00951 return FALSE; 00952 } 00953 00954 return TRUE; 00955 } 00956 00957 00958 /* 00959 * @implemented 00960 */ 00961 BOOL 00962 WINAPI 00963 GetWsChanges(HANDLE hProcess, 00964 PPSAPI_WS_WATCH_INFORMATION lpWatchInfo, 00965 DWORD cb) 00966 { 00967 NTSTATUS Status; 00968 00969 Status = NtQueryInformationProcess(hProcess, 00970 ProcessWorkingSetWatch, 00971 (PVOID)lpWatchInfo, 00972 cb, 00973 NULL); 00974 if(!NT_SUCCESS(Status)) 00975 { 00976 SetLastErrorByStatus(Status); 00977 return FALSE; 00978 } 00979 00980 return TRUE; 00981 } 00982 00983 00984 /* 00985 * @implemented 00986 */ 00987 DWORD 00988 WINAPI 00989 GetProcessImageFileNameW(HANDLE hProcess, 00990 LPWSTR lpImageFileName, 00991 DWORD nSize) 00992 { 00993 PUNICODE_STRING ImageFileName; 00994 SIZE_T BufferSize; 00995 NTSTATUS Status; 00996 DWORD Ret = 0; 00997 00998 BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR)); 00999 01000 ImageFileName = (PUNICODE_STRING)LocalAlloc(LMEM_FIXED, BufferSize); 01001 if(ImageFileName != NULL) 01002 { 01003 Status = NtQueryInformationProcess(hProcess, 01004 ProcessImageFileName, 01005 ImageFileName, 01006 BufferSize, 01007 NULL); 01008 if(NT_SUCCESS(Status)) 01009 { 01010 memcpy(lpImageFileName, ImageFileName->Buffer, ImageFileName->Length); 01011 01012 /* make sure the string is null-terminated! */ 01013 lpImageFileName[ImageFileName->Length / sizeof(WCHAR)] = L'\0'; 01014 Ret = ImageFileName->Length / sizeof(WCHAR); 01015 } 01016 else if(Status == STATUS_INFO_LENGTH_MISMATCH) 01017 { 01018 /* XP sets this error code for some reason if the buffer is too small */ 01019 SetLastError(ERROR_INSUFFICIENT_BUFFER); 01020 } 01021 else 01022 { 01023 SetLastErrorByStatus(Status); 01024 } 01025 01026 LocalFree((HLOCAL)ImageFileName); 01027 } 01028 01029 return Ret; 01030 } 01031 01032 01033 /* 01034 * @implemented 01035 */ 01036 DWORD 01037 WINAPI 01038 GetProcessImageFileNameA(HANDLE hProcess, 01039 LPSTR lpImageFileName, 01040 DWORD nSize) 01041 { 01042 PUNICODE_STRING ImageFileName; 01043 SIZE_T BufferSize; 01044 NTSTATUS Status; 01045 DWORD Ret = 0; 01046 01047 BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR)); 01048 01049 ImageFileName = (PUNICODE_STRING)LocalAlloc(LMEM_FIXED, BufferSize); 01050 if(ImageFileName != NULL) 01051 { 01052 Status = NtQueryInformationProcess(hProcess, 01053 ProcessImageFileName, 01054 ImageFileName, 01055 BufferSize, 01056 NULL); 01057 if(NT_SUCCESS(Status)) 01058 { 01059 WideCharToMultiByte(CP_ACP, 01060 0, 01061 ImageFileName->Buffer, 01062 ImageFileName->Length / sizeof(WCHAR), 01063 lpImageFileName, 01064 nSize, 01065 NULL, 01066 NULL); 01067 01068 /* make sure the string is null-terminated! */ 01069 lpImageFileName[ImageFileName->Length / sizeof(WCHAR)] = '\0'; 01070 Ret = ImageFileName->Length / sizeof(WCHAR); 01071 } 01072 else if(Status == STATUS_INFO_LENGTH_MISMATCH) 01073 { 01074 /* XP sets this error code for some reason if the buffer is too small */ 01075 SetLastError(ERROR_INSUFFICIENT_BUFFER); 01076 } 01077 else 01078 { 01079 SetLastErrorByStatus(Status); 01080 } 01081 01082 LocalFree((HLOCAL)ImageFileName); 01083 } 01084 01085 return Ret; 01086 } 01087 01088 01089 /* 01090 * @implemented 01091 */ 01092 BOOL 01093 WINAPI 01094 EnumPageFilesA(PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine, 01095 LPVOID lpContext) 01096 { 01097 INTERNAL_ENUM_PAGE_FILES_CONTEXT Context; 01098 01099 Context.pCallbackRoutine = pCallbackRoutine; 01100 Context.lpContext = lpContext; 01101 01102 return EnumPageFilesW(InternalAnsiPageFileCallback, &Context); 01103 } 01104 01105 01106 /* 01107 * @implemented 01108 */ 01109 BOOL 01110 WINAPI 01111 EnumPageFilesW(PENUM_PAGE_FILE_CALLBACKW pCallbackRoutine, 01112 LPVOID lpContext) 01113 { 01114 NTSTATUS Status; 01115 PVOID Buffer; 01116 ULONG BufferSize = 0; 01117 BOOL Ret = FALSE; 01118 01119 for(;;) 01120 { 01121 BufferSize += 0x1000; 01122 Buffer = LocalAlloc(LMEM_FIXED, BufferSize); 01123 if(Buffer == NULL) 01124 { 01125 return FALSE; 01126 } 01127 01128 Status = NtQuerySystemInformation(SystemPageFileInformation, 01129 Buffer, 01130 BufferSize, 01131 NULL); 01132 if(Status == STATUS_INFO_LENGTH_MISMATCH) 01133 { 01134 LocalFree((HLOCAL)Buffer); 01135 } 01136 else 01137 { 01138 break; 01139 } 01140 } 01141 01142 if(NT_SUCCESS(Status)) 01143 { 01144 ENUM_PAGE_FILE_INFORMATION Information; 01145 PSYSTEM_PAGEFILE_INFORMATION pfi = (PSYSTEM_PAGEFILE_INFORMATION)Buffer; 01146 ULONG Offset = 0; 01147 01148 do 01149 { 01150 PWCHAR Colon; 01151 01152 pfi = (PSYSTEM_PAGEFILE_INFORMATION)((ULONG_PTR)pfi + Offset); 01153 01154 Information.cb = sizeof(Information); 01155 Information.Reserved = 0; 01156 Information.TotalSize = pfi->TotalSize; 01157 Information.TotalInUse = pfi->TotalInUse; 01158 Information.PeakUsage = pfi->PeakUsage; 01159 01160 /* strip the \??\ prefix from the file name. We do this by searching for the first 01161 : character and then just change Buffer to point to the previous character. */ 01162 01163 Colon = wcschr(pfi->PageFileName.Buffer, L':'); 01164 if(Colon != NULL) 01165 { 01166 pfi->PageFileName.Buffer = --Colon; 01167 } 01168 01169 /* FIXME - looks like the PageFileName string is always NULL-terminated on win. 01170 At least I haven't encountered a different case so far, we should 01171 propably manually NULL-terminate the string here... */ 01172 01173 if(!pCallbackRoutine(lpContext, &Information, pfi->PageFileName.Buffer)) 01174 { 01175 break; 01176 } 01177 01178 Offset = pfi->NextEntryOffset; 01179 } while(Offset != 0); 01180 01181 Ret = TRUE; 01182 } 01183 else 01184 { 01185 SetLastErrorByStatus(Status); 01186 } 01187 01188 LocalFree((HLOCAL)Buffer); 01189 01190 return Ret; 01191 } 01192 01193 01194 /* 01195 * @implemented 01196 */ 01197 BOOL 01198 WINAPI 01199 GetPerformanceInfo(PPERFORMANCE_INFORMATION pPerformanceInformation, 01200 DWORD cb) 01201 { 01202 SYSTEM_PERFORMANCE_INFORMATION spi; 01203 SYSTEM_BASIC_INFORMATION sbi; 01204 SYSTEM_HANDLE_INFORMATION shi; 01205 PSYSTEM_PROCESS_INFORMATION ProcessInfo; 01206 ULONG BufferSize, ProcOffset, ProcessCount, ThreadCount; 01207 PVOID Buffer; 01208 NTSTATUS Status; 01209 01210 Status = NtQuerySystemInformation(SystemPerformanceInformation, 01211 &spi, 01212 sizeof(spi), 01213 NULL); 01214 if(!NT_SUCCESS(Status)) 01215 { 01216 SetLastErrorByStatus(Status); 01217 return FALSE; 01218 } 01219 01220 Status = NtQuerySystemInformation(SystemBasicInformation, 01221 &sbi, 01222 sizeof(sbi), 01223 NULL); 01224 if(!NT_SUCCESS(Status)) 01225 { 01226 SetLastErrorByStatus(Status); 01227 return FALSE; 01228 } 01229 01230 /* 01231 * allocate enough memory to get a dump of all processes and threads 01232 */ 01233 BufferSize = 0; 01234 for(;;) 01235 { 01236 BufferSize += 0x10000; 01237 Buffer = (PVOID)LocalAlloc(LMEM_FIXED, BufferSize); 01238 if(Buffer == NULL) 01239 { 01240 return FALSE; 01241 } 01242 01243 Status = NtQuerySystemInformation(SystemProcessInformation, 01244 Buffer, 01245 BufferSize, 01246 NULL); 01247 if(Status == STATUS_INFO_LENGTH_MISMATCH) 01248 { 01249 LocalFree((HLOCAL)Buffer); 01250 } 01251 else 01252 { 01253 break; 01254 } 01255 } 01256 01257 if(!NT_SUCCESS(Status)) 01258 { 01259 LocalFree((HLOCAL)Buffer); 01260 SetLastErrorByStatus(Status); 01261 return FALSE; 01262 } 01263 01264 /* 01265 * determine the process and thread count 01266 */ 01267 ProcessCount = ThreadCount = ProcOffset = 0; 01268 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)Buffer; 01269 do 01270 { 01271 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset); 01272 ProcessCount++; 01273 ThreadCount += ProcessInfo->NumberOfThreads; 01274 01275 ProcOffset = ProcessInfo->NextEntryOffset; 01276 } while(ProcOffset != 0); 01277 01278 LocalFree((HLOCAL)Buffer); 01279 01280 /* 01281 * it's enough to supply a SYSTEM_HANDLE_INFORMATION structure as buffer. Even 01282 * though it returns STATUS_INFO_LENGTH_MISMATCH, it already sets the NumberOfHandles 01283 * field which is all we're looking for anyway. 01284 */ 01285 Status = NtQuerySystemInformation(SystemHandleInformation, 01286 &shi, 01287 sizeof(shi), 01288 NULL); 01289 if(!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH)) 01290 { 01291 SetLastErrorByStatus(Status); 01292 return FALSE; 01293 } 01294 01295 /* 01296 * all required information collected, fill the structure 01297 */ 01298 01299 pPerformanceInformation->cb = sizeof(PERFORMANCE_INFORMATION); 01300 pPerformanceInformation->CommitTotal = spi.CommittedPages; 01301 pPerformanceInformation->CommitLimit = spi.CommitLimit; 01302 pPerformanceInformation->CommitPeak = spi.PeakCommitment; 01303 pPerformanceInformation->PhysicalTotal = sbi.NumberOfPhysicalPages; 01304 pPerformanceInformation->PhysicalAvailable = spi.AvailablePages; 01305 pPerformanceInformation->SystemCache = 0; /* FIXME - where to get this information from? */ 01306 pPerformanceInformation->KernelTotal = spi.PagedPoolPages + spi.NonPagedPoolPages; 01307 pPerformanceInformation->KernelPaged = spi.PagedPoolPages; 01308 pPerformanceInformation->KernelNonpaged = spi.NonPagedPoolPages; 01309 pPerformanceInformation->PageSize = sbi.PageSize; 01310 pPerformanceInformation->HandleCount = shi.NumberOfHandles; 01311 pPerformanceInformation->ProcessCount = ProcessCount; 01312 pPerformanceInformation->ThreadCount = ThreadCount; 01313 01314 return TRUE; 01315 } 01316 01317 01318 /* 01319 * @implemented 01320 */ 01321 BOOL 01322 WINAPI 01323 GetProcessMemoryInfo(HANDLE Process, 01324 PPROCESS_MEMORY_COUNTERS ppsmemCounters, 01325 DWORD cb) 01326 { 01327 NTSTATUS Status; 01328 VM_COUNTERS vmc; 01329 BOOL Ret = FALSE; 01330 01331 /* XP's implementation secures access to ppsmemCounters in SEH, we should behave 01332 similar so we can return the proper error codes when bad pointers are passed 01333 to this function! */ 01334 01335 _SEH2_TRY 01336 { 01337 if(cb < sizeof(PROCESS_MEMORY_COUNTERS)) 01338 { 01339 SetLastError(ERROR_INSUFFICIENT_BUFFER); 01340 _SEH2_LEAVE; 01341 } 01342 01343 /* ppsmemCounters->cb isn't checked at all! */ 01344 01345 Status = NtQueryInformationProcess(Process, 01346 ProcessVmCounters, 01347 &vmc, 01348 sizeof(vmc), 01349 NULL); 01350 if(!NT_SUCCESS(Status)) 01351 { 01352 SetLastErrorByStatus(Status); 01353 _SEH2_LEAVE; 01354 } 01355 01356 /* fill the structure with the collected information, in case of bad pointers 01357 SEH will catch the exception and set the appropriate error code */ 01358 ppsmemCounters->cb = sizeof(PROCESS_MEMORY_COUNTERS); 01359 ppsmemCounters->PageFaultCount = vmc.PageFaultCount; 01360 ppsmemCounters->PeakWorkingSetSize = vmc.PeakWorkingSetSize; 01361 ppsmemCounters->WorkingSetSize = vmc.WorkingSetSize; 01362 ppsmemCounters->QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage; 01363 ppsmemCounters->QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage; 01364 ppsmemCounters->QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage; 01365 ppsmemCounters->QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage; 01366 ppsmemCounters->PagefileUsage = vmc.PagefileUsage; 01367 ppsmemCounters->PeakPagefileUsage = vmc.PeakPagefileUsage; 01368 01369 Ret = TRUE; 01370 } 01371 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01372 { 01373 SetLastErrorByStatus(_SEH2_GetExceptionCode()); 01374 } 01375 _SEH2_END; 01376 01377 return Ret; 01378 } 01379 01380 01381 /* 01382 * @implemented 01383 */ 01384 BOOL 01385 WINAPI 01386 QueryWorkingSet(HANDLE hProcess, 01387 PVOID pv, 01388 DWORD cb) 01389 { 01390 NTSTATUS Status; 01391 01392 Status = NtQueryVirtualMemory(hProcess, 01393 NULL, 01394 MemoryWorkingSetList, 01395 pv, 01396 cb, 01397 NULL); 01398 if(!NT_SUCCESS(Status)) 01399 { 01400 SetLastErrorByStatus(Status); 01401 return FALSE; 01402 } 01403 01404 return TRUE; 01405 } 01406 01407 /* 01408 * @unimplemented 01409 */ 01410 BOOL 01411 WINAPI 01412 QueryWorkingSetEx(IN HANDLE hProcess, 01413 IN OUT PVOID pv, 01414 IN DWORD cb) 01415 { 01416 UNIMPLEMENTED; 01417 return FALSE; 01418 } 01419 01420 /* EOF */ Generated on Sun May 27 2012 04:25:55 for ReactOS by
1.7.6.1
|