📄 init.c
字号:
DbgPrint("ABORTING UsbCom_Create\n");
goto done;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Create a buffer for the RX data when no reads are outstanding.
//
deviceExtension->InterruptReadBuffer = NULL;
deviceExtension->BufferSize = 0;
switch (MmQuerySystemSize()) {
case MmLargeSystem: {
deviceExtension->BufferSize = 4096;
deviceExtension->InterruptReadBuffer = ExAllocatePool(
NonPagedPool,
deviceExtension->BufferSize
);
if (deviceExtension->InterruptReadBuffer) {
break;
}
}
case MmMediumSystem: {
deviceExtension->BufferSize = 1024;
deviceExtension->InterruptReadBuffer = ExAllocatePool(
NonPagedPool,
deviceExtension->BufferSize
);
if (deviceExtension->InterruptReadBuffer) {
break;
}
}
case MmSmallSystem: {
deviceExtension->BufferSize = 128;
deviceExtension->InterruptReadBuffer = ExAllocatePool(
NonPagedPool,
deviceExtension->BufferSize
);
}
}
//DbgPrint("Interrupt buffer size is %d\n", deviceExtension->BufferSize);
if (!deviceExtension->InterruptReadBuffer) {
ExReleaseFastMutex(&deviceExtension->OpenMutex);
deviceExtension->BufferSize = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
SerialDump(
SERIRPPATH,
("SERIAL: Complete Irp: %x\n",Irp)
);
InterlockedDecrement(&deviceExtension->OpenCount);
SerialCompleteRequest(deviceExtension, Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Ok, it looks like we really are going to open. Lock down the
// driver.
//
// SerialLockPagableSectionByHandle(SerialGlobals.PAGESER_Handle); henry
//
// Power up the stack
//
// (void)SerialGotoPowerState(DeviceObject, deviceExtension, PowerDeviceD0); henry
//
// Not currently waiting for wake up
//
deviceExtension->SendWaitWake = FALSE;
//
// On a new open we "flush" the read queue by initializing the
// count of characters.
//
deviceExtension->CharsInInterruptBuffer = 0;
deviceExtension->LastCharSlot = deviceExtension->InterruptReadBuffer +
(deviceExtension->BufferSize - 1);
deviceExtension->ReadBufferBase = deviceExtension->InterruptReadBuffer;
deviceExtension->CurrentCharSlot = deviceExtension->InterruptReadBuffer;
deviceExtension->FirstReadableChar = deviceExtension->InterruptReadBuffer;
deviceExtension->TotalCharsQueued = 0;
//
// We set up the default xon/xoff limits.
//
deviceExtension->HandFlow.XoffLimit = deviceExtension->BufferSize >> 3;
deviceExtension->HandFlow.XonLimit = deviceExtension->BufferSize >> 1;
deviceExtension->WmiCommData.XoffXmitThreshold = deviceExtension->HandFlow.XoffLimit;
deviceExtension->WmiCommData.XonXmitThreshold = deviceExtension->HandFlow.XonLimit;
deviceExtension->BufferSizePt8 = ((3*(deviceExtension->BufferSize>>2))+
(deviceExtension->BufferSize>>4));
deviceExtension->ToSubmitReadUrb = TRUE;
deviceExtension->NoReadUrb = FALSE;
//
// Mark the device as busy for WMI
//
deviceExtension->WmiCommData.IsBusy = TRUE;
deviceExtension->IrpMaskLocation = NULL;
deviceExtension->HistoryMask = 0;
deviceExtension->IsrWaitMask = 0;
deviceExtension->SendXonChar = FALSE;
deviceExtension->SendXoffChar = FALSE;
//
// The escape char replacement must be reset upon every open.
//
deviceExtension->EscapeChar = 0;
done:
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
deviceExtension->DeviceIsOpened = TRUE;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
UsbCom_DecrementIoCount(DeviceObject);
DbgPrint("exit UsbCom_Create %x\n", ntStatus);
return ntStatus;
}
LONG
UsbCom_DecrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
We keep a pending IO count ( extension->PendingIoCount ) in the device extension.
The first increment of this count is done on adding the device.
Subsequently, the count is incremented for each new IRP received and
decremented when each IRP is completed or passed on.
Transition to 'one' therefore indicates no IO is pending and signals
deviceExtension->NoPendingIoEvent. This is needed for processing
IRP_MN_QUERY_REMOVE_DEVICE
Transition to 'zero' signals an event ( deviceExtension->RemoveEvent )
to enable device removal. This is used in processing for IRP_MN_REMOVE_DEVICE
Arguments:
DeviceObject -- ptr to our FDO
Return Value:
deviceExtension->PendingIoCount
--*/
{
PDEVICE_EXTENSION deviceExtension;
LONG ioCount;
KIRQL oldIrql;
deviceExtension = DeviceObject->DeviceExtension;
KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);
ioCount = InterlockedDecrement(&deviceExtension->PendingIoCount);
// ASSERT(0 <= ioCount);
if (ioCount > 1)
KeResetEvent(&deviceExtension->NoPendingIoEvent);
if (ioCount==1) {
// trigger no pending io
KeSetEvent(&deviceExtension->NoPendingIoEvent,
1,
FALSE);
}
if (ioCount==0) {
// trigger remove-device event
KeSetEvent(&deviceExtension->RemoveEvent,
1,
FALSE);
}
KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);
// DbgPrint("Exit UsbCom_DecrementIoCount() Pending io count = %x\n", ioCount);
return ioCount;
}
VOID
UsbCom_IncrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
We keep a pending IO count ( extension->PendingIoCount ) in the device extension.
The first increment of this count is done on adding the device.
Subsequently, the count is incremented for each new IRP received and
decremented when each IRP is completed or passed on.
Arguments:
DeviceObject -- ptr to our FDO
Return Value:
None
--*/
{
PDEVICE_EXTENSION deviceExtension;
KIRQL oldIrql;
deviceExtension = DeviceObject->DeviceExtension;
// DbgPrint("Enter UsbCom_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount);
KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);
InterlockedIncrement(&deviceExtension->PendingIoCount);
KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);
// DbgPrint("Exit UsbCom_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount);
}
NTSTATUS
SerialGetRegistryKeyValue (
IN HANDLE Handle,
IN PWCHAR KeyNameString,
IN ULONG KeyNameStringLength,
IN OUT PVOID Data,
IN OUT PULONG DataLength
)
/*++
Routine Description:
Reads a registry key value from an already opened registry key.
Arguments:
Handle Handle to the opened registry key
KeyNameString ANSI string to the desired key
KeyNameStringLength Length of the KeyNameString
Data Buffer to place the key value in
DataLength Length of the data buffer
Return Value:
STATUS_SUCCESS if all works, otherwise status of system call that
went wrong.
--*/
{
UNICODE_STRING keyName;
ULONG length;
PKEY_VALUE_FULL_INFORMATION fullInfo;
NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES;
PAGED_CODE();
DbgPrint("Enter SerialGetRegistryKeyValue\n");
RtlInitUnicodeString (&keyName, KeyNameString);
length = sizeof(KEY_VALUE_FULL_INFORMATION) + KeyNameStringLength
+ *DataLength;
fullInfo = ExAllocatePool(PagedPool, length);
if (fullInfo) {
ntStatus = ZwQueryValueKey (Handle,
&keyName,
KeyValueFullInformation,
fullInfo,
length,
&length);
if (NT_SUCCESS(ntStatus)) {
//
// If there is enough room in the data buffer, copy the output
//
if (*DataLength >= fullInfo->DataLength) {
*DataLength = fullInfo->DataLength;
RtlCopyMemory (Data,
((PUCHAR) fullInfo) + fullInfo->DataOffset,
fullInfo->DataLength);
}
}
ExFreePool(fullInfo);
}
return ntStatus;
}
LARGE_INTEGER
SerialGetCharTime(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This function will return the number of 100 nanosecond intervals
there are in one character time (based on the present form
of flow control.
Arguments:
Extension - Just what it says.
Return Value:
100 nanosecond intervals in a character time.
--*/
{
ULONG dataSize;
ULONG paritySize;
ULONG stopSize;
ULONG charTime;
ULONG bitTime;
LARGE_INTEGER tmp;
if ((Extension->LineControl & SERIAL_DATA_MASK) == SERIAL_5_DATA) {
dataSize = 5;
} else if ((Extension->LineControl & SERIAL_DATA_MASK)
== SERIAL_6_DATA) {
dataSize = 6;
} else if ((Extension->LineControl & SERIAL_DATA_MASK)
== SERIAL_7_DATA) {
dataSize = 7;
} else if ((Extension->LineControl & SERIAL_DATA_MASK)
== SERIAL_8_DATA) {
dataSize = 8;
}
paritySize = 1;
if ((Extension->LineControl & SERIAL_PARITY_MASK)
== SERIAL_NONE_PARITY) {
paritySize = 0;
}
if (Extension->LineControl & SERIAL_2_STOP) {
//
// Even if it is 1.5, for sanities sake were going
// to say 2.
//
stopSize = 2;
} else {
stopSize = 1;
}
//
// First we calculate the number of 100 nanosecond intervals
// are in a single bit time (Approximately).
//
bitTime = (10000000+(Extension->CurrentBaud-1))/Extension->CurrentBaud;
charTime = bitTime + ((dataSize+paritySize+stopSize)*bitTime);
tmp.QuadPart = charTime;
return tmp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -