Использование ресурсов
В этом разделе содержатся фрагменты кода для следующих задач:
Обновление ресурсов
В следующем примере ресурс диалогового окна копируется из одного исполняемого файла Hand.exe в другой, Foot.exe, выполнив следующие действия.
- Используйте функцию LoadLibrary для загрузки исполняемого файла Hand.exe.
- Используйте функции FindResource и LoadResource для поиска и загрузки ресурса диалогового окна.
- Используйте функцию LockResource для получения указателя на данные ресурса диалогового окна.
- Используйте функцию BeginUpdateResource , чтобы открыть дескриптор обновления для Foot.exe.
- Используйте функцию UpdateResource для копирования ресурса диалогового окна из Hand.exe в Foot.exe.
- Для завершения обновления используйте функцию EndUpdateResource .
Эти шаги реализованы в следующем коде.
Предупреждение системы безопасности: Неправильное использование LoadLibrary может поставить под угрозу безопасность приложения, загрузив неправильную библиотеку DLL. Сведения о том, как правильно загружать библиотеки DLL с различными версиями Windows, см. в документации по LoadLibrary .
HGLOBAL hResLoad; // handle to loaded resource
HMODULE hExe; // handle to existing .EXE file
HRSRC hRes; // handle/ptr. to res. info. in hExe
HANDLE hUpdateRes; // update resource handle
LPVOID lpResLock; // pointer to resource data
BOOL result;
#define IDD_HAND_ABOUTBOX 103
#define IDD_FOOT_ABOUTBOX 110
// Load the .EXE file that contains the dialog box you want to copy.
hExe = LoadLibrary(TEXT("hand.exe"));
if (hExe == NULL)
{
ErrorHandler(TEXT("Could not load exe."));
return;
}
// Locate the dialog box resource in the .EXE file.
hRes = FindResource(hExe, MAKEINTRESOURCE(IDD_HAND_ABOUTBOX), RT_DIALOG);
if (hRes == NULL)
{
ErrorHandler(TEXT("Could not locate dialog box."));
return;
}
// Load the dialog box into global memory.
hResLoad = LoadResource(hExe, hRes);
if (hResLoad == NULL)
{
ErrorHandler(TEXT("Could not load dialog box."));
return;
}
// Lock the dialog box into global memory.
lpResLock = LockResource(hResLoad);
if (lpResLock == NULL)
{
ErrorHandler(TEXT("Could not lock dialog box."));
return;
}
// Open the file to which you want to add the dialog box resource.
hUpdateRes = BeginUpdateResource(TEXT("foot.exe"), FALSE);
if (hUpdateRes == NULL)
{
ErrorHandler(TEXT("Could not open file for writing."));
return;
}
// Add the dialog box resource to the update list.
result = UpdateResource(hUpdateRes, // update resource handle
RT_DIALOG, // change dialog box resource
MAKEINTRESOURCE(IDD_FOOT_ABOUTBOX), // dialog box id
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), // neutral language
lpResLock, // ptr to resource info
SizeofResource(hExe, hRes)); // size of resource info
if (result == FALSE)
{
ErrorHandler(TEXT("Could not add resource."));
return;
}
// Write changes to FOOT.EXE and then close it.
if (!EndUpdateResource(hUpdateRes, FALSE))
{
ErrorHandler(TEXT("Could not write changes to file."));
return;
}
// Clean up.
if (!FreeLibrary(hExe))
{
ErrorHandler(TEXT("Could not free executable."));
return;
}
Создание списка ресурсов
В следующем примере создается список всех ресурсов в файле Hand.exe. Список записывается в файл Resinfo.txt.
В коде показано, как загрузить исполняемый файл, создать файл для записи сведений о ресурсе и вызвать функцию EnumResourceTypes для отправки каждого типа ресурса, найденного в модуле, в определяемую приложением функцию EnumTypesFunc
обратного вызова . Сведения о функциях обратного вызова этого типа см. в разделе EnumResTypeProc . Эта функция обратного вызова использует функцию EnumResourceNames для передачи имени каждого ресурса в указанном типе другой определяемой приложением функции обратного вызова , EnumNamesFunc
. Сведения о функциях обратного вызова этого типа см. в разделе EnumResNameProc .
EnumNamesFunc
использует функцию EnumResourceLanguages для передачи языка каждого ресурса указанного типа и имени в третью функцию обратного вызова , EnumLangsFunc
. Дополнительные сведения о функциях обратного вызова этого типа см. в разделе EnumResLangProc .
EnumLangsFunc
записывает сведения о ресурсе указанного типа, имени и языка в файл Resinfo.txt.
Обратите внимание, что lpszType в EnumResTypeProc является либо идентификатором ресурса, либо указателем на строку (содержащую идентификатор ресурса или имя типа); lpszType и lpszName в EnumResNameProc и EnumResLangProc похожи. Чтобы загрузить перечислимый ресурс, просто вызовите соответствующую функцию. Например, если был перечислен ресурс меню (RT_MENU), передайте lpszName в LoadMenu. Для пользовательских ресурсов передайте lpszType и lpszName в FindResource.
Код обновления ресурсов соответствует аналогичному шаблону для ресурса диалогового окна.
Предупреждение системы безопасности: Неправильное использование LoadLibrary может поставить под угрозу безопасность приложения, загрузив неправильную библиотеку DLL. Сведения о том, как правильно загружать библиотеки DLL с различными версиями Windows, см. в документации по LoadLibrary .
HANDLE g_hFile; // global handle to resource info file
// Declare callback functions.
BOOL EnumTypesFunc(
HMODULE hModule,
LPTSTR lpType,
LONG lParam);
BOOL EnumNamesFunc(
HMODULE hModule,
LPCTSTR lpType,
LPTSTR lpName,
LONG lParam);
BOOL EnumLangsFunc(
HMODULE hModule,
LPCTSTR lpType,
LPCTSTR lpName,
WORD wLang,
LONG lParam);
HMODULE hExe; // handle to .EXE file
TCHAR szBuffer[80]; // print buffer for info file
DWORD cbWritten; // number of bytes written to resource info file
size_t cbString; // length of string in szBuffer
HRESULT hResult;
// Load the .EXE whose resources you want to list.
hExe = LoadLibrary(TEXT("hand.exe"));
if (hExe == NULL)
{
// Add code to fail as securely as possible.
return;
}
// Create a file to contain the resource info.
g_hFile = CreateFile(TEXT("resinfo.txt"), // name of file
GENERIC_READ | GENERIC_WRITE, // access mode
0, // share mode
(LPSECURITY_ATTRIBUTES) NULL, // default security
CREATE_ALWAYS, // create flags
FILE_ATTRIBUTE_NORMAL, // file attributes
(HANDLE) NULL); // no template
if (g_hFile == INVALID_HANDLE_VALUE)
{
ErrorHandler(TEXT("Could not open file."));
return;
}
// Find all of the loaded file's resources.
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR),
TEXT("The file contains the following resources:\r\n\r\n"));
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return;
}
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return;
}
WriteFile(g_hFile, // file to hold resource info
szBuffer, // what to write to the file
(DWORD) cbString, // number of bytes in szBuffer
&cbWritten, // number of bytes written
NULL); // no overlapped I/O
EnumResourceTypes(hExe, // module handle
(ENUMRESTYPEPROC)EnumTypesFunc, // callback function
0); // extra parameter
// Unload the executable file whose resources were
// enumerated and close the file created to contain
// the resource information.
FreeLibrary(hExe);
CloseHandle(g_hFile);
// FUNCTION: EnumTypesFunc(HANDLE, LPSTR, LONG)
//
// PURPOSE: Resource type callback
BOOL EnumTypesFunc(
HMODULE hModule, // module handle
LPTSTR lpType, // address of resource type
LONG lParam) // extra parameter, could be
// used for error checking
{
TCHAR szBuffer[80]; // print buffer for info file
DWORD cbWritten; // number of bytes written to resource info file
size_t cbString;
HRESULT hResult;
// Write the resource type to a resource information file.
// The type may be a string or an unsigned decimal
// integer, so test before printing.
if (!IS_INTRESOURCE(lpType))
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("Type: %s\r\n"), lpType);
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return FALSE;
}
}
else
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("Type: %u\r\n"), (USHORT)lpType);
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return FALSE;
}
}
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return FALSE;
}
WriteFile(g_hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL);
// Find the names of all resources of type lpType.
EnumResourceNames(hModule,
lpType,
(ENUMRESNAMEPROC)EnumNamesFunc,
0);
return TRUE;
}
// FUNCTION: EnumNamesFunc(HANDLE, LPSTR, LPSTR, LONG)
//
// PURPOSE: Resource name callback
BOOL EnumNamesFunc(
HMODULE hModule, // module handle
LPCTSTR lpType, // address of resource type
LPTSTR lpName, // address of resource name
LONG lParam) // extra parameter, could be
// used for error checking
{
TCHAR szBuffer[80]; // print buffer for info file
DWORD cbWritten; // number of bytes written to resource info file
size_t cbString;
HRESULT hResult;
// Write the resource name to a resource information file.
// The name may be a string or an unsigned decimal
// integer, so test before printing.
if (!IS_INTRESOURCE(lpName))
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("\tName: %s\r\n"), lpName);
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return FALSE;
}
}
else
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("\tName: %u\r\n"), (USHORT)lpName);
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return FALSE;
}
}
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return FALSE;
}
WriteFile(g_hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL);
// Find the languages of all resources of type
// lpType and name lpName.
EnumResourceLanguages(hModule,
lpType,
lpName,
(ENUMRESLANGPROC)EnumLangsFunc,
0);
return TRUE;
}
// FUNCTION: EnumLangsFunc(HANDLE, LPSTR, LPSTR, WORD, LONG)
//
// PURPOSE: Resource language callback
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;
TCHAR szBuffer[80]; // print buffer for info file
DWORD cbWritten; // number of bytes written to resource info file
size_t cbString;
HRESULT hResult;
hResInfo = FindResourceEx(hModule, lpType, lpName, wLang);
// Write the resource language to the resource information file.
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("\t\tLanguage: %u\r\n"), (USHORT) wLang);
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return FALSE;
}
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return FALSE;
}
WriteFile(g_hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL);
// Write the resource handle and size to buffer.
hResult = StringCchPrintf(szBuffer,
sizeof(szBuffer)/sizeof(TCHAR),
TEXT("\t\thResInfo == %lx, Size == %lu\r\n\r\n"),
hResInfo,
SizeofResource(hModule, hResInfo));
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return FALSE;
}
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
if (FAILED(hResult))
{
// Add code to fail as securely as possible.
return FALSE;
}
WriteFile(g_hFile, szBuffer, (DWORD)cbString, &cbWritten, NULL);
return TRUE;
}