⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util.c

📁 win2k kernel 的并口驱动程序模板
💻 C
📖 第 1 页 / 共 3 页
字号:
#pragma warning( disable : 4054 4055 4152 )
    return IoSetCancelRoutine(Irp, CancelRoutine);
    // #pragma warning( pop )
}

BOOLEAN
CheckPort(
    IN  PUCHAR  wPortAddr,
    IN  UCHAR   bMask,
    IN  UCHAR   bValue,
    IN  USHORT  usTimeDelay
    )
/*++

Routine Description:
    This routine will loop for a given time period (actual time is
    passed in as an arguement) and wait for the dsr to match
    predetermined value (dsr value is passed in).

Arguments:
    wPortAddr   - Supplies the base address of the parallel port + some offset.
                  This will have us point directly to the dsr (controller + 1).
    bMask       - Mask used to determine which bits we are looking at
    bValue      - Value we are looking for.
    usTimeDelay - Max time to wait for peripheral response (in us)

Return Value:
    TRUE if a dsr match was found.
    FALSE if the time period expired before a match was found.
--*/

{
    UCHAR  dsr;
    LARGE_INTEGER   Wait;
    LARGE_INTEGER   Start;
    LARGE_INTEGER   End;

    // Do a quick check in case we have one stinkingly fast peripheral!
    dsr = READ_PORT_UCHAR(wPortAddr);
    if ((dsr & bMask) == bValue)
        return TRUE;

    Wait.QuadPart = (usTimeDelay * 10 * 10) + KeQueryTimeIncrement();
    KeQueryTickCount(&Start);

CheckPort_Start:
    KeQueryTickCount(&End);
    dsr = READ_PORT_UCHAR(wPortAddr);
    if ((dsr & bMask) == bValue)
        return TRUE;

    if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() > Wait.QuadPart)
    {
        // We timed out!!!

        #if DBG
            PptDump2(PARERRORS, ("CheckPort: Timeout\n"));
            PptDump2(PARERRORS, ("<==========================================================\n"));
            {
                int i;

                for (i = 3; i < 8; i++) {
        
                    if ((bMask >> i) & 1) {
                    
                        if (((bValue >> i) & 1) !=  ((dsr >> i) & 1)) {
                        
                            PptDump2(PARERRORS, ("\t\t Bit %d is %d and should be %d!!!\n",
                                        i, (dsr >> i) & 1, (bValue >> i) & 1));
                        }
                    }
                }
            }
            PptDump2(PARERRORS, ("<==========================================================\n"));
        #endif
        goto CheckPort_TimeOut;
    }
    goto CheckPort_Start;

CheckPort_TimeOut:
    return FALSE;    
}

NTSTATUS
PptBuildParallelPortDeviceName(
    IN  ULONG           Number,
    OUT PUNICODE_STRING DeviceName
    )
/*++
      
Routine Description:
      
    Build a Device Name of the form: \Device\ParallelPortN
      
    *** On success this function returns allocated memory that must be freed by the caller

Arguments:
      
    DriverObject          - ParPort driver object
    PhysicalDeviceObject  - PDO whose stack the ParPort FDO will attach to
    DeviceObject          - ParPort FDO
    UniNameString         - the DeviceName (e.g., \Device\ParallelPortN)
    PortName              - the "LPTx" PortName from the devnode
    PortNumber            - the "N" in \Device\ParallelPortN
      
Return Value:
      
    STATUS_SUCCESS on success

    error status otherwise
      
--*/
{
    UNICODE_STRING      uniDeviceString;
    UNICODE_STRING      uniBaseNameString;
    UNICODE_STRING      uniPortNumberString;
    WCHAR               wcPortNum[10];
    NTSTATUS            status;

    PptDump2(PARPNP1, ("util::PptBuildParallelPortDeviceName - Enter - Number=%d\n", Number) );

    //
    // Init strings
    //
    RtlInitUnicodeString( DeviceName, NULL );
    RtlInitUnicodeString( &uniDeviceString, (PWSTR)L"\\Device\\" );
    RtlInitUnicodeString( &uniBaseNameString, (PWSTR)DD_PARALLEL_PORT_BASE_NAME_U );


    //
    // Convert Port Number to UNICODE_STRING
    //
    uniPortNumberString.Length        = 0;
    uniPortNumberString.MaximumLength = sizeof( wcPortNum );
    uniPortNumberString.Buffer        = wcPortNum;

    status = RtlIntegerToUnicodeString( Number, 10, &uniPortNumberString);
    if( !NT_SUCCESS( status ) ) {
        PptDump2(PARERRORS, ("util::PptBuildParallelPortDeviceName - RtlIntegerToUnicodeString FAILED\n") );
        return status;
    }


    //
    // Compute size required and alloc a buffer
    //
    DeviceName->MaximumLength = (USHORT)( uniDeviceString.Length +
                                          uniBaseNameString.Length +
                                          uniPortNumberString.Length +
                                          sizeof(UNICODE_NULL) );

    DeviceName->Buffer = ExAllocatePool( PagedPool, DeviceName->MaximumLength );
    if( NULL == DeviceName->Buffer ) {
        PptDump2(PARERRORS, ("util::PptBuildParallelPortDeviceName - Alloc Buffer FAILED\n") );
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory( DeviceName->Buffer, DeviceName->MaximumLength );


    //
    // Catenate the parts to construct the DeviceName
    //
    RtlAppendUnicodeStringToString(DeviceName, &uniDeviceString);
    RtlAppendUnicodeStringToString(DeviceName, &uniBaseNameString);
    RtlAppendUnicodeStringToString(DeviceName, &uniPortNumberString);

    return STATUS_SUCCESS;
}

NTSTATUS
PptInitializeDeviceExtension(
    IN PDRIVER_OBJECT  DriverObject,
    IN PDEVICE_OBJECT  PhysicalDeviceObject,
    IN PDEVICE_OBJECT  DeviceObject,
    IN PUNICODE_STRING UniNameString,
    IN PWSTR           PortName,
    IN ULONG           PortNumber
    )
/*++
      
Routine Description:
      
    Initialize a ParPort FDO DeviceExtension
      
Arguments:
      
    DriverObject          - ParPort driver object
    PhysicalDeviceObject  - PDO whose stack the ParPort FDO will attach to
    DeviceObject          - ParPort FDO
    UniNameString         - the DeviceName (e.g., \Device\ParallelPortN)
    PortName              - the "LPTx" PortName from the devnode
    PortNumber            - the "N" in \Device\ParallelPortN
      
Return Value:
      
    STATUS_SUCCESS on success

    error status otherwise
      
--*/
{
    PDEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;

    RtlZeroMemory( Extension, sizeof(DEVICE_EXTENSION) );

    //
    // ExtensionSignature helps confirm that we are looking at a Parport DeviceExtension
    //
    Extension->ExtensionSignatureBegin = 0x78877887; 
    Extension->ExtensionSignatureEnd   = 0x87788778; 

    //
    // Standard Info
    //
    Extension->DriverObject         = DriverObject;
    Extension->PhysicalDeviceObject = PhysicalDeviceObject;
    Extension->DeviceObject         = DeviceObject;
    Extension->PnpInfo.PortNumber   = PortNumber; // this is the "N" in \Device\ParallelPortN

    //
    // Mutual Exclusion initialization
    //
    IoInitializeRemoveLock(&Extension->RemoveLock, PARPORT_POOL_TAG, 1, 10);
    ExInitializeFastMutex(&Extension->OpenCloseMutex);
    ExInitializeFastMutex(&Extension->ExtensionFastMutex);

    //
    // chipset detection initialization - redundant, but safer
    //
    Extension->NationalChipFound = FALSE;
    Extension->NationalChecked   = FALSE;

    //
    // Initialize 'WorkQueue' - a Queue for Allocate and Select requests
    //
    InitializeListHead(&Extension->WorkQueue);
    Extension->WorkQueueCount = -1;

    //
    // Initialize Exports - Exported via Internal IOCTLs
    //
    Extension->PortInfo.FreePort            = PptFreePort;
    Extension->PortInfo.TryAllocatePort     = PptTryAllocatePort;
    Extension->PortInfo.QueryNumWaiters     = PptQueryNumWaiters;
    Extension->PortInfo.Context             = Extension;

    Extension->PnpInfo.HardwareCapabilities = PPT_NO_HARDWARE_PRESENT;
    Extension->PnpInfo.TrySetChipMode       = PptSetChipMode;
    Extension->PnpInfo.ClearChipMode        = PptClearChipMode;
    Extension->PnpInfo.TrySelectDevice      = PptTrySelectDevice;
    Extension->PnpInfo.DeselectDevice       = PptDeselectDevice;
    Extension->PnpInfo.Context              = Extension;
    Extension->PnpInfo.PortName             = PortName;

    //
    // List of devices to report in reponse to 
    //   QUERY_DEVICE_RELATIONS/RemovalRelations
    //
    InitializeListHead( &Extension->RemovalRelationsList );

    //
    // Empty list of interrupt service routines, interrupt NOT connected
    //
    InitializeListHead( &Extension->IsrList );
    Extension->InterruptObject   = NULL;
    Extension->InterruptRefCount = 0;

    //
    // Initialize the free port DPC.
    //
    KeInitializeDpc( &Extension->FreePortDpc, PptFreePortDpc, Extension );

    //
    // Save Device Name in our extension
    //
    {
        ULONG bufferLength = UniNameString->MaximumLength + sizeof(UNICODE_NULL);
        Extension->DeviceName.Buffer = ExAllocatePool(NonPagedPool, bufferLength);
        if( !Extension->DeviceName.Buffer ) {
            return STATUS_INSUFFICIENT_RESOURCES;
        }
        RtlZeroMemory( Extension->DeviceName.Buffer, bufferLength );
        Extension->DeviceName.Length        = 0;
        Extension->DeviceName.MaximumLength = UniNameString->MaximumLength;
        RtlCopyUnicodeString( &Extension->DeviceName, UniNameString );
    }

    //
    // Port is in default mode and mode has not been set 
    //   by a lower filter driver
    //
    Extension->PnpInfo.CurrentMode  = INITIAL_MODE;
    Extension->FilterMode           = FALSE;

    return STATUS_SUCCESS;
}

NTSTATUS
PptGetPortNumberFromLptName( 
    IN  PWSTR  PortName, 
    OUT PULONG PortNumber 
    )
/*++
      
Routine Description:
      
    Verify that the LptName is of the form LPTn, if so then return
    the integer value of n
      
Arguments:
      
    PortName   - the PortName extracted from the devnode - expected to be 
                   of the form: "LPTn"

    PortNumber - points to the UNLONG that will hold the result on success
      
Return Value:
      
    STATUS_SUCCESS on success - *PortNumber will contain the integer value of n

    error status otherwise
      
--*/
{
    NTSTATUS       status;
    UNICODE_STRING str;

    //
    // Verify that the PortName looks like LPTx where x is a number
    //

    if( PortName[0] != L'L' || PortName[1] != L'P' || PortName[2] != L'T' ) {
        PptDump2(PARPNP1, ("util::PptGetPortNumberFromLptName - name prefix doesn't look like LPT\n"));
        return STATUS_UNSUCCESSFUL;
    }

    //
    // prefix is LPT, check for integer suffix with value > 0
    //
    RtlInitUnicodeString( &str, (PWSTR)&PortName[3] );

    status = RtlUnicodeStringToInteger( &str, 10, PortNumber );

    if( !NT_SUCCESS( status ) ) {
        PptDump2(PARPNP1, ("util::PptGetPortNumberFromLptName - name suffix doesn't look like an integer\n"));
        return STATUS_UNSUCCESSFUL;
    }

    if( *PortNumber == 0 ) {
        PptDump2(PARPNP1, ("util::PptGetPortNumberFromLptName - name suffix == 0 - FAIL - Invalid value\n"));
        return STATUS_UNSUCCESSFUL;
    }

    PptDump2(PARPNP1, ("util::PptGetPortNumberFromLptName - LPT name suffix= %d\n", *PortNumber));

    return STATUS_SUCCESS;
}

PDEVICE_OBJECT
PptBuildDeviceObject( 
    IN PDRIVER_OBJECT DriverObject, 
    IN PDEVICE_OBJECT PhysicalDeviceObject 
    )
/*++
      
Routine Description:
      
    This routine constructs and initializes a parport FDO
      
Arguments:
      
    DriverObject         - Pointer to the parport driver object
    PhysicalDeviceObject - Pointer to the PDO whose stack we will attach to
      
Return Value:
      
    Pointer to the new ParPort Device Object on Success

    NULL otherwise
      
--*/
{
    UNICODE_STRING      uniNameString = {0,0,0};
    ULONG               portNumber    = 0;
    PWSTR               portName      = NULL;
    NTSTATUS            status        = STATUS_SUCCESS;
    PDEVICE_OBJECT      deviceObject = NULL;

    PptDump2(PARPNP1, ("util::PptBuildDeviceObject - Enter\n"));

    //
    // Get the LPTx name for this port from the registry.
    //
    // The initial LPTx name for a port is determined by the ports class installer 
    //   msports.dll, but the name can subsequently be changed by the user via
    //   a device manager property page.
    //
    portName = PptGetPortNameFromPhysicalDeviceObject( PhysicalDeviceObject );
    if( NULL == portName ) {
        PptDump2(PARERRORS, ("util::PptBuildDeviceObject - get LPTx Name from registry - FAILED\n") );
        goto targetExit;
    }

    PptDump2(PARPNP1, ("util::PptBuildDeviceObject - portName = <%S>\n", portName));

    //
    // Extract the preferred port number N to use for the \Device\ParallelPortN 
    //   DeviceName from the LPTx name
    //
    // Preferred DeviceName for LPT(n) is ParallelPort(n-1) - e.g., LPT3 -> ParallelPort2
    //
    status = PptGetPortNumberFromLptName( portName, &portNumber );
    if( !NT_SUCCESS( status ) ) {
        PptDump2(PARERRORS, ("util::PptBuildDeviceObject - extract portNumber from LPTx Name - FAILED\n") );
        ExFreePool( portName );
        goto targetExit;
    }
    --portNumber;               // convert 1 (LPT) based number to 0 (ParallelPort) based number
    PptDump2(PARPNP1, ("util::PptBuildDeviceObject - portNumber (after decrement) = %d\n", portNumber));

    //
    // Build a DeviceName of the form: \Device\ParallelPortN
    //
    status = PptBuildParallelPortDeviceName(portNumber, &uniNameString);
    if( !NT_SUCCESS( status ) ) {
        // we couldn't make up a name - bail out
        PptDump2(PARERRORS, ("util::PptBuildDeviceObject - Build ParallelPort DeviceName - FAILED\n") );
        ExFreePool( portName );
        goto targetExit;
    }

    PptDump2(PARPNP1, ("util::PptBuildDeviceObject - uniNameString = <%wZ>\n", &uniNameString));

    //
    // Create the device object for this device.
    //
    status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &uniNameString, 
                            FILE_DEVICE_PARALLEL_PORT, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject);

    
    if( STATUS_OBJECT_NAME_COLLISION == status ) {
        //
        // Preferred DeviceName already exists - try made up names
        // 

        PptDump2(PARPNP1, ("util::PptBuildDeviceObject - Initial Device Creation FAILED - Name Collision\n"));

        //
        // use an offset so that our made up names won't collide with 
        //   the preferred names of ports that have not yet started
        //   (start with ParallelPort8)
        //
        #define PPT_CLASSNAME_OFFSET 7
        portNumber = PPT_CLASSNAME_OFFSET;

        do {
            RtlFreeUnicodeString( &uniNameString );
            ++portNumber;
            status = PptBuildParallelPortDeviceName(portNumber, &uniNameString);
            if( !NT_SUCCESS( status ) ) {
                // we couldn't make up a name - bail out
                PptDump2(PARERRORS, ("util::PptBuildDeviceObject - Build ParallelPort DeviceName - FAILED\n") );
                ExFreePool( portName );
                goto targetExit;
            }
            PptDump2(PARPNP1, ("util::PptBuildDeviceObject - Trying Device Creation <%wZ>\n", &uniNameString));
            status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &uniNameString, 
                                    FILE_DEVICE_PARALLEL_PORT, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject);

        } while( STATUS_OBJECT_NAME_COLLISION == status );
    }

    if( !NT_SUCCESS( status ) ) {
        // we got a failure other than a name collision - bail out
        PptDump2(PARPNP1, ("util::PptBuildDeviceObject - Device Creation FAILED - status=%x\n", status));
        deviceObject = NULL;
        ExFreePool( portName );
        goto targetExit;
    }

    //
    // We have a deviceObject - Initialize DeviceExtension
    //
    status = PptInitializeDeviceExtension( DriverObject, PhysicalDeviceObject, deviceObject, 
                                           &uniNameString, portName, portNumber );
    if( !NT_SUCCESS( status ) ) {
        // failure initializing the device extension - clean up and bail out
        PptDump2(PARPNP1, ("util::PptBuildDeviceObject - Device Initialization FAILED - status=%x\n", status));
        IoDeleteDevice( deviceObject );
        deviceObject = NULL;
        ExFreePool( portName );
        goto targetExit;
    }

    //
    // Propagate the power pagable flag of the PDO to our new FDO
    //
    if( PhysicalDeviceObject->Flags & DO_POWER_PAGABLE ) {
        deviceObject->Flags |= DO_POWER_PAGABLE;
    }

    PptDump2(PARPNP1, ("util::PptBuildDeviceObject - SUCCESS - deviceObject= %x\n", deviceObject));

targetExit:

    RtlFreeUnicodeString( &uniNameString );

    return deviceObject;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -