Do not dereference a ptr we just checked being NULL.
[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 "winbase.h"
13 #include "wine/winbase16.h"
14 #include "winerror.h"
15 #include "process.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  *           ToolHelpHook                             (KERNEL.341)
133  *      see "Undocumented Windows"
134  */
135 FARPROC16 WINAPI ToolHelpHook16(FARPROC16 lpfnNotifyHandler)
136 {
137 FARPROC16 tmp;
138         tmp = HookNotify;
139         HookNotify = lpfnNotifyHandler;
140         /* just return previously installed notification function */
141         return tmp;
142 }
143
144
145 /***********************************************************************
146  *           CreateToolhelp32Snapshot                   (KERNEL32.179)
147  */
148 HANDLE WINAPI CreateToolhelp32Snapshot( DWORD flags, DWORD process ) 
149 {
150     struct create_snapshot_request *req = get_req_buffer();
151
152     TRACE("%lx,%lx\n", flags, process );
153     if (flags & (TH32CS_SNAPHEAPLIST|TH32CS_SNAPMODULE|TH32CS_SNAPTHREAD))
154         FIXME("flags %lx not implemented\n", flags );
155     if (!(flags & TH32CS_SNAPPROCESS))
156     {
157         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
158         return INVALID_HANDLE_VALUE;
159     }
160     
161     /* Now do the snapshot */
162     req->flags   = flags & ~TH32CS_INHERIT;
163     req->inherit = (flags & TH32CS_INHERIT) != 0;
164     server_call( REQ_CREATE_SNAPSHOT );
165     return req->handle;
166 }
167
168
169 /***********************************************************************
170  *              Thread32First    (KERNEL32.686)
171  *
172  * Return info about the first thread in a toolhelp32 snapshot
173  */
174 BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY lpte)
175 {
176     if (!lpte)
177         return FALSE;
178
179     FIXME("(%d,%p),stub!\n",hSnapshot,lpte);
180     return FALSE;
181 }
182
183 /***********************************************************************
184  *              Thread32Next   (KERNEL32.687)
185  *
186  * Return info about the "next" thread in a toolhelp32 snapshot
187  */
188 BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY lpte)
189 {
190     if (!lpte)
191         return FALSE;
192
193     FIXME("(%d,%p),stub!\n",hSnapshot,lpte);
194     return FALSE;
195 }
196
197 /***********************************************************************
198  *              TOOLHELP_Process32Next
199  *
200  * Implementation of Process32First/Next
201  */
202 static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY lppe, BOOL first )
203 {
204     struct next_process_request *req = get_req_buffer();
205
206     if (lppe->dwSize < sizeof (PROCESSENTRY))
207     {
208         SetLastError( ERROR_INSUFFICIENT_BUFFER );
209         ERR("Result buffer too small\n");
210         return FALSE;
211     }
212     req->handle = handle;
213     req->reset = first;
214     if (server_call( REQ_NEXT_PROCESS )) return FALSE;
215     lppe->cntUsage            = 1;
216     lppe->th32ProcessID       = (DWORD)req->pid;
217     lppe->th32DefaultHeapID   = 0;  /* FIXME */ 
218     lppe->th32ModuleID        = 0;  /* FIXME */
219     lppe->cntThreads          = req->threads;
220     lppe->th32ParentProcessID = 0;  /* FIXME */
221     lppe->pcPriClassBase      = req->priority;
222     lppe->dwFlags             = -1; /* FIXME */
223     lppe->szExeFile[0]        = 0;  /* FIXME */
224     return TRUE;
225 }
226
227
228 /***********************************************************************
229  *              Process32First    (KERNEL32.555)
230  *
231  * Return info about the first process in a toolhelp32 snapshot
232  */
233 BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY lppe)
234 {
235     return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE );
236 }
237
238 /***********************************************************************
239  *              Process32Next   (KERNEL32.556)
240  *
241  * Return info about the "next" process in a toolhelp32 snapshot
242  */
243 BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY lppe)
244 {
245     return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE );
246 }
247
248 /***********************************************************************
249  *              Module32First   (KERNEL32.527)
250  *
251  * Return info about the "first" module in a toolhelp32 snapshot
252  */
253 BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY lpme)
254 {
255     FIXME("(%d,%p),stub!\n",hSnapshot,lpme);
256     return FALSE;
257 }
258
259 /***********************************************************************
260  *              Module32Next   (KERNEL32.528)
261  *
262  * Return info about the "next" module in a toolhelp32 snapshot
263  */
264 BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY lpme)
265 {
266     FIXME("(%d,%p),stub!\n",hSnapshot,lpme);
267     return FALSE;
268 }
269
270 /************************************************************************
271  *              GlobalMasterHandle16 (KERNEL.28)
272  *
273  *
274  * Should return selector and handle of the information structure for 
275  * the global heap. selector and handle are stored in the THHOOK as
276  * pGlobalHeap and hGlobalHeap.
277  * As Wine doesn't have this structure, we return both values as zero
278  * Applications should interpret this as "No Global Heap"
279  */
280 DWORD WINAPI GlobalMasterHandle16(void)
281 {
282     FIXME(": stub\n");
283     return 0;
284 }