|
|
- #include <windows.h>
- #include <vector>
- #include <string>
- #include <fstream>
- #include <cstdlib>
- #include <iostream>
- #include <iomanip>
- #include <sstream>
- #include <algorithm>
- // 全局向量存储资源名称(替代 AutoIt 的 $aEN 数组)
- std::vector<std::wstring> g_resourceNames;
- // 资源枚举回调函数(替代 AutoIt 的 ___EnumResNameProc)
- BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam) {
- if (IS_INTRESOURCE(lpszName)) {
- // ★ 处理整数型资源 ID(如 #123)
- WORD id = static_cast<WORD>(reinterpret_cast<ULONG_PTR>(lpszName));
- std::wstringstream wss;
- wss << L"#" << id;
- g_resourceNames.push_back(wss.str());
- } else {
- // ★ 处理字符串型资源名称
- g_resourceNames.push_back(lpszName);
- }
- return TRUE; // 继续枚举
- }
- int wmain(int argc, wchar_t* argv[]) {
- // ===== 1. 命令行参数处理 =====
- if (argc != 4) {
- std::wcerr << L"用法: " << argv[0] << L" <文件> <索引> <输出文件>\n";
- return -1;
- }
- std::wstring file = argv[1];
- int index = _wtoi(argv[2]); // 转换索引参数
- std::wstring outputFile = argv[3];
- // ===== 2. 文件存在性检查 =====
- if (!PathFileExistsW(file.c_str())) {
- wchar_t sysDir[MAX_PATH];
- // 获取系统目录路径
- UINT sysDirLen = GetSystemDirectoryW(sysDir, MAX_PATH);
- if (sysDirLen == 0 || sysDirLen > MAX_PATH) {
- std::wcerr << L"错误: 无法获取系统目录\n";
- return -2;
- }
- // 尝试在系统目录中查找
- std::wstring sysFile = std::wstring(sysDir) + L"\" + file;
- if (!PathFileExistsW(sysFile.c_str())) {
- std::wcerr << argv[1] << L" 未找到\n";
- return -2;
- }
- file = sysFile; // 使用系统目录中的文件
- }
- // ===== 3. 加载目标文件为数据文件 =====
- HMODULE hModule = LoadLibraryExW(
- file.c_str(),
- NULL,
- LOAD_LIBRARY_AS_DATAFILE // 重要:仅作为资源加载
- );
- if (!hModule) {
- std::wcerr << L"错误: 无法加载文件资源\n";
- return -3;
- }
- // ===== 4. 枚举图标组资源 =====
- g_resourceNames.clear();
- if (!EnumResourceNamesW(
- hModule,
- RT_GROUP_ICON, // 图标组资源类型
- EnumResNameProc, // 回调函数
- 0 // 回调参数
- )) {
- FreeLibrary(hModule);
- std::wcerr << L"错误: 枚举资源失败\n";
- return -3;
- }
- // ===== 5. 验证并选择图标索引 =====
- int absIndex = abs(index); // 处理负索引
- if (absIndex < 1 || absIndex > static_cast<int>(g_resourceNames.size())) {
- FreeLibrary(hModule);
- std::wcerr << L"错误: 无效的图标索引\n";
- return -3;
- }
- std::wstring resName = g_resourceNames[absIndex - 1]; // 转换为0-based索引
- // ===== 6. 准备资源标识符 =====
- LPCWSTR lpResName;
- if (resName[0] == L'#') {
- // ★ 转换 "#数字" 格式为资源ID
- int id = std::wcstol(resName.substr(1).c_str(), nullptr, 10);
- lpResName = MAKEINTRESOURCEW(id);
- } else {
- // ★ 直接使用字符串资源名
- lpResName = resName.c_str();
- }
- // ===== 7. 加载图标组资源 =====
- HRSRC hGroupRes = FindResourceW(hModule, lpResName, RT_GROUP_ICON);
- if (!hGroupRes) {
- FreeLibrary(hModule);
- std::wcerr << L"错误: 未找到图标组资源\n";
- return -3;
- }
- // 获取资源大小
- DWORD groupSize = SizeofResource(hModule, hGroupRes);
- if (groupSize < 6) { // 最小头尺寸检查
- FreeLibrary(hModule);
- return -3;
- }
- // 加载并锁定资源
- HGLOBAL hGroupData = LoadResource(hModule, hGroupRes);
- if (!hGroupData) {
- FreeLibrary(hModule);
- return -3;
- }
- BYTE* pGroupData = static_cast<BYTE*>(LockResource(hGroupData));
- if (!pGroupData) {
- FreeLibrary(hModule);
- return -3;
- }
- // ===== 8. 解析图标组头信息 =====
- WORD reserved = *reinterpret_cast<WORD*>(pGroupData); // 保留字段 (应为0)
- WORD type = *reinterpret_cast<WORD*>(pGroupData + 2); // 资源类型 (应为1)
- WORD count = *reinterpret_cast<WORD*>(pGroupData + 4); // 图标数量
- // 验证图标组头
- if (reserved != 0 || type != 1 || groupSize < 6 + 14 * count) {
- FreeLibrary(hModule);
- std::wcerr << L"错误: 无效的图标组格式\n";
- return -3;
- }
- // ===== 9. 创建输出ICO文件 =====
- std::ofstream outFile(outputFile, std::ios::binary);
- if (!outFile.is_open()) {
- FreeLibrary(hModule);
- std::wcerr << L"错误: 无法创建输出文件\n";
- return -3;
- }
- // ===== 10. 写入ICO文件头 =====
- DWORD offset = 6 + 16 * count; // 计算首个图标数据偏移量
- outFile.write(reinterpret_cast<char*>(pGroupData), 6); // 写入ICO头
- if (!outFile) {
- outFile.close();
- FreeLibrary(hModule);
- return -3;
- }
- // ===== 11. 处理每个图标条目 =====
- for (WORD i = 0; i < count; ++i) {
- BYTE* pEntry = pGroupData + 6 + 14 * i; // 当前图标条目指针
-
- // 修改条目中的偏移量字段
- outFile.write(reinterpret_cast<char*>(pEntry), 12); // 写入前12字节
- outFile.write(reinterpret_cast<char*>(&offset), 4); // 写入新计算的偏移量
-
- if (!outFile) {
- outFile.close();
- FreeLibrary(hModule);
- return -3;
- }
-
- // 更新下一个图标的偏移量
- DWORD iconSize = *reinterpret_cast<DWORD*>(pEntry + 8);
- offset += iconSize;
- }
- // ===== 12. 写入图标数据 =====
- for (WORD i = 0; i < count; ++i) {
- BYTE* pEntry = pGroupData + 6 + 14 * i;
- WORD iconId = *reinterpret_cast<WORD*>(pEntry + 12); // 获取图标ID
-
- // 加载单个图标资源
- HRSRC hIconRes = FindResourceW(hModule, MAKEINTRESOURCEW(iconId), RT_ICON);
- if (!hIconRes) {
- outFile.close();
- FreeLibrary(hModule);
- std::wcerr << L"错误: 未找到图标资源\n";
- return -3;
- }
- // 获取图标数据
- DWORD iconSize = SizeofResource(hModule, hIconRes);
- HGLOBAL hIconData = LoadResource(hModule, hIconRes);
- if (!hIconData || iconSize == 0) {
- outFile.close();
- FreeLibrary(hModule);
- return -3;
- }
-
- BYTE* pIconData = static_cast<BYTE*>(LockResource(hIconData));
- if (!pIconData) {
- outFile.close();
- FreeLibrary(hModule);
- return -3;
- }
- // 写入图标数据到文件
- outFile.write(reinterpret_cast<char*>(pIconData), iconSize);
- if (!outFile) {
- outFile.close();
- FreeLibrary(hModule);
- return -3;
- }
- }
- // ===== 13. 清理资源 =====
- outFile.close();
- FreeLibrary(hModule);
- std::wcout << L"图标成功导出至: " << outputFile << std::endl;
- return 0; // 成功退出
- }
复制代码 |
|