sal2kilo
sal2kilo

Reputation: 31

FindResource call returns NULL for text file with type RCDATA

I'm writing a C++ program that needs to handle large chunks of data, specifically text files, however the data is longer than the given string limit. As a result I am attempting to load a text file as a resource file, however whenever I call FindResource the response is a null handle.

I have gone over other stack overflow posts, and MSDN to attempt to correctly implement this functionality however nothing I have tried has returned a valid handle.

C++ code:

HGLOBAL     res_handle = NULL;
HRSRC       res;
char *      res_data;
DWORD       res_size;

auto g_hInstance = GetModuleHandle(NULL);
res = FindResource(g_hInstance, MAKEINTRESOURCE(MY_RESOURCE), RT_RCDATA);
std::cout << res << std::endl;
std::cout << GetLastError() << std::endl;
res_handle = LoadResource(NULL, res);
std::cout << GetLastError() << std::endl;
res_data = (char*)LockResource(res_handle);
std::cout << GetLastError() << std::endl;
res_size = SizeofResource(NULL, res);
std::cout << GetLastError() << std::endl;

Output:

0000000000000000
1813
87
87
87

Resource.h:

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Resource.rc
//
#define MY_RESOURCE 300
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40002
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

Resource.rc:

MY_RESOURCE RCDATA "C:\\Users\\foobar\\Desktop\\projects\\foobar\\test0.txt"

Upvotes: 3

Views: 2245

Answers (2)

Adrian McCarthy
Adrian McCarthy

Reputation: 48002

This works for me. I suspect something about your build setup is going wrong.

I started with an empty project in Visual Studio 2017 and the only thing I changed in the project settings was Configuration Properties > General > Character Set > "Use Unicode Character Set"

Source.cpp

#include <iostream>
#include <Windows.h>
#include "resource.h"

int main() {
  auto hinst = ::GetModuleHandleW(NULL);
  std::cout << hinst << std::endl;
  auto hrsrc = ::FindResourceW(hinst, MAKEINTRESOURCE(IDTHING), RT_RCDATA);
  std::cout << hrsrc << std::endl;
  auto hglob = ::LoadResource(hinst, hrsrc);
  std::cout << hglob << std::endl;
  return 0;
}

resource.h

#define IDTHING 300

Resource.rc

#include "resource.h"

IDTHING RCDATA "C:\\Windows\\notepad.exe"

I completely avoided all the auto-generated resource stuff from VS and just wrote them as plain text files.

If you run in the debugger, stop after hglob is assigned and drop its value into a memory window, I can clearly see the PE header of notepad.exe.

Upvotes: 2

Soonts
Soonts

Reputation: 21956

When you receive error codes from GetLastError(), you should either call FormatMessage API (with FORMAT_MESSAGE_FROM_SYSTEM flag) or use error lookup tool, “Tools / Error Lookup” in visual studio.

Code 1813 translates into the following message: “The specified resource type cannot be found in the image file.”

As you see, it complains about resource type.

I don’t think you need RCDATA. It’s something very old from 16 bit windows. In Win32, custom resources types are strings, not integers. RCDATA is not even supported in the IDE.

The correct way — right click on your .rc file, “Add Resource”, “Import”, browse for the file you want to include, visual studio will ask you resource type, write any string e.g. text will do, then pass that string as the last parameter of FindResource function. If you're building with the default project settings, it's Unicode, so you'll need to pass Unicode string L"text" there.

Upvotes: 0

Related Questions