mspylib.c

来自「文件系统过滤驱动程序的框架」· C语言 代码 · 共 742 行 · 第 1/2 页

C
742
字号
}


VOID
SpyLogPostOperationData (
    IN PFLT_CALLBACK_DATA Data,
    IN PRECORD_LIST RecordList
    )
/*++

Routine Description:

    This is called from the post-operation callback routine to copy the
    necessary information into the log record.

    NOTE:  This code must be NON-PAGED because it can be called on the
           paging path or at DPC level.

Arguments:

    Data - The Data structure that contains the information we want to record.

    RecordList - Where we want to save the data

Return Value:

    None.
    
--*/
{
    PRECORD_DATA recordData = &RecordList->LogRecord.Data;

    recordData->Status = Data->IoStatus.Status;
    recordData->Information = Data->IoStatus.Information;
    KeQuerySystemTime( &recordData->CompletionTime );
}


VOID
SpyLog (
    IN PRECORD_LIST RecordList
    )
/*++

Routine Description:

    This routine inserts the given log record into the list to be sent
    to the user mode application.

    NOTE:  This code must be NON-PAGED because it can be called on the
           paging path or at DPC level and uses a spin-lock

Arguments:

    RecordList - The record to append to the MiniSpyData.OutputBufferList

Return Value:

    The function returns STATUS_SUCCESS.



--*/
{
    KIRQL oldIrql;
    
    KeAcquireSpinLock(&MiniSpyData.OutputBufferLock, &oldIrql);
    InsertTailList(&MiniSpyData.OutputBufferList, &RecordList->List);
    KeReleaseSpinLock(&MiniSpyData.OutputBufferLock, oldIrql);
}


NTSTATUS
SpyGetLog (
    OUT PUCHAR OutputBuffer,
    IN ULONG OutputBufferLength,
    OUT PULONG ReturnOutputBufferLength
    )
/*++

Routine Description:
    This function fills OutputBuffer with as many LOG_RECORDs as possible.  
    The LOG_RECORDs are variable sizes and are tightly packed in the 
    OutputBuffer.

    NOTE:  This code must be NON-PAGED because it uses a spin-lock.

Arguments:
    OutputBuffer - The user's buffer to fill with the log data we have
        collected

    OutputBufferLength - The size in bytes of OutputBuffer

    ReturnOutputBufferLength - The amount of data actually written into the 
        OutputBuffer.

Return Value:
    STATUS_SUCCESS if some records were able to be written to the OutputBuffer.
    
    STATUS_NO_MORE_ENTRIES if we have no data to return.
      
    STATUS_BUFFER_TOO_SMALL if the OutputBuffer is too small to 
        hold even one record and we have data to return.

--*/
{
    PLIST_ENTRY pList;
    ULONG bytesWritten = 0;
    PLOG_RECORD pLogRecord;
    NTSTATUS status = STATUS_NO_MORE_ENTRIES;
    PRECORD_LIST pRecordList;
    KIRQL oldIrql;
    BOOLEAN recordsAvailable = FALSE;

    KeAcquireSpinLock( &MiniSpyData.OutputBufferLock, &oldIrql );
    
    while (!IsListEmpty( &MiniSpyData.OutputBufferList ) && (OutputBufferLength > 0)) {

        //
        //  Mark we have records
        //

        recordsAvailable = TRUE;

        //
        //  Get the next available record
        //

        pList = RemoveHeadList( &MiniSpyData.OutputBufferList );
    
        pRecordList = CONTAINING_RECORD( pList, RECORD_LIST, List );
    
        pLogRecord = &pRecordList->LogRecord;
    
        //
        //  If no filename was set then make it into a NULL file name.
        //
    
        if (REMAINING_NAME_SPACE( pLogRecord ) == MAX_NAME_SPACE) {

            //
            //  We don't have a name, so return an empty string.
            //  We have to always start a new log record on a PVOID aligned boundary.
            //

            pLogRecord->Length += ROUND_TO_SIZE( sizeof( UNICODE_NULL ), sizeof( PVOID ) );
            pLogRecord->Name[0] = UNICODE_NULL;
        }
    
        //
        //  Put it back if we've run out of room.
        //
    
        if (OutputBufferLength < pLogRecord->Length) {

            InsertHeadList( &MiniSpyData.OutputBufferList, pList );
            break;
        }
    
        KeReleaseSpinLock( &MiniSpyData.OutputBufferLock, oldIrql );
    
        //
        //  The lock is released, return the data, adjust pointers.
        //  Protect access to raw user-mode OutputBuffer with an exception handler
        //

        try {
            RtlCopyMemory( OutputBuffer, pLogRecord, pLogRecord->Length );
        } except( EXCEPTION_EXECUTE_HANDLER ) {

            //
            //  Put the record back in
            //

            KeAcquireSpinLock( &MiniSpyData.OutputBufferLock, &oldIrql );
            InsertHeadList( &MiniSpyData.OutputBufferList, pList );
            KeReleaseSpinLock( &MiniSpyData.OutputBufferLock, oldIrql );

            return GetExceptionCode();

        }
    
        bytesWritten += pLogRecord->Length;

        OutputBufferLength -= pLogRecord->Length;

        OutputBuffer += pLogRecord->Length;
    
        SpyFreeRecord( pRecordList );
    
        //
        //  Relock the list
        //

        KeAcquireSpinLock( &MiniSpyData.OutputBufferLock, &oldIrql );
    }
    
    KeReleaseSpinLock( &MiniSpyData.OutputBufferLock, oldIrql );
    
    //
    //  Set proper status
    //

    if ((bytesWritten == 0) && recordsAvailable) {

        // 
        //  There were records to be sent up but 
        //  there was not enough room in the buffer.
        //

        status = STATUS_BUFFER_TOO_SMALL;

    } else if (bytesWritten > 0) {

        // 
        //  We were able to write some data to the output buffer,
        //  so this was a success.
        //

        status = STATUS_SUCCESS;
    }

    *ReturnOutputBufferLength = bytesWritten;

    return status;
}


VOID
SpyEmptyOutputBufferList (
    VOID
    )
/*++

Routine Description:

    This routine frees all the remaining log records in the OutputBufferList
    that are not going to get sent up to the user mode application since
    MiniSpy is shutting down.
    
    NOTE:  This code must be NON-PAGED because it uses a spin-lock

Arguments:

    None.
    
Return Value:

    None.
    
--*/
{
    PLIST_ENTRY pList;
    PRECORD_LIST pRecordList;
    KIRQL oldIrql;

    KeAcquireSpinLock( &MiniSpyData.OutputBufferLock, &oldIrql );

    while (!IsListEmpty( &MiniSpyData.OutputBufferList )) {

        pList = RemoveHeadList( &MiniSpyData.OutputBufferList );   
        KeReleaseSpinLock( &MiniSpyData.OutputBufferLock, oldIrql );

        pRecordList = CONTAINING_RECORD( pList, RECORD_LIST, List );

        SpyFreeRecord( pRecordList );

        KeAcquireSpinLock( &MiniSpyData.OutputBufferLock, &oldIrql );
    }

    KeReleaseSpinLock( &MiniSpyData.OutputBufferLock, oldIrql );
}

//---------------------------------------------------------------------------
//                    Logging routines
//---------------------------------------------------------------------------

VOID
SpyReadDriverParameters (
    IN PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

    This routine tries to read the MiniSpy-specific parameters from 
    the registry.  These values will be found in the registry location
    indicated by the RegistryPath passed in.

Arguments:

    RegistryPath - the path key which contains the values that are
        the MiniSpy parameters
        
Return Value:

    None.

--*/
{
    OBJECT_ATTRIBUTES attributes;
    HANDLE driverRegKey;
    NTSTATUS status;
    ULONG resultLength;
    UNICODE_STRING valueName;
    PKEY_VALUE_PARTIAL_INFORMATION pValuePartialInfo;
    UCHAR buffer[sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( LONG )];

    //
    //  Open the registry
    //

    InitializeObjectAttributes( &attributes,
                                RegistryPath,
                                OBJ_CASE_INSENSITIVE,
                                NULL,
                                NULL );

    status = ZwOpenKey( &driverRegKey,
                        KEY_READ,
                        &attributes );

    if (!NT_SUCCESS( status )) {

        return;
    }

    //
    // Read the MaxRecordsToAllocate entry from the registry
    //

    RtlInitUnicodeString( &valueName, MAX_RECORDS_TO_ALLOCATE );

    status = ZwQueryValueKey( driverRegKey,
                              &valueName,
                              KeyValuePartialInformation,
                              buffer,
                              sizeof(buffer),
                              &resultLength );

    if (NT_SUCCESS( status )) {

        pValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
        ASSERT( pValuePartialInfo->Type == REG_DWORD );
        MiniSpyData.MaxRecordsToAllocate = *((PLONG)&(pValuePartialInfo->Data));
    }

    //
    // Read the NameQueryMethod entry from the registry
    //

    RtlInitUnicodeString( &valueName, NAME_QUERY_METHOD );

    status = ZwQueryValueKey( driverRegKey,
                              &valueName,
                              KeyValuePartialInformation,
                              buffer,
                              sizeof(buffer),
                              &resultLength );

    if (NT_SUCCESS( status )) {

        pValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
        ASSERT( pValuePartialInfo->Type == REG_DWORD );
        MiniSpyData.NameQueryMethod = *((PLONG)&(pValuePartialInfo->Data));
    }

    ZwClose(driverRegKey);
}

⌨️ 快捷键说明

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