C++: Access embedded resource from dll

2020-04-06 15:42发布

问题:

I have a c++ dll project, in which, I have embedded some raw data through "resource.rc" file.

IDR_TEMPLATE1           RCDATA                "areaTemplate.bin"

Now I want to access the data of "areaTemplate.bin" file from the dll. How can I read the contents of "areaTemplate.bin" in a byte array?

回答1:

First use FindResource or FindResourceEx, then use LoadResource and LockResource.

Use SizeofResource to get the size of datas.

Code:

HMODULE g_hModDll;

[...]

HRSRC hRscr = FindResource( g_hModDll, MAKEINTRESOURCE( IDR_TEMPLATE1 ),
                            MAKEINTRESOURCE( RT_RCDATA ) );
if ( hRscr ) {
    HGLOBAL hgRscr = LoadResource( g_hModDll, hRscr );
    if ( hgRscr ) {
        PVOID pRscr = LockResource( hgRscr );
        DWORD cbRscr = SizeofResource( g_hModDll, hRscr );
    }
}

Be sure to read the following remark about LoadResource:

Remarks The return type of LoadResource is HGLOBAL for backward compatibility, not because the function returns a handle to a global memory block. Do not pass this handle to the GlobalLock or GlobalFree function.

There is no "unlock resource" or "free resource" APIs.

Remarks The pointer returned by LockResource is valid until the module containing the resource is unloaded. It is not necessary to unlock resources because the system automatically deletes them when the process that created them terminates.



回答2:

As Manuell says, you use FindResource(), LoadResource() and probably LockResource() and SizeofResource()

I happen to have some code which does pulls out a resource and writes it to a file, and may help with your understanding of the API in question.

void WriteResourceToFile(
   HANDLE hFile,
   const _tstring &resourceName,
   const _tstring &resourceType,
   HMODULE hModule)
{
   HRSRC hResource = ::FindResource(
      hModule,
      resourceName.c_str(),
      resourceType.c_str());

   if (!hResource)
   {
      const DWORD lastError = ::GetLastError();

      throw CWin32Exception(
         _T("WriteResourceToFile() - FindResource"),
         lastError);
   }

   HGLOBAL hGlobal = ::LoadResource(hModule, hResource);

   if (!hGlobal)
   {
      const DWORD lastError = ::GetLastError();

      throw CWin32Exception(
         _T("WriteResourceToFile() - LoadResource"),
         lastError);
   }

   void *pData = ::LockResource(hGlobal);

   if (!pData)
   {
      const DWORD lastError = ::GetLastError();

      throw CWin32Exception(
         _T("WriteResourceToFile() - LockResource"),
         lastError);
   }

   const DWORD bytes = ::SizeofResource(hModule, hResource);

   DWORD bytesWritten = 0;

   if (!::WriteFile(hFile, pData, bytes, &bytesWritten, 0))
   {
      const DWORD lastError = ::GetLastError();

      throw CWin32Exception(
         _T("WriteResourceToFile() - WriteFile"),
         lastError);
   }

   if (bytesWritten != bytes)
   {
      throw CWin32Exception(
         _T("WriteResourceToFile() - WriteFile"),
         _T("Wrote less bytes (") + ToString(bytesWritten) +
         _T("( than expected: ") + ToString(bytes));
   }
}


回答3:

// Determine the module handle of your DLL by locating a function
// you know resides in that DLL
HMODULE hModule;
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
        (LPCSTR)&myDLLfuncName, &hModule)

HRSRC hRscr = FindResource(hModule, MAKEINTRESOURCE(IDR_TEMPLATE1),
                           MAKEINTRESOURCE(RT_RCDATA));