バイナリがx86、x64、またはia64のいずれであるかをプログラムで判断する方法を見つけようとしています。
プラットフォーム:Windows。言語:c /c++。
背景:サードパーティのdllをロードする前に、そのビット数を確認する必要があります。
ポインタに感謝します。
GetBinaryType(...)を使用する
これは、管理されたexeファイルに対する同じ質問です。
ImageNtHeader(...)を使用してファイルのPEデータを取得し、IMAGE_FILE_HEADER.Machineフィールドを確認します。
これが私がグーグルコード検索を使って見つけたいくつかのコードです
クリーンアップもエラーチェックもありません
// map the file to our address space
// first, create a file mapping object
hMap = CreateFileMapping(
hFile,
NULL, // security attrs
PAGE_READONLY, // protection flags
0, // max size - high DWORD
0, // max size - low DWORD
NULL ); // mapping name - not used
// next, map the file to our address space
void* mapAddr = MapViewOfFileEx(
hMap, // mapping object
FILE_MAP_READ, // desired access
0, // loc to map - hi DWORD
0, // loc to map - lo DWORD
0, // #bytes to map - 0=all
NULL ); // suggested map addr
peHdr = ImageNtHeader( mapAddr );
私はGithubでプロジェクトをオープンソース化し、VC ++再配布可能DLLを具体的にチェックし、Shayの回答の関数に基づいて作成したコードスニペットがあり、DLLのx86 / x64互換性を正常に検出、ロード、および検査します。
以下の完全なコードスニペット:
/******************************************************************
Function Name: CheckProductUsingCurrentDirectory
Description: Queries the current working directory for a given binary.
Inputs: pszProductFolderToCheck - the product name to look up.
pBinaryArchitecture - the desired processor architecture
of the binary (x86, x64, etc..).
Results: true if the requested product is installed
false otherwise
******************************************************************/
bool CheckProductUsingCurrentDirectory(const LPCTSTR pszProductBinaryToCheck, Architecture pBinaryArchitecture){
bool bFoundRequestedProduct = false;
//Get the length of the buffer first
TCHAR currentDirectory[MAX_PATH];
DWORD currentDirectoryChars = GetCurrentDirectory(MAX_PATH, currentDirectory);
//exit if couldn't get current directory
if (currentDirectoryChars <= 0) return bFoundRequestedProduct;
TCHAR searchPath[MAX_PATH];
//exit if we couldn't combine the path to the requested binary
if (PathCombine(searchPath, currentDirectory, pszProductBinaryToCheck) == NULL) return bFoundRequestedProduct;
WIN32_FIND_DATA FindFileData;
HANDLE hFind= FindFirstFile(searchPath, &FindFileData);
//exit if the binary was not found
if (hFind == INVALID_HANDLE_VALUE) return bFoundRequestedProduct;
HANDLE hFile = CreateFile(searchPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if (hFile == INVALID_HANDLE_VALUE) goto cleanup;
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, pszProductBinaryToCheck);
if (hMapping == INVALID_HANDLE_VALUE) goto cleanup;
LPVOID addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (addrHeader == NULL) goto cleanup; //couldn't memory map the file
PIMAGE_NT_HEADERS peHdr = ImageNtHeader(addrHeader);
if (peHdr == NULL) goto cleanup; //couldn't read the header
//Found the binary, AND its architecture matches. Success!
if (peHdr->FileHeader.Machine == pBinaryArchitecture){
bFoundRequestedProduct = true;
}
cleanup: //release all of our handles
FindClose(hFind);
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
if (hMapping != INVALID_HANDLE_VALUE)
CloseHandle(hMapping);
return bFoundRequestedProduct;
}
この質問とShayの回答は、私がこれを作成しているときに役に立ちました。そこで、プロジェクトをここに投稿すると思いました。
IMAGE_FILE_MACHINE
PEヘッダーを自分でチェックして、フィールド を読み取ることができます。これは、C ++に適応するのにそれほど難しくないはずのC#実装です。