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