WindowsXP-SP1/windows/core/ntcon/exts/stdext64.c
2020-09-30 16:53:49 +02:00

502 lines
12 KiB
C

/****************************** Module Header ******************************\
* Module Name: stdexts.c
*
* Copyright (c) 1995-1998, Microsoft Corporation
*
* This module contains standard routines for creating sane debuging extensions.
* It is meant to be included after stdexts.h in one of the files comprising
* the debug extsnsions for a given product or module.
*
* History:
* 11-Apr-1995 Sanfords Created
\***************************************************************************/
#include <stdext64.h>
HANDLE hCurrentProcess;
HANDLE hCurrentThread;
ULONG64 dwCurrentPc;
WINDBG_EXTENSION_APIS *lpExtensionApis;
DWORD dwProcessor;
PSTR pszAccessViolation = "%s: Access violation on \"%s\".\n";
PSTR pszMoveException = "%s: exception in moveBlock()\n";
PSTR pszReadFailure = "%s: lpReadProcessMemoryRoutine failed!\n";
PSTR pszCantContinue = "%s: Non-continuable exception.\n";
BOOL fCtrlCHit = FALSE;
/*
* This function returns TRUE once the user has hit a Ctrl-C.
* This allows proper operation of nested SAFEWHILE loops so
* that all levels exit.
*
* The globall fCtrlCHit flag needs to be reset manually and
* is done so in the CommandEP function.
*/
BOOL IsCtrlCHit(
VOID)
{
if ((lpExtensionApis->lpCheckControlCRoutine)()) {
fCtrlCHit = TRUE;
}
return fCtrlCHit;
}
VOID moveBlock(
PVOID pdst,
ULONG64 src,
DWORD size)
{
BOOL fSuccess = TRUE;
ULONG Result;
try {
if (IsWinDbg()) {
if (!ReadMem(src, pdst, size, &Result)) {
fSuccess = FALSE;
}
} else {
if (!NT_SUCCESS(NtReadVirtualMemory(hCurrentProcess,
(PVOID)src, pdst, size, NULL))) {
fSuccess = FALSE;
}
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Print(pszMoveException, pszExtName);
fSuccess = FALSE;
}
if (!fSuccess) {
DEBUGPRINT("%s: moveBlock(%p, %p, %x) failed.\n",
pszExtName, pdst, src, size);
OUTAHERE();
}
}
BOOL tryMoveBlock(
PVOID pdst,
ULONG64 src,
DWORD size)
{
BOOL fSuccess = TRUE;
ULONG Result;
try {
if (IsWinDbg()) {
if (!ReadMem(src, pdst, size, &Result)) {
DEBUGPRINT("%s: tryMoveBlock(%p, %p, %x) failed.\n", pszExtName, pdst, src, size);
fSuccess = FALSE;
}
} else {
if (!NT_SUCCESS(NtReadVirtualMemory(hCurrentProcess, (PVOID)src, pdst, size, NULL))) {
DEBUGPRINT("%s: tryMoveBlock(%p, %p, %x) failed.\n", pszExtName, pdst, src, size);
fSuccess = FALSE;
}
}
} except (EXCEPTION_EXECUTE_HANDLER) {
DEBUGPRINT("%s: tryMoveBlock(%p, %p, %x) faulted.\n", pszExtName, pdst, src, size);
fSuccess = FALSE;
}
return fSuccess;
}
VOID moveExp(
PULONG64 pdst,
LPSTR pszExp)
{
BOOL fSuccess = TRUE;
try {
*pdst = EvalExp(pszExp);
} except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Print(pszAccessViolation, pszExtName, pszExp);
fSuccess = FALSE;
}
if (!fSuccess) {
Print("%s: moveExp failed on %s.\n", pszExtName, pszExp);
OUTAHERE();
}
}
BOOL tryMoveExp(
PULONG64 pdst,
LPSTR pszExp)
{
BOOL fSuccess = TRUE;
try {
*pdst = EvalExp(pszExp);
} except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Print(pszAccessViolation, pszExtName, pszExp);
DEBUGPRINT("%s: tryMoveExp(%p, %s) faulted.\n", pszExtName, pdst, pszExp);
fSuccess = FALSE;
}
return fSuccess;
}
VOID moveExpValue(
PVOID pdst,
LPSTR pszExp)
{
DWORD dw;
ULONG64 addr;
if (tryMoveExp(&addr, pszExp)) {
if (tryMoveBlock(&dw, addr, sizeof(DWORD))) {
*((PDWORD)pdst) = dw;
return;
}
}
Print("%s: moveExpValue failed on %s.\n", pszExtName, pszExp);
OUTAHERE();
}
BOOL tryMoveExpValue(
PVOID pdst,
LPSTR pszExp)
{
DWORD dw;
ULONG64 addr;
if (tryMoveExp(&addr, pszExp)) {
if (tryMove(dw, addr)) {
*((PDWORD)pdst) = dw;
return TRUE;
}
}
DEBUGPRINT("%s: tryMoveExpValue failed on %s.\n", pszExtName, pszExp);
return FALSE;
}
BOOL tryMoveExpPtr(
PULONG64 pdst,
LPSTR pszExp)
{
BOOL fSuccess = TRUE;
try {
*pdst = EvalExp(pszExp);
} except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Print(pszAccessViolation, pszExtName, pszExp);
DEBUGPRINT("%s: tryMoveExpPtr(%p, %s) faulted.\n", pszExtName, pdst, pszExp);
fSuccess = FALSE;
}
return fSuccess;
}
VOID moveExpValuePtr(
PULONG64 pdst,
LPSTR pszExp)
{
ULONG64 dw;
if (tryMoveExpPtr(&dw, pszExp)) {
if (tryMoveBlock(&dw, dw, sizeof(dw))) {
*pdst = dw;
return;
}
}
Print("%s: moveExpValue failed on %s.\n", pszExtName, pszExp);
OUTAHERE();
}
ULONG64 EvalExp(
LPSTR psz)
{
ULONG64 p;
p = (lpExtensionApis->lpGetExpressionRoutine)(psz);
if (p == 0) {
Print("%s: EvalExp failed to evaluate %s.\n", pszExtName, psz);
}
return p;
}
ULONG64 OptEvalExp(
LPSTR psz)
{
while (*psz == ' ') {
psz++;
}
if (*psz == '\0') {
return 0;
}
return EvalExp(psz);
}
ULONG64 OptEvalExp2(
LPSTR *ppsz)
{
LPSTR psz = *ppsz;
ULONG64 dwRet = 0;
while (*psz == ' ') {
psz++;
}
if (*psz != '\0') {
dwRet = EvalExp(psz);
while (*psz != '\0' && *psz != ' ') {
psz++;
}
}
*ppsz = psz;
return dwRet;
}
DWORD StringToOpts(
LPSTR psz)
{
DWORD opts = 0;
while (*psz != '\0' && *psz != ' ') {
if (*psz >= 'a' && *psz <= 'z') {
opts |= 1 << (*psz - 'a');
} else if (*psz >= 'A' && *psz <= 'Z') {
opts |= 1 << (*psz - 'A');
} else {
return OPTS_ERROR; // any non-letter option is an error.
}
psz++;
}
return opts;
}
/*
* Function to convert an option string to a DWORD of flags. pszLegalArgs
* is used to allow option validation at the same time.
*
* *ppszArgs is set to point to after the options on exit.
* On error, returns OPTS_ERROR.
*/
DWORD GetOpts(
LPSTR *ppszArgs,
LPSTR pszLegalArgs OPTIONAL)
{
DWORD Opts = 0;
LPSTR pszArgs = *ppszArgs;
/*
* Skip whitespace
*/
while (*pszArgs == ' ') {
pszArgs++;
}
/*
* process '-' prepended options.
*/
while (*pszArgs == '-') {
pszArgs++;
Opts = StringToOpts(pszArgs);
/*
* skip to whitespace or end.
*/
while (*pszArgs != '\0' && *pszArgs != ' ') {
pszArgs++;
}
/*
* skip trailing whitespace.
*/
while (*pszArgs == ' ') {
pszArgs++;
}
*ppszArgs = pszArgs;
/*
* optionally validate against LegalArgs
*/
if (pszLegalArgs != NULL && ((Opts & StringToOpts(pszLegalArgs)) != Opts)) {
Opts = OPTS_ERROR;
Print("Bad options.\n");
return Opts;
}
}
return Opts;
}
/*
* Dispatcher function used by generated entrypoint functions.
*/
VOID CommonEP(
PVOID pFunction,
LPSTR pszName,
int type,
LPSTR pszLegalOpts,
HANDLE hcp,
HANDLE hct,
ULONG64 dwcp,
DWORD dwp,
LPSTR lpas)
{
BOOL dwOptions, fSuccess;
ULONG64 param1, param2, param3;
hCurrentProcess = hcp;
hCurrentThread = hct;
dwCurrentPc = dwcp;
dwProcessor = dwp;
lpExtensionApis = &ExtensionApis;
fCtrlCHit = FALSE; // reset this with each command. (SAFEWHILE fix)
switch (type) {
case NOARGS:
fSuccess = ((TYPE_NOARGS)pFunction)();
goto Exit;
}
dwOptions = GetOpts(&lpas, pszLegalOpts);
if (dwOptions == OPTS_ERROR) {
fSuccess = Ihelp(0, pszName);
goto Exit;
}
try {
switch (type) {
case CUSTOM:
fSuccess = ((TYPE_CUSTOM)pFunction)(dwOptions, lpas);
break;
case STDARGS0:
fSuccess = ((TYPE_STDARGS0)pFunction)(dwOptions);
break;
case STDARGS1:
fSuccess = ((TYPE_STDARGS1)pFunction)(dwOptions, OptEvalExp(lpas));
break;
case STDARGS2:
param1 = OptEvalExp2(&lpas);
fSuccess = ((TYPE_STDARGS2)pFunction)(dwOptions, param1, OptEvalExp(lpas));
break;
case STDARGS3:
param1 = OptEvalExp2(&lpas);
param2 = OptEvalExp2(&lpas);
fSuccess = ((TYPE_STDARGS3)pFunction)(dwOptions, param1, param2, OptEvalExp(lpas));
break;
case STDARGS4:
param1 = OptEvalExp2(&lpas);
param2 = OptEvalExp2(&lpas);
param3 = OptEvalExp2(&lpas);
fSuccess = ((TYPE_STDARGS4)pFunction)(dwOptions, param1, param2, param3, OptEvalExp(lpas));
break;
default:
Print("CommonEP: Don't recognize function type %d.\n", type);
break;
}
} except (GetExceptionCode() == STATUS_NONCONTINUABLE_EXCEPTION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Print(pszCantContinue, pszExtName);
}
Exit:
if (!fSuccess) {
Print("%s failed.\n", pszName);
Ihelp(0, pszName);
}
}
/*
* Entrypoint functions (generated from exts.h)
*/
#define DOIT(name, h1, h2, opts, type) \
VOID name##( \
HANDLE hcp, \
HANDLE hct, \
ULONG64 dwcp, \
DWORD dwp, \
LPSTR lpas) \
{ \
CommonEP(I##name, #name, type, opts, hcp, hct, dwcp, dwp, lpas); \
}
#include "exts.h"
#undef DOIT
/*
* Standard help extension - present in all standard extensions.
*/
BOOL Ihelp(
DWORD opts,
LPSTR lpas)
{
#define DOIT(name, help1, help2, opts, type) { #name, help1, help2 },
static struct {
LPSTR pszCmdName;
LPSTR pszHelp1;
LPSTR pszHelp2;
} he[] = {
#include "exts.h"
};
#undef DOIT
int i;
while (*lpas == ' ') {
lpas++;
}
if (*lpas == '\0') {
Print("-------------- %s Debug Extension help:--------------\n\n", pszExtName);
for (i = 0; i < sizeof(he) / sizeof(he[0]); i++) {
if (IsCtrlCHit()) {
break;
}
Print(he[i].pszHelp1);
if (opts & OFLAG(v)) {
Print(he[i].pszHelp2);
}
}
return TRUE;
} else {
for (i = 0; i < sizeof(he) / sizeof(he[0]); i++) {
if (IsCtrlCHit()) {
break;
}
if (strcmp(lpas, he[i].pszCmdName) == 0) {
Print(he[i].pszHelp1);
Print(he[i].pszHelp2);
return TRUE;
}
}
Print("%s is not supported.\n", lpas);
}
return FALSE;
}