#define DONG_NT_DEVICE_NAME L"\\Device\\DongLpt" #define DONG_NT_PORT_DEVICE_NAME L"\\Device\\ParallelPort" #define DONG_WIN32_DEVICE_NAME L"\\DosDevices\\DongLpt" #define DONG_DOS_DEVICES L"\\DosDevices\\" #define DONG_DRIVER_NAME L"DongLpt" #define DONG_MAX_NAME_LENGTH 50 NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath ) { ULONG NtDeviceNumber, NumParallelPorts; NTSTATUS status = STATUS_SUCCESS; DongInitializeEventLog(pDriverObject); // Export other driver entry points... pDriverObject->DriverUnload = DongDriverUnload; pDriverObject->MajorFunction[ IRP_MJ_CREATE ] = DongDispatchOpen; pDriverObject->MajorFunction[ IRP_MJ_CLOSE ] = DongDispatchClose; pDriverObject->MajorFunction[ IRP_MJ_WRITE ] = DongDispatchWrite; pDriverObject->MajorFunction[ IRP_MJ_READ ] = DongDispatchRead; pDriverObject->MajorFunction[ IRP_MJ_CLEANUP ] = DongDispatchCleanup; // Initialize a Device object for each parallel port NumParallelPorts = IoGetConfigurationInformation()->ParallelCount; for( NtDeviceNumber=0; NtDeviceNumber<NumParallelPorts; NtDeviceNumber++) { status = DongCreateDevice( pDriverObject, NtDeviceNumber); if( !NT_SUCCESS(status)) return status; } // Log that we've started // ... return status; } static NTSTATUS DongCreateDevice ( IN PDRIVER_OBJECT pDriverObject, IN ULONG NtDeviceNumber ) { NTSTATUS status; PDEVICE_OBJECT pDevObj; PDEVICE_EXTENSION pDevExt; UNICODE_STRING deviceName, portName, linkName, number; WCHAR deviceNameBuffer[DONG_MAX_NAME_LENGTH]; WCHAR portNameBuffer[DONG_MAX_NAME_LENGTH]; WCHAR linkNameBuffer[DONG_MAX_NAME_LENGTH]; WCHAR numberBuffer[10]; PFILE_OBJECT pFileObject; // Initialise strings number.Buffer = numberBuffer; number.MaximumLength = 20; deviceName.Buffer = deviceNameBuffer; deviceName.MaximumLength = DONG_MAX_NAME_LENGTH*2; portName.Buffer = portNameBuffer; portName.MaximumLength = DONG_MAX_NAME_LENGTH*2; linkName.Buffer = linkNameBuffer; linkName.MaximumLength = DONG_MAX_NAME_LENGTH*2; ///////////////////////////////////////////////////////////////////////// // Form the base NT device name... deviceName.Length = 0; RtlAppendUnicodeToString( &deviceName, DONG_NT_DEVICE_NAME); number.Length = 0; RtlIntegerToUnicodeString( NtDeviceNumber, 10, &number); RtlAppendUnicodeStringToString( &deviceName, &number); // Create a Device object for this device... status = IoCreateDevice( pDriverObject, sizeof( DEVICE_EXTENSION ), &deviceName, FILE_DEVICE_PARALLEL_PORT, 0, TRUE, &pDevObj); if( !NT_SUCCESS(status)) { DongReportUnexpectedFailure(DONG_ERRORLOG_INIT,DONG_INIT_IoCreateDevice); return status; } ///////////////////////////////////////////////////////////////////////// // Use buffered I/O pDevObj->Flags |= DO_BUFFERED_IO; ///////////////////////////////////////////////////////////////////////// // Initialize the Device Extension pDevExt = pDevObj->DeviceExtension; RtlZeroMemory(pDevExt, sizeof(DEVICE_EXTENSION)); pDevExt->DeviceObject = pDevObj; pDevExt->NtDeviceNumber = NtDeviceNumber; ///////////////////////////////////////////////////////////////////////// // Attach to parport device portName.Length = 0; RtlAppendUnicodeToString( &portName, DONG_NT_PORT_DEVICE_NAME); number.Length = 0; RtlIntegerToUnicodeString( NtDeviceNumber, 10, &number); RtlAppendUnicodeStringToString( &portName, &number); status = IoGetDeviceObjectPointer(&portName, FILE_READ_ATTRIBUTES, &pFileObject, &pDevExt->PortDeviceObject); if (!NT_SUCCESS(status)) { IoDeleteDevice(pDevObj); DongReportUnexpectedFailure(DONG_ERRORLOG_INIT,DONG_INIT_IoGetDeviceObjectPointer); return status; } ObReferenceObjectByPointer( pDevExt->PortDeviceObject,FILE_READ_ATTRIBUTES, NULL,KernelMode); ObDereferenceObject(pFileObject); pDevExt->DeviceObject->StackSize = pDevExt->PortDeviceObject->StackSize + 1; // Get the port information from the port device object. status = DongGetPortInfoFromPortDevice(pDevExt); if (!NT_SUCCESS(status)) { IoDeleteDevice(pDevObj); return status; } ///////////////////////////////////////////////////////////////////////// // Form the Win32 symbolic link name. linkName.Length = 0; RtlAppendUnicodeToString( &linkName, DONG_WIN32_DEVICE_NAME); number.Length = 0; RtlIntegerToUnicodeString( NtDeviceNumber + 1, 10, &number); RtlAppendUnicodeStringToString( &linkName, &number); // Create a symbolic link so our device is visible to Win32... status = IoCreateSymbolicLink( &linkName, &deviceName); if( !NT_SUCCESS(status)) { IoDeleteDevice( pDevObj ); DongReportUnexpectedFailure(DONG_ERRORLOG_INIT,DONG_INIT_IoCreateSymbolicLink); return status; } return status; } static NTSTATUS DongGetPortInfoFromPortDevice( IN OUT PDEVICE_EXTENSION pDevExt ) { KEVENT event; PIRP irp; PARALLEL_PORT_INFORMATION portInfo; IO_STATUS_BLOCK ioStatus; NTSTATUS status; ///////////////////////////////////////////////////////////////////////// // Get parallel port information KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest( IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO, pDevExt->PortDeviceObject, NULL, 0, &portInfo, sizeof(PARALLEL_PORT_INFORMATION), TRUE, &event, &ioStatus); if (!irp) { DongReportUnexpectedFailure(DONG_ERRORLOG_INIT,DONG_INIT_IoBuildDeviceIoControlRequest); return STATUS_INSUFFICIENT_RESOURCES; } status = IoCallDriver(pDevExt->PortDeviceObject, irp); if (!NT_SUCCESS(status)) { DongReportUnexpectedFailure(DONG_ERRORLOG_INIT,DONG_INIT_IoCallDriver); return status; } status = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); if (!NT_SUCCESS(status)) { DongReportUnexpectedFailure(DONG_ERRORLOG_INIT,DONG_INIT_KeWaitForSingleObject); return status; } pDevExt->OriginalController = portInfo.OriginalController; pDevExt->Controller = portInfo.Controller; pDevExt->SpanOfController = portInfo.SpanOfController; pDevExt->FreePort = portInfo.FreePort; pDevExt->TryAllocatePort = portInfo.TryAllocatePort; pDevExt->PortContext = portInfo.Context; // Check register span if (pDevExt->SpanOfController < DONG_REGISTER_SPAN) { DongReportUnexpectedFailure(DONG_ERRORLOG_INIT,DONG_INIT_RegisterSpan); return STATUS_INSUFFICIENT_RESOURCES; } return STATUS_SUCCESS; }