根據文件句柄獲得文件名


今天心血來潮,在MSDN中看到了一篇Obtain file name from Handle的文章,貌似是這么個標題,看到文章中用到了一個很重要的函數

GetMappedFileName,缺點就是只能獲得自己進程打開的文件,其它進程打開的文件貌似不行。

基本思路就是根據HANDLE 創建映射文件,調用GetMappedFileName獲得一個DosDevice路徑,然后GetLogicaDriveStrings獲得盤符字串,依次讀取盤符字串獲得對應的DosDevice路徑,看之前的DosDevice路徑中是否有現在的DosDevice路徑(strstr),有的話,就拿到盤符字串,然后把之前的DosDevice路徑中最后出現\的位置的字串和盤符字串連接起來就行程最后的路徑了,沒有的話,就再讀取下一個盤符的DosDevice路徑,依次這樣,直到找到為止。

 

下面是代碼。

// GetFileNameByHandle.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"
#include "Psapi.h"


int GetFileNameByHandle(HANDLE hFile,LPTSTR buff,DWORD size);
typedef DWORD (WINAPI *MyGetMappedFileName)(HANDLE,LPVOID,LPTSTR,DWORD);

int main(int argc, char* argv[])
{
    //先打開一個文件,獲得HANDE之后,把HANDLE傳遞給GetFileNameByHandle

    char filename[]="D:\\456.rar";
    HANDLE hFile =CreateFile(filename,
                            GENERIC_READ|GENERIC_WRITE,
                            FILE_SHARE_READ|FILE_SHARE_WRITE,
                            NULL,
                            OPEN_EXISTING,
                            NULL,
                            NULL);

    if(NULL==hFile||INVALID_HANDLE_VALUE==hFile)
    {
        printf("open file error%d",GetLastError());
        return 0;
    }

    char filepath[MAX_PATH]={0};
    GetFileNameByHandle(hFile,filepath,MAX_PATH);
    printf("%s\n",filepath);


    return 0;
}




int GetFileNameByHandle(HANDLE hFile,LPSTR buff,DWORD size)
{
    HANDLE hfilemap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,NULL,NULL,NULL);
    if(INVALID_HANDLE_VALUE==hfilemap)
    {
        printf("file mapping error");
        return 0;
    }


    LPVOID lpmap = MapViewOfFile(hfilemap,FILE_MAP_READ|FILE_MAP_WRITE,NULL,NULL,0);
    if(NULL==lpmap)
    {
        printf("map view file error%d",GetLastError());
        return 0;
    }

    //明明添加了Psapi.h 非說我GetMappedFileName沒有聲明
//    DWORD length = GetMappedFileName(GetCurrentProcess(),map,buff,size);

    MyGetMappedFileName GetMappedFileName =(MyGetMappedFileName)GetProcAddress(LoadLibrary("psapi.dll"),"GetMappedFileNameA");
    
    if(GetMappedFileName==NULL)
    {
        printf("Get funcaddress error");
        return 0;
    }
    DWORD length = GetMappedFileName(GetCurrentProcess(),lpmap,buff,size);
    if(0==length)
    {
        printf("get mapped file name error");
        return 0;
    
    }
//    printf("%s",buff);

    
    char DosPath[MAX_PATH]={0};
    char DriverString[MAX_PATH]={0};

    GetLogicalDriveStrings(MAX_PATH,DriverString);
    char * p = (char *)DriverString;  //p用來指向盤符
    do
    {
        *(p+2)='\0'; //由於QuerDosDevice第一個參數必須是c:這種類型的,不能有\所以我把那個\給抹掉了  
        QueryDosDevice((LPCTSTR)p,DosPath,MAX_PATH);
        char * q = strstr(buff,DosPath);//檢測buff中是否有DosDevice中的DosPath,有的話,p指向的那個字串就是要的盤符
        if(q!=0)
        {
            //找到之后應該把buff中最后一個出現\地方的字串復制過來和盤符組成路徑

            q = strrchr(buff,0x5c);

            //再把DriverString路徑中其它字符清零,只留下找到的盤符
            memset(p+2,0,MAX_PATH-2);
            strcat(p,q);  //連接路徑
            strcpy(buff,p);
            return 1;
        }
        
    
        p=p+4;  //指針移動到DriverString的下一個盤符處
    }while(*p!=0);

    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM