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

📄 vcom_device.c

📁 一个虚拟串口的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	KeInitializeSemaphore(&pDeviceExtension->writeIRPQueueSemaphore, 0, MAXLONG);
		
	KeInitializeTimerEx(&pDeviceExtension->readTotalTimer, SynchronizationTimer);
	KeInitializeTimerEx(&pDeviceExtension->readIntervalTimer, SynchronizationTimer);
	KeInitializeTimerEx(&pDeviceExtension->writeTotalTimer, SynchronizationTimer);
	
	KeInitializeEvent(&pDeviceExtension->transferNeededEvent, SynchronizationEvent, FALSE);
	KeInitializeEvent(&pDeviceExtension->transferOccurredEvent, SynchronizationEvent, FALSE);
	KeInitializeEvent(&pDeviceExtension->readOccurredEvent, SynchronizationEvent, FALSE);
	KeInitializeEvent(&pDeviceExtension->currentReadIrpWasCancelledEvent, SynchronizationEvent, FALSE);
	KeInitializeEvent(&pDeviceExtension->currentWriteIrpWasCancelledEvent, SynchronizationEvent, FALSE);
	
	InitializeListHead(&pDeviceExtension->readPendingQueue);
	InitializeListHead(&pDeviceExtension->writePendingQueue);

	IoCsqInitialize (&pDeviceExtension->cancelSafeReadQueue,
		                     vCOMInsertReadIrp,
		                     vCOMRemoveReadIrp,
		                     vCOMPeekNextReadIrp,
		                     vCOMAcquireReadLock,
		                     vCOMReleaseReadLock,
		                     vCOMCompleteCanceledReadIrp );

	IoCsqInitialize (&pDeviceExtension->cancelSafeWriteQueue,
		                     vCOMInsertWriteIrp,
		                     vCOMRemoveWriteIrp,
		                     vCOMPeekNextWriteIrp,
		                     vCOMAcquireWriteLock,
		                     vCOMReleaseWriteLock,
		                     vCOMCompleteCanceledWriteIrp );
	
	KdPrint(("Device %d created\n", devNumber));

	return STATUS_SUCCESS;
		
}

VOID vCOMDeleteFailedDevice(PDEVICE_OBJECT pFDO, ULONG devNumber)
{
	PvCOM_DEVICE_EXTENSION 	pDeviceExtension = pFDO->DeviceExtension;
	UNICODE_STRING          		ntDeviceName;

	vCOMTransferThreadStop(pFDO);
	vCOMReadThreadStop(pFDO);
	vCOMWriteThreadStop(pFDO);
	
	pDeviceExtension->isOpened = FALSE;
	pDeviceExtension->isRemoved = TRUE;	

	if (pDeviceExtension->symbolicLinkIsDone)
		IoDeleteSymbolicLink(&pDeviceExtension->symbolicLinkName);	

	if (pDeviceExtension->symbolicLinkName.Buffer != NULL)
		ExFreePool(pDeviceExtension->symbolicLinkName.Buffer);	

	if ((pDeviceExtension->isSet == TRUE) && (pDeviceExtension->deviceNumber == 0))
		IoSetDeviceInterfaceState(&pDeviceExtension->interfaceName, FALSE);
	
	if (pDeviceExtension->interfaceName.Buffer != NULL)
	{		
		ExFreePool(pDeviceExtension->interfaceName.Buffer);
	}	

	if (pDeviceExtension->deviceMapEntryIsCreated)
	{
		RtlInitUnicodeString(&ntDeviceName, vCOMDevNames[devNumber]);
		RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP, ntDeviceName.Buffer);
	}
		
	if (pDeviceExtension->isAttached && devNumber == 0)
		IoDetachDevice(pDeviceExtension->pNextDriver);
	
	if (pFDO != NULL)
		IoDeleteDevice(pFDO);
}

VOID vCOMDeleteDevice(PDEVICE_OBJECT pFDO)
{
	PvCOM_DEVICE_EXTENSION		pCurrentDeviceExtension; 
	UNICODE_STRING          		ntDeviceName;	
	ULONG						i;
	
	for (i=0; i < MAX_PAIR_COUNT * 2; i++)
	{
		KdPrint(("Deleting device %d\n", i));
		
		if (pDevices[i] == NULL)
		{
			KdPrint(("pDevices %d was NULL - break...\n", i));
			break;
		}
		
		pCurrentDeviceExtension = pDevices[i]->DeviceExtension;

		if (pCurrentDeviceExtension == NULL)
		{
			KdPrint(("pCurrentDeviceExtension %d was NULL - break...\n", i));
			break;
		}			

		KdPrint(("Stopping Threads for %d \n", i));
		
		vCOMTransferThreadStop(pCurrentDeviceExtension->pMe);	
		vCOMReadThreadStop(pCurrentDeviceExtension->pMe);
		vCOMWriteThreadStop(pCurrentDeviceExtension->pMe);
				
		pCurrentDeviceExtension->isOpened = FALSE;
				
		pCurrentDeviceExtension->isRemoved = TRUE;
				
		if (pCurrentDeviceExtension->symbolicLinkIsDone)
			IoDeleteSymbolicLink(&pCurrentDeviceExtension->symbolicLinkName);
		
		if (pCurrentDeviceExtension->symbolicLinkName.Buffer != NULL)
			ExFreePool(pCurrentDeviceExtension->symbolicLinkName.Buffer);		

		if ((pCurrentDeviceExtension->isSet == TRUE) && (pCurrentDeviceExtension->deviceNumber == 0))
			IoSetDeviceInterfaceState(&pCurrentDeviceExtension->interfaceName, FALSE);
		
		if (pCurrentDeviceExtension->interfaceName.Buffer != NULL)
		{
			ExFreePool(pCurrentDeviceExtension->interfaceName.Buffer);
		}
				
		if (pCurrentDeviceExtension->deviceMapEntryIsCreated)
		{
			RtlInitUnicodeString(&ntDeviceName, vCOMDevNames[i]);
			RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP, ntDeviceName.Buffer);
		}
				
		KeCancelTimer(&pCurrentDeviceExtension->readIntervalTimer);
		KeCancelTimer(&pCurrentDeviceExtension->readTotalTimer);
		KeCancelTimer(&pCurrentDeviceExtension->writeTotalTimer);
		
	}	

	KdPrint(("IoDetachDevice device 0\n"));
	
	pCurrentDeviceExtension = pFDO->DeviceExtension;

	if ((pCurrentDeviceExtension->isAttached == TRUE) & (pCurrentDeviceExtension->deviceNumber == 0))
			IoDetachDevice(pCurrentDeviceExtension->pNextDriver);
	
	for (i=1; i<MAX_PAIR_COUNT * 2; i++)
	{
		if (pDevices[i] != NULL)
		{
			IoDeleteDevice(pDevices[i]);
			pDevices[i] = NULL;
			KdPrint(("IoDeleteDevice for device %d\n", i));
		}
		else
		{
			KdPrint(("IoDeleteDevice pDevices %d was NULL - break...\n", i));
			break;
		}
	}		

	KdPrint(("IoDeleteDevice for device 0\n"));
	
	if (pFDO != NULL)
			IoDeleteDevice(pFDO);
	
}

NTSTATUS vCOMCreateDevice(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
	NTSTATUS 					status;
	PvCOM_DEVICE_EXTENSION 	pDeviceExtension;

	pDeviceExtension = DeviceObject->DeviceExtension;
	
	if ((IoGetCurrentIrpStackLocation(pIrp)->Parameters.Create.Options & FILE_DIRECTORY_FILE) != 0)
		status = STATUS_NOT_A_DIRECTORY;
	else
	{
			ExAcquireFastMutex(&pDeviceExtension->openMutex);

		if (pDeviceExtension->isOpened)
		{
			status = STATUS_ACCESS_DENIED;
			ExReleaseFastMutex(&pDeviceExtension->openMutex);
		}
		else
		{
			pDeviceExtension->eventMask = 0;
			pDeviceExtension->eventHistory = 0;
			pDeviceExtension->isOpened = TRUE;
						
			ExReleaseFastMutex(&pDeviceExtension->openMutex);

			status = STATUS_SUCCESS;
		}
	}

	KdPrint(("Creating File device %d done...", pDeviceExtension->deviceNumber));	
	
	return vCOMCompleteRequest(pIrp, status, 0);
		
}

NTSTATUS vCOMCloseDevice(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
	NTSTATUS 					status;
	PvCOM_DEVICE_EXTENSION 	pDeviceExtension;

	pDeviceExtension = DeviceObject->DeviceExtension;

	pDeviceExtension->isOpened = FALSE;	
	
	KdPrint(("Closing File device %d done...", pDeviceExtension->deviceNumber));
	
	return vCOMCompleteRequest(pIrp, STATUS_SUCCESS, 0);
	
}

NTSTATUS vCOMReadDevice(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
	PvCOM_DEVICE_EXTENSION 	pDeviceExtension;
    			
	pDeviceExtension = DeviceObject->DeviceExtension;    	

	//this is a fix to make the driver work with MSCOMM in return with any mode
	//see http://support.microsoft.com/default.aspx?scid=kb;en-us;318784
	//driver mode is TIMEOUTS_IMMEDIATE_RETURN_WITH_BYTES
	if (vCOMFastRead(DeviceObject, pIrp) == STATUS_SUCCESS)
	{
		pIrp->IoStatus.Status = STATUS_SUCCESS;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);	
		return STATUS_SUCCESS;
	}
	else
	{
		IoCsqInsertIrp(&pDeviceExtension->cancelSafeReadQueue, pIrp, NULL);
		KeReleaseSemaphore(&pDeviceExtension->readIRPQueueSemaphore, 0, 1, FALSE);	
		return STATUS_PENDING;
	}		
	
}

NTSTATUS vCOMFastRead(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
	PvCOM_DEVICE_EXTENSION 	pDeviceExtension;
	PvCOM_DEVICE_EXTENSION 	pTwinDeviceExtension;
    	PIO_STACK_LOCATION  		pIrpStackLocation;
	KIRQL 						read_oldIrql;
	ULONG 						bufferLength;
    	PCHAR 						pBuffer;
	
	pDeviceExtension = DeviceObject->DeviceExtension; 
	pTwinDeviceExtension = pDeviceExtension->pTwin->DeviceExtension;
	
	pIrpStackLocation = IoGetCurrentIrpStackLocation(pIrp);
	pBuffer = pIrp->AssociatedIrp.SystemBuffer;		
	bufferLength = pIrpStackLocation->Parameters.Read.Length;

	if (bufferLength == 0)
		return STATUS_SUCCESS;
		
	if (pDeviceExtension->outBufferCount >= bufferLength || pDeviceExtension->fastRead)
	{				
		pDeviceExtension->readBufferCount = 0;

		KeAcquireSpinLock(&pDeviceExtension->readSpinLock, &read_oldIrql);
			
		while (pDeviceExtension->outBufferCount)
		{
			pBuffer[pDeviceExtension->readBufferCount] = pDeviceExtension->outBuffer[pDeviceExtension->outBufferReadPosition];
			pDeviceExtension->readBufferCount++;
			pDeviceExtension->outBufferReadPosition++;
			pDeviceExtension->outBufferCount--;
			if (pDeviceExtension->readBufferCount >= bufferLength)
				break;
		}

		if (pDeviceExtension->outBufferCount <= 0)
		{
			pDeviceExtension->outBufferCount = 0;
			pDeviceExtension->outBufferReadPosition = 0;
			pDeviceExtension->outBufferWritePosition = 0;			
		}
		
		KeReleaseSpinLock(&pDeviceExtension->readSpinLock, read_oldIrql);				

		pIrp->IoStatus.Information = pDeviceExtension->readBufferCount;
		
		KeSetEvent(&pTwinDeviceExtension->readOccurredEvent, 0, FALSE);
		
		return STATUS_SUCCESS;
		
	}
	else
	{		
		return STATUS_PENDING;
	}	
	
}

NTSTATUS vCOMWriteDevice(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
	PvCOM_DEVICE_EXTENSION 	pDeviceExtension;
    	PIO_STACK_LOCATION 		pIrpStackLocation;
    			
	pDeviceExtension = DeviceObject->DeviceExtension;

	if (vCOMFastWrite(DeviceObject, pIrp) == STATUS_SUCCESS)
	{
		pIrp->IoStatus.Status = STATUS_SUCCESS;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);	
		return STATUS_SUCCESS;
	}
	else
	{
		IoCsqInsertIrp(&pDeviceExtension->cancelSafeWriteQueue, pIrp, NULL);
		KeReleaseSemaphore(&pDeviceExtension->writeIRPQueueSemaphore, 0, 1, FALSE);
		return STATUS_PENDING;
	}	
}

NTSTATUS vCOMFastWrite(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
	PvCOM_DEVICE_EXTENSION 	pDeviceExtension =  DeviceObject->DeviceExtension;
	PvCOM_DEVICE_EXTENSION 	pTwinDeviceExtension = pDeviceExtension->pTwin->DeviceExtension;
	PIO_STACK_LOCATION 		pIrpStackLocation;
    	KIRQL 						write_oldIrql;
	KIRQL 						read_oldIrql;
    	ULONG 						dataLength = 0;
    	PCHAR 						pData = NULL;
    	ULONG 						count = 0;	
	
	pIrpStackLocation = IoGetCurrentIrpStackLocation(pIrp); 
	dataLength = pIrpStackLocation->Parameters.Read.Length;
	pData = pIrp->AssociatedIrp.SystemBuffer;

	if (dataLength == 0)
		return STATUS_SUCCESS;
		
	if ((pDeviceExtension->inBufferSize - pDeviceExtension->inBufferCount) >= dataLength) //room in buffer
	{
		KeAcquireSpinLock(&pDeviceExtension->writeSpinLock, &write_oldIrql);
		
		if (pDeviceExtension->inBufferCount == 0)
		{
			pDeviceExtension->inBufferWritePosition = 0;
			pDeviceExtension->inBufferReadPosition = 0;
		}
	
		for (count = 0; count < dataLength; count++)
		{
			pDeviceExtension->inBuffer[pDeviceExtension->inBufferWritePosition] = pData[count];
			pDeviceExtension->inBufferWritePosition++;
			pDeviceExtension->inBufferCount++;
			if (pDeviceExtension->inBufferCount >= pDeviceExtension->inBufferSize)
				break;
		}
						
		KeReleaseSpinLock(&pDeviceExtension->writeSpinLock, write_oldIrql);

		pIrp->IoStatus.Information = count;
		
		vCOMCheckComEvents(pDeviceExtension, SERIAL_EV_TXEMPTY);

		if (vCOMFastTransfer(DeviceObject, pIrp) == STATUS_PENDING)
			KeSetEvent(&pDeviceExtension->transferNeededEvent, 8, FALSE);

		return STATUS_SUCCESS;
		
	}
	else //not enough room
	{
		return STATUS_PENDING;
	}		
}

NTSTATUS vCOMFastTransfer(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
	PvCOM_DEVICE_EXTENSION 	pDeviceExtension =  DeviceObject->DeviceExtension;
	PvCOM_DEVICE_EXTENSION 	pTwinDeviceExtension = pDeviceExtension->pTwin->DeviceExtension;
    	KIRQL                       			oldIrql;
	ULONG                       			count;
	ULONG						events;
	UCHAR						byte = 0;
	BOOLEAN						eventCharRcvd = FALSE;
	KIRQL 						read_oldIrql;
	KIRQL 						write_oldIrql;
	
	eventCharRcvd = FALSE;
			
	if ((pTwinDeviceExtension->outBufferSize - pTwinDeviceExtension->outBufferCount) < pDeviceExtension->inBufferCount)
	{
		return STATUS_PENDING;
	}
	else
	{
		KeAcquireSpinLock(&pDeviceExtension->writeSpinLock, &write_oldIrql);
		
		for (count = 0; count < pDeviceExtension->inBufferCount; count++)
		{
			byte = pDeviceExtension->inBuffer[pDeviceExtension->inBufferReadPosition];
			if (byte == pTwinDeviceExtension->serEventCharacter)
				eventCharRcvd = TRUE;
			pTwinDeviceExtension->outBuffer[pTwinDeviceExtension->outBufferWritePosition] = byte;			
			pTwinDeviceExtension->outBufferWritePosition++;
			pDeviceExtension->inBufferReadPosition++;

⌨️ 快捷键说明

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