In Win32, suppose you have an application resource (added with the resource compiler) and you want to open an OLE IStream interface on it. One reason might be to load an image with GDI+.
I initially made my own IStream implementation to provide read-only access to the resource data but I eventually decided to do the following, which is less code but does make a copy of the resource. The API is 'inspired by' the Shell's
CreateStreamOnHGlobal
function.
HRESULT CreateStreamOnResource(LPCTSTR name, LPSTREAM* stream) {
HINSTANCE hInst = GetModuleHandle(0);
return CreateStreamOnResource(hInst, name, stream);
}
HRESULT CreateStreamOnResource(HINSTANCE hInst, LPCTSTR name, LPSTREAM* stream)
{
assert(hInst != 0);
assert(name != 0);
assert(stream != 0);
*stream = NULL;
HRSRC hC = FindResource(hInst, name, RT_RCDATA);
if (hC) {
// This is not really a HGLOBAL http://msdn.microsoft.com/en-us/library/windows/desktop/ms648046(v=vs.85).aspx
HGLOBAL hG = LoadResource(hInst, hC);
if (hG) {
void* bytes = LockResource(hG);
ULONG size = SizeofResource(hInst, hC);
// Create a new empty stream.
HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream);
if (SUCCEEDED(hr)) {
ULONG written;
// Copy the resource into it.
hr = (*stream)->Write(bytes, size, &written);
}
return hr;
}
}
return E_INVALIDARG;
}
It should have been even easier - just get an
HGLOBAL
with LoadResource
and pass it to CreateStreamOnHGlobal
but LoadResource
does not really return a handle to global memory so I needed to make the additional steps of creating a new stream, locking the resource and copying its data. I think I remember in the Win16 days you really did have to worry about loading and unloading resources from the segmented .exe but these days I think it all just gets mapped anyway.