NTSTATUS NTAPI BeepDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION Stack; PBEEP_SET_PARAMETERS BeepParam; NTSTATUS Status; /* Get the stack location and parameters */ Stack = IoGetCurrentIrpStackLocation(Irp); BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer; /* We only support one IOCTL */ if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET) { /* Unsupported command */ Status = STATUS_NOT_IMPLEMENTED; } else { /* Validate the input buffer length */ if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(BEEP_SET_PARAMETERS)) { /* Invalid buffer */ Status = STATUS_INVALID_PARAMETER; } else if ((BeepParam->Frequency != 0) && !(BeepParam->Duration)) { /* No duration, return imemdiately */ Status = STATUS_SUCCESS; } else { /* We'll queue this request */ Status = STATUS_PENDING; } } /* Set packet information */ Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; /* Check if we're completing or queuing a packet */ if (Status == STATUS_PENDING) { /* Start the queue */ IoMarkIrpPending(Irp); IoStartPacket(DeviceObject, Irp, NULL, BeepCancel); } else { /* Complete the request */ IoCompleteRequest(Irp, IO_NO_INCREMENT); } /* Return */ return Status; }
NTSTATUS USBSTOR_HandleInternalDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStack; PSCSI_REQUEST_BLOCK Request; PPDO_DEVICE_EXTENSION PDODeviceExtension; NTSTATUS Status; // // get current stack location // IoStack = IoGetCurrentIrpStackLocation(Irp); // // get request block // Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; // // sanity check // ASSERT(Request); // // get device extension // PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); switch(Request->Function) { case SRB_FUNCTION_EXECUTE_SCSI: { DPRINT("SRB_FUNCTION_EXECUTE_SCSI\n"); // // check if request is valid // if (Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)) { // // data is transferred with this irp // if ((Request->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)) == (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT) || Request->DataTransferLength == 0 || Irp->MdlAddress == NULL) { // // invalid parameter // Status = STATUS_INVALID_PARAMETER; break; } } else { // // sense buffer request // if (Request->DataTransferLength || Request->DataBuffer || Irp->MdlAddress) { // // invalid parameter // Status = STATUS_INVALID_PARAMETER; break; } } // // add the request // if (!USBSTOR_QueueAddIrp(PDODeviceExtension->LowerDeviceObject, Irp)) { // // irp was not added to the queue // IoStartPacket(PDODeviceExtension->LowerDeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo); } // // irp pending // return STATUS_PENDING; } case SRB_FUNCTION_RELEASE_DEVICE: { DPRINT1("SRB_FUNCTION_RELEASE_DEVICE\n"); // // sanity check // ASSERT(PDODeviceExtension->Claimed == TRUE); // // release claim // PDODeviceExtension->Claimed = FALSE; Status = STATUS_SUCCESS; break; } case SRB_FUNCTION_CLAIM_DEVICE: { DPRINT1("SRB_FUNCTION_CLAIM_DEVICE\n"); // // check if the device has been claimed // if (PDODeviceExtension->Claimed) { // // device has already been claimed // Status = STATUS_DEVICE_BUSY; Request->SrbStatus = SRB_STATUS_BUSY; break; } // // claim device // PDODeviceExtension->Claimed = TRUE; // // output device object // Request->DataBuffer = DeviceObject; // // completed successfully // Status = STATUS_SUCCESS; break; } case SRB_FUNCTION_RELEASE_QUEUE: { DPRINT1("SRB_FUNCTION_RELEASE_QUEUE\n"); // // release queue // USBSTOR_QueueRelease(PDODeviceExtension->LowerDeviceObject); // // set status success // Request->SrbStatus = SRB_STATUS_SUCCESS; Status = STATUS_SUCCESS; break; } case SRB_FUNCTION_SHUTDOWN: case SRB_FUNCTION_FLUSH: case SRB_FUNCTION_FLUSH_QUEUE: { DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE / SRB_FUNCTION_SHUTDOWN\n"); // HACK: don't flush pending requests #if 0 // we really need a proper storage stack // // wait for pending requests to finish // USBSTOR_QueueWaitForPendingRequests(PDODeviceExtension->LowerDeviceObject); #endif // // set status success // Request->SrbStatus = SRB_STATUS_SUCCESS; Status = STATUS_SUCCESS; break; } default: { // // not supported // Status = STATUS_NOT_SUPPORTED; Request->SrbStatus = SRB_STATUS_ERROR; } } // // complete request // Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
VOID USBSTOR_QueueRelease( IN PDEVICE_OBJECT DeviceObject) { PFDO_DEVICE_EXTENSION FDODeviceExtension; PIRP Irp; KIRQL OldLevel; PIO_STACK_LOCATION IoStack; PSCSI_REQUEST_BLOCK Request; // // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO); // // acquire lock // KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); // // clear freezed status // FDODeviceExtension->IrpListFreeze = FALSE; // // release irp list lock // KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); // // grab newest irp // Irp = USBSTOR_RemoveIrp(DeviceObject); // // is there an irp // if (!Irp) { // // no irp // return; } // // get current irp stack location // IoStack = IoGetCurrentIrpStackLocation(Irp); // // get srb // Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; // // start new packet // IoStartPacket(DeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo); }
VOID USBSTOR_QueueNextRequest( IN PDEVICE_OBJECT DeviceObject) { PFDO_DEVICE_EXTENSION FDODeviceExtension; PIRP Irp; PIO_STACK_LOCATION IoStack; PSCSI_REQUEST_BLOCK Request; // // get pdo device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO); // // check first if there's already a request pending or the queue is frozen // if (FDODeviceExtension->ActiveSrb != NULL || FDODeviceExtension->IrpListFreeze) { // // no work to do yet // return; } // // remove first irp from list // Irp = USBSTOR_RemoveIrp(DeviceObject); // // is there an irp pending // if (!Irp) { // // no work to do // IoStartNextPacket(DeviceObject, TRUE); return; } // // get current stack location // IoStack = IoGetCurrentIrpStackLocation(Irp); // // get srb // Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; // // sanity check // ASSERT(Request); // // set the active SRB // FDODeviceExtension->ActiveSrb = Request; // // start next packet // IoStartPacket(DeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo); // // start next request // IoStartNextPacket(DeviceObject, TRUE); }
NTSTATUS DBusInternalDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine is the dispatch routine for internal device control requests. Arguments: DeviceObject - Pointer to the device object. Irp - Pointer to the request packet. Return Value: Status is returned. --*/ { PIO_STACK_LOCATION irpSp; PDEVICE_EXTENSION deviceExtension; NTSTATUS status; BusPrint((2,"DBusInternalDeviceControl: enter\n")); // // Get a pointer to the device extension. // deviceExtension = DeviceObject->DeviceExtension; // // Initialize the returned Information field. // Irp->IoStatus.Information = 0; // // Get a pointer to the current parameters for this request. The // information is contained in the current stack location. // irpSp = IoGetCurrentIrpStackLocation(Irp); // // Case on the device control subfunction that is being performed by the // requestor. // switch (irpSp->Parameters.DeviceIoControl.IoControlCode) { // // Connect a mouse class device driver to the port driver. // case IOCTL_INTERNAL_MOUSE_CONNECT: BusPrint(( 2, "DBusInternalDeviceControl: mouse connect\n" )); // // Only allow one connection. // // FUTURE: Consider allowing multiple connections, just for // the sake of generality? // if (deviceExtension->ConnectData.ClassService != NULL) { BusPrint(( 2, "DBusInternalDeviceControl: error - already connected\n" )); status = STATUS_SHARING_VIOLATION; break; } else if (irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA)) { BusPrint(( 2, "DBusInternalDeviceControl: error - invalid buffer length\n" )); status = STATUS_INVALID_PARAMETER; break; } // // Copy the connection parameters to the device extension. // deviceExtension->ConnectData = *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer)); // // Reinitialize the port input data queue synchronously. // KeSynchronizeExecution( deviceExtension->InterruptObject, (PKSYNCHRONIZE_ROUTINE) BusInitializeDataQueue, (PVOID) deviceExtension ); // // Set the completion status. // status = STATUS_SUCCESS; break; // // Disconnect a mouse class device driver from the port driver. // // NOTE: Not implemented. // case IOCTL_INTERNAL_MOUSE_DISCONNECT: BusPrint(( 2, "DBusInternalDeviceControl: mouse disconnect\n" )); // // Perform a mouse interrupt disable call. // // // Clear the connection parameters in the device extension. // NOTE: Must synchronize this with the mouse ISR. // // //deviceExtension->ConnectData.ClassDeviceObject = // Null; //deviceExtension->ConnectData.ClassService = // Null; // // Set the completion status. // status = STATUS_NOT_IMPLEMENTED; break; // // Enable mouse interrupts (mark the request pending and handle // it in StartIo). // case IOCTL_INTERNAL_MOUSE_ENABLE: BusPrint(( 2, "DBusInternalDeviceControl: mouse enable\n" )); status = STATUS_PENDING; break; // // Disable mouse interrupts (mark the request pending and handle // it in StartIo). // case IOCTL_INTERNAL_MOUSE_DISABLE: BusPrint(( 2, "DBusInternalDeviceControl: mouse disable\n" )); status = STATUS_PENDING; break; // // Query the mouse attributes. First check for adequate buffer // length. Then, copy the mouse attributes from the device // extension to the output buffer. // case IOCTL_MOUSE_QUERY_ATTRIBUTES: BusPrint(( 2, "DBusInternalDeviceControl: mouse query attributes\n" )); if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES)) { status = STATUS_BUFFER_TOO_SMALL; } else { // // Copy the attributes from the DeviceExtension to the // buffer. // *(PMOUSE_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer = deviceExtension->Configuration.MouseAttributes; Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES); status = STATUS_SUCCESS; } break; default: BusPrint(( 2, "DBusInternalDeviceControl: INVALID REQUEST\n" )); status = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Status = status; if (status == STATUS_PENDING) { IoMarkIrpPending(Irp); IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL); } else { IoCompleteRequest(Irp, IO_NO_INCREMENT); } BusPrint((2,"DBusInternalDeviceControl: exit\n")); return(status); }
/* * Runs the keyboard IOCTL_INTERNAL dispatch. */ NTSTATUS NTAPI i8042KbdInternalDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION Stack; PI8042_KEYBOARD_EXTENSION DeviceExtension; NTSTATUS Status; Stack = IoGetCurrentIrpStackLocation(Irp); Irp->IoStatus.Information = 0; DeviceExtension = (PI8042_KEYBOARD_EXTENSION)DeviceObject->DeviceExtension; switch (Stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_INTERNAL_KEYBOARD_CONNECT: { SIZE_T Size; PIO_WORKITEM WorkItem = NULL; PI8042_HOOK_WORKITEM WorkItemData = NULL; TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_CONNECT\n"); if (Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(CONNECT_DATA)) { Status = STATUS_INVALID_PARAMETER; goto cleanup; } DeviceExtension->KeyboardData = *((PCONNECT_DATA)Stack->Parameters.DeviceIoControl.Type3InputBuffer); /* Send IOCTL_INTERNAL_I8042_HOOK_KEYBOARD to device stack */ WorkItem = IoAllocateWorkItem(DeviceObject); if (!WorkItem) { WARN_(I8042PRT, "IoAllocateWorkItem() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } WorkItemData = ExAllocatePoolWithTag( NonPagedPool, sizeof(I8042_HOOK_WORKITEM), I8042PRT_TAG); if (!WorkItemData) { WARN_(I8042PRT, "ExAllocatePoolWithTag() failed\n"); Status = STATUS_NO_MEMORY; goto cleanup; } WorkItemData->WorkItem = WorkItem; WorkItemData->Irp = Irp; /* Initialize extension */ DeviceExtension->Common.Type = Keyboard; Size = DeviceExtension->Common.PortDeviceExtension->Settings.KeyboardDataQueueSize * sizeof(KEYBOARD_INPUT_DATA); DeviceExtension->KeyboardBuffer = ExAllocatePoolWithTag( NonPagedPool, Size, I8042PRT_TAG); if (!DeviceExtension->KeyboardBuffer) { WARN_(I8042PRT, "ExAllocatePoolWithTag() failed\n"); Status = STATUS_NO_MEMORY; goto cleanup; } RtlZeroMemory(DeviceExtension->KeyboardBuffer, Size); KeInitializeDpc( &DeviceExtension->DpcKeyboard, i8042KbdDpcRoutine, DeviceExtension); DeviceExtension->PowerWorkItem = IoAllocateWorkItem(DeviceObject); if (!DeviceExtension->PowerWorkItem) { WARN_(I8042PRT, "IoAllocateWorkItem() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } DeviceExtension->DebugWorkItem = IoAllocateWorkItem(DeviceObject); if (!DeviceExtension->DebugWorkItem) { WARN_(I8042PRT, "IoAllocateWorkItem() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } DeviceExtension->Common.PortDeviceExtension->KeyboardExtension = DeviceExtension; DeviceExtension->Common.PortDeviceExtension->Flags |= KEYBOARD_CONNECTED; i8042InitializeKeyboardAttributes(DeviceExtension); IoMarkIrpPending(Irp); /* FIXME: DeviceExtension->KeyboardHook.IsrWritePort = ; */ DeviceExtension->KeyboardHook.QueueKeyboardPacket = i8042KbdQueuePacket; DeviceExtension->KeyboardHook.CallContext = DeviceExtension; IoQueueWorkItem(WorkItem, i8042SendHookWorkItem, DelayedWorkQueue, WorkItemData); Status = STATUS_PENDING; break; cleanup: if (DeviceExtension->KeyboardBuffer) ExFreePoolWithTag(DeviceExtension->KeyboardBuffer, I8042PRT_TAG); if (DeviceExtension->PowerWorkItem) IoFreeWorkItem(DeviceExtension->PowerWorkItem); if (DeviceExtension->DebugWorkItem) IoFreeWorkItem(DeviceExtension->DebugWorkItem); if (WorkItem) IoFreeWorkItem(WorkItem); if (WorkItemData) ExFreePoolWithTag(WorkItemData, I8042PRT_TAG); break; } case IOCTL_INTERNAL_KEYBOARD_DISCONNECT: { TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_DISCONNECT\n"); /* MSDN says that operation is to implemented. * To implement it, we just have to do: * DeviceExtension->KeyboardData.ClassService = NULL; */ Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD: { TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_I8042_HOOK_KEYBOARD\n"); /* Nothing to do here */ Status = STATUS_SUCCESS; break; } case IOCTL_KEYBOARD_QUERY_ATTRIBUTES: { PKEYBOARD_ATTRIBUTES KeyboardAttributes; /* FIXME: KeyboardAttributes are not initialized anywhere */ TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_QUERY_ATTRIBUTES\n"); if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_ATTRIBUTES)) { Status = STATUS_BUFFER_TOO_SMALL; break; } KeyboardAttributes = Irp->AssociatedIrp.SystemBuffer; *KeyboardAttributes = DeviceExtension->KeyboardAttributes; Irp->IoStatus.Information = sizeof(KEYBOARD_ATTRIBUTES); Status = STATUS_SUCCESS; break; Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_KEYBOARD_QUERY_TYPEMATIC: { DPRINT1("IOCTL_KEYBOARD_QUERY_TYPEMATIC not implemented\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_KEYBOARD_SET_TYPEMATIC: { DPRINT1("IOCTL_KEYBOARD_SET_TYPEMATIC not implemented\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: { TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION\n"); /* We should check the UnitID, but it's kind of pointless as * all keyboards are supposed to have the same one */ if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION)) { Status = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &IndicatorTranslation, sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION)); Irp->IoStatus.Information = sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION); Status = STATUS_SUCCESS; } break; } case IOCTL_KEYBOARD_QUERY_INDICATORS: { TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_QUERY_INDICATORS\n"); if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS)) { Status = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &DeviceExtension->KeyboardIndicators, sizeof(KEYBOARD_INDICATOR_PARAMETERS)); Irp->IoStatus.Information = sizeof(KEYBOARD_INDICATOR_PARAMETERS); Status = STATUS_SUCCESS; } break; } case IOCTL_KEYBOARD_SET_INDICATORS: { TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_SET_INDICATORS\n"); if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS)) { Status = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory( &DeviceExtension->KeyboardIndicators, Irp->AssociatedIrp.SystemBuffer, sizeof(KEYBOARD_INDICATOR_PARAMETERS)); Status = STATUS_PENDING; IoMarkIrpPending(Irp); IoStartPacket(DeviceObject, Irp, NULL, NULL); } break; } default: { ERR_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / unknown ioctl code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); ASSERT(FALSE); return ForwardIrpAndForget(DeviceObject, Irp); } } Irp->IoStatus.Status = Status; if (Status != STATUS_PENDING) IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
NTSTATUS LspDispatchRead( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Read disptach routine Arguments: DeviceObject - pointer to a device object. Irp - pointer to current Irp Return Value: NT status code. --*/ { NTSTATUS status; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; LARGE_INTEGER currentTime; PAGED_CODE(); LSP_KDPRINT(("LspRead Enter: Irp=%p\n", Irp)); // // Get a pointer to the device extension. // deviceExtension = DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); // // First make sure there is enough room. // // // read should be aligned to a sector size (512 bytes) // if (0 != (irpStack->Parameters.Read.Length % 512)) { Irp->IoStatus.Status = status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } if (irpStack->Parameters.Read.Length < sizeof(INPUT_DATA)) { Irp->IoStatus.Status = status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } IoMarkIrpPending(Irp); IoStartPacket(DeviceObject, Irp, NULL, NULL); return STATUS_PENDING; //// // // FOR TESTING: // // Initialize the data to mod 2 of some random number. // // With this value you can control the number of times the // // Irp will be queued before completion. Check // // LspPollDevice routine to know how this works. // // // KeQuerySystemTime(¤tTime); // // *(ULONG *)Irp->AssociatedIrp.SystemBuffer =((currentTime.LowPart/13)%2); //// Irp->DriverContext[4] = ((currentTime.LowPart/13)%2); // // // // Queue the IRP and return STATUS_PENDING after signaling the // // polling thread. //// // // **Note: IoCsqInsertIrp marks the IRP pending. // // // IoCsqInsertIrp(&deviceExtension->CancelSafeQueue, Irp, NULL); // // // // A semaphore remains signaled as long as its count is greater than // // zero, and non-signaled when the count is zero. Following function // // increments the semaphore count by 1. // // // KeReleaseSemaphore( // &deviceExtension->IrpQueueSemaphore, // 0,// No priority boost // 1,// Increment semaphore by 1 // FALSE );// No WaitForXxx after this call // return STATUS_PENDING; }
NTSTATUS LspDispatchClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Process the close IRPs sent to this device. Arguments: DeviceObject - pointer to a device object. Irp - pointer to an I/O Request Packet. Return Value: NT Status code --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status = STATUS_SUCCESS, cleanupStatus; PAGED_CODE (); LSP_KDPRINT(("LspDispatchClose Enter\n")); // // Get a pointer to the current location in the Irp. // irpStack = IoGetCurrentIrpStackLocation(Irp); ASSERT(IRP_MJ_CLOSE == irpStack->MajorFunction); LSP_KDPRINT(("IRP_MJ_CLOSE\n")); // // The IRP_MJ_CLOSE dispatch routine is called when a file object // opened on the driver is being removed from the system; that is, // all file object handles have been closed and the reference count // of the file object is down to 0. // Irp->IoStatus.Information = 0; IoMarkIrpPending(Irp); IoStartPacket(DeviceObject, Irp, NULL, NULL); return STATUS_PENDING; //// // // Save Status for return and complete Irp // // // // Irp->IoStatus.Status = status; // IoCompleteRequest(Irp, IO_NO_INCREMENT); // LSP_KDPRINT((" LspCreateClose Exit = %x\n", status)); return status; }
NTSTATUS LspDispatchCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Process the Create and close IRPs sent to this device. Arguments: DeviceObject - pointer to a device object. Irp - pointer to an I/O Request Packet. Return Value: NT Status code --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension; KIRQL oldIrql; PAGED_CODE (); LSP_KDPRINT(("LspDispatchCreate Enter\n")); // // Get a pointer to the current location in the Irp. // irpStack = IoGetCurrentIrpStackLocation(Irp); ASSERT(IRP_MJ_CREATE == irpStack->MajorFunction); // // The dispatch routine for IRP_MJ_CREATE is called when a // file object associated with the device is created. // This is typically because of a call to CreateFile() in // a user-mode program or because a another driver is // layering itself over a this driver. A driver is // required to supply a dispatch routine for IRP_MJ_CREATE. // Irp->IoStatus.Information = 0; IoMarkIrpPending(Irp); IoStartPacket(DeviceObject, Irp, NULL, NULL); return STATUS_PENDING; //deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; // //status = LspInitializeConnection(DeviceObject); //if (STATUS_PENDING == status) //{ // IoMarkIrpPending(Irp); // status = STATUS_PENDING; //} //else //{ // Irp->IoStatus.Information = 0; // Irp->IoStatus.Status = status; // IoCompleteRequest(Irp, IO_NO_INCREMENT); //} // LSP_KDPRINT((" LspCreate Exit = %x\n", status)); return status; }
NTSTATUS ScsiPortStopAdapter( IN PDEVICE_OBJECT Adapter, IN PIRP StopRequest ) /*++ Routine Description: This routine will stop an adapter and release it's io and interrupt resources. Pool allocations will not be freed, nor will the various miniport extensions. Arguments: Adapter - the device object for the adapter. Return Value: status --*/ { PADAPTER_EXTENSION adapterExtension = Adapter->DeviceExtension; PCOMMON_EXTENSION commonExtension = Adapter->DeviceExtension; KEVENT event; ULONG bin; PAGED_CODE(); ASSERT(adapterExtension->IsPnp); // // If we're not started and we weren't started then there's no reason // to do any work when stopping. // if((commonExtension->CurrentPnpState != IRP_MN_START_DEVICE) && (commonExtension->PreviousPnpState != IRP_MN_START_DEVICE)) { return STATUS_SUCCESS; } // // Since all the children are stopped no requests can get through to the // adapter. // // // Send a request through the start-io routine to shut it down so that we // can start it back up later. // KeInitializeEvent(&event, SynchronizationEvent, FALSE); StopRequest->IoStatus.Information = (ULONG_PTR) &event; IoStartPacket(Adapter, StopRequest, 0, NULL); KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); // // Call the miniport and get it to shut the adapter down. // SpEnableDisableAdapter(adapterExtension, FALSE); SpReleaseAdapterResources(adapterExtension, TRUE); // // Zero out all the logical unit extensions. // for(bin = 0; bin < NUMBER_LOGICAL_UNIT_BINS; bin++) { PLOGICAL_UNIT_EXTENSION lun; for(lun = adapterExtension->LogicalUnitList[bin].List; lun != NULL; lun = lun->NextLogicalUnit) { RtlZeroMemory(lun->HwLogicalUnitExtension, adapterExtension->HwLogicalUnitExtensionSize); } } return STATUS_SUCCESS; }
VOID NTAPI CdRompFlushDelayedList( IN PDEVICE_OBJECT Fdo, IN PCDROM_MMC_EXTENSION MmcData, IN NTSTATUS Status, IN BOOLEAN CalledFromWorkItem ) { PSINGLE_LIST_ENTRY list; PIRP irp; // NOTE - REF #0002 // // need to set the new state first to prevent deadlocks. // this is only done from the workitem, to prevent any // edge cases where we'd "lose" the UpdateRequired // // then, must ignore the state, since it's not guaranteed to // be the same any longer. the only thing left is to handle // all the delayed irps by flushing the queue and sending them // back onto the StartIo queue for the device. // if (CalledFromWorkItem) { LONG oldState; LONG newState; if (NT_SUCCESS(Status)) { newState = CdromMmcUpdateComplete; } else { newState = CdromMmcUpdateRequired; } oldState = InterlockedCompareExchange(&MmcData->UpdateState, newState, CdromMmcUpdateStarted); ASSERT(oldState == CdromMmcUpdateStarted); } else { // // just flushing the queue if not called from the workitem, // and we don't want to ever fail the queue in those cases. // ASSERT(NT_SUCCESS(Status)); } list = ExInterlockedFlushSList(&MmcData->DelayedIrps); // if this assert fires, it means that we have started // a workitem when the previous workitem took the delayed // irp. if this happens, then the logic in HACKHACK #0002 // is either flawed or the rules set within are not being // followed. this would require investigation. ASSERT(list != NULL); // // now either succeed or fail all the delayed irps, according // to the update status. // while (list != NULL) { irp = (PIRP)( ((PUCHAR)list) - FIELD_OFFSET(IRP, Tail.Overlay.DriverContext[0]) ); list = list->Next; irp->Tail.Overlay.DriverContext[0] = 0; irp->Tail.Overlay.DriverContext[1] = 0; irp->Tail.Overlay.DriverContext[2] = 0; irp->Tail.Overlay.DriverContext[3] = 0; if (NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdRomUpdateMmc => Re-sending delayed irp %p\n", irp)); IoStartPacket(Fdo, irp, NULL, NULL); } else { KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdRomUpdateMmc => Failing delayed irp %p with " " status %x\n", irp, Status)); irp->IoStatus.Information = 0; irp->IoStatus.Status = Status; ClassReleaseRemoveLock(Fdo, irp); IoCompleteRequest(irp, IO_CD_ROM_INCREMENT); } } // while (list) return; }