Создание списка ресурсов
Пример ниже создает список каждого ресурса в файле Hand.exe. Список записывается в файл Resinfo.txt.
Код демонстрирует, как загрузить исполняемый файл, как создать файл в котором записывается информация о ресурсе, и как вызвать функцию EnumResourceTypes, чтобы отправить каждый тип ресурса, найденный в модуле в определяемую программой функцию повторного вызова EnumTypesFunc. Информацию о функции повторного вызова этого типа см. в описании EnumResTypeProc. Эта функция повторного вызова использует функцию EnumResourceNames, чтобы передавать имя каждого ресурса внутри заданного типа в другую определяемую программой функцию повторного вызова EnumNamesFunc. Информацию о функции повторного вызова этого типа см. в описании EnumResNameProc. EnumNamesFunc использует функцию EnumResourceLanguages, чтобы передать язык каждого ресурса заданного типа и имени в третью функцию повторного вызова, EnumLangsFunc. Информацию о функции повторного вызова этого типа см. в описании EnumResLangProc. EnumLangsFunc пишет информацию о ресурсе заданного типа, имени и языка в файл Resinfo.txt.
Обратите внимание! на то, что то, что параметр lpszType в EnumResTypeProc является или идентификатором ресурса (ID) или указателем на строку (содержащую ID ресурса или имя типа); параметры lpszType и lpszName в EnumResNameProc являются похожими. |
Чтобы использовать перечисленный ресурс, возьмите имя ресурса или ID и вызовите соответствующую функцию. Например, чтобы загрузить строковый ресурс (RT_STRING), если lpszName в EnumResNameProc дает ID ресурса (или непосредственно или в строке, которая начинается с символа номера (#)), вызовите LoadString. Если же, lpszName указывает на символьную) строку, содержащую имя ресурса, тогда сделайте следующее:
Код корректировки ресурсов следует за похожим шаблоном для ресурса диалогового окна.
Обратите внимание! на то, что неправильное использование LoadLibrary может поставить под угрозу защиту вашего приложения, загружая неправильную DLL. Обратитесь к документации LoadLibrary за информацией о том, как правильно загружать DLLs в разных версиях Microsoft ® Windows ®. |
Демонстрационный пример
char szBuffer[80]; // буфер печати EnumResourceTypes DWORD cbWritten; // число записанных байтов в файле ресурса инф. size_t cbString; // длина строки в sprintf HRESULT hResult; // Объявление функций повторного вызова. BOOL EnumTypesFunc( HANDLE hModule, LPTSTR lpType, LONG lParam); BOOL EnumNamesFunc( HANDLE hModule, LPCTSTR lpType, LPTSTR lpName, LONG lParam); BOOL EnumLangsFunc( HANDLE hModule, LPCTSTR lpType, LPCTSTR lpName, WORD wLang, LONG lParam); // Загружаем .EXE, ресурсы которого хотим перечислить. hExe = LoadLibrary("hand.exe"); if (hExe == NULL) { // Добавление кода защиты, насколько возможно, от ошибки. return; } // Создадим файл для содержания информации о ресурсе. hFile = CreateFile("resinfo.txt", // имя файла GENERIC_READ | GENERIC_WRITE, // режим доступа 0, // режим совместного доступа (LPSECURITY_ATTRIBUTES) NULL, // защита по умолчанию CREATE_ALWAYS, // флажки создания FILE_ATTRIBUTE_NORMAL, // атрибуты файла (HANDLE) NULL); // шаблона нет if (hFile == INVALID_HANDLE_VALUE) { ErrorHandler("Could not open file."); } // Находим все загруженные файлы ресурсов. hResult = StringCchPrintf(szBuffer, 80/sizeof(TCHAR), // cbString = sprintf(szBuffer, "The file contains the following resources:\n\n"); if (FAILED(hResult)) { // Добавление кода защиты, насколько возможно, от ошибки. return; } hResult = StringCchLength(szBuffer, 80/sizeof(TCHAR), cbString); if (FAILED(hResult)) { // Добавление кода защиты, насколько возможно, от ошибки. return; } WriteFile(hFile, // файл, удерживающий информацию о ресурсе. szBuffer, // что записывать в файл (DWORD) cbString, // число байтов в szBuffer &cbWritten, // записанное число байтов NULL); // не асинхронный ввод-вывод EnumResourceTypes(hExe, // дескриптор модуля (ENUMRESTYPEPROC)EnumTypesFunc, // функция повторного вызова 0); // дополнительный параметр // Выгрузите исполняемый файл, ресурсы которого были // перечислены и закройте файл, созданный, чтобы содержать // информацию о ресурсе. FreeLibrary(hExe); CloseHandle(hFile); // ФУНКЦИЯ: EnumTypesFunc(HANDLE, LPSTR, LONG) // // ПРЕДНАЗНАЧЕНИЕ: Повторный вызов типа ресурса BOOL EnumTypesFunc( HANDLE hModule, // дескриптор модуля LPTSTR lpType, // адрес типа ресурса LONG lParam) // дополнительный параметр, должен // использоваться для проверки ошибок { size_t cbString; HRESULT hResult; // Запишите тип ресурса в файл информации ресурса. // Тип может быть строкой или десятичным целым // числом без знака, как проверка перед печатью. if ((ULONG)lpType & 0xFFFF0000) { hResult = StringCchPrintf(szBuffer, 80/sizeof(TCHAR), "Type: %s\n", lpType); if (FAILED(hResult)) { // Добавление кода защиты, насколько возможно, от ошибки. return; } // cbString = sprintf(szBuffer, "Type: %s\n", lpType); } else { hResult = StringCchPrintf(szBuffer, 80/sizeof(TCHAR), "Type: %u\n", (USHORT)lpType); if (FAILED(hResult)) { // Добавление кода защиты, насколько возможно, от ошибки. return; } // cbString = sprintf(szBuffer, "Type: %u\n", (USHORT)lpType); } hResult = StringCchLength(szBuffer, 80/sizeof(TCHAR), cbString); if (FAILED(hResult)) { // Добавление кода защиты, насколько возможно, от ошибки. return; } WriteFile(hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL); // Найдите названия всех ресурсов типа lpType. EnumResourceNames(hModule, lpType, (ENUMRESNAMEPROC)EnumNamesFunc, 0); return TRUE; } // ФУНКЦИЯ: EnumNamesFunc(HANDLE, LPSTR, LPSTR, LONG) // // ПРЕДНАЗНАЧЕНИЕ: повторный вызов имени ресурса BOOL EnumNamesFunc( HANDLE hModule, // дескриптор модуля LPCTSTR lpType, // адрес типа ресурса LPTSTR lpName, // адрес имени ресурса LONG lParam) // дополнительный параметр, должен // использоваться для проверки ошибок { size_t cbString; HRESULT hResult; // Запишите имя ресурса в файл информации ресурса. // Имя может быть строкой или десятичным целым // числом без знака, как проверка перед печатью. if ((ULONG)lpName & 0xFFFF0000) { hResult = StringCchPrintf(szBuffer, 80/sizeof(TCHAR), "\tName: %s\n", lpName); if (FAILED(hResult)) { // Добавление кода защиты, насколько возможно, от ошибки. return; } // cbString = sprintf(szBuffer, "\tName: %s\n", lpName); } else { hResult = StringCchPrintf(szBuffer, 80/sizeof(TCHAR), "\tName: %u\n", (USHORT)lpName); if (FAILED(hResult)) { // Добавление кода защиты, насколько возможно, от ошибки. return; } // cbString = sprintf(szBuffer, "\tName: %u\n", (USHORT)lpName); } hResult = StringCchLength(szBuffer, 80/sizeof(TCHAR), cbString); if (FAILED(hResult)) { // Добавление кода защиты, насколько возможно, от ошибки. return; } WriteFile(hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL); // Найдем языки всех ресурсов типа // lpType и имени lpName. EnumResourceLanguages(hModule, lpType, lpName, (ENUMRESLANGPROC)EnumLangsFunc, 0); return TRUE; } // ФУНКЦИЯ: EnumLangsFunc(HANDLE, LPSTR, LPSTR, WORD, LONG) // // ПРЕДНАЗНАЧЕНИЕ: Повторный вызов языка Ресурса BOOL EnumLangsFunc( HANDLE hModule, // дескриптор модуля LPCTSTR lpType, // адрес типа ресурса LPCTSTR lpName, // адрес имени ресурса WORD wLang, // язык ресурса LONG lParam) // дополнительный параметр, который должен // использоваться для выявления ошибок { HANDLE hResInfo; char szBuffer[80]; size_t cbString = 0; HRESULT hResult; hResInfo = FindResourceEx(hModule, lpType, lpName, wLang); // Запишем язык ресурса в файл информации ресурса. hResult = StringCchPrintf(szBuffer, 80/sizeof(TCHAR), "\t\tLanguage: %u\n", (USHORT) wLang); if (FAILED(hResult)) { // Добавление кода защиты, насколько возможно, от ошибки. return; } hResult = StringCchLength(szBuffer, 80/sizeof(TCHAR), cbString); if (FAILED(hResult)) { // Добавление кода защиты, насколько возможно, от ошибки. return; } // cbString = sprintf(szBuffer, "\t\tLanguage: %u\n", (USHORT)wLang); WriteFile(hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL); // Запишите дескриптор ресурса и размер буфера. cbString = sprintf(szBuffer, "\t\thResInfo == %lx, Size == %lu\n\n", hResInfo, SizeofResource(hModule, hResInfo)); WriteFile(hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL); return TRUE; } |