-
-
[分享]驱动中获取长文件名
-
发表于: 2010-1-23 14:39 4381
-
楚狂人的方法, 自己实现了一下
//
//this routine query long name of a full path name of
// file or dir name path (short or long)
// NOTE: if the input name couldn't or needn't to converse
// to short name, return STATUS_INVALID_PARAMETER
// NOTE: used in DisptchHook(), so, irp file io
//
NTSTATUS
QueryLongNameFile(
//full path name, like "C:\\aaa~1\\bbb",
// or "C:\\aaa\\bbb\\" (can with "\\" at last ),
// NOT ACCEPT "c:\\aaa\\\\bbb..." or "C:\\aaa/bbb..."
IN PUNICODE_STRING FileName,
//full path name, allocate buffer IN THIS ROUTINE,
// remember use ExFreePool()
OUT PUNICODE_STRING LongFileName
)
{
NTSTATUS status;
BOOLEAN shortName;
PWCHAR currPointer;
PWCHAR lastPointer;
IO_STATUS_BLOCK ioStatus;
ULONG size;
PFILE_BOTH_DIR_INFORMATION fileBothDirInfo;
AL_FILE_ID alFileId;
UNICODE_STRING dirName;
UNICODE_STRING fileName;
LIST_ENTRY longNameList;
PLIST_ENTRY entry;
PLONG_FILE_NAME_LIST listNode;
//
//check FileName if could and need to converse to long name
//
//file name must like "C:\\Xxx..." and lenth is 2 times
if(FileName->Length <= 3 * sizeof(WCHAR) ||
FileName->Length % 2!= 0 ||
FileName->Buffer [2] != L'\\')
{
return STATUS_INVALID_PARAMETER ;
}
//check if there's "~" in file name
shortName = FALSE;
for ( currPointer = FileName->Buffer + 3;
currPointer < FileName->Buffer + (ULONG)(FileName->Length / 2) ;
currPointer ++ )
{
if( *currPointer == L'~' ){
//may be short name
shortName = TRUE;
break;
}
}
if(!shortName){
return STATUS_INVALID_PARAMETER ;
}
//
//init long file name list
//
InitializeListHead(&longNameList);
//
//parse file name, and insert each longname in list
// "c:\\aaa~1\\bbb~2\\ccc~3.txt" should be break into
// query long name of "aaa~1" in "c:\\"
// query long name of "bbb~2" in "c:\\aaa~1\\"
// query long name of "ccc~3.txt" in "c:\\aaa~1\\bbb~2\\"
//
lastPointer = FileName->Buffer + 2;
currPointer = lastPointer + 1;
while(TRUE){
if( *currPointer == L'\\' ||
currPointer == FileName->Buffer + (ULONG)(FileName->Length / 2) )
{
if(currPointer > lastPointer + 1){
//
//got one file,
// open containing dir
//
dirName.Buffer = FileName->Buffer;
dirName.MaximumLength = dirName.Length = (USHORT)
( sizeof(WCHAR) * (lastPointer - FileName->Buffer + 1));
fileName .Buffer = lastPointer + 1;
fileName.MaximumLength = fileName.Length = (USHORT)
(sizeof(WCHAR) * (currPointer - lastPointer - 1));
status = AlFileCreate(
&alFileId,
&dirName,
FILE_LIST_DIRECTORY | FILE_TRAVERSE ,
FILE_ATTRIBUTE_NORMAL ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE , //because we just query,
// not set 0 to exclude others
FILE_OPEN,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ,
&ioStatus
);
if(!NT_SUCCESS(status)){
ListRemoveLongFileNameList( &longNameList);
return status;
}
//query FileBothDirectoryInformation of containing dir
// use a serial of size to try query info,
// because we won't know the proper size of info
// max size = 256 KB
// each time, enlarge size to 2 times to try again
for(size = 1024 ; size <= 256 * 1024 ; size *= 2){
fileBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)ExAllocatePool(
NonPagedPool, size);
if(!fileBothDirInfo){
AlFileClose(&alFileId);
ListRemoveLongFileNameList( &longNameList);
return STATUS_INSUFFICIENT_RESOURCES ;
}
status = AlDirectoryQuery (
&alFileId,
&ioStatus,
size,
FileBothDirectoryInformation ,
fileBothDirInfo,
TRUE,
FALSE,
&fileName
);
if(NT_SUCCESS(status)){
break;
}
ExFreePool(fileBothDirInfo );
}
AlFileClose(&alFileId);
if(!NT_SUCCESS(status)) {
ListRemoveLongFileNameList( &longNameList);
return status;
}
//
//check FileNameLength must >= 0 and be 2's times because
// we'll connect them later
if( fileBothDirInfo->FileNameLength == 0 ||
fileBothDirInfo->FileNameLength % 2 != 0 )
{
ExFreePool(fileBothDirInfo);
ListRemoveLongFileNameList( &longNameList);
return STATUS_INTERNAL_ERROR ;
}
//
//insert long file name list
//
listNode = (PLONG_FILE_NAME_LIST )ExAllocatePool(NonPagedPool , sizeof(LONG_FILE_NAME_LIST ));
if(!listNode){
ExFreePool(fileBothDirInfo);
ListRemoveLongFileNameList( &longNameList);
return STATUS_INSUFFICIENT_RESOURCES;
}
listNode->fileBothDirInfo = fileBothDirInfo ;
InsertTailList(&longNameList, &listNode->entry );
//
//update lastPointer
//
lastPointer = currPointer;
}else{
if(currPointer == FileName->Buffer + (ULONG)(FileName->Length / 2)){
//
//there's a "\\" at last of the path
// such as "C:\\aaa\\bbb\\"
// finish parse
//
break;
}else{
//
//invalid path
//
ListRemoveLongFileNameList( &longNameList);
return STATUS_INVALID_PARAMETER;
}
}
}
if(currPointer == FileName->Buffer + (ULONG)(FileName->Length / 2)){
//
//finish parse
//
break;
}
//
//next wchar
//
currPointer ++;
}
//
//collect each long file name to build full path
//
//generate length
LongFileName ->Length = 2 * sizeof(WCHAR); // "C:"
for(entry = longNameList.Flink ;
entry != &longNameList;
entry = entry->Flink )
{
LongFileName ->Length += sizeof(WCHAR); // "\\"
fileBothDirInfo =
((PLONG_FILE_NAME_LIST )CONTAINING_RECORD(entry, LONG_FILE_NAME_LIST , entry))->fileBothDirInfo ;
LongFileName ->Length += ((USHORT)fileBothDirInfo->FileNameLength);
}
if( *(currPointer - 1) == L'\\'){
//
//there's a "\\" at last of the path
// such as "C:\\aaa\\bbb\\"
//
LongFileName ->Length += sizeof(WCHAR);
}
//allocate buffer
LongFileName ->MaximumLength = LongFileName ->Length + sizeof(WCHAR);
LongFileName->Buffer = (PWCHAR)ExAllocatePool(NonPagedPool , LongFileName ->MaximumLength );
if( !LongFileName->Buffer){
ListRemoveLongFileNameList( &longNameList);
return STATUS_INSUFFICIENT_RESOURCES;
}
//fill buffer
lastPointer = LongFileName ->Buffer ;//reuse lastPointer
RtlCopyMemory(lastPointer, FileName->Buffer, 2 * sizeof(WCHAR)); //"C:"
lastPointer += 2 ;
for(entry = longNameList.Flink ;
entry != &longNameList;
entry = entry->Flink )
{
*lastPointer = L'\\';
lastPointer ++;
fileBothDirInfo =
((PLONG_FILE_NAME_LIST )CONTAINING_RECORD(entry, LONG_FILE_NAME_LIST , entry))->fileBothDirInfo ;
RtlCopyMemory( lastPointer, &fileBothDirInfo->FileName[0], fileBothDirInfo->FileNameLength);
lastPointer += ( fileBothDirInfo->FileNameLength / 2);
}
if( *(currPointer - 1) == L'\\'){
//
//there's a "\\" at last of the path
// such as "C:\\aaa\\bbb\\"
// add "\\" at last of LongFileName
//
*lastPointer = L'\\';
}
ListRemoveLongFileNameList( &longNameList);
return STATUS_SUCCESS;
}
//
//this routine query long name of a full path name of
// file or dir name path (short or long)
// NOTE: if the input name couldn't or needn't to converse
// to short name, return STATUS_INVALID_PARAMETER
// NOTE: used in DisptchHook(), so, irp file io
//
NTSTATUS
QueryLongNameFile(
//full path name, like "C:\\aaa~1\\bbb",
// or "C:\\aaa\\bbb\\" (can with "\\" at last ),
// NOT ACCEPT "c:\\aaa\\\\bbb..." or "C:\\aaa/bbb..."
IN PUNICODE_STRING FileName,
//full path name, allocate buffer IN THIS ROUTINE,
// remember use ExFreePool()
OUT PUNICODE_STRING LongFileName
)
{
NTSTATUS status;
BOOLEAN shortName;
PWCHAR currPointer;
PWCHAR lastPointer;
IO_STATUS_BLOCK ioStatus;
ULONG size;
PFILE_BOTH_DIR_INFORMATION fileBothDirInfo;
AL_FILE_ID alFileId;
UNICODE_STRING dirName;
UNICODE_STRING fileName;
LIST_ENTRY longNameList;
PLIST_ENTRY entry;
PLONG_FILE_NAME_LIST listNode;
//
//check FileName if could and need to converse to long name
//
//file name must like "C:\\Xxx..." and lenth is 2 times
if(FileName->Length <= 3 * sizeof(WCHAR) ||
FileName->Length % 2!= 0 ||
FileName->Buffer [2] != L'\\')
{
return STATUS_INVALID_PARAMETER ;
}
//check if there's "~" in file name
shortName = FALSE;
for ( currPointer = FileName->Buffer + 3;
currPointer < FileName->Buffer + (ULONG)(FileName->Length / 2) ;
currPointer ++ )
{
if( *currPointer == L'~' ){
//may be short name
shortName = TRUE;
break;
}
}
if(!shortName){
return STATUS_INVALID_PARAMETER ;
}
//
//init long file name list
//
InitializeListHead(&longNameList);
//
//parse file name, and insert each longname in list
// "c:\\aaa~1\\bbb~2\\ccc~3.txt" should be break into
// query long name of "aaa~1" in "c:\\"
// query long name of "bbb~2" in "c:\\aaa~1\\"
// query long name of "ccc~3.txt" in "c:\\aaa~1\\bbb~2\\"
//
lastPointer = FileName->Buffer + 2;
currPointer = lastPointer + 1;
while(TRUE){
if( *currPointer == L'\\' ||
currPointer == FileName->Buffer + (ULONG)(FileName->Length / 2) )
{
if(currPointer > lastPointer + 1){
//
//got one file,
// open containing dir
//
dirName.Buffer = FileName->Buffer;
dirName.MaximumLength = dirName.Length = (USHORT)
( sizeof(WCHAR) * (lastPointer - FileName->Buffer + 1));
fileName .Buffer = lastPointer + 1;
fileName.MaximumLength = fileName.Length = (USHORT)
(sizeof(WCHAR) * (currPointer - lastPointer - 1));
status = AlFileCreate(
&alFileId,
&dirName,
FILE_LIST_DIRECTORY | FILE_TRAVERSE ,
FILE_ATTRIBUTE_NORMAL ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE , //because we just query,
// not set 0 to exclude others
FILE_OPEN,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ,
&ioStatus
);
if(!NT_SUCCESS(status)){
ListRemoveLongFileNameList( &longNameList);
return status;
}
//query FileBothDirectoryInformation of containing dir
// use a serial of size to try query info,
// because we won't know the proper size of info
// max size = 256 KB
// each time, enlarge size to 2 times to try again
for(size = 1024 ; size <= 256 * 1024 ; size *= 2){
fileBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)ExAllocatePool(
NonPagedPool, size);
if(!fileBothDirInfo){
AlFileClose(&alFileId);
ListRemoveLongFileNameList( &longNameList);
return STATUS_INSUFFICIENT_RESOURCES ;
}
status = AlDirectoryQuery (
&alFileId,
&ioStatus,
size,
FileBothDirectoryInformation ,
fileBothDirInfo,
TRUE,
FALSE,
&fileName
);
if(NT_SUCCESS(status)){
break;
}
ExFreePool(fileBothDirInfo );
}
AlFileClose(&alFileId);
if(!NT_SUCCESS(status)) {
ListRemoveLongFileNameList( &longNameList);
return status;
}
//
//check FileNameLength must >= 0 and be 2's times because
// we'll connect them later
if( fileBothDirInfo->FileNameLength == 0 ||
fileBothDirInfo->FileNameLength % 2 != 0 )
{
ExFreePool(fileBothDirInfo);
ListRemoveLongFileNameList( &longNameList);
return STATUS_INTERNAL_ERROR ;
}
//
//insert long file name list
//
listNode = (PLONG_FILE_NAME_LIST )ExAllocatePool(NonPagedPool , sizeof(LONG_FILE_NAME_LIST ));
if(!listNode){
ExFreePool(fileBothDirInfo);
ListRemoveLongFileNameList( &longNameList);
return STATUS_INSUFFICIENT_RESOURCES;
}
listNode->fileBothDirInfo = fileBothDirInfo ;
InsertTailList(&longNameList, &listNode->entry );
//
//update lastPointer
//
lastPointer = currPointer;
}else{
if(currPointer == FileName->Buffer + (ULONG)(FileName->Length / 2)){
//
//there's a "\\" at last of the path
// such as "C:\\aaa\\bbb\\"
// finish parse
//
break;
}else{
//
//invalid path
//
ListRemoveLongFileNameList( &longNameList);
return STATUS_INVALID_PARAMETER;
}
}
}
if(currPointer == FileName->Buffer + (ULONG)(FileName->Length / 2)){
//
//finish parse
//
break;
}
//
//next wchar
//
currPointer ++;
}
//
//collect each long file name to build full path
//
//generate length
LongFileName ->Length = 2 * sizeof(WCHAR); // "C:"
for(entry = longNameList.Flink ;
entry != &longNameList;
entry = entry->Flink )
{
LongFileName ->Length += sizeof(WCHAR); // "\\"
fileBothDirInfo =
((PLONG_FILE_NAME_LIST )CONTAINING_RECORD(entry, LONG_FILE_NAME_LIST , entry))->fileBothDirInfo ;
LongFileName ->Length += ((USHORT)fileBothDirInfo->FileNameLength);
}
if( *(currPointer - 1) == L'\\'){
//
//there's a "\\" at last of the path
// such as "C:\\aaa\\bbb\\"
//
LongFileName ->Length += sizeof(WCHAR);
}
//allocate buffer
LongFileName ->MaximumLength = LongFileName ->Length + sizeof(WCHAR);
LongFileName->Buffer = (PWCHAR)ExAllocatePool(NonPagedPool , LongFileName ->MaximumLength );
if( !LongFileName->Buffer){
ListRemoveLongFileNameList( &longNameList);
return STATUS_INSUFFICIENT_RESOURCES;
}
//fill buffer
lastPointer = LongFileName ->Buffer ;//reuse lastPointer
RtlCopyMemory(lastPointer, FileName->Buffer, 2 * sizeof(WCHAR)); //"C:"
lastPointer += 2 ;
for(entry = longNameList.Flink ;
entry != &longNameList;
entry = entry->Flink )
{
*lastPointer = L'\\';
lastPointer ++;
fileBothDirInfo =
((PLONG_FILE_NAME_LIST )CONTAINING_RECORD(entry, LONG_FILE_NAME_LIST , entry))->fileBothDirInfo ;
RtlCopyMemory( lastPointer, &fileBothDirInfo->FileName[0], fileBothDirInfo->FileNameLength);
lastPointer += ( fileBothDirInfo->FileNameLength / 2);
}
if( *(currPointer - 1) == L'\\'){
//
//there's a "\\" at last of the path
// such as "C:\\aaa\\bbb\\"
// add "\\" at last of LongFileName
//
*lastPointer = L'\\';
}
ListRemoveLongFileNameList( &longNameList);
return STATUS_SUCCESS;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: