Usando recursos
Esta seção contém snippets de código para as seguintes tarefas:
Atualizando recursos
O exemplo a seguir copia um recurso de caixa de diálogo de um arquivo executável, Hand.exe, para outro, Foot.exe seguindo estas etapas:
- Use a função LoadLibrary para carregar o arquivo executável Hand.exe.
- Use as funções FindResource e LoadResource para localizar e carregar o recurso da caixa de diálogo.
- Use a função LockResource para recuperar um ponteiro para os dados do recurso da caixa de diálogo.
- Use a função BeginUpdateResource para abrir um identificador de atualização para Foot.exe.
- Use a função UpdateResource para copiar o recurso da caixa de diálogo de Hand.exe para Foot.exe.
- Use a função EndUpdateResource para concluir a atualização.
O código a seguir implementa essas etapas.
Aviso de segurança: Usar LoadLibrary incorretamente pode comprometer a segurança do aplicativo carregando a DLL errada. Consulte a documentação do LoadLibrary para obter informações sobre como carregar corretamente DLLs com diferentes versões do Windows.
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;
}
Criando uma lista de recursos
O exemplo a seguir cria uma lista de todos os recursos no arquivo Hand.exe. A lista é gravada no arquivo Resinfo.txt.
O código demonstra como carregar o arquivo executável, criar um arquivo no qual gravar informações de recurso e chamar a função EnumResourceTypes para enviar cada tipo de recurso encontrado no módulo para a função EnumTypesFunc
de retorno de chamada definida pelo aplicativo. Consulte EnumResTypeProc para obter informações sobre funções de retorno de chamada desse tipo. Essa função de retorno de chamada usa a função EnumResourceNames para passar o nome de cada recurso dentro do tipo especificado para outra função de retorno de chamada definida pelo aplicativo, EnumNamesFunc
. Consulte EnumResNameProc para obter informações sobre funções de retorno de chamada desse tipo.
EnumNamesFunc
usa a função EnumResourceLanguages para passar o idioma de todos os recursos do tipo e nome especificados para uma terceira função de retorno de chamada, EnumLangsFunc
. Consulte EnumResLangProc para obter informações sobre funções de retorno de chamada desse tipo.
EnumLangsFunc
grava informações sobre o recurso do tipo, nome e idioma especificados no arquivo Resinfo.txt.
Observe que o lpszType em EnumResTypeProc é uma ID de recurso ou um ponteiro para uma cadeia de caracteres (contendo uma ID de recurso ou um nome de tipo); lpszType e lpszName em EnumResNameProc e EnumResLangProc são semelhantes. Para carregar um recurso enumerado, basta chamar a função apropriada. Por exemplo, se um recurso de menu (RT_MENU) foi enumerado, passe lpszName para LoadMenu. Para recursos personalizados, passe lpszType e lpszName para FindResource.
O código Atualizando Recursos segue um padrão semelhante para um recurso de caixa de diálogo.
Aviso de segurança: Usar LoadLibrary incorretamente pode comprometer a segurança do aplicativo carregando a DLL errada. Consulte a documentação do LoadLibrary para obter informações sobre como carregar corretamente DLLs com diferentes versões do Windows.
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;
}