From 3f8e1e4d444b66764389e5caa1c121fed2092031 Mon Sep 17 00:00:00 2001 From: Patrick Spinler Date: Fri, 11 Dec 1998 15:04:11 +0000 Subject: [PATCH] Implemented CreateToolhelp32Snapshot, including two of the routines using snapshots, Process32First and Process32Next. --- include/process.h | 6 + include/tlhelp32.h | 29 +++++ include/toolhelp.h | 3 + misc/toolhelp.c | 337 +++++++++++++++++++++++++++++++++++++++++++++++++++- scheduler/k32obj.c | 1 + scheduler/process.c | 126 +++++++++++++++++--- 6 files changed, 483 insertions(+), 19 deletions(-) create mode 100644 include/tlhelp32.h diff --git a/include/process.h b/include/process.h index 46eb24a7130..51e62073ed6 100644 --- a/include/process.h +++ b/include/process.h @@ -108,6 +108,8 @@ typedef struct _PDB32 LCID locale; /* c4 Locale to be queried by GetThreadLocale (NT) */ /* The following are Wine-specific fields */ void *server_pid; /* Server id for this process */ + struct _PDB32 *list_next; /* List reference - list of PDB's */ + struct _PDB32 *list_prev; /* List reference - list of PDB's */ } PDB32; /* Process flags */ @@ -157,5 +159,9 @@ extern PDB32 *PROCESS_Create( struct _NE_MODULE *pModule, LPCSTR cmd_line, PROCESS_INFORMATION *info ); extern void PROCESS_SuspendOtherThreads(void); extern void PROCESS_ResumeOtherThreads(void); +extern int PROCESS_PDBList_Getsize (void); +extern PDB32* PROCESS_PDBList_Getfirst (void); +extern PDB32* PROCESS_PDBList_Getnext (PDB32*); #endif /* __WINE_PROCESS_H */ + diff --git a/include/tlhelp32.h b/include/tlhelp32.h new file mode 100644 index 00000000000..b8b798a087b --- /dev/null +++ b/include/tlhelp32.h @@ -0,0 +1,29 @@ +#ifndef __WINE_TLHELP32_H +#define __WINE_TLHELP32_H + +#include "windows.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /*=================================================================== + * Arguments for Toolhelp routines + */ + + /* + * CreateToolhelp32Snapshot + */ + +#define TH32CS_SNAPHEAPLIST 0x00000001 +#define TH32CS_SNAPPROCESS 0x00000002 +#define TH32CS_SNAPTHREAD 0x00000004 +#define TH32CS_SNAPMODULE 0x00000008 +#define TH32CS_SNAPALL (TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE) +#define TH32CS_INHERIT 0x80000000 + +#ifdef __cplusplus +extern "C" { +#endif + +#endif /* __WINE_TLHELP32_H */ diff --git a/include/toolhelp.h b/include/toolhelp.h index bb0a572f79f..f2b1629de8b 100644 --- a/include/toolhelp.h +++ b/include/toolhelp.h @@ -2,10 +2,13 @@ #define __WINE_TOOLHELP_H #include "windows.h" +#include "tlhelp32.h" #define MAX_DATA 11 #define MAX_MODULE_NAME 9 +#ifndef MAX_PATH #define MAX_PATH 255 +#endif #define MAX_CLASSNAME 255 #pragma pack(1) diff --git a/misc/toolhelp.c b/misc/toolhelp.c index c3cb60aaaad..387727f5f19 100644 --- a/misc/toolhelp.c +++ b/misc/toolhelp.c @@ -8,11 +8,54 @@ #include #include #include +#include #include "windows.h" #include "win.h" +#include "winerror.h" +#include "tlhelp32.h" #include "toolhelp.h" #include "debug.h" #include "heap.h" +#include "process.h" +#include "k32obj.h" + +/* + * Support for toolhelp's snapshots. They + * are supposed to be Kernel32 Objects. + * Only the Destroy() method is implemented + */ + +static void SNAPSHOT_Destroy( K32OBJ *obj ); + +const K32OBJ_OPS SNAPSHOT_Ops = +{ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* add_wait */ + NULL, /* remove_wait */ + NULL, /* read */ + NULL, /* write */ + SNAPSHOT_Destroy /* destroy */ +}; + +/* The K32 snapshot object object */ +/* Process snapshot kernel32 object */ +typedef struct _Process32Snapshot +{ + K32OBJ header; + + DWORD numProcs; + DWORD arrayCounter; + /* + * Store a reference to the PDB list. + * Insuure in the alloc and dealloc routines for this structure that + * I increment and decrement the pdb->head.refcount, so that the + * original pdb will stay around for as long as I use it, but it's + * not locked forver into memory. + */ + PDB32 **processArray; +} +SNAPSHOT_OBJECT; /* FIXME: to make this working, we have to callback all these registered * functions from all over the WINE code. Someone with more knowledge than @@ -103,10 +146,298 @@ FARPROC16 tmp; } /*********************************************************************** + * SNAPSHOT_Destroy + * + * Deallocate K32 snapshot objects + */ +static void SNAPSHOT_Destroy (K32OBJ *obj) +{ + int i; + SNAPSHOT_OBJECT *snapshot = (SNAPSHOT_OBJECT *) obj; + assert (obj->type == K32OBJ_CHANGE); + + if (snapshot->processArray) + { + for (i = 0; snapshot->processArray[i] && i numProcs; i++) + { + K32OBJ_DecCount (&snapshot->processArray[i]->header); + } + HeapFree (GetProcessHeap (), 0, snapshot->processArray); + snapshot->processArray = NULL; + } + + obj->type = K32OBJ_UNKNOWN; + HeapFree (GetProcessHeap (), 0, snapshot); +} + +/*********************************************************************** * CreateToolHelp32Snapshot (KERNEL32.179) * see "Undocumented Windows" */ -HANDLE32 WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID) { - FIXME(toolhelp,"(0x%08lx,0x%08lx), stub!\n",dwFlags,th32ProcessID); - return INVALID_HANDLE_VALUE32; +HANDLE32 WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD + th32ProcessID) +{ + HANDLE32 ssHandle; + SNAPSHOT_OBJECT *snapshot; + int numProcesses; + int i; + PDB32* pdb; + + printf ("%x & TH32CS_INHERIT (%x) = %x %s\n", dwFlags, + TH32CS_INHERIT, TH32CS_INHERIT, + dwFlags & TH32CS_INHERIT, + dwFlags & TH32CS_INHERIT ? "TRUE" : "FALSE"); + printf ("%x & TH32CS_SNAPHEAPLIST (%x) = %x %s\n", dwFlags, + TH32CS_SNAPHEAPLIST, TH32CS_SNAPHEAPLIST, + dwFlags & TH32CS_SNAPHEAPLIST, + dwFlags & TH32CS_SNAPHEAPLIST ? "TRUE" : "FALSE"); + printf ("%x & TH32CS_SNAPMODULE (%x) = %x %s\n", dwFlags, + TH32CS_SNAPMODULE, TH32CS_SNAPMODULE, + dwFlags & TH32CS_SNAPMODULE, + dwFlags & TH32CS_SNAPMODULE ? "TRUE" : "FALSE"); + printf ("%x & TH32CS_SNAPPROCESS (%x) = %x %s\n", dwFlags, + TH32CS_SNAPPROCESS, TH32CS_SNAPPROCESS, + dwFlags & TH32CS_SNAPPROCESS, + dwFlags & TH32CS_SNAPPROCESS ? "TRUE" : "FALSE"); + printf ("%x & TH32CS_SNAPTHREAD (%x) = %x %s\n", dwFlags, + TH32CS_SNAPTHREAD, TH32CS_SNAPTHREAD, + dwFlags & TH32CS_SNAPTHREAD, + dwFlags & TH32CS_SNAPTHREAD ? "TRUE" : "FALSE"); + + /**** FIXME: Not implmented ***/ + if (dwFlags & TH32CS_INHERIT) + { + FIXME(toolhelp,"(0x%08lx (TH32CS_INHERIT),0x%08lx), stub!\n", + dwFlags,th32ProcessID); + + return INVALID_HANDLE_VALUE32; + } + if (dwFlags & TH32CS_SNAPHEAPLIST) + { + FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPHEAPLIST),0x%08lx), stub!\n", + dwFlags,th32ProcessID); + return INVALID_HANDLE_VALUE32; + } + if (dwFlags & TH32CS_SNAPMODULE) + { + FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPMODULE),0x%08lx), stub!\n", + dwFlags,th32ProcessID); + return INVALID_HANDLE_VALUE32; + } + + if (dwFlags & TH32CS_SNAPPROCESS) + { + TRACE (toolhelp, "(0x%08lx (TH32CS_SNAPMODULE),0x%08lx)\n", + dwFlags,th32ProcessID); + snapshot = HeapAlloc (GetProcessHeap (), 0, sizeof + (SNAPSHOT_OBJECT)); + if (!snapshot) + { + return INVALID_HANDLE_VALUE32; + } + + snapshot->header.type = K32OBJ_TOOLHELP_SNAPSHOT; + snapshot->header.refcount = 1; + snapshot->arrayCounter = 0; + + /* + * Lock here, to prevent processes from being created or + * destroyed while the snapshot is gathered + */ + + SYSTEM_LOCK (); + numProcesses = PROCESS_PDBList_Getsize (); + + snapshot->processArray = (PDB32**) + HeapAlloc (GetProcessHeap (), 0, sizeof (PDB32*) * numProcesses); + + if (!snapshot->processArray) + { + HeapFree (GetProcessHeap (), 0, snapshot->processArray); + SetLastError (INVALID_HANDLE_VALUE32); + ERR (toolhelp, "Error allocating %d bytes for snapshot\n", + sizeof (PDB32*) * numProcesses); + return INVALID_HANDLE_VALUE32; + } + + snapshot->numProcs = numProcesses; + + pdb = PROCESS_PDBList_Getfirst (); + for (i = 0; pdb && i < numProcesses; i++) + { + TRACE (toolhelp, "Saving ref to pdb %ld\n", PDB_TO_PROCESS_ID(pdb)); + snapshot->processArray[i] = pdb; + K32OBJ_IncCount (&pdb->header); + pdb = PROCESS_PDBList_Getnext (pdb); + } + SYSTEM_UNLOCK (); + + ssHandle = HANDLE_Alloc (PROCESS_Current (), &snapshot->header, + FILE_ALL_ACCESS, TRUE, -1); + if (ssHandle == INVALID_HANDLE_VALUE32) + { + /* HANDLE_Alloc is supposed to deallocate the + * heap memory if it fails. This code doesn't need to. + */ + SetLastError (INVALID_HANDLE_VALUE32); + ERR (toolhelp, "Error allocating handle\n"); + return INVALID_HANDLE_VALUE32; + } + + TRACE (toolhelp, "snapshotted %d processes, expected %d\n", + i, numProcesses); + return ssHandle; + } + + if (dwFlags & TH32CS_SNAPTHREAD) + { + FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPMODULE),0x%08lx), stub!\n", + dwFlags,th32ProcessID); + return INVALID_HANDLE_VALUE32; + } + + return INVALID_HANDLE_VALUE32; +} + +/*********************************************************************** + * Process32First + * Return info about the first process in a toolhelp32 snapshot + */ +BOOL32 WINAPI Process32First(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe) +{ + PDB32 *pdb; + SNAPSHOT_OBJECT *snapshot; + int i; + + TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot, + (DWORD) lppe); + + if (lppe->dwSize < sizeof (PROCESSENTRY32)) + { + SetLastError (ERROR_INSUFFICIENT_BUFFER); + ERR (toolhelp, "Result buffer too small\n"); + return FALSE; + } + + SYSTEM_LOCK (); + snapshot = (SNAPSHOT_OBJECT*) HANDLE_GetObjPtr (PROCESS_Current (), + hSnapshot, + K32OBJ_UNKNOWN, + FILE_ALL_ACCESS, + NULL); + if (!snapshot) + { + SYSTEM_UNLOCK (); + SetLastError (ERROR_INVALID_HANDLE); + ERR (toolhelp, "Error retreiving snapshot\n"); + return FALSE; + } + + snapshot->arrayCounter = i = 0; + pdb = snapshot->processArray[i]; + + if (!pdb) + { + SetLastError (ERROR_NO_MORE_FILES); + ERR (toolhelp, "End of snapshot array\n"); + return FALSE; + } + + TRACE (toolhelp, "Returning info on process %d, id %ld\n", + i, PDB_TO_PROCESS_ID (pdb)); + + lppe->cntUsage = 1; + lppe->th32ProcessID = PDB_TO_PROCESS_ID (pdb); + lppe->th32DefaultHeapID = (DWORD) pdb->heap; + lppe->cntThreads = pdb->threads; + lppe->th32ParentProcessID = PDB_TO_PROCESS_ID (pdb->parent); + lppe->pcPriClassBase = 6; /* FIXME: this is a made-up value */ + lppe->dwFlags = -1; /* FIXME: RESERVED by Microsoft :-) */ + if (pdb->exe_modref) + { + lppe->th32ModuleID = (DWORD) pdb->exe_modref->module; + strncpy (lppe->szExeFile, pdb->exe_modref->longname, + sizeof (lppe->szExeFile)); + } + else + { + lppe->th32ModuleID = (DWORD) 0; + strcpy (lppe->szExeFile, ""); + } + + SYSTEM_UNLOCK (); + + return TRUE; +} + +/*********************************************************************** + * Process32Next + * Return info about the "next" process in a toolhelp32 snapshot + */ +BOOL32 WINAPI Process32Next(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe) +{ + PDB32 *pdb; + SNAPSHOT_OBJECT *snapshot; + int i; + + TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot, + (DWORD) lppe); + + if (lppe->dwSize < sizeof (PROCESSENTRY32)) + { + SetLastError (ERROR_INSUFFICIENT_BUFFER); + ERR (toolhelp, "Result buffer too small\n"); + return FALSE; + } + + SYSTEM_LOCK (); + snapshot = (SNAPSHOT_OBJECT*) HANDLE_GetObjPtr (PROCESS_Current (), + hSnapshot, + K32OBJ_UNKNOWN, + FILE_ALL_ACCESS, + NULL); + if (!snapshot) + { + SYSTEM_UNLOCK (); + SetLastError (ERROR_INVALID_HANDLE); + ERR (toolhelp, "Error retreiving snapshot\n"); + return FALSE; + } + + snapshot->arrayCounter ++; + i = snapshot->arrayCounter; + pdb = snapshot->processArray[i]; + + if (!pdb || snapshot->arrayCounter >= snapshot->numProcs) + { + SetLastError (ERROR_NO_MORE_FILES); + ERR (toolhelp, "End of snapshot array\n"); + return FALSE; + } + + TRACE (toolhelp, "Returning info on process %d, id %ld\n", + i, PDB_TO_PROCESS_ID (pdb)); + + lppe->cntUsage = 1; + lppe->th32ProcessID = PDB_TO_PROCESS_ID (pdb); + lppe->th32DefaultHeapID = (DWORD) pdb->heap; + lppe->cntThreads = pdb->threads; + lppe->th32ParentProcessID = PDB_TO_PROCESS_ID (pdb->parent); + lppe->pcPriClassBase = 6; /* FIXME: this is a made-up value */ + lppe->dwFlags = -1; /* FIXME: RESERVED by Microsoft :-) */ + if (pdb->exe_modref) + { + lppe->th32ModuleID = (DWORD) pdb->exe_modref->module; + strncpy (lppe->szExeFile, pdb->exe_modref->longname, + sizeof (lppe->szExeFile)); + } + else + { + lppe->th32ModuleID = (DWORD) 0; + strcpy (lppe->szExeFile, ""); + } + + SYSTEM_UNLOCK (); + + return TRUE; } diff --git a/scheduler/k32obj.c b/scheduler/k32obj.c index 7eaab60bffa..f6543bf1ddc 100644 --- a/scheduler/k32obj.c +++ b/scheduler/k32obj.c @@ -23,6 +23,7 @@ extern const K32OBJ_OPS CHANGE_Ops; extern const K32OBJ_OPS MEM_MAPPED_FILE_Ops; extern const K32OBJ_OPS DEVICE_Ops; extern const K32OBJ_OPS CONSOLE_Ops; +extern const K32OBJ_OPS SNAPSHOT_Ops; static const K32OBJ_OPS K32OBJ_NullOps = { diff --git a/scheduler/process.c b/scheduler/process.c index 19d7503b78a..1432ea74d23 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -22,7 +22,6 @@ #include "task.h" #include "server.h" #include "debug.h" -#include "toolhelp.h" static BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id ); static BOOL32 PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id ); @@ -42,7 +41,8 @@ const K32OBJ_OPS PROCESS_Ops = }; static DWORD PROCESS_InitialProcessID = 0; - +static PDB32 *PROCESS_PDBList = NULL; +static DWORD PROCESS_PDBList_Size = 0; /*********************************************************************** * PROCESS_Current @@ -177,6 +177,105 @@ static BOOL32 PROCESS_InheritEnvDB( PDB32 *pdb, LPCSTR cmd_line, LPCSTR env, return TRUE; } +/*********************************************************************** + * PROCESS_PDBList_Insert + * Insert this PDB into the global PDB list + */ + +static void PROCESS_PDBList_Insert (PDB32 *pdb) +{ + TRACE (process, "Inserting PDB 0x%0lx, #%ld current\n", + PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size); + + SYSTEM_LOCK (); /* FIXME: Do I need to worry about this ? + * I.e., could more than one process be + * created at once ? + */ + if (PROCESS_PDBList == NULL) + { + PROCESS_PDBList = pdb; + pdb->list_next = NULL; + pdb->list_prev = NULL; + } + else + { + PDB32 *first = PROCESS_PDBList, *last = PROCESS_PDBList; + if (first->list_prev) last = first->list_prev; + + PROCESS_PDBList = pdb; + pdb->list_next = first; + pdb->list_prev = last; + last->list_next = pdb; + first->list_prev = pdb; + } + PROCESS_PDBList_Size ++; + SYSTEM_UNLOCK (); +} + +/*********************************************************************** + * PROCESS_PDBList_Remove + * Remove this PDB from the global PDB list + */ + +static void PROCESS_PDBList_Remove (PDB32 *pdb) +{ + PDB32 *next = pdb->list_next, *prev = pdb->list_prev; + + TRACE (process, "Removing PDB 0x%0lx, #%ld current\n", + PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size); + + SYSTEM_LOCK (); + + if (prev == next) + { + next->list_prev = NULL; + next->list_next = NULL; + } + else + { + if (next) next->list_prev = prev; + if (prev) prev->list_next = next; + } + + if (pdb == PROCESS_PDBList) + { + PROCESS_PDBList = next ? next : prev; + } + PROCESS_PDBList_Size --; + + SYSTEM_UNLOCK (); +} + +/*********************************************************************** + * PROCESS_PDBList_Getsize + * Return the number of items in the global PDB list + */ + +int PROCESS_PDBList_Getsize () +{ + return PROCESS_PDBList_Size; +} + +/*********************************************************************** + * PROCESS_PDBList_Getfirst + * Return the head of the PDB list + */ + +PDB32* PROCESS_PDBList_Getfirst () +{ + return PROCESS_PDBList; +} + +/*********************************************************************** + * PROCESS_PDBList_Getnext + * Return the "next" pdb as referenced from the argument. + * If at the end of the list, return NULL. + */ + +PDB32* PROCESS_PDBList_Getnext (PDB32 *pdb) +{ + return (pdb->list_next != PROCESS_PDBList) ? pdb->list_next : NULL; +} /*********************************************************************** * PROCESS_FreePDB @@ -185,6 +284,13 @@ static BOOL32 PROCESS_InheritEnvDB( PDB32 *pdb, LPCSTR cmd_line, LPCSTR env, */ static void PROCESS_FreePDB( PDB32 *pdb ) { + /* + * FIXME: + * If this routine is called because PROCESS_CreatePDB fails, the + * following call to PROCESS_PDBList_Remove will probably screw + * up. + */ + PROCESS_PDBList_Remove (pdb); pdb->header.type = K32OBJ_UNKNOWN; if (pdb->handle_table) HANDLE_CloseAll( pdb, NULL ); ENV_FreeEnvironment( pdb ); @@ -230,6 +336,8 @@ static PDB32 *PROCESS_CreatePDB( PDB32 *parent ) if (!HANDLE_CreateTable( pdb, TRUE )) goto error; + PROCESS_PDBList_Insert (pdb); + return pdb; error: @@ -934,17 +1042,3 @@ void PROCESS_ResumeOtherThreads(void) SYSTEM_UNLOCK(); } -BOOL32 WINAPI Process32First(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe) -{ - FIXME (process, "(0x%08x,%p), stub!\n", hSnapshot, lppe); - SetLastError (ERROR_NO_MORE_FILES); - return FALSE; -} - -BOOL32 WINAPI Process32Next(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe) -{ - FIXME (process, "(0x%08x,%p), stub!\n", hSnapshot, lppe); - SetLastError (ERROR_NO_MORE_FILES); - return FALSE; -} - -- 2.11.4.GIT