547 lines
11 KiB
C
547 lines
11 KiB
C
|
/*++
|
||
|
Copyright (c) 1992 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
pidtid.c
|
||
|
|
||
|
Author:
|
||
|
Griffith Wm. Kadnier (v-griffk)
|
||
|
|
||
|
Environment:
|
||
|
Win32 - User
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
|
||
|
/****************************** DATA **************************************/
|
||
|
|
||
|
static LPPD LppdHead = NULL;
|
||
|
static int ipid = 0;
|
||
|
|
||
|
/****************************** CODE **************************************/
|
||
|
|
||
|
|
||
|
VOID SetIpid(int i)
|
||
|
{
|
||
|
ipid = i;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID RecycleIpid1(void)
|
||
|
{
|
||
|
if (LppdHead && LppdHead->pstate != psDestroyed && !LppdHead->lppdNext&& ipid == 2)
|
||
|
{
|
||
|
ipid = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
LPPD GetLppdHead(void)
|
||
|
/*++
|
||
|
Routine Description:
|
||
|
Retrieves head of LPPD chain.
|
||
|
Return Value:
|
||
|
Pointer to first PD in chain
|
||
|
--*/
|
||
|
{
|
||
|
return LppdHead;
|
||
|
}
|
||
|
|
||
|
|
||
|
LPPD CreatePd(HPID hpid)
|
||
|
/*++
|
||
|
Routine Description:
|
||
|
This function will create a process descriptor block, fill in
|
||
|
the defaults for the fields and return a pointer to the descriptor
|
||
|
block. No attempts are made to verify that the hpid (handle to
|
||
|
process identifier) passed in is correct in any way.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hpid - Handle to process in the OSDebug world
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NULL on failure or a pointer to a PD structure
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LPPD lppd;
|
||
|
LPPD lppdT;
|
||
|
|
||
|
/*
|
||
|
** first allocate and verify the allocation succeeded
|
||
|
*/
|
||
|
|
||
|
lppd = (LPPD) malloc(sizeof(PD));
|
||
|
if (lppd == NULL) {
|
||
|
return lppd;
|
||
|
}
|
||
|
memset(lppd, 0, sizeof(PD));
|
||
|
|
||
|
/*
|
||
|
** Now fill in the default set of values for the structure
|
||
|
|
||
|
** hpid == passed in value
|
||
|
** state == no program has yet been loaded here.
|
||
|
** lptdNext == No threads currently linked on this process.
|
||
|
*/
|
||
|
|
||
|
lppd->hpid = hpid;
|
||
|
lppd->pstate = psNoProgLoaded;
|
||
|
lppd->lptdList = NULL;
|
||
|
lppd->ctid = 0;
|
||
|
lppd->ipid = ipid++;
|
||
|
lppd->exceptionList=NULL;
|
||
|
lppd->lpBaseExeName = NULL;
|
||
|
lppd->fPrecious = FALSE;
|
||
|
lppd->fChild = FALSE;
|
||
|
lppd->fFrozen = FALSE;
|
||
|
|
||
|
/*
|
||
|
** Now append it to the list of process descriptors
|
||
|
*/
|
||
|
|
||
|
lppd->lppdNext = NULL;
|
||
|
lppdT = LppdHead;
|
||
|
if (lppdT == NULL) {
|
||
|
LppdHead = lppd;
|
||
|
} else {
|
||
|
while (lppdT->lppdNext) {
|
||
|
lppdT = lppdT->lppdNext;
|
||
|
}
|
||
|
lppdT->lppdNext = lppd;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Return the pointer to the process descriptor block allocated
|
||
|
*/
|
||
|
|
||
|
return(lppd);
|
||
|
} /* CreatePd() */
|
||
|
|
||
|
|
||
|
VOID
|
||
|
DestroyPd(
|
||
|
LPPD lppd,
|
||
|
BOOL fDestroyPrecious
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Remove a PD from the list and free it.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
lppd - Supplies pointer to PD to be destroyed
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LPPD *lplppd;
|
||
|
|
||
|
/*
|
||
|
* Remove it from the chain
|
||
|
*/
|
||
|
for (lplppd = &LppdHead; *lplppd; lplppd = &((*lplppd)->lppdNext) ) {
|
||
|
if (*lplppd == lppd) {
|
||
|
if (lppd->lpBaseExeName) {
|
||
|
free(lppd->lpBaseExeName);
|
||
|
lppd->lpBaseExeName = NULL;
|
||
|
}
|
||
|
if (lppd->fPrecious && !fDestroyPrecious) {
|
||
|
lppd->pstate = psDestroyed;
|
||
|
} else {
|
||
|
*lplppd = lppd->lppdNext;
|
||
|
free(lppd);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} /* DestroyPd() */
|
||
|
|
||
|
|
||
|
/*** LppdOfHpid
|
||
|
|
||
|
** Synopsis:
|
||
|
** lppd = LppdOfHpid(hpid)
|
||
|
|
||
|
** Entry:
|
||
|
** hpid - Process id handle to be found
|
||
|
|
||
|
** Returns:
|
||
|
** pointer to PD if hpid is found and NULL otherwise
|
||
|
|
||
|
** Description:
|
||
|
** This routine looks down the list of PDS looking for the specific
|
||
|
** hpid. If it is found then a pointer to that pd will be returned
|
||
|
** otherwise NULL is returned
|
||
|
*/
|
||
|
|
||
|
LPPD
|
||
|
LppdOfHpid(
|
||
|
HPID hpid
|
||
|
)
|
||
|
{
|
||
|
LPPD lppd = LppdHead;
|
||
|
|
||
|
while (lppd != NULL) {
|
||
|
if (lppd->hpid == hpid) {
|
||
|
break;
|
||
|
}
|
||
|
lppd = lppd->lppdNext;
|
||
|
}
|
||
|
|
||
|
return(lppd);
|
||
|
} /* LppdOfHpid() */
|
||
|
|
||
|
|
||
|
/*** LppdOfIpid
|
||
|
|
||
|
** Synopsis:
|
||
|
** lppd = LppdOfIpid(ipid)
|
||
|
|
||
|
** Entry:
|
||
|
** ipid - Internal index number of the process
|
||
|
|
||
|
** Returns:
|
||
|
** Pointer to process structure if one exists else NULL
|
||
|
|
||
|
** Description:
|
||
|
|
||
|
*/
|
||
|
|
||
|
LPPD
|
||
|
LppdOfIpid(
|
||
|
UINT ipid
|
||
|
)
|
||
|
{
|
||
|
LPPD lppd = LppdHead;
|
||
|
|
||
|
while (lppd != NULL) {
|
||
|
if (lppd->ipid == ipid) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
lppd = lppd->lppdNext;
|
||
|
}
|
||
|
|
||
|
return lppd;
|
||
|
} /* LppdOfIpid() */
|
||
|
|
||
|
|
||
|
LPPD
|
||
|
ValidLppdOfIpid(
|
||
|
UINT ipid
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Look up LPPD by its index #, ignoring destroyed lppd's
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ipid - ordinal number of process
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
LPPD or NULL
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LPPD lppd;
|
||
|
|
||
|
for (lppd = LppdHead; lppd != NULL; lppd = lppd->lppdNext) {
|
||
|
if (lppd->pstate != psDestroyed && lppd->ipid == ipid) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return lppd;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
GetFirstValidPDTD(
|
||
|
LPPD *plppd,
|
||
|
LPTD *plptd
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Find first non-destroyed LPPD/LPTD pair in list
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
plppd - returns lppd
|
||
|
plptd - returns lptd
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE for success, FALSE of none found. Values pointed to by
|
||
|
args are not modified if search fails.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LPPD lppd;
|
||
|
|
||
|
for (lppd = LppdHead; lppd; lppd = lppd->lppdNext) {
|
||
|
if (lppd->pstate != psDestroyed && lppd->lptdList) {
|
||
|
*plppd = lppd;
|
||
|
*plptd = lppd->lptdList;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*** CreateTd
|
||
|
|
||
|
** Synopsis:
|
||
|
** lptd = CreateTd(lppd, htid)
|
||
|
|
||
|
** Entry:
|
||
|
** lppd - Pointer to process descriptor block to create thread in
|
||
|
** htid - OSDebug thread handle to be added to process
|
||
|
|
||
|
** Returns:
|
||
|
** pointer to thread descriptor block on success, NULL on failure
|
||
|
|
||
|
** Description:
|
||
|
** This function will create a thread descriptor block for the
|
||
|
** osdebug handle to a thread. It will be added to the list of
|
||
|
** threads for the specified process descriptor block.
|
||
|
*/
|
||
|
|
||
|
|
||
|
LPTD
|
||
|
CreateTd(
|
||
|
LPPD lppd,
|
||
|
HTID htid
|
||
|
)
|
||
|
{
|
||
|
LPTD lptd;
|
||
|
LPTD lptd2;
|
||
|
|
||
|
|
||
|
/*
|
||
|
** First allocate and verify success
|
||
|
*/
|
||
|
|
||
|
lptd = (LPTD) malloc(sizeof(TD));
|
||
|
if (lptd == NULL)
|
||
|
return lptd;
|
||
|
memset(lptd, 0, sizeof(TD));
|
||
|
|
||
|
/*
|
||
|
** Now fill in the default set of values for a thread descriptor
|
||
|
|
||
|
*/
|
||
|
|
||
|
lptd->htid = htid;
|
||
|
lptd->lppd = lppd;
|
||
|
lptd->tstate = tsPreRunning;
|
||
|
lptd->itid = lppd->ctid++;
|
||
|
|
||
|
/*
|
||
|
** Now insert it in the thread list for the process
|
||
|
*/
|
||
|
|
||
|
lptd->lptdNext = NULL;
|
||
|
lptd2 = lppd->lptdList;
|
||
|
if (lptd2 == NULL) {
|
||
|
lppd->lptdList = lptd;
|
||
|
} else {
|
||
|
while (lptd2->lptdNext != NULL) {
|
||
|
lptd2 = lptd2->lptdNext;
|
||
|
}
|
||
|
lptd2->lptdNext = lptd;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
*/
|
||
|
|
||
|
return lptd;
|
||
|
} /* CreateTd() */
|
||
|
|
||
|
|
||
|
VOID
|
||
|
SetTdInfo(
|
||
|
LPTD lptd
|
||
|
)
|
||
|
{
|
||
|
// BUGBUG need portable structures here
|
||
|
BYTE buf[sizeof(IOCTLGENERIC)+sizeof(GET_TEB_ADDRESS)];
|
||
|
PIOCTLGENERIC pig = (PIOCTLGENERIC)&buf[0];
|
||
|
PGET_TEB_ADDRESS Gta = (PGET_TEB_ADDRESS)pig->data;
|
||
|
LPTD lptdSave;
|
||
|
DWORD dw;
|
||
|
|
||
|
|
||
|
if (g_contWorkspace_WkSp.m_bKernelDebugger) {
|
||
|
lptd->lpszTname = NULL;
|
||
|
lptd->TebBaseAddress = 0;
|
||
|
} else {
|
||
|
if (lptd->TebBaseAddress == 0) {
|
||
|
lptdSave = LptdCur;
|
||
|
LptdCur = lptd;
|
||
|
pig->ioctlSubType = IG_GET_TEB_ADDRESS;
|
||
|
pig->length = sizeof(GET_TEB_ADDRESS);
|
||
|
OSDSystemService( LppdCur->hpid,
|
||
|
lptd->htid,
|
||
|
(SSVC) ssvcGeneric,
|
||
|
(LPV)pig,
|
||
|
pig->length + sizeof(IOCTLGENERIC),
|
||
|
&dw
|
||
|
);
|
||
|
lptd->TebBaseAddress = Gta->Address;
|
||
|
lptd->lpszTname = GetLastFrameFuncName();
|
||
|
LptdCur = lptdSave;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
SetPdInfo(
|
||
|
LPPD lppd
|
||
|
)
|
||
|
{
|
||
|
// BUGBUG Need portable structures here
|
||
|
BYTE buf[sizeof(IOCTLGENERIC)+sizeof(RTL_USER_PROCESS_PARAMETERS64)];
|
||
|
PIOCTLGENERIC pig = (PIOCTLGENERIC)&buf[0];
|
||
|
PRTL_USER_PROCESS_PARAMETERS64 Upp = (PRTL_USER_PROCESS_PARAMETERS64)pig->data;
|
||
|
DWORD dw;
|
||
|
XOSD xosd;
|
||
|
|
||
|
pig->ioctlSubType = IG_GET_PROCESS_PARAMETERS;
|
||
|
pig->length = sizeof(RTL_USER_PROCESS_PARAMETERS64);
|
||
|
|
||
|
OSDGetDebugMetric( lppd->hpid,
|
||
|
0,
|
||
|
mtrcProcessorType,
|
||
|
&lppd->mptProcessorType
|
||
|
);
|
||
|
|
||
|
if (!g_contWorkspace_WkSp.m_bKernelDebugger) {
|
||
|
xosd = OSDSystemService( lppd->hpid,
|
||
|
NULL,
|
||
|
(SSVC) ssvcGeneric,
|
||
|
(LPV)pig,
|
||
|
pig->length + sizeof(IOCTLGENERIC),
|
||
|
&dw
|
||
|
);
|
||
|
|
||
|
if (xosd == xosdNone) {
|
||
|
memcpy(&lppd->ProcessParameters, Upp, sizeof(RTL_USER_PROCESS_PARAMETERS64));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID DestroyTd(LPTD lptd)
|
||
|
{
|
||
|
LPPD lppd = lptd->lppd;
|
||
|
LPTD lptdT;
|
||
|
|
||
|
if (lppd->lptdList == lptd) {
|
||
|
lppd->lptdList = lptd->lptdNext;
|
||
|
} else {
|
||
|
lptdT = lppd->lptdList;
|
||
|
while (lptdT->lptdNext != lptd) {
|
||
|
lptdT = lptdT->lptdNext;
|
||
|
Assert(lptdT != NULL);
|
||
|
}
|
||
|
lptdT->lptdNext = lptd->lptdNext;
|
||
|
}
|
||
|
|
||
|
free(lptd);
|
||
|
} /* DestroyTd() */
|
||
|
|
||
|
/*** LptdOfLppdHtid
|
||
|
|
||
|
** Synopsis:
|
||
|
** lppd = LptdOfLppdHtid(lppd, htid)
|
||
|
|
||
|
** Entry:
|
||
|
** lppd - Process descripter table to look in for thread descriptor
|
||
|
** htid - thread id handle to be found
|
||
|
|
||
|
** Returns:
|
||
|
** pointer to TD if htid is found and NULL otherwise
|
||
|
|
||
|
** Description:
|
||
|
** This routine looks down the list of TDs looking for the specific
|
||
|
** htid. If it is found then a pointer to that td will be returned
|
||
|
** otherwise NULL is returned
|
||
|
*/
|
||
|
|
||
|
LPTD
|
||
|
LptdOfLppdHtid(
|
||
|
LPPD lppd,
|
||
|
HTID htid
|
||
|
)
|
||
|
{
|
||
|
LPTD lptd;
|
||
|
|
||
|
if (!lppd) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
lptd = lppd->lptdList;
|
||
|
|
||
|
while (lptd != NULL) {
|
||
|
if (lptd->htid == htid) {
|
||
|
return lptd;
|
||
|
}
|
||
|
lptd = lptd->lptdNext;
|
||
|
}
|
||
|
|
||
|
return(lptd);
|
||
|
} /* LptdOfLppdHtid() */
|
||
|
|
||
|
|
||
|
/*** LptdOfLppdItid
|
||
|
|
||
|
** Synopsis:
|
||
|
** lptd = LptdOfLppdItid(lppd, itid)
|
||
|
|
||
|
** Entry:
|
||
|
** lppd - pointer to process
|
||
|
** itid - index of thread
|
||
|
|
||
|
** Returns:
|
||
|
** pointer to thread if found else NULL
|
||
|
|
||
|
** Description:
|
||
|
** This function will locate a thread within the given process which
|
||
|
** has the correct thread id. This thread id is local to the shell
|
||
|
** of the debugger and is not the same as a Htid. If no such thread
|
||
|
** is found then NULL will be returned
|
||
|
*/
|
||
|
|
||
|
LPTD
|
||
|
LptdOfLppdItid(
|
||
|
LPPD lppd,
|
||
|
UINT itid
|
||
|
)
|
||
|
{
|
||
|
LPTD lptd = lppd->lptdList;
|
||
|
|
||
|
while (lptd != NULL) {
|
||
|
if (lptd->itid == itid)
|
||
|
return lptd;
|
||
|
lptd = lptd->lptdNext;
|
||
|
}
|
||
|
|
||
|
return lptd;
|
||
|
} /* LptdOfLppdItid() */
|