Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The following are the predefined resource types.
| Constant/value | Description |
|---|---|
|
Accelerator table. |
|
Animated cursor. |
|
Animated icon. |
|
Bitmap resource. |
|
Hardware-dependent cursor resource. |
|
Dialog box. |
|
Allows a resource editing tool to associate a string with an .rc file. Typically, the string is the name of the header file that provides symbolic names. The resource compiler parses the string but otherwise ignores the value. For example, 1 DLGINCLUDE "MyFile.h" |
|
Font resource. |
|
Font directory resource. |
|
Hardware-independent cursor resource. |
|
Hardware-independent icon resource. |
|
HTML resource. |
|
Hardware-dependent icon resource. |
|
Side-by-Side Assembly Manifest. |
|
Menu resource. |
|
Message-table entry. |
|
Plug and Play resource. |
|
Application-defined resource (raw data). |
|
String-table entry. See Remarks below for more info. |
|
Version resource. |
|
VXD. |
Remarks
String Table Resources
When enumerating String Table resources (type RT_STRING) with functions such as EnumResourceNamesW, the system doesn't enumerate each individual string resource ID; instead it enumerates blocks of resources. You must inspect these blocks to determine which string resource ID(s) they actually contain.
String resources are packaged into blocks, each of which contains 16 length-prefixed strings representing 16 consecutive
IDs (some of which may not be used; see below). Given a string resource ID X, it will be placed in the resource block number
(X \ 16) + 1 (where \ denotes integer division). Within that block, the resource can be found as the Nth entry,
where N = X % 16.
The following table shows some example string resource IDs and the block number (and offset) of where they will be located:
| Resource ID | Block # | Offset |
|---|---|---|
| 1 | (1 \ 16) + 1 = 1 |
1 % 16 = 1 |
| 2 | (2 \ 16) + 1 = 1 |
2 % 16 = 2 |
| 5 | (5 \ 16) + 1 = 1 |
5 % 16 = 5 |
| 15 | (15 \ 16) + 1 = 1 |
15 % 16 = 15 |
| 20 | (20 \ 16) + 1 = 2 |
20 % 16 = 4 |
| 32 | (32 \ 16) + 1 = 3 |
32 % 16 = 0 |
| 50 | (50 \ 16) + 1 = 4 |
50 % 16 = 2 |
| 100 | (100 \ 16) + 1 = 7 |
100 % 16 = 4 |
Any unused (missing) resource IDs are denoted by zero-length strings. So in the example above, block #1 will have zero-length strings representing IDs 0, 3, 4, and 6 - 14. None of the strings in the block have terminating NULL characters, since it is permitted for string resources to contain embedded NULLs. Thus, the memory layout of block #1 looks like this, assuming each string's value is "Hello world" (11 characters long) and where the numbers in angle brackets represent integers (not literal characters):
<0><11>Hello world<11>Hello world<0><0>
<11>Hello world<0><0><0><0><0><0><0><0>
<0><11>Hello world
The following code snippet shows an enumeration callback function that will enumerate individual RT_STRING resources just like other types (like RT_ICON) rather than the blocks:
// Number of entries in the string table.
constexpr UINT STRING_TABLE_SIZE{ 16 };
// Returns the original resource ID from a given block / offset.
inline UINT GetStringResourceIdFromStringTable(LPCWSTR lpName, const unsigned int index)
{
_ASSERT(index < STRING_TABLE_SIZE);
return ((reinterpret_cast<UINT>(lpName) - 1) * STRING_TABLE_SIZE) + index;
}
// Helper function that will enumerate string table blocks, looking for resources.
BOOL EnumerateResourceNamesWrapperForStrings(HMODULE hModule, LPWSTR lpName, LONG_PTR lParam, ENUMRESNAMEPROCW lpEnumFunc)
{
// No need to free or unlock resources in Win32, so OK to throw away intermediates
auto ptr = (wchar_t*)LockResource(LoadResource(hModule, FindResource(hModule, lpName, RT_STRING)));
if (ptr)
{
for (unsigned int i = 0; i < STRING_TABLE_SIZE; ++i)
{
wchar_t size = *ptr;
if (size > 0)
{
auto id = GetStringResourceIdFromStringTable(lpName, i);
// Invoke the callback for this string resource ID.
auto callbackResult = lpEnumFunc(hModule, RT_STRING, MAKEINTRESOURCE(id), lParam);
if (!callbackResult)
{
return callbackResult;
}
}
// Skip to next potential string in the block
ptr += size + 1;
}
return TRUE;
}
// Couldn't load the string table entry; something is wrong.
return FALSE;
}
// Wrapper function for EnumResourceNamesW that will enumerate individual string resources.
BOOL EnumResourceNamesIncludingStringsW(HMODULE hModule, LPCWSTR lpType, ENUMRESNAMEPROCW lpEnumFunc, LONG_PTR lParam)
{
struct param_wrapper { ENUMRESNAMEPROCW lpEnumFunc; LONG_PTR lParam; } params{ lpEnumFunc, lParam };
// Use a simple lambda to either call our String helper, or directly call the user's callback
return EnumResourceNamesW(hModule, lpType, [](auto hModule, auto lpType, auto lpName, auto lParam)
{
auto params = reinterpret_cast<param_wrapper*>(lParam);
if (lpType == RT_STRING)
{
return EnumerateResourceNamesWrapperForStrings(hModule, lpName, params->lParam, params->lpEnumFunc);
}
return params->lpEnumFunc(hModule, lpType, lpName, params->lParam);
}, reinterpret_cast<LONG_PTR>(¶ms));
};
//////////
// Sample callback that just increments a counter.
BOOL CountResources(HMODULE, LPCWSTR, LPWSTR, LONG_PTR lParam)
{
// Add one to the count...
(*(reinterpret_cast<UINT*>(lParam)))++;
return TRUE;
}
// Sample usage:
void CountStringsInExplorer()
{
auto lib = LoadLibraryExW(LR"(c:\windows\explorer.exe)", nullptr, LOAD_LIBRARY_AS_DATAFILE);
if (!lib)
{
return;
}
UINT nStringBlocks{ 0 };
UINT nStrings{ 0 };
// Count the number of string blocks using raw Win32 API.
EnumResourceNamesW(lib, RT_STRING, CountResources, (LONG_PTR)&nStringBlocks);
// Count the number of actual strings, using the wrapper.
EnumResourceNamesIncludingStringsW(lib, RT_STRING, CountResources, (LONG_PTR)&nStrings);
// Outputs something like:
//
// Explorer.exe contains 44 strings (in 17 blocks).
//
std::wcout << L"Explorer.exe contains " << nStrings << L" strings (in " << nStringBlocks
<< L" blocks)." << std::endl;
}
Requirements
| Requirement | Value |
|---|---|
| Header |
|