diff options
| author | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
| commit | 97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch) | |
| tree | 46f3701832d70b420eb0fc0eb93261f9da45db3f /filesys/miniFilter/scanner/filter | |
| parent | ef1905bf1e8825bb31120dfb27e0daf3154d859a (diff) | |
Initial publish
Diffstat (limited to 'filesys/miniFilter/scanner/filter')
| -rw-r--r-- | filesys/miniFilter/scanner/filter/scanner.c | 1685 | ||||
| -rw-r--r-- | filesys/miniFilter/scanner/filter/scanner.h | 160 | ||||
| -rw-r--r-- | filesys/miniFilter/scanner/filter/scanner.rc | 10 | ||||
| -rw-r--r-- | filesys/miniFilter/scanner/filter/scanner.vcxproj | 192 | ||||
| -rw-r--r-- | filesys/miniFilter/scanner/filter/scanner.vcxproj.Filters | 31 |
5 files changed, 2078 insertions, 0 deletions
diff --git a/filesys/miniFilter/scanner/filter/scanner.c b/filesys/miniFilter/scanner/filter/scanner.c new file mode 100644 index 00000000..cd72d71b --- /dev/null +++ b/filesys/miniFilter/scanner/filter/scanner.c @@ -0,0 +1,1685 @@ +/*++ + +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: + + RegistryPath - The path key passed to the driver during DriverEntry. + +Return Value: + + STATUS_SUCCESS if the function completes successfully. Otherwise a valid + NTSTATUS code is returned. + +--*/ +{ + NTSTATUS status; + OBJECT_ATTRIBUTES attributes; + HANDLE driverRegKey = NULL; + UNICODE_STRING valueName; + PKEY_VALUE_PARTIAL_INFORMATION valueBuffer = NULL; + ULONG valueLength = 0; + BOOLEAN closeHandle = FALSE; + PWCHAR ch; + SIZE_T length; + ULONG count; + PUNICODE_STRING ext; + + PAGED_CODE(); + + ScannedExtensions = NULL; + ScannedExtensionCount = 0; + + // + // Open the driver registry key. + // + + InitializeObjectAttributes( &attributes, + RegistryPath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL ); + + status = ZwOpenKey( &driverRegKey, + KEY_READ, + &attributes ); + + if (!NT_SUCCESS( status )) { + + goto ScannerInitializeScannedExtensionsCleanup; + } + + closeHandle = TRUE; + + // + // Query the length of the reg value + // + + RtlInitUnicodeString( &valueName, L"Extensions" ); + + status = ZwQueryValueKey( driverRegKey, + &valueName, + KeyValuePartialInformation, + NULL, + 0, + &valueLength ); + + if (status!=STATUS_BUFFER_TOO_SMALL && status!=STATUS_BUFFER_OVERFLOW) { + + status = STATUS_INVALID_PARAMETER; + goto ScannerInitializeScannedExtensionsCleanup; + } + + // + // Extract the path. + // + + valueBuffer = ExAllocatePoolWithTag( NonPagedPool, + valueLength, + SCANNER_REG_TAG ); + + if (valueBuffer == NULL) { + + status = STATUS_INSUFFICIENT_RESOURCES; + goto ScannerInitializeScannedExtensionsCleanup; + } + + status = ZwQueryValueKey( driverRegKey, + &valueName, + KeyValuePartialInformation, + valueBuffer, + valueLength, + &valueLength ); + + if (!NT_SUCCESS( status )) { + + goto ScannerInitializeScannedExtensionsCleanup; + } + + ch = (PWCHAR)(valueBuffer->Data); + + count = 0; + + // + // Count how many strings are in the multi string + // + + while (*ch != '\0') { + + ch = ch + wcslen( ch ) + 1; + count++; + } + + ScannedExtensions = ExAllocatePoolWithTag( PagedPool, + count * sizeof(UNICODE_STRING), + SCANNER_STRING_TAG ); + + if (ScannedExtensions == NULL) { + goto ScannerInitializeScannedExtensionsCleanup; + } + + ch = (PWCHAR)((PKEY_VALUE_PARTIAL_INFORMATION)valueBuffer->Data); + ext = ScannedExtensions; + + while (ScannedExtensionCount < count) { + + length = wcslen( ch ) * sizeof(WCHAR); + + ext->MaximumLength = (USHORT) length; + + status = ScannerAllocateUnicodeString( ext ); + + if (!NT_SUCCESS( status )) { + goto ScannerInitializeScannedExtensionsCleanup; + } + + ext->Length = (USHORT)length; + + RtlCopyMemory( ext->Buffer, ch, length ); + + ch = ch + length/sizeof(WCHAR) + 1; + + ScannedExtensionCount++; + + ext++; + + } + +ScannerInitializeScannedExtensionsCleanup: + + // + // Note that this function leaks the global buffers. + // On failure DriverEntry will clean up the globals + // so we don't have to do that here. + // + + if (valueBuffer != NULL) { + + ExFreePoolWithTag( valueBuffer, SCANNER_REG_TAG ); + valueBuffer = NULL; + } + + if (closeHandle) { + + ZwClose( driverRegKey ); + } + + if (!NT_SUCCESS( status )) { + + ScannerFreeExtensions(); + } + + return status; +} + + +VOID +ScannerFreeExtensions( + ) +/*++ + +Routine Descrition: + + This routine cleans up the global buffers on both + teardown and initialization failure. + +Arguments: + +Return Value: + + None. + +--*/ +{ + PAGED_CODE(); + + // + // Free the strings in the scanned extension array + // + + while (ScannedExtensionCount > 0) { + + ScannedExtensionCount--; + + if (ScannedExtensions != &ScannedExtensionDefault) { + + ScannerFreeUnicodeString( ScannedExtensions + ScannedExtensionCount ); + } + } + + if (ScannedExtensions != &ScannedExtensionDefault && ScannedExtensions != NULL) { + + ExFreePoolWithTag( ScannedExtensions, SCANNER_STRING_TAG ); + } + + ScannedExtensions = NULL; + +} + + +NTSTATUS +ScannerAllocateUnicodeString ( + _Inout_ PUNICODE_STRING String + ) +/*++ + +Routine Description: + + This routine allocates a unicode string + +Arguments: + + String - supplies the size of the string to be allocated in the MaximumLength field + return the unicode string + +Return Value: + + STATUS_SUCCESS - success + STATUS_INSUFFICIENT_RESOURCES - failure + +--*/ +{ + + PAGED_CODE(); + + String->Buffer = ExAllocatePoolWithTag( NonPagedPool, + String->MaximumLength, + SCANNER_STRING_TAG ); + + if (String->Buffer == NULL) { + + return STATUS_INSUFFICIENT_RESOURCES; + } + + String->Length = 0; + + return STATUS_SUCCESS; +} + + +VOID +ScannerFreeUnicodeString ( + _Inout_ PUNICODE_STRING String + ) +/*++ + +Routine Description: + + This routine frees a unicode string + +Arguments: + + String - supplies the string to be freed + +Return Value: + + None + +--*/ +{ + PAGED_CODE(); + + if (String->Buffer) { + + ExFreePoolWithTag( String->Buffer, + SCANNER_STRING_TAG ); + String->Buffer = NULL; + } + + String->Length = String->MaximumLength = 0; + String->Buffer = NULL; +} + + +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 + ) +/*++ + +Routine Description + + This is called when user-mode connects to the server port - to establish a + connection + +Arguments + + ClientPort - This is the client connection port that will be used to + send messages from the filter + + ServerPortCookie - The context associated with this port when the + minifilter created this port. + + ConnectionContext - Context from entity connecting to this port (most likely + your user mode service) + + SizeofContext - Size of ConnectionContext in bytes + + ConnectionCookie - Context to be passed to the port disconnect routine. + +Return Value + + STATUS_SUCCESS - to accept the connection + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER( ServerPortCookie ); + UNREFERENCED_PARAMETER( ConnectionContext ); + UNREFERENCED_PARAMETER( SizeOfContext); + UNREFERENCED_PARAMETER( ConnectionCookie = NULL ); + + FLT_ASSERT( ScannerData.ClientPort == NULL ); + FLT_ASSERT( ScannerData.UserProcess == NULL ); + + // + // Set the user process and port. In a production filter it may + // be necessary to synchronize access to such fields with port + // lifetime. For instance, while filter manager will synchronize + // FltCloseClientPort with FltSendMessage's reading of the port + // handle, synchronizing access to the UserProcess would be up to + // the filter. + // + + ScannerData.UserProcess = PsGetCurrentProcess(); + ScannerData.ClientPort = ClientPort; + + DbgPrint( "!!! scanner.sys --- connected, port=0x%p\n", ClientPort ); + + return STATUS_SUCCESS; +} + + +VOID +ScannerPortDisconnect( + _In_opt_ PVOID ConnectionCookie + ) +/*++ + +Routine Description + + This is called when the connection is torn-down. We use it to close our + handle to the connection + +Arguments + + ConnectionCookie - Context from the port connect routine + +Return value + + None + +--*/ +{ + UNREFERENCED_PARAMETER( ConnectionCookie ); + + PAGED_CODE(); + + DbgPrint( "!!! scanner.sys --- disconnected, port=0x%p\n", ScannerData.ClientPort ); + + // + // Close our handle to the connection: note, since we limited max connections to 1, + // another connect will not be allowed until we return from the disconnect routine. + // + + FltCloseClientPort( ScannerData.Filter, &ScannerData.ClientPort ); + + // + // Reset the user-process field. + // + + ScannerData.UserProcess = NULL; +} + + +NTSTATUS +ScannerUnload ( + _In_ FLT_FILTER_UNLOAD_FLAGS Flags + ) +/*++ + +Routine Description: + + This is the unload routine for the Filter driver. This unregisters the + Filter with the filter manager and frees any allocated global data + structures. + +Arguments: + + None. + +Return Value: + + Returns the final status of the deallocation routines. + +--*/ +{ + UNREFERENCED_PARAMETER( Flags ); + + ScannerFreeExtensions(); + + // + // Close the server port. + // + + FltCloseCommunicationPort( ScannerData.ServerPort ); + + // + // Unregister the filter + // + + FltUnregisterFilter( ScannerData.Filter ); + + return STATUS_SUCCESS; +} + + +NTSTATUS +ScannerInstanceSetup ( + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _In_ FLT_INSTANCE_SETUP_FLAGS Flags, + _In_ DEVICE_TYPE VolumeDeviceType, + _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType + ) +/*++ + +Routine Description: + + This routine is called by the filter manager when a new instance is created. + We specified in the registry that we only want for manual attachments, + so that is all we should receive here. + +Arguments: + + FltObjects - Describes the instance and volume which we are being asked to + setup. + + Flags - Flags describing the type of attachment this is. + + VolumeDeviceType - The DEVICE_TYPE for the volume to which this instance + will attach. + + VolumeFileSystemType - The file system formatted on this volume. + +Return Value: + + STATUS_SUCCESS - we wish to attach to the volume + STATUS_FLT_DO_NOT_ATTACH - no, thank you + +--*/ +{ + UNREFERENCED_PARAMETER( FltObjects ); + UNREFERENCED_PARAMETER( Flags ); + UNREFERENCED_PARAMETER( VolumeFilesystemType ); + + PAGED_CODE(); + + FLT_ASSERT( FltObjects->Filter == ScannerData.Filter ); + + // + // Don't attach to network volumes. + // + + if (VolumeDeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) { + + return STATUS_FLT_DO_NOT_ATTACH; + } + + return STATUS_SUCCESS; +} + +NTSTATUS +ScannerQueryTeardown ( + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags + ) +/*++ + +Routine Description: + + This is the instance detach routine for the filter. This + routine is called by filter manager when a user initiates a manual instance + detach. This is a 'query' routine: if the filter does not want to support + manual detach, it can return a failure status + +Arguments: + + FltObjects - Describes the instance and volume for which we are receiving + this query teardown request. + + Flags - Unused + +Return Value: + + STATUS_SUCCESS - we allow instance detach to happen + +--*/ +{ + UNREFERENCED_PARAMETER( FltObjects ); + UNREFERENCED_PARAMETER( Flags ); + + return STATUS_SUCCESS; +} + + +FLT_PREOP_CALLBACK_STATUS +ScannerPreCreate ( + _Inout_ PFLT_CALLBACK_DATA Data, + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _Flt_CompletionContext_Outptr_ PVOID *CompletionContext + ) +/*++ + +Routine Description: + + Pre create callback. We need to remember whether this file has been + opened for write access. If it has, we'll want to rescan it in cleanup. + This scheme results in extra scans in at least two cases: + -- if the create fails (perhaps for access denied) + -- the file is opened for write access but never actually written to + The assumption is that writes are more common than creates, and checking + or setting the context in the write path would be less efficient than + taking a good guess before the create. + +Arguments: + + Data - The structure which describes the operation parameters. + + FltObject - The structure which describes the objects affected by this + operation. + + CompletionContext - Output parameter which can be used to pass a context + from this pre-create callback to the post-create callback. + +Return Value: + + FLT_PREOP_SUCCESS_WITH_CALLBACK - If this is not our user-mode process. + FLT_PREOP_SUCCESS_NO_CALLBACK - All other threads. + +--*/ +{ + UNREFERENCED_PARAMETER( FltObjects ); + UNREFERENCED_PARAMETER( CompletionContext = NULL ); + + PAGED_CODE(); + + // + // See if this create is being done by our user process. + // + + if (IoThreadToProcess( Data->Thread ) == ScannerData.UserProcess) { + + DbgPrint( "!!! scanner.sys -- allowing create for trusted process \n" ); + + return FLT_PREOP_SUCCESS_NO_CALLBACK; + } + + return FLT_PREOP_SUCCESS_WITH_CALLBACK; +} + + +BOOLEAN +ScannerpCheckExtension ( + _In_ PUNICODE_STRING Extension + ) +/*++ + +Routine Description: + + Checks if this file name extension is something we are interested in + +Arguments + + Extension - Pointer to the file name extension + +Return Value + + TRUE - Yes we are interested + FALSE - No +--*/ +{ + ULONG count; + + if (Extension->Length == 0) { + + return FALSE; + } + + // + // Check if it matches any one of our static extension list + // + + for (count = 0; count < ScannedExtensionCount; count++) { + + if (RtlCompareUnicodeString( Extension, ScannedExtensions + count, TRUE ) == 0) { + + // + // A match. We are interested in this file + // + + return TRUE; + } + } + + return FALSE; +} + + +FLT_POSTOP_CALLBACK_STATUS +ScannerPostCreate ( + _Inout_ PFLT_CALLBACK_DATA Data, + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _In_opt_ PVOID CompletionContext, + _In_ FLT_POST_OPERATION_FLAGS Flags + ) +/*++ + +Routine Description: + + Post create callback. We can't scan the file until after the create has + gone to the filesystem, since otherwise the filesystem wouldn't be ready + to read the file for us. + +Arguments: + + Data - The structure which describes the operation parameters. + + FltObject - The structure which describes the objects affected by this + operation. + + CompletionContext - The operation context passed fron the pre-create + callback. + + Flags - Flags to say why we are getting this post-operation callback. + +Return Value: + + FLT_POSTOP_FINISHED_PROCESSING - ok to open the file or we wish to deny + access to this file, hence undo the open + +--*/ +{ + PSCANNER_STREAM_HANDLE_CONTEXT scannerContext; + FLT_POSTOP_CALLBACK_STATUS returnStatus = FLT_POSTOP_FINISHED_PROCESSING; + PFLT_FILE_NAME_INFORMATION nameInfo; + NTSTATUS status; + BOOLEAN safeToOpen, scanFile; + + UNREFERENCED_PARAMETER( CompletionContext ); + UNREFERENCED_PARAMETER( Flags ); + + // + // If this create was failing anyway, don't bother scanning now. + // + + if (!NT_SUCCESS( Data->IoStatus.Status ) || + (STATUS_REPARSE == Data->IoStatus.Status)) { + + return FLT_POSTOP_FINISHED_PROCESSING; + } + + // + // Check if we are interested in this file. + // + + status = FltGetFileNameInformation( Data, + FLT_FILE_NAME_NORMALIZED | + FLT_FILE_NAME_QUERY_DEFAULT, + &nameInfo ); + + if (!NT_SUCCESS( status )) { + + return FLT_POSTOP_FINISHED_PROCESSING; + } + + FltParseFileNameInformation( nameInfo ); + + // + // Check if the extension matches the list of extensions we are interested in + // + + scanFile = ScannerpCheckExtension( &nameInfo->Extension ); + + // + // Release file name info, we're done with it + // + + FltReleaseFileNameInformation( nameInfo ); + + if (!scanFile) { + + // + // Not an extension we are interested in + // + + return FLT_POSTOP_FINISHED_PROCESSING; + } + + (VOID) ScannerpScanFileInUserMode( FltObjects->Instance, + FltObjects->FileObject, + &safeToOpen ); + + if (!safeToOpen) { + + // + // Ask the filter manager to undo the create. + // + + DbgPrint( "!!! scanner.sys -- foul language detected in postcreate !!!\n" ); + + DbgPrint( "!!! scanner.sys -- undoing create \n" ); + + FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject ); + + Data->IoStatus.Status = STATUS_ACCESS_DENIED; + Data->IoStatus.Information = 0; + + returnStatus = FLT_POSTOP_FINISHED_PROCESSING; + + } else if (FltObjects->FileObject->WriteAccess) { + + // + // + // The create has requested write access, mark to rescan the file. + // Allocate the context. + // + + status = FltAllocateContext( ScannerData.Filter, + FLT_STREAMHANDLE_CONTEXT, + sizeof(SCANNER_STREAM_HANDLE_CONTEXT), + PagedPool, + &scannerContext ); + + if (NT_SUCCESS(status)) { + + // + // Set the handle context. + // + + scannerContext->RescanRequired = TRUE; + + (VOID) FltSetStreamHandleContext( FltObjects->Instance, + FltObjects->FileObject, + FLT_SET_CONTEXT_REPLACE_IF_EXISTS, + scannerContext, + NULL ); + + // + // Normally we would check the results of FltSetStreamHandleContext + // for a variety of error cases. However, The only error status + // that could be returned, in this case, would tell us that + // contexts are not supported. Even if we got this error, + // we just want to release the context now and that will free + // this memory if it was not successfully set. + // + + // + // Release our reference on the context (the set adds a reference) + // + + FltReleaseContext( scannerContext ); + } + } + + return returnStatus; +} + + +FLT_PREOP_CALLBACK_STATUS +ScannerPreCleanup ( + _Inout_ PFLT_CALLBACK_DATA Data, + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _Flt_CompletionContext_Outptr_ PVOID *CompletionContext + ) +/*++ + +Routine Description: + + Pre cleanup callback. If this file was opened for write access, we want + to rescan it now. + +Arguments: + + Data - The structure which describes the operation parameters. + + FltObject - The structure which describes the objects affected by this + operation. + + CompletionContext - Output parameter which can be used to pass a context + from this pre-cleanup callback to the post-cleanup callback. + +Return Value: + + Always FLT_PREOP_SUCCESS_NO_CALLBACK. + +--*/ +{ + NTSTATUS status; + PSCANNER_STREAM_HANDLE_CONTEXT context; + BOOLEAN safe; + + UNREFERENCED_PARAMETER( Data ); + UNREFERENCED_PARAMETER( CompletionContext ); + + status = FltGetStreamHandleContext( FltObjects->Instance, + FltObjects->FileObject, + &context ); + + if (NT_SUCCESS( status )) { + + if (context->RescanRequired) { + + (VOID) ScannerpScanFileInUserMode( FltObjects->Instance, + FltObjects->FileObject, + &safe ); + + if (!safe) { + + DbgPrint( "!!! scanner.sys -- foul language detected in precleanup !!!\n" ); + } + } + + FltReleaseContext( context ); + } + + + return FLT_PREOP_SUCCESS_NO_CALLBACK; +} + + +FLT_PREOP_CALLBACK_STATUS +ScannerPreWrite ( + _Inout_ PFLT_CALLBACK_DATA Data, + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _Flt_CompletionContext_Outptr_ PVOID *CompletionContext + ) +/*++ + +Routine Description: + + Pre write callback. We want to scan what's being written now. + +Arguments: + + Data - The structure which describes the operation parameters. + + FltObject - The structure which describes the objects affected by this + operation. + + CompletionContext - Output parameter which can be used to pass a context + from this pre-write callback to the post-write callback. + +Return Value: + + Always FLT_PREOP_SUCCESS_NO_CALLBACK. + +--*/ +{ + FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK; + NTSTATUS status; + PSCANNER_NOTIFICATION notification = NULL; + PSCANNER_STREAM_HANDLE_CONTEXT context = NULL; + ULONG replyLength; + BOOLEAN safe = TRUE; + PUCHAR buffer; + + UNREFERENCED_PARAMETER( CompletionContext ); + + // + // If not client port just ignore this write. + // + + if (ScannerData.ClientPort == NULL) { + + return FLT_PREOP_SUCCESS_NO_CALLBACK; + } + + status = FltGetStreamHandleContext( FltObjects->Instance, + FltObjects->FileObject, + &context ); + + if (!NT_SUCCESS( status )) { + + // + // We are not interested in this file + // + + return FLT_PREOP_SUCCESS_NO_CALLBACK; + } + + // + // Use try-finally to cleanup + // + + try { + + // + // Pass the contents of the buffer to user mode. + // + + if (Data->Iopb->Parameters.Write.Length != 0) { + + // + // Get the users buffer address. If there is a MDL defined, use + // it. If not use the given buffer address. + // + + if (Data->Iopb->Parameters.Write.MdlAddress != NULL) { + + buffer = MmGetSystemAddressForMdlSafe( Data->Iopb->Parameters.Write.MdlAddress, + NormalPagePriority | MdlMappingNoExecute ); + + // + // If we have a MDL but could not get and address, we ran out + // of memory, report the correct error + // + + if (buffer == NULL) { + + Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + Data->IoStatus.Information = 0; + returnStatus = FLT_PREOP_COMPLETE; + leave; + } + + } else { + + // + // Use the users buffer + // + + buffer = Data->Iopb->Parameters.Write.WriteBuffer; + } + + // + // In a production-level filter, we would actually let user mode scan the file directly. + // Allocating & freeing huge amounts of non-paged pool like this is not very good for system perf. + // This is just a sample! + // + + notification = ExAllocatePoolWithTag( NonPagedPool, + sizeof( SCANNER_NOTIFICATION ), + 'nacS' ); + if (notification == NULL) { + + Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + Data->IoStatus.Information = 0; + returnStatus = FLT_PREOP_COMPLETE; + leave; + } + + notification->BytesToScan = min( Data->Iopb->Parameters.Write.Length, SCANNER_READ_BUFFER_SIZE ); + + // + // The buffer can be a raw user buffer. Protect access to it + // + + try { + + RtlCopyMemory( ¬ification->Contents, + buffer, + notification->BytesToScan ); + + } except( EXCEPTION_EXECUTE_HANDLER ) { + + // + // Error accessing buffer. Complete i/o with failure + // + + Data->IoStatus.Status = GetExceptionCode() ; + Data->IoStatus.Information = 0; + returnStatus = FLT_PREOP_COMPLETE; + leave; + } + + // + // Send message to user mode to indicate it should scan the buffer. + // We don't have to synchronize between the send and close of the handle + // as FltSendMessage takes care of that. + // + + replyLength = sizeof( SCANNER_REPLY ); + + status = FltSendMessage( ScannerData.Filter, + &ScannerData.ClientPort, + notification, + sizeof( SCANNER_NOTIFICATION ), + notification, + &replyLength, + NULL ); + + if (STATUS_SUCCESS == status) { + + safe = ((PSCANNER_REPLY) notification)->SafeToOpen; + + } else { + + // + // Couldn't send message. This sample will let the i/o through. + // + + DbgPrint( "!!! scanner.sys --- couldn't send message to user-mode to scan file, status 0x%X\n", status ); + } + } + + if (!safe) { + + // + // Block this write if not paging i/o (as a result of course, this scanner will not prevent memory mapped writes of contaminated + // strings to the file, but only regular writes). The effect of getting ERROR_ACCESS_DENIED for many apps to delete the file they + // are trying to write usually. + // To handle memory mapped writes - we should be scanning at close time (which is when we can really establish that the file object + // is not going to be used for any more writes) + // + + DbgPrint( "!!! scanner.sys -- foul language detected in write !!!\n" ); + + if (!FlagOn( Data->Iopb->IrpFlags, IRP_PAGING_IO )) { + + DbgPrint( "!!! scanner.sys -- blocking the write !!!\n" ); + + Data->IoStatus.Status = STATUS_ACCESS_DENIED; + Data->IoStatus.Information = 0; + returnStatus = FLT_PREOP_COMPLETE; + } + } + + } finally { + + if (notification != NULL) { + + ExFreePoolWithTag( notification, 'nacS' ); + } + + if (context) { + + FltReleaseContext( context ); + } + } + + return returnStatus; +} + +#if (WINVER>=0x0602) + +FLT_PREOP_CALLBACK_STATUS +ScannerPreFileSystemControl ( + _Inout_ PFLT_CALLBACK_DATA Data, + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _Flt_CompletionContext_Outptr_ PVOID *CompletionContext + ) +/*++ + +Routine Description: + + Pre FS Control callback. + +Arguments: + + Data - The structure which describes the operation parameters. + + FltObject - The structure which describes the objects affected by this + operation. + + CompletionContext - Output parameter which can be used to pass a context + from this callback to the post-write callback. + +Return Value: + + FLT_PREOP_SUCCESS_NO_CALLBACK or FLT_PREOP_COMPLETE + +--*/ +{ + FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK; + NTSTATUS status; + ULONG fsControlCode; + PSCANNER_STREAM_HANDLE_CONTEXT context = NULL; + + UNREFERENCED_PARAMETER( CompletionContext ); + + FLT_ASSERT( Data != NULL ); + FLT_ASSERT( Data->Iopb != NULL ); + + // + // If not client port just ignore this write. + // + + if (ScannerData.ClientPort == NULL) { + + return FLT_PREOP_SUCCESS_NO_CALLBACK; + } + + status = FltGetStreamHandleContext( FltObjects->Instance, + FltObjects->FileObject, + &context ); + + if (!NT_SUCCESS( status )) { + + // + // We are not interested in this file + // + + return FLT_PREOP_SUCCESS_NO_CALLBACK; + } + + // + // Use try-finally to cleanup + // + + try { + + fsControlCode = Data->Iopb->Parameters.FileSystemControl.Common.FsControlCode; + + if (fsControlCode == FSCTL_OFFLOAD_WRITE) { + + // + // Scanner cannot access the data in this offload write request. + // In a production-level filter, we would actually let user mode + // scan the file after offload write completes (on cleanup etc). + // Since this is just a sample, block offload write with + // STATUS_ACCESS_DENIED, although this is not an acceptable + // production-level behavior. + // + + DbgPrint( "!!! scanner.sys -- blocking the offload write !!!\n" ); + + Data->IoStatus.Status = STATUS_ACCESS_DENIED; + Data->IoStatus.Information = 0; + + returnStatus = FLT_PREOP_COMPLETE; + } + + } finally { + + if (context) { + + FltReleaseContext( context ); + } + } + + return returnStatus; +} + +#endif + +////////////////////////////////////////////////////////////////////////// +// Local support routines. +// +///////////////////////////////////////////////////////////////////////// + +NTSTATUS +ScannerpScanFileInUserMode ( + _In_ PFLT_INSTANCE Instance, + _In_ PFILE_OBJECT FileObject, + _Out_ PBOOLEAN SafeToOpen + ) +/*++ + +Routine Description: + + This routine is called to send a request up to user mode to scan a given + file and tell our caller whether it's safe to open this file. + + Note that if the scan fails, we set SafeToOpen to TRUE. The scan may fail + because the service hasn't started, or perhaps because this create/cleanup + is for a directory, and there's no data to read & scan. + + If we failed creates when the service isn't running, there'd be a + bootstrapping problem -- how would we ever load the .exe for the service? + +Arguments: + + Instance - Handle to the filter instance for the scanner on this volume. + + FileObject - File to be scanned. + + SafeToOpen - Set to FALSE if the file is scanned successfully and it contains + foul language. + +Return Value: + + The status of the operation, hopefully STATUS_SUCCESS. The common failure + status will probably be STATUS_INSUFFICIENT_RESOURCES. + +--*/ + +{ + NTSTATUS status = STATUS_SUCCESS; + PVOID buffer = NULL; + ULONG bytesRead; + PSCANNER_NOTIFICATION notification = NULL; + FLT_VOLUME_PROPERTIES volumeProps; + LARGE_INTEGER offset; + ULONG replyLength, length; + PFLT_VOLUME volume = NULL; + + *SafeToOpen = TRUE; + + // + // If not client port just return. + // + + if (ScannerData.ClientPort == NULL) { + + return STATUS_SUCCESS; + } + + try { + + // + // Obtain the volume object . + // + + status = FltGetVolumeFromInstance( Instance, &volume ); + + if (!NT_SUCCESS( status )) { + + leave; + } + + // + // Determine sector size. Noncached I/O can only be done at sector size offsets, and in lengths which are + // multiples of sector size. A more efficient way is to make this call once and remember the sector size in the + // instance setup routine and setup an instance context where we can cache it. + // + + status = FltGetVolumeProperties( volume, + &volumeProps, + sizeof( volumeProps ), + &length ); + // + // STATUS_BUFFER_OVERFLOW can be returned - however we only need the properties, not the names + // hence we only check for error status. + // + + if (NT_ERROR( status )) { + + leave; + } + + length = max( SCANNER_READ_BUFFER_SIZE, volumeProps.SectorSize ); + + // + // Use non-buffered i/o, so allocate aligned pool + // + + buffer = FltAllocatePoolAlignedWithTag( Instance, + NonPagedPool, + length, + 'nacS' ); + + if (NULL == buffer) { + + status = STATUS_INSUFFICIENT_RESOURCES; + leave; + } + + notification = ExAllocatePoolWithTag( NonPagedPool, + sizeof( SCANNER_NOTIFICATION ), + 'nacS' ); + + if(NULL == notification) { + + status = STATUS_INSUFFICIENT_RESOURCES; + leave; + } + + // + // Read the beginning of the file and pass the contents to user mode. + // + + offset.QuadPart = bytesRead = 0; + status = FltReadFile( Instance, + FileObject, + &offset, + length, + buffer, + FLTFL_IO_OPERATION_NON_CACHED | + FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET, + &bytesRead, + NULL, + NULL ); + + if (NT_SUCCESS( status ) && (0 != bytesRead)) { + + notification->BytesToScan = (ULONG) bytesRead; + + // + // Copy only as much as the buffer can hold + // + + RtlCopyMemory( ¬ification->Contents, + buffer, + min( notification->BytesToScan, SCANNER_READ_BUFFER_SIZE ) ); + + replyLength = sizeof( SCANNER_REPLY ); + + status = FltSendMessage( ScannerData.Filter, + &ScannerData.ClientPort, + notification, + sizeof(SCANNER_NOTIFICATION), + notification, + &replyLength, + NULL ); + + if (STATUS_SUCCESS == status) { + + *SafeToOpen = ((PSCANNER_REPLY) notification)->SafeToOpen; + + } else { + + // + // Couldn't send message + // + + DbgPrint( "!!! scanner.sys --- couldn't send message to user-mode to scan file, status 0x%X\n", status ); + } + } + + } finally { + + if (NULL != buffer) { + + FltFreePoolAlignedWithTag( Instance, buffer, 'nacS' ); + } + + if (NULL != notification) { + + ExFreePoolWithTag( notification, 'nacS' ); + } + + if (NULL != volume) { + + FltObjectDereference( volume ); + } + } + + return status; +} + diff --git a/filesys/miniFilter/scanner/filter/scanner.h b/filesys/miniFilter/scanner/filter/scanner.h new file mode 100644 index 00000000..c45592e9 --- /dev/null +++ b/filesys/miniFilter/scanner/filter/scanner.h @@ -0,0 +1,160 @@ +/*++ + +Copyright (c) 1999-2002 Microsoft Corporation + +Module Name: + + scrubber.h + +Abstract: + Header file which contains the structures, type definitions, + constants, global variables and function prototypes that are + only visible within the kernel. + +Environment: + + Kernel mode + +--*/ +#ifndef __SCANNER_H__ +#define __SCANNER_H__ + + +/////////////////////////////////////////////////////////////////////////// +// +// Global variables +// +/////////////////////////////////////////////////////////////////////////// + + +typedef struct _SCANNER_DATA { + + // + // The object that identifies this driver. + // + + PDRIVER_OBJECT DriverObject; + + // + // The filter handle that results from a call to + // FltRegisterFilter. + // + + PFLT_FILTER Filter; + + // + // Listens for incoming connections + // + + PFLT_PORT ServerPort; + + // + // User process that connected to the port + // + + PEPROCESS UserProcess; + + // + // Client port for a connection to user-mode + // + + PFLT_PORT ClientPort; + +} SCANNER_DATA, *PSCANNER_DATA; + +extern SCANNER_DATA ScannerData; + +typedef struct _SCANNER_STREAM_HANDLE_CONTEXT { + + BOOLEAN RescanRequired; + +} SCANNER_STREAM_HANDLE_CONTEXT, *PSCANNER_STREAM_HANDLE_CONTEXT; + +#pragma warning(push) +#pragma warning(disable:4200) // disable warnings for structures with zero length arrays. + +typedef struct _SCANNER_CREATE_PARAMS { + + WCHAR String[0]; + +} SCANNER_CREATE_PARAMS, *PSCANNER_CREATE_PARAMS; + +#pragma warning(pop) + + +/////////////////////////////////////////////////////////////////////////// +// +// Prototypes for the startup and unload routines used for +// this Filter. +// +// Implementation in scanner.c +// +/////////////////////////////////////////////////////////////////////////// +DRIVER_INITIALIZE DriverEntry; +NTSTATUS +DriverEntry ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath + ); + +NTSTATUS +ScannerUnload ( + _In_ FLT_FILTER_UNLOAD_FLAGS Flags + ); + +NTSTATUS +ScannerQueryTeardown ( + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags + ); + +FLT_PREOP_CALLBACK_STATUS +ScannerPreCreate ( + _Inout_ PFLT_CALLBACK_DATA Data, + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _Flt_CompletionContext_Outptr_ PVOID *CompletionContext + ); + +FLT_POSTOP_CALLBACK_STATUS +ScannerPostCreate ( + _Inout_ PFLT_CALLBACK_DATA Data, + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _In_opt_ PVOID CompletionContext, + _In_ FLT_POST_OPERATION_FLAGS Flags + ); + +FLT_PREOP_CALLBACK_STATUS +ScannerPreCleanup ( + _Inout_ PFLT_CALLBACK_DATA Data, + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _Flt_CompletionContext_Outptr_ PVOID *CompletionContext + ); + +FLT_PREOP_CALLBACK_STATUS +ScannerPreWrite ( + _Inout_ PFLT_CALLBACK_DATA Data, + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _Flt_CompletionContext_Outptr_ PVOID *CompletionContext + ); + +#if (WINVER >= 0x0602) + +FLT_PREOP_CALLBACK_STATUS +ScannerPreFileSystemControl ( + _Inout_ PFLT_CALLBACK_DATA Data, + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _Flt_CompletionContext_Outptr_ PVOID *CompletionContext + ); + +#endif + +NTSTATUS +ScannerInstanceSetup ( + _In_ PCFLT_RELATED_OBJECTS FltObjects, + _In_ FLT_INSTANCE_SETUP_FLAGS Flags, + _In_ DEVICE_TYPE VolumeDeviceType, + _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType + ); + +#endif /* __SCANNER_H__ */ + diff --git a/filesys/miniFilter/scanner/filter/scanner.rc b/filesys/miniFilter/scanner/filter/scanner.rc new file mode 100644 index 00000000..9269b6cf --- /dev/null +++ b/filesys/miniFilter/scanner/filter/scanner.rc @@ -0,0 +1,10 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Scanner Filter" +#define VER_INTERNALNAME_STR "scanner.sys" + +#include "common.ver" diff --git a/filesys/miniFilter/scanner/filter/scanner.vcxproj b/filesys/miniFilter/scanner/filter/scanner.vcxproj new file mode 100644 index 00000000..99432692 --- /dev/null +++ b/filesys/miniFilter/scanner/filter/scanner.vcxproj @@ -0,0 +1,192 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{6F2E7887-B782-4624-A03A-7AC8CB1D6AB3}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{82607450-8E93-44E4-9EDC-AA0C310E0E64}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>WDM</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>WDM</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>WDM</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>WDM</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>scanner</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>scanner</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>scanner</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>scanner</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\fltMgr.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\fltMgr.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\fltMgr.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);POOL_NX_OPTIN=1</PreprocessorDefinitions> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\fltMgr.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="scanner.c" /> + <ResourceCompile Include="scanner.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/filesys/miniFilter/scanner/filter/scanner.vcxproj.Filters b/filesys/miniFilter/scanner/filter/scanner.vcxproj.Filters new file mode 100644 index 00000000..37511409 --- /dev/null +++ b/filesys/miniFilter/scanner/filter/scanner.vcxproj.Filters @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{714BE986-D639-4C08-B0B5-CEDD7F5A24B3}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{8E4DEA17-46F6-459E-91CA-8EB73909B60A}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{A4702A45-F819-43D0-B05B-56FFCA504075}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{A873A433-3F6A-4828-9BDA-9FDF6C9D4726}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="scanner.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="scanner.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file |
