/*************************************************************************** Copyright (c) 2000 Microsoft Corporation Module Name: Parport.sys - Parallel port (IEEE 1284, IEEE 1284.3) driver. File Name: driverEntry.c Abstract: DriverEntry routine - driver initialization Environment: Kernel mode only Notes: THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. Copyright (c) 2000 Microsoft Corporation. All Rights Reserved. Revision History: 2000-07-25 - Doug Fritz - code cleanup, add comments, add copyright Author(s): Doug Fritz ****************************************************************************/ #include "pch.h" /************************************************************************/ /* DriverEntry */ /************************************************************************/ // // Routine Description: // // This is the DriverEntry routine -- the first function called // after the driver has been loaded into memory. // // Arguments: // // DriverObject - points to the DRIVER_OBJECT for this driver // RegPath - the service registry key for this driver // // Return Value: // // STATUS_SUCCESS - on success // STATUS_NO_MEMORY - if unable to allocate pool // // Notes: // // Log: // /************************************************************************/ NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath ) { // // Save a copy of *RegPath in driver global RegistryPath for future reference. // // UNICODE_NULL terminate the path so that we can safely use RegistryPath.Buffer // as a PWSTR. // { USHORT size = RegPath->Length + sizeof(WCHAR); RegistryPath.Buffer = ExAllocatePool( (PagedPool | POOL_COLD_ALLOCATION), size ); if( NULL == RegistryPath.Buffer ) { return STATUS_NO_MEMORY; } RegistryPath.Length = 0; RegistryPath.MaximumLength = size; RtlCopyUnicodeString( &RegistryPath, RegPath ); RegistryPath.Buffer[ size/sizeof(WCHAR) - 1 ] = UNICODE_NULL; } // // Initialize Driver Globals // // Non-zero means don't raise IRQL from PASSIVE_LEVEL to DISPATCH_LEVEL // when doing CENTRONICS mode (SPP) writes. SppNoRaiseIrql = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"SppNoRaiseIrql", &SppNoRaiseIrql ); // Non-zero means override CENTRONICS as the default Forward mode and/or NIBBLE as // the default Reverse mode. Valid modes are those defined in ntddpar.h as // parameters for IOCTL_IEEE1284_NEGOTIATE. // *** Warning: invalid settings and/or setting/device incompatibilities can render // the port unusable until the settings are corrected DefaultModes = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"DefaultModes", &DefaultModes ); // Set tracing level for driver DbgPrint messages. Trace values defined in debug.h. // Zero means no trace output. Trace = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"Trace", &Trace ); // Request DbgBreakPoint on driver events. Event values defined in debug.h. // Zero means no breakpoints requested. Break = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"Break", &Break ); // Mask OFF debug spew for specific devices. See debug.h for flag definitions // 0 means allow debug spew for that device // ~0 means mask OFF all (show NO) debug spew for that device type DbgMaskFdo = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"DbgMaskFdo", &DbgMaskFdo ); DbgMaskRawPort = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"DbgMaskRawPort", &DbgMaskRawPort ); DbgMaskDaisyChain0 = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"DbgMaskDaisyChain0", &DbgMaskDaisyChain0 ); DbgMaskDaisyChain1 = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"DbgMaskDaisyChain1", &DbgMaskDaisyChain1 ); DbgMaskEndOfChain = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"DbgMaskEndOfChain", &DbgMaskEndOfChain ); DbgMaskLegacyZip = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"DbgMaskLegacyZip", &DbgMaskLegacyZip ); DbgMaskNoDevice = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"DbgMaskNoDevice", &DbgMaskNoDevice ); #if 1 == DBG_SHOW_BYTES DbgShowBytes = 1; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"DbgShowBytes", &DbgShowBytes ); #endif // // Allow asserts? non-zero means allow assertions // AllowAsserts = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"AllowAsserts", &AllowAsserts ); // Non-zero means enable detection of Iomega Legacy Zip-100 drives that use // an Iomega proprietary Select/Deselect mechanism rather than the Select/Deselect // mechanism defined by IEEE 1284.3. (These drives pre-date IEEE 1284.3) // *** Note: if zero, this registry setting is checked again during every PnP QDR/BusRelations // query to see if the user has enabled detection via the Ports property page "Enable // legacy Plug and Play detection" checkbox. ParEnableLegacyZip = 0; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"ParEnableLegacyZip", &ParEnableLegacyZip ); // Default timeout when trying to acquire exclusive access to the (shared) port { const ULONG halfSecond = 500; // in milliseconds const ULONG fiveSeconds = 5000; ULONG requestedTimeout = halfSecond; PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"AcquirePortTimeout", &requestedTimeout ); if( requestedTimeout < halfSecond ) { requestedTimeout = halfSecond; } else if( requestedTimeout > fiveSeconds ) { requestedTimeout = fiveSeconds; } PPT_SET_RELATIVE_TIMEOUT_IN_MILLISECONDS( AcquirePortTimeout, requestedTimeout ); } { // // register for callbacks so that we can detect switch between // AC and battery power and tone done "polling for printers" // when machine switches to battery power. // OBJECT_ATTRIBUTES objAttributes; UNICODE_STRING callbackName; NTSTATUS localStatus; RtlInitUnicodeString(&callbackName, L"\\Callback\\PowerState"); InitializeObjectAttributes(&objAttributes, &callbackName, OBJ_CASE_INSENSITIVE, NULL, NULL); localStatus = ExCreateCallback(&PowerStateCallbackObject, &objAttributes, FALSE, TRUE); if( STATUS_SUCCESS == localStatus ) { PowerStateCallbackRegistration = ExRegisterCallback(PowerStateCallbackObject, PowerStateCallback, NULL); } } // // Set dispatch table entries for IRP_MJ_* functions that we handle // DriverObject->MajorFunction[ IRP_MJ_CREATE ] = PptDispatchCreateOpen; DriverObject->MajorFunction[ IRP_MJ_CLOSE ] = PptDispatchClose; DriverObject->MajorFunction[ IRP_MJ_CLEANUP ] = PptDispatchCleanup; DriverObject->MajorFunction[ IRP_MJ_READ ] = PptDispatchRead; DriverObject->MajorFunction[ IRP_MJ_WRITE ] = PptDispatchWrite; DriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = PptDispatchDeviceControl; DriverObject->MajorFunction[ IRP_MJ_INTERNAL_DEVICE_CONTROL ] = PptDispatchInternalDeviceControl; DriverObject->MajorFunction[ IRP_MJ_QUERY_INFORMATION ] = PptDispatchQueryInformation; DriverObject->MajorFunction[ IRP_MJ_SET_INFORMATION ] = PptDispatchSetInformation; DriverObject->MajorFunction[ IRP_MJ_PNP ] = PptDispatchPnp; DriverObject->MajorFunction[ IRP_MJ_POWER ] = PptDispatchPower; DriverObject->MajorFunction[ IRP_MJ_SYSTEM_CONTROL ] = PptDispatchSystemControl; DriverObject->DriverExtension->AddDevice = P5AddDevice; DriverObject->DriverUnload = PptUnload; // // Break on user request // (typically via registry setting ...\Services\Parport\Parameters : Break : REG_DWORD : 0x1) // // This is a useful breakpoint in order to manually set appropriate breakpoints elsewhere in the driver. // PptBreakOnRequest( PPT_BREAK_ON_DRIVER_ENTRY, ("PPT_BREAK_ON_DRIVER_ENTRY - BreakPoint requested") ); DD(NULL,DDT,"Parport DriverEntry - SUCCESS\n"); return STATUS_SUCCESS; }