/*++ Copyright (c) 1989 Microsoft Corporation Module Name: dispatch.c Abstract: This module contains the dispatch routines for SAC. Author: Sean Selitrennikoff (v-seans) - Jan 13, 1999 Brian Guarraci (briangu), 2001 Revision History: --*/ #include #include "sac.h" DEFINE_GUID(SAC_CMD_CHANNEL_APPLICATION_GUID, 0x63d02271, 0x8aa4, 0x11d5, 0xbc, 0xcf, 0x00, 0xb0, 0xd0, 0x14, 0xa2, 0xd0); NTSTATUS DispatchClose( IN PSAC_DEVICE_CONTEXT DeviceContext, IN PIRP Irp ); NTSTATUS DispatchCreate( IN PSAC_DEVICE_CONTEXT DeviceContext, IN PIRP Irp ); NTSTATUS Dispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the dispatch routine for SAC. Arguments: DeviceObject - Pointer to device object for target device Irp - Pointer to I/O request packet Return Value: NTSTATUS -- Indicates whether the request was successfully queued. Security: interface: external --> internal exposed to anything that can get a handle device object --*/ { PSAC_DEVICE_CONTEXT DeviceContext = (PSAC_DEVICE_CONTEXT)DeviceObject->DeviceExtension; PIO_STACK_LOCATION IrpSp; NTSTATUS Status; // // // Status = STATUS_UNSUCCESSFUL; IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC Dispatch: Entering.\n"))); IrpSp = IoGetCurrentIrpStackLocation(Irp); switch (IrpSp->MajorFunction) { case IRP_MJ_CREATE: Status = DispatchCreate(DeviceContext, Irp); IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC Dispatch: Exiting with status 0x%x\n", Status))); break; case IRP_MJ_CLEANUP: #if ENABLE_SERVICE_FILE_OBJECT_CHECKING // // Determine if the process that is closing // their driver handle owns any channels or // is the process that registered the cmd event info. // If it is any of these, close the respective // resource. // // // Compare the FileObject against // // the service fileobject // the existing channel fileobjects // // if (IsCmdEventRegistrationProcess(IrpSp->FileObject)) { Status = UnregisterSacCmdEvent(IrpSp->FileObject); if (NT_SUCCESS(Status)) { // // Notify the Console Manager that the service has unregistered // Status = IoMgrHandleEvent( IO_MGR_EVENT_UNREGISTER_SAC_CMD_EVENT, NULL, NULL ); } } #endif else { // // Find all channels that have the same File object // and notify the Io Mgr that they should be closed // Status = ChanMgrCloseChannelsWithFileObject(IrpSp->FileObject); } // // we return SUCCESS regardless of our attempts to clean up // the service or channels. // Status = STATUS_SUCCESS; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC Dispatch: Exiting cleanup status 0x%x\n", Status))); break; case IRP_MJ_CLOSE: Status = DispatchClose(DeviceContext, Irp); IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC Dispatch: Exiting close status 0x%x\n", Status))); break; case IRP_MJ_DEVICE_CONTROL: ASSERT(0); Status = DispatchDeviceControl(DeviceObject, Irp); IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC Dispatch: Exiting with status 0x%x\n", Status))); break; default: IF_SAC_DEBUG(SAC_DEBUG_FAILS, KdPrint(( "SAC Dispatch: Invalid major function %lx\n", IrpSp->MajorFunction ))); Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; IoCompleteRequest(Irp, DeviceContext->PriorityBoost); Status = STATUS_NOT_IMPLEMENTED; IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC Dispatch: Exiting with status 0x%x\n", Status))); break; } return Status; } // Dispatch NTSTATUS DispatchDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the dispatch routine for SAC IOCTLs. Arguments: DeviceObject - Pointer to device object for target device Irp - Pointer to I/O request packet Return Value: NTSTATUS -- Indicates whether the request was successfully queued. Security: interface: external -> internal internal -> external --*/ { NTSTATUS Status; PSAC_DEVICE_CONTEXT DeviceContext; PIO_STACK_LOCATION IrpSp; ULONG i; ULONG ResponseLength; ULONG IoControlCode; ResponseLength = 0; DeviceContext = (PSAC_DEVICE_CONTEXT)DeviceObject->DeviceExtension; IrpSp = IoGetCurrentIrpStackLocation(Irp); IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchDeviceControl: Entering.\n"))); // // Get the IOCTL code // IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode; switch (IoControlCode) { case IOCTL_SAC_OPEN_CHANNEL: { PSAC_CHANNEL Channel; PSAC_CMD_OPEN_CHANNEL OpenChannelCmd; PSAC_RSP_OPEN_CHANNEL OpenChannelRsp; PSAC_CHANNEL_OPEN_ATTRIBUTES Attributes; // // // Channel = NULL; // // Verify the parameters of the IRP // if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SAC_CMD_OPEN_CHANNEL)) { Status = STATUS_INVALID_BUFFER_SIZE; break; } if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(SAC_RSP_OPEN_CHANNEL)) { Status = STATUS_INVALID_BUFFER_SIZE; break; } // // Get the IRP buffers // OpenChannelCmd = (PSAC_CMD_OPEN_CHANNEL)Irp->AssociatedIrp.SystemBuffer; OpenChannelRsp = (PSAC_RSP_OPEN_CHANNEL)Irp->AssociatedIrp.SystemBuffer; // // Get the attributes from the command structure // Attributes = &OpenChannelCmd->Attributes; // // Verify that the Channel Type is valid // if (! ChannelIsValidType(Attributes->Type)) { Status = STATUS_INVALID_PARAMETER_1; break; } // // Verify that if the user wants to use the CLOSE_EVENT, we received on to use // if (Attributes->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT) { #if DEBUG_DISPATCH ASSERT(Attributes->CloseEvent != NULL); #endif if (Attributes->CloseEvent == NULL) { Status = STATUS_INVALID_PARAMETER_5; break; } } else { #if DEBUG_DISPATCH ASSERT(Attributes->CloseEvent == NULL); #endif if (Attributes->CloseEvent != NULL) { Status = STATUS_INVALID_PARAMETER_5; break; } } // // Verify that if the user wants to use the HAS_NEW_DATA_EVENT, we received one to use // if (Attributes->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT) { #if DEBUG_DISPATCH ASSERT(Attributes->HasNewDataEvent); #endif if (! Attributes->HasNewDataEvent) { Status = STATUS_INVALID_PARAMETER_6; break; } } else { #if DEBUG_DISPATCH ASSERT(Attributes->HasNewDataEvent == NULL); #endif if (Attributes->HasNewDataEvent != NULL) { Status = STATUS_INVALID_PARAMETER_6; break; } } #if ENABLE_CHANNEL_LOCKING // // Verify that if the user wants to use the LOCK_EVENT, we received one to use // if (Attributes->Flags & SAC_CHANNEL_FLAG_LOCK_EVENT) { #if DEBUG_DISPATCH ASSERT(Attributes->LockEvent); #endif if (! Attributes->LockEvent) { Status = STATUS_INVALID_PARAMETER_7; break; } } else { #if DEBUG_DISPATCH ASSERT(Attributes->LockEvent == NULL); #endif if (Attributes->LockEvent != NULL) { Status = STATUS_INVALID_PARAMETER_7; break; } } #endif // // Verify that if the user wants to use the REDRAW_EVENT, we received one to use // if (Attributes->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT) { #if DEBUG_DISPATCH ASSERT(Attributes->RedrawEvent); #endif if (! Attributes->RedrawEvent) { Status = STATUS_INVALID_PARAMETER_8; break; } } else { #if DEBUG_DISPATCH ASSERT(Attributes->RedrawEvent == NULL); #endif if (Attributes->RedrawEvent != NULL) { Status = STATUS_INVALID_PARAMETER_8; break; } } // // SECURITY: // // at this point we have at least a properly formed set of flags // and event handles. The events still need to be validated, however. // this is done via ChanMgrCreateChannel. // // // Create the channel based on type // if (Attributes->Type == ChannelTypeCmd) { PSAC_CHANNEL_OPEN_ATTRIBUTES tmpAttributes; PWCHAR Name; PCWSTR Description; // // // tmpAttributes = NULL; Name = NULL; Description = NULL; // // Create a channel for this IRP // do { // // the cmd channel requires all of the events // hence, ensure we have them // if (!(Attributes->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT) || !(Attributes->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT) || !(Attributes->Flags & SAC_CHANNEL_FLAG_LOCK_EVENT) || !(Attributes->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT)) { Status = STATUS_INVALID_PARAMETER_7; break; } // // Allocate a temporary attributes structure that // we'll populate with attributes appropriate for // creating a cmd type channel // tmpAttributes = ALLOCATE_POOL(sizeof(SAC_CHANNEL_OPEN_ATTRIBUTES), GENERAL_POOL_TAG); if (! tmpAttributes) { Status = STATUS_NO_MEMORY; break; } // // Allocate a buffer for the channel's name // Name = ALLOCATE_POOL(SAC_MAX_CHANNEL_NAME_SIZE, GENERAL_POOL_TAG); if (! Name) { Status = STATUS_NO_MEMORY; break; } // // Generate a name for the command console channel // Status = ChanMgrGenerateUniqueCmdName(Name); if (! NT_SUCCESS(Status)) { break; } // // Initialize the Command Console attributes // RtlZeroMemory(tmpAttributes, sizeof(SAC_CHANNEL_OPEN_ATTRIBUTES)); tmpAttributes->Type = Attributes->Type; // attempt to copy the name wcsncpy(tmpAttributes->Name, Name, SAC_MAX_CHANNEL_NAME_LENGTH); tmpAttributes->Name[SAC_MAX_CHANNEL_NAME_LENGTH] = UNICODE_NULL; // attempt to copy the channel description Description = GetMessage(CMD_CHANNEL_DESCRIPTION); ASSERT(Description); if (!Description) { Status = STATUS_NO_MEMORY; break; } wcsncpy(tmpAttributes->Description, Description, SAC_MAX_CHANNEL_DESCRIPTION_LENGTH); tmpAttributes->Description[SAC_MAX_CHANNEL_DESCRIPTION_LENGTH] = UNICODE_NULL; tmpAttributes->Flags = Attributes->Flags | SAC_CHANNEL_FLAG_APPLICATION_TYPE; tmpAttributes->CloseEvent = Attributes->CloseEvent; tmpAttributes->HasNewDataEvent = Attributes->HasNewDataEvent; #if ENABLE_CHANNEL_LOCKING tmpAttributes->LockEvent = Attributes->LockEvent; #endif tmpAttributes->RedrawEvent = Attributes->RedrawEvent; tmpAttributes->ApplicationType = SAC_CMD_CHANNEL_APPLICATION_GUID; // // attempt to create the new channel // Status = ChanMgrCreateChannel( &Channel, tmpAttributes ); } while (FALSE); // // Cleanup // SAFE_FREE_POOL(&Name); SAFE_FREE_POOL(&tmpAttributes); } else { // // Validate the Name & Description strings // // // Verify name string is NULL terminated. // i = 0; while (i < SAC_MAX_CHANNEL_NAME_LENGTH) { if (Attributes->Name[i] == UNICODE_NULL) { break; } i++; } // // fail if string is not NULL terminated or if string is empty // if ((i == SAC_MAX_CHANNEL_NAME_LENGTH) || (i == 0)) { Status = STATUS_INVALID_PARAMETER_2; break; } // // Verify description string is NULL terminated. // Note: the Description is allowed to have zero length, so we don't check it. // i = 0; while (i < SAC_MAX_CHANNEL_DESCRIPTION_LENGTH) { if (Attributes->Description[i] == UNICODE_NULL) { break; } i++; } if (i == SAC_MAX_CHANNEL_DESCRIPTION_LENGTH) { Status = STATUS_INVALID_PARAMETER_3; break; } // // attempt to create the new channel // Status = ChanMgrCreateChannel( &Channel, Attributes ); } if (NT_SUCCESS(Status)) { // // Keep track of the File Object used to reference the driver // ChannelSetFileObject(Channel, IrpSp->FileObject); // // Populate the response message with the new channel handle // OpenChannelRsp->Handle = ChannelGetHandle(Channel); ResponseLength = sizeof(SAC_RSP_OPEN_CHANNEL); // // Notify the Console Manager that a new channel has been created // IoMgrHandleEvent( IO_MGR_EVENT_CHANNEL_CREATE, Channel, NULL ); } break; } case IOCTL_SAC_CLOSE_CHANNEL: { PSAC_CMD_CLOSE_CHANNEL ChannelCloseCmd; PSAC_CHANNEL Channel; // // Verify the parameters of the IRP // if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SAC_CMD_CLOSE_CHANNEL)) { Status = STATUS_INVALID_BUFFER_SIZE; break; } // // Close the given channel. // ChannelCloseCmd = (PSAC_CMD_CLOSE_CHANNEL)Irp->AssociatedIrp.SystemBuffer; // // Get the referred channel by it's handle while making // sure the driver handle is the same one as the one // that created the channel - the same process // Status = ChanMgrGetByHandleAndFileObject( ChannelCloseCmd->Handle, IrpSp->FileObject, &Channel ); if (NT_SUCCESS(Status)) { // // close the channel // Status = ChanMgrCloseChannel(Channel); // // We are done with the channel // ChanMgrReleaseChannel(Channel); } break; } case IOCTL_SAC_WRITE_CHANNEL: { PSAC_CMD_WRITE_CHANNEL ChannelWriteCmd; PSAC_CHANNEL Channel; // // Verify the parameters of the IRP // if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SAC_CMD_WRITE_CHANNEL)) { Status = STATUS_BUFFER_TOO_SMALL; break; } // // Get the Write cmd structure // ChannelWriteCmd = (PSAC_CMD_WRITE_CHANNEL)Irp->AssociatedIrp.SystemBuffer; // // Verify that the specified write bufferSize is reasonable // if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != (sizeof(SAC_CMD_WRITE_CHANNEL) + ChannelWriteCmd->Size)) { // // if the buffer sizes dont match, // then the specified the wrong size // Status = STATUS_INVALID_PARAMETER_2; break; } // // Get the referred channel by it's handle while making // sure the driver handle is the same one as the one // that created the channel - the same process // Status = ChanMgrGetByHandleAndFileObject( ChannelWriteCmd->Handle, IrpSp->FileObject, &Channel ); if (NT_SUCCESS(Status)) { // // Call the I/O Manager's OWrite method // Status = IoMgrHandleEvent( IO_MGR_EVENT_CHANNEL_WRITE, Channel, ChannelWriteCmd ); // // We are done with the channel // ChanMgrReleaseChannel(Channel); } #if DEBUG_DISPATCH ASSERT(NT_SUCCESS(Status) || Status == STATUS_NOT_FOUND); #endif break; } case IOCTL_SAC_READ_CHANNEL: { PSAC_CHANNEL Channel; PSAC_CMD_READ_CHANNEL ChannelReadCmd; PSAC_RSP_READ_CHANNEL ChannelReadRsp; // // // Channel = NULL; // // Verify the parameters of the IRP // if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SAC_CMD_READ_CHANNEL)) { Status = STATUS_INVALID_BUFFER_SIZE; break; } if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SAC_RSP_READ_CHANNEL)) { Status = STATUS_BUFFER_TOO_SMALL; break; } // // Read from the given channel. // ChannelReadCmd = (PSAC_CMD_READ_CHANNEL)Irp->AssociatedIrp.SystemBuffer; // // Get the referred channel by it's handle while making // sure the driver handle is the same one as the one // that created the channel - the same process // Status = ChanMgrGetByHandleAndFileObject( ChannelReadCmd->Handle, IrpSp->FileObject, &Channel ); if (NT_SUCCESS(Status)) { ChannelReadRsp = (PSAC_RSP_READ_CHANNEL)Irp->AssociatedIrp.SystemBuffer; // // SECURITY: // // it is safe to use the OutputBufferLength since we know the buffer // is large enough to hold at least one byte. // the response structure is essentially a byte array of bytes // read, we read the # of bytes specified by OutputBufferLength // Status = ChannelIRead( Channel, &(ChannelReadRsp->Buffer[0]), IrpSp->Parameters.DeviceIoControl.OutputBufferLength, &ResponseLength ); // // We are done with the channel // ChanMgrReleaseChannel(Channel); } #if DEBUG_DISPATCH ASSERT(NT_SUCCESS(Status) || Status == STATUS_NOT_FOUND); #endif break; } case IOCTL_SAC_POLL_CHANNEL: { PSAC_CHANNEL Channel; PSAC_CMD_POLL_CHANNEL PollChannelCmd; PSAC_RSP_POLL_CHANNEL PollChannelRsp; // // // Channel = NULL; // // Verify the parameters of the IRP // if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SAC_CMD_POLL_CHANNEL)) { Status = STATUS_INVALID_BUFFER_SIZE; break; } if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(SAC_RSP_POLL_CHANNEL)) { Status = STATUS_INVALID_BUFFER_SIZE; break; } // // get the channel specified by the incoming channel handle // PollChannelCmd = (PSAC_CMD_POLL_CHANNEL)Irp->AssociatedIrp.SystemBuffer; PollChannelRsp = (PSAC_RSP_POLL_CHANNEL)Irp->AssociatedIrp.SystemBuffer; // // Get the referred channel by it's handle while making // sure the driver handle is the same one as the one // that created the channel - the same process // Status = ChanMgrGetByHandleAndFileObject( PollChannelCmd->Handle, IrpSp->FileObject, &Channel ); if (NT_SUCCESS(Status)) { // // see if there is data waiting // // SECURITY: // // the InputWaiting variable is guaranteed to be safe since // we validated the OutputBufferLength // PollChannelRsp->InputWaiting = ChannelHasNewIBufferData(Channel); ResponseLength = sizeof(SAC_RSP_POLL_CHANNEL); // // We are done with the channel // Status = ChanMgrReleaseChannel(Channel); } #if DEBUG_DISPATCH ASSERT(NT_SUCCESS(Status) || Status == STATUS_NOT_FOUND); #endif break; } case IOCTL_SAC_REGISTER_CMD_EVENT: { PSAC_CMD_SETUP_CMD_EVENT SetupCmdEvent; // // Verify the parameters of the IRP // if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SAC_CMD_SETUP_CMD_EVENT)) { Status = STATUS_INVALID_BUFFER_SIZE; break; } // // get the event info // SetupCmdEvent = (PSAC_CMD_SETUP_CMD_EVENT)Irp->AssociatedIrp.SystemBuffer; #if ENABLE_CMD_SESSION_PERMISSION_CHECKING // // If we are not able to launch cmd sessions, // then notify that we cannot peform this action // if (! IsCommandConsoleLaunchingEnabled()) { Status = STATUS_UNSUCCESSFUL; break; } #endif // // Attempt to register the callers cmd event info // // SECURITY: // // the SAC_CMD_SETUP_CMD_EVENT has events handles that must be // validated as part of the registration process // Status = RegisterSacCmdEvent( IrpSp->FileObject, SetupCmdEvent ); if (NT_SUCCESS(Status)) { // // Notify the Console Manager that the Command Prompt // service has REGISTERED // Status = IoMgrHandleEvent( IO_MGR_EVENT_REGISTER_SAC_CMD_EVENT, NULL, NULL ); } #if DEBUG_DISPATCH ASSERT(NT_SUCCESS(Status)); #endif break; } case IOCTL_SAC_UNREGISTER_CMD_EVENT: { Status = STATUS_UNSUCCESSFUL; #if ENABLE_CMD_SESSION_PERMISSION_CHECKING // // If we are not able to launch cmd sessions, // then notify that we cannot peform this action // if (! IsCommandConsoleLaunchingEnabled()) { break; } #endif #if ENABLE_SERVICE_FILE_OBJECT_CHECKING // // If the current process is the one that registered // the cmd event info, // then unregister // if (! IsCmdEventRegistrationProcess(IrpSp->FileObject)) { break; } #endif Status = UnregisterSacCmdEvent(IrpSp->FileObject); if (NT_SUCCESS(Status)) { // // Notify the Console Manager that the Command Prompt // service has UNREGISTERED // Status = IoMgrHandleEvent( IO_MGR_EVENT_UNREGISTER_SAC_CMD_EVENT, NULL, NULL ); } #if DEBUG_DISPATCH ASSERT(NT_SUCCESS(Status)); #endif break; } default: Status = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Status = Status; Irp->IoStatus.Information = ResponseLength; if (Status != STATUS_PENDING) { IoCompleteRequest(Irp, DeviceContext->PriorityBoost); } IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchDeviceControl: Exiting with status 0x%x\n", Status))); return Status; } // DispatchDeviceControl NTSTATUS DispatchShutdownControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the dispatch routine which receives the shutdown IRP. Arguments: DeviceObject - Pointer to device object for target device Irp - Pointer to I/O request packet Return Value: NTSTATUS -- Indicates whether the request was successfully queued. --*/ { UNREFERENCED_PARAMETER(DeviceObject); IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchShutdownControl: Entering.\n"))); // // Notify any user. // IoMgrHandleEvent( IO_MGR_EVENT_SHUTDOWN, NULL, NULL ); IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchShutdownControl: Exiting.\n"))); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } // DispatchShutdownControl NTSTATUS DispatchCreate( IN PSAC_DEVICE_CONTEXT DeviceContext, IN PIRP Irp ) /*++ Routine Description: This is the dispatch routine for SAC IOCTL Create Arguments: DeviceContext - Pointer to device context for target device Irp - Pointer to I/O request packet Return Value: NTSTATUS -- Indicates whether the request was successfully queued. --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchCreate: Entering.\n"))); // // Check to see if we are done initializing. // if (!GlobalDataInitialized || !DeviceContext->InitializedAndReady) { Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE; IoCompleteRequest(Irp, DeviceContext->PriorityBoost); Status = STATUS_INVALID_DEVICE_STATE; IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchCreate: Exiting with status 0x%x\n", Status))); // // We need to catch this state // ASSERT(0); return Status; } // // Get a pointer to the current stack location in the IRP. This is where // the function codes and parameters are stored. // IrpSp = IoGetCurrentIrpStackLocation(Irp); // // Case on the function that is being performed by the requestor. If the // operation is a valid one for this device, then make it look like it was // successfully completed, where possible. // switch (IrpSp->MajorFunction) { // // The Create function opens a connection to this device. // case IRP_MJ_CREATE: Status = STATUS_SUCCESS; break; default: Status = STATUS_INVALID_DEVICE_REQUEST; } Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, DeviceContext->PriorityBoost); // // Return the immediate status code to the caller. // IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchCreate: Exiting with status 0x%x\n", Status))); // // We need to catch this state // ASSERT(NT_SUCCESS(Status)); return Status; } NTSTATUS DispatchClose( IN PSAC_DEVICE_CONTEXT DeviceContext, IN PIRP Irp ) /*++ Routine Description: This is the dispatch routine for SAC IOCTL Close Arguments: DeviceContext - Pointer to device context for target device Irp - Pointer to I/O request packet Return Value: NTSTATUS -- Indicates whether the request was successfully queued. --*/ { NTSTATUS Status; IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchClose: Entering.\n"))); // // Check to see if we are done initializing. // if (!GlobalDataInitialized || !DeviceContext->InitializedAndReady) { Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE; IoCompleteRequest(Irp, DeviceContext->PriorityBoost); Status = STATUS_INVALID_DEVICE_STATE; IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchClose: Exiting with status 0x%x\n", Status))); return Status; } Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, DeviceContext->PriorityBoost); Status = STATUS_SUCCESS; return Status; }