544 lines
12 KiB
C++
544 lines
12 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1995
|
|
//
|
|
// File: ole.cxx
|
|
//
|
|
// Contents: Implements ntsd extensions to dump ole tables
|
|
//
|
|
// Functions:
|
|
//
|
|
//
|
|
// History: 06-01-95 BruceMa Created
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#include <ole2int.h>
|
|
#include <windows.h>
|
|
#include "ole.h"
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: readMemory
|
|
//
|
|
// Synopsis: Transfer memory from debuggee virtual space to a local
|
|
// kernel memory
|
|
//
|
|
// Arguments: [lpArgumentString] - command line string
|
|
// [a] - where to return next argument
|
|
//
|
|
// Returns: -
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void readMemory(HANDLE hProcess, PNTSD_EXTENSION_APIS lpExtensionApis,
|
|
BYTE *to, BYTE *from, INT cbSize)
|
|
{
|
|
__try
|
|
{
|
|
NtReadVirtualMemory(hProcess, (void *) from, (void *) to,
|
|
cbSize , NULL);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Printf("...Exception reading %08x-%08x\n", from, from + cbSize - 1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: writeMemory
|
|
//
|
|
// Synopsis: Transfer memory from local memoryto debuggee virtual space
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: -
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void writeMemory(HANDLE hProcess, PNTSD_EXTENSION_APIS lpExtensionApis,
|
|
BYTE *to, BYTE *from, INT cbSize)
|
|
{
|
|
__try
|
|
{
|
|
NtWriteVirtualMemory(hProcess, (void *) to, (void *) from,
|
|
cbSize, NULL);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Printf("...Exception writing %08x-%08x\n", to, to + cbSize - 1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: getArgument
|
|
//
|
|
// Synopsis: Return next command line argument
|
|
//
|
|
// Arguments: [lpArgumentString] - command line string
|
|
// [a] - where to return next argument
|
|
//
|
|
// Returns: -
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void getArgument(LPSTR *lpArgumentString, LPSTR a)
|
|
{
|
|
char *s = *lpArgumentString;
|
|
|
|
// Skip whitespace
|
|
while (*s && (*s == ' ' || *s == '\t'))
|
|
{
|
|
s++;
|
|
}
|
|
while (*s && *s != ' ' && *s != '\t')
|
|
{
|
|
*a++ = *s++;
|
|
}
|
|
*a = '\0';
|
|
*lpArgumentString = s;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: IsEqualGUID
|
|
//
|
|
// Synopsis: Compares two guids for equality
|
|
//
|
|
// Arguments: [pClsid1] - the first clsid
|
|
// [pClsid2] - the second clsid to compare the first one with
|
|
//
|
|
// Returns: TRUE if equal, FALSE if not.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
BOOL IsEqualCLSID(CLSID *pClsid1, CLSID *pClsid2)
|
|
{
|
|
return !memcmp((void *) pClsid1,(void *) pClsid2, sizeof(CLSID));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: ScanAddr
|
|
//
|
|
// Synopsis: Parse the indput string as a hexadecimal address
|
|
//
|
|
// Arguments: [lpsz] - the hex string to convert
|
|
//
|
|
// Returns: TRUE for success
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
ULONG ScanAddr(char *lpsz)
|
|
{
|
|
ULONG val = NULL;
|
|
|
|
// Peel off any leading "0x"
|
|
if (lpsz[0] == '0' && lpsz[1] == 'x')
|
|
{
|
|
lpsz += 2;
|
|
}
|
|
|
|
// Parse as a hex address
|
|
while (*lpsz)
|
|
{
|
|
if (*lpsz >= '0' && *lpsz <= '9')
|
|
{
|
|
val = (val << 4) + *lpsz - '0';
|
|
}
|
|
else if (*lpsz >= 'A' && *lpsz <= 'F')
|
|
{
|
|
val = (val << 4) + *lpsz - 'A' + 10;
|
|
}
|
|
else if (*lpsz >= 'a' && *lpsz <= 'f')
|
|
{
|
|
val = (val << 4) + *lpsz - 'a' + 10;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
lpsz++;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: HexStringToDword
|
|
//
|
|
// Synopsis: scan lpsz for a number of hex digits (at most 8); update lpsz
|
|
// return value in Value; check for chDelim;
|
|
//
|
|
// Arguments: [lpsz] - the hex string to convert
|
|
// [Value] - the returned value
|
|
// [cDigits] - count of digits
|
|
//
|
|
// Returns: TRUE for success
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
static BOOL HexStringToDword(LPSTR &lpsz, DWORD &Value,
|
|
int cDigits, WCHAR chDelim)
|
|
{
|
|
int Count;
|
|
|
|
Value = 0;
|
|
for (Count = 0; Count < cDigits; Count++, lpsz++)
|
|
{
|
|
if (*lpsz >= '0' && *lpsz <= '9')
|
|
Value = (Value << 4) + *lpsz - '0';
|
|
else if (*lpsz >= 'A' && *lpsz <= 'F')
|
|
Value = (Value << 4) + *lpsz - 'A' + 10;
|
|
else if (*lpsz >= 'a' && *lpsz <= 'f')
|
|
Value = (Value << 4) + *lpsz - 'a' + 10;
|
|
else
|
|
return(FALSE);
|
|
}
|
|
|
|
if (chDelim != 0)
|
|
return *lpsz++ == chDelim;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CLSIDFromString
|
|
//
|
|
// Synopsis: Parse above format; always writes over *pguid.
|
|
//
|
|
// Arguments: [lpsz] - the guid string to convert
|
|
// [pguid] - guid to return
|
|
//
|
|
// Returns: TRUE if successful
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
BOOL ScanCLSID(LPSTR lpsz, CLSID *pClsid)
|
|
{
|
|
DWORD dw;
|
|
if (*lpsz++ != '{')
|
|
return FALSE;
|
|
|
|
if (!HexStringToDword(lpsz, pClsid->Data1, sizeof(DWORD)*2, '-'))
|
|
return FALSE;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
|
|
return FALSE;
|
|
|
|
pClsid->Data2 = (WORD)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
|
|
return FALSE;
|
|
|
|
pClsid->Data3 = (WORD)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pClsid->Data4[0] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
|
|
return FALSE;
|
|
|
|
pClsid->Data4[1] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pClsid->Data4[2] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pClsid->Data4[3] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pClsid->Data4[4] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pClsid->Data4[5] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
return FALSE;
|
|
|
|
pClsid->Data4[6] = (BYTE)dw;
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, /*(*/ '}'))
|
|
return FALSE;
|
|
|
|
pClsid->Data4[7] = (BYTE)dw;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: FormatCLSID
|
|
//
|
|
// Synopsis: converts GUID into {...} form without leading identifier;
|
|
//
|
|
// Arguments: [rguid] - the guid to convert
|
|
// [lpszy] - buffer to hold the results
|
|
// [cbMax] - sizeof the buffer
|
|
//
|
|
// Returns: amount of data copied to lpsz if successful
|
|
// 0 if buffer too small.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void FormatCLSID(REFGUID rguid, LPSTR lpsz)
|
|
{
|
|
wsprintf(lpsz, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\0",
|
|
rguid.Data1, rguid.Data2, rguid.Data3,
|
|
rguid.Data4[0], rguid.Data4[1],
|
|
rguid.Data4[2], rguid.Data4[3],
|
|
rguid.Data4[4], rguid.Data4[5],
|
|
rguid.Data4[6], rguid.Data4[7]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern BOOL fScmNeedsInit;
|
|
extern BOOL fInScm;
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CheckForScm
|
|
//
|
|
// Synopsis: Checks whether the debuggee is 'scm'
|
|
//
|
|
// Arguments: -
|
|
//
|
|
// Returns: Sets global boolean fInScm to TRUE if this is the scm;
|
|
// FALSE otherwise
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void checkForScm(PNTSD_EXTENSION_APIS lpExtensionApis)
|
|
{
|
|
ULONG padr = NULL;
|
|
|
|
if (fScmNeedsInit)
|
|
{
|
|
fScmNeedsInit = FALSE;
|
|
padr = GetExpression("scm!CPerMachineROT__CPerMachineROT");
|
|
fInScm = padr != NULL ? TRUE : FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: NotInScm
|
|
//
|
|
// Synopsis: Prints error message
|
|
//
|
|
// Arguments: -
|
|
//
|
|
// Returns:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void NotInScm(PNTSD_EXTENSION_APIS lpExtensionApis)
|
|
{
|
|
Printf("...not meaningful in the scm\n");
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: NotInOle
|
|
//
|
|
// Synopsis: Prints error message
|
|
//
|
|
// Arguments: -
|
|
//
|
|
// Returns:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void NotInOle(PNTSD_EXTENSION_APIS lpExtensionApis)
|
|
{
|
|
Printf("...only meaningful in the scm\n");
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// F O R D E B U G G I N G
|
|
|
|
|
|
void dbTrace(char *sz, DWORD *adr, ULONG amt,
|
|
PNTSD_EXTENSION_APIS lpExtensionApis)
|
|
{
|
|
UINT k;
|
|
|
|
Printf("\n%s", sz);
|
|
for (k = 0; k < amt; k++)
|
|
{
|
|
if (k % 8 == 0)
|
|
{
|
|
Printf("\n");
|
|
}
|
|
Printf("%08x ", *adr++);
|
|
}
|
|
Printf("\n");
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+--------------------------------------------------------
|
|
//
|
|
// Function: GetRegistryInterfaceName
|
|
//
|
|
// Algorithm: Fetch the name from the registry for the specified interface
|
|
//
|
|
// History: 21-Jun-95 BruceMa Created
|
|
//
|
|
//---------------------------------------------------------
|
|
BOOL GetRegistryInterfaceName(REFIID iid, char *szValue, DWORD *pcbValue)
|
|
{
|
|
DWORD dwRESERVED = 0;
|
|
HKEY hKey;
|
|
char szIID[CLSIDSTR_MAX];
|
|
char szInterface[32 + 1 + CLSIDSTR_MAX];
|
|
DWORD dwValueType;
|
|
HKEY hClsidKey;
|
|
HKEY hInproc32Key;
|
|
|
|
// Prepare to open the "...Interface\<iid>" key
|
|
FormatCLSID(iid, szIID);
|
|
lstrcpy(szInterface, "Interface\\");
|
|
lstrcat(szInterface, szIID);
|
|
|
|
// Open the key for the specified interface
|
|
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szInterface, dwRESERVED,
|
|
KEY_READ, &hKey) != ERROR_SUCCESS)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Read the value as the interface name
|
|
if (RegQueryValueEx(hKey, NULL, NULL, &dwValueType,
|
|
(LPBYTE) szValue, pcbValue) != ERROR_SUCCESS)
|
|
{
|
|
CloseHandle(hKey);
|
|
return FALSE;
|
|
}
|
|
|
|
// Close registry handle and return success
|
|
CloseHandle(hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+--------------------------------------------------------
|
|
//
|
|
// Function: GetRegistryClsidKey
|
|
//
|
|
// Algorithm: Fetch the value from the registry for the specified clsid
|
|
// and key
|
|
//
|
|
// History: 21-Jun-95 BruceMa Created
|
|
//
|
|
//---------------------------------------------------------
|
|
BOOL GetRegistryClsidKey(REFCLSID clsid, char *szKey,
|
|
char *szValue, DWORD *pcbValue)
|
|
{
|
|
DWORD dwRESERVED = 0;
|
|
HKEY hKey;
|
|
char szCLSID[CLSIDSTR_MAX];
|
|
char szClsid[5 + 1 + CLSIDSTR_MAX + 1 + 32];
|
|
DWORD dwValueType;
|
|
HKEY hClsidKey;
|
|
HKEY hInproc32Key;
|
|
|
|
// Prepare to open the "...Interface\<clsid>" key
|
|
FormatCLSID(clsid, szCLSID);
|
|
lstrcpy(szClsid, "CLSID\\");
|
|
lstrcat(szClsid, szCLSID);
|
|
lstrcat(szClsid,"\\");
|
|
lstrcat(szClsid, szKey);
|
|
|
|
// Open the key for the specified clsid and key
|
|
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szClsid, dwRESERVED,
|
|
KEY_READ, &hKey) != ERROR_SUCCESS)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Read the value for the specified key
|
|
if (RegQueryValueEx(hKey, NULL, NULL, &dwValueType,
|
|
(LPBYTE) szValue, pcbValue) != ERROR_SUCCESS)
|
|
{
|
|
CloseHandle(hKey);
|
|
return FALSE;
|
|
}
|
|
|
|
// Close registry handle and return success
|
|
CloseHandle(hKey);
|
|
return TRUE;
|
|
}
|