Reputation: 1416
There is GetBinaryType()
for determining if an .exe
file is 32-bit or 64-bit, but how can I do this for a .dll
file? I want to ensure that a DLL is the right architecture before trying to load it with LoadLibrary()
.
Upvotes: 0
Views: 257
Reputation: 33706
if you want use dll for call functions or load resource from it - just try load it. if it was wrong architecture - you got error ERROR_BAD_EXE_FORMAT
and dll wil be not loaded. check before this nothing more give. the try load is check already.
if you need check for some other reasons, exist several ways. most correct is next - open file, create image section from it and check section (last operation is undocumented)
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());
}
you got or some error from this func (file not found, bad image, etc) or some IMAGE_FILE_MACHINE_*
. usually IMAGE_FILE_MACHINE_AMD64
or IMAGE_FILE_MACHINE_I386
another way - use LoadLibraryExW
with LOAD_LIBRARY_AS_DATAFILE
and check IMAGE_NT_HEADERS
of mapped image - really this way do all what first (including ZwQuerySection
call internally) + mapped dll to memory - last is not need. so this is less efficient way.
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());
}
else one way - direct read file and check it headers. this from one side is fastest, from another side - even if headers is correct - no guarantee that whole file is ok and not corrupted
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());
}
Upvotes: 6