[PATCH] - rewrote toolhelp implementation only on top of ntdll
functions
Eric Pouech
eric.pouech at wanadoo.fr
Mon Apr 3 13:32:24 CDT 2006
A+
---
dlls/kernel/toolhelp.c | 503 ++++++++++++++++++++++++++++++++++--------------
1 files changed, 354 insertions(+), 149 deletions(-)
diff --git a/dlls/kernel/toolhelp.c b/dlls/kernel/toolhelp.c
index 2aef731..a563e25 100644
--- a/dlls/kernel/toolhelp.c
+++ b/dlls/kernel/toolhelp.c
@@ -2,6 +2,7 @@
* Misc Toolhelp functions
*
* Copyright 1996 Marcus Meissner
+ * 2005 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -28,23 +29,247 @@
#endif
#include <ctype.h>
#include <assert.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "tlhelp32.h"
-#include "wine/server.h"
-#include "wine/unicode.h"
+#include "winnls.h"
+#include "winternl.h"
+
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(toolhelp);
+struct snapshot
+{
+ int process_count;
+ int process_pos;
+ int process_offset;
+ int thread_count;
+ int thread_pos;
+ int thread_offset;
+ int module_count;
+ int module_pos;
+ int module_offset;
+ char data[1];
+};
+
+static BOOL fetch_module( DWORD process, DWORD flags, LDR_MODULE** ldr_mod, ULONG* num )
+{
+ HANDLE hProcess;
+ PROCESS_BASIC_INFORMATION pbi;
+ PPEB_LDR_DATA pLdrData;
+ NTSTATUS status;
+ PLIST_ENTRY head, curr;
+ BOOL ret = FALSE;
+
+ *num = 0;
+ if (!(flags & TH32CS_SNAPMODULE)) return TRUE;
+
+ if (process)
+ {
+ hProcess = OpenProcess( PROCESS_VM_READ, FALSE, process );
+ if (hProcess == INVALID_HANDLE_VALUE) return FALSE;
+ }
+ else
+ hProcess = GetCurrentProcess();
+
+ status = NtQueryInformationProcess( hProcess, ProcessBasicInformation,
+ &pbi, sizeof(pbi), NULL );
+ if (!status)
+ {
+ if (ReadProcessMemory( hProcess, &((PEB*)pbi.PebBaseAddress)->LdrData,
+ &pLdrData, sizeof(pLdrData), NULL ) &&
+ ReadProcessMemory( hProcess,
+ &pLdrData->InLoadOrderModuleList.Flink,
+ &curr, sizeof(curr), NULL ))
+ {
+ head = &pLdrData->InLoadOrderModuleList;
+
+ while (curr != head)
+ {
+ if (!*num)
+ *ldr_mod = HeapAlloc( GetProcessHeap(), 0, sizeof(LDR_MODULE) );
+ else
+ *ldr_mod = HeapReAlloc( GetProcessHeap(), 0, *ldr_mod,
+ (*num + 1) * sizeof(LDR_MODULE) );
+ if (!ReadProcessMemory( hProcess,
+ CONTAINING_RECORD(curr, LDR_MODULE,
+ InLoadOrderModuleList),
+ &(*ldr_mod)[*num],
+ sizeof(LDR_MODULE), NULL) )
+ break;
+ curr = (*ldr_mod)[*num].InLoadOrderModuleList.Flink;
+ (*num)++;
+ }
+ ret = TRUE;
+ }
+ }
+ else SetLastError( RtlNtStatusToDosError( status ) );
+
+ if (process) CloseHandle( hProcess );
+ return ret;
+}
+
+static void fill_module( struct snapshot* snap, ULONG* offset, ULONG process,
+ LDR_MODULE* ldr_mod, ULONG num )
+{
+ MODULEENTRY32W* mod;
+ ULONG i;
+ SIZE_T l;
+
+ snap->module_count = num;
+ snap->module_pos = 0;
+ if (!num) return;
+ snap->module_offset = *offset;
+
+ mod = (MODULEENTRY32W*)&snap->data[*offset];
+
+ for (i = 0; i < num; i++)
+ {
+ mod->dwSize = sizeof(MODULEENTRY32W);
+ mod->th32ModuleID = 1; /* toolhelp internal id, never used */
+ mod->th32ProcessID = process ? process : GetCurrentProcessId();
+ mod->GlblcntUsage = 0xFFFF; /* FIXME */
+ mod->ProccntUsage = 0xFFFF; /* FIXME */
+ mod->modBaseAddr = (BYTE*)ldr_mod[i].BaseAddress;
+ mod->modBaseSize = ldr_mod[i].SizeOfImage;
+ mod->hModule = (HMODULE)ldr_mod[i].BaseAddress;
+
+ l = min(ldr_mod[i].BaseDllName.Length, sizeof(mod->szModule) - sizeof(WCHAR));
+ memcpy(mod->szModule, ldr_mod[i].BaseDllName.Buffer, l);
+ mod->szModule[l / sizeof(WCHAR)] = '\0';
+ l = min(ldr_mod[i].FullDllName.Length, sizeof(mod->szModule) - sizeof(WCHAR));
+ memcpy(mod->szExePath, ldr_mod[i].FullDllName.Buffer, l);
+ mod->szExePath[l / sizeof(WCHAR)] = '\0';
+
+ mod++;
+ }
+
+ *offset += num * sizeof(MODULEENTRY32W);
+}
+
+static BOOL fetch_process_thread( DWORD flags, SYSTEM_PROCESS_INFORMATION** pspi,
+ ULONG* num_pcs, ULONG* num_thd)
+{
+ NTSTATUS status;
+ ULONG size, offset;
+ PSYSTEM_PROCESS_INFORMATION spi;
+
+ *num_pcs = *num_thd = 0;
+ if (!(flags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD))) return TRUE;
+
+ *pspi = HeapAlloc( GetProcessHeap(), 0, size = 4096 );
+ for (;;)
+ {
+ status = NtQuerySystemInformation( SystemProcessInformation, *pspi,
+ size, NULL );
+ switch (status)
+ {
+ case STATUS_SUCCESS:
+ *num_pcs = *num_thd = offset = 0;
+ spi = *pspi;
+ do
+ {
+ spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + offset);
+ if (flags & TH32CS_SNAPPROCESS) (*num_pcs)++;
+ if (flags & TH32CS_SNAPTHREAD) *num_thd += spi->dwThreadCount;
+ } while ((offset = spi->dwOffset));
+ return TRUE;
+ case STATUS_INFO_LENGTH_MISMATCH:
+ *pspi = HeapReAlloc( GetProcessHeap(), 0, *pspi, size *= 2 );
+ break;
+ default:
+ SetLastError( RtlNtStatusToDosError( status ) );
+ break;
+ }
+ }
+}
+
+static void fill_process( struct snapshot* snap, ULONG* offset,
+ SYSTEM_PROCESS_INFORMATION* spi, ULONG num )
+{
+ PROCESSENTRY32W* pcs_entry;
+ ULONG poff = 0;
+ SIZE_T l;
+
+ snap->process_count = num;
+ snap->process_pos = 0;
+ if (!num) return;
+ snap->process_offset = *offset;
+
+ pcs_entry = (PROCESSENTRY32W*)&snap->data[*offset];
+
+ do
+ {
+ spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + poff);
+
+ pcs_entry->dwSize = sizeof(PROCESSENTRY32W);
+ pcs_entry->cntUsage = 0; /* MSDN says no longer used, always 0 */
+ pcs_entry->th32ProcessID = spi->dwProcessID;
+ pcs_entry->th32DefaultHeapID = 0; /* MSDN says no longer used, always 0 */
+ pcs_entry->th32ModuleID = 0; /* MSDN says no longer used, always 0 */
+ pcs_entry->cntThreads = spi->dwThreadCount;
+ pcs_entry->th32ParentProcessID = spi->dwParentProcessID;
+ pcs_entry->pcPriClassBase = spi->dwBasePriority;
+ pcs_entry->dwFlags = 0; /* MSDN says no longer used, always 0 */
+ l = min(spi->ProcessName.Length, sizeof(pcs_entry->szExeFile) - sizeof(WCHAR));
+ memcpy(pcs_entry->szExeFile, spi->ProcessName.Buffer, l);
+ pcs_entry->szExeFile[l / sizeof(WCHAR)] = '\0';
+ pcs_entry++;
+ } while ((poff = spi->dwOffset));
+
+ *offset += num * sizeof(PROCESSENTRY32W);
+}
+
+static void fill_thread( struct snapshot* snap, ULONG* offset, LPVOID info, ULONG num )
+{
+ THREADENTRY32* thd_entry;
+ SYSTEM_PROCESS_INFORMATION* spi;
+ SYSTEM_THREAD_INFORMATION* sti;
+ ULONG i, poff = 0;
+
+ snap->thread_count = num;
+ snap->thread_pos = 0;
+ if (!num) return;
+ snap->thread_offset = *offset;
+
+ thd_entry = (THREADENTRY32*)&snap->data[*offset];
+
+ spi = (SYSTEM_PROCESS_INFORMATION*)info;
+ do
+ {
+ spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + poff);
+ sti = &spi->ti[0];
+
+ for (i = 0; i < spi->dwThreadCount; i++)
+ {
+ thd_entry->dwSize = sizeof(THREADENTRY32);
+ thd_entry->cntUsage = 0; /* MSDN says no longer used, always 0 */
+ thd_entry->th32ThreadID = (ULONG)sti->dwThreadID;
+ thd_entry->th32OwnerProcessID = (ULONG)sti->dwOwningPID;
+ thd_entry->tpBasePri = sti->dwBasePriority;
+ thd_entry->tpDeltaPri = 0; /* MSDN says no longer used, always 0 */
+ thd_entry->dwFlags = 0; /* MSDN says no longer used, always 0" */
+
+ sti++;
+ thd_entry++;
+ }
+ } while ((poff = spi->dwOffset));
+ *offset += num * sizeof(THREADENTRY32);
+}
/***********************************************************************
* CreateToolhelp32Snapshot (KERNEL32.@)
*/
HANDLE WINAPI CreateToolhelp32Snapshot( DWORD flags, DWORD process )
{
- HANDLE ret;
+ SYSTEM_PROCESS_INFORMATION* spi = NULL;
+ LDR_MODULE* mod = NULL;
+ ULONG num_pcs, num_thd, num_mod;
+ HANDLE hSnapShot = INVALID_HANDLE_VALUE;
TRACE("%lx,%lx\n", flags, process );
if (!(flags & (TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD|TH32CS_SNAPMODULE)))
@@ -54,32 +279,48 @@ HANDLE WINAPI CreateToolhelp32Snapshot(
return INVALID_HANDLE_VALUE;
}
- /* Now do the snapshot */
- SERVER_START_REQ( create_snapshot )
+ if (fetch_module( process, flags, &mod, &num_mod ) &&
+ fetch_process_thread( flags, &spi, &num_pcs, &num_thd ))
{
- req->flags = 0;
- if (flags & TH32CS_SNAPMODULE) req->flags |= SNAP_MODULE;
- if (flags & TH32CS_SNAPPROCESS) req->flags |= SNAP_PROCESS;
- if (flags & TH32CS_SNAPTHREAD) req->flags |= SNAP_THREAD;
- req->attributes = (flags & TH32CS_INHERIT) ? OBJ_INHERIT : 0;
- req->pid = process;
- wine_server_call_err( req );
- ret = reply->handle;
+ ULONG sect_size;
+ struct snapshot*snap;
+ SECURITY_ATTRIBUTES sa;
+
+ /* create & fill the snapshot section */
+ sect_size = sizeof(struct snapshot) - 1; /* for last data[1] */
+ if (flags & TH32CS_SNAPMODULE) sect_size += num_mod * sizeof(MODULEENTRY32W);
+ if (flags & TH32CS_SNAPPROCESS) sect_size += num_pcs * sizeof(PROCESSENTRY32W);
+ if (flags & TH32CS_SNAPTHREAD) sect_size += num_thd * sizeof(THREADENTRY32);
+ if (flags & TH32CS_SNAPHEAPLIST)FIXME("Unimplemented: heap list snapshot\n");
+
+ sa.bInheritHandle = (flags & TH32CS_INHERIT) ? TRUE : FALSE;
+ sa.lpSecurityDescriptor = NULL;
+
+ hSnapShot = CreateFileMappingW( INVALID_HANDLE_VALUE, &sa,
+ SEC_COMMIT | PAGE_READWRITE,
+ 0, sect_size, NULL );
+ if (hSnapShot != INVALID_HANDLE_VALUE &&
+ (snap = MapViewOfFile( hSnapShot, FILE_MAP_ALL_ACCESS, 0, 0, 0 )))
+ {
+ DWORD offset = 0;
+
+ fill_module( snap, &offset, process, mod, num_mod );
+ fill_process( snap, &offset, spi, num_pcs );
+ fill_thread( snap, &offset, spi, num_thd );
+ UnmapViewOfFile( (void*)snap );
+ }
}
- SERVER_END_REQ;
- if (!ret) ret = INVALID_HANDLE_VALUE;
- return ret;
-}
+ HeapFree( GetProcessHeap(), 0, mod );
+ HeapFree( GetProcessHeap(), 0, spi );
-/***********************************************************************
- * TOOLHELP_Thread32Next
- *
- * Implementation of Thread32First/Next
- */
-static BOOL TOOLHELP_Thread32Next( HANDLE handle, LPTHREADENTRY32 lpte, BOOL first )
+ return hSnapShot;
+}
+
+static BOOL next_thread( HANDLE hSnapShot, LPTHREADENTRY32 lpte, BOOL first )
{
- BOOL ret;
+ struct snapshot* snap;
+ BOOL ret = FALSE;
if (lpte->dwSize < sizeof(THREADENTRY32))
{
@@ -87,21 +328,18 @@ static BOOL TOOLHELP_Thread32Next( HANDL
ERR("Result buffer too small (%ld)\n", lpte->dwSize);
return FALSE;
}
- SERVER_START_REQ( next_thread )
+ if ((snap = MapViewOfFile( hSnapShot, FILE_MAP_ALL_ACCESS, 0, 0, 0 )))
{
- req->handle = handle;
- req->reset = first;
- if ((ret = !wine_server_call_err( req )))
+ if (first) snap->thread_pos = 0;
+ if (snap->thread_pos < snap->thread_count)
{
- lpte->cntUsage = reply->count;
- lpte->th32ThreadID = (DWORD)reply->tid;
- lpte->th32OwnerProcessID = (DWORD)reply->pid;
- lpte->tpBasePri = reply->base_pri;
- lpte->tpDeltaPri = reply->delta_pri;
- lpte->dwFlags = 0; /* SDK: "reserved; do not use" */
+ LPTHREADENTRY32 te = (THREADENTRY32*)&snap->data[snap->thread_offset];
+ *lpte = te[snap->thread_pos++];
+ ret = TRUE;
}
+ else SetLastError( ERROR_NO_MORE_FILES );
+ UnmapViewOfFile( (void*)snap );
}
- SERVER_END_REQ;
return ret;
}
@@ -110,92 +348,71 @@ static BOOL TOOLHELP_Thread32Next( HANDL
*
* Return info about the first thread in a toolhelp32 snapshot
*/
-BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
+BOOL WINAPI Thread32First( HANDLE hSnapShot, LPTHREADENTRY32 lpte )
{
- return TOOLHELP_Thread32Next(hSnapshot, lpte, TRUE);
+ return next_thread( hSnapShot, lpte, TRUE );
}
/***********************************************************************
- * Thread32Next (KERNEL32.@)
+ * Thread32Next (KERNEL32.@)
*
- * Return info about the "next" thread in a toolhelp32 snapshot
+ * Return info about the first thread in a toolhelp32 snapshot
*/
-BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
+BOOL WINAPI Thread32Next( HANDLE hSnapShot, LPTHREADENTRY32 lpte )
{
- return TOOLHELP_Thread32Next(hSnapshot, lpte, FALSE);
+ return next_thread( hSnapShot, lpte, FALSE );
}
/***********************************************************************
- * TOOLHELP_Process32Next
+ * process_next
*
* Implementation of Process32First/Next. Note that the ANSI / Unicode
* version check is a bit of a hack as it relies on the fact that only
* the last field is actually different.
*/
-static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32W lppe, BOOL first, BOOL unicode )
+static BOOL process_next( HANDLE hSnapShot, LPPROCESSENTRY32W lppe,
+ BOOL first, BOOL unicode )
{
- BOOL ret;
- WCHAR exe[MAX_PATH-1];
- DWORD len, sz;
+ struct snapshot* snap;
+ BOOL ret = FALSE;
+ DWORD sz = unicode ? sizeof(PROCESSENTRY32W) : sizeof(PROCESSENTRY32);
- sz = unicode ? sizeof(PROCESSENTRY32W) : sizeof(PROCESSENTRY32);
if (lppe->dwSize < sz)
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
- ERR("Result buffer too small (req: %ld, was: %ld)\n", sz, lppe->dwSize);
+ ERR("Result buffer too small (%ld)\n", lppe->dwSize);
return FALSE;
}
-
- SERVER_START_REQ( next_process )
+ if ((snap = MapViewOfFile( hSnapShot, FILE_MAP_ALL_ACCESS, 0, 0, 0 )))
{
- req->handle = handle;
- req->reset = first;
- wine_server_set_reply( req, exe, sizeof(exe) );
- if ((ret = !wine_server_call_err( req )))
+ if (first) snap->process_pos = 0;
+ if (snap->process_pos < snap->process_count)
{
- lppe->cntUsage = reply->count;
- lppe->th32ProcessID = reply->pid;
- lppe->th32DefaultHeapID = (DWORD)reply->heap;
- lppe->th32ModuleID = (DWORD)reply->module;
- lppe->cntThreads = reply->threads;
- lppe->th32ParentProcessID = reply->ppid;
- switch (reply->priority)
- {
- case PROCESS_PRIOCLASS_IDLE:
- lppe->pcPriClassBase = IDLE_PRIORITY_CLASS; break;
- case PROCESS_PRIOCLASS_BELOW_NORMAL:
- lppe->pcPriClassBase = BELOW_NORMAL_PRIORITY_CLASS; break;
- case PROCESS_PRIOCLASS_NORMAL:
- lppe->pcPriClassBase = NORMAL_PRIORITY_CLASS; break;
- case PROCESS_PRIOCLASS_ABOVE_NORMAL:
- lppe->pcPriClassBase = ABOVE_NORMAL_PRIORITY_CLASS; break;
- case PROCESS_PRIOCLASS_HIGH:
- lppe->pcPriClassBase = HIGH_PRIORITY_CLASS; break;
- case PROCESS_PRIOCLASS_REALTIME:
- lppe->pcPriClassBase = REALTIME_PRIORITY_CLASS; break;
- default:
- FIXME("Unknown NT priority class %d, setting to normal\n", reply->priority);
- lppe->pcPriClassBase = NORMAL_PRIORITY_CLASS;
- break;
- }
- lppe->dwFlags = -1; /* FIXME */
+ LPPROCESSENTRY32W pe = (PROCESSENTRY32W*)&snap->data[snap->process_offset];
if (unicode)
- {
- len = wine_server_reply_size(reply) / sizeof(WCHAR);
- memcpy(lppe->szExeFile, reply, wine_server_reply_size(reply));
- lppe->szExeFile[len] = 0;
- }
+ *lppe = pe[snap->process_pos];
else
{
- LPPROCESSENTRY32 lppe_a = (LPPROCESSENTRY32) lppe;
-
- len = WideCharToMultiByte( CP_ACP, 0, exe, wine_server_reply_size(reply) / sizeof(WCHAR),
- lppe_a->szExeFile, sizeof(lppe_a->szExeFile)-1, NULL, NULL );
- lppe_a->szExeFile[len] = 0;
+ lppe->cntUsage = pe[snap->process_pos].cntUsage;
+ lppe->th32ProcessID = pe[snap->process_pos].th32ProcessID;
+ lppe->th32DefaultHeapID = pe[snap->process_pos].th32DefaultHeapID;
+ lppe->th32ModuleID = pe[snap->process_pos].th32ModuleID;
+ lppe->cntThreads = pe[snap->process_pos].cntThreads;
+ lppe->th32ParentProcessID = pe[snap->process_pos].th32ParentProcessID;
+ lppe->pcPriClassBase = pe[snap->process_pos].pcPriClassBase;
+ lppe->dwFlags = pe[snap->process_pos].dwFlags;
+
+ WideCharToMultiByte( CP_ACP, 0, pe[snap->process_pos].szExeFile, -1,
+ (char*)lppe->szExeFile, sizeof(lppe->szExeFile),
+ 0, 0 );
}
+ snap->process_pos++;
+ ret = TRUE;
}
+ else SetLastError( ERROR_NO_MORE_FILES );
+ UnmapViewOfFile( (void*)snap );
}
- SERVER_END_REQ;
+
return ret;
}
@@ -207,7 +424,7 @@ static BOOL TOOLHELP_Process32Next( HAND
*/
BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
{
- return TOOLHELP_Process32Next( hSnapshot, (LPPROCESSENTRY32W) lppe, TRUE, FALSE /* ANSI */ );
+ return process_next( hSnapshot, (PROCESSENTRY32W*)lppe, TRUE, FALSE /* ANSI */ );
}
/***********************************************************************
@@ -217,7 +434,7 @@ BOOL WINAPI Process32First(HANDLE hSnaps
*/
BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
{
- return TOOLHELP_Process32Next( hSnapshot, (LPPROCESSENTRY32W) lppe, FALSE, FALSE /* ANSI */ );
+ return process_next( hSnapshot, (PROCESSENTRY32W*)lppe, FALSE, FALSE /* ANSI */ );
}
/***********************************************************************
@@ -227,7 +444,7 @@ BOOL WINAPI Process32Next(HANDLE hSnapsh
*/
BOOL WINAPI Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
{
- return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE, TRUE /* Unicode */ );
+ return process_next( hSnapshot, lppe, TRUE, TRUE /* Unicode */ );
}
/***********************************************************************
@@ -237,20 +454,18 @@ BOOL WINAPI Process32FirstW(HANDLE hSnap
*/
BOOL WINAPI Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
{
- return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE, TRUE /* Unicode */ );
+ return process_next( hSnapshot, lppe, FALSE, TRUE /* Unicode */ );
}
-
/***********************************************************************
- * TOOLHELP_Module32NextW
+ * module_nextW
*
- * Implementation of Module32First/Next
+ * Implementation of Module32{First|Next}W
*/
-static BOOL TOOLHELP_Module32NextW( HANDLE handle, LPMODULEENTRY32W lpme, BOOL first )
+static BOOL module_nextW( HANDLE hSnapShot, LPMODULEENTRY32W lpme, BOOL first )
{
- BOOL ret;
- WCHAR exe[MAX_PATH];
- DWORD len;
+ struct snapshot* snap;
+ BOOL ret = FALSE;
if (lpme->dwSize < sizeof (MODULEENTRY32W))
{
@@ -258,44 +473,53 @@ static BOOL TOOLHELP_Module32NextW( HAND
ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32W), lpme->dwSize);
return FALSE;
}
- SERVER_START_REQ( next_module )
+ if ((snap = MapViewOfFile( hSnapShot, FILE_MAP_ALL_ACCESS, 0, 0, 0 )))
{
- req->handle = handle;
- req->reset = first;
- wine_server_set_reply( req, exe, sizeof(exe) );
- if ((ret = !wine_server_call_err( req )))
+ if (first) snap->module_pos = 0;
+ if (snap->module_pos < snap->module_count)
{
- const WCHAR* ptr;
- lpme->th32ModuleID = 1; /* toolhelp internal id, never used */
- lpme->th32ProcessID = reply->pid;
- lpme->GlblcntUsage = 0xFFFF; /* FIXME */
- lpme->ProccntUsage = 0xFFFF; /* FIXME */
- lpme->modBaseAddr = reply->base;
- lpme->modBaseSize = reply->size;
- lpme->hModule = reply->base;
- len = wine_server_reply_size(reply) / sizeof(WCHAR);
- memcpy(lpme->szExePath, exe, wine_server_reply_size(reply));
- lpme->szExePath[len] = 0;
- if ((ptr = strrchrW(lpme->szExePath, '\\'))) ptr++;
- else ptr = lpme->szExePath;
- lstrcpynW( lpme->szModule, ptr, sizeof(lpme->szModule)/sizeof(lpme->szModule[0]));
+ LPMODULEENTRY32W pe = (MODULEENTRY32W*)&snap->data[snap->module_offset];
+ *lpme = pe[snap->module_pos++];
+ ret = TRUE;
}
+ else SetLastError( ERROR_NO_MORE_FILES );
+ UnmapViewOfFile( (void*)snap );
}
- SERVER_END_REQ;
+
return ret;
}
/***********************************************************************
- * TOOLHELP_Module32NextA
+ * Module32FirstW (KERNEL32.@)
+ *
+ * Return info about the "first" module in a toolhelp32 snapshot
+ */
+BOOL WINAPI Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
+{
+ return module_nextW( hSnapshot, lpme, TRUE );
+}
+
+/***********************************************************************
+ * Module32NextW (KERNEL32.@)
+ *
+ * Return info about the "next" module in a toolhelp32 snapshot
+ */
+BOOL WINAPI Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
+{
+ return module_nextW( hSnapshot, lpme, FALSE );
+}
+
+/***********************************************************************
+ * module_nextA
*
- * Implementation of Module32First/Next
+ * Implementation of Module32{First|Next}A
*/
-static BOOL TOOLHELP_Module32NextA( HANDLE handle, LPMODULEENTRY32 lpme, BOOL first )
+static BOOL module_nextA( HANDLE handle, LPMODULEENTRY32 lpme, BOOL first )
{
BOOL ret;
MODULEENTRY32W mew;
- if (lpme->dwSize < sizeof (MODULEENTRY32))
+ if (lpme->dwSize < sizeof(MODULEENTRY32))
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32), lpme->dwSize);
@@ -303,13 +527,14 @@ static BOOL TOOLHELP_Module32NextA( HAND
}
mew.dwSize = sizeof(mew);
- if ((ret = TOOLHELP_Module32NextW( handle, &mew, first )))
+ if ((ret = module_nextW( handle, &mew, first )))
{
lpme->th32ModuleID = mew.th32ModuleID;
lpme->th32ProcessID = mew.th32ProcessID;
lpme->GlblcntUsage = mew.GlblcntUsage;
lpme->ProccntUsage = mew.ProccntUsage;
lpme->modBaseAddr = mew.modBaseAddr;
+ lpme->modBaseSize = mew.modBaseSize;
lpme->hModule = mew.hModule;
WideCharToMultiByte( CP_ACP, 0, mew.szModule, -1, lpme->szModule, sizeof(lpme->szModule), NULL, NULL );
WideCharToMultiByte( CP_ACP, 0, mew.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), NULL, NULL );
@@ -318,33 +543,13 @@ static BOOL TOOLHELP_Module32NextA( HAND
}
/***********************************************************************
- * Module32FirstW (KERNEL32.@)
- *
- * Return info about the "first" module in a toolhelp32 snapshot
- */
-BOOL WINAPI Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
-{
- return TOOLHELP_Module32NextW( hSnapshot, lpme, TRUE );
-}
-
-/***********************************************************************
* Module32First (KERNEL32.@)
*
* Return info about the "first" module in a toolhelp32 snapshot
*/
BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
{
- return TOOLHELP_Module32NextA( hSnapshot, lpme, TRUE );
-}
-
-/***********************************************************************
- * Module32NextW (KERNEL32.@)
- *
- * Return info about the "next" module in a toolhelp32 snapshot
- */
-BOOL WINAPI Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
-{
- return TOOLHELP_Module32NextW( hSnapshot, lpme, FALSE );
+ return module_nextA( hSnapshot, lpme, TRUE );
}
/***********************************************************************
@@ -354,7 +559,7 @@ BOOL WINAPI Module32NextW(HANDLE hSnapsh
*/
BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
{
- return TOOLHELP_Module32NextA( hSnapshot, lpme, FALSE );
+ return module_nextA( hSnapshot, lpme, FALSE );
}
/************************************************************************
More information about the wine-patches
mailing list