2 * Misc Toolhelp functions
4 * Copyright 1996 Marcus Meissner
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.
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.
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
33 #include "wine/winbase16.h"
38 #include "wine/server.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(toolhelp
);
44 /* FIXME: to make this work, we have to call back all these registered
45 * functions from all over the WINE code. Someone with more knowledge than
46 * me please do that. -Marcus
51 FARPROC16 lpfnCallback
;
55 static int nrofnotifys
= 0;
57 static FARPROC16 HookNotify
= NULL
;
59 /***********************************************************************
60 * NotifyRegister (TOOLHELP.73)
62 BOOL16 WINAPI
NotifyRegister16( HTASK16 htask
, FARPROC16 lpfnCallback
,
67 FIXME("(%x,%lx,%x), semi-stub.\n",
68 htask
, (DWORD
)lpfnCallback
, wFlags
);
69 if (!htask
) htask
= GetCurrentTask();
70 for (i
=0;i
<nrofnotifys
;i
++)
71 if (notifys
[i
].htask
==htask
)
75 notifys
=(struct notify
*)HeapAlloc( GetProcessHeap(), 0,
76 sizeof(struct notify
) );
78 notifys
=(struct notify
*)HeapReAlloc( GetProcessHeap(), 0, notifys
,
79 sizeof(struct notify
)*(nrofnotifys
+1));
80 if (!notifys
) return FALSE
;
83 notifys
[i
].htask
=htask
;
84 notifys
[i
].lpfnCallback
=lpfnCallback
;
85 notifys
[i
].wFlags
=wFlags
;
89 /***********************************************************************
90 * NotifyUnregister (TOOLHELP.74)
92 BOOL16 WINAPI
NotifyUnregister16( HTASK16 htask
)
96 FIXME("(%x), semi-stub.\n", htask
);
97 if (!htask
) htask
= GetCurrentTask();
98 for (i
=nrofnotifys
;i
--;)
99 if (notifys
[i
].htask
==htask
)
103 memcpy(notifys
+i
,notifys
+(i
+1),sizeof(struct notify
)*(nrofnotifys
-i
-1));
104 notifys
=(struct notify
*)HeapReAlloc( GetProcessHeap(), 0, notifys
,
105 (nrofnotifys
-1)*sizeof(struct notify
));
110 /***********************************************************************
111 * StackTraceCSIPFirst (TOOLHELP.67)
113 BOOL16 WINAPI
StackTraceCSIPFirst16(STACKTRACEENTRY
*ste
, WORD wSS
, WORD wCS
, WORD wIP
, WORD wBP
)
115 FIXME("(%p, ss %04x, cs %04x, ip %04x, bp %04x): stub.\n", ste
, wSS
, wCS
, wIP
, wBP
);
119 /***********************************************************************
120 * StackTraceFirst (TOOLHELP.66)
122 BOOL16 WINAPI
StackTraceFirst16(STACKTRACEENTRY
*ste
, HTASK16 Task
)
124 FIXME("(%p, %04x), stub.\n", ste
, Task
);
128 /***********************************************************************
129 * StackTraceNext (TOOLHELP.68)
131 BOOL16 WINAPI
StackTraceNext16(STACKTRACEENTRY
*ste
)
133 FIXME("(%p), stub.\n", ste
);
137 /***********************************************************************
138 * InterruptRegister (TOOLHELP.75)
140 BOOL16 WINAPI
InterruptRegister16( HTASK16 task
, FARPROC callback
)
142 FIXME("(%04x, %p), stub.\n", task
, callback
);
146 /***********************************************************************
147 * InterruptUnRegister (TOOLHELP.76)
149 BOOL16 WINAPI
InterruptUnRegister16( HTASK16 task
)
151 FIXME("(%04x), stub.\n", task
);
155 /***********************************************************************
156 * TimerCount (TOOLHELP.80)
158 BOOL16 WINAPI
TimerCount16( TIMERINFO
*pTimerInfo
)
161 * In standard mode, dwmsSinceStart = dwmsThisVM
163 * I tested this, under Windows in enhanced mode, and
164 * if you never switch VM (ie start/stop DOS) these
165 * values should be the same as well.
167 * Also, Wine should adjust for the hardware timer
168 * to reduce the amount of error to ~1ms.
169 * I can't be bothered, can you?
171 pTimerInfo
->dwmsSinceStart
= pTimerInfo
->dwmsThisVM
= GetTickCount();
175 /***********************************************************************
176 * SystemHeapInfo (TOOLHELP.71)
178 BOOL16 WINAPI
SystemHeapInfo16( SYSHEAPINFO
*pHeapInfo
)
180 WORD user
= LoadLibrary16( "USER.EXE" );
181 WORD gdi
= LoadLibrary16( "GDI.EXE" );
182 pHeapInfo
->wUserFreePercent
= (int)LOCAL_CountFree(user
) * 100 / LOCAL_HeapSize(user
);
183 pHeapInfo
->wGDIFreePercent
= (int)LOCAL_CountFree(gdi
) * 100 / LOCAL_HeapSize(gdi
);
184 pHeapInfo
->hUserSegment
= user
;
185 pHeapInfo
->hGDISegment
= gdi
;
186 FreeLibrary16( user
);
187 FreeLibrary16( gdi
);
192 /***********************************************************************
193 * ToolHelpHook (KERNEL.341)
194 * see "Undocumented Windows"
196 FARPROC16 WINAPI
ToolHelpHook16(FARPROC16 lpfnNotifyHandler
)
200 FIXME("(%p), stub.\n", lpfnNotifyHandler
);
202 HookNotify
= lpfnNotifyHandler
;
203 /* just return previously installed notification function */
208 /***********************************************************************
209 * CreateToolhelp32Snapshot (KERNEL32.@)
211 HANDLE WINAPI
CreateToolhelp32Snapshot( DWORD flags
, DWORD process
)
215 TRACE("%lx,%lx\n", flags
, process
);
216 if (!(flags
& (TH32CS_SNAPPROCESS
|TH32CS_SNAPTHREAD
|TH32CS_SNAPMODULE
)))
218 FIXME("flags %lx not implemented\n", flags
);
219 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
220 return INVALID_HANDLE_VALUE
;
223 /* Now do the snapshot */
224 SERVER_START_REQ( create_snapshot
)
227 if (flags
& TH32CS_SNAPMODULE
) req
->flags
|= SNAP_MODULE
;
228 if (flags
& TH32CS_SNAPPROCESS
) req
->flags
|= SNAP_PROCESS
;
229 if (flags
& TH32CS_SNAPTHREAD
) req
->flags
|= SNAP_THREAD
;
231 req
->inherit
= (flags
& TH32CS_INHERIT
) != 0;
233 wine_server_call_err( req
);
237 if (!ret
) ret
= INVALID_HANDLE_VALUE
;
242 /***********************************************************************
243 * TOOLHELP_Thread32Next
245 * Implementation of Thread32First/Next
247 static BOOL
TOOLHELP_Thread32Next( HANDLE handle
, LPTHREADENTRY32 lpte
, BOOL first
)
251 if (lpte
->dwSize
< sizeof(THREADENTRY32
))
253 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
254 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(THREADENTRY32
), lpte
->dwSize
);
257 SERVER_START_REQ( next_thread
)
259 req
->handle
= handle
;
261 if ((ret
= !wine_server_call_err( req
)))
263 lpte
->cntUsage
= reply
->count
;
264 lpte
->th32ThreadID
= (DWORD
)reply
->tid
;
265 lpte
->th32OwnerProcessID
= (DWORD
)reply
->pid
;
266 lpte
->tpBasePri
= reply
->base_pri
;
267 lpte
->tpDeltaPri
= reply
->delta_pri
;
268 lpte
->dwFlags
= 0; /* SDK: "reserved; do not use" */
275 /***********************************************************************
276 * Thread32First (KERNEL32.@)
278 * Return info about the first thread in a toolhelp32 snapshot
280 BOOL WINAPI
Thread32First(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
282 return TOOLHELP_Thread32Next(hSnapshot
, lpte
, TRUE
);
285 /***********************************************************************
286 * Thread32Next (KERNEL32.@)
288 * Return info about the "next" thread in a toolhelp32 snapshot
290 BOOL WINAPI
Thread32Next(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
292 return TOOLHELP_Thread32Next(hSnapshot
, lpte
, FALSE
);
295 /***********************************************************************
296 * TOOLHELP_Process32Next
298 * Implementation of Process32First/Next
300 static BOOL
TOOLHELP_Process32Next( HANDLE handle
, LPPROCESSENTRY32 lppe
, BOOL first
)
306 if (lppe
->dwSize
< sizeof(PROCESSENTRY32
))
308 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
309 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32
), lppe
->dwSize
);
312 SERVER_START_REQ( next_process
)
314 req
->handle
= handle
;
316 wine_server_set_reply( req
, exe
, sizeof(exe
) );
317 if ((ret
= !wine_server_call_err( req
)))
319 lppe
->cntUsage
= reply
->count
;
320 lppe
->th32ProcessID
= reply
->pid
;
321 lppe
->th32DefaultHeapID
= (DWORD
)reply
->heap
;
322 lppe
->th32ModuleID
= (DWORD
)reply
->module
;
323 lppe
->cntThreads
= reply
->threads
;
324 lppe
->th32ParentProcessID
= reply
->ppid
;
325 lppe
->pcPriClassBase
= reply
->priority
;
326 lppe
->dwFlags
= -1; /* FIXME */
327 len
= WideCharToMultiByte( CP_ACP
, 0, exe
, wine_server_reply_size(reply
) / sizeof(WCHAR
),
328 lppe
->szExeFile
, sizeof(lppe
->szExeFile
), NULL
, NULL
);
329 lppe
->szExeFile
[len
] = 0;
337 /***********************************************************************
338 * Process32First (KERNEL32.@)
340 * Return info about the first process in a toolhelp32 snapshot
342 BOOL WINAPI
Process32First(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
344 return TOOLHELP_Process32Next( hSnapshot
, lppe
, TRUE
);
347 /***********************************************************************
348 * Process32Next (KERNEL32.@)
350 * Return info about the "next" process in a toolhelp32 snapshot
352 BOOL WINAPI
Process32Next(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
354 return TOOLHELP_Process32Next( hSnapshot
, lppe
, FALSE
);
358 /***********************************************************************
359 * TOOLHELP_Module32Next
361 * Implementation of Module32First/Next
363 static BOOL
TOOLHELP_Module32Next( HANDLE handle
, LPMODULEENTRY32 lpme
, BOOL first
)
369 if (lpme
->dwSize
< sizeof (MODULEENTRY32
))
371 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
372 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32
), lpme
->dwSize
);
375 SERVER_START_REQ( next_module
)
377 req
->handle
= handle
;
379 wine_server_set_reply( req
, exe
, sizeof(exe
) );
380 if ((ret
= !wine_server_call_err( req
)))
382 lpme
->th32ModuleID
= 0; /* toolhelp internal id, never used */
383 lpme
->th32ProcessID
= reply
->pid
;
384 lpme
->GlblcntUsage
= 0; /* FIXME */
385 lpme
->ProccntUsage
= 0; /* FIXME */
386 lpme
->modBaseAddr
= reply
->base
;
387 lpme
->modBaseSize
= reply
->size
;
388 lpme
->hModule
= reply
->base
;
389 lpme
->szModule
[0] = 0; /* FIXME */
390 len
= WideCharToMultiByte( CP_ACP
, 0, exe
, wine_server_reply_size(reply
) / sizeof(WCHAR
),
391 lpme
->szExePath
, sizeof(lpme
->szExePath
), NULL
, NULL
);
392 lpme
->szExePath
[len
] = 0;
399 /***********************************************************************
400 * Module32First (KERNEL32.@)
402 * Return info about the "first" module in a toolhelp32 snapshot
404 BOOL WINAPI
Module32First(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
406 return TOOLHELP_Module32Next( hSnapshot
, lpme
, TRUE
);
409 /***********************************************************************
410 * Module32Next (KERNEL32.@)
412 * Return info about the "next" module in a toolhelp32 snapshot
414 BOOL WINAPI
Module32Next(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
416 return TOOLHELP_Module32Next( hSnapshot
, lpme
, FALSE
);
419 /************************************************************************
420 * GlobalMasterHandle (KERNEL.28)
423 * Should return selector and handle of the information structure for
424 * the global heap. selector and handle are stored in the THHOOK as
425 * pGlobalHeap and hGlobalHeap.
426 * As Wine doesn't have this structure, we return both values as zero
427 * Applications should interpret this as "No Global Heap"
429 DWORD WINAPI
GlobalMasterHandle16(void)
435 /************************************************************************
436 * Heap32ListFirst (KERNEL.@)
439 BOOL WINAPI
Heap32ListFirst(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
445 /******************************************************************
446 * Toolhelp32ReadProcessMemory (KERNEL.@)
450 BOOL WINAPI
Toolhelp32ReadProcessMemory(DWORD pid
, const void* base
,
451 void* buf
, SIZE_T len
, SIZE_T
* r
)
456 h
= (pid
) ? OpenProcess(PROCESS_VM_READ
, FALSE
, pid
) : GetCurrentProcess();
459 ret
= ReadProcessMemory(h
, base
, buf
, len
, r
);
460 if (pid
) CloseHandle(h
);