⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intpnp.c

📁 学习usb编程很好的例子 自己学习用的。
💻 C
📖 第 1 页 / 共 5 页
字号:
}


VOID
ProcessQueuedRequests(
    IN OUT PDEVICE_EXTENSION DeviceExtension
    )
/*++
 
Routine Description:

    Remove and process the entries in the queue. If this routine is called
    when processing IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE
    or IRP_MN_START_DEVICE, the requests are passed to the next lower driver.
    If the routine is called when IRP_MN_REMOVE_DEVICE is received, the IRPs
    are complete with STATUS_DELETE_PENDING

Arguments:

    DeviceExtension - pointer to device extension

Return Value:

    None

--*/
{
    KIRQL       oldIrql;
    PIRP        nextIrp,
                cancelledIrp;
    PVOID       cancelRoutine;
    LIST_ENTRY  cancelledIrpList;
    PLIST_ENTRY listEntry;

    KdPrint( ("ProcessQueuedRequests - begins\n"));

    //
    // initialize variables
    //

    cancelRoutine = NULL;
    InitializeListHead(&cancelledIrpList);

    //
    // 1.  dequeue the entries in the queue
    // 2.  reset the cancel routine
    // 3.  process them
    // 3a. if the device is active, send them down
    // 3b. else complete with STATUS_DELETE_PENDING
    //

    while(1) {

        KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);

        if(IsListEmpty(&DeviceExtension->NewRequestsQueue)) {

            KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
            break;
        }
    
        //
        // Remove a request from the queue
        //

        listEntry = RemoveHeadList(&DeviceExtension->NewRequestsQueue);
        nextIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);

        //
        // set the cancel routine to NULL
        //

        cancelRoutine = IoSetCancelRoutine(nextIrp, NULL);

        //
        // check if its already cancelled
        //

        if(nextIrp->Cancel) {
            if(cancelRoutine) {

                //
                // the cancel routine for this IRP hasnt been called yet
                // so queue the IRP in the cancelledIrp list and complete
                // after releasing the lock
                //
                
                InsertTailList(&cancelledIrpList, listEntry);
            }
            else {

                //
                // the cancel routine has run
                // it must be waiting to hold the queue lock
                // so initialize the IRPs listEntry
                //

                InitializeListHead(listEntry);
            }

            KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
        }
        else {

            KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);

            if(FailRequests == DeviceExtension->QueueState) {

                nextIrp->IoStatus.Information = 0;
                nextIrp->IoStatus.Status = STATUS_DELETE_PENDING;
                IoCompleteRequest(nextIrp, IO_NO_INCREMENT);
            }
            else {

                PIO_STACK_LOCATION irpStack;

                KdPrint( ("ProcessQueuedRequests::"));
                IntUsb_IoIncrement(DeviceExtension);

                IoSkipCurrentIrpStackLocation(nextIrp);
                IoCallDriver(DeviceExtension->TopOfStackDeviceObject, nextIrp);
               
                KdPrint( ("ProcessQueuedRequests::"));
                IntUsb_IoDecrement(DeviceExtension);
            }
        }
    } // while loop

    //
    // walk through the cancelledIrp list and cancel them
    //

    while(!IsListEmpty(&cancelledIrpList)) {

        PLIST_ENTRY listEntry = RemoveHeadList(&cancelledIrpList);
        
        cancelledIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);

        cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
        cancelledIrp->IoStatus.Information = 0;

        IoCompleteRequest(cancelledIrp, IO_NO_INCREMENT);
    }

    KdPrint( ("ProcessQueuedRequests - ends\n"));

    return;
}

NTSTATUS
IntUsb_GetRegistryDword(
    IN     PWCHAR RegPath,
    IN     PWCHAR ValueName,
    IN OUT PULONG Value
    )
/*++
 
Routine Description:

    This routine reads the specified reqistry value.

Arguments:

    RegPath - registry path
    ValueName - property to be fetched from the registry
    Value - corresponding value read from the registry.

Return Value:

    NT status value

--*/
{
    ULONG                    defaultData;
    WCHAR                    buffer[MAXIMUM_FILENAME_LENGTH];
    NTSTATUS                 ntStatus;
    UNICODE_STRING           regPath;
    RTL_QUERY_REGISTRY_TABLE paramTable[2];

    KdPrint( ("IntUsb_GetRegistryDword - begins\n"));

    regPath.Length = 0;
    regPath.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR);
    regPath.Buffer = buffer;

    RtlZeroMemory(regPath.Buffer, regPath.MaximumLength);
    RtlMoveMemory(regPath.Buffer,
                  RegPath,
                  wcslen(RegPath) * sizeof(WCHAR));

    RtlZeroMemory(paramTable, sizeof(paramTable));

    paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
    paramTable[0].Name = ValueName;
    paramTable[0].EntryContext = Value;
    paramTable[0].DefaultType = REG_DWORD;
    paramTable[0].DefaultData = &defaultData;
    paramTable[0].DefaultLength = sizeof(ULONG);

    ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE |
                                      RTL_REGISTRY_OPTIONAL,
                                      regPath.Buffer,
                                      paramTable,
                                      NULL,
                                      NULL);

    if(NT_SUCCESS(ntStatus)) {

        KdPrint( ("success Value = %X\n", *Value));
        return STATUS_SUCCESS;
    }
    else {

        *Value = 0;
        return STATUS_UNSUCCESSFUL;
    }
}


NTSTATUS
IntUsb_DispatchClean(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
/*++
 
Routine Description:

    Dispatch routine for IRP_MJ_CLEANUP

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet sent by the pnp manager

Return Value:

    NT status value

--*/
{
    PDEVICE_EXTENSION  deviceExtension;
    KIRQL              oldIrql;
    LIST_ENTRY         cleanupList;
    PLIST_ENTRY        thisEntry, 
                       nextEntry, 
                       listHead;
    PIRP               pendingIrp;
    PIO_STACK_LOCATION pendingIrpStack, 
                       irpStack;
    NTSTATUS           ntStatus;

    //
    // initialize variables
    //

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    InitializeListHead(&cleanupList);

    KdPrint( ("IntUsb_DispatchClean::"));
    IntUsb_IoIncrement(deviceExtension);

    //
    // acquire queue lock
    //
    KeAcquireSpinLock(&deviceExtension->QueueLock, &oldIrql);

    //
    // remove all Irp's that belong to input Irp's fileobject
    //

    listHead = &deviceExtension->NewRequestsQueue;

    for(thisEntry = listHead->Flink, nextEntry = thisEntry->Flink;
       thisEntry != listHead;
       thisEntry = nextEntry, nextEntry = thisEntry->Flink) {

        pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);

        pendingIrpStack = IoGetCurrentIrpStackLocation(pendingIrp);

        if(irpStack->FileObject == pendingIrpStack->FileObject) {

            RemoveEntryList(thisEntry);

            //
            // set the cancel routine to NULL
            //
            if(NULL == IoSetCancelRoutine(pendingIrp, NULL)) {

                InitializeListHead(thisEntry);
            }
            else {

                InsertTailList(&cleanupList, thisEntry);
            }
        }
    }

    //
    // Release the spin lock
    //

    KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);

    //
    // walk thru the cleanup list and cancel all the Irps
    //

    while(!IsListEmpty(&cleanupList)) {

        //
        // complete the Irp
        //
        thisEntry = RemoveHeadList(&cleanupList);

        pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);

        pendingIrp->IoStatus.Information = 0;
        pendingIrp->IoStatus.Status = STATUS_CANCELLED;

        IoCompleteRequest(pendingIrp, IO_NO_INCREMENT);
    }

	CleanupReadRequestQueue(deviceExtension, STATUS_CANCELLED, irpStack->FileObject);


    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = STATUS_SUCCESS;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    KdPrint( ("IntUsb_DispatchClean::"));
    IntUsb_IoDecrement(deviceExtension);

    return STATUS_SUCCESS;
}


///////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE

// @func Cleanup cached I/O control requests
// @parm Generic.sys device extension
// @parm Status code to use in completing requests
// @parm File object for which requests are to be completed. NULL if all cached
// requests for the calling driver are to be completed.
// @comm The main purpose of this routine is to help handle an IRP_MJ_CLEANUP when
// the file handle may have been used to submit pending control requests.

VOID CleanupReadRequestQueue(PDEVICE_EXTENSION  deviceExtension, NTSTATUS status, PFILE_OBJECT fop)
	{							// GenericCleanupControlRequests
	//if (!(pdx->Flags & GENERIC_PENDING_IOCTLS))
	//	return;					// didn't signup for pending ioctl service!

	LIST_ENTRY cancellist;
	KIRQL oldirql;
	PLIST_ENTRY first;
	PLIST_ENTRY next;
	PIRP Irp;
	PIRP Irp2;
	PIO_STACK_LOCATION stack;
	PLIST_ENTRY current;



	InitializeListHead(&cancellist);

	// Create a list of IRPs that belong to the same file object

	KeAcquireSpinLock(&deviceExtension->Cachelock, &oldirql);

	first = &deviceExtension->Pending_IOCTL_READINT_List;
	
	if((first->Flink != NULL) && (first != first->Flink))
	{
		for (next = first->Flink; next != first; )
			{						// for each queued IRP
			Irp = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry);
			stack = IoGetCurrentIrpStackLocation(Irp);

			// Follow the chain to the next IRP now (so that the next iteration of
			// the loop is properly setup whether we dequeue this IRP or not)

			current = next;
			next = next->Flink;

			// Skip this IRP if it's not for the same file object as the
			// current IRP_MJ_CLEANUP.

			if (fop && stack->FileObject != fop)
				continue;			// not for same file object

			// Set the CancelRoutine pointer to NULL and remove the IRP from the
			// queue.

			if (!IoSetCancelRoutine(Irp, NULL))
				continue;			// being cancelled right this instant
			RemoveEntryList(current);
			InsertTailList(&cancellist, current);
			}						// for each queued IRP
	

		// Release the spin lock. We're about to undertake a potentially time-consuming
		// operation that might conceivably result in a deadlock if we keep the lock.

		KeReleaseSpinLock(&deviceExtension->Cachelock, oldirql);

		// Complete the selected requests.

		while (!IsListEmpty(&cancellist))
			{						// cancel selected requests
			next = RemoveHeadList(&cancellist);
			Irp2 = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry);
			Irp2->IoStatus.Status = STATUS_CANCELLED;
			IoCompleteRequest(Irp2, IO_NO_INCREMENT);
			}						// cancel selected requests
	}
	else
		// Release the spin lock.
		KeReleaseSpinLock(&deviceExtension->Cachelock, oldirql);	

}							// GenericCleanupControlRequests

///////////////////////////////////////////////////////////////////////////////

BOOLEAN
CanDeviceSuspend(
    IN PDEVICE_EXTENSION DeviceExtension
    )
/*++
 
Routine Description:

    This is the routine where we check if the device
    can selectively suspend. 

Arguments:

    DeviceExtension - pointer to device extension

Return Value:

    TRUE - if the device can suspend
    FALSE - otherwise.

--*/
{
    KdPrint( ("CanDeviceSuspend\n"));

    if((DeviceExtension->OpenHandleCount == 0) &&
        (DeviceExtension->OutStandingIO == 1)) {
        
        return TRUE;
    }
    else {

        return FALSE;
    }
}

NTSTATUS
IntUsb_AbortPipes(
    IN PDEVICE_OBJECT DeviceObject
    )
/*++
 
Routine Description

    sends an abort pipe request for open pipes.

Arguments:

    DeviceObject - pointer to device object

Return Value:

    NT status value

--*/
{
    PURB                        urb;
    ULONG                       i;
    NTSTATUS                    ntStatus;
    PDEVICE_EXTENSION           deviceExtension;
    PINTUSB_PIPE_CONTEXT       pipeContext;
    PUSBD_PIPE_INFORMATION      pipeInformation;
    PUSBD_INTERFACE_INFORMATION interfaceInfo;

    //
    // initialize variables
    //
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    pipeContext = deviceExtension->PipeContext;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -