Allocate a DOS handle if we open a normal file with LZOpenFile16.
[wine] / misc / toolhelp.c
1 /*
2  * Misc Toolhelp functions
3  *
4  * Copyright 1996 Marcus Meissner
5  */
6
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"
21
22 /*
23  * Support for toolhelp's snapshots.  They
24  * are supposed to be Kernel32 Objects.
25  * Only the Destroy() method is implemented
26  */
27
28 static void SNAPSHOT_Destroy( K32OBJ *obj );
29
30 const K32OBJ_OPS SNAPSHOT_Ops =
31 {
32   SNAPSHOT_Destroy      /* destroy */
33 };
34
35 /* The K32 snapshot object object */
36 /* Process snapshot kernel32 object */
37 typedef struct _Process32Snapshot
38 {
39   K32OBJ                header;
40
41   DWORD                 numProcs;
42   DWORD                 arrayCounter;
43   /*
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.
49    */
50   PDB32         **processArray;
51 }
52 SNAPSHOT_OBJECT;
53
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
57  */
58 static struct notify
59 {
60     HTASK16   htask;
61     FARPROC16 lpfnCallback;
62     WORD     wFlags;
63 } *notifys = NULL;
64
65 static int nrofnotifys = 0;
66
67 static FARPROC16 HookNotify = NULL;
68
69 BOOL16 WINAPI NotifyRegister( HTASK16 htask, FARPROC16 lpfnCallback,
70                               WORD wFlags )
71 {
72     int i;
73
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++;
89     }
90     notifys[i].htask=htask;
91     notifys[i].lpfnCallback=lpfnCallback;
92     notifys[i].wFlags=wFlags;
93     return TRUE;
94 }
95
96 BOOL16 WINAPI NotifyUnregister( HTASK16 htask )
97 {
98     int i;
99     
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;
112 }
113
114 BOOL16 WINAPI StackTraceCSIPFirst(STACKTRACEENTRY *ste, WORD wSS, WORD wCS, WORD wIP, WORD wBP)
115 {
116     return TRUE;
117 }
118
119 BOOL16 WINAPI StackTraceFirst(STACKTRACEENTRY *ste, HTASK16 Task)
120 {
121     return TRUE;
122 }
123
124 BOOL16 WINAPI StackTraceNext(STACKTRACEENTRY *ste)
125 {
126     return TRUE;
127 }
128
129 /***********************************************************************
130  *           ToolHelpHook                             (KERNEL.341)
131  *      see "Undocumented Windows"
132  */
133 FARPROC16 WINAPI ToolHelpHook(FARPROC16 lpfnNotifyHandler)
134 {
135 FARPROC16 tmp;
136         tmp = HookNotify;
137         HookNotify = lpfnNotifyHandler;
138         /* just return previously installed notification function */
139         return tmp;
140 }
141
142 /***********************************************************************
143  *           SNAPSHOT_Destroy
144  *
145  * Deallocate K32 snapshot objects
146  */
147 static void SNAPSHOT_Destroy (K32OBJ *obj)
148 {
149   int   i;
150   SNAPSHOT_OBJECT *snapshot = (SNAPSHOT_OBJECT *) obj;
151   assert (obj->type == K32OBJ_CHANGE);
152
153   if (snapshot->processArray)
154     {   
155       for (i = 0; snapshot->processArray[i] && i <snapshot->numProcs; i++)
156         {
157           K32OBJ_DecCount (&snapshot->processArray[i]->header);
158         }
159       HeapFree (GetProcessHeap (), 0, snapshot->processArray);
160       snapshot->processArray = NULL;      
161     }   
162
163   obj->type = K32OBJ_UNKNOWN;
164   HeapFree (GetProcessHeap (), 0, snapshot);
165 }
166
167 /***********************************************************************
168  *           CreateToolHelp32Snapshot                   (KERNEL32.179)
169  *      see "Undocumented Windows"
170  */
171 HANDLE32 WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD
172                                          th32ProcessID) 
173 {
174   HANDLE32              ssHandle;
175   SNAPSHOT_OBJECT       *snapshot;
176   int                   numProcesses;
177   int                   i;
178   PDB32*                pdb;
179
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");  
200
201   /**** FIXME: Not implmented ***/
202   if (dwFlags & TH32CS_INHERIT)
203     {
204       FIXME(toolhelp,"(0x%08lx (TH32CS_INHERIT),0x%08lx), stub!\n",
205             dwFlags,th32ProcessID);
206
207       return INVALID_HANDLE_VALUE32;
208     }
209   if (dwFlags & TH32CS_SNAPHEAPLIST)
210     {
211       FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPHEAPLIST),0x%08lx), stub!\n",
212             dwFlags,th32ProcessID);
213       return INVALID_HANDLE_VALUE32;
214     }
215   if (dwFlags & TH32CS_SNAPMODULE)
216     {
217       FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPMODULE),0x%08lx), stub!\n",
218             dwFlags,th32ProcessID);
219       return INVALID_HANDLE_VALUE32;
220     }
221
222   if (dwFlags & TH32CS_SNAPPROCESS)
223     {
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)
229         {
230           return INVALID_HANDLE_VALUE32;
231         }
232
233       snapshot->header.type = K32OBJ_TOOLHELP_SNAPSHOT;
234       snapshot->header.refcount = 1;
235       snapshot->arrayCounter = 0;
236   
237       /*
238        * Lock here, to prevent processes from being created or
239        * destroyed while the snapshot is gathered
240        */
241
242       SYSTEM_LOCK ();
243       numProcesses = PROCESS_PDBList_Getsize ();
244
245       snapshot->processArray = (PDB32**) 
246         HeapAlloc (GetProcessHeap (), 0, sizeof (PDB32*) * numProcesses); 
247
248       if (!snapshot->processArray)
249         {
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;
255         }
256
257       snapshot->numProcs = numProcesses;
258
259       pdb = PROCESS_PDBList_Getfirst ();
260       for (i = 0; pdb && i < numProcesses; i++)
261         {
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);
266         }
267       SYSTEM_UNLOCK ();
268
269       ssHandle = HANDLE_Alloc (PROCESS_Current (), &snapshot->header,
270                                FILE_ALL_ACCESS, TRUE, -1);
271       if (ssHandle == INVALID_HANDLE_VALUE32) 
272         {
273           /*  HANDLE_Alloc is supposed to deallocate the 
274            *  heap memory if it fails.  This code doesn't need to.
275            */
276           SetLastError (INVALID_HANDLE_VALUE32);
277           ERR (toolhelp, "Error allocating handle\n");
278           return INVALID_HANDLE_VALUE32;
279         }
280       
281       TRACE (toolhelp, "snapshotted %d processes, expected %d\n",
282             i, numProcesses);
283       return ssHandle;
284     }
285
286   if (dwFlags & TH32CS_SNAPTHREAD)
287     {
288       FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPMODULE),0x%08lx), stub!\n",
289             dwFlags,th32ProcessID);
290       return INVALID_HANDLE_VALUE32;
291     }
292
293   return INVALID_HANDLE_VALUE32;
294 }
295
296 /***********************************************************************
297  *              Process32First
298  * Return info about the first process in a toolhelp32 snapshot
299  */
300 BOOL32 WINAPI Process32First(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe)
301 {
302   PDB32           *pdb; 
303   SNAPSHOT_OBJECT *snapshot;
304   int             i;
305
306   TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot,
307          (DWORD) lppe);
308
309   if (lppe->dwSize < sizeof (PROCESSENTRY32))
310     {
311       SetLastError (ERROR_INSUFFICIENT_BUFFER);
312       ERR (toolhelp, "Result buffer too small\n");
313       return FALSE;
314     }
315
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)
323     {
324       SYSTEM_UNLOCK ();
325       SetLastError (ERROR_INVALID_HANDLE);
326       ERR (toolhelp, "Error retreiving snapshot\n");
327       return FALSE;
328     }
329
330   snapshot->arrayCounter = i = 0;
331   pdb = snapshot->processArray[i];
332
333   if (!pdb)
334     {
335       SetLastError (ERROR_NO_MORE_FILES);
336       ERR (toolhelp, "End of snapshot array\n");
337       return FALSE;
338     }
339
340   TRACE (toolhelp, "Returning info on process %d, id %ld\n", 
341          i, PDB_TO_PROCESS_ID (pdb));
342
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) 
351     {
352       lppe->th32ModuleID = (DWORD) pdb->exe_modref->module;
353       strncpy (lppe->szExeFile, pdb->exe_modref->longname, 
354                sizeof (lppe->szExeFile)); 
355     }
356   else
357     {
358       lppe->th32ModuleID = (DWORD) 0;
359       strcpy (lppe->szExeFile, "");
360     }
361
362   SYSTEM_UNLOCK ();
363
364   return TRUE;
365 }
366
367 /***********************************************************************
368  *              Process32Next
369  * Return info about the "next" process in a toolhelp32 snapshot
370  */
371 BOOL32 WINAPI Process32Next(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe)
372 {
373   PDB32           *pdb; 
374   SNAPSHOT_OBJECT *snapshot;
375   int             i;
376
377   TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot,
378          (DWORD) lppe);
379
380   if (lppe->dwSize < sizeof (PROCESSENTRY32))
381     {
382       SetLastError (ERROR_INSUFFICIENT_BUFFER);
383       ERR (toolhelp, "Result buffer too small\n");
384       return FALSE;
385     }
386
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)
394     {
395       SYSTEM_UNLOCK ();
396       SetLastError (ERROR_INVALID_HANDLE);
397       ERR (toolhelp, "Error retreiving snapshot\n");
398       return FALSE;
399     }
400
401   snapshot->arrayCounter ++;
402   i = snapshot->arrayCounter;
403   pdb = snapshot->processArray[i];
404
405   if (!pdb || snapshot->arrayCounter >= snapshot->numProcs)
406     {
407       SetLastError (ERROR_NO_MORE_FILES);
408       ERR (toolhelp, "End of snapshot array\n");
409       return FALSE;
410     }
411
412   TRACE (toolhelp, "Returning info on process %d, id %ld\n", 
413          i, PDB_TO_PROCESS_ID (pdb));
414
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) 
423     {
424       lppe->th32ModuleID = (DWORD) pdb->exe_modref->module;
425       strncpy (lppe->szExeFile, pdb->exe_modref->longname, 
426                sizeof (lppe->szExeFile)); 
427     }
428   else
429     {
430       lppe->th32ModuleID = (DWORD) 0;
431       strcpy (lppe->szExeFile, "");
432     }
433
434   SYSTEM_UNLOCK ();
435
436   return TRUE;
437 }