Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1246 lines
38 KiB

/******************************Module*Header*******************************\
* Module Name: process.cxx
*
* Support for dteb and dpeb APIs
*
* Created: 12-Mar-1996
* Author: Mark Enstrom [marke]
*
* Copyright (c) 1996-2000 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
HRESULT
GetProcessField(
IN PDEBUG_CLIENT Client,
IN OUT PULONG64 pProcessAddress,
IN PCSTR FieldPath,
OUT PDEBUG_VALUE FieldValue,
IN ULONG DesiredType
)
{
HRESULT hr;
OutputControl OutCtl(Client);
PDEBUG_SYSTEM_OBJECTS System;
PDEBUG_SYMBOLS Symbols;
ULONG64 ProcessAddress = (pProcessAddress != NULL) ? *pProcessAddress : CURRENT_PROCESS_ADDRESS;
if (Client == NULL || FieldPath == NULL) return E_INVALIDARG;
PCSTR Field = FieldPath;
PCSTR Dot;
// Check FieldPath's basic validity
if (!iscsymf(*Field)) return E_INVALIDARG;
while ((Dot = strchr(Field, '.')) != NULL)
{
Field = Dot + 1;
if (!iscsymf(*Field)) return E_INVALIDARG;
}
// Query interfaces needed
if ((hr = Client->QueryInterface(__uuidof(IDebugSystemObjects),
(void **)&System)) != S_OK)
{
return hr;
}
if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
(void **)&Symbols)) != S_OK)
{
System->Release();
return hr;
}
if (ProcessAddress == CURRENT_PROCESS_ADDRESS)
{
hr = System->GetCurrentProcessDataOffset(&ProcessAddress);
if (hr == S_OK)
{
if (ProcessAddress != NULL) *pProcessAddress = ProcessAddress;
}
else
{
OutCtl.OutErr("GetCurrentProcess returned %s.\n", pszHRESULT(hr));
}
}
if (hr == S_OK)
{
TypeOutputParser TypeParser(Client);
OutputState OutState(Client, FALSE);
OutputControl OutCtlToParser;
ULONG ProcessTypeId;
ULONG64 NTModule;
DEBUG_VALUE ProcessObject;
DEBUG_VALUE ObjectType;
if ((hr = OutState.Setup(0, &TypeParser)) == S_OK &&
(hr = OutCtlToParser.SetControl(DEBUG_OUTCTL_THIS_CLIENT |
DEBUG_OUTCTL_NOT_LOGGED |
DEBUG_OUTCTL_OVERRIDE_MASK,
OutState.Client)) == S_OK &&
(hr = Symbols->GetSymbolTypeId("nt!_EPROCESS", &ProcessTypeId, &NTModule)) == S_OK)
{
TypeOutputDumper TypeReader(OutState.Client, &OutCtlToParser);
if ((hr = OutState.OutputTypeVirtual(0, "nt!KOBJECTS", 0)) == S_OK)
{
hr = TypeParser.Get(&ProcessObject, "ProcessObject", DEBUG_VALUE_INT64);
}
if (hr != S_OK)
{
OutCtl.OutWarn("enum nt!KOBJECTS's ProcessObject value wasn't found.\n");
ProcessObject.I64 = 3; // From ke.h
}
TypeParser.DiscardOutput();
TypeReader.IncludeMarked();
TypeReader.MarkField("Pcb.Header.Type");
TypeReader.MarkField(FieldPath);
if ((hr = TypeReader.OutputVirtual(NTModule, ProcessTypeId, ProcessAddress)) == S_OK)
{
// Make sure this object is a process
if ((hr = TypeParser.Get(&ObjectType, "Type", DEBUG_VALUE_INT64)) == S_OK &&
ObjectType.I64 == ProcessObject.I64)
{
OutCtl.OutVerb(" Process Addr = 0x%p\n", ProcessAddress);
hr = TypeParser.Get(FieldValue, Field, DesiredType);
}
else
{
if (hr == S_OK)
{
OutCtl.OutErr("0x%p is not a process object.\n", ProcessAddress);
hr = S_FALSE;
}
else
{
OutCtl.OutErr("Unable to find 'Type' value from nt!_EPROCESS Pcb.Header.\n");
}
}
}
else
{
OutCtl.OutErr("Unable to get process contents at 0x%p.\n", ProcessAddress);
}
}
else
{
OutCtl.OutErr("Unable to prepare nt!_EPROCESS type read.\n");
}
}
Symbols->Release();
System->Release();
return hr;
}
HRESULT
GetThreadField(
IN PDEBUG_CLIENT Client,
IN OUT PULONG64 pThreadAddress,
IN PCSTR FieldPath,
OUT PDEBUG_VALUE FieldValue,
IN ULONG DesiredType
)
{
HRESULT hr;
OutputControl OutCtl(Client);
PDEBUG_SYSTEM_OBJECTS System;
PDEBUG_SYMBOLS Symbols;
ULONG64 ThreadAddress = (pThreadAddress != NULL) ? *pThreadAddress : CURRENT_THREAD_ADDRESS;
if (Client == NULL || FieldPath == NULL) return E_INVALIDARG;
PCSTR Field = FieldPath;
PCSTR Dot;
// Check FieldPath's basic validity
if (!iscsymf(*Field)) return E_INVALIDARG;
while ((Dot = strchr(Field, '.')) != NULL)
{
Field = Dot + 1;
if (!iscsymf(*Field)) return E_INVALIDARG;
}
// Query interfaces needed
if ((hr = Client->QueryInterface(__uuidof(IDebugSystemObjects),
(void **)&System)) != S_OK)
{
return hr;
}
if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
(void **)&Symbols)) != S_OK)
{
System->Release();
return hr;
}
if (ThreadAddress == CURRENT_THREAD_ADDRESS)
{
hr = System->GetCurrentThreadDataOffset(&ThreadAddress);
if (hr == S_OK && ThreadAddress != NULL)
*pThreadAddress = ThreadAddress;
}
if (hr == S_OK)
{
TypeOutputParser TypeParser(Client);
OutputState OutState(Client, FALSE);
OutputControl OutCtlToParser;
ULONG ThreadTypeId;
ULONG64 NTModule;
DEBUG_VALUE ThreadObject;
DEBUG_VALUE ObjectType;
if ((hr = OutState.Setup(0, &TypeParser)) == S_OK &&
(hr = OutCtlToParser.SetControl(DEBUG_OUTCTL_THIS_CLIENT |
DEBUG_OUTCTL_NOT_LOGGED |
DEBUG_OUTCTL_OVERRIDE_MASK,
OutState.Client)) == S_OK &&
(hr = Symbols->GetSymbolTypeId("nt!_ETHREAD", &ThreadTypeId, &NTModule)) == S_OK)
{
TypeOutputDumper TypeReader(OutState.Client, &OutCtlToParser);
if ((hr = OutState.OutputTypeVirtual(0, "nt!KOBJECTS", 0)) == S_OK)
{
hr = TypeParser.Get(&ThreadObject, "ThreadObject", DEBUG_VALUE_INT64);
}
if (hr != S_OK)
{
OutCtl.OutWarn("enum nt!KOBJECTS's ThreadObject value wasn't found.\n");
ThreadObject.I64 = 6; // From ke.h
}
TypeParser.DiscardOutput();
TypeReader.IncludeMarked();
TypeReader.MarkField("Tcb.Header.Type");
TypeReader.MarkField(FieldPath);
if ((hr = TypeReader.OutputVirtual(NTModule, ThreadTypeId, ThreadAddress)) == S_OK)
{
// Make sure this object is a thread
if ((hr = TypeParser.Get(&ObjectType, "Type", DEBUG_VALUE_INT64)) == S_OK &&
ObjectType.I64 == ThreadObject.I64)
{
OutCtl.OutVerb(" Thread Addr = 0x%p\n", ThreadAddress);
hr = TypeParser.Get(FieldValue, Field, DesiredType);
}
else
{
if (hr == S_OK)
{
OutCtl.OutErr("0x%p is not a thread object.\n", ThreadAddress);
hr = S_FALSE;
}
else
{
OutCtl.OutErr("Unable to find 'Type' value from nt!_ETHREAD Tcb.Header.\n");
}
}
}
else
{
OutCtl.OutErr("Unable to get thread contents at 0x%p.\n", ThreadAddress);
}
}
else
{
OutCtl.OutErr("Unable to prepare nt!_ETHREAD type read.\n");
}
}
Symbols->Release();
System->Release();
return hr;
}
HRESULT
GetCurrentProcessor(
IN PDEBUG_CLIENT Client,
OPTIONAL OUT PULONG pProcessor,
OPTIONAL OUT PHANDLE phCurrentThread
)
{
HRESULT hr = E_INVALIDARG;
PDEBUG_SYSTEM_OBJECTS DebugSystem;
ULONG64 hCurrentThread;
if (phCurrentThread != NULL) *phCurrentThread = NULL;
if (pProcessor != NULL) *pProcessor = 0;
if (Client == NULL ||
(hr = Client->QueryInterface(__uuidof(IDebugSystemObjects),
(void **)&DebugSystem)) != S_OK)
{
return hr;
}
hr = DebugSystem->GetCurrentThreadHandle(&hCurrentThread);
if (hr == S_OK)
{
if (phCurrentThread != NULL)
{
*phCurrentThread = (HANDLE) hCurrentThread;
}
if (pProcessor != NULL)
{
*pProcessor = (ULONG) hCurrentThread - 1;
}
}
DebugSystem->Release();
return hr;
}
/******************************Public*Routine******************************\
* DumpTebBatch
*
* Dumps GDI TEB batch info
*
* Arguments:
*
* TebAddress - address of Teb
*
* Return Value:
*
* None
*
* History:
*
* 20-Sep-2000 -by- Jason Hartman [jasonha]
*
\**************************************************************************/
// from hmgshare.h
enum _BATCH_TYPE
{
BatchTypePatBlt,
BatchTypePolyPatBlt,
BatchTypeTextOut,
BatchTypeTextOutRect,
BatchTypeSetBrushOrg,
BatchTypeSelectClip,
BatchTypeSelectFont,
BatchTypeDeleteBrush,
BatchTypeDeleteRegion
};
VOID
DumpTebBatch(
PDEBUG_CLIENT Client,
ULONG64 TebAddress
)
{
FIELD_INFO TebBatchFields[] = {
{ DbgStr("GdiBatchCount"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("GdiTebBatch.Offset"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("GdiTebBatch.HDC"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("GdiTebBatch.Buffer"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME | DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL},
};
SYM_DUMP_PARAM TebBatchSym = {
sizeof (SYM_DUMP_PARAM), DbgStr(GDIType(_TEB)),
0,
TebAddress,
NULL, NULL, NULL,
sizeof(TebBatchFields)/sizeof(TebBatchFields[0]), TebBatchFields
};
ULONG BatchCount;
BOOL OldBatch = FALSE;
ULONG64 BatchEntryAddress;
ULONG64 BatchBufferLength = 0;
ULONG64 BatchBufferEnd;
ULONG SmallestBatchEntrySize = max(1, GetTypeSize(GDIType(BATCHCOMMAND)));
USHORT BatchEntryLength;
USHORT BatchEntryType;
ULONG error;
PrepareCallbacks(FALSE, 0);
ExtOut("GDI Batch Info from Teb %p:\n", TebAddress);
error = Ioctl(IG_DUMP_SYMBOL_INFO, &TebBatchSym, TebBatchSym.size);
if (error)
{
ExtErr("Ioctl returned %s\n", pszWinDbgError(error));
}
else
{
BatchCount = (ULONG)TebBatchFields[0].address;
BatchEntryAddress = TebBatchFields[3].address;
if (BatchCount == 0)
{
ExtOut(" ** Dumping old batch entries **\n");
OldBatch = TRUE;
}
ExtOut("First batch entry @ %p.\n", BatchEntryAddress);
GetArrayDimensions(Client, "_GDI_TEB_BATCH", "Buffer", NULL, (ULONG *)&BatchBufferLength, NULL);
if (TebBatchFields[1].address && TebBatchFields[1].address < BatchBufferLength)
{
BatchBufferLength = TebBatchFields[1].address;
}
BatchBufferEnd = BatchEntryAddress + BatchBufferLength;
while ((OldBatch || BatchCount > 0) && BatchEntryAddress < BatchBufferEnd)
{
error = (ULONG)InitTypeRead(BatchEntryAddress, win32k!BATCHCOMMAND);
if (error)
{
ExtErr("InitTypeRead(%p, %s) returned %s.\n", BatchEntryAddress, GDIType(BATCHCOMMAND), pszWinDbgError(error));
break;
}
BatchEntryLength = (USHORT)ReadField(Length);
if (BatchEntryAddress + BatchEntryLength > BatchBufferEnd)
{
ExtOut("Invalid batch entry - length is too long.\n");
break;
}
if (BatchEntryLength < SmallestBatchEntrySize)
{
ExtOut("Invalid batch entry - length is too small.\n");
break;
}
BatchEntryType = (USHORT)ReadField(Type);
switch (BatchEntryType)
{
case BatchTypePatBlt:
{
ExtOut(" BatchTypePatBlt\n");
}
break;
case BatchTypePolyPatBlt:
{
ExtOut(" BatchTypePolyPatBlt\n");
}
break;
case BatchTypeTextOut:
{
ExtOut(" BatchTypeTextOut\n");
}
break;
case BatchTypeTextOutRect:
{
ExtOut(" BatchTypeTextOutRect\n");
}
break;
case BatchTypeSetBrushOrg:
{
ExtOut(" BatchTypeSetBrushOrg\n");
}
break;
case BatchTypeSelectClip:
{
ExtOut(" BatchTypeSelectClip\n");
}
break;
case BatchTypeSelectFont:
{
ExtOut(" BatchTypeSelectFont\n");
}
break;
case BatchTypeDeleteBrush:
{
ExtOut(" BatchTypeDeleteBrush\n");
}
break;
case BatchTypeDeleteRegion:
{
ExtOut(" BatchTypeDeleteRegion\n");
}
break;
default:
ExtOut(" BatchType %hu is not recognized.\n", BatchEntryType);
}
BatchCount--;
BatchEntryAddress += (ULONG64)BatchEntryLength;
}
if (!OldBatch && BatchCount)
{
ExtOut("Batch may be invalid %lu entries unchecked.\n", BatchCount);
}
}
#if 0
if (istatus)
{
dprintf ("\nGDI Batch count = %li\n",pteb->GdiBatchCount);
if (pteb->GdiBatchCount > 0)
{
ULONG index;
PBATCHCOMMAND pBatch = (PBATCHCOMMAND)&pteb->GdiTebBatch.Buffer[0];
dprintf ("\nGDI Batch HDC = 0x%lx\n",pteb->GdiTebBatch.HDC);
dprintf ("\nGDI Batch offet = 0x%lx\n",pteb->GdiTebBatch.Offset);
for (index=pteb->GdiBatchCount;index>0;index--)
{
dprintf("-----------------------------------------------------\n");
switch (pBatch->Type)
{
case BatchTypePatBlt:
{
PBATCHPATBLT pPatblt = (PBATCHPATBLT)pBatch;
dprintf("Patblt: length = 0x%lx\n",pPatblt->Length);
dprintf("Patblt: x = 0x%lx\n",pPatblt->x);
dprintf("Patblt: y = 0x%lx\n",pPatblt->y);
dprintf("Patblt: cx = 0x%lx\n",pPatblt->cx);
dprintf("Patblt: cy = 0x%lx\n",pPatblt->cy);
dprintf("Patblt: hbr = 0x%lx\n",pPatblt->hbr);
dprintf("Patblt: rop4 = 0x%lx\n",pPatblt->rop4);
dprintf("Patblt: textclr = 0x%lx\n",pPatblt->TextColor);
dprintf("Patblt: backclr = 0x%lx\n",pPatblt->BackColor);
}
break;
case BatchTypePolyPatBlt:
{
PBATCHPOLYPATBLT pPatblt = (PBATCHPOLYPATBLT)pBatch;
PPOLYPATBLT ppoly = (PPOLYPATBLT)(&pPatblt->ulBuffer[0]);
ULONG Count = pPatblt->Count;
dprintf("PolyPatblt: length = 0x%lx\n",pPatblt->Length);
dprintf("Patblt: Count = 0x%lx\n",pPatblt->Count);
dprintf("Patblt: Mode = 0x%lx\n",pPatblt->Mode);
dprintf("Patblt: rop4 = 0x%lx\n",pPatblt->rop4);
dprintf("Patblt: textclr = 0x%lx\n",pPatblt->TextColor);
dprintf("Patblt: backclr = 0x%lx\n",pPatblt->BackColor);
while (Count--)
{
dprintf("\n");
dprintf("\t x = 0x%lx\n",ppoly->x);
dprintf("\t y = 0x%lx\n",ppoly->y);
dprintf("\t cx = 0x%lx\n",ppoly->cx);
dprintf("\t cy = 0x%lx\n",ppoly->cy);
dprintf("\t hbr = 0x%lx\n",ppoly->BrClr.hbr);
ppoly++;
}
}
break;
case BatchTypeTextOut:
{
PBATCHTEXTOUT pText = (PBATCHTEXTOUT)pBatch;
PWCHAR pwchar = (PWCHAR)(&pText->ulBuffer[0]);
PLONG pdx = (PLONG)(&pText->ulBuffer[pText->PdxOffset]);
dprintf("Textout: length = 0x%lx\n",pText->Length);
dprintf("Textout: TextColor = 0x%lx\n",pText->TextColor);
dprintf("Textout: BackColor = 0x%lx\n",pText->BackColor);
dprintf("Textout: BackMode = 0x%lx\n",pText->BackMode);
dprintf("Textout: x = 0x%lx\n",pText->x);
dprintf("Textout: y = 0x%lx\n",pText->y);
dprintf("Textout: fl = 0x%lx\n",pText->fl);
dprintf("Textout: rcl.left = 0x%lx\n",pText->rcl.left);
dprintf("Textout: rcl.top = 0x%lx\n",pText->rcl.top);
dprintf("Textout: rcl.right = 0x%lx\n",pText->rcl.right);
dprintf("Textout: rcl.bottom = 0x%lx\n",pText->rcl.bottom);
dprintf("Textout: dwCodePage = 0x%lx\n",pText->dwCodePage);
dprintf("Textout: cChar = 0x%lx\n",pText->cChar);
dprintf("Textout: PdxOffset = 0x%lx\n",pText->PdxOffset);
if (pText->cChar != 0)
{
dprintf("\t wchar array\n");
dprintf("\t\t");
ULONG ix = pText->cChar;
while (ix--)
{
dprintf("%x ",*pwchar++);
}
dprintf("\n");
if (pText->PdxOffset != 0)
{
dprintf("\t pdx array\n");
dprintf("\t\t");
ULONG ix = pText->cChar;
while (ix--)
{
dprintf("%li ",*pdx++);
}
dprintf("\n");
}
}
}
break;
case BatchTypeTextOutRect:
{
PBATCHTEXTOUTRECT pText = (PBATCHTEXTOUTRECT)pBatch;
dprintf("TextoutRect: length = 0x%lx\n",pText->Length);
dprintf("TextoutRect: BackColor = 0x%lx\n",pText->BackColor);
dprintf("TextoutRect: fl = 0x%lx\n",pText->fl);
dprintf("TextoutRect: rcl.left = 0x%lx\n",pText->rcl.left);
dprintf("TextoutRect: rcl.top = 0x%lx\n",pText->rcl.top);
dprintf("TextoutRect: rcl.right = 0x%lx\n",pText->rcl.right);
dprintf("TextoutRect: rcl.bottom = 0x%lx\n",pText->rcl.bottom);
}
break;
case BatchTypeSetBrushOrg:
{
PBATCHSETBRUSHORG pOrg = (PBATCHSETBRUSHORG)pBatch;
dprintf("SetBrushOrg: length = 0x%lx\n",pOrg->Length);
dprintf("SetBrushOrg: x = 0x%lx\n",pOrg->x);
dprintf("SetBrushOrg: y = 0x%lx\n",pOrg->y);
}
break;
case BatchTypeSelectClip:
{
PBATCHSETBRUSHORG pOrg = (PBATCHSETBRUSHORG)pBatch;
dprintf("SetBrushOrg: length = 0x%lx\n",pOrg->Length);
dprintf("SetBrushOrg: x = 0x%lx\n",pOrg->x);
dprintf("SetBrushOrg: y = 0x%lx\n",pOrg->y);
}
break;
case BatchTypeDeleteBrush:
{
PBATCHDELETEBRUSH pbr = (PBATCHDELETEBRUSH)pBatch;
dprintf("DeleteBrush: length = 0x%lx\n",pbr->Length);
dprintf("DeleteBrush: hbrush = 0x%lx\n",pbr->hbrush);
}
break;
case BatchTypeDeleteRegion:
{
PBATCHDELETEREGION prg = (PBATCHDELETEREGION)pBatch;
dprintf("DeleteRegion: length = 0x%lx\n",prg->Length);
dprintf("DeleteRegion: hregion = 0x%lx\n",prg->hregion);
}
break;
}
pBatch = (PBATCHCOMMAND)((PBYTE)pBatch + pBatch->Length);
}
}
}
else
{
dprintf("Error reading TEB contents\n");
}
#endif // DOES NOT SUPPORT API64
}
/******************************Public*Routine******************************\
* batch
*
* Lists a threads batched GDI commands
\**************************************************************************/
DECLARE_API( batch )
{
dprintf("Extension 'batch' is not fully implemented.\n");
DEBUG_VALUE DebugValue;
ULONG64 TebAddress = -1;
BOOL bShowHelp = FALSE;
INIT_API();
while (*args && isspace(*args)) args++;
if (*args)
{
if (args[0] == '-')
{
if (args[1]=='t' && isspace(args[2]))
{
ULONG64 ThreadAddress;
args += 2;
while (*args && isspace(*args)) args++;
if (*args &&
(g_pExtControl->Evaluate(args,
DEBUG_VALUE_INT64,
&DebugValue,
NULL) != S_OK)
)
{
ExtErr("Invalid arguments: %s\n", args);
bShowHelp = TRUE;
}
else
{
ThreadAddress = DebugValue.I64;
GetThreadField(Client, &ThreadAddress, "Tcb.Teb",
&DebugValue, DEBUG_VALUE_INT64);
TebAddress = DebugValue.I64;
}
}
else
{
if (args[1]!='?')
ExtErr("Invalid arguments: %s\n", args);
bShowHelp = TRUE;
}
}
else
{
if (S_OK != g_pExtControl->Evaluate(args, DEBUG_VALUE_INT64, &DebugValue, NULL))
{
ExtErr("Couldn't evaluate: %s\n", args);
EXIT_API(S_OK);
}
TebAddress = DebugValue.I64;
}
}
if (!bShowHelp)
{
if (TebAddress == (ULONG64)-1)
{
g_pExtSystem->GetCurrentThreadTeb(&TebAddress);
}
ExtVerb(" Teb = %p\n", TebAddress);
if (TebAddress)
{
DumpTebBatch(Client, TebAddress);
}
else
{
ExtErr("NULL Teb.\n");
}
}
if (bShowHelp)
{
ExtOut("Usage: batch [-?] [TEB | -t Thread]\n");
ExtOut(" If TEB and Thread are omitted, defaults to the current thread\n");
}
EXIT_API(S_OK);
}
/******************************Public*Routine******************************\
* dpeb
*
* Dump gdi structure in PEB
*
* Arguments:
*
* pPEB
*
* Return Value:
*
* None
*
* History:
*
* 6-Mar-1996 -by- Mark Enstrom [marke]
*
\**************************************************************************/
#if 0 // DOES NOT SUPPORT API64
VOID
GdiDPEB(
PPEB ppebIn,
PW32PROCESS pw32process,
BOOL bw32
)
{
BYTE lpeb[4096];
BYTE lw32proc[sizeof(W32PROCESS)];
PPEB ppeb = (PPEB)&lpeb[0];
PW32PROCESS pw32 = (PW32PROCESS)&lw32proc[0];
PGDIHANDLECACHE pCache = (PGDIHANDLECACHE)ppeb->GdiHandleBuffer;
int iStatus = move2(lpeb,ppebIn,sizeof(PEB));
if (iStatus)
{
dprintf("\nDump PEB 0x%lx\n",ppebIn);
dprintf("GdiSharedHandleTable = 0x%lx\n",ppeb->GdiSharedHandleTable);
dprintf("GdiDCAttributeList = 0x%lx\n",ppeb->GdiDCAttributeList);
dprintf("\n");
dprintf("GDI Cached brush handles = %li\n",pCache->ulNumHandles[BrushHandle]);
dprintf("GDI Cached pen handles = %li\n",pCache->ulNumHandles[PenHandle]);
dprintf("GDI Cached region handles = %li\n",pCache->ulNumHandles[RegionHandle]);
dprintf("GDI Cached lfont handles = %li\n",pCache->ulNumHandles[LFontHandle]);
PHANDLE pHandle = &pCache->Handle[0];
ULONG ux;
dprintf("\nBRUSH handles\n");
for (ux=0;ux<CACHE_BRUSH_ENTRIES;ux++)
{
dprintf("0x%08lx ",*pHandle++);
if (((ux+1) % 4) == 0)
{
dprintf("\n");
}
}
dprintf("\n\nPEN handles\n");
for (ux=0;ux<CACHE_PEN_ENTRIES;ux++)
{
dprintf("0x%08lx ",*pHandle++);
if (((ux+1) % 4) == 0)
{
dprintf("\n");
}
}
dprintf("\nREGION handles\n");
for (ux=0;ux<CACHE_REGION_ENTRIES;ux++)
{
dprintf("0x%08lx ",*pHandle++);
if (((ux+1) % 4) == 0)
{
dprintf("\n");
}
}
dprintf("\n");
}
else
{
dprintf("Error reading PEB contents\n");
return;
}
if (bw32)
{
iStatus = move2(lw32proc,pw32process,sizeof(W32PROCESS));
if (iStatus)
{
dprintf("W32PROCESS\n");
dprintf("Process Handle Count %li\n",pw32->GDIHandleCount);
PSINGLE_LIST_ENTRY pList = (PSINGLE_LIST_ENTRY)pw32->pDCAttrList;
dprintf("Process DC_ATTRs 0x%lx\n",pw32->pDCAttrList);
//
// dump DCATTRs
//
// while (pList)
// {
// BYTE lList[sizeof(SINGLE_LIST_ENTRY)];
// PSINGLE_LIST_ENTRY puList = (PSINGLE_LIST_ENTRY)&lList[0];
//
// move2(lList,pList,sizeof(SINGLE_LIST_ENTRY));
//
// dprintf("dcattr 0x%lx, next = 0x%lx\n",pList,puList->Next);
//
// pList = puList->Next;
//
// if (CheckControlC())
// {
// return;
// }
// }
//
//
// dump brushattrs
//
pList = (PSINGLE_LIST_ENTRY)pw32->pBrushAttrList;
dprintf("Process BRUSHATTRs 0x%lx:\n",pw32->pBrushAttrList);
// while (pList)
// {
// BYTE lList[sizeof(SINGLE_LIST_ENTRY)];
// PSINGLE_LIST_ENTRY puList = (PSINGLE_LIST_ENTRY)&lList[0];
//
// move2(lList,pList,sizeof(SINGLE_LIST_ENTRY));
//
// dprintf("brushattr 0x%lx, next = 0x%lx\n",pList,puList->Next);
//
// pList = puList->Next;
//
// if (CheckControlC())
// {
// return;
// }
// }
}
}
}
#endif // DOES NOT SUPPORT API64
DECLARE_API( dpeb )
{
dprintf("Extension 'dpeb' is not converted.\n");
#if 0 // DOES NOT SUPPORT API64
PVOID Process;
EPROCESS ProcessContents;
PPEB ppeb;
PW32PROCESS pw32process;
BOOL bW32Thread = FALSE;
//
// dpeb [peb], look for peb input
//
PARSE_ARGUMENTS(peb_help);
if(parse_iFindSwitch(tokens, ntok, 'w')!=-1) {bW32Thread=TRUE;}
//
// use current peb
//
Process = GetCurrentProcessAddress( dwProcessor, hCurrentThread, NULL );
if ( !ReadMemory( (UINT_PTR)Process,
&ProcessContents,
sizeof(EPROCESS),
NULL))
{
dprintf("%08lx: Unable to read _EPROCESS\n", Process );
return;
}
dprintf("Process 0x%p W32Process: 0x%p\n",
(ULONG_PTR)Process,
(ULONG_PTR)ProcessContents.Win32Process);
ppeb = ProcessContents.Peb;
pw32process = (PW32PROCESS)ProcessContents.Win32Process;
GdiDPEB(ppeb,pw32process,bW32Thread);
return;
peb_help:
dprintf("Usage: dpeb [-?] [-w]\n");
dprintf("-w indicates W32PROCESS structure\n");
#endif // DOES NOT SUPPORT API64
EXIT_API(S_OK);
}
DECLARE_API( w32p )
{
HRESULT hr = S_OK;
OutputControl OutCtl(Client);
BOOL BadArg = FALSE;
BOOL ProcessArg = FALSE;
DEBUG_VALUE Address = {0, DEBUG_VALUE_INVALID};
while (!BadArg)
{
while (isspace(*args)) args++;
if (*args == '-')
{
// Process switches
args++;
BadArg = (*args == '\0' || isspace(*args));
while (*args != '\0' && !isspace(*args))
{
switch (tolower(*args))
{
case 'p':
ProcessArg = TRUE;
break;
default:
BadArg = TRUE;
break;
}
if (BadArg) break;
args++;
}
}
else
{
if (*args == '\0') break;
if (Address.Type == DEBUG_VALUE_INVALID)
{
// This argument must be an address or a Process.
CHAR EOPChar;
PSTR EOP = (PSTR)args;
ULONG Rem;
// Find end of string to evaulate as an address or Process
while (*EOP != '\0' && !isspace(*EOP)) EOP++;
EOPChar = *EOP;
*EOP = '\0';
if (isxdigit(*args) &&
Evaluate(Client, args, DEBUG_VALUE_INT64,
EVALUATE_DEFAULT_RADIX, &Address,
&Rem) == S_OK &&
args + Rem == EOP &&
Address.I64 != 0)
{
args = EOP;
}
else
{
OutCtl.OutErr("Error: Couldn't evaluate '%s' as a %s.\n",
args,
(ProcessArg ? "Process" : "W32PROCESS address"));
BadArg = TRUE;
}
*EOP = EOPChar;
}
else
{
// All other arguments are invalid
OutCtl.OutErr("Error: Invalid argument '%s'.\n", args);
BadArg = TRUE;
break;
}
}
}
if (!BadArg)
{
if (ProcessArg && Address.Type == DEBUG_VALUE_INVALID)
{
OutCtl.OutErr("Error: Missing Process.\n");
BadArg = TRUE;
}
}
if (BadArg)
{
if (*args == '?')
{
OutCtl.Output("w32p dumps W32PROCESS stucture for current or specified process.\n\n");
}
OutCtl.Output("Usage: w32p [-?] [W32PROCESS Addr | -p Process]\n");
}
else
{
if (Address.Type == DEBUG_VALUE_INVALID || ProcessArg)
{
ULONG64 ProcessAddr = (Address.Type == DEBUG_VALUE_INVALID) ?
CURRENT_PROCESS_ADDRESS :
Address.I64;
hr = GetProcessField(Client, &ProcessAddr, "Win32Process", &Address, DEBUG_VALUE_INT64);
if (hr == S_OK)
{
if (Address.I64 == 0)
{
OutCtl.Output(" Process 0x%p does not have a Win32Process.\n", ProcessAddr);
hr = S_FALSE;
}
}
else
{
OutCtl.OutErr("Unable to look up Win32Process address.\n");
}
}
if (hr == S_OK)
{
hr = DumpType(Client, "_W32PROCESS", Address.I64);
}
}
return hr;
}
DECLARE_API( w32t )
{
HRESULT hr = S_OK;
OutputControl OutCtl(Client);
BOOL BadArg = FALSE;
BOOL ThreadArg = FALSE;
DEBUG_VALUE Address = {0, DEBUG_VALUE_INVALID};
while (!BadArg)
{
while (isspace(*args)) args++;
if (*args == '-')
{
// Process switches
args++;
BadArg = (*args == '\0' || isspace(*args));
while (*args != '\0' && !isspace(*args))
{
switch (tolower(*args))
{
case 't':
ThreadArg = TRUE;
break;
default:
BadArg = TRUE;
break;
}
if (BadArg) break;
args++;
}
}
else
{
if (*args == '\0') break;
if (Address.Type == DEBUG_VALUE_INVALID)
{
// This argument must be an address or a Thread.
CHAR EOPChar;
PSTR EOP = (PSTR)args;
ULONG Rem;
// Find end of string to evaulate as an address or Thread
while (*EOP != '\0' && !isspace(*EOP)) EOP++;
EOPChar = *EOP;
*EOP = '\0';
if (isxdigit(*args) &&
Evaluate(Client, args, DEBUG_VALUE_INT64,
EVALUATE_DEFAULT_RADIX, &Address,
&Rem) == S_OK &&
args + Rem == EOP &&
Address.I64 != 0)
{
args = EOP;
}
else
{
OutCtl.OutErr("Error: Couldn't evaluate '%s' as a %s.\n",
args,
(ThreadArg ? "Thread" : "W32THREAD address"));
BadArg = TRUE;
}
*EOP = EOPChar;
}
else
{
// All other arguments are invalid
OutCtl.OutErr("Error: Invalid argument '%s'.\n", args);
BadArg = TRUE;
break;
}
}
}
if (!BadArg)
{
if (ThreadArg && Address.Type == DEBUG_VALUE_INVALID)
{
OutCtl.OutErr("Error: Missing Thread.\n");
BadArg = TRUE;
}
}
if (BadArg)
{
if (*args == '?')
{
OutCtl.Output("w32t dumps W32TRHEAD stucture for current or specified thread.\n\n");
}
OutCtl.Output("Usage: w32t [-?] [W32THREAD Addr | -t Thread]\n");
}
else
{
if (Address.Type == DEBUG_VALUE_INVALID || ThreadArg)
{
ULONG64 ThreadAddr = (Address.Type == DEBUG_VALUE_INVALID) ?
CURRENT_THREAD_ADDRESS :
Address.I64;
hr = GetThreadField(Client, &ThreadAddr, "Tcb.Win32Thread", &Address, DEBUG_VALUE_INT64);
if (hr == S_OK)
{
if (Address.I64 == 0)
{
OutCtl.Output(" Thread 0x%p does not have a Win32Thread.\n", ThreadAddr);
hr = S_FALSE;
}
}
else
{
OutCtl.OutErr("Unable to look up Win32Thread address.\n");
}
}
if (hr == S_OK)
{
hr = DumpType(Client, "_W32THREAD", Address.I64);
}
}
return hr;
}