paladinii
驱动中牛
驱动中牛
  • 注册日期2003-10-28
  • 最后登录2012-03-09
  • 粉丝0
  • 关注0
  • 积分282分
  • 威望74点
  • 贡献值0点
  • 好评度23点
  • 原创分0分
  • 专家分0分
阅读:1472回复:2

SfGetFileFullPath问题(附带源代码)

楼主#
更多 发布于:2005-01-28 16:51
之前我看了Filemon和FileSpy代码并写了我自己的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: %wsn", fileObject->FileName.Buffer );

DbgPrint("===== Irp FileObject: %wsn", 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 tablen");
}
}
__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:computersharerealpath
//
// 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:0computersharerealpath
//
// 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:computersharerealpath
{

//
// 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);
}
Ideas for life!
fslife
驱动大牛
驱动大牛
  • 注册日期2004-06-07
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望49点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2005-01-28 18:02
呵呵,又来这个版了
看看这个帖子:
http://www.driverdevelop.com/forum/viewthread.php?tid=61247
在交流中学习。。。
paladinii
驱动中牛
驱动中牛
  • 注册日期2003-10-28
  • 最后登录2012-03-09
  • 粉丝0
  • 关注0
  • 积分282分
  • 威望74点
  • 贡献值0点
  • 好评度23点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2005-01-28 20:05
呵呵,这也被你找到了。看完了,还是有问题。你有没有做过类似的?能不能给我发个代码看看 paladin@redsec.org 先谢过了。

[编辑 -  1/28/05 by  paladinii]
Ideas for life!
游客

返回顶部