From a812f4e0b2f2d215c426eac4e1b5fbd0a448d02c Mon Sep 17 00:00:00 2001 From: "KJK::Hyperion" Date: Wed, 2 Apr 2003 22:09:57 +0000 Subject: [PATCH] Long due update to PSAPI svn path=/trunk/; revision=4478 --- reactos/lib/psapi/enum/module.c | 15 +- reactos/lib/psapi/enum/process.c | 332 ++++++++++++++++++--- reactos/lib/psapi/include/internal/psapi.h | 117 +++++++- reactos/lib/psapi/makefile | 4 +- reactos/lib/psapi/misc/malloc.c | 10 +- reactos/lib/psapi/misc/win32.c | 28 +- 6 files changed, 440 insertions(+), 66 deletions(-) diff --git a/reactos/lib/psapi/enum/module.c b/reactos/lib/psapi/enum/module.c index 14280205a2b..5e3eb111ec0 100644 --- a/reactos/lib/psapi/enum/module.c +++ b/reactos/lib/psapi/enum/module.c @@ -1,4 +1,4 @@ -/* $Id: module.c,v 1.3 2002/08/31 15:36:55 hyperion Exp $ +/* $Id: module.c,v 1.4 2003/04/02 22:09:56 hyperion Exp $ */ /* * COPYRIGHT: See COPYING in the top level directory @@ -11,6 +11,8 @@ * 10/06/2002: Created * 29/08/2002: Generalized the interface to improve reusability, * more efficient use of memory operations + * 12/02/2003: malloc and free renamed to PsaiMalloc and PsaiFree, + * for better reusability */ #include @@ -19,7 +21,7 @@ #include NTSTATUS -STDCALL +NTAPI PsaEnumerateSystemModules ( IN PSYSMOD_ENUM_ROUTINE Callback, @@ -62,13 +64,14 @@ PsaEnumerateSystemModules /* free the buffer, and reallocate it to the new size. RATIONALE: since we ignore the buffer's content at this point, there's no point in a realloc(), that could end up copying a large chunk of data we'd discard anyway */ - free(pnModuleCount); - pTmp = malloc(nSize); + PsaiFree(pnModuleCount); + pTmp = PsaiMalloc(nSize); if(pTmp == NULL) { /* failure */ nErrCode = STATUS_NO_MEMORY; + DPRINT(FAILED_WITH_STATUS, "PsaiMalloc", nErrCode); goto esm_Finalize; } @@ -118,13 +121,13 @@ PsaEnumerateSystemModules esm_Finalize: /* free the buffer */ - free(pnModuleCount); + PsaiFree(pnModuleCount); return (nErrCode); } NTSTATUS -STDCALL +NTAPI PsaEnumerateProcessModules ( IN HANDLE ProcessHandle, diff --git a/reactos/lib/psapi/enum/process.c b/reactos/lib/psapi/enum/process.c index 6c187080fc7..ee28c1808c3 100644 --- a/reactos/lib/psapi/enum/process.c +++ b/reactos/lib/psapi/enum/process.c @@ -1,35 +1,52 @@ -/* $Id: process.c,v 1.3 2002/08/31 15:36:55 hyperion Exp $ +/* $Id: process.c,v 1.4 2003/04/02 22:09:56 hyperion Exp $ */ /* * 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/enum/process.c - * PURPOSE: Enumerate processes + * PURPOSE: Enumerate processes and threads * PROGRAMMER: KJK::Hyperion * UPDATE HISTORY: * 10/06/2002: Created * 29/08/2002: Generalized the interface to improve reusability, * more efficient use of memory operations + * 12/02/2003: malloc and free renamed to PsaiMalloc and PsaiFree, + * for better reusability. PsaEnumerateProcesses now + * expanded into: + * - PsaCaptureProcessesAndThreads + * - PsaFreeCapture + * - PsaWalkProcessesAndThreads + * - PsaWalkProcesses + * - PsaWalkThreads + * - PsaWalkFirstProcess + * - PsaWalkNextProcess + * - PsaWalkFirstThread + * - PsaWalkNextThread + * - PsaEnumerateProcessesAndThreads + * - PsaEnumerateProcesses + * - PsaEnumerateThreads */ -#include #include #include +#include #include NTSTATUS -STDCALL -PsaEnumerateProcesses +NTAPI +PsaCaptureProcessesAndThreads ( - IN PPROC_ENUM_ROUTINE Callback, - IN OUT PVOID CallbackContext + OUT PSYSTEM_PROCESSES * ProcessesAndThreads ) { - register NTSTATUS nErrCode = STATUS_SUCCESS; - PSYSTEM_PROCESS_INFORMATION pInfoBuffer = NULL; - PSYSTEM_PROCESS_INFORMATION pInfoHead = NULL; - ULONG nSize = 32768; + NTSTATUS nErrCode = STATUS_SUCCESS; + PSYSTEM_PROCESSES pInfoBuffer = NULL; + SIZE_T nSize = 32768; + + /* parameter validation */ + if(!ProcessesAndThreads) + return STATUS_INVALID_PARAMETER_1; /* FIXME: if the system has loaded several processes and threads, the buffer could get really big. But if there's several processes and threads, the @@ -39,19 +56,19 @@ PsaEnumerateProcesses do { void * pTmp; - + /* free the buffer, and reallocate it to the new size. RATIONALE: since we ignore the buffer's contents at this point, there's no point in a realloc() that could end up copying a large chunk of data we'd discard anyway */ - free(pInfoBuffer); - pTmp = malloc(nSize); + PsaiFree(pInfoBuffer); + pTmp = PsaiMalloc(nSize); if(pTmp == NULL) { /* failure */ - DPRINT(FAILED_WITH_STATUS, "malloc", STATUS_NO_MEMORY); + DPRINT(FAILED_WITH_STATUS, "PsaiMalloc", STATUS_NO_MEMORY); nErrCode = STATUS_NO_MEMORY; - goto esp_Finalize; + break; } pInfoBuffer = pTmp; @@ -75,36 +92,281 @@ PsaEnumerateProcesses if(!NT_SUCCESS(nErrCode)) { DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", nErrCode); - goto esp_Finalize; + return nErrCode; } - - /* list head */ - pInfoHead = pInfoBuffer; - /* scan the list */ - while(1) + /* success */ + *ProcessesAndThreads = pInfoBuffer; + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +PsaWalkProcessesAndThreads +( + IN PSYSTEM_PROCESSES ProcessesAndThreads, + IN PPROC_ENUM_ROUTINE ProcessCallback, + IN OUT PVOID ProcessCallbackContext, + IN PTHREAD_ENUM_ROUTINE ThreadCallback, + IN OUT PVOID ThreadCallbackContext +) +{ + register NTSTATUS nErrCode = STATUS_SUCCESS; + + /* parameter validation */ + if(!ProcessCallback && !ThreadCallback) + return STATUS_INVALID_PARAMETER; + + ProcessesAndThreads = PsaWalkFirstProcess(ProcessesAndThreads); + + /* scan the process list */ + do { - /* notify the callback */ - nErrCode = Callback(pInfoHead, CallbackContext); + /* if the caller provided a process callback */ + if(ProcessCallback) + { + /* notify the callback */ + nErrCode = ProcessCallback(ProcessesAndThreads, ProcessCallbackContext); + + /* if the callback returned an error, break out */ + if(!NT_SUCCESS(nErrCode)) + break; + } + + /* if the caller provided a thread callback */ + if(ThreadCallback) + { + ULONG i; + PSYSTEM_THREADS pCurThread; + + /* scan the current process's thread list */ + for + ( + i = 0, pCurThread = PsaWalkFirstThread(ProcessesAndThreads); + i < ProcessesAndThreads->ThreadCount; + ++ i, pCurThread = PsaWalkNextThread(pCurThread) + ) + { + /* notify the callback */ + nErrCode = ThreadCallback(pCurThread, ThreadCallbackContext); + + /* if the callback returned an error, break out */ + if(!NT_SUCCESS(nErrCode)) goto epat_Breakout; + } + } - /* if the callback returned an error or this is the end of the process list, - break out */ - if(!NT_SUCCESS(nErrCode) || pInfoHead->RelativeOffset == 0) - break; - /* move to the next process */ - pInfoHead = - (SYSTEM_PROCESS_INFORMATION*) - ((ULONG)pInfoHead + pInfoHead->RelativeOffset); + ProcessesAndThreads = PsaWalkNextProcess(ProcessesAndThreads); } + /* repeat until the end of the string */ + while(ProcessesAndThreads); -esp_Finalize: +epat_Breakout: + /* return the last status */ + return (nErrCode); +} + +NTSTATUS +NTAPI +PsaEnumerateProcessesAndThreads +( + IN PPROC_ENUM_ROUTINE ProcessCallback, + IN OUT PVOID ProcessCallbackContext, + IN PTHREAD_ENUM_ROUTINE ThreadCallback, + IN OUT PVOID ThreadCallbackContext +) +{ + register NTSTATUS nErrCode; + PSYSTEM_PROCESSES pInfoBuffer; + + /* parameter validation */ + if(!ProcessCallback && !ThreadCallback) + return STATUS_INVALID_PARAMETER; + + /* get the processes and threads list */ + nErrCode = PsaCaptureProcessesAndThreads(&pInfoBuffer); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) + goto epat_Finalize; + + /* walk the processes and threads list */ + nErrCode = PsaWalkProcessesAndThreads + ( + pInfoBuffer, + ProcessCallback, + ProcessCallbackContext, + ThreadCallback, + ThreadCallbackContext + ); + +epat_Finalize: /* free the buffer */ - free(pInfoBuffer); + PsaFreeCapture(pInfoBuffer); /* return the last status */ return (nErrCode); } -/* EOF */ +VOID +NTAPI +PsaFreeCapture +( + IN PVOID Capture +) +{ + PsaiFree(Capture); +} +NTSTATUS +NTAPI +PsaWalkProcesses +( + IN PSYSTEM_PROCESSES ProcessesAndThreads, + IN PPROC_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +) +{ + return PsaWalkProcessesAndThreads + ( + ProcessesAndThreads, + Callback, + CallbackContext, + NULL, + NULL + ); +} + +NTSTATUS +NTAPI +PsaWalkThreads +( + IN PSYSTEM_PROCESSES ProcessesAndThreads, + IN PTHREAD_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +) +{ + return PsaWalkProcessesAndThreads + ( + ProcessesAndThreads, + NULL, + NULL, + Callback, + CallbackContext + ); +} + +NTSTATUS +NTAPI +PsaEnumerateProcesses +( + IN PPROC_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +) +{ + return PsaEnumerateProcessesAndThreads + ( + Callback, + CallbackContext, + NULL, + NULL + ); +} + +NTSTATUS +NTAPI +PsaEnumerateThreads +( + IN PTHREAD_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +) +{ + return PsaEnumerateProcessesAndThreads + ( + NULL, + NULL, + Callback, + CallbackContext + ); +} + +PSYSTEM_PROCESSES +FASTCALL +PsaWalkFirstProcess +( + IN PSYSTEM_PROCESSES ProcessesAndThreads +) +{ + return ProcessesAndThreads; +} + +PSYSTEM_PROCESSES +FASTCALL +PsaWalkNextProcess +( + IN PSYSTEM_PROCESSES CurrentProcess +) +{ + if(CurrentProcess->NextEntryDelta == 0) + return NULL; + else + return + (PSYSTEM_PROCESSES) + ((ULONG_PTR)CurrentProcess + CurrentProcess->NextEntryDelta); +} + +PSYSTEM_THREADS +FASTCALL +PsaWalkFirstThread +( + IN PSYSTEM_PROCESSES CurrentProcess +) +{ + static SIZE_T nOffsetOfThreads = 0; + +#define printoffset(__T__, __F__) fprintf(stderr, "%02X %s->%s\n", offsetof(__T__, __F__), #__T__, #__F__) + + /* get the offset of the Threads field (dependant on the kernel version) */ + if(!nOffsetOfThreads) + { + switch(SharedUserData->NtMajorVersion) + { + /* NT 3 and 4 */ + case 3: + case 4: + { + nOffsetOfThreads = offsetof(SYSTEM_PROCESSES_NT4, Threads); + break; + } + + /* NT 5 and later */ + default: + case 5: + { + nOffsetOfThreads = offsetof(SYSTEM_PROCESSES_NT5, Threads); + break; + } + } + } + + return (PSYSTEM_THREADS)((ULONG_PTR)CurrentProcess + nOffsetOfThreads); +} + +PSYSTEM_THREADS +FASTCALL +PsaWalkNextThread +( + IN PSYSTEM_THREADS CurrentThread +) +{ + return (PSYSTEM_THREADS) + ( + (ULONG_PTR)CurrentThread + + ( + offsetof(SYSTEM_PROCESSES, Threads[1]) - + offsetof(SYSTEM_PROCESSES, Threads[0]) + ) + ); +} + +/* EOF */ diff --git a/reactos/lib/psapi/include/internal/psapi.h b/reactos/lib/psapi/include/internal/psapi.h index c8ba3a29c74..f6fddedc9ba 100644 --- a/reactos/lib/psapi/include/internal/psapi.h +++ b/reactos/lib/psapi/include/internal/psapi.h @@ -1,4 +1,4 @@ -/* $Id: psapi.h,v 1.3 2002/08/31 15:36:55 hyperion Exp $ +/* $Id: psapi.h,v 1.4 2003/04/02 22:09:56 hyperion Exp $ */ /* * internal/psapi.h @@ -32,20 +32,26 @@ /* OBJECTS */ /* TYPES */ -typedef NTSTATUS STDCALL (*PPROC_ENUM_ROUTINE) +typedef NTSTATUS NTAPI (*PPROC_ENUM_ROUTINE) ( - IN PSYSTEM_PROCESS_INFORMATION CurrentProcess, + IN PSYSTEM_PROCESSES CurrentProcess, IN OUT PVOID CallbackContext ); -typedef NTSTATUS STDCALL (*PSYSMOD_ENUM_ROUTINE) +typedef NTSTATUS NTAPI (*PTHREAD_ENUM_ROUTINE) +( + IN PSYSTEM_THREADS CurrentThread, + IN OUT PVOID CallbackContext +); + +typedef NTSTATUS NTAPI (*PSYSMOD_ENUM_ROUTINE) ( IN ULONG ModuleCount, IN PSYSTEM_MODULE_ENTRY CurrentModule, IN OUT PVOID CallbackContext ); -typedef NTSTATUS STDCALL (*PPROCMOD_ENUM_ROUTINE) +typedef NTSTATUS NTAPI (*PPROCMOD_ENUM_ROUTINE) ( IN HANDLE ProcessHandle, IN PLDR_MODULE CurrentModule, @@ -57,7 +63,88 @@ typedef NTSTATUS STDCALL (*PPROCMOD_ENUM_ROUTINE) /* PROTOTYPES */ NTSTATUS -STDCALL +NTAPI +PsaCaptureProcessesAndThreads +( + OUT PSYSTEM_PROCESSES * ProcessesAndThreads +); + +NTSTATUS +NTAPI +PsaWalkProcessesAndThreads +( + IN PSYSTEM_PROCESSES ProcessesAndThreads, + IN PPROC_ENUM_ROUTINE ProcessCallback, + IN OUT PVOID ProcessCallbackContext, + IN PTHREAD_ENUM_ROUTINE ThreadCallback, + IN OUT PVOID ThreadCallbackContext +); + +NTSTATUS +NTAPI +PsaEnumerateProcessesAndThreads +( + IN PPROC_ENUM_ROUTINE ProcessCallback, + IN OUT PVOID ProcessCallbackContext, + IN PTHREAD_ENUM_ROUTINE ThreadCallback, + IN OUT PVOID ThreadCallbackContext +); + +VOID +NTAPI +PsaFreeCapture +( + IN PVOID Capture +); + +PSYSTEM_PROCESSES +FASTCALL +PsaWalkFirstProcess +( + IN PSYSTEM_PROCESSES ProcessesAndThreads +); + +PSYSTEM_PROCESSES +FASTCALL +PsaWalkNextProcess +( + IN PSYSTEM_PROCESSES CurrentProcess +); + +PSYSTEM_THREADS +FASTCALL +PsaWalkFirstThread +( + IN PSYSTEM_PROCESSES CurrentProcess +); + +PSYSTEM_THREADS +FASTCALL +PsaWalkNextThread +( + IN PSYSTEM_THREADS CurrentThread +); + +NTSTATUS +NTAPI +PsaWalkProcesses +( + IN PSYSTEM_PROCESSES ProcessesAndThreads, + IN PPROC_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +); + +NTSTATUS +NTAPI +PsaWalkThreads +( + IN PSYSTEM_PROCESSES ProcessesAndThreads, + IN PTHREAD_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +); + +NTSTATUS +NTAPI PsaEnumerateProcesses ( IN PPROC_ENUM_ROUTINE Callback, @@ -65,7 +152,15 @@ PsaEnumerateProcesses ); NTSTATUS -STDCALL +NTAPI +PsaEnumerateThreads +( + IN PTHREAD_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +); + +NTSTATUS +NTAPI PsaEnumerateSystemModules ( IN PSYSMOD_ENUM_ROUTINE Callback, @@ -73,7 +168,7 @@ PsaEnumerateSystemModules ); NTSTATUS -STDCALL +NTAPI PsaEnumerateProcessModules ( IN HANDLE ProcessHandle, @@ -81,6 +176,12 @@ PsaEnumerateProcessModules IN OUT PVOID CallbackContext ); +/* The user must define these functions. They are called by PSAPI to allocate + memory. This allows PSAPI to be called from any environment */ +void *PsaiMalloc(SIZE_T size); +void *PsaiRealloc(void *ptr, SIZE_T size); +void PsaiFree(void *ptr); + /* MACROS */ #define DEFINE_DBG_MSG(__str__) "PSAPI: " __str__ "\n" diff --git a/reactos/lib/psapi/makefile b/reactos/lib/psapi/makefile index 7094e85498e..e54255bdf6e 100644 --- a/reactos/lib/psapi/makefile +++ b/reactos/lib/psapi/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.3 2002/08/31 15:36:56 hyperion Exp $ +# $Id: makefile,v 1.4 2003/04/02 22:09:57 hyperion Exp $ PATH_TO_TOP = ../.. @@ -10,6 +10,8 @@ TARGET_SDKLIBS = ntdll.a kernel32.a TARGET_CFLAGS = -I./include -Wall +TARGET_LFLAGS = -nostartfiles -nostdlib + TARGET_BASE = 0x68F70000 TARGET_OBJECTS = \ diff --git a/reactos/lib/psapi/misc/malloc.c b/reactos/lib/psapi/misc/malloc.c index 1dc90152128..41fb6d4886e 100644 --- a/reactos/lib/psapi/misc/malloc.c +++ b/reactos/lib/psapi/misc/malloc.c @@ -1,4 +1,4 @@ -/* $Id: malloc.c,v 1.3 2002/08/31 17:11:24 hyperion Exp $ +/* $Id: malloc.c,v 1.4 2003/04/02 22:09:57 hyperion Exp $ */ /* * COPYRIGHT: None @@ -9,6 +9,8 @@ * PROGRAMMER: KJK::Hyperion * UPDATE HISTORY: * 10/06/2002: Created + * 12/02/2003: malloc and free renamed to PsaiMalloc and PsaiFree, + * for better reusability */ #include @@ -46,17 +48,17 @@ PVOID STDCALL MemAlloc return pBuf; } -void *malloc(size_t size) +void *PsaiMalloc(SIZE_T size) { return MemAlloc(NULL, NULL, size); } -void *realloc(void *ptr, size_t size) +void *PsaiRealloc(void *ptr, SIZE_T size) { return MemAlloc(NULL, ptr, size); } -void free(void *ptr) +void PsaiFree(void *ptr) { MemAlloc(NULL, ptr, 0); } diff --git a/reactos/lib/psapi/misc/win32.c b/reactos/lib/psapi/misc/win32.c index 9766780ddce..95ee46f628e 100644 --- a/reactos/lib/psapi/misc/win32.c +++ b/reactos/lib/psapi/misc/win32.c @@ -1,4 +1,4 @@ -/* $Id: win32.c,v 1.5 2003/02/02 19:26:08 hyperion Exp $ +/* $Id: win32.c,v 1.6 2003/04/02 22:09:57 hyperion Exp $ */ /* * COPYRIGHT: See COPYING in the top level directory @@ -143,7 +143,7 @@ typedef struct _ENUM_PROCESSES_CONTEXT /* callback routine */ NTSTATUS STDCALL EnumProcessesCallback ( - IN PSYSTEM_PROCESS_INFORMATION CurrentProcess, + IN PSYSTEM_PROCESSES CurrentProcess, IN OUT PVOID CallbackContext ) { @@ -165,7 +165,7 @@ NTSTATUS STDCALL EnumProcessesCallback } /* exported interface */ -/* +/*! @brief Enumerate the process identifiers of the currently active processes @param lpidProcess Array that receives the list of process identifiers @@ -194,7 +194,11 @@ BOOL STDCALL EnumProcesses } /* enumerate the process ids */ - nErrCode = PsaEnumerateProcesses(&EnumProcessesCallback, &epcContext); + nErrCode = PsaEnumerateProcesses + ( + &EnumProcessesCallback, + &epcContext + ); *lpcbNeeded = (cb - epcContext.nCount) * sizeof(DWORD); @@ -492,7 +496,7 @@ DWORD FASTCALL internalGetMappedFileName( nBufSize = nSize * sizeof(WCHAR); /* allocate the memory */ - pmsnName = malloc(nBufSize + offsetof(MEMORY_SECTION_NAME, NameBuffer)); + pmsnName = PsaiMalloc(nBufSize + offsetof(MEMORY_SECTION_NAME, NameBuffer)); if(pmsnName == NULL) { @@ -527,7 +531,7 @@ DWORD FASTCALL internalGetMappedFileName( #if 0 #else /* free the buffer */ - free(pmsnName); + PsaiFree(pmsnName); #endif return 0; } @@ -546,7 +550,7 @@ DWORD FASTCALL internalGetMappedFileName( #if 0 #else /* free the buffer */ - free(pmsnName); + PsaiFree(pmsnName); #endif if(pmsnName->SectionFileName.Length < nSize) @@ -572,7 +576,7 @@ DWORD FASTCALL internalGetMappedFileName( #if 0 #else /* free the buffer */ - free(pmsnName); + PsaiFree(pmsnName); #endif if(strAnsi.Length < nSize) @@ -589,7 +593,7 @@ DWORD FASTCALL internalGetMappedFileName( } __finally { - free(pmsnName); + PsaiFree(pmsnName); } #endif } @@ -715,7 +719,7 @@ NTSTATUS STDCALL GetModuleInformationCallback UNICODE_STRING wstrUnicodeBuf; /* allocate the local buffer */ - pwcUnicodeBuf = malloc(pwstrSource->Length); + pwcUnicodeBuf = PsaiMalloc(pwstrSource->Length); #if 0 __try @@ -767,7 +771,7 @@ NTSTATUS STDCALL GetModuleInformationCallback __finally { /* free the buffer */ - free(pwcUnicodeBuf); + PsaiFree(pwcUnicodeBuf); } #else /* success */ @@ -775,7 +779,7 @@ NTSTATUS STDCALL GetModuleInformationCallback exitWithStatus: /* free the buffer */ - free(pwcUnicodeBuf); + PsaiFree(pwcUnicodeBuf); return nErrCode; #endif }