今天心血來潮,在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; }