亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? write.c

?? 微軟的point of sale的源代碼
?? C
字號:
/*++

Copyright (c) 1999  Microsoft Corporation

Module Name:

    write.c

Abstract: ESC/POS (serial) interface for USB Point-of-Sale devices

Author:

    ervinp

Environment:

    Kernel mode

Revision History:


--*/

#include <WDM.H>

#include <usbdi.h>
#include "usbdlib.h"
#include <usbioctl.h>

#include "escpos.h"
#include "debug.h"




NTSTATUS WriteComPort(POSPDOEXT *pdoExt, PIRP irp)
{
	NTSTATUS status;
	PIO_STACK_LOCATION currentIrpSp;

    /* 
     *  In order to support ODD ENDPOINTs, we check
     *  whether this COM port has a write endpoint or not.
     */
    if(!pdoExt->outputEndpointInfo.pipeHandle) {
        DBGVERBOSE(("This PORT does not have an OUT endpoint - Write request Rejected."));
        return STATUS_NOT_SUPPORTED;
    }

	currentIrpSp = IoGetCurrentIrpStackLocation(irp);

	/*
	 *  Because this pdo's buffering method is METHOD_NEITHER,
	 *  the buffer pointer is irp->UserBuffer, which may be an application address.
	 *  Since we may not be able to send this buffer synchronously on this thread,
	 *  we have to allocate an MDL for it.
	 */
	ASSERT(!irp->MdlAddress);
	ASSERT(currentIrpSp->Parameters.Write.Length);
	irp->MdlAddress = MmCreateMdl(NULL, irp->UserBuffer, currentIrpSp->Parameters.Write.Length);
	if (irp->MdlAddress){
		status = STATUS_SUCCESS;
		__try {
			/*
			 *  We're reading the write data from the buffer, so probe for ReadAccess.
			 */
			MmProbeAndLockPages(irp->MdlAddress, UserMode, IoReadAccess);
		}
		__except(EXCEPTION_EXECUTE_HANDLER) {
			status = GetExceptionCode();
			DBGERR(("MmProbeAndLockPages triggered exception status %xh.", status));
		}
		if (NT_SUCCESS(status)){
			status = TryWrite(pdoExt, irp);
		}
	}
	else {
		DBGERR(("MmCreateMdl failed"));
		status = STATUS_DATA_ERROR;
	}

	return status;
}


NTSTATUS TryWrite(POSPDOEXT *pdoExt, PIRP irp)
{
    NTSTATUS status = STATUS_PENDING;
    BOOLEAN isBusy;
    KIRQL oldIrql;
    BOOLEAN irpWasCancelled = FALSE;


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

    if (pdoExt->outputEndpointInfo.endpointIsBusy){
        /*
         *  Another thread is writing to this endpoint now.
         *  Queue the IRP.
         */
        PDRIVER_CANCEL oldCancelRoutine;

        DBGWARN(("WriteComPort:  endpoint is busy so queuing irp"));
        oldCancelRoutine = IoSetCancelRoutine(irp, WriteCancelRoutine);
        ASSERT(!oldCancelRoutine);
        if (irp->Cancel){
            DBGWARN(("WriteComPort: irp %ph was cancelled.", irp));
            irpWasCancelled = TRUE;
            oldCancelRoutine = IoSetCancelRoutine(irp, NULL);
            if (oldCancelRoutine){
                /*
                 *  Cancel routine was not called, so complete the IRP here.
                 */
                ASSERT(oldCancelRoutine == ReadCancelRoutine);
                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.
                 */
                status = STATUS_PENDING;
            }
        }
        else {
            InsertTailList(&pdoExt->pendingWriteIrpsList, &irp->Tail.Overlay.ListEntry);
        }
        isBusy = TRUE;
    }
    else {
        pdoExt->outputEndpointInfo.endpointIsBusy = TRUE;
        isBusy = FALSE;
    }

    KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);


    if (!isBusy){

        PUCHAR mappedUserBuffer;
        ULONG dataLen;
        ULONG dataWritten = 0;
        PIO_STACK_LOCATION currentIrpSp;
        BOOLEAN callWriteWorkItem = FALSE;

        currentIrpSp = IoGetCurrentIrpStackLocation(irp);

        status = STATUS_SUCCESS;  // in case dataLen = 0

        /*
         *  This function is called from the dispatch routine and also
         *  from a workItem callback.  So we may not be on the calling thread.
         *  Therefore, we cannot use irp->UserBuffer because it may not be
         *  mapped in this context.  Use the MDL we created at call time instead.
         */
        mappedUserBuffer = PosMmGetSystemAddressForMdlSafe(irp->MdlAddress);

        if(mappedUserBuffer) {
            dataLen = currentIrpSp->Parameters.Write.Length;

            while (dataLen){
                ULONG len = MIN(dataLen, pdoExt->outputEndpointInfo.pipeLen);

                DBGVERBOSE(("Writing %xh bytes to pipe.", len));
                status = WritePipe( pdoExt->parentFdoExt, 
                                    pdoExt->outputEndpointInfo.pipeHandle, 
                                    mappedUserBuffer, 
                                    len);
                if (NT_SUCCESS(status)){
                    dataLen -= len;
                    dataWritten += len;
                    mappedUserBuffer += len;
                }
                else {
                    DBGERR(("Write failed with status %xh.", status));
                    break;
                }
            }

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

            irp->IoStatus.Information = dataWritten;

            KeAcquireSpinLock(&pdoExt->devExtSpinLock, &oldIrql);
            pdoExt->outputEndpointInfo.endpointIsBusy = FALSE;
            if (!IsListEmpty(&pdoExt->pendingWriteIrpsList)){
	            callWriteWorkItem = TRUE;;
            }
            KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);

            /*
             *  If there are some writes waiting, schedule a workItem to process them.
             */
            if (callWriteWorkItem){
                ExQueueWorkItem(&pdoExt->writeWorkItem, DelayedWorkQueue);
            }
        }
        else {
            /*
             *  Return STATUS_UNSUCCESSFUL and free the MDL we created for the UserBuffer.
             */
            DBGERR(("PosMmGetSystemAddressForMdlSafe failed"));
            irp->IoStatus.Information = 0;
            status = STATUS_UNSUCCESSFUL;

            ASSERT(irp->MdlAddress);
            MmUnlockPages(irp->MdlAddress);
            FREEPOOL(irp->MdlAddress);
            irp->MdlAddress = NULL;
        }
    }

    return status;
}


VOID WorkItemCallback_Write(PVOID context)
{
	POSPDOEXT *pdoExt = (POSPDOEXT *)context;
	KIRQL oldIrql;
	PIRP irp = NULL;

	DBGVERBOSE(("WorkItemCallback_Write:  pdoExt=%ph ", pdoExt));

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

	if (IsListEmpty(&pdoExt->pendingWriteIrpsList)){
		DBGERR(("WorkItemCallback_Write: list is empty ?!"));
	}
	else {
		while (!irp && !IsListEmpty(&pdoExt->pendingWriteIrpsList)){

			PDRIVER_CANCEL cancelRoutine;
			PLIST_ENTRY listEntry = RemoveHeadList(&pdoExt->pendingWriteIrpsList);

			ASSERT(listEntry);
			irp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
			cancelRoutine = IoSetCancelRoutine(irp, NULL);

			if (cancelRoutine){
				ASSERT(cancelRoutine == WriteCancelRoutine);
			}
			else {
				/*
				 *  This IRP was cancelled and the cancel routine was called.
				 *  The cancel routine will complete this IRP as soon as we drop
				 *  the spinlock, so don't touch the IRP.
				 */
				ASSERT(irp->Cancel);
				DBGWARN(("WorkItemCallback_Write: irp was cancelled"));
				irp = NULL;
			}
		}
	}

	KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);

	if (irp){
		NTSTATUS status = TryWrite(pdoExt, irp);
		if (status != STATUS_PENDING){

			/*
			 *  Set the SL_PENDING in the IRP 
			 *  to indicate that the IRP is completing on a different thread.
			 */
			IoMarkIrpPending(irp);

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


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

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

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

	KeAcquireSpinLock(&pdoExt->devExtSpinLock, &oldIrql);
	RemoveEntryList(&irp->Tail.Overlay.ListEntry);
	KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);

	IoReleaseCancelSpinLock(irp->CancelIrql);

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

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
欧美男男青年gay1069videost| 一区二区三区色| 亚洲日韩欧美一区二区在线| 亚洲成av人片www| 国产98色在线|日韩| 欧美日本国产一区| 中文字幕在线一区免费| 国产麻豆视频精品| 91精品国产91热久久久做人人| 中文字幕在线不卡视频| 国产一区二区三区四区五区美女| 6080国产精品一区二区| 18欧美亚洲精品| 不卡视频在线观看| 国产日韩欧美电影| 国产精品996| 精品国精品自拍自在线| 日韩电影一区二区三区| 欧美片在线播放| 亚洲国产精品嫩草影院| 色呦呦国产精品| 亚洲免费在线视频一区 二区| 成人网男人的天堂| 国产视频不卡一区| 国产老肥熟一区二区三区| 精品久久久久久久久久久久久久久| 午夜影视日本亚洲欧洲精品| 在线观看视频91| 一区二区久久久久久| 在线免费av一区| 夜夜爽夜夜爽精品视频| 欧美在线影院一区二区| 亚洲精品乱码久久久久久黑人| 91女人视频在线观看| 亚洲欧美日韩国产另类专区 | 国产精品久久久久久久久搜平片| 国产精品综合久久| 久久久亚洲精品石原莉奈| 国产精品一区二区三区乱码| 欧美国产日韩精品免费观看| 成人h精品动漫一区二区三区| 国产精品人人做人人爽人人添| 成人app在线| 亚洲在线视频网站| 在线电影一区二区三区| 蜜桃视频一区二区三区在线观看 | 久久久欧美精品sm网站| 久久精品国产一区二区三区免费看| 日韩精品专区在线| 国产一区二区电影| 亚洲人成网站精品片在线观看| 91色porny在线视频| 亚洲国产三级在线| 精品免费视频.| 99久久99久久精品国产片果冻| 亚洲午夜在线电影| 欧美成人一区二区三区在线观看| 国产高清久久久| 亚洲免费在线电影| 欧美电影免费观看高清完整版在线观看| 久久国产麻豆精品| 国产精品短视频| 欧美日韩另类一区| 国产成人免费视频 | 中文字幕高清不卡| 欧美久久久久久蜜桃| 国产一区二区视频在线| 亚洲乱码一区二区三区在线观看| 欧美美女一区二区在线观看| 国产精品白丝av| 午夜欧美一区二区三区在线播放| 精品国产电影一区二区| 欧美在线观看视频一区二区三区| 久久国产尿小便嘘嘘尿| 亚洲自拍另类综合| 精品国产乱码久久| 欧美日韩一区二区在线观看| 国产在线看一区| 亚洲chinese男男1069| 国产日韩在线不卡| 日韩一区二区中文字幕| 色综合久久综合中文综合网| 国产一区免费电影| 日本不卡高清视频| 一区二区三区在线播| 中文字幕乱码久久午夜不卡| 91精品在线观看入口| 色吊一区二区三区| 国产传媒一区在线| 久久99精品国产91久久来源| 亚洲高清免费在线| 亚洲欧洲精品一区二区三区 | 风间由美中文字幕在线看视频国产欧美 | 欧美一区二区三区的| 在线观看www91| 99久久婷婷国产综合精品电影| 老司机精品视频在线| 日韩精品一二三区| 亚洲一区二区成人在线观看| 国产精品的网站| 中文字幕+乱码+中文字幕一区| 日韩免费观看高清完整版| 欧美精品一二三区| 91激情五月电影| 91美女精品福利| 91麻豆福利精品推荐| 99视频精品全部免费在线| 成人免费毛片嘿嘿连载视频| 国产成人亚洲精品青草天美| caoporm超碰国产精品| 大桥未久av一区二区三区中文| 国产一区二区三区美女| 狠狠久久亚洲欧美| 国产精品69毛片高清亚洲| 国产在线一区观看| 国产成人在线看| 国产·精品毛片| heyzo一本久久综合| 99麻豆久久久国产精品免费| 波多野洁衣一区| 91福利在线观看| 欧美日韩国产中文| 精品少妇一区二区三区在线播放| 日韩午夜精品电影| 久久综合色综合88| 日本一区二区三区四区 | 成人性色生活片| 粗大黑人巨茎大战欧美成人| 成人综合婷婷国产精品久久免费| 成人午夜电影网站| 一本在线高清不卡dvd| 欧美日韩在线直播| 精品久久五月天| 欧美激情中文字幕一区二区| 中文字幕一区二区三中文字幕 | 欧美激情一区在线| 一区二区三国产精华液| 日av在线不卡| 成人毛片老司机大片| 色八戒一区二区三区| 555www色欧美视频| 国产日韩欧美一区二区三区乱码 | 日韩精品一二区| 国产91精品免费| 欧美视频在线不卡| 久久亚洲二区三区| 亚洲一区av在线| 久久99国产乱子伦精品免费| av毛片久久久久**hd| 欧美一区二区视频网站| 亚洲国产高清aⅴ视频| 亚洲成人免费视频| 大陆成人av片| 欧美成人在线直播| 亚洲自拍欧美精品| 成人免费观看视频| 日韩精品最新网址| 亚洲一区二区3| 国产成人精品aa毛片| 在线电影一区二区三区| 自拍偷拍欧美激情| 激情五月婷婷综合网| 欧美丝袜丝交足nylons| 国产婷婷一区二区| 蜜臀久久99精品久久久久宅男| 成人美女视频在线看| 日韩精品一区二区三区在线 | 欧美熟乱第一页| 国产精品成人午夜| 国产一区二区免费在线| 欧美日韩国产一二三| 亚洲视频在线观看一区| 国产一区二区视频在线| 欧美一区二区在线看| 亚洲一区二区视频在线观看| 东方aⅴ免费观看久久av| 日韩一区二区三| 午夜精品免费在线| 色老汉一区二区三区| 中文字幕亚洲区| 风间由美性色一区二区三区| 精品国精品自拍自在线| 免费精品视频在线| 欧美一区在线视频| 男男成人高潮片免费网站| 欧美日韩一区 二区 三区 久久精品 | 欧美tickling挠脚心丨vk| 性感美女极品91精品| 欧美性生活大片视频| 伊人夜夜躁av伊人久久| 91网上在线视频| 综合自拍亚洲综合图不卡区| 国产91综合网| 国产欧美综合在线| 国产大片一区二区| 国产精品久久看| 99热精品一区二区| 国产精品激情偷乱一区二区∴| 成人黄色av电影| 中文字幕欧美一|