Berend Reitsma <berend at asset-control.com>
[wine.git] / misc / toolhelp.c
blob10fb40877e55c4f9e2d58ae7d4ec8905c34b8801
1 /*
2 * Misc Toolhelp functions
4 * Copyright 1996 Marcus Meissner
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <ctype.h>
11 #include <assert.h>
12 #include "windows.h"
13 #include "win.h"
14 #include "winerror.h"
15 #include "process.h"
16 #include "tlhelp32.h"
17 #include "toolhelp.h"
18 #include "heap.h"
19 #include "k32obj.h"
20 #include "debug.h"
23 * Support for toolhelp's snapshots. They
24 * are supposed to be Kernel32 Objects.
25 * Only the Destroy() method is implemented
28 static void SNAPSHOT_Destroy( K32OBJ *obj );
30 const K32OBJ_OPS SNAPSHOT_Ops =
32 SNAPSHOT_Destroy /* destroy */
35 /* The K32 snapshot object object */
36 /* Process snapshot kernel32 object */
37 typedef struct _Process32Snapshot
39 K32OBJ header;
41 DWORD numProcs;
42 DWORD arrayCounter;
44 * Store a reference to the PDB list.
45 * Insuure in the alloc and dealloc routines for this structure that
46 * I increment and decrement the pdb->head.refcount, so that the
47 * original pdb will stay around for as long as I use it, but it's
48 * not locked forver into memory.
50 PDB32 **processArray;
52 SNAPSHOT_OBJECT;
54 /* FIXME: to make this working, we have to callback all these registered
55 * functions from all over the WINE code. Someone with more knowledge than
56 * me please do that. -Marcus
58 static struct notify
60 HTASK16 htask;
61 FARPROC16 lpfnCallback;
62 WORD wFlags;
63 } *notifys = NULL;
65 static int nrofnotifys = 0;
67 static FARPROC16 HookNotify = NULL;
69 BOOL16 WINAPI NotifyRegister( HTASK16 htask, FARPROC16 lpfnCallback,
70 WORD wFlags )
72 int i;
74 TRACE(toolhelp, "(%x,%lx,%x) called.\n",
75 htask, (DWORD)lpfnCallback, wFlags );
76 if (!htask) htask = GetCurrentTask();
77 for (i=0;i<nrofnotifys;i++)
78 if (notifys[i].htask==htask)
79 break;
80 if (i==nrofnotifys) {
81 if (notifys==NULL)
82 notifys=(struct notify*)HeapAlloc( SystemHeap, 0,
83 sizeof(struct notify) );
84 else
85 notifys=(struct notify*)HeapReAlloc( SystemHeap, 0, notifys,
86 sizeof(struct notify)*(nrofnotifys+1));
87 if (!notifys) return FALSE;
88 nrofnotifys++;
90 notifys[i].htask=htask;
91 notifys[i].lpfnCallback=lpfnCallback;
92 notifys[i].wFlags=wFlags;
93 return TRUE;
96 BOOL16 WINAPI NotifyUnregister( HTASK16 htask )
98 int i;
100 TRACE(toolhelp, "(%x) called.\n", htask );
101 if (!htask) htask = GetCurrentTask();
102 for (i=nrofnotifys;i--;)
103 if (notifys[i].htask==htask)
104 break;
105 if (i==-1)
106 return FALSE;
107 memcpy(notifys+i,notifys+(i+1),sizeof(struct notify)*(nrofnotifys-i-1));
108 notifys=(struct notify*)HeapReAlloc( SystemHeap, 0, notifys,
109 (nrofnotifys-1)*sizeof(struct notify));
110 nrofnotifys--;
111 return TRUE;
114 BOOL16 WINAPI StackTraceCSIPFirst(STACKTRACEENTRY *ste, WORD wSS, WORD wCS, WORD wIP, WORD wBP)
116 return TRUE;
119 BOOL16 WINAPI StackTraceFirst(STACKTRACEENTRY *ste, HTASK16 Task)
121 return TRUE;
124 BOOL16 WINAPI StackTraceNext(STACKTRACEENTRY *ste)
126 return TRUE;
129 /***********************************************************************
130 * ToolHelpHook (KERNEL.341)
131 * see "Undocumented Windows"
133 FARPROC16 WINAPI ToolHelpHook(FARPROC16 lpfnNotifyHandler)
135 FARPROC16 tmp;
136 tmp = HookNotify;
137 HookNotify = lpfnNotifyHandler;
138 /* just return previously installed notification function */
139 return tmp;
142 /***********************************************************************
143 * SNAPSHOT_Destroy
145 * Deallocate K32 snapshot objects
147 static void SNAPSHOT_Destroy (K32OBJ *obj)
149 int i;
150 SNAPSHOT_OBJECT *snapshot = (SNAPSHOT_OBJECT *) obj;
151 assert (obj->type == K32OBJ_CHANGE);
153 if (snapshot->processArray)
155 for (i = 0; snapshot->processArray[i] && i <snapshot->numProcs; i++)
157 K32OBJ_DecCount (&snapshot->processArray[i]->header);
159 HeapFree (GetProcessHeap (), 0, snapshot->processArray);
160 snapshot->processArray = NULL;
163 obj->type = K32OBJ_UNKNOWN;
164 HeapFree (GetProcessHeap (), 0, snapshot);
167 /***********************************************************************
168 * CreateToolHelp32Snapshot (KERNEL32.179)
169 * see "Undocumented Windows"
171 HANDLE32 WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD
172 th32ProcessID)
174 HANDLE32 ssHandle;
175 SNAPSHOT_OBJECT *snapshot;
176 int numProcesses;
177 int i;
178 PDB32* pdb;
180 TRACE(toolhelp, "%lx & TH32CS_INHERIT (%x) = %lx %s\n", dwFlags,
181 TH32CS_INHERIT,
182 dwFlags & TH32CS_INHERIT,
183 dwFlags & TH32CS_INHERIT ? "TRUE" : "FALSE");
184 TRACE(toolhelp, "%lx & TH32CS_SNAPHEAPLIST (%x) = %lx %s\n", dwFlags,
185 TH32CS_SNAPHEAPLIST,
186 dwFlags & TH32CS_SNAPHEAPLIST,
187 dwFlags & TH32CS_SNAPHEAPLIST ? "TRUE" : "FALSE");
188 TRACE(toolhelp, "%lx & TH32CS_SNAPMODULE (%x) = %lx %s\n", dwFlags,
189 TH32CS_SNAPMODULE,
190 dwFlags & TH32CS_SNAPMODULE,
191 dwFlags & TH32CS_SNAPMODULE ? "TRUE" : "FALSE");
192 TRACE(toolhelp, "%lx & TH32CS_SNAPPROCESS (%x) = %lx %s\n", dwFlags,
193 TH32CS_SNAPPROCESS,
194 dwFlags & TH32CS_SNAPPROCESS,
195 dwFlags & TH32CS_SNAPPROCESS ? "TRUE" : "FALSE");
196 TRACE(toolhelp, "%lx & TH32CS_SNAPTHREAD (%x) = %lx %s\n", dwFlags,
197 TH32CS_SNAPTHREAD,
198 dwFlags & TH32CS_SNAPTHREAD,
199 dwFlags & TH32CS_SNAPTHREAD ? "TRUE" : "FALSE");
201 /**** FIXME: Not implmented ***/
202 if (dwFlags & TH32CS_INHERIT)
204 FIXME(toolhelp,"(0x%08lx (TH32CS_INHERIT),0x%08lx), stub!\n",
205 dwFlags,th32ProcessID);
207 return INVALID_HANDLE_VALUE32;
209 if (dwFlags & TH32CS_SNAPHEAPLIST)
211 FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPHEAPLIST),0x%08lx), stub!\n",
212 dwFlags,th32ProcessID);
213 return INVALID_HANDLE_VALUE32;
215 if (dwFlags & TH32CS_SNAPMODULE)
217 FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPMODULE),0x%08lx), stub!\n",
218 dwFlags,th32ProcessID);
219 return INVALID_HANDLE_VALUE32;
222 if (dwFlags & TH32CS_SNAPPROCESS)
224 TRACE (toolhelp, "(0x%08lx (TH32CS_SNAPMODULE),0x%08lx)\n",
225 dwFlags,th32ProcessID);
226 snapshot = HeapAlloc (GetProcessHeap (), 0, sizeof
227 (SNAPSHOT_OBJECT));
228 if (!snapshot)
230 return INVALID_HANDLE_VALUE32;
233 snapshot->header.type = K32OBJ_TOOLHELP_SNAPSHOT;
234 snapshot->header.refcount = 1;
235 snapshot->arrayCounter = 0;
238 * Lock here, to prevent processes from being created or
239 * destroyed while the snapshot is gathered
242 SYSTEM_LOCK ();
243 numProcesses = PROCESS_PDBList_Getsize ();
245 snapshot->processArray = (PDB32**)
246 HeapAlloc (GetProcessHeap (), 0, sizeof (PDB32*) * numProcesses);
248 if (!snapshot->processArray)
250 HeapFree (GetProcessHeap (), 0, snapshot->processArray);
251 SetLastError (INVALID_HANDLE_VALUE32);
252 ERR (toolhelp, "Error allocating %d bytes for snapshot\n",
253 sizeof (PDB32*) * numProcesses);
254 return INVALID_HANDLE_VALUE32;
257 snapshot->numProcs = numProcesses;
259 pdb = PROCESS_PDBList_Getfirst ();
260 for (i = 0; pdb && i < numProcesses; i++)
262 TRACE (toolhelp, "Saving ref to pdb %ld\n", PDB_TO_PROCESS_ID(pdb));
263 snapshot->processArray[i] = pdb;
264 K32OBJ_IncCount (&pdb->header);
265 pdb = PROCESS_PDBList_Getnext (pdb);
267 SYSTEM_UNLOCK ();
269 ssHandle = HANDLE_Alloc (PROCESS_Current (), &snapshot->header,
270 FILE_ALL_ACCESS, TRUE, -1);
271 if (ssHandle == INVALID_HANDLE_VALUE32)
273 /* HANDLE_Alloc is supposed to deallocate the
274 * heap memory if it fails. This code doesn't need to.
276 SetLastError (INVALID_HANDLE_VALUE32);
277 ERR (toolhelp, "Error allocating handle\n");
278 return INVALID_HANDLE_VALUE32;
281 TRACE (toolhelp, "snapshotted %d processes, expected %d\n",
282 i, numProcesses);
283 return ssHandle;
286 if (dwFlags & TH32CS_SNAPTHREAD)
288 FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPMODULE),0x%08lx), stub!\n",
289 dwFlags,th32ProcessID);
290 return INVALID_HANDLE_VALUE32;
293 return INVALID_HANDLE_VALUE32;
296 /***********************************************************************
297 * Process32First
298 * Return info about the first process in a toolhelp32 snapshot
300 BOOL32 WINAPI Process32First(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe)
302 PDB32 *pdb;
303 SNAPSHOT_OBJECT *snapshot;
304 int i;
306 TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot,
307 (DWORD) lppe);
309 if (lppe->dwSize < sizeof (PROCESSENTRY32))
311 SetLastError (ERROR_INSUFFICIENT_BUFFER);
312 ERR (toolhelp, "Result buffer too small\n");
313 return FALSE;
316 SYSTEM_LOCK ();
317 snapshot = (SNAPSHOT_OBJECT*) HANDLE_GetObjPtr (PROCESS_Current (),
318 hSnapshot,
319 K32OBJ_UNKNOWN,
320 FILE_ALL_ACCESS,
321 NULL);
322 if (!snapshot)
324 SYSTEM_UNLOCK ();
325 SetLastError (ERROR_INVALID_HANDLE);
326 ERR (toolhelp, "Error retreiving snapshot\n");
327 return FALSE;
330 snapshot->arrayCounter = i = 0;
331 pdb = snapshot->processArray[i];
333 if (!pdb)
335 SetLastError (ERROR_NO_MORE_FILES);
336 ERR (toolhelp, "End of snapshot array\n");
337 return FALSE;
340 TRACE (toolhelp, "Returning info on process %d, id %ld\n",
341 i, PDB_TO_PROCESS_ID (pdb));
343 lppe->cntUsage = 1;
344 lppe->th32ProcessID = PDB_TO_PROCESS_ID (pdb);
345 lppe->th32DefaultHeapID = (DWORD) pdb->heap;
346 lppe->cntThreads = pdb->threads;
347 lppe->th32ParentProcessID = PDB_TO_PROCESS_ID (pdb->parent);
348 lppe->pcPriClassBase = 6; /* FIXME: this is a made-up value */
349 lppe->dwFlags = -1; /* FIXME: RESERVED by Microsoft :-) */
350 if (pdb->exe_modref)
352 lppe->th32ModuleID = (DWORD) pdb->exe_modref->module;
353 strncpy (lppe->szExeFile, pdb->exe_modref->longname,
354 sizeof (lppe->szExeFile));
356 else
358 lppe->th32ModuleID = (DWORD) 0;
359 strcpy (lppe->szExeFile, "");
362 SYSTEM_UNLOCK ();
364 return TRUE;
367 /***********************************************************************
368 * Process32Next
369 * Return info about the "next" process in a toolhelp32 snapshot
371 BOOL32 WINAPI Process32Next(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe)
373 PDB32 *pdb;
374 SNAPSHOT_OBJECT *snapshot;
375 int i;
377 TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot,
378 (DWORD) lppe);
380 if (lppe->dwSize < sizeof (PROCESSENTRY32))
382 SetLastError (ERROR_INSUFFICIENT_BUFFER);
383 ERR (toolhelp, "Result buffer too small\n");
384 return FALSE;
387 SYSTEM_LOCK ();
388 snapshot = (SNAPSHOT_OBJECT*) HANDLE_GetObjPtr (PROCESS_Current (),
389 hSnapshot,
390 K32OBJ_UNKNOWN,
391 FILE_ALL_ACCESS,
392 NULL);
393 if (!snapshot)
395 SYSTEM_UNLOCK ();
396 SetLastError (ERROR_INVALID_HANDLE);
397 ERR (toolhelp, "Error retreiving snapshot\n");
398 return FALSE;
401 snapshot->arrayCounter ++;
402 i = snapshot->arrayCounter;
403 pdb = snapshot->processArray[i];
405 if (!pdb || snapshot->arrayCounter >= snapshot->numProcs)
407 SetLastError (ERROR_NO_MORE_FILES);
408 ERR (toolhelp, "End of snapshot array\n");
409 return FALSE;
412 TRACE (toolhelp, "Returning info on process %d, id %ld\n",
413 i, PDB_TO_PROCESS_ID (pdb));
415 lppe->cntUsage = 1;
416 lppe->th32ProcessID = PDB_TO_PROCESS_ID (pdb);
417 lppe->th32DefaultHeapID = (DWORD) pdb->heap;
418 lppe->cntThreads = pdb->threads;
419 lppe->th32ParentProcessID = PDB_TO_PROCESS_ID (pdb->parent);
420 lppe->pcPriClassBase = 6; /* FIXME: this is a made-up value */
421 lppe->dwFlags = -1; /* FIXME: RESERVED by Microsoft :-) */
422 if (pdb->exe_modref)
424 lppe->th32ModuleID = (DWORD) pdb->exe_modref->module;
425 strncpy (lppe->szExeFile, pdb->exe_modref->longname,
426 sizeof (lppe->szExeFile));
428 else
430 lppe->th32ModuleID = (DWORD) 0;
431 strcpy (lppe->szExeFile, "");
434 SYSTEM_UNLOCK ();
436 return TRUE;