Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenprocesses.c
Go to the documentation of this file.
00001 /* $Id: processes.c 52985 2011-07-28 16:21:48Z akhaldi $ 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/epsapi/enum/processes.c 00008 * PURPOSE: Enumerate processes and threads 00009 * PROGRAMMER: KJK::Hyperion <noog@libero.it> 00010 * UPDATE HISTORY: 00011 * 10/06/2002: Created 00012 * 29/08/2002: Generalized the interface to improve reusability, 00013 * more efficient use of memory operations 00014 * 12/02/2003: malloc and free renamed to PsaiMalloc and PsaiFree, 00015 * for better reusability. PsaEnumerateProcesses now 00016 * expanded into: 00017 * - PsaCaptureProcessesAndThreads 00018 * - PsaFreeCapture 00019 * - PsaWalkProcessesAndThreads 00020 * - PsaWalkProcesses 00021 * - PsaWalkThreads 00022 * - PsaWalkFirstProcess 00023 * - PsaWalkNextProcess 00024 * - PsaWalkFirstThread 00025 * - PsaWalkNextThread 00026 * - PsaEnumerateProcessesAndThreads 00027 * - PsaEnumerateProcesses 00028 * - PsaEnumerateThreads 00029 * 12/04/2003: internal PSAPI renamed EPSAPI (Extended PSAPI) and 00030 * isolated in its own library to clear the confusion 00031 * and improve reusability 00032 */ 00033 00034 #include "precomp.h" 00035 00036 #define NDEBUG 00037 #include <debug.h> 00038 00039 NTSTATUS NTAPI 00040 PsaCaptureProcessesAndThreads(OUT PSYSTEM_PROCESS_INFORMATION *ProcessesAndThreads) 00041 { 00042 PSYSTEM_PROCESS_INFORMATION pInfoBuffer = NULL; 00043 SIZE_T nSize = 0x8000; 00044 NTSTATUS Status; 00045 00046 if(ProcessesAndThreads == NULL) 00047 { 00048 return STATUS_INVALID_PARAMETER_1; 00049 } 00050 00051 /* FIXME: if the system has loaded several processes and threads, the buffer 00052 could get really big. But if there's several processes and threads, the 00053 system is already under stress, and a huge buffer could only make things 00054 worse. The function should be profiled to see what's the average minimum 00055 buffer size, to succeed on the first shot */ 00056 do 00057 { 00058 PVOID pTmp; 00059 00060 /* free the buffer, and reallocate it to the new size. RATIONALE: since we 00061 ignore the buffer's contents at this point, there's no point in a realloc() 00062 that could end up copying a large chunk of data we'd discard anyway */ 00063 PsaiFree(pInfoBuffer); 00064 pTmp = PsaiMalloc(nSize); 00065 00066 if(pTmp == NULL) 00067 { 00068 DPRINT(FAILED_WITH_STATUS, "PsaiMalloc", STATUS_NO_MEMORY); 00069 Status = STATUS_NO_MEMORY; 00070 break; 00071 } 00072 00073 pInfoBuffer = pTmp; 00074 00075 /* query the information */ 00076 Status = NtQuerySystemInformation(SystemProcessInformation, 00077 pInfoBuffer, 00078 nSize, 00079 NULL); 00080 00081 /* double the buffer size */ 00082 nSize *= 2; 00083 } while(Status == STATUS_INFO_LENGTH_MISMATCH); 00084 00085 if(!NT_SUCCESS(Status)) 00086 { 00087 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", Status); 00088 return Status; 00089 } 00090 00091 *ProcessesAndThreads = pInfoBuffer; 00092 return STATUS_SUCCESS; 00093 } 00094 00095 NTSTATUS NTAPI 00096 PsaWalkProcessesAndThreads(IN PSYSTEM_PROCESS_INFORMATION ProcessesAndThreads, 00097 IN PPROC_ENUM_ROUTINE ProcessCallback, 00098 IN OUT PVOID ProcessCallbackContext, 00099 IN PTHREAD_ENUM_ROUTINE ThreadCallback, 00100 IN OUT PVOID ThreadCallbackContext) 00101 { 00102 NTSTATUS Status; 00103 00104 if(ProcessCallback == NULL && ThreadCallback == NULL) 00105 { 00106 return STATUS_INVALID_PARAMETER; 00107 } 00108 00109 Status = STATUS_SUCCESS; 00110 00111 ProcessesAndThreads = PsaWalkFirstProcess(ProcessesAndThreads); 00112 00113 /* scan the process list */ 00114 do 00115 { 00116 if(ProcessCallback) 00117 { 00118 Status = ProcessCallback(ProcessesAndThreads, ProcessCallbackContext); 00119 00120 if(!NT_SUCCESS(Status)) 00121 { 00122 break; 00123 } 00124 } 00125 00126 /* if the caller provided a thread callback */ 00127 if(ThreadCallback) 00128 { 00129 ULONG i; 00130 PSYSTEM_THREAD_INFORMATION pCurThread; 00131 00132 /* scan the current process's thread list */ 00133 for(i = 0, pCurThread = PsaWalkFirstThread(ProcessesAndThreads); 00134 i < ProcessesAndThreads->NumberOfThreads; 00135 i++, pCurThread = PsaWalkNextThread(pCurThread)) 00136 { 00137 Status = ThreadCallback(pCurThread, ThreadCallbackContext); 00138 00139 if(!NT_SUCCESS(Status)) 00140 { 00141 goto Bail; 00142 } 00143 } 00144 } 00145 00146 /* move to the next process */ 00147 ProcessesAndThreads = PsaWalkNextProcess(ProcessesAndThreads); 00148 } while(ProcessesAndThreads); 00149 00150 Bail: 00151 return Status; 00152 } 00153 00154 NTSTATUS NTAPI 00155 PsaEnumerateProcessesAndThreads(IN PPROC_ENUM_ROUTINE ProcessCallback, 00156 IN OUT PVOID ProcessCallbackContext, 00157 IN PTHREAD_ENUM_ROUTINE ThreadCallback, 00158 IN OUT PVOID ThreadCallbackContext) 00159 { 00160 PSYSTEM_PROCESS_INFORMATION pInfoBuffer = NULL; 00161 NTSTATUS Status; 00162 00163 if(ProcessCallback == NULL && ThreadCallback == NULL) 00164 { 00165 return STATUS_INVALID_PARAMETER; 00166 } 00167 00168 /* get the processes and threads list */ 00169 Status = PsaCaptureProcessesAndThreads(&pInfoBuffer); 00170 00171 if(!NT_SUCCESS(Status)) 00172 { 00173 goto Bail; 00174 } 00175 00176 /* walk the processes and threads list */ 00177 Status = PsaWalkProcessesAndThreads(pInfoBuffer, 00178 ProcessCallback, 00179 ProcessCallbackContext, 00180 ThreadCallback, 00181 ThreadCallbackContext); 00182 00183 Bail: 00184 PsaFreeCapture(pInfoBuffer); 00185 00186 return Status; 00187 } 00188 00189 VOID NTAPI 00190 PsaFreeCapture(IN PVOID Capture) 00191 { 00192 PsaiFree(Capture); 00193 } 00194 00195 NTSTATUS NTAPI 00196 PsaWalkProcesses(IN PSYSTEM_PROCESS_INFORMATION ProcessesAndThreads, 00197 IN PPROC_ENUM_ROUTINE Callback, 00198 IN OUT PVOID CallbackContext) 00199 { 00200 return PsaWalkProcessesAndThreads(ProcessesAndThreads, 00201 Callback, 00202 CallbackContext, 00203 NULL, 00204 NULL); 00205 } 00206 00207 NTSTATUS NTAPI 00208 PsaWalkThreads(IN PSYSTEM_PROCESS_INFORMATION ProcessesAndThreads, 00209 IN PTHREAD_ENUM_ROUTINE Callback, 00210 IN OUT PVOID CallbackContext) 00211 { 00212 return PsaWalkProcessesAndThreads(ProcessesAndThreads, 00213 NULL, 00214 NULL, 00215 Callback, 00216 CallbackContext); 00217 } 00218 00219 NTSTATUS NTAPI 00220 PsaEnumerateProcesses(IN PPROC_ENUM_ROUTINE Callback, 00221 IN OUT PVOID CallbackContext) 00222 { 00223 return PsaEnumerateProcessesAndThreads(Callback, 00224 CallbackContext, 00225 NULL, 00226 NULL); 00227 } 00228 00229 NTSTATUS NTAPI 00230 PsaEnumerateThreads(IN PTHREAD_ENUM_ROUTINE Callback, 00231 IN OUT PVOID CallbackContext) 00232 { 00233 return PsaEnumerateProcessesAndThreads(NULL, 00234 NULL, 00235 Callback, 00236 CallbackContext); 00237 } 00238 00239 PSYSTEM_PROCESS_INFORMATION FASTCALL 00240 PsaWalkFirstProcess(IN PSYSTEM_PROCESS_INFORMATION ProcessesAndThreads) 00241 { 00242 return ProcessesAndThreads; 00243 } 00244 00245 PSYSTEM_PROCESS_INFORMATION FASTCALL 00246 PsaWalkNextProcess(IN PSYSTEM_PROCESS_INFORMATION CurrentProcess) 00247 { 00248 if(CurrentProcess->NextEntryOffset == 0) 00249 { 00250 return NULL; 00251 } 00252 else 00253 { 00254 return (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)CurrentProcess + CurrentProcess->NextEntryOffset); 00255 } 00256 } 00257 00258 PSYSTEM_THREAD_INFORMATION FASTCALL 00259 PsaWalkFirstThread(IN PSYSTEM_PROCESS_INFORMATION CurrentProcess) 00260 { 00261 static SIZE_T nOffsetOfThreads = 0; 00262 00263 /* get the offset of the Threads field */ 00264 nOffsetOfThreads = sizeof(SYSTEM_PROCESS_INFORMATION); 00265 00266 return (PSYSTEM_THREAD_INFORMATION)((ULONG_PTR)CurrentProcess + nOffsetOfThreads); 00267 } 00268 00269 PSYSTEM_THREAD_INFORMATION FASTCALL 00270 PsaWalkNextThread(IN PSYSTEM_THREAD_INFORMATION CurrentThread) 00271 { 00272 return (PSYSTEM_THREAD_INFORMATION)((ULONG_PTR)CurrentThread + 00273 ((sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION)) - 00274 sizeof(SYSTEM_PROCESS_INFORMATION))); 00275 } 00276 00277 /* EOF */ Generated on Sat May 19 2012 04:34:07 for ReactOS by
1.7.6.1
|