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

📄 pnputils.c

📁 鼠标Windows驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
#include "pch.h"

VOID
P5WorkItemFreePort( PDEVICE_OBJECT Fdo, PFDO_EXTENSION Fdx ) {
    PIO_WORKITEM workItem;

    UNREFERENCED_PARAMETER( Fdo );

    workItem = InterlockedExchangePointer( &Fdx->FreePortWorkItem, NULL );
    if( workItem ) {
        IoFreeWorkItem( workItem );
    }
    
    PptFreePort( Fdx );
}

BOOLEAN
P5SelectDaisyChainDevice(
    IN  PUCHAR  Controller,
    IN  UCHAR   DeviceId
    )
{
    const ULONG  maxRetries = 4;
    ULONG        retryCount = 0;
    BOOLEAN      selected   = FALSE;
    DD(NULL,DDE,"P5SelectDaisyChainDevice %x %d\n",Controller,DeviceId);
    while( !selected && retryCount < maxRetries ) {
        selected = PptSend1284_3Command( Controller, (UCHAR)(CPP_SELECT | DeviceId) );
        ++retryCount;
    }
    return selected;
}

BOOLEAN
P5DeselectAllDaisyChainDevices(
    IN  PUCHAR  Controller
    )
{
    const ULONG  maxRetries = 4;
    ULONG        retryCount = 0;
    BOOLEAN      deselected = FALSE;
    DD(NULL,DDE,"P5DeselectAllDaisyChainDevices %x\n",Controller);
    while( !deselected && retryCount < maxRetries ) {
        deselected = PptSend1284_3Command( Controller, (UCHAR)CPP_DESELECT );
        ++retryCount;
    }
    return deselected;
}

VOID
P5DeletePdoSymLink(
    IN  PDEVICE_OBJECT  Pdo
    )
//
// clean up symbolic link so we can reuse it immediately for a new PDO
//
{
    PPDO_EXTENSION  pdx = Pdo->DeviceExtension;

    if( pdx->SymLinkName ) {
        UNICODE_STRING  uniSymLinkName;
        NTSTATUS        status;

        DD((PCE)pdx,DDE,"P5DeletePdoSymLink\n");

        RtlInitUnicodeString( &uniSymLinkName, pdx->SymLinkName );
        status = IoDeleteSymbolicLink( &uniSymLinkName );
        PptAssert( STATUS_SUCCESS == status );
        ExFreePool( pdx->SymLinkName );
        pdx->SymLinkName = NULL;
    }

    return;
}

VOID
P5MarkPdoAsHardwareGone(
    IN  PDEVICE_OBJECT  Fdo,
    IN  enum _PdoType   PdoType,
    IN  ULONG           DaisyChainId  OPTIONAL // ignored if PdoType != PdoTypeDaisyChain
    )
{
    PFDO_EXTENSION  fdx = Fdo->DeviceExtension;
    PPDO_EXTENSION  pdx;
    PDEVICE_OBJECT  pdo;

    switch( PdoType ) {

    case PdoTypeRawPort:

        DD((PCE)fdx,DDE,"P5MarkPdoAsHardwareGone - PdoTypeRawPort\n");
        pdo = fdx->RawPortPdo;
        fdx->RawPortPdo = NULL;
        break;

    case PdoTypeEndOfChain:

        DD((PCE)fdx,DDE,"P5MarkPdoAsHardwareGone - PdoTypeEndOfChain\n");
        pdo = fdx->EndOfChainPdo;
        fdx->EndOfChainPdo = NULL;
        break;

    case PdoTypeDaisyChain:

        PptAssert( (0 == DaisyChainId) || (1 == DaisyChainId) );
        DD((PCE)fdx,DDE,"P5MarkPdoAsHardwareGone - PdoTypeDaisyChain - %d\n",DaisyChainId);
        pdo = fdx->DaisyChainPdo[ DaisyChainId ];
        fdx->DaisyChainPdo[ DaisyChainId ] = NULL;
        break;

    case PdoTypeLegacyZip:

        DD((PCE)fdx,DDE,"P5MarkPdoAsHardwareGone - PdoTypeLegacyZip\n");
        pdo = fdx->LegacyZipPdo;
        fdx->LegacyZipPdo = NULL;
        break;

    default:

        DD((PCE)fdx,DDE,"P5MarkPdoAsHardwareGone - Invalid PdoType parameter\n",FALSE);
        PptAssertMsg("P5MarkPdoAsHardwareGone - Invalid PdoType parameter",FALSE);
        return;

    }

    pdx = pdo->DeviceExtension;
    P5DeletePdoSymLink( pdo );
    InsertTailList( &fdx->DevDeletionListHead, &pdx->DevDeletionList );
    pdx->DeleteOnRemoveOk = TRUE;

    return;
}

BOOLEAN
P5IsDeviceStillThere( 
    IN  PDEVICE_OBJECT  Fdo,
    IN  PDEVICE_OBJECT  Pdo
    )
//
// Is the Pdo device still connected to the port represented by the Fdo?
//
// N.B. Fdo must own (have locked for exclusive access) the port before calling this function
//   or we can corrupt the data stream and hang devices connected to the port
//
{
    PFDO_EXTENSION  fdx              = Fdo->DeviceExtension;
    PPDO_EXTENSION  pdx              = Pdo->DeviceExtension;
    BOOLEAN         deviceStillThere = FALSE;
    PCHAR           devIdString      = NULL;
    PUCHAR          controller       = fdx->PortInfo.Controller;
        
    PptAssert( DevTypeFdo == fdx->DevType );
    PptAssert( DevTypePdo == pdx->DevType );

    //
    // Select device if needed, pull a fresh 1284 device ID string
    // from the device, and compare the Mfg and Mdl from the fresh
    // device ID with those stored in our extension. If the Mfg and
    // Mdl fields match then the device is still there.
    //

    switch( pdx->PdoType ) {

    case PdoTypeRawPort:
        
        // raw port is always present - it's a virtual device
        DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeRawPort - StillThere\n");
        deviceStillThere = TRUE;
        break;
        
    case PdoTypeLegacyZip:
        
        deviceStillThere = P5LegacyZipDetected( fdx->PortInfo.Controller );
        if( deviceStillThere ) {
            DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeLegacyZip - StillThere\n");
        } else {
            DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeLegacyZip - Gone\n");
        }
        break;
    
    case PdoTypeDaisyChain:
            
        //
        // Select device, pull a fresh 1284 device ID string
        // from the device, and compare the Mfg and Mdl from the fresh
        // device ID with those stored in our extension. If the Mfg and
        // Mdl fields match then the device is still there.
        //

        {
            UCHAR daisyChainId = pdx->Ieee1284_3DeviceId;

            // select device
            if( P5SelectDaisyChainDevice( controller, daisyChainId ) ) {

                BOOLEAN         bBuildStlDeviceId = FALSE;
                PPDO_EXTENSION  dummyPdx          = NULL;

                devIdString = NULL;

                // do a check to see if this is an SCM Micro device
                dummyPdx = ExAllocatePool( PagedPool, sizeof(PDO_EXTENSION) );
                if( dummyPdx != NULL ) {
                    RtlZeroMemory( dummyPdx, sizeof(PDO_EXTENSION) );
                    dummyPdx->Controller = fdx->PortInfo.Controller;
                    bBuildStlDeviceId = ParStlCheckIfStl( dummyPdx, daisyChainId );

                    if( bBuildStlDeviceId ) {
                        // SCM Micro device
                        ULONG DeviceIdSize;
                        devIdString = ParStlQueryStlDeviceId( dummyPdx, NULL, 0,&DeviceIdSize, TRUE );
                    } else {
                        // non-SCM Micro device
                        devIdString = P4ReadRawIeee1284DeviceId( controller );
                    }
                    ExFreePool( dummyPdx );
                }

                if( devIdString ) {
                    // got a 1284 device ID string from the device
                    PCHAR mfg, mdl, cls, des, aid, cid;
                    ParPnpFindDeviceIdKeys( &mfg, &mdl, &cls, &des, &aid, &cid, devIdString+2 );
                    if( mfg && mdl ) {
                        // we have a device, is it the same device?
                        if( (0 == strcmp( mfg, pdx->Mfg )) && (0 == strcmp( mdl, pdx->Mdl )) ) {
                            // same device
                            DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeDaisyChain %d - StillThere\n",daisyChainId);
                            deviceStillThere = TRUE;
                        } else {
                            // different device - IDs don't match
                            DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeDaisyChain %d - Gone - diff 1284 ID\n",daisyChainId);
                            deviceStillThere = FALSE;
                        }
                    } else {
                        // either mfg or mdl field not found
                        DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeDaisyChain %d - Gone - bad 1284 ID\n",daisyChainId);
                        deviceStillThere = FALSE;
                    }
                    // don't forget to free temp pool
                    ExFreePool( devIdString );
                    
                } else {
                    // unable to get a 1284 device ID string from the device
                    DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeDaisyChain %d - Gone - no 1284 ID\n",daisyChainId);
                    deviceStillThere = FALSE;
                }
                // don't forget to deselect device
                P5DeselectAllDaisyChainDevices( controller );
                
            } else {
                // unable to select device
                DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeDaisyChain %d - Gone - unable to select\n",daisyChainId);
                deviceStillThere = FALSE;
            }
        } // end new scope for case PdoTypeDaisyChain
        break;
            
    case PdoTypeEndOfChain:
        
        //
        // Pull a fresh 1284 device ID string from the device, and
        // compare the Mfg and Mdl from the fresh device ID with
        // those stored in our extension. If the Mfg and Mdl
        // fields match then the device is still there.
        //
        {
            ULONG        tryNumber = 0;
            const ULONG  maxTries  = 5; // arbitrary number

            do {

                ++tryNumber;

                devIdString = P4ReadRawIeee1284DeviceId( controller );            

                if( devIdString ) {
                    PCHAR mfg, mdl, cls, des, aid, cid;
                    ParPnpFindDeviceIdKeys( &mfg, &mdl, &cls, &des, &aid, &cid, devIdString+2 );
                    if( mfg && mdl ) {
                        // we have a device, is it the same device?
                        if( (0 == strcmp( mfg, pdx->Mfg )) && (0 == strcmp( mdl, pdx->Mdl )) ) {
                            // same device
                            DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeEndOfChain - StillThere\n");
                            deviceStillThere = TRUE;
                        } else {
                            // different device - IDs don't match
                            DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeEndOfChain - Gone - diff 1284 ID\n");
                            deviceStillThere = FALSE;
                        }
                    } else {
                        // either mfg or mdl field not found
                        DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeEndOfChain - Gone - bad 1284 ID\n");
                        deviceStillThere = FALSE;
                    }
                    // don't forget to free temp pool
                    ExFreePool( devIdString );
                } else {
                    // unable to get a 1284 device ID string from the device
                    DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeEndOfChain - Gone - no 1284 ID\n");
                    deviceStillThere = FALSE;
                }

                if( (FALSE == deviceStillThere ) && (PASSIVE_LEVEL == KeGetCurrentIrql()) ) {
                    LARGE_INTEGER delay;
                    delay.QuadPart = - 10 * 1000 * 120; // 120 ms - 3x the usual arbitrary delay 
                    KeDelayExecutionThread( KernelMode, FALSE, &delay);
                }

            } while( (FALSE == deviceStillThere) && (tryNumber < maxTries) );

        }
        break;
        
    default:
        
        PptAssertMsg("P5IsDeviceStillThere - invalid PdoType",FALSE);
        DD((PCE)Fdo,DDE,"P5IsDeviceStillThere - invalid PdoType\n");
        deviceStillThere = TRUE; // don't know what to do here - so, guess
    }
    
    return deviceStillThere;
}


NTSTATUS
PptAcquirePortViaIoctl(
    IN PDEVICE_OBJECT PortDeviceObject,
    IN PLARGE_INTEGER Timeout OPTIONAL
    )
/*++dvdf

Routine Description:

    This routine acquires the specified parallel port from the parallel 
      port arbiter ParPort via an IOCTL_INTERNAL_PARALLEL_PORT_ALLOCATE.

Arguments:

    PortDeviceObject - points to the ParPort device to be acquired

Return Value:

    STATUS_SUCCESS  - if the port was successfully acquired
    !STATUS_SUCCESS - otherwise

--*/
{
    LARGE_INTEGER    localTimeout;
    
    if( Timeout ) {
        localTimeout = *Timeout;           // caller specified
    } else {
        localTimeout = AcquirePortTimeout; // driver global variable default
    }

    return ParBuildSendInternalIoctl(IOCTL_INTERNAL_PARALLEL_PORT_ALLOCATE, 
                                     PortDeviceObject, NULL, 0, NULL, 0, &localTimeout);
}


NTSTATUS
PptReleasePortViaIoctl(
    IN PDEVICE_OBJECT PortDeviceObject
    )

⌨️ 快捷键说明

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