diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index 4e68874..95905f6 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -45,6 +45,8 @@ ULONG getModuleSize( ULONG64 baseOffset ); std::string getModuleSymbolFileName( ULONG64 baseOffset ); ULONG getModuleTimeStamp( ULONG64 baseOffset ); ULONG getModuleCheckSum( ULONG64 baseOffset ); +std::string getModuleVersionInfo( ULONG64 baseOffset, const std::string &value ); +void getModuleFileVersion( ULONG64 baseOffset, USHORT &majorHigh, USHORT &majorLow, USHORT &minorHigh, USHORT &minorLow ); // CPU registers ULONG getRegIndexByName( const std::string ®Name ); diff --git a/pykd/module.cpp b/pykd/module.cpp index 9ab5072..620a6f7 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -397,4 +397,21 @@ python::list Module::enumTypes( const std::string &mask ) } /////////////////////////////////////////////////////////////////////////////////// + +std::string Module::queryVersion( const std::string &value) { + return getModuleVersionInfo( m_base, value ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +python::tuple Module::getVersion() +{ + USHORT a1,a2,a3,a4; + getModuleFileVersion( m_base, a1,a2,a3,a4 ); + + return python::make_tuple(a1,a2,a3,a4); +} + +/////////////////////////////////////////////////////////////////////////////////// + }; // end of namespace pykd diff --git a/pykd/module.h b/pykd/module.h index 39a8747..b9a219b 100644 --- a/pykd/module.h +++ b/pykd/module.h @@ -137,6 +137,10 @@ public: std::string print(); + std::string queryVersion( const std::string &value); + + python::tuple getVersion(); + private: SymbolPtr& getSymScope(); diff --git a/pykd/python/pymod.cpp b/pykd/python/pymod.cpp index ecd7afc..d62794a 100644 --- a/pykd/python/pymod.cpp +++ b/pykd/python/pymod.cpp @@ -389,6 +389,10 @@ BOOST_PYTHON_MODULE( pykd ) "Return a image file checksum: IMAGE_OPTIONAL_HEADER.CheckSum" ) .def("timestamp",&Module::getTimeDataStamp, "Return a low 32 bits of the time stamp of the image: IMAGE_FILE_HEADER.TimeDateStamp" ) + .def("queryVersion", &Module::queryVersion, + "Return string from the module's version resources" ) + .def("getVersion", &Module::getVersion, + "Return tuple of the module's file version" ) .def("__getattr__", &Module::getSymbolOffset, "Return address of the symbol" ) .def( "__str__", &Module::print ); diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index ddaacc3..a56d986 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include +#include #include "win/dbgeng.h" #include "win/dbgio.h" @@ -541,7 +542,110 @@ ULONG getModuleCheckSum( ULONG64 baseOffset ) return moduleParam.Checksum; } -/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void getModuleFileVersion( ULONG64 baseOffset, USHORT &majorHigh, USHORT &majorLow, USHORT &minorHigh, USHORT &minorLow ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + VS_FIXEDFILEINFO fileInfo={}; + + HRESULT hres; + + hres = g_dbgEng->symbols->GetModuleVersionInformation( + DEBUG_ANY_ID, + baseOffset, + "\\", + (PVOID)&fileInfo, + sizeof(fileInfo), + NULL ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol2::GetModuleVersionInformation failed" ); + + majorHigh = HIWORD(fileInfo.dwFileVersionMS); + majorLow = LOWORD(fileInfo.dwFileVersionMS); + minorHigh = HIWORD(fileInfo.dwFileVersionLS); + minorLow = LOWORD(fileInfo.dwFileVersionLS); +} + +/////////////////////////////////////////////////////////////////////////////// + +std::string getModuleVersionInfo( ULONG64 baseOffset, const std::string &value ) +{ + struct LANGANDCODEPAGE { + WORD wLanguage; + WORD wCodePage; + }; + + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + ULONG codePagesSize = 0; + + hres = g_dbgEng->symbols->GetModuleVersionInformation( + DEBUG_ANY_ID, + baseOffset, + "\\VarFileInfo\\Translation", + NULL, + 0, + &codePagesSize ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol2::GetModuleVersionInformation failed" ); + + size_t codePageNum = codePagesSize / sizeof(LANGANDCODEPAGE); + + std::vector codePages(codePageNum); + + hres = g_dbgEng->symbols->GetModuleVersionInformation( + DEBUG_ANY_ID, + baseOffset, + "\\VarFileInfo\\Translation", + &codePages[0], + codePagesSize, + NULL ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol2::GetModuleVersionInformation failed" ); + + ULONG productNameLength = 0; + + std::stringstream sstr; + sstr << "\\StringFileInfo\\" << std::hex + << std::setw(4) << std::setfill('0') << codePages[0].wLanguage + << std::setw(4) << std::setfill('0') << codePages[0].wCodePage + << "\\" << value; + + ULONG valueLength; + + g_dbgEng->symbols->GetModuleVersionInformation( + DEBUG_ANY_ID, + baseOffset, + sstr.str().c_str(), + NULL, + 0, + &valueLength ); + + std::vector valueStr(valueLength); + + hres = g_dbgEng->symbols->GetModuleVersionInformation( + DEBUG_ANY_ID, + baseOffset, + sstr.str().c_str(), + &valueStr[0], + valueLength, + NULL ); + + if ( hres == S_OK ) + return std::string( &valueStr[0] ); + + return ""; + +} + +/////////////////////////////////////////////////////////////////////////////// ULONG ptrSize() { @@ -1464,6 +1568,7 @@ std::string callExtension( ULONG64 extHandle, const std::wstring command, const /////////////////////////////////////////////////////////////////////////////// + } // end pykd namespace