有没有 Win32 函数可以获取 DLL 的体系结构?

Rya*_*len 0 c++ winapi

可以确定GetBinaryType()文件.exe是 32 位还是 64 位,但如何对.dll文件执行此操作?我想在尝试使用 .DLL 加载它之前确保 DLL 是正确的体系结构LoadLibrary()。

RbM*_*bMm 5

如果您想使用 dll 来调用函数或从中加载资源 - 只需尝试加载它即可。如果它是错误的架构 - 你会得到错误ERROR_BAD_EXE_FORMAT并且 dll 将不会被加载。在此之前检查仅此而已。尝试负载已经检查。

如果您因其他原因需要检查,有多种方法。最正确的是下一步 - 打开文件,从中创建图像部分并检查部分(最后一个操作未记录)

HRESULT CheckImage( _In_ PCWSTR lpLibFileName, _Out_ PUSHORT Machine)
{
    HANDLE hFile = CreateFileW(lpLibFileName, FILE_EXECUTE|FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        HANDLE hSection = CreateFileMappingW(hFile, 0, PAGE_EXECUTE_READ|SEC_IMAGE, 0, 0, 0);
        NtClose(hFile);
        if (hSection)
        {
            SECTION_IMAGE_INFORMATION sii;
            NTSTATUS status = ZwQuerySection(hSection, SectionImageInformation, &sii, sizeof(sii), 0);
            NtClose(hSection);

            *Machine = sii.Machine;

            return status ? HRESULT_FROM_NT(status) : S_OK;
        }
    }
    return HRESULT_FROM_WIN32(GetLastError());
}
Run Code Online (Sandbox Code Playgroud)

你从这个函数中得到了一些错误(找不到文件,图像错误等)或一些IMAGE_FILE_MACHINE_*. 通常IMAGE_FILE_MACHINE_AMD64或IMAGE_FILE_MACHINE_I386

另一种方式 - 使用LoadLibraryExW和LOAD_LIBRARY_AS_DATAFILE检查IMAGE_NT_HEADERS映射图像 - 实际上这种方式首先执行所有操作(包括ZwQuerySection内部调用)+将 dll 映射到内存 - 最后不需要。所以这是效率较低的方法。

HRESULT CheckImage2( _In_ PCWSTR lpLibFileName, _Out_ PUSHORT Machine)
{
    if (HMODULE hmod = LoadLibraryExW(lpLibFileName, 0, LOAD_LIBRARY_AS_DATAFILE))
    {
        HRESULT hr = S_OK;

        if (PIMAGE_NT_HEADERS pinth = RtlImageNtHeader(PAGE_ALIGN(hmod)))
        {
            *Machine = pinth->FileHeader.Machine;
        }
        else
        {
            hr = HRESULT_FROM_NT(STATUS_INVALID_IMAGE_NOT_MZ);
        }
        FreeLibrary(hmod);

        return hr;
    }
    return HRESULT_FROM_WIN32(GetLastError());
}
Run Code Online (Sandbox Code Playgroud)

其他一种方法 - 直接读取文件并检查它的标题。从一侧来看这是最快的,从另一侧来看 - 即使标头正确 - 也不能保证整个文件正常并且没有损坏

HRESULT CheckImage3( _In_ PCWSTR lpLibFileName, _Out_ PUSHORT Machine, _Out_ PBOOL Is64Bit)
{
    HANDLE hFile = CreateFileW(lpLibFileName, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    
    if (hFile != INVALID_HANDLE_VALUE)
    {
        HRESULT hr = HRESULT_FROM_NT(STATUS_INVALID_IMAGE_NOT_MZ);

        union {
            IMAGE_DOS_HEADER idh;
            IMAGE_NT_HEADERS inth;
        };

        OVERLAPPED ov {};

        ULONG dwBytesRead;
        if (ReadFile(hFile, &idh, sizeof(idh), &dwBytesRead, &ov))
        {
            if (dwBytesRead == sizeof(idh) && idh.e_magic == IMAGE_DOS_SIGNATURE)
            {
                hr = HRESULT_FROM_NT(STATUS_INVALID_IMAGE_FORMAT);

                ov.Offset = idh.e_lfanew;

                if (ReadFile(hFile, &inth, sizeof(inth), &dwBytesRead, &ov))
                {
                    if (dwBytesRead == sizeof(inth) && inth.Signature == IMAGE_NT_SIGNATURE)
                    {
                        switch (inth.OptionalHeader.Magic)
                        {
                        case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
                            *Is64Bit = FALSE;
                            hr = S_OK;
                            break;
                        case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
                            *Is64Bit = TRUE;
                            hr = S_OK;
                            break;
                        }

                        *Machine = inth.FileHeader.Machine;
                    }
                }
            }
        }

        CloseHandle(hFile);

        return hr;
    }

    return HRESULT_FROM_WIN32(GetLastError());
}
Run Code Online (Sandbox Code Playgroud)