windows-nt/Source/XPSP1/NT/net/rras/ndis/raspptp/nt/dbgapi.c
2020-09-26 16:20:57 +08:00

467 lines
11 KiB
C

/*****************************************************************************
*
* Copyright (c) 1998-1999 Microsoft Corporation
*
* DBGAPI.C - NT specific debugging macros, etc.
*
* Author: Stan Adermann (stana)
*
* Created: 9/3/1998
*
*****************************************************************************/
#if DBG
#include "raspptp.h"
#include <ntddk.h>
#include <cxport.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "dbgapi.h"
#define UNICODE_STRING_CONST(x) {sizeof(L##x)-2, sizeof(L##x), L##x}
ULONG DbgSettings = 0;
ULONG DbgOutput = DBG_OUTPUT_BUFFER;
CHAR DbgMsgs[DBG_MSG_CNT][MAX_MSG_LEN];
ULONG First, Last;
CTETimer DbgTimer;
BOOLEAN TimerRunning;
CTELock DbgLock;
PIRP pDbgIrp;
UCHAR *IrpBuf;
ULONG IrpBufLen;
ULONG IrpBufWritten;
UCHAR CharTable[256];
VOID DbgTimerExp(CTEEvent *Event, void *Arg);
VOID
DbgMsgInit()
{
ULONG i;
pDbgIrp = NULL;
First = 0;
Last = 0;
TimerRunning = FALSE;
for (i=0; i<256; i++)
{
CharTable[i] = (UCHAR)((i>=' ') ? i : '.');
}
CharTable[0xfe] = '.'; // Debugger seems to get stuck when we print this.
CTEInitLock(&DbgLock);
CTEInitTimer(&DbgTimer);
}
VOID
DbgMsgUninit()
{
CTELockHandle LockHandle;
KIRQL Irql;
CTEGetLock(&DbgLock, &LockHandle);
if (pDbgIrp)
{
IoAcquireCancelSpinLock(&Irql);
IoSetCancelRoutine(pDbgIrp, NULL);
IoReleaseCancelSpinLock(Irql);
pDbgIrp->IoStatus.Information = 0;
pDbgIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
DbgPrint("Complete irp!\n");
IoCompleteRequest(pDbgIrp, IO_NO_INCREMENT);
pDbgIrp = NULL;
}
CTEFreeLock(&DbgLock, LockHandle);
}
VOID
DbgMsg(CHAR *Format, ...)
{
va_list Args;
CTELockHandle LockHandle;
CHAR Temp[MAX_MSG_LEN];
va_start(Args, Format);
vsprintf(Temp, Format, Args);
if (DbgOutput & DBG_OUTPUT_DEBUGGER)
{
DbgPrint("RASPPTP: ");
DbgPrint(Temp);
}
if (DbgOutput & DBG_OUTPUT_BUFFER)
{
CTEGetLock(&DbgLock, &LockHandle);
strcpy(DbgMsgs[Last], Temp);
Last++;
if (Last == DBG_MSG_CNT)
Last = 0;
if (First == Last)
{
First++;
if (First == DBG_MSG_CNT)
First = 0;
}
if (pDbgIrp && !TimerRunning)
{
CTEStartTimer(&DbgTimer, DBG_TIMER_INTERVAL,
DbgTimerExp, NULL);
TimerRunning = TRUE;
}
CTEFreeLock(&DbgLock, LockHandle);
}
va_end(Args);
}
NTSTATUS
FillDbgIrp(UCHAR Msg[])
{
NTSTATUS Status = STATUS_PENDING;
ULONG i;
if ((IrpBufLen - IrpBufWritten) < MAX_MSG_LEN)
{
Status = STATUS_SUCCESS;
}
else
{
Msg[MAX_MSG_LEN - 1] = 0; // just to be sure
i = 0;
while (1)
{
IrpBuf[IrpBufWritten++] = Msg[i];
if (Msg[i] == 0)
break;
i++;
}
}
return Status;
}
VOID CancelDbgIrp(
PDEVICE_OBJECT DeviceObject,
PIRP pIrp)
{
// DbgPrint("CancelDbgIrp %x\n", pIrp);
pDbgIrp = NULL;
IoReleaseCancelSpinLock(pIrp->CancelIrql);
pIrp->IoStatus.Status = STATUS_CANCELLED;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
}
NTSTATUS
DbgMsgIrp(
PIRP pIrp,
PIO_STACK_LOCATION pIrpSp)
{
CTELockHandle LockHandle;
NTSTATUS Status = STATUS_PENDING;
if (pDbgIrp != NULL)
return STATUS_DEVICE_BUSY;
CTEGetLock(&DbgLock, &LockHandle);
IrpBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
IrpBufWritten = 0;
if (IrpBufLen < MAX_MSG_LEN)
{
CTEFreeLock(&DbgLock, LockHandle);
return STATUS_BUFFER_OVERFLOW;
}
IrpBuf = pIrp->AssociatedIrp.SystemBuffer;
while (First != Last)
{
Status = FillDbgIrp(DbgMsgs[First]);
if (Status == STATUS_SUCCESS)
break;
First++;
if (First == DBG_MSG_CNT)
First = 0;
}
if (Status == STATUS_SUCCESS)
{
pIrp->IoStatus.Information = IrpBufWritten;
}
else if (Status == STATUS_PENDING)
{
KIRQL Irql;
PDRIVER_CANCEL PrevCancel;
pDbgIrp = pIrp;
IoMarkIrpPending(pIrp);
IoAcquireCancelSpinLock(&Irql);
PrevCancel = IoSetCancelRoutine(pIrp, CancelDbgIrp);
CTEAssert(PrevCancel == NULL);
IoReleaseCancelSpinLock(Irql);
if (IrpBufWritten != 0)
{
CTEStartTimer(&DbgTimer, DBG_TIMER_INTERVAL,
DbgTimerExp, NULL);
TimerRunning = TRUE;
}
}
CTEFreeLock(&DbgLock, LockHandle);
//DbgPrint("DbgIrp status %x, bw %d, irp %x\n", Status, IrpBufWritten, pIrp);
return Status;
}
VOID
DbgTimerExp(CTEEvent *Event, void *Arg)
{
CTELockHandle LockHandle;
PIRP pIrp;
KIRQL Irql;
//DbgPrint("Texp\n");
if (pDbgIrp == NULL)
{
DbgPrint("DbgIrp is null\n");
return;
}
IoAcquireCancelSpinLock(&Irql);
IoSetCancelRoutine(pDbgIrp, NULL);
IoReleaseCancelSpinLock(Irql);
if (pDbgIrp->Cancel)
{
DbgPrint("DbgIrp is being canceled\n");
pDbgIrp = NULL;
return;
}
CTEGetLock(&DbgLock, &LockHandle);
TimerRunning = FALSE;
while (First != Last)
{
if (FillDbgIrp(DbgMsgs[First]) == STATUS_SUCCESS)
break;
First++;
if (First == DBG_MSG_CNT)
First = 0;
}
pIrp = pDbgIrp;
pDbgIrp = NULL;
CTEFreeLock(&DbgLock, LockHandle);
pIrp->IoStatus.Information = IrpBufWritten;
pIrp->IoStatus.Status = STATUS_SUCCESS;
// DbgPrint("Comp bw %d, irp %x\n", IrpBufWritten, pIrp);
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
}
VOID DbgMemory(PVOID pMemory, ULONG Length, ULONG WordSize)
{
ULONG i, j;
UCHAR AsciiData[17];
for (i=0; i<Length; )
{
DbgMsg("%08x: ", pMemory);
for (j=0; j<16 && i+j<Length; j++)
{
AsciiData[j] = CharTable[((PUCHAR)pMemory)[j]];
}
AsciiData[j] = '\0';
for (j=0; j<16; j+=WordSize, i+=WordSize)
{
if (i<Length)
{
switch (WordSize)
{
case 1:
DbgMsg("%02x ", *(PUCHAR)pMemory);
break;
case 2:
DbgMsg("%04x ", *(PUSHORT)pMemory);
break;
case 4:
DbgMsg("%08x ", *(PULONG)pMemory);
break;
}
}
else
{
DbgMsg("%*s ", WordSize*2, "");
}
pMemory = (PUCHAR)pMemory + WordSize;
}
DbgMsg(" %s\n", AsciiData);
}
}
VOID DbgRegInit(PUNICODE_STRING pRegistryPath, ULONG DefaultDebug)
{
struct {
KEY_VALUE_PARTIAL_INFORMATION Value;
ULONG_PTR Filler;
} DwordValue;
ULONG InformationLength;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hReg;
NTSTATUS Status;
UNICODE_STRING DbgSettingsString = UNICODE_STRING_CONST("DbgSettings");
UNICODE_STRING DbgOutputString = UNICODE_STRING_CONST("DbgOutput");
UNICODE_STRING PromptString = UNICODE_STRING_CONST("Prompt");
InitializeObjectAttributes(&ObjectAttributes,
pRegistryPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(&hReg, MAXIMUM_ALLOWED, &ObjectAttributes);
if (Status==STATUS_SUCCESS)
{
Status = ZwQueryValueKey(hReg,
&DbgSettingsString,
KeyValuePartialInformation,
&DwordValue,
sizeof(DwordValue),
&InformationLength);
if (Status==STATUS_SUCCESS)
{
DbgSettings = *(PULONG)DwordValue.Value.Data;
}
else
{
DbgSettings = DefaultDebug;
}
Status = ZwQueryValueKey(hReg,
&DbgOutputString,
KeyValuePartialInformation,
&DwordValue,
sizeof(DwordValue),
&InformationLength);
if (Status==STATUS_SUCCESS)
{
DbgOutput = *(PULONG)DwordValue.Value.Data;
}
Status = ZwQueryValueKey(hReg,
&PromptString,
KeyValuePartialInformation,
&DwordValue,
sizeof(DwordValue),
&InformationLength);
if (Status==STATUS_SUCCESS && DwordValue.Value.Data[0])
{
char Response[2];
BOOLEAN ValidChar;
extern ULONG AbortLoad;
extern ULONG
DbgPrompt(
IN PCHAR Prompt,
OUT PCHAR Response,
IN ULONG MaximumResponseLength
);
do
{
ValidChar = TRUE;
DbgPrompt("RASPPTP: Debugging: Full, Default, Minimal, Abort load, Break (FDMAB)? ",
Response, sizeof(Response));
switch (Response[0])
{
case 'A': case 'a':
AbortLoad = TRUE;
break;
case 'B': case 'b':
DbgBreakPoint();
break;
case 'M': case 'm':
DbgSettings = DBG_ERROR|DBG_WARN;
break;
case 'D': case 'd':
// Default already set. Leave untouched.
break;
case 'F': case 'f':
DbgSettings =
DBG_ERROR |
DBG_WARN |
DBG_FUNC |
DBG_INIT |
DBG_TX |
DBG_RX |
DBG_TDI |
DBG_TUNNEL |
DBG_CALL |
DBG_NDIS |
DBG_TAPI |
DBG_THREAD |
DBG_REF |
0;
break;
default:
ValidChar = FALSE;
break;
}
} while ( !ValidChar );
}
ZwClose(hReg);
}
}
#endif