fdothread.c

来自「鼠标Windows驱动」· C语言 代码 · 共 192 行

C
192
字号
#include "pch.h"

// experimental vars - to tweek debugging for this thread
ULONG x1; // set nonzero to disable port acquisition
ULONG x2; // set nonzero to try to select LPT1.0 and negotiate/terminate ECP_HW_NOIRQ
ULONG x3; // set nonzero to try to negotiate the periph to ECP and then terminate
ULONG x4;

ULONG t1; // timeout between thread polls (in ms)
ULONG t2; // time to sit on port before releasing it (in ms)

VOID
P5FdoThread(
    IN  PFDO_EXTENSION Fdx
    )
{
    LARGE_INTEGER   timeOut1;
    NTSTATUS        status;
    UCHAR           deviceStatus;
    PCHAR           devId;
    BOOLEAN         requestRescan;
    const ULONG     pollingFailureThreshold = 10; // pick an arbitrary but reasonable number

    do {

        if( PowerStateIsAC ) {

            PPT_SET_RELATIVE_TIMEOUT_IN_MILLISECONDS( timeOut1, (WarmPollPeriod * 1000) );

        } else {

            // running on batteries - use a longer (4x) timeout
            PPT_SET_RELATIVE_TIMEOUT_IN_MILLISECONDS( timeOut1, (WarmPollPeriod * 1000 * 4) );

        }

        status = KeWaitForSingleObject(&Fdx->FdoThreadEvent, Executive, KernelMode, FALSE, &timeOut1);

        if( Fdx->TimeToTerminateThread ) {

            //
            // another thread (PnP REMOVE handler) has requested that we die and is likely waiting on us to do so
            //
            DD((PCE)Fdx,DDT,"P5FdoThread - killing self\n");
            PsTerminateSystemThread( STATUS_SUCCESS );

        }

        if( !PowerStateIsAC ) {
            // Still on Batteries - don't "poll for printers" - just go back to sleep
            continue;
        }

        if( STATUS_TIMEOUT == status ) {

            if( NULL == Fdx->EndOfChainPdo ) {

                // try to acquire port
                if( PptTryAllocatePort( Fdx ) ) {
                
                    DD((PCE)Fdx,DDT,"P5FdoThread - port acquired\n");

                    requestRescan = FALSE;

                    // check for something connected
                    deviceStatus = GetStatus(Fdx->PortInfo.Controller);

                    if( PAR_POWERED_OFF(deviceStatus)   ||
                        PAR_NOT_CONNECTED(deviceStatus) ||
                        PAR_NO_CABLE(deviceStatus) ) {
                        
                        // doesn't appear to be anything connected - do nothing
                        DD((PCE)Fdx,DDT,"P5FdoThread - nothing connected? - deviceStatus = %02x\n",deviceStatus);

                    } else {

                        // we might have something connected

                        // try a device ID to confirm

                        DD((PCE)Fdx,DDT,"P5FdoThread - might be something connected - deviceStatus = %02x\n",deviceStatus);                        

                        devId = P4ReadRawIeee1284DeviceId( Fdx->PortInfo.Controller );

                        if( devId ) {

                            PCHAR  mfg, mdl, cls, des, aid, cid;

                            // RawIeee1284 string includes 2 bytes of length data at beginning
                            DD((PCE)Fdx,DDT,"P5FdoThread - EndOfChain device detected <%s>\n",(devId+2));

                            ParPnpFindDeviceIdKeys( &mfg, &mdl, &cls, &des, &aid, &cid, devId+2 );

                            if( mfg && mdl ) {
                                DD((PCE)Fdx,DDT,"P5FdoThread - found mfg - <%s>\n",mfg);
                                DD((PCE)Fdx,DDT,"P5FdoThread - found mdl - <%s>\n",mdl);
                                requestRescan = TRUE;
                            }

                            ExFreePool( devId );

                        } else {
                            DD((PCE)Fdx,DDT,"P5FdoThread - no EndOfChain device detected - NULL devId\n");
                        }

                        if( requestRescan ) {

                            // we appear to have retrieved a valid 1284 ID, reset failure counter
                            Fdx->PollingFailureCounter = 0;

                        } else {

                            // Our heuristics tell us that there is something
                            // connected to the port but we are unable to retrieve
                            // a valid IEEE 1284 Device ID

                            if( ++(Fdx->PollingFailureCounter) > pollingFailureThreshold ) {

                                // too many consecutive failures - we're burning CPU for no good reason, give up and die
                                Fdx->TimeToTerminateThread = TRUE;

                                // don't delay before killing self
                                KeSetEvent( &Fdx->FdoThreadEvent, 0, FALSE );

                            }

                        } 

                    }

                    DD((PCE)Fdx,DDT,"P5FdoThread - freeing port\n");
                    PptFreePort( Fdx );

                    if( requestRescan ) {
                        DD((PCE)Fdx,DDT,"P5FdoThread - requesting Rescan\n");
                        IoInvalidateDeviceRelations( Fdx->PhysicalDeviceObject, BusRelations );
                    }

                } else {
                    DD((PCE)Fdx,DDT,"P5FdoThread - unable to acquire port\n");
                }

            } else {
                DD((PCE)Fdx,DDT,"P5FdoThread - already have EndOfChain device\n");
            }

        }

    } while( TRUE );

}

NTSTATUS
P5FdoCreateThread(
    PFDO_EXTENSION Fdx
    )
{
    NTSTATUS        status;
    HANDLE          handle;
    OBJECT_ATTRIBUTES objAttrib;

    DD((PCE)Fdx,DDT,"P5CreateFdoWorkerThread - %s - enter\n",Fdx->Location);

    // Start the thread - save referenced pointer to thread in our extension
    InitializeObjectAttributes( &objAttrib, NULL, OBJ_KERNEL_HANDLE, NULL, NULL );

    status = PsCreateSystemThread( &handle, THREAD_ALL_ACCESS, &objAttrib, NULL, NULL, P5FdoThread, Fdx );

    if( STATUS_SUCCESS == status ) {

        // We've got the thread.  Now get a pointer to it.

        status = ObReferenceObjectByHandle( handle, THREAD_ALL_ACCESS, NULL, KernelMode, &Fdx->ThreadObjectPointer, NULL );

        if( STATUS_SUCCESS == status ) {
            // Now that we have a reference to the thread we can simply close the handle.
            ZwClose(handle);

        } else {
            Fdx->TimeToTerminateThread = TRUE;
        }

        DD((PCE)Fdx,DDT,"ParCreateSystemThread - %s - SUCCESS\n",Fdx->Location);

    } else {
        DD((PCE)Fdx,DDT,"ParCreateSystemThread - %s FAIL - status = %x\n",Fdx->Location, status);
    }

    return status;
}

⌨️ 快捷键说明

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