467 lines
11 KiB
C
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
|