NTSTATUS HidUmdfInternalIoctlWorker( _In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp ) /*++ Routine Description: IOCTL handler. Arguments: DeviceObject - pointer to a device object. Irp - pointer to an I/O Request Packet. Return Value: NT status code --*/ { PIO_STACK_LOCATION currStack, nextStack; ULONG ioctlCode, newIoctlCode; BOOLEAN setCompletionRoutine = FALSE; NTSTATUS status = STATUS_SUCCESS; BOOLEAN modeChanged = FALSE; PULONG temp = NULL; currStack = IoGetCurrentIrpStackLocation(Irp); // // Copy current stack to next instead of skipping. We do this to preserve // current stack information provided by hidclass driver to the minidriver // IoCopyCurrentIrpStackLocationToNext(Irp); // // HIDclass uses INTERNAL_IOCTL but since UMDF doesn't yet have support for // internal IOCTLS we change the IOCTL type to DEVICE_CONTROL for next stack // so that UMDF stack can handle it as normal IOCTL. // Note that user mode apps cannot open a handle to minidriver since // HIDClass doesn't allow that (it own's minidriver's dispatch table), // and therefore they can't send these IOCTLs to UMDF minidriver by calling // win32 API. // nextStack = IoGetNextIrpStackLocation(Irp); nextStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; // // Some IOCTLs are not of type METHOD_NEITHER and are forwarded by // HIDClass to minidriver. We modify those IOCTLs to use METHOD_NEITHER // and send it down to UMDF driver. // ioctlCode = nextStack->Parameters.DeviceIoControl.IoControlCode; newIoctlCode = ioctlCode; switch(ioctlCode) { case IOCTL_HID_GET_DEVICE_DESCRIPTOR: // METHOD_NEITHER, KM case IOCTL_HID_GET_REPORT_DESCRIPTOR: // METHOD_NEITHER, KM case IOCTL_HID_READ_REPORT: // METHOD_NEITHER, KM case IOCTL_HID_ACTIVATE_DEVICE: // METHOD_NEITHER, KM case IOCTL_HID_DEACTIVATE_DEVICE: // METHOD_NEITHER, KM case IOCTL_HID_GET_DEVICE_ATTRIBUTES: // METHOD_NEITHER, KM case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST: // METHOD_NEITHER, KM // // Nothing to do. These IOCTLs have been listed for completeness. // break; case IOCTL_HID_WRITE_REPORT: // METHOD_NEITHER, KM case IOCTL_HID_SET_FEATURE: // METHOD_IN_DIRECT, KM/UM case IOCTL_HID_GET_FEATURE: // METHOD_OUT_DIRECT, KM/UM case IOCTL_HID_GET_INPUT_REPORT: // METHOD_OUT_DIRECT, KM/UM case IOCTL_HID_SET_OUTPUT_REPORT: // METHOD_IN_DIRECT, KM/UM // // These IOCTLs use HID_XFER_PACKET. They need their buffer location // updated. See comments in function for IOCTL specific updates. // status = UpdateBufferLocationAndIoctl(Irp, &newIoctlCode); if (!NT_SUCCESS(status)) { KdPrint(("HidUmdf: Ioctl %s failed status 0x%x\n", DbgHidInternalIoctlString(ioctlCode), status)); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } // // set completion routine // setCompletionRoutine = TRUE; break; case IOCTL_GET_PHYSICAL_DESCRIPTOR: // METHOD_OUT_DIRECT, KM/UM // // These IOCTLs are not METHOD_NEITHER but hidclass places buffers at // locations that are standard locations for METHOD_NEITHER // (Type3InputBuffer and Irp->UserBuffer), so we modify the IOCTL type // to use METHOD_NEITHER so that UMDF can provide the buffers from // standard METHOD_NEITHER buffer locations. // newIoctlCode = IOCTL_UMDF_GET_PHYSICAL_DESCRIPTOR; break; case IOCTL_HID_GET_STRING: // METHOD_NEITHER, KM // // This is a METHOD_NEITHER IOCTL. Hidclass places an input // ULONG value, and not a buffer, at Type3inputBuffer location. // We store the input value in Irp->AssocatedIrp.SystemBuffer location // and store pointer to Irp->AssocatedIrp.SystemBuffer at // Type3InputBuffer so that lower driver can access it as input buffer. // // // swap current SystemBuffer content with Type3inputBuffer // temp = Irp->AssociatedIrp.SystemBuffer; Irp->AssociatedIrp.SystemBuffer = currStack->Parameters.DeviceIoControl.Type3InputBuffer; currStack->Parameters.DeviceIoControl.Type3InputBuffer = temp; // // store the address of SystemBuffer in next stack's Type3InputBuffer // and set buffer size // nextStack->Parameters.DeviceIoControl.Type3InputBuffer = &Irp->AssociatedIrp.SystemBuffer; nextStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(ULONG); setCompletionRoutine = TRUE; break; case IOCTL_HID_GET_INDEXED_STRING: // METHOD_OUT_DIRECT, KM/UM // // This is a METHOD_OUT_DIRECT IOCTL however hidclass places buffer/value // in a mix of locations (Type3InputBuffer for input instead of // Irp->AssociatedIrp.SystemBuffer and Irp->MdlAddress for output). // Also, the input is not a buffer but a ULONG value. // // We store the address of next stack's Type3InputBuffer that contains // the input value at Irp->AssiciatedIrp.SystemBuffer // (standard location for METHOD_OUT_DIRECT), and keep the output buffer // location (Irp->UserBuffer) unchanged since it's already at standard // location. The input buffer location is reverted back to original in // completion routine. // // // store SystemBuffer in curr stack's Type3inputBuffer so we // can get it back in completion routine. // currStack->Parameters.DeviceIoControl.Type3InputBuffer = Irp->AssociatedIrp.SystemBuffer; // // store the address of next stack's Type3InputBuffer in SystemBuffer // and set buffer size. // Irp->AssociatedIrp.SystemBuffer = &nextStack->Parameters.DeviceIoControl.Type3InputBuffer; nextStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(ULONG); setCompletionRoutine = TRUE; break; default: NT_ASSERTMSG("Unexpected IOCTL", FALSE); break; } // // update ioctl code for next stack location // nextStack->Parameters.DeviceIoControl.IoControlCode = newIoctlCode; if (Irp->RequestorMode == UserMode) { Irp->RequestorMode = KernelMode; setCompletionRoutine = TRUE; modeChanged = TRUE; } if (setCompletionRoutine) { IoSetCompletionRoutine(Irp, UserIoctlCompletion, (modeChanged ? (PVOID)Irp : NULL), // context TRUE, TRUE, TRUE ); } return IoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp); }
NTSTATUS OnWriteComplete(PDEVICE_OBJECT fdo, PIRP Irp, PRWCONTEXT ctx) { PIO_STACK_LOCATION stack; NTSTATUS status; ULONG length; KIRQL OldIrql; ULONG count; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; status = Irp->IoStatus.Status; if(NT_SUCCESS(status) && ctx->remain && !Irp->Cancel) { /* we have more to transfer */ length = ctx->remain; if(length > pdx->maxtransfer) length = pdx->maxtransfer; UsbBuildInterruptOrBulkTransferRequest(&ctx->urb, sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER), pdx->houtpipe, ctx->data, NULL, length, (USBD_TRANSFER_DIRECTION_OUT | USBD_SHORT_TRANSFER_OK), NULL); ctx->data += length; ctx->remain -= length; stack = IoGetNextIrpStackLocation(Irp); stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; stack->Parameters.Others.Argument1 = (PVOID)&ctx->urb; stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)OnWriteComplete, (PVOID) ctx, TRUE, TRUE, TRUE); IoCallDriver(pdx->LowerDeviceObject, Irp); return STATUS_MORE_PROCESSING_REQUIRED; } if(NT_SUCCESS(status)) { Irp->IoStatus.Information = ctx->total; } else { KdPrint((DRIVERNAME " - finished with error!\n")); } ExFreePool(ctx); StartNextPacket ( &pdx->dqWrite, fdo ); IoReleaseRemoveLock( &pdx->RemoveLock, Irp ); return STATUS_SUCCESS; }
NTSTATUS IrpCreateFile( IN PUNICODE_STRING FileName, IN ACCESS_MASK DesiredAccess, __out PIO_STATUS_BLOCK IoStatusBlock, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT RealDevice, OUT PFILE_OBJECT *Object ) { NTSTATUS status; KEVENT event; PIRP irp; PIO_STACK_LOCATION irpSp; IO_SECURITY_CONTEXT securityContext; ACCESS_STATE accessState; OBJECT_ATTRIBUTES objectAttributes; PFILE_OBJECT fileObject; AUX_ACCESS_DATA auxData; PAGED_CODE(); RtlZeroMemory(&auxData, sizeof(AUX_ACCESS_DATA)); InitializeObjectAttributes(&objectAttributes, NULL, OBJ_CASE_INSENSITIVE| OBJ_KERNEL_HANDLE, 0, NULL); status = ObCreateObject(KernelMode, *IoFileObjectType, &objectAttributes, KernelMode, NULL, sizeof(FILE_OBJECT), 0, 0, (PVOID *)&fileObject); if (!NT_SUCCESS(status)) { return status; } RtlZeroMemory(fileObject, sizeof(FILE_OBJECT)); fileObject->Type = IO_TYPE_FILE; fileObject->Size = sizeof(FILE_OBJECT); fileObject->DeviceObject = RealDevice; // fileObject->RelatedFileObject = NULL; fileObject->Flags = FO_SYNCHRONOUS_IO; fileObject->FileName.MaximumLength = FileName->MaximumLength; fileObject->FileName.Buffer = (PWCH)ExAllocatePoolWithTag(NonPagedPool, FileName->MaximumLength, 'File'); //fileObject->FileObjectExtension if (fileObject->FileName.Buffer == NULL) { ObDereferenceObject(fileObject); return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyUnicodeString(&fileObject->FileName, FileName); KeInitializeEvent(&fileObject->Lock, SynchronizationEvent, FALSE); KeInitializeEvent(&fileObject->Event, NotificationEvent, FALSE); irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (irp == NULL) { ObDereferenceObject(fileObject); return STATUS_INSUFFICIENT_RESOURCES; } KeInitializeEvent(&event, SynchronizationEvent, FALSE); irp->MdlAddress = NULL; irp->Flags |= IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API; irp->RequestorMode = KernelMode; irp->UserIosb = IoStatusBlock; ////LCXL:CHANGE irp->UserEvent = &event; //irp->UserEvent = NULL; irp->PendingReturned = FALSE; irp->Cancel = FALSE; irp->CancelRoutine = NULL; irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); irp->Tail.Overlay.AuxiliaryBuffer = NULL; irp->Tail.Overlay.OriginalFileObject = fileObject; status = SeCreateAccessState(&accessState, &auxData, DesiredAccess, IoGetFileObjectGenericMapping()); if (!NT_SUCCESS(status)) { IoFreeIrp(irp); ExFreePool(fileObject->FileName.Buffer); ObDereferenceObject(fileObject); return status; } securityContext.SecurityQos = NULL; securityContext.AccessState = &accessState; securityContext.DesiredAccess = DesiredAccess; securityContext.FullCreateOptions = 0; irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_CREATE; irpSp->DeviceObject = DeviceObject; irpSp->FileObject = fileObject; irpSp->Parameters.Create.SecurityContext = &securityContext; irpSp->Parameters.Create.Options = (CreateDisposition << 24) | CreateOptions; irpSp->Parameters.Create.FileAttributes = (USHORT)FileAttributes; irpSp->Parameters.Create.ShareAccess = (USHORT)ShareAccess; irpSp->Parameters.Create.EaLength = 0; IoSetCompletionRoutine(irp, IoCompletionRoutine, NULL, TRUE, TRUE, TRUE); status = IoCallDriver(DeviceObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL); } status = IoStatusBlock->Status; if (!NT_SUCCESS(status)) { ExFreePool(fileObject->FileName.Buffer); fileObject->FileName.Length = 0; fileObject->DeviceObject = NULL; ObDereferenceObject(fileObject); } else { InterlockedIncrement(&fileObject->DeviceObject->ReferenceCount); if (fileObject->Vpb) { InterlockedIncrement((PLONG)&fileObject->Vpb->ReferenceCount); } *Object = fileObject; KdPrint(("IrpCreateFile:Open file success! object = %x\n", fileObject)); } return status; }
VOID Ext2MediaEjectControl ( IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN BOOLEAN bPrevent ) { PIRP Irp; KEVENT Event; NTSTATUS Status; PREVENT_MEDIA_REMOVAL Prevent; IO_STATUS_BLOCK IoStatus; ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); if (bPrevent != IsFlagOn(Vcb->Flags, VCB_REMOVAL_PREVENTED)) { if (bPrevent) { SetFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED); } else { ClearFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED); } } ExReleaseResourceLite(&Vcb->MainResource); Prevent.PreventMediaRemoval = bPrevent; KeInitializeEvent( &Event, NotificationEvent, FALSE ); Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_MEDIA_REMOVAL, Vcb->TargetDeviceObject, &Prevent, sizeof(PREVENT_MEDIA_REMOVAL), NULL, 0, FALSE, NULL, &IoStatus ); if (Irp != NULL) { IoSetCompletionRoutine( Irp, Ext2MediaEjectControlCompletion, &Event, TRUE, TRUE, TRUE ); Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); if (Status == STATUS_PENDING) { Status = KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); } } }
VOID StartIo( PDEVICE_OBJECT fdo, PIRP Irp ) { PIO_STACK_LOCATION stack; PRWCONTEXT ctx; ULONG length, i; KIRQL OldIrql; NTSTATUS status; if((Irp == NULL) || (Irp->AssociatedIrp.SystemBuffer == NULL)) { CompleteRequest(Irp, STATUS_INVALID_PARAMETER, 0); return; } PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp); if(!NT_SUCCESS(status)) { CompleteRequest(Irp, status, 0); return; } stack = IoGetCurrentIrpStackLocation(Irp); if(stack->MajorFunction == IRP_MJ_WRITE) { // start a write operation ctx = (PRWCONTEXT) ExAllocatePoolWithTag(NonPagedPool, sizeof(RWCONTEXT), SPOT_TAG); if(ctx == NULL) { KdPrint((DRIVERNAME " - Could not allocate transfer context\n")); StartNextPacket ( &pdx->dqWrite, fdo ); CompleteRequest ( Irp, STATUS_INSUFFICIENT_RESOURCES, 0 ); IoReleaseRemoveLock( &pdx->RemoveLock, Irp ); return; } RtlZeroMemory(ctx, sizeof(RWCONTEXT)); ctx->total = ctx->remain = stack->Parameters.Write.Length; ctx->data = (PCHAR)Irp->AssociatedIrp.SystemBuffer; length = ctx->remain; if(length > pdx->maxtransfer) length = pdx->maxtransfer; UsbBuildInterruptOrBulkTransferRequest(&ctx->urb, sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER), pdx->houtpipe, ctx->data, NULL, length, (USBD_TRANSFER_DIRECTION_OUT | USBD_SHORT_TRANSFER_OK), NULL); ctx->data += length; ctx->remain -= length; stack = IoGetNextIrpStackLocation(Irp); stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; stack->Parameters.Others.Argument1 = (PVOID)&ctx->urb; stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)OnWriteComplete, (PVOID) ctx, TRUE, TRUE, TRUE); IoCallDriver(pdx->LowerDeviceObject, Irp); } else { // flush KdPrint((DRIVERNAME " - Flushed!\n")); StartNextPacket ( &pdx->dqWrite, fdo ); CompleteRequest ( Irp, STATUS_SUCCESS, 0 ); IoReleaseRemoveLock( &pdx->RemoveLock, Irp ); } return; }
// Handle power events NTSTATUS FreeBT_DispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus; PIO_STACK_LOCATION irpStack; PUNICODE_STRING tagString; PDEVICE_EXTENSION deviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; // We don't queue power Irps, we'll only check if the // device was removed, otherwise we'll take appropriate // action and send it to the next lower driver. In general // drivers should not cause long delays while handling power // IRPs. If a driver cannot handle a power IRP in a brief time, // it should return STATUS_PENDING and queue all incoming // IRPs until the IRP completes. if (Removed == deviceExtension->DeviceState) { // Even if a driver fails the IRP, it must nevertheless call // PoStartNextPowerIrp to inform the Power Manager that it // is ready to handle another power IRP. PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus = STATUS_DELETE_PENDING; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } if (NotStarted == deviceExtension->DeviceState) { // if the device is not started yet, pass it down PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); return PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::")); FreeBT_IoIncrement(deviceExtension); switch(irpStack->MinorFunction) { case IRP_MN_SET_POWER: // The Power Manager sends this IRP for one of the // following reasons: // 1) To notify drivers of a change to the system power state. // 2) To change the power state of a device for which // the Power Manager is performing idle detection. // A driver sends IRP_MN_SET_POWER to change the power // state of its device if it's a power policy owner for the // device. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_SET_POWER\n")); IoMarkIrpPending(Irp); switch(irpStack->Parameters.Power.Type) { case SystemPowerState: HandleSystemSetPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; case DevicePowerState: HandleDeviceSetPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; } break; case IRP_MN_QUERY_POWER: // The Power Manager sends a power IRP with the minor // IRP code IRP_MN_QUERY_POWER to determine whether it // can safely change to the specified system power state // (S1-S5) and to allow drivers to prepare for such a change. // If a driver can put its device in the requested state, // it sets status to STATUS_SUCCESS and passes the IRP down. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_QUERY_POWER\n")); IoMarkIrpPending(Irp); switch(irpStack->Parameters.Power.Type) { case SystemPowerState: HandleSystemQueryPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; case DevicePowerState: HandleDeviceQueryPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; } break; case IRP_MN_WAIT_WAKE: // The minor power IRP code IRP_MN_WAIT_WAKE provides // for waking a device or waking the system. Drivers // of devices that can wake themselves or the system // send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE // only to devices that always wake the system, such as // the power-on switch. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE\n")); IoMarkIrpPending(Irp); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine, deviceExtension, TRUE, TRUE, TRUE); PoStartNextPowerIrp(Irp); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: Lower drivers failed the wait-wake Irp\n")); } ntStatus = STATUS_PENDING; // push back the count HERE and NOT in completion routine // a pending Wait Wake Irp should not impede stopping the device FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE::")); FreeBT_IoDecrement(deviceExtension); break; case IRP_MN_POWER_SEQUENCE: // A driver sends this IRP as an optimization to determine // whether its device actually entered a specific power state. // This IRP is optional. Power Manager cannot send this IRP. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_POWER_SEQUENCE\n")); default: PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchPower: Lower drivers failed this Irp\n")); } FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::")); FreeBT_IoDecrement(deviceExtension); break; } return ntStatus; }
NTSTATUS TapeReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine builds SRBs and CDBs for read and write requests to 4MM DAT devices. Arguments: DeviceObject Irp Return Value: Returns STATUS_PENDING. --*/ { PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); PSCSI_REQUEST_BLOCK srb; PCDB cdb; ULONG transferBlocks; LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; // // Allocate an Srb. // if (deviceExtension->SrbZone != NULL && (srb = ExInterlockedAllocateFromZone( deviceExtension->SrbZone, deviceExtension->SrbZoneSpinLock)) != NULL) { srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE; } else { // // Allocate Srb from non-paged pool. // This call must succeed. // srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE); srb->SrbFlags = 0; } // // Write length to SRB. // srb->Length = SCSI_REQUEST_BLOCK_SIZE; // // Set up IRP Address. // srb->OriginalRequest = Irp; // // Set up target id and logical unit number. // srb->PathId = deviceExtension->PathId; srb->TargetId = deviceExtension->TargetId; srb->Lun = deviceExtension->Lun; srb->Function = SRB_FUNCTION_EXECUTE_SCSI; srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); // // Save byte count of transfer in SRB Extension. // srb->DataTransferLength = currentIrpStack->Parameters.Read.Length; // // Indicate auto request sense by specifying buffer and size. // srb->SenseInfoBuffer = deviceExtension->SenseData; srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; // // Initialize the queue actions field. // srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; // // Indicate auto request sense by specifying buffer and size. // srb->SenseInfoBuffer = deviceExtension->SenseData; srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; // // Set timeout value in seconds. // srb->TimeOutValue = deviceExtension->TimeOutValue; // // Zero statuses. // srb->SrbStatus = srb->ScsiStatus = 0; srb->NextSrb = 0; // // Indicate that 6-byte CDB's will be used. // srb->CdbLength = CDB6GENERIC_LENGTH; // // Fill in CDB fields. // cdb = (PCDB)srb->Cdb; // // Zero CDB in SRB. // RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); if (deviceExtension->DiskGeometry->BytesPerSector) { // // Since we are writing fixed block mode, normalize transfer count // to number of blocks. // transferBlocks = currentIrpStack->Parameters.Read.Length / deviceExtension->DiskGeometry->BytesPerSector; // // Tell the device that we are in fixed block mode. // cdb->CDB6READWRITETAPE.VendorSpecific = 1; } else { // // Variable block mode transfer. // transferBlocks = currentIrpStack->Parameters.Read.Length; cdb->CDB6READWRITETAPE.VendorSpecific = 0; } // // Set up transfer length // cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff); cdb->CDB6READWRITETAPE.TransferLen = (UCHAR)((transferBlocks >> 8) & 0xff); cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff); // // Set transfer direction flag and Cdb command. // if (currentIrpStack->MajorFunction == IRP_MJ_READ) { DebugPrint((3, "TapeReadWrite: Read Command\n")); srb->SrbFlags = SRB_FLAGS_DATA_IN; cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6; } else { DebugPrint((3, "TapeReadWrite: Write Command\n")); srb->SrbFlags = SRB_FLAGS_DATA_OUT; cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6; } // // Or in the default flags from the device object. // srb->SrbFlags |= deviceExtension->SrbFlags; // // Set up major SCSI function. // nextIrpStack->MajorFunction = IRP_MJ_SCSI; // // Save SRB address in next stack for port driver. // nextIrpStack->Parameters.Scsi.Srb = srb; // // Save retry count in current IRP stack. // currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; // // Set up IoCompletion routine address. // IoSetCompletionRoutine(Irp, ScsiClassIoComplete, srb, TRUE, TRUE, FALSE); return STATUS_PENDING; } // end TapeReadWrite()
NTSTATUS SpWmiPassToMiniPort( IN PDEVICE_OBJECT DeviceObject, IN UCHAR WmiMinorCode, IN OUT PWMI_PARAMETERS WmiParameters ) /*++ Routine Description: This function pass a WMI request to the miniport driver for processing. It creates an SRB which is processed normally by the port driver. This call is synchronous. Callers of SpWmiPassToMiniPort must be running at IRQL PASSIVE_LEVEL. Arguments: DeviceObject - Pointer to the functional or physical device object. WmiMinorCode - WMI action to perform. WmiParameters - WMI parameters. Return Value: An NTSTATUS code describing the result of handling the WMI request. Complete the IRP with this status. Notes: If this WMI request is completed with STATUS_SUCCESS, the WmiParameters BufferSize field will reflect the actual size of the WMI return buffer. --*/ { PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension; PADAPTER_EXTENSION fdoExtension; SCSI_WMI_REQUEST_BLOCK srb; LARGE_INTEGER startingOffset; PLOGICAL_UNIT_EXTENSION logicalUnit; ULONG commonBufferSize; PUCHAR commonBuffer; PHYSICAL_ADDRESS physicalAddress; PVOID removeTag = (PVOID)((ULONG_PTR)WmiParameters+3); PWNODE_HEADER wnode; NTSTATUS status; PAGED_CODE(); startingOffset.QuadPart = (LONGLONG) 1; // // Zero out the SRB. // RtlZeroMemory(&srb, sizeof(SCSI_WMI_REQUEST_BLOCK)); // // Initialize the SRB for a WMI request. // if (commonExtension->IsPdo) { // [PDO] // // Set the logical unit addressing from this PDO's device extension. // logicalUnit = DeviceObject->DeviceExtension; SpAcquireRemoveLock(DeviceObject, removeTag); srb.PathId = logicalUnit->PathId; srb.TargetId = logicalUnit->TargetId; srb.Lun = logicalUnit->Lun; fdoExtension = logicalUnit->AdapterExtension; } else { // [FDO] // // Set the logical unit addressing to the first logical unit. This is // merely used for addressing purposes for adapter requests only. // NOTE: SpFindSafeLogicalUnit will acquire the remove lock // logicalUnit = SpFindSafeLogicalUnit(DeviceObject, 0xff, removeTag); if (logicalUnit == NULL) { return(STATUS_DEVICE_DOES_NOT_EXIST); } fdoExtension = DeviceObject->DeviceExtension; srb.WMIFlags = SRB_WMI_FLAGS_ADAPTER_REQUEST; srb.PathId = logicalUnit->PathId; srb.TargetId = logicalUnit->TargetId; srb.Lun = logicalUnit->Lun; } // // HACK - allocate a chunk of common buffer for the actual request to // get processed in. We need to determine the size of buffer to allocate // this is the larger of the input or output buffers // if (WmiMinorCode == IRP_MN_EXECUTE_METHOD) { wnode = (PWNODE_HEADER)WmiParameters->Buffer; commonBufferSize = (WmiParameters->BufferSize > wnode->BufferSize) ? WmiParameters->BufferSize : wnode->BufferSize; } else { commonBufferSize = WmiParameters->BufferSize; } commonBuffer = HalAllocateCommonBuffer(fdoExtension->DmaAdapterObject, commonBufferSize, &physicalAddress, FALSE); if(commonBuffer == NULL) { DebugPrint((1, "SpWmiPassToMiniPort: Unable to allocate %#x bytes of " "common buffer\n", commonBufferSize)); SpReleaseRemoveLock(logicalUnit->DeviceObject, removeTag); return STATUS_INSUFFICIENT_RESOURCES; } try { KEVENT event; PIRP irp; PMDL mdl; PIO_STACK_LOCATION irpStack; RtlCopyMemory(commonBuffer, WmiParameters->Buffer, commonBufferSize); srb.DataBuffer = commonBuffer; // [already non-paged] srb.DataTransferLength = WmiParameters->BufferSize; srb.Function = SRB_FUNCTION_WMI; srb.Length = sizeof(SCSI_REQUEST_BLOCK); srb.WMISubFunction = WmiMinorCode; srb.DataPath = WmiParameters->DataPath; srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE; srb.TimeOutValue = 10; // [ten seconds] // // Note that the value in DataBuffer may be used regardless of the value // of the MapBuffers field. // // // Initialize the notification event. // KeInitializeEvent(&event, NotificationEvent, FALSE); // // Build IRP for this request. // Note we do this synchronously for two reasons. If it was done // asynchonously then the completion code would have to make a special // check to deallocate the buffer. Second if a completion routine were // used then an additional IRP stack location would be needed. // irp = IoAllocateIrp(logicalUnit->DeviceObject->StackSize, FALSE); if(irp == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; leave; } mdl = IoAllocateMdl(commonBuffer, WmiParameters->BufferSize, FALSE, FALSE, irp); if(mdl == NULL) { IoFreeIrp(irp); status = STATUS_INSUFFICIENT_RESOURCES; leave; } MmBuildMdlForNonPagedPool(mdl); srb.OriginalRequest = irp; irpStack = IoGetNextIrpStackLocation(irp); // // Set major code. // irpStack->MajorFunction = IRP_MJ_SCSI; // // Set SRB pointer. // irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)&srb; // // Setup a completion routine so we know when the request has completed. // IoSetCompletionRoutine(irp, SpSignalCompletion, &event, TRUE, TRUE, TRUE); // // Flush the data buffer for output. This will insure that the data is // written back to memory. Since the data-in flag is the the port driver // will flush the data again for input which will ensure the data is not // in the cache. // KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE); // // Call port driver to handle this request. // IoCallDriver(logicalUnit->CommonExtension.DeviceObject, irp); // // Wait for request to complete. // KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = irp->IoStatus.Status; // // Relay the return buffer's size to the caller on success. // if (NT_SUCCESS(status)) { WmiParameters->BufferSize = srb.DataTransferLength; } // // Copy back the correct number of bytes into the caller provided buffer. // RtlCopyMemory(WmiParameters->Buffer, commonBuffer, WmiParameters->BufferSize); // // Free the irp and MDL. // IoFreeMdl(mdl); IoFreeIrp(irp); } finally { HalFreeCommonBuffer(fdoExtension->DmaAdapterObject, commonBufferSize, physicalAddress, commonBuffer, FALSE); SpReleaseRemoveLock(logicalUnit->CommonExtension.DeviceObject, removeTag); } // // Return the IRP's status. // return status; }
/* *@implemented */ BOOLEAN STREAMAPI StreamClassReadWriteConfig( IN PVOID HwDeviceExtension, IN BOOLEAN Read, IN PVOID Buffer, IN ULONG OffSet, IN ULONG Length) { PIRP Irp; ULONG MajorFunction; KEVENT Event; PSTREAM_DEVICE_EXTENSION DeviceExtension; LARGE_INTEGER Offset; IO_STATUS_BLOCK StatusBlock; NTSTATUS Status; /* Get our DeviceExtension */ DeviceExtension = (PSTREAM_DEVICE_EXTENSION) ((ULONG_PTR)HwDeviceExtension - sizeof(STREAM_DEVICE_EXTENSION)); ASSERT(DeviceExtension->DeviceExtension == HwDeviceExtension); if (Read) { /* Zero input buffer */ RtlZeroMemory(Buffer, Length); } /* Set request type */ MajorFunction = (Read ? IRP_MJ_READ : IRP_MJ_WRITE); /* Initialize event */ KeInitializeEvent(&Event, NotificationEvent, FALSE); /* Set offset */ Offset.QuadPart = OffSet; /* Pre-init status block */ StatusBlock.Status = STATUS_NOT_SUPPORTED; /* Create Irp */ Irp = IoBuildSynchronousFsdRequest(MajorFunction, DeviceExtension->LowerDeviceObject, /* Verify */ Buffer, Length, &Offset, &Event, &StatusBlock); if (!Irp) { /* Failed to allocate memory */ return FALSE; } /* Setup a completion routine */ IoSetCompletionRoutine(Irp, StreamClassRWCompletion, (PVOID)&Event, TRUE, TRUE, TRUE); /* Call driver */ Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); if (Status == STATUS_PENDING) { /* Request is pending, wait for result */ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); /* Fetch result */ Status = StatusBlock.Status; } if (!NT_SUCCESS(Status)) { return FALSE; } /* FIXME Handle Length != InputLength */ return TRUE; }
NTSTATUS NTAPI DiskGetPortGeometry( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, OUT PDISK_GEOMETRY Geometry ) /*++ Routine Description: This routine will query the port driver for disk geometry. Some port drivers (in particular IDEPORT) may be able to provide geometry for the device. Arguments: FdoExtension - the device object for the disk. Geometry - a structure to save the geometry information into (if any is available) Return Value: STATUS_SUCCESS if geometry information can be provided or error status indicating why it can't. --*/ { PCOMMON_DEVICE_EXTENSION commonExtension = &(FdoExtension->CommonExtension); PIRP irp; PIO_STACK_LOCATION irpStack; KEVENT event; NTSTATUS status; PAGED_CODE(); // // Build an irp to send IOCTL_DISK_GET_DRIVE_GEOMETRY to the lower driver. // irp = IoAllocateIrp(commonExtension->LowerDeviceObject->StackSize, FALSE); if(irp == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } irpStack = IoGetNextIrpStackLocation(irp); irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_DISK_GET_DRIVE_GEOMETRY; irpStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(DISK_GEOMETRY); irp->AssociatedIrp.SystemBuffer = Geometry; KeInitializeEvent(&event, SynchronizationEvent, FALSE); IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE)ClassSignalCompletion, &event, TRUE, TRUE, TRUE); status = IoCallDriver(commonExtension->LowerDeviceObject, irp); KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); ASSERT((status == STATUS_PENDING) || (status == irp->IoStatus.Status)); status = irp->IoStatus.Status; IoFreeIrp(irp); return status; }
NTSTATUS ClasspCreateClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine will handle create/close operations for a given classpnp device if the class driver doesn't supply it's own handler. If there is a file object supplied for our driver (if it's a FO_DIRECT_DEVICE_OPEN file object) then it will initialize a file extension on create or destroy the extension on a close. Arguments: DeviceObject - the device object being opened or closed. Irp - the create/close irp Return Value: status --*/ { PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT fileObject = irpStack->FileObject; NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); // // ISSUE-2000/3/28-henrygab - if lower stack fails create/close, we end up // in an inconsistent state. re-write to verify all args and allocate all // required resources, then pass the irp down, then complete the // transaction. this is because we also cannot forward the irp, then fail // it after it has succeeded a lower-level driver. // if(irpStack->MajorFunction == IRP_MJ_CREATE) { PIO_SECURITY_CONTEXT securityContext = irpStack->Parameters.Create.SecurityContext; TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCREATEClose: create received for device %p\n", DeviceObject)); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCREATEClose: desired access %lx\n", securityContext->DesiredAccess)); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCREATEClose: file object %p\n", irpStack->FileObject)); NT_ASSERT(BreakOnClose == FALSE); if(irpStack->FileObject != NULL) { PFILE_OBJECT_EXTENSION fsContext; // // Allocate our own file object extension for this device object. // status = AllocateDictionaryEntry( &commonExtension->FileObjectDictionary, (ULONGLONG) irpStack->FileObject, sizeof(FILE_OBJECT_EXTENSION), CLASS_TAG_FILE_OBJECT_EXTENSION, &fsContext); if(NT_SUCCESS(status)) { RtlZeroMemory(fsContext, sizeof(FILE_OBJECT_EXTENSION)); fsContext->FileObject = irpStack->FileObject; fsContext->DeviceObject = DeviceObject; } else if (status == STATUS_OBJECT_NAME_COLLISION) { status = STATUS_SUCCESS; } } } else { TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCreateCLOSE: close received for device %p\n", DeviceObject)); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCreateCLOSE: file object %p\n", fileObject)); if(irpStack->FileObject != NULL) { PFILE_OBJECT_EXTENSION fsContext = ClassGetFsContext(commonExtension, irpStack->FileObject); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCreateCLOSE: file extension %p\n", fsContext)); if(fsContext != NULL) { TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCreateCLOSE: extension is ours - " "freeing\n")); NT_ASSERT(BreakOnClose == FALSE); ClasspCleanupProtectedLocks(fsContext); ClasspCleanupDisableMcn(fsContext); FreeDictionaryEntry(&(commonExtension->FileObjectDictionary), fsContext); } } } // // Notify the lower levels about the create or close operation - give them // a chance to cleanup too. // TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCreateClose: %s for devobj %p\n", (NT_SUCCESS(status) ? "Success" : "FAILED"), DeviceObject)); if(NT_SUCCESS(status)) { KEVENT event; // // Set up the event to wait on // KeInitializeEvent(&event, SynchronizationEvent, FALSE); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, ClassSignalCompletion, &event, TRUE, TRUE, TRUE); status = IoCallDriver(commonExtension->LowerDeviceObject, Irp); if(status == STATUS_PENDING) { (VOID)KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = Irp->IoStatus.Status; } if (!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClasspCreateClose: Lower driver failed, but we " "succeeded. This is a problem, lock counts will be " "out of sync between levels.\n")); } } return status; }
/************************************************************************* * * Function: Ext2CommonFlush() * * Description: * The actual work is performed here. This routine may be invoked in one' * of the two possible contexts: * (a) in the context of a system worker thread * (b) in the context of the original caller * * Expected Interrupt Level (for execution) : * * IRQL_PASSIVE_LEVEL * * Return Value: STATUS_SUCCESS/Error * *************************************************************************/ NTSTATUS NTAPI Ext2CommonFlush( PtrExt2IrpContext PtrIrpContext, PIRP PtrIrp) { NTSTATUS RC = STATUS_SUCCESS; PIO_STACK_LOCATION PtrIoStackLocation = NULL; PFILE_OBJECT PtrFileObject = NULL; PtrExt2FCB PtrFCB = NULL; PtrExt2CCB PtrCCB = NULL; PtrExt2VCB PtrVCB = NULL; PtrExt2NTRequiredFCB PtrReqdFCB = NULL; BOOLEAN AcquiredFCB = FALSE; BOOLEAN PostRequest = FALSE; BOOLEAN CanWait = TRUE; try { // First, get a pointer to the current I/O stack location PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); ASSERT(PtrIoStackLocation); PtrFileObject = PtrIoStackLocation->FileObject; ASSERT(PtrFileObject); // Get the FCB and CCB pointers PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2); ASSERT(PtrCCB); PtrFCB = PtrCCB->PtrFCB; AssertFCB( PtrFCB ); /*ASSERT(PtrFCB); ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB );*/ PtrReqdFCB = &(PtrFCB->NTRequiredFCB); // Get some of the parameters supplied to us CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); // If we cannot wait, post the request immediately since a flush is inherently blocking/synchronous. if (!CanWait) { PostRequest = TRUE; try_return(); } // Check the type of object passed-in. That will determine the course of // action we take. if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || (PtrFCB->FCBFlags & EXT2_FCB_ROOT_DIRECTORY)) { if (PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) { PtrVCB = (PtrExt2VCB)(PtrFCB); } else { PtrVCB = PtrFCB->PtrVCB; } // The caller wishes to flush all files for the mounted // logical volume. The flush volume routine below should simply // walk through all of the open file streams, acquire the // FCB resource, and request the flush operation from the Cache // Manager. Basically, the sequence of operations listed below // for a single file should be executed on all open files. Ext2FlushLogicalVolume(PtrIrpContext, PtrIrp, PtrVCB); try_return(); } if (!(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)) { // This is a regular file. ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE); AcquiredFCB = TRUE; // Request the Cache Manager to perform a flush operation. // Further, instruct the Cache Manager that we wish to flush the // entire file stream. Ext2FlushAFile(PtrReqdFCB, &(PtrIrp->IoStatus)); RC = PtrIrp->IoStatus.Status; // All done. You may want to also flush the directory entry for the // file stream at this time. // Some log-based FSD implementations may wish to flush their // log files at this time. Finally, you should update the time-stamp // values for the file stream appropriately. This would involve // obtaining the current time and modifying the appropriate directory // entry fields. } try_exit: if (AcquiredFCB) { Ext2ReleaseResource(&(PtrReqdFCB->MainResource)); DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Flush]", 0); DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Flush]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters ); AcquiredFCB = FALSE; } if (!PostRequest) { PIO_STACK_LOCATION PtrNextIoStackLocation = NULL; NTSTATUS RC1 = STATUS_SUCCESS; // Send the request down at this point. // To do this, you must set the next IRP stack location, and // maybe set a completion routine. // Be careful about marking the IRP pending if the lower level // driver returned pending and you do have a completion routine! PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp); *PtrNextIoStackLocation = *PtrIoStackLocation; // Set the completion routine to "eat-up" any // STATUS_INVALID_DEVICE_REQUEST error code returned by the lower // level driver. IoSetCompletionRoutine(PtrIrp, Ext2FlushCompletion, NULL, TRUE, TRUE, TRUE); /* * The exception handlers propably masked out the * fact that PtrVCB was never set. * -- Filip Navara, 18/08/2004 */ PtrVCB = PtrFCB->PtrVCB; RC1 = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp); RC = ((RC1 == STATUS_INVALID_DEVICE_REQUEST) ? RC : RC1); } } finally { if (PostRequest) { // Nothing to lock now. RC = Ext2PostRequest(PtrIrpContext, PtrIrp); } else { // Release the IRP context at this time. Ext2ReleaseIrpContext(PtrIrpContext); } } return(RC); }
__drv_mustHoldCriticalRegion NTSTATUS RfsdPnpSurpriseRemove ( PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb ) { NTSTATUS Status; KEVENT Event; BOOLEAN bDeleted; PAGED_CODE(); _SEH2_TRY { RfsdPrint((DBG_PNP, "RfsdPnpSupriseRemove by RfsdPnp ...\n")); #if (_WIN32_WINNT >= 0x0500) CcWaitForCurrentLazyWriterActivity(); #endif ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); Status = RfsdLockVcb(Vcb, IrpContext->FileObject); ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); // // Setup the Irp. We'll send it to the lower disk driver. // IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); KeInitializeEvent( &Event, NotificationEvent, FALSE ); IoSetCompletionRoutine( IrpContext->Irp, RfsdPnpCompletionRoutine, &Event, TRUE, TRUE, TRUE ); Status = IoCallDriver( Vcb->TargetDeviceObject, IrpContext->Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); Status = IrpContext->Irp->IoStatus.Status; } ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); RfsdPurgeVolume(Vcb, FALSE); ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); bDeleted = RfsdCheckDismount(IrpContext, Vcb, TRUE); } _SEH2_FINALLY { RfsdCompleteRequest( IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? IO_DISK_INCREMENT : IO_NO_INCREMENT) ); IrpContext->Irp = NULL; } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS RfsdPnpQueryRemove ( PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb ) { NTSTATUS Status; KEVENT Event; BOOLEAN bDeleted = FALSE; BOOLEAN VcbAcquired = FALSE; PAGED_CODE(); _SEH2_TRY { RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove by RfsdPnp ...\n")); RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdFlushVolume ...\n")); #if (_WIN32_WINNT >= 0x0500) CcWaitForCurrentLazyWriterActivity(); #endif ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); VcbAcquired = TRUE; RfsdFlushFiles(Vcb, FALSE); RfsdFlushVolume(Vcb, FALSE); RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdLockVcb: Vcb=%xh FileObject=%xh ...\n", Vcb, IrpContext->FileObject)); Status = RfsdLockVcb(Vcb, IrpContext->FileObject); RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdPurgeVolume ...\n")); RfsdPurgeVolume(Vcb, TRUE); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); VcbAcquired = FALSE; IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); KeInitializeEvent( &Event, NotificationEvent, FALSE ); IoSetCompletionRoutine( IrpContext->Irp, RfsdPnpCompletionRoutine, &Event, TRUE, TRUE, TRUE ); RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: Call lower level driver...\n")); Status = IoCallDriver( Vcb->TargetDeviceObject, IrpContext->Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); Status = IrpContext->Irp->IoStatus.Status; } if (NT_SUCCESS(Status)) { RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdCheckDismount ...\n")); bDeleted = RfsdCheckDismount(IrpContext, Vcb, TRUE); RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdFlushVolume bDelted=%xh ...\n", bDeleted)); } ASSERT( !(NT_SUCCESS(Status) && !bDeleted)); } _SEH2_FINALLY { if (VcbAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread() ); } RfsdCompleteRequest( IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? IO_DISK_INCREMENT : IO_NO_INCREMENT) ); IrpContext->Irp = NULL; } _SEH2_END; return Status; }
NTSTATUS XixFsdCommonDeviceControl( IN PXIFS_IRPCONTEXT pIrpContext ) { NTSTATUS RC = STATUS_SUCCESS; PIRP pIrp = NULL; PIO_STACK_LOCATION pIrpSp= NULL; PIO_STACK_LOCATION pNextIrpSp = NULL; PFILE_OBJECT PtrFileObject = NULL; PXIFS_FCB pFCB = NULL; PXIFS_CCB pCCB = NULL; PXIFS_VCB pVCB = NULL; BOOLEAN CompleteIrp = FALSE; ULONG IoControlCode = 0; void *BufferPointer = NULL; BOOLEAN Wait = FALSE; BOOLEAN PostRequest = FALSE; TYPE_OF_OPEN TypeOfOpen = UnopenedFileObject; KEVENT WaitEvent; PVOID CompletionContext = NULL; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_DEVCTL, ("Enter XixFsdCommonDeviceControl .\n")); DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, ("!!!!Enter XixFsdCommonDeviceControl \n")); ASSERT(pIrpContext); ASSERT(pIrpContext->Irp); pIrp = pIrpContext->Irp; try { Wait = XifsdCheckFlagBoolean(pIrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT); if(!Wait){ PostRequest = TRUE; try_return(RC = STATUS_PENDING); } // First, get a pointer to the current I/O stack location pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrpSp); PtrFileObject = pIrpSp->FileObject; ASSERT(PtrFileObject); DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_DEVCTL, (" Decode File Object\n")); TypeOfOpen = XixFsdDecodeFileObject( PtrFileObject, &pFCB, &pCCB ); DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_DEVCTL|DEBUG_TARGET_IRPCONTEXT), ("pIrpSp->Parameters.DeviceIoControl.IoControlCode(0x%02x) .\n", pIrpSp->Parameters.DeviceIoControl.IoControlCode)); if (TypeOfOpen == UserVolumeOpen) { pVCB = (PXIFS_VCB)(pFCB ->PtrVCB); ASSERT_VCB(pVCB); } else { DebugTrace(DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ("User Volume Open Not supported!!.\n")); RC = STATUS_INVALID_PARAMETER; XixFsdCompleteRequest(pIrpContext, RC, 0); try_return(RC); } switch(pIrpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES: //DbgPrint("!!! IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES\n"); XifsdAcquireVcbExclusive(TRUE, pVCB, FALSE); XixFsdFlusVolume(pIrpContext, pVCB); KeInitializeEvent( &WaitEvent, NotificationEvent, FALSE ); CompletionContext = &WaitEvent; IoCopyCurrentIrpStackLocationToNext(pIrp ); IoSetCompletionRoutine(pIrp, XixFsdDevFlushAndHoldWriteCompletionRoutine, CompletionContext, TRUE, TRUE, TRUE ); break; default: IoSkipCurrentIrpStackLocation( pIrp ); /* IoCopyCurrentIrpStackLocationToNext(pIrp ); // Set a completion routine. IoSetCompletionRoutine(pIrp, XixFsdDevIoctlCompletion, NULL, TRUE, TRUE, TRUE); */ break; } // Send the request. RC = IoCallDriver(pVCB->TargetDeviceObject, pIrp); if(RC == STATUS_PENDING && CompletionContext){ //DbgPrint("!!! IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES2\n"); KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL); RC = pIrp->IoStatus.Status; } if(CompletionContext) { /* DbgPrint("!!! IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES RC(0x%x) Status(0x%x) Information(%ld) \n", RC, pIrp->IoStatus.Status, pIrp->IoStatus.Information); */ XifsdReleaseVcb(TRUE, pVCB); XixFsdCompleteRequest(pIrpContext, RC, (uint32)pIrp->IoStatus.Information); }else{ XixFsdReleaseIrpContext(pIrpContext); } } finally { if (!(pIrpContext->IrpContextFlags & XIFSD_IRP_CONTEXT_EXCEPTION)) { ; } if(PostRequest ){ DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_DEVCTL|DEBUG_TARGET_IRPCONTEXT), ("PostRequest pIrpCotnext(0x%x) pIrp(0x%x)\n", pIrpContext, pIrp)); RC = XixFsdPostRequest(pIrpContext, pIrp); } } DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_DEVCTL, ("Exit XixFsdCommonDeviceControl .\n")); return(RC); }
NTSTATUS FatCommonDeviceControl ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for doing Device control operations called by both the fsd and fsp threads Arguments: Irp - Supplies the Irp to process InFsp - Indicates if this is the fsp thread or someother thread Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; KEVENT WaitEvent; PVOID CompletionContext = NULL; PVCB Vcb; PFCB Fcb; PCCB Ccb; #ifdef __ND_FAT_PRIMARY__ if (IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL && IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode == IOCTL_INSERT_PRIMARY_SESSION) { PVOLUME_DEVICE_OBJECT VolDo = CONTAINING_RECORD( IoGetCurrentIrpStackLocation(Irp)->DeviceObject, VOLUME_DEVICE_OBJECT, DeviceObject ); PSESSION_INFORMATION inputBuffer = (PSESSION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ULONG inputBufferLength = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.InputBufferLength; ULONG outputBufferLength; PULONG outputBuffer; PPRIMARY_SESSION primarySession; if (inputBufferLength != sizeof(SESSION_INFORMATION)) { FatCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_PARAMETER ); return Status; } outputBufferLength = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.OutputBufferLength; outputBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer; primarySession = PrimarySession_Create( IrpContext, VolDo, inputBuffer, Irp ); ASSERT( primarySession ); FatCompleteRequest( IrpContext, NULL, 0 ); Status = STATUS_PENDING; return Status; } #endif // // Get a pointer to the current Irp stack location // IrpSp = IoGetCurrentIrpStackLocation( Irp ); DebugTrace(+1, Dbg, "FatCommonDeviceControl\n", 0); DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp); DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction); // // Decode the file object, the only type of opens we accept are // user volume opens. // if (FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb ) != UserVolumeOpen) { FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); DebugTrace(-1, Dbg, "FatCommonDeviceControl -> %08lx\n", STATUS_INVALID_PARAMETER); return STATUS_INVALID_PARAMETER; } // // A few IOCTLs actually require some intervention on our part // switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES: #ifdef __ND_FAT_WIN2K_SUPPORT__ if (!IS_WINDOWSXP_OR_LATER()) { ASSERT( FALSE ); IoSkipCurrentIrpStackLocation( Irp ); break; } #endif // // This is sent by the Volume Snapshot driver (Lovelace). // We flush the volume, and hold all file resources // to make sure that nothing more gets dirty. Then we wait // for the IRP to complete or cancel. // SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ); FatAcquireExclusiveVolume( IrpContext, Vcb ); FatFlushAndCleanVolume( IrpContext, Irp, Vcb, FlushWithoutPurge ); KeInitializeEvent( &WaitEvent, NotificationEvent, FALSE ); CompletionContext = &WaitEvent; // // Get the next stack location, and copy over the stack location // IoCopyCurrentIrpStackLocationToNext( Irp ); // // Set up the completion routine // IoSetCompletionRoutine( Irp, FatDeviceControlCompletionRoutine, CompletionContext, TRUE, TRUE, TRUE ); break; default: // // FAT doesn't need to see this on the way back, so skip ourselves. // IoSkipCurrentIrpStackLocation( Irp ); break; } // // Send the request. // Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); if (Status == STATUS_PENDING && CompletionContext) { KeWaitForSingleObject( &WaitEvent, Executive, KernelMode, FALSE, NULL ); Status = Irp->IoStatus.Status; } // // If we had a context, the IRP remains for us and we will complete it. // Handle it appropriately. // if (CompletionContext) { // // Release all the resources that we held because of a // VOLSNAP_FLUSH_AND_HOLD. // ASSERT( IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES ); FatReleaseVolume( IrpContext, Vcb ); // // If we had no context, the IRP will complete asynchronously. // } else { Irp = NULL; } FatCompleteRequest( IrpContext, Irp, Status ); DebugTrace(-1, Dbg, "FatCommonDeviceControl -> %08lx\n", Status); return Status; }
NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp) { // DispatchPnp PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); ULONG fcn = stack->MinorFunction; NTSTATUS status; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp); if (!NT_SUCCESS(status)) return CompleteRequest(Irp, status, 0); #if DBG static char* pnpname[] = { "IRP_MN_START_DEVICE", "IRP_MN_QUERY_REMOVE_DEVICE", "IRP_MN_REMOVE_DEVICE", "IRP_MN_CANCEL_REMOVE_DEVICE", "IRP_MN_STOP_DEVICE", "IRP_MN_QUERY_STOP_DEVICE", "IRP_MN_CANCEL_STOP_DEVICE", "IRP_MN_QUERY_DEVICE_RELATIONS", "IRP_MN_QUERY_INTERFACE", "IRP_MN_QUERY_CAPABILITIES", "IRP_MN_QUERY_RESOURCES", "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", "IRP_MN_QUERY_DEVICE_TEXT", "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", "", "IRP_MN_READ_CONFIG", "IRP_MN_WRITE_CONFIG", "IRP_MN_EJECT", "IRP_MN_SET_LOCK", "IRP_MN_QUERY_ID", "IRP_MN_QUERY_PNP_DEVICE_STATE", "IRP_MN_QUERY_BUS_INFORMATION", "IRP_MN_DEVICE_USAGE_NOTIFICATION", "IRP_MN_SURPRISE_REMOVAL", "IRP_MN_QUERY_LEGACY_BUS_INFORMATION", }; if (fcn < arraysize(pnpname)) KdPrint((DRIVERNAME " - IRP_MJ_PNP (%s)\n", pnpname[fcn])); else KdPrint((DRIVERNAME " - IRP_MJ_PNP (%2.2X)\n", fcn)); #endif // DBG // Handle usage notification specially in order to track power pageable // flag correctly. We need to avoid allowing a non-pageable handler to be // layered on top of a pageable handler. if (fcn == IRP_MN_DEVICE_USAGE_NOTIFICATION) { // usage notification if (!fido->AttachedDevice || (fido->AttachedDevice->Flags & DO_POWER_PAGABLE)) fido->Flags |= DO_POWER_PAGABLE; IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) UsageNotificationCompletionRoutine, (PVOID) pdx, TRUE, TRUE, TRUE); return IoCallDriver(pdx->LowerDeviceObject, Irp); } // usage notification // Handle start device specially in order to correctly inherit // FILE_REMOVABLE_MEDIA if (fcn == IRP_MN_START_DEVICE) { // device start IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) StartDeviceCompletionRoutine, (PVOID) pdx, TRUE, TRUE, TRUE); return IoCallDriver(pdx->LowerDeviceObject, Irp); } // device start // Handle remove device specially in order to cleanup device stack if (fcn == IRP_MN_REMOVE_DEVICE) { // remove device IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(pdx->LowerDeviceObject, Irp); IoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp); RemoveDevice(fido); return status; } // remove device // Simply forward any other type of PnP request IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(pdx->LowerDeviceObject, Irp); IoReleaseRemoveLock(&pdx->RemoveLock, Irp); return status; } // DispatchPnp
NTSTATUS FatPnpQueryRemove ( PIRP_CONTEXT IrpContext, PIRP Irp, PVCB Vcb ) /*++ Routine Description: This routine handles the PnP query remove operation. The filesystem is responsible for answering whether there are any reasons it sees that the volume can not go away (and the device removed). Initiation of the dismount begins when we answer yes to this question. Query will be followed by a Cancel or Remove. Arguments: Irp - Supplies the Irp to process Vcb - Supplies the volume being queried. Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; KEVENT Event; BOOLEAN VcbDeleted = FALSE; BOOLEAN GlobalHeld = FALSE; // // Having said yes to a QUERY, any communication with the // underlying storage stack is undefined (and may block) // until the bounding CANCEL or REMOVE is sent. // // // Acquire the global resource so that we can try to vaporize // the volume, and the vcb resource itself. // FatAcquireExclusiveVcb( IrpContext, Vcb ); try { Status = FatLockVolumeInternal( IrpContext, Vcb, NULL ); // // Reacquire the resources in the right order. // FatReleaseVcb( IrpContext, Vcb ); FatAcquireExclusiveGlobal( IrpContext ); GlobalHeld = TRUE; FatAcquireExclusiveVcb( IrpContext, Vcb ); if (NT_SUCCESS( Status )) { // // With the volume held locked, note that we must finalize as much // as possible right now. // FatFlushAndCleanVolume( IrpContext, Irp, Vcb, Flush ); // // We need to pass this down before starting the dismount, which // could disconnect us immediately from the stack. // // // Get the next stack location, and copy over the stack location // IoCopyCurrentIrpStackLocationToNext( Irp ); // // Set up the completion routine // KeInitializeEvent( &Event, NotificationEvent, FALSE ); IoSetCompletionRoutine( Irp, FatPnpCompletionRoutine, &Event, TRUE, TRUE, TRUE ); // // Send the request and wait. // Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); Status = Irp->IoStatus.Status; } // // Now if no one below us failed already, initiate the dismount // on this volume, make it go away. PnP needs to see our internal // streams close and drop their references to the target device. // // Since we were able to lock the volume, we are guaranteed to // move this volume into dismount state and disconnect it from // the underlying storage stack. The force on our part is actually // unnecesary, though complete. // // What is not strictly guaranteed, though, is that the closes // for the metadata streams take effect synchronously underneath // of this call. This would leave references on the target device // even though we are disconnected! // if (NT_SUCCESS( Status )) { VcbDeleted = FatCheckForDismount( IrpContext, Vcb, TRUE ); ASSERT( VcbDeleted || Vcb->VcbCondition == VcbBad ); } } } finally { // // Release the Vcb if it could still remain. // if (!VcbDeleted) { FatReleaseVcb( IrpContext, Vcb ); } if (GlobalHeld) { FatReleaseGlobal( IrpContext ); } } // // Cleanup our IrpContext and complete the IRP if neccesary. // FatCompleteRequest( IrpContext, Irp, Status ); return Status; }
NTSTATUS HandleDeviceSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { KIRQL oldIrql; NTSTATUS ntStatus; POWER_STATE newState; PIO_STACK_LOCATION irpStack; PDEVICE_EXTENSION deviceExtension; DEVICE_POWER_STATE newDevState, oldDevState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Entered\n")); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); oldDevState = deviceExtension->DevPower; newState = irpStack->Parameters.Power.State; newDevState = newState.DeviceState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Set request for device power state D%X\n" "FBTUSB: HandleDeviceSetPower: Current device power state D%X\n", newDevState - 1, deviceExtension->DevPower - 1)); if (newDevState < oldDevState) { FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Adding power to the device\n")); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)FinishDevPoUpIrp, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } else { // newDevState >= oldDevState // hold I/O if transition from D0 -> DX (X = 1, 2, 3) // if transition from D1 or D2 to deeper sleep states, // I/O queue is already on hold. if(PowerDeviceD0 == oldDevState && newDevState > oldDevState) { // D0 -> DX transition FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Removing power from the device\n")); ntStatus = HoldIoRequests(DeviceObject, Irp); if (!NT_SUCCESS(ntStatus)) { PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower::")); FreeBT_IoDecrement(deviceExtension); return ntStatus; } else { goto HandleDeviceSetPower_Exit; } } else if (PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState) { // D0 -> D0 // unblock the queue which may have been blocked processing // query irp FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: A SetD0 request\n")); KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql); deviceExtension->QueueState = AllowRequests; KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql); ProcessQueuedRequests(deviceExtension); } IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: HandleDeviceSetPower: Lower drivers failed a power Irp\n")); } } HandleDeviceSetPower_Exit: FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Leaving\n")); return STATUS_PENDING; }
NTSTATUS FatPnpRemove ( PIRP_CONTEXT IrpContext, PIRP Irp, PVCB Vcb ) /*++ Routine Description: This routine handles the PnP remove operation. This is our notification that the underlying storage device for the volume we have is gone, and an excellent indication that the volume will never reappear. The filesystem is responsible for initiation or completion of the dismount. Arguments: Irp - Supplies the Irp to process Vcb - Supplies the volume being removed. Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; KEVENT Event; BOOLEAN VcbDeleted; // // REMOVE - a storage device is now gone. We either got // QUERY'd and said yes OR got a SURPRISE OR a storage // stack failed to spin back up from a sleep/stop state // (the only case in which this will be the first warning). // // Note that it is entirely unlikely that we will be around // for a REMOVE in the first two cases, as we try to intiate // dismount. // // // Acquire the global resource so that we can try to vaporize // the volume, and the vcb resource itself. // FatAcquireExclusiveGlobal( IrpContext ); FatAcquireExclusiveVcb( IrpContext, Vcb ); // // The device will be going away. Remove our lock (benign // if we never had it). // (VOID) FatUnlockVolumeInternal( IrpContext, Vcb, NULL ); // // We need to pass this down before starting the dismount, which // could disconnect us immediately from the stack. // // // Get the next stack location, and copy over the stack location // IoCopyCurrentIrpStackLocationToNext( Irp ); // // Set up the completion routine // KeInitializeEvent( &Event, NotificationEvent, FALSE ); IoSetCompletionRoutine( Irp, FatPnpCompletionRoutine, &Event, TRUE, TRUE, TRUE ); // // Send the request and wait. // Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); Status = Irp->IoStatus.Status; } try { // // Knock as many files down for this volume as we can. // FatFlushAndCleanVolume( IrpContext, Irp, Vcb, NoFlush ); // // Now make our dismount happen. This may not vaporize the // Vcb, of course, since there could be any number of handles // outstanding if we were not preceeded by a QUERY. // // PnP will take care of disconnecting this stack if we // couldn't get off of it immediately. // VcbDeleted = FatCheckForDismount( IrpContext, Vcb, TRUE ); } finally { // // Release the Vcb if it could still remain. // if (!VcbDeleted) { FatReleaseVcb( IrpContext, Vcb ); } FatReleaseGlobal( IrpContext ); } // // Cleanup our IrpContext and complete the IRP. // FatCompleteRequest( IrpContext, Irp, Status ); return Status; }
NTSTATUS Ext2ReadWriteBlocks( IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_EXTENT Chain, IN ULONG Length, IN BOOLEAN bVerify ) { PIRP Irp; PIRP MasterIrp = IrpContext->Irp; PIO_STACK_LOCATION IrpSp; PMDL Mdl; PEXT2_RW_CONTEXT pContext = NULL; PEXT2_EXTENT Extent; KEVENT Wait; NTSTATUS Status = STATUS_SUCCESS; BOOLEAN bBugCheck = FALSE; ASSERT(MasterIrp); __try { pContext = Ext2AllocatePool(NonPagedPool, sizeof(EXT2_RW_CONTEXT), EXT2_RWC_MAGIC); if (!pContext) { DEBUG(DL_ERR, ( "Ex2ReadWriteBlocks: failed to allocate pContext.\n")); Status = STATUS_INSUFFICIENT_RESOURCES; __leave; } INC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); RtlZeroMemory(pContext, sizeof(EXT2_RW_CONTEXT)); pContext->Wait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); pContext->MasterIrp = MasterIrp; pContext->Length = Length; if (IrpContext->MajorFunction == IRP_MJ_WRITE) { SetFlag(pContext->Flags, EXT2_RW_CONTEXT_WRITE); } if (pContext->Wait) { KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE); } else if (IrpContext->Fcb->Identifier.Type == EXT2FCB) { if (IsFlagOn(MasterIrp->Flags, IRP_PAGING_IO)) { pContext->Resource = &IrpContext->Fcb->PagingIoResource; } else { pContext->Resource = &IrpContext->Fcb->MainResource; } pContext->FileObject = IrpContext->FileObject; pContext->ThreadId = ExGetCurrentResourceThread(); } if (NULL == Chain->Next && 0 == Chain->Offset) { /* we get only 1 extent to dispatch, then don't bother allocating new irps */ /* setup the Stack location to do a read from the disk driver. */ IrpSp = IoGetNextIrpStackLocation(MasterIrp); IrpSp->MajorFunction = IrpContext->MajorFunction; IrpSp->Parameters.Read.Length = Chain->Length; IrpSp->Parameters.Read.ByteOffset.QuadPart = Chain->Lba; if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) { SetFlag(IrpSp->Flags, SL_WRITE_THROUGH); } if (bVerify || IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) { SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME); } IoSetCompletionRoutine( MasterIrp, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ? Ext2ReadWriteBlockSyncCompletionRoutine : Ext2ReadWriteBlockAsyncCompletionRoutine, (PVOID) pContext, TRUE, TRUE, TRUE ); /* intialize context block */ Chain->Irp = MasterIrp; pContext->Blocks = 1; } else { for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { Irp = IoMakeAssociatedIrp( MasterIrp, (CCHAR)(Vcb->TargetDeviceObject->StackSize + 1) ); if (!Irp) { Status = STATUS_INSUFFICIENT_RESOURCES; __leave; } Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer + Extent->Offset, Extent->Length, FALSE, FALSE, Irp ); if (!Mdl) { Status = STATUS_INSUFFICIENT_RESOURCES; __leave; } IoBuildPartialMdl( MasterIrp->MdlAddress, Mdl, (PCHAR)MasterIrp->UserBuffer +Extent->Offset, Extent->Length ); IoSetNextIrpStackLocation(Irp); IrpSp = IoGetCurrentIrpStackLocation(Irp); IrpSp->MajorFunction = IrpContext->MajorFunction; IrpSp->Parameters.Read.Length = Extent->Length; IrpSp->Parameters.Read.ByteOffset.QuadPart = Extent->Lba; IoSetCompletionRoutine( Irp, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ? Ext2ReadWriteBlockSyncCompletionRoutine : Ext2ReadWriteBlockAsyncCompletionRoutine, (PVOID) pContext, TRUE, TRUE, TRUE ); IrpSp = IoGetNextIrpStackLocation(Irp); IrpSp->MajorFunction = IrpContext->MajorFunction; IrpSp->Parameters.Read.Length =Extent->Length; IrpSp->Parameters.Read.ByteOffset.QuadPart = Extent->Lba; /* set write through flag */ if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) { SetFlag( IrpSp->Flags, SL_WRITE_THROUGH ); } /* set verify flag */ if (bVerify ||IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) { SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME); } Extent->Irp = Irp; pContext->Blocks += 1; } MasterIrp->AssociatedIrp.IrpCount = pContext->Blocks; if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) { MasterIrp->AssociatedIrp.IrpCount += 1; } } if (!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) { /* mark MasterIrp pending */ IoMarkIrpPending(pContext->MasterIrp); } bBugCheck = TRUE; for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { Status = IoCallDriver ( Vcb->TargetDeviceObject, Extent->Irp); Extent->Irp = NULL; } if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) { KeWaitForSingleObject( &(pContext->Event), Executive, KernelMode, FALSE, NULL ); KeClearEvent( &(pContext->Event) ); } } __finally { for (Extent = Chain; Extent != NULL; Extent = Extent->Next) { if (Extent->Irp != NULL ) { if (Extent->Irp->MdlAddress != NULL) { IoFreeMdl(Extent->Irp->MdlAddress ); } IoFreeIrp(Extent->Irp); } } if (AbnormalTermination()) { if (bBugCheck) { Ext2BugCheck(EXT2_BUGCHK_BLOCK, 0, 0, 0); } if (pContext) { Ext2FreePool(pContext, EXT2_RWC_MAGIC); DEC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); } } else { if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) { if (MasterIrp) { Status = MasterIrp->IoStatus.Status; } if (pContext) { Ext2FreePool(pContext, EXT2_RWC_MAGIC); DEC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT)); } } else { IrpContext->Irp = NULL; Status = STATUS_PENDING; } } } return Status; }
NTSTATUS FatPnpSurpriseRemove ( PIRP_CONTEXT IrpContext, PIRP Irp, PVCB Vcb ) /*++ Routine Description: This routine handles the PnP surprise remove operation. This is another type of notification that the underlying storage device for the volume we have is gone, and is excellent indication that the volume will never reappear. The filesystem is responsible for initiation or completion the dismount. For the most part, only "real" drivers care about the distinction of a surprise remove, which is a result of our noticing that a user (usually) physically reached into the machine and pulled something out. Surprise will be followed by a Remove when all references have been shut down. Arguments: Irp - Supplies the Irp to process Vcb - Supplies the volume being removed. Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; KEVENT Event; BOOLEAN VcbDeleted; // // SURPRISE - a device was physically yanked away without // any warning. This means external forces. // FatAcquireExclusiveGlobal( IrpContext ); FatAcquireExclusiveVcb( IrpContext, Vcb ); // // We need to pass this down before starting the dismount, which // could disconnect us immediately from the stack. // // // Get the next stack location, and copy over the stack location // IoCopyCurrentIrpStackLocationToNext( Irp ); // // Set up the completion routine // KeInitializeEvent( &Event, NotificationEvent, FALSE ); IoSetCompletionRoutine( Irp, FatPnpCompletionRoutine, &Event, TRUE, TRUE, TRUE ); // // Send the request and wait. // Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); Status = Irp->IoStatus.Status; } try { // // Knock as many files down for this volume as we can. // FatFlushAndCleanVolume( IrpContext, Irp, Vcb, NoFlush ); // // Now make our dismount happen. This may not vaporize the // Vcb, of course, since there could be any number of handles // outstanding since this is an out of band notification. // VcbDeleted = FatCheckForDismount( IrpContext, Vcb, TRUE ); } finally { // // Release the Vcb if it could still remain. // if (!VcbDeleted) { FatReleaseVcb( IrpContext, Vcb ); } FatReleaseGlobal( IrpContext ); } // // Cleanup our IrpContext and complete the IRP. // FatCompleteRequest( IrpContext, Irp, Status ); return Status; }
NTSTATUS Serenum_FDO_Power(PFDO_DEVICE_DATA Data, PIRP Irp) /*++ --*/ { NTSTATUS status; BOOLEAN hookit = FALSE; POWER_STATE powerState; POWER_STATE_TYPE powerType; PIO_STACK_LOCATION stack; stack = IoGetCurrentIrpStackLocation(Irp); powerType = stack->Parameters.Power.Type; powerState = stack->Parameters.Power.State; status = Serenum_IncIoCount (Data); if (!NT_SUCCESS(status)) { Irp->IoStatus.Information = 0; Irp->IoStatus.Status = status; PoStartNextPowerIrp(Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } switch (stack->MinorFunction) { case IRP_MN_SET_POWER: // // If it hasn't started, we just pass it through // if (Data->Started != TRUE) { status = Irp->IoStatus.Status = STATUS_SUCCESS; break; } Serenum_KdPrint(Data, SER_DBG_PNP_TRACE, ("Serenum-PnP Setting %s state to %d\n", ((powerType == SystemPowerState) ? "System" : "Device"), powerState.SystemState)); switch (powerType) { case DevicePowerState: status = Irp->IoStatus.Status = STATUS_SUCCESS; if (Data->DeviceState < powerState.DeviceState) { PoSetPowerState (Data->Self, powerType, powerState); Data->DeviceState = powerState.DeviceState; } else if (Data->DeviceState > powerState.DeviceState) { // // Powering Up // hookit = TRUE; } break; case SystemPowerState: // // status should be STATUS_SUCCESS // break; } break; case IRP_MN_QUERY_POWER: status = Irp->IoStatus.Status = STATUS_SUCCESS; break; default: // // status should be STATUS_SUCCESS // break; } IoCopyCurrentIrpStackLocationToNext (Irp); if (hookit) { status = Serenum_IncIoCount (Data); ASSERT (STATUS_SUCCESS == status); IoSetCompletionRoutine(Irp, Serenum_FDOPowerComplete, NULL, TRUE, TRUE, TRUE); status = PoCallDriver (Data->TopOfStack, Irp); } else { PoStartNextPowerIrp (Irp); status = PoCallDriver (Data->TopOfStack, Irp); } Serenum_DecIoCount (Data); return status; }
NTSTATUS NdasDluSendIoctlSrbAsynch( IN PDEVICE_OBJECT DeviceObject, IN ULONG IoctlCode, IN PVOID InputBuffer, IN LONG InputBufferLength, OUT PVOID OutputBuffer, IN LONG OutputBufferLength ){ PIRP irp; PMINISENDSRB_CONTEXT context = NULL; PSRB_IO_CONTROL psrbIoctl; PSCSI_REQUEST_BLOCK srb; LONG srbIoctlLength; PVOID srbIoctlBuffer; LONG srbIoctlBufferLength; NTSTATUS status; PIO_STACK_LOCATION irpStack; LARGE_INTEGER startingOffset; IO_STATUS_BLOCK ioStatusBlock; ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); psrbIoctl = NULL; irp = NULL; // // build an SRB for the miniport // srbIoctlBufferLength = (InputBufferLength>OutputBufferLength)?InputBufferLength:OutputBufferLength; srbIoctlLength = sizeof(SRB_IO_CONTROL) + srbIoctlBufferLength; context = (PMINISENDSRB_CONTEXT)ExAllocatePoolWithTag(NonPagedPool, FIELD_OFFSET(MINISENDSRB_CONTEXT, SrbIoctl) + srbIoctlLength, NDAS_DLU_PTAG_SRB_CMPDATA); if(context == NULL) { KDPrint(1, ("STATUS_INSUFFICIENT_RESOURCES\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } context->UserBuffer = OutputBuffer; context->UserBufferLen = OutputBufferLength; srb = &context->Srb; psrbIoctl = &context->SrbIoctl; RtlZeroMemory(psrbIoctl, srbIoctlLength); psrbIoctl->HeaderLength = sizeof(SRB_IO_CONTROL); RtlCopyMemory(psrbIoctl->Signature, NDASSCSI_IOCTL_SIGNATURE, 8); psrbIoctl->Timeout = 10; psrbIoctl->ControlCode = IoctlCode; psrbIoctl->Length = srbIoctlBufferLength; srbIoctlBuffer = (PUCHAR)psrbIoctl + sizeof(SRB_IO_CONTROL); RtlCopyMemory(srbIoctlBuffer, InputBuffer, InputBufferLength); startingOffset.QuadPart = 1; // // Build IRP for this request. // Note we do this synchronously for two reasons. If it was done // asynchronously then the completion code would have to make a special // check to deallocate the buffer. Second if a completion routine were // used then an additional IRP stack location would be needed. // irp = IoBuildAsynchronousFsdRequest( IRP_MJ_SCSI, DeviceObject, psrbIoctl, srbIoctlLength, &startingOffset, &ioStatusBlock); context->Irp = irp; IoSetCompletionRoutine(irp, NdasDluSendSrbIoCompletion, context, TRUE, TRUE, TRUE); irpStack = IoGetNextIrpStackLocation(irp); if (irp == NULL) { KDPrint(1,("STATUS_INSUFFICIENT_RESOURCES\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } // // Set major and minor codes. // irpStack->MajorFunction = IRP_MJ_SCSI; irpStack->MinorFunction = 1; // // Fill in SRB fields. // irpStack->Parameters.Others.Argument1 = srb; // // Zero out the srb. // RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); srb->PathId = 0; srb->TargetId = 0; srb->Lun = 0; srb->Function = SRB_FUNCTION_IO_CONTROL; srb->Length = sizeof(SCSI_REQUEST_BLOCK); srb->SrbFlags = SRB_FLAGS_DATA_OUT | SRB_FLAGS_NO_QUEUE_FREEZE; srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; srb->QueueTag = SP_UNTAGGED; srb->OriginalRequest = irp; // // Set timeout to requested value. // srb->TimeOutValue = psrbIoctl->Timeout; // // Set the data buffer. // srb->DataBuffer = psrbIoctl; srb->DataTransferLength = srbIoctlLength; // // Flush the data buffer for output. This will insure that the data is // written back to memory. Since the data-in flag is the the port driver // will flush the data again for input which will ensure the data is not // in the cache. // /* KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE); */ status = IoCallDriver( DeviceObject, irp ); return status; cleanup: if(context) ExFreePool(context); return status; }
NTSTATUS StartPolling(PDEVICE_EXTENSION pdx) { PIO_STACK_LOCATION stack; KIRQL OldIrql; NTSTATUS status; ASSERT(pdx->PollingIrp); KeAcquireSpinLock(&pdx->PollLock, &OldIrql); if(pdx->PollPending) { KeReleaseSpinLock(&pdx->PollLock, OldIrql); return STATUS_SUCCESS; } KeReleaseSpinLock(&pdx->PollLock, OldIrql); status = IoAcquireRemoveLock(&pdx->RemoveLock, pdx->PollingIrp); if(!NT_SUCCESS(status)) { KeAcquireSpinLock(&pdx->PollLock, &OldIrql); pdx->PollPending = FALSE; KeReleaseSpinLock(&pdx->PollLock, OldIrql); return status; } // safe to do since we passed in FALSE for the second parameter // of IoAllocateIrp IoInitializeIrp(pdx->PollingIrp, sizeof(IRP), pdx->LowerDeviceObject->StackSize); IoSetCompletionRoutine( pdx->PollingIrp, (PIO_COMPLETION_ROUTINE) OnPollComplete, pdx, TRUE, TRUE, TRUE ); stack = IoGetNextIrpStackLocation(pdx->PollingIrp); memset(&pdx->PollingUrb, 0, sizeof(URB)); UsbBuildInterruptOrBulkTransferRequest( &pdx->PollingUrb, sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER), pdx->hinpipe, &pdx->PollingBuffer[0], NULL, POLLING_BUFFER_SIZE, (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), NULL ); stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; stack->Parameters.Others.Argument1 = &pdx->PollingUrb; pdx->PollPending = TRUE; return IoCallDriver(pdx->LowerDeviceObject, pdx->PollingIrp); }
static FORCEINLINE NTSTATUS __DriverQueryId( IN PDEVICE_OBJECT PhysicalDeviceObject, IN BUS_QUERY_ID_TYPE IdType, OUT PVOID *Information ) { PDEVICE_OBJECT DeviceObject; PIRP Irp; KEVENT Event; PIO_STACK_LOCATION StackLocation; NTSTATUS status; ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); DeviceObject = IoGetAttachedDeviceReference(PhysicalDeviceObject); Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); status = STATUS_INSUFFICIENT_RESOURCES; if (Irp == NULL) goto fail1; StackLocation = IoGetNextIrpStackLocation(Irp); StackLocation->MajorFunction = IRP_MJ_PNP; StackLocation->MinorFunction = IRP_MN_QUERY_ID; StackLocation->Flags = 0; StackLocation->Parameters.QueryId.IdType = IdType; StackLocation->DeviceObject = DeviceObject; StackLocation->FileObject = NULL; KeInitializeEvent(&Event, NotificationEvent, FALSE); IoSetCompletionRoutine(Irp, DriverQueryIdCompletion, &Event, TRUE, TRUE, TRUE); // Default completion status Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; status = IoCallDriver(DeviceObject, Irp); if (status == STATUS_PENDING) { (VOID) KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); status = Irp->IoStatus.Status; } else { ASSERT3U(status, ==, Irp->IoStatus.Status); } if (!NT_SUCCESS(status)) goto fail2; *Information = (PVOID)Irp->IoStatus.Information; IoFreeIrp(Irp); ObDereferenceObject(DeviceObject); return STATUS_SUCCESS; fail2: Error("fail2\n"); IoFreeIrp(Irp); fail1: Error("fail1 (%08x)\n", status); ObDereferenceObject(DeviceObject); return status; }
NTSTATUS Ext2DeviceControlNormal (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; BOOLEAN CompleteRequest = TRUE; NTSTATUS Status = STATUS_UNSUCCESSFUL; PEXT2_VCB Vcb; PIRP Irp; PIO_STACK_LOCATION IrpSp; PIO_STACK_LOCATION NextIrpSp; PDEVICE_OBJECT TargetDeviceObject; __try { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); CompleteRequest = TRUE; DeviceObject = IrpContext->DeviceObject; if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp); Vcb = (PEXT2_VCB) IrpSp->FileObject->FsContext; if (!((Vcb) && (Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { Status = STATUS_INVALID_PARAMETER; __leave; } TargetDeviceObject = Vcb->TargetDeviceObject; // // Pass on the IOCTL to the driver below // CompleteRequest = FALSE; NextIrpSp = IoGetNextIrpStackLocation( Irp ); *NextIrpSp = *IrpSp; IoSetCompletionRoutine( Irp, Ext2DeviceControlCompletion, NULL, FALSE, TRUE, TRUE ); Status = IoCallDriver(TargetDeviceObject, Irp); } __finally { if (!IrpContext->ExceptionInProgress) { if (IrpContext) { if (!CompleteRequest) { IrpContext->Irp = NULL; } Ext2CompleteIrpContext(IrpContext, Status); } } } return Status; }
VOID DCamDetachAndCancelOnePacket( IN PHW_STREAM_REQUEST_BLOCK pSrbToCancel, PISOCH_DESCRIPTOR IsochDescriptorToDetach, HANDLE hResource, PDEVICE_OBJECT pBusDeviceObject ) /*++ Routine Description: Detach an isoch descriptor and then cancel pending SRB in the completion routine. Arguments: pSrbToCancel - Pointer to SRB to cancel IsochDescriptorToDetach - Iosch descriptor to detach hResource - isoch resource allocated hBusDeviceObject - bus device object Return Value: None. --*/ { PIO_STACK_LOCATION NextIrpStack; NTSTATUS Status; PIRB pIrb; PIRP pIrp; DbgMsg2(("\'DCamDetachAndCancelOnePacket: pSrbTocancel %p, detaching IsochDescriptorToDetach %p\n", pSrbToCancel, IsochDescriptorToDetach)); // Reuse cached IRP pIrp = (PIRP) IsochDescriptorToDetach->DeviceReserved[5]; pIrb = pSrbToCancel->SRBExtension; pIrb->Flags = 0; pIrb->FunctionNumber = REQUEST_ISOCH_DETACH_BUFFERS; pIrb->u.IsochDetachBuffers.hResource = hResource; pIrb->u.IsochDetachBuffers.nNumberOfDescriptors = 1; pIrb->u.IsochDetachBuffers.pIsochDescriptor = IsochDescriptorToDetach; NextIrpStack = IoGetNextIrpStackLocation(pIrp); NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS; NextIrpStack->Parameters.Others.Argument1 = pIrb; IoSetCompletionRoutine( pIrp, DCamCancelOnePacketCR, IsochDescriptorToDetach, TRUE, TRUE, TRUE ); Status = IoCallDriver( pBusDeviceObject, pIrp ); ASSERT(Status == STATUS_SUCCESS || Status == STATUS_PENDING); }
NTSTATUS IrpReadFile( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN ULONG Length, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatusBlock ) { NTSTATUS status; KEVENT event; PIRP irp; PIO_STACK_LOCATION irpSp; PDEVICE_OBJECT deviceObject; if (ByteOffset == NULL) { if (!(FileObject->Flags & FO_SYNCHRONOUS_IO)) return STATUS_INVALID_PARAMETER; ByteOffset = &FileObject->CurrentByteOffset; } if (FileObject->Vpb == 0 || FileObject->Vpb->RealDevice == NULL) return STATUS_UNSUCCESSFUL; deviceObject = FileObject->Vpb->DeviceObject; irp = IoAllocateIrp(deviceObject->StackSize, FALSE); if (irp == NULL) return STATUS_INSUFFICIENT_RESOURCES; irp->MdlAddress = IoAllocateMdl(Buffer, Length, FALSE, TRUE, NULL); if (irp->MdlAddress == NULL) { IoFreeIrp(irp); return STATUS_INSUFFICIENT_RESOURCES;; } MmBuildMdlForNonPagedPool(irp->MdlAddress); irp->Flags = IRP_READ_OPERATION; irp->RequestorMode = KernelMode; irp->UserIosb = IoStatusBlock; irp->UserEvent = &event; irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); irp->Tail.Overlay.OriginalFileObject = FileObject; irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_READ; irpSp->MinorFunction = IRP_MN_NORMAL; irpSp->DeviceObject = deviceObject; irpSp->FileObject = FileObject; irpSp->Parameters.Read.Length = Length; irpSp->Parameters.Read.ByteOffset = *ByteOffset; KeInitializeEvent(&event, SynchronizationEvent, FALSE); IoSetCompletionRoutine(irp, IoCompletionRoutine, NULL, TRUE, TRUE, TRUE); status = IoCallDriver(deviceObject, irp); if (status == STATUS_PENDING) status = KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL); return status; }
/** * Handle the Power requests. * * @returns NT status code * @param pDevObj device object * @param pIrp IRP */ NTSTATUS vgdrvNtPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) { PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; POWER_STATE_TYPE enmPowerType = pStack->Parameters.Power.Type; POWER_STATE PowerState = pStack->Parameters.Power.State; POWER_ACTION enmPowerAction = pStack->Parameters.Power.ShutdownType; Log(("vgdrvNtPower:\n")); switch (pStack->MinorFunction) { case IRP_MN_SET_POWER: { Log(("vgdrvNtPower: IRP_MN_SET_POWER, type= %d\n", enmPowerType)); switch (enmPowerType) { case SystemPowerState: { Log(("vgdrvNtPower: SystemPowerState, action = %d, state = %d/%d\n", enmPowerAction, PowerState.SystemState, PowerState.DeviceState)); switch (enmPowerAction) { case PowerActionSleep: /* System now is in a working state. */ if (PowerState.SystemState == PowerSystemWorking) { if ( pDevExt && pDevExt->LastSystemPowerAction == PowerActionHibernate) { Log(("vgdrvNtPower: Returning from hibernation!\n")); int rc = VGDrvCommonReinitDevExtAfterHibernation(&pDevExt->Core, vgdrvNtVersionToOSType(g_enmVGDrvNtVer)); if (RT_FAILURE(rc)) Log(("vgdrvNtPower: Cannot re-init VMMDev chain, rc = %d!\n", rc)); } } break; case PowerActionShutdownReset: { Log(("vgdrvNtPower: Power action reset!\n")); /* Tell the VMM that we no longer support mouse pointer integration. */ VMMDevReqMouseStatus *pReq = NULL; int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof (VMMDevReqMouseStatus), VMMDevReq_SetMouseStatus); if (RT_SUCCESS(vrc)) { pReq->mouseFeatures = 0; pReq->pointerXPos = 0; pReq->pointerYPos = 0; vrc = VbglGRPerform(&pReq->header); if (RT_FAILURE(vrc)) { Log(("vgdrvNtPower: error communicating new power status to VMMDev. vrc = %Rrc\n", vrc)); } VbglGRFree(&pReq->header); } /* Don't do any cleanup here; there might be still coming in some IOCtls after we got this * power action and would assert/crash when we already cleaned up all the stuff! */ break; } case PowerActionShutdown: case PowerActionShutdownOff: { Log(("vgdrvNtPower: Power action shutdown!\n")); if (PowerState.SystemState >= PowerSystemShutdown) { Log(("vgdrvNtPower: Telling the VMMDev to close the VM ...\n")); VMMDevPowerStateRequest *pReq = pDevExt->pPowerStateRequest; int vrc = VERR_NOT_IMPLEMENTED; if (pReq) { pReq->header.requestType = VMMDevReq_SetPowerStatus; pReq->powerState = VMMDevPowerState_PowerOff; vrc = VbglGRPerform(&pReq->header); } if (RT_FAILURE(vrc)) Log(("vgdrvNtPower: Error communicating new power status to VMMDev. vrc = %Rrc\n", vrc)); /* No need to do cleanup here; at this point we should've been * turned off by VMMDev already! */ } break; } case PowerActionHibernate: Log(("vgdrvNtPower: Power action hibernate!\n")); break; } /* * Save the current system power action for later use. * This becomes handy when we return from hibernation for example. */ if (pDevExt) pDevExt->LastSystemPowerAction = enmPowerAction; break; } default: break; } break; } default: break; } /* * Whether we are completing or relaying this power IRP, * we must call PoStartNextPowerIrp. */ PoStartNextPowerIrp(pIrp); /* * Send the IRP down the driver stack, using PoCallDriver * (not IoCallDriver, as for non-power irps). */ IoCopyCurrentIrpStackLocationToNext(pIrp); IoSetCompletionRoutine(pIrp, vgdrvNtPowerComplete, (PVOID)pDevExt, TRUE, TRUE, TRUE); return PoCallDriver(pDevExt->pNextLowerDriver, pIrp); }