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

📄 filespy.c

📁 一个文件过滤驱动程序的例子
💻 C
📖 第 1 页 / 共 5 页
字号:
    //

    for (;;) {

        //
        //  Get what device objects we can for this driver.  Quit if there
        //  are not any more.  Note that this routine should always be defined
        //  since this routine is only compiled for Windows XP and later.
        //

        ASSERT( NULL != gSpyDynamicFunctions.EnumerateDeviceObjectList );
        status = (gSpyDynamicFunctions.EnumerateDeviceObjectList)(
                        DriverObject,
                        devList,
                        sizeof(devList),
                        &numDevices);

        if (numDevices <= 0)  {

            break;
        }

        numDevices = min( numDevices, DEVOBJ_LIST_SIZE );

        //
        //  First go through the list and detach each of the devices.
        //  Our control device object does not have a DeviceExtension and
        //  is not attached to anything so don't detach it.
        //

        for (i=0; i < numDevices; i++) {

            devExt = devList[i]->DeviceExtension;
            if (NULL != devExt) {

                IoDetachDevice( devExt->NLExtHeader.AttachedToDeviceObject );
            }
        }

        //
        //  The IO Manager does not currently add a reference count to a device
        //  object for each outstanding IRP.  This means there is no way to
        //  know if there are any outstanding IRPs on the given device.
        //  We are going to wait for a reasonable amount of time for pending
        //  IRPs to complete.
        //
        //  WARNING: This does not work 100% of the time and the driver may be
        //           unloaded before all IRPs are completed during high stress
        //           situations.  The system will fault if this occurs.  This
        //           is a sample of how to do this during testing.  This is
        //           not recommended for production code.
        //

        interval.QuadPart = (5 * DELAY_ONE_SECOND);      //delay 5 seconds
        KeDelayExecutionThread( KernelMode, FALSE, &interval );

        //
        //  Now go back through the list and delete the device objects.
        //

        for (i=0; i < numDevices; i++) {

            //
            //  See if this is our control device object.  If not then cleanup
            //  the device extension.  If so then clear the global pointer
            //  that references it.
            //

            if (NULL != devList[i]->DeviceExtension) {

                SpyCleanupMountedDevice( devList[i] );

            } else {

                ASSERT(devList[i] == gControlDeviceObject);
                ASSERT(gControlDeviceState == CLOSED);
                gControlDeviceObject = NULL;
            }

            //
            //  Delete the device object, remove reference counts added by
            //  IoEnumerateDeviceObjectList.  Note that the delete does
            //  not actually occur until the reference count goes to zero.
            //

            IoDeleteDevice( devList[i] );
            ObDereferenceObject( devList[i] );
        }
    }

    //
    //  Delete the look aside list.
    //

    ASSERT(IsListEmpty( &gSpyDeviceExtensionList ));

#ifndef MEMORY_DBG
    ExDeleteNPagedLookasideList( &gFreeBufferList );
#endif

    //
    //  Free our FastIO table
    //

    fastIoDispatch = DriverObject->FastIoDispatch;
    DriverObject->FastIoDispatch = NULL;
    ExFreePoolWithTag( fastIoDispatch, FILESPY_POOL_TAG );
    ExDeletePagedLookasideList(&gFsCtxLookAsideList);
    ExDeleteNPagedLookasideList(&gReadWriteCompletionCtxLookAsideList);
	ExDeleteResourceLite(&gRulesResource);
   
	if (FilenameRules)
	{
		ExFreePoolWithTag(FilenameRules, FILESPY_POOL_TAG);
		FilenameRules = NULL;
	}

    SPY_LOG_PRINT( SPYDEBUG_DISPLAY_ATTACHMENT_NAMES,
                   ("FileSpy!DriverUnload:                        Unloading Complete (%p)\n",
                    DriverObject) );
}

#endif

VOID
SpyFsNotification (
    IN PDEVICE_OBJECT DeviceObject,
    IN BOOLEAN FsActive
    )
/*++

Routine Description:

    This routine is invoked whenever a file system has either registered or
    unregistered itself as an active file system.

    For the former case, this routine creates a device object and attaches it
    to the specified file system's device object.  This allows this driver
    to filter all requests to that file system.

    For the latter case, this file system's device object is located,
    detached, and deleted.  This removes this file system as a filter for
    the specified file system.

Arguments:

    DeviceObject - Pointer to the file system's device object.

    FsActive - Boolean indicating whether the file system has registered
        (TRUE) or unregistered (FALSE) itself as an active file system.

Return Value:

    None.

--*/
{
    PNAME_CONTROL devName;

    PAGED_CODE();

    //
    //  The DeviceObject passed in is always the base device object at this
    //  point because it is the file system's control device object.  We can
    //  just query this object's name directly.
    //

    devName = NLGetAndAllocateObjectName( DeviceObject,
                                          &gFileSpyNameBufferLookasideList );

    if (devName == NULL) {

        SPY_LOG_PRINT( SPYDEBUG_DISPLAY_ATTACHMENT_NAMES,
                       ("FileSpy!SpyFsNotification:                   Not attaching to %p, insufficient resources.\n",
                        DeviceObject) );
        return;
    }


    SPY_LOG_PRINT( SPYDEBUG_DISPLAY_ATTACHMENT_NAMES,
                   ("FileSpy!SpyFsNotification:                   %s   %p \"%wZ\" (%s)\n",
                    (FsActive) ? "Activating file system  " : "Deactivating file system",
                    DeviceObject,
                    &devName->Name,
                    GET_DEVICE_TYPE_NAME(DeviceObject->DeviceType)) );

    //
    //  See if we want to ATTACH or DETACH from the given file system.
    //

    if (FsActive) {

        SpyAttachToFileSystemDevice( DeviceObject, devName );

    } else {

        SpyDetachFromFileSystemDevice( DeviceObject );
    }

    //
    //  We're done with name (SpyAttachToFileSystemDevice copies the name to
    //  the device extension) so free it.
    //

    NLFreeNameControl( devName, &gFileSpyNameBufferLookasideList );
}


NTSTATUS
SpyPassThrough (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
)
/*++

Routine Description:

    This routine is the main dispatch routine for the general purpose file
    system driver.  It simply passes requests onto the next driver in the
    stack, which is presumably a disk file system, while logging any
    relevant information if logging is turned on for this DeviceObject.

Arguments:

    DeviceObject - Pointer to device object Filespy attached to the file system
        filter stack for the volume receiving this I/O request.

    Irp - Pointer to the request packet representing the I/O request.

Return Value:

    The function value is the status of the operation.

Note:

    This routine passes the I/O request through to the next driver
    *without* removing itself from the stack (like sfilter) since it could
    want to see the result of this I/O request.

    To remain in the stack, we have to copy the caller's parameters to the
    next stack location.  Note that we do not want to copy the caller's I/O
    completion routine into the next stack location, or the caller's routine
    will get invoked twice.  This is why we NULL out the Completion routine.
    If we are logging this device, we set our own Completion routine.

--*/
{
    PRECORD_LIST recordList = NULL;
    KEVENT waitEvent;
    NTSTATUS status;
    BOOLEAN syncToDispatch;

    ASSERT(IS_FILESPY_DEVICE_OBJECT( DeviceObject ));

    //
    //  If the specified debug level is set, output what operation
    //  we are seeing to the debugger.
    //
/*
    if (FlagOn( gFileSpyDebugLevel, SPYDEBUG_TRACE_IRP_OPS )) {

        SpyDumpIrpOperation( TRUE, Irp );
    }
*/
    //
    //  See if we should log this IRP
    //

    if (SHOULD_LOG( DeviceObject ) && 0) {

        //
        //  The ControlDevice is opened, so allocate the Record
        //  and log the Irp information if we have the memory.
        //

        recordList = SpyNewRecord(0);

        if (NULL != recordList) {

            SpyLogIrp( Irp, recordList );
            
			//recordList->LogRecord.Name[recordList->LogRecord.Length] = L'\0';
		//	KdPrint(("sfilter! %ws \n",recordList->LogRecord.Name));

            //
            //  Since we are logging this operation, we want to
            //  call our completion routine.
            //

            IoCopyCurrentIrpStackLocationToNext( Irp );

            KeInitializeEvent( &waitEvent,
                               NotificationEvent,
                               FALSE );

            recordList->WaitEvent = &waitEvent;

            IoSetCompletionRoutine( Irp,
                                    SpyPassThroughCompletion,
                                    recordList,
                                    TRUE,
                                    TRUE,
                                    TRUE);
			
        } else {

            //
            //  We could not get a record to log with so get this driver out
            //  of the driver stack and get to the next driver as quickly as
            //  possible.
            //

            IoSkipCurrentIrpStackLocation( Irp );
        }

    } else {

        //
        //  We are not logging so get this driver out of the driver stack and
        //  get to the next driver as quickly as possible.
        //

        IoSkipCurrentIrpStackLocation( Irp );
    }

    //
    //  Determine if we are syncing back to the dispatch routine.  We need to
    //  do this before calling down because the recordList entry could be free
    //  upon return.
    //

    syncToDispatch = ((NULL != recordList) &&
                      (FlagOn(recordList->Flags,RLFL_SYNC_TO_DISPATCH)));

    //
    //  Now call the next file system driver with the request.
    //

    status = IoCallDriver( ((PFILESPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
                            Irp );

    //
    //  If we are logging and we need to synchronize back to our dispatch
    //  routine for completion processing, do it now.
    //

    if (syncToDispatch && 0) {

        //
        //  We are syncing back to the dispatch routine, wait for the operation
        //  to complete.
        //

        if (STATUS_PENDING == status) {

            status = KeWaitForSingleObject( &waitEvent,
                                            Executive,
                                            KernelMode,
                                            FALSE,
                                            NULL );

            ASSERT(STATUS_SUCCESS == status);
        }

        //
        //  Verify the completion has actually been run
        //

        ASSERT(KeReadStateEvent(&waitEvent) ||
               !NT_SUCCESS(Irp->IoStatus.Status));

        //
        //  Do completion processing
        //

        SpyLogIrpCompletion( Irp, recordList );

        //
        //  Continue processing the operation
        //

        status = Irp->IoStatus.Status;

        IoCompleteRequest( Irp, IO_NO_INCREMENT );
    }

    return status;
}

NTSTATUS
SpyPassThroughCompletion (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
)
/*++

Routine Description:

    This routine is the completion routine SpyPassThrough.  This is used
    to log the information that can only be gathered after the I/O request
    has been completed.

    Once we are done logging all the information we care about, we append
    the record to the gOutputBufferList to be returned to the user.

    Note: This routine will only be set if we were trying to log the
        specified device when the Irp originated and we were able to
        allocate a record to store this logging information.

Arguments:

    DeviceObject - Pointer to device object Filespy attached to the file system
        filter stack for the volume receiving this I/O request.

    Irp - Pointer to the request packet representing the I/O request.

    Context - Pointer to the RECORD_LIST structure in which we store the
        information we are logging.

Return Value:

    The function value is the status of the operation.

--*/
{
    PRECORD_LIST recordList = (PRECORD_LIST)Context;

⌨️ 快捷键说明

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