阅读:4096回复:22
用SFILTER中的sfGetFileName 函数取不到文件名有哪位大虾知道原因?谁能提供一个好的获取文件全路径的方法,不胜感激!!!
用SFILTER中的sfGetFileName 函数取不到文件名有哪位大虾知道原因?谁能提供一个好的获取文件全路径的方法,不胜感激!!!
|
|
最新喜欢:aasa2
|
沙发#
发布于:2005-01-28 09:31
在驱动里获取路径是一个很麻烦的问题,在filemon里提供了一个完整的获取IRP请求的文件的完整路径的一套东西,它是通过构造一个IRP请求来实现的,你可以参考一下,感觉还挺好的。
其中的函数是FilemonGetFullPath(),FilemonQueryFile(); |
|
|
板凳#
发布于:2005-01-28 11:56
之前我看了Filemon并按照它的代码写了我自己的SfGetFileFullPath和SfQueryFile函数,但我在SfCreate函数中调用后BugCheck,由于我的Softice在系统引导时候无法正常显示(花屏)所以也无法看到错误信息(郁闷)。大家帮我看看代码,还有谁知道为什么SOftice花屏,是不是我的softice版本的问题??
ULONG SfGetFileFullPath( BOOLEAN createPath, PFILE_OBJECT fileObject, PHOOK_EXTENSION hookExt, PCHAR fullPathName ) { PHASH_ENTRY hashEntry; PHASH_ENTRY newEntry; ULONG prefixLen; ANSI_STRING fileName; ANSI_STRING relatedName; BOOLEAN gotPath; FILE_INTERNAL_INFORMATION fileInternalInfo; PFILE_NAME_INFORMATION fileNameInfo; UNICODE_STRING fullUniName; ULONGLONG mftIndex; ULONG pathLen; ULONG slashes; PFILE_OBJECT relatedFileObject; PCHAR pathOffset = NULL; PCHAR ptr = NULL; CHAR szTmp[256] = {0}; sprintf(szTmp, "===== Irp FileObject: %ws\n", fileObject->FileName.Buffer ); DbgPrint("===== Irp FileObject: %ws\n", fileObject->FileName.Buffer); if( fullPathName ) { fullPathName[0] = 0; } if ( !hookExt || !hookExt->Hooked || !fullPathName || KeGetCurrentIrql() >= DISPATCH_LEVEL ) { return 0; } _try { _try { // // 1.Lookup the object in the hash table first to see if a name // has already been generated for it // KeEnterCriticalRegion(); ExAcquireResourceSharedLite( &HashResource, TRUE ); hashEntry = HashTable[ HASHOBJECT( fileObject ) ]; while( hashEntry && hashEntry->FileObject != fileObject ) { hashEntry = hashEntry->Next; } // // Did we find an entry? // if( hashEntry ) { // // Yes, so get the name from the entry. // strcpy( fullPathName, hashEntry->FullPathName ); return strlen(fullPathName); } } _except( EXCEPTION_EXECUTE_HANDLER ) { DbgPrint("Expression occures when try to get file name in Hash table\n"); } } __finally { ExReleaseResourceLite( &HashResource ); KeLeaveCriticalRegion(); } // // Not found the name in the hash table so either ask // the file system for it or construct it from the FileObject. // // // 2.1Calculate prefix length at first ( Here not in Hash entry ) // switch( hookExt->Type ) { case NPFS: prefixLen = NAMED_PIPE_PREFIX_LENGTH; break; case MSFS: prefixLen = MAIL_SLOT_PREFIX_LENGTH; break; default: // define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x14 if ( !fileObject || fileObject->DeviceObject == FILE_DEVICE_NETWORK_FILE_SYSTEM ) { prefixLen = 0; //net work file system has no prefix } else { //FileObject && FileObject->DeviceObject->DeviceType != 0x14 prefixLen = 2; // "C:" } break; }//end Calculating prefix length // // 2.2 If FileObject==NULL, we can't even ask for a name, // instead, construct it all by hand.(The Prefix len = 0) // // // If there's no file object, we can't even ask for a name. // if( !fileObject ) { if( hookExt->Type == NPFS ) { strcpy( fullPathName, NAMED_PIPE_PREFIX ); } else if ( hookExt->Type == MSFS ) { strcpy( fullPathName, MAIL_SLOT_PREFIX ); } else { sprintf( fullPathName, "%C:", hookExt->LogicalDrive ); } return strlen(fullPathName); }// end !FileObject // // Initialize variables // fileName.Buffer = NULL; relatedName.Buffer = NULL; gotPath = FALSE; // // Check for special case first: NTFS volume and a file object // with no name. It might be a metadata file that we "know" the name of. This // special case also stops us from querying NTFS for the name of a metadata // file on versions of NTFS prior to Whistler, which is a good thing since // that causes hangs and crashes. On Whistler metadata files have file names. // if ( !fileObject->FileName.Buffer && hookExt->FsAttributes && !memcmp( hookExt->FsAttributes->FileSystemName, L"NTFS", sizeof(L"NTFS")-sizeof(WCHAR))) { // // The only file that is opened without a name is a volume // if( createPath ) { sprintf( fullPathName, "%C:", hookExt->LogicalDrive ); // // Return right here without inserting this into the hash table, since this might // be the cleanup path of a metadata file and we can retrieve the metada's index // at a later point. // return strlen(fullPathName); } //END "if( IsCreate ) ", that is ! IsCreate else if( SfQueryFile( hookExt->FileSystem, fileObject, FileInternalInformation, &fileInternalInfo, sizeof( fileInternalInfo ) )) { // // Use the name in the metadata name index // mftIndex = fileInternalInfo.IndexNumber.QuadPart & ~0xF0000000; if( mftIndex <= MAX_NTFS_METADATA_FILE ) { sprintf( fullPathName, "%C:\\%s", hookExt->LogicalDrive, NtfsMetadataFileNames[ mftIndex ] ); gotPath = TRUE; } } // END SfQueryFile() } // END special case(NTFS volume and no name buffer) // // If we are not in the create path, we can ask the file system for the name. If we // are in the create path, we can't ask the file system for the name of the file object, since // the file system driver hasn't even seen the file object yet. // if( !gotPath && !createPath ) //Not special case : Normal case { // // Ask the file system for the name of the file, which its required to be // able to provide for the Win32 filename query function. We could use the // undocumented ObQueryNameString, but then we'd have to worry about // re-entrancy issues, since that call generates the IRP that we create // manually here. Since we send the IRP to the FSD below us, we don't need // to worry about seeing the IRP in our dispatch entry point. This can fail // in some cases, so we fall back on constructing the name ourselves if // we have to. // // // FILE_NAME_INFORMATION docuemented in IFS kit or NTDDK 5.0 // fileNameInfo = (PFILE_NAME_INFORMATION) ExAllocatePool( NonPagedPool, MAXPATHLEN * sizeof(WCHAR) ); if( fileNameInfo && SfQueryFile(hookExt->FileSystem, fileObject, FileNameInformation, fileNameInfo, (MAXPATHLEN - prefixLen - 1)*sizeof(WCHAR) )) { fullUniName.Length = (SHORT) fileNameInfo->FileNameLength; fullUniName.Buffer = fileNameInfo->FileName; if( NT_SUCCESS( RtlUnicodeStringToAnsiString( &fileName, &fullUniName, TRUE ))) { fullPathName[ fileName.Length + prefixLen ] = 0; //set end flag if( hookExt->Type == NPFS ) { strcpy( fullPathName, NAMED_PIPE_PREFIX ); } else if( hookExt->Type == MSFS ) { strcpy( fullPathName, MAIL_SLOT_PREFIX ); } else if( fileObject->DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM ) { sprintf( fullPathName, "%C:", hookExt->LogicalDrive ); } else { // // No prefix for network devices // } // End setting prefix string //memcpy( &fullPathName[prefixLen], fileName.Buffer, fileName.Length ); RtlCopyMemory( &fullPathName[prefixLen], fileName.Buffer, fileName.Length ); gotPath = TRUE; RtlFreeAnsiString( &fileName ); fileName.Buffer = NULL; } } if( fileNameInfo ) { ExFreePool( fileNameInfo ); } } // End if( !gotFile && !IsCreate ) //not special case : Normal case // // If we don't have a name yet then we are in the create path, or we failed // when we asked the file system for the name. In that case we'll go ahead // and construct the name based on file object names. // // IsCreate || ! FileproQueryFile // if( !gotPath ) { // // If there is no file name at this point, just return "DEVICE" to indicate // raw access to a device // if( !fileObject->FileName.Buffer ) { if( hookExt->Type == NPFS ) { strcpy( fullPathName, NAMED_PIPE_PREFIX ); } else if( hookExt->Type == MSFS ) { strcpy( fullPathName, MAIL_SLOT_PREFIX ); } else { sprintf( fullPathName, "%C:", hookExt->LogicalDrive ); } return strlen( fullPathName ); } // // Create the full path name. First, calculate the length taking into // account space for seperators and the leading prefix // if( !NT_SUCCESS( RtlUnicodeStringToAnsiString( &fileName, &fileObject->FileName, TRUE ))) { if( hookExt->Type == NPFS ) { sprintf( fullPathName, "%s: <Out of Memory>", NAMED_PIPE_PREFIX ); } else if( hookExt->Type == MSFS ) { sprintf( fullPathName, "%s: <Out of Memory>", MAIL_SLOT_PREFIX ); } else { sprintf( fullPathName, "%C: <Out of Memory>", hookExt->LogicalDrive ); } return strlen( fullPathName ); } pathLen = fileName.Length + prefixLen; relatedFileObject = fileObject->RelatedFileObject; // // Only look at related file object if this is a relative name // if( fileObject->FileName.Buffer[0] != L'\\' && //Get related fileobject namelength relatedFileObject && relatedFileObject->FileName.Length ) { if( !NT_SUCCESS( RtlUnicodeStringToAnsiString( &relatedName, &relatedFileObject->FileName, TRUE ))) { if( hookExt->Type == NPFS ) { sprintf( fullPathName, "%s: <Out of Memory>", NAMED_PIPE_PREFIX ); } else if( hookExt->Type == MSFS ) { sprintf( fullPathName, "%s: <Out of Memory>", MAIL_SLOT_PREFIX ); } else { sprintf( fullPathName, "%C: <Out of Memory>", hookExt->LogicalDrive ); } RtlFreeAnsiString( &fileName ); return strlen( fullPathName ); } pathLen += relatedName.Length+1; } // End Filename.Buffer[0]!="\\" // // Add the drive letter first at the front of the name // if( hookExt->Type == NPFS ) { strcpy( fullPathName, NAMED_PIPE_PREFIX ); } else if( hookExt->Type == MSFS ) { strcpy( fullPathName, MAIL_SLOT_PREFIX ); } else if( fileObject->DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM ) { sprintf( fullPathName, "%C:", hookExt->LogicalDrive ); } // // If the name is too long, quit now // if( pathLen >= MAXPATHLEN ) { strcat( fullPathName, " <Name Too Long>" ); } else { // // Now we can build the path name // fullPathName[ pathLen ] = 0; // Set end flag pathOffset = fullPathName + pathLen - fileName.Length; // from next of prefix //memcpy( pathOffset, fileName.Buffer, fileName.Length + 1 ); RtlCopyMemory( pathOffset, fileName.Buffer, fileName.Length + 1 ); if( fileObject->FileName.Buffer[0] != L'\\' && relatedFileObject && relatedFileObject->FileName.Length ) { // // Copy the component, adding a slash separator // *(pathOffset - 1) = '\\'; pathOffset -= relatedName.Length + 1; //memcpy( pathOffset, relatedName.Buffer, relatedName.Length ); RtlCopyMemory( pathOffset, relatedName.Buffer, relatedName.Length ); // // If we've got to slashes at the front zap one // if( pathLen > 3 && fullPathName[2] == '\\' && fullPathName[3] == '\\' ) { strcpy( fullPathName + 2, fullPathName + 3 ); } } // End processing related fileobject } // End pathLen < MAXPATHLEN } // End !gotFile if( fileName.Buffer ) { RtlFreeAnsiString( &fileName ); } if( relatedName.Buffer ) { RtlFreeAnsiString( &relatedName ); } // // Network redirector names already specify a share name that we // have to strip: // // \X:\computer\share\realpath // // And we want to present: // // X:\realpath // // to the user. // if( fileObject->DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM && strlen( fullPathName ) >= strlen("\\X:\\") ) { // // If this is Win2k the name is specified like this: // // \;X:0\computer\share\realpath // // so we have to handle that case as well // if( fullPathName[1] == ';' ) { // // Win2K-style name. Grab the drive letter // and skip over the share // fullPathName[0] = fullPathName[2]; fullPathName[1] = ':'; fullPathName[2] = '\\'; // // The third slash after the drive is the // start of the real path (we start scanning // at the ':' since we don't want to make assumptions // about the length of the number). // slashes = 0; // begin to count ptr = &fullPathName[3]; // ==':' while( *ptr && slashes != 3 ) // The third '\' character { if( *ptr == '\\' ) { slashes++; } ptr++; } strcpy( &fullPathName[3], ptr ); // found the third '\' character } else if( fullPathName[2] == ':' ) // "\X:\computer\share\realpath { // // NT 4-style name. Skip the share name // fullPathName[0] = fullPathName[1]; fullPathName[1] = ':'; fullPathName[2] = '\\'; // // The second slash after the drive's slash (x:\) // is the start of the real path // slashes = 0; ptr = &fullPathName[3]; while( *ptr && slashes != 3 ) { if( *ptr == '\\' ) { slashes++; } ptr++; } strcpy( &fullPathName[3], ptr ); } else { // // Its a UNC path // RtlMoveMemory( &fullPathName[1], fullPathName, strlen(fullPathName) + 1); fullPathName[0] = '\\'; } } // End network name processing // // Allocate a hash entry // newEntry = ExAllocatePool( NonPagedPool, sizeof(HASH_ENTRY ) + strlen( fullPathName ) + 1); // // If no memory for a new entry, oh well. // if( newEntry ) { // // Fill in the new entry // newEntry->FileObject = fileObject; strcpy( newEntry->FullPathName, fullPathName ); // // Put it in the hash table // KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite( &HashResource, TRUE ); newEntry->Next = HashTable[ HASHOBJECT(fileObject) ]; HashTable[ HASHOBJECT(fileObject) ] = newEntry; ExReleaseResourceLite( &HashResource ); KeLeaveCriticalRegion(); } return strlen(fullPathName); } |
|
|
地板#
发布于:2005-01-28 13:50
你先用下面的代码试试看,也就是你注释出来的Normal case段代码,看看效果如何。SoftIce花屏可能是显卡的问题(听别人说的,呵呵)
fileNameInfo = (PFILE_NAME_INFORMATION) ExAllocatePool( NonPagedPool, MAXPATHLEN * sizeof(WCHAR) ); if( fileNameInfo && SfQueryFile(hookExt->FileSystem, fileObject, FileNameInformation, fileNameInfo, (MAXPATHLEN - prefixLen - 1)*sizeof(WCHAR) )) { fullUniName.Length = (SHORT) fileNameInfo->FileNameLength; fullUniName.Buffer = fileNameInfo->FileName; if( NT_SUCCESS( RtlUnicodeStringToAnsiString( &fileName, &fullUniName, TRUE ))) { fullPathName[ fileName.Length + prefixLen ] = 0; //set end flag if( hookExt->Type == NPFS ) { strcpy( fullPathName, NAMED_PIPE_PREFIX ); } else if( hookExt->Type == MSFS ) { strcpy( fullPathName, MAIL_SLOT_PREFIX ); } else if( fileObject->DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM ) { sprintf( fullPathName, "%C:", hookExt->LogicalDrive ); } else { // // No prefix for network devices // } // End setting prefix string //memcpy( &fullPathName[prefixLen], fileName.Buffer, fileName.Length ); RtlCopyMemory( &fullPathName[prefixLen], fileName.Buffer, fileName.Length ); gotPath = TRUE; RtlFreeAnsiString( &fileName ); fileName.Buffer = NULL; } } if( fileNameInfo ) { ExFreePool( fileNameInfo ); } |
|
|
地下室#
发布于:2005-01-28 14:03
建议你再看看这个帖子,应该会有所帮助。
|
|
|
5楼#
发布于:2005-01-28 14:49
感谢fslife,你是唯一活跃的顶级会员了,其他人不知道是太忙还是觉得我的问题太小儿科了都不现身了。我在试试,如果你能给个例子代码就更好了。
|
|
|
6楼#
发布于:2005-01-28 17:20
用SFILTER中的sfGetFileName 函数得到文件名自己感觉挺好用的,当然我只是大概测试了一下,没有深入研究。如果得不到最好用windbg或则softice调试一下,看看是哪儿出现了问题。
|
|
|
7楼#
发布于:2005-01-28 17:47
你用的是什么版本的?我问了Neal 微软的 file filter driver group leader 他说以前版本的有Bug 建议用最新的,不知道你的是什么版本能否给兄弟上传一个,多谢了!
|
|
|
8楼#
发布于:2005-01-28 17:51
不好意思,刚才把链接给掉了,给你补上了,呵呵
下面这个帖子跟你的问题一样的: http://www.driverdevelop.com/forum/viewthread.php?tid=61247 |
|
|
9楼#
发布于:2005-01-28 19:11
感谢fslife,我的问题还是和他的有区别的,RtlVolumeDeviceToDosName routine ,you called it at dispatch level.
我要在SfCreate中拦截文件路径全名,在这里使用这个函数bugcheck 先给分。你有没有例子阿? |
|
|
10楼#
发布于:2005-01-28 19:15
在问个非技术问题,怎么给分阿? :D
|
|
|
11楼#
发布于:2005-01-30 18:47
给分了,不过还是希望大家谁能提供一个完成的例子。谢谢
|
|
|
12楼#
发布于:2005-02-01 12:56
搞定了
|
|
|
13楼#
发布于:2005-02-02 00:26
还是用filemon的函数搞定的吧?
|
|
14楼#
发布于:2005-02-02 10:09
呵呵,也是也不是。。。
|
|
|
15楼#
发布于:2005-02-02 14:57
简单说说你的思路吧
|
|
|
16楼#
发布于:2005-02-02 15:41
其实也没有什么,主要是参考了filespy代码,并感谢OSR的Neal以及这里热心的朋友的指点。总之,不能简单的构造IRP包,要视情况而论。
|
|
|
17楼#
发布于:2005-02-02 23:17
paladinii :
为什么不贡献出来呢? ;) 为大家指民方向啊 |
|
18楼#
发布于:2005-02-03 11:45
过一阵子我会把完整代码贴出来,现在还在完善。
|
|
|
19楼#
发布于:2005-02-26 09:11
期待
|
|
|
上一页
下一页