Reputation: 31
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
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
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