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