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 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)
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 TRACE("(%x) called.\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)
99 /***********************************************************************
102 BOOL16 WINAPI StackTraceFirst16(STACKTRACEENTRY *ste, HTASK16 Task)
107 /***********************************************************************
110 BOOL16 WINAPI StackTraceNext16(STACKTRACEENTRY *ste)
115 /***********************************************************************
116 * InterruptRegister16
118 BOOL16 WINAPI InterruptRegister16( HTASK16 task, FARPROC callback )
123 /***********************************************************************
124 * InterruptUnRegister16
126 BOOL16 WINAPI InterruptUnRegister16( HTASK16 task )
131 /***********************************************************************
132 * TimerCount (TOOLHELP.80)
134 BOOL16 WINAPI TimerCount16( TIMERINFO *pTimerInfo )
137 * In standard mode, dwmsSinceStart = dwmsThisVM
139 * I tested this, under Windows in enhanced mode, and
140 * if you never switch VM (ie start/stop DOS) these
141 * values should be the same as well.
143 * Also, Wine should adjust for the hardware timer
144 * to reduce the amount of error to ~1ms.
145 * I can't be bothered, can you?
147 pTimerInfo->dwmsSinceStart = pTimerInfo->dwmsThisVM = GetTickCount();
151 /***********************************************************************
152 * SystemHeapInfo (TOOLHELP.71)
154 BOOL16 WINAPI SystemHeapInfo16( SYSHEAPINFO *pHeapInfo )
156 WORD user = LoadLibrary16( "USER.EXE" );
157 WORD gdi = LoadLibrary16( "GDI.EXE" );
158 pHeapInfo->wUserFreePercent = (int)LOCAL_CountFree(user) * 100 / LOCAL_HeapSize(user);
159 pHeapInfo->wGDIFreePercent = (int)LOCAL_CountFree(gdi) * 100 / LOCAL_HeapSize(gdi);
160 pHeapInfo->hUserSegment = user;
161 pHeapInfo->hGDISegment = gdi;
162 FreeLibrary16( user );
163 FreeLibrary16( gdi );
168 /***********************************************************************
169 * ToolHelpHook (KERNEL.341)
170 * see "Undocumented Windows"
172 FARPROC16 WINAPI ToolHelpHook16(FARPROC16 lpfnNotifyHandler)
176 HookNotify = lpfnNotifyHandler;
177 /* just return previously installed notification function */
182 /***********************************************************************
183 * CreateToolhelp32Snapshot (KERNEL32.179)
185 HANDLE WINAPI CreateToolhelp32Snapshot( DWORD flags, DWORD process )
189 TRACE("%lx,%lx\n", flags, process );
190 if (!(flags & (TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD|TH32CS_SNAPMODULE)))
192 FIXME("flags %lx not implemented\n", flags );
193 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
194 return INVALID_HANDLE_VALUE;
197 /* Now do the snapshot */
200 struct create_snapshot_request *req = server_alloc_req( sizeof(*req), 0 );
201 req->flags = flags & ~TH32CS_INHERIT;
202 req->inherit = (flags & TH32CS_INHERIT) != 0;
203 req->pid = (void *)process;
204 server_call( REQ_CREATE_SNAPSHOT );
212 /***********************************************************************
213 * TOOLHELP_Thread32Next
215 * Implementation of Thread32First/Next
217 static BOOL TOOLHELP_Thread32Next( HANDLE handle, LPTHREADENTRY32 lpte, BOOL first )
221 if (lpte->dwSize < sizeof(THREADENTRY32))
223 SetLastError( ERROR_INSUFFICIENT_BUFFER );
224 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(THREADENTRY32), lpte->dwSize);
229 struct next_thread_request *req = server_alloc_req( sizeof(*req), 0 );
230 req->handle = handle;
232 if ((ret = !server_call( REQ_NEXT_THREAD )))
234 lpte->cntUsage = req->count;
235 lpte->th32ThreadID = (DWORD)req->tid;
236 lpte->th32OwnerProcessID = (DWORD)req->pid;
237 lpte->tpBasePri = req->base_pri;
238 lpte->tpDeltaPri = req->delta_pri;
239 lpte->dwFlags = 0; /* SDK: "reserved; do not use" */
246 /***********************************************************************
247 * Thread32First (KERNEL32.686)
249 * Return info about the first thread in a toolhelp32 snapshot
251 BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
253 return TOOLHELP_Thread32Next(hSnapshot, lpte, TRUE);
256 /***********************************************************************
257 * Thread32Next (KERNEL32.687)
259 * Return info about the "next" thread in a toolhelp32 snapshot
261 BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
263 return TOOLHELP_Thread32Next(hSnapshot, lpte, FALSE);
266 /***********************************************************************
267 * TOOLHELP_Process32Next
269 * Implementation of Process32First/Next
271 static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32 lppe, BOOL first )
275 if (lppe->dwSize < sizeof(PROCESSENTRY32))
277 SetLastError( ERROR_INSUFFICIENT_BUFFER );
278 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32), lppe->dwSize);
283 struct next_process_request *req = server_alloc_req( sizeof(*req), 0 );
284 req->handle = handle;
286 if ((ret = !server_call( REQ_NEXT_PROCESS )))
288 lppe->cntUsage = req->count;
289 lppe->th32ProcessID = (DWORD)req->pid;
290 lppe->th32DefaultHeapID = 0; /* FIXME */
291 lppe->th32ModuleID = 0; /* FIXME */
292 lppe->cntThreads = req->threads;
293 lppe->th32ParentProcessID = 0; /* FIXME */
294 lppe->pcPriClassBase = req->priority;
295 lppe->dwFlags = -1; /* FIXME */
296 lppe->szExeFile[0] = 0; /* FIXME */
304 /***********************************************************************
305 * Process32First (KERNEL32.555)
307 * Return info about the first process in a toolhelp32 snapshot
309 BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
311 return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE );
314 /***********************************************************************
315 * Process32Next (KERNEL32.556)
317 * Return info about the "next" process in a toolhelp32 snapshot
319 BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
321 return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE );
325 /***********************************************************************
326 * TOOLHELP_Module32Next
328 * Implementation of Module32First/Next
330 static BOOL TOOLHELP_Module32Next( HANDLE handle, LPMODULEENTRY32 lpme, BOOL first )
334 if (lpme->dwSize < sizeof (MODULEENTRY32))
336 SetLastError( ERROR_INSUFFICIENT_BUFFER );
337 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32), lpme->dwSize);
342 struct next_module_request *req = server_alloc_req( sizeof(*req), 0 );
343 req->handle = handle;
345 if ((ret = !server_call( REQ_NEXT_MODULE )))
347 lpme->th32ModuleID = 0; /* toolhelp internal id, never used */
348 lpme->th32ProcessID = (DWORD)req->pid;
349 lpme->GlblcntUsage = 0; /* FIXME */
350 lpme->ProccntUsage = 0; /* FIXME */
351 lpme->modBaseAddr = req->base;
352 lpme->modBaseSize = 0; /* FIXME */
353 lpme->hModule = (DWORD)req->base;
354 lpme->szModule[0] = 0; /* FIXME */
355 lpme->szExePath[0] = 0; /* FIXME */
362 /***********************************************************************
363 * Module32First (KERNEL32.527)
365 * Return info about the "first" module in a toolhelp32 snapshot
367 BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
369 return TOOLHELP_Module32Next( hSnapshot, lpme, TRUE );
372 /***********************************************************************
373 * Module32Next (KERNEL32.528)
375 * Return info about the "next" module in a toolhelp32 snapshot
377 BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
379 return TOOLHELP_Module32Next( hSnapshot, lpme, FALSE );
382 /************************************************************************
383 * GlobalMasterHandle16 (KERNEL.28)
386 * Should return selector and handle of the information structure for
387 * the global heap. selector and handle are stored in the THHOOK as
388 * pGlobalHeap and hGlobalHeap.
389 * As Wine doesn't have this structure, we return both values as zero
390 * Applications should interpret this as "No Global Heap"
392 DWORD WINAPI GlobalMasterHandle16(void)