VOID PtOperationStatusCallback ( __in PCFLT_RELATED_OBJECTS FltObjects, __in PFLT_IO_PARAMETER_BLOCK ParameterSnapshot, __in NTSTATUS OperationStatus, __in PVOID RequesterContext ) /*++ Routine Description: This routine is called when the given operation returns from the call to IoCallDriver. This is useful for operations where STATUS_PENDING means the operation was successfully queued. This is useful for OpLocks and directory change notification operations. This callback is called in the context of the originating thread and will never be called at DPC level. The file object has been correctly referenced so that you can access it. It will be automatically dereferenced upon return. This is non-pageable because it could be called on the paging path Arguments: FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance, its associated volume and file object. RequesterContext - The context for the completion routine for this operation. OperationStatus - Return Value: The return value is the status of the operation. --*/ { UNREFERENCED_PARAMETER( FltObjects ); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("PassThrough!PtOperationStatusCallback: Entered\n") ); PT_DBG_PRINT( PTDBG_TRACE_OPERATION_STATUS, ("PassThrough!PtOperationStatusCallback: Status=%08x ctx=%p IrpMj=%02x.%02x \"%s\"\n", OperationStatus, RequesterContext, ParameterSnapshot->MajorFunction, ParameterSnapshot->MinorFunction, FltGetIrpName(ParameterSnapshot->MajorFunction)) ); }
/************************************************************************* MiniFilter initialization and unload routines. *************************************************************************/ NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ) { NTSTATUS status; UNREFERENCED_PARAMETER( RegistryPath ); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("minifilter0!DriverEntry: Entered\n") ); // // Register with FltMgr to tell it our callback routines // status = FltRegisterFilter( DriverObject, &FilterRegistration, &gFilterHandle ); ASSERT( NT_SUCCESS( status ) ); if (NT_SUCCESS( status )) { // // Start filtering i/o // status = FltStartFiltering( gFilterHandle ); if (!NT_SUCCESS( status )) FltUnregisterFilter( gFilterHandle ); } return status; }
VOID PtInstanceTeardownComplete ( __in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_TEARDOWN_FLAGS Flags ) /*++ Routine Description: This routine is called at the end of instance teardown. Arguments: FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance and its associated volume. Flags - Reason why this instance is been deleted. Return Value: None. --*/ { UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("PassThrough!PtInstanceTeardownComplete: Entered\n") ); }
NTSTATUS PtUnload ( __in FLT_FILTER_UNLOAD_FLAGS Flags ) /*++ Routine Description: This is the unload routine for this miniFilter driver. This is called when the minifilter is about to be unloaded. We can fail this unload request if this is not a mandatory unloaded indicated by the Flags parameter. Arguments: Flags - Indicating if this is a mandatory unload. Return Value: Returns the final status of this operation. --*/ { UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("PassThrough!PtUnload: Entered\n") ); FltUnregisterFilter( gFilterHandle ); return STATUS_SUCCESS; }
NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ) /*++ Routine Description: This is the initialization routine for this miniFilter driver. This registers with FltMgr and initializes all 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. --*/ { NTSTATUS status; UNREFERENCED_PARAMETER( RegistryPath ); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("PassThrough!DriverEntry: Entered\n") ); // // Register with FltMgr to tell it our callback routines // status = FltRegisterFilter( DriverObject, &FilterRegistration, &gFilterHandle ); ASSERT( NT_SUCCESS( status ) ); if (NT_SUCCESS( status )) { // // Start filtering i/o // status = FltStartFiltering( gFilterHandle ); if (!NT_SUCCESS( status )) { FltUnregisterFilter( gFilterHandle ); } } return status; }
NTSTATUS NPInstanceQueryTeardown ( __in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags ) { UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("minifilter1!NPInstanceQueryTeardown: Entered\n") ); return STATUS_SUCCESS; }
VOID NPInstanceTeardownComplete ( __in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_TEARDOWN_FLAGS Flags ) { UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("minifilter0!NPInstanceTeardownComplete: Entered\n") ); }
NTSTATUS NPUnload ( __in FLT_FILTER_UNLOAD_FLAGS Flags ) { UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("NPminifilter!NPUnload: Entered: Unregister Filter...\n") ); FltUnregisterFilter( gFilterHandle ); return STATUS_SUCCESS; }
VOID NPInstanceTeardownStart ( __in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_TEARDOWN_FLAGS Flags ) { NTSTATUS status = STATUS_SUCCESS; PVOLUME_CONTEXT context = NULL; UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("minifilter1!NPInstanceTeardownStart: Entered\n") ); status = FltGetVolumeContext(FltObjects->Filter, FltObjects->Volume, &context); if( NT_SUCCESS(status) && context->Name.Buffer != NULL) DbgPrint("[%wZ]\n", &context->Name); FltReleaseContext( context ); }
NTSTATUS NPInstanceSetup ( __in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_SETUP_FLAGS Flags, __in DEVICE_TYPE VolumeDeviceType, __in FLT_FILESYSTEM_TYPE VolumeFilesystemType ) { UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( Flags ); UNREFERENCED_PARAMETER( VolumeDeviceType ); UNREFERENCED_PARAMETER( VolumeFilesystemType ); PAGED_CODE(); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("minifilter0!NPInstanceSetup: Entered\n") ); return STATUS_SUCCESS; }
FLT_POSTOP_CALLBACK_STATUS PtPostOperationPassThrough ( __inout PFLT_CALLBACK_DATA Data, __in PCFLT_RELATED_OBJECTS FltObjects, __in_opt PVOID CompletionContext, __in FLT_POST_OPERATION_FLAGS Flags ) /*++ Routine Description: This routine is the post-operation completion routine for this miniFilter. This is non-pageable because it may be called at DPC level. Arguments: Data - Pointer to the filter callbackData that is passed to us. FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance, its associated volume and file object. CompletionContext - The completion context set in the pre-operation routine. Flags - Denotes whether the completion is successful or is being drained. Return Value: The return value is the status of the operation. --*/ { UNREFERENCED_PARAMETER( Data ); UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( CompletionContext ); UNREFERENCED_PARAMETER( Flags ); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("PassThrough!PtPostOperationPassThrough: Entered\n") ); return FLT_POSTOP_FINISHED_PROCESSING; }
FLT_PREOP_CALLBACK_STATUS claimsmanPreOperationNoPostOperation( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Flt_CompletionContext_Outptr_ PVOID *CompletionContext ) /*++ Routine Description: This routine is a pre-operation dispatch routine for this miniFilter. This is non-pageable because it could be called on the paging path Arguments: Data - Pointer to the filter callbackData that is passed to us. FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance, its associated volume and file object. CompletionContext - The context for the completion routine for this operation. Return Value: The return value is the status of the operation. --*/ { UNREFERENCED_PARAMETER(Data); UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(CompletionContext); PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanPreOperationNoPostOperation: Entered\n")); // This template code does not do anything with the callbackData, but // rather returns FLT_PREOP_SUCCESS_NO_CALLBACK. // This passes the request down to the next miniFilter in the chain. return FLT_PREOP_SUCCESS_NO_CALLBACK; }
FLT_PREOP_CALLBACK_STATUS PtPreOperationNoPostOperationPassThrough ( __inout PFLT_CALLBACK_DATA Data, __in PCFLT_RELATED_OBJECTS FltObjects, __deref_out_opt PVOID *CompletionContext ) /*++ Routine Description: This routine is the main pre-operation dispatch routine for this miniFilter. Since this is just a simple passThrough miniFilter it does not do anything with the callbackData but rather return FLT_PREOP_SUCCESS_WITH_CALLBACK thereby passing it down to the next miniFilter in the chain. This is non-pageable because it could be called on the paging path Arguments: Data - Pointer to the filter callbackData that is passed to us. FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance, its associated volume and file object. CompletionContext - The context for the completion routine for this operation. Return Value: The return value is the status of the operation. --*/ { UNREFERENCED_PARAMETER( Data ); UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( CompletionContext ); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("PassThrough!PtPreOperationNoPostOperationPassThrough: Entered\n") ); return FLT_PREOP_SUCCESS_NO_CALLBACK; }
NTSTATUS claimsmanInstanceSetup( _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 whenever a new instance is created on a volume. This gives us a chance to decide if we need to attach to this volume or not. If this routine is not defined in the registration structure, automatic instances are always created. Arguments: FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance and its associated volume. Flags - Flags describing the reason for this attach request. Return Value: STATUS_SUCCESS - attach STATUS_FLT_DO_NOT_ATTACH - do not attach --*/ { UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(Flags); UNREFERENCED_PARAMETER(VolumeDeviceType); UNREFERENCED_PARAMETER(VolumeFilesystemType); PAGED_CODE(); PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanInstanceSetup: Entered\n")); return STATUS_SUCCESS; }
VOID NPCleanupVolumeContext( __in PFLT_CONTEXT Context, __in FLT_CONTEXT_TYPE ContextType ) { PVOLUME_CONTEXT context = Context; UNREFERENCED_PARAMETER( ContextType ); PAGED_CODE(); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("minifilter1!NPCleanupVolumeContext: Entered\n") ); ASSERT(ContextType == FLT_VOLUME_CONTEXT); if(context->Name.Buffer != NULL) { DbgPrint("minifilter1!NPCleanupVolumeContext: [%wZ]\n", &context->Name); ExFreePool(context->Name.Buffer); context->Name.Buffer = NULL; } }
NTSTATUS claimsmanInstanceQueryTeardown( _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags ) /*++ Routine Description: This is called when an instance is being manually deleted by a call to FltDetachVolume or FilterDetach thereby giving us a chance to fail that detach request. If this routine is not defined in the registration structure, explicit detach requests via FltDetachVolume or FilterDetach will always be failed. Arguments: FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance and its associated volume. Flags - Indicating where this detach request came from. Return Value: Returns the status of this operation. --*/ { UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(Flags); PAGED_CODE(); PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanInstanceQueryTeardown: Entered\n")); return STATUS_SUCCESS; }
FLT_PREOP_CALLBACK_STATUS NPPreCreate ( __inout PFLT_CALLBACK_DATA Data, __in PCFLT_RELATED_OBJECTS FltObjects, __deref_out_opt PVOID *CompletionContext ) { NTSTATUS status; PFLT_FILE_NAME_INFORMATION nameInfo; ANSI_STRING ansiStr; UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( CompletionContext ); PAGED_CODE(); __try { status = FltGetFileNameInformation( Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo ); if ( !NT_SUCCESS( status ) ) leave; status = FltParseFileNameInformation( nameInfo ); if ( !NT_SUCCESS( status ) ) leave; RtlUnicodeStringToAnsiString(&ansiStr, &nameInfo->Name, TRUE); PT_DBG_PRINT( PTDBG_TRACE_OPERATION_STATUS, ("minifilter0!NPPretCreate: create [%Z]\n", &ansiStr) ); RtlFreeAnsiString( &ansiStr ); FltReleaseFileNameInformation( nameInfo ); } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("NPPreCreate EXCEPTION_EXECUTE_HANDLER\n"); } return FLT_PREOP_SUCCESS_WITH_CALLBACK; }
FLT_POSTOP_CALLBACK_STATUS NPPostCreate ( __inout PFLT_CALLBACK_DATA Data, __in PCFLT_RELATED_OBJECTS FltObjects, __in_opt PVOID CompletionContext, __in FLT_POST_OPERATION_FLAGS Flags ) { UNREFERENCED_PARAMETER( CompletionContext ); UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); // // If this create was failing anyway, don't bother scanning now. // if (!NT_SUCCESS( Data->IoStatus.Status )) { PT_DBG_PRINT( PTDBG_TRACE_OPERATION_STATUS, ("minifilter0!NPPostCreate: failed\n") ); } return FLT_POSTOP_FINISHED_PROCESSING; }
NTSTATUS claimsmanUnload( _In_ FLT_FILTER_UNLOAD_FLAGS Flags ) /*++ Routine Description: This is the unload routine for this miniFilter driver. This is called when the minifilter is about to be unloaded. We can fail this unload request if this is not a mandatory unload indicated by the Flags parameter. Arguments: Flags - Indicating if this is a mandatory unload. Return Value: Returns STATUS_SUCCESS. --*/ { UNREFERENCED_PARAMETER(Flags); PAGED_CODE(); PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanUnload: Entered\n")); FltCloseCommunicationPort(ClaimsmanData.ServerPort); FltUnregisterFilter(ClaimsmanData.Filter); ClaimsmanFreeExtensions(); ClaimsmanFreeIgnoredUsers(); return STATUS_SUCCESS; }
NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ) /*++ Routine Description: This is the initialization routine for this miniFilter driver. This registers with FltMgr and initializes all 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. --*/ { NTSTATUS status; BOOLEAN bInit = FALSE; PSECURITY_DESCRIPTOR sd; OBJECT_ATTRIBUTES oa; UNICODE_STRING uniString; UNREFERENCED_PARAMETER( RegistryPath ); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("PassThrough!DriverEntry: Entered\n") ); try { status = FltRegisterFilter( DriverObject, &FilterRegistration, &gFilterHandle ); if (!NT_SUCCESS( status )) { leave; } #ifdef CV VirtualizerStart(); #endif status = InitDriverEntry( DriverObject,RegistryPath); #ifdef CV VirtualizerEnd(); #endif if (!NT_SUCCESS( status )) { bInit = FALSE; leave; } bInit = TRUE; status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS ); if (!NT_SUCCESS( status )) { leave; } RtlInitUnicodeString( &uniString, X70FSD_PORT_NAME ); InitializeObjectAttributes( &oa, &uniString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, sd ); status = FltCreateCommunicationPort( gFilterHandle, &gServerPort, &oa, NULL, PtMiniConnect, PtMiniDisconnect, PtMiniMessage, 1 ); FltFreeSecurityDescriptor( sd ); if (!NT_SUCCESS( status )) { leave; } status = FltStartFiltering( gFilterHandle ); } finally { if (!NT_SUCCESS( status ) ) { if (NULL != gServerPort) { FltCloseCommunicationPort( gServerPort); } if (NULL != gFilterHandle) { FltUnregisterFilter( gFilterHandle ); } if(bInit) { UnloadDriver(); } } } DbgPrint("status = %x ",status); return status; }
FLT_POSTOP_CALLBACK_STATUS claimsmanPostOperation( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_opt_ PVOID CompletionContext, _In_ FLT_POST_OPERATION_FLAGS Flags ) /*++ Routine Description: This routine is the post-operation completion routine for this miniFilter. This is non-pageable because it may be called at DPC level. Arguments: Data - Pointer to the filter callbackData that is passed to us. FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance, its associated volume and file object. CompletionContext - The completion context set in the pre-operation routine. Flags - Denotes whether the completion is successful or is being drained. Return Value: The return value is the status of the operation. --*/ { UNREFERENCED_PARAMETER(Data); UNREFERENCED_PARAMETER(CompletionContext); UNREFERENCED_PARAMETER(Flags); NTSTATUS status; PFLT_FILE_NAME_INFORMATION nameInfo = NULL; PUNICODE_STRING fileName = NULL; PTOKEN_USER pTokenUser = NULL; UNICODE_STRING sidString; LARGE_INTEGER Timeout; Timeout.QuadPart = (LONGLONG)1 * 10 * 1000 * 1000; // If there is no client registered, bail out immediately! // If the event is from kernel, bail out immediately! // If the event check for existence of file, bail out immediately! if ( (ClaimsmanData.ClientPort == NULL) || (Data->RequestorMode == KernelMode) || (Data->IoStatus.Information == FILE_DOES_NOT_EXIST) || (Data->IoStatus.Information == FILE_EXISTS) ) { return FLT_POSTOP_FINISHED_PROCESSING; } // We got a log record, if there is a file object, get its name. if (FltObjects->FileObject != NULL) { status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo); } else { // Can't get a name when there's no file object status = STATUS_UNSUCCESSFUL; } if (NT_SUCCESS(status)) { FltParseFileNameInformation(nameInfo); fileName = &nameInfo->Name; // Produces way too much logging //PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, // ("claimsman!claimsmanPostOperation: fileName=%wZ\n", fileName)); } else { // No point continuing because we obviously did not get a filename anyways return FLT_POSTOP_FINISHED_PROCESSING; } //The only IRP you can trust for user information is IRP_MJ_CREATE. Things //like write can be in arbitrary thread context, and even if the call works //you can get the wrong SID. status = SeQueryInformationToken(SeQuerySubjectContextToken(&(Data->Iopb->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext)), TokenUser, &pTokenUser); if (STATUS_SUCCESS == status && RtlValidSid(pTokenUser->User.Sid)) { // Interesting extension? if (ClaimsmanCheckExtension(&nameInfo->Extension)) { CLAIMSMAN_MESSAGE msg; status = RtlConvertSidToUnicodeString(&sidString, pTokenUser->User.Sid, TRUE); if (NT_SUCCESS(status)) { PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanPostOperation: SID=%wZ\n", &sidString)); } else { // No point continuing because we obviously did not get a valid SID FltReleaseFileNameInformation(nameInfo); ExFreePool(pTokenUser); return FLT_POSTOP_FINISHED_PROCESSING; } if (ClaimsmanCheckUserIgnore(&sidString)) { // Ignored user! Bail out! FltReleaseFileNameInformation(nameInfo); ExFreePool(pTokenUser); RtlFreeUnicodeString(&sidString); return FLT_POSTOP_FINISHED_PROCESSING; } LONGLONG size; LONGLONG modified; getSizeModified(FltObjects->Instance, fileName, &size, &modified); InitializeMessage(&msg, &sidString, fileName, FltObjects->FileObject->ReadAccess, FltObjects->FileObject->WriteAccess, FltObjects->FileObject->DeleteAccess, size, modified, Data->IoStatus.Status); // Ready, send the message! // But only if there's a client connected if (ClaimsmanData.ClientPort != NULL) { FltSendMessage(ClaimsmanData.Filter, &ClaimsmanData.ClientPort, &msg, sizeof(msg), NULL, 0, &Timeout ); PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanPostOperation: sent message=%d\n", status)); } else { PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanPostOperation: no client connected!")); } RtlFreeUnicodeString(&sidString); } } FltReleaseFileNameInformation(nameInfo); if (pTokenUser != NULL) { ExFreePool(pTokenUser); } return FLT_POSTOP_FINISHED_PROCESSING; }
void InitializeMessage( _Inout_ CLAIMSMAN_MESSAGE *message, _In_ PUNICODE_STRING sid, _In_ PUNICODE_STRING name, _In_ BOOLEAN ReadAccess, _In_ BOOLEAN WriteAccess, _In_ BOOLEAN DeleteAccess, _In_ LONGLONG size, _In_ LONGLONG modified, _In_ NTSTATUS status ) /* ... */ { PAGED_CODE(); PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanInitializeMessage: Entered\n")); // SID USHORT len = (sid->Length < ((CLAIMSMAN_MESSAGE_SID_SIZE - 1) * sizeof(WCHAR))) ? sid->Length : (CLAIMSMAN_MESSAGE_SID_SIZE - 1) * sizeof(WCHAR); RtlCopyMemory(message->Sid, sid->Buffer, len); message->Sid[(len / sizeof(WCHAR)) + (len % sizeof(WCHAR))] = 0; // FileName len = (name->Length < ((CLAIMSMAN_MESSAGE_FILENAME_SIZE - 1) * sizeof(WCHAR))) ? name->Length : (CLAIMSMAN_MESSAGE_FILENAME_SIZE - 1) * sizeof(WCHAR); RtlCopyMemory(message->FileName, name->Buffer, len); message->FileName[(len / sizeof(WCHAR)) + (len % sizeof(WCHAR))] = 0; // Access info message->ReadAccess = ReadAccess; message->WriteAccess = WriteAccess; message->DeleteAccess = DeleteAccess; // Size message->size = size; // Last modified TIME_FIELDS tf; message->UnixLastModified = modified; LONGLONG tstmp = (modified * 10000) + DIFF_TO_UNIX_EPOCH; RtlTimeToTimeFields(&tstmp, &tf); RtlStringCchPrintfW((NTSTRSAFE_PWSTR)message->LastModified, CLAIMSMAN_MESSAGE_TIMESTAMP_SIZE - 1, L"%04u-%02u-%02uT%02u:%02u:%02u.%03uZ", tf.Year, tf.Month, tf.Day, tf.Hour, tf.Minute, tf.Second, tf.Milliseconds); // Iostatus message->Status = status; // Event timestamp LARGE_INTEGER st; KeQuerySystemTime(&st); // Store as timestamp (Unix epoch + 3 decimals for milliseconds) message->UnixTimeStamp = (st.QuadPart - DIFF_TO_UNIX_EPOCH) / 10000; //PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, // ("claimsman!claimsmanInitializeMessage: message->UnixTimeStamp: %I64u\n", message->UnixTimeStamp)); // And as ISO-8601... RtlTimeToTimeFields(&st, &tf); RtlStringCchPrintfW((NTSTRSAFE_PWSTR)message->TimeStamp, CLAIMSMAN_MESSAGE_TIMESTAMP_SIZE - 1, L"%04u-%02u-%02uT%02u:%02u:%02u.%03uZ", tf.Year, tf.Month, tf.Day, tf.Hour, tf.Minute, tf.Second, tf.Milliseconds); //PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, // ("claimsman!claimsmanInitializeMessage: message->TimeStamp: %ws\n", message->TimeStamp)); }
/************************************************************************* MiniFilter callback routines. *************************************************************************/ FLT_PREOP_CALLBACK_STATUS claimsmanPreOperation( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Flt_CompletionContext_Outptr_ PVOID *CompletionContext ) /*++ Routine Description: This routine is a pre-operation dispatch routine for this miniFilter. This is non-pageable because it could be called on the paging path Arguments: Data - Pointer to the filter callbackData that is passed to us. FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance, its associated volume and file object. CompletionContext - The context for the completion routine for this operation. Return Value: The return value is the status of the operation. --*/ { NTSTATUS status; UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(CompletionContext); PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanPreOperation: Entered\n")); // // See if this is an operation we would like the operation status // for. If so request it. // // NOTE: most filters do NOT need to do this. You only need to make // this call if, for example, you need to know if the oplock was // actually granted. // if (claimsmanDoRequestOperationStatus(Data)) { status = FltRequestOperationStatusCallback(Data, claimsmanOperationStatusCallback, (PVOID)(++OperationStatusCtx)); if (!NT_SUCCESS(status)) { PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS, ("claimsman!claimsmanPreOperation: FltRequestOperationStatusCallback Failed, status=%08x\n", status)); } } // This template code does not do anything with the callbackData, but // rather returns FLT_PREOP_SUCCESS_WITH_CALLBACK. // This passes the request down to the next miniFilter in the chain. return FLT_PREOP_SUCCESS_WITH_CALLBACK; }
NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ Routine Description: This is the initialization routine for this miniFilter driver. This registers with FltMgr and initializes all 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: Routine can return non success error codes. --*/ { NTSTATUS status; OBJECT_ATTRIBUTES oa; PSECURITY_DESCRIPTOR sd; UNICODE_STRING uniString; //UNREFERENCED_PARAMETER(RegistryPath); PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!DriverEntry: Entered\n")); // // Default to NonPagedPoolNx for non paged pool allocations where supported. // ExInitializeDriverRuntime(DrvRtPoolNxOptIn); // // Obtain the extensions to monitor from the registry // status = InitializeMonitoredExtensions(RegistryPath); if (!NT_SUCCESS(status)) { status = STATUS_SUCCESS; ClaimsmanData.MonitoredExtensions = &MonitoredExtensionDefault; ClaimsmanData.MonitoredExtensionCount = 1; } // // Obtain the ignored users from the registry // status = InitializeIgnoredUsers(RegistryPath); if (!NT_SUCCESS(status)) { status = STATUS_SUCCESS; ClaimsmanData.IgnoredUsers = &MonitoredExtensionDefault; ClaimsmanData.IgnoredUserCount = 1; } // // Register with FltMgr to tell it our callback routines // status = FltRegisterFilter(DriverObject, &FilterRegistration, &ClaimsmanData.Filter); if (!NT_SUCCESS(status)) { return status; } // // Initialize communication port // RtlInitUnicodeString(&uniString, ClaimsmanPortName); // Only ADMINs & SYSTEM can access the port status = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS); if (NT_SUCCESS(status)) { InitializeObjectAttributes(&oa, &uniString, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, sd); status = FltCreateCommunicationPort(ClaimsmanData.Filter, &ClaimsmanData.ServerPort, &oa, NULL, ClaimsmanConnect, ClaimsmanDisconnect, NULL, 1); // Not needed anymore FltFreeSecurityDescriptor(sd); if (!NT_SUCCESS(status)) { PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!DriverEntry: Unable to create communication port: %d\n", status)); } else { // // Start filtering I/O. // status = FltStartFiltering(ClaimsmanData.Filter); if (!NT_SUCCESS(status)) { FltUnregisterFilter(ClaimsmanData.Filter); FltCloseCommunicationPort(ClaimsmanData.ServerPort); } } } return status; }
/************************************************************************* MiniFilter callback routines. *************************************************************************/ FLT_PREOP_CALLBACK_STATUS PtPreOperationPassThrough ( __inout PFLT_CALLBACK_DATA Data, __in PCFLT_RELATED_OBJECTS FltObjects, __deref_out_opt PVOID *CompletionContext ) /*++ Routine Description: This routine is the main pre-operation dispatch routine for this miniFilter. Since this is just a simple passThrough miniFilter it does not do anything with the callbackData but rather return FLT_PREOP_SUCCESS_WITH_CALLBACK thereby passing it down to the next miniFilter in the chain. This is non-pageable because it could be called on the paging path Arguments: Data - Pointer to the filter callbackData that is passed to us. FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance, its associated volume and file object. CompletionContext - The context for the completion routine for this operation. Return Value: The return value is the status of the operation. --*/ { NTSTATUS status; FLT_PREOP_CALLBACK_STATUS FltStatus = FLT_PREOP_COMPLETE; UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( CompletionContext ); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("PassThrough!PtPreOperationPassThrough: Entered\n") ); if(IsMyFakeFcb(FltObjects->FileObject)) { if(FLT_IS_FASTIO_OPERATION(Data)) { /*DbgPrint("收到我们自己的fcb请求MajorFunction %x \n",Data->Iopb->MajorFunction ); DbgPrint("收到我们自己的fcb请求MinorFunction %x \n",Data->Iopb->MinorFunction ); DbgPrint("FastIo Passthru \n");*/ FltStatus = FLT_PREOP_DISALLOW_FASTIO ; return FltStatus; } if(FLT_IS_IRP_OPERATION(Data)) { DbgPrint("收到我们自己的fcb请求MajorFunction %x \n",Data->Iopb->MajorFunction ); DbgPrint("收到我们自己的fcb请求MinorFunction %x \n",Data->Iopb->MinorFunction ); DbgPrint("Irp Passthru \n"); FltStatus = X70FsdPrePassThroughIrp(Data,FltObjects,CompletionContext); return FltStatus; } if(FLT_IS_FS_FILTER_OPERATION(Data)) { Data->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; return FltStatus; } } // // See if this is an operation we would like the operation status // for. If so request it. // // NOTE: most filters do NOT need to do this. You only need to make // this call if, for example, you need to know if the oplock was // actually granted. // if (PtDoRequestOperationStatus( Data )) { status = FltRequestOperationStatusCallback( Data, PtOperationStatusCallback, (PVOID)(++OperationStatusCtx) ); if (!NT_SUCCESS(status)) { PT_DBG_PRINT( PTDBG_TRACE_OPERATION_STATUS, ("PassThrough!PtPreOperationPassThrough: FltRequestOperationStatusCallback Failed, status=%08x\n", status) ); } } return FLT_PREOP_SUCCESS_WITH_CALLBACK; }
NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ) { NTSTATUS status; PSECURITY_DESCRIPTOR sd; OBJECT_ATTRIBUTES oa; UNICODE_STRING uniString; //for communication port name UNREFERENCED_PARAMETER( RegistryPath ); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("NPminifilter!DriverEntry: Entered\n") ); // // Register with FltMgr to tell it our callback routines // status = FltRegisterFilter( DriverObject, &FilterRegistration, &gFilterHandle ); ASSERT( NT_SUCCESS( status ) ); if (NT_SUCCESS( status )) { // // Start filtering i/o // status = FltStartFiltering( gFilterHandle ); if (!NT_SUCCESS( status )) { FltUnregisterFilter( gFilterHandle ); } } //Communication Port status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS ); if (!NT_SUCCESS( status )) { goto final; } status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS ); if (!NT_SUCCESS( status )) { goto final; } RtlInitUnicodeString( &uniString, MINISPY_PORT_NAME ); InitializeObjectAttributes( &oa, &uniString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, sd ); status = FltCreateCommunicationPort( gFilterHandle, &gServerPort, &oa, NULL, NPMiniConnect, NPMiniDisconnect, NPMiniMessage, 1 ); FltFreeSecurityDescriptor( sd ); if (!NT_SUCCESS( status )) { goto final; } final :
NTSTATUS NPInstanceSetup ( __in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_SETUP_FLAGS Flags, __in DEVICE_TYPE VolumeDeviceType, __in FLT_FILESYSTEM_TYPE VolumeFilesystemType ) { NTSTATUS status = STATUS_SUCCESS; PVOLUME_CONTEXT context = NULL; ULONG retLen; UCHAR volPropBuffer[sizeof(FLT_VOLUME_PROPERTIES)+512]; PFLT_VOLUME_PROPERTIES volProp = (PFLT_VOLUME_PROPERTIES)volPropBuffer; PDEVICE_OBJECT devObj = NULL; UNREFERENCED_PARAMETER( Flags ); UNREFERENCED_PARAMETER( VolumeDeviceType ); UNREFERENCED_PARAMETER( VolumeFilesystemType ); PAGED_CODE(); PT_DBG_PRINT( PTDBG_TRACE_ROUTINES, ("minifilter1!NPInstanceSetup: Entered\n") ); try { // Allocate a volume context structure. status = FltAllocateContext( FltObjects->Filter, FLT_VOLUME_CONTEXT, sizeof(VOLUME_CONTEXT), NonPagedPool, &context ); if( !NT_SUCCESS(status) ) leave; // Get the volume properties, so I can get a sector size status = FltGetVolumeProperties( FltObjects->Volume, volProp, sizeof(volPropBuffer), &retLen ); if( !NT_SUCCESS(status) ) leave; // Get sector size ASSERT((volProp->SectorSize == 0) || (volProp->SectorSize >= MIN_SECTOR_SIZE)); context->SectorSize = max(volProp->SectorSize, MIN_SECTOR_SIZE); // Get device object, so I can get disk name context->Name.Buffer = NULL; status = FltGetDiskDeviceObject( FltObjects->Volume, &devObj ); if( !NT_SUCCESS(status) ) leave; status = IoVolumeDeviceToDosName( devObj, &context->Name); if( !NT_SUCCESS(status) ) leave; // Set the context status = FltSetVolumeContext( FltObjects->Volume, FLT_SET_CONTEXT_KEEP_IF_EXISTS, context, NULL ); DbgPrint("minifilter1!NPInstanceSetup: [%wZ 0x%04x/0x%04x]\n", &context->Name, context->SectorSize, volProp->SectorSize); DbgPrint("[%wZ - %wZ - %wZ]\n", &volProp->FileSystemDriverName, &volProp->FileSystemDeviceName, &volProp->RealDeviceName); if (status == STATUS_FLT_CONTEXT_ALREADY_DEFINED ) { status = STATUS_SUCCESS; } } finally { // Always release the context. If the set failed, it will free the // context. If not, it will remove the reference added by the set. // Note that the name buffer in the context will get freed by the // NPCleanupVolumeContext() routine. if(context) FltReleaseContext( context ); if(devObj) ObDereferenceObject( devObj ); } return status; }