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

📄 read.c

📁 微软的point of sale的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:


	while (!IsListEmpty(&irpsToCompleteList)){
		listEntry = RemoveHeadList(&irpsToCompleteList);
		ASSERT(listEntry);
		irp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
		DBGVERBOSE(("SatisfyPendingReads: completing irp with %xh bytes.", irp->IoStatus.Information));

		/*
		 *  Free the MDL we created for the UserBuffer
		 */
		ASSERT(irp->MdlAddress);
		MmUnlockPages(irp->MdlAddress);
		FREEPOOL(irp->MdlAddress);
		irp->MdlAddress = NULL;

		IoCompleteRequest(irp, IO_NO_INCREMENT);
	}

	while (!IsListEmpty(&readPacketsToFree)){
		listEntry = RemoveHeadList(&readPacketsToFree);
		ASSERT(listEntry);
		readPacket = CONTAINING_RECORD(listEntry, READPACKET, listEntry);
        FreeReadPacket(readPacket);
	}


}


/*
 *  IssueReadForClient
 *
 *		Must be called with exclusive access on the input endpoint held.
 */
VOID IssueReadForClient(POSPDOEXT *pdoExt)
{
	PUCHAR readBuf;
	ULONG readLen;

	DBGVERBOSE(("IssueReadForClient"));

	/*
	 *  We always read the full pipe size.
	 *  
	 *  BUGBUG - pipe info needs to be moved to pdoExt.
	 */
	readLen = pdoExt->inputEndpointInfo.pipeLen;

	readBuf = ALLOCPOOL(NonPagedPool, readLen);
	if (readBuf){
		READPACKET *readPacket;

		RtlZeroMemory(readBuf, readLen);

		readPacket = AllocReadPacket(readBuf, readLen, pdoExt);
		if (readPacket){
			ReadPipe(pdoExt->parentFdoExt, pdoExt->inputEndpointInfo.pipeHandle, readPacket, FALSE);
		}
		else {
			FREEPOOL(readBuf);
			FlushBuffers(pdoExt);
		}
	}
	else {
		ASSERT(readBuf);
		FlushBuffers(pdoExt);
	}

}


VOID WorkItemCallback_Read(PVOID context)
{
	POSPDOEXT *pdoExt = context;
	KIRQL oldIrql;
	BOOLEAN issueReadNow = FALSE;

	DBGVERBOSE(("WorkItemCallback_Read"));

	KeAcquireSpinLock(&pdoExt->devExtSpinLock, &oldIrql);

	if (IsListEmpty(&pdoExt->pendingReadIrpsList)){
		DBGERR(("WorkItemCallback_Read: list is empty ?!"));
	}
	else {
		if (pdoExt->inputEndpointInfo.endpointIsBusy){
			DBGWARN(("WorkItemCallback_Read: endpoint is busy"));
		}
		else {
			pdoExt->inputEndpointInfo.endpointIsBusy = TRUE;
			issueReadNow = TRUE;
		}
	}

	KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);

	if (issueReadNow){
		IssueReadForClient(pdoExt);
	}

}



NTSTATUS EnqueueReadIrp(POSPDOEXT *pdoExt, PIRP irp, BOOLEAN enqueueAtFront, BOOLEAN lockHeld)
{
    PDRIVER_CANCEL oldCancelRoutine;
    NTSTATUS status = STATUS_PENDING;
    KIRQL oldIrql;

    if (!lockHeld) KeAcquireSpinLock(&pdoExt->devExtSpinLock, &oldIrql);

    /*
     *  Enqueue the IRP 
     */
    if (enqueueAtFront){
        InsertHeadList(&pdoExt->pendingReadIrpsList, &irp->Tail.Overlay.ListEntry);
    }
    else {
        InsertTailList(&pdoExt->pendingReadIrpsList, &irp->Tail.Overlay.ListEntry);
    }

    /*
     *  Apply the IoMarkIrpPending macro to indicate that the
     *  irp may complete on a different thread.
     *  The kernel will see this flag set when we complete the IRP and get the IRP
     *  back on the right thread if there was a synchronous client.
     */
    IoMarkIrpPending(irp);

    /*
     *  Must set the cancel routine before checking the cancel flag.
     */
    oldCancelRoutine = IoSetCancelRoutine(irp, ReadCancelRoutine);
    ASSERT(!oldCancelRoutine);

    if (irp->Cancel){
        /*
         *  This IRP was cancelled.  
         *  We need to coordinate with the cancel routine to complete this irp.
         */
        oldCancelRoutine = IoSetCancelRoutine(irp, NULL);
        if (oldCancelRoutine){
            /*
             *  Cancel routine was not called, so dequeue the IRP and return
             *  error so the dispatch routine completes the IRP.
             */
            ASSERT(oldCancelRoutine == ReadCancelRoutine);
            RemoveEntryList(&irp->Tail.Overlay.ListEntry);
            status = STATUS_CANCELLED;
        }
        else {
            /*
             *  Cancel routine was called and it will complete the IRP
             *  as soon as we drop the spinlock.  So don't touch this IRP.
             *  Return PENDING so dispatch routine won't complete the IRP.
             */
        }
    }

    if (!lockHeld) KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);

    return status;
}


PIRP DequeueReadIrp(POSPDOEXT *pdoExt, BOOLEAN lockHeld)
{
    PIRP nextIrp = NULL;
    KIRQL oldIrql;

    if (!lockHeld) KeAcquireSpinLock(&pdoExt->devExtSpinLock, &oldIrql);

    while (!nextIrp && !IsListEmpty(&pdoExt->pendingReadIrpsList)){
        PDRIVER_CANCEL oldCancelRoutine;
        PLIST_ENTRY listEntry = RemoveHeadList(&pdoExt->pendingReadIrpsList);

        nextIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);

        oldCancelRoutine = IoSetCancelRoutine(nextIrp, NULL);

        /*
         *  IoCancelIrp() could have just been called on this IRP.
         *  What we're interested in is not whether IoCancelIrp() was called (nextIrp->Cancel flag set),
         *  but whether IoCancelIrp() called (or is about to call) our cancel routine.
         *  To check that, check the result of the test-and-set macro IoSetCancelRoutine.
         */
        if (oldCancelRoutine){
            /*
             *  Cancel routine not called for this IRP.  Return this IRP.
             */
            ASSERT(oldCancelRoutine == ReadCancelRoutine);
        }
        else {
            /*
             *  This IRP was just cancelled and the cancel routine was (or will be) called.
             *  The cancel routine will complete this IRP as soon as we drop the spinlock.
             *  So don't do anything with the IRP.
             *  Also, the cancel routine will try to dequeue the IRP, 
             *  so make the IRP's listEntry point to itself.
             */
            ASSERT(nextIrp->Cancel);
            InitializeListHead(&nextIrp->Tail.Overlay.ListEntry);
            nextIrp = NULL;
        }
    }

    if (!lockHeld) KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);

    return nextIrp;
}


VOID ReadCancelRoutine(PDEVICE_OBJECT devObj, PIRP irp)
{
	DEVEXT *devExt;
	POSPDOEXT *pdoExt;
	KIRQL oldIrql;

	DBGWARN(("ReadCancelRoutine: devObj=%ph, irp=%ph.", devObj, irp));

	devExt = devObj->DeviceExtension;
	ASSERT(devExt->signature == DEVICE_EXTENSION_SIGNATURE);
	ASSERT(devExt->isPdo);
	pdoExt = &devExt->pdoExt;

	IoReleaseCancelSpinLock(irp->CancelIrql);

	KeAcquireSpinLock(&pdoExt->devExtSpinLock, &oldIrql);

	RemoveEntryList(&irp->Tail.Overlay.ListEntry);

	KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);

    irp->IoStatus.Status = STATUS_CANCELLED;
    IoCompleteRequest(irp, IO_NO_INCREMENT);
}


READPACKET *AllocReadPacket(PVOID data, ULONG dataLen, PVOID context)
{
	READPACKET *readPacket;

	readPacket = ALLOCPOOL(NonPagedPool, sizeof(READPACKET));
	if (readPacket){
		readPacket->signature = READPACKET_SIG;
		readPacket->data = data;
		readPacket->length = dataLen;
		readPacket->offset = 0;
		readPacket->context = context;
		readPacket->urb = BAD_POINTER;
		readPacket->listEntry.Flink = readPacket->listEntry.Blink = BAD_POINTER;
	}
	else {
		ASSERT(readPacket);
	}

	return readPacket;
}

VOID FreeReadPacket(READPACKET *readPacket)
{
    DBGVERBOSE(("Freeing readPacket..."));
    ASSERT(readPacket->signature == READPACKET_SIG);
    FREEPOOL(readPacket->data);
    FREEPOOL(readPacket);
}

⌨️ 快捷键说明

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