CreateStreamOnHGlobal对html资源造成堆损坏

CreateStreamOnHGlobal on html resource cause heap corruption

本文关键字:损坏 资源 html CreateStreamOnHGlobal      更新时间:2023-10-16

我在microsoft visual studio项目中添加了一个html文件作为资源。我计划在我的程序中动态地改变它的内容,并使用res://webapp.exe/IDR_HTML导航到它,这样它就不会在文件系统中。我做了以下的事情。但是CreateStreamOnHGlobal导致堆损坏。我做错了什么?html资源可以用这种方式修改吗?我没有问题,如果我自己的GlobalAlloc和CreateStreamOnHGlobal对它在我的程序。

//problem code
    // Load current module.
    HMODULE hExe = GetModuleHandle(NULL);
    if (hExe == NULL)
    {
        ATLTRACE2(TEXT("Could not load exe."));
        return -1;
    }

    // Locate the html resource in the .EXE file.
    HRSRC hRes = FindResource(hExe, MAKEINTRESOURCE(IDR_HTML), RT_HTML);
    if (hRes == NULL)
    {
        ATLTRACE2(TEXT("Could not locate dialog box."));
        return -1;
    }
    // Load the html into global memory.
    HGLOBAL hResLoad = LoadResource(hExe, hRes);
    if (hResLoad == NULL)
    {
        ATLTRACE2(TEXT("Could not load html."));
        return -1;
    }
    CComPtr<IStream> spStream;
    HRESULT hr = ::CreateStreamOnHGlobal( hResLoad, TRUE, &spStream );
//heap error displayed 
HEAP[WebApp.exe]: Invalid address specified to RtlGetUserInfoHeap( 00560000, 012844C8 )
Windows has triggered a breakpoint in WebApp.exe.
This may be due to a corruption of the heap, which indicates a bug in WebApp.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while WebApp.exe has focus.
The output window may have more diagnostic information.
//this is fine 
char *acTemp;
    char *acXml = "Hello";
    SIZE_T dwBytes = 256;
    CComPtr<IStream> pDataStream;
    acTemp = (CHAR *) GlobalAlloc (GMEM_FIXED, dwBytes);
    memcpy (acTemp, acXml, dwBytes);
    HRESULT hhr = ::CreateStreamOnHGlobal(acTemp, TRUE, &pDataStream);

正如Raymond Chen所说,LoadResource()返回的HGLOBAL不是真正的HGLOBAL,所以不能传递给CreateStreamOnHGlobal()。您必须在内存中复制数据,例如:

CComPtr<IStream> spStream;
HRESULT hr;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, SizeofResource(hResLoad));
if (!hMem)
{
    hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
    LPVOID ptr = GlobalLock(hMem);
    if (ptr)
    {
        memcpy( ptr, LockResource(hResLoad), SizeofResource(hResLoad) );
        GlobalUnlock(hMem);
    }
    hr = CreateStreamOnHGlobal( hMem, TRUE, &spStream );
}

正如文档所建议的,您应该考虑使用SHCreateMemStream(),例如:

CComPtr<IStream> spStream = ::SHCreateMemStream( (LPBYTE) LockResource(hResLoad), SizeofResource(hResLoad) );