?? main.c
字號:
/*++
Copyright (c) 2005 Changzhi Zhou All Rights Reserved
Module Name:
main.c
Abstract:
This module is main module that deals with
DriverEntry, AddDevice, Unload, handles to device name.
SampleIoCrement and SampleIoDecrement.
Environment:
Kernel mode
Revision History:
Changzhi Zhou Dec 20 2004
--*/
#include <wdm.h>
#include <ntddk.h>
#include <initguid.h>
#include "main.h"
#include "..\inc\wdmioctl.h"
#include <wmistr.h>
#include <wmilib.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, AddDevice)
#pragma alloc_text (PAGE, SamplePnpDispatch)
#pragma alloc_text (PAGE, Unload)
#endif
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Installable driver initialization entry point.
This entry point is called directly by the I/O system.
Arguments:
DriverObject - pointer to the driver object
RegistryPath - pointer to a unicode string representing the path,
to driver-specific key in the registry.
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise.
--*/
NTSTATUS status;
UNREFERENCED_PARAMETER (RegistryPath);
DbgPrint("------ VirtualSerial Build on %s %s -------\n", __DATE__, __TIME__ );
status = STATUS_SUCCESS;
DriverObject->MajorFunction[IRP_MJ_PNP] = SamplePnpDispatch;
DriverObject->MajorFunction[IRP_MJ_POWER] = SamplePowerDispatch;
DriverObject->MajorFunction[IRP_MJ_CREATE] = SampleCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SampleClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP ] = SampleCleanup;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SampleIoControl;
DriverObject->MajorFunction[IRP_MJ_WRITE] = SampleWrite;
DriverObject->MajorFunction[IRP_MJ_READ] = SampleRead;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = ToasterSystemControl;
DriverObject->DriverExtension->AddDevice = AddDevice;
DriverObject->DriverUnload = Unload;
return status;
}
NTSTATUS
AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
The Plug & Play subsystem is handing us a brand new PDO, for which we
(by means of INF registration) have been asked to provide a driver.
We need to determine if we need to be in the driver stack for the device.
Create a function device object to attach to the stack
Initialize that device object
Return status success.
Remember: We can NOT actually send ANY non pnp IRPS to the given driver
stack, UNTIL we have received an IRP_MN_START_DEVICE.
Arguments:
DeviceObject - pointer to a device object.
PhysicalDeviceObject - pointer to a device object created by the
underlying bus driver.
Return Value:
NT status code.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_EXTENSION deviceExtension;
UNICODE_STRING deviceObjName;
PAGED_CODE ();
DbgPrint("------- AddDevice build on %s %s ---------\n", __DATE__, __TIME__);
if( FALSE == InitializeSerialDevName( &deviceObjName ) )
return STATUS_INSUFFICIENT_RESOURCES;
status = IoCreateDevice (DriverObject,
sizeof (DEVICE_EXTENSION),
&deviceObjName,
FILE_DEVICE_SERIAL_PORT,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObject);
if (!NT_SUCCESS (status)) {
DebugPrint(("IoCreateDevice failed\n"));
if ( deviceObjName.Buffer != NULL )
ExFreePool ( deviceObjName.Buffer );
return status;
}
DebugPrint (("AddDevice PDO (0x%x) FDO (0x%x)\n", PhysicalDeviceObject, deviceObject));
deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
deviceExtension->DeviceName.MaximumLength = deviceObjName.MaximumLength;
deviceExtension->DeviceName.Length = deviceObjName.Length;
deviceExtension->DeviceName.Buffer = deviceObjName.Buffer;
deviceExtension->CreatedSerialCommEntry = FALSE;
deviceExtension->CreatedSymbolicLink = FALSE;
// for working thread
KeInitializeSpinLock( &deviceExtension->ThreadSpinLock );
deviceExtension->NextLowerDriver = IoAttachDeviceToDeviceStack (
deviceObject,
PhysicalDeviceObject);
if(NULL == deviceExtension->NextLowerDriver) {
IoDeleteDevice(deviceObject);
return STATUS_UNSUCCESSFUL;
}
DebugPrint(("AddDevice: %x to %x->%x \n", deviceObject,
deviceExtension->NextLowerDriver,
PhysicalDeviceObject));
// Initialize the remove event to not-signaled.
//
KeInitializeEvent(&deviceExtension->RemoveEvent,
SynchronizationEvent,
FALSE);
//
// Initialize the stop event to signaled.
// This event is signaled when the OutstandingIO becomes 1
//
KeInitializeEvent(&deviceExtension->StopEvent,
SynchronizationEvent,
TRUE);
deviceExtension->OutStandingIO = 1;
deviceExtension->bIsOpen = FALSE;
if ( PhysicalDeviceObject->Flags & DO_POWER_PAGABLE) {
deviceObject->Flags |= DO_POWER_PAGABLE;
}
deviceObject->Flags |= DO_DIRECT_IO;
deviceExtension->Self = deviceObject;
// Initialize serial-related parameters
deviceExtension->WaitOnMaskIrp = NULL;
deviceExtension->CurrentBaud = 0;
deviceExtension->PendingReadIrp = NULL;
KeInitializeTimer ( &deviceExtension->ReadTimer );
KeInitializeDpc ( &deviceExtension->ReadDpc, ReadDpcRoutine, (PVOID)deviceExtension );
RtlZeroMemory( &deviceExtension->SerialStatus, sizeof( SERIAL_STATUS ) );
// initialize members relevant to TDI.
deviceExtension->RxBuffer = ExAllocatePoolWithTag( NonPagedPool, RINGBUFFER_SIZE, 'RBuf' );
if ( deviceExtension->RxBuffer == NULL )
goto Error_Exit;
deviceExtension->lpRead = deviceExtension->RxBuffer;
deviceExtension->lpRx = deviceExtension->RxBuffer;
deviceExtension->hTransAddr = NULL;
deviceExtension->lpTransAddrFileObject = NULL;
deviceExtension->TDILowerDeviceObject = NULL;
deviceExtension->RemoteAddress = 0x601a8c0; // 192.168.1.6
deviceExtension->RemotePort = 0x7217; // 6002
RtlZeroMemory( (PVOID)&deviceExtension->recvContext, sizeof( RECV_CONTEXT ) );
deviceExtension->recvContext.RemainderBuffer = ExAllocatePoolWithTag ( NonPagedPool, RECVREMAINDER_BUFFER_SIZE, 'Rrem' );
if ( deviceExtension->recvContext.RemainderBuffer == NULL )
goto Error_Exit;
KeInitializeEvent(&deviceExtension->recvContext.Event,
SynchronizationEvent,
FALSE);
RtlZeroMemory ( (PVOID)&deviceExtension->recvContext.ReceiveDatagramInfo, sizeof ( TDI_CONNECTION_INFORMATION ) );
RtlZeroMemory ( (PVOID)&deviceExtension->recvContext.ReturnInfo, sizeof ( TDI_CONNECTION_INFORMATION ) );
INITIALIZE_PNP_STATE(deviceExtension);
//++ Register device interface for win32app
status = IoRegisterDeviceInterface( PhysicalDeviceObject,
(LPGUID)&GUID_CLASS_COMPORT,
NULL,
&deviceExtension->InterfaceName );
DebugPrint(("InterfaceName: %ws\n", deviceExtension->InterfaceName.Buffer ));
if( !NT_SUCCESS ( status ) ){
DebugPrint(( "AddDevice: IoRegisterDeviceInterface failed (%x) \n", status ));
goto Error_Exit;
}
//--
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
Error_Exit:
if( deviceExtension->RxBuffer )
{
ExFreePool ( deviceExtension->RxBuffer );
deviceExtension->RxBuffer = NULL;
}
if ( deviceExtension->recvContext.RemainderBuffer )
{
ExFreePool ( deviceExtension->recvContext.RemainderBuffer );
deviceExtension->recvContext.RemainderBuffer = NULL;
}
IoDetachDevice( deviceExtension->NextLowerDriver );
IoDeleteDevice( deviceObject );
return status;
}
NTSTATUS
SerialDoExternalNaming(
IN PDEVICE_EXTENSION deviceExtension,
IN LONG ComX
)
/*++
Routine Description:
Create external name, SymbolicLinkName and DOS name.
Arguments:
deviceExtension - pointer to a device object extension.
ComX - indicates the number of Serial Ports.
Return Value:
NT status code.
--*/
{
NTSTATUS status;
ULONG bufLen;
WCHAR ComXBuffer[ 4 ];
UNICODE_STRING instanceStr;
DebugPrint(("Enter SerialdoExternalNaming routine...\n"));
if( deviceExtension->CreatedSymbolicLink || deviceExtension->CreatedSerialCommEntry ){
DebugPrint(("Already create symboliclink or serial commentry\n"));
return STATUS_UNSUCCESSFUL;
}
ASSERT( deviceExtension->SymbolicLinkName.Buffer == NULL );
ASSERT( deviceExtension->DosName.Buffer == NULL );
RtlInitUnicodeString(&instanceStr, NULL);
instanceStr.MaximumLength = sizeof( ComXBuffer );
instanceStr.Buffer = ComXBuffer; // 4 WCHAR
RtlIntegerToUnicodeString( ComX, 10, &instanceStr );
// 將SymbolicLinkName設(shè)置為 \DosDevices\COMn 的形式。其中n = ComX
RtlZeroMemory( &deviceExtension->SymbolicLinkName, sizeof( UNICODE_STRING ) );
deviceExtension->SymbolicLinkName.MaximumLength = DEVICE_OBJECT_NAME_LENGTH + sizeof( WCHAR );
deviceExtension->SymbolicLinkName.Buffer = ExAllocatePoolWithTag( PagedPool, deviceExtension->SymbolicLinkName.MaximumLength, 'SymL' );
if( deviceExtension->SymbolicLinkName.Buffer == NULL ){
DebugPrint(("SERIAL: Couldn't allocate memory for symbolic link name\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
goto SerialDoExternalNamingError;
}
RtlZeroMemory( deviceExtension->SymbolicLinkName.Buffer, deviceExtension->SymbolicLinkName.MaximumLength );
RtlAppendUnicodeToString( &deviceExtension->SymbolicLinkName, DOS_DEVICE_NAME ); //L"\\DosDevices\\COM"
RtlAppendUnicodeStringToString( &deviceExtension->SymbolicLinkName, &instanceStr);
DebugPrint(("SymbolicLinkName: %wZ\n", deviceExtension->SymbolicLinkName ));
// 將DosName初始化 COMn 的形式, 其中 n = ComX
deviceExtension->DosName.MaximumLength = 64 + sizeof(WCHAR);
deviceExtension->DosName.Buffer = ExAllocatePoolWithTag( PagedPool, 64 + sizeof( WCHAR ), 'Name' );
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -