401 lines
11 KiB
C
401 lines
11 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
event.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the event handling routines for SAC.
|
||
|
||
Author:
|
||
|
||
Sean Selitrennikoff (v-seans) - Jan 22, 1999
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "sac.h"
|
||
|
||
//
|
||
// Definitions for this file.
|
||
//
|
||
|
||
#define RESPONSE_BUFFER_SIZE (80 + sizeof(HEADLESS_RSP_GET_LINE) - sizeof(UCHAR))
|
||
UCHAR ResponseBuffer[RESPONSE_BUFFER_SIZE];
|
||
|
||
//
|
||
// Forward declarations for this file.
|
||
//
|
||
VOID
|
||
ProcessInputLine(
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
WorkerProcessEvents(
|
||
IN PSAC_DEVICE_CONTEXT DeviceContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the routine for the worker thread. It blocks on an event, when
|
||
the event is signalled, then that indicates a request is ready to be processed.
|
||
|
||
Arguments:
|
||
|
||
DeviceContext - A pointer to this device.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
KIRQL OldIrql;
|
||
|
||
IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC WorkerProcessEvents: Entering.\n")));
|
||
|
||
//
|
||
// Loop forever.
|
||
//
|
||
while (1) {
|
||
|
||
//
|
||
// Block until there is work to do.
|
||
//
|
||
Status = KeWaitForSingleObject((PVOID)&(DeviceContext->ProcessEvent), Executive, KernelMode, FALSE, NULL);
|
||
|
||
if (DeviceContext->UnloadDeferred) {
|
||
CancelIPIoRequest();
|
||
SacPutSimpleMessage(SAC_ENTER);
|
||
SacPutSimpleMessage(SAC_UNLOADED);
|
||
SacPutSimpleMessage(SAC_ENTER);
|
||
KeSetEvent(&(DeviceContext->UnloadEvent), DeviceContext->PriorityBoost, FALSE);
|
||
IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC WorkerProcessEvents: Terminating.\n")));
|
||
PsTerminateSystemThread(STATUS_SUCCESS);
|
||
}
|
||
switch ( ProcessingType ){
|
||
|
||
case SAC_PROCESS_INPUT:
|
||
//
|
||
// Process the input line.
|
||
//
|
||
ProcessInputLine();
|
||
|
||
//
|
||
// Put the next command prompt
|
||
//
|
||
SacPutSimpleMessage(SAC_PROMPT);
|
||
break;
|
||
|
||
case SAC_SUBMIT_IOCTL:
|
||
if ( !IoctlSubmitted ) {
|
||
// submit the notify request with the
|
||
// IP driver. This procedure will also
|
||
// ensure that it is done only once in
|
||
// the lifetime of the driver.
|
||
SubmitIPIoRequest();
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
|
||
//
|
||
// Unset the processing flag
|
||
//
|
||
KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
|
||
|
||
DeviceContext->Processing = FALSE;
|
||
|
||
KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
|
||
|
||
//
|
||
// If there is any stuff that got delayed, process it.
|
||
//
|
||
DoDeferred(DeviceContext);
|
||
}
|
||
|
||
ASSERT(0);
|
||
}
|
||
|
||
|
||
|
||
|
||
VOID
|
||
DoDeferred(
|
||
IN PSAC_DEVICE_CONTEXT DeviceContext
|
||
)
|
||
{
|
||
IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC DoDeferred: Entering.\n")));
|
||
|
||
if (DeviceContext->UnloadDeferred) {
|
||
|
||
KeSetEvent(&(DeviceContext->UnloadEvent), DeviceContext->PriorityBoost, FALSE);
|
||
|
||
}
|
||
|
||
IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC DoDeferred: Exiting.\n")));
|
||
|
||
}
|
||
|
||
VOID
|
||
TimerDpcRoutine(
|
||
IN struct _KDPC *Dpc,
|
||
IN PVOID DeferredContext,
|
||
IN PVOID SystemArgument1,
|
||
IN PVOID SystemArgument2
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is a DPC routine that is queue'd by DriverEntry. It is used to check for any
|
||
user input and then processes them.
|
||
|
||
Arguments:
|
||
|
||
DeferredContext - A pointer to the device context.
|
||
|
||
All other parameters are unused.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PSAC_DEVICE_CONTEXT DeviceContext = (PSAC_DEVICE_CONTEXT)DeferredContext;
|
||
KIRQL OldIrql;
|
||
SIZE_T i;
|
||
PHEADLESS_RSP_GET_LINE Response;
|
||
NTSTATUS Status;
|
||
|
||
IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC TimerDpcRoutine: Entering.\n")));
|
||
|
||
UNREFERENCED_PARAMETER(Dpc);
|
||
UNREFERENCED_PARAMETER(SystemArgument1);
|
||
UNREFERENCED_PARAMETER(SystemArgument2);
|
||
|
||
KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
|
||
|
||
//
|
||
// If we are processing, then move on.
|
||
//
|
||
if (DeviceContext->Processing) {
|
||
KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
|
||
IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC TimerDpcRoutine: Exiting.\n")));
|
||
return;
|
||
}
|
||
|
||
DeviceContext->Processing = TRUE;
|
||
|
||
KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
|
||
|
||
//
|
||
// Check for user input
|
||
//
|
||
i = RESPONSE_BUFFER_SIZE;
|
||
Response = (PHEADLESS_RSP_GET_LINE)ResponseBuffer;
|
||
Status = HeadlessDispatch(HeadlessCmdGetLine,
|
||
NULL,
|
||
0,
|
||
Response,
|
||
&i
|
||
);
|
||
|
||
if (NT_SUCCESS(Status) && Response->LineComplete) {
|
||
|
||
//
|
||
// Lower case all the characters. We do not use strlwr() or the like, so that
|
||
// the SAC (expecting ASCII always) doesn't accidently get DBCS or the like
|
||
// translation of the UCHAR stream.
|
||
//
|
||
Response->Buffer[(RESPONSE_BUFFER_SIZE - sizeof(HEADLESS_RSP_GET_LINE)) / sizeof(UCHAR)] = '\0';
|
||
|
||
for (i = 0; Response->Buffer[i] != '\0'; i++) {
|
||
if ((Response->Buffer[i] >= 'A') && (Response->Buffer[i] <= 'Z')) {
|
||
Response->Buffer[i] = Response->Buffer[i] - 'A' + 'a';
|
||
}
|
||
}
|
||
|
||
//
|
||
// Fire off the worker thread to do the line. It will unset the processing
|
||
// flag when it is done.
|
||
//
|
||
ProcessingType = SAC_PROCESS_INPUT;
|
||
|
||
KeSetEvent(&(DeviceContext->ProcessEvent), DeviceContext->PriorityBoost, FALSE);
|
||
|
||
} else {
|
||
|
||
if ( !IoctlSubmitted ) {
|
||
|
||
// We Still need to try and submit the notify IOCTL
|
||
|
||
if(Attempts == 0){
|
||
|
||
ProcessingType = SAC_SUBMIT_IOCTL;
|
||
|
||
Attempts = SAC_RETRY_GAP;
|
||
|
||
KeSetEvent(&(DeviceContext->ProcessEvent), DeviceContext->PriorityBoost, FALSE);
|
||
|
||
|
||
IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC TimerDpcRoutine: Exiting.\n")));
|
||
|
||
return;
|
||
|
||
} else {
|
||
|
||
Attempts --;
|
||
}
|
||
}
|
||
KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
|
||
|
||
DeviceContext->Processing = FALSE;
|
||
|
||
KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
|
||
|
||
//
|
||
// If there is any, process it.
|
||
//
|
||
DoDeferred(DeviceContext);
|
||
|
||
}
|
||
|
||
IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC TimerDpcRoutine: Exiting.\n")));
|
||
}
|
||
|
||
VOID
|
||
ProcessInputLine(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to process an input line.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
HEADLESS_CMD_DISPLAY_LOG Command;
|
||
PUCHAR InputLine;
|
||
BOOLEAN CommandFound = FALSE;
|
||
|
||
InputLine = &(((PHEADLESS_RSP_GET_LINE)ResponseBuffer)->Buffer[0]);
|
||
|
||
if (!strcmp((LPSTR)InputLine, TLIST_COMMAND_STRING)) {
|
||
DoTlistCommand();
|
||
CommandFound = TRUE;
|
||
} else if ((!strcmp((LPSTR)InputLine, HELP1_COMMAND_STRING)) ||
|
||
(!strcmp((LPSTR)InputLine, HELP2_COMMAND_STRING))) {
|
||
DoHelpCommand();
|
||
CommandFound = TRUE;
|
||
} else if (!strcmp((LPSTR)InputLine, DUMP_COMMAND_STRING)) {
|
||
|
||
Command.Paging = GlobalPagingNeeded;
|
||
HeadlessDispatch(HeadlessCmdDisplayLog,
|
||
&Command,
|
||
sizeof(HEADLESS_CMD_DISPLAY_LOG),
|
||
NULL,
|
||
NULL
|
||
);
|
||
CommandFound = TRUE;
|
||
|
||
} else if (!strcmp((LPSTR)InputLine, FULLINFO_COMMAND_STRING)) {
|
||
DoFullInfoCommand();
|
||
CommandFound = TRUE;
|
||
} else if (!strcmp((LPSTR)InputLine, PAGING_COMMAND_STRING)) {
|
||
DoPagingCommand();
|
||
CommandFound = TRUE;
|
||
} else if (!strcmp((LPSTR)InputLine, REBOOT_COMMAND_STRING)) {
|
||
DoRebootCommand(TRUE);
|
||
CommandFound = TRUE;
|
||
} else if (!strcmp((LPSTR)InputLine, SHUTDOWN_COMMAND_STRING)) {
|
||
DoRebootCommand(FALSE);
|
||
CommandFound = TRUE;
|
||
} else if (!strcmp((LPSTR)InputLine, CRASH_COMMAND_STRING)) {
|
||
CommandFound = TRUE;
|
||
DoCrashCommand(); // this call does not return
|
||
} else if (!strncmp((LPSTR)InputLine,
|
||
KILL_COMMAND_STRING,
|
||
sizeof(KILL_COMMAND_STRING) - sizeof(UCHAR))) {
|
||
if ((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) {
|
||
DoKillCommand(InputLine);
|
||
CommandFound = TRUE;
|
||
}
|
||
} else if (!strncmp((LPSTR)InputLine,
|
||
LOWER_COMMAND_STRING,
|
||
sizeof(LOWER_COMMAND_STRING) - sizeof(UCHAR))) {
|
||
if ((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) {
|
||
DoLowerPriorityCommand(InputLine);
|
||
CommandFound = TRUE;
|
||
}
|
||
} else if (!strncmp((LPSTR)InputLine,
|
||
RAISE_COMMAND_STRING,
|
||
sizeof(RAISE_COMMAND_STRING) - sizeof(UCHAR))) {
|
||
if ((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) {
|
||
DoRaisePriorityCommand(InputLine);
|
||
CommandFound = TRUE;
|
||
}
|
||
} else if (!strncmp((LPSTR)InputLine,
|
||
LIMIT_COMMAND_STRING,
|
||
sizeof(LIMIT_COMMAND_STRING) - sizeof(UCHAR))) {
|
||
if ((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) {
|
||
DoLimitMemoryCommand(InputLine);
|
||
CommandFound = TRUE;
|
||
}
|
||
} else if (!strncmp((LPSTR)InputLine,
|
||
TIME_COMMAND_STRING,
|
||
sizeof(TIME_COMMAND_STRING) - sizeof(UCHAR))) {
|
||
if (((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) ||
|
||
(strlen((LPSTR)InputLine) == 1)) {
|
||
DoSetTimeCommand(InputLine);
|
||
CommandFound = TRUE;
|
||
}
|
||
} else if (!strcmp((LPSTR)InputLine, INFORMATION_COMMAND_STRING)) {
|
||
DoMachineInformationCommand();
|
||
CommandFound = TRUE;
|
||
} else if (!strncmp((LPSTR)InputLine,
|
||
SETIP_COMMAND_STRING,
|
||
sizeof(SETIP_COMMAND_STRING) - sizeof(UCHAR))) {
|
||
if (((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) ||
|
||
(strlen((LPSTR)InputLine) == 1)) {
|
||
DoSetIpAddressCommand(InputLine);
|
||
CommandFound = TRUE;
|
||
}
|
||
} else if ((InputLine[0] == '\n') || (InputLine[0] == '\0')) {
|
||
CommandFound = TRUE;
|
||
}
|
||
|
||
|
||
if( !CommandFound ) {
|
||
//
|
||
// We don't know what this is.
|
||
//
|
||
SacPutSimpleMessage(SAC_UNKNOWN_COMMAND);
|
||
}
|
||
|
||
}
|
||
|