|
|
/*++
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); } }
|