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.
 
 
 
 
 
 

1277 lines
33 KiB

/******************************Module*Header*******************************\
* Module Name: callback.cxx
*
* Copyright (c) 2000 Microsoft Corporation
*
\**************************************************************************/
#include "precomp.hxx"
BOOL gbCallbacksPrintNewline = FALSE;
int gCallbacksPrintNameWidth = -1;
NTSTATUS gCallbackReturnValue = STATUS_SUCCESS;
ULONG FieldCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
if (gbCallbacksPrintNewline) dprintf("\n");
dprintf(" ** FieldCallback(%lx, %lx) **\n", pField, UserContext);
if (pField)
{
dprintf(" Field:\n");
dprintf(" fName : %s\n", pField->fName);
dprintf(" printName : %s\n", pField->printName);
dprintf(" size : %d\n", pField->size);
dprintf(" fOptions : %#x\n", pField->fOptions);
dprintf(" address : %#I64x\n", pField->address);
dprintf(" fieldCallBack: %lx\n", pField->fieldCallBack);
}
if (UserContext)
{
dprintf(" UserContext: ???\n");
}
return gCallbackReturnValue;
}
/**************************************************************************\
*
* PrintName
*
* Prints the field name or print name if callbacks are supposed to.
*
\**************************************************************************/
VOID PrintName(PFIELD_INFO pField)
{
if (pField)
{
if (gCallbacksPrintNameWidth >= 0)
{
if (pField->printName)
{
dprintf("%*s", gCallbacksPrintNameWidth, pField->printName);
}
else if (pField->fName)
{
dprintf("%*s", gCallbacksPrintNameWidth, pField->fName);
}
}
else
{
if (pField->fOptions & DBG_DUMP_FIELD_NO_PRINT)
{
if (pField->printName)
{
dprintf(" +0x___ %s ", pField->printName);
}
else if (pField->fName)
{
dprintf(" +0x___ %s ", pField->fName);
}
}
}
}
}
/**************************************************************************\
*
* NextItemCallbackInit
*
* Specify printing and validation info to NextItemCallbacks.
*
\**************************************************************************/
BOOL PrintItemHeader = FALSE;
char szItemHeader[512] = "";
ULONG64 LastItemExpected = 0;
BOOL FoundLastItemExpected = FALSE;
void NextItemCallbackInit(
const char *pszPrintHeader,
ULONG64 LastItemAddr
)
{
if (pszPrintHeader != NULL)
{
strncpy(szItemHeader, pszPrintHeader, sizeof(szItemHeader));
szItemHeader[sizeof(szItemHeader)-1] = 0;
PrintItemHeader = TRUE;
}
else
{
PrintItemHeader = FALSE;
}
LastItemExpected = LastItemAddr;
FoundLastItemExpected = (LastItemExpected == 0);
}
/**************************************************************************\
*
* LastCallbackItemFound
*
* Returns TRUE if address specified in NextItemCallbackInit was found.
* Note: Always returns TRUE if 0 was specified for address.
*
\**************************************************************************/
BOOL LastCallbackItemFound()
{
return FoundLastItemExpected;
}
/**************************************************************************\
*
* NextItemCallback
*
* Use with linked list dumping when initial address is the first item's.
*
\**************************************************************************/
ULONG NextItemCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
ULONG64 NextAddr = 0;
if (pField == NULL)
{
if (gbCallbacksPrintNewline) dprintf("\n");
dprintf("Error: NextItemCallback was given NULL pField.\n");
}
else
{
if (pField->address == 0)
return STATUS_UNSUCCESSFUL;
if (LastItemExpected != 0)
{
if (FoundLastItemExpected)
{
dprintf(" * Error: Next item is beyond last expected @ %#p\n", LastItemExpected);
}
else if (LastItemExpected == pField->address)
{
FoundLastItemExpected = TRUE;
}
}
if (PrintItemHeader)
{
dprintf(szItemHeader);
dprintf("%#p\n", pField->address);
}
}
return STATUS_SUCCESS;
}
/**************************************************************************\
*
* PointerToNextItemCallback
*
* Use with linked list dumping when initial address is a pointer to type.
*
\**************************************************************************/
ULONG PointerToNextItemCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
ULONG64 NextAddr = 0;
if (pField == NULL)
{
if (gbCallbacksPrintNewline) dprintf("\n");
dprintf("Error: PointerToNextItemCallback was given NULL pField.\n");
}
else
{
if (pField->address == 0)
return STATUS_UNSUCCESSFUL;
if (!ReadPointer(pField->address, &NextAddr) || NextAddr == 0)
return STATUS_UNSUCCESSFUL;
if (LastItemExpected != 0)
{
if (FoundLastItemExpected)
{
dprintf(" * Error: Next item is beyond last expected @ %#p\n", LastItemExpected);
}
else if (LastItemExpected == NextAddr)
{
FoundLastItemExpected = TRUE;
}
}
if (PrintItemHeader)
{
dprintf(szItemHeader);
}
}
return STATUS_SUCCESS;
}
/**************************************************************************\
*
* ArrayCallback
*
* Use with array dumping.
*
\**************************************************************************/
ULONG ArrayCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
static PFIELD_INFO ArrayField = NULL;
static ULONG ArrayIndex = 0;
static ULONG ArrayIndexWidth;
if (pField != ArrayField || pField->size <= ArrayIndex)
{
ArrayField = pField;
if (ArrayIndex != 0 && gbVerbose)
{
dprintf("Warning: Beginning new array w/o completing last.\n");
}
ArrayIndex = 0;
}
if (ArrayIndex == 0)
{
ULONG i = pField->size-1;
ArrayIndexWidth = 1;
dprintf("Idx");
while (i /= 10)
{
dprintf(" ");
ArrayIndexWidth++;
}
PrintName(pField);
}
dprintf("\n[%*u]", ArrayIndexWidth, ArrayIndex++);
// If we hit the end of an array,
// prepare for a new array.
if (pField->size == ArrayIndex)
{
ArrayField = NULL;
ArrayIndex = 0;
}
return STATUS_SUCCESS;
}
/**************************************************************************\
*
* NewlineCallback
*
* To be used with DBG_DUMP_COMPACT_OUT as default callback.
*
\**************************************************************************/
ULONG NewlineCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
dprintf("\n");
if (!gbCallbacksPrintNewline && gbVerbose)
{
dprintf(" Note: NewlineCallback called, but gbCallbacksPrintNewline is FALSE.\n");
}
return STATUS_SUCCESS;
}
/**************************************************************************\
*
* AddressPrintCallback
*
* Useful with DBG_DUMP_FIELD_RETURN_ADDRESS when the field is
* a large embedded structure you don't want to print.
*
\**************************************************************************/
ULONG AddressPrintCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
if (pField == NULL)
{
dprintf("\nError: AddressPrintCallback was given NULL pField.");
}
else
{
PrintName(pField);
if (gbVerbose) dprintf(" (pField->size = %d) ", pField->size);
dprintf("%#p", pField->address);
}
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
/**************************************************************************\
*
* Basic Type Callbacks:
* BOOL, BYTE, CHAR, DecimalCHAR, DecimalUCHAR,
* DWORD, LONG, SHORT, WORD, ULONG, USHORT
*
\**************************************************************************/
ULONG BOOLCallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("%s", ((BOOL)pField->address) ? "TRUE" : "FALSE");
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
ULONG BYTECallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("0x%2.2X", (BYTE)pField->address);
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
ULONG CHARCallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("'%c'", (CHAR)pField->address);
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
ULONG DecimalCHARCallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("%d", (CHAR)pField->address);
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
ULONG DecimalUCHARCallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("%u", (UCHAR)pField->address);
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
ULONG DWORDCallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("0x%8.8lX", (DWORD)pField->address);
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
ULONG LONGCallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("%ld", (LONG)pField->address);
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
ULONG WORDCallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("0x%4.4X", (WORD)pField->address);
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
ULONG SHORTCallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("%d", (SHORT)pField->address);
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
ULONG ULONGCallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("%lu", (ULONG)pField->address);
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
ULONG USHORTCallback(PFIELD_INFO pField, PVOID UserContext)
{
PrintName(pField);
dprintf("%u", (USHORT)pField->address);
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
/**************************************************************************\
*
* EnumCallback
*
* Specify ENUMDEF * in SYM_DUMP_PARAM.Context field
*
* Note: Only one Enum/FlagCallback can be specified per FIELD_INFO array.
*
\**************************************************************************/
ULONG EnumCallback(
PFIELD_INFO pField,
ENUMDEF *pEnumDef
)
{
if (pField == NULL || pEnumDef == NULL)
{
if (gbCallbacksPrintNewline) dprintf("\n");
dprintf("Error: EnumCallback had NULL parameter.\n");
return STATUS_UNSUCCESSFUL;
}
PrintName(pField);
if (!gbCallbacksPrintNewline &&
!(pField->fOptions & DBG_DUMP_FIELD_NO_PRINT))
{
dprintf(" ");
}
dprintf(" ");
if (! bPrintEnum(pEnumDef, (ULONG)pField->address))
{
dprintf("Unknown Value");
if (pField->fOptions & DBG_DUMP_FIELD_NO_PRINT)
{
dprintf(": %lu", (ULONG)pField->address);
}
}
dprintf("\n");
return gCallbackReturnValue;
}
/**************************************************************************\
*
* FlagCallback
*
* Specify FLAGDEF * in SYM_DUMP_PARAM.Context field
*
* Note: Only one Enum/FlagCallback can be specified per FIELD_INFO array.
*
\**************************************************************************/
ULONG FlagCallback(
PFIELD_INFO pField,
FLAGDEF *pFlagDef
)
{
ULONG64 UnknownFlags;
PrintName(pField);
if (gbCallbacksPrintNewline) dprintf("\n");
if (pField == NULL || pFlagDef == NULL)
{
dprintf("Error: FlagCallback had NULL parameter.\n");
return STATUS_UNSUCCESSFUL;
}
UnknownFlags = flPrintFlags(pFlagDef, pField->address);
if (UnknownFlags)
{
if (UnknownFlags != pField->address) dprintf("\n");
dprintf(" Uknown flags: 0x%lx", UnknownFlags);
}
dprintf("\n");
return gCallbackReturnValue;
}
/**************************************************************************\
*
* POINTLCallback
*
\**************************************************************************/
ULONG POINTLCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
NTSTATUS RetVal = gCallbackReturnValue;
ULONG error;
if (pField == NULL)
{
dprintf("\nError: POINTLCallback was given NULL pField.");
}
else
{
PrintName(pField);
if (!pField->address)
{
dprintf("\nError: POINTLCallback: pField->address = NULL");
RetVal = STATUS_UNSUCCESSFUL;
}
else if (error = (ULONG)InitTypeRead(pField->address, win32k!_POINTL))
{
dprintf("\n InitTypeRead returned %s", pszWinDbgError(error));
RetVal = error;
}
else
{
dprintf("(%d,%d)",
(LONG)ReadField(x),
(LONG)ReadField(y));
}
}
if (gbCallbacksPrintNewline) dprintf("\n");
return RetVal;
}
/**************************************************************************\
*
* RECTLCallback
*
\**************************************************************************/
ULONG RECTLCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
NTSTATUS RetVal = gCallbackReturnValue;
ULONG error;
if (pField == NULL)
{
dprintf("\nError: RECTLCallback was given NULL pField.");
}
else
{
PrintName(pField);
if (!pField->address)
{
dprintf("\nError: RECTLCallback: pField->address = NULL");
RetVal = STATUS_UNSUCCESSFUL;
}
else if (error = (ULONG)InitTypeRead(pField->address, win32k!_RECTL))
{
dprintf("\n InitTypeRead returned %s", pszWinDbgError(error));
RetVal = error;
}
else
{
dprintf("(%d,%d) - (%d,%d)",
(LONG)ReadField(left),
(LONG)ReadField(top),
(LONG)ReadField(right),
(LONG)ReadField(bottom));
}
}
if (gbCallbacksPrintNewline) dprintf("\n");
return RetVal;
}
/**************************************************************************\
*
* SIZECallback
*
\**************************************************************************/
ULONG SIZECallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
NTSTATUS RetVal = gCallbackReturnValue;
ULONG error;
if (pField == NULL)
{
dprintf("\nError: SIZECallback was given NULL pField.");
}
else
{
PrintName(pField);
if (!pField->address)
{
dprintf("\nError: SIZECallback: pField->address = NULL");
RetVal = STATUS_UNSUCCESSFUL;
}
else if (error = (ULONG)InitTypeRead(pField->address, win32k!tagSIZE))
{
dprintf("\n InitTypeRead returned %s", pszWinDbgError(error));
RetVal = error;
}
else
{
dprintf("%d x %d",
(LONG)ReadField(cx),
(LONG)ReadField(cy));
}
}
if (gbCallbacksPrintNewline) dprintf("\n");
return RetVal;
}
/**************************************************************************\
*
* SIZELCallback
*
\**************************************************************************/
ULONG SIZELCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
return SIZECallback(pField, UserContext);
}
/**************************************************************************\
*
* PrintDEVMODEList
*
\**************************************************************************/
ULONG PrintDEVMODEList(
ULONG64 DevModeListAddr,
ULONG DevModeListSize
)
{
ULONG64 DevModeEnd;
ULONG error = 0;
#define DEVMODE_DMDRIVEREXTRA 0
#define DEVMODE_DMSIZE 1
#define DEVMODE_DMPELSWIDTH 2
#define DEVMODE_DMPELSHEIGHT 3
#define DEVMODE_DMBITSPERPEL 4
#define DEVMODE_DMDISPLAYFREQUENCY 5
FIELD_INFO DevModeFields[] = {
{ DbgStr("dmDriverExtra"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("dmSize"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("dmPelsWidth"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("dmPelsHeight"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("dmBitsPerPel"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("dmDisplayFrequency"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
};
SYM_DUMP_PARAM DevModeSym = {
sizeof(SYM_DUMP_PARAM), DbgStr(GDIType(_devicemodeW)), DBG_DUMP_NO_PRINT, DevModeListAddr,
NULL, NULL, NULL, sizeof(DevModeFields)/sizeof(DevModeFields[0]), DevModeFields
};
DevModeEnd = DevModeSym.addr + DevModeListSize;
while ((DevModeSym.addr < DevModeEnd) &&
!(error = Ioctl( IG_DUMP_SYMBOL_INFO, &DevModeSym, DevModeSym.size )))
{
dprintf("\t %4d x %4d %2d %3d\n",
(DWORD)DevModeFields[DEVMODE_DMPELSWIDTH].address,
(DWORD)DevModeFields[DEVMODE_DMPELSHEIGHT].address,
(DWORD)DevModeFields[DEVMODE_DMBITSPERPEL].address,
(DWORD)DevModeFields[DEVMODE_DMDISPLAYFREQUENCY].address);
DevModeSym.addr += DevModeFields[DEVMODE_DMDRIVEREXTRA].address + DevModeFields[DEVMODE_DMSIZE].address;
}
return error;
}
/**************************************************************************\
*
* DEVMODECallback
*
\**************************************************************************/
ULONG DEVMODECallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
PrintName(pField);
if (pField == NULL)
{
if (gbCallbacksPrintNewline) dprintf("\n");
dprintf(" Error: DEVMODEListCallback was given NULL pField.\n");
}
else if (pField->address)
{
ULONG error;
if (error = PrintDEVMODEList(pField->address, 1))
{
dprintf(" PrintDEVMODEList returned %s in DEVMODECallback\n", pszWinDbgError(error));
}
}
else
{
dprintf(" DEVMODE address is NULL\n");
}
return gCallbackReturnValue;
}
/**************************************************************************\
*
* DEVMODEListCallback and SizeDEVMODEListCallback
*
* Make sure these are always called in conjuction with
* SizeDEVMODEListCallback before DEVMODEListCallback.
*
\**************************************************************************/
ULONG cbDevModeList = -1;
ULONG SizeDEVMODEListCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
if (gbCallbacksPrintNewline) dprintf("\n");
if (pField == NULL)
{
dprintf("Error: SizeDEVMODEListCallback was given NULL pField.\n");
}
else
{
if (cbDevModeList != -1)
{
dprintf(" Warning: cbDevModeList (%d) was not clear before call to SizeDEVMODEListCallback\n", cbDevModeList);
}
cbDevModeList = (ULONG)pField->address;
}
return STATUS_SUCCESS;
}
ULONG DEVMODEListCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
PrintName(pField);
if (gbCallbacksPrintNewline) dprintf("\n");
if (pField == NULL)
{
dprintf(" Error: DEVMODEListCallback was given NULL pField.\n");
}
else if (cbDevModeList == -1)
{
dprintf(" Error: cbDevModeList has not been set properly.\n");
}
else if (pField->address)
{
ULONG error;
if (error = PrintDEVMODEList(pField->address, cbDevModeList))
{
dprintf(" PrintDEVMODEList returned %s in DEVMODEListCallback\n", pszWinDbgError(error));
}
}
else if (cbDevModeList != 0)
{
dprintf(" DEVMODE list size (%d) is non-zero, but DEVMODE list address is NULL.\n", cbDevModeList);
}
cbDevModeList = -1;
return gCallbackReturnValue;
}
/**************************************************************************\
*
* PrintAString
*
* Reads and prints a char string at given target address.
*
* Returns address just past end of string or address of read failure.
*
\**************************************************************************/
ULONG64 PrintAString(
ULONG64 StringAddr
)
{
CHAR Char;
ULONG cbRead;
if (StringAddr != 0)
{
while (ReadMemory(StringAddr, &Char, sizeof(Char), &cbRead) &&
cbRead == sizeof(Char) &&
(StringAddr+=sizeof(Char)) &&
Char != 0)
{
dprintf("%hc", Char);
}
}
return StringAddr;
}
/**************************************************************************\
*
* PrintWString
*
* Reads and prints a two-byte char string at given target address.
*
* Returns address just past end of string or address of read failure.
*
\**************************************************************************/
ULONG64 PrintWString(
ULONG64 StringAddr
)
{
WCHAR Char;
ULONG cbRead;
if (StringAddr != 0)
{
while (ReadMemory(StringAddr, &Char, sizeof(Char), &cbRead) &&
cbRead == sizeof(Char) &&
(StringAddr+=sizeof(Char)) &&
Char != 0)
{
dprintf("%lc", Char);
}
}
return StringAddr;
}
/**************************************************************************\
*
* String printing callbacks
*
* To be used when DBG_DUMP_FIELD_xxx_STRING flags can't be used.
*
\**************************************************************************/
/**************************************************************************\
*
* ACharArrayCallback callback for an array of chars
*
* Use DBG_DUMP_FIELD_RETURN_ADDRESS flag
*
\**************************************************************************/
ULONG ACharArrayCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
CHAR szBuffer[128];
ULONG cbRead = 0;
if (pField == NULL)
{
dprintf("\nError: ACharArrayCallback was given NULL pField.");
}
else
{
PrintName(pField);
if (gbVerbose && pField->size == 0)
dprintf("\n Note: ACharArrayCallback was given zero length array.\n");
if (pField->address)
{
if (pField->size < sizeof(szBuffer))
{
if (!ReadMemory(pField->address, szBuffer, pField->size, &cbRead) || cbRead == 0)
{
dprintf(" Memory read failed @ %#p", pField->address);
}
else
{
szBuffer[min(cbRead,sizeof(szBuffer)-sizeof(CHAR))/sizeof(CHAR)] = (CHAR) 0;
dprintf(" \"%hs\"", szBuffer);
}
}
else
{
PCHAR pszBuffer = (PCHAR) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, pField->size+sizeof(CHAR));
if (pszBuffer == NULL)
{
dprintf(" Buffer allocation failed - single-byte string @ %#p", pField->address);
}
else if (!ReadMemory(pField->address, szBuffer, pField->size, &cbRead) || cbRead == 0)
{
dprintf(" Memory read failed @ %#p", pField->address);
}
else
{
dprintf(" \"%hs\"", szBuffer);
}
}
}
else
{
dprintf(" (null)");
}
}
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
/**************************************************************************\
*
* WCharArrayCallback callback for an array of two-byte chars
*
* Use DBG_DUMP_FIELD_RETURN_ADDRESS flag
*
\**************************************************************************/
ULONG WCharArrayCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
WCHAR wszBuffer[128];
ULONG cbRead = 0;
if (pField == NULL)
{
dprintf("\nError: WStringCallback was given NULL pField.");
}
else
{
PrintName(pField);
if (gbVerbose && pField->size == 0)
dprintf("\n Note: WCharArrayCallback was given zero length array.\n");
if (pField->address)
{
if (pField->size < sizeof(wszBuffer))
{
if (!ReadMemory(pField->address, wszBuffer, pField->size, &cbRead) || cbRead == 0)
{
dprintf(" Memory read failed @ %#p", pField->address);
}
else
{
wszBuffer[min(cbRead,sizeof(wszBuffer)-sizeof(WCHAR))/sizeof(WCHAR)] = (WCHAR) 0;
dprintf(" \"%ls\"", wszBuffer);
}
}
else
{
PWCHAR pwszBuffer = (PWCHAR) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, pField->size+sizeof(WCHAR));
if (pwszBuffer == NULL)
{
dprintf(" Buffer allocation failed - wide string @ %#p", pField->address);
}
else if (!ReadMemory(pField->address, wszBuffer, pField->size, &cbRead) || cbRead == 0)
{
dprintf(" Memory read failed @ %#p", pField->address);
}
else
{
dprintf(" \"%ls\"", wszBuffer);
}
}
}
else
{
dprintf(" (null)");
}
}
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
/**************************************************************************\
*
* AStringCallback callback for a pointer to char string
*
\**************************************************************************/
ULONG AStringCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
CHAR szBuffer[128];
ULONG cbRead = 0;
if (pField == NULL)
{
dprintf("\nError: AStringCallback was given NULL pField.");
}
else
{
PrintName(pField);
if (gbVerbose)
{
if (pField->size == 0)
dprintf("\n Note: AStringCallback was given zero length type.\n");
else if (pField->size != GetTypeSize("PVOID"))
dprintf("\n Note: AStringCallback: String length is not the size of a pointer.\n"
" Should you be using ACharArrayCallback?\n");
}
if (pField->address)
{
dprintf(" \"");
PrintAString(pField->address);
dprintf("\"");
}
else
{
dprintf(" (null)");
}
}
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
/**************************************************************************\
*
* WStringCallback callback for a pointer to two-byte char string
*
\**************************************************************************/
ULONG WStringCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
CHAR szBuffer[128];
ULONG cbRead = 0;
if (pField == NULL)
{
dprintf("\nError: WStringCallback was given NULL pField.");
}
else
{
PrintName(pField);
if (gbVerbose)
{
if (pField->size == 0)
dprintf("\n Note: WStringCallback was given zero length type.\n");
else if (pField->size != GetTypeSize("PVOID"))
dprintf("\n Note: WStringCallback: String length is not the size of a pointer.\n"
" Should you be using WCharArrayCallback?\n");
}
if (pField->address)
{
dprintf(" \"");
PrintWString(pField->address);
dprintf("\"");
}
else
{
dprintf(" (null)");
}
}
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
/**************************************************************************\
*
* AMultiStringCallback callback for a pointer to several char
* strings one after another.
*
\**************************************************************************/
ULONG AMultiStringCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
if (pField == NULL)
{
dprintf("\nError: AMultiStringCallback was given NULL pField.");
}
else
{
PrintName(pField);
if (gbVerbose)
{
if (pField->size == 0)
dprintf("\n Note: AMultiStringCallback was given zero length type.\n");
else if (pField->size != GetTypeSize("PVOID"))
dprintf("\n Note: AMulitStringCallback: String length is not the size of a pointer.\n"
" Should you be using ACharArrayCallback?\n");
}
if (pField->address)
{
ULONG64 PrevAddr = NULL;
ULONG64 CurAddr = pField->address;
CHAR Char;
ULONG cbRead;
while (CurAddr != PrevAddr &&
ReadMemory(CurAddr, &Char, sizeof(Char), &cbRead) &&
cbRead == sizeof(Char) &&
Char != 0)
{
PrevAddr = CurAddr;
dprintf("\n\t\"");
CurAddr = PrintAString(CurAddr);
dprintf("\"");
}
}
else
{
dprintf(" (null)");
}
}
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}
/**************************************************************************\
*
* WMultiStringCallback callback for a pointer to several two-byte char
* strings one after another.
*
\**************************************************************************/
ULONG WMultiStringCallback(
PFIELD_INFO pField,
PVOID UserContext
)
{
if (pField == NULL)
{
dprintf("\nError: WMultiStringCallback was given NULL pField.");
}
else
{
PrintName(pField);
if (gbVerbose)
{
if (pField->size == 0)
dprintf("\n Note: WMultiStringCallback was given zero length type.\n");
else if (pField->size != GetTypeSize("PVOID"))
dprintf("\n Note: WMulitStringCallback: String length is not the size of a pointer.\n"
" Should you be using WCharArrayCallback?\n");
}
if (pField->address)
{
ULONG64 PrevAddr = NULL;
ULONG64 CurAddr = pField->address;
WCHAR Char;
ULONG cbRead;
while (CurAddr != PrevAddr &&
ReadMemory(CurAddr, &Char, sizeof(Char), &cbRead) &&
cbRead == sizeof(Char) &&
Char != 0)
{
PrevAddr = CurAddr;
dprintf("\n\t\"");
CurAddr = PrintWString(CurAddr);
dprintf("\"");
}
}
else
{
dprintf(" (null)");
}
}
if (gbCallbacksPrintNewline) dprintf("\n");
return gCallbackReturnValue;
}