diff --git a/pykd-0.3-2013.sln b/pykd-0.3-2013.sln
index d6975e3..b9e471d 100644
--- a/pykd-0.3-2013.sln
+++ b/pykd-0.3-2013.sln
@@ -45,6 +45,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{D1F122
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "targetapp", "kdlibcpp\tests\targetapp\targetapp_vc120.vcxproj", "{0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pykd_bootstrapper", "pykd_bootstrapper\pykd_bootstrapper_vc120.vcxproj", "{CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_2.7|Any CPU = Debug_2.7|Any CPU
@@ -222,6 +224,34 @@ Global
{0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release|Win32.Build.0 = Release|Win32
{0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release|x64.ActiveCfg = Release|x64
{0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release|x64.Build.0 = Release|x64
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug_2.7|Any CPU.ActiveCfg = Debug_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug_2.7|Mixed Platforms.ActiveCfg = Debug_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug_2.7|Mixed Platforms.Build.0 = Debug_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug_2.7|Win32.ActiveCfg = Debug_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug_2.7|Win32.Build.0 = Debug_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug_2.7|x64.ActiveCfg = Debug_2.7|x64
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug_2.7|x64.Build.0 = Debug_2.7|x64
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug|Any CPU.ActiveCfg = Debug_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug|Mixed Platforms.ActiveCfg = Debug_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug|Mixed Platforms.Build.0 = Debug_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug|Win32.ActiveCfg = Debug_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug|Win32.Build.0 = Debug_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug|x64.ActiveCfg = Debug_2.7|x64
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Debug|x64.Build.0 = Debug_2.7|x64
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release_2.7|Any CPU.ActiveCfg = Release_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release_2.7|Mixed Platforms.ActiveCfg = Release_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release_2.7|Mixed Platforms.Build.0 = Release_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release_2.7|Win32.ActiveCfg = Release_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release_2.7|Win32.Build.0 = Release_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release_2.7|x64.ActiveCfg = Debug_2.7|x64
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release_2.7|x64.Build.0 = Debug_2.7|x64
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release|Any CPU.ActiveCfg = Release_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release|Mixed Platforms.ActiveCfg = Release_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release|Mixed Platforms.Build.0 = Release_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release|Win32.ActiveCfg = Release_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release|Win32.Build.0 = Release_2.7|Win32
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release|x64.ActiveCfg = Release_2.7|x64
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}.Release|x64.Build.0 = Release_2.7|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/pykd/pykd_vc120.vcxproj b/pykd/pykd_vc120.vcxproj
index c94a038..75d2284 100644
--- a/pykd/pykd_vc120.vcxproj
+++ b/pykd/pykd_vc120.vcxproj
@@ -75,19 +75,23 @@
true
.pyd
true
+ $(ProjectName)
true
.pyd
true
+ $(ProjectName)
false
.pyd
+ $(ProjectName)
false
.pyd
+ $(ProjectName)
diff --git a/pykd_bootstrapper/dllmain.cpp b/pykd_bootstrapper/dllmain.cpp
new file mode 100644
index 0000000..8a4edd3
--- /dev/null
+++ b/pykd_bootstrapper/dllmain.cpp
@@ -0,0 +1,19 @@
+// dllmain.cpp : Defines the entry point for the DLL application.
+#include "stdafx.h"
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
diff --git a/pykd_bootstrapper/export.def b/pykd_bootstrapper/export.def
new file mode 100644
index 0000000..49bb1e9
--- /dev/null
+++ b/pykd_bootstrapper/export.def
@@ -0,0 +1,4 @@
+EXPORTS
+ DebugExtensionInitialize
+ DebugExtensionUninitialize
+ py
diff --git a/pykd_bootstrapper/packages.pykd_bootstrapper_vc120.config b/pykd_bootstrapper/packages.pykd_bootstrapper_vc120.config
new file mode 100644
index 0000000..26eab34
--- /dev/null
+++ b/pykd_bootstrapper/packages.pykd_bootstrapper_vc120.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pykd_bootstrapper/pykd_bootstrapper_vc120.vcxproj b/pykd_bootstrapper/pykd_bootstrapper_vc120.vcxproj
new file mode 100644
index 0000000..49e44c1
--- /dev/null
+++ b/pykd_bootstrapper/pykd_bootstrapper_vc120.vcxproj
@@ -0,0 +1,220 @@
+
+
+
+
+ Debug_2.7
+ Win32
+
+
+ Debug_2.7
+ x64
+
+
+ Release_2.7
+ Win32
+
+
+ Release_2.7
+ x64
+
+
+
+ {CA0252CE-EF81-4DD8-A96F-A0E0E3644B7B}
+ Win32Proj
+ pykd_bootstrapper
+ pykd_ext
+ ..\
+ true
+
+
+
+ DynamicLibrary
+ true
+ v120
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v120
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v120
+ true
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v120
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 7f4aed3e
+
+
+ true
+ pykd
+
+
+ true
+ pykd
+
+
+ false
+ pykd
+
+
+ false
+ pykd
+
+
+
+ Use
+ Level3
+ Disabled
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;PYKD_BOOTSTRAPPER_EXPORTS;%(PreprocessorDefinitions)
+ true
+ $(ProjectDir)..\kdlibcpp\include;
+
+
+ Windows
+ true
+ export.def
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+
+
+ Use
+ Level3
+ Disabled
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;PYKD_BOOTSTRAPPER_EXPORTS;%(PreprocessorDefinitions)
+ true
+ $(ProjectDir)..\kdlibcpp\include;
+
+
+ Windows
+ true
+ export.def
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+
+
+ Level3
+ Use
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;PYKD_BOOTSTRAPPER_EXPORTS;%(PreprocessorDefinitions)
+ true
+ $(ProjectDir)..\kdlibcpp\include;
+ MultiThreaded
+
+
+ Windows
+ true
+ true
+ true
+ export.def
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+
+
+ Level3
+ Use
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;PYKD_BOOTSTRAPPER_EXPORTS;%(PreprocessorDefinitions)
+ true
+ $(ProjectDir)..\kdlibcpp\include;
+ MultiThreaded
+
+
+ Windows
+ true
+ true
+ true
+ export.def
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+
+
+
+
+
+
+
+
+
+ false
+ false
+
+
+
+
+ false
+ false
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
+
+
+ {3e9c538f-f060-4e86-ab7d-d44439615b63}
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pykd_bootstrapper/pykd_bootstrapper_vc120.vcxproj.filters b/pykd_bootstrapper/pykd_bootstrapper_vc120.vcxproj.filters
new file mode 100644
index 0000000..f1936f5
--- /dev/null
+++ b/pykd_bootstrapper/pykd_bootstrapper_vc120.vcxproj.filters
@@ -0,0 +1,130 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Source Files
+
+
+
+
+
\ No newline at end of file
diff --git a/pykd_bootstrapper/stdafx.cpp b/pykd_bootstrapper/stdafx.cpp
new file mode 100644
index 0000000..75c83a9
--- /dev/null
+++ b/pykd_bootstrapper/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// pykd_bootstrapper.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/pykd_bootstrapper/stdafx.h b/pykd_bootstrapper/stdafx.h
new file mode 100644
index 0000000..677e68a
--- /dev/null
+++ b/pykd_bootstrapper/stdafx.h
@@ -0,0 +1,16 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+// Windows Header Files:
+#include
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/pykd_bootstrapper/targetver.h b/pykd_bootstrapper/targetver.h
new file mode 100644
index 0000000..90e767b
--- /dev/null
+++ b/pykd_bootstrapper/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include
diff --git a/pykd_bootstrapper/windbgext.cpp b/pykd_bootstrapper/windbgext.cpp
new file mode 100644
index 0000000..e5c91e9
--- /dev/null
+++ b/pykd_bootstrapper/windbgext.cpp
@@ -0,0 +1,459 @@
+#include "stdafx.h"
+
+#include
+
+namespace python = boost::python;
+
+#include "kdlib/windbg.h"
+
+using namespace kdlib;
+
+///////////////////////////////////////////////////////////////////////////////
+
+class PykdBootsTrapper: public windbg::WindbgExtension
+{
+public:
+
+ KDLIB_EXT_COMMAND_METHOD(py);
+
+ virtual void setUp();
+
+ virtual void tearDown();
+
+private:
+
+ void startConsole();
+
+ void printUsage();
+
+ void printException();
+
+ std::string getScriptFileName(const std::string &scriptName);
+
+ std::string findScript(const std::string &fullFileName);
+
+ PyThreadState *m_pyState;
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class AutoRestorePyState
+{
+public:
+
+ AutoRestorePyState()
+ {
+ m_state = PyEval_SaveThread();
+ }
+
+ explicit AutoRestorePyState(PyThreadState **state)
+ {
+ *state = PyEval_SaveThread();
+ m_state = *state;
+ }
+
+ ~AutoRestorePyState()
+ {
+ PyEval_RestoreThread(m_state);
+ }
+
+private:
+
+ PyThreadState* m_state;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class DbgOut : public windbg::WindbgOut
+{
+public:
+
+ virtual void write(const std::wstring& str) {
+ AutoRestorePyState pystate;
+ windbg::WindbgOut::write(str);
+ }
+
+ virtual void writedml(const std::wstring& str) {
+ AutoRestorePyState pystate;
+ windbg::WindbgOut::writedml(str);
+ }
+
+ void flush() {
+ }
+
+ std::wstring encoding() {
+ return L"ascii";
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class DbgIn : public windbg::WindbgIn
+{
+public:
+
+ std::wstring readline() {
+ AutoRestorePyState pystate;
+ return kdlib::windbg::WindbgIn::readline();
+ }
+
+ std::wstring encoding() {
+ return L"ascii";
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class InterruptWatch : public windbg::InterruptWatch
+{
+ virtual bool onInterrupt()
+ {
+ HANDLE quitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ PyGILState_STATE state = PyGILState_Ensure();
+ Py_AddPendingCall(&quit, (void*)quitEvent);
+ PyGILState_Release(state);
+ WaitForSingleObject(quitEvent, INFINITE);
+ CloseHandle(quitEvent);
+ return true;
+ }
+
+ static int quit(void *context)
+ {
+ HANDLE quitEvent = (HANDLE)context;
+ kdlib::eprintln(L"User Interrupt: CTRL+BREAK");
+ PyErr_SetString(PyExc_SystemExit, "CTRL+BREAK");
+ SetEvent(quitEvent);
+ return -1;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+KDLIB_WINDBG_EXTENSION_INIT(PykdBootsTrapper);
+
+KDLIB_EXT_COMMAND_METHOD_IMPL(PykdBootsTrapper, py)
+{
+ ArgsList args = getArgs();
+
+ bool global = false;
+ bool local = false;
+ bool clean = false;
+
+ ArgsList::iterator foundArg;
+
+ if (!args.empty())
+ {
+ if (args[0] == "-h" || args[0] == "--help")
+ {
+ printUsage();
+ return;
+ }
+ else
+ if (args[0] == "-g" || args[0] == "--global")
+ {
+ global = true;
+ args.erase(args.begin());
+ }
+ else
+ if (args[0] == "-l" || args[0] == "--local")
+ {
+ local = true;
+ args.erase(args.begin());
+ }
+ }
+
+ PyThreadState *localState = NULL;
+ PyThreadState *globalState = NULL;
+
+ PyEval_RestoreThread(m_pyState);
+
+ std::string scriptFileName;
+ if (args.size() > 0)
+ {
+ scriptFileName = getScriptFileName(args[0]);
+
+ if (scriptFileName.empty())
+ {
+ kdlib::eprintln(L"script file not found");
+ return;
+ }
+
+ global = !(global || local) ? false : global; //set local by default
+ }
+ else
+ {
+ global = !(global || local) ? true : global; //set global by default
+ }
+
+ if (!global)
+ {
+ globalState = PyThreadState_Swap(NULL);
+
+ Py_NewInterpreter();
+
+ localState = PyThreadState_Get();
+
+ python::object sys = python::import("sys");
+
+ sys.attr("stdout") = python::object(::DbgOut());
+ sys.attr("stderr") = python::object(::DbgOut());
+ sys.attr("stdin") = python::object(::DbgIn());
+ }
+
+ if (args.size() == 0)
+ {
+ startConsole();
+ }
+ else
+ {
+ std::string scriptFileName = getScriptFileName(args[0]);
+
+ // óñòàíàâèëèâàåì ïèòîíîâñêèå àðãóìåíòû
+ char **pythonArgs = new char*[args.size()];
+
+ pythonArgs[0] = const_cast(scriptFileName.c_str());
+
+ for (size_t i = 1; i < args.size(); ++i)
+ pythonArgs[i] = const_cast(args[i].c_str());
+
+ PySys_SetArgv((int)args.size(), pythonArgs);
+
+ delete[] pythonArgs;
+
+ // ïîëó÷àåì äîñòïó ê ãëîáàëüíîìó ìàïó ( íóæåí äëÿ âûçîâà exec_file )
+ python::object main = python::import("__main__");
+
+ python::object global(main.attr("__dict__"));
+
+ try {
+ InterruptWatch interruptWatch;
+
+ python::exec_file(scriptFileName.c_str(), global);
+ }
+ catch (python::error_already_set const &)
+ {
+ printException();
+ }
+ }
+
+ if (!global)
+ {
+ PyInterpreterState *interpreter = localState->interp;
+
+ while (interpreter->tstate_head != NULL)
+ {
+ PyThreadState *threadState = (PyThreadState*)(interpreter->tstate_head);
+
+ PyThreadState_Clear(threadState);
+
+ PyThreadState_Swap(NULL);
+
+ PyThreadState_Delete(threadState);
+ }
+
+ PyInterpreterState_Clear(interpreter);
+
+ PyInterpreterState_Delete(interpreter);
+
+ PyThreadState_Swap(globalState);
+ }
+
+ m_pyState = PyEval_SaveThread();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void PykdBootsTrapper::setUp()
+{
+ WindbgExtension::setUp();
+
+ PyEval_InitThreads();
+
+ Py_Initialize();
+
+ python::object main = boost::python::import("__main__");
+
+ python::object main_namespace = main.attr("__dict__");
+
+ python::object pykd = python::import("pykd");
+
+ // äåëàåì àíàëîã from pykd import *
+ python::dict pykd_namespace(pykd.attr("__dict__"));
+
+ python::list iterkeys(pykd_namespace.iterkeys());
+
+ for (int i = 0; i < boost::python::len(iterkeys); i++)
+ {
+ std::string key = boost::python::extract(iterkeys[i]);
+
+ main_namespace[key] = pykd_namespace[key];
+ }
+
+ // Python debug output console helper classes
+ python::class_<::DbgOut>("dout", "dout", python::no_init)
+ .def("write", &::DbgOut::write)
+ .def("flush", &::DbgOut::flush)
+ .add_property("encoding", &::DbgOut::encoding);
+
+ python::class_<::DbgIn>("din", "din", python::no_init)
+ .def("readline", &::DbgIn::readline)
+ .add_property("encoding", &::DbgIn::encoding);
+
+ python::object sys = python::import("sys");
+
+ sys.attr("stdout") = python::object(::DbgOut());
+ sys.attr("stderr") = python::object(::DbgOut());
+ sys.attr("stdin") = python::object(::DbgIn());
+
+ m_pyState = PyEval_SaveThread();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void PykdBootsTrapper::tearDown()
+{
+ PyEval_RestoreThread(m_pyState);
+
+ Py_Finalize();
+
+ WindbgExtension::tearDown();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void PykdBootsTrapper::startConsole()
+{
+
+ // ïîëó÷àåì äîñòóï ê ãëîáàëüíîìó ìàïó ( íóæåí äëÿ âûçîâà exec_file )
+ python::object main = python::import("__main__");
+
+ python::object global(main.attr("__dict__"));
+
+ try {
+ InterruptWatch interruptWatch;
+
+ python::exec("__import__('code').InteractiveConsole(__import__('__main__').__dict__).interact()\n", global);
+ }
+ catch (python::error_already_set const &)
+ {
+ printException();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void PykdBootsTrapper::printUsage()
+{
+ kdlib::dprintln(L"usage: !py [options] [file]");
+ kdlib::dprintln(L"Options:");
+ kdlib::dprintln(L"-g --global : run code in the common namespace");
+ kdlib::dprintln(L"-l --local : run code in the isolate namespace");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+std::string PykdBootsTrapper::getScriptFileName(const std::string &scriptName)
+{
+ std::string scriptFileName = findScript(scriptName);
+
+ if (scriptFileName.empty())
+ {
+ std::string scriptNameLow;
+ scriptNameLow.resize(scriptName.size());
+ std::transform(
+ scriptName.begin(),
+ scriptName.end(),
+ scriptNameLow.begin(),
+ ::tolower);
+ if (scriptNameLow.rfind(".py") != (scriptNameLow.length() - 3))
+ scriptFileName = findScript(scriptName + ".py");
+ }
+
+ return scriptFileName;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+std::string PykdBootsTrapper::findScript(const std::string &fullFileName)
+{
+ if (GetFileAttributesA(fullFileName.c_str()) != INVALID_FILE_ATTRIBUTES)
+ return fullFileName;
+
+ python::object sys = python::import("sys");
+
+ python::list pathList(sys.attr("path"));
+
+ python::ssize_t n = python::len(pathList);
+
+ for (python::ssize_t i = 0; i < n; i++)
+ {
+ std::string path = boost::python::extract(pathList[i]);
+
+ DWORD bufSize = SearchPathA(
+ path.c_str(),
+ fullFileName.c_str(),
+ NULL,
+ 0,
+ NULL,
+ NULL);
+
+ if (bufSize > 0)
+ {
+ bufSize += 1;
+ std::vector fullFileNameCStr(bufSize);
+ char *partFileNameCStr = NULL;
+
+ bufSize = SearchPathA(
+ path.c_str(),
+ fullFileName.c_str(),
+ NULL,
+ bufSize,
+ &fullFileNameCStr[0],
+ &partFileNameCStr);
+
+ if (bufSize > 0)
+ {
+ return std::string(&fullFileNameCStr[0]);
+ }
+ }
+ }
+
+ return "";
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+void PykdBootsTrapper::printException()
+{
+ // îøèáêà â ñêðèïòå
+ PyObject *errtype = NULL, *errvalue = NULL, *traceback = NULL;
+
+ PyErr_Fetch(&errtype, &errvalue, &traceback);
+
+ PyErr_NormalizeException(&errtype, &errvalue, &traceback);
+
+ if (errtype == PyExc_SystemExit)
+ return;
+
+ python::object tracebackModule = python::import("traceback");
+
+ std::wstringstream sstr;
+
+ python::object lst =
+ python::object(tracebackModule.attr("format_exception"))(
+ python::handle<>(errtype),
+ python::handle<>(python::allow_null(errvalue)),
+ python::handle<>(python::allow_null(traceback)));
+
+ sstr << std::endl << std::endl;
+
+ for (long i = 0; i < python::len(lst); ++i)
+ sstr << std::wstring(python::extract(lst[i])) << std::endl;
+
+ kdlib::eprintln(sstr.str());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+