Commit | Line | Data |
---|---|---|
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 | 35 | WINE_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 | */ | |
42 | static struct notify | |
43 | { | |
bf9130af | 44 | HTASK16 htask; |
18f92e76 | 45 | FARPROC16 lpfnCallback; |
7e56f684 AJ |
46 | WORD wFlags; |
47 | } *notifys = NULL; | |
48 | ||
49 | static int nrofnotifys = 0; | |
50 | ||
60ce85c9 AJ |
51 | static FARPROC16 HookNotify = NULL; |
52 | ||
2d6457c1 | 53 | /*********************************************************************** |
01d5e5b0 | 54 | * NotifyRegister (TOOLHELP.73) |
2d6457c1 | 55 | */ |
a3960292 | 56 | BOOL16 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 | 86 | BOOL16 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 | 107 | BOOL16 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 | 116 | BOOL16 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 | 125 | BOOL16 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 |
134 | BOOL16 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 |
143 | BOOL16 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 | */ | |
152 | BOOL16 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 | */ | |
172 | BOOL16 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 | 190 | FARPROC16 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 | 205 | HANDLE 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 | */ | |
237 | static 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 | 270 | BOOL 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 | 280 | BOOL 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 | 290 | static 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 | 328 | BOOL 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 | 338 | BOOL 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 | */ | |
349 | static 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 | 386 | BOOL 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 | 396 | BOOL 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 | */ | |
411 | DWORD WINAPI GlobalMasterHandle16(void) | |
412 | { | |
61fece05 | 413 | FIXME(": stub\n"); |
2df1afdf UB |
414 | return 0; |
415 | } |