Implemented CreateToolhelp32Snapshot, including two of the routines

using snapshots, Process32First and Process32Next.
This commit is contained in:
Patrick Spinler 1998-12-11 15:04:11 +00:00 committed by Alexandre Julliard
parent bc93bc833e
commit 3f8e1e4d44
6 changed files with 483 additions and 19 deletions

View File

@ -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 */

29
include/tlhelp32.h Normal file
View File

@ -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 */

View File

@ -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)

View File

@ -8,11 +8,54 @@
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
#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
@ -102,11 +145,299 @@ FARPROC16 tmp;
return 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 <snapshot->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;
}

View File

@ -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 =
{

View File

@ -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;
}