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 )
187 struct create_snapshot_request *req = get_req_buffer();
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 */
198 req->flags = flags & ~TH32CS_INHERIT;
199 req->inherit = (flags & TH32CS_INHERIT) != 0;
200 req->pid = (void *)process;
201 server_call( REQ_CREATE_SNAPSHOT );
206 /***********************************************************************
207 * TOOLHELP_Thread32Next
209 * Implementation of Thread32First/Next
211 static BOOL TOOLHELP_Thread32Next( HANDLE handle, LPTHREADENTRY32 lpte, BOOL first )
213 struct next_thread_request *req = get_req_buffer();
215 if (lpte->dwSize < sizeof(THREADENTRY32))
217 SetLastError( ERROR_INSUFFICIENT_BUFFER );
218 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(THREADENTRY32), lpte->dwSize);
221 req->handle = handle;
223 if (server_call( REQ_NEXT_THREAD )) return FALSE;
224 lpte->cntUsage = req->count;
225 lpte->th32ThreadID = (DWORD)req->tid;
226 lpte->th32OwnerProcessID = (DWORD)req->pid;
227 lpte->tbBasePri = req->base_pri;
228 lpte->tbDeltaPri = req->delta_pri;
229 lpte->dwFlags = 0; /* SDK: "reserved; do not use" */
233 /***********************************************************************
234 * Thread32First (KERNEL32.686)
236 * Return info about the first thread in a toolhelp32 snapshot
238 BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
240 return TOOLHELP_Thread32Next(hSnapshot, lpte, TRUE);
243 /***********************************************************************
244 * Thread32Next (KERNEL32.687)
246 * Return info about the "next" thread in a toolhelp32 snapshot
248 BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
250 return TOOLHELP_Thread32Next(hSnapshot, lpte, FALSE);
253 /***********************************************************************
254 * TOOLHELP_Process32Next
256 * Implementation of Process32First/Next
258 static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32 lppe, BOOL first )
260 struct next_process_request *req = get_req_buffer();
262 if (lppe->dwSize < sizeof(PROCESSENTRY32))
264 SetLastError( ERROR_INSUFFICIENT_BUFFER );
265 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32), lppe->dwSize);
268 req->handle = handle;
270 if (server_call( REQ_NEXT_PROCESS )) return FALSE;
271 lppe->cntUsage = req->count;
272 lppe->th32ProcessID = (DWORD)req->pid;
273 lppe->th32DefaultHeapID = 0; /* FIXME */
274 lppe->th32ModuleID = 0; /* FIXME */
275 lppe->cntThreads = req->threads;
276 lppe->th32ParentProcessID = 0; /* FIXME */
277 lppe->pcPriClassBase = req->priority;
278 lppe->dwFlags = -1; /* FIXME */
279 lppe->szExeFile[0] = 0; /* FIXME */
284 /***********************************************************************
285 * Process32First (KERNEL32.555)
287 * Return info about the first process in a toolhelp32 snapshot
289 BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
291 return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE );
294 /***********************************************************************
295 * Process32Next (KERNEL32.556)
297 * Return info about the "next" process in a toolhelp32 snapshot
299 BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
301 return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE );
305 /***********************************************************************
306 * TOOLHELP_Module32Next
308 * Implementation of Module32First/Next
310 static BOOL TOOLHELP_Module32Next( HANDLE handle, LPMODULEENTRY32 lpme, BOOL first )
312 struct next_module_request *req = get_req_buffer();
314 if (lpme->dwSize < sizeof (MODULEENTRY32))
316 SetLastError( ERROR_INSUFFICIENT_BUFFER );
317 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32), lpme->dwSize);
320 req->handle = handle;
322 if (server_call( REQ_NEXT_MODULE )) return FALSE;
323 lpme->th32ModuleID = 0; /* toolhelp internal id, never used */
324 lpme->th32ProcessID = (DWORD)req->pid;
325 lpme->GlblcntUsage = 0; /* FIXME */
326 lpme->ProccntUsage = 0; /* FIXME */
327 lpme->modBaseAddr = req->base;
328 lpme->modBaseSize = 0; /* FIXME */
329 lpme->hModule = (DWORD)req->base;
330 lpme->szModule[0] = 0; /* FIXME */
331 lpme->szExePath[0] = 0; /* FIXME */
335 /***********************************************************************
336 * Module32First (KERNEL32.527)
338 * Return info about the "first" module in a toolhelp32 snapshot
340 BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
342 return TOOLHELP_Module32Next( hSnapshot, lpme, TRUE );
345 /***********************************************************************
346 * Module32Next (KERNEL32.528)
348 * Return info about the "next" module in a toolhelp32 snapshot
350 BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
352 return TOOLHELP_Module32Next( hSnapshot, lpme, FALSE );
355 /************************************************************************
356 * GlobalMasterHandle16 (KERNEL.28)
359 * Should return selector and handle of the information structure for
360 * the global heap. selector and handle are stored in the THHOOK as
361 * pGlobalHeap and hGlobalHeap.
362 * As Wine doesn't have this structure, we return both values as zero
363 * Applications should interpret this as "No Global Heap"
365 DWORD WINAPI GlobalMasterHandle16(void)