根据文件句柄获得文件名

今天心血来潮,在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;
}
posted @ 2012-08-23 18:28  shremie  阅读(7084)  评论(1编辑  收藏  举报