/////////////////////////////////////////////////////////////////////////////// // // OsrRead // // This is the read dispatch entry point for the driver, called when the // I/O Manager has an IRP_MJ_READ request for the driver to process. // // INPUTS: // // DeviceObject - Address of the DEVICE_OBJECT for our device. // // Irp - Address of the IRP representing the IRP_MJ_READ call. // // OUTPUTS: // // None. // // RETURNS: // // STATUS_PENDING, since we are putting the IRP on our internal queue. // // IRQL: // // This routine is called at IRQL_PASSIVE_LEVEL. // // NOTES: // // Since we set the DO_DIRECT_IO bit in the Device Object, all buffers // passed to us will have been probed and locked and described by an MDL. // The I/O manager will provides us the MDL address in Irp->MdlAddress. // /////////////////////////////////////////////////////////////////////////////// NTSTATUS OsrRead(PDEVICE_OBJECT DeviceObject, PIRP Irp) { POSR_DEVICE_EXT devExt = DeviceObject->DeviceExtension; KIRQL oldIrql; NTSTATUS code = STATUS_SUCCESS; BOOLEAN listWasEmpty; PIO_STACK_LOCATION ioStack; ULONG temp; #if DBG DbgPrint("OsrRead: entered\n"); #endif // // See what sort of state we're in // if (devExt->State < STATE_ALL_BELOW_FAIL) { code = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = 0; Irp->IoStatus.Status = code; IoCompleteRequest (Irp, IO_NO_INCREMENT); return code; } OsrRequestIncrement(devExt); // // Validate the IRP we've received // ioStack = IoGetCurrentIrpStackLocation(Irp); // // If the length of the requested transfer is either zero or too long, // we immediately compelte the IRP with an error status. // if (ioStack->Parameters.Read.Length == 0 || ioStack->Parameters.Read.Length > OSR_PCI_MAX_TXFER) { Irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(STATUS_INVALID_USER_BUFFER); } // // Get the Read Queue lock, so we can insert our IRP // KeAcquireSpinLock(&devExt->ReadQueueLock, &oldIrql); // // Since we'll probably be queuing this request, set a routine // to be called by the I/O Manager in case he needs to cancel // this IRP. // IoSetCancelRoutine(Irp, OsrCancelFromReadQueue); // // Do we need to cancel this IRP, instead of queue it? // if (Irp->Cancel) { // // Can't complete a request with a valid cancel routine! // IoSetCancelRoutine(Irp, NULL); KeReleaseSpinLock(&devExt->ReadQueueLock, oldIrql); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(STATUS_CANCELLED); } // // We'll be returning with this request pending // IoMarkIrpPending(Irp); // // Do we need to start this request on the device? // // If there is no IRP currently in progress, we'll start the // one we've just received, if the device state allows it. // if (devExt->CurrentReadIrp == NULL && devExt->State == STATE_STARTED) { // // No read operation presently active. Start this request... // (Note that we're still holding the queue lock here) // OsrStartReadIrp(DeviceObject,Irp); } else { // // Put this request on the end of the write queue // InsertTailList(&devExt->ReadQueue, &Irp->Tail.Overlay.ListEntry); } // // We're done // KeReleaseSpinLock(&devExt->ReadQueueLock, oldIrql); #if DBG DbgPrint("OsrRead: exiting\n"); #endif return(STATUS_PENDING); }
// IRP_MJ_CREATE NTSTATUS TapDeviceCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp) /*++ Routine Description: This routine is called by the I/O system when the device is opened. No action is performed other than completing the request successfully. Arguments: DeviceObject - a pointer to the object that represents the device that I/O is to be done on. Irp - a pointer to the I/O Request Packet for this request. Return Value: NT status code --*/ { NDIS_STATUS status; PIO_STACK_LOCATION irpSp; // Pointer to current stack location PTAP_ADAPTER_CONTEXT adapter = NULL; PFILE_OBJECT originalFileObject; PAGED_CODE(); DEBUGP(("[TAP] --> TapDeviceCreate\n")); irpSp = IoGetCurrentIrpStackLocation(Irp); // // Invalidate file context // irpSp->FileObject->FsContext = NULL; irpSp->FileObject->FsContext2 = NULL; // // Find adapter context for this device. // ------------------------------------- // Returns with added reference on adapter context. // adapter = tapAdapterContextFromDeviceObject(DeviceObject); // Insure that adapter exists. ASSERT(adapter); if (adapter == NULL) { DEBUGP(("[TAP] release [%d.%d] open request; adapter not found\n", TAP_DRIVER_MAJOR_VERSION, TAP_DRIVER_MINOR_VERSION)); Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_DEVICE_DOES_NOT_EXIST; } DEBUGP(("[%s] [TAP] release [%d.%d] open request (TapFileIsOpen=%d)\n", MINIPORT_INSTANCE_ID(adapter), TAP_DRIVER_MAJOR_VERSION, TAP_DRIVER_MINOR_VERSION, adapter->TapFileIsOpen)); // Enforce exclusive access originalFileObject = InterlockedCompareExchangePointer(&adapter->TapFileObject, irpSp->FileObject, NULL); if (originalFileObject == NULL) { irpSp->FileObject->FsContext = adapter; // Quick reference status = STATUS_SUCCESS; } else { status = STATUS_UNSUCCESSFUL; } // Release the lock. // tapAdapterReleaseLock(adapter,FALSE); if (status == STATUS_SUCCESS) { // Reset adapter state on successful open. tapResetAdapterState(adapter); adapter->TapFileIsOpen = 1; // Legacy... // NOTE!!! Reference added by tapAdapterContextFromDeviceObject // will be removed when file is closed. } else { DEBUGP(("[%s] TAP is presently unavailable (TapFileIsOpen=%d)\n", MINIPORT_INSTANCE_ID(adapter), adapter->TapFileIsOpen)); NOTE_ERROR(); // Remove reference added by tapAdapterContextFromDeviceObject. tapAdapterContextDereference(adapter); } // Complete the IRP. Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DEBUGP(("[TAP] <-- TapDeviceCreate; status = %8.8X\n", status)); return status; }
NTSTATUS DriverDispatchHandler (__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { NTSTATUS nsStatus = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (Irp); PBDKIT_DEVICE_EXTENSION pDevExt = (PBDKIT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; WCHAR szImageName[MAX_PATH - 1] = {L"\0"}; ULONG ulLength = 0; do { if ( IrpSp->MajorFunction != IRP_MJ_SHUTDOWN ) { if ( !NT_SUCCESS(BDKitIsAuthorizedProcess(PsGetCurrentProcess())) ) { nsStatus=BDKitGetProcessImageNameByEProcess_s(PsGetCurrentProcess(), szImageName, sizeof(szImageName)); if ( !NT_SUCCESS(nsStatus) ) { Irp->IoStatus.Status = nsStatus = STATUS_ACCESS_DENIED; Irp->IoStatus.Information = 0; break; } #ifndef DBG nsStatus = VerifyFile(szImageName); if ( !NT_SUCCESS(nsStatus) ) { Irp->IoStatus.Status = nsStatus = STATUS_ACCESS_DENIED; Irp->IoStatus.Information = 0; break; } #endif nsStatus = BDKitAddAuthorizedProcess (PsGetCurrentProcess()); BDKit_If_Not_Break(NT_SUCCESS(nsStatus)); } } switch(IrpSp->MajorFunction) { case IRP_MJ_CREATE: { BDbgPrint ("[BDKIT]Open Deivce\r\n"); InterlockedIncrement((volatile LONG*)&pDevExt->DeviceRefence); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = nsStatus = STATUS_SUCCESS; } break; case IRP_MJ_DEVICE_CONTROL: { nsStatus = DriverControlUtilityHandler (DeviceObject, Irp); } break; case IRP_MJ_CLOSE: { BDbgPrint ("[BDKIT]Close Device\r\n"); InterlockedDecrement((LONG volatile*)&pDevExt->DeviceRefence); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = nsStatus = STATUS_SUCCESS; BDKitRemoveAuthorizedProcess (PsGetCurrentProcess()); } break; case IRP_MJ_SHUTDOWN: { //BDbgPrint ("[BDKIT]Clear Delete FileList\r\n"); //BDKitClearDeleteFileList (); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = nsStatus = STATUS_SUCCESS; } break; default: { return DriverPassthroughHandler (DeviceObject, Irp); } } } while (FALSE); if ( nsStatus != STATUS_PENDING ) { IoCompleteRequest(Irp, IO_NO_INCREMENT); } return nsStatus; }
NTSTATUS Bus_CreateClose ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Some outside source is trying to create a file against us. If this is for the FDO (the bus itself) then the caller is trying to open the proprietary connection to tell us to enumerate or remove a device. If this is for the PDO (an object on the bus) then this is a client that wishes to use the toaster 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; PFDO_DEVICE_DATA fdoData; PAGED_CODE (); Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Entered. \n")); fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; Bus_IncIoCount (fdoData); // // If it's not for the FDO. We don't allow create/close on PDO // if (fdoData->IsFDO) { // // Check to see whether the bus is removed // if (fdoData->DevicePnPState == Deleted){ status = STATUS_NO_SUCH_DEVICE; } else { irpStack = IoGetCurrentIrpStackLocation (Irp); switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Create \n")); status = STATUS_SUCCESS; break; case IRP_MJ_CLOSE: Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Close \n")); status = STATUS_SUCCESS; break; default: break; } } } Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); Bus_DecIoCount (fdoData); return status; }
////////////////////////////////////////////////////////////////////////// //取出pendding的IRP,并完成,用户层异步得到通知 VOID AskUserWorker(PDEVICE_OBJECT DeviceObject, PVOID pContext) { PIO_WORKITEM pWorkItem = NULL; PASKUserWorkItemContext pAskContext =NULL; PIRP Irp=NULL; PLIST_ENTRY pListEntry=NULL; NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION irpStack; PVOID ioBuf; ULONG inBufLength, outBufLength; PFIREWALL_ASKUSER pFireAskUser=NULL; KIRQL CIrql,CIrql2; CIrql=CIrql2=0; CIrql = KeGetCurrentIrql(); pAskContext = (PASKUserWorkItemContext)pContext; do { if (pAskContext==NULL) { break; } while(!IsListEmpty(&g_AskUserConnectListHeader)) { //find a pendding irp 2 ask user decision pListEntry = ExInterlockedRemoveHeadList(&g_AskUserConnectListHeader, &g_AskUserConnectListLock); Irp = CONTAINING_RECORD(pListEntry, IRP, Tail.Overlay.ListEntry); break; } if (Irp==NULL) { break; } irpStack = IoGetCurrentIrpStackLocation(Irp); ioBuf = Irp->AssociatedIrp.SystemBuffer; inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; pFireAskUser = (PFIREWALL_ASKUSER)ioBuf; //把DST、SRC IP,PORT带上去,后面再带下来 //let ring3 know what the port is asking for permission *pFireAskUser = *(PFIREWALL_ASKUSER)pAskContext->pContext; Status = STATUS_SUCCESS; Irp->IoStatus.Status = Status; Irp->IoStatus.Information = sizeof(FIREWALL_ASKUSER); IoCompleteRequest(Irp, IO_NO_INCREMENT); } while (0); if (pAskContext) { IoFreeWorkItem(pAskContext->pWorkItem); kfree(pAskContext->pContext); kfree(pAskContext); } if (KeGetCurrentIrql()>CIrql) { KeLowerIrql(CIrql); } if (KeGetCurrentIrql()<CIrql) { KeRaiseIrql(CIrql, &CIrql2); } }
/* * FUNCTION: File system control */ NTSTATUS VfatFileSystemControl( PVFAT_IRP_CONTEXT IrpContext) { NTSTATUS Status; DPRINT("VfatFileSystemControl(IrpContext %p)\n", IrpContext); ASSERT(IrpContext); ASSERT(IrpContext->Irp); ASSERT(IrpContext->Stack); IrpContext->Irp->IoStatus.Information = 0; switch (IrpContext->MinorFunction) { case IRP_MN_KERNEL_CALL: case IRP_MN_USER_FS_REQUEST: switch(IrpContext->Stack->Parameters.DeviceIoControl.IoControlCode) { case FSCTL_GET_VOLUME_BITMAP: Status = VfatGetVolumeBitmap(IrpContext); break; case FSCTL_GET_RETRIEVAL_POINTERS: Status = VfatGetRetrievalPointers(IrpContext); break; case FSCTL_MOVE_FILE: Status = VfatMoveFile(IrpContext); break; case FSCTL_IS_VOLUME_DIRTY: Status = VfatIsVolumeDirty(IrpContext); break; case FSCTL_MARK_VOLUME_DIRTY: Status = VfatMarkVolumeDirty(IrpContext); break; case FSCTL_LOCK_VOLUME: Status = VfatLockOrUnlockVolume(IrpContext, TRUE); break; case FSCTL_UNLOCK_VOLUME: Status = VfatLockOrUnlockVolume(IrpContext, FALSE); break; case FSCTL_DISMOUNT_VOLUME: Status = VfatDismountVolume(IrpContext); break; default: Status = STATUS_INVALID_DEVICE_REQUEST; } break; case IRP_MN_MOUNT_VOLUME: Status = VfatMount(IrpContext); break; case IRP_MN_VERIFY_VOLUME: DPRINT("VFATFS: IRP_MN_VERIFY_VOLUME\n"); Status = VfatVerify(IrpContext); break; default: DPRINT("VFAT FSC: MinorFunction %u\n", IrpContext->MinorFunction); Status = STATUS_INVALID_DEVICE_REQUEST; break; } IrpContext->Irp->IoStatus.Status = Status; IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT); VfatFreeIrpContext(IrpContext); return Status; }
VOID DokanCompleteCreate( __in PIRP_ENTRY IrpEntry, __in PEVENT_INFORMATION EventInfo ) { PIRP irp; PIO_STACK_LOCATION irpSp; NTSTATUS status; ULONG info; PDokanCCB ccb; PDokanFCB fcb; irp = IrpEntry->Irp; irpSp = IrpEntry->IrpSp; DDbgPrint("==> DokanCompleteCreate\n"); ccb = IrpEntry->FileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); DDbgPrint(" FileName:%wZ\n", &fcb->FileName); ccb->UserContext = EventInfo->Context; //DDbgPrint(" set Context %X\n", (ULONG)ccb->UserContext); status = EventInfo->Status; info = EventInfo->Operation.Create.Information; switch (info) { case FILE_OPENED: DDbgPrint(" FILE_OPENED\n"); break; case FILE_CREATED: DDbgPrint(" FILE_CREATED\n"); break; case FILE_OVERWRITTEN: DDbgPrint(" FILE_OVERWRITTEN\n"); break; case FILE_DOES_NOT_EXIST: DDbgPrint(" FILE_DOES_NOT_EXIST\n"); break; case FILE_EXISTS: DDbgPrint(" FILE_EXISTS\n"); break; case FILE_SUPERSEDED: DDbgPrint(" FILE_SUPERSEDED\n"); break; default: DDbgPrint(" info = %d\n", info); break; } KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&fcb->Resource, TRUE); if (NT_SUCCESS(status) && (irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE || EventInfo->Operation.Create.Flags & DOKAN_FILE_DIRECTORY)) { if (irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE) { DDbgPrint(" FILE_DIRECTORY_FILE %p\n", fcb); } else { DDbgPrint(" DOKAN_FILE_DIRECTORY %p\n", fcb); } fcb->Flags |= DOKAN_FILE_DIRECTORY; } ExReleaseResourceLite(&fcb->Resource); KeLeaveCriticalRegion(); KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&ccb->Resource, TRUE); if (NT_SUCCESS(status)) { ccb->Flags |= DOKAN_FILE_OPENED; } ExReleaseResourceLite(&ccb->Resource); KeLeaveCriticalRegion(); if (NT_SUCCESS(status)) { if (info == FILE_CREATED) { if (fcb->Flags & DOKAN_FILE_DIRECTORY) { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_ADDED); } else { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED); } } } else { DDbgPrint(" IRP_MJ_CREATE failed. Free CCB:%p\n", ccb); DokanFreeCCB(ccb); DokanFreeFCB(fcb); } irp->IoStatus.Status = status; irp->IoStatus.Information = info; IoCompleteRequest(irp, IO_NO_INCREMENT); DokanPrintNTStatus(status); DDbgPrint("<== DokanCompleteCreate\n"); }
NTSTATUS FatFsdClose ( IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine implements the FSD part of Close. Arguments: VolumeDeviceObject - Supplies the volume device object where the file exists Irp - Supplies the Irp being processed Return Value: NTSTATUS - The FSD status for the IRP --*/ { NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp; PFILE_OBJECT FileObject; PVCB Vcb; PFCB Fcb; PCCB Ccb; TYPE_OF_OPEN TypeOfOpen; BOOLEAN TopLevel; BOOLEAN VcbDeleted; #ifdef __ND_FAT__ if ((PVOID)FatControlDeviceObject == VolumeDeviceObject) { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = FILE_OPENED; IoCompleteRequest( Irp, IO_DISK_INCREMENT ); return STATUS_SUCCESS; } #endif // // If we were called with our file system device object instead of a // volume device object, just complete this request with STATUS_SUCCESS // if (FatDeviceIsFatFsdo( VolumeDeviceObject)) { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = FILE_OPENED; IoCompleteRequest( Irp, IO_DISK_INCREMENT ); return STATUS_SUCCESS; } DebugTrace(+1, Dbg, "FatFsdClose\n", 0); // // Call the common Close routine // FsRtlEnterFileSystem(); TopLevel = FatIsIrpTopLevel( Irp ); // // Get a pointer to the current stack location and the file object // IrpSp = IoGetCurrentIrpStackLocation( Irp ); FileObject = IrpSp->FileObject; // // Decode the file object and set the read-only bit in the Ccb. // TypeOfOpen = FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ); if (Ccb && IsFileObjectReadOnly(FileObject)) { SetFlag( Ccb->Flags, CCB_FLAG_READ_ONLY ); } try { PCLOSE_CONTEXT CloseContext; // // If we are top level, WAIT can be TRUE, otherwise make it FALSE // to avoid deadlocks, unless this is a top // level request not originating from the system process. // BOOLEAN Wait = TopLevel && (PsGetCurrentProcess() != FatData.OurProcess); #ifdef __ND_FAT__ if (Ccb) { SetFlag( Ccb->NdFatFlags, ND_FAT_CCB_FLAG_CLOSE ); ((PCCB)(FileObject->FsContext2))->FileObject = NULL; FileObject->FsContext = NULL; FileObject->FsContext2 = NULL; } #endif // // Call the common Close routine if we are not delaying this close. // if ((((TypeOfOpen == UserFileOpen) || (TypeOfOpen == UserDirectoryOpen)) && FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE) && !FatData.ShutdownStarted) || (FatCommonClose( Vcb, Fcb, Ccb, TypeOfOpen, Wait, &VcbDeleted ) == STATUS_PENDING)) { // // Metadata streams have had close contexts preallocated. // if (TypeOfOpen == VirtualVolumeFile || TypeOfOpen == DirectoryFile || TypeOfOpen == EaFile) { CloseContext = FatAllocateCloseContext(); ASSERT( CloseContext != NULL ); CloseContext->Free = TRUE; } else { // // Free up any query template strings before using the close context fields, // which overlap (union) // FatDeallocateCcbStrings( Ccb); CloseContext = &Ccb->CloseContext; CloseContext->Free = FALSE; SetFlag( Ccb->Flags, CCB_FLAG_CLOSE_CONTEXT ); } // // If the status is pending, then let's get the information we // need into the close context we already have bagged, complete // the request, and post it. It is important we allocate nothing // in the close path. // CloseContext->Vcb = Vcb; CloseContext->Fcb = Fcb; CloseContext->TypeOfOpen = TypeOfOpen; // // Send it off, either to an ExWorkerThread or to the async // close list. // FatQueueClose( CloseContext, (BOOLEAN)(Fcb && FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE))); } else { // // The close proceeded synchronously, so for the metadata objects we // can now drop the close context we preallocated. // if (TypeOfOpen == VirtualVolumeFile || TypeOfOpen == DirectoryFile || TypeOfOpen == EaFile) { CloseContext = FatAllocateCloseContext(); ASSERT( CloseContext != NULL ); ExFreePool( CloseContext ); } } FatCompleteRequest( FatNull, Irp, Status ); } except(FatExceptionFilter( NULL, GetExceptionInformation() )) { // // We had some trouble trying to perform the requested // operation, so we'll abort the I/O request with the // error status that we get back from the execption code. // Status = FatProcessException( NULL, Irp, GetExceptionCode() ); } if (TopLevel) { IoSetTopLevelIrp( NULL ); } FsRtlExitFileSystem(); // // And return to our caller // DebugTrace(-1, Dbg, "FatFsdClose -> %08lx\n", Status); UNREFERENCED_PARAMETER( VolumeDeviceObject ); return Status; }
VOID tapCompleteIrpAndFreeReceiveNetBufferList( __in PTAP_ADAPTER_CONTEXT Adapter, __in PNET_BUFFER_LIST NetBufferList, // Only one NB here... __in NTSTATUS IoCompletionStatus ) { PIRP irp; ULONG frameType, netBufferCount, byteCount; LONG nblCount; // Fetch NB frame type. frameType = tapGetNetBufferFrameType(NET_BUFFER_LIST_FIRST_NB(NetBufferList)); // Fetch statistics for all NBs linked to the NB. netBufferCount = tapGetNetBufferCountsFromNetBufferList( NetBufferList, &byteCount ); // Update statistics by frame type if(IoCompletionStatus == STATUS_SUCCESS) { switch(frameType) { case NDIS_PACKET_TYPE_DIRECTED: Adapter->FramesRxDirected += netBufferCount; Adapter->BytesRxDirected += byteCount; break; case NDIS_PACKET_TYPE_BROADCAST: Adapter->FramesRxBroadcast += netBufferCount; Adapter->BytesRxBroadcast += byteCount; break; case NDIS_PACKET_TYPE_MULTICAST: Adapter->FramesRxMulticast += netBufferCount; Adapter->BytesRxMulticast += byteCount; break; default: ASSERT(FALSE); break; } } // // Handle P2P Packet // ----------------- // Free MDL allocated for P2P Ethernet header. // if(TAP_RX_NBL_FLAG_TEST(NetBufferList,TAP_RX_NBL_FLAGS_IS_P2P)) { PNET_BUFFER netBuffer; PMDL mdl; netBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList); mdl = NET_BUFFER_FIRST_MDL(netBuffer); mdl->Next = NULL; NdisFreeMdl(mdl); } // // Handle Injected Packet // ----------------------- // Free MDL and data buffer allocated for injected packet. // if(TAP_RX_NBL_FLAG_TEST(NetBufferList,TAP_RX_NBL_FLAGS_IS_INJECTED)) { ULONG pagePriority; PNET_BUFFER netBuffer; PMDL mdl; PUCHAR injectBuffer; netBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList); mdl = NET_BUFFER_FIRST_MDL(netBuffer); // // On Windows versions 8 and above, the MDL can be marked as not executable. // This is required for the driver to function under HyperVisor-enforced // Code Integrity (HVCI). // pagePriority = NormalPagePriority; if (GlobalData.RunningWindows8OrGreater != FALSE) { pagePriority |= MdlMappingNoExecute; } injectBuffer = (PUCHAR )MmGetSystemAddressForMdlSafe(mdl,pagePriority); if(injectBuffer) { NdisFreeMemory(injectBuffer,0,0); } NdisFreeMdl(mdl); } // // Complete the IRP // irp = (PIRP )NetBufferList->MiniportReserved[0]; if(irp) { irp->IoStatus.Status = IoCompletionStatus; IoCompleteRequest(irp, IO_NO_INCREMENT); } // Decrement in-flight receive NBL count. nblCount = NdisInterlockedDecrement(&Adapter->ReceiveNblInFlightCount); ASSERT(nblCount >= 0 ); if (0 == nblCount) { NdisSetEvent(&Adapter->ReceiveNblInFlightCountZeroEvent); } // Free the NBL NdisFreeNetBufferList(NetBufferList); }
NTSTATUS NTAPI USBPORT_HandleSubmitURB(IN PDEVICE_OBJECT PdoDevice, IN PIRP Irp, IN PURB Urb) { PUSBPORT_RHDEVICE_EXTENSION PdoExtension; PDEVICE_OBJECT FdoDevice; PUSBPORT_DEVICE_EXTENSION FdoExtension; USHORT Function; PUSBPORT_DEVICE_HANDLE DeviceHandle; NTSTATUS Status = STATUS_NOT_IMPLEMENTED; ASSERT(Urb); PdoExtension = PdoDevice->DeviceExtension; FdoDevice = PdoExtension->FdoDevice; FdoExtension = FdoDevice->DeviceExtension; Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; Urb->UrbHeader.UsbdFlags = 0; Function = Urb->UrbHeader.Function; if (Function > URB_FUNCTION_MAX) { Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_INVALID_URB_FUNCTION); DPRINT1("USBPORT_HandleSubmitURB: Unknown URB function - %x !!!\n", Function); return Status; } if (FdoExtension->TimerFlags & USBPORT_TMFLAG_RH_SUSPENDED) { DPRINT1("USBPORT_HandleSubmitURB: Bad Request\n"); USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_DEVICE_GONE); Irp->IoStatus.Status = STATUS_PENDING; IoMarkIrpPending(Irp); IoCsqInsertIrp(&FdoExtension->BadRequestIoCsq, Irp, NULL); return STATUS_PENDING; } DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle; if (!DeviceHandle) { DeviceHandle = &PdoExtension->DeviceHandle; Urb->UrbHeader.UsbdDeviceHandle = DeviceHandle; } if (!USBPORT_ValidateDeviceHandle(PdoExtension->FdoDevice, DeviceHandle)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid device handle\n"); Irp->IoStatus.Status = STATUS_PENDING; IoMarkIrpPending(Irp); IoCsqInsertIrp(&FdoExtension->BadRequestIoCsq, Irp, NULL); return STATUS_PENDING; } InterlockedIncrement(&DeviceHandle->DeviceHandleLock); DPRINT_URB("USBPORT_HandleSubmitURB: Function - 0x%02X, DeviceHandle - %p\n", Function, Urb->UrbHeader.UsbdDeviceHandle); switch (Function) { case URB_FUNCTION_ISOCH_TRANSFER: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_ISOCH_TRANSFER UNIMPLEMENTED. FIXME. \n"); break; case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: case URB_FUNCTION_CONTROL_TRANSFER: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, FALSE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleDataTransfers(Urb); break; case URB_FUNCTION_VENDOR_DEVICE: case URB_FUNCTION_VENDOR_INTERFACE: case URB_FUNCTION_VENDOR_ENDPOINT: case URB_FUNCTION_CLASS_DEVICE: case URB_FUNCTION_CLASS_INTERFACE: case URB_FUNCTION_CLASS_ENDPOINT: case URB_FUNCTION_CLASS_OTHER: case URB_FUNCTION_VENDOR_OTHER: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleVendorOrClass(Irp, Urb); break; case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE: case URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT: case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT: case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE: case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleGetSetDescriptor(Irp, Urb); break; case URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR (0x2A) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_INVALID_URB_FUNCTION); case URB_FUNCTION_GET_STATUS_FROM_DEVICE: case URB_FUNCTION_GET_STATUS_FROM_INTERFACE: case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT: case URB_FUNCTION_GET_STATUS_FROM_OTHER: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleGetStatus(Irp, Urb); break; case URB_FUNCTION_SELECT_CONFIGURATION: Status = USBPORT_HandleSelectConfiguration(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_SELECT_INTERFACE: Status = USBPORT_HandleSelectInterface(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_GET_CONFIGURATION: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleGetConfiguration(Urb); break; case URB_FUNCTION_GET_INTERFACE: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_INTERFACE (0x27) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_INVALID_URB_FUNCTION); case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: Status = USBPORT_SyncResetPipeAndClearStall(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_SYNC_RESET_PIPE: Status = USBPORT_ResetPipe(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_SYNC_CLEAR_STALL: Status = USBPORT_ClearStall(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_ABORT_PIPE: Status = USBPORT_AbortPipe(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_SET_FEATURE_TO_DEVICE: case URB_FUNCTION_SET_FEATURE_TO_INTERFACE: case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT: case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE: case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT: case URB_FUNCTION_CLEAR_FEATURE_TO_OTHER: case URB_FUNCTION_SET_FEATURE_TO_OTHER: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, TRUE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleSetOrClearFeature(Urb); break; case URB_FUNCTION_GET_CURRENT_FRAME_NUMBER: Status = USBPORT_HandleGetCurrentFrame(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL (0x03) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED); case URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL (0x04) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED); case URB_FUNCTION_GET_FRAME_LENGTH: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_FRAME_LENGTH (0x05) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED); case URB_FUNCTION_SET_FRAME_LENGTH: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_SET_FRAME_LENGTH (0x06) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED); default: DPRINT1("USBPORT_HandleSubmitURB: Unknown URB Function - %x\n", Function); //URB_FUNCTION_RESERVED_0X0016 //URB_FUNCTION_RESERVE_0X001D //URB_FUNCTION_RESERVE_0X002B //URB_FUNCTION_RESERVE_0X002C //URB_FUNCTION_RESERVE_0X002D //URB_FUNCTION_RESERVE_0X002E //URB_FUNCTION_RESERVE_0X002F break; } if (Status == STATUS_PENDING) { return Status; } if (Urb->UrbHeader.UsbdFlags & USBD_FLAG_ALLOCATED_TRANSFER) { PUSBPORT_TRANSFER Transfer; Transfer = Urb->UrbControlTransfer.hca.Reserved8[0]; Urb->UrbControlTransfer.hca.Reserved8[0] = NULL; Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_TRANSFER; ExFreePoolWithTag(Transfer, USB_PORT_TAG); } InterlockedDecrement(&DeviceHandle->DeviceHandleLock); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
NTSTATUS AFSProcessQueuedResults( IN BOOLEAN CancelRequest) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSLibraryQueueRequestCB *pRequest = NULL; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; __Enter { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Entry\n", __FUNCTION__)); // // Loop through the queue either resubmitting requests or cancelling them // while( TRUE) { AFSAcquireExcl( &pDevExt->Specific.Control.LibraryQueueLock, TRUE); if( pDevExt->Specific.Control.LibraryQueueHead == NULL) { AFSReleaseResource( &pDevExt->Specific.Control.LibraryQueueLock); break; } pRequest = pDevExt->Specific.Control.LibraryQueueHead; pDevExt->Specific.Control.LibraryQueueHead = pRequest->fLink; if( pDevExt->Specific.Control.LibraryQueueHead == NULL) { pDevExt->Specific.Control.LibraryQueueTail = NULL; } AFSReleaseResource( &pDevExt->Specific.Control.LibraryQueueLock); if( CancelRequest) { pRequest->Irp->IoStatus.Status = STATUS_CANCELLED; AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Cancelling request Irp %p\n", __FUNCTION__, pRequest->Irp)); IoCompleteRequest( pRequest->Irp, IO_NO_INCREMENT); } else { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Resubmitting request Irp %p\n", __FUNCTION__, pRequest->Irp)); AFSSubmitLibraryRequest( pRequest->Irp); } ExFreePool( pRequest); } AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Completed\n", __FUNCTION__)); } return ntStatus; }
NTSTATUS Bus_FDO_PnP ( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PIO_STACK_LOCATION IrpStack, __in PFDO_DEVICE_DATA DeviceData ) /*++ Routine Description: Handle requests from the Plug & Play system for the BUS itself --*/ { NTSTATUS status; ULONG length, prevcount, numPdosPresent; PLIST_ENTRY entry, listHead, nextEntry; PPDO_DEVICE_DATA pdoData; PDEVICE_RELATIONS relations, oldRelations; PAGED_CODE (); Bus_IncIoCount (DeviceData); switch (IrpStack->MinorFunction) { case IRP_MN_START_DEVICE: // // Send the Irp down and wait for it to come back. // Do not touch the hardware until then. // status = Bus_SendIrpSynchronously (DeviceData->NextLowerDriver, Irp); if (NT_SUCCESS(status)) { // // Initialize your device with the resources provided // by the PnP manager to your device. // status = Bus_StartFdo (DeviceData, Irp); } // // We must now complete the IRP, since we stopped it in the // completion routine with MORE_PROCESSING_REQUIRED. // Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); Bus_DecIoCount (DeviceData); return status; case IRP_MN_QUERY_STOP_DEVICE: // // The PnP manager is trying to stop the device // for resource rebalancing. Fail this now if you // cannot stop the device in response to STOP_DEVICE. // SET_NEW_PNP_STATE(DeviceData, StopPending); Irp->IoStatus.Status = STATUS_SUCCESS; // You must not fail the IRP. break; case IRP_MN_CANCEL_STOP_DEVICE: // // The PnP Manager sends this IRP, at some point after an // IRP_MN_QUERY_STOP_DEVICE, to inform the drivers for a // device that the device will not be stopped for // resource reconfiguration. // // // First check to see whether you have received cancel-stop // without first receiving a query-stop. This could happen if // someone above us fails a query-stop and passes down the subsequent // cancel-stop. // if (StopPending == DeviceData->DevicePnPState) { // // We did receive a query-stop, so restore. // RESTORE_PREVIOUS_PNP_STATE(DeviceData); ASSERT(DeviceData->DevicePnPState == Started); } Irp->IoStatus.Status = STATUS_SUCCESS; // We must not fail the IRP. break; case IRP_MN_STOP_DEVICE: // // Stop device means that the resources given during Start device // are now revoked. Note: You must not fail this Irp. // But before you relieve resources make sure there are no I/O in // progress. Wait for the existing ones to be finished. // To do that, first we will decrement this very operation. // When the counter goes to 1, Stop event is set. // Bus_DecIoCount(DeviceData); KeWaitForSingleObject( &DeviceData->StopEvent, Executive, // Waiting reason of a driver KernelMode, // Waiting in kernel mode FALSE, // No allert NULL); // No timeout // // Increment the counter back because this IRP has to // be sent down to the lower stack. // Bus_IncIoCount (DeviceData); // // Free resources given by start device. // SET_NEW_PNP_STATE(DeviceData, Stopped); // // We don't need a completion routine so fire and forget. // // Set the current stack location to the next stack location and // call the next device object. // Irp->IoStatus.Status = STATUS_SUCCESS; break; case IRP_MN_QUERY_REMOVE_DEVICE: // // If we were to fail this call then we would need to complete the // IRP here. Since we are not, set the status to SUCCESS and // call the next driver. // SET_NEW_PNP_STATE(DeviceData, RemovePending); Irp->IoStatus.Status = STATUS_SUCCESS; break; case IRP_MN_CANCEL_REMOVE_DEVICE: // // If we were to fail this call then we would need to complete the // IRP here. Since we are not, set the status to SUCCESS and // call the next driver. // // // First check to see whether you have received cancel-remove // without first receiving a query-remove. This could happen if // someone above us fails a query-remove and passes down the // subsequent cancel-remove. // if (RemovePending == DeviceData->DevicePnPState) { // // We did receive a query-remove, so restore. // RESTORE_PREVIOUS_PNP_STATE(DeviceData); } Irp->IoStatus.Status = STATUS_SUCCESS;// You must not fail the IRP. break; case IRP_MN_SURPRISE_REMOVAL: // // The device has been unexpectedly removed from the machine // and is no longer available for I/O. Bus_RemoveFdo clears // all the resources, frees the interface and de-registers // with WMI, but it doesn't delete the FDO. That's done // later in Remove device query. // SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending); Bus_RemoveFdo(DeviceData); ExAcquireFastMutex (&DeviceData->Mutex); listHead = &DeviceData->ListOfPDOs; for(entry = listHead->Flink,nextEntry = entry->Flink; entry != listHead; entry = nextEntry,nextEntry = entry->Flink) { pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); RemoveEntryList (&pdoData->Link); InitializeListHead (&pdoData->Link); pdoData->ParentFdo = NULL; pdoData->ReportedMissing = TRUE; } ExReleaseFastMutex (&DeviceData->Mutex); Irp->IoStatus.Status = STATUS_SUCCESS; // You must not fail the IRP. break; case IRP_MN_REMOVE_DEVICE: // // The Plug & Play system has dictated the removal of this device. // We have no choice but to detach and delete the device object. // // // Check the state flag to see whether you are surprise removed // if (DeviceData->DevicePnPState != SurpriseRemovePending) { Bus_RemoveFdo(DeviceData); } SET_NEW_PNP_STATE(DeviceData, Deleted); // // Wait for all outstanding requests to complete. // We need two decrements here, one for the increment in // the beginning of this function, the other for the 1-biased value of // OutstandingIO. // Bus_DecIoCount (DeviceData); // // The requestCount is at least one here (is 1-biased) // Bus_DecIoCount (DeviceData); KeWaitForSingleObject ( &DeviceData->RemoveEvent, Executive, KernelMode, FALSE, NULL); // // Typically the system removes all the children before // removing the parent FDO. If for any reason child Pdos are // still present we will destroy them explicitly, with one exception - // we will not delete the PDOs that are in SurpriseRemovePending state. // ExAcquireFastMutex (&DeviceData->Mutex); listHead = &DeviceData->ListOfPDOs; for(entry = listHead->Flink,nextEntry = entry->Flink; entry != listHead; entry = nextEntry,nextEntry = entry->Flink) { pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); RemoveEntryList (&pdoData->Link); if (SurpriseRemovePending == pdoData->DevicePnPState) { // // We will reinitialize the list head so that we // wouldn't barf when we try to delink this PDO from // the parent's PDOs list, when the system finally // removes the PDO. Let's also not forget to set the // ReportedMissing flag to cause the deletion of the PDO. // Bus_KdPrint_Cont(DeviceData, BUS_DBG_PNP_INFO, ("\tFound a surprise removed device: 0x%p\n", pdoData->Self)); InitializeListHead (&pdoData->Link); pdoData->ParentFdo = NULL; pdoData->ReportedMissing = TRUE; continue; } DeviceData->NumPDOs--; Bus_DestroyPdo (pdoData->Self, pdoData); } ExReleaseFastMutex (&DeviceData->Mutex); // // We need to send the remove down the stack before we detach, // but we don't need to wait for the completion of this operation // (and to register a completion routine). // Irp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation (Irp); status = IoCallDriver (DeviceData->NextLowerDriver, Irp); // // Detach from the underlying devices. // IoDetachDevice (DeviceData->NextLowerDriver); Bus_KdPrint_Cont(DeviceData, BUS_DBG_PNP_INFO, ("\tDeleting FDO: 0x%p\n", DeviceObject)); IoDeleteDevice (DeviceObject); return status; case IRP_MN_QUERY_DEVICE_RELATIONS: Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE, ("\tQueryDeviceRelation Type: %s\n", DbgDeviceRelationString(\ IrpStack->Parameters.QueryDeviceRelations.Type))); if (BusRelations != IrpStack->Parameters.QueryDeviceRelations.Type) { // // We don't support any other Device Relations // break; } // // Tell the plug and play system about all the PDOs. // // There might also be device relations below and above this FDO, // so, be sure to propagate the relations from the upper drivers. // // No Completion routine is needed so long as the status is preset // to success. (PDOs complete plug and play irps with the current // IoStatus.Status and IoStatus.Information as the default.) // ExAcquireFastMutex (&DeviceData->Mutex); oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information; if (oldRelations) { prevcount = oldRelations->Count; if (!DeviceData->NumPDOs) { // // There is a device relations struct already present and we have // nothing to add to it, so just call IoSkip and IoCall // ExReleaseFastMutex (&DeviceData->Mutex); break; } } else { prevcount = 0; } // // Calculate the number of PDOs actually present on the bus // numPdosPresent = 0; for (entry = DeviceData->ListOfPDOs.Flink; entry != &DeviceData->ListOfPDOs; entry = entry->Flink) { pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); if (pdoData->Present) numPdosPresent++; } // // Need to allocate a new relations structure and add our // PDOs to it. // length = sizeof(DEVICE_RELATIONS) + ((numPdosPresent + prevcount) * sizeof (PDEVICE_OBJECT)) -1; relations = (PDEVICE_RELATIONS) ExAllocatePoolWithTag (PagedPool, length, BUSENUM_POOL_TAG); if (NULL == relations) { // // Fail the IRP // ExReleaseFastMutex (&DeviceData->Mutex); Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES; IoCompleteRequest (Irp, IO_NO_INCREMENT); Bus_DecIoCount (DeviceData); return status; } // // Copy in the device objects so far // if (prevcount) { RtlCopyMemory (relations->Objects, oldRelations->Objects, prevcount * sizeof (PDEVICE_OBJECT)); } relations->Count = prevcount + numPdosPresent; // // For each PDO present on this bus add a pointer to the device relations // buffer, being sure to take out a reference to that object. // The Plug & Play system will dereference the object when it is done // with it and free the device relations buffer. // for (entry = DeviceData->ListOfPDOs.Flink; entry != &DeviceData->ListOfPDOs; entry = entry->Flink) { pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); if (pdoData->Present) { relations->Objects[prevcount] = pdoData->Self; ObReferenceObject (pdoData->Self); prevcount++; } else { pdoData->ReportedMissing = TRUE; } } Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE, ("\t#PDOS present = %d\n\t#PDOs reported = %d\n", DeviceData->NumPDOs, relations->Count)); // // Replace the relations structure in the IRP with the new // one. // if (oldRelations) { ExFreePool (oldRelations); } Irp->IoStatus.Information = (ULONG_PTR) relations; ExReleaseFastMutex (&DeviceData->Mutex); // // Set up and pass the IRP further down the stack // Irp->IoStatus.Status = STATUS_SUCCESS; break; default: // // In the default case we merely call the next driver. // We must not modify Irp->IoStatus.Status or complete the IRP. // break; } IoSkipCurrentIrpStackLocation (Irp); status = IoCallDriver (DeviceData->NextLowerDriver, Irp); Bus_DecIoCount (DeviceData); return status; }
NTSTATUS Bus_PnP ( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) /*++ Routine Description: Handles PnP Irps sent to both FDO and child PDOs. Arguments: DeviceObject - Pointer to deviceobject Irp - Pointer to a PnP Irp. Return Value: NT Status is returned. --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status; PCOMMON_DEVICE_DATA commonData; PAGED_CODE (); KdPrint(("Bus_PnP\r\n")); irpStack = IoGetCurrentIrpStackLocation (Irp); ASSERT (IRP_MJ_PNP == irpStack->MajorFunction); commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; // // If the device has been removed, the driver should // not pass the IRP down to the next lower driver. // if (commonData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE ; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } if (commonData->IsFDO) { Bus_KdPrint (commonData, BUS_DBG_PNP_TRACE, ("FDO %s IRP:0x%p\n", PnPMinorFunctionString(irpStack->MinorFunction), Irp)); // // Request is for the bus FDO // status = Bus_FDO_PnP ( DeviceObject, Irp, irpStack, (PFDO_DEVICE_DATA) commonData); } else { Bus_KdPrint (commonData, BUS_DBG_PNP_TRACE, ("PDO %s IRP: 0x%p\n", PnPMinorFunctionString(irpStack->MinorFunction), Irp)); // // Request is for the child PDO. // status = Bus_PDO_PnP ( DeviceObject, Irp, irpStack, (PPDO_DEVICE_DATA) commonData); } return status; }
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint(("DriverB:Enter B HelloDDKRead\n")); NTSTATUS ntStatus = STATUS_SUCCESS; UNICODE_STRING DeviceName; RtlInitUnicodeString( &DeviceName, L"\\Device\\MyDDKDeviceA" ); PDEVICE_OBJECT DeviceObject = NULL; PFILE_OBJECT FileObject = NULL; //得到设备对象指针 ntStatus = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&FileObject,&DeviceObject); KdPrint(("DriverB:FileObject:%x\n",FileObject)); KdPrint(("DriverB:DeviceObject:%x\n",DeviceObject)); if (!NT_SUCCESS(ntStatus)) { KdPrint(("DriverB:IoGetDeviceObjectPointer() 0x%x\n", ntStatus )); ntStatus = STATUS_UNSUCCESSFUL; // 完成IRP pIrp->IoStatus.Status = ntStatus; pIrp->IoStatus.Information = 0; // bytes xfered IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("DriverB:Leave B HelloDDKRead\n")); return ntStatus; } KEVENT event; KeInitializeEvent(&event,NotificationEvent,FALSE); IO_STATUS_BLOCK status_block; LARGE_INTEGER offsert = RtlConvertLongToLargeInteger(0); //创建异步IRP PIRP pNewIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ, DeviceObject, NULL,0, &offsert,&status_block); KdPrint(("pNewIrp->UserEvent :%x\n",pNewIrp->UserEvent)); //设置pNewIrp->UserEvent,这样在IRP完成后可以通知该事件 pNewIrp->UserEvent = &event; KdPrint(("DriverB:pNewIrp:%x\n",pNewIrp)); PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(pNewIrp); stack->FileObject = FileObject; NTSTATUS status = IoCallDriver(DeviceObject,pNewIrp); if (status == STATUS_PENDING) { status = KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, // Not alertable NULL); status = status_block.Status; } ZwClose(FileObject); //关闭设备句柄 ObDereferenceObject( FileObject ); ntStatus = STATUS_SUCCESS; // 完成IRP pIrp->IoStatus.Status = ntStatus; pIrp->IoStatus.Information = 0; // bytes xfered IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("DriverB:Leave B HelloDDKRead\n")); return ntStatus; }
VOID ndisprotServiceReads( IN PNDISPROT_OPEN_CONTEXT pOpenContext ) /*++ Routine Description: Utility routine to copy received data into user buffers and complete READ IRPs. Arguments: pOpenContext - pointer to open context Return Value: None --*/ { PIRP pIrp = NULL; PLIST_ENTRY pIrpEntry; PNET_BUFFER_LIST pRcvNetBufList; PLIST_ENTRY pRcvNetBufListEntry; PUCHAR pSrc, pDst; ULONG BytesRemaining; // at pDst PMDL pMdl; ULONG BytesAvailable; BOOLEAN FoundPendingIrp = FALSE; ULONG SrcTotalLength = 0; // Source NetBuffer DataLenght ULONG Offset = 0; // CurrentMdlOffset ULONG BytesToCopy = 0; DEBUGP(DL_VERY_LOUD, ("ServiceReads: open %p/%x\n", pOpenContext, pOpenContext->Flags)); NPROT_REF_OPEN(pOpenContext); // temp ref - service reads NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); while (!NPROT_IS_LIST_EMPTY(&pOpenContext->PendedReads) && !NPROT_IS_LIST_EMPTY(&pOpenContext->RecvNetBufListQueue)) { FoundPendingIrp = FALSE; // // Get the first pended Read IRP // pIrpEntry = pOpenContext->PendedReads.Flink; while (pIrpEntry != &pOpenContext->PendedReads) { pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry); // // Check to see if it is being cancelled. // if (IoSetCancelRoutine(pIrp, NULL)) { // // It isn't being cancelled, and can't be cancelled henceforth. // NPROT_REMOVE_ENTRY_LIST(pIrpEntry); FoundPendingIrp = TRUE; break; // // NOTE: we decrement PendedReadCount way below in the // while loop, to avoid letting through a thread trying // to unbind. // } else { // // The IRP is being cancelled; let the cancel routine handle it. // DEBUGP(DL_INFO, ("ServiceReads: open %p, skipping cancelled IRP %p\n", pOpenContext, pIrp)); pIrpEntry = pIrpEntry->Flink; } } if (FoundPendingIrp == FALSE) { break; } // // Get the first queued receive packet // pRcvNetBufListEntry = pOpenContext->RecvNetBufListQueue.Flink; NPROT_REMOVE_ENTRY_LIST(pRcvNetBufListEntry); pOpenContext->RecvNetBufListCount --; NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); NPROT_DEREF_OPEN(pOpenContext); // Service: dequeue rcv packet pRcvNetBufList = NPROT_RCV_NBL_FROM_LIST_ENTRY(pRcvNetBufListEntry); NPROT_ASSERT(pRcvNetBufList != NULL); _Analysis_assume_(pRcvNetBufList != NULL); NPROT_RCV_NBL_FROM_LIST_ENTRY(pRcvNetBufListEntry) = NULL; // // Copy as much data as possible from the receive packet to // the IRP MDL. // pDst = NULL; NdisQueryMdl(pIrp->MdlAddress, &pDst, &BytesRemaining, NormalPagePriority); NPROT_ASSERT(pDst != NULL); // since it was already mapped _Analysis_assume_(pDst != NULL); pMdl = NET_BUFFER_CURRENT_MDL(NET_BUFFER_LIST_FIRST_NB(pRcvNetBufList)); // // Copy the data in the received packet into the buffer provided by the client. // If the length of the receive packet is greater than length of the given buffer, // we just copy as many bytes as we can. Once the buffer is full, we just discard // the rest of the data, and complete the IRP sucessfully even we only did a partial copy. // SrcTotalLength = NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(pRcvNetBufList)); Offset = NET_BUFFER_CURRENT_MDL_OFFSET(NET_BUFFER_LIST_FIRST_NB(pRcvNetBufList)); while (BytesRemaining && (pMdl != NULL) && SrcTotalLength) { pSrc = NULL; NdisQueryMdl(pMdl, &pSrc, &BytesAvailable, NormalPagePriority); if (pSrc == NULL) { DEBUGP(DL_FATAL, ("ServiceReads: Open %p, NdisQueryMdl failed for MDL %p\n", pOpenContext, pMdl)); break; } NPROT_ASSERT(BytesAvailable > Offset); BytesToCopy = MIN(BytesAvailable - Offset, BytesRemaining); BytesToCopy = MIN(BytesToCopy, SrcTotalLength); NPROT_COPY_MEM(pDst, pSrc + Offset, BytesToCopy); BytesRemaining -= BytesToCopy; pDst += BytesToCopy; SrcTotalLength -= BytesToCopy; // // CurrentMdlOffset is used only for the first Mdl processed. For the remaining Mdls, it is 0. // Offset = 0; NdisGetNextMdl(pMdl, &pMdl); } // // Complete the IRP. // pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining; DEBUGP(DL_INFO, ("ServiceReads: Open %p, IRP %p completed with %d bytes\n", pOpenContext, pIrp, (ULONG)pIrp->IoStatus.Information)); IoCompleteRequest(pIrp, IO_NO_INCREMENT); ndisprotFreeReceiveNetBufferList(pOpenContext, pRcvNetBufList,FALSE); NPROT_DEREF_OPEN(pOpenContext); // took out pended Read NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); pOpenContext->PendedReadCount--; } NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); NPROT_DEREF_OPEN(pOpenContext); // temp ref - service reads }
NTSTATUS Bus_IoCtl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Handle user mode PlugIn, UnPlug and device Eject requests. 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; ULONG inlen, outlen; PFDO_DEVICE_DATA fdoData; PVOID buffer; PAGED_CODE (); // // It is not safe to call IOCTL in raised IRQL. // ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; // // We only take Device Control requests for the FDO. // That is the bus itself. // if (!fdoData->IsFDO) { // // These commands are only allowed to go to the FDO. // status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // // Check to see whether the bus is removed // if (fdoData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } Bus_IncIoCount (fdoData); irpStack = IoGetCurrentIrpStackLocation (Irp); buffer = Irp->AssociatedIrp.SystemBuffer; inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength; outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength; status = STATUS_INVALID_PARAMETER; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode)); switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_NDASBUS_ADD_TARGET: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); if ((inlen == outlen) && (sizeof(NDASBUS_ADD_TARGET_DATA) <= inlen)) { ULONG ulSize; PNDASBUS_ADD_TARGET_DATA addTargetData = buffer; BOOLEAN accepted; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_ADD_TARGET called\n")); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET Target Type %d\n", addTargetData->ucTargetType)); status = STATUS_SUCCESS; // // Check structure size // if(VerifySizeOfAddTargetData(addTargetData, &ulSize) == 0) { status = STATUS_INVALID_PARAMETER; break; } if(ulSize != inlen) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen)); status = STATUS_UNSUCCESSFUL; break; } // // Check to see if acceptable structure. // accepted = TRUE; switch(addTargetData->ucTargetType) { case NDASSCSI_TYPE_DISK_NORMAL: case NDASSCSI_TYPE_DVD: case NDASSCSI_TYPE_VDVD: case NDASSCSI_TYPE_MO: if(addTargetData->ulNumberOfUnitDiskList != 1) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_MIRROR: if(2 != addTargetData->ulNumberOfUnitDiskList) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_AGGREGATION: if (addTargetData->ulNumberOfUnitDiskList < 2 || addTargetData->ulNumberOfUnitDiskList > MAX_NR_UNITDISK_FOR_AGGR) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_RAID0: switch(addTargetData->ulNumberOfUnitDiskList) { case 2: case 4: case 8: break; default: // do not accept accepted = FALSE; break; } break; case NDASSCSI_TYPE_DISK_RAID1R3: { ULONG ulDiskCount; ulDiskCount = addTargetData->ulNumberOfUnitDiskList - addTargetData->RAID_Info.nSpareDisk; if (2 != ulDiskCount) accepted = FALSE; } break; case NDASSCSI_TYPE_DISK_RAID4R3: case NDASSCSI_TYPE_DISK_RAID5: { ULONG ulDiskCount; ulDiskCount = addTargetData->ulNumberOfUnitDiskList - addTargetData->RAID_Info.nSpareDisk; switch(ulDiskCount) { case 3: // 2 + 1 case 5: // 4 + 1 case 9: // 8 + 1 break; default: // do not accept accepted = FALSE; break; } break; } default: Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Bad Disk Type.\n")); accepted = FALSE; break; } if(accepted == FALSE) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Invaild type.\n")); status = STATUS_UNSUCCESSFUL; break; } #if DBG NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_TRY_TO_ADDTARGET, IOCTL_NDASBUS_ADD_TARGET, addTargetData->ulSlotNo); #endif // Find Pdo Data... pdoData = LookupPdoData(fdoData, addTargetData->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_ADD_TARGET, addTargetData->ulSlotNo); break; } // // Save the add target information to the PDO extension // pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePoolWithTag(NonPagedPool, inlen, BUSENUM_POOL_TAG); if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { Irp->IoStatus.Information = 0; status = STATUS_INSUFFICIENT_RESOURCES; break; } else { RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, addTargetData, inlen); status = STATUS_SUCCESS; } pdoData->LanscsiAdapterPDO.AddDevInfoLength = inlen; // // Init PDO status // pdoData->LanscsiAdapterPDO.LastAdapterStatus = NDASSCSI_ADAPTER_STATUS_INIT; pdoData->LanscsiAdapterPDO.DeviceMode = addTargetData->DeviceMode; // // Notify to NDASSCSI // Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET SetEvent AddTargetEvent!\n")); KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE); // // Register Target // if(pdoData->Persistent) { status = LSBus_RegisterTarget(fdoData, addTargetData); if(!NT_SUCCESS(status)) { ExFreePoolWithTag(pdoData->LanscsiAdapterPDO.AddDevInfo, BUSENUM_POOL_TAG); pdoData->LanscsiAdapterPDO.AddDevInfo = NULL; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: LSBus_RegisterTarget() failed. STATUS=%08lx\n", status)); status = STATUS_INTERNAL_DB_ERROR; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_REGISTER_TARGET_FAIL, IOCTL_NDASBUS_ADD_TARGET, addTargetData->ulSlotNo); } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("ADD_TARGET: Successfully registered.\n")); } } ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); } } break; case IOCTL_NDASBUS_REMOVE_TARGET: { PPDO_DEVICE_DATA pdoData; PNDASBUS_REMOVE_TARGET_DATA removeTarget; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_REMOVE_TARGET called\n")); if (sizeof (NDASBUS_REMOVE_TARGET_DATA) != inlen) break; removeTarget = (PNDASBUS_REMOVE_TARGET_DATA)buffer; pdoData = LookupPdoData(fdoData, removeTarget->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_REMOVE_TARGET, removeTarget->ulSlotNo); break; } // // redirect to the NDAS SCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_REMOVE_DEVICE, NULL, 0, NULL, 0 ); if(NT_SUCCESS(status) && pdoData->Persistent) { status = LSBus_UnregisterTarget(fdoData, removeTarget->ulSlotNo, removeTarget->ulTargetId); if(!NT_SUCCESS(status)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ( "REMOVE_TARGET: Removed Target instance," " but LSBus_UnregisterTarget() failed.\n")); status = STATUS_INTERNAL_DB_ERROR; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_UNREGISTER_TARGET_FAIL, IOCTL_NDASBUS_REMOVE_TARGET, removeTarget->ulSlotNo); } #if DBG else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("REMOVE_TARGET: LSBus_UnregisterTarget() succeeded.\n")); } #endif } ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = 0; break; } case IOCTL_NDASBUS_STARTSTOP_REGISTRARENUM:{ PULONG onOff = (PULONG)buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "STARTSTOP_REGISTRARENUM: inlen %d, outlen %d OnOff %u\n", inlen, outlen, *onOff)); KeEnterCriticalRegion(); ExAcquireFastMutexUnsafe(&fdoData->RegMutex); if(*onOff != 0) { // // Save old state. // Activate the registrar's enumeration // *onOff = fdoData->StartStopRegistrarEnum; fdoData->StartStopRegistrarEnum = TRUE; } else { // // Save old state. // Deactivate the registrar's enumeration // *onOff = fdoData->StartStopRegistrarEnum; fdoData->StartStopRegistrarEnum = FALSE; } // // Clean up non-enumerated entries. // LSBus_CleanupNDASDeviceRegistryUnsafe(fdoData); ExReleaseFastMutexUnsafe(&fdoData->RegMutex); KeLeaveCriticalRegion(); Irp->IoStatus.Information = sizeof(ULONG); status = STATUS_SUCCESS; break; } case IOCTL_NDASBUS_REGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_DEVICE: inlen %d, outlen %d," " sizeof(NDASBUS_PLUGIN_HARDWARE_EX2) %d\n", inlen, outlen, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2))); if ((inlen == outlen)) { PNDASBUS_PLUGIN_HARDWARE_EX2 PlugIn = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_DEVICE: entered\n")); status = LSBus_RegisterDevice(fdoData, PlugIn); Irp->IoStatus.Information = 0; } else Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("REGISTER_DEVICE: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2) %d\n", inlen, outlen, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2))); } break; case IOCTL_NDASBUS_REGISTER_TARGET: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_TARGET: inlen %d, outlen %d," " sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); if ((inlen == outlen)) { PNDASBUS_ADD_TARGET_DATA AddTargetData = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_TARGET: entered\n")); status = LSBus_RegisterTarget(fdoData, AddTargetData); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_TARGET: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); } } break; case IOCTL_NDASBUS_UNREGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_DEVICE: inlen %d, outlen %d," " sizeof(NDASBUS_UNREGISTER_NDASDEV) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_NDASDEV))); if ((inlen == outlen)) { PNDASBUS_UNREGISTER_NDASDEV UnregDev = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_DEVICE: entered\n")); status = LSBus_UnregisterDevice(fdoData, UnregDev->SlotNo); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_DEVICE: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_NDASDEV))); } } break; case IOCTL_NDASBUS_UNREGISTER_TARGET: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_TARGET: inlen %d, outlen %d," " sizeof(NDASBUS_UNREGISTER_TARGET) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_TARGET))); if ((inlen == outlen)) { PNDASBUS_UNREGISTER_TARGET UnregTarget = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_TARGET: entered\n")); status = LSBus_UnregisterTarget(fdoData, UnregTarget->SlotNo, UnregTarget->TargetId); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_TARGET: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_UNREGISTER_TARGET) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_TARGET))); } } break; case IOCTL_NDASBUS_SETPDOINFO: { PPDO_DEVICE_DATA pdoData; PNDASBUS_SETPDOINFO SetPdoInfo; KIRQL oldIrql; PVOID sectionHandle; BOOLEAN acceptStatus; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_SETPDOINFO called\n")); if (sizeof (NDASBUS_SETPDOINFO) != inlen) break; acceptStatus = TRUE; SetPdoInfo = (PNDASBUS_SETPDOINFO)buffer; pdoData = LookupPdoData(fdoData, SetPdoInfo->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_SETPDOINFO, SetPdoInfo->SlotNo); break; } // // lock the code section of this function to acquire spinlock in raised IRQL. // sectionHandle = MmLockPagableCodeSection(Bus_IoCtl); KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! SETPDOINFO: PDO %p: %08lx %08lx %08lx\n", pdoData->Self, SetPdoInfo->AdapterStatus, SetPdoInfo->SupportedFeatures, SetPdoInfo->EnabledFeatures)); // // Deny the status change if the current status is STATUS_STOPPED except for RESETSTATUS flag. // if(ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.LastAdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPED)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'An event occured after 'Stopped' event\n")); if(ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTER_STATUSFLAG_RESETSTATUS)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Reset-status event accepted.\n")); } else { acceptStatus = FALSE; } } else { if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { acceptStatus = FALSE; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! SETPDOINFO: AddTarget is not occured. Too early to set status.\n")); } } // // Mask off RESETSTATUS. // NDAS service does not need to know it. // SetPdoInfo->AdapterStatus &= ~NDASSCSI_ADAPTER_STATUSFLAG_RESETSTATUS; // // Set status values to the corresponding physical device object. // Save to the extension // if(acceptStatus) { PNDASBUS_PDOEVENT_ENTRY pdoEventEntry; pdoEventEntry = NdasBusCreatePdoStatusItem(SetPdoInfo->AdapterStatus); if(pdoEventEntry) { NdasBusQueuePdoStatusItem(&pdoData->LanscsiAdapterPDO, pdoEventEntry); } #if DBG else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Could not allocate PDO status entry.\n")); } #endif pdoData->LanscsiAdapterPDO.LastAdapterStatus = SetPdoInfo->AdapterStatus; pdoData->LanscsiAdapterPDO.SupportedFeatures = SetPdoInfo->SupportedFeatures; pdoData->LanscsiAdapterPDO.EnabledFeatures = SetPdoInfo->EnabledFeatures; // // Queue plugout worker if the NDAS SCSI stop abnormally. // Notify the NDAS service of abnormal termination // if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPED) && ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTER_STATUSFLAG_ABNORMAL_TERMINAT)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Queueing Unplug worker!!!!!!!!\n")); status = QueueUnplugWorker(fdoData, SetPdoInfo->SlotNo); // // Set disconnection event // KeSetEvent(pdoData->LanscsiAdapterPDO.DisconEventToService, IO_DISK_INCREMENT, FALSE); } else { // // Notify the adapter status change // KeSetEvent(pdoData->LanscsiAdapterPDO.AlarmEventToService, IO_DISK_INCREMENT, FALSE); } } KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); // // Release the code section. // MmUnlockPagableImageSection(sectionHandle); status = STATUS_SUCCESS; ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } break; case IOCTL_NDASBUS_QUERY_NODE_ALIVE: { PPDO_DEVICE_DATA pdoData; BOOLEAN bAlive; PNDASBUS_NODE_ALIVE_IN pNodeAliveIn; NDASBUS_NODE_ALIVE_OUT nodeAliveOut; // Check Parameter. if(inlen != sizeof(NDASBUS_NODE_ALIVE_IN) || outlen != sizeof(NDASBUS_NODE_ALIVE_OUT)) { status = STATUS_UNKNOWN_REVISION; break; } pNodeAliveIn = (PNDASBUS_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE, ("FDO: IOCTL_NDASBUS_QUERY_NODE_ALIVE SlotNumber = %d\n", pNodeAliveIn->SlotNo)); pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo); if(pdoData == NULL) { // Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, // ("[LanScsiBus]Bus_IoCtl: IOCTL_NDASBUS_QUERY_NODE_ALIVE No pdo\n")); bAlive = FALSE; } else { // // Check this PDO would be removed... // if(pdoData->Present == TRUE) bAlive = TRUE; else bAlive = FALSE; } // For Result... nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo; nodeAliveOut.bAlive = bAlive; // Get Adapter Status. if(bAlive == TRUE) { if( ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.LastAdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPING)) { nodeAliveOut.bHasError = TRUE; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError)); } else { nodeAliveOut.bHasError = FALSE; } } if(pdoData) ObDereferenceObject(pdoData->Self); RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &nodeAliveOut, sizeof(NDASBUS_NODE_ALIVE_OUT) ); Irp->IoStatus.Information = sizeof(NDASBUS_NODE_ALIVE_OUT); status = STATUS_SUCCESS; } break; // // added by hootch 01172004 // case IOCTL_NDASBUS_UPGRADETOWRITE: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_UPGRADETOWRITE called\n")); // Check Parameter. if(inlen != sizeof(NDASBUS_UPGRADE_TO_WRITE)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_UPGRADETOWRITE: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_UPGRADETOWRITE: No pdo for Slotno:%d\n", ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo)); status = STATUS_NO_SUCH_DEVICE; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_UPGRADETOWRITE, ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo); } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_UPGRADETOWRITE, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_NDASBUS_REDIRECT_NDASSCSI: { PPDO_DEVICE_DATA pdoData; PNDASBUS_REDIRECT_NDASSCSI redirectIoctl; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI called\n")); // Check Parameter. if(inlen < sizeof(NDASBUS_REDIRECT_NDASSCSI)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } redirectIoctl = (PNDASBUS_REDIRECT_NDASSCSI)buffer; pdoData = LookupPdoData(fdoData, redirectIoctl->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI: No pdo for Slotno:%d\n", redirectIoctl->SlotNo)); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, redirectIoctl->IoctlCode, redirectIoctl->IoctlData, redirectIoctl->IoctlDataSize, redirectIoctl->IoctlData, redirectIoctl->IoctlDataSize ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_NDASBUS_QUERY_NDASSCSIINFO: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO called\n")); // Check Parameter. if(inlen < FIELD_OFFSET(NDASSCSI_QUERY_INFO_DATA, QueryData) ) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO: Invalid input buffer length too small.\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PNDASSCSI_QUERY_INFO_DATA)buffer)->NdasScsiAddress.SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO No pdo\n")); status = STATUS_NO_SUCH_DEVICE; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_QUERY_NDASSCSIINFO, ((PNDASSCSI_QUERY_INFO_DATA)buffer)->NdasScsiAddress.SlotNo); } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_QUERYINFO_EX, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = outlen; } break; case IOCTL_NDASBUS_QUERY_INFORMATION: { // PPDO_DEVICE_DATA pdoData; NDASBUS_QUERY_INFORMATION Query; PNDASBUS_INFORMATION Information; LONG BufferLenNeeded; // Check Parameter. if( inlen < sizeof(NDASBUS_QUERY_INFORMATION) /*|| outlen < sizeof(NDASBUS_INFORMATION) */) { status = STATUS_UNKNOWN_REVISION; break; } RtlCopyMemory(&Query, buffer, sizeof(NDASBUS_QUERY_INFORMATION)); Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, ("FDO: IOCTL_NDASBUS_QUERY_INFORMATION QueryType : %d SlotNumber = %d\n", Query.InfoClass, Query.SlotNo)); Information = (PNDASBUS_INFORMATION)buffer; ASSERT(Information); Information->InfoClass = Query.InfoClass; status = LSBus_QueryInformation(fdoData, IoIs32bitProcess(Irp), &Query, Information, outlen, &BufferLenNeeded); if(NT_SUCCESS(status)) { Information->Size = BufferLenNeeded; Irp->IoStatus.Information = BufferLenNeeded; } else { Irp->IoStatus.Information = BufferLenNeeded; } } break; case IOCTL_NDASBUS_PLUGIN_HARDWARE_EX2: { ULONG structLen; // Without variable length field ULONG wholeStructLen; // With variable length field ULONG inputWholeStructLen; // // Check 32 bit thunking request // if(IoIs32bitProcess(Irp)) { structLen = FIELD_OFFSET(NDASBUS_PLUGIN_HARDWARE_EX2_32, HardwareIDs); wholeStructLen = sizeof(NDASBUS_PLUGIN_HARDWARE_EX2_32); inputWholeStructLen = ((PNDASBUS_PLUGIN_HARDWARE_EX2_32) buffer)->Size; } else { structLen = FIELD_OFFSET(NDASBUS_PLUGIN_HARDWARE_EX2, HardwareIDs); wholeStructLen = sizeof(NDASBUS_PLUGIN_HARDWARE_EX2); inputWholeStructLen = ((PNDASBUS_PLUGIN_HARDWARE_EX2) buffer)->Size; } if ((inlen == outlen) && // // Make sure it has at least two nulls and the size // field is set to the declared size of the struct // ((structLen + sizeof(UNICODE_NULL) * 2) <= inlen) && // // The size field should be set to the sizeof the struct as declared // and *not* the size of the struct plus the multi_sz // (wholeStructLen == inputWholeStructLen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n")); status= Bus_PlugInDeviceEx2((PNDASBUS_PLUGIN_HARDWARE_EX2)buffer, inlen, fdoData, IoIs32bitProcess(Irp), Irp->RequestorMode, FALSE); Irp->IoStatus.Information = outlen; } } break; case IOCTL_NDASBUS_GETVERSION: { if (outlen >= sizeof(NDASBUS_GET_VERSION)) { PNDASBUS_GET_VERSION version = (PNDASBUS_GET_VERSION)buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_GETVERSION: called\n")); try { version->VersionMajor = VER_FILEMAJORVERSION; version->VersionMinor = VER_FILEMINORVERSION; version->VersionBuild = VER_FILEBUILD; version->VersionPrivate = VER_FILEBUILD_QFE; Irp->IoStatus.Information = sizeof(NDASBUS_GET_VERSION); status = STATUS_SUCCESS; } except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); Irp->IoStatus.Information = 0; } } } break; case IOCTL_NDASBUS_UNPLUG_HARDWARE: { if ((sizeof (NDASBUS_UNPLUG_HARDWARE) == inlen) && (inlen == outlen) && (((PNDASBUS_UNPLUG_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n")); status= Bus_UnPlugDevice( (PNDASBUS_UNPLUG_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_NDASBUS_EJECT_HARDWARE: { if ((sizeof (NDASBUS_EJECT_HARDWARE) == inlen) && (inlen == outlen) && (((PNDASBUS_EJECT_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n")); status= Bus_EjectDevice((PNDASBUS_EJECT_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_NDASBUS_DVD_GET_STATUS: { PPDO_DEVICE_DATA pdoData; PNDASBUS_DVD_STATUS pDvdStatusData; // Check Parameter. if((inlen != outlen) || (sizeof(NDASBUS_DVD_STATUS) > inlen)) { status = STATUS_UNSUCCESSFUL ; break; } pDvdStatusData = (PNDASBUS_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("FDO: IOCTL_NDASBUS_DVD_GET_STATUS SlotNumber = %d\n", pDvdStatusData->SlotNo)); pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_DVD_GET_STATUS No pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_DVD_GET_STATUS, pDvdStatusData->SlotNo); break; } else { if(pdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) { // // A LUR descriptor is set. // if(((PLURELATION_DESC)pdoData->LanscsiAdapterPDO.AddDevInfo)->DevType != NDASSCSI_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } else { // // ADD_TARGET_DATA is set. // if(((PNDASBUS_ADD_TARGET_DATA)pdoData->LanscsiAdapterPDO.AddDevInfo)->ucTargetType != NDASSCSI_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_GET_DVD_STATUS, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); status = STATUS_SUCCESS; Irp->IoStatus.Information = outlen; } } break; default: break; // default status is STATUS_INVALID_PARAMETER }
NTSTATUS NdisprotRead( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) /*++ Routine Description: Dispatch routine to handle IRP_MJ_READ. Arguments: pDeviceObject - pointer to our device object pIrp - Pointer to request packet Return Value: NT status code. --*/ { PIO_STACK_LOCATION pIrpSp; NTSTATUS NtStatus; PNDISPROT_OPEN_CONTEXT pOpenContext; UNREFERENCED_PARAMETER(pDeviceObject); pIrpSp = IoGetCurrentIrpStackLocation(pIrp); pOpenContext = pIrpSp->FileObject->FsContext; do { // // Validate! // if (pOpenContext == NULL) { DEBUGP(DL_FATAL, ("Read: NULL FsContext on FileObject %p\n", pIrpSp->FileObject)); NtStatus = STATUS_INVALID_HANDLE; break; } NPROT_STRUCT_ASSERT(pOpenContext, oc); if (pIrp->MdlAddress == NULL) { DEBUGP(DL_FATAL, ("Read: NULL MDL address on IRP %p\n", pIrp)); NtStatus = STATUS_INVALID_PARAMETER; break; } // // Try to get a virtual address for the MDL. // if (MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority) == NULL) { DEBUGP(DL_FATAL, ("Read: MmGetSystemAddr failed for IRP %p, MDL %p\n", pIrp, pIrp->MdlAddress)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; } NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_ACTIVE)) { NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); NtStatus = STATUS_INVALID_HANDLE; break; } IoSetCancelRoutine(pIrp, NdisprotCancelRead); if (pIrp->Cancel && IoSetCancelRoutine(pIrp, NULL)) { // // IRP has been canceled but the I/O manager did not manage to call our cancel routine. This // code is safe referencing the Irp->Cancel field without locks because of the memory barriers // in the interlocked exchange sequences used by IoSetCancelRoutine. // NtStatus = STATUS_CANCELLED; // IRP should be completed after releasing the lock } else { // // Add this IRP to the list of pended Read IRPs // NPROT_INSERT_TAIL_LIST(&pOpenContext->PendedReads, &pIrp->Tail.Overlay.ListEntry); pIrp->Tail.Overlay.DriverContext[0] = (PVOID)pOpenContext; NPROT_REF_OPEN(pOpenContext); // pended read IRP pOpenContext->PendedReadCount++; IoMarkIrpPending(pIrp); NtStatus = STATUS_PENDING; } NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); // // Run the service routine for reads. // ndisprotServiceReads(pOpenContext); } while (FALSE); if (NtStatus != STATUS_PENDING) { NPROT_ASSERT(NtStatus != STATUS_SUCCESS); pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = NtStatus; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } return (NtStatus); }
/* * FUNCTION: Retrieve the specified file information */ NTSTATUS NTAPI CdfsQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp) { FILE_INFORMATION_CLASS FileInformationClass; PIO_STACK_LOCATION Stack; PFILE_OBJECT FileObject; PFCB Fcb; PVOID SystemBuffer; ULONG BufferLength; NTSTATUS Status = STATUS_SUCCESS; DPRINT("CdfsQueryInformation() called\n"); Stack = IoGetCurrentIrpStackLocation(Irp); FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass; FileObject = Stack->FileObject; Fcb = FileObject->FsContext; SystemBuffer = Irp->AssociatedIrp.SystemBuffer; BufferLength = Stack->Parameters.QueryFile.Length; switch (FileInformationClass) { case FileStandardInformation: Status = CdfsGetStandardInformation(Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FilePositionInformation: Status = CdfsGetPositionInformation(FileObject, SystemBuffer, &BufferLength); break; case FileBasicInformation: Status = CdfsGetBasicInformation(FileObject, Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FileNameInformation: Status = CdfsGetNameInformation(FileObject, Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FileInternalInformation: Status = CdfsGetInternalInformation(Fcb, SystemBuffer, &BufferLength); break; case FileNetworkOpenInformation: Status = CdfsGetNetworkOpenInformation(Fcb, SystemBuffer, &BufferLength); break; case FileAllInformation: Status = CdfsGetAllInformation(FileObject, Fcb, SystemBuffer, &BufferLength); break; case FileAlternateNameInformation: Status = STATUS_NOT_IMPLEMENTED; break; default: DPRINT("Unimplemented information class %x\n", FileInformationClass); Status = STATUS_INVALID_PARAMETER; break; } Irp->IoStatus.Status = Status; if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) Irp->IoStatus.Information = Stack->Parameters.QueryFile.Length - BufferLength; else Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(Status); }
/////////////////////////////////////////////////////////////////////////////// // // OsrProcessQueuedRequests // // This interface checks the current state of the read and write // queues, and starts requests on the device if either are not // busy. // // INPUTS: // // devExt - Pointer to device extension of device to start // // OUTPUTS: // // None. // // RETURNS: // // None. // // IRQL: // // // NOTES: // /////////////////////////////////////////////////////////////////////////////// VOID OsrProcessQueuedRequests(IN OUT POSR_DEVICE_EXT devExt) { PVOID entry; PIRP irp; KIRQL oldIrql; // // See if there's something to start on the WRITE queue // KeAcquireSpinLock(&devExt->WriteQueueLock, &oldIrql); while ( !devExt->CurrentWriteIrp && !IsListEmpty(&devExt->WriteQueue) ) { entry = RemoveHeadList(&devExt->WriteQueue); irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry); #if DBG DbgPrint("OsrProcessQueued: IRP removed from WRITE queue = 0x%0x\n",irp); #endif // // If this IRP is cancelled, cancel it now, without // initiating it on the device // if (irp->Cancel) { #if DBG DbgPrint("OsrProcessQueued: CANCEL flag set in READ IRP removed from queue 0x%0x\n",irp); #endif irp->IoStatus.Status = STATUS_CANCELLED; irp->IoStatus.Information = 0; // // Complete the request now // IoCompleteRequest(irp, IO_NO_INCREMENT); } else { // // Since we do not cancel in-progress requests // on this device, we will reset the cancel // routine in the IRP to NULL. // IoSetCancelRoutine(irp, NULL); // // Make this IRP the current write IRP, and // start the request on the device. This routine // sets devExt->CurrentWriteIrp // OsrStartWriteIrp(devExt->FunctionalDeviceObject, irp); } } // while (!devExt->CurrentWriteIrp && // !IsListEmpty(devExt->WriteQueue) ) // // Drop the lock // KeReleaseSpinLock(&devExt->WriteQueueLock, oldIrql); // // See if there's something to start on the READ queue // KeAcquireSpinLock(&devExt->ReadQueueLock, &oldIrql); while ( !devExt->CurrentReadIrp && !IsListEmpty(&devExt->ReadQueue) ) { entry = RemoveHeadList(&devExt->ReadQueue); irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry); #if DBG DbgPrint("OsrProcessQueued: IRP removed from READ queue = 0x%0x\n",irp); #endif // // If this IRP is cancelled, cancel it now, without // initiating it on the device // if (irp->Cancel) { #if DBG DbgPrint("OsrProcessQueued: CANCEL flag set in READ IRP removed from queue 0x%0x\n",irp); #endif irp->IoStatus.Status = STATUS_CANCELLED; irp->IoStatus.Information = 0; // // Complete the request now // IoCompleteRequest(irp, IO_NO_INCREMENT); } else { // // Since we do not cancel in-progress requests // on this device, we will reset the cancel // routine in the IRP to NULL. // IoSetCancelRoutine(irp, NULL); // // Make this IRP the current read IRP, and // start the request on the device. This routine // sets devExt->CurrentReadIrp // OsrStartReadIrp(devExt->FunctionalDeviceObject, irp); } } // while (!devExt->CurrentReadIrp && // !IsListEmpty(devExt->ReadQueue) ) // // Drop the lock // KeReleaseSpinLock(&devExt->ReadQueueLock, oldIrql); }
NTSTATUS DeviceControl ( _In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp ) /*++ Routine Description: Dispatches ioctl requests. Arguments: DeviceObject - The device object receiving the request. Irp - The request packet. Return Value: Status returned from the method called. --*/ { PIO_STACK_LOCATION IrpStack; ULONG Ioctl; NTSTATUS Status; UNREFERENCED_PARAMETER(DeviceObject); Status = STATUS_SUCCESS; IrpStack = IoGetCurrentIrpStackLocation(Irp); Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode; switch (Ioctl) { case IOCTL_DO_KERNELMODE_SAMPLES: Status = DoCallbackSamples(DeviceObject, Irp); break; case IOCTL_REGISTER_CALLBACK: Status = RegisterCallback(DeviceObject, Irp); break; case IOCTL_UNREGISTER_CALLBACK: Status = UnRegisterCallback(DeviceObject, Irp); break; case IOCTL_GET_CALLBACK_VERSION: Status = GetCallbackVersion(DeviceObject, Irp); break; default: ErrorPrint("Unrecognized ioctl code 0x%x", Ioctl); } // // Complete the irp and return. // Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
/////////////////////////////////////////////////////////////////////////////// // // OsrWrite // // This is the write dispatch entry point for the driver, called when the // I/O Manager has an IRP_MJ_WRITE request for the driver to process. // // INPUTS: // // DeviceObject - Address of the DEVICE_OBJECT for our device. // // Irp - Address of the IRP representing the IRP_MJ_WRITE call. // // OUTPUTS: // // None. // // RETURNS: // // STATUS_PENDING, since we are putting the IRP on our internal queue. // // IRQL: // // This routine is called at IRQL_PASSIVE_LEVEL. // // NOTES: // // Since we set the DO_DIRECT_IO bit in the Device Object, all buffers // passed to us will have been probed and locked and described by an MDL. // The I/O manager will provides us the MDL address in Irp->MdlAddress. // /////////////////////////////////////////////////////////////////////////////// NTSTATUS OsrWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp) { POSR_DEVICE_EXT devExt = DeviceObject->DeviceExtension; KIRQL oldIrql; NTSTATUS code = STATUS_SUCCESS; BOOLEAN listWasEmpty; PIO_STACK_LOCATION ioStack; ULONG temp; #if DBG DbgPrint("OsrWrite: entered\n"); #endif // // See what sort of state we're in // if (devExt->State < STATE_ALL_BELOW_FAIL) { code = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = 0; Irp->IoStatus.Status = code; IoCompleteRequest (Irp, IO_NO_INCREMENT); return code; } OsrRequestIncrement(devExt); // // Validate the IRP we've received // ioStack = IoGetCurrentIrpStackLocation(Irp); // // If the length of the requested transfer is either zero or too long, // we immediately compelte the IRP with an error status. // if (ioStack->Parameters.Write.Length == 0 || ioStack->Parameters.Write.Length > OSR_PCI_MAX_TXFER) { Irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(STATUS_INVALID_USER_BUFFER); } // Take out the Write list lock, since we'll insert this IRP // onto the write queue // KeAcquireSpinLock(&devExt->WriteQueueLock, &oldIrql); // // Since we'll probably be queuing this request, set a routine // to be called by the I/O Manager in case he needs to cancel // this IRP. // IoSetCancelRoutine(Irp, OsrCancelFromWriteQueue); // // Before we queue this request, has it been cancelled?? // // What we're doing here is closing that tiny window between the time // the Dispatch routine is called and when we acquired the queue spin // lock. Once the queue spin lock is held, and the IRP is queued, the // cancellation routine will deal with any requests to cancel the IRP. // if (Irp->Cancel) { // // Can't complete a request with a valid cancel routine! // // TECHNICAL ERRATA: Page 466, Example 17.5 has the following // line, which is obviously in error: // // IoSetCancelRoutine(Irp, OsrCancelFromWriteQueue); // // This line SHOULD READ: // IoSetCancelRoutine(Irp, NULL); KeReleaseSpinLock(&devExt->WriteQueueLock, oldIrql); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(STATUS_CANCELLED); } // // If we get this far, we will return with this request pending // IoMarkIrpPending(Irp); // // Do we need to start this request on the device? // // If there is no IRP currently in progress, we'll start the // one we've just received, if the device state allows it. // if (devExt->CurrentWriteIrp == NULL && devExt->State == STATE_STARTED) { // // No write presently active. Start this request... // (Note that we're still holding the queue lock here) // OsrStartWriteIrp(DeviceObject,Irp); } else { // // Put this request on the end of the write queue // InsertTailList(&devExt->WriteQueue, &Irp->Tail.Overlay.ListEntry); } // // We're done playing with the write queue now // KeReleaseSpinLock(&devExt->WriteQueueLock, oldIrql); #if DBG DbgPrint("OsrWrite: exiting\n"); #endif return(STATUS_PENDING); }
NTSTATUS NTAPI SerialDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION Stack; ULONG IoControlCode; PSERIAL_DEVICE_EXTENSION DeviceExtension; ULONG LengthIn, LengthOut; ULONG_PTR Information = 0; PVOID BufferIn, BufferOut; PUCHAR ComPortBase; NTSTATUS Status; TRACE_(SERIAL, "IRP_MJ_DEVICE_CONTROL dispatch\n"); Stack = IoGetCurrentIrpStackLocation(Irp); LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength; LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength; DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ComPortBase = ULongToPtr(DeviceExtension->BaseAddress); IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode; SerialGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut); /* FIXME: need to probe buffers */ /* FIXME: see http://www.osronline.com/ddkx/serial/serref_61bm.htm */ switch (IoControlCode) { case IOCTL_SERIAL_CLEAR_STATS: { TRACE_(SERIAL, "IOCTL_SERIAL_CLEAR_STATS\n"); KeSynchronizeExecution( DeviceExtension->Interrupt, (PKSYNCHRONIZE_ROUTINE)SerialClearPerfStats, DeviceExtension); Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_CLR_DTR: { TRACE_(SERIAL, "IOCTL_SERIAL_CLR_DTR\n"); /* FIXME: If the handshake flow control of the device is configured to * automatically use DTR, return STATUS_INVALID_PARAMETER */ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { DeviceExtension->MCR &= ~SR_MCR_DTR; WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } break; } case IOCTL_SERIAL_CLR_RTS: { TRACE_(SERIAL, "IOCTL_SERIAL_CLR_RTS\n"); /* FIXME: If the handshake flow control of the device is configured to * automatically use RTS, return STATUS_INVALID_PARAMETER */ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { DeviceExtension->MCR &= ~SR_MCR_RTS; WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } break; } case IOCTL_SERIAL_CONFIG_SIZE: { /* Obsolete on Microsoft Windows 2000+ */ PULONG pConfigSize; TRACE_(SERIAL, "IOCTL_SERIAL_CONFIG_SIZE\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pConfigSize = (PULONG)BufferOut; *pConfigSize = 0; Information = sizeof(ULONG); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_BAUD_RATE: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_BAUD_RATE\n"); if (LengthOut < sizeof(SERIAL_BAUD_RATE)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { ((PSERIAL_BAUD_RATE)BufferOut)->BaudRate = DeviceExtension->BaudRate; Information = sizeof(SERIAL_BAUD_RATE); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_CHARS: { /* FIXME */ PSERIAL_CHARS pSerialChars; ERR_(SERIAL, "IOCTL_SERIAL_GET_CHARS not implemented.\n"); if (LengthOut < sizeof(SERIAL_CHARS)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pSerialChars = (PSERIAL_CHARS)BufferOut; pSerialChars->EofChar = 0; pSerialChars->ErrorChar = 0; pSerialChars->BreakChar = 0; pSerialChars->EventChar = 0; pSerialChars->XonChar = 0; pSerialChars->XoffChar = 0; Information = sizeof(SERIAL_CHARS); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_COMMSTATUS: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_COMMSTATUS\n"); if (LengthOut < sizeof(SERIAL_STATUS)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { Status = SerialGetCommStatus((PSERIAL_STATUS)BufferOut, DeviceExtension); Information = sizeof(SERIAL_STATUS); } break; } case IOCTL_SERIAL_GET_DTRRTS: { PULONG pDtrRts; TRACE_(SERIAL, "IOCTL_SERIAL_GET_DTRRTS\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pDtrRts = (PULONG)BufferOut; *pDtrRts = 0; if (DeviceExtension->MCR & SR_MCR_DTR) *pDtrRts |= SERIAL_DTR_STATE; if (DeviceExtension->MCR & SR_MCR_RTS) *pDtrRts |= SERIAL_RTS_STATE; Information = sizeof(ULONG); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_HANDFLOW: { /* FIXME */ PSERIAL_HANDFLOW pSerialHandflow; ERR_(SERIAL, "IOCTL_SERIAL_GET_HANDFLOW not implemented.\n"); if (LengthOut < sizeof(SERIAL_HANDFLOW)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pSerialHandflow = (PSERIAL_HANDFLOW)BufferOut; pSerialHandflow->ControlHandShake = 0; pSerialHandflow->FlowReplace = 0; pSerialHandflow->XonLimit = 0; pSerialHandflow->XoffLimit = 0; Information = sizeof(SERIAL_HANDFLOW); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_LINE_CONTROL: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_LINE_CONTROL\n"); if (LengthOut < sizeof(SERIAL_LINE_CONTROL)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { *((PSERIAL_LINE_CONTROL)BufferOut) = DeviceExtension->SerialLineControl; Information = sizeof(SERIAL_LINE_CONTROL); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_MODEM_CONTROL: { PULONG pMCR; TRACE_(SERIAL, "IOCTL_SERIAL_GET_MODEM_CONTROL\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pMCR = (PULONG)BufferOut; *pMCR = DeviceExtension->MCR; Information = sizeof(ULONG); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_MODEMSTATUS: { PULONG pMSR; TRACE_(SERIAL, "IOCTL_SERIAL_GET_MODEMSTATUS\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pMSR = (PULONG)BufferOut; *pMSR = DeviceExtension->MSR; Information = sizeof(ULONG); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_PROPERTIES: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_PROPERTIES\n"); if (LengthOut < sizeof(SERIAL_COMMPROP)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { Status = SerialGetCommProp((PSERIAL_COMMPROP)BufferOut, DeviceExtension); Information = sizeof(SERIAL_COMMPROP); } break; } case IOCTL_SERIAL_GET_STATS: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_STATS\n"); if (LengthOut < sizeof(SERIALPERF_STATS)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { KeSynchronizeExecution(DeviceExtension->Interrupt, (PKSYNCHRONIZE_ROUTINE)SerialGetPerfStats, Irp); Information = sizeof(SERIALPERF_STATS); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_TIMEOUTS: { TRACE_(SERIAL, "IOCTL_SERIAL_GET_TIMEOUTS\n"); if (LengthOut != sizeof(SERIAL_TIMEOUTS) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { *(PSERIAL_TIMEOUTS)BufferOut = DeviceExtension->SerialTimeOuts; Information = sizeof(SERIAL_TIMEOUTS); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_GET_WAIT_MASK: { PULONG pWaitMask; TRACE_(SERIAL, "IOCTL_SERIAL_GET_WAIT_MASK\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { pWaitMask = (PULONG)BufferOut; *pWaitMask = DeviceExtension->WaitMask; Information = sizeof(ULONG); Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_IMMEDIATE_CHAR: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_IMMEDIATE_CHAR not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_LSRMST_INSERT: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_LSRMST_INSERT not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_PURGE: { KIRQL Irql; TRACE_(SERIAL, "IOCTL_SERIAL_PURGE\n"); /* FIXME: SERIAL_PURGE_RXABORT and SERIAL_PURGE_TXABORT * should stop current request */ if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { ULONG PurgeMask = *(PULONG)BufferIn; Status = STATUS_SUCCESS; /* FIXME: use SERIAL_PURGE_RXABORT and SERIAL_PURGE_TXABORT flags */ if (PurgeMask & SERIAL_PURGE_RXCLEAR) { KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql); DeviceExtension->InputBuffer.ReadPosition = DeviceExtension->InputBuffer.WritePosition = 0; if (DeviceExtension->UartType >= Uart16550A) { /* Clear also Uart FIFO */ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { WRITE_PORT_UCHAR(SER_FCR(ComPortBase), SR_FCR_CLEAR_RCVR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql); } if (PurgeMask & SERIAL_PURGE_TXCLEAR) { KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql); DeviceExtension->OutputBuffer.ReadPosition = DeviceExtension->OutputBuffer.WritePosition = 0; if (DeviceExtension->UartType >= Uart16550A) { /* Clear also Uart FIFO */ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { WRITE_PORT_UCHAR(SER_FCR(ComPortBase), SR_FCR_CLEAR_XMIT); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql); } } break; } case IOCTL_SERIAL_RESET_DEVICE: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_RESET_DEVICE not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_SET_BAUD_RATE: { PULONG pNewBaudRate; TRACE_(SERIAL, "IOCTL_SERIAL_SET_BAUD_RATE\n"); if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { pNewBaudRate = (PULONG)BufferIn; Status = SerialSetBaudRate(DeviceExtension, *pNewBaudRate); } break; } case IOCTL_SERIAL_SET_BREAK_OFF: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_BREAK_OFF not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_SET_BREAK_ON: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_BREAK_ON not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_SET_CHARS: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_CHARS not implemented.\n"); Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_SET_DTR: { /* FIXME: If the handshake flow control of the device is configured to * automatically use DTR, return STATUS_INVALID_PARAMETER */ TRACE_(SERIAL, "IOCTL_SERIAL_SET_DTR\n"); if (!(DeviceExtension->MCR & SR_MCR_DTR)) { Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { DeviceExtension->MCR |= SR_MCR_DTR; WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } else Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_SET_FIFO_CONTROL: { TRACE_(SERIAL, "IOCTL_SERIAL_SET_FIFO_CONTROL\n"); if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)BufferIn) & 0xff)); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } break; } case IOCTL_SERIAL_SET_HANDFLOW: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_HANDFLOW not implemented.\n"); Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_SET_LINE_CONTROL: { TRACE_(SERIAL, "IOCTL_SERIAL_SET_LINE_CONTROL\n"); if (LengthIn < sizeof(SERIAL_LINE_CONTROL)) Status = STATUS_BUFFER_TOO_SMALL; else if (BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else Status = SerialSetLineControl(DeviceExtension, (PSERIAL_LINE_CONTROL)BufferIn); break; } case IOCTL_SERIAL_SET_MODEM_CONTROL: { PULONG pMCR; TRACE_(SERIAL, "IOCTL_SERIAL_SET_MODEM_CONTROL\n"); if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { pMCR = (PULONG)BufferIn; DeviceExtension->MCR = (UCHAR)(*pMCR & 0xff); WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } break; } case IOCTL_SERIAL_SET_QUEUE_SIZE: { if (LengthIn < sizeof(SERIAL_QUEUE_SIZE )) return STATUS_BUFFER_TOO_SMALL; else if (BufferIn == NULL) return STATUS_INVALID_PARAMETER; else { KIRQL Irql; PSERIAL_QUEUE_SIZE NewQueueSize = (PSERIAL_QUEUE_SIZE)BufferIn; Status = STATUS_SUCCESS; if (NewQueueSize->InSize > DeviceExtension->InputBuffer.Length) { KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql); Status = IncreaseCircularBufferSize(&DeviceExtension->InputBuffer, NewQueueSize->InSize); KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql); } if (NT_SUCCESS(Status) && NewQueueSize->OutSize > DeviceExtension->OutputBuffer.Length) { KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql); Status = IncreaseCircularBufferSize(&DeviceExtension->OutputBuffer, NewQueueSize->OutSize); KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql); } } break; } case IOCTL_SERIAL_SET_RTS: { /* FIXME: If the handshake flow control of the device is configured to * automatically use DTR, return STATUS_INVALID_PARAMETER */ TRACE_(SERIAL, "IOCTL_SERIAL_SET_RTS\n"); if (!(DeviceExtension->MCR & SR_MCR_RTS)) { Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (NT_SUCCESS(Status)) { DeviceExtension->MCR |= SR_MCR_RTS; WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); } } else Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_SET_TIMEOUTS: { TRACE_(SERIAL, "IOCTL_SERIAL_SET_TIMEOUTS\n"); if (LengthIn != sizeof(SERIAL_TIMEOUTS) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { DeviceExtension->SerialTimeOuts = *(PSERIAL_TIMEOUTS)BufferIn; Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_SET_WAIT_MASK: { PULONG pWaitMask = (PULONG)BufferIn; TRACE_(SERIAL, "IOCTL_SERIAL_SET_WAIT_MASK\n"); if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else if (DeviceExtension->WaitOnMaskIrp) /* FIXME: Race condition ; field may be currently in modification */ { WARN_(SERIAL, "An IRP is already currently processed\n"); Status = STATUS_INVALID_PARAMETER; } else { DeviceExtension->WaitMask = *pWaitMask; Status = STATUS_SUCCESS; } break; } case IOCTL_SERIAL_SET_XOFF: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_XOFF not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_SET_XON: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_SET_XON not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_SERIAL_WAIT_ON_MASK: { PIRP WaitingIrp; TRACE_(SERIAL, "IOCTL_SERIAL_WAIT_ON_MASK\n"); if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { IoMarkIrpPending(Irp); WaitingIrp = InterlockedCompareExchangePointer( &DeviceExtension->WaitOnMaskIrp, Irp, NULL); /* Check if an Irp is already pending */ if (WaitingIrp != NULL) { /* Unable to have a 2nd pending IRP for this IOCTL */ WARN_(SERIAL, "Unable to pend a second IRP for IOCTL_SERIAL_WAIT_ON_MASK\n"); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return STATUS_PENDING; } break; } case IOCTL_SERIAL_XOFF_COUNTER: { /* FIXME */ ERR_(SERIAL, "IOCTL_SERIAL_XOFF_COUNTER not implemented.\n"); Status = STATUS_NOT_IMPLEMENTED; break; } default: { /* Pass Irp to lower driver */ TRACE_(SERIAL, "Unknown IOCTL code 0x%x\n", Stack->Parameters.DeviceIoControl.IoControlCode); IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DeviceExtension->LowerDevice, Irp); } } Irp->IoStatus.Status = Status; if (Status == STATUS_PENDING) { IoMarkIrpPending(Irp); } else { Irp->IoStatus.Information = Information; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return Status; }
NTSTATUS Bus_FDO_PnP(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PIO_STACK_LOCATION IrpStack, __in PFDO_DEVICE_DATA DeviceData) { NTSTATUS status; ULONG length, prevcount, numPdosPresent, numPdosMissing; PLIST_ENTRY entry, listHead, nextEntry; PPDO_DEVICE_DATA pdoData; PDEVICE_RELATIONS relations, oldRelations; PAGED_CODE(); Bus_IncIoCount(DeviceData); switch (IrpStack->MinorFunction) { case IRP_MN_START_DEVICE: status = Bus_SendIrpSynchronously(DeviceData->NextLowerDriver, Irp); if (NT_SUCCESS(status)) { status = Bus_StartFdo (DeviceData, Irp); } Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); Bus_DecIoCount(DeviceData); return status; case IRP_MN_QUERY_STOP_DEVICE: SET_NEW_PNP_STATE(DeviceData, StopPending); Irp->IoStatus.Status = STATUS_SUCCESS; break; case IRP_MN_CANCEL_STOP_DEVICE: if (StopPending == DeviceData->DevicePnPState) { RESTORE_PREVIOUS_PNP_STATE(DeviceData); ASSERT(DeviceData->DevicePnPState == Started); } Irp->IoStatus.Status = STATUS_SUCCESS; break; case IRP_MN_STOP_DEVICE: Bus_DecIoCount(DeviceData); KeWaitForSingleObject(&DeviceData->StopEvent, Executive, KernelMode, FALSE, NULL); Bus_IncIoCount(DeviceData); SET_NEW_PNP_STATE(DeviceData, Stopped); Irp->IoStatus.Status = STATUS_SUCCESS; break; case IRP_MN_QUERY_REMOVE_DEVICE: SET_NEW_PNP_STATE(DeviceData, RemovePending); Irp->IoStatus.Status = STATUS_SUCCESS; break; case IRP_MN_CANCEL_REMOVE_DEVICE: if (DeviceData->DevicePnPState == RemovePending) { RESTORE_PREVIOUS_PNP_STATE(DeviceData); } Irp->IoStatus.Status = STATUS_SUCCESS; break; case IRP_MN_SURPRISE_REMOVAL: SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending); Bus_RemoveFdo(DeviceData); ExAcquireFastMutex(&DeviceData->Mutex); { listHead = &DeviceData->ListOfPDOs; for(entry = listHead->Flink,nextEntry = entry->Flink; entry != listHead; entry = nextEntry, nextEntry = entry->Flink) { pdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); RemoveEntryList(&pdoData->Link); InitializeListHead(&pdoData->Link); pdoData->ParentFdo = NULL; pdoData->ReportedMissing = TRUE; } } ExReleaseFastMutex(&DeviceData->Mutex); Irp->IoStatus.Status = STATUS_SUCCESS; break; case IRP_MN_REMOVE_DEVICE: if (DeviceData->DevicePnPState != SurpriseRemovePending) { Bus_RemoveFdo(DeviceData); } SET_NEW_PNP_STATE(DeviceData, Deleted); Bus_DecIoCount(DeviceData); Bus_DecIoCount(DeviceData); KeWaitForSingleObject(&DeviceData->RemoveEvent, Executive, KernelMode, FALSE, NULL); ExAcquireFastMutex(&DeviceData->Mutex); { listHead = &DeviceData->ListOfPDOs; for(entry = listHead->Flink,nextEntry = entry->Flink; entry != listHead; entry = nextEntry, nextEntry = entry->Flink) { pdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); RemoveEntryList(&pdoData->Link); if (pdoData->DevicePnPState == SurpriseRemovePending) { Bus_KdPrint(("\tFound a surprise removed device: 0x%p\n", pdoData->Self)); InitializeListHead(&pdoData->Link); pdoData->ParentFdo = NULL; pdoData->ReportedMissing = TRUE; continue; } Bus_DestroyPdo(pdoData->Self, pdoData); } } ExReleaseFastMutex(&DeviceData->Mutex); Irp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(DeviceData->NextLowerDriver, Irp); IoDetachDevice(DeviceData->NextLowerDriver); Bus_KdPrint(("\tDeleting FDO: 0x%p\n", DeviceObject)); IoDeleteDevice(DeviceObject); return status; case IRP_MN_QUERY_DEVICE_RELATIONS: Bus_KdPrint(("\tQueryDeviceRelation Type: %s\n", DbgDeviceRelationString(IrpStack->Parameters.QueryDeviceRelations.Type))); if (IrpStack->Parameters.QueryDeviceRelations.Type != BusRelations) { break; } ExAcquireFastMutex(&DeviceData->Mutex); oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information; if (oldRelations) { prevcount = oldRelations->Count; if (!DeviceData->NumPDOs) { ExReleaseFastMutex(&DeviceData->Mutex); break; } } else { prevcount = 0; } numPdosPresent = 0; numPdosMissing = 0; for (entry = DeviceData->ListOfPDOs.Flink; entry != &DeviceData->ListOfPDOs; entry = entry->Flink) { pdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); if (pdoData->Present) numPdosPresent++; } length = sizeof(DEVICE_RELATIONS) + ((numPdosPresent + prevcount) * sizeof (PDEVICE_OBJECT)) - 1; relations = (PDEVICE_RELATIONS) ExAllocatePoolWithTag(PagedPool, length, BUSENUM_POOL_TAG); if (relations == NULL) { ExReleaseFastMutex(&DeviceData->Mutex); Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES; IoCompleteRequest(Irp, IO_NO_INCREMENT); Bus_DecIoCount(DeviceData); return status; } if (prevcount) { RtlCopyMemory(relations->Objects, oldRelations->Objects, prevcount * sizeof (PDEVICE_OBJECT)); } relations->Count = prevcount + numPdosPresent; for (entry = DeviceData->ListOfPDOs.Flink; entry != &DeviceData->ListOfPDOs; entry = entry->Flink) { pdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); if (pdoData->Present) { relations->Objects[prevcount] = pdoData->Self; ObReferenceObject(pdoData->Self); prevcount++; } else { pdoData->ReportedMissing = TRUE; numPdosMissing++; } } Bus_KdPrint(("#PDOS Present = %d, Reported = %d, Missing = %d, Listed = %d", numPdosPresent, relations->Count, numPdosMissing, DeviceData->NumPDOs)); if (oldRelations) { ExFreePool(oldRelations); } Irp->IoStatus.Information = (ULONG_PTR) relations; ExReleaseFastMutex(&DeviceData->Mutex); Irp->IoStatus.Status = STATUS_SUCCESS; break; default: break; } IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(DeviceData->NextLowerDriver, Irp); Bus_DecIoCount(DeviceData); return status; }
int main() { if (__VERIFIER_nondet_int()) { // haven't stopped yet, lets do so ntStatus = t1394Diag_PnpStopDevice(DeviceObject, Irp); } ntStatus = IoSetDeviceInterfaceState(); // lets free up any crom data structs we've allocated... keA = 1; keA = 0; KeAcquireSpinLock(&lock3, &Irql); k1 = __VERIFIER_nondet_int(); while (k1>0) { CromData = __VERIFIER_nondet_int(); // get struct off list k1--; // need to free up everything associated with this allocate... if (CromData) { if (__VERIFIER_nondet_int()) ExFreePool0(); if (__VERIFIER_nondet_int()) IoFreeMdl(); // we already checked CromData ExFreePool1(CromData); } } keR = 1; keR = 0; KeReleaseSpinLock(&lock3, Irql); keA = 1; keA = 0; KeAcquireSpinLock(&lock1, &Irql); k2 = __VERIFIER_nondet_int(); while (k2>0) { AsyncAddressData = __VERIFIER_nondet_int(); // get struct off list AsyncAddressData = __VERIFIER_nondet_int(); k2--; // need to free up everything associated with this allocate... if (__VERIFIER_nondet_int()) IoFreeMdl(); if (__VERIFIER_nondet_int()) ExFreePool0(); if (__VERIFIER_nondet_int()) ExFreePool0(); if (AsyncAddressData) ExFreePool0(); } keR = 1; keR = 0; KeReleaseSpinLock(&lock1, Irql); // free up any attached isoch buffers while (TRUE) { keA = 1; keA = 0; KeAcquireSpinLock(&lock4, &Irql); k3 = __VERIFIER_nondet_int(); if (k3>0) { IsochDetachData = __VERIFIER_nondet_int(); i = __VERIFIER_nondet_int(); IsochDetachData = __VERIFIER_nondet_int(); k3--; KeCancelTimer(); keR = 1; keR = 0; KeReleaseSpinLock(&lock4, Irql); t1394_IsochCleanup(IsochDetachData); } else { keR = 1; keR = 0; KeReleaseSpinLock(&lock4, Irql); break; } } // remove any isoch resource data k4 = __VERIFIER_nondet_int(); while (TRUE) { keA = 1; keA = 0; KeAcquireSpinLock(&lock5, &Irql); if (k4>0) { IsochResourceData = __VERIFIER_nondet_int(); k4--; keR = 1; keR = 0; KeReleaseSpinLock(&lock5, Irql); if (IsochResourceData) { pIrb = __VERIFIER_nondet_int(); ResourceIrp = __VERIFIER_nondet_int(); StackSize = __VERIFIER_nondet_int(); ResourceIrp = IoAllocateIrp(StackSize, FALSE); if (ResourceIrp == NULL) { } else { pIrb = ExAllocatePool(NonPagedPool, sizeof(IRB)); if (!pIrb) { IoFreeIrp(ResourceIrp); } else { RtlZeroMemory (pIrb, sizeof (IRB)); ntStatus = t1394_SubmitIrpSynch(ResourceIrp, pIrb); ExFreePool1(pIrb); IoFreeIrp(ResourceIrp); } } } } else { keR = 1; keR = 0; KeReleaseSpinLock(&lock5, Irql); break; } } // get rid of any pending bus reset notify requests keA = 1; keA = 0; KeAcquireSpinLock(&lock6, &Irql); k5 = __VERIFIER_nondet_int(); while (k5>0) { prevCancel = NULL; // get the irp off of the list BusResetIrp = __VERIFIER_nondet_int(); k5--; // make this irp non-cancelable... prevCancel = IoSetCancelRoutine(NULL); // and complete it... IoCompleteRequest(IO_NO_INCREMENT); ExFreePool1(BusResetIrp); } keR = 1; keR = 0; KeReleaseSpinLock(&lock6, Irql); // free up the symbolic link while(1); }
NTSTATUS FWDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION irpStack; PDEVICE_EXTENSION deviceExtension; PVOID ioBuf; ULONG inBufLength, outBufLength; ULONG ioControlCode; ULONG_PTR num=0; irpStack = IoGetCurrentIrpStackLocation(Irp); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; Irp->IoStatus.Information = 0; // // Get the pointer to the input/output buffer and it's length // ioBuf = Irp->AssociatedIrp.SystemBuffer; inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; // Irp->UserBuffer; // If METHOD_NEITHER, This is Output Buffer switch (ioControlCode) { case IOCTL_SETUPFW: { // if (g_AlreadyHookTCPIP) { InterlockedExchange(&g_InterceptTCPIPRcv, 1); } else { Status= FWHookTcpipRecvHandler(); if (NT_SUCCESS(Status)) { InterlockedExchange(&g_InterceptTCPIPRcv, 1); g_AlreadyHookTCPIP = 1; } } break; } case IOCTL_UNSETFW: { // InterlockedExchange(&g_InterceptTCPIPRcv, 0); //UNHOOK的行为就放到驱动卸载时候了 break; } case IOCTL_PENDDINGCHECKPORT: { //pendding进去 IoMarkIrpPending(Irp); ExInterlockedInsertHeadList(&g_AskUserConnectListHeader, &Irp->Tail.Overlay.ListEntry, &g_AskUserConnectListLock); Status= STATUS_PENDING; Irp->IoStatus.Status = Status; return Status; break; } case IOCTL_SETONEPORTSTATUS: { Status = SetupPortStatus(ioBuf, 1); break; } case IOCTL_RESPONSEPORTASK: { Status = ResponsePortAsk((PFIREWALL_ASKUSER)ioBuf); break; } case IOCTL_ReleasePENDDINGCHECKPORT: { Status = ReleasePenddingCheckPortIrp(); break; } case IOCTL_GETPORTSTATUS: { Status = GetPortRules(ioBuf, &outBufLength); if (Status==STATUS_INFO_LENGTH_MISMATCH) { Status = STATUS_SUCCESS; } Irp->IoStatus.Information = outBufLength; break; } default: { //Status = STATUS_INVALID_PARAMETER; kprintf("[SuperCI] Unknown IOCTL: 0x%X (%04X,%04X)\n", ioControlCode, DEVICE_TYPE_FROM_CTL_CODE(ioControlCode), IoGetFunctionCodeFromCtlCode(ioControlCode)); break; } } Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
//前面说到为每一个磁盘设备对象生成了一个系统线程,用来处理Irp VOID FileDiskThread ( IN PVOID Context ) { PDEVICE_OBJECT device_object; PDEVICE_EXTENSION device_extension; PLIST_ENTRY request; PIRP irp; PIO_STACK_LOCATION io_stack; PUCHAR system_buffer; PUCHAR buffer; ASSERT(Context != NULL); device_object = (PDEVICE_OBJECT) Context; device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension; KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY); for (;;) { KeWaitForSingleObject( &device_extension->request_event, Executive, KernelMode, FALSE, NULL ); if (device_extension->terminate_thread) { PsTerminateSystemThread(STATUS_SUCCESS); } while (request = ExInterlockedRemoveHeadList( &device_extension->list_head, &device_extension->list_lock )) { irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry); io_stack = IoGetCurrentIrpStackLocation(irp); switch (io_stack->MajorFunction) { case IRP_MJ_READ: system_buffer = (PUCHAR) MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (system_buffer == NULL) { irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; irp->IoStatus.Information = 0; break; } buffer = (PUCHAR) ExAllocatePool(PagedPool, io_stack->Parameters.Read.Length); if (buffer == NULL) { irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; irp->IoStatus.Information = 0; break; } ZwReadFile( device_extension->file_handle, NULL, NULL, NULL, &irp->IoStatus, buffer, io_stack->Parameters.Read.Length, &io_stack->Parameters.Read.ByteOffset, NULL ); RtlCopyMemory(system_buffer, buffer, io_stack->Parameters.Read.Length); ExFreePool(buffer); break; case IRP_MJ_WRITE: if ((io_stack->Parameters.Write.ByteOffset.QuadPart + io_stack->Parameters.Write.Length) > device_extension->file_size.QuadPart) { irp->IoStatus.Status = STATUS_INVALID_PARAMETER; irp->IoStatus.Information = 0; } ZwWriteFile( device_extension->file_handle, NULL, NULL, NULL, &irp->IoStatus, MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority), io_stack->Parameters.Write.Length, &io_stack->Parameters.Write.ByteOffset, NULL ); break; case IRP_MJ_DEVICE_CONTROL: switch (io_stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_FILE_DISK_OPEN_FILE: SeImpersonateClient(device_extension->security_client_context, NULL); irp->IoStatus.Status = FileDiskOpenFile(device_object, irp); PsRevertToSelf(); break; case IOCTL_FILE_DISK_CLOSE_FILE: irp->IoStatus.Status = FileDiskCloseFile(device_object, irp); break; default: irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR; } break; default: irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR; } IoCompleteRequest( irp, (CCHAR) (NT_SUCCESS(irp->IoStatus.Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT) ); } } }
NTSTATUS Bus_IoCtl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Handle user mode PlugIn, UnPlug and device Eject requests. 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; ULONG inlen, outlen; PFDO_DEVICE_DATA fdoData; PVOID buffer; PAGED_CODE (); fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; // // We only take Device Control requests for the FDO. // That is the bus itself. // if (!fdoData->IsFDO) { // // These commands are only allowed to go to the FDO. // status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // // Check to see whether the bus is removed // if (fdoData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } Bus_IncIoCount (fdoData); irpStack = IoGetCurrentIrpStackLocation (Irp); buffer = Irp->AssociatedIrp.SystemBuffer; inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength; outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength; status = STATUS_INVALID_PARAMETER; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode)); switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_LANSCSI_ADD_TARGET: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen) && (sizeof(LANSCSI_ADD_TARGET_DATA) <= inlen)) { ULONG ulSize; PLANSCSI_ADD_TARGET_DATA addTargetData = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_ADD_TARGET called\n")); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET Target Type %d\n", addTargetData->ucTargetType)); // Check Parameter. switch(addTargetData->ucTargetType) { case DISK_TYPE_NORMAL: case DISK_TYPE_DVD: case DISK_TYPE_VDVD: case DISK_TYPE_MO: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA); if(addTargetData->ulNumberOfUnitDiskList != 1) { ulSize = 0; // Exit when Check if(ulSize != inlen)... } break; case DISK_TYPE_MIRROR: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK); if(2 != addTargetData->ulNumberOfUnitDiskList) { ulSize = 0; // Exit when Check if(ulSize != inlen)... } break; case DISK_TYPE_AGGREGATION: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1); if (addTargetData->ulNumberOfUnitDiskList < 2 || addTargetData->ulNumberOfUnitDiskList > MAX_NR_TC_PER_TARGET) { ulSize = 0; // Exit when Check if(ulSize != inlen)... } break; case DISK_TYPE_BIND_RAID0: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1); switch(addTargetData->ulNumberOfUnitDiskList) { case 2: case 4: case 8: break; default: // do not accept ulSize = 0; break; } break; case DISK_TYPE_BIND_RAID1: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1); if (addTargetData->ulNumberOfUnitDiskList < 2 || addTargetData->ulNumberOfUnitDiskList > MAX_NR_TC_PER_TARGET) { ulSize = 0; // Exit when Check if(ulSize != inlen)... } if (addTargetData->ulNumberOfUnitDiskList % 2) { // should be the multiples of 2 ulSize = 0; // Exit when Check if(ulSize != inlen)... } break; case DISK_TYPE_BIND_RAID4: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (addTargetData->ulNumberOfUnitDiskList - 1); switch(addTargetData->ulNumberOfUnitDiskList) { case 3: // 2 + 1 case 5: // 4 + 1 case 9: // 8 + 1 break; default: // do not accept ulSize = 0; break; } break; default: Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET: Bad Disk Type.\n")); status = STATUS_UNSUCCESSFUL; break; } // Check Size. if(ulSize != inlen) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen)); status = STATUS_UNSUCCESSFUL; break; } // Find Pdo Data... pdoData = LookupPdoData(fdoData, addTargetData->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; break; } pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePool(NonPagedPool, inlen); if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; } else { RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, addTargetData, inlen); status = STATUS_SUCCESS; } pdoData->LanscsiAdapterPDO.AddDevInfoLength = inlen; // // Notify to LanscsiMiniport // Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET SetEvent AddTargetEvent!\n")); KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE); // // Register Target // if(pdoData->Persistent) { status = LSBus_RegisterTarget(fdoData, addTargetData); if(!NT_SUCCESS(status)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: LSBus_RegisterTarget() failed. STATUS=%08lx\n", status)); status = STATUS_INTERNAL_DB_ERROR; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("ADD_TARGET: Successfully registered.\n")); } } ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET length mismatch!!!" " inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } } break; case IOCTL_LANSCSI_REMOVE_TARGET: { PPDO_DEVICE_DATA pdoData; PLANSCSI_REMOVE_TARGET_DATA removeTarget; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REMOVE_TARGET called\n")); if (sizeof (LANSCSI_REMOVE_TARGET_DATA) != inlen) break; removeTarget = (PLANSCSI_REMOVE_TARGET_DATA)buffer; pdoData = LookupPdoData(fdoData, removeTarget->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; break; } // // redirect to the NDAS SCSI Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_REMOVE_TARGET, buffer, sizeof(LANSCSI_REMOVE_TARGET_DATA), NULL, 0 ); if(NT_SUCCESS(status) && pdoData->Persistent) { status = LSBus_UnregisterTarget(fdoData, removeTarget->ulSlotNo, removeTarget->ulTargetId); if(!NT_SUCCESS(status)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ( "REMOVE_TARGET: Removed Target instance," " but LSBus_UnregisterTarget() failed.\n")); status = STATUS_INTERNAL_DB_ERROR; } #if DBG else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("REMOVE_TARGET: LSBus_UnregisterTarget() succeeded.\n")); } #endif } ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = 0; break; } case IOCTL_LANSCSI_RECOVER_TARGET: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_RECOVER_TARGET called\n")); if (sizeof (LANSCSI_RECOVER_TARGET_DATA) != inlen) break; pdoData = LookupPdoData(fdoData, ((PLANSCSI_RECOVER_TARGET_DATA)buffer)->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; break; } // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_RECOVER_TARGET, buffer, sizeof(LANSCSI_RECOVER_TARGET_DATA), NULL, 0 ); ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; break; } case IOCTL_LANSCSI_REGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_DEVICE: inlen %d, outlen %d," " sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen)) { PBUSENUM_PLUGIN_HARDWARE_EX2 PlugIn = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_DEVICE: entered\n")); status = LSBus_RegisterDevice(fdoData, PlugIn); Irp->IoStatus.Information = 0; } else Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("REGISTER_DEVICE: length mismatch!!!" " inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } break; case IOCTL_LANSCSI_REGISTER_TARGET: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_TARGET: inlen %d, outlen %d," " sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen)) { PLANSCSI_ADD_TARGET_DATA AddTargetData = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_TARGET: entered\n")); status = LSBus_RegisterTarget(fdoData, AddTargetData); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_TARGET: length mismatch!!!" " inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } } break; case IOCTL_LANSCSI_UNREGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_DEVICE: inlen %d, outlen %d," " sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen)) { PLANSCSI_UNREGISTER_NDASDEV UnregDev = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_DEVICE: entered\n")); status = LSBus_UnregisterDevice(fdoData, UnregDev->SlotNo); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_DEVICE: length mismatch!!!" " inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } } break; case IOCTL_LANSCSI_UNREGISTER_TARGET: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_TARGET: inlen %d, outlen %d," " sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen)) { PLANSCSI_UNREGISTER_TARGET UnregTarget = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_TARGET: entered\n")); status = LSBus_UnregisterTarget(fdoData, UnregTarget->SlotNo, UnregTarget->TargetId); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_TARGET: length mismatch!!!" " inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } } break; case IOCTL_LANSCSI_SETPDOINFO: { PPDO_DEVICE_DATA pdoData; PBUSENUM_SETPDOINFO SetPdoInfo; KIRQL oldIrql; PVOID sectionHandle; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_SETPDOINFO called\n")); if (sizeof (BUSENUM_SETPDOINFO) != inlen) break; SetPdoInfo = (PBUSENUM_SETPDOINFO)buffer; pdoData = LookupPdoData(fdoData, (SetPdoInfo)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; break; } // // lock the code section of this function to acquire spinlock in raised IRQL. // sectionHandle = MmLockPagableCodeSection(Bus_IoCtl); KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! IOCTL_LANSCSI_SETPDOINFO: %08lx %08lx %08lx\n", SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess)); // // Set status values to the corresponding physical device object. // if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, ADAPTERINFO_STATUS_STOPPING) && ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_STOPPED)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'Stopping' event occured after 'Stopped' event\n", SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess)); } else { pdoData->LanscsiAdapterPDO.AdapterStatus = SetPdoInfo->AdapterStatus; pdoData->LanscsiAdapterPDO.DesiredAccess = SetPdoInfo->DesiredAccess; pdoData->LanscsiAdapterPDO.GrantedAccess = SetPdoInfo->GrantedAccess; } KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); // // Release the code section. // MmUnlockPagableImageSection(sectionHandle); status = STATUS_SUCCESS; ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } break; case IOCTL_BUSENUM_QUERY_NODE_ALIVE: { PPDO_DEVICE_DATA pdoData; BOOLEAN bAlive; PBUSENUM_NODE_ALIVE_IN pNodeAliveIn; BUSENUM_NODE_ALIVE_OUT nodeAliveOut; // Check Parameter. if(inlen != sizeof(BUSENUM_NODE_ALIVE_IN) || outlen != sizeof(BUSENUM_NODE_ALIVE_OUT)) { status = STATUS_UNKNOWN_REVISION; break; } pNodeAliveIn = (PBUSENUM_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE, ("FDO: IOCTL_BUSENUM_QUERY_NODE_ALIVE SlotNumber = %d\n", pNodeAliveIn->SlotNo)); pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo); if(pdoData == NULL) { // Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, // ("[LanScsiBus]Bus_IoCtl: IOCTL_BUSENUM_QUERY_NODE_ALIVE No pdo\n")); bAlive = FALSE; } else { // // Check this PDO would be removed... // if(pdoData->Present == TRUE) bAlive = TRUE; else bAlive = FALSE; } // For Result... nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo; nodeAliveOut.bAlive = bAlive; // Get Adapter Status. if(bAlive == TRUE) { if( ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_IN_ERROR) || ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_STOPPING) /*|| ADAPTERINFO_ISSTATUSFLAG(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUSFLAG_MEMBER_FAULT) */ ) { nodeAliveOut.bHasError = TRUE; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_BUSENUM_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError)); } else { nodeAliveOut.bHasError = FALSE; } } if(pdoData) ObDereferenceObject(pdoData->Self); RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &nodeAliveOut, sizeof(BUSENUM_NODE_ALIVE_OUT) ); Irp->IoStatus.Information = sizeof(BUSENUM_NODE_ALIVE_OUT); status = STATUS_SUCCESS; } break; // // added by hootch 01172004 // case IOCTL_LANSCSI_UPGRADETOWRITE: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_UPGRADETOWRITE called\n")); // Check Parameter. if(inlen != sizeof(BUSENUM_UPGRADE_TO_WRITE)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_UPGRADETOWRITE: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_UPGRADETOWRITE: No pdo for Slotno:%d\n", ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo)); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_LANSCSI_REDIRECT_NDASSCSI: { PPDO_DEVICE_DATA pdoData; PBUSENUM_REDIRECT_NDASSCSI redirectIoctl; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REDIRECT_NDASSCSI called\n")); // Check Parameter. if(inlen < sizeof(BUSENUM_REDIRECT_NDASSCSI)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_REDIRECT_NDASSCSI: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } redirectIoctl = (PBUSENUM_REDIRECT_NDASSCSI)buffer; pdoData = LookupPdoData(fdoData, redirectIoctl->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_REDIRECT_NDASSCSI: No pdo for Slotno:%d\n", redirectIoctl->SlotNo)); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, redirectIoctl->IoctlCode, redirectIoctl->IoctlData, redirectIoctl->IoctlDataSize, redirectIoctl->IoctlData, redirectIoctl->IoctlDataSize ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_LANSCSI_QUERY_LSMPINFORMATION: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION called\n")); // Check Parameter. if(inlen < FIELD_OFFSET(LSMPIOCTL_QUERYINFO, QueryData) ) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION: Invalid input buffer length too small.\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PLSMPIOCTL_QUERYINFO)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION No pdo\n")); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_QUERYINFO_EX, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = outlen; } break; case IOCTL_BUSENUM_QUERY_INFORMATION: { // PPDO_DEVICE_DATA pdoData; BUSENUM_QUERY_INFORMATION Query; PBUSENUM_INFORMATION Information; LONG BufferLenNeeded; // Check Parameter. if( inlen < sizeof(BUSENUM_QUERY_INFORMATION) /*|| outlen < sizeof(BUSENUM_INFORMATION) */) { status = STATUS_UNKNOWN_REVISION; break; } RtlCopyMemory(&Query, buffer, sizeof(BUSENUM_QUERY_INFORMATION)); Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, ("FDO: IOCTL_BUSENUM_QUERY_INFORMATION QueryType : %d SlotNumber = %d\n", Query.InfoClass, Query.SlotNo)); Information = (PBUSENUM_INFORMATION)buffer; ASSERT(Information); Information->InfoClass = Query.InfoClass; status = LSBus_QueryInformation(fdoData, &Query, Information, outlen, &BufferLenNeeded); if(NT_SUCCESS(status)) { Information->Size = BufferLenNeeded; Irp->IoStatus.Information = BufferLenNeeded; } else { Irp->IoStatus.Information = BufferLenNeeded; } } break; case IOCTL_BUSENUM_PLUGIN_HARDWARE_EX: { if ((inlen == outlen) && // // Make sure it has at least two nulls and the size // field is set to the declared size of the struct // ((sizeof (BUSENUM_PLUGIN_HARDWARE_EX) + sizeof(UNICODE_NULL) * 2) <= inlen) && // // The size field should be set to the sizeof the struct as declared // and *not* the size of the struct plus the multi_sz // (sizeof (BUSENUM_PLUGIN_HARDWARE_EX) == ((PBUSENUM_PLUGIN_HARDWARE_EX) buffer)->Size)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n")); status= Bus_PlugInDeviceEx((PBUSENUM_PLUGIN_HARDWARE_EX)buffer, inlen, fdoData, Irp->RequestorMode); Irp->IoStatus.Information = outlen; } } break; case IOCTL_BUSENUM_PLUGIN_HARDWARE_EX2: { if ((inlen == outlen) && // // Make sure it has at least two nulls and the size // field is set to the declared size of the struct // ((sizeof (BUSENUM_PLUGIN_HARDWARE_EX2) + sizeof(UNICODE_NULL) * 2) <= inlen) && // // The size field should be set to the sizeof the struct as declared // and *not* the size of the struct plus the multi_sz // (sizeof (BUSENUM_PLUGIN_HARDWARE_EX2) == ((PBUSENUM_PLUGIN_HARDWARE_EX2) buffer)->Size)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n")); status= Bus_PlugInDeviceEx2((PBUSENUM_PLUGIN_HARDWARE_EX2)buffer, inlen, fdoData, Irp->RequestorMode, FALSE); Irp->IoStatus.Information = outlen; } } break; case IOCTL_LANSCSI_GETVERSION: { if (outlen >= sizeof(BUSENUM_GET_VERSION)) { PBUSENUM_GET_VERSION version = (PBUSENUM_GET_VERSION)buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_GETVERSION: called\n")); try { version->VersionMajor = VER_FILEMAJORVERSION; version->VersionMinor = VER_FILEMINORVERSION; version->VersionBuild = VER_FILEBUILD; version->VersionPrivate = VER_FILEBUILD_QFE; Irp->IoStatus.Information = sizeof(BUSENUM_GET_VERSION); status = STATUS_SUCCESS; } except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); Irp->IoStatus.Information = 0; } } } break; case IOCTL_BUSENUM_UNPLUG_HARDWARE: { if ((sizeof (BUSENUM_UNPLUG_HARDWARE) == inlen) && (inlen == outlen) && (((PBUSENUM_UNPLUG_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n")); status= Bus_UnPlugDevice( (PBUSENUM_UNPLUG_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_BUSENUM_EJECT_HARDWARE: { if ((sizeof (BUSENUM_EJECT_HARDWARE) == inlen) && (inlen == outlen) && (((PBUSENUM_EJECT_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n")); status= Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_DVD_GET_STATUS: { PPDO_DEVICE_DATA pdoData; PBUSENUM_DVD_STATUS pDvdStatusData; // Check Parameter. if((inlen != outlen) || (sizeof(BUSENUM_DVD_STATUS) > inlen)) { status = STATUS_UNSUCCESSFUL ; break; } pDvdStatusData = (PBUSENUM_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("FDO: IOCTL_DVD_GET_STATUS SlotNumber = %d\n", pDvdStatusData->SlotNo)); pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No pdo\n")); status = STATUS_UNSUCCESSFUL; break; } else { if(pdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) { // // A LUR descriptor is set. // if(((PLURELATION_DESC)pdoData->LanscsiAdapterPDO.AddDevInfo)->DevType != DISK_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } else { // // ADD_TARGET_DATA is set. // if(((PLANSCSI_ADD_TARGET_DATA)pdoData->LanscsiAdapterPDO.AddDevInfo)->ucTargetType != DISK_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_GET_DVD_STATUS, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); status = STATUS_SUCCESS; Irp->IoStatus.Information = outlen; } } break; default: break; // default status is STATUS_INVALID_PARAMETER }
NTSTATUS FileDiskDeviceControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION device_extension; PIO_STACK_LOCATION io_stack; NTSTATUS status; // 得到设备扩展 device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; // 得到当前设备栈 io_stack = IoGetCurrentIrpStackLocation(Irp); // 判断如果是还没有加载物理媒质就返回失败。但是 // IOCTL_FILE_DISK_OPEN_FILE是自定义的功能号,专 // 用来加载物理媒质的 if (!device_extension->media_in_device && io_stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_FILE_DISK_OPEN_FILE) { Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_MEDIA_IN_DEVICE; } // 根据不同的功能号处理... switch (io_stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_FILE_DISK_OPEN_FILE: { SECURITY_QUALITY_OF_SERVICE security_quality_of_service; if (device_extension->media_in_device) { KdPrint(("FileDisk: IOCTL_FILE_DISK_OPEN_FILE: Media already opened\n")); status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; break; } if (io_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(OPEN_FILE_INFORMATION)) { status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; break; } if (io_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(OPEN_FILE_INFORMATION) + ((POPEN_FILE_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->FileNameLength - sizeof(UCHAR)) { status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; break; } if (device_extension->security_client_context != NULL) { SeDeleteClientSecurity(device_extension->security_client_context); } else { device_extension->security_client_context = ExAllocatePool(NonPagedPool, sizeof(SECURITY_CLIENT_CONTEXT)); } RtlZeroMemory(&security_quality_of_service, sizeof(SECURITY_QUALITY_OF_SERVICE)); security_quality_of_service.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); security_quality_of_service.ImpersonationLevel = SecurityImpersonation; security_quality_of_service.ContextTrackingMode = SECURITY_STATIC_TRACKING; security_quality_of_service.EffectiveOnly = FALSE; SeCreateClientSecurity( PsGetCurrentThread(), &security_quality_of_service, FALSE, device_extension->security_client_context ); IoMarkIrpPending(Irp); ExInterlockedInsertTailList( &device_extension->list_head, &Irp->Tail.Overlay.ListEntry, &device_extension->list_lock ); KeSetEvent( &device_extension->request_event, (KPRIORITY) 0, FALSE ); status = STATUS_PENDING; break; } case IOCTL_FILE_DISK_CLOSE_FILE: { IoMarkIrpPending(Irp); ExInterlockedInsertTailList( &device_extension->list_head, &Irp->Tail.Overlay.ListEntry, &device_extension->list_lock ); KeSetEvent( &device_extension->request_event, (KPRIORITY) 0, FALSE ); status = STATUS_PENDING; break; } case IOCTL_FILE_DISK_QUERY_FILE: { POPEN_FILE_INFORMATION open_file_information; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(OPEN_FILE_INFORMATION) + device_extension->file_name.Length - sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } open_file_information = (POPEN_FILE_INFORMATION) Irp->AssociatedIrp.SystemBuffer; open_file_information->FileSize.QuadPart = device_extension->file_size.QuadPart; open_file_information->ReadOnly = device_extension->read_only; open_file_information->FileNameLength = device_extension->file_name.Length; RtlCopyMemory( open_file_information->FileName, device_extension->file_name.Buffer, device_extension->file_name.Length ); status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(OPEN_FILE_INFORMATION) + open_file_information->FileNameLength - sizeof(UCHAR); break; } case IOCTL_DISK_CHECK_VERIFY: case IOCTL_CDROM_CHECK_VERIFY: case IOCTL_STORAGE_CHECK_VERIFY: case IOCTL_STORAGE_CHECK_VERIFY2: { status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; break; } case IOCTL_DISK_GET_DRIVE_GEOMETRY: case IOCTL_CDROM_GET_DRIVE_GEOMETRY: { PDISK_GEOMETRY disk_geometry; ULONGLONG length; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } disk_geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer; length = device_extension->file_size.QuadPart; disk_geometry->Cylinders.QuadPart = length / SECTOR_SIZE / 32 / 2; disk_geometry->MediaType = FixedMedia; disk_geometry->TracksPerCylinder = 2; disk_geometry->SectorsPerTrack = 32; disk_geometry->BytesPerSector = SECTOR_SIZE; status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); break; } case IOCTL_DISK_GET_LENGTH_INFO: { PGET_LENGTH_INFORMATION get_length_information; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GET_LENGTH_INFORMATION)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } get_length_information = (PGET_LENGTH_INFORMATION) Irp->AssociatedIrp.SystemBuffer; get_length_information->Length.QuadPart = device_extension->file_size.QuadPart; status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION); break; } case IOCTL_DISK_GET_PARTITION_INFO: { PPARTITION_INFORMATION partition_information; ULONGLONG length; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARTITION_INFORMATION)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } partition_information = (PPARTITION_INFORMATION) Irp->AssociatedIrp.SystemBuffer; length = device_extension->file_size.QuadPart; partition_information->StartingOffset.QuadPart = 0; partition_information->PartitionLength.QuadPart = length; partition_information->HiddenSectors = 1; partition_information->PartitionNumber = 0; partition_information->PartitionType = 0; partition_information->BootIndicator = FALSE; partition_information->RecognizedPartition = FALSE; partition_information->RewritePartition = FALSE; status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION); break; } case IOCTL_DISK_GET_PARTITION_INFO_EX: { PPARTITION_INFORMATION_EX partition_information_ex; ULONGLONG length; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARTITION_INFORMATION_EX)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } partition_information_ex = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer; length = device_extension->file_size.QuadPart; partition_information_ex->PartitionStyle = PARTITION_STYLE_MBR; partition_information_ex->StartingOffset.QuadPart = 0; partition_information_ex->PartitionLength.QuadPart = length; partition_information_ex->PartitionNumber = 0; partition_information_ex->RewritePartition = FALSE; partition_information_ex->Mbr.PartitionType = 0; partition_information_ex->Mbr.BootIndicator = FALSE; partition_information_ex->Mbr.RecognizedPartition = FALSE; partition_information_ex->Mbr.HiddenSectors = 1; status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX); break; } case IOCTL_DISK_IS_WRITABLE: { if (!device_extension->read_only) { status = STATUS_SUCCESS; } else { status = STATUS_MEDIA_WRITE_PROTECTED; } Irp->IoStatus.Information = 0; break; } case IOCTL_DISK_MEDIA_REMOVAL: case IOCTL_STORAGE_MEDIA_REMOVAL: { status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; break; } case IOCTL_CDROM_READ_TOC: { PCDROM_TOC cdrom_toc; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(CDROM_TOC)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } cdrom_toc = (PCDROM_TOC) Irp->AssociatedIrp.SystemBuffer; RtlZeroMemory(cdrom_toc, sizeof(CDROM_TOC)); cdrom_toc->FirstTrack = 1; cdrom_toc->LastTrack = 1; cdrom_toc->TrackData[0].Control = TOC_DATA_TRACK; status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(CDROM_TOC); break; } case IOCTL_DISK_SET_PARTITION_INFO: { if (device_extension->read_only) { status = STATUS_MEDIA_WRITE_PROTECTED; Irp->IoStatus.Information = 0; break; } if (io_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SET_PARTITION_INFORMATION)) { status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; break; } status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; break; } case IOCTL_DISK_VERIFY: { PVERIFY_INFORMATION verify_information; if (io_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(VERIFY_INFORMATION)) { status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; break; } verify_information = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer; status = STATUS_SUCCESS; Irp->IoStatus.Information = verify_information->Length; break; } default: { KdPrint(( "FileDisk: Unknown IoControlCode %#x\n", io_stack->Parameters.DeviceIoControl.IoControlCode )); status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; } } if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return status; }
VOID NotificationLoop( __in PIRP_LIST PendingIrp, __in PIRP_LIST NotifyEvent ) { PDRIVER_EVENT_CONTEXT driverEventContext; PLIST_ENTRY listHead; PIRP_ENTRY irpEntry; LIST_ENTRY completeList; NTSTATUS status; KIRQL irpIrql; KIRQL notifyIrql; PIRP irp; ULONG eventLen; ULONG bufferLen; PVOID buffer; //DDbgPrint("=> NotificationLoop\n"); InitializeListHead(&completeList); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); KeAcquireSpinLock(&PendingIrp->ListLock, &irpIrql); KeAcquireSpinLock(&NotifyEvent->ListLock, ¬ifyIrql); while (!IsListEmpty(&PendingIrp->ListHead) && !IsListEmpty(&NotifyEvent->ListHead)) { listHead = RemoveHeadList(&NotifyEvent->ListHead); driverEventContext = CONTAINING_RECORD( listHead, DRIVER_EVENT_CONTEXT, ListEntry); listHead = RemoveHeadList(&PendingIrp->ListHead); irpEntry = CONTAINING_RECORD(listHead, IRP_ENTRY, ListEntry); eventLen = driverEventContext->EventContext.Length; // ensure this eventIrp is not cancelled irp = irpEntry->Irp; if (irp == NULL) { // this IRP has already been canceled ASSERT(irpEntry->CancelRoutineFreeMemory == FALSE); DokanFreeIrpEntry(irpEntry); // push back InsertTailList(&NotifyEvent->ListHead, &driverEventContext->ListEntry); continue; } if (IoSetCancelRoutine(irp, NULL) == NULL) { // Cancel routine will run as soon as we release the lock InitializeListHead(&irpEntry->ListEntry); irpEntry->CancelRoutineFreeMemory = TRUE; // push back InsertTailList(&NotifyEvent->ListHead, &driverEventContext->ListEntry); continue; } // available size that is used for event notification bufferLen = irpEntry->IrpSp->Parameters.DeviceIoControl.OutputBufferLength; // buffer that is used to inform Event buffer = irp->AssociatedIrp.SystemBuffer; // buffer is not specified or short of length if (bufferLen == 0 || buffer == NULL || bufferLen < eventLen) { DDbgPrint("EventNotice : STATUS_INSUFFICIENT_RESOURCES\n"); DDbgPrint(" bufferLen: %d, eventLen: %d\n", bufferLen, eventLen); // push back InsertTailList(&NotifyEvent->ListHead, &driverEventContext->ListEntry); // marks as STATUS_INSUFFICIENT_RESOURCES irpEntry->SerialNumber = 0; } else { // let's copy EVENT_CONTEXT RtlCopyMemory(buffer, &driverEventContext->EventContext, eventLen); // save event length irpEntry->SerialNumber = eventLen; if (driverEventContext->Completed) { KeSetEvent(driverEventContext->Completed, IO_NO_INCREMENT, FALSE); } ExFreePool(driverEventContext); } InsertTailList(&completeList, &irpEntry->ListEntry); } KeClearEvent(&NotifyEvent->NotEmpty); KeClearEvent(&PendingIrp->NotEmpty); KeReleaseSpinLock(&NotifyEvent->ListLock, notifyIrql); KeReleaseSpinLock(&PendingIrp->ListLock, irpIrql); while (!IsListEmpty(&completeList)) { listHead = RemoveHeadList(&completeList); irpEntry = CONTAINING_RECORD(listHead, IRP_ENTRY, ListEntry); irp = irpEntry->Irp; if (irpEntry->SerialNumber == 0) { irp->IoStatus.Information = 0; irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; } else { irp->IoStatus.Information = irpEntry->SerialNumber; irp->IoStatus.Status = STATUS_SUCCESS; } DokanFreeIrpEntry(irpEntry); IoCompleteRequest(irp, IO_NO_INCREMENT); } //DDbgPrint("<= NotificationLoop\n"); }
NTSTATUS Bus_Power ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Handles power Irps sent to both FDO and child PDOs. Note: Currently we do not implement full power handling for the FDO. Arguments: DeviceObject - Pointer to the device object. Irp - Pointer to the irp. Return Value: NT status is returned. --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status; PCOMMON_DEVICE_DATA commonData; status = STATUS_SUCCESS; irpStack = IoGetCurrentIrpStackLocation (Irp); ASSERT (IRP_MJ_POWER == irpStack->MajorFunction); commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; // // If the device has been removed, the driver should // not pass the IRP down to the next lower driver. // if (commonData->DevicePnPState == Deleted) { PoStartNextPowerIrp (Irp); Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } if (commonData->IsFDO) { Bus_KdPrint (commonData, BUS_DBG_PNP_TRACE, ("FDO %s IRP:0x%x %s %s\n", PowerMinorFunctionString(irpStack->MinorFunction), Irp, DbgSystemPowerString(commonData->SystemPowerState), DbgDevicePowerString(commonData->DevicePowerState))); status = Bus_FDO_Power ((PFDO_DEVICE_DATA)DeviceObject->DeviceExtension, Irp); } else { Bus_KdPrint (commonData, BUS_DBG_PNP_TRACE, ("PDO %s IRP:0x%x %s %s\n", PowerMinorFunctionString(irpStack->MinorFunction), Irp, DbgSystemPowerString(commonData->SystemPowerState), DbgDevicePowerString(commonData->DevicePowerState))); status = Bus_PDO_Power ((PPDO_DEVICE_DATA)DeviceObject->DeviceExtension, Irp); } return status; }