Hi, everyone.
Recently, I'm triying to write a file system minifilter driver to intercept some I/O operations like "IRP_MJ_CREATE" to do some trace logging. I wrote a windows service which is to be enabled at system startup and load the minifilter driver. However, after I installed my minifilter driver, My windows cannot startup. It's stuck doing "startup repair". My platform is windows 7 build 7601, windows kits 6.9.9200.16384.
Here is my DriverEntry function
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 UNICODE_STRING uniEventName; UNREFERENCED_PARAMETER( RegistryPath ); DbgPrint (" hpp DriverObject base addr : %X \n",(ULONG)DriverObject->DriverStart); DbgPrint (" hpp DriverObject DriverSize : %u \n",DriverObject->DriverSize); thisDriInfo.DriverStart=DriverObject->DriverStart; thisDriInfo.DriverSize=DriverObject->DriverSize; ExInitializeFastMutex( &LogMutex ); InitializeListHead( &OutputBufferList ); KeInitializeSpinLock( &OutputBufferLock ); MaxRecordsToAllocate = DEFAULT_MAX_RECORDS_TO_ALLOCATE; RecordsAllocated = 0; ExInitializeNPagedLookasideList( &FreeBufferList, NULL, NULL, 0, RECORD_SIZE, SPY_TAG, 0 ); // // Register with FltMgr to tell it our callback routines // KdPrint(("hpp-----MzfFile-----DriverEntry---\n ")); 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; } RtlInitUnicodeString(&uniEventName, EVENT_NAME); //pEvent = IoCreateNotificationEvent(&uniEventName, &gEventHandle); //if (pEvent != NULL) //{ //KeClearEvent(pEvent); //} //ExInitializeFastMutex( &LogMutex ); //CurrentLog = ExAllocatePool( NonPagedPool, sizeof(*CurrentLog) ); //if( !CurrentLog ) { //return STATUS_INSUFFICIENT_RESOURCES; //goto final; //} //CurrentLog->Len = 0; //CurrentLog->Next = NULL; NumLog = 1; //DebugLogNum=0; final : if (!NT_SUCCESS( status ) ) { if (NULL != gServerPort) { FltCloseCommunicationPort( gServerPort ); } if (NULL != gFilterHandle) { FltUnregisterFilter( gFilterHandle ); } //if(!CurrentLog){ //不需要处理, 因为进入这里面的话说明还没初始化成功就挂了 //} ExDeleteNPagedLookasideList( &FreeBufferList ); } KdPrint(("hpp-----MzfFile-----DriverEntry--end-\n ")); return status; }
And this is my major I/O event process function:
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. FilemonHookRoutine --*/ { PFLT_FILE_NAME_INFORMATION FNameInfo; NTSTATUS Status; CHAR attributeString[ERRORLEN]; CHAR optionString[ERRORLEN]; CHAR fileName[MAXPATHLEN] = ""; CHAR volumeName[MAXPATHLEN] = ""; //CHAR fileAttr[500] = ""; UNICODE_STRING DosName; CHAR pathName[MAXPATHLEN] = ""; UNREFERENCED_PARAMETER( FltObjects ); UNREFERENCED_PARAMETER( CompletionContext ); UNREFERENCED_PARAMETER( Flags ); //这部分先预留 /*** if( Data->Iopb->MajorFunction == IRP_MJ_CREATE ) { // // Clear any existing fileobject/name association stored in the // hash table // //FilemonFreeHashEntry( FileObject ); //createPath = TRUE; } else if( currentIrpStack->MajorFunction == IRP_MJ_CLOSE ) { // // We treat close as a special case of create for name querying // since calling into NTFS during a close can result in a deadlock. // //createPath = TRUE; } else if( currentIrpStack->MajorFunction == IRP_MJ_CLEANUP && FileObject->Flags & FO_STREAM_FILE ) { // // Treat cleanup of stream file objects as special create case, because // querying them causes NTFS to screwup on NT 4 // } else { //createPath = FALSE; } GETPATHNAME( createPath ); ***/ //DbgPrint(("hpp---------PtPostOperationPassThrough-111-\n")); //分析一下这个判断是否通用 if ( !NT_SUCCESS( Data->IoStatus.Status ) || ( STATUS_REPARSE == Data->IoStatus.Status ) ) { //DbgPrint(("hpp---------PtPostOperationPassThrough-22-\n")); //return FLT_POSTOP_FINISHED_PROCESSING; } Status = FltGetFileNameInformation( Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &FNameInfo ); // If we could not get the name information then exit if (!NT_SUCCESS( Status )) { //DbgPrint(("hpp---------PtPostOperationPassThrough-333-\n")); return FLT_POSTOP_FINISHED_PROCESSING; } Status = FltParseFileNameInformation( FNameInfo ); // If we could not get the name information then exit if (!NT_SUCCESS( Status )) { //DbgPrint(("hpp---------PtPostOperationPassThrough-333---11-\n")); return FLT_POSTOP_FINISHED_PROCESSING; } if (!NPUnicodeStringToChar(&FNameInfo->Name, fileName)){ DbgPrint(("hpp----- NPUnicodeStringToChar-- -\n")); return FLT_POSTOP_FINISHED_PROCESSING; } if (!NPUnicodeStringToChar(&FNameInfo->Volume, volumeName)){ DbgPrint(("hpp----- NPUnicodeStringToChar-- -\n")); return FLT_POSTOP_FINISHED_PROCESSING; } if (! FilterVolumeDeviceNameToDosName(&FNameInfo->Volume,&DosName)){ DbgPrint(("hpp----- NPUnicodeStringToChar-- -\n")); return FLT_POSTOP_FINISHED_PROCESSING; } if (!NPUnicodeStringToChar(&DosName, pathName)){ DbgPrint(("hpp----- NPUnicodeStringToChar-- -\n")); return FLT_POSTOP_FINISHED_PROCESSING; } //getFullFileName(pathName,fileName); strcat_s(pathName,MAXPATHLEN,fileName+strlen(volumeName)); switch( Data->Iopb->MajorFunction ) { case IRP_MJ_CREATE: /** DbgPrint("hpp IRP_MJ_CREATE\t%s\tAttributes: %s Options:%s\n", pathName, CreateAttributesString( Data->Iopb->Parameters.Create.FileAttributes, attributeString ), CreateOptionsString( Data->Iopb->Parameters.Create.Options, optionString )); **/ LogRecord("hpp IRP_MJ_CREATE\tbegin\\%s\\end\tAttributes: %s Options:%s\n", pathName, CreateAttributesString( Data->Iopb->Parameters.Create.FileAttributes, attributeString ), CreateOptionsString( Data->Iopb->Parameters.Create.Options, optionString )); // If its an open-by-id we free the hash entry now so that on the next access to // the file we'll pick up the file's real name. // //这里是预留的代码 // if( currentIrpStack->Parameters.Create.Options & FILE_OPEN_BY_FILE_ID ) { // FilemonFreeHashEntry( FileObject ); // } break; case IRP_MJ_READ : LogRecord("hpp IRP_MJ_READ begin\\%s\\end\n",pathName ); break; case IRP_MJ_WRITE: LogRecord("hpp IRP_MJ_WRITE begin\\%s\\end \n",pathName ); //DbgPrint(("hpp IRP_MJ_WRITE\n")); break; case IRP_MJ_QUERY_INFORMATION : LogRecord("hpp IRP_MJ_QUERY_INFORMATION begin\\%s\\end \n",pathName ); //DbgPrint(("hpp IRP_MJ_QUERY_INFORMATION\n")); break; case IRP_MJ_SET_INFORMATION : if (Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation){ //strcpy(fileAttr,"FileDispositionInformation"); LogRecord(" hpp IRP_MJ_SET_INFORMATION begin\\%s\\end FileDispositionInformation ",pathName ); }else if (Data->Iopb->Parameters.SetFileInformation.FileInformationClass ==FileRenameInformation){ //strcpy(fileAttr,"FileRenameInformation"); LogRecord(" hpp IRP_MJ_SET_INFORMATION begin\\%s\\end FileRenameInformation",pathName ); }else{ //strcpy(fileAttr,"Any"); LogRecord(" hpp IRP_MJ_SET_INFORMATION begin\\%s\\end Any",pathName ); } break; case IRP_MJ_QUERY_EA : LogRecord("hpp IRP_MJ_QUERY_EA begin\\%s\\end \n",pathName ); //DbgPrint(("hpp IRP_MJ_QUERY_EA\n")); break; case IRP_MJ_SET_EA : LogRecord("hpp IRP_MJ_SET_EA begin\\%s\\end \n",pathName ); break; case IRP_MJ_QUERY_VOLUME_INFORMATION: LogRecord("hpp IRP_MJ_QUERY_VOLUME_INFORMATION\tbegin\\%s\\end\t%s", pathName, VolumeInformation[Data->Iopb->Parameters.QueryVolumeInformation.FsInformationClass] ); break; case IRP_MJ_SET_VOLUME_INFORMATION : LogRecord("%hpp IRP_MJ_SET_VOLUME_INFORMATION begin\\%s\\end", pathName); // VolumeInformation[Data->Iopb->Parameters.QueryVolumeInformation.FsInformationClass] ); break; case IRP_MJ_DIRECTORY_CONTROL : switch( Data->Iopb->MinorFunction ) { case IRP_MN_NOTIFY_CHANGE_DIRECTORY: LogRecord("hpp IRP_MJ_DIRECTORY_CONTROL begin\\%s\\end Change Notify", pathName); break; default: LogRecord("hpp IRP_MJ_DIRECTORY_CONTROL begin\\%s\\end", pathName); break; } break; case IRP_MJ_FILE_SYSTEM_CONTROL : LogRecord("hpp IRP_MJ_FILE_SYSTEM_CONTROL begin\\%s\\end\n", fileName); break; case IRP_MJ_DEVICE_CONTROL: LogRecord("hpp IRP_MJ_DEVICE_CONTROL begin\\%s\\end \n", fileName); break; case IRP_MJ_INTERNAL_DEVICE_CONTROL : LogRecord("hpp IRP_MJ_INTERNAL_DEVICE_CONTROL begin\\%s\\end\n", fileName); break; case IRP_MJ_CLEANUP : LogRecord("hpp IRP_MJ_CLEANUP begin\\%s\\end\n", fileName); break; case IRP_MJ_QUERY_QUOTA : LogRecord("hpp IRP_MJ_QUERY_QUOTA begin\\%s\\end \n", fileName); break; case IRP_MJ_SET_QUOTA : LogRecord("hpp IRP_MJ_SET_QUOTA begin\\%s\\end \n", fileName); break; case IRP_MJ_CLOSE : LogRecord("hpp IRP_MJ_CLOSE begin\\%s\\end \n", fileName); break; default: break; } //DbgPrint("hpp---------PtPostOperationPassThrough-444-\n"); return FLT_POSTOP_FINISHED_PROCESSING; }
Please help me, thank you