VOID Primary_FileSystemShutdown ( IN PPRIMARY Primary ) { ULONG listenSocketIndex; Primary_Reference(Primary); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_ERROR, ("Primary_FileSystemShutdown: Entered primary = %p\n", Primary)); do { if(Primary->Agent.ThreadHandle == NULL) { ASSERT(LFS_BUG); break; } ASSERT(Primary->Agent.ThreadObject != NULL); if(Primary->Agent.Flags & PRIMARY_AGENT_TERMINATED) { break; } else { PPRIMARY_AGENT_REQUEST primaryAgentRequest; NTSTATUS ntStatus; LARGE_INTEGER timeOut; primaryAgentRequest = AllocPrimaryAgentRequest(TRUE); primaryAgentRequest->RequestType = PRIMARY_AGENT_REQ_SHUTDOWN; QueueingPrimaryAgentRequest( Primary, primaryAgentRequest ); timeOut.QuadPart = - LFS_TIME_OUT; // 10 sec ntStatus = KeWaitForSingleObject( &primaryAgentRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut ); ASSERT(ntStatus == STATUS_SUCCESS); KeClearEvent(&primaryAgentRequest->CompleteEvent); if(ntStatus == STATUS_SUCCESS) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("Primary_FileSystemShutdown: thread shutdown\n")); } else { ASSERT(LFS_BUG); break; } } }while(0); for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++) { if(Primary->Agent.ListenSocket[listenSocketIndex].Active != TRUE) continue; while(1) { KIRQL oldIrql; BOOLEAN found; PLIST_ENTRY primarySessionListEntry; KeAcquireSpinLock(&Primary->PrimarySessionQSpinLock[listenSocketIndex], &oldIrql); found = FALSE; for (primarySessionListEntry = Primary->PrimarySessionQueue[listenSocketIndex].Flink; primarySessionListEntry != &Primary->PrimarySessionQueue[listenSocketIndex]; primarySessionListEntry = primarySessionListEntry->Flink) { PPRIMARY_SESSION primarySession; primarySession = CONTAINING_RECORD (primarySessionListEntry, PRIMARY_SESSION, ListEntry); //if(primarySession->LfsDeviceExt && primarySession->LfsDeviceExt->FileSystemType == FileSystemType) //{ RemoveEntryList(primarySessionListEntry); KeReleaseSpinLock(&Primary->PrimarySessionQSpinLock[listenSocketIndex], oldIrql); InitializeListHead(primarySessionListEntry); PrimarySession_FileSystemShutdown(primarySession); found = TRUE; break; //} } if(found == FALSE) { KeReleaseSpinLock(&Primary->PrimarySessionQSpinLock[listenSocketIndex], oldIrql); break; } } } Primary_Dereference(Primary); return; }
/*++//////////////////////////////////////////////////////////////////////////// ClassReleaseRemoveLock() Routine Description: This routine is called to release the remove lock on the device object. It must be called when finished using a previously locked reference to the device object. If an Tag was specified when acquiring the lock then the same Tag must be specified when releasing the lock. When the lock count reduces to zero, this routine will signal the waiting remove Tag to delete the device object. As a result the DeviceObject pointer should not be used again once the lock has been released. Arguments: DeviceObject - the device object to lock Tag - The irp (if any) specified when acquiring the lock. This is used for lock tracking purposes Return Value: none --*/ VOID NTAPI ClassReleaseRemoveLock( IN PDEVICE_OBJECT DeviceObject, IN OPTIONAL PIRP Tag ) { PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; LONG lockValue; #if DBG PREMOVE_TRACKING_BLOCK *listEntry = (PREMOVE_TRACKING_BLOCK*)&commonExtension->RemoveTrackingList; BOOLEAN found = FALSE; LONGLONG maxCount; BOOLEAN isRemoved = (commonExtension->IsRemoved == REMOVE_COMPLETE); KIRQL oldIrql; if(isRemoved) { DBGTRAP(("ClassReleaseRemoveLock: REMOVE_COMPLETE set; this should never happen")); InterlockedDecrement(&(commonExtension->RemoveLock)); return; } // // Check the tick count and make sure this thing hasn't been locked // for more than MaxLockedMinutes. // maxCount = KeQueryTimeIncrement() * 10; // microseconds maxCount *= 1000; // milliseconds maxCount *= 1000; // seconds maxCount *= 60; // minutes maxCount *= MaxLockedMinutes; DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: " "maxCount = %0I64x\n", maxCount)); KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock, &oldIrql); while(*listEntry != NULL) { PREMOVE_TRACKING_BLOCK block; LARGE_INTEGER difference; block = *listEntry; KeQueryTickCount((&difference)); difference.QuadPart -= block->TimeLocked.QuadPart; DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: " "Object %p (tag %p) locked for %I64d ticks\n", DeviceObject, block->Tag, difference.QuadPart)); if(difference.QuadPart >= maxCount) { DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: " "Object %p (tag %p) locked for %I64d ticks - TOO LONG\n", DeviceObject, block->Tag, difference.QuadPart)); DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: " "Lock acquired in file %s on line %d\n", block->File, block->Line)); ASSERT(FALSE); } if((found == FALSE) && ((*listEntry)->Tag == Tag)) { *listEntry = block->NextBlock; ExFreePool(block); found = TRUE; } else { listEntry = &((*listEntry)->NextBlock); } } if(!found) { if(commonExtension->RemoveTrackingUntrackedCount == 0) { DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: " "Couldn't find Tag %p in the lock tracking list\n", Tag)); ASSERT(FALSE); } else { DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: " "Couldn't find Tag %p in the lock tracking list - " "may be one of the %d untracked requests still " "outstanding\n", Tag, commonExtension->RemoveTrackingUntrackedCount)); commonExtension->RemoveTrackingUntrackedCount--; ASSERT(commonExtension->RemoveTrackingUntrackedCount >= 0); } } KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, oldIrql); #endif lockValue = InterlockedDecrement(&commonExtension->RemoveLock); DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: " "Released for Object %p & irp %p - count is %d\n", DeviceObject, Tag, lockValue)); ASSERT(lockValue >= 0); ASSERTMSG("RemoveLock decreased to meet LockLowWatermark", ((LockLowWatermark == 0) || !(lockValue == LockLowWatermark))); if(lockValue == 0) { ASSERT(commonExtension->IsRemoved); // // The device needs to be removed. Signal the remove event // that it's safe to go ahead. // DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: " "Release for object %p & irp %p caused lock to go to zero\n", DeviceObject, Tag)); KeSetEvent(&commonExtension->RemoveEvent, IO_NO_INCREMENT, FALSE); } return; }
NTSTATUS USBPcapBufferHandleReadIrp(PIRP pIrp, PDEVICE_EXTENSION pDevExt, PUINT32 pBytesRead) { PDEVICE_EXTENSION pRootExt; PUSBPCAP_ROOTHUB_DATA pRootData; PVOID buffer; UINT32 bufferLength; UINT32 bytesRead; NTSTATUS status; KIRQL irql; PIO_STACK_LOCATION pStack = NULL; pStack = IoGetCurrentIrpStackLocation(pIrp); *pBytesRead = 0; if (pStack->Parameters.Read.Length == 0) { return STATUS_SUCCESS; } pRootExt = (PDEVICE_EXTENSION)pDevExt->context.control.pRootHubObject->DeviceExtension; pRootData = pRootExt->context.usb.pDeviceData->pRootData; if (pRootData->buffer == NULL) { return STATUS_UNSUCCESSFUL; } /* * Since control device has DO_DIRECT_IO bit set the MDL is already * probed and locked */ buffer = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); if (buffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } else { bufferLength = MmGetMdlByteCount(pIrp->MdlAddress); } /* Get data from data queue, if there is no data we put * this IRP to Cancel-Safe queue and return status pending * otherwise complete this IRP then return SUCCESS */ KeAcquireSpinLock(&pRootData->bufferLock, &irql); bytesRead = USBPcapBufferRead(pRootData, buffer, bufferLength); KeReleaseSpinLock(&pRootData->bufferLock, irql); *pBytesRead = bytesRead; if (bytesRead == 0) { IoCsqInsertIrp(&pDevExt->context.control.ioCsq, pIrp, NULL); return STATUS_PENDING; } return STATUS_SUCCESS; }
NTSTATUS AnajoystDispatch( IN PDEVICE_OBJECT pDO, IN PIRP pIrp ) /*++ Routine Description: Driver dispatch routine. Processes IRPs based on IRP MajorFunction Arguments: pDO -- pointer to the device object pIrp -- pointer to the IRP to process Return Value: Returns the value of the IRP IoStatus.Status --*/ { PIO_STACK_LOCATION pIrpStack; KIRQL OldIrql; NTSTATUS Status; DWORD dwRetries = 0; //DbgBreakPoint(); pIrpStack = IoGetCurrentIrpStackLocation(pIrp); Status = STATUS_SUCCESS; pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = 0; switch (pIrpStack->MajorFunction) { case IRP_MJ_CREATE: // // perform synchronous I/O // //pIrpStack->FileObject->Flags |= FO_SYNCHRONOUS_IO; //NB This is bad code -- we are simply one thread wandering off through the computer -- we should be queuing up a DPC, //returning status_pending to the calling program, then finishing the job when the dpc goes. This is possible given //the analog game port technology. // don't slam it into digital mode //Status = AnajoystReset (((PJOY_EXTENSION)pDO->DeviceExtension)->DeviceAddress); //((PJOY_EXTENSION)pDO->DeviceExtension)->CurrentDeviceMode = NULL; // KeDelayExecutionThread( KernelMode, FALSE, &LI10ms); //unnecessary since AnajoystReset has a delay in it? pIrp->IoStatus.Status = Status; break; case IRP_MJ_CLOSE: break; case IRP_MJ_READ: // // Find out which device we are and read, but first make sure // there is enough room // DebugTrace(("IRP_MJ_READ")); //DbgBreakPoint(); if (pIrpStack->Parameters.Read.Length < sizeof(JOY_DD_INPUT_DATA)) { Status = STATUS_BUFFER_TOO_SMALL; pIrp->IoStatus.Status = Status; break; } // // Serialize and get the current device values // KeAcquireSpinLock(((PJOY_EXTENSION) pDO->DeviceExtension)->SpinLock, & OldIrql); Status = AnajoystPoll(pDO, pIrp); // // release the spinlock // KeReleaseSpinLock(((PJOY_EXTENSION)pDO->DeviceExtension)->SpinLock, OldIrql); pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = sizeof (JOY_DD_INPUT_DATA); break; case IRP_MJ_DEVICE_CONTROL: switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_JOY_GET_STATISTICS: // report statistics ((PJOY_STATISTICS)pIrp->AssociatedIrp.SystemBuffer)->Version = JoyStatistics.Version; ((PJOY_STATISTICS)pIrp->AssociatedIrp.SystemBuffer)->Polls = JoyStatistics.Polls; ((PJOY_STATISTICS)pIrp->AssociatedIrp.SystemBuffer)->Timeouts = JoyStatistics.Timeouts; ((PJOY_STATISTICS)pIrp->AssociatedIrp.SystemBuffer)->PolledTooSoon = JoyStatistics.PolledTooSoon; ((PJOY_STATISTICS)pIrp->AssociatedIrp.SystemBuffer)->Redo = JoyStatistics.Redo; ((PJOY_STATISTICS)pIrp->AssociatedIrp.SystemBuffer)->nQuiesceLoop = nQuiesceLoop; ((PJOY_STATISTICS)pIrp->AssociatedIrp.SystemBuffer)->Frequency = Frequency; ((PJOY_STATISTICS)pIrp->AssociatedIrp.SystemBuffer)->NumberOfAxes = ((PJOY_EXTENSION)pDO->DeviceExtension)->NumberOfAxes; ((PJOY_STATISTICS)pIrp->AssociatedIrp.SystemBuffer)->bTwoSticks = ((PJOY_EXTENSION)pDO->DeviceExtension)->bTwoSticks; Status = STATUS_SUCCESS; pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = sizeof(JOY_STATISTICS); // reset statistics JoyStatistics.Polls = 0; JoyStatistics.Timeouts = 0; JoyStatistics.PolledTooSoon = 0; JoyStatistics.Redo = 0; break; case IOCTL_JOY_GET_JOYREGHWCONFIG: AnajoystGetConfig ( (LPJOYREGHWCONFIG)(pIrp->AssociatedIrp.SystemBuffer), ((PJOY_EXTENSION)pDO->DeviceExtension) ); pIrp->IoStatus.Information = sizeof(JOYREGHWCONFIG); break; default: DebugTrace(("Unknown IoControlCode")); break; } // end switch on IOCTL code break; default: DebugTrace(("Unknown IRP Major Function %d", pIrpStack->MajorFunction)); } // end switch on IRP_MAJOR_XXXX // pIrp->IoStatus.Status must be set to Status by this point. // pIrp->IoStatus.Information must be set to the correct size by this point. IoCompleteRequest(pIrp, IO_NO_INCREMENT); return Status; }
/* * @implemented */ NTSTATUS NTAPI IoAcquireRemoveLockEx(IN PIO_REMOVE_LOCK RemoveLock, IN OPTIONAL PVOID Tag, IN LPCSTR File, IN ULONG Line, IN ULONG RemlockSize) { KIRQL OldIrql; LONG LockValue; PIO_REMOVE_LOCK_TRACKING_BLOCK TrackingBlock; PEXTENDED_IO_REMOVE_LOCK Lock = (PEXTENDED_IO_REMOVE_LOCK)RemoveLock; /* Increase the lock count */ LockValue = InterlockedIncrement(&(Lock->Common.IoCount)); ASSERT(LockValue > 0); if (!Lock->Common.Removed) { /* Check what kind of lock this is */ if (RemlockSize == (sizeof(IO_REMOVE_LOCK_DBG_BLOCK) + sizeof(IO_REMOVE_LOCK_COMMON_BLOCK))) { ASSERT(Lock->Dbg.HighWatermark == 0 || LockValue <= Lock->Dbg.HighWatermark); /* Allocate a tracking block */ TrackingBlock = ExAllocatePoolWithTag(NonPagedPool, sizeof(IO_REMOVE_LOCK_TRACKING_BLOCK), Lock->Dbg.AllocateTag); if (!TrackingBlock) { /* Keep count of failures for lock release and missing tags */ InterlockedIncrement(&(Lock->Dbg.LowMemoryCount)); } else { /* Initialize block */ RtlZeroMemory(TrackingBlock, sizeof(IO_REMOVE_LOCK_TRACKING_BLOCK)); TrackingBlock->Tag = Tag; TrackingBlock->File = File; TrackingBlock->Line = Line; KeQueryTickCount(&(TrackingBlock->LockMoment)); /* Queue the block */ KeAcquireSpinLock(&(Lock->Dbg.Spin), &OldIrql); TrackingBlock->Next = Lock->Dbg.Blocks; Lock->Dbg.Blocks = TrackingBlock; KeReleaseSpinLock(&(Lock->Dbg.Spin), OldIrql); } } } else { /* Otherwise, decrement the count and check if it's gone */ if (!InterlockedDecrement(&(Lock->Common.IoCount))) { /* Signal the event */ KeSetEvent(&(Lock->Common.RemoveEvent), IO_NO_INCREMENT, FALSE); } /* Return pending delete */ return STATUS_DELETE_PENDING; } /* Otherwise, return success */ return STATUS_SUCCESS; }
// When user-mode file system application returns EventInformation, // search corresponding pending IRP and complete it NTSTATUS DokanCompleteIrp( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { KIRQL oldIrql; PLIST_ENTRY thisEntry, nextEntry, listHead; PIRP_ENTRY irpEntry; PDokanVCB vcb; PEVENT_INFORMATION eventInfo; eventInfo = (PEVENT_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ASSERT(eventInfo != NULL); //DDbgPrint("==> DokanCompleteIrp [EventInfo #%X]\n", eventInfo->SerialNumber); vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB) { return STATUS_INVALID_PARAMETER; } //DDbgPrint(" Lock IrpList.ListLock\n"); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); KeAcquireSpinLock(&vcb->Dcb->PendingIrp.ListLock, &oldIrql); // search corresponding IRP through pending IRP list listHead = &vcb->Dcb->PendingIrp.ListHead; for (thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = nextEntry) { PIRP irp; PIO_STACK_LOCATION irpSp; nextEntry = thisEntry->Flink; irpEntry = CONTAINING_RECORD(thisEntry, IRP_ENTRY, ListEntry); // check whether this is corresponding IRP //DDbgPrint("SerialNumber irpEntry %X eventInfo %X\n", irpEntry->SerialNumber, eventInfo->SerialNumber); // this irpEntry must be freed in this if statement if (irpEntry->SerialNumber != eventInfo->SerialNumber) { continue; } RemoveEntryList(thisEntry); irp = irpEntry->Irp; if (irp == NULL) { // this IRP is already canceled ASSERT(irpEntry->CancelRoutineFreeMemory == FALSE); DokanFreeIrpEntry(irpEntry); irpEntry = NULL; break; } if (IoSetCancelRoutine(irp, NULL) == NULL) { // Cancel routine will run as soon as we release the lock InitializeListHead(&irpEntry->ListEntry); irpEntry->CancelRoutineFreeMemory = TRUE; break; } // IRP is not canceled yet irpSp = irpEntry->IrpSp; ASSERT(irpSp != NULL); // IrpEntry is saved here for CancelRoutine // Clear it to prevent to be completed by CancelRoutine twice irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_IRP_ENTRY] = NULL; KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql); switch (irpSp->MajorFunction) { case IRP_MJ_DIRECTORY_CONTROL: DokanCompleteDirectoryControl(irpEntry, eventInfo); break; case IRP_MJ_READ: DokanCompleteRead(irpEntry, eventInfo); break; case IRP_MJ_WRITE: DokanCompleteWrite(irpEntry, eventInfo); break; case IRP_MJ_QUERY_INFORMATION: DokanCompleteQueryInformation(irpEntry, eventInfo); break; case IRP_MJ_QUERY_VOLUME_INFORMATION: DokanCompleteQueryVolumeInformation(irpEntry, eventInfo); break; case IRP_MJ_CREATE: DokanCompleteCreate(irpEntry, eventInfo); break; case IRP_MJ_CLEANUP: DokanCompleteCleanup(irpEntry, eventInfo); break; case IRP_MJ_LOCK_CONTROL: DokanCompleteLock(irpEntry, eventInfo); break; case IRP_MJ_SET_INFORMATION: DokanCompleteSetInformation(irpEntry, eventInfo); break; case IRP_MJ_FLUSH_BUFFERS: DokanCompleteFlush(irpEntry, eventInfo); break; case IRP_MJ_QUERY_SECURITY: DokanCompleteQuerySecurity(irpEntry, eventInfo); break; case IRP_MJ_SET_SECURITY: DokanCompleteSetSecurity(irpEntry, eventInfo); break; default: DDbgPrint("Unknown IRP %d\n", irpSp->MajorFunction); // TODO: in this case, should complete this IRP break; } DokanFreeIrpEntry(irpEntry); irpEntry = NULL; return STATUS_SUCCESS; } KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql); //DDbgPrint("<== AACompleteIrp [EventInfo #%X]\n", eventInfo->SerialNumber); // TODO: should return error return STATUS_SUCCESS; }
NTSTATUS RegisterPendingIrpMain( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in ULONG SerialNumber, __in PIRP_LIST IrpList, __in ULONG Flags, __in ULONG CheckMount ) { PIRP_ENTRY irpEntry; PIO_STACK_LOCATION irpSp; KIRQL oldIrql; //DDbgPrint("==> DokanRegisterPendingIrpMain\n"); if (GetIdentifierType(DeviceObject->DeviceExtension) == VCB) { PDokanVCB vcb = DeviceObject->DeviceExtension; if (CheckMount && !vcb->Dcb->Mounted) { DDbgPrint(" device is not mounted\n"); return STATUS_INSUFFICIENT_RESOURCES; } } irpSp = IoGetCurrentIrpStackLocation(Irp); // Allocate a record and save all the event context. irpEntry = DokanAllocateIrpEntry(); if (NULL == irpEntry) { DDbgPrint(" can't allocate IRP_ENTRY\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(irpEntry, sizeof(IRP_ENTRY)); InitializeListHead(&irpEntry->ListEntry); irpEntry->SerialNumber = SerialNumber; irpEntry->FileObject = irpSp->FileObject; irpEntry->Irp = Irp; irpEntry->IrpSp = irpSp; irpEntry->IrpList = IrpList; irpEntry->Flags = Flags; DokanUpdateTimeout(&irpEntry->TickCount, DOKAN_IRP_PENDING_TIMEOUT); //DDbgPrint(" Lock IrpList.ListLock\n"); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); KeAcquireSpinLock(&IrpList->ListLock, &oldIrql); IoSetCancelRoutine(Irp, DokanIrpCancelRoutine); if (Irp->Cancel) { if (IoSetCancelRoutine(Irp, NULL) != NULL) { //DDbgPrint(" Release IrpList.ListLock %d\n", __LINE__); KeReleaseSpinLock(&IrpList->ListLock, oldIrql); DokanFreeIrpEntry(irpEntry); return STATUS_CANCELLED; } } IoMarkIrpPending(Irp); InsertTailList(&IrpList->ListHead, &irpEntry->ListEntry); irpEntry->CancelRoutineFreeMemory = FALSE; // save the pointer in order to be accessed by cancel routine Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_IRP_ENTRY] = irpEntry; KeSetEvent(&IrpList->NotEmpty, IO_NO_INCREMENT, FALSE); //DDbgPrint(" Release IrpList.ListLock\n"); KeReleaseSpinLock(&IrpList->ListLock, oldIrql); //DDbgPrint("<== DokanRegisterPendingIrpMain\n"); return STATUS_PENDING;; }
NTSTATUS DokanGetAccessToken( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { KIRQL oldIrql; PLIST_ENTRY thisEntry, nextEntry, listHead; PIRP_ENTRY irpEntry; PDokanVCB vcb; PEVENT_INFORMATION eventInfo; PACCESS_TOKEN accessToken; NTSTATUS status = STATUS_INVALID_PARAMETER; HANDLE handle; PIO_STACK_LOCATION irpSp = NULL; BOOLEAN hasLock = FALSE; ULONG outBufferLen; ULONG inBufferLen; PACCESS_STATE accessState; DDbgPrint("==> DokanGetAccessToken\n"); __try { eventInfo = (PEVENT_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ASSERT(eventInfo != NULL); if (Irp->RequestorMode != UserMode) { DDbgPrint(" needs to be called from user-mode\n"); status = STATUS_INVALID_PARAMETER; __leave; } vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB) { DDbgPrint(" GetIdentifierType != VCB\n"); status = STATUS_INVALID_PARAMETER; __leave; } irpSp = IoGetCurrentIrpStackLocation(Irp); outBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength; inBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength; if (outBufferLen != sizeof(EVENT_INFORMATION) || inBufferLen != sizeof(EVENT_INFORMATION)) { DDbgPrint(" wrong input or output buffer length\n"); status = STATUS_INVALID_PARAMETER; __leave; } ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); KeAcquireSpinLock(&vcb->Dcb->PendingIrp.ListLock, &oldIrql); hasLock = TRUE; // search corresponding IRP through pending IRP list listHead = &vcb->Dcb->PendingIrp.ListHead; for (thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = nextEntry) { nextEntry = thisEntry->Flink; irpEntry = CONTAINING_RECORD(thisEntry, IRP_ENTRY, ListEntry); if (irpEntry->SerialNumber != eventInfo->SerialNumber) { continue; } // this irp must be IRP_MJ_CREATE if (irpEntry->IrpSp->Parameters.Create.SecurityContext) { accessState = irpEntry->IrpSp->Parameters.Create.SecurityContext->AccessState; } break; } KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql); hasLock = FALSE; if (accessState == NULL) { DDbgPrint(" can't find pending Irp: %d\n", eventInfo->SerialNumber); __leave; } accessToken = SeQuerySubjectContextToken(&accessState->SubjectSecurityContext); if (accessToken == NULL) { DDbgPrint(" accessToken == NULL\n"); __leave; } // NOTE: Accessing *SeTokenObjectType while acquring sping lock causes // BSOD on Windows XP. status = ObOpenObjectByPointer(accessToken, 0, NULL, GENERIC_ALL, *SeTokenObjectType, KernelMode, &handle); if (!NT_SUCCESS(status)) { DDbgPrint(" ObOpenObjectByPointer failed: 0x%x\n", status); __leave; } eventInfo->AccessToken.Handle = handle; Irp->IoStatus.Information = sizeof(EVENT_INFORMATION); status = STATUS_SUCCESS; } __finally { if (hasLock) { KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql); } } DDbgPrint("<== DokanGetAccessToken\n"); return status; }
ULONG MpHwFindAdapter( __in PVOID DeviceExtension, __in PVOID pReservedArg1, __in PVOID pReservedArg2, #ifdef USE_STORPORT __in PVOID pReservedArg3, #endif __in PCHAR ArgumentString, __in __out PPORT_CONFIGURATION_INFORMATION pConfigInfo, __out PBOOLEAN pBAgain ) { ULONG i, len, status = SP_RETURN_FOUND; PCHAR pChar; PHW_HBA_EXT pHBAExt = (PHW_HBA_EXT)DeviceExtension; NTSTATUS ntstatus; #if defined(_AMD64_) KLOCK_QUEUE_HANDLE LockHandle; #else KIRQL SaveIrql; #endif UNREFERENCED_PARAMETER(pReservedArg1); UNREFERENCED_PARAMETER(pReservedArg2); #ifdef USE_STORPORT UNREFERENCED_PARAMETER(pReservedArg3); #endif UNREFERENCED_PARAMETER(ArgumentString); KdPrint2(("PhDskMnt::MpHwFindAdapter: Arg=%s%s%s, pHBAExt = 0x%p, pConfigInfo = 0x%p, IRQL=%i\n", ArgumentString != NULL ? "\"" : "(", ArgumentString != NULL ? ArgumentString : "null", ArgumentString != NULL ? "\"" : ")", pHBAExt, pConfigInfo, KeGetCurrentIrql())); #if VERBOSE_DEBUG_TRACE > 0 if (!KD_DEBUGGER_NOT_PRESENT) DbgBreakPoint(); #endif if (pMPDrvInfoGlobal->GlobalsInitialized) { LARGE_INTEGER wait_time; DbgPrint("PhDskMnt::MpHwFindAdapter: Already initialized.\n"); wait_time.QuadPart = -1000000; KeDelayExecutionThread(KernelMode, FALSE, &wait_time); } KeInitializeSpinLock(&pHBAExt->LUListLock); InitializeListHead(&pHBAExt->LUList); pHBAExt->HostTargetId = (UCHAR)pMPDrvInfoGlobal->MPRegInfo.InitiatorID; pConfigInfo->WmiDataProvider = FALSE; // Indicate WMI provider. pConfigInfo->NumberOfPhysicalBreaks = 4096; pConfigInfo->MaximumTransferLength = 8 << 20; // 8 MB. #ifdef USE_STORPORT pConfigInfo->VirtualDevice = TRUE; // Inidicate no real hardware. pConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex; if (pConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED) pConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_FULL64BIT_SUPPORTED; #endif #ifdef USE_SCSIPORT //if (pConfigInfo->NumberOfPhysicalBreaks == SP_UNINITIALIZED_VALUE) // pConfigInfo->NumberOfPhysicalBreaks = 4096; //if (pConfigInfo->MaximumTransferLength > (64 << 10)) // pConfigInfo->MaximumTransferLength = 64 << 10; // 64 KB. pConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED; #endif pConfigInfo->AlignmentMask = 0x3; // Indicate DWORD alignment. pConfigInfo->CachesData = FALSE; // Indicate miniport wants flush and shutdown notification. pConfigInfo->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS; // Indicate maximum targets. pConfigInfo->NumberOfBuses = (UCHAR) pMPDrvInfoGlobal->MPRegInfo.NumberOfBuses; // Indicate number of busses. pConfigInfo->ScatterGather = TRUE; // Indicate scatter-gather (explicit setting needed for Win2003 at least). pConfigInfo->AutoRequestSense = TRUE; pConfigInfo->TaggedQueuing = TRUE; pConfigInfo->MultipleRequestPerLu = TRUE; // Save Vendor Id, Product Id, Revision in device extension. pChar = (PCHAR)pMPDrvInfoGlobal->MPRegInfo.VendorId.Buffer; len = min(8, (pMPDrvInfoGlobal->MPRegInfo.VendorId.Length/2)); for ( i = 0; i < len; i++, pChar+=2) pHBAExt->VendorId[i] = *pChar; pChar = (PCHAR)pMPDrvInfoGlobal->MPRegInfo.ProductId.Buffer; len = min(16, (pMPDrvInfoGlobal->MPRegInfo.ProductId.Length/2)); for ( i = 0; i < len; i++, pChar+=2) pHBAExt->ProductId[i] = *pChar; pChar = (PCHAR)pMPDrvInfoGlobal->MPRegInfo.ProductRevision.Buffer; len = min(4, (pMPDrvInfoGlobal->MPRegInfo.ProductRevision.Length/2)); for ( i = 0; i < len; i++, pChar+=2) pHBAExt->ProductRevision[i] = *pChar; // Add HBA extension to master driver object's linked list. #if defined(_AMD64_) KeAcquireInStackQueuedSpinLock(&pMPDrvInfoGlobal->DrvInfoLock, &LockHandle); #else KeAcquireSpinLock(&pMPDrvInfoGlobal->DrvInfoLock, &SaveIrql); #endif InsertTailList(&pMPDrvInfoGlobal->ListMPHBAObj, &pHBAExt->List); pMPDrvInfoGlobal->DrvInfoNbrMPHBAObj++; #if defined(_AMD64_) KeReleaseInStackQueuedSpinLock(&LockHandle); #else KeReleaseSpinLock(&pMPDrvInfoGlobal->DrvInfoLock, SaveIrql); #endif if (!pMPDrvInfoGlobal->GlobalsInitialized) { HANDLE thread_handle; OBJECT_ATTRIBUTES object_attributes; KeInitializeSpinLock(&pMPDrvInfoGlobal->RequestListLock); InitializeListHead(&pMPDrvInfoGlobal->RequestList); KeInitializeEvent(&pMPDrvInfoGlobal->RequestEvent, SynchronizationEvent, FALSE); #ifdef USE_SCSIPORT KeInitializeSpinLock(&pMPDrvInfoGlobal->ResponseListLock); KeInitializeEvent(&pMPDrvInfoGlobal->ResponseEvent, SynchronizationEvent, FALSE); InitializeListHead(&pMPDrvInfoGlobal->ResponseList); #endif KeInitializeEvent(&pMPDrvInfoGlobal->StopWorker, NotificationEvent, FALSE); pMPDrvInfoGlobal->GlobalsInitialized = TRUE; InitializeObjectAttributes(&object_attributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); ntstatus = PsCreateSystemThread( &thread_handle, (ACCESS_MASK) 0L, &object_attributes, NULL, NULL, ImScsiWorkerThread, NULL); if (!NT_SUCCESS(ntstatus)) { DbgPrint("PhDskMnt::ScsiGetLUExtension: Cannot create worker thread. (%#x)\n", ntstatus); status = SP_RETURN_ERROR; } else { ObReferenceObjectByHandle( thread_handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, *PsThreadType, KernelMode, (PVOID*)&pMPDrvInfoGlobal->WorkerThread, NULL ); ZwClose(thread_handle); //for (i = 0; i < pHBAExt->NbrLUNsperHBA; i++) // ImScsiCreateLU(pHBAExt, 0, (UCHAR)i, 0); } } //Done: *pBAgain = FALSE; KdPrint2(("PhDskMnt::MpHwFindAdapter: End, status = 0x%X\n", status)); return status; } // End MpHwFindAdapter().
// // Query information on LanscsiBus // NTSTATUS LSBus_QueryInformation( PFDO_DEVICE_DATA FdoData, BOOLEAN Request32, PNDASBUS_QUERY_INFORMATION Query, PNDASBUS_INFORMATION Information, LONG OutBufferLength, PLONG OutBufferLenNeeded ) { NTSTATUS ntStatus; PLIST_ENTRY entry; PPDO_DEVICE_DATA PdoData; ntStatus = STATUS_SUCCESS; *OutBufferLenNeeded = OutBufferLength; PdoData = NULL; // // Acquire the mutex to prevent PdoData ( Device Extension ) to disappear. // KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); switch(Query->InfoClass) { case INFORMATION_NUMOFPDOS: { ULONG NumOfPDOs; NumOfPDOs = 0; for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { NumOfPDOs ++; } Information->NumberOfPDOs = NumOfPDOs; break; } case INFORMATION_PDO: { KIRQL oldIrql; for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); if(Query->SlotNo == PdoData->SlotNo) { ObReferenceObject(PdoData->Self); break; } PdoData = NULL; } if(PdoData) { KeAcquireSpinLock(&PdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql); if((Query->Flags & NDASBUS_QUERYFLAG_EVENTQUEUE) == 0) { // // Return legacy status value. // Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("LastAdapterStatus:PDO:%p Status:%08lx DevMod:%08lx SupFeat:%08lx EnFeat:%08lx\n", PdoData->Self, PdoData->LanscsiAdapterPDO.LastAdapterStatus, PdoData->LanscsiAdapterPDO.DeviceMode, PdoData->LanscsiAdapterPDO.SupportedFeatures, PdoData->LanscsiAdapterPDO.EnabledFeatures )); Information->PdoInfo.AdapterStatus = PdoData->LanscsiAdapterPDO.LastAdapterStatus; Information->PdoInfo.DeviceMode = PdoData->LanscsiAdapterPDO.DeviceMode; Information->PdoInfo.SupportedFeatures = PdoData->LanscsiAdapterPDO.SupportedFeatures; Information->PdoInfo.EnabledFeatures = PdoData->LanscsiAdapterPDO.EnabledFeatures; } else { // // Return status from the event queue. // ULONG adapterStatus; PNDASBUS_PDOEVENT_ENTRY ndasPdoStatus; ndasPdoStatus = NdasBusDequeuePdoStatusItem(&PdoData->LanscsiAdapterPDO); if(ndasPdoStatus) { BOOLEAN empty; adapterStatus = ndasPdoStatus->AdapterStatus; empty = NdasBusIsEmpty(&PdoData->LanscsiAdapterPDO); if(!empty) { adapterStatus |= NDASSCSI_ADAPTERINFO_STATUSFLAG_NEXT_EVENT_EXIST; } // // Free the entry // NdasBusDestroyPdoStatusItem(ndasPdoStatus); } else { KeReleaseSpinLock(&PdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); // // No more entry // Bus_KdPrint_Def(BUS_DBG_SS_NOISE, ("No more status item for SlotNo %d!\n", Query->SlotNo)); ntStatus = STATUS_NO_MORE_ENTRIES; break; } Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("QueuedAdapterStatus:PDO:%p Status:%08lx DevMod:%08lx SupFeat:%08lx EnFeat:%08lx\n", PdoData->Self, adapterStatus, PdoData->LanscsiAdapterPDO.DeviceMode, PdoData->LanscsiAdapterPDO.SupportedFeatures, PdoData->LanscsiAdapterPDO.EnabledFeatures )); Information->PdoInfo.AdapterStatus = adapterStatus; Information->PdoInfo.DeviceMode = PdoData->LanscsiAdapterPDO.DeviceMode; Information->PdoInfo.SupportedFeatures = PdoData->LanscsiAdapterPDO.SupportedFeatures; Information->PdoInfo.EnabledFeatures = PdoData->LanscsiAdapterPDO.EnabledFeatures; } KeReleaseSpinLock(&PdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); ObDereferenceObject(PdoData->Self); } else { Bus_KdPrint_Def(BUS_DBG_SS_NOISE, ("No PDO for SlotNo %d!\n", Query->SlotNo)); ntStatus = STATUS_NO_SUCH_DEVICE; } break; } case INFORMATION_PDOENUM: { LARGE_INTEGER TimeOut; ULONG resultLength; DEVICE_INSTALL_STATE deviceInstallState; for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); if(Query->SlotNo == PdoData->SlotNo) { ObReferenceObject(PdoData->Self); break; } PdoData = NULL; } ExReleaseFastMutex (&FdoData->Mutex); KeLeaveCriticalRegion(); if(!PdoData) { KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); ntStatus = STATUS_NO_SUCH_DEVICE; break; } // // Wait until NDAS service sends AddTargetData. // Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("waiting for AddTargetEvent.\n")); TimeOut.QuadPart = -10 * 1000 * 1000 * 120; // 120 seconds ntStatus = KeWaitForSingleObject( &PdoData->LanscsiAdapterPDO.AddTargetEvent, Executive, KernelMode, FALSE, &TimeOut ); if(ntStatus != STATUS_SUCCESS) { KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("failed to wait for AddTargetEvent.\n")); ntStatus = STATUS_NO_SUCH_DEVICE; ObDereferenceObject(PdoData->Self); break; } Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Completed to wait for AddTargetEvent.\n")); if(PdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) { // // A LUR descriptor is set. // if(PdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); ntStatus = STATUS_NO_SUCH_DEVICE; ObDereferenceObject(PdoData->Self); break; } *OutBufferLenNeeded = FIELD_OFFSET(NDASBUS_INFORMATION, PdoEnumInfo) + FIELD_OFFSET(NDASBUS_INFORMATION_PDOENUM, AddDevInfo) + PdoData->LanscsiAdapterPDO.AddDevInfoLength; if(OutBufferLength < *OutBufferLenNeeded) { ntStatus = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory( Information->PdoEnumInfo.AddDevInfo, PdoData->LanscsiAdapterPDO.AddDevInfo, PdoData->LanscsiAdapterPDO.AddDevInfoLength ); Information->PdoEnumInfo.Flags = PDOENUM_FLAG_LURDESC; Information->PdoEnumInfo.MaxRequestLength = PdoData->LanscsiAdapterPDO.MaxRequestLength; // // Check to see if this is the first enumeration. // ntStatus = DrGetDeviceProperty( PdoData->Self, DevicePropertyInstallState, sizeof(deviceInstallState), &deviceInstallState, &resultLength, (Globals.MajorVersion == 5) && (Globals.MinorVersion == 0) ); if(NT_SUCCESS(ntStatus)) { if(deviceInstallState != InstallStateInstalled) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("First time installation. Do not enumerate a device.\n")); Information->PdoEnumInfo.Flags |= PDOENUM_FLAG_DRV_NOT_INSTALLED; } } else { // // Even if DrGetDeviceProperty() fails, // we can mount the device successfully. // ntStatus = STATUS_SUCCESS; } } } else { // // ADD_TARGET_DATA is set. // PNDASBUS_ADD_TARGET_DATA AddTargetData; LONG InfoBuffLenNeeded; AddTargetData = PdoData->LanscsiAdapterPDO.AddDevInfo; if(AddTargetData == NULL) { KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); ntStatus = STATUS_NO_SUCH_DEVICE; ObDereferenceObject(PdoData->Self); break; } // // calculate the length needed. // InfoBuffLenNeeded = FIELD_OFFSET(NDASBUS_INFORMATION, PdoEnumInfo) + FIELD_OFFSET(NDASBUS_INFORMATION_PDOENUM, AddDevInfo) + PdoData->LanscsiAdapterPDO.AddDevInfoLength; *OutBufferLenNeeded = InfoBuffLenNeeded; if(OutBufferLength < InfoBuffLenNeeded) { ntStatus = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory( Information->PdoEnumInfo.AddDevInfo, AddTargetData, PdoData->LanscsiAdapterPDO.AddDevInfoLength); Information->PdoEnumInfo.Flags = 0; Information->PdoEnumInfo.MaxRequestLength = PdoData->LanscsiAdapterPDO.MaxRequestLength; // // Check to see if this is the first enumeration. // ntStatus = DrGetDeviceProperty( PdoData->Self, DevicePropertyInstallState, sizeof(deviceInstallState), &deviceInstallState, &resultLength, (Globals.MajorVersion == 5) && (Globals.MinorVersion == 0) ); if(NT_SUCCESS(ntStatus)) { if(deviceInstallState != InstallStateInstalled) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("First time installation. Do not enumerate a device.\n")); Information->PdoEnumInfo.Flags |= PDOENUM_FLAG_DRV_NOT_INSTALLED; } } else { // // Even if DrGetDeviceProperty() fails, // we can mount the device successfully. // ntStatus = STATUS_SUCCESS; Information->PdoEnumInfo.Flags &= ~PDOENUM_FLAG_DRV_NOT_INSTALLED; } } } KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); ObDereferenceObject(PdoData->Self); break; } case INFORMATION_PDOEVENT: { for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); if(Query->SlotNo == PdoData->SlotNo) { ObReferenceObject(PdoData->Self); break; } PdoData = NULL; } if(PdoData == NULL) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not find the PDO:%u.\n", Query->SlotNo)); ntStatus = STATUS_NO_SUCH_DEVICE; break; } if( Query->Flags & NDASBUS_QUERYFLAG_USERHANDLE) { if(Request32 == FALSE) { Information->PdoEvents.SlotNo = PdoData->SlotNo; Information->PdoEvents.Flags = NDASBUS_QUERYFLAG_USERHANDLE; // // Get user-mode event handles. // ntStatus = ObOpenObjectByPointer( PdoData->LanscsiAdapterPDO.DisconEventToService, 0, NULL, EVENT_ALL_ACCESS, *ExEventObjectType, UserMode, &Information->PdoEvents.DisconEvent ); if(!NT_SUCCESS(ntStatus)) { ObDereferenceObject(PdoData->Self); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n")); break; } ntStatus = ObOpenObjectByPointer( PdoData->LanscsiAdapterPDO.AlarmEventToService, 0, NULL, EVENT_ALL_ACCESS, *ExEventObjectType, UserMode, &Information->PdoEvents.AlarmEvent ); if(!NT_SUCCESS(ntStatus)) { ObDereferenceObject(PdoData->Self); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n")); break; } } else { HANDLE disconEvent, alarmEvent; // // Need 32-bit thunk // Information->PdoEvents32.SlotNo = PdoData->SlotNo; Information->PdoEvents32.Flags = NDASBUS_QUERYFLAG_USERHANDLE; // // Get user-mode event handles. // ntStatus = ObOpenObjectByPointer( PdoData->LanscsiAdapterPDO.DisconEventToService, 0, NULL, EVENT_ALL_ACCESS, *ExEventObjectType, UserMode, &disconEvent ); if(!NT_SUCCESS(ntStatus)) { ObDereferenceObject(PdoData->Self); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n")); break; } ntStatus = ObOpenObjectByPointer( PdoData->LanscsiAdapterPDO.AlarmEventToService, 0, NULL, EVENT_ALL_ACCESS, *ExEventObjectType, UserMode, &alarmEvent ); if(!NT_SUCCESS(ntStatus)) { ObDereferenceObject(PdoData->Self); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n")); break; } // // Thunk event handles to 32 bit // ntStatus = RtlULongPtrToULong((ULONG_PTR)disconEvent, (PULONG)&Information->PdoEvents32.DisconEvent); if(!NT_SUCCESS(ntStatus)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOEVENTS: error conversion. Handle=%p\n", disconEvent)); ObDereferenceObject(PdoData->Self); break; } ntStatus = RtlULongPtrToULong((ULONG_PTR)alarmEvent, (PULONG)&Information->PdoEvents32.AlarmEvent); if(!NT_SUCCESS(ntStatus)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOEVENTS: error conversion. Handle=%p\n", alarmEvent)); ObDereferenceObject(PdoData->Self); break; } } } else { if(Request32) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOEVENTS: 32-bit thunking not supported.\n")); ObDereferenceObject(PdoData->Self); ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } Information->PdoEvents.SlotNo = PdoData->SlotNo; Information->PdoEvents.Flags = 0; Information->PdoEvents.DisconEvent = PdoData->LanscsiAdapterPDO.DisconEventToService; Information->PdoEvents.AlarmEvent = PdoData->LanscsiAdapterPDO.AlarmEventToService; } ObDereferenceObject(PdoData->Self); break; } case INFORMATION_ISREGISTERED: { ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); ntStatus = LSBus_IsRegistered(FdoData, Query->SlotNo); break; } case INFORMATION_PDOSLOTLIST: { LONG outputLength; LONG entryCnt; if(OutBufferLength < FIELD_OFFSET(NDASBUS_INFORMATION, PdoSlotList)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Buffer size is less than required\n")); ntStatus = STATUS_INVALID_PARAMETER; break; } Information->Size = 0; Information->InfoClass = INFORMATION_PDOSLOTLIST; // // Add the size of information header. // outputLength = FIELD_OFFSET(NDASBUS_INFORMATION, PdoSlotList); outputLength += sizeof(UINT32); // SlotNoCnt entryCnt = 0; for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); // // Add the size of each slot entry. // outputLength += sizeof(UINT32); if(outputLength > OutBufferLength) { continue; } Information->PdoSlotList.SlotNo[entryCnt] = PdoData->SlotNo; Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Entry #%u: %u\n", entryCnt, PdoData->SlotNo)); entryCnt ++; } if(outputLength > OutBufferLength) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Could not find a Device(%d).\n", Query->SlotNo)); *OutBufferLenNeeded = outputLength; ntStatus = STATUS_BUFFER_TOO_SMALL; } else { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Entry count:%d.\n", entryCnt)); Information->Size = outputLength; Information->PdoSlotList.SlotNoCnt = entryCnt; *OutBufferLenNeeded = outputLength; } break; } case INFORMATION_PDOFILEHANDLE: { PWCHAR devName; USHORT devNameLen; OBJECT_ATTRIBUTES objectAttr; UNICODE_STRING objName; HANDLE devFileHandle; IO_STATUS_BLOCK ioStatus; devName = NULL; for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); if(Query->SlotNo == PdoData->SlotNo) { ObReferenceObject(PdoData->Self); break; } PdoData = NULL; } if(PdoData == NULL) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not find the PDO:%u.\n", Query->SlotNo)); ntStatus = STATUS_NO_SUCH_DEVICE; break; } // // Get the name of the physical device object. // ntStatus = GetPhyDeviceName(PdoData->Self, &devName, &devNameLen); if(!NT_SUCCESS(ntStatus)) { ObDereferenceObject(PdoData->Self); break; } // // Build unicode name of the device. // Get rid of NULL termination from the length // objName.Buffer = devName; if(devNameLen > 0 && devName[devNameLen/sizeof(WCHAR) - 1] == L'\0') { objName.MaximumLength = devNameLen; objName.Length = devNameLen - sizeof(WCHAR); } else { objName.MaximumLength = objName.Length = devNameLen; } // // Open a device file. // if(Query->Flags & NDASBUS_QUERYFLAG_USERHANDLE) { if(Request32 == FALSE) Information->PdoFile.Flags = NDASBUS_QUERYFLAG_USERHANDLE; else Information->PdoFile32.Flags = NDASBUS_QUERYFLAG_USERHANDLE; InitializeObjectAttributes(&objectAttr, &objName, OBJ_CASE_INSENSITIVE , NULL, NULL); } else { if(Request32 == FALSE) Information->PdoFile.Flags = 0; else Information->PdoFile32.Flags = 0; InitializeObjectAttributes(&objectAttr, &objName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); } ntStatus = ZwCreateFile( &devFileHandle, SYNCHRONIZE|FILE_READ_DATA, &objectAttr, &ioStatus, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if(!NT_SUCCESS(ntStatus)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open the PDO:%u. STATUS=%08lx\n", Query->SlotNo, ntStatus)); ExFreePool(devName); ObDereferenceObject(PdoData->Self); break; } // // Set the return values // if(Request32 == FALSE) { Information->PdoFile.SlotNo = PdoData->SlotNo; Information->PdoFile.PdoFileHandle = devFileHandle; } else { // // Need 32 bit thunking // ntStatus = RtlULongPtrToULong((ULONG_PTR)devFileHandle, (PULONG)&Information->PdoFile32.PdoFileHandle); if(!NT_SUCCESS(ntStatus)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOEVENTS: error conversion. Handle=%p\n", devFileHandle)); ObDereferenceObject(PdoData->Self); break; } Information->PdoFile32.SlotNo = PdoData->SlotNo; } if(devName) ExFreePool(devName); ObDereferenceObject(PdoData->Self); break; } default: ntStatus = STATUS_INVALID_PARAMETER; } ExReleaseFastMutex (&FdoData->Mutex); KeLeaveCriticalRegion(); return ntStatus; }
int tdi_connect(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) { PTDI_REQUEST_KERNEL_CONNECT param = (PTDI_REQUEST_KERNEL_CONNECT)(&irps->Parameters); TA_ADDRESS *remote_addr = ((TRANSPORT_ADDRESS *)(param->RequestConnectionInformation->RemoteAddress))->Address; PFILE_OBJECT addrobj; NTSTATUS status; TA_ADDRESS *local_addr; int result = FILTER_DENY, ipproto; struct ot_entry *ote_conn = NULL, *ote_addr; KIRQL irql; struct flt_request request; struct flt_rule rule; memset(&request, 0, sizeof(request)); KdPrint(("[tdi_fw] tdi_connect: connobj 0x%x, to address %x:%u\n", irps->FileObject, ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port))); // check device object: TCP or UDP if (irps->DeviceObject != g_tcpfltobj && irps->DeviceObject != g_udpfltobj) { KdPrint(("[tdi_fw] tdi_connect: unknown DeviceObject 0x%x!\n", irps->DeviceObject)); goto done; } ote_conn = ot_find_fileobj(irps->FileObject, &irql); if (ote_conn == NULL) { KdPrint(("[tdi_fw] tdi_connect: ot_find_fileobj(0x%x)!\n", irps->FileObject)); goto done; } if (get_original_devobj(irps->DeviceObject, &ipproto) == NULL || (ipproto != IPPROTO_TCP && ipproto != IPPROTO_UDP)) { // invalid device object! KdPrint(("[tdi_fw] tdi_connect: invalid device object 0x%x!\n", irps->DeviceObject)); goto done; } if (ipproto == IPPROTO_TCP) { /* * For TCP: get addrobj by connobj and get local address by it */ addrobj = ote_conn->associated_fileobj; if (addrobj == NULL) { KdPrint(("[tdi_fw] tdi_connect: empty addrobj!\n")); goto done; } ote_addr = ot_find_fileobj(addrobj, NULL); // we're already in spinlock if (ote_addr == NULL) { KdPrint(("[tdi_fw] tdi_connect: ot_find_fileobj(0x%x)!\n", addrobj)); goto done; } } else { /* * For UDP: connobj and addrobj are the same */ KdPrint(("[tdi_fw] tdi_connect: connected UDP socket detected\n")); // for connected UDP sockets connobj and addrobj are the same addrobj= irps->FileObject; ote_addr = ote_conn; } local_addr = (TA_ADDRESS *)(ote_addr->local_addr); // sanity check if (local_addr->AddressLength != remote_addr->AddressLength) { KdPrint(("[tdi_fw] tdi_connect: different addr lengths! (%u != %u)\n", local_addr->AddressLength, remote_addr->AddressLength)); goto done; } // set remote address with connobj if (remote_addr->AddressLength > sizeof(ote_conn->remote_addr)) { KdPrint(("[tdi_fw] tdi_connect: address too long! (%u)\n", remote_addr->AddressLength)); goto done; } memcpy(ote_conn->remote_addr, remote_addr, remote_addr->AddressLength); // set local address with connobj if (local_addr->AddressLength > sizeof(ote_conn->local_addr)) { KdPrint(("[tdi_fw] tdi_connect: address to long! (%u)\n", local_addr->AddressLength)); goto done; } memcpy(ote_conn->local_addr, local_addr, local_addr->AddressLength); KdPrint(("[tdi_fw] tdi_connect(pid:%u/%u): %x:%u -> %x:%u (ipproto = %d)\n", ote_conn->pid, PsGetCurrentProcessId(), ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr), ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port), ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port), ipproto)); /* * Call quick_filter */ request.struct_size = sizeof(request); request.type = TYPE_CONNECT; request.direction = DIRECTION_OUT; request.proto = ipproto; // don't use ote_conn->pid because one process can create connection object // but another one can connect request.pid = (ULONG)PsGetCurrentProcessId(); if (request.pid == 0) { // avoid idle process pid (XXX do we need this?) request.pid = ote_addr->pid; } // get user SID & attributes (can't call get_current_sid_a at DISPATCH_LEVEL) if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL) request.sid_a_size = ote_addr->sid_a_size; memcpy(&request.addr.from, &local_addr->AddressType, sizeof(struct sockaddr)); memcpy(&request.addr.to, &remote_addr->AddressType, sizeof(struct sockaddr)); request.addr.len = sizeof(struct sockaddr_in); memset(&rule, 0, sizeof(rule)); result = quick_filter(&request, &rule); memcpy(request.log_rule_id, rule.rule_id, RULE_ID_SIZE); if (result == FILTER_ALLOW && ipproto == IPPROTO_TCP) { struct flt_request *context_req = NULL; // add connection with state "SYN_SENT" status = add_tcp_conn(ote_conn, TCP_STATE_SYN_SENT); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] tdi_connect: add_conn: 0x%x!\n", status)); result = FILTER_DENY; goto done; // don't log this failure } if (rule.log >= RULE_LOG_LOG) { // set ote_conn->log_disconnect ote_conn->log_disconnect = (rule.log >= RULE_LOG_COUNT); // copy request for completion (LOG success or not) context_req = (struct flt_request *)malloc_np(sizeof(*context_req)); if (context_req != NULL) { memcpy(context_req, &request, sizeof(*context_req)); // don't free SID request.sid_a = NULL; // don't log request in this time rule.log = RULE_LOG_NOLOG; } } // set completion to add connection info to connection table completion->routine = tdi_connect_complete; completion->context = context_req; } // if logging is needed log request if (rule.log >= RULE_LOG_LOG) log_request(&request); done: // cleanup if (ote_conn != NULL) KeReleaseSpinLock(&g_ot_hash_guard, irql); if (request.sid_a != NULL) free(request.sid_a); if (result != FILTER_ALLOW) { irp->IoStatus.Status = STATUS_REMOTE_NOT_LISTENING; // set fake status } return result; }
static void usbd_ctrl_callback(struct usb_xfer *xfer, usb_error_t error) { irp *ip; struct ndis_softc *sc = usbd_xfer_softc(xfer); struct ndisusb_ep *ne = usbd_xfer_get_priv(xfer); struct ndisusb_xfer *nx; uint8_t irql; union usbd_urb *urb; struct usbd_urb_vendor_or_class_request *vcreq; struct usb_page_cache *pc; uint8_t type = 0; struct usb_device_request req; int len; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: nx = usbd_aq_getfirst(sc, ne); if (nx == NULL) return; ip = nx->nx_priv; urb = usbd_geturb(ip); vcreq = &urb->uu_vcreq; if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) { pc = usbd_xfer_get_frame(xfer, 1); len = usbd_xfer_frame_len(xfer, 1); usbd_copy_out(pc, 0, vcreq->uvc_trans_buf, len); nx->nx_urbactlen += len; } usbd_xfer_complete(sc, ne, nx, USB_ERR_NORMAL_COMPLETION); /* fall through */ case USB_ST_SETUP: next: /* get next transfer */ KeAcquireSpinLock(&ne->ne_lock, &irql); if (IsListEmpty(&ne->ne_pending)) { KeReleaseSpinLock(&ne->ne_lock, irql); return; } nx = CONTAINING_RECORD(ne->ne_pending.nle_flink, struct ndisusb_xfer, nx_next); RemoveEntryList(&nx->nx_next); /* add a entry to the active queue's tail. */ InsertTailList((&ne->ne_active), (&nx->nx_next)); KeReleaseSpinLock(&ne->ne_lock, irql); ip = nx->nx_priv; urb = usbd_geturb(ip); vcreq = &urb->uu_vcreq; switch (urb->uu_hdr.uuh_func) { case URB_FUNCTION_CLASS_DEVICE: type = UT_CLASS | UT_DEVICE; break; case URB_FUNCTION_CLASS_INTERFACE: type = UT_CLASS | UT_INTERFACE; break; case URB_FUNCTION_CLASS_OTHER: type = UT_CLASS | UT_OTHER; break; case URB_FUNCTION_CLASS_ENDPOINT: type = UT_CLASS | UT_ENDPOINT; break; case URB_FUNCTION_VENDOR_DEVICE: type = UT_VENDOR | UT_DEVICE; break; case URB_FUNCTION_VENDOR_INTERFACE: type = UT_VENDOR | UT_INTERFACE; break; case URB_FUNCTION_VENDOR_OTHER: type = UT_VENDOR | UT_OTHER; break; case URB_FUNCTION_VENDOR_ENDPOINT: type = UT_VENDOR | UT_ENDPOINT; break; default: /* never reached. */ break; } type |= (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ? UT_READ : UT_WRITE; type |= vcreq->uvc_reserved1; req.bmRequestType = type; req.bRequest = vcreq->uvc_req; USETW(req.wIndex, vcreq->uvc_idx); USETW(req.wValue, vcreq->uvc_value); USETW(req.wLength, vcreq->uvc_trans_buflen); nx->nx_urbbuf = vcreq->uvc_trans_buf; nx->nx_urblen = vcreq->uvc_trans_buflen; nx->nx_urbactlen = 0; pc = usbd_xfer_get_frame(xfer, 0); usbd_copy_in(pc, 0, &req, sizeof(req)); usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); usbd_xfer_set_frames(xfer, 1); if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) { if (vcreq->uvc_trans_buflen >= USBD_CTRL_READ_BUFFER_SP) device_printf(sc->ndis_dev, "warning: not enough buffer space (%d).\n", vcreq->uvc_trans_buflen); usbd_xfer_set_frame_len(xfer, 1, MIN(usbd_xfer_max_len(xfer), vcreq->uvc_trans_buflen)); usbd_xfer_set_frames(xfer, 2); } else { if (nx->nx_urblen > USBD_CTRL_WRITE_BUFFER_SP) device_printf(sc->ndis_dev, "warning: not enough write buffer space" " (%d).\n", nx->nx_urblen); /* * XXX with my local tests there was no cases to require * a extra buffer until now but it'd need to update in * the future if it needs to be. */ if (nx->nx_urblen > 0) { pc = usbd_xfer_get_frame(xfer, 1); usbd_copy_in(pc, 0, nx->nx_urbbuf, nx->nx_urblen); usbd_xfer_set_frame_len(xfer, 1, nx->nx_urblen); usbd_xfer_set_frames(xfer, 2); } } usbd_transfer_submit(xfer); break; default: nx = usbd_aq_getfirst(sc, ne); if (nx == NULL) return; if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); device_printf(sc->ndis_dev, "usb xfer warning (%s)\n", usbd_errstr(error)); } usbd_xfer_complete(sc, ne, nx, error); if (error != USB_ERR_CANCELLED) goto next; break; } }
static void usbd_non_isoc_callback(struct usb_xfer *xfer, usb_error_t error) { irp *ip; struct ndis_softc *sc = usbd_xfer_softc(xfer); struct ndisusb_ep *ne = usbd_xfer_get_priv(xfer); struct ndisusb_xfer *nx; struct usbd_urb_bulk_or_intr_transfer *ubi; struct usb_page_cache *pc; uint8_t irql; uint32_t len; union usbd_urb *urb; usb_endpoint_descriptor_t *ep; int actlen, sumlen; usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: nx = usbd_aq_getfirst(sc, ne); pc = usbd_xfer_get_frame(xfer, 0); if (nx == NULL) return; /* copy in data with regard to the URB */ if (ne->ne_dirin != 0) usbd_copy_out(pc, 0, nx->nx_urbbuf, actlen); nx->nx_urbbuf += actlen; nx->nx_urbactlen += actlen; nx->nx_urblen -= actlen; /* check for short transfer */ if (actlen < sumlen) nx->nx_urblen = 0; else { /* check remainder */ if (nx->nx_urblen > 0) { KeAcquireSpinLock(&ne->ne_lock, &irql); InsertHeadList((&ne->ne_active), (&nx->nx_next)); KeReleaseSpinLock(&ne->ne_lock, irql); ip = nx->nx_priv; urb = usbd_geturb(ip); ubi = &urb->uu_bulkintr; ep = ubi->ubi_epdesc; goto extra; } } usbd_xfer_complete(sc, ne, nx, ((actlen < sumlen) && (nx->nx_shortxfer == 0)) ? USB_ERR_SHORT_XFER : USB_ERR_NORMAL_COMPLETION); /* fall through */ case USB_ST_SETUP: next: /* get next transfer */ KeAcquireSpinLock(&ne->ne_lock, &irql); if (IsListEmpty(&ne->ne_pending)) { KeReleaseSpinLock(&ne->ne_lock, irql); return; } nx = CONTAINING_RECORD(ne->ne_pending.nle_flink, struct ndisusb_xfer, nx_next); RemoveEntryList(&nx->nx_next); /* add a entry to the active queue's tail. */ InsertTailList((&ne->ne_active), (&nx->nx_next)); KeReleaseSpinLock(&ne->ne_lock, irql); ip = nx->nx_priv; urb = usbd_geturb(ip); ubi = &urb->uu_bulkintr; ep = ubi->ubi_epdesc; nx->nx_urbbuf = ubi->ubi_trans_buf; nx->nx_urbactlen = 0; nx->nx_urblen = ubi->ubi_trans_buflen; nx->nx_shortxfer = (ubi->ubi_trans_flags & USBD_SHORT_TRANSFER_OK) ? 1 : 0; extra: len = MIN(usbd_xfer_max_len(xfer), nx->nx_urblen); pc = usbd_xfer_get_frame(xfer, 0); if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_OUT) usbd_copy_in(pc, 0, nx->nx_urbbuf, len); usbd_xfer_set_frame_len(xfer, 0, len); usbd_xfer_set_frames(xfer, 1); usbd_transfer_submit(xfer); break; default: nx = usbd_aq_getfirst(sc, ne); if (nx == NULL) return; if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); device_printf(sc->ndis_dev, "usb xfer warning (%s)\n", usbd_errstr(error)); } usbd_xfer_complete(sc, ne, nx, error); if (error != USB_ERR_CANCELLED) goto next; break; } }
BOOLEAN Primary_PassThrough( IN PLFS_DEVICE_EXTENSION LfsDeviceExt, IN PIRP Irp, OUT PNTSTATUS NtStatus ) { PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT fileObject; KIRQL oldIrql; // Do not allow exclusive access to the volume when connected to secondaries. if(irpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL && (irpSp->MinorFunction == IRP_MN_USER_FS_REQUEST || irpSp->MinorFunction == IRP_MN_KERNEL_CALL)) { struct FileSystemControl *fileSystemControl =(struct FileSystemControl *)&(irpSp->Parameters.FileSystemControl); fileObject = irpSp->FileObject; // // Do not allow exclusive access to the volume and dismount volume to protect format // We allow exclusive access if secondaries are connected locally. // if( (fileSystemControl->FsControlCode == FSCTL_LOCK_VOLUME // 6 || fileSystemControl->FsControlCode == FSCTL_DISMOUNT_VOLUME) // 8 && NetdiskManager_ThisVolumeHasSecondary(GlobalLfs.NetdiskManager, LfsDeviceExt->EnabledNetdisk, LfsDeviceExt, FALSE) ) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("Primary_PassThrough, IRP_MJ_FILE_SYSTEM_CONTROL: Trying to acquire the volume exclusively. \n")); ASSERT(fileObject && fileObject->FileName.Length == 0 && fileObject->RelatedFileObject == NULL); *NtStatus = Irp->IoStatus.Status = STATUS_ACCESS_DENIED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_DISK_INCREMENT); return TRUE; // // Do not support encryption. // } else if(fileSystemControl->FsControlCode == FSCTL_SET_ENCRYPTION) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("Primary_PassThrough, IRP_MJ_FILE_SYSTEM_CONTROL: Setting encryption denied.\n")); *NtStatus = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_DISK_INCREMENT); return TRUE; } } // Need to test much whether this is okay.. if (irpSp->MajorFunction == IRP_MJ_PNP && (irpSp->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE || irpSp->MinorFunction == IRP_MN_REMOVE_DEVICE)) { PNETDISK_PARTITION Partition; Partition = LookUpNetdiskPartition(LfsDeviceExt->EnabledNetdisk, NULL, 0, LfsDeviceExt, NULL); if (Partition) { SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR, ("%s: Releasing Unplugging lock\n", (irpSp->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE)?"CANCEL_REMOVE_DEVICE":"REMOVE_DEVICE")); InterlockedDecrement(&LfsDeviceExt->EnabledNetdisk->UnplugInProgressCount); NetdiskPartition_Dereference(Partition); // by LookUpNetdiskPartition } else { ASSERT(0); SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR, ("%s: Failed to find matching parition. Release unplugging lock anyway\n", (irpSp->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE)?"CANCEL_REMOVE_DEVICE":"REMOVE_DEVICE")); InterlockedDecrement(&LfsDeviceExt->EnabledNetdisk->UnplugInProgressCount); } } // // Close files opened by secondary if unmount of primary host is requested . // This helps primary can unmount while secondary has mounted. // if (irpSp->MajorFunction == IRP_MJ_PNP && irpSp->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE) { int i; PLIST_ENTRY primarySessionListEntry; PLIST_ENTRY PrimarySessionList; POPEN_FILE openFile; PLIST_ENTRY OpenFileListEntry; NTSTATUS closeStatus; #if DBG int j; CHAR NameBuf[512] = {0}; #endif PPRIMARY_SESSION primarySession; PNETDISK_PARTITION Partition; Partition = LookUpNetdiskPartition(LfsDeviceExt->EnabledNetdisk, NULL, 0, LfsDeviceExt, NULL); if (Partition) { SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR, ("QUERY_REMOVE: Locking disks for removal\n")); InterlockedIncrement(&LfsDeviceExt->EnabledNetdisk->UnplugInProgressCount); // wait until DispatchInProgressCount becomes zero KeAcquireSpinLock(&LfsDeviceExt->EnabledNetdisk->SpinLock, &oldIrql); while(LfsDeviceExt->EnabledNetdisk->DispatchInProgressCount>0) { LARGE_INTEGER Timeout; SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR, ("QUERY_REMOVE: %d IO is in progress by secondary\n", LfsDeviceExt->EnabledNetdisk->DispatchInProgressCount)); Timeout.QuadPart = - HZ/10; // 100ms KeReleaseSpinLock(&LfsDeviceExt->EnabledNetdisk->SpinLock, oldIrql); KeDelayExecutionThread(KernelMode, FALSE, &Timeout); KeAcquireSpinLock(&LfsDeviceExt->EnabledNetdisk->SpinLock, &oldIrql); } KeReleaseSpinLock(&LfsDeviceExt->EnabledNetdisk->SpinLock, oldIrql); NetdiskPartition_Dereference(Partition); // by LookUpNetdiskPartition } else { SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR, ("QUERY_REMOVE: Failed to find matching parition\n")); } for(i=0;i<MAX_SOCKETLPX_INTERFACE;i++) { PrimarySessionList = &GlobalLfs.Primary->PrimarySessionQueue[i]; for (primarySessionListEntry = PrimarySessionList->Flink; primarySessionListEntry != PrimarySessionList; primarySessionListEntry = primarySessionListEntry->Flink) { primarySession = CONTAINING_RECORD (primarySessionListEntry, PRIMARY_SESSION, ListEntry); if (primarySession->NetdiskPartition == NULL || primarySession->NetdiskPartition->EnabledNetdisk == NULL) { SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ("Primary is closed: Session=%p\n", primarySession )); continue; } // // Is there any way to check to get proper netdisk?? // if (primarySession->NetdiskPartition->EnabledNetdisk == LfsDeviceExt->EnabledNetdisk) { for (OpenFileListEntry = primarySession->OpenedFileQueue.Flink; OpenFileListEntry != &primarySession->OpenedFileQueue; OpenFileListEntry = OpenFileListEntry->Flink) { openFile = CONTAINING_RECORD (OpenFileListEntry, OPEN_FILE, ListEntry); // Close open files opened by secondary. if (openFile->AlreadyClosed == FALSE) { // Store file offset before close. if (openFile->CreateOptions &(FILE_SYNCHRONOUS_IO_ALERT |FILE_SYNCHRONOUS_IO_NONALERT)) { NTSTATUS QueryStatus; IO_STATUS_BLOCK IoStatus; FILE_POSITION_INFORMATION FileInfo; // File position is meaningful only in this open mode. QueryStatus = ZwQueryInformationFile( openFile->FileHandle, &IoStatus, (PVOID)&FileInfo, sizeof(FileInfo), FilePositionInformation ); if (NT_SUCCESS(QueryStatus)) { SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ("Closing secondary files: Stroring offset %x\n", FileInfo.CurrentByteOffset)); openFile->CurrentByteOffset = FileInfo.CurrentByteOffset; } else { SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR, ("Closing secondary files: Failed to get current file offset\n")); openFile->CurrentByteOffset.HighPart = 0; openFile->CurrentByteOffset.LowPart = 0; } } closeStatus = ZwClose(openFile->FileHandle); ObDereferenceObject(openFile->FileObject); ASSERT(openFile->EventHandle !=NULL); ZwClose(openFile->EventHandle); openFile->EventHandle = NULL; openFile->AlreadyClosed = TRUE; } #if DBG // Print of unicode is available only PASSIVE_LEVEL. // So print in ASCII assuming file name is always ascii range. for(j=0;openFile->FullFileNameBuffer[j]!=0 && j<sizeof(NameBuf)-1;j++) { NameBuf[j]= (CHAR)openFile->FullFileNameBuffer[j]; } NameBuf[j] = 0; SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ("Closing secondary files: Session=%p, FileId=%x, FileName=%s\n", primarySession, openFile->OpenFileId, NameBuf )); #endif } } } } } return FALSE; }
NDIS_STATUS ProIndicatePacket( PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet) /* * FUNCTION: Indicates a packet to bound protocols * ARGUMENTS: * Adapter = Pointer to logical adapter * Packet = Pointer to packet to indicate * RETURNS: * STATUS_SUCCESS in all cases * NOTES: * - XXX ATM, this only handles loopback packets - is that its designed function? */ { UINT BufferedLength; UINT PacketLength; KIRQL OldIrql; PUCHAR LookaheadBuffer; NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); #if DBG MiniDisplayPacket(Packet); #endif NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength); LookaheadBuffer = ExAllocatePool(NonPagedPool, PacketLength); if (!LookaheadBuffer) { NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); return NDIS_STATUS_RESOURCES; } NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n")); KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); { BufferedLength = CopyPacketToBuffer(LookaheadBuffer, Packet, 0, PacketLength); Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = Packet; } KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); if (BufferedLength > Adapter->MediumHeaderSize) { /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */ MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize, &LookaheadBuffer[Adapter->MediumHeaderSize], BufferedLength - Adapter->MediumHeaderSize, PacketLength - Adapter->MediumHeaderSize); } else { MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize, NULL, 0, 0); } ExFreePool(LookaheadBuffer); KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); { Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = NULL; } KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); return NDIS_STATUS_SUCCESS; }
NTSTATUS NTAPI HandleDeviceSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { KIRQL oldIrql; NTSTATUS ntStatus; POWER_STATE newState; PIO_STACK_LOCATION irpStack; PDEVICE_EXTENSION deviceExtension; DEVICE_POWER_STATE newDevState, oldDevState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Entered\n")); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); oldDevState = deviceExtension->DevPower; newState = irpStack->Parameters.Power.State; newDevState = newState.DeviceState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Set request for device power state D%X\n" "FBTUSB: HandleDeviceSetPower: Current device power state D%X\n", newDevState - 1, deviceExtension->DevPower - 1)); if (newDevState < oldDevState) { FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Adding power to the device\n")); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)FinishDevPoUpIrp, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } else { // newDevState >= oldDevState // hold I/O if transition from D0 -> DX (X = 1, 2, 3) // if transition from D1 or D2 to deeper sleep states, // I/O queue is already on hold. if(PowerDeviceD0 == oldDevState && newDevState > oldDevState) { // D0 -> DX transition FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Removing power from the device\n")); ntStatus = HoldIoRequests(DeviceObject, Irp); if (!NT_SUCCESS(ntStatus)) { PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower::")); FreeBT_IoDecrement(deviceExtension); return ntStatus; } else { goto HandleDeviceSetPower_Exit; } } else if (PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState) { // D0 -> D0 // unblock the queue which may have been blocked processing // query irp FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: A SetD0 request\n")); KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql); deviceExtension->QueueState = AllowRequests; KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql); ProcessQueuedRequests(deviceExtension); } IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: HandleDeviceSetPower: Lower drivers failed a power Irp\n")); } } HandleDeviceSetPower_Exit: FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Leaving\n")); return STATUS_PENDING; }
VOID DokanIrpCancelRoutine( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { KIRQL oldIrql; PIRP_ENTRY irpEntry; ULONG serialNumber; PIO_STACK_LOCATION irpSp; DDbgPrint("==> DokanIrpCancelRoutine\n"); // Release the cancel spinlock IoReleaseCancelSpinLock(Irp->CancelIrql); irpEntry = Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_IRP_ENTRY]; if (irpEntry != NULL) { PKSPIN_LOCK lock = &irpEntry->IrpList->ListLock; // Acquire the queue spinlock ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); KeAcquireSpinLock(lock, &oldIrql); irpSp = IoGetCurrentIrpStackLocation(Irp); ASSERT(irpSp != NULL); serialNumber = irpEntry->SerialNumber; RemoveEntryList(&irpEntry->ListEntry); // If Write is canceld before completion and buffer that saves writing // content is not freed, free it here if (irpSp->MajorFunction == IRP_MJ_WRITE) { PVOID eventContext = Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT]; if (eventContext != NULL) { DokanFreeEventContext(eventContext); } Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = NULL; } if (IsListEmpty(&irpEntry->IrpList->ListHead)) { //DDbgPrint(" list is empty ClearEvent\n"); KeClearEvent(&irpEntry->IrpList->NotEmpty); } irpEntry->Irp = NULL; if (irpEntry->CancelRoutineFreeMemory == FALSE) { InitializeListHead(&irpEntry->ListEntry); } else { DokanFreeIrpEntry(irpEntry); irpEntry = NULL; } Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_IRP_ENTRY] = NULL; KeReleaseSpinLock(lock, oldIrql); } DDbgPrint(" canceled IRP #%X\n", serialNumber); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DDbgPrint("<== DokanIrpCancelRoutine\n"); return; }
BOOLEAN USBSTOR_QueueAddIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PDRIVER_CANCEL OldDriverCancel; KIRQL OldLevel; PFDO_DEVICE_EXTENSION FDODeviceExtension; BOOLEAN IrpListFreeze; BOOLEAN SrbProcessing; PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; // // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO); // // mark irp pending // IoMarkIrpPending(Irp); // // acquire lock // KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); // // check if there are irp pending // SrbProcessing = FDODeviceExtension->IrpPendingCount != 0; if (SrbProcessing) { // // add irp to queue // InsertTailList(&FDODeviceExtension->IrpListHead, &Irp->Tail.Overlay.ListEntry); } // // increment pending count // FDODeviceExtension->IrpPendingCount++; // // clear the no requests pending event // KeClearEvent(&FDODeviceExtension->NoPendingRequests); // // check if queue is freezed // IrpListFreeze = FDODeviceExtension->IrpListFreeze; // // release list lock // KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); // // synchronize with cancellations by holding the cancel lock // IoAcquireCancelSpinLock(&Irp->CancelIrql); // // now set the driver cancel routine // if (SrbProcessing) { ASSERT(FDODeviceExtension->ActiveSrb != NULL); OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_Cancel); } else { ASSERT(FDODeviceExtension->ActiveSrb == NULL); FDODeviceExtension->ActiveSrb = Request; OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_CancelIo); } // // check if the irp has already been cancelled // if (Irp->Cancel && OldDriverCancel == NULL) { // // cancel irp // Irp->CancelRoutine(DeviceObject, Irp); // // irp was cancelled // return FALSE; } // // release the cancel lock // IoReleaseCancelSpinLock(Irp->CancelIrql); // // if list is freezed, dont start this packet // DPRINT("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze, FDODeviceExtension->IrpPendingCount); return (IrpListFreeze || SrbProcessing); }
// user assinged bigger buffer that is enough to return WriteEventContext NTSTATUS DokanEventWrite( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { KIRQL oldIrql; PLIST_ENTRY thisEntry, nextEntry, listHead; PIRP_ENTRY irpEntry; PDokanVCB vcb; PEVENT_INFORMATION eventInfo; PIRP writeIrp; eventInfo = (PEVENT_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ASSERT(eventInfo != NULL); DDbgPrint("==> DokanEventWrite [EventInfo #%X]\n", eventInfo->SerialNumber); vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB) { return STATUS_INVALID_PARAMETER; } ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); KeAcquireSpinLock(&vcb->Dcb->PendingIrp.ListLock, &oldIrql); // search corresponding write IRP through pending IRP list listHead = &vcb->Dcb->PendingIrp.ListHead; for (thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = nextEntry) { PIO_STACK_LOCATION writeIrpSp, eventIrpSp; PEVENT_CONTEXT eventContext; ULONG info = 0; NTSTATUS status; nextEntry = thisEntry->Flink; irpEntry = CONTAINING_RECORD(thisEntry, IRP_ENTRY, ListEntry); // check whehter this is corresponding IRP //DDbgPrint("SerialNumber irpEntry %X eventInfo %X\n", irpEntry->SerialNumber, eventInfo->SerialNumber); if (irpEntry->SerialNumber != eventInfo->SerialNumber) { continue; } // do NOT free irpEntry here writeIrp = irpEntry->Irp; if (writeIrp == NULL) { // this IRP has already been canceled ASSERT(irpEntry->CancelRoutineFreeMemory == FALSE); DokanFreeIrpEntry(irpEntry); continue; } if (IoSetCancelRoutine(writeIrp, DokanIrpCancelRoutine) == NULL) { //if (IoSetCancelRoutine(writeIrp, NULL) != NULL) { // Cancel routine will run as soon as we release the lock InitializeListHead(&irpEntry->ListEntry); irpEntry->CancelRoutineFreeMemory = TRUE; continue; } writeIrpSp = irpEntry->IrpSp; eventIrpSp = IoGetCurrentIrpStackLocation(Irp); ASSERT(writeIrpSp != NULL); ASSERT(eventIrpSp != NULL); eventContext = (PEVENT_CONTEXT)writeIrp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT]; ASSERT(eventContext != NULL); // short of buffer length if (eventIrpSp->Parameters.DeviceIoControl.OutputBufferLength < eventContext->Length) { DDbgPrint(" EventWrite: STATUS_INSUFFICIENT_RESOURCE\n"); status = STATUS_INSUFFICIENT_RESOURCES; } else { PVOID buffer; //DDbgPrint(" EventWrite CopyMemory\n"); //DDbgPrint(" EventLength %d, BufLength %d\n", eventContext->Length, // eventIrpSp->Parameters.DeviceIoControl.OutputBufferLength); if (Irp->MdlAddress) buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); else buffer = Irp->AssociatedIrp.SystemBuffer; ASSERT(buffer != NULL); RtlCopyMemory(buffer, eventContext, eventContext->Length); info = eventContext->Length; status = STATUS_SUCCESS; } DokanFreeEventContext(eventContext); writeIrp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0; KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql); Irp->IoStatus.Status = status; Irp->IoStatus.Information = info; // this IRP will be completed by caller function return Irp->IoStatus.Status; } KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql); return STATUS_SUCCESS; }
VOID USBSTOR_QueueRelease( IN PDEVICE_OBJECT DeviceObject) { PFDO_DEVICE_EXTENSION FDODeviceExtension; PIRP Irp; KIRQL OldLevel; PIO_STACK_LOCATION IoStack; PSCSI_REQUEST_BLOCK Request; // // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO); // // acquire lock // KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); // // clear freezed status // FDODeviceExtension->IrpListFreeze = FALSE; // // release irp list lock // KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); // // grab newest irp // Irp = USBSTOR_RemoveIrp(DeviceObject); // // is there an irp // if (!Irp) { // // no irp // return; } // // get current irp stack location // IoStack = IoGetCurrentIrpStackLocation(Irp); // // get srb // Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; // // start new packet // IoStartPacket(DeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo); }
NTSTATUS CcRosTrimCache ( ULONG Target, ULONG Priority, PULONG NrFreed) /* * FUNCTION: Try to free some memory from the file cache. * ARGUMENTS: * Target - The number of pages to be freed. * Priority - The priority of free (currently unused). * NrFreed - Points to a variable where the number of pages * actually freed is returned. */ { PLIST_ENTRY current_entry; PROS_VACB current; ULONG PagesFreed; KIRQL oldIrql; LIST_ENTRY FreeList; PFN_NUMBER Page; ULONG i; BOOLEAN FlushedPages = FALSE; DPRINT("CcRosTrimCache(Target %lu)\n", Target); InitializeListHead(&FreeList); *NrFreed = 0; retry: KeAcquireGuardedMutex(&ViewLock); current_entry = VacbLruListHead.Flink; while (current_entry != &VacbLruListHead) { current = CONTAINING_RECORD(current_entry, ROS_VACB, VacbLruListEntry); current_entry = current_entry->Flink; KeAcquireSpinLock(¤t->SharedCacheMap->CacheMapLock, &oldIrql); /* Reference the VACB */ CcRosVacbIncRefCount(current); /* Check if it's mapped and not dirty */ if (current->MappedCount > 0 && !current->Dirty) { /* We have to break these locks because Cc sucks */ KeReleaseSpinLock(¤t->SharedCacheMap->CacheMapLock, oldIrql); KeReleaseGuardedMutex(&ViewLock); /* Page out the VACB */ for (i = 0; i < VACB_MAPPING_GRANULARITY / PAGE_SIZE; i++) { Page = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)current->BaseAddress + (i * PAGE_SIZE)).QuadPart >> PAGE_SHIFT); MmPageOutPhysicalAddress(Page); } /* Reacquire the locks */ KeAcquireGuardedMutex(&ViewLock); KeAcquireSpinLock(¤t->SharedCacheMap->CacheMapLock, &oldIrql); } /* Dereference the VACB */ CcRosVacbDecRefCount(current); /* Check if we can free this entry now */ if (current->ReferenceCount == 0) { ASSERT(!current->Dirty); ASSERT(!current->MappedCount); RemoveEntryList(¤t->CacheMapVacbListEntry); RemoveEntryList(¤t->VacbLruListEntry); InsertHeadList(&FreeList, ¤t->CacheMapVacbListEntry); /* Calculate how many pages we freed for Mm */ PagesFreed = min(VACB_MAPPING_GRANULARITY / PAGE_SIZE, Target); Target -= PagesFreed; (*NrFreed) += PagesFreed; } KeReleaseSpinLock(¤t->SharedCacheMap->CacheMapLock, oldIrql); }
VOID NTAPI USBSTOR_StartIo( PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION IoStack; PFDO_DEVICE_EXTENSION FDODeviceExtension; PPDO_DEVICE_EXTENSION PDODeviceExtension; KIRQL OldLevel; BOOLEAN ResetInProgress; DPRINT("USBSTOR_StartIo\n"); // // get FDO device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // sanity check // ASSERT(FDODeviceExtension->Common.IsFDO); // // acquire cancel spinlock // IoAcquireCancelSpinLock(&OldLevel); // // set cancel routine to zero // IoSetCancelRoutine(Irp, NULL); // // check if the irp has been cancelled // if (Irp->Cancel) { // // irp has been cancelled, release cancel spinlock // IoReleaseCancelSpinLock(OldLevel); // // irp is cancelled // Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; // // terminate request // USBSTOR_QueueTerminateRequest(DeviceObject, Irp); // // complete request // IoCompleteRequest(Irp, IO_NO_INCREMENT); // // queue next request // USBSTOR_QueueNextRequest(DeviceObject); // // done // return; } // // release cancel spinlock // IoReleaseCancelSpinLock(OldLevel); // // acquire lock // KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); // // check reset is in progress // ResetInProgress = FDODeviceExtension->ResetInProgress; ASSERT(ResetInProgress == FALSE); // // release lock // KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); // // get current irp stack location // IoStack = IoGetCurrentIrpStackLocation(Irp); // // get pdo device extension // PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension; // // sanity check // ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); // // is a reset in progress // if (ResetInProgress) { // // hard reset is in progress // Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; USBSTOR_QueueTerminateRequest(DeviceObject, Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); return; } // // execute scsi // USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp, 0); // // FIXME: handle error // }
/* * @implemented */ VOID NTAPI IoReleaseRemoveLockEx(IN PIO_REMOVE_LOCK RemoveLock, IN PVOID Tag, IN ULONG RemlockSize) { KIRQL OldIrql; LONG LockValue; BOOLEAN TagFound; LARGE_INTEGER CurrentMoment; PIO_REMOVE_LOCK_TRACKING_BLOCK TrackingBlock; PIO_REMOVE_LOCK_TRACKING_BLOCK *TrackingBlockLink; PEXTENDED_IO_REMOVE_LOCK Lock = (PEXTENDED_IO_REMOVE_LOCK)RemoveLock; /* Check what kind of lock this is */ if (RemlockSize == (sizeof(IO_REMOVE_LOCK_DBG_BLOCK) + sizeof(IO_REMOVE_LOCK_COMMON_BLOCK))) { /* Acquire blocks queue */ KeAcquireSpinLock(&(Lock->Dbg.Spin), &OldIrql); /* Get the release moment */ KeQueryTickCount(&CurrentMoment); /* Start browsing tracking blocks to find a block that would match given tag */ TagFound = FALSE; TrackingBlock = Lock->Dbg.Blocks; TrackingBlockLink = &(Lock->Dbg.Blocks); while (TrackingBlock != NULL) { /* First of all, check if the lock was locked for too long */ if (Lock->Dbg.MaxLockedTicks && CurrentMoment.QuadPart - TrackingBlock->LockMoment.QuadPart > Lock->Dbg.MaxLockedTicks) { DPRINT("Lock %#08lx (with tag %#08lx) was supposed to be held at max %I64d ticks but lasted longer\n", Lock, TrackingBlock->Tag, Lock->Dbg.MaxLockedTicks); DPRINT("Lock was acquired in file %s at line %d\n", TrackingBlock->File, TrackingBlock->Line); ASSERT(FALSE); } /* Check if this is the first matching tracking block */ if ((TagFound == FALSE) && (TrackingBlock->Tag == Tag)) { /* Unlink this tracking block, and free it */ TagFound = TRUE; *TrackingBlockLink = TrackingBlock->Next; ExFreePoolWithTag(TrackingBlock, Lock->Dbg.AllocateTag); TrackingBlock = *TrackingBlockLink; } else { /* Go to the next tracking block */ TrackingBlockLink = &(TrackingBlock->Next); TrackingBlock = TrackingBlock->Next; } } /* We're done, release queue lock */ KeReleaseSpinLock(&(Lock->Dbg.Spin), OldIrql); /* If we didn't find any matching block */ if (TagFound == FALSE) { /* Check if it was because we were low in memory * If yes, then ignore, that's normal */ if (InterlockedDecrement(&(Lock->Dbg.LowMemoryCount)) < 0) { /* Otherwise signal the issue, it shouldn't happen */ InterlockedIncrement(&(Lock->Dbg.LowMemoryCount)); DPRINT("Failed finding block for tag: %#08lx\n", Tag); ASSERT(FALSE); } } } /* Decrement the lock count */ LockValue = InterlockedDecrement(&(Lock->Common.IoCount)); ASSERT(LockValue >= 0); if (!LockValue) { /* Someone should be waiting... */ ASSERT(Lock->Common.Removed); /* Signal the event */ KeSetEvent(&(Lock->Common.RemoveEvent), IO_NO_INCREMENT, FALSE); } }
static NTSTATUS GnttabCreateCache( IN PINTERFACE Interface, IN const CHAR *Name, IN ULONG Reservation, IN VOID (*AcquireLock)(PVOID), IN VOID (*ReleaseLock)(PVOID), IN PVOID Argument, OUT PXENBUS_GNTTAB_CACHE *Cache ) { PXENBUS_GNTTAB_CONTEXT Context = Interface->Context; KIRQL Irql; NTSTATUS status; *Cache = __GnttabAllocate(sizeof (XENBUS_GNTTAB_CACHE)); status = STATUS_NO_MEMORY; if (*Cache == NULL) goto fail1; (*Cache)->Context = Context; status = RtlStringCbPrintfA((*Cache)->Name, sizeof ((*Cache)->Name), "%s_gnttab", Name); if (!NT_SUCCESS(status)) goto fail2; (*Cache)->AcquireLock = AcquireLock; (*Cache)->ReleaseLock = ReleaseLock; (*Cache)->Argument = Argument; status = XENBUS_CACHE(Create, &Context->CacheInterface, (*Cache)->Name, sizeof (XENBUS_GNTTAB_ENTRY), Reservation, GnttabEntryCtor, GnttabEntryDtor, GnttabAcquireLock, GnttabReleaseLock, *Cache, &(*Cache)->Cache); if (!NT_SUCCESS(status)) goto fail3; KeAcquireSpinLock(&Context->Lock, &Irql); InsertTailList(&Context->List, &(*Cache)->ListEntry); KeReleaseSpinLock(&Context->Lock, Irql); return STATUS_SUCCESS; fail3: Error("fail3\n"); (*Cache)->Argument = NULL; (*Cache)->ReleaseLock = NULL; (*Cache)->AcquireLock = NULL; RtlZeroMemory((*Cache)->Name, sizeof ((*Cache)->Name)); fail2: Error("fail2\n"); (*Cache)->Context = NULL; ASSERT(IsZeroMemory(*Cache, sizeof (XENBUS_GNTTAB_CACHE))); __GnttabFree(*Cache); fail1: Error("fail1 (%08x)\n", status); return status; }
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: { 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_ADAPTERINFO_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_TARGET, buffer, sizeof(NDASBUS_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; 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_ADAPTERINFO_STATUS_STOPPED)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'An event occured after 'Stopped' event\n")); if(ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_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_ADAPTERINFO_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_ADAPTERINFO_STATUS_STOPPED) && ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_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_ADAPTERINFO_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 GnttabAcquire( IN PINTERFACE Interface ) { PXENBUS_GNTTAB_CONTEXT Context = Interface->Context; PXENBUS_FDO Fdo = Context->Fdo; KIRQL Irql; ULONG Size; NTSTATUS status; KeAcquireSpinLock(&Context->Lock, &Irql); if (Context->References++ != 0) goto done; Trace("====>\n"); Size = XENBUS_GNTTAB_MAXIMUM_FRAME_COUNT * PAGE_SIZE; status = FdoAllocateIoSpace(Fdo, Size, &Context->Address); if (!NT_SUCCESS(status)) goto fail1; Context->Table = (grant_entry_v1_t *)MmMapIoSpace(Context->Address, Size, MmCached); status = STATUS_UNSUCCESSFUL; if (Context->Table == NULL) goto fail2; Context->FrameIndex = -1; status = XENBUS_RANGE_SET(Acquire, &Context->RangeSetInterface); if (!NT_SUCCESS(status)) goto fail3; status = XENBUS_RANGE_SET(Create, &Context->RangeSetInterface, "gnttab", &Context->RangeSet); if (!NT_SUCCESS(status)) goto fail4; status = XENBUS_CACHE(Acquire, &Context->CacheInterface); if (!NT_SUCCESS(status)) goto fail5; status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface); if (!NT_SUCCESS(status)) goto fail6; status = XENBUS_SUSPEND(Register, &Context->SuspendInterface, SUSPEND_CALLBACK_EARLY, GnttabSuspendCallbackEarly, Context, &Context->SuspendCallbackEarly); if (!NT_SUCCESS(status)) goto fail7; status = XENBUS_DEBUG(Acquire, &Context->DebugInterface); if (!NT_SUCCESS(status)) goto fail8; status = XENBUS_DEBUG(Register, &Context->DebugInterface, __MODULE__ "|GNTTAB", GnttabDebugCallback, Context, &Context->DebugCallback); if (!NT_SUCCESS(status)) goto fail9; Trace("<====\n"); done: KeReleaseSpinLock(&Context->Lock, Irql); return STATUS_SUCCESS; fail9: Error("fail9\n"); XENBUS_DEBUG(Release, &Context->DebugInterface); fail8: Error("fail8\n"); XENBUS_SUSPEND(Deregister, &Context->SuspendInterface, Context->SuspendCallbackEarly); Context->SuspendCallbackEarly = NULL; fail7: Error("fail7\n"); XENBUS_SUSPEND(Release, &Context->SuspendInterface); fail6: Error("fail6\n"); XENBUS_CACHE(Release, &Context->CacheInterface); fail5: Error("fail5\n"); GnttabContract(Context); ASSERT3S(Context->FrameIndex, ==, -1); XENBUS_RANGE_SET(Destroy, &Context->RangeSetInterface, Context->RangeSet); Context->RangeSet = NULL; Context->FrameIndex = 0; fail4: Error("fail4\n"); XENBUS_RANGE_SET(Release, &Context->RangeSetInterface); fail3: Error("fail3\n"); MmUnmapIoSpace(Context->Table, Size); Context->Table = NULL; fail2: Error("fail2\n"); FdoFreeIoSpace(Fdo, Context->Address, Size); Context->Address.QuadPart = 0; fail1: Error("fail1 (%08x)\n", status); --Context->References; ASSERT3U(Context->References, ==, 0); KeReleaseSpinLock(&Context->Lock, Irql); return status; }
/*++//////////////////////////////////////////////////////////////////////////// ClassAcquireRemoveLockEx() Routine Description: This routine is called to acquire the remove lock on the device object. While the lock is held, the caller can assume that no pending pnp REMOVE requests will be completed. The lock should be acquired immediately upon entering a dispatch routine. It should also be acquired before creating any new reference to the device object if there's a chance of releasing the reference before the new one is done. This routine will return TRUE if the lock was successfully acquired or FALSE if it cannot be because the device object has already been removed. Arguments: DeviceObject - the device object to lock Tag - Used for tracking lock allocation and release. If an irp is specified when acquiring the lock then the same Tag must be used to release the lock before the Tag is completed. Return Value: The value of the IsRemoved flag in the device extension. If this is non-zero then the device object has received a Remove irp and non-cleanup IRP's should fail. If the value is REMOVE_COMPLETE, the caller should not even release the lock. --*/ ULONG NTAPI ClassAcquireRemoveLockEx( IN PDEVICE_OBJECT DeviceObject, IN OPTIONAL PVOID Tag, IN PCSTR File, IN ULONG Line ) { PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; LONG lockValue; // // Grab the remove lock // lockValue = InterlockedIncrement(&commonExtension->RemoveLock); #if DBG DebugPrint((ClassDebugRemoveLock, "ClassAcquireRemoveLock: " "Acquired for Object %p & irp %p - count is %d\n", DeviceObject, Tag, lockValue)); ASSERTMSG("ClassAcquireRemoveLock - lock value was negative : ", (lockValue > 0)); ASSERTMSG("RemoveLock increased to meet LockHighWatermark", ((LockHighWatermark == 0) || (lockValue != LockHighWatermark))); if (commonExtension->IsRemoved != REMOVE_COMPLETE){ PREMOVE_TRACKING_BLOCK trackingBlock; trackingBlock = ExAllocatePool(NonPagedPool, sizeof(REMOVE_TRACKING_BLOCK)); if(trackingBlock == NULL) { KIRQL oldIrql; KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock, &oldIrql); commonExtension->RemoveTrackingUntrackedCount++; DebugPrint((ClassDebugWarning, ">>>>>ClassAcquireRemoveLock: " "Cannot track Tag %p - currently %d untracked requsts\n", Tag, commonExtension->RemoveTrackingUntrackedCount)); KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, oldIrql); } else { PREMOVE_TRACKING_BLOCK *removeTrackingList = (PREMOVE_TRACKING_BLOCK*)&commonExtension->RemoveTrackingList; KIRQL oldIrql; trackingBlock->Tag = Tag; trackingBlock->File = File; trackingBlock->Line = Line; KeQueryTickCount((&trackingBlock->TimeLocked)); KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock, &oldIrql); while(*removeTrackingList != NULL) { if((*removeTrackingList)->Tag > Tag) { break; } if((*removeTrackingList)->Tag == Tag) { DebugPrint((ClassDebugError, ">>>>>ClassAcquireRemoveLock: " "already tracking Tag %p\n", Tag)); DebugPrint((ClassDebugError, ">>>>>ClassAcquireRemoveLock: " "acquired in file %s on line %d\n", (*removeTrackingList)->File, (*removeTrackingList)->Line)); ASSERT(FALSE); } removeTrackingList = &((*removeTrackingList)->NextBlock); } trackingBlock->NextBlock = *removeTrackingList; *removeTrackingList = trackingBlock; KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, oldIrql); } } #endif return (commonExtension->IsRemoved); }
VOID GnttabRelease( IN PINTERFACE Interface ) { PXENBUS_GNTTAB_CONTEXT Context = Interface->Context; PXENBUS_FDO Fdo = Context->Fdo; KIRQL Irql; ULONG Size; KeAcquireSpinLock(&Context->Lock, &Irql); if (--Context->References > 0) goto done; Trace("====>\n"); if (!IsListEmpty(&Context->List)) BUG("OUTSTANDING CACHES"); XENBUS_DEBUG(Deregister, &Context->DebugInterface, Context->DebugCallback); Context->DebugCallback = NULL; XENBUS_DEBUG(Release, &Context->DebugInterface); XENBUS_SUSPEND(Deregister, &Context->SuspendInterface, Context->SuspendCallbackEarly); Context->SuspendCallbackEarly = NULL; XENBUS_SUSPEND(Release, &Context->SuspendInterface); XENBUS_CACHE(Release, &Context->CacheInterface); GnttabContract(Context); ASSERT3S(Context->FrameIndex, ==, -1); XENBUS_RANGE_SET(Destroy, &Context->RangeSetInterface, Context->RangeSet); Context->RangeSet = NULL; Context->FrameIndex = 0; XENBUS_RANGE_SET(Release, &Context->RangeSetInterface); Size = XENBUS_GNTTAB_MAXIMUM_FRAME_COUNT * PAGE_SIZE; MmUnmapIoSpace(Context->Table, Size); Context->Table = NULL; FdoFreeIoSpace(Fdo, Context->Address, Size); Context->Address.QuadPart = 0; Trace("<====\n"); done: KeReleaseSpinLock(&Context->Lock, Irql); }
NTSTATUS USBPcapBufferWritePacket(PUSBPCAP_ROOTHUB_DATA pRootData, PUSBPCAP_BUFFER_PACKET_HEADER header, PVOID buffer) { UINT32 bytes; UINT32 bytesFree; KIRQL irql; NTSTATUS status; PDEVICE_EXTENSION pControlExt; PIRP pIrp = NULL; pcaprec_hdr_t pcapHeader; pControlExt = (PDEVICE_EXTENSION)pRootData->controlDevice->DeviceExtension; ASSERT(pControlExt->deviceMagic == USBPCAP_MAGIC_CONTROL); bytes = header->headerLen + header->dataLength; KeAcquireSpinLock(&pRootData->bufferLock, &irql); USBPcapInitializePcapHeader(pRootData, &pcapHeader, bytes); /* pcapHeader.incl_len contains the number of bytes to write */ bytes = pcapHeader.incl_len; status = STATUS_SUCCESS; bytesFree = USBPcapGetBufferFree(pRootData); if ((pRootData->buffer == NULL) || (bytesFree < sizeof(pcaprec_hdr_t)) || ((bytesFree - sizeof(pcaprec_hdr_t)) < bytes)) { DkDbgStr("No enough free space left."); status = STATUS_INSUFFICIENT_RESOURCES; } else { UINT32 tmp; /* Write Packet Header */ USBPcapBufferWriteUnsafe(pRootData, (PVOID) &pcapHeader, (UINT32) sizeof(pcaprec_hdr_t)); /* Write USBPCAP_BUFFER_PACKET_HEADER */ tmp = min(bytes, (UINT32)header->headerLen); if (tmp > 0) { USBPcapBufferWriteUnsafe(pRootData, (PVOID) header, tmp); } bytes -= tmp; if (bytes > 0 && header->dataLength > 0) { /* Write data */ tmp = min(bytes, header->dataLength); USBPcapBufferWriteUnsafe(pRootData, buffer, tmp); } } KeReleaseSpinLock(&pRootData->bufferLock, irql); if (NT_SUCCESS(status)) { pIrp = IoCsqRemoveNextIrp(&pControlExt->context.control.ioCsq, NULL); if (pIrp != NULL) { PVOID buffer; UINT32 bufferLength; UINT32 bytesRead; /* * Only IRPs with non-zero buffer are being queued. * * Since control device has DO_DIRECT_IO bit set the MDL is already * probed and locked */ buffer = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); if (buffer == NULL) { pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; bytes = 0; } else { UINT32 bufferLength = MmGetMdlByteCount(pIrp->MdlAddress); if (bufferLength != 0) { KeAcquireSpinLock(&pRootData->bufferLock, &irql); bytes = USBPcapBufferRead(pRootData, buffer, bufferLength); KeReleaseSpinLock(&pRootData->bufferLock, irql); } else { bytes = 0; } pIrp->IoStatus.Status = STATUS_SUCCESS; } pIrp->IoStatus.Information = (ULONG_PTR) bytes; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } } return status; }
int tdi_set_event_handler(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) { PTDI_REQUEST_KERNEL_SET_EVENT r = (PTDI_REQUEST_KERNEL_SET_EVENT)&irps->Parameters; NTSTATUS status; struct ot_entry *ote_addr = NULL; KIRQL irql; int result = FILTER_DENY; TDI_EVENT_CONTEXT *ctx; KdPrint(("[tdi_fw] tdi_set_event_handler: [%s] devobj 0x%x; addrobj 0x%x; EventType: %d\n", r->EventHandler ? "(+)ADD" : "(-)REMOVE", irps->DeviceObject, irps->FileObject, r->EventType)); ote_addr = ot_find_fileobj(irps->FileObject, &irql); if (ote_addr == NULL) { KdPrint(("[tdi_fw] tdi_set_event_handler: ot_find_fileobj(0x%x)\n", irps->FileObject)); if (r->EventHandler == NULL) { // for fileobjects loaded earlier than our driver allow removing result = FILTER_ALLOW; } goto done; } if (r->EventType < 0 || r->EventType >= MAX_EVENT) { KdPrint(("[tdi_fw] tdi_set_event_handler: unknown EventType %d!\n", r->EventType)); result = FILTER_ALLOW; goto done; } ctx = &ote_addr->ctx[r->EventType]; if (r->EventHandler != NULL) { /* add EventHandler */ int i; for (i = 0; g_tdi_event_handlers[i].event != (ULONG)-1; i++) if (g_tdi_event_handlers[i].event == r->EventType) break; if (g_tdi_event_handlers[i].event == (ULONG)-1) { KdPrint(("[tdi_fw] tdi_set_event_handler: unknown EventType %d!\n", r->EventType)); result = FILTER_ALLOW; goto done; } ctx->old_handler = r->EventHandler; ctx->old_context = r->EventContext; if (g_tdi_event_handlers[i].handler != NULL) { r->EventHandler = g_tdi_event_handlers[i].handler; r->EventContext = ctx; } else { r->EventHandler = NULL; r->EventContext = NULL; } KdPrint(("[tdi_fw] tdi_set_event_handler: old_handler 0x%x; old_context 0x%x\n", r->EventHandler, r->EventContext)); } else { /* remove EventHandler */ ctx->old_handler = NULL; ctx->old_context = NULL; } // change LISTEN state if (r->EventType == TDI_EVENT_CONNECT) { TA_ADDRESS *local_addr; if (r->EventHandler != NULL) { // add "LISTEN" info status = add_listen(ote_addr); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] tdi_set_event_handler: add_listen: 0x%x!\n", status)); goto done; } } else if (ote_addr->listen_entry != NULL) { // remove "LISTEN" info del_listen_obj(ote_addr->listen_entry, FALSE); ote_addr->listen_entry = NULL; } // log it if address is not 127.0.0.1 local_addr = (TA_ADDRESS *)(ote_addr->local_addr); if (ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr) != 0x7f000001) { struct flt_request request; memset(&request, 0, sizeof(request)); request.struct_size = sizeof(request); request.type = (r->EventHandler != NULL) ? TYPE_LISTEN : TYPE_NOT_LISTEN; request.proto = IPPROTO_TCP; // correct? if (r->EventHandler != NULL) { // for removing event handler ProcessNotifyProc can be already called request.pid = (ULONG)PsGetCurrentProcessId(); if (request.pid == 0) { // avoid idle process pid (XXX do we need this?) request.pid = ote_addr->pid; } } else request.pid = (ULONG)-1; // get user SID & attributes (can't call get_current_sid_a at DISPATCH_LEVEL) if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL) request.sid_a_size = ote_addr->sid_a_size; memcpy(&request.addr.from, &local_addr->AddressType, sizeof(struct sockaddr)); request.addr.len = sizeof(struct sockaddr_in); log_request(&request); if (request.sid_a != NULL) free(request.sid_a); } } result = FILTER_ALLOW; done: // cleanup if (ote_addr != NULL) KeReleaseSpinLock(&g_ot_hash_guard, irql); return result; }