📄 main.c
字号:
if( deviceExtension->DosName.Buffer == NULL ){
DebugPrint(("SERIAL: Couldn't allocate memory for Dos name\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
goto SerialDoExternalNamingError;
}
deviceExtension->DosName.Length = 0;
RtlZeroMemory( deviceExtension->DosName.Buffer, deviceExtension->DosName.MaximumLength );
RtlAppendUnicodeToString( &deviceExtension->DosName, L"COM" );
RtlAppendUnicodeStringToString( &deviceExtension->DosName, &instanceStr);
DebugPrint(("DosName: %wZ\n", &deviceExtension->DosName ));
DebugPrint(("DeviceName: %wZ\n", &deviceExtension->DeviceName ));
// 生成符号连接,至此本设备对win32应用表现的Dos设备名为 \DosDevices\COMn
status = IoCreateSymbolicLink( &deviceExtension->SymbolicLinkName, &deviceExtension->DeviceName );
if( !NT_SUCCESS( status )){
DebugPrint(("SERIAL: Couldn't create the symbolic link with error %d\n", status));
goto SerialDoExternalNamingError;
}else{
DebugPrint(("Create the symbolic link OK\n"));
deviceExtension->CreatedSymbolicLink = TRUE;
}
// 在注册表的 HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM 中,添加ComX的键值
// 若不进行这一步,则超级终端程序无法检测到本虚拟串口设备
status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
deviceExtension->DeviceName.Buffer, REG_SZ,
deviceExtension->DosName.Buffer,
deviceExtension->DosName.Length + sizeof(WCHAR));
if( !NT_SUCCESS( status )){
DebugPrint(("SERIAL: Couldn't create the device map entry\n------- for port %wZ\n", deviceExtension->DeviceName ));
goto SerialDoExternalNamingError;
}
deviceExtension->ComX = ComX;
deviceExtension->CreatedSerialCommEntry = TRUE;
SerialDoExternalNamingError:
if( !NT_SUCCESS( status )){
if( deviceExtension->DosName.Buffer != NULL ){
ExFreePool( deviceExtension->DosName.Buffer );
deviceExtension->DosName.Buffer = NULL;
deviceExtension->CreatedSerialCommEntry = FALSE;
}
if( deviceExtension->CreatedSymbolicLink ){
IoDeleteSymbolicLink( &deviceExtension->SymbolicLinkName );
deviceExtension->CreatedSymbolicLink = FALSE;
}
if( deviceExtension->SymbolicLinkName.Buffer != NULL ){
ExFreePool( deviceExtension->SymbolicLinkName.Buffer );
deviceExtension->SymbolicLinkName.Buffer = NULL;
}
}
return status;
}
BOOLEAN InitializeSerialDevName( PUNICODE_STRING lpDeviceName )
/*++
Routine Description:
Initialize serial device name. This name is available in Kernel Mode.
Arguments:
PUNICODE_STRING lpDeviceName - the pointer to device name string.
Return Value:
return TRUE if it is successful, otherwise return FALSE.
--*/
{
WCHAR instanceNumberBuffer[ 4 ];
UNICODE_STRING instanceStr;
static ULONG currentInstance = 10;
// 首先处理deviceObjName,这是一个核心态使用的设备名,形如"\\Device\\SiSerial0"
// Zero out allocated memory pointers so we know if they must be freed
RtlZeroMemory( lpDeviceName, sizeof(UNICODE_STRING) );
lpDeviceName->MaximumLength = DEVICE_OBJECT_NAME_LENGTH * sizeof(WCHAR);
lpDeviceName->Buffer = ExAllocatePool(PagedPool, lpDeviceName->MaximumLength + sizeof(WCHAR));
if ( lpDeviceName->Buffer == NULL) {
DebugPrint(("Couldn't allocate memory for device name\n"));
return FALSE;
}
RtlZeroMemory( lpDeviceName->Buffer, lpDeviceName->MaximumLength + sizeof(WCHAR));
// now, the size of deviceObjName.Buffer is (128 + 1)(WCHAR)
RtlAppendUnicodeToString( lpDeviceName, DEVICE_NAME); // L"\\Device\\VSer"
// 处理 lpDeviceName 的后缀序号
RtlInitUnicodeString(&instanceStr, NULL);
instanceStr.MaximumLength = sizeof(instanceNumberBuffer);
instanceStr.Buffer = instanceNumberBuffer; // 20 WCHAR
currentInstance++;
RtlIntegerToUnicodeString( currentInstance, 10, &instanceStr);
RtlAppendUnicodeStringToString( lpDeviceName, &instanceStr);
DebugPrint(("DeviceName:\n"));
DebugPrint(("----------- %ws\n", lpDeviceName->Buffer ));
return TRUE;
}
NTSTATUS
SerialUndoExternalNaming(
IN PDEVICE_EXTENSION deviceExtension
)
/*++
Routine Description:
Delete or unregister external name, SymbolicLinkName and DOS name.
Arguments:
deviceExtension - pointer to a device object extension.
Return Value:
NT status code.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
if( deviceExtension->CreatedSymbolicLink ){
IoDeleteSymbolicLink( &deviceExtension->SymbolicLinkName );
ExFreePool( deviceExtension->SymbolicLinkName.Buffer );
deviceExtension->SymbolicLinkName.Buffer = NULL;
deviceExtension->CreatedSymbolicLink = FALSE;
}else{
ASSERT( deviceExtension->SymbolicLinkName.Buffer == NULL );
}
ASSERT( deviceExtension->DeviceName.Buffer != NULL );
if( deviceExtension->CreatedSerialCommEntry ){
status = RtlDeleteRegistryValue( RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP, deviceExtension->DeviceName.Buffer );
if( !NT_SUCCESS( status ) ){
DebugPrint(("RtlDeleteRegistryValue device map failed\n"));
}
ExFreePool( deviceExtension->DosName.Buffer );
deviceExtension->DosName.Buffer = NULL;
deviceExtension->CreatedSerialCommEntry = FALSE;
}else{
ASSERT( deviceExtension->DosName.Buffer == NULL );
}
return status;
}
NTSTATUS
SerialRemoveDevObj(IN PDEVICE_OBJECT PDevObj)
/*++
Routine Description:
Removes a serial device object from the system.
Arguments:
PDevObj - A pointer to the Device Object we want removed.
Return Value:
Always TRUE
--*/
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)PDevObj->DeviceExtension;
PAGED_CODE();
DebugPrint(("SERIAL: Enter SerialRemoveDevObj\n"));
//
// Free memory allocated in the extension
//
if (pDevExt->DeviceName.Buffer != NULL) {
ExFreePool(pDevExt->DeviceName.Buffer);
}
if (pDevExt->SymbolicLinkName.Buffer != NULL) {
ExFreePool(pDevExt->SymbolicLinkName.Buffer);
}
if (pDevExt->DosName.Buffer != NULL) {
ExFreePool(pDevExt->DosName.Buffer);
}
DebugPrint(("SERIAL: Leave SerialRemoveDevObj\n"));
return STATUS_SUCCESS;
}
NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG info)
{
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
VOID
Unload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Free all the allocated resources in DriverEntry, etc.
Arguments:
DriverObject - pointer to a driver object.
Return Value:
VOID.
--*/
{
PAGED_CODE ();
//
// The device object(s) should be NULL now
// (since we unload, all the devices objects associated with this
// driver must be deleted.
//
DebugPrint( ("Is unloading......\n") );
ASSERT(DriverObject->DeviceObject == NULL);
//
// We should not be unloaded until all the devices we control
// have been removed from our queue.
//
DebugPrint (("Unload: unload\n"));
return;
}
LONG
SampleIoIncrement(
IN OUT PDEVICE_EXTENSION DeviceExtension
)
/* ++
Routine Description:
Increment deviceExtension->OutStandingIO within the scope of IOCountLock.
Arguments:
deviceExtension - pointer to a device object extension.
Return Value:
deviceExtension->OutStandingIO
--*/
{
LONG result = 0;
KIRQL oldIrql;
KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
result = InterlockedIncrement(&DeviceExtension->OutStandingIO);
//
// when OutStandingIO bumps from 1 to 2, clear the StopEvent
//
if(result == 2) {
KeClearEvent(&DeviceExtension->StopEvent);
}
KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
DebugPrint(("SampleIncrement: %d\n", result));
return result;
}
LONG
SampleIoDecrement(
IN OUT PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
Decrement deviceExtension->OutStandingIO within the scope of IOCountLock.
Arguments:
deviceExtension - pointer to a device object extension.
Return Value:
deviceExtension->OutStandingIO
--*/
{
LONG result = 0;
KIRQL oldIrql;
KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
result = InterlockedDecrement(&DeviceExtension->OutStandingIO);
if(result == 1) {
KeSetEvent(&DeviceExtension->StopEvent, IO_NO_INCREMENT, FALSE);
}
if(result == 0) {
ASSERT(Removed == DeviceExtension->DevicePnPState);
KeSetEvent(&DeviceExtension->RemoveEvent, IO_NO_INCREMENT, FALSE);
}
KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
DebugPrint(("SampleIoDecrement: %d\n", result));
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -