首页
社区
课程
招聘
[分享]驱动中获取长文件名
发表于: 2010-1-23 14:39 4381

[分享]驱动中获取长文件名

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;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 324
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
兄台的方法貌似很是浪费CPU哦!
2010-1-23 14:49
0
游客
登录 | 注册 方可回帖
返回
//