Support Board
Date/Time: Sat, 18 Jan 2025 00:38:51 +0000
Post From: Sierra ARM64 version lag and extra x64 log messages on SierraChart_ARM64.exe
[2025-01-17 18:37:34] |
User719512 - Posts: 287 |
This message is to add clarity around reading the "source of truth" for determining the machine type rather than relying on the file name. I am certain the Sierra Engineering team know all this, so this post is aimed at the aspiring developers who were curious about reading machine information from a dll (or exe). This is a POC (proof of concept) demo app that shows machine information for dll or exe files. Could also be refactored into a library of course for other usage. #include <windows.h> #include <filesystem> #include <iostream> #include <regex> #include <string> #include <vector> namespace fs = std::filesystem; bool GetDLLArchitecture(const std::wstring& dllPath, WORD& machineType) { HANDLE file = CreateFile(dllPath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (file == INVALID_HANDLE_VALUE) { std::wcerr << L"Failed to open file: " << dllPath << std::endl; return false; } // Read the DOS header IMAGE_DOS_HEADER dosHeader; DWORD bytesRead; if (!ReadFile(file, &dosHeader, sizeof(dosHeader), &bytesRead, nullptr) || bytesRead != sizeof(dosHeader)) { std::wcerr << L"Failed to read DOS header from: " << dllPath << std::endl; CloseHandle(file); return false; } if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) { std::wcerr << L"Invalid DOS signature in: " << dllPath << std::endl; CloseHandle(file); return false; } if (SetFilePointer(file, dosHeader.e_lfanew, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { std::wcerr << L"Failed to seek to PE header in: " << dllPath << std::endl; CloseHandle(file); return false; } DWORD peSignature; if (!ReadFile(file, &peSignature, sizeof(peSignature), &bytesRead, nullptr) || bytesRead != sizeof(peSignature)) { std::wcerr << L"Failed to read PE signature from: " << dllPath << std::endl; CloseHandle(file); return false; } if (peSignature != IMAGE_NT_SIGNATURE) { std::wcerr << L"Invalid PE signature in: " << dllPath << std::endl; CloseHandle(file); return false; } IMAGE_FILE_HEADER fileHeader; if (!ReadFile(file, &fileHeader, sizeof(fileHeader), &bytesRead, nullptr) || bytesRead != sizeof(fileHeader)) { std::wcerr << L"Failed to read File Header from: " << dllPath << std::endl; CloseHandle(file); return false; } machineType = fileHeader.Machine; CloseHandle(file); return true; } std::wstring GetArchitectureName(WORD machineType) { switch (machineType) { case IMAGE_FILE_MACHINE_ARM64: return L"ARM64"; case IMAGE_FILE_MACHINE_AMD64: return L"x64"; case IMAGE_FILE_MACHINE_I386: return L"x86"; default: return L"Unknown"; } } void ProcessDLL(const std::wstring& dllPath) { WORD machineType; if (GetDLLArchitecture(dllPath, machineType)) { std::wcout << L"Architecture of " << dllPath << L": " << GetArchitectureName(machineType) << std::endl; } else { std::wcerr << L"Failed to determine architecture of: " << dllPath << std::endl; } } void ProcessDirectory(const std::wstring& directory, const std::wstring& pattern = L"*.dll") { std::wregex regex; bool useRegex = false; // Convert wildcard pattern to a regex if it contains '*' if (pattern.find(L'*') != std::wstring::npos) { std::wstring regexPattern = std::regex_replace(pattern, std::wregex(L"\\*"), L".*"); regex.assign(regexPattern, std::regex_constants::icase); useRegex = true; } // Iterate over files in the directory for (const auto& entry : fs::directory_iterator(directory)) { if (entry.is_regular_file()) { const auto& path = entry.path(); const std::wstring filename = path.filename().wstring(); // Match filename with the wildcard pattern if (useRegex) { if (std::regex_match(filename, regex)) { ProcessDLL(path.wstring()); } } else { if (filename == pattern) { ProcessDLL(path.wstring()); } } } } } int wmain(int argc, wchar_t* argv[]) { if (argc == 2 || argc == 3) { std::wstring input(argv[1]); // Check for wildcard usage if (argc == 3) { std::wstring pattern(argv[2]); if (fs::is_directory(input)) { ProcessDirectory(input, pattern); } else { std::wcerr << L"Invalid input: Wildcard requires a valid directory\n"; } } else if (fs::is_regular_file(input)) { ProcessDLL(input); } else if (fs::is_directory(input)) { ProcessDirectory(input); // Default to *.dll } else { std::wcerr << L"Invalid input: " << input << std::endl; } } else { std::wcout << L"Usage:\n" << L" <program> <dll-file> Process a single DLL file\n" << L" <program> <directory> [pattern] Process DLLs matching a wildcard pattern\n"; } return 0; } |