Example #1
0
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;
}
Example #2
0
/*++////////////////////////////////////////////////////////////////////////////

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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
/*
 * @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;
}
Example #6
0
// 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;
}
Example #7
0
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;;
}
Example #8
0
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;
}
Example #9
0
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().
Example #10
0
//
//	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;
}
Example #11
0
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;
}
Example #12
0
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;
	}
}
Example #13
0
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;
	}
}
Example #14
0
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;
}
Example #15
0
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;
}
Example #16
0
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;

}
Example #17
0
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;

}
Example #18
0
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);
}
Example #19
0
// 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;
}
Example #20
0
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);
}
Example #21
0
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(&current->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(&current->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(&current->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(&current->CacheMapVacbListEntry);
            RemoveEntryList(&current->VacbLruListEntry);
            InsertHeadList(&FreeList, &current->CacheMapVacbListEntry);

            /* Calculate how many pages we freed for Mm */
            PagesFreed = min(VACB_MAPPING_GRANULARITY / PAGE_SIZE, Target);
            Target -= PagesFreed;
            (*NrFreed) += PagesFreed;
        }

        KeReleaseSpinLock(&current->SharedCacheMap->CacheMapLock, oldIrql);
    }
Example #22
0
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
    //
}
Example #23
0
/*
 * @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);
    }
}
Example #24
0
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;
}
Example #25
0
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
    }
Example #26
0
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;
}
Example #27
0
/*++////////////////////////////////////////////////////////////////////////////

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);
}
Example #28
0
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);
}
Example #29
0
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;
}
Example #30
0
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;
}