📄 vcom_device.c
字号:
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 + -