【问题标题】:DeviceIoControl Invalid access to memory locationDeviceIoControl 对内存位置的无效访问
【发布时间】:2017-05-12 18:44:53
【问题描述】:

当我运行以下代码时,我无法访问内存位置

WIN32_FIND_DATAW FD;
WCHAR cPath[MAX_PATH], cFindPath[MAX_PATH];

if (!GetCurrentDirectoryW(MAX_PATH, cPath))
    ErrorExit("GetCurrentDirectory");
else
    printf("Current Path: %s\n", cPath);

StringCchCopyW(cFindPath, MAX_PATH, cPath);
StringCchCatW(cFindPath, MAX_PATH, L"\\*");

BOOL bsuccess;

HANDLE hFind = FindFirstFileW(cFindPath, &FD);

if (INVALID_HANDLE_VALUE != hFind)
{
    vector<wstring> links;
    do
    {
        WCHAR  fullFileName[MAX_PATH];
        StringCchPrintfW(fullFileName, MAX_PATH, L"\\\\?\\%s\\%s", cPath, FD.cFileName);

        DWORD dwBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
        REPARSE_DATA_BUFFER* rdata;
        rdata = (REPARSE_DATA_BUFFER*)malloc(dwBufSize);

        DWORD bytesReturned;
        HANDLE hFile = CreateFileW(fullFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
        if (INVALID_HANDLE_VALUE != hFile)
        {
            if (DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, &rdata, dwBufSize, &bytesReturned, NULL))
            {
                if (IsReparseTagMicrosoft(rdata->ReparseTag))
                {

                    if (rdata->ReparseTag == IO_REPARSE_TAG_SYMLINK)
                    {
                        printf("Symbolic-Link\n");
                        size_t slen = rdata->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
                        WCHAR *szSubName = new WCHAR[slen + 1];
                        wcsncpy_s(szSubName, slen + 1, &rdata->SymbolicLinkReparseBuffer.PathBuffer[rdata->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], slen);
                        szSubName[slen] = 0;
                        printf("SubstitutionName (len: %d): '%S'\n", rdata->SymbolicLinkReparseBuffer.SubstituteNameLength, szSubName);
                        delete[] szSubName;

                        size_t plen = rdata->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(WCHAR);
                        WCHAR *szPrintName = new WCHAR[plen + 1];
                        wcsncpy_s(szPrintName, plen + 1, &rdata->SymbolicLinkReparseBuffer.PathBuffer[rdata->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)], plen);
                        szPrintName[plen] = 0;
                        printf("PrintName (len: %d): '%S'\n", rdata->SymbolicLinkReparseBuffer.PrintNameLength, szPrintName);
                        delete[] szPrintName;
                    }
                    else if (rdata->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
                    {
                        printf("Mount-Point\n");
                        size_t slen = rdata->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
                        WCHAR *szSubName = new WCHAR[slen + 1];
                        wcsncpy_s(szSubName, slen + 1, &rdata->MountPointReparseBuffer.PathBuffer[rdata->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], slen);
                        szSubName[slen] = 0;
                        printf("SubstitutionName (len: %d): '%S'\n", rdata->MountPointReparseBuffer.SubstituteNameLength, szSubName);
                        delete[] szSubName;

                        size_t plen = rdata->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR);
                        WCHAR *szPrintName = new WCHAR[plen + 1];
                        wcsncpy_s(szPrintName, plen + 1, &rdata->MountPointReparseBuffer.PathBuffer[rdata->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR)], plen);
                        szPrintName[plen] = 0;
                        printf("PrintName (len: %d): '%S'\n", rdata->MountPointReparseBuffer.PrintNameLength, szPrintName);
                        delete[] szPrintName;
                    }
                    else
                    {
                        printf("No Mount-Point or Symblic-Link...\n");
                    }
                }
                else
                {
                    printf("Not a Microsoft-reparse point - could not query data!\n");
                }
                free(rdata);
            }
            else
                ErrorExit("DeviceIoControl");
        }

        CloseHandle(hFile);


    } while (FindNextFileW(hFind, &FD));
}
else
    ErrorExit("FindFirstFile");

但以下代码可以正常工作。

HANDLE hFile;
LPCTSTR szMyFile = ("C:\\Documents and Settings");  // Mount-Point (JUNCTION)
//LPCTSTR szMyFile = _T("C:\\Users\\All Users");  // Symbolic-Link (SYMLINKD)

hFile = CreateFile(szMyFile, FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
    printf(("Could not open dir '%s'; error: %d\n"), szMyFile, GetLastError());
    return;
}

// Allocate the reparse data structure
DWORD dwBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
REPARSE_DATA_BUFFER* rdata;
rdata = (REPARSE_DATA_BUFFER*)malloc(dwBufSize);

// Query the reparse data
DWORD dwRetLen;
BOOL bRet = DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, rdata, dwBufSize, &dwRetLen, NULL);
if (bRet == FALSE)
{
    printf(("DeviceIoControl failed with error: %d\n"), GetLastError());
    CloseHandle(hFile);
    return;
}
CloseHandle(hFile);

if (IsReparseTagMicrosoft(rdata->ReparseTag))
{
    if (rdata->ReparseTag == IO_REPARSE_TAG_SYMLINK)
    {
        printf("Symbolic-Link\n");
        size_t slen = rdata->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
        WCHAR *szSubName = new WCHAR[slen + 1];
        wcsncpy_s(szSubName, slen + 1, &rdata->SymbolicLinkReparseBuffer.PathBuffer[rdata->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], slen);
        szSubName[slen] = 0;
        printf("SubstitutionName (len: %d): '%S'\n", rdata->SymbolicLinkReparseBuffer.SubstituteNameLength, szSubName);
        delete[] szSubName;

        size_t plen = rdata->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(WCHAR);
        WCHAR *szPrintName = new WCHAR[plen + 1];
        wcsncpy_s(szPrintName, plen + 1, &rdata->SymbolicLinkReparseBuffer.PathBuffer[rdata->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)], plen);
        szPrintName[plen] = 0;
        printf("PrintName (len: %d): '%S'\n", rdata->SymbolicLinkReparseBuffer.PrintNameLength, szPrintName);
        delete[] szPrintName;
    }
    else if (rdata->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
    {
        printf("Mount-Point\n");
        size_t slen = rdata->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
        WCHAR *szSubName = new WCHAR[slen + 1];
        wcsncpy_s(szSubName, slen + 1, &rdata->MountPointReparseBuffer.PathBuffer[rdata->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], slen);
        szSubName[slen] = 0;
        printf("SubstitutionName (len: %d): '%S'\n", rdata->MountPointReparseBuffer.SubstituteNameLength, szSubName);
        delete[] szSubName;

        size_t plen = rdata->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR);
        WCHAR *szPrintName = new WCHAR[plen + 1];
        wcsncpy_s(szPrintName, plen + 1, &rdata->MountPointReparseBuffer.PathBuffer[rdata->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR)], plen);
        szPrintName[plen] = 0;
        printf("PrintName (len: %d): '%S'\n", rdata->MountPointReparseBuffer.PrintNameLength, szPrintName);
        delete[] szPrintName;
    }
    else
    {
        printf("No Mount-Point or Symblic-Link...\n");
    }
}
else
{
    printf(("Not a Microsoft-reparse point - could not query data!\n"));
}
free(rdata);

我正在尝试获取给定文件夹中文件的重新解析数据。这是我的REPARSE_DATA_BUFFER

typedef struct _REPARSE_DATA_BUFFER {
ULONG  ReparseTag;
USHORT  ReparseDataLength;
USHORT  Reserved;
union {
    struct {
        USHORT  SubstituteNameOffset;
        USHORT  SubstituteNameLength;
        USHORT  PrintNameOffset;
        USHORT  PrintNameLength;
        ULONG   Flags; // it seems that the docu is missing this entry (at least 2008-03-07)
        WCHAR  PathBuffer[1];
    } SymbolicLinkReparseBuffer;
    struct {
        USHORT  SubstituteNameOffset;
        USHORT  SubstituteNameLength;
        USHORT  PrintNameOffset;
        USHORT  PrintNameLength;
        WCHAR  PathBuffer[1];
    } MountPointReparseBuffer;
    struct {
        UCHAR  DataBuffer[1];
    } GenericReparseBuffer;
};
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;

我不知道我哪里出错了。请帮我修复我的第一个代码。

【问题讨论】:

  • 很难说您在哪一行获得了对内存的无效访问权限?你不先尝试在调试器下运行你的代码,更多的是写更多关于错误的信息?
  • 与您的问题无关(无论如何您都没有足够详细地解释),"C:\\Documents and Settings" 是一个等待发生的错误。这肯定不会在 Windows 的本地化版本或任何最新(基于 NT)版本的 Windows 上运行。有关解决方案,请参阅Known Folders
  • 在哪个部分发生了对内存的无效访问。你检查过 GetLastError 代码
  • @Angelica:当代码触发访问冲突时,GetLastError 不会返回任何有用的东西。
  • @IInspectable - 第二个代码 sn-p 显然是仅在 OP 系统上的 测试代码,而不是发布代码。在这种 test code 绝对正常的 hardcode 任何具体的测试路径

标签: c++ winapi deviceiocontrol reparsepoint


【解决方案1】:

您的代码包含 2 个错误的最小值

您无条件地为所有文件调用FSCTL_GET_REPARSE_POINT,但您只能这样做

if (FD.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {..}

否则你在DeviceIoControl 中得到ERROR_NOT_A_REPARSE_POINT,然后ErrorExit("DeviceIoControl"); 被执行。

这一行的第二个错误:

DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, &rdata, dwBufSize, &bytesReturned, NULL)

&amp;rdata - !!

必须是什么时候

DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, rdata, dwBufSize, &bytesReturned, NULL)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 2012-12-02
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    相关资源
    最近更新 更多