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

📄 comport.c

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

NTSTATUS QueryInfo(POSPDOEXT *pdoExt, PIRP irp)
{
	NTSTATUS status;
	PIO_STACK_LOCATION irpSp;

	irpSp = IoGetCurrentIrpStackLocation(irp);

	switch (irpSp->Parameters.QueryFile.FileInformationClass){

		case FileBasicInformation:
			DBGVERBOSE(("  QueryInfo: FileBasicInformation"));
			{
				PFILE_BASIC_INFORMATION basicInfoBuf = irp->AssociatedIrp.SystemBuffer;
				ASSERT(basicInfoBuf);
				RtlCopyMemory(basicInfoBuf, &pdoExt->fileBasicInfo, sizeof(FILE_BASIC_INFORMATION));
				irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION);
				status = STATUS_SUCCESS;
			}
			break;

		case FileStandardInformation:
			DBGVERBOSE(("  QueryInfo: FileStandardInformation"));
			{
				PFILE_STANDARD_INFORMATION stdInfoBuf = irp->AssociatedIrp.SystemBuffer;
				ASSERT(stdInfoBuf);
				stdInfoBuf->AllocationSize.QuadPart = 0;
				stdInfoBuf->EndOfFile = stdInfoBuf->AllocationSize;
				stdInfoBuf->NumberOfLinks = 0;
				stdInfoBuf->DeletePending = FALSE;
				stdInfoBuf->Directory = FALSE;
				irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
				status = STATUS_SUCCESS;
			}
			break;

		case FilePositionInformation:
			DBGVERBOSE(("  QueryInfo: FilePositionInformation"));
			/*
			 *  Always return position 0
			 */
			((PFILE_POSITION_INFORMATION)irp->AssociatedIrp.SystemBuffer)->CurrentByteOffset.QuadPart = 0;
			irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
			status = STATUS_SUCCESS;
			break;

		case FileEndOfFileInformation:
			DBGWARN(("  QueryInfo: FileEndOfFileInformation"));
			irp->IoStatus.Information = 0;
			status = STATUS_INVALID_PARAMETER;
			break;

		default:
			DBGWARN(("  QueryInfo: ??? (%xh)", (ULONG)irpSp->Parameters.QueryFile.FileInformationClass));
			irp->IoStatus.Information = 0;
			status = STATUS_INVALID_PARAMETER;
			break;

	}


	return status;
}

NTSTATUS SetInfo(POSPDOEXT *pdoExt, PIRP irp)
{
	NTSTATUS status;
	PIO_STACK_LOCATION irpSp;

	irpSp = IoGetCurrentIrpStackLocation(irp);

	switch (irpSp->Parameters.SetFile.FileInformationClass){

		case FileBasicInformation:
			DBGVERBOSE(("  SetInfo: FileBasicInformation"));
			{
				PFILE_BASIC_INFORMATION basicInfoBuf = irp->AssociatedIrp.SystemBuffer;
				ASSERT(basicInfoBuf);
				RtlCopyMemory(&pdoExt->fileBasicInfo, basicInfoBuf, sizeof(FILE_BASIC_INFORMATION));
				irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION);
				status = STATUS_SUCCESS;
			}
			break;

		case FileEndOfFileInformation:
			DBGVERBOSE(("  SetInfo: FileEndOfFileInformation"));
			irp->IoStatus.Information = 0;
			status = STATUS_SUCCESS;
			break;

		#define FileAllocationInformation 19  // BUGBUG - defined in ntioapi.h
		case FileAllocationInformation:
			DBGVERBOSE(("  SetInfo: FileAllocationInformation"));
			irp->IoStatus.Information = 0;
			status = STATUS_SUCCESS;
			break;

		default:
			DBGWARN(("  SetInfo: ??? (%xh)", (ULONG)irpSp->Parameters.SetFile.FileInformationClass));
			irp->IoStatus.Information = 0;
			status = STATUS_INVALID_PARAMETER;
			break;
	}

	return status;
}



NTSTATUS FlushBuffers(POSPDOEXT *pdoExt)
{
    LIST_ENTRY irpsToCompleteList;
    PLIST_ENTRY listEntry;
    PIRP irp;
    KIRQL oldIrql;
    NTSTATUS status = STATUS_SUCCESS;

    DBGVERBOSE(("FlushBuffers"));

    /*
     *  This is so we don't loop forever if they get re-queued on the same thread.
     */
    InitializeListHead(&irpsToCompleteList);

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

    /*
     *  Flush all pending Read and Wait Irps (if serial emulation feature is ON)
     */
    while (irp = DequeueReadIrp(pdoExt, TRUE)){
        InsertTailList(&irpsToCompleteList, &irp->Tail.Overlay.ListEntry);
    }

    if (pdoExt->parentFdoExt->posFlag & SERIAL_EMULATION) {
        while (irp = DequeueWaitIrp(pdoExt)){
            InsertTailList(&irpsToCompleteList, &irp->Tail.Overlay.ListEntry);
        }
    }

    /*
     *  Empty out the queued readPackets.  
     *  It's ok to free locked memory with the spinlock held.
     */
    while (!IsListEmpty(&pdoExt->completedReadPacketsList)){
        READPACKET *readPacket;

	    listEntry = RemoveHeadList(&pdoExt->completedReadPacketsList);
	    ASSERT(listEntry);
	    readPacket = CONTAINING_RECORD(listEntry, READPACKET, listEntry);
        FreeReadPacket(readPacket);
    }

    KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);

    while (!IsListEmpty(&irpsToCompleteList)) {
        listEntry = RemoveHeadList(&irpsToCompleteList);
        ASSERT(listEntry);
        irp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
        irp->IoStatus.Information = 0;
        irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
    }

    return status;
}



NTSTATUS InternalIoctl(POSPDOEXT *pdoExt, PIRP irp)
{
	NTSTATUS status;
	PIO_STACK_LOCATION irpSp;

	irpSp = IoGetCurrentIrpStackLocation(irp);

	switch (irpSp->Parameters.DeviceIoControl.IoControlCode){

		// BUGBUG FINISH

		default:
			DBGVERBOSE(("InternalIoctl: ??? (%xh)", (ULONG)irpSp->Parameters.DeviceIoControl.IoControlCode));
			status = irp->IoStatus.Status;
			break;
	}

	return status;
}



LONG GetComPort(PARENTFDOEXT *parentFdoExt, ULONG comInterfaceIndex)
/*++

Routine Description:

    Get the serial COM port index for a serial interface we're about to create.
    If this is not the first plug-in, it should be sitting in the registry.
    If this is the first plug-in, call GetFreeComPortNumber to reserve a new
    static COM port for this device and store it in our software key.

Arguments:


Return Value:

    Return COM port number or -1 if unsuccessful.

--*/
{
    LONG comNumber = -1;
    NTSTATUS status;
    HANDLE hRegDevice;

    status = IoOpenDeviceRegistryKey(   parentFdoExt->physicalDevObj, 
                                        PLUGPLAY_REGKEY_DEVICE, 
                                        KEY_READ, 
                                        &hRegDevice);
    if (NT_SUCCESS(status)){
        UNICODE_STRING keyName;
        PKEY_VALUE_FULL_INFORMATION keyValueInfo;
        ULONG keyValueTotalSize, actualLength;
        WCHAR interfaceKeyName[] = L"COMPortForInterfaceXXXX";

        NumToHexString( interfaceKeyName+sizeof(interfaceKeyName)/sizeof(WCHAR)-1-4, 
                        (USHORT)comInterfaceIndex, 
                        4);

        RtlInitUnicodeString(&keyName, interfaceKeyName); 
        keyValueTotalSize = sizeof(KEY_VALUE_FULL_INFORMATION) +
                            keyName.Length*sizeof(WCHAR) +
                            sizeof(ULONG);
        keyValueInfo = ALLOCPOOL(PagedPool, keyValueTotalSize);
        if (keyValueInfo){
            status = ZwQueryValueKey(   hRegDevice,
                                        &keyName,
                                        KeyValueFullInformation,
                                        keyValueInfo,
                                        keyValueTotalSize,
                                        &actualLength); 
            if (NT_SUCCESS(status)){

                ASSERT(keyValueInfo->Type == REG_DWORD);
                ASSERT(keyValueInfo->DataLength == sizeof(ULONG));
                                
                comNumber = (LONG)*((PULONG)(((PCHAR)keyValueInfo)+keyValueInfo->DataOffset));
                DBGVERBOSE(("GetComPort: read comport #%xh for interface %xh from registry.", (ULONG)comNumber, comInterfaceIndex));
            }
            else {

                /*
                 *  No COM port number recorded in registry.
                 *  Allocate a new static COM port from the COM name arbiter
                 *  and record it in our software key for the next PnP.
                 */
                comNumber = GetFreeComPortNumber();
                if (comNumber == -1){
                    DBGERR(("GetComPort: GetFreeComPortNumber failed"));
                }
                else {
                    status = ZwSetValueKey( hRegDevice,
                                            &keyName,
                                            0,
                                            REG_DWORD,
                                            &comNumber,
                                            sizeof(ULONG));
                    if (!NT_SUCCESS(status)){
                        DBGERR(("GetComPort: ZwSetValueKey failed with status %xh.", status));
                    }
                }
            }

            FREEPOOL(keyValueInfo);
        }
        else {
            ASSERT(keyValueInfo);
        }

        ZwClose(hRegDevice);
    }
    else {
        DBGERR(("GetComPort: IoOpenDeviceRegistryKey failed with %xh.", status));
    }


    return comNumber;
}




LONG GetFreeComPortNumber()
/*++

Routine Description:

    Find the index of the next unused serial COM port name in the system
    (e.g. COM3, COM4, etc).

Arguments:


Return Value:

    Return COM port number or -1 if unsuccessful.

--*/

{
	LONG comNumber = -1;


    if (isWin9x){
        /*
         *  Windows 98
         *      Find the first unused name under Hardware\DeviceMap\SerialComm.
         *
         *
         *      BUGBUG:
         *          This algorithm does not find all the COM ports reserved
         *          by modems.  May want to port tomgreen's AllocateCommPort
         *          function from \faulty\Wdm10\usb\driver\ccport\utils.c
         */
	    HANDLE hKey;
	    UNICODE_STRING keyName;
	    NTSTATUS status;
	    OBJECT_ATTRIBUTES objectAttributes;

	    RtlInitUnicodeString(&keyName, L"\\Registry\\Machine\\Hardware\\DeviceMap\\SerialComm");
	    InitializeObjectAttributes( &objectAttributes,
								    &keyName,
								    OBJ_CASE_INSENSITIVE,
								    NULL,				
								    (PSECURITY_DESCRIPTOR)NULL);

	    status = ZwOpenKey(&hKey, KEY_QUERY_VALUE | KEY_SET_VALUE, &objectAttributes);
	    if (NT_SUCCESS(status)){
            #define MAX_COMPORT_NAME_LEN (sizeof("COMxxxx")-1)
            UCHAR keyValueBytes[sizeof(KEY_VALUE_FULL_INFORMATION)+(MAX_COMPORT_NAME_LEN+1)*sizeof(WCHAR)+sizeof(ULONG)];
            PKEY_VALUE_FULL_INFORMATION keyValueInfo = (PKEY_VALUE_FULL_INFORMATION)keyValueBytes;
            ULONG i, actualLen;
            ULONG keyIndex = 0;

            /*
             *  This bitmask represents the used COM ports.
             *  Bit i set indicates com port i+1 is reserved.
             *  Initialize with COM1 and COM2 reserved.
             *
             *  BUGBUG - only works for up to 32 ports.
             */
            ULONG comNameMask = 3;

            do {
                status = ZwEnumerateValueKey(
                            hKey,
                            keyIndex++,
                            KeyValueFullInformation,
                            keyValueInfo,
                            sizeof(keyValueBytes),
                            &actualLen); 
                if (NT_SUCCESS(status)){
                    if (keyValueInfo->Type == REG_SZ){
                        PWCHAR valuePtr = (PWCHAR)(((PCHAR)keyValueInfo)+keyValueInfo->DataOffset);
                        if (!WStrNCmpI(valuePtr, L"COM", 3)){
                            /*
                             *  valuePtr+3 points the index portion of the COMx string,
                             *  but we can't call LAtoD on it because it is
                             *  NOT NULL-TERMINATED.
                             *  So copy the index into our own buffer, 
                             *  null-terminate that, 
                             *  and call LAtoD to get the numerical index.

⌨️ 快捷键说明

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