Handle WM_CHARs and pass them to TREEVIEW_ProcessLetterKeys. See also
[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 (TOOLHELP.73)
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 (TOOLHELP.74)
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  *              StackTraceCSIPFirst (TOOLHELP.67)
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  *              StackTraceFirst (TOOLHELP.66)
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  *              StackTraceNext (TOOLHELP.68)
111  */
112 BOOL16 WINAPI StackTraceNext16(STACKTRACEENTRY *ste)
113 {
114     FIXME("(%p), stub.\n", ste);
115     return TRUE;
116 }
117
118 /***********************************************************************
119  *              InterruptRegister (TOOLHELP.75)
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  *              InterruptUnRegister (TOOLHELP.76)
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     if (!ret) ret = INVALID_HANDLE_VALUE;
216     return ret;
217 }
218
219
220 /***********************************************************************
221  *              TOOLHELP_Thread32Next
222  *
223  * Implementation of Thread32First/Next
224  */
225 static BOOL TOOLHELP_Thread32Next( HANDLE handle, LPTHREADENTRY32 lpte, BOOL first )
226 {
227     BOOL ret;
228
229     if (lpte->dwSize < sizeof(THREADENTRY32))
230     {
231         SetLastError( ERROR_INSUFFICIENT_BUFFER );
232         ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(THREADENTRY32), lpte->dwSize);
233         return FALSE;
234     }
235     SERVER_START_REQ
236     {
237         struct next_thread_request *req = server_alloc_req( sizeof(*req), 0 );
238         req->handle = handle;
239         req->reset = first;
240         if ((ret = !server_call( REQ_NEXT_THREAD )))
241         {
242             lpte->cntUsage           = req->count;
243             lpte->th32ThreadID       = (DWORD)req->tid;
244             lpte->th32OwnerProcessID = (DWORD)req->pid;
245             lpte->tpBasePri          = req->base_pri;
246             lpte->tpDeltaPri         = req->delta_pri;
247             lpte->dwFlags            = 0;  /* SDK: "reserved; do not use" */
248         }
249     }
250     SERVER_END_REQ;
251     return ret;
252 }
253
254 /***********************************************************************
255  *              Thread32First    (KERNEL32.686)
256  *
257  * Return info about the first thread in a toolhelp32 snapshot
258  */
259 BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
260 {
261     return TOOLHELP_Thread32Next(hSnapshot, lpte, TRUE);
262 }
263
264 /***********************************************************************
265  *              Thread32Next   (KERNEL32.687)
266  *
267  * Return info about the "next" thread in a toolhelp32 snapshot
268  */
269 BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
270 {
271     return TOOLHELP_Thread32Next(hSnapshot, lpte, FALSE);
272 }
273
274 /***********************************************************************
275  *              TOOLHELP_Process32Next
276  *
277  * Implementation of Process32First/Next
278  */
279 static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32 lppe, BOOL first )
280 {
281     BOOL ret;
282
283     if (lppe->dwSize < sizeof(PROCESSENTRY32))
284     {
285         SetLastError( ERROR_INSUFFICIENT_BUFFER );
286         ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32), lppe->dwSize);
287         return FALSE;
288     }
289     SERVER_START_REQ
290     {
291         struct next_process_request *req = server_alloc_req( sizeof(*req), 0 );
292         req->handle = handle;
293         req->reset = first;
294         if ((ret = !server_call( REQ_NEXT_PROCESS )))
295         {
296             lppe->cntUsage            = req->count;
297             lppe->th32ProcessID       = (DWORD)req->pid;
298             lppe->th32DefaultHeapID   = 0;  /* FIXME */
299             lppe->th32ModuleID        = 0;  /* FIXME */
300             lppe->cntThreads          = req->threads;
301             lppe->th32ParentProcessID = 0;  /* FIXME */
302             lppe->pcPriClassBase      = req->priority;
303             lppe->dwFlags             = -1; /* FIXME */
304             lppe->szExeFile[0]        = 0;  /* FIXME */
305         }
306     }
307     SERVER_END_REQ;
308     return ret;
309 }
310
311
312 /***********************************************************************
313  *              Process32First    (KERNEL32.555)
314  *
315  * Return info about the first process in a toolhelp32 snapshot
316  */
317 BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
318 {
319     return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE );
320 }
321
322 /***********************************************************************
323  *              Process32Next   (KERNEL32.556)
324  *
325  * Return info about the "next" process in a toolhelp32 snapshot
326  */
327 BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
328 {
329     return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE );
330 }
331
332
333 /***********************************************************************
334  *              TOOLHELP_Module32Next
335  *
336  * Implementation of Module32First/Next
337  */
338 static BOOL TOOLHELP_Module32Next( HANDLE handle, LPMODULEENTRY32 lpme, BOOL first )
339 {
340     BOOL ret;
341
342     if (lpme->dwSize < sizeof (MODULEENTRY32))
343     {
344         SetLastError( ERROR_INSUFFICIENT_BUFFER );
345         ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32), lpme->dwSize);
346         return FALSE;
347     }
348     SERVER_START_REQ
349     {
350         struct next_module_request *req = server_alloc_req( sizeof(*req), 0 );
351         req->handle = handle;
352         req->reset = first;
353         if ((ret = !server_call( REQ_NEXT_MODULE )))
354         {
355             lpme->th32ModuleID   = 0;  /* toolhelp internal id, never used */
356             lpme->th32ProcessID  = (DWORD)req->pid;
357             lpme->GlblcntUsage   = 0; /* FIXME */
358             lpme->ProccntUsage   = 0; /* FIXME */ 
359             lpme->modBaseAddr    = req->base;
360             lpme->modBaseSize    = 0; /* FIXME */
361             lpme->hModule        = (DWORD)req->base;
362             lpme->szModule[0]    = 0;  /* FIXME */
363             lpme->szExePath[0]   = 0;  /* FIXME */
364         }
365     }
366     SERVER_END_REQ;
367     return ret;
368 }
369
370 /***********************************************************************
371  *              Module32First   (KERNEL32.527)
372  *
373  * Return info about the "first" module in a toolhelp32 snapshot
374  */
375 BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
376 {
377     return TOOLHELP_Module32Next( hSnapshot, lpme, TRUE );
378 }
379
380 /***********************************************************************
381  *              Module32Next   (KERNEL32.528)
382  *
383  * Return info about the "next" module in a toolhelp32 snapshot
384  */
385 BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
386 {
387     return TOOLHELP_Module32Next( hSnapshot, lpme, FALSE );
388 }
389
390 /************************************************************************
391  *              GlobalMasterHandle16 (KERNEL.28)
392  *
393  *
394  * Should return selector and handle of the information structure for 
395  * the global heap. selector and handle are stored in the THHOOK as
396  * pGlobalHeap and hGlobalHeap.
397  * As Wine doesn't have this structure, we return both values as zero
398  * Applications should interpret this as "No Global Heap"
399  */
400 DWORD WINAPI GlobalMasterHandle16(void)
401 {
402     FIXME(": stub\n");
403     return 0;
404 }