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