📄 usb2com.adddev.cpp
字号:
//********************************************************************
// created: 11:7:2008 21:33
// file: usb2com.adddev.cpp
// author: tiamo
// purpose: add device
//********************************************************************
#include "stdafx.h"
//
// we need to instantiate the GUID,see ntddser.h for detail
//
#include <initguid.h>
#include <ntddser.h>
#pragma alloc_text(PAGED,Usb2ComAddDevice)
//
// add device
//
NTSTATUS Usb2ComAddDevice(__in PDRIVER_OBJECT DriverObject,__in PDEVICE_OBJECT Pdo)
{
PAGED_CODE();
NTSTATUS Status = STATUS_OBJECT_NAME_EXISTS;
PDEVICE_OBJECT Fdo = 0;
UNICODE_STRING DeviceName;
__try
{
//
// alloc device name buffer
//
DeviceName.MaximumLength = static_cast<USHORT>(sizeof(L"\\Device\\Serial0"));
DeviceName.Length = static_cast<USHORT>(DeviceName.MaximumLength - sizeof(WCHAR));
DeviceName.Buffer = static_cast<PWCH>(ExAllocatePoolWithTag(PagedPool,DeviceName.MaximumLength,'Name'));
if(!DeviceName.Buffer)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
RtlCopyMemory(DeviceName.Buffer,L"\\Device\\Serial0",DeviceName.MaximumLength);
//
// always skip COM1 and COM2
//
ULONG DeviceNumber = 3;
ULONG DevNumIndex = DeviceName.Length / sizeof(WCHAR) - 1;
//
// loop until we got a device object
//
while(!Fdo && DeviceNumber < 10)
{
//
// build device name,DeviceNumber will always contain only one digit,because we limited it to be less than 10
//
DeviceName.Buffer[DevNumIndex] = static_cast<WCHAR>(DeviceNumber + L'0');
//
// try to create the device object,this call may fail because the device with the name already exists,
// if failed,we simply try another device name
//
Status = IoCreateDevice(DriverObject,sizeof(USB2COM_DEVICE_EXTENSION),&DeviceName,FILE_DEVICE_SERIAL_PORT,0,TRUE,&Fdo);
if(NT_SUCCESS(Status))
break;
//
// try next device number,check the return value first?
//
DeviceNumber += 1;
}
//
// we can't create a fdo,Status has already been set correctly.
//
if(!Fdo)
try_leave(NOTHING);
//
// actually there is no need to zero it out,but well, for safe
//
PUSB2COM_DEVICE_EXTENSION DevExt = static_cast<PUSB2COM_DEVICE_EXTENSION>(Fdo->DeviceExtension);
RtlZeroMemory(DevExt,sizeof(USB2COM_DEVICE_EXTENSION));
//
// allocate dos device name buffer
//
DevExt->DosDeviceName.MaximumLength = 0x100;
DevExt->DosDeviceName.Buffer = static_cast<PWCH>(ExAllocatePoolWithTag(PagedPool,DevExt->DosDeviceName.MaximumLength,'Name'));
if(!DevExt->DosDeviceName.Buffer)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
RtlZeroMemory(DevExt->DosDeviceName.Buffer,DevExt->DosDeviceName.MaximumLength);
RtlCopyMemory(DevExt->DosDeviceName.Buffer,L"\\DosDevices\\COM0",sizeof(L"\\DosDevices\\COM0"));
//
// read port name from reg
//
Status = Usb2ComReadPortName(&DevExt->DosDeviceName,Pdo);
if(!NT_SUCCESS(Status))
try_leave(NOTHING);
//
// create dos device name
//
Status = IoCreateSymbolicLink(&DevExt->DosDeviceName,&DeviceName);
if(!NT_SUCCESS(Status))
try_leave(NOTHING);
//
// write name map into registry
//
RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,L"SERIALCOMM",DeviceName.Buffer,REG_SZ,DevExt->DosDeviceName.Buffer,DevExt->DosDeviceName.MaximumLength);
//
// attach ourself to device stack
//
DevExt->LowerDeviceObject = IoAttachDeviceToDeviceStack(Fdo,Pdo);
if(!DevExt->LowerDeviceObject)
try_leave(Status = STATUS_UNSUCCESSFUL);
//
// register device interface
//
Status = IoRegisterDeviceInterface(Pdo,&GUID_CLASS_COMPORT,0,&DevExt->SymbolicLinkName);
if(!NT_SUCCESS(Status))
try_leave(NOTHING);
//
// allocate bulk in irp,urb,buffer
//
DevExt->BulkInBuffer = ExAllocatePoolWithTag(NonPagedPool,0x40,'uBIb');
if(!DevExt->BulkInBuffer)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
DevExt->BulkInUrb = static_cast<PURB>(ExAllocatePoolWithTag(NonPagedPool,sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),'uBIu'));
if(!DevExt->BulkInUrb)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
DevExt->BulkInIrp = IoAllocateIrp(DevExt->LowerDeviceObject->StackSize,FALSE);
if(!DevExt->BulkInIrp)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
KeInitializeEvent(&DevExt->BulkInUrbStopEvent,NotificationEvent,TRUE);
//
// allocate bulk out irp,urb,buffer
//
DevExt->BulkOutBuffer = ExAllocatePoolWithTag(NonPagedPool,0x40,'uBOb');
if(!DevExt->BulkOutBuffer)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
DevExt->BulkOutUrb = static_cast<PURB>(ExAllocatePoolWithTag(NonPagedPool,sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),'uBOu'));
if(!DevExt->BulkOutUrb)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
DevExt->BulkOutIrp = IoAllocateIrp(DevExt->LowerDeviceObject->StackSize,FALSE);
if(!DevExt->BulkOutIrp)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
KeInitializeEvent(&DevExt->BulkOutUrbStopEvent,NotificationEvent,TRUE);
//
// allocate interrupt irp,urb,buffer
//
DevExt->InterruptBuffer = ExAllocatePoolWithTag(NonPagedPool,0x04,'uIb ');
if(!DevExt->InterruptBuffer)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
DevExt->InterruptUrb = static_cast<PURB>(ExAllocatePoolWithTag(NonPagedPool,sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),'uIu '));
if(!DevExt->InterruptUrb)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
DevExt->InterruptIrp = IoAllocateIrp(DevExt->LowerDeviceObject->StackSize,FALSE);
if(!DevExt->InterruptIrp)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
KeInitializeEvent(&DevExt->InterruptUrbStopEvent,NotificationEvent,TRUE);
//
// allocate read buffer
//
DevExt->ReadBuffer = static_cast<PUCHAR>(ExAllocatePoolWithTag(NonPagedPool,0x2000,'RDBF'));
if(!DevExt->ReadBuffer)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
KeInitializeSpinLock(&DevExt->ReadLock);
KeInitializeSpinLock(&DevExt->WriteLock);
KeInitializeSpinLock(&DevExt->InterruptLock);
InitializeListHead(&DevExt->ReadQueueListHead);
InitializeListHead(&DevExt->WriteQueueListHead);
//
// setup the device extension
//
DevExt->DeviceName = DeviceName;
DevExt->DeviceNumber = DeviceNumber;
DevExt->FunctionDeviceObject = Fdo;
DevExt->PhysicalDeviceObject = Pdo;
DevExt->Signature = 'U2C ';
//
// we only support buffered io
//
Fdo->Flags |= (DO_BUFFERED_IO | DO_POWER_PAGABLE);
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
//
// initialize remove lock
//
IoInitializeRemoveLock(&DevExt->RemoveLock,DevExt->Signature,0,0);
}
__finally
{
if(!NT_SUCCESS(Status) || AbnormalTermination())
{
if(DeviceName.Buffer)
ExFreePool(DeviceName.Buffer);
if(Fdo)
Usb2ComCleanupFunctionDeviceObject(Fdo);
}
}
return Status;
}
//
// cleanup fdo
//
VOID Usb2ComCleanupFunctionDeviceObject(__in PDEVICE_OBJECT Fdo)
{
PUSB2COM_DEVICE_EXTENSION DeviceExtension = static_cast<PUSB2COM_DEVICE_EXTENSION>(Fdo->DeviceExtension);
//
// deattach from the device stack
//
if(DeviceExtension->LowerDeviceObject)
IoDetachDevice(DeviceExtension->LowerDeviceObject);
//
// delete dos device symbolic link
//
if(DeviceExtension->DosDeviceName.Buffer)
IoDeleteSymbolicLink(&DeviceExtension->DosDeviceName);
//
// free device name
//
if(DeviceExtension->DeviceName.Buffer)
{
RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP,L"SERIALCOMM",DeviceExtension->DeviceName.Buffer);
ExFreePool(DeviceExtension->DeviceName.Buffer);
}
//
// free dos device name
//
if(DeviceExtension->DosDeviceName.Buffer)
ExFreePool(DeviceExtension->DosDeviceName.Buffer);
//
// delete device interface symbolic link name
//
if(DeviceExtension->SymbolicLinkName.Buffer)
RtlFreeUnicodeString(&DeviceExtension->SymbolicLinkName);
//
// free bulk in urb,irp,buffer
//
if(DeviceExtension->BulkInIrp)
IoFreeIrp(DeviceExtension->BulkInIrp);
if(DeviceExtension->BulkInBuffer)
ExFreePool(DeviceExtension->BulkInBuffer);
if(DeviceExtension->BulkInUrb)
ExFreePool(DeviceExtension->BulkInUrb);
//
// free bulk out urb,irp,buffer
//
if(DeviceExtension->BulkOutIrp)
IoFreeIrp(DeviceExtension->BulkOutIrp);
if(DeviceExtension->BulkOutBuffer)
ExFreePool(DeviceExtension->BulkOutBuffer);
if(DeviceExtension->BulkOutUrb)
ExFreePool(DeviceExtension->BulkOutUrb);
//
// free interrupt urb,irp,buffer
//
if(DeviceExtension->InterruptIrp)
IoFreeIrp(DeviceExtension->InterruptIrp);
if(DeviceExtension->InterruptBuffer)
ExFreePool(DeviceExtension->InterruptBuffer);
if(DeviceExtension->InterruptUrb)
ExFreePool(DeviceExtension->InterruptUrb);
//
// free read buffer
//
if(DeviceExtension->ReadBuffer)
ExFreePool(DeviceExtension->ReadBuffer);
//
// delete device
//
IoDeleteDevice(Fdo);
}
//
// read port name
//
NTSTATUS Usb2ComReadPortName(__in __out PUNICODE_STRING DosDeviceName,__in PDEVICE_OBJECT Pdo)
{
NTSTATUS Status = STATUS_SUCCESS;
HANDLE RegKey = 0;
PKEY_VALUE_FULL_INFORMATION FullInfo = 0;
UNICODE_STRING KeyName;
__try
{
Status = IoOpenDeviceRegistryKey(Pdo,PLUGPLAY_REGKEY_DEVICE,STANDARD_RIGHTS_READ,&RegKey);
if(!NT_SUCCESS(Status))
try_leave(NOTHING);
PWCHAR PortName = DosDeviceName->Buffer + sizeof(L"\\DosDevices\\") / sizeof(WCHAR) - 1;
ULONG PortNameLength = DosDeviceName->MaximumLength - sizeof(L"\\DosDevices\\") - sizeof(WCHAR) - sizeof(WCHAR);
RtlInitUnicodeString(&KeyName,L"PortName");
ULONG Length = sizeof(KEY_VALUE_FULL_INFORMATION) + sizeof(L"PortName") + PortNameLength;
FullInfo = static_cast<PKEY_VALUE_FULL_INFORMATION>(ExAllocatePoolWithTag(PagedPool,Length,'REG '));
if(!FullInfo)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
Status = ZwQueryValueKey(RegKey,&KeyName,KeyValueFullInformation,FullInfo,Length,&Length);
if(NT_SUCCESS(Status) && PortNameLength >= FullInfo->DataLength)
{
RtlCopyMemory(PortName,static_cast<PUCHAR>(static_cast<PVOID>(FullInfo)) + FullInfo->DataOffset,FullInfo->DataLength);
DosDeviceName->Length = static_cast<USHORT>(sizeof(L"\\DosDevices\\") - sizeof(WCHAR) + FullInfo->DataLength - sizeof(WCHAR));
}
}
__finally
{
if(RegKey)
ZwClose(RegKey);
if(FullInfo)
ExFreePool(FullInfo);
}
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -