mirror of https://github.com/lianthony/NT4.0
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.
1931 lines
51 KiB
1931 lines
51 KiB
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Module Name: sde.c
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This function contains some Cairo Shell32 ntsd debugger extensions
|
|
//
|
|
// Author:
|
|
//
|
|
// Steve Cathcart (SteveCat) 20-Feb-1995 Created
|
|
//
|
|
// Revision History:
|
|
//
|
|
//
|
|
//
|
|
// Copyright (c) 1995 Microsoft Corporation
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "sde.h"
|
|
|
|
#define SDE_VERSION "0.3"
|
|
|
|
//
|
|
// NOTE: The PRINTF routine only excepts ANSI strings for printout
|
|
// so we have to convert all UNICODE strings to ANSI for
|
|
// display. The following DEFINE is enabled when the Explorer
|
|
// and Shell32 go into full UNICODE mode.
|
|
//
|
|
|
|
#ifdef UNICODE
|
|
#define UC_SHELL 1
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: help
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Prints out a brief help screen describing the Shell32 Debugger
|
|
// Extension commands available.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.help
|
|
//
|
|
// Returns:
|
|
//
|
|
// nothing
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID help (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
|
|
|
|
PRINTF("sde help (Cairo Shell32 debugger extensions) Version %s\n\n", SDE_VERSION);
|
|
PRINTF("cd <addr> - Dump ControlData structure\n");
|
|
PRINTF("cei <addr> - Dump CPLEXECINFO structure\n");
|
|
PRINTF("cid <addr> - Dump CPLAPPLETID structure\n");
|
|
PRINTF("cpl <addr> - Dump CPLINFO structure\n");
|
|
PRINTF("cpli <addr> - Dump CPLITEM structure\n");
|
|
PRINTF("cplm <addr> - Dump CPLMODULE structure\n");
|
|
PRINTF("idc <addr> - Dump IDCONTROL structure\n");
|
|
PRINTF("mi <addr> - Dump ModuleInfo structure\n");
|
|
PRINTF("minst <addr> - Dump 'minst' structure\n");
|
|
PRINTF("ncia <addr> - Dump NewCPL Ansi structure\n");
|
|
PRINTF("nciw <addr> - Dump NewCPL Unicode structure\n");
|
|
PRINTF("rcpl <addr> - Dump RegCPLInfo structure\n");
|
|
PRINTF("\n");
|
|
PRINTF("Most of this works with Unicode.\n");
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: read_struct
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Reads specified amount of memory from the debuggee's process
|
|
// address space into the passed in memory buffer (struct pointer).
|
|
//
|
|
// NOTE: An message is printed out thru the debugger in case of error
|
|
// reading from the debuggee's address space.
|
|
//
|
|
// Returns:
|
|
//
|
|
// TRUE/FALSE
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL read_struct (PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
HANDLE hProcess,
|
|
ULONG lpAddress,
|
|
PVOID p,
|
|
ULONG cb
|
|
)
|
|
{
|
|
try {
|
|
if (lpExtensionApis->nSize >= sizeof(WINDBG_EXTENSION_APIS)) {
|
|
if (!(*lpExtensionApis->lpReadProcessMemoryRoutine)(
|
|
(DWORD)lpAddress, p, cb, NULL)) {
|
|
EPRINTF("Failure reading 0x%X bytes at memory location %08lX\n", cb, lpAddress );
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
NtReadVirtualMemory(hProcess,
|
|
(LPVOID)lpAddress, p, cb, NULL);
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
EPRINTF("Exception trying to read from memory location %08lX\n", lpAddress );
|
|
return FALSE;
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: read_dword
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Reads a dword value from the debuggee's process address space and
|
|
// returns it the caller.
|
|
//
|
|
// NOTE: An message is printed out thru the debugger in case of error
|
|
// reading from the debuggee's address space.
|
|
//
|
|
// Returns:
|
|
//
|
|
// 0 - on failure
|
|
// dword value - on success
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD read_dword (PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
HANDLE hProcess,
|
|
ULONG lpAddress
|
|
)
|
|
{
|
|
DWORD dword;
|
|
|
|
try {
|
|
if (lpExtensionApis->nSize >= sizeof(WINDBG_EXTENSION_APIS)) {
|
|
if (!(*lpExtensionApis->lpReadProcessMemoryRoutine)(
|
|
(DWORD)lpAddress, &dword, sizeof(dword), NULL)) {
|
|
EPRINTF("Failure reading DWORD at memory location %08lX\n", lpAddress );
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
NtReadVirtualMemory(hProcess,
|
|
(LPVOID)lpAddress, &dword, sizeof(dword), NULL);
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
EPRINTF("Exception trying to read DWORD from memory location %08lX\n", lpAddress );
|
|
return FALSE;
|
|
}
|
|
|
|
return ( dword );
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: read_long
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Reads a long value from the debuggee's process address space and
|
|
// returns it the caller.
|
|
//
|
|
// NOTE: An message is printed out thru the debugger in case of error
|
|
// reading from the debuggee's address space.
|
|
//
|
|
// Returns:
|
|
//
|
|
// 0 - on failure
|
|
// long value - on success
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
LONG read_long (PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
HANDLE hProcess,
|
|
ULONG lpAddress
|
|
)
|
|
{
|
|
LONG lval;
|
|
|
|
try {
|
|
if (lpExtensionApis->nSize >= sizeof(WINDBG_EXTENSION_APIS)) {
|
|
if (!(*lpExtensionApis->lpReadProcessMemoryRoutine)(
|
|
(DWORD)lpAddress, &lval, sizeof(lval), NULL)) {
|
|
EPRINTF("Failure reading LONG at memory location %08lX\n", lpAddress );
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
NtReadVirtualMemory(hProcess,
|
|
(LPVOID)lpAddress, &lval, sizeof(lval), NULL);
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
EPRINTF("Exception trying to read LONG from memory location %08lX\n", lpAddress );
|
|
return FALSE;
|
|
}
|
|
|
|
return( lval );
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: read_word
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Reads a word value from the debuggee's process address space and
|
|
// returns it the caller.
|
|
//
|
|
// NOTE: An message is printed out thru the debugger in case of error
|
|
// reading from the debuggee's address space.
|
|
//
|
|
// Returns:
|
|
//
|
|
// 0 - on failure
|
|
// word value - on success
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
WORD read_word (PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
HANDLE hProcess,
|
|
ULONG lpAddress
|
|
)
|
|
{
|
|
WORD word;
|
|
|
|
try {
|
|
if (lpExtensionApis->nSize >= sizeof(WINDBG_EXTENSION_APIS)) {
|
|
if (!(*lpExtensionApis->lpReadProcessMemoryRoutine)(
|
|
(DWORD)lpAddress, &word, sizeof(word), NULL)) {
|
|
EPRINTF("Failure reading WORD at memory location %08lX\n", lpAddress );
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
NtReadVirtualMemory(hProcess,
|
|
(LPVOID)lpAddress, &word, sizeof(word), NULL);
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
EPRINTF("Exception trying to read WORD from memory location %08lX\n", lpAddress );
|
|
return FALSE;
|
|
}
|
|
|
|
return( word );
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: read_byte
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Reads a byte value from the debuggee's process address space and
|
|
// returns it the caller.
|
|
//
|
|
// NOTE: An message is printed out thru the debugger in case of error
|
|
// reading from the debuggee's address space.
|
|
//
|
|
// Returns:
|
|
//
|
|
// 0 - on failure
|
|
// byte value - on success
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
BYTE read_byte (PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
HANDLE hProcess,
|
|
ULONG lpAddress
|
|
)
|
|
{
|
|
BYTE byte;
|
|
|
|
try {
|
|
if (lpExtensionApis->nSize >= sizeof(WINDBG_EXTENSION_APIS)) {
|
|
if (!(*lpExtensionApis->lpReadProcessMemoryRoutine)(
|
|
(DWORD)lpAddress, &byte, sizeof(byte), NULL)) {
|
|
EPRINTF("Failure reading BYTE at memory location %08lX\n", lpAddress );
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
NtReadVirtualMemory(hProcess,
|
|
(LPVOID)lpAddress, &byte, sizeof(byte), NULL);
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
EPRINTF("Exception trying to read BYTE from memory location %08lX\n", lpAddress );
|
|
return FALSE;
|
|
}
|
|
|
|
return( byte );
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: read_unicode_string
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Reads a null-terminated string from the debuggee's process address
|
|
// space and returns it the caller.
|
|
//
|
|
// NOTE: An message is printed out thru the debugger in case of error
|
|
// reading from the debuggee's address space.
|
|
//
|
|
// Returns:
|
|
//
|
|
// -1 - on buffer too small
|
|
// 0 - on failure
|
|
// number of chars - on success
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
int read_unicode_string (PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
HANDLE hProcess,
|
|
ULONG lpAddress,
|
|
LPWSTR lpsz,
|
|
ULONG cb
|
|
)
|
|
{
|
|
BOOL b;
|
|
WORD word;
|
|
int i = 0;
|
|
|
|
while (1)
|
|
{
|
|
try {
|
|
if (lpExtensionApis->nSize >= sizeof(WINDBG_EXTENSION_APIS)) {
|
|
if (!(*lpExtensionApis->lpReadProcessMemoryRoutine)(
|
|
(DWORD)lpAddress, &word, sizeof(word), NULL)) {
|
|
EPRINTF("Failure reading WCHAR at memory location %08lX\n", lpAddress );
|
|
return 0;
|
|
}
|
|
} else {
|
|
NtReadVirtualMemory(hProcess,
|
|
(LPVOID)lpAddress, &word, sizeof(word), NULL);
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
EPRINTF("Exception trying to read WCHAR from memory location %08lX\n", lpAddress );
|
|
return 0;
|
|
}
|
|
|
|
lpAddress += 2;
|
|
|
|
if (i <= (int)cb)
|
|
{
|
|
if ((lpsz[i++] = (WCHAR)word) == 0)
|
|
return (i);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Be nice and Null terminate string
|
|
//
|
|
|
|
lpsz[i-1] = (char) 0;
|
|
|
|
return (-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: read_ansi_string
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Reads a null-terminated string from the debuggee's process address
|
|
// space and returns it the caller.
|
|
//
|
|
// NOTE: An message is printed out thru the debugger in case of error
|
|
// reading from the debuggee's address space.
|
|
//
|
|
// Returns:
|
|
//
|
|
// -1 - on buffer too small
|
|
// 0 - on failure
|
|
// number of chars - on success
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
int read_ansi_string (PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
HANDLE hProcess,
|
|
ULONG lpAddress,
|
|
LPSTR lpsz,
|
|
ULONG cb
|
|
)
|
|
{
|
|
BOOL b;
|
|
BYTE byte;
|
|
int i = 0;
|
|
|
|
while (1)
|
|
{
|
|
try {
|
|
if (lpExtensionApis->nSize >= sizeof(WINDBG_EXTENSION_APIS)) {
|
|
if (!(*lpExtensionApis->lpReadProcessMemoryRoutine)(
|
|
(DWORD)lpAddress, &byte, sizeof(byte), NULL)) {
|
|
EPRINTF("Failure reading CHAR at memory location %08lX\n", lpAddress );
|
|
return 0;
|
|
}
|
|
} else {
|
|
NtReadVirtualMemory(hProcess,
|
|
(LPVOID)lpAddress, &byte, sizeof(byte), NULL);
|
|
}
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
EPRINTF("Exception trying to read BYTE from memory location %08lX\n", lpAddress );
|
|
return 0;
|
|
}
|
|
|
|
if (i <= (int)cb)
|
|
{
|
|
if ((lpsz[i++] = byte) == 0)
|
|
return (i);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Be nice and Null terminate string
|
|
//
|
|
|
|
lpsz[i-1] = 0;
|
|
|
|
return (-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: print_minst_fields
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Prints out the "minst" structure fields.
|
|
//
|
|
// Returns:
|
|
// Nothing
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
VOID print_minst_fields (PWINDBG_OUTPUT_ROUTINE lpOutputRoutine, MINST *pminst)
|
|
{
|
|
PRINTF ("MINST structure fields:\n");
|
|
PRINTF ("\tfIs16bit = %s\n",
|
|
(pminst->fIs16bit) ? "TRUE" : "FALSE");
|
|
|
|
PRINTF ("\thinst = 0x%08lx\n", pminst->hinst);
|
|
PRINTF ("\tidOwner = 0x%08lx\n", pminst->idOwner);
|
|
PRINTF ("\thOwner = 0x%08lx\n", pminst->hOwner);
|
|
|
|
PRINTF("\n");
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: cd
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "cd" debugger extension command to print out the
|
|
// values of an Control Data structure maintained by the Shell32
|
|
// Control Panel code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.cd <addr>
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID cd (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
ControlData ctldata;
|
|
PControlData pctldata;
|
|
BOOL fFoundArgs;
|
|
CHAR ch;
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pctldata = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pctldata = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.cd: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pctldata, &ctldata, sizeof(ctldata)))
|
|
{
|
|
PRINTF( "sde.cd: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// NOTE: [stevecat] Either this command should be expanded to list all
|
|
// of the array elements pointed to by these structure
|
|
// members, or additional commands should be created.
|
|
//
|
|
|
|
PRINTF ("ControlData structure fields:\n");
|
|
PRINTF ("\thaminst = 0x%08lx\n", ctldata.haminst);
|
|
PRINTF ("\thamiModule = 0x%08lx\n", ctldata.hamiModule);
|
|
PRINTF ("\tcModules = 0x%08lx\n", ctldata.cModules);
|
|
PRINTF ("\tpRegCPLBuffer = 0x%08lx\n", ctldata.pRegCPLBuffer);
|
|
PRINTF ("\thRegCPLs = 0x%08lx\n", ctldata.hRegCPLs);
|
|
PRINTF ("\tcRegCPLs = 0x%08lx\n", ctldata.cRegCPLs);
|
|
PRINTF ("\tfRegCPLChanged = 0x%08lx\n", ctldata.fRegCPLChanged);
|
|
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: cei
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "cei" debugger extension command to print out the
|
|
// values of an CPLEXECINFO structure maintained by the Shell32 Control
|
|
// Panel code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.cei <addr>
|
|
//
|
|
// Returns:
|
|
// Nothing
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID cei (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
CPLEXECINFO cei;
|
|
CPLEXECINFO *pcei;
|
|
BOOL fFoundArgs;
|
|
TCHAR ch;
|
|
TCHAR szString[MAX_PATH];
|
|
int i;
|
|
|
|
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pcei = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pcei = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.cei: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pcei, &cei, sizeof(cei)))
|
|
{
|
|
PRINTF( "sde.cei: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
PRINTF ("CPLEXECINFO structure fields:\n");
|
|
PRINTF ("\ticon = %d (decimal)\n", cei.icon);
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (cei.cpl, szString, ARRAYSIZE(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (cei.cpl, szString, ARRAYSIZE(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tcpl = ERROR reading cpl string\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tcpl = ERROR cpl string > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tcpl = %s\n", szString);
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (cei.applet, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (cei.applet, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tapplet = ERROR reading applet string\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tapplet = ERROR applet string > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tapplet = %s\n", szString);
|
|
|
|
if (cei.params == NULL)
|
|
{
|
|
PRINTF ("\tparams = NULL - there are no param for this applet\n");
|
|
}
|
|
else
|
|
{
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (cei.params, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (cei.params, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tparams = ERROR reading params string\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tparams = ERROR params string > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tparams = %s\n", szString);
|
|
}
|
|
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: cid
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "cid" debugger extension command to print out the
|
|
// values of an CPLAPPLETID structure maintained by the Shell32 Control
|
|
// Panel code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.cid <addr>
|
|
//
|
|
// Returns:
|
|
// Nothing
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID cid (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
CPLAPPLETID cid;
|
|
CPLAPPLETID *pcid;
|
|
BOOL fFoundArgs;
|
|
TCHAR ch;
|
|
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pcid = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pcid = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.cid: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pcid, &cid, sizeof(cid)))
|
|
{
|
|
PRINTF( "sde.cid: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
PRINTF ("CPLAPPLETID structure fields:\n");
|
|
PRINTF ("\taCPL = %d (decimal)\n", (DWORD)(WORD)cid.aCPL);
|
|
PRINTF ("\taApplet = %d (decimal)\n", (DWORD)(WORD)cid.aApplet);
|
|
PRINTF ("\thwndStub = 0x%08lx\n", cid.hwndStub);
|
|
PRINTF ("\tflags = 0x%08lx\n", cid.flags);
|
|
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: cpl
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "cpl" debugger extension command to print out the
|
|
// values of an CPLINFO structure returned by an applet and maintained
|
|
// by the Shell32 Control Panel code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.cpl <addr>
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID cpl (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
CPLINFO cpl;
|
|
LPCPLINFO pcpl;
|
|
BOOL fFoundArgs;
|
|
TCHAR ch;
|
|
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pcpl = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pcpl = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.cpl: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pcpl, &cpl, sizeof(cpl)))
|
|
{
|
|
PRINTF( "sde.cpl: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
PRINTF ("CPLINFO structure fields (decimal):\n");
|
|
PRINTF ("\tidIcon = %d\n", cpl.idIcon);
|
|
PRINTF ("\tidName = %d\n", cpl.idName);
|
|
PRINTF ("\tidInfo = %d\n", cpl.idInfo);
|
|
PRINTF ("\tlData = %d\n", cpl.lData);
|
|
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
#ifdef LATER
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: print_cpli_fields
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Prints out the "CPLITEM" structure fields.
|
|
//
|
|
// Returns:
|
|
// Nothing
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
VOID print_cpli_fields (PWINDBG_OUTPUT_ROUTINE lpOutputRoutine, LPCPLITEM pci)
|
|
{
|
|
TCHAR szString[MAX_PATH];
|
|
int i;
|
|
|
|
//
|
|
// NOTE that the passed in structure has been read from the processes
|
|
// address space; HOWEVER, the string pointers in this structure have
|
|
// not been read yet. That is why we do it here.
|
|
//
|
|
|
|
PRINTF ("CPLITEM structure fields:\n");
|
|
PRINTF ("\tidControl = 0x%08lx\n", pci->idControl);
|
|
PRINTF ("\thIcon = 0x%08lx\n", pci->hIcon);
|
|
PRINTF ("\tidIcon = 0x%08lx\n", pci->idIcon);
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (pci->pszName, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (pci->pszName, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tpszName = ERROR reading applet name string\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tpszName = ERROR applet name string > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tpszName = %s\n", szString);
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (pci->pszInfo, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (pci->pszInfo, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tpszInfo = ERROR reading applet info string\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tpszInfo = ERROR applet info string > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tpszInfo = %s\n", szString);
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (pci->pszHelpFile, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (pci->pszHelpFile, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tpszHelpFile = ERROR reading applet helpfile name\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tpszHelpFile = ERROR applet helpfile path > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tpszHelpFile = %s\n", szString);
|
|
|
|
PRINTF ("\tlData = 0x%08lx\n", pci->lData);
|
|
PRINTF ("\tdwContext = 0x%08lx\n", pci->dwContext);
|
|
|
|
PRINTF("\n");
|
|
}
|
|
#endif // LATER
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: cpli
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "cpli" debugger extension command to print out the
|
|
// values of an CPLITEM structure maintained by the Shell32 Control
|
|
// Panel code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.cpli <addr>
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID cpli (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
CPLITEM ci;
|
|
LPCPLITEM pci;
|
|
BOOL fFoundArgs;
|
|
TCHAR ch;
|
|
TCHAR szString[MAX_PATH];
|
|
int i;
|
|
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pci = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pci = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.ci: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pci, &ci, sizeof(ci)))
|
|
{
|
|
PRINTF( "sde.ci: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
// print_cpli_fields (lpOutputRoutine, &ci);
|
|
|
|
|
|
PRINTF ("CPLITEM structure fields:\n");
|
|
PRINTF ("\tidControl = 0x%08lx\n", ci.idControl);
|
|
PRINTF ("\thIcon = 0x%08lx\n", ci.hIcon);
|
|
PRINTF ("\tidIcon = 0x%08lx\n", ci.idIcon);
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (ci.pszName, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (ci.pszName, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tpszName = ERROR reading applet name string\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tpszName = ERROR applet name string > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tpszName = %s\n", szString);
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (ci.pszInfo, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (ci.pszInfo, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tpszInfo = ERROR reading applet info string\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tpszInfo = ERROR applet info string > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tpszInfo = %s\n", szString);
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (ci.pszHelpFile, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (ci.pszHelpFile, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tpszHelpFile = ERROR reading applet helpfile name\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tpszHelpFile = ERROR applet helpfile path > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tpszHelpFile = %s\n", szString);
|
|
|
|
PRINTF ("\tlData = 0x%08lx\n", ci.lData);
|
|
PRINTF ("\tdwContext = 0x%08lx\n", ci.dwContext);
|
|
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: cplm
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "cplm" debugger extension command to print out the
|
|
// values of an CPLMODULE structure maintained by the Shell32 Control
|
|
// Panel code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.cplm <addr>
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID cplm (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
CPLMODULE cm;
|
|
PCPLMODULE pcm;
|
|
BOOL fFoundArgs;
|
|
TCHAR ch;
|
|
TCHAR szString[MAX_PATH];
|
|
int i;
|
|
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if ( ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n' )
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pcm = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pcm = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.cm: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pcm, &cm, sizeof(cm)))
|
|
{
|
|
PRINTF( "sde.cm: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
PRINTF ("CPLMODULE structure fields:\n");
|
|
PRINTF ("\tcRef = 0x%08lx\n", cm.cRef);
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (cm.szModule, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (cm.szModule, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tszModule = ERROR reading module string\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tszModule = ERROR module path > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tszModule = %s\n", szString);
|
|
|
|
PRINTF ("\tlpfnCPL = 0x%08lx\n", cm.lpfnCPL);
|
|
PRINTF ("\thacpli = 0x%08lx\n", cm.hacpli);
|
|
|
|
PRINTF("\n");
|
|
|
|
print_minst_fields (lpOutputRoutine, &cm.minst);
|
|
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: idc
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "idc" debugger extension command to print out the
|
|
// values of an IDCONTROL structure maintained by the Shell32
|
|
// Control Panel code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.idc <addr>
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID idc (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
IDCONTROL idc;
|
|
LPIDCONTROL pidc;
|
|
BOOL fFoundArgs;
|
|
CHAR ch;
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pidc = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pidc = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.idc: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pidc, &idc, sizeof(idc)))
|
|
{
|
|
PRINTF( "sde.idc: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
PRINTF ("IDCONTROL structure fields (decimal):\n");
|
|
PRINTF ("\tcb (Size) = %d (decimal)\n", idc.cb);
|
|
PRINTF ("\tidIcon = %d\n", idc.idIcon);
|
|
PRINTF ("\toName = %d\n", idc.oName);
|
|
PRINTF ("\toInfo = %d\n", idc.oInfo);
|
|
|
|
PRINTF ("\tFilename = %ws\n", idc.cBuf[0]);
|
|
|
|
if (idc.oName < sizeof(idc.cBuf))
|
|
PRINTF ("\tName = %ws\n", idc.cBuf[idc.oName]);
|
|
else
|
|
PRINTF ("\tName = ERROR - string offset > buffer size\n");
|
|
|
|
if (idc.oInfo < sizeof(idc.cBuf))
|
|
PRINTF ("\tDescription = %ws\n", idc.cBuf[idc.oInfo]);
|
|
else
|
|
PRINTF ("\tDescription = ERROR - string offset > buffer size\n");
|
|
|
|
PRINTF ("\tuTerm = %d\n", idc.uTerm);
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: mi
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "mi" debugger extension command to print out the
|
|
// values of an MODULEINFO structure maintained by the Shell32 Control
|
|
// Panel code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.mi <addr>
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID mi (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
MODULEINFO mi;
|
|
PMODULEINFO pmi;
|
|
BOOL fFoundArgs;
|
|
TCHAR ch;
|
|
CHAR szString[MAX_PATH];
|
|
int i;
|
|
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if ( ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n' )
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pmi = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pmi = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.mi: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pmi, &mi, sizeof(mi)))
|
|
{
|
|
PRINTF( "sde.mi: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
PRINTF ("MODULEINFO structure fields:\n");
|
|
PRINTF ("\tflags = 0x%08lx\n", mi.flags);
|
|
PRINTF ("\t\t%s\n", (mi.flags & MI_FIND_FILE) ?
|
|
"WIN32_FIND_FILE info filled in." :
|
|
"WIN32_FIND_FILE info NOT filled in." );
|
|
|
|
PRINTF ("\t\t%s\n", (mi.flags & MI_REG_ENUM) ?
|
|
"Module enumerated thru registry." :
|
|
"Module NOT enumerated thru registry.");
|
|
|
|
PRINTF ("\t\t%s\n", (mi.flags & MI_CPL_LOADED) ?
|
|
"CPLD_InitModule called." :
|
|
"CPLD_InitModule NOT called.");
|
|
|
|
PRINTF ("\tftCreationTime\n");
|
|
PRINTF ("\t dwLowDateTime = 0x%lx\n", mi.ftCreationTime.dwLowDateTime);
|
|
PRINTF ("\t dwHighDateTime= 0x%lx\n", mi.ftCreationTime.dwHighDateTime);
|
|
PRINTF ("\tnFileSizeHigh = 0x%lx\n", mi.nFileSizeHigh);
|
|
PRINTF ("\tnFileSizeLow = 0x%lx\n", mi.nFileSizeLow);
|
|
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (mi.pszModule, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (mi.pszModule, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tpszModule = ERROR reading module string\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tpszModule = ERROR module path > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tpszModule = %s\n", szString);
|
|
|
|
|
|
#ifdef UC_SHELL
|
|
i = ReadUnicodeStrSafe (mi.pszModuleName, szString, sizeof(szString));
|
|
#else
|
|
i = ReadAnsiStrSafe (mi.pszModuleName, szString, sizeof(szString));
|
|
#endif // UC_SHELL
|
|
|
|
if (i == 0)
|
|
PRINTF ("\tpszModuleName = ERROR reading module string\n");
|
|
else if ( i == -1)
|
|
PRINTF ("\tpszModuleName = ERROR module name > MAX_PATH chars\n");
|
|
else
|
|
PRINTF ("\tpszModuleName = %s\n", szString);
|
|
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: minst
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "minst" debugger extension command to print out the
|
|
// values of an Module Instance structure maintained by the Shell32
|
|
// Control Panel code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.minst <addr>
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID minst (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
MINST minst;
|
|
MINST *pminst;
|
|
BOOL fFoundArgs;
|
|
CHAR ch;
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pminst = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pminst = (MINST*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.minst: Error - no address given\n" );
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pminst, &minst, sizeof(minst)))
|
|
{
|
|
PRINTF( "sde.minst: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
print_minst_fields (lpOutputRoutine, &minst);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: ncia
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "ncia" debugger extension command to print out the
|
|
// values of an Ansi version of the public NewCPLInfoA structure
|
|
// returned by an applet and maintained by the Shell32 Control Panel
|
|
// code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.ncia <addr>
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID ncia (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
NEWCPLINFOA ncia;
|
|
LPNEWCPLINFOA pncia;
|
|
BOOL fFoundArgs;
|
|
TCHAR ch;
|
|
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pncia = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pncia = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.ncia: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pncia, &ncia, sizeof(ncia)))
|
|
{
|
|
PRINTF( "sde.ncia: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
PRINTF ("NEWCPLINFOA structure fields:\n");
|
|
PRINTF ("\tdwSize = 0x%08lx\n", ncia.dwSize);
|
|
PRINTF ("\tdwFlags = 0x%08lx\n", ncia.dwFlags);
|
|
PRINTF ("\tdwHelpContext = 0x%08lx\n", ncia.dwHelpContext);
|
|
PRINTF ("\tlData = 0x%08lx\n", ncia.lData);
|
|
PRINTF ("\thIcon = 0x%08lx\n", ncia.hIcon);
|
|
|
|
PRINTF ("\tszName = %s\n", ncia.szName);
|
|
PRINTF ("\tszInfo = %s\n", ncia.szInfo);
|
|
PRINTF ("\tszHelpFile = %s\n", ncia.szHelpFile);
|
|
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: nciw
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "nciw" debugger extension command to print out the
|
|
// values of an Unicode version of the public NewCPLInfoW structure
|
|
// returned by an applet and maintained by the Shell32 Control Panel
|
|
// code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.nciw <addr>
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID nciw (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
NEWCPLINFOW nciw;
|
|
LPNEWCPLINFOW pnciw;
|
|
BOOL fFoundArgs;
|
|
TCHAR ch;
|
|
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
pnciw = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
pnciw = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.nciw: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (pnciw, &nciw, sizeof(nciw)))
|
|
{
|
|
PRINTF( "sde.nciw: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
PRINTF ("NEWCPLINFOW structure fields:\n");
|
|
PRINTF ("\tdwSize = 0x%08lx\n", nciw.dwSize);
|
|
PRINTF ("\tdwFlags = 0x%08lx\n", nciw.dwFlags);
|
|
PRINTF ("\tdwHelpContext = 0x%08lx\n", nciw.dwHelpContext);
|
|
PRINTF ("\tlData = 0x%08lx\n", nciw.lData);
|
|
PRINTF ("\thIcon = 0x%08lx\n", nciw.hIcon);
|
|
|
|
PRINTF ("\tszName = %ws\n", nciw.szName);
|
|
PRINTF ("\tszInfo = %ws\n", nciw.szInfo);
|
|
PRINTF ("\tszHelpFile = %ws\n", nciw.szHelpFile);
|
|
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: rcpl
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implements the "rcpl" debugger extension command to print out the
|
|
// values of an RegCPLInfo structure maintained by the Shell32
|
|
// Control Panel code.
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.rcpl <addr>
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID rcpl (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
RegCPLInfo rci;
|
|
PRegCPLInfo prci;
|
|
BOOL fFoundArgs;
|
|
CHAR ch;
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get address argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
prci = NULL;
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
prci = (VOID*)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.rcpl: Error - no address given.\n");
|
|
return;
|
|
}
|
|
|
|
if (!ReadStruct (prci, &rci, sizeof(rci)))
|
|
{
|
|
PRINTF( "sde.rcpl: Error reading from address.\n" );
|
|
return;
|
|
}
|
|
|
|
PRINTF ("RegCPLInfo structure fields:\n");
|
|
PRINTF ("\tcbSize = %d (decimal)\n", rci.cbSize);
|
|
PRINTF ("\tflags = 0x%lx (0x0001 == Loaded from registry)\n", rci.flags);
|
|
PRINTF ("\tftCreationTime\n");
|
|
PRINTF ("\t dwLowDateTime = 0x%lx\n", rci.ftCreationTime.dwLowDateTime);
|
|
PRINTF ("\t dwHighDateTime= 0x%lx\n", rci.ftCreationTime.dwHighDateTime);
|
|
PRINTF ("\tnFileSizeHigh = 0x%lx\n", rci.nFileSizeHigh);
|
|
PRINTF ("\tnFileSizeLow = 0x%lx\n", rci.nFileSizeLow);
|
|
PRINTF ("\tidIcon = 0x%lx\n", rci.idIcon);
|
|
PRINTF ("\toName = 0x%lx\n", rci.oName);
|
|
PRINTF ("\toInfo = 0x%lx\n", rci.oInfo);
|
|
PRINTF ("\tCPL FileName = %ws\n", REGCPL_FILENAME(&rci));
|
|
|
|
if (rci.oName < sizeof(rci.buf))
|
|
PRINTF ("\tCPL Name = %ws\n", REGCPL_CPLNAME(&rci));
|
|
else
|
|
PRINTF ("\tCPL Name = ERROR - string offset > buffer size\n");
|
|
|
|
if (rci.oInfo < sizeof(rci.buf))
|
|
PRINTF ("\tCPL Info = %ws\n", REGCPL_CPLINFO(&rci));
|
|
else
|
|
PRINTF ("\tCPL Info = ERROR - string offset > buffer size\n");
|
|
|
|
PRINTF("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function: hkey
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// If running on a debug build, this will print out what the registry
|
|
// key actually maps to -- i.e., "HKEY_CURRENT_USERS\etc\etc\etc"
|
|
//
|
|
// Command Description:
|
|
//
|
|
// !sde.hkey 0 ==> prints out all open handles
|
|
// !sde.hkey <hkey value> ==> prints out <hkey value> handle
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID hkey (HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
|
LPSTR lpArgumentString
|
|
)
|
|
{
|
|
PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
|
|
PWINDBG_GET_EXPRESSION lpGetExpressionRoutine;
|
|
PWINDBG_GET_SYMBOL lpGetSymbolRoutine;
|
|
KEY_NODE keyNode;
|
|
LPVOID lpNodeAddr = NULL;
|
|
HKEY hkey;
|
|
BOOL fFoundArgs;
|
|
CHAR ch;
|
|
|
|
UNREFERENCED_PARAMETER(dwCurrentPc);
|
|
|
|
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
|
|
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
|
|
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
|
|
|
|
//
|
|
// Get hkey argument from command line
|
|
//
|
|
|
|
fFoundArgs = FALSE;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' )
|
|
{
|
|
if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n')
|
|
{
|
|
fFoundArgs = TRUE;
|
|
break;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
|
|
if ( fFoundArgs )
|
|
{
|
|
hkey = (HKEY)(* lpGetExpressionRoutine)( lpArgumentString );
|
|
}
|
|
else
|
|
{
|
|
PRINTF( "sde.hkey: *** no key given.\n *** use \"sde.hkey 0\" to dump entire HKEY list\n");
|
|
return;
|
|
}
|
|
|
|
lpNodeAddr = (LPVOID)(* lpGetExpressionRoutine)( "shell32!RegKeyHead" );
|
|
|
|
if (!lpNodeAddr) {
|
|
PRINTF( "sde.hkey: *** Not able to get address for shell32!RegKeyHead\n *** Make sure you are running on a debug build!");
|
|
return;
|
|
}
|
|
|
|
do {
|
|
|
|
if (!ReadStruct( lpNodeAddr, &keyNode, sizeof(KEY_NODE)))
|
|
{
|
|
PRINTF( "sde.hkey: *** Error reading from RegKey list (0x%lx).\n", lpNodeAddr );
|
|
return;
|
|
}
|
|
|
|
if ((keyNode.hKey!=(HKEY)0xFFFFFFFF) && ((hkey==0) || (keyNode.hKey==hkey)))
|
|
{
|
|
|
|
CHAR szTemp[ 1024 ];
|
|
#ifdef UNICODE
|
|
WCHAR swzTemp[ 1024 ];
|
|
if (ReadUnicodeStr(keyNode.lpName, swzTemp, 1024 ))
|
|
{
|
|
WideCharToMultiByte( CP_ACP, 0, swzTemp, -1, szTemp, 1024, NULL, NULL );
|
|
PRINTF( "HKEY(0x%lx) == (%s)\n", keyNode.hKey, szTemp );
|
|
}
|
|
#else
|
|
if (ReadAnsiStr(keyNode.lpName, szTemp, 1024))
|
|
{
|
|
PRINTF( "HKEY(0x%lx) == (%s)\n", keyNode.hKey, keyNode.szName );
|
|
}
|
|
#endif
|
|
}
|
|
lpNodeAddr = keyNode.next;
|
|
|
|
if ((hkey) && (keyNode.hKey==hkey))
|
|
break;
|
|
|
|
} while( lpNodeAddr );
|
|
|
|
PRINTF( "\n" );
|
|
|
|
return;
|
|
|
|
}
|