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
35 #include "wine/server.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(toolhelp);
42 /***********************************************************************
43 * CreateToolhelp32Snapshot (KERNEL32.@)
45 HANDLE WINAPI CreateToolhelp32Snapshot( DWORD flags, DWORD process )
49 TRACE("%lx,%lx\n", flags, process );
50 if (!(flags & (TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD|TH32CS_SNAPMODULE)))
52 FIXME("flags %lx not implemented\n", flags );
53 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
54 return INVALID_HANDLE_VALUE;
57 /* Now do the snapshot */
58 SERVER_START_REQ( create_snapshot )
61 if (flags & TH32CS_SNAPMODULE) req->flags |= SNAP_MODULE;
62 if (flags & TH32CS_SNAPPROCESS) req->flags |= SNAP_PROCESS;
63 if (flags & TH32CS_SNAPTHREAD) req->flags |= SNAP_THREAD;
65 req->inherit = (flags & TH32CS_INHERIT) != 0;
67 wine_server_call_err( req );
71 if (!ret) ret = INVALID_HANDLE_VALUE;
76 /***********************************************************************
77 * TOOLHELP_Thread32Next
79 * Implementation of Thread32First/Next
81 static BOOL TOOLHELP_Thread32Next( HANDLE handle, LPTHREADENTRY32 lpte, BOOL first )
85 if (lpte->dwSize < sizeof(THREADENTRY32))
87 SetLastError( ERROR_INSUFFICIENT_BUFFER );
88 ERR("Result buffer too small (%ld)\n", lpte->dwSize);
91 SERVER_START_REQ( next_thread )
95 if ((ret = !wine_server_call_err( req )))
97 lpte->cntUsage = reply->count;
98 lpte->th32ThreadID = (DWORD)reply->tid;
99 lpte->th32OwnerProcessID = (DWORD)reply->pid;
100 lpte->tpBasePri = reply->base_pri;
101 lpte->tpDeltaPri = reply->delta_pri;
102 lpte->dwFlags = 0; /* SDK: "reserved; do not use" */
109 /***********************************************************************
110 * Thread32First (KERNEL32.@)
112 * Return info about the first thread in a toolhelp32 snapshot
114 BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
116 return TOOLHELP_Thread32Next(hSnapshot, lpte, TRUE);
119 /***********************************************************************
120 * Thread32Next (KERNEL32.@)
122 * Return info about the "next" thread in a toolhelp32 snapshot
124 BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
126 return TOOLHELP_Thread32Next(hSnapshot, lpte, FALSE);
129 /***********************************************************************
130 * TOOLHELP_Process32Next
132 * Implementation of Process32First/Next. Note that the ANSI / Unicode
133 * version check is a bit of a hack as it relies on the fact that only
134 * the last field is actually different.
136 static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32W lppe, BOOL first, BOOL unicode )
139 WCHAR exe[MAX_PATH-1];
142 sz = unicode ? sizeof(PROCESSENTRY32W) : sizeof(PROCESSENTRY32);
143 if (lppe->dwSize < sz)
145 SetLastError( ERROR_INSUFFICIENT_BUFFER );
146 ERR("Result buffer too small (req: %ld, was: %ld)\n", sz, lppe->dwSize);
150 SERVER_START_REQ( next_process )
152 req->handle = handle;
154 wine_server_set_reply( req, exe, sizeof(exe) );
155 if ((ret = !wine_server_call_err( req )))
157 lppe->cntUsage = reply->count;
158 lppe->th32ProcessID = reply->pid;
159 lppe->th32DefaultHeapID = (DWORD)reply->heap;
160 lppe->th32ModuleID = (DWORD)reply->module;
161 lppe->cntThreads = reply->threads;
162 lppe->th32ParentProcessID = reply->ppid;
163 lppe->pcPriClassBase = reply->priority;
164 lppe->dwFlags = -1; /* FIXME */
167 len = wine_server_reply_size(reply) / sizeof(WCHAR);
168 memcpy(lppe->szExeFile, reply, wine_server_reply_size(reply));
169 lppe->szExeFile[len] = 0;
173 LPPROCESSENTRY32 lppe_a = (LPPROCESSENTRY32) lppe;
175 len = WideCharToMultiByte( CP_ACP, 0, exe, wine_server_reply_size(reply) / sizeof(WCHAR),
176 lppe_a->szExeFile, sizeof(lppe_a->szExeFile)-1, NULL, NULL );
177 lppe_a->szExeFile[len] = 0;
186 /***********************************************************************
187 * Process32First (KERNEL32.@)
189 * Return info about the first process in a toolhelp32 snapshot
191 BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
193 return TOOLHELP_Process32Next( hSnapshot, (LPPROCESSENTRY32W) lppe, TRUE, FALSE /* ANSI */ );
196 /***********************************************************************
197 * Process32Next (KERNEL32.@)
199 * Return info about the "next" process in a toolhelp32 snapshot
201 BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
203 return TOOLHELP_Process32Next( hSnapshot, (LPPROCESSENTRY32W) lppe, FALSE, FALSE /* ANSI */ );
206 /***********************************************************************
207 * Process32FirstW (KERNEL32.@)
209 * Return info about the first process in a toolhelp32 snapshot
211 BOOL WINAPI Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
213 return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE, TRUE /* Unicode */ );
216 /***********************************************************************
217 * Process32NextW (KERNEL32.@)
219 * Return info about the "next" process in a toolhelp32 snapshot
221 BOOL WINAPI Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
223 return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE, TRUE /* Unicode */ );
227 /***********************************************************************
228 * TOOLHELP_Module32NextW
230 * Implementation of Module32First/Next
232 static BOOL TOOLHELP_Module32NextW( HANDLE handle, LPMODULEENTRY32W lpme, BOOL first )
238 if (lpme->dwSize < sizeof (MODULEENTRY32W))
240 SetLastError( ERROR_INSUFFICIENT_BUFFER );
241 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32W), lpme->dwSize);
244 SERVER_START_REQ( next_module )
246 req->handle = handle;
248 wine_server_set_reply( req, exe, sizeof(exe) );
249 if ((ret = !wine_server_call_err( req )))
252 lpme->th32ModuleID = 1; /* toolhelp internal id, never used */
253 lpme->th32ProcessID = reply->pid;
254 lpme->GlblcntUsage = 0xFFFF; /* FIXME */
255 lpme->ProccntUsage = 0xFFFF; /* FIXME */
256 lpme->modBaseAddr = reply->base;
257 lpme->modBaseSize = reply->size;
258 lpme->hModule = reply->base;
259 len = wine_server_reply_size(reply) / sizeof(WCHAR);
260 memcpy(lpme->szExePath, exe, wine_server_reply_size(reply));
261 lpme->szExePath[len] = 0;
262 if ((ptr = strrchrW(lpme->szExePath, '\\'))) ptr++;
263 else ptr = lpme->szExePath;
264 lstrcpynW( lpme->szModule, ptr, sizeof(lpme->szModule)/sizeof(lpme->szModule[0]));
271 /***********************************************************************
272 * TOOLHELP_Module32NextA
274 * Implementation of Module32First/Next
276 static BOOL TOOLHELP_Module32NextA( HANDLE handle, LPMODULEENTRY32 lpme, BOOL first )
281 if (lpme->dwSize < sizeof (MODULEENTRY32))
283 SetLastError( ERROR_INSUFFICIENT_BUFFER );
284 ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32), lpme->dwSize);
288 mew.dwSize = sizeof(mew);
289 if ((ret = TOOLHELP_Module32NextW( handle, &mew, first )))
291 lpme->th32ModuleID = mew.th32ModuleID;
292 lpme->th32ProcessID = mew.th32ProcessID;
293 lpme->GlblcntUsage = mew.GlblcntUsage;
294 lpme->ProccntUsage = mew.ProccntUsage;
295 lpme->modBaseAddr = mew.modBaseAddr;
296 lpme->hModule = mew.hModule;
297 WideCharToMultiByte( CP_ACP, 0, mew.szModule, -1, lpme->szModule, sizeof(lpme->szModule), NULL, NULL );
298 WideCharToMultiByte( CP_ACP, 0, mew.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), NULL, NULL );
303 /***********************************************************************
304 * Module32FirstW (KERNEL32.@)
306 * Return info about the "first" module in a toolhelp32 snapshot
308 BOOL WINAPI Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
310 return TOOLHELP_Module32NextW( hSnapshot, lpme, TRUE );
313 /***********************************************************************
314 * Module32First (KERNEL32.@)
316 * Return info about the "first" module in a toolhelp32 snapshot
318 BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
320 return TOOLHELP_Module32NextA( hSnapshot, lpme, TRUE );
323 /***********************************************************************
324 * Module32NextW (KERNEL32.@)
326 * Return info about the "next" module in a toolhelp32 snapshot
328 BOOL WINAPI Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
330 return TOOLHELP_Module32NextW( hSnapshot, lpme, FALSE );
333 /***********************************************************************
334 * Module32Next (KERNEL32.@)
336 * Return info about the "next" module in a toolhelp32 snapshot
338 BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
340 return TOOLHELP_Module32NextA( hSnapshot, lpme, FALSE );
343 /************************************************************************
344 * Heap32ListFirst (KERNEL32.@)
347 BOOL WINAPI Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl)
353 /******************************************************************
354 * Toolhelp32ReadProcessMemory (KERNEL32.@)
358 BOOL WINAPI Toolhelp32ReadProcessMemory(DWORD pid, const void* base,
359 void* buf, SIZE_T len, SIZE_T* r)
364 h = (pid) ? OpenProcess(PROCESS_VM_READ, FALSE, pid) : GetCurrentProcess();
367 ret = ReadProcessMemory(h, base, buf, len, r);
368 if (pid) CloseHandle(h);