Use tpXXX instead of tbXXX in tagTHREADENTRY32.
[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     TRACE("(%x,%lx,%x) called.\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     TRACE("(%x) called.\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     return TRUE;
97 }
98
99 /***********************************************************************
100  *              StackTraceFirst16
101  */
102 BOOL16 WINAPI StackTraceFirst16(STACKTRACEENTRY *ste, HTASK16 Task)
103 {
104     return TRUE;
105 }
106
107 /***********************************************************************
108  *              StackTraceNext16
109  */
110 BOOL16 WINAPI StackTraceNext16(STACKTRACEENTRY *ste)
111 {
112     return TRUE;
113 }
114
115 /***********************************************************************
116  *              InterruptRegister16
117  */
118 BOOL16 WINAPI InterruptRegister16( HTASK16 task, FARPROC callback )
119 {
120     return TRUE;
121 }
122
123 /***********************************************************************
124  *              InterruptUnRegister16
125  */
126 BOOL16 WINAPI InterruptUnRegister16( HTASK16 task )
127 {
128     return TRUE;
129 }
130
131 /***********************************************************************
132  *           TimerCount   (TOOLHELP.80)
133  */
134 BOOL16 WINAPI TimerCount16( TIMERINFO *pTimerInfo )
135 {
136     /* FIXME
137      * In standard mode, dwmsSinceStart = dwmsThisVM 
138      *
139      * I tested this, under Windows in enhanced mode, and
140      * if you never switch VM (ie start/stop DOS) these
141      * values should be the same as well. 
142      *
143      * Also, Wine should adjust for the hardware timer
144      * to reduce the amount of error to ~1ms. 
145      * I can't be bothered, can you?
146      */
147     pTimerInfo->dwmsSinceStart = pTimerInfo->dwmsThisVM = GetTickCount();
148     return TRUE;
149 }
150
151 /***********************************************************************
152  *           SystemHeapInfo   (TOOLHELP.71)
153  */
154 BOOL16 WINAPI SystemHeapInfo16( SYSHEAPINFO *pHeapInfo )
155 {
156     WORD user = LoadLibrary16( "USER.EXE" );
157     WORD gdi = LoadLibrary16( "GDI.EXE" );
158     pHeapInfo->wUserFreePercent = (int)LOCAL_CountFree(user) * 100 / LOCAL_HeapSize(user);
159     pHeapInfo->wGDIFreePercent  = (int)LOCAL_CountFree(gdi) * 100 / LOCAL_HeapSize(gdi);
160     pHeapInfo->hUserSegment = user;
161     pHeapInfo->hGDISegment  = gdi;
162     FreeLibrary16( user );
163     FreeLibrary16( gdi );
164     return TRUE;
165 }
166
167
168 /***********************************************************************
169  *           ToolHelpHook                             (KERNEL.341)
170  *      see "Undocumented Windows"
171  */
172 FARPROC16 WINAPI ToolHelpHook16(FARPROC16 lpfnNotifyHandler)
173 {
174 FARPROC16 tmp;
175         tmp = HookNotify;
176         HookNotify = lpfnNotifyHandler;
177         /* just return previously installed notification function */
178         return tmp;
179 }
180
181
182 /***********************************************************************
183  *           CreateToolhelp32Snapshot                   (KERNEL32.179)
184  */
185 HANDLE WINAPI CreateToolhelp32Snapshot( DWORD flags, DWORD process ) 
186 {
187     HANDLE ret;
188
189     TRACE("%lx,%lx\n", flags, process );
190     if (!(flags & (TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD|TH32CS_SNAPMODULE)))
191     {
192         FIXME("flags %lx not implemented\n", flags );
193         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
194         return INVALID_HANDLE_VALUE;
195     }
196
197     /* Now do the snapshot */
198     SERVER_START_REQ
199     {
200         struct create_snapshot_request *req = server_alloc_req( sizeof(*req), 0 );
201         req->flags   = flags & ~TH32CS_INHERIT;
202         req->inherit = (flags & TH32CS_INHERIT) != 0;
203         req->pid     = (void *)process;
204         server_call( REQ_CREATE_SNAPSHOT );
205         ret = req->handle;
206     }
207     SERVER_END_REQ;
208     return ret;
209 }
210
211
212 /***********************************************************************
213  *              TOOLHELP_Thread32Next
214  *
215  * Implementation of Thread32First/Next
216  */
217 static BOOL TOOLHELP_Thread32Next( HANDLE handle, LPTHREADENTRY32 lpte, BOOL first )
218 {
219     BOOL ret;
220
221     if (lpte->dwSize < sizeof(THREADENTRY32))
222     {
223         SetLastError( ERROR_INSUFFICIENT_BUFFER );
224         ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(THREADENTRY32), lpte->dwSize);
225         return FALSE;
226     }
227     SERVER_START_REQ
228     {
229         struct next_thread_request *req = server_alloc_req( sizeof(*req), 0 );
230         req->handle = handle;
231         req->reset = first;
232         if ((ret = !server_call( REQ_NEXT_THREAD )))
233         {
234             lpte->cntUsage           = req->count;
235             lpte->th32ThreadID       = (DWORD)req->tid;
236             lpte->th32OwnerProcessID = (DWORD)req->pid;
237             lpte->tpBasePri          = req->base_pri;
238             lpte->tpDeltaPri         = req->delta_pri;
239             lpte->dwFlags            = 0;  /* SDK: "reserved; do not use" */
240         }
241     }
242     SERVER_END_REQ;
243     return ret;
244 }
245
246 /***********************************************************************
247  *              Thread32First    (KERNEL32.686)
248  *
249  * Return info about the first thread in a toolhelp32 snapshot
250  */
251 BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
252 {
253     return TOOLHELP_Thread32Next(hSnapshot, lpte, TRUE);
254 }
255
256 /***********************************************************************
257  *              Thread32Next   (KERNEL32.687)
258  *
259  * Return info about the "next" thread in a toolhelp32 snapshot
260  */
261 BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
262 {
263     return TOOLHELP_Thread32Next(hSnapshot, lpte, FALSE);
264 }
265
266 /***********************************************************************
267  *              TOOLHELP_Process32Next
268  *
269  * Implementation of Process32First/Next
270  */
271 static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32 lppe, BOOL first )
272 {
273     BOOL ret;
274
275     if (lppe->dwSize < sizeof(PROCESSENTRY32))
276     {
277         SetLastError( ERROR_INSUFFICIENT_BUFFER );
278         ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32), lppe->dwSize);
279         return FALSE;
280     }
281     SERVER_START_REQ
282     {
283         struct next_process_request *req = server_alloc_req( sizeof(*req), 0 );
284         req->handle = handle;
285         req->reset = first;
286         if ((ret = !server_call( REQ_NEXT_PROCESS )))
287         {
288             lppe->cntUsage            = req->count;
289             lppe->th32ProcessID       = (DWORD)req->pid;
290             lppe->th32DefaultHeapID   = 0;  /* FIXME */
291             lppe->th32ModuleID        = 0;  /* FIXME */
292             lppe->cntThreads          = req->threads;
293             lppe->th32ParentProcessID = 0;  /* FIXME */
294             lppe->pcPriClassBase      = req->priority;
295             lppe->dwFlags             = -1; /* FIXME */
296             lppe->szExeFile[0]        = 0;  /* FIXME */
297         }
298     }
299     SERVER_END_REQ;
300     return ret;
301 }
302
303
304 /***********************************************************************
305  *              Process32First    (KERNEL32.555)
306  *
307  * Return info about the first process in a toolhelp32 snapshot
308  */
309 BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
310 {
311     return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE );
312 }
313
314 /***********************************************************************
315  *              Process32Next   (KERNEL32.556)
316  *
317  * Return info about the "next" process in a toolhelp32 snapshot
318  */
319 BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
320 {
321     return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE );
322 }
323
324
325 /***********************************************************************
326  *              TOOLHELP_Module32Next
327  *
328  * Implementation of Module32First/Next
329  */
330 static BOOL TOOLHELP_Module32Next( HANDLE handle, LPMODULEENTRY32 lpme, BOOL first )
331 {
332     BOOL ret;
333
334     if (lpme->dwSize < sizeof (MODULEENTRY32))
335     {
336         SetLastError( ERROR_INSUFFICIENT_BUFFER );
337         ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32), lpme->dwSize);
338         return FALSE;
339     }
340     SERVER_START_REQ
341     {
342         struct next_module_request *req = server_alloc_req( sizeof(*req), 0 );
343         req->handle = handle;
344         req->reset = first;
345         if ((ret = !server_call( REQ_NEXT_MODULE )))
346         {
347             lpme->th32ModuleID   = 0;  /* toolhelp internal id, never used */
348             lpme->th32ProcessID  = (DWORD)req->pid;
349             lpme->GlblcntUsage   = 0; /* FIXME */
350             lpme->ProccntUsage   = 0; /* FIXME */ 
351             lpme->modBaseAddr    = req->base;
352             lpme->modBaseSize    = 0; /* FIXME */
353             lpme->hModule        = (DWORD)req->base;
354             lpme->szModule[0]    = 0;  /* FIXME */
355             lpme->szExePath[0]   = 0;  /* FIXME */
356         }
357     }
358     SERVER_END_REQ;
359     return ret;
360 }
361
362 /***********************************************************************
363  *              Module32First   (KERNEL32.527)
364  *
365  * Return info about the "first" module in a toolhelp32 snapshot
366  */
367 BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
368 {
369     return TOOLHELP_Module32Next( hSnapshot, lpme, TRUE );
370 }
371
372 /***********************************************************************
373  *              Module32Next   (KERNEL32.528)
374  *
375  * Return info about the "next" module in a toolhelp32 snapshot
376  */
377 BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
378 {
379     return TOOLHELP_Module32Next( hSnapshot, lpme, FALSE );
380 }
381
382 /************************************************************************
383  *              GlobalMasterHandle16 (KERNEL.28)
384  *
385  *
386  * Should return selector and handle of the information structure for 
387  * the global heap. selector and handle are stored in the THHOOK as
388  * pGlobalHeap and hGlobalHeap.
389  * As Wine doesn't have this structure, we return both values as zero
390  * Applications should interpret this as "No Global Heap"
391  */
392 DWORD WINAPI GlobalMasterHandle16(void)
393 {
394     FIXME(": stub\n");
395     return 0;
396 }