Link to home
Start Free TrialLog in
Avatar of Karrtik Iyer
Karrtik IyerFlag for India

asked on

Windows | Visual C++ | String table Comparison tool | WIndows Exes and DLLs

Hi Experts,
We have a requirement to extract resource strings (only string table entries, ID & value) from DLL's and exe's and generate a comparison tool across different languages.
Like we may have a resource DLL for EN, JP, etc.. and we need to list in a tabular format, the ID's, its corresponding values in EN and JP language.
The user shall select multiple DLL's for comparison.
I have looked at MSDN documentation and understand that we can use EnumResourceNames and EnumResourceLanguages functions to get call backs after loading the DLL. In the below code I am able to get all the resource strings (the values), however I do not know how to get the resource ID corresponding to each string. In the loop below I am able to traverse and print all the entries(values) in string table but not sure how to get their corresponding ID's.
How do tools like resource hackers work? (http://angusj.com/resourcehacker/#download), does it read the executable as PE image and COFF specification and locate the string table? Are there are any libraries or API's support from Windows to read the string table in a simple way?
BOOL EnumLangsFunc(
	HMODULE hModule, // module handle
	LPCTSTR lpType,  // address of resource type
	LPCTSTR lpName,  // address of resource name
	WORD wLang,      // resource language
	LONG lParam)     // extra parameter, could be
	// used for error checking
{
	HRSRC hResInfo;
	HRESULT hResult;
	hResInfo = FindResourceEx(hModule, lpType, lpName, wLang);
	if( hResInfo != nullptr &&  lpType ==RT_STRING )
	{
		wchar_t *pwchMem = (wchar_t *)LoadResource( hModule, hResInfo );

		if( pwchMem != nullptr )
		{
			wchar_t *pwchCur = pwchMem;
			for(int i = 0; i<16; i++ )
			{
				if( *pwchCur )
				{
					int cchString = *pwchCur;  // String size in characters.
					pwchCur++;		
					wchar_t *pwchTemp = new wchar_t[ cchString ];
					wcsncpy( pwchTemp, pwchCur, cchString );//Here I get all the resource strings in this variable
					pwchCur += cchString;
				}
				else
					pwchCur++;
			}
		}
	}
	return TRUE;
}

Open in new window

Avatar of Thommy
Thommy
Flag of Germany image

Have you already dealt with ResourceManager Class
Avatar of Zoppo
Hi Karrtik Iyer,

loading strings from resource is a bit tricky because of the way how strings are compiled into the binary. To see how this is done you should take a look at https://support.microsoft.com/en-us/kb/200893 and try to adopt it to your needs.

The main points to take care is that a string with ID x is stored in a RT_STRING resource block with ID ( x / 16 ) + 1 and can be found by searching the ( x % 16 )'s entry in the block.

In your function the passed lpName is either an integer ID or really a resource string. You can test if it's a integer ID using the macro IS_INTRESOURCE, if it is not you'll have to parse the string for the integer ID, it's format is "#<number>".

Hope this helps,

ZOPPO
Avatar of Karrtik Iyer

ASKER

Hi Thommy,
Thanks for your comments.
Can ResourceManager Class class be used to get resources from a un-managed windows/MFC DLL?

Regards,
Karrtik
Hi Zoppo,
Thanks for your comments.
I have already looked the link you shared. The code that I shared in my original question is inspired from that link.
The problem is that I do not have a specific ID to load. I want to read all the strings with their IDs.
I am able to load all the strings from the table using that code, however I do not know how to find the specific resource ID associated with each string.
Regards,
Karrtik
ASKER CERTIFIED SOLUTION
Avatar of Zoppo
Zoppo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Resourcemanager supports file-based resource retrieving  from binary resource files on disk  (including DLLs)

For file-based mode you have to use method CreateFileBasedResourceManager...
Thanks a lot @Zoppo, that works for me.
@Thommy: I tried your suggestion to use Resourcemanager (CreateFileBasedResourceManager), however I could not get it to work for pure C++ (unmanaged) MFC resource DLL's. Thanks for your suggestions though.