Removed a few dependencies on kernel32 functions.
[wine] / dlls / kernel / 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 "winbase.h"
13 #include "wine/winbase16.h"
14 #include "winerror.h"
15 #include "local.h"
16 #include "tlhelp32.h"
17 #include "toolhelp.h"
18 #include "heap.h"
19 #include "server.h"
20 #include "debugtools.h"
21
22 DEFAULT_DEBUG_CHANNEL(toolhelp);
23
24
25 /* FIXME: to make this working, we have to callback all these registered 
26  * functions from all over the WINE code. Someone with more knowledge than
27  * me please do that. -Marcus
28  */
29 static struct notify
30 {
31     HTASK16   htask;
32     FARPROC16 lpfnCallback;
33     WORD     wFlags;
34 } *notifys = NULL;
35
36 static int nrofnotifys = 0;
37
38 static FARPROC16 HookNotify = NULL;
39
40 /***********************************************************************
41  *              NotifyRegister16
42  */
43 BOOL16 WINAPI NotifyRegister16( HTASK16 htask, FARPROC16 lpfnCallback,
44                               WORD wFlags )
45 {
46     int i;
47
48     FIXME("(%x,%lx,%x), semi-stub.\n",
49                       htask, (DWORD)lpfnCallback, wFlags );
50     if (!htask) htask = GetCurrentTask();
51     for (i=0;i<nrofnotifys;i++)
52         if (notifys[i].htask==htask)
53             break;
54     if (i==nrofnotifys) {
55         if (notifys==NULL)
56             notifys=(struct notify*)HeapAlloc( GetProcessHeap(), 0,
57                                                sizeof(struct notify) );
58         else
59             notifys=(struct notify*)HeapReAlloc( GetProcessHeap(), 0, notifys,
60                                         sizeof(struct notify)*(nrofnotifys+1));
61         if (!notifys) return FALSE;
62         nrofnotifys++;
63     }
64     notifys[i].htask=htask;
65     notifys[i].lpfnCallback=lpfnCallback;
66     notifys[i].wFlags=wFlags;
67     return TRUE;
68 }
69
70 /***********************************************************************
71  *              NotifyUnregister16
72  */
73 BOOL16 WINAPI NotifyUnregister16( HTASK16 htask )
74 {
75     int i;
76     
77     FIXME("(%x), semi-stub.\n", htask );
78     if (!htask) htask = GetCurrentTask();
79     for (i=nrofnotifys;i--;)
80         if (notifys[i].htask==htask)
81             break;
82     if (i==-1)
83         return FALSE;
84     memcpy(notifys+i,notifys+(i+1),sizeof(struct notify)*(nrofnotifys-i-1));
85     notifys=(struct notify*)HeapReAlloc( GetProcessHeap(), 0, notifys,
86                                         (nrofnotifys-1)*sizeof(struct notify));
87     nrofnotifys--;
88     return TRUE;
89 }
90
91 /***********************************************************************
92  *              StackTraceCSIPFirst16
93  */
94 BOOL16 WINAPI StackTraceCSIPFirst16(STACKTRACEENTRY *ste, WORD wSS, WORD wCS, WORD wIP, WORD wBP)
95 {
96     FIXME("(%p, ss %04x, cs %04x, ip %04x, bp %04x): stub.\n", ste, wSS, wCS, wIP, wBP);
97     return TRUE;
98 }
99
100 /***********************************************************************
101  *              StackTraceFirst16
102  */
103 BOOL16 WINAPI StackTraceFirst16(STACKTRACEENTRY *ste, HTASK16 Task)
104 {
105     FIXME("(%p, %04x), stub.\n", ste, Task);
106     return TRUE;
107 }
108
109 /***********************************************************************
110  *              StackTraceNext16
111  */
112 BOOL16 WINAPI StackTraceNext16(STACKTRACEENTRY *ste)
113 {
114     FIXME("(%p), stub.\n", ste);
115     return TRUE;
116 }
117
118 /***********************************************************************
119  *              InterruptRegister16
120  */
121 BOOL16 WINAPI InterruptRegister16( HTASK16 task, FARPROC callback )
122 {
123     FIXME("(%04x, %p), stub.\n", task, callback);
124     return TRUE;
125 }
126
127 /***********************************************************************
128  *              InterruptUnRegister16
129  */
130 BOOL16 WINAPI InterruptUnRegister16( HTASK16 task )
131 {
132     FIXME("(%04x), stub.\n", task);
133     return TRUE;
134 }
135
136 /***********************************************************************
137  *           TimerCount   (TOOLHELP.80)
138  */
139 BOOL16 WINAPI TimerCount16( TIMERINFO *pTimerInfo )
140 {
141     /* FIXME
142      * In standard mode, dwmsSinceStart = dwmsThisVM 
143      *
144      * I tested this, under Windows in enhanced mode, and
145      * if you never switch VM (ie start/stop DOS) these
146      * values should be the same as well. 
147      *
148      * Also, Wine should adjust for the hardware timer
149      * to reduce the amount of error to ~1ms. 
150      * I can't be bothered, can you?
151      */
152     pTimerInfo->dwmsSinceStart = pTimerInfo->dwmsThisVM = GetTickCount();
153     return TRUE;
154 }
155
156 /***********************************************************************
157  *           SystemHeapInfo   (TOOLHELP.71)
158  */
159 BOOL16 WINAPI SystemHeapInfo16( SYSHEAPINFO *pHeapInfo )
160 {
161     WORD user = LoadLibrary16( "USER.EXE" );
162     WORD gdi = LoadLibrary16( "GDI.EXE" );
163     pHeapInfo->wUserFreePercent = (int)LOCAL_CountFree(user) * 100 / LOCAL_HeapSize(user);
164     pHeapInfo->wGDIFreePercent  = (int)LOCAL_CountFree(gdi) * 100 / LOCAL_HeapSize(gdi);
165     pHeapInfo->hUserSegment = user;
166     pHeapInfo->hGDISegment  = gdi;
167     FreeLibrary16( user );
168     FreeLibrary16( gdi );
169     return TRUE;
170 }
171
172
173 /***********************************************************************
174  *           ToolHelpHook                             (KERNEL.341)
175  *      see "Undocumented Windows"
176  */
177 FARPROC16 WINAPI ToolHelpHook16(FARPROC16 lpfnNotifyHandler)
178 {
179         FARPROC16 tmp;
180
181         FIXME("(%p), stub.\n", lpfnNotifyHandler);
182         tmp = HookNotify;
183         HookNotify = lpfnNotifyHandler;
184         /* just return previously installed notification function */
185         return tmp;
186 }
187
188
189 /***********************************************************************
190  *           CreateToolhelp32Snapshot                   (KERNEL32.179)
191  */
192 HANDLE WINAPI CreateToolhelp32Snapshot( DWORD flags, DWORD process ) 
193 {
194     HANDLE ret;
195
196     TRACE("%lx,%lx\n", flags, process );
197     if (!(flags & (TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD|TH32CS_SNAPMODULE)))
198     {
199         FIXME("flags %lx not implemented\n", flags );
200         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
201         return INVALID_HANDLE_VALUE;
202     }
203
204     /* Now do the snapshot */
205     SERVER_START_REQ
206     {
207         struct create_snapshot_request *req = server_alloc_req( sizeof(*req), 0 );
208         req->flags   = flags & ~TH32CS_INHERIT;
209         req->inherit = (flags & TH32CS_INHERIT) != 0;
210         req->pid     = (void *)process;
211         server_call( REQ_CREATE_SNAPSHOT );
212         ret = req->handle;
213     }
214     SERVER_END_REQ;
215     return ret;
216 }
217
218
219 /***********************************************************************
220  *              TOOLHELP_Thread32Next
221  *
222  * Implementation of Thread32First/Next
223  */
224 static BOOL TOOLHELP_Thread32Next( HANDLE handle, LPTHREADENTRY32 lpte, BOOL first )
225 {
226     BOOL ret;
227
228     if (lpte->dwSize < sizeof(THREADENTRY32))
229     {
230         SetLastError( ERROR_INSUFFICIENT_BUFFER );
231         ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(THREADENTRY32), lpte->dwSize);
232         return FALSE;
233     }
234     SERVER_START_REQ
235     {
236         struct next_thread_request *req = server_alloc_req( sizeof(*req), 0 );
237         req->handle = handle;
238         req->reset = first;
239         if ((ret = !server_call( REQ_NEXT_THREAD )))
240         {
241             lpte->cntUsage           = req->count;
242             lpte->th32ThreadID       = (DWORD)req->tid;
243             lpte->th32OwnerProcessID = (DWORD)req->pid;
244             lpte->tpBasePri          = req->base_pri;
245             lpte->tpDeltaPri         = req->delta_pri;
246             lpte->dwFlags            = 0;  /* SDK: "reserved; do not use" */
247         }
248     }
249     SERVER_END_REQ;
250     return ret;
251 }
252
253 /***********************************************************************
254  *              Thread32First    (KERNEL32.686)
255  *
256  * Return info about the first thread in a toolhelp32 snapshot
257  */
258 BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
259 {
260     return TOOLHELP_Thread32Next(hSnapshot, lpte, TRUE);
261 }
262
263 /***********************************************************************
264  *              Thread32Next   (KERNEL32.687)
265  *
266  * Return info about the "next" thread in a toolhelp32 snapshot
267  */
268 BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
269 {
270     return TOOLHELP_Thread32Next(hSnapshot, lpte, FALSE);
271 }
272
273 /***********************************************************************
274  *              TOOLHELP_Process32Next
275  *
276  * Implementation of Process32First/Next
277  */
278 static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32 lppe, BOOL first )
279 {
280     BOOL ret;
281
282     if (lppe->dwSize < sizeof(PROCESSENTRY32))
283     {
284         SetLastError( ERROR_INSUFFICIENT_BUFFER );
285         ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32), lppe->dwSize);
286         return FALSE;
287     }
288     SERVER_START_REQ
289     {
290         struct next_process_request *req = server_alloc_req( sizeof(*req), 0 );
291         req->handle = handle;
292         req->reset = first;
293         if ((ret = !server_call( REQ_NEXT_PROCESS )))
294         {
295             lppe->cntUsage            = req->count;
296             lppe->th32ProcessID       = (DWORD)req->pid;
297             lppe->th32DefaultHeapID   = 0;  /* FIXME */
298             lppe->th32ModuleID        = 0;  /* FIXME */
299             lppe->cntThreads          = req->threads;
300             lppe->th32ParentProcessID = 0;  /* FIXME */
301             lppe->pcPriClassBase      = req->priority;
302             lppe->dwFlags             = -1; /* FIXME */
303             lppe->szExeFile[0]        = 0;  /* FIXME */
304         }
305     }
306     SERVER_END_REQ;
307     return ret;
308 }
309
310
311 /***********************************************************************
312  *              Process32First    (KERNEL32.555)
313  *
314  * Return info about the first process in a toolhelp32 snapshot
315  */
316 BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
317 {
318     return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE );
319 }
320
321 /***********************************************************************
322  *              Process32Next   (KERNEL32.556)
323  *
324  * Return info about the "next" process in a toolhelp32 snapshot
325  */
326 BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
327 {
328     return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE );
329 }
330
331
332 /***********************************************************************
333  *              TOOLHELP_Module32Next
334  *
335  * Implementation of Module32First/Next
336  */
337 static BOOL TOOLHELP_Module32Next( HANDLE handle, LPMODULEENTRY32 lpme, BOOL first )
338 {
339     BOOL ret;
340
341     if (lpme->dwSize < sizeof (MODULEENTRY32))
342     {
343         SetLastError( ERROR_INSUFFICIENT_BUFFER );
344         ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32), lpme->dwSize);
345         return FALSE;
346     }
347     SERVER_START_REQ
348     {
349         struct next_module_request *req = server_alloc_req( sizeof(*req), 0 );
350         req->handle = handle;
351         req->reset = first;
352         if ((ret = !server_call( REQ_NEXT_MODULE )))
353         {
354             lpme->th32ModuleID   = 0;  /* toolhelp internal id, never used */
355             lpme->th32ProcessID  = (DWORD)req->pid;
356             lpme->GlblcntUsage   = 0; /* FIXME */
357             lpme->ProccntUsage   = 0; /* FIXME */ 
358             lpme->modBaseAddr    = req->base;
359             lpme->modBaseSize    = 0; /* FIXME */
360             lpme->hModule        = (DWORD)req->base;
361             lpme->szModule[0]    = 0;  /* FIXME */
362             lpme->szExePath[0]   = 0;  /* FIXME */
363         }
364     }
365     SERVER_END_REQ;
366     return ret;
367 }
368
369 /***********************************************************************
370  *              Module32First   (KERNEL32.527)
371  *
372  * Return info about the "first" module in a toolhelp32 snapshot
373  */
374 BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
375 {
376     return TOOLHELP_Module32Next( hSnapshot, lpme, TRUE );
377 }
378
379 /***********************************************************************
380  *              Module32Next   (KERNEL32.528)
381  *
382  * Return info about the "next" module in a toolhelp32 snapshot
383  */
384 BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
385 {
386     return TOOLHELP_Module32Next( hSnapshot, lpme, FALSE );
387 }
388
389 /************************************************************************
390  *              GlobalMasterHandle16 (KERNEL.28)
391  *
392  *
393  * Should return selector and handle of the information structure for 
394  * the global heap. selector and handle are stored in the THHOOK as
395  * pGlobalHeap and hGlobalHeap.
396  * As Wine doesn't have this structure, we return both values as zero
397  * Applications should interpret this as "No Global Heap"
398  */
399 DWORD WINAPI GlobalMasterHandle16(void)
400 {
401     FIXME(": stub\n");
402     return 0;
403 }