/*++ Copyright (c) 1991 - 2002 Microsoft Corporation Module Name: ## ## ### ## # ## ##### #### ##### ##### ### ### ## # ## ### ## ## ## ## # ## ## ## ## ######## ### ## ### ## ## ## ## ## ## ## ## # ### ## ### ## # # ## ## ## ## ## ## ## ## # # ## ### ### ### ## ## ## ##### ##### # ## # ## ### ### ## ## ## ## # ## ## # ## ### ## ## ##### ## #### ## ## Abstract: This module contains the entire implementation of the virtual watchdog miniport driver. @@BEGIN_DDKSPLIT Author: Wesley Witt (wesw) 1-Oct-2001 @@END_DDKSPLIT Environment: Kernel mode only. Notes: --*/ #include "mswd.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT,DriverEntry) #endif VOID MsWdTimerReset( IN PDEVICE_EXTENSION DeviceExtension ) { LARGE_INTEGER DueTime; KeQuerySystemTime( &DeviceExtension->StartTime ); DueTime.QuadPart = DeviceExtension->TimeoutValue.QuadPart; KeSetTimer( &DeviceExtension->Timer, DueTime, &DeviceExtension->TimerDpc ); } VOID MsWdShutdownWorker( IN PDEVICE_OBJECT DeviceObject, IN PVOID Context ) { PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) Context; ULONG ExpireBehavior; ExAcquireFastMutex( &DeviceExtension->WdIoLock ); ExpireBehavior = DeviceExtension->ExpireBehavior; ExReleaseFastMutex( &DeviceExtension->WdIoLock ); SaPortShutdownSystem( ExpireBehavior == 1 ); } VOID MsWdTimerDpc( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ) { PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeferredContext; PIO_WORKITEM WorkItem; WorkItem = IoAllocateWorkItem( DeviceExtension->DeviceObject ); if (WorkItem) { IoQueueWorkItem( WorkItem, MsWdShutdownWorker, DelayedWorkQueue, DeviceExtension ); } } NTSTATUS MsWdDeviceIoctl( IN PVOID DeviceExtensionIn, IN PIRP Irp, IN PVOID FsContext, IN ULONG FunctionCode, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength ) /*++ Routine Description: This function is called by the SAPORT driver so that the mini-port driver can service an IOCTL call. Arguments: DeviceExtension - A pointer to the mini-port's device extension FunctionCode - The IOCTL function code InputBuffer - Pointer to the input buffer, contains the data sent down by the I/O InputBufferLength - Length in bytes of the InputBuffer OutputBuffer - Pointer to the output buffer, contains the data generated by this call OutputBufferLength - Length in bytes of the OutputBuffer Context: IRQL: IRQL PASSIVE_LEVEL, arbitrary thread context Return Value: If the function succeeds, it must return STATUS_SUCCESS. Otherwise, it must return one of the error status values defined in ntstatus.h. --*/ { PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceExtensionIn; NTSTATUS Status = STATUS_SUCCESS; PSA_WD_CAPS WdCaps = NULL; LARGE_INTEGER CurrentTime; switch (FunctionCode) { case FUNC_SA_GET_VERSION: *((PULONG)OutputBuffer) = SA_INTERFACE_VERSION; break; case FUNC_SA_GET_CAPABILITIES: WdCaps = (PSA_WD_CAPS)OutputBuffer; WdCaps->SizeOfStruct = sizeof(SA_WD_CAPS); WdCaps->Minimum = 1; WdCaps->Maximum = 512; break; case FUNC_SAWD_DISABLE: ExAcquireFastMutex( &DeviceExtension->WdIoLock ); if (*((PULONG)InputBuffer) == 1) { DeviceExtension->Enabled = 1; MsWdTimerReset( DeviceExtension ); } else if (*((PULONG)InputBuffer) == 0) { DeviceExtension->Enabled = 0; KeCancelTimer( &DeviceExtension->Timer ); } else { Status = STATUS_INVALID_PARAMETER_1; } ExReleaseFastMutex( &DeviceExtension->WdIoLock ); break; case FUNC_SAWD_QUERY_EXPIRE_BEHAVIOR: ExAcquireFastMutex( &DeviceExtension->WdIoLock ); *((PULONG)OutputBuffer) = DeviceExtension->ExpireBehavior; ExReleaseFastMutex( &DeviceExtension->WdIoLock ); break; case FUNC_SAWD_SET_EXPIRE_BEHAVIOR: ExAcquireFastMutex( &DeviceExtension->WdIoLock ); if (*((PULONG)InputBuffer) == 1) { DeviceExtension->ExpireBehavior = 1; } else { DeviceExtension->ExpireBehavior = 0; } ExReleaseFastMutex( &DeviceExtension->WdIoLock ); break; case FUNC_SAWD_PING: ExAcquireFastMutex( &DeviceExtension->WdIoLock ); MsWdTimerReset( DeviceExtension ); ExReleaseFastMutex( &DeviceExtension->WdIoLock ); break; case FUNC_SAWD_QUERY_TIMER: ExAcquireFastMutex( &DeviceExtension->WdIoLock ); KeQuerySystemTime( &CurrentTime ); CurrentTime.QuadPart = DeviceExtension->TimeoutValue.QuadPart - (CurrentTime.QuadPart - DeviceExtension->StartTime.QuadPart); *((PULONG)OutputBuffer) = (ULONG)NanoToSec( CurrentTime.QuadPart ); ExReleaseFastMutex( &DeviceExtension->WdIoLock ); break; case FUNC_SAWD_SET_TIMER: ExAcquireFastMutex( &DeviceExtension->WdIoLock ); DeviceExtension->TimeoutValue.QuadPart = (ULONGLONG)-SecToNano( *((PLONG)InputBuffer) ); MsWdTimerReset( DeviceExtension ); ExReleaseFastMutex( &DeviceExtension->WdIoLock ); break; default: Status = STATUS_NOT_SUPPORTED; REPORT_ERROR( SA_DEVICE_WATCHDOG, "Unsupported device control", Status ); break; } return Status; } NTSTATUS MsWdHwInitialize( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID DeviceExtensionIn, IN PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResources, IN ULONG PartialResourceCount ) /*++ Routine Description: This function is called by the SAPORT driver so that the mini-port driver can initialize it's hardware resources. Arguments: DeviceObject - Pointer to the target device object. Irp - Pointer to an IRP structure that describes the requested I/O operation. DeviceExtension - A pointer to the mini-port's device extension. PartialResources - Pointer to the translated resources alloacted by the system. PartialResourceCount - The number of resources in the PartialResources array. Context: IRQL: IRQL PASSIVE_LEVEL, system thread context Return Value: If the function succeeds, it must return STATUS_SUCCESS. Otherwise, it must return one of the error status values defined in ntstatus.h. --*/ { PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn; DeviceExtension->DeviceObject = DeviceObject; ExInitializeFastMutex( &DeviceExtension->WdIoLock ); KeInitializeTimer( &DeviceExtension->Timer ); KeInitializeDpc( &DeviceExtension->TimerDpc, MsWdTimerDpc, DeviceExtension ); DeviceExtension->TimeoutValue.QuadPart = -SecToNano(DEFAULT_WD_TIMEOUT_SECS); DeviceExtension->Enabled = 1; DeviceExtension->ExpireBehavior = 0; MsWdTimerReset( DeviceExtension ); return STATUS_SUCCESS; } NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: This routine is the driver's entry point, called by the I/O system to load the driver. The driver's entry points are initialized and a mutex to control paging is initialized. In DBG mode, this routine also examines the registry for special debug parameters. Arguments: DriverObject - a pointer to the object that represents this device driver. RegistryPath - a pointer to this driver's key in the Services tree. Return Value: STATUS_SUCCESS --*/ { NTSTATUS Status; SAPORT_INITIALIZATION_DATA SaPortInitData; RtlZeroMemory( &SaPortInitData, sizeof(SAPORT_INITIALIZATION_DATA) ); SaPortInitData.StructSize = sizeof(SAPORT_INITIALIZATION_DATA); SaPortInitData.DeviceType = SA_DEVICE_WATCHDOG; SaPortInitData.HwInitialize = MsWdHwInitialize; SaPortInitData.DeviceIoctl = MsWdDeviceIoctl; SaPortInitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION); Status = SaPortInitialize( DriverObject, RegistryPath, &SaPortInitData ); if (!NT_SUCCESS(Status)) { REPORT_ERROR( SA_DEVICE_WATCHDOG, "SaPortInitialize failed\n", Status ); return Status; } return STATUS_SUCCESS; }