467 lines
14 KiB
C
467 lines
14 KiB
C
/*++
|
||
|
||
Copyright (c) 1992-1993 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
dbgctrl.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the NtDebugControl service
|
||
|
||
Author:
|
||
|
||
Chuck Lenzmeier (chuckl) 2-Dec-1992
|
||
|
||
Environment:
|
||
|
||
Kernel mode only.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "exp.h"
|
||
|
||
#pragma hdrstop
|
||
#include "kdp.h"
|
||
|
||
#if defined(ALLOC_PRAGMA)
|
||
#pragma alloc_text(PAGE, NtSystemDebugControl)
|
||
#endif
|
||
|
||
|
||
NTSTATUS
|
||
NtSystemDebugControl (
|
||
IN SYSDBG_COMMAND Command,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength,
|
||
OUT PVOID OutputBuffer,
|
||
IN ULONG OutputBufferLength,
|
||
OUT PULONG ReturnLength OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function controls the system debugger.
|
||
|
||
Arguments:
|
||
|
||
Command - The command to be executed. One of the following:
|
||
|
||
SysDbgQueryTraceInformation
|
||
SysDbgSetTracepoint
|
||
SysDbgSetSpecialCall
|
||
SysDbgClearSpecialCalls
|
||
SysDbgQuerySpecialCalls
|
||
|
||
InputBuffer - A pointer to a buffer describing the input data for
|
||
the request, if any. The structure of this buffer varies
|
||
depending upon Command.
|
||
|
||
InputBufferLength - The length in bytes of InputBuffer.
|
||
|
||
OutputBuffer - A pointer to a buffer that is to receive the output
|
||
data for the request, if any. The structure of this buffer
|
||
varies depending upon Command.
|
||
|
||
OutputBufferLength - The length in bytes of OutputBuffer.
|
||
|
||
ReturnLength - A optional pointer to a ULONG that is to receive the
|
||
output data length for the request.
|
||
|
||
Return Value:
|
||
|
||
Returns one of the following status codes:
|
||
|
||
STATUS_SUCCESS - normal, successful completion.
|
||
|
||
STATUS_INVALID_INFO_CLASS - The Command parameter did not
|
||
specify a valid value.
|
||
|
||
STATUS_INFO_LENGTH_MISMATCH - The value of the Length field in the
|
||
Parameters buffer was not correct.
|
||
|
||
STATUS_ACCESS_VIOLATION - Either the Parameters buffer pointer
|
||
or a pointer within the Parameters buffer specified an
|
||
invalid address.
|
||
|
||
STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
|
||
for this request to complete.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
ULONG length = 0;
|
||
KPROCESSOR_MODE PreviousMode;
|
||
PVOID LockedBuffer = NULL;
|
||
PVOID LockVariable = NULL;
|
||
|
||
PreviousMode = KeGetPreviousMode();
|
||
|
||
if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode)) {
|
||
return STATUS_ACCESS_DENIED;
|
||
}
|
||
|
||
//
|
||
// Operate within a try block in order to catch errors.
|
||
//
|
||
|
||
try {
|
||
|
||
//
|
||
// Probe input and output buffers, if previous mode is not
|
||
// kernel.
|
||
//
|
||
|
||
if ( PreviousMode != KernelMode ) {
|
||
|
||
if ( InputBufferLength != 0 ) {
|
||
ProbeForRead( InputBuffer, InputBufferLength, sizeof(ULONG) );
|
||
}
|
||
|
||
if ( OutputBufferLength != 0 ) {
|
||
ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof(ULONG) );
|
||
}
|
||
|
||
if ( ARGUMENT_PRESENT(ReturnLength) ) {
|
||
ProbeForWriteUlong( ReturnLength );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Switch on the command code.
|
||
//
|
||
|
||
switch ( Command ) {
|
||
|
||
#if i386
|
||
|
||
case SysDbgQueryTraceInformation:
|
||
|
||
status = KdGetTraceInformation(
|
||
OutputBuffer,
|
||
OutputBufferLength,
|
||
&length
|
||
);
|
||
|
||
break;
|
||
|
||
case SysDbgSetTracepoint:
|
||
|
||
if ( InputBufferLength != sizeof(DBGKD_MANIPULATE_STATE64) ) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
KdSetInternalBreakpoint( InputBuffer );
|
||
|
||
break;
|
||
|
||
case SysDbgSetSpecialCall:
|
||
|
||
if ( InputBufferLength != sizeof(PVOID) ) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
KdSetSpecialCall( InputBuffer, NULL );
|
||
|
||
break;
|
||
|
||
case SysDbgClearSpecialCalls:
|
||
|
||
KdClearSpecialCalls( );
|
||
|
||
break;
|
||
|
||
case SysDbgQuerySpecialCalls:
|
||
|
||
status = KdQuerySpecialCalls(
|
||
OutputBuffer,
|
||
OutputBufferLength,
|
||
&length
|
||
);
|
||
|
||
break;
|
||
|
||
#endif
|
||
|
||
case SysDbgBreakPoint:
|
||
if (KdDebuggerEnabled) {
|
||
DbgBreakPointWithStatus(DBG_STATUS_DEBUG_CONTROL);
|
||
} else {
|
||
status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
break;
|
||
|
||
case SysDbgQueryVersion:
|
||
if (OutputBufferLength != sizeof(DBGKD_GET_VERSION64)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
KdpSysGetVersion((PDBGKD_GET_VERSION64)OutputBuffer);
|
||
status = STATUS_SUCCESS;
|
||
break;
|
||
|
||
case SysDbgReadVirtual:
|
||
if (InputBufferLength != sizeof(SYSDBG_VIRTUAL)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_VIRTUAL Cmd = (PSYSDBG_VIRTUAL)InputBuffer;
|
||
|
||
status = ExLockUserBuffer(Cmd->Buffer,
|
||
Cmd->Request,
|
||
&LockedBuffer,
|
||
&LockVariable);
|
||
if (!NT_SUCCESS(status)) {
|
||
break;
|
||
}
|
||
|
||
status = KdpCopyMemoryChunks((ULONG_PTR)Cmd->Address,
|
||
LockedBuffer,
|
||
Cmd->Request, 0,
|
||
0,
|
||
&length);
|
||
}
|
||
break;
|
||
|
||
case SysDbgWriteVirtual:
|
||
if (InputBufferLength != sizeof(SYSDBG_VIRTUAL)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_VIRTUAL Cmd = (PSYSDBG_VIRTUAL)InputBuffer;
|
||
|
||
status = ExLockUserBuffer(Cmd->Buffer,
|
||
Cmd->Request,
|
||
&LockedBuffer,
|
||
&LockVariable);
|
||
if (!NT_SUCCESS(status)) {
|
||
break;
|
||
}
|
||
|
||
status = KdpCopyMemoryChunks((ULONG_PTR)Cmd->Address,
|
||
LockedBuffer,
|
||
Cmd->Request, 0,
|
||
MMDBG_COPY_WRITE,
|
||
&length);
|
||
}
|
||
break;
|
||
|
||
case SysDbgReadPhysical:
|
||
if (InputBufferLength != sizeof(SYSDBG_PHYSICAL)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_PHYSICAL Cmd = (PSYSDBG_PHYSICAL)InputBuffer;
|
||
|
||
status = ExLockUserBuffer(Cmd->Buffer,
|
||
Cmd->Request,
|
||
&LockedBuffer,
|
||
&LockVariable);
|
||
if (!NT_SUCCESS(status)) {
|
||
break;
|
||
}
|
||
|
||
status = KdpCopyMemoryChunks(Cmd->Address.QuadPart,
|
||
LockedBuffer,
|
||
Cmd->Request, 0,
|
||
MMDBG_COPY_PHYSICAL,
|
||
&length);
|
||
}
|
||
break;
|
||
|
||
case SysDbgWritePhysical:
|
||
if (InputBufferLength != sizeof(SYSDBG_PHYSICAL)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_PHYSICAL Cmd = (PSYSDBG_PHYSICAL)InputBuffer;
|
||
|
||
status = ExLockUserBuffer(Cmd->Buffer,
|
||
Cmd->Request,
|
||
&LockedBuffer,
|
||
&LockVariable);
|
||
if (!NT_SUCCESS(status)) {
|
||
break;
|
||
}
|
||
|
||
status = KdpCopyMemoryChunks(Cmd->Address.QuadPart,
|
||
LockedBuffer,
|
||
Cmd->Request, 0,
|
||
MMDBG_COPY_WRITE |
|
||
MMDBG_COPY_PHYSICAL,
|
||
&length);
|
||
}
|
||
break;
|
||
|
||
case SysDbgReadControlSpace:
|
||
if (InputBufferLength != sizeof(SYSDBG_CONTROL_SPACE)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_CONTROL_SPACE Cmd = (PSYSDBG_CONTROL_SPACE)InputBuffer;
|
||
|
||
status = ExLockUserBuffer(Cmd->Buffer,
|
||
Cmd->Request,
|
||
&LockedBuffer,
|
||
&LockVariable);
|
||
if (!NT_SUCCESS(status)) {
|
||
break;
|
||
}
|
||
|
||
status = KdpSysReadControlSpace(Cmd->Processor,
|
||
Cmd->Address, LockedBuffer,
|
||
Cmd->Request, &length);
|
||
}
|
||
break;
|
||
|
||
case SysDbgWriteControlSpace:
|
||
if (InputBufferLength != sizeof(SYSDBG_CONTROL_SPACE)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_CONTROL_SPACE Cmd = (PSYSDBG_CONTROL_SPACE)InputBuffer;
|
||
|
||
status = ExLockUserBuffer(Cmd->Buffer,
|
||
Cmd->Request,
|
||
&LockedBuffer,
|
||
&LockVariable);
|
||
if (!NT_SUCCESS(status)) {
|
||
break;
|
||
}
|
||
|
||
status = KdpSysWriteControlSpace(Cmd->Processor,
|
||
Cmd->Address, LockedBuffer,
|
||
Cmd->Request, &length);
|
||
}
|
||
break;
|
||
|
||
case SysDbgReadIoSpace:
|
||
if (InputBufferLength != sizeof(SYSDBG_IO_SPACE)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_IO_SPACE Cmd = (PSYSDBG_IO_SPACE)InputBuffer;
|
||
|
||
status = KdpSysReadIoSpace(Cmd->InterfaceType,
|
||
Cmd->BusNumber,
|
||
Cmd->AddressSpace,
|
||
Cmd->Address, Cmd->Buffer,
|
||
Cmd->Request, &length);
|
||
}
|
||
break;
|
||
|
||
case SysDbgWriteIoSpace:
|
||
if (InputBufferLength != sizeof(SYSDBG_IO_SPACE)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_IO_SPACE Cmd = (PSYSDBG_IO_SPACE)InputBuffer;
|
||
|
||
status = KdpSysWriteIoSpace(Cmd->InterfaceType,
|
||
Cmd->BusNumber,
|
||
Cmd->AddressSpace,
|
||
Cmd->Address, Cmd->Buffer,
|
||
Cmd->Request, &length);
|
||
}
|
||
break;
|
||
|
||
case SysDbgReadMsr:
|
||
if (InputBufferLength != sizeof(SYSDBG_MSR)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_MSR Cmd = (PSYSDBG_MSR)InputBuffer;
|
||
|
||
status = KdpSysReadMsr(Cmd->Msr, &Cmd->Data);
|
||
}
|
||
break;
|
||
|
||
case SysDbgWriteMsr:
|
||
if (InputBufferLength != sizeof(SYSDBG_MSR)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_MSR Cmd = (PSYSDBG_MSR)InputBuffer;
|
||
|
||
status = KdpSysWriteMsr(Cmd->Msr, &Cmd->Data);
|
||
}
|
||
break;
|
||
|
||
case SysDbgReadBusData:
|
||
if (InputBufferLength != sizeof(SYSDBG_BUS_DATA)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_BUS_DATA Cmd = (PSYSDBG_BUS_DATA)InputBuffer;
|
||
|
||
status = KdpSysReadBusData(Cmd->BusDataType,
|
||
Cmd->BusNumber, Cmd->SlotNumber,
|
||
Cmd->Address, Cmd->Buffer,
|
||
Cmd->Request, &length);
|
||
}
|
||
break;
|
||
|
||
case SysDbgWriteBusData:
|
||
if (InputBufferLength != sizeof(SYSDBG_BUS_DATA)) {
|
||
return STATUS_INFO_LENGTH_MISMATCH;
|
||
}
|
||
|
||
{
|
||
PSYSDBG_BUS_DATA Cmd = (PSYSDBG_BUS_DATA)InputBuffer;
|
||
|
||
status = KdpSysWriteBusData(Cmd->BusDataType,
|
||
Cmd->BusNumber, Cmd->SlotNumber,
|
||
Cmd->Address, Cmd->Buffer,
|
||
Cmd->Request, &length);
|
||
}
|
||
break;
|
||
|
||
case SysDbgCheckLowMemory:
|
||
status = KdpSysCheckLowMemory();
|
||
break;
|
||
|
||
default:
|
||
|
||
//
|
||
// Invalid Command.
|
||
//
|
||
|
||
status = STATUS_INVALID_INFO_CLASS;
|
||
}
|
||
|
||
if ( ARGUMENT_PRESENT(ReturnLength) ) {
|
||
*ReturnLength = length;
|
||
}
|
||
}
|
||
|
||
except ( EXCEPTION_EXECUTE_HANDLER ) {
|
||
|
||
status = GetExceptionCode();
|
||
|
||
}
|
||
|
||
if (LockedBuffer) {
|
||
ExUnlockUserBuffer(LockVariable);
|
||
}
|
||
|
||
return status;
|
||
|
||
} // NtSystemDebugControl
|