/*++
Copyright (c) 1999-2002 Microsoft Corporation
Module Name:
scanner.c
Abstract:
This is the main module of the scanner filter.
This filter scans the data in a file before allowing an open to proceed. This is similar
to what virus checkers do.
Environment:
Kernel mode
--*/
#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>
#include "scanuk.h"
#include "scanner.h"
#pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")
#define SCANNER_REG_TAG 'Rncs'
#define SCANNER_STRING_TAG 'Sncs'
//
// Structure that contains all the global data structures
// used throughout the scanner.
//
SCANNER_DATA ScannerData;
//
// This is a static list of file name extensions files we are interested in scanning
//
PUNICODE_STRING ScannedExtensions;
ULONG ScannedExtensionCount;
//
// The default extension to scan if not configured in the registry
//
UNICODE_STRING ScannedExtensionDefault = RTL_CONSTANT_STRING( L"doc" );
//
// Function prototypes
//
NTSTATUS
ScannerInitializeScannedExtensions(
_In_ PUNICODE_STRING RegistryPath
);
VOID
ScannerFreeExtensions(
);
NTSTATUS
ScannerAllocateUnicodeString (
_Inout_ PUNICODE_STRING String
);
VOID
ScannerFreeUnicodeString (
_Inout_ PUNICODE_STRING String
);
NTSTATUS
ScannerPortConnect (
_In_ PFLT_PORT ClientPort,
_In_opt_ PVOID ServerPortCookie,
_In_reads_bytes_opt_(SizeOfContext) PVOID ConnectionContext,
_In_ ULONG SizeOfContext,
_Outptr_result_maybenull_ PVOID *ConnectionCookie
);
VOID
ScannerPortDisconnect (
_In_opt_ PVOID ConnectionCookie
);
NTSTATUS
ScannerpScanFileInUserMode (
_In_ PFLT_INSTANCE Instance,
_In_ PFILE_OBJECT FileObject,
_Out_ PBOOLEAN SafeToOpen
);
BOOLEAN
ScannerpCheckExtension (
_In_ PUNICODE_STRING Extension
);
//
// Assign text sections for each routine.
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(INIT, ScannerInitializeScannedExtensions)
#pragma alloc_text(PAGE, ScannerInstanceSetup)
#pragma alloc_text(PAGE, ScannerPreCreate)
#pragma alloc_text(PAGE, ScannerPortConnect)
#pragma alloc_text(PAGE, ScannerPortDisconnect)
#pragma alloc_text(PAGE, ScannerFreeExtensions)
#pragma alloc_text(PAGE, ScannerAllocateUnicodeString)
#pragma alloc_text(PAGE, ScannerFreeUnicodeString)
#endif
//
// Constant FLT_REGISTRATION structure for our filter. This
// initializes the callback routines our filter wants to register
// for. This is only used to register with the filter manager
//
const FLT_OPERATION_REGISTRATION Callbacks[] = {
{ IRP_MJ_CREATE,
0,
ScannerPreCreate,
ScannerPostCreate},
{ IRP_MJ_CLEANUP,
0,
ScannerPreCleanup,
NULL},
{ IRP_MJ_WRITE,
0,
ScannerPreWrite,
NULL},
#if (WINVER>=0x0602)
{ IRP_MJ_FILE_SYSTEM_CONTROL,
0,
ScannerPreFileSystemControl,
NULL
},
#endif
{ IRP_MJ_OPERATION_END}
};
const FLT_CONTEXT_REGISTRATION ContextRegistration[] = {
{ FLT_STREAMHANDLE_CONTEXT,
0,
NULL,
sizeof(SCANNER_STREAM_HANDLE_CONTEXT),
'chBS' },
{ FLT_CONTEXT_END }
};
const FLT_REGISTRATION FilterRegistration = {
sizeof( FLT_REGISTRATION ), // Size
FLT_REGISTRATION_VERSION, // Version
0, // Flags
ContextRegistration, // Context Registration.
Callbacks, // Operation callbacks
ScannerUnload, // FilterUnload
ScannerInstanceSetup, // InstanceSetup
ScannerQueryTeardown, // InstanceQueryTeardown
NULL, // InstanceTeardownStart
NULL, // InstanceTeardownComplete
NULL, // GenerateFileName
NULL, // GenerateDestinationFileName
NULL // NormalizeNameComponent
};
////////////////////////////////////////////////////////////////////////////
//
// Filter initialization and unload routines.
//
////////////////////////////////////////////////////////////////////////////
NTSTATUS
DriverEntry (
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This is the initialization routine for the Filter driver. This
registers the Filter with the filter manager and initializes all
its global data structures.
Arguments:
DriverObject - Pointer to driver object created by the system to
represent this driver.
RegistryPath - Unicode string identifying where the parameters for this
driver are located in the registry.
Return Value:
Returns STATUS_SUCCESS.
--*/
{
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString;
PSECURITY_DESCRIPTOR sd;
NTSTATUS status;
//
// Default to NonPagedPoolNx for non paged pool allocations where supported.
//
ExInitializeDriverRuntime( DrvRtPoolNxOptIn );
//
// Register with filter manager.
//
status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&ScannerData.Filter );
if (!NT_SUCCESS( status )) {
return status;
}
//
// Obtain the extensions to scan from the registry
//
status = ScannerInitializeScannedExtensions( RegistryPath );
if (!NT_SUCCESS( status )) {
status = STATUS_SUCCESS;
ScannedExtensions = &ScannedExtensionDefault;
ScannedExtensionCount = 1;
}
//
// Create a communication port.
//
RtlInitUnicodeString( &uniString, ScannerPortName );
//
// We secure the port so only ADMINs & SYSTEM can acecss it.
//
status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );
if (NT_SUCCESS( status )) {
InitializeObjectAttributes( &oa,
&uniString,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
sd );
status = FltCreateCommunicationPort( ScannerData.Filter,
&ScannerData.ServerPort,
&oa,
NULL,
ScannerPortConnect,
ScannerPortDisconnect,
NULL,
1 );
//
// Free the security descriptor in all cases. It is not needed once
// the call to FltCreateCommunicationPort() is made.
//
FltFreeSecurityDescriptor( sd );
if (NT_SUCCESS( status )) {
//
// Start filtering I/O.
//
status = FltStartFiltering( ScannerData.Filter );
if (NT_SUCCESS( status )) {
return STATUS_SUCCESS;
}
FltCloseCommunicationPort( ScannerData.ServerPort );
}
}
ScannerFreeExtensions();
FltUnregisterFilter( ScannerData.Filter );
return status;
}
NTSTATUS
ScannerInitializeScannedExtensions(
_In_ PUNICODE_STRING RegistryPath
)
/*++
Routine Descrition:
This routine sets the the extensions for files to be scanned based
on the registry.
Arguments: