曲径通幽论坛

标题: GetFileNameFromHandle() -- 通过文件句柄获取文件路径 [打印本页]

作者: beyes    时间: 2012-2-23 11:17
标题: GetFileNameFromHandle() -- 通过文件句柄获取文件路径
GetFileNameFromHandle() 原型如下:
[C++] 纯文本查看 复制代码
DWORD WINAPI GetMappedFileName(
  __in   HANDLE hProcess,
  __in   LPVOID lpv,
  __out  LPTSTR lpFilename,
  __in   DWORD nSize
);

该函数可以实现从文件映射对象的句柄得到被映射文件的路径,但该路径是以设备名的形式给出的,也就是 MS-DOS 形式,类似于:
\Device\HarddiskVolume2\tmp.txt
上面的 \Device\HarddiskVolume2 就是 MS-DOS 形式设备名,将这样的设备名转换为我们通常所见的磁盘格路径形式(如 C:\)可以利用 QueryDosDevice() 函数来实现。

第 1 个参数 hProcess 是输入参数,表示映射对象所属的进程,若对象是在本进程中创建,那么进程句柄可以通过函数 GetCurrentProcess() 函数获得。

第 2 个参数 lpv 是输入参数,是映射视图的地址,MapViewOfFile()  函数的返回值就是它。

第 3 个参数 lpFilename 是输出参数,指向用来存储文件路径的缓冲区。

第 4 个参数 nSize 是输入参数,它是第 3 个参数所指缓冲区的大小,用来防止溢出。

测试代码
[C++] 纯文本查看 复制代码
// GetMapFileName.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#pragma comment(lib,"Psapi.lib")

#define    MAP_SIZE    0x28c04

#define BUFSIZE    512

typedef TCHAR *PTCHAR;

int _tmain(int argc, _TCHAR* argv[])
{
    setlocale (LC_ALL, "chs");

    HANDLE    hFile;
    HANDLE  hMapFile;    // 文件内存映射区域的句柄

    DWORD    dBtyesWritten;

    INT    i;

    LPVOID    lpMapAddress;    // 内存映射区域起始位置

    TCHAR    szFileName[MAX_PATH + 1];

    hFile = CreateFile (argv[1], GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        printf ("Create file error\n");
        return (-1);
    }

    //依次写入整数,一共 65535 个,共 65535*4 个字节
    for (i = 0; i < 65535; i++)
        WriteFile (hFile, &i, sizeof(i), &dBtyesWritten, NULL);

    hMapFile = CreateFileMapping ( hFile,                // 需要映射的文件句柄
                                   NULL,                // 使用默认安全选项
                                   PAGE_READWRITE,        // 可读,可写
                                   0,                    // mapping 对象的大小,高位
                                   MAP_SIZE,        // mapping 对象的大小,低位
                                   NULL);
    if (hMapFile == NULL) {
        printf ("CreateFileMapping error : %d\n", GetLastError());
        return (-2);
    }

    DWORD    dwFileMapStart = 0x20000;
    DWORD    dwMapViewSize = 0x8c04;

    lpMapAddress = MapViewOfFile ( hMapFile,             // mapping 对象的句柄
                                   FILE_MAP_ALL_ACCESS,  // 可读,可写
                                   0,                     // 映射的文件偏移,高位
                                   dwFileMapStart,         // 映射的文件偏移,低位
                                   dwMapViewSize);         // 映射到 View 的文件大小
    if (hMapFile == NULL) {
        printf ("CreateFileMapping error : %d\n", GetLastError());
        return (-2);
    }

    // 从 Mapping 对象获取文件名
    if (0 == GetMappedFileName (GetCurrentProcess(), lpMapAddress, szFileName, MAX_PATH)) {
        printf ("GetMappedFileName error : %d\n", GetLastError());
        return (-3);
    }

    _tprintf (TEXT("%s\n"), szFileName);

    TCHAR szTemp[BUFSIZE] = {0};        //临时缓冲区

    if (0 == GetLogicalDriveStrings(BUFSIZE-1, szTemp))    {    // 返回 C:\, D:\ 这样的驱动器根路径到 szTemp
        printf ("GetLogicalDriveStrings error : %d\n", GetLastError());
        return (-4);
    }

    TCHAR    szName[MAX_PATH];
    TCHAR    szDrive[3] = {0};
    BOOL    bFound = FALSE;
    PTCHAR    p = szTemp;
    

    do {
        CopyMemory(szDrive, p, 2*sizeof(TCHAR));    //注意,要去掉反斜杠(\)
        
        //通过路径查找设备名
        if (!QueryDosDevice(szDrive, szName, BUFSIZE)) {
            printf ("QueryDosDevice error : %d\n", GetLastError());
            return (-5);
        }

        UINT uNameLen = _tcslen(szName);    // 设备名长度

        if (uNameLen < MAX_PATH)
            bFound = _tcsnccmp (szFileName, szName, uNameLen);    // 比较驱动器
            if (!bFound) {                    //返回值为0表示 szFileName 包含了 szName,此时匹配
                TCHAR    szTempFile[MAX_PATH];
                wsprintf (szTempFile, TEXT("%s%s"), szDrive, szFileName + uNameLen);    //构造路径
                _tcscpy (szName, szTempFile);
                break;
            }
            while (*p++);    // 循环到下一个 NULL
    } while (*p);

    UnmapViewOfFile (lpMapAddress);
    CloseHandle (hMapFile);

    _tprintf (TEXT("被映射文件路径为:%s\n"), szName);

    return 0;
}

运行输出:
D:\WinAPI\GetMapFileName\Debug>GetMapFileName.exe d:\tmp.txt
\Device\HarddiskVolume1\tmp.txt
被映射文件路径为:D:\tmp.txt





欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2