FindResource按名称查找资源失败

时间:2019-10-25 16:58:47

标签: c++ winapi

HRSRC test = FindResourceW(hModule, L"TEST", RT_MANIFEST);

FindResource失败,出现 ERROR_RESOURCE_NAME_NOT_FOUND 。我只将清单的资源名称重命名为字符串,然后尝试找到它。我认为这与MAKEINTRESOURCE / IS_INTRESOURCE有关,或者我不确定。有任何想法吗?但是,仅将资源命名为1时,它就可以正常工作。

  

ERROR_RESOURCE_NAME_NOT_FOUND

     

1814(0x716)

     

在图像文件中找不到指定的资源名称。

enter image description here

编辑:

第一次迭代: enter image description here

第二次迭代: enter image description here

struct Resource
{
    LPVOID lpData;
    LPCWSTR lpType;
    LPCWSTR lpName;
    DWORD dwSize;
};

bool EnumNamesFunc(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam)
{
    HRSRC hResource = nullptr;

    if (!IS_INTRESOURCE(lpName))
    {
        hResource = FindResource(hModule, lpName, lpType);

        std::wcout << "It is not. " << lpName << std::endl;
    }
    else if (IS_INTRESOURCE(lpName))
    {
        hResource = FindResource(hModule, lpName, lpType);

        std::cout << "It is" << std::endl;
    }

    if (!hResource)
    {
        return false;
    }

    DWORD dwSize = SizeofResource(hModule, hResource);
    HGLOBAL hGlobal = LoadResource(hModule, hResource);

    if (!hGlobal)
    {
        return false;
    }

    LPVOID lpResource = LockResource(hGlobal);

    if (!lpResource)
    {
        return false;
    }

    Resource temp;
    temp.lpData = hGlobal;
    temp.lpType = lpType;
    temp.lpName = lpName;
    temp.dwSize = dwSize;

    resources.push_back(temp);

    FreeResource(lpResource);

    return true;
}

此代码有效,但会泄漏:

Resource temp;
temp.lpData = hGlobal;
temp.lpType = lpType;

if (!IS_INTRESOURCE(lpName))
{
    LPVOID temp = malloc(sizeof(LPCWSTR) * wcslen(lpName));
    memcpy(temp, lpName, sizeof(LPCWSTR) * wcslen(lpName));
    temp.lpName = temp;
}
else
{
    temp.lpName = lpName;
}

1 个答案:

答案 0 :(得分:3)

EnumResourceNames()回调中,当lpType返回false时,无法保存lpNameIS_INTRESOURCE()的原始指针。一旦回调退出,该数据就会消失,从而使resources容器中的指针无效。因此,在这种情况下,您需要复制它们指向的以空字符结尾的字符数据(您尝试这样做,但是没有正确执行)。

为避免内存泄漏,请在Resource为假时向lpName添加一个析构函数以释放lpType / IS_INTRESOURCE()数据。另外,您需要向Resource添加一个 copy构造函数和一个 copy赋值运算符来深度复制lpType / lpName数据正确(按Rule of 3)。

此外,您的回调函数需要返回BOOL而不是bool,并且需要使用__stdcall调用约定(由WINAPI和{{ 1}}宏。

尝试更多类似的方法:

CALLBACK
struct Resource
{
    LPWSTR lpType;
    LPWSTR lpName;
    HANDLE lpData;
    DWORD dwSize;

    Resource(LPCWSTR, LPWSTR, HANDLE, DWORD);
    Resource(const Resource &);
    ~Resource();
    Resource& operator=(const Resource &);
};
LPWSTR MakeResourceCopy(LPCWSTR Value)
{
    if (IS_INTRESOURCE(Value))
        return const_cast<LPWSTR>(Value);

    int len = wcslen(Value) + 1;
    LPWSTR copy = new WCHAR[len];
    memcpy(copy, Value, sizeof(WCHAR) * len);
    return copy;
}

Resource::Resource(LPCWSTR Type, LPWSTR Name, HANDLE Data, DWORD Size)
{
    lpType = MakeResourceCopy(Type);
    lpName = MakeResourceCopy(Name);
    lpData = Data;
    dwSize = Size;
}

Resource::Resource(const Resource &src)
{
    lpType = MakeResourceCopy(src.lpType);
    lpName = MakeResourceCopy(src.lpName);
    lpData = src.lpData;
    dwSize = src.dwSize;
}

Resource::~Resource()
{
    if (!IS_INTRESOURCE(lpType))
        delete[] lpType;

    if (!IS_INTRESOURCE(lpName))
        delete[] lpName;
}

Resource& Resource::operator=(const Resource &rhs)
{
    if (&rhs != this)
    {
        Resource copy(rhs);

        using std::swap;
        swap(lpType, copy.lpType);
        swap(lpName, copy.lpName);
        swap(lpData, copy.lpData);
        swap(dwSize, copy.dwSize);
    }

    return *this;
}

也就是说,我建议将BOOL CALLBACK EnumNamesFunc(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam) { if (!IS_INTRESOURCE(lpType)) std::wcout << "lpType is not an integer. " << lpType << std::endl; else std::cout << "lpType is an integer. #" << reinterpret_cast<int>(lpType) << std::endl; if (!IS_INTRESOURCE(lpName)) std::wcout << "lpName is not an integer. " << lpName << std::endl; else std::cout << "lpName is an integer. #" << reinterpret_cast<int>(lpName) << std::endl; HRSRC hResource = FindResource(hModule, lpName, lpType); if (!hResource) return FALSE; DWORD dwSize = SizeofResource(hModule, hResource); HGLOBAL hGlobal = LoadResource(hModule, hResource); if (!hGlobal) return FALSE; LPVOID lpResource = LockResource(hGlobal); if (!lpResource) return FALSE; Resource res(lpType, lpName, hGlobal, dwSize); resources.push_back(res); return TRUE; } 的{​​{1}} / Resource字段改为lpType。如果获得数字lpName / std::wstring值,只需将其转换为lpType格式。让编译器为您处理所有内存管理:

lpName
"#..."

或者,使用struct Resource { std::wstring lpType; std::wstring lpName; HANDLE lpData; DWORD dwSize; }; 代替:

std::wstring MakeResourceWString(LPCWSTR Value)
{
    if (IS_INTRESOURCE(Value))
        return L"#" + std::to_wstring(reinterpret_cast<int>(Value));
    else
        return Value;
}

BOOL CALLBACK EnumNamesFunc(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam)
{
    if (!IS_INTRESOURCE(lpType))
        std::wcout << "lpType is not an integer. " << lpType << std::endl;
    else
        std::cout << "lpType is an integer. #" << reinterpret_cast<int>(lpType) << std::endl;

    if (!IS_INTRESOURCE(lpName))
        std::wcout << "lpName is not an integer. " << lpName << std::endl;
    else
        std::cout << "lpName is an integer. #" << reinterpret_cast<int>(lpName) << std::endl;

    HRSRC hResource = FindResource(hModule, lpName, lpType);
    if (!hResource)
        return FALSE;

    DWORD dwSize = SizeofResource(hModule, hResource);
    HGLOBAL hGlobal = LoadResource(hModule, hResource);
    if (!hGlobal)
        return FALSE;

    LPVOID lpResource = LockResource(hGlobal);
    if (!lpResource)
        return FALSE;

    Resource res;
    res.lpType = MakeResourceWString(lpType);
    res.lpName = MakeResourceWString(lpName);
    res.lpData = hGlobal;
    res.dwSize = dwSize;

    resources.push_back(res);

    return TRUE;
}
std::variant