From cf9aa94082386cafa83e19c932f1861035652eae Mon Sep 17 00:00:00 2001 From: "SND\\ussrhero_cp" Date: Wed, 22 Jun 2016 23:20:06 +0000 Subject: [PATCH] [pykd_ext_2.0] fixed : many bugs git-svn-id: https://pykd.svn.codeplex.com/svn@90992 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd_ext/arglist.cpp | 2 +- pykd_ext/pyinterpret.cpp | 227 +++++++++++++++++++++++---------------- pykd_ext/pyinterpret.h | 11 ++ pykd_ext/windbgext.cpp | 25 ++++- 4 files changed, 172 insertions(+), 93 deletions(-) diff --git a/pykd_ext/arglist.cpp b/pykd_ext/arglist.cpp index 0a8151b..a0b8b9b 100644 --- a/pykd_ext/arglist.cpp +++ b/pykd_ext/arglist.cpp @@ -28,7 +28,7 @@ ArgsList getArgsList(const char* args) static const std::regex versionRe("^-([2,3])(?:\\.(\\d+))?$"); Options::Options(const ArgsList& argList) : - pyMajorVersion(2), + pyMajorVersion(-1), pyMinorVersion(-1), global(true), showHelp(false) diff --git a/pykd_ext/pyinterpret.cpp b/pykd_ext/pyinterpret.cpp index b0d1b90..78e0d09 100644 --- a/pykd_ext/pyinterpret.cpp +++ b/pykd_ext/pyinterpret.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "pymodule.h" #include "pyclass.h" @@ -60,67 +62,67 @@ public: PyObject* Py_None; PyObject* PyExc_SystemExit; - void(__stdcall *Py_Initialize)(); - void(__stdcall *Py_Finalize)(); + void( *Py_Initialize)(); + void( *Py_Finalize)(); - PyThreadState* (__stdcall *Py_NewInterpreter)(); - void(__stdcall *Py_EndInterpreter)(PyThreadState *tstate); - PyObject* (__stdcall *PyEval_GetGlobals)(); - PyObject* (__stdcall *PyImport_Import)(PyObject *name); - PyObject* (__stdcall *PyImport_ImportModule)(const char *name); - void(__stdcall *PyEval_InitThreads)(); - PyThreadState* (__stdcall *PyEval_SaveThread)(); - void(__stdcall *PyEval_RestoreThread)(PyThreadState *tstate); - PyThreadState* (__stdcall *PyThreadState_Swap)(PyThreadState *tstate); - PyObject* (__stdcall *PyRun_String)(const char *str, int start, PyObject *globals, PyObject *locals); - int(__stdcall *PyRun_SimpleString)(const char* str); - PyObject* (__stdcall *PyRun_File)(FILE *fp, const char *filename, int start, PyObject *globals, PyObject *locals); - PyObject* (__stdcall *PyDict_New)(); - int(__stdcall *PyDict_SetItemString)(PyObject *p, const char *key, PyObject *val); - PyObject*(__stdcall *PyDict_GetItemString)(PyObject *p, const char* key); - void(__stdcall *Py_IncRef)(PyObject* object); - void(__stdcall *Py_DecRef)(PyObject* object); - PyObject* (__stdcall *PyObject_Call)(PyObject *callable_object, PyObject *args, PyObject *kw); - PyObject* (__stdcall *PyObject_GetAttr)(PyObject *object, PyObject *attr_name); - PyObject* (__stdcall *PyObject_GetAttrString)(PyObject *object, const char *attr_name); - int(__stdcall *PyObject_SetAttr)(PyObject *object, PyObject *attr_name, PyObject *value); - PyObject* (__stdcall *PyObject_CallObject)(PyObject *callable_object, PyObject *args); - PyObject* (__stdcall *PyTuple_New)(size_t len); - int(__stdcall *PyTuple_SetItem)(PyObject *p, size_t pos, PyObject *o); - PyObject* (__stdcall *PyTuple_GetItem)(PyObject *p, size_t pos); - size_t(__stdcall *PyTuple_Size)(PyObject *p); - PyObject* (__stdcall *PyCFunction_NewEx)(PyMethodDef *, PyObject *, PyObject *); - PyObject* (__stdcall *PySys_GetObject)(char *name); - int(__stdcall *PySys_SetObject)(char *name, PyObject *v); - void(__stdcall *PySys_SetArgv)(int argc, char **argv); - void(__stdcall *PySys_SetArgv_Py3)(int argc, wchar_t **argv); - PyObject* (__stdcall *PyString_FromString)(const char *v); - char* (__stdcall *PyString_AsString)(PyObject *string); - void(__stdcall *PyErr_Fetch)(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback); - void(__stdcall *PyErr_NormalizeException)(PyObject**exc, PyObject**val, PyObject**tb); - void(__stdcall *PyErr_SetString)(PyObject *type, const char *message); - void(__stdcall *PyErr_Clear)(); - PyObject* (__stdcall *PyImport_AddModule)(const char *name); - PyObject* (__stdcall *PyClass_New)(PyObject* className, PyObject* classBases, PyObject* classDict); - PyObject* (__stdcall *PyInstance_New)(PyObject *classobj, PyObject *arg, PyObject *kw); - PyObject* (__stdcall *PyMethod_New)(PyObject *func, PyObject *self, PyObject *classobj); - PyObject* (__stdcall *PyCapsule_New)(void *pointer, const char *name, PyCapsule_Destructor destructor); - void* (__stdcall *PyCapsule_GetPointer)(PyObject *capsule, const char *name); - int(__stdcall *PyObject_SetAttrString)(PyObject *o, const char *attr_name, PyObject *v); - PyObject* (__stdcall *PyUnicode_FromWideChar)(const wchar_t *w, size_t size); - PyObject* (__stdcall *PyBool_FromLong)(long v); - size_t(__stdcall *PyList_Size)(PyObject* list); - PyObject* (__stdcall *PyList_GetItem)(PyObject *list, size_t index); - PyObject* (__stdcall *PyFile_FromString)(char *filename, char *mode); - FILE* (__stdcall *PyFile_AsFile)(PyObject *pyfile); - PyObject* (__stdcall *PyUnicode_FromString)(const char *u); - PyObject* (__stdcall *PyInstanceMethod_New)(PyObject *func); - size_t(__stdcall *PyUnicode_AsWideChar)(PyObject *unicode, wchar_t *w, size_t size); - FILE* ( __stdcall *_Py_fopen)(const char* filename, const char* mode); - int(__stdcall *Py_AddPendingCall)(int(*func)(void *), void *arg); - PyGILState_STATE(__stdcall *PyGILState_Ensure)(); - void(__stdcall *PyGILState_Release)(PyGILState_STATE state); - PyObject* (__stdcall *PyDescr_NewMethod)(PyObject* type, struct PyMethodDef *meth); + PyThreadState* ( *Py_NewInterpreter)(); + void( *Py_EndInterpreter)(PyThreadState *tstate); + PyObject* ( *PyEval_GetGlobals)(); + PyObject* ( *PyImport_Import)(PyObject *name); + PyObject* ( *PyImport_ImportModule)(const char *name); + void( *PyEval_InitThreads)(); + PyThreadState* ( *PyEval_SaveThread)(); + void( *PyEval_RestoreThread)(PyThreadState *tstate); + PyThreadState* ( *PyThreadState_Swap)(PyThreadState *tstate); + PyObject* ( *PyRun_String)(const char *str, int start, PyObject *globals, PyObject *locals); + int( *PyRun_SimpleString)(const char* str); + PyObject* ( *PyRun_File)(FILE *fp, const char *filename, int start, PyObject *globals, PyObject *locals); + PyObject* ( *PyDict_New)(); + int( *PyDict_SetItemString)(PyObject *p, const char *key, PyObject *val); + PyObject*( *PyDict_GetItemString)(PyObject *p, const char* key); + void( *Py_IncRef)(PyObject* object); + void( *Py_DecRef)(PyObject* object); + PyObject* ( *PyObject_Call)(PyObject *callable_object, PyObject *args, PyObject *kw); + PyObject* ( *PyObject_GetAttr)(PyObject *object, PyObject *attr_name); + PyObject* ( *PyObject_GetAttrString)(PyObject *object, const char *attr_name); + int( *PyObject_SetAttr)(PyObject *object, PyObject *attr_name, PyObject *value); + PyObject* ( *PyObject_CallObject)(PyObject *callable_object, PyObject *args); + PyObject* ( *PyTuple_New)(size_t len); + int( *PyTuple_SetItem)(PyObject *p, size_t pos, PyObject *o); + PyObject* ( *PyTuple_GetItem)(PyObject *p, size_t pos); + size_t( *PyTuple_Size)(PyObject *p); + PyObject* ( *PyCFunction_NewEx)(PyMethodDef *, PyObject *, PyObject *); + PyObject* ( *PySys_GetObject)(char *name); + int( *PySys_SetObject)(char *name, PyObject *v); + void( *PySys_SetArgv)(int argc, char **argv); + void( *PySys_SetArgv_Py3)(int argc, wchar_t **argv); + PyObject* ( *PyString_FromString)(const char *v); + char* ( *PyString_AsString)(PyObject *string); + void( *PyErr_Fetch)(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback); + void( *PyErr_NormalizeException)(PyObject**exc, PyObject**val, PyObject**tb); + void( *PyErr_SetString)(PyObject *type, const char *message); + void( *PyErr_Clear)(); + PyObject* ( *PyImport_AddModule)(const char *name); + PyObject* ( *PyClass_New)(PyObject* className, PyObject* classBases, PyObject* classDict); + PyObject* ( *PyInstance_New)(PyObject *classobj, PyObject *arg, PyObject *kw); + PyObject* ( *PyMethod_New)(PyObject *func, PyObject *self, PyObject *classobj); + PyObject* ( *PyCapsule_New)(void *pointer, const char *name, PyCapsule_Destructor destructor); + void* ( *PyCapsule_GetPointer)(PyObject *capsule, const char *name); + int( *PyObject_SetAttrString)(PyObject *o, const char *attr_name, PyObject *v); + PyObject* ( *PyUnicode_FromWideChar)(const wchar_t *w, size_t size); + PyObject* ( *PyBool_FromLong)(long v); + size_t( *PyList_Size)(PyObject* list); + PyObject* ( *PyList_GetItem)(PyObject *list, size_t index); + PyObject* ( *PyFile_FromString)(char *filename, char *mode); + FILE* ( *PyFile_AsFile)(PyObject *pyfile); + PyObject* ( *PyUnicode_FromString)(const char *u); + PyObject* ( *PyInstanceMethod_New)(PyObject *func); + size_t( *PyUnicode_AsWideChar)(PyObject *unicode, wchar_t *w, size_t size); + FILE* ( *_Py_fopen)(const char* filename, const char* mode); + int( *Py_AddPendingCall)(int(*func)(void *), void *arg); + PyGILState_STATE( *PyGILState_Ensure)(); + void( *PyGILState_Release)(PyGILState_STATE state); + PyObject* ( *PyDescr_NewMethod)(PyObject* type, struct PyMethodDef *meth); HMODULE m_handlePython; PyThreadState* m_globalState; @@ -261,8 +263,37 @@ private: std::auto_ptr PythonSingleton::m_singleton; +HMODULE LoadPythonForKey(HKEY installPathKey, int majorVersion, int minorVersion) +{ -HMODULE LoadPythonLibrary(int majorVesion, int minorVersion) + HMODULE hmodule = NULL; + + char installPath[1000]; + DWORD installPathSize = sizeof(installPath); + + if (ERROR_SUCCESS == RegQueryValueExA(installPathKey, NULL, NULL, NULL, (LPBYTE)installPath, &installPathSize)) + { + std::stringstream dllName; + dllName << "python" << majorVersion << minorVersion << ".dll"; + + std::stringstream imagePath; + imagePath << installPath << dllName.str(); + + hmodule = LoadLibraryExA(imagePath.str().c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (hmodule) + return hmodule; + + hmodule = LoadLibraryA(dllName.str().c_str()); + if (hmodule) + return hmodule; + + } + + return NULL; +} + + +HMODULE LoadPythonLibrary(int majorVersion, int minorVersion) { HKey pythonCoreKey; @@ -274,29 +305,26 @@ HMODULE LoadPythonLibrary(int majorVesion, int minorVersion) HKey installPathKey; std::stringstream installPathStr; - installPathStr << majorVesion << '.' << minorVersion << "\\InstallPath"; + + if (majorVersion == 2 || (majorVersion == 3 && minorVersion <= 4)) + { + installPathStr << majorVersion << '.' << minorVersion << "\\InstallPath"; + } + else + if (majorVersion == 3 && minorVersion >= 5) + { +#ifdef _M_X64 + installPathStr << majorVersion << '.' << minorVersion << "\\InstallPath"; +#else + installPathStr << majorVersion << '.' << minorVersion << "-32" << "\\InstallPath"; +#endif + } if (ERROR_SUCCESS == RegOpenKeyA(pythonCoreKey, installPathStr.str().c_str(), installPathKey)) { - char installPath[1000]; - DWORD installPathSize = sizeof(installPath); - - if (ERROR_SUCCESS == RegQueryValueExA(installPathKey, NULL, NULL, NULL, (LPBYTE)installPath, &installPathSize)) - { - std::stringstream dllName; - dllName << "python" << majorVesion << minorVersion << ".dll"; - - HMODULE hmodule = LoadLibraryA(dllName.str().c_str()); - if (hmodule) - return hmodule; - - std::stringstream imagePath; - imagePath << installPath << dllName.str(); - - hmodule = LoadLibraryExA(imagePath.str().c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - if (hmodule) - return hmodule; - } + HMODULE hmodule = LoadPythonForKey(installPathKey, majorVersion, minorVersion); + if (hmodule) + return hmodule; } } } @@ -304,14 +332,17 @@ HMODULE LoadPythonLibrary(int majorVesion, int minorVersion) return NULL; } + + + std::list getInstalledInterpreter() { - std::list lst; + std::set interpretSet; - for (auto rootKey : std::list({ HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER })) + for (auto rootKey : const std::list({ HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER })) { HKey pythonCoreKey; - + if (ERROR_SUCCESS != RegOpenKeyA(rootKey, "SOFTWARE\\Python\\PythonCore", pythonCoreKey)) continue; @@ -321,25 +352,39 @@ std::list getInstalledInterpreter() if (ERROR_SUCCESS != RegEnumKeyA(pythonCoreKey, i, versionStr, sizeof(versionStr))) break; - int majorVersion, minorVersion; - + int majorVersion = -1, minorVersion = -1; sscanf_s(versionStr, "%d.%d", &majorVersion, &minorVersion); - HMODULE hmodule = LoadPythonLibrary(majorVersion, minorVersion); + HKey installPathKey; + std::string installPathStr(versionStr); + installPathStr += "\\InstallPath"; + if (ERROR_SUCCESS != RegOpenKeyA(pythonCoreKey, installPathStr.c_str(), installPathKey)) + continue; + + HMODULE hmodule = LoadPythonForKey(installPathKey, majorVersion, minorVersion); + if (hmodule) { char fullPath[1000]; - + if (GetModuleFileNameA(hmodule, fullPath, sizeof(fullPath))) - lst.push_back({ majorVersion, minorVersion, fullPath }); - + { + interpretSet.insert({ majorVersion, minorVersion, fullPath }); + } + FreeLibrary(hmodule); } } } - return lst; + std::list interpretLst; + + std::copy(interpretSet.begin(), interpretSet.end(), std::inserter(interpretLst, interpretLst.begin())); + + interpretLst.sort(); + + return interpretLst; } PyModule::PyModule(int majorVesion, int minorVersion) diff --git a/pykd_ext/pyinterpret.h b/pykd_ext/pyinterpret.h index 5ec828f..49f10b8 100644 --- a/pykd_ext/pyinterpret.h +++ b/pykd_ext/pyinterpret.h @@ -18,6 +18,17 @@ struct InterpreterDesc { std::string imagePath; }; +inline bool operator < (const InterpreterDesc& d1, const InterpreterDesc& d2) +{ + if (d1.majorVersion != d2.majorVersion) + return d1.majorVersion < d2.majorVersion; + + if (d1.minorVersion != d2.minorVersion) + return d1.minorVersion < d2.minorVersion; + + return d1.imagePath < d2.imagePath; +} + std::list getInstalledInterpreter(); bool isInterpreterLoaded(int majorVersion, int minorVersion); diff --git a/pykd_ext/windbgext.cpp b/pykd_ext/windbgext.cpp index 1df444e..f827815 100644 --- a/pykd_ext/windbgext.cpp +++ b/pykd_ext/windbgext.cpp @@ -538,13 +538,36 @@ void getPythonVersion(int& majorVersion, int& minorVersion) bool found = false; bool anyMinorVersion = minorVersion == -1; + bool anyMajorVersion = majorVersion == -1; + + if (anyMajorVersion) + { + for (auto interpret : interpreterList) + { + + if (2 == interpret.majorVersion && + anyMinorVersion ? (minorVersion <= interpret.minorVersion) : (minorVersion == interpret.minorVersion)) + { + found = true; + minorVersion = interpret.minorVersion; + } + } + + if (found) + { + majorVersion = 2; + return; + } + } + for (auto interpret : interpreterList) { - if (majorVersion == interpret.majorVersion && + if (anyMajorVersion ? (majorVersion <= interpret.majorVersion) : (majorVersion==interpret.majorVersion) && anyMinorVersion ? (minorVersion <= interpret.minorVersion) : (minorVersion == interpret.minorVersion)) { found = true; minorVersion = interpret.minorVersion; + majorVersion = interpret.majorVersion; } }