公式ドキュメントは確認していませんが、Windows NT系列ではモジュールハンドルHMODULE
は実行可能ファイルのメモリマップトファイルアドレスらしいです。なので、GetModuleHandle
やLoadLibrary
で取得したモジュールハンドルをchar
型文字列にキャストすると最初の2文字はMZ
(IMAGE_DOS_HEADER
の最初のメンバー変数)で、PSAPI
のGetMappedFileName
関数で実行ファイル名を取得できます。
#include <bit> #include <string> #define STRICT #define NOMINMAX #include <Windows.h> #include <Psapi.h> constexpr std::wstring unpack_chars2_to_wstring_le(uint16_t x) { return { static_cast<wchar_t>(x & 0xff), static_cast<wchar_t>((x >> 8) & 0xff) }; } constexpr std::wstring unpack_chars4_to_wstring_le(uint32_t x) { return { static_cast<wchar_t>(x & 0xff), static_cast<wchar_t>((x >> 8) & 0xff), static_cast<wchar_t>((x >> 16) & 0xff), static_cast<wchar_t>((x >> 24) & 0xff) }; } #include <iostream> int main() { for (auto handle : {GetModuleHandleW(nullptr), LoadLibraryW(L"user32.dll")}) { auto base{std::bit_cast<const PBYTE>(handle)}; auto pimg_dos_hdr{std::bit_cast<const PIMAGE_DOS_HEADER>(base)}; auto pimg_nt_hdrs_magic{std::bit_cast<const PDWORD>(base + pimg_dos_hdr->e_lfanew)}; std::wcout << unpack_chars2_to_wstring_le(pimg_dos_hdr->e_magic).data() << std::endl; // MZ (IMAGE_DOS_SIGNATURE) std::wcout << unpack_chars4_to_wstring_le(*pimg_nt_hdrs_magic).data() << std::endl; // PE\0\0 (IMAGE_NT_SIGNATURE) std::wstring sz(MAX_PATH - 1, '\0'); ::GetMappedFileNameW(GetCurrentProcess(), handle, sz.data(), MAX_PATH); std::wcout << sz << std::endl; std::wcout << std::endl; } }
constexpr
、std::bit_cast
を使わないコード
#include <string> #include <iostream> #define STRICT #define NOMINMAX #include <Windows.h> #include <Psapi.h> inline auto conv_uint16_into_chars(uint16_t x) { return std::string(reinterpret_cast<const char* const>(&x), sizeof x); } inline auto conv_uint32_into_chars(uint32_t x) { return std::string(reinterpret_cast<const char* const>(&x), sizeof x); } int main() { for (auto handle : { ::GetModuleHandleW(nullptr), ::LoadLibraryW(L"user32.dll") }) { auto base = reinterpret_cast<const PBYTE>(handle); auto pimg_dos_hdr = reinterpret_cast<PIMAGE_DOS_HEADER>(base); auto pimg_nt_hdrs_magic = reinterpret_cast<PDWORD>(base + pimg_dos_hdr->e_lfanew); std::cout.setf(std::ios_base::boolalpha); std::cout << conv_uint16_into_chars(pimg_dos_hdr->e_magic) << std::endl; // MZ (IMAGE_DOS_SIGNATURE) std::cout << conv_uint32_into_chars(*pimg_nt_hdrs_magic) << std::endl; // PE\0\0 (IMAGE_NT_SIGNATURE) std::wstring sz(MAX_PATH - 1, '\0'); ::GetMappedFileNameW(GetCurrentProcess(), handle, sz.data(), MAX_PATH); std::wcout << sz << std::endl; std::wcout << std::endl; } }
出力例(システムディレクトリと実行ファイルProject1.exeがHarddiskVolume2にある場合)
MZ PE \Device\HarddiskVolume2\...\Project1.exe MZ PE \Device\HarddiskVolume2\Windows\System32\user32.dll
参考