IPaddress common control implementation. First try; needs more work to
[wine/multimedia.git] / misc / toolhelp.c
blobf69039c45a92fa33a67c72814999a9c59406cb38
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 "tlhelp32.h"
16 #include "toolhelp.h"
17 #include "debug.h"
18 #include "heap.h"
19 #include "process.h"
20 #include "k32obj.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 NULL, /* signaled */
33 NULL, /* satisfied */
34 NULL, /* add_wait */
35 NULL, /* remove_wait */
36 NULL, /* read */
37 NULL, /* write */
38 SNAPSHOT_Destroy /* destroy */
41 /* The K32 snapshot object object */
42 /* Process snapshot kernel32 object */
43 typedef struct _Process32Snapshot
45 K32OBJ header;
47 DWORD numProcs;
48 DWORD arrayCounter;
50 * Store a reference to the PDB list.
51 * Insuure in the alloc and dealloc routines for this structure that
52 * I increment and decrement the pdb->head.refcount, so that the
53 * original pdb will stay around for as long as I use it, but it's
54 * not locked forver into memory.
56 PDB32 **processArray;
58 SNAPSHOT_OBJECT;
60 /* FIXME: to make this working, we have to callback all these registered
61 * functions from all over the WINE code. Someone with more knowledge than
62 * me please do that. -Marcus
64 static struct notify
66 HTASK16 htask;
67 FARPROC16 lpfnCallback;
68 WORD wFlags;
69 } *notifys = NULL;
71 static int nrofnotifys = 0;
73 static FARPROC16 HookNotify = NULL;
75 BOOL16 WINAPI NotifyRegister( HTASK16 htask, FARPROC16 lpfnCallback,
76 WORD wFlags )
78 int i;
80 TRACE(toolhelp, "(%x,%lx,%x) called.\n",
81 htask, (DWORD)lpfnCallback, wFlags );
82 if (!htask) htask = GetCurrentTask();
83 for (i=0;i<nrofnotifys;i++)
84 if (notifys[i].htask==htask)
85 break;
86 if (i==nrofnotifys) {
87 if (notifys==NULL)
88 notifys=(struct notify*)HeapAlloc( SystemHeap, 0,
89 sizeof(struct notify) );
90 else
91 notifys=(struct notify*)HeapReAlloc( SystemHeap, 0, notifys,
92 sizeof(struct notify)*(nrofnotifys+1));
93 if (!notifys) return FALSE;
94 nrofnotifys++;
96 notifys[i].htask=htask;
97 notifys[i].lpfnCallback=lpfnCallback;
98 notifys[i].wFlags=wFlags;
99 return TRUE;
102 BOOL16 WINAPI NotifyUnregister( HTASK16 htask )
104 int i;
106 TRACE(toolhelp, "(%x) called.\n", htask );
107 if (!htask) htask = GetCurrentTask();
108 for (i=nrofnotifys;i--;)
109 if (notifys[i].htask==htask)
110 break;
111 if (i==-1)
112 return FALSE;
113 memcpy(notifys+i,notifys+(i+1),sizeof(struct notify)*(nrofnotifys-i-1));
114 notifys=(struct notify*)HeapReAlloc( SystemHeap, 0, notifys,
115 (nrofnotifys-1)*sizeof(struct notify));
116 nrofnotifys--;
117 return TRUE;
120 BOOL16 WINAPI StackTraceCSIPFirst(STACKTRACEENTRY *ste, WORD wSS, WORD wCS, WORD wIP, WORD wBP)
122 return TRUE;
125 BOOL16 WINAPI StackTraceFirst(STACKTRACEENTRY *ste, HTASK16 Task)
127 return TRUE;
130 BOOL16 WINAPI StackTraceNext(STACKTRACEENTRY *ste)
132 return TRUE;
135 /***********************************************************************
136 * ToolHelpHook (KERNEL.341)
137 * see "Undocumented Windows"
139 FARPROC16 WINAPI ToolHelpHook(FARPROC16 lpfnNotifyHandler)
141 FARPROC16 tmp;
142 tmp = HookNotify;
143 HookNotify = lpfnNotifyHandler;
144 /* just return previously installed notification function */
145 return tmp;
148 /***********************************************************************
149 * SNAPSHOT_Destroy
151 * Deallocate K32 snapshot objects
153 static void SNAPSHOT_Destroy (K32OBJ *obj)
155 int i;
156 SNAPSHOT_OBJECT *snapshot = (SNAPSHOT_OBJECT *) obj;
157 assert (obj->type == K32OBJ_CHANGE);
159 if (snapshot->processArray)
161 for (i = 0; snapshot->processArray[i] && i <snapshot->numProcs; i++)
163 K32OBJ_DecCount (&snapshot->processArray[i]->header);
165 HeapFree (GetProcessHeap (), 0, snapshot->processArray);
166 snapshot->processArray = NULL;
169 obj->type = K32OBJ_UNKNOWN;
170 HeapFree (GetProcessHeap (), 0, snapshot);
173 /***********************************************************************
174 * CreateToolHelp32Snapshot (KERNEL32.179)
175 * see "Undocumented Windows"
177 HANDLE32 WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD
178 th32ProcessID)
180 HANDLE32 ssHandle;
181 SNAPSHOT_OBJECT *snapshot;
182 int numProcesses;
183 int i;
184 PDB32* pdb;
186 TRACE(toolhelp, "%lx & TH32CS_INHERIT (%x) = %lx %s\n", dwFlags,
187 TH32CS_INHERIT,
188 dwFlags & TH32CS_INHERIT,
189 dwFlags & TH32CS_INHERIT ? "TRUE" : "FALSE");
190 TRACE(toolhelp, "%lx & TH32CS_SNAPHEAPLIST (%x) = %lx %s\n", dwFlags,
191 TH32CS_SNAPHEAPLIST,
192 dwFlags & TH32CS_SNAPHEAPLIST,
193 dwFlags & TH32CS_SNAPHEAPLIST ? "TRUE" : "FALSE");
194 TRACE(toolhelp, "%lx & TH32CS_SNAPMODULE (%x) = %lx %s\n", dwFlags,
195 TH32CS_SNAPMODULE,
196 dwFlags & TH32CS_SNAPMODULE,
197 dwFlags & TH32CS_SNAPMODULE ? "TRUE" : "FALSE");
198 TRACE(toolhelp, "%lx & TH32CS_SNAPPROCESS (%x) = %lx %s\n", dwFlags,
199 TH32CS_SNAPPROCESS,
200 dwFlags & TH32CS_SNAPPROCESS,
201 dwFlags & TH32CS_SNAPPROCESS ? "TRUE" : "FALSE");
202 TRACE(toolhelp, "%lx & TH32CS_SNAPTHREAD (%x) = %lx %s\n", dwFlags,
203 TH32CS_SNAPTHREAD,
204 dwFlags & TH32CS_SNAPTHREAD,
205 dwFlags & TH32CS_SNAPTHREAD ? "TRUE" : "FALSE");
207 /**** FIXME: Not implmented ***/
208 if (dwFlags & TH32CS_INHERIT)
210 FIXME(toolhelp,"(0x%08lx (TH32CS_INHERIT),0x%08lx), stub!\n",
211 dwFlags,th32ProcessID);
213 return INVALID_HANDLE_VALUE32;
215 if (dwFlags & TH32CS_SNAPHEAPLIST)
217 FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPHEAPLIST),0x%08lx), stub!\n",
218 dwFlags,th32ProcessID);
219 return INVALID_HANDLE_VALUE32;
221 if (dwFlags & TH32CS_SNAPMODULE)
223 FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPMODULE),0x%08lx), stub!\n",
224 dwFlags,th32ProcessID);
225 return INVALID_HANDLE_VALUE32;
228 if (dwFlags & TH32CS_SNAPPROCESS)
230 TRACE (toolhelp, "(0x%08lx (TH32CS_SNAPMODULE),0x%08lx)\n",
231 dwFlags,th32ProcessID);
232 snapshot = HeapAlloc (GetProcessHeap (), 0, sizeof
233 (SNAPSHOT_OBJECT));
234 if (!snapshot)
236 return INVALID_HANDLE_VALUE32;
239 snapshot->header.type = K32OBJ_TOOLHELP_SNAPSHOT;
240 snapshot->header.refcount = 1;
241 snapshot->arrayCounter = 0;
244 * Lock here, to prevent processes from being created or
245 * destroyed while the snapshot is gathered
248 SYSTEM_LOCK ();
249 numProcesses = PROCESS_PDBList_Getsize ();
251 snapshot->processArray = (PDB32**)
252 HeapAlloc (GetProcessHeap (), 0, sizeof (PDB32*) * numProcesses);
254 if (!snapshot->processArray)
256 HeapFree (GetProcessHeap (), 0, snapshot->processArray);
257 SetLastError (INVALID_HANDLE_VALUE32);
258 ERR (toolhelp, "Error allocating %d bytes for snapshot\n",
259 sizeof (PDB32*) * numProcesses);
260 return INVALID_HANDLE_VALUE32;
263 snapshot->numProcs = numProcesses;
265 pdb = PROCESS_PDBList_Getfirst ();
266 for (i = 0; pdb && i < numProcesses; i++)
268 TRACE (toolhelp, "Saving ref to pdb %ld\n", PDB_TO_PROCESS_ID(pdb));
269 snapshot->processArray[i] = pdb;
270 K32OBJ_IncCount (&pdb->header);
271 pdb = PROCESS_PDBList_Getnext (pdb);
273 SYSTEM_UNLOCK ();
275 ssHandle = HANDLE_Alloc (PROCESS_Current (), &snapshot->header,
276 FILE_ALL_ACCESS, TRUE, -1);
277 if (ssHandle == INVALID_HANDLE_VALUE32)
279 /* HANDLE_Alloc is supposed to deallocate the
280 * heap memory if it fails. This code doesn't need to.
282 SetLastError (INVALID_HANDLE_VALUE32);
283 ERR (toolhelp, "Error allocating handle\n");
284 return INVALID_HANDLE_VALUE32;
287 TRACE (toolhelp, "snapshotted %d processes, expected %d\n",
288 i, numProcesses);
289 return ssHandle;
292 if (dwFlags & TH32CS_SNAPTHREAD)
294 FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPMODULE),0x%08lx), stub!\n",
295 dwFlags,th32ProcessID);
296 return INVALID_HANDLE_VALUE32;
299 return INVALID_HANDLE_VALUE32;
302 /***********************************************************************
303 * Process32First
304 * Return info about the first process in a toolhelp32 snapshot
306 BOOL32 WINAPI Process32First(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe)
308 PDB32 *pdb;
309 SNAPSHOT_OBJECT *snapshot;
310 int i;
312 TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot,
313 (DWORD) lppe);
315 if (lppe->dwSize < sizeof (PROCESSENTRY32))
317 SetLastError (ERROR_INSUFFICIENT_BUFFER);
318 ERR (toolhelp, "Result buffer too small\n");
319 return FALSE;
322 SYSTEM_LOCK ();
323 snapshot = (SNAPSHOT_OBJECT*) HANDLE_GetObjPtr (PROCESS_Current (),
324 hSnapshot,
325 K32OBJ_UNKNOWN,
326 FILE_ALL_ACCESS,
327 NULL);
328 if (!snapshot)
330 SYSTEM_UNLOCK ();
331 SetLastError (ERROR_INVALID_HANDLE);
332 ERR (toolhelp, "Error retreiving snapshot\n");
333 return FALSE;
336 snapshot->arrayCounter = i = 0;
337 pdb = snapshot->processArray[i];
339 if (!pdb)
341 SetLastError (ERROR_NO_MORE_FILES);
342 ERR (toolhelp, "End of snapshot array\n");
343 return FALSE;
346 TRACE (toolhelp, "Returning info on process %d, id %ld\n",
347 i, PDB_TO_PROCESS_ID (pdb));
349 lppe->cntUsage = 1;
350 lppe->th32ProcessID = PDB_TO_PROCESS_ID (pdb);
351 lppe->th32DefaultHeapID = (DWORD) pdb->heap;
352 lppe->cntThreads = pdb->threads;
353 lppe->th32ParentProcessID = PDB_TO_PROCESS_ID (pdb->parent);
354 lppe->pcPriClassBase = 6; /* FIXME: this is a made-up value */
355 lppe->dwFlags = -1; /* FIXME: RESERVED by Microsoft :-) */
356 if (pdb->exe_modref)
358 lppe->th32ModuleID = (DWORD) pdb->exe_modref->module;
359 strncpy (lppe->szExeFile, pdb->exe_modref->longname,
360 sizeof (lppe->szExeFile));
362 else
364 lppe->th32ModuleID = (DWORD) 0;
365 strcpy (lppe->szExeFile, "");
368 SYSTEM_UNLOCK ();
370 return TRUE;
373 /***********************************************************************
374 * Process32Next
375 * Return info about the "next" process in a toolhelp32 snapshot
377 BOOL32 WINAPI Process32Next(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe)
379 PDB32 *pdb;
380 SNAPSHOT_OBJECT *snapshot;
381 int i;
383 TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot,
384 (DWORD) lppe);
386 if (lppe->dwSize < sizeof (PROCESSENTRY32))
388 SetLastError (ERROR_INSUFFICIENT_BUFFER);
389 ERR (toolhelp, "Result buffer too small\n");
390 return FALSE;
393 SYSTEM_LOCK ();
394 snapshot = (SNAPSHOT_OBJECT*) HANDLE_GetObjPtr (PROCESS_Current (),
395 hSnapshot,
396 K32OBJ_UNKNOWN,
397 FILE_ALL_ACCESS,
398 NULL);
399 if (!snapshot)
401 SYSTEM_UNLOCK ();
402 SetLastError (ERROR_INVALID_HANDLE);
403 ERR (toolhelp, "Error retreiving snapshot\n");
404 return FALSE;
407 snapshot->arrayCounter ++;
408 i = snapshot->arrayCounter;
409 pdb = snapshot->processArray[i];
411 if (!pdb || snapshot->arrayCounter >= snapshot->numProcs)
413 SetLastError (ERROR_NO_MORE_FILES);
414 ERR (toolhelp, "End of snapshot array\n");
415 return FALSE;
418 TRACE (toolhelp, "Returning info on process %d, id %ld\n",
419 i, PDB_TO_PROCESS_ID (pdb));
421 lppe->cntUsage = 1;
422 lppe->th32ProcessID = PDB_TO_PROCESS_ID (pdb);
423 lppe->th32DefaultHeapID = (DWORD) pdb->heap;
424 lppe->cntThreads = pdb->threads;
425 lppe->th32ParentProcessID = PDB_TO_PROCESS_ID (pdb->parent);
426 lppe->pcPriClassBase = 6; /* FIXME: this is a made-up value */
427 lppe->dwFlags = -1; /* FIXME: RESERVED by Microsoft :-) */
428 if (pdb->exe_modref)
430 lppe->th32ModuleID = (DWORD) pdb->exe_modref->module;
431 strncpy (lppe->szExeFile, pdb->exe_modref->longname,
432 sizeof (lppe->szExeFile));
434 else
436 lppe->th32ModuleID = (DWORD) 0;
437 strcpy (lppe->szExeFile, "");
440 SYSTEM_UNLOCK ();
442 return TRUE;