📄 init.c
字号:
}
DbgPrint("***** DRV=%08x PDO=%08x FDO=%08x (%wZ) ***** \n",
DriverObject, PhysicalDeviceObject, *DeviceObject, &deviceObjName );
// END CODEMACHINE
deviceExtension = (PDEVICE_EXTENSION) ((*DeviceObject)->DeviceExtension);
RtlZeroMemory(&deviceExtension->DeviceName, sizeof(UNICODE_STRING));
RtlZeroMemory(&deviceExtension->SymbolicLinkName, sizeof(UNICODE_STRING));
//
// Allocate Pool and save the nt device name in the device extension.
//
deviceExtension->DeviceName.Buffer =
ExAllocatePool(PagedPool, deviceObjName.Length + sizeof(WCHAR));
if (!deviceExtension->DeviceName.Buffer) {
DbgPrint("Couldn't allocate memory for DeviceName\n");
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ErrorFreeBuffer;
}
deviceExtension->DeviceName.MaximumLength = deviceObjName.Length
+ sizeof(WCHAR);
//
// Zero fill it.
//
RtlZeroMemory(deviceExtension->DeviceName.Buffer,
deviceExtension->DeviceName.MaximumLength);
RtlAppendUnicodeStringToString(&deviceExtension->DeviceName, &deviceObjName);
//default maximum transfer size per staged io request
deviceExtension->MaximumTransferSize = UsbCom_MAX_TRANSFER_SIZE ;
// this event is triggered when there is no pending io of any kind and device is removed
KeInitializeEvent(&deviceExtension->RemoveEvent, NotificationEvent, FALSE);
// this event is triggered when self-requested power irps complete
KeInitializeEvent(&deviceExtension->SelfRequestedPowerIrpEvent, NotificationEvent, FALSE);
// this event is triggered when there is no pending io (pending io count == 1 )
KeInitializeEvent(&deviceExtension->NoPendingIoEvent, NotificationEvent, FALSE);
// spinlock used to protect inc/dec iocount logic
KeInitializeSpinLock (&deviceExtension->IoCountSpinLock);
KeInitializeEvent(&deviceExtension->PendingIRPEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&deviceExtension->PendingDpcEvent, SynchronizationEvent, FALSE);
deviceExtension->DeviceIsOpened = FALSE;
InitializeListHead(&deviceExtension->ReadQueue);
InitializeListHead(&deviceExtension->WriteQueue);
InitializeListHead(&deviceExtension->MaskQueue);
InitializeListHead(&deviceExtension->PurgeQueue);
InitializeListHead(&deviceExtension->StalledIrpQueue);
//
// Initialize the timers used to timeout operations.
//
KeInitializeTimer(&deviceExtension->ReadRequestTotalTimer);
KeInitializeTimer(&deviceExtension->ReadRequestIntervalTimer);
KeInitializeTimer(&deviceExtension->WriteRequestTotalTimer);
KeInitializeTimer(&deviceExtension->ImmediateTotalTimer);
KeInitializeTimer(&deviceExtension->XoffCountTimer);
KeInitializeTimer(&deviceExtension->LowerRTSTimer);
//
// Intialialize the dpcs that will be used to complete
// or timeout various IO operations.
//
KeInitializeDpc(&deviceExtension->CompleteWriteDpc, SerialCompleteWrite, deviceExtension);
KeInitializeDpc(&deviceExtension->CompleteReadDpc, SerialCompleteRead, deviceExtension);
KeInitializeDpc(&deviceExtension->TotalReadTimeoutDpc, SerialReadTimeout, deviceExtension);
KeInitializeDpc(&deviceExtension->IntervalReadTimeoutDpc, SerialIntervalReadTimeout,
deviceExtension);
KeInitializeDpc(&deviceExtension->TotalWriteTimeoutDpc, SerialWriteTimeout, deviceExtension);
// KeInitializeDpc(&deviceExtension->CommErrorDpc, SerialCommError, deviceExtension);
// KeInitializeDpc(&deviceExtension->CompleteImmediateDpc, SerialCompleteImmediate,
// deviceExtension);
// KeInitializeDpc(&deviceExtension->TotalImmediateTimeoutDpc, SerialTimeoutImmediate,
// deviceExtension);
KeInitializeDpc(&deviceExtension->CommWaitDpc, SerialCompleteWait, deviceExtension);
KeInitializeDpc(&deviceExtension->XoffCountTimeoutDpc, SerialTimeoutXoff, deviceExtension);
KeInitializeDpc(&deviceExtension->XoffCountCompleteDpc, SerialCompleteXoff, deviceExtension);
KeInitializeDpc(&deviceExtension->StartTimerLowerRTSDpc, SerialStartTimerLowerRTS,
deviceExtension);
KeInitializeDpc(&deviceExtension->PerhapsLowerRTSDpc, SerialInvokePerhapsLowerRTS,
deviceExtension);
// KeInitializeDpc(&deviceExtension->IsrUnlockPagesDpc, SerialUnlockPages, deviceExtension);
//
// Initialize the count of IRP's pending
//
deviceExtension->PendingIRPCnt = 1;
//
// Initialize the count of DPC's pending
//
deviceExtension->DpcCount = 1;
//
// Initialize the spinlock associated with fields read (& set)
// by IO Control functions and the flags spinlock.
//
KeInitializeSpinLock(&deviceExtension->ControlLock);
KeInitializeSpinLock(&deviceExtension->FlagsLock);
KeInitializeSpinLock(&deviceExtension->IntBufferLock);
// The workitem is never used.
deviceExtension->WorkItem = IoAllocateWorkItem(*DeviceObject);
if (deviceExtension->WorkItem == NULL) {
DbgPrint("Insufficient memory for WorkItem Routine.\n");
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ErrorFreeBuffer;
}
KeInitializeMutex(&deviceExtension->CompleteRequestMutex, 0);
// Create SymbolicLink name -- ComX.
deviceExtension->CreatedSymbolicLink = FALSE;
deviceExtension->CreatedSerialCommEntry = FALSE;
linkName.MaximumLength = SYMBOLIC_NAME_LENGTH*sizeof(WCHAR);
linkName.Buffer = ExAllocatePool(PagedPool, linkName.MaximumLength
+ sizeof(WCHAR));
if (linkName.Buffer == NULL) {
DbgPrint("Couldn't allocate memory for linkName\n");
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ErrorFreeBuffer;
}
RtlZeroMemory(linkName.Buffer, linkName.MaximumLength + sizeof(WCHAR));
//
// Create the "\\DosDevices\\<symbolicName>" string
//
RtlAppendUnicodeToString(&linkName, L"\\DosDevices\\");
RtlAppendUnicodeToString(&linkName, pRegName);
//
// Allocate Pool and save the symbolic link name in the device extension.
//
deviceExtension->SymbolicLinkName.MaximumLength = linkName.Length + sizeof(WCHAR);
deviceExtension->SymbolicLinkName.Buffer
= ExAllocatePool(PagedPool, deviceExtension->SymbolicLinkName.MaximumLength);
if (!deviceExtension->SymbolicLinkName.Buffer) {
DbgPrint("Couldn't allocate memory for symbolic link name\n");
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ErrorFreeBuffer;
}
//
// Zero fill it.
//
RtlZeroMemory(deviceExtension->SymbolicLinkName.Buffer,
deviceExtension->SymbolicLinkName.MaximumLength);
RtlAppendUnicodeStringToString(&deviceExtension->SymbolicLinkName,
&linkName);
ntStatus = IoCreateSymbolicLink (&deviceExtension->SymbolicLinkName,
&deviceExtension->DeviceName);
if (!NT_SUCCESS(ntStatus)) {
//
// Oh well, couldn't create the symbolic link. No point
// in trying to create the device map entry.
//
DbgPrint("IoCreateSymbolicLink() (%wZ -> %wZ) FAIL=%08x\n",
&deviceExtension->SymbolicLinkName,
&deviceExtension->DeviceName,
ntStatus );
goto ErrorFreeBuffer;
}
deviceExtension->CreatedSymbolicLink = TRUE;
// Write comm port name to registry, USBSwt.exe will use this value
ntStatus = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, L"SERIALCOMM",
deviceObjName.Buffer, REG_SZ,
pRegName,
regLength);
if (!NT_SUCCESS(ntStatus)) {
DbgPrint("Couldn't create the device map entry\n");
goto ErrorFreeBuffer;
}
deviceExtension->CreatedSerialCommEntry = TRUE;
// option: client can use GUID interface open our fake comm port.
ntStatus = UsbCom_SymbolicLink( PhysicalDeviceObject, &deviceLinkUnicodeString);
if (!NT_SUCCESS(ntStatus)) {
DbgPrint("Couldn't register symbolic link interface!\n");
goto ErrorFreeBuffer;
}
// Name buffer for our named Functional device object link
// The name is generated based on the driver's class GUID
RtlCopyMemory(deviceExtension->DeviceLinkNameBuffer,
deviceLinkUnicodeString.Buffer,
deviceLinkUnicodeString.Length);
RtlInitUnicodeString ( &deviceExtension->DeviceNameLink, deviceExtension->DeviceLinkNameBuffer );
DbgPrint ( "DO=%08x SYMBOLIC LINK = %wZ\n", (*DeviceObject), &deviceExtension->DeviceNameLink );
// don't confuse with this lable, only ntStatus != STATUS_SUCCESS
// means error.
ErrorFreeBuffer:
if (!NT_SUCCESS(ntStatus) && (*DeviceObject != NULL)) {
//
// Create Device Object failed, Clean up error conditions
//
DbgPrint("AddDevice Error: Clean up error conditions\n");
if (deviceExtension->WorkItem != NULL) {
IoFreeWorkItem(deviceExtension->WorkItem);
}
DbgPrint("AddDevice Error: Clean up error conditions\n");
if (deviceExtension->CreatedSymbolicLink == TRUE) {
IoDeleteSymbolicLink(&deviceExtension->SymbolicLinkName);
deviceExtension->CreatedSymbolicLink = FALSE;
}
if (deviceExtension->SymbolicLinkName.Buffer != NULL) {
ExFreePool(deviceExtension->SymbolicLinkName.Buffer);
deviceExtension->SymbolicLinkName.Buffer = NULL;
}
if (deviceExtension->DeviceName.Buffer != NULL) {
RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
deviceExtension->DeviceName.Buffer);
}
if (deviceExtension->DeviceName.Buffer != NULL) {
ExFreePool(deviceExtension->DeviceName.Buffer);
}
if (*DeviceObject) {
IoDeleteDevice(*DeviceObject);
}
}
//
// Always clean up our temp buffers.
//
if (linkName.Buffer != NULL) {
ExFreePool(linkName.Buffer);
}
if (pRegName != NULL) {
ExFreePool(pRegName);
}
if (deviceObjName.Buffer != NULL) {
ExFreePool(deviceObjName.Buffer);
}
//free buffer from unicode string we used to init interface
if (deviceLinkUnicodeString.Buffer != NULL){
IoSetDeviceInterfaceState (&deviceLinkUnicodeString, FALSE);
ExFreePool( deviceLinkUnicodeString.Buffer );
}
return ntStatus;
}
NTSTATUS
UsbCom_CallUSBD(
IN PDEVICE_OBJECT DeviceObject,
IN PURB Urb
)
/*++
Routine Description:
Passes a URB to the USBD class driver
The client device driver passes USB request block (URB) structures
to the class driver as a parameter in an IRP with Irp->MajorFunction
set to IRP_MJ_INTERNAL_DEVICE_CONTROL and the next IRP stack location
Parameters.DeviceIoControl.IoControlCode field set to
IOCTL_INTERNAL_USB_SUBMIT_URB.
Arguments:
DeviceObject - pointer to the physical device object (PDO)
Urb - pointer to an already-formatted Urb request block
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
deviceExtension = DeviceObject->DeviceExtension;
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
deviceExtension->TopOfStackDeviceObject, //Points to the next-lower driver's device object
NULL, // optional input bufer; none needed here
0, // input buffer len if used
NULL, // optional output bufer; none needed here
0, // output buffer len if used
TRUE, // If InternalDeviceControl is TRUE the target driver's Dispatch
// outine for IRP_MJ_INTERNAL_DEVICE_CONTROL or IRP_MJ_SCSI
// is called; otherwise, the Dispatch routine for
// IRP_MJ_DEVICE_CONTROL is called.
&event, // event to be signalled on completion
&ioStatus); // Specifies an I/O status block to be set when the request is completed the lower driver.
//
// As an alternative, we could call KeDelayExecutionThread, wait for some
// period of time, and try again....but we keep it simple for right now
//
if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
nextStack = IoGetNextIrpStackLocation(irp);
//
// pass the URB to the USB driver stack
//
nextStack->Parameters.Others.Argument1 = Urb;
DbgPrint("UsbCom_CallUSBD() (%u) DO=%08x Urb=%08x Irp=%08x\n", UsbCom_CallUSBD_Counter++,
DeviceObject, Urb, irp );
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
//DbgPrint("UsbCom_CallUSBD() return from IoCallDriver USBD %x\n", ntStatus);
if (ntStatus == STATUS_PENDING) {
KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
} else {
ioStatus.Status = ntStatus;
}
// DbgPrint("exit UsbCom_CallUSBD DO=%08x Urb=%08x(%08x) Irp=%08x(%08x)\n", DeviceObject,
// Urb, Urb->UrbHeader.Status, irp, ioStatus.Status );
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
return ntStatus;
}
NTSTATUS
UsbCom_ConfigureDevice(
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
PURB urb;
ULONG Size;
DbgPrint("enter UsbCom_ConfigureDevice\n");
deviceExtension = DeviceObject->DeviceExtension;
if ( ( urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)) ) == NULL ) {
DbgPrint("UsbCom_ConfigureDevice() DO=%08x ExAllocatePool(URB_CONTROL_DESCRIPTOR_REQUEST) : FAIL\n",
DeviceObject );
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto UsbCom_ConfigureDevice_Exit1;
}
if ( ( deviceExtension->UsbConfigurationDescriptor = ExAllocatePool(NonPagedPool, sizeof(USB_CONFIGURATION_DESCRIPTOR) ) ) == NULL ) {
DbgPrint("UsbCom_ConfigureDevice() DO=%08x ExAllocatePool(USB_CONFIGURATION_DESCRIPTOR+512) : FAIL\n",
DeviceObject );
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto UsbCom_ConfigureDevice_Exit2;
}
UsbBuildGetDescriptorRequest(
urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
deviceExtension->UsbConfigurationDescriptor,
NULL,
sizeof (USB_CONFIGURATION_DESCRIPTOR),
NULL);
ntStatus = UsbCom_CallUSBD(DeviceObject, urb);
if (!(NT_SUCCESS(ntStatus))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -