438 lines
12 KiB
C
438 lines
12 KiB
C
/*
|
|
* Misc Toolhelp functions
|
|
*
|
|
* Copyright 1996 Marcus Meissner
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#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 =
|
|
{
|
|
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
|
|
* me please do that. -Marcus
|
|
*/
|
|
static struct notify
|
|
{
|
|
HTASK16 htask;
|
|
FARPROC16 lpfnCallback;
|
|
WORD wFlags;
|
|
} *notifys = NULL;
|
|
|
|
static int nrofnotifys = 0;
|
|
|
|
static FARPROC16 HookNotify = NULL;
|
|
|
|
BOOL16 WINAPI NotifyRegister( HTASK16 htask, FARPROC16 lpfnCallback,
|
|
WORD wFlags )
|
|
{
|
|
int i;
|
|
|
|
TRACE(toolhelp, "(%x,%lx,%x) called.\n",
|
|
htask, (DWORD)lpfnCallback, wFlags );
|
|
if (!htask) htask = GetCurrentTask();
|
|
for (i=0;i<nrofnotifys;i++)
|
|
if (notifys[i].htask==htask)
|
|
break;
|
|
if (i==nrofnotifys) {
|
|
if (notifys==NULL)
|
|
notifys=(struct notify*)HeapAlloc( SystemHeap, 0,
|
|
sizeof(struct notify) );
|
|
else
|
|
notifys=(struct notify*)HeapReAlloc( SystemHeap, 0, notifys,
|
|
sizeof(struct notify)*(nrofnotifys+1));
|
|
if (!notifys) return FALSE;
|
|
nrofnotifys++;
|
|
}
|
|
notifys[i].htask=htask;
|
|
notifys[i].lpfnCallback=lpfnCallback;
|
|
notifys[i].wFlags=wFlags;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL16 WINAPI NotifyUnregister( HTASK16 htask )
|
|
{
|
|
int i;
|
|
|
|
TRACE(toolhelp, "(%x) called.\n", htask );
|
|
if (!htask) htask = GetCurrentTask();
|
|
for (i=nrofnotifys;i--;)
|
|
if (notifys[i].htask==htask)
|
|
break;
|
|
if (i==-1)
|
|
return FALSE;
|
|
memcpy(notifys+i,notifys+(i+1),sizeof(struct notify)*(nrofnotifys-i-1));
|
|
notifys=(struct notify*)HeapReAlloc( SystemHeap, 0, notifys,
|
|
(nrofnotifys-1)*sizeof(struct notify));
|
|
nrofnotifys--;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL16 WINAPI StackTraceCSIPFirst(STACKTRACEENTRY *ste, WORD wSS, WORD wCS, WORD wIP, WORD wBP)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL16 WINAPI StackTraceFirst(STACKTRACEENTRY *ste, HTASK16 Task)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL16 WINAPI StackTraceNext(STACKTRACEENTRY *ste)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ToolHelpHook (KERNEL.341)
|
|
* see "Undocumented Windows"
|
|
*/
|
|
FARPROC16 WINAPI ToolHelpHook(FARPROC16 lpfnNotifyHandler)
|
|
{
|
|
FARPROC16 tmp;
|
|
tmp = HookNotify;
|
|
HookNotify = lpfnNotifyHandler;
|
|
/* just return previously installed notification function */
|
|
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)
|
|
{
|
|
HANDLE32 ssHandle;
|
|
SNAPSHOT_OBJECT *snapshot;
|
|
int numProcesses;
|
|
int i;
|
|
PDB32* pdb;
|
|
|
|
TRACE(toolhelp, "%lx & TH32CS_INHERIT (%x) = %lx %s\n", dwFlags,
|
|
TH32CS_INHERIT,
|
|
dwFlags & TH32CS_INHERIT,
|
|
dwFlags & TH32CS_INHERIT ? "TRUE" : "FALSE");
|
|
TRACE(toolhelp, "%lx & TH32CS_SNAPHEAPLIST (%x) = %lx %s\n", dwFlags,
|
|
TH32CS_SNAPHEAPLIST,
|
|
dwFlags & TH32CS_SNAPHEAPLIST,
|
|
dwFlags & TH32CS_SNAPHEAPLIST ? "TRUE" : "FALSE");
|
|
TRACE(toolhelp, "%lx & TH32CS_SNAPMODULE (%x) = %lx %s\n", dwFlags,
|
|
TH32CS_SNAPMODULE,
|
|
dwFlags & TH32CS_SNAPMODULE,
|
|
dwFlags & TH32CS_SNAPMODULE ? "TRUE" : "FALSE");
|
|
TRACE(toolhelp, "%lx & TH32CS_SNAPPROCESS (%x) = %lx %s\n", dwFlags,
|
|
TH32CS_SNAPPROCESS,
|
|
dwFlags & TH32CS_SNAPPROCESS,
|
|
dwFlags & TH32CS_SNAPPROCESS ? "TRUE" : "FALSE");
|
|
TRACE(toolhelp, "%lx & TH32CS_SNAPTHREAD (%x) = %lx %s\n", dwFlags,
|
|
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;
|
|
}
|