In our app we have resource strings that are apparently too long for the compiler. The build breaks stating the "line length is too long." I have found little information about the topic of lengthy string resources and even had a difficult time finding what the limit on such a resource string is. Eventually I found this article which gives the limit: MSDN . Have you had any expierence with limits on string resources?
Is there some way to concatonate these without doing any coding?
Any other suggestions would be greatly appriecated.
I would have a look at RCDATA resources. I used it to store large text files in my application.
Edit: Here is my MFC code, it should be able to give you some pointers.
CString CWSApplication::LoadTextResource(UINT nID)
{
HRSRC hResInfo;
HGLOBAL hResData;
hResInfo = ::FindResource(AfxGetResourceHandle(),
MAKEINTRESOURCE(nID),
RT_RCDATA);
if ( hResInfo == NULL )
{
return CString();
}
hResData = ::LoadResource(NULL, hResInfo);
if ( hResData == NULL )
{
return CString();
}
char *data = (char*)(::LockResource(hResData));
DWORD len = ::SizeofResource(NULL, hResInfo);
return CString(data, len);
}
The string resources are designed to store essentially UI-related resources and messages to be shown to the user; this way an application can be internationalized switching from one DLL containing strings for language A to another DLL containing the same string IDs for another language B. I recommend to review for what purpose are you using string resources. If you intend to store large data, use a custom binary resource in the RC. Later you can interpret it as you want.
You can embed a text file into the resource, load it and use it inside CString.
You need to use a custom data (RCDATA) to avoid such a limitation. Basically by using a binary field the compiler leaves your data alone and doesn't try to "massage" it. On the other hand, if you have string resources they are subject to getting merged (to conserve space, if you set that compiler option that is) and are stored in typically stored in a special section in the image. So you want to avoid all that and tell the compiler to "just store" your data. Use RCDATA, you already have sample code to extract it.
You may not use resource files for storing your lengthy strings.
Instead, you may put all your huge strings into say a XML file and read the string as and when you need. If you want NLS support you can also have language specific files.
Related
I have written a C++ code for application, in which there are some variables that must have different values for every user will use it ( lets call it the variable X for simplicity)
X have different values for different user. This (X)should be not changed and also embedded in the exe itself ( so I can't read it from a file or any other similar solution)
I don't want to distribute the source code then compile. Instead, I want a method that makes me edit the final exe directly without need to compile ( it is just value of variable X which differs !) Is this possible ?
My idea to do this is if I can force this (X) at a constant memory location, I can then edit its value easily from Hex-editor as example. ( I mean the same ideas when hackers writes cheat tool for a certain game )
Is the mechanism of fixed memory position possible?
Is there any other idea to make what I want?
I hope my question is clear enough
In this answer I'll use Visual Studio 2017 Community Edition because I wanted to be sure to a have a development environment fully compatible with Windows.
I'll present five methods, from the most maintainable to the less. Of course the focus of this answer in strictly limited to the goal of "sharing" a C++ variable with an external tool.
Security of such an operation is a different topic and ultimately a futile attempt anyway.
Method 1 - Resources
Windows APIs1 and the PE2 support embedding resources in an executable3.
Resources are typically images, icons or localized strings but they can be anything - including raw binary data.
With Visual Studio is quite easy to add a resource: In the Solution Explorer > Resource files > Add > New item > Resource > Resource file (.rc)
This will open the Resource view, right-click on Resource.rc and select Add resource....
It's possible to create the standard resources but we need a Custom... type that we can call RAW.
This will create a new binary resource, gives it an ID and makes a few files in the solution.
Switching back to the Solution explorer we can see these new files and eventually edit the .bin file with a better hex editor than the VS's integrated one.
Of particular interest is the resource.h file that we can include to have the definition for the resource id, in my case it was IDR_RAW1.
After the bin file has been crafted we are ready to read it in the application, the pattern to use is the usual one - I don't feel like going over these API one more time a new answer so I'll link the Official documentation and provides a sample code:
#include <Windows.h>
#include "resource.h"
int WINAPI WinMain(HMODULE hModule, HMODULE hPrevModule, LPSTR lpCmdLine, int showCmd)
{
//Get an handle to our resource
HRSRC hRes = FindResource(hModule, MAKEINTRESOURCE(IDR_RAW1), "RAW");
//Load the resource (Compatibility reasons make this use two APIs)
HGLOBAL hResData = LoadResource(hModule, hRes);
LPVOID ptrData = LockResource(hResData);
/*
ptrData is out binary content. Here is assumed it was a ASCIIZ string
*/
MessageBox(NULL, (LPCSTR)ptrData, "Title", MB_ICONINFORMATION);
return 0;
}
Resources are good because they allow for an easy integration with other automatic build tools: it's easy to add a build step before the resources are compiled to generate them on the fly.
It is also very easy to alter them after the exe file as been generated - CFF Explorer III is a simple and effective tools to edit a PE module's resources.
It's even possible to replace a resource entirely thereby not limiting ourselves to keeping the new resource the same size as the old one.
Just open the module in CFF, select Resource editor, browse to the raw resource and edit/replace it. Then save.
Method 2 - PE exports
Executable are ordinary PE module just like Dlls, the difference is really a batter of a bit.
Just like Dlls can exports functions and variables4 so can exes.
With VC++ the way to tag a symbol as exported is __declspec(dllexport):
#include <Windows.h>
__declspec(dllexport) char var[30] = "Hello, cruel world!";
int WINAPI WinMain(HMODULE hModule, HMODULE hPrevModule, LPSTR lpCmdLine, int showCmd)
{
MessageBox(NULL, var, "Title 2", MB_ICONINFORMATION);
return 0;
}
The C++ side of the matter is little affected.
The editing of the PE module is less user friendly but still very easy for everyone to follow.
With CFF open the export directory, all the exports will be listed.
C++ compilers have to mangle variables names when they can be shared due to the C++ features they support - so you won't find a nice name like var in the exports but something like ?var##3PADA.
The export name doesn't really fulfil any goal in this context but you must be able to identify the correct export.
This should be easy since it's very likely to be only one.
CFF will show you the function RVA, this is the RVA (relative to the image base) of the variable, you can easily convert it into a file offset or simply use the Address converted integrated in CFF.
This will open an hex editor and points you at the right bytes.
Method 3 - Map files
If you don't want to have a PE exports pointing right at your variable you can tell VS to generate a MAP file.
Map files will list all the symbols exported by an object file (note: an object file, not a PE module).
So you must make sure a variable, in this case, is exported by your translation unit - this is the default case for "global" variables but make sure to remember to not attach the static linkage modified to it and eventually make it volatile to prevent the compiler from eliminating it during the constants folding step.
#include "Windows.h"
//extern is redundant, I use it only for documenting the intention
//volatile is a hack to prevent constant folding in this simple case
extern volatile int var2 = 3;
int WINAPI WinMain(HMODULE hModule, HMODULE hPrevModule, LPSTR lpCmdLine, int showCmd)
{
//A simple use of an int
return var2;
}
A MAP file will be generated in the output dir, along with the exe, inside it's present a row like this one:
0003:00000018 ?var2##3HC 00403018 Source.obj
This gives you the VA of the variable (403018) that you can use in CFF Address translator.
Method 4 - PE scan
You can initialise the variable with an unique value.
To be able to do so the variable size must be big enough that the probability that a random sequence of bits of equal size end up with the same value is negligible.
For example, if the var is a QWORD the probability of finding, in the PE module, another QWORD with the same value is very low (one in 264) but if the var is a byte then the probability is just one in 256.
Eventually, add a marker variable (I'd use a random array of 16 bytes) before the variable to mark it (i.e. act as the unique value).
To modify the PE use an hex editor to look for that unique value, this will give you the offset of the var to edit.
Method 5 - Reverse engineering
After each release, reverse engine the application (this is easy as you can debug it with VS along with the sources) and look where the compiler allocated the variable.
Take note of the RVA (nota bene: RVA not VA, the VA is variable) and then use CFF to edit the exe.
This requires a reverse engineering analysis each time a new release is built.
1 To be correct, "Win32" APIs.
2 I strongly advice the reader to be at least accustomized with the PE file format as I must assume so to keep this answer in topic and short. Having no understanding of the PE file format will likely result in no understanding of the question as a whole.
3 Actually, in any PE module.
4 Symbols in general.
I have a code in this format:
srcSAXController control(input_filename.c_str());
std::string output_filename = input_filename;
output_filename = "c-" + output_filename.erase(input_filename.rfind(XML_STR));
std:: ofstream myfile(output_filename.c_str());
coverage_handler handler(i == MAIN_POS ? true : false, output_filename);
control.parse(&handler);
myfile.write((char *)&control, sizeof(control));
myfile.close();
I want the content of object 'control' to be written into my file. How to fix the code above, so that content of the control object is written to the file.
In general you need much more than just writing the bytes of the object to be able to save and reload it.
The problem is named "serialization" and depending on a lot of factors there are several strategies.
For example it's important to know if you need to save and reload the object on the same system or if you may need to reload it on a different system; it's also fundamental to know if the object contains links to other objects, if the link graph is a simple tree or if there are possibly loops, if you need to support versioning etc. etc.
Writing the bytes to disk like the code is doing is not going to work even for something as simple as an object containing an std::string.
I'm running program correctly and I see Version Information but in the update resource api run and does not replace the compnayname.
LPCWSTR filename = _T("r1.exe");
size = GetFileVersionInfoSize(filename, &dwHandle);
std::vector<BYTE> fileInfo(size,0);
f = GetFileVersionInfo(filename, 0, size, &fileInfo[0]);
VerQueryValue(&fileInfo[0], TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&pValueBuffer, &verLength);
SubBlock.Format(_T("\\StringFileInfo\\040904B0\\CompanyName"), "0x0409", "1200");
VerQueryValue(&fileInfo[0], SubBlock, (LPVOID *)&lpBuffer, &dwBytes);
ZeroMemory(lpBuffer, _tcslen(lpBuffer) * sizeof(TCHAR));
_tcscpy(lpBuffer, _T("My Company"));
HANDLE hResource = BeginUpdateResource(filename, FALSE);
VerQueryValueW(&fileInfo[0], TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&pValueBuffer, &verLength);
f=UpdateResource(hResource, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), MAKELANGID(SUBLANG_ENGLISH_UK, SUBLANG_DEFAULT), &fileInfo[0], sizeof(lpBuffer));
EndUpdateResource(hResource, FALSE);
How can I Replace the Company name or other String Info Table Features????
Your code snippet does not do what you expect it to do.
BeginUpdateResource, UpdateResource, EndUpdateResource indeed do the update cycle and you use the API in a presumably correct order. However your UpdateResource uses the same original data block you read from the file.
VerQueryValue extracts you the string and does not provide you with a method to update the value within the original block.
If you want to update the resource, you are responsible for reading the entire VERSIONINFO resource, for parsing it out into parts, updating the string in question, assembling the resource back into a byte buffer and then using the UpdateResource API. There is no API, to my best knowledge that helps you with parsing and assembling the VERSIONINFO data end to end, you are responsible for taking care of this yourself following MSDN data structure (and it's doable).
The GetFileVersionInfo[Size] and VerQueryValue functions abstract away some of the resource version layout details and cannot be used when you want to build resources. You can use them to read if you really want to but you have to manually create the full version resource in memory if you want to update it because 1) there are some alignment requirements and 2) it stores the string size in the string header.
MSDN has decent documentation that should help you to lay things out correctly in memory. It starts with VS_VERSIONINFO and VS_FIXEDFILEINFO and the rest are not true C/C++ compatible structs but you can study other resources in a hex-editor to make sure you are doing it correctly.
Is there a standards for language conversion in programming? If this is to broad a question, then specifically for my example:
I've designed a program in c++ & hardcoded English words but I wish to adapt this to accommodate for the display of equivalent words in Italian. I am thinking of using a simple Lang.ini file like so;
English=Language
Do=Fare
Column=Colonna
etc
Load this & and swap out words at run-time. There is nothing web related.
Would there be a better way to do this & any issues I should be mindful of?
Thanks.
EDIT:
To clarify:
I wish to have the English words that I've used hardcoded in my program automatically converted to whatever language is being used on the users PC.
What you're looking for is described as "internationalization" (or, for those who appreciate a little irony, as "internationalisation"). There is a fair amount of introductory material that may be found using google.
The topic involves more than just translating words. There are also considerations about how numeric values are output, currency is represented, etc etc.
Standard C and C++ support such features. An article (from C/C++ Users Journal) on the topic is http://www.angelikalanger.com/Articles/Cuj/Internationalization/I18N.html
Separately from C++, windows also has its own features that may be used for internationalization of applications. One starting point is https://msdn.microsoft.com/en-au/library/windows/desktop/dd318661%28v=vs.85%29.aspx
It is possible to load resources for language, and save strings in resources.
https://msdn.microsoft.com/en-us/library/cc194810.aspx
Usable standart lnaguage macroses:
WORD lang_id = MAKELANGID( primary, sublang )
BYTE primary = PRIMARYLANGID( lang_id )
BYTE sublang = SUBLANGID( lang_id )
Loading resources:
HRSRC hrsrc = FindResourceEx(hMod, RT_ICON, id, langID );
HGLOBAL hglb = LoadResource(hMod, hrsrc);
LPVOID lpsz = LockResource(hglb);
Language initialization code:
static DWORD dwJapanese =
MAKELCID(MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT));
// load Japanese resource
SetThreadLocale(dwJapanese, SORT_DEFAULT)
Use LoadString function, possible write wrapper function for convenient using like tihs:
http://www.codeproject.com/Tips/86496/Load-a-Windows-string-resource-into-a-std-string-o
We are contemplating changing from PCRE regular expressions to
ICU regular expressions to take advantage of ICU's UTF-8 Unicode regular
expressions. We have wriiten a test program to load the ICU pnames.icu file
which is necessary to compile and exercise the ICU UTF-8 Regular
expressions which appears to be functioning correctly.
Is it possible to store the contents of pnames.icu in a Windows
DLL global variable in order to avoid shipping the ICU pnames.icu to users?
Thank you.
You start by adding the files to the resource script in the same way you do an icon. The difference is you will specify the resource by name instead of an integer value and tell the resource compiler that the files are a custom resource type called "ICU"
pname1 ICU "pname1.icu"
pname2 ICU "pname2.icu"
pname3 ICU "pname3.icu"
To load the resource you will first need to find it by name and by the type (in this case ICU). Once you have found it you can tell windows to load the resource data and then "lock" it to obtain a pointer to it.
// Find the resource
HRSRC hRes = FindResource(NULL, L"pname1", L"ICU");
// Load the resource
HGLOBAL hResLoad = LoadResource(NULL, hRes);
void* icuData = LockResource(hResLoad);
// ... do something with the resource # icuData
// We're done so let it go.
UnlockResource(icuData);