2 * Misc Toolhelp functions
4 * Copyright 1996 Marcus Meissner
13 #include "wine/winbase16.h"
20 #include "debugtools.h"
22 DEFAULT_DEBUG_CHANNEL(toolhelp
);
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
32 FARPROC16 lpfnCallback
;
36 static int nrofnotifys
= 0;
38 static FARPROC16 HookNotify
= NULL
;
40 /***********************************************************************
43 BOOL16 WINAPI
NotifyRegister16( HTASK16 htask
, FARPROC16 lpfnCallback
,
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
)
56 notifys
=(struct notify
*)HeapAlloc( GetProcessHeap(), 0,
57 sizeof(struct notify
) );
59 notifys
=(struct notify
*)HeapReAlloc( GetProcessHeap(), 0, notifys
,
60 sizeof(struct notify
)*(nrofnotifys
+1));
61 if (!notifys
) return FALSE
;
64 notifys
[i
].htask
=htask
;
65 notifys
[i
].lpfnCallback
=lpfnCallback
;
66 notifys
[i
].wFlags
=wFlags
;
70 /***********************************************************************
73 BOOL16 WINAPI
NotifyUnregister16( HTASK16 htask
)
77 FIXME("(%x), semi-stub.\n", htask
);
78 if (!htask
) htask
= GetCurrentTask();
79 for (i
=nrofnotifys
;i
--;)
80 if (notifys
[i
].htask
==htask
)
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
));
91 /***********************************************************************
92 * StackTraceCSIPFirst16
94 BOOL16 WINAPI
StackTraceCSIPFirst16(STACKTRACEENTRY
*ste
, WORD wSS
, WORD wCS
, WORD wIP
, WORD wBP
)
96 FIXME("(%p, ss %04x, cs %04x, ip %04x, bp %04x): stub.\n", ste
, wSS
, wCS
, wIP
, wBP
);
100 /***********************************************************************
103 BOOL16 WINAPI
StackTraceFirst16(STACKTRACEENTRY
*ste
, HTASK16 Task
)
105 FIXME("(%p, %04x), stub.\n", ste
, Task
);
109 /***********************************************************************
112 BOOL16 WINAPI
StackTraceNext16(STACKTRACEENTRY
*ste
)
114 FIXME("(%p), stub.\n", ste
);
118 /***********************************************************************
119 * InterruptRegister16
121 BOOL16 WINAPI
InterruptRegister16( HTASK16 task
, FARPROC callback
)
123 FIXME("(%04x, %p), stub.\n", task
, callback
);
127 /***********************************************************************
128 * InterruptUnRegister16
130 BOOL16 WINAPI
InterruptUnRegister16( HTASK16 task
)
132 FIXME("(%04x), stub.\n", task
);
136 /***********************************************************************
137 * TimerCount (TOOLHELP.80)
139 BOOL16 WINAPI
TimerCount16( TIMERINFO
*pTimerInfo
)
142 * In standard mode, dwmsSinceStart = dwmsThisVM
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.
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?
152 pTimerInfo
->dwmsSinceStart
= pTimerInfo
->dwmsThisVM
= GetTickCount();
156 /***********************************************************************
157 * SystemHeapInfo (TOOLHELP.71)
159 BOOL16 WINAPI
SystemHeapInfo16( SYSHEAPINFO
*pHeapInfo
)
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
);
173 /***********************************************************************
174 * ToolHelpHook (KERNEL.341)
175 * see "Undocumented Windows"
177 FARPROC16 WINAPI
ToolHelpHook16(FARPROC16 lpfnNotifyHandler
)
181 FIXME("(%p), stub.\n", lpfnNotifyHandler
);
183 HookNotify
= lpfnNotifyHandler
;
184 /* just return previously installed notification function */
189 /***********************************************************************
190 * CreateToolhelp32Snapshot (KERNEL32.179)
192 HANDLE WINAPI
CreateToolhelp32Snapshot( DWORD flags
, DWORD process
)
196 TRACE("%lx,%lx\n", flags
, process
);
197 if (!(flags
& (TH32CS_SNAPPROCESS
|TH32CS_SNAPTHREAD
|TH32CS_SNAPMODULE
)))
199 FIXME("flags %lx not implemented\n", flags
);
200 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
201 return INVALID_HANDLE_VALUE
;
204 /* Now do the snapshot */
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
);
219 /***********************************************************************
220 * TOOLHELP_Thread32Next
222 * Implementation of Thread32First/Next
224 static BOOL
TOOLHELP_Thread32Next( HANDLE handle
, LPTHREADENTRY32 lpte
, BOOL first
)
228 if (lpte
->dwSize
< sizeof(THREADENTRY32
))
230 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
231 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(THREADENTRY32
), lpte
->dwSize
);
236 struct next_thread_request
*req
= server_alloc_req( sizeof(*req
), 0 );
237 req
->handle
= handle
;
239 if ((ret
= !server_call( REQ_NEXT_THREAD
)))
241 lpte
->cntUsage
= req
->count
;
242 lpte
->th32ThreadID
= (DWORD
)req
->tid
;
243 lpte
->th32OwnerProcessID
= (DWORD
)req
->pid
;
244 lpte
->tpBasePri
= req
->base_pri
;
245 lpte
->tpDeltaPri
= req
->delta_pri
;
246 lpte
->dwFlags
= 0; /* SDK: "reserved; do not use" */
253 /***********************************************************************
254 * Thread32First (KERNEL32.686)
256 * Return info about the first thread in a toolhelp32 snapshot
258 BOOL WINAPI
Thread32First(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
260 return TOOLHELP_Thread32Next(hSnapshot
, lpte
, TRUE
);
263 /***********************************************************************
264 * Thread32Next (KERNEL32.687)
266 * Return info about the "next" thread in a toolhelp32 snapshot
268 BOOL WINAPI
Thread32Next(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
270 return TOOLHELP_Thread32Next(hSnapshot
, lpte
, FALSE
);
273 /***********************************************************************
274 * TOOLHELP_Process32Next
276 * Implementation of Process32First/Next
278 static BOOL
TOOLHELP_Process32Next( HANDLE handle
, LPPROCESSENTRY32 lppe
, BOOL first
)
282 if (lppe
->dwSize
< sizeof(PROCESSENTRY32
))
284 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
285 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32
), lppe
->dwSize
);
290 struct next_process_request
*req
= server_alloc_req( sizeof(*req
), 0 );
291 req
->handle
= handle
;
293 if ((ret
= !server_call( REQ_NEXT_PROCESS
)))
295 lppe
->cntUsage
= req
->count
;
296 lppe
->th32ProcessID
= (DWORD
)req
->pid
;
297 lppe
->th32DefaultHeapID
= 0; /* FIXME */
298 lppe
->th32ModuleID
= 0; /* FIXME */
299 lppe
->cntThreads
= req
->threads
;
300 lppe
->th32ParentProcessID
= 0; /* FIXME */
301 lppe
->pcPriClassBase
= req
->priority
;
302 lppe
->dwFlags
= -1; /* FIXME */
303 lppe
->szExeFile
[0] = 0; /* FIXME */
311 /***********************************************************************
312 * Process32First (KERNEL32.555)
314 * Return info about the first process in a toolhelp32 snapshot
316 BOOL WINAPI
Process32First(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
318 return TOOLHELP_Process32Next( hSnapshot
, lppe
, TRUE
);
321 /***********************************************************************
322 * Process32Next (KERNEL32.556)
324 * Return info about the "next" process in a toolhelp32 snapshot
326 BOOL WINAPI
Process32Next(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
328 return TOOLHELP_Process32Next( hSnapshot
, lppe
, FALSE
);
332 /***********************************************************************
333 * TOOLHELP_Module32Next
335 * Implementation of Module32First/Next
337 static BOOL
TOOLHELP_Module32Next( HANDLE handle
, LPMODULEENTRY32 lpme
, BOOL first
)
341 if (lpme
->dwSize
< sizeof (MODULEENTRY32
))
343 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
344 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32
), lpme
->dwSize
);
349 struct next_module_request
*req
= server_alloc_req( sizeof(*req
), 0 );
350 req
->handle
= handle
;
352 if ((ret
= !server_call( REQ_NEXT_MODULE
)))
354 lpme
->th32ModuleID
= 0; /* toolhelp internal id, never used */
355 lpme
->th32ProcessID
= (DWORD
)req
->pid
;
356 lpme
->GlblcntUsage
= 0; /* FIXME */
357 lpme
->ProccntUsage
= 0; /* FIXME */
358 lpme
->modBaseAddr
= req
->base
;
359 lpme
->modBaseSize
= 0; /* FIXME */
360 lpme
->hModule
= (DWORD
)req
->base
;
361 lpme
->szModule
[0] = 0; /* FIXME */
362 lpme
->szExePath
[0] = 0; /* FIXME */
369 /***********************************************************************
370 * Module32First (KERNEL32.527)
372 * Return info about the "first" module in a toolhelp32 snapshot
374 BOOL WINAPI
Module32First(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
376 return TOOLHELP_Module32Next( hSnapshot
, lpme
, TRUE
);
379 /***********************************************************************
380 * Module32Next (KERNEL32.528)
382 * Return info about the "next" module in a toolhelp32 snapshot
384 BOOL WINAPI
Module32Next(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
386 return TOOLHELP_Module32Next( hSnapshot
, lpme
, FALSE
);
389 /************************************************************************
390 * GlobalMasterHandle16 (KERNEL.28)
393 * Should return selector and handle of the information structure for
394 * the global heap. selector and handle are stored in the THHOOK as
395 * pGlobalHeap and hGlobalHeap.
396 * As Wine doesn't have this structure, we return both values as zero
397 * Applications should interpret this as "No Global Heap"
399 DWORD WINAPI
GlobalMasterHandle16(void)