2 * Misc Toolhelp functions
4 * Copyright 1996 Marcus Meissner
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
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.
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
61 FARPROC16 lpfnCallback;
65 static int nrofnotifys = 0;
67 static FARPROC16 HookNotify = NULL;
69 BOOL16 WINAPI NotifyRegister( HTASK16 htask, FARPROC16 lpfnCallback,
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)
82 notifys=(struct notify*)HeapAlloc( SystemHeap, 0,
83 sizeof(struct notify) );
85 notifys=(struct notify*)HeapReAlloc( SystemHeap, 0, notifys,
86 sizeof(struct notify)*(nrofnotifys+1));
87 if (!notifys) return FALSE;
90 notifys[i].htask=htask;
91 notifys[i].lpfnCallback=lpfnCallback;
92 notifys[i].wFlags=wFlags;
96 BOOL16 WINAPI NotifyUnregister( HTASK16 htask )
100 TRACE(toolhelp, "(%x) called.\n", htask );
101 if (!htask) htask = GetCurrentTask();
102 for (i=nrofnotifys;i--;)
103 if (notifys[i].htask==htask)
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));
114 BOOL16 WINAPI StackTraceCSIPFirst(STACKTRACEENTRY *ste, WORD wSS, WORD wCS, WORD wIP, WORD wBP)
119 BOOL16 WINAPI StackTraceFirst(STACKTRACEENTRY *ste, HTASK16 Task)
124 BOOL16 WINAPI StackTraceNext(STACKTRACEENTRY *ste)
129 /***********************************************************************
130 * ToolHelpHook (KERNEL.341)
131 * see "Undocumented Windows"
133 FARPROC16 WINAPI ToolHelpHook(FARPROC16 lpfnNotifyHandler)
137 HookNotify = lpfnNotifyHandler;
138 /* just return previously installed notification function */
142 /***********************************************************************
145 * Deallocate K32 snapshot objects
147 static void SNAPSHOT_Destroy (K32OBJ *obj)
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
175 SNAPSHOT_OBJECT *snapshot;
180 TRACE(toolhelp, "%lx & TH32CS_INHERIT (%x) = %lx %s\n", dwFlags,
182 dwFlags & TH32CS_INHERIT,
183 dwFlags & TH32CS_INHERIT ? "TRUE" : "FALSE");
184 TRACE(toolhelp, "%lx & TH32CS_SNAPHEAPLIST (%x) = %lx %s\n", dwFlags,
186 dwFlags & TH32CS_SNAPHEAPLIST,
187 dwFlags & TH32CS_SNAPHEAPLIST ? "TRUE" : "FALSE");
188 TRACE(toolhelp, "%lx & TH32CS_SNAPMODULE (%x) = %lx %s\n", dwFlags,
190 dwFlags & TH32CS_SNAPMODULE,
191 dwFlags & TH32CS_SNAPMODULE ? "TRUE" : "FALSE");
192 TRACE(toolhelp, "%lx & TH32CS_SNAPPROCESS (%x) = %lx %s\n", dwFlags,
194 dwFlags & TH32CS_SNAPPROCESS,
195 dwFlags & TH32CS_SNAPPROCESS ? "TRUE" : "FALSE");
196 TRACE(toolhelp, "%lx & TH32CS_SNAPTHREAD (%x) = %lx %s\n", dwFlags,
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
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
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);
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",
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 /***********************************************************************
298 * Return info about the first process in a toolhelp32 snapshot
300 BOOL32 WINAPI Process32First(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe)
303 SNAPSHOT_OBJECT *snapshot;
306 TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot,
309 if (lppe->dwSize < sizeof (PROCESSENTRY32))
311 SetLastError (ERROR_INSUFFICIENT_BUFFER);
312 ERR (toolhelp, "Result buffer too small\n");
317 snapshot = (SNAPSHOT_OBJECT*) HANDLE_GetObjPtr (PROCESS_Current (),
325 SetLastError (ERROR_INVALID_HANDLE);
326 ERR (toolhelp, "Error retreiving snapshot\n");
330 snapshot->arrayCounter = i = 0;
331 pdb = snapshot->processArray[i];
335 SetLastError (ERROR_NO_MORE_FILES);
336 ERR (toolhelp, "End of snapshot array\n");
340 TRACE (toolhelp, "Returning info on process %d, id %ld\n",
341 i, PDB_TO_PROCESS_ID (pdb));
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 :-) */
352 lppe->th32ModuleID = (DWORD) pdb->exe_modref->module;
353 strncpy (lppe->szExeFile, pdb->exe_modref->longname,
354 sizeof (lppe->szExeFile));
358 lppe->th32ModuleID = (DWORD) 0;
359 strcpy (lppe->szExeFile, "");
367 /***********************************************************************
369 * Return info about the "next" process in a toolhelp32 snapshot
371 BOOL32 WINAPI Process32Next(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe)
374 SNAPSHOT_OBJECT *snapshot;
377 TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot,
380 if (lppe->dwSize < sizeof (PROCESSENTRY32))
382 SetLastError (ERROR_INSUFFICIENT_BUFFER);
383 ERR (toolhelp, "Result buffer too small\n");
388 snapshot = (SNAPSHOT_OBJECT*) HANDLE_GetObjPtr (PROCESS_Current (),
396 SetLastError (ERROR_INVALID_HANDLE);
397 ERR (toolhelp, "Error retreiving snapshot\n");
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");
412 TRACE (toolhelp, "Returning info on process %d, id %ld\n",
413 i, PDB_TO_PROCESS_ID (pdb));
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 :-) */
424 lppe->th32ModuleID = (DWORD) pdb->exe_modref->module;
425 strncpy (lppe->szExeFile, pdb->exe_modref->longname,
426 sizeof (lppe->szExeFile));
430 lppe->th32ModuleID = (DWORD) 0;
431 strcpy (lppe->szExeFile, "");