diff --git a/pykd/pydbgeng.h b/pykd/pydbgeng.h
index f9548e0..c3dca93 100644
--- a/pykd/pydbgeng.h
+++ b/pykd/pydbgeng.h
@@ -304,6 +304,13 @@ kdlib::ExecutionStatus targetStepIn()
     return kdlib::targetStepIn();
 }
 
+inline
+kdlib::ExecutionStatus targetStepOut()
+{
+    AutoRestorePyState  pystate;
+    return kdlib::targetStepOut();
+}
+
 inline
 kdlib::ExecutionStatus targetExecutionStatus()
 {
@@ -311,6 +318,21 @@ kdlib::ExecutionStatus targetExecutionStatus()
     return kdlib::targetExecutionStatus();
 }
 
+inline
+kdlib::ExecutionStatus sourceStep()
+{
+    AutoRestorePyState  pystate;
+    return kdlib::sourceStepIn();
+}
+
+inline
+kdlib::ExecutionStatus sourceStepOver()
+{
+    AutoRestorePyState  pystate;
+    return kdlib::sourceStepOver();
+}
+
+
 ///////////////////////////////////////////////////////////////////////////////
 // system properties
 
diff --git a/pykd/pyeventhandler.cpp b/pykd/pyeventhandler.cpp
index 9a94222..7276a94 100644
--- a/pykd/pyeventhandler.cpp
+++ b/pykd/pyeventhandler.cpp
@@ -242,6 +242,108 @@ kdlib::DebugCallbackResult  EventHandler::onModuleUnload( kdlib::MEMOFFSET_64 of
 
 /////////////////////////////////////////////////////////////////////////////////
 
+kdlib::DebugCallbackResult EventHandler::onThreadStart()
+{
+    kdlib::DebugCallbackResult  result = kdlib::DebugCallbackNoChange;
+
+    PyEval_RestoreThread(m_pystate);
+
+    try {
+
+        do {
+
+            python::override pythonHandler = get_override("onThreadStart");
+            if (!pythonHandler)
+            {
+                result = kdlib::EventHandler::onThreadStart();
+                break;
+            }
+
+            python::object  resObj = pythonHandler();
+
+            if (resObj.is_none())
+            {
+                result = kdlib::DebugCallbackNoChange;
+                break;
+            }
+
+            int retVal = python::extract<int>(resObj);
+
+            if (retVal >= kdlib::DebugCallbackMax)
+            {
+                result = kdlib::DebugCallbackBreak;
+                break;
+            }
+
+            result = kdlib::DebugCallbackResult(retVal);
+
+        } while (FALSE);
+
+    }
+    catch (const python::error_already_set &)
+    {
+        printException();
+        result = kdlib::DebugCallbackBreak;
+    }
+
+    m_pystate = PyEval_SaveThread();
+
+    return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+
+kdlib::DebugCallbackResult EventHandler::onThreadStop()
+{
+    kdlib::DebugCallbackResult  result = kdlib::DebugCallbackNoChange;
+
+    PyEval_RestoreThread(m_pystate);
+
+    try {
+
+        do {
+
+            python::override pythonHandler = get_override("onThreadStop");
+            if (!pythonHandler)
+            {
+                result = kdlib::EventHandler::onThreadStop();
+                break;
+            }
+
+            python::object  resObj = pythonHandler();
+
+            if (resObj.is_none())
+            {
+                result = kdlib::DebugCallbackNoChange;
+                break;
+            }
+
+            int retVal = python::extract<int>(resObj);
+
+            if (retVal >= kdlib::DebugCallbackMax)
+            {
+                result = kdlib::DebugCallbackBreak;
+                break;
+            }
+
+            result = kdlib::DebugCallbackResult(retVal);
+
+        } while (FALSE);
+
+    }
+    catch (const python::error_already_set &)
+    {
+        printException();
+        result = kdlib::DebugCallbackBreak;
+    }
+
+    m_pystate = PyEval_SaveThread();
+
+    return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+
 void EventHandler::onCurrentThreadChange(kdlib::THREAD_DEBUG_ID  threadid)
 {
     PyEval_RestoreThread( m_pystate );
diff --git a/pykd/pyeventhandler.h b/pykd/pyeventhandler.h
index e5db4c7..2e08b50 100644
--- a/pykd/pyeventhandler.h
+++ b/pykd/pyeventhandler.h
@@ -29,15 +29,20 @@ public:
     EventHandler();
 
     virtual kdlib::DebugCallbackResult onBreakpoint( kdlib::BREAKPOINT_ID bpId );
-    virtual void onExecutionStatusChange( kdlib::ExecutionStatus executionStatus );
     virtual kdlib::DebugCallbackResult onException( const kdlib::ExceptionInfo &exceptionInfo );
     virtual kdlib::DebugCallbackResult onModuleLoad( kdlib::MEMOFFSET_64 offset, const std::wstring &name );
     virtual kdlib::DebugCallbackResult onModuleUnload( kdlib::MEMOFFSET_64 offset, const std::wstring &name );
+    virtual kdlib::DebugCallbackResult onThreadStart();
+    virtual kdlib::DebugCallbackResult onThreadStop();
+
+    virtual void onExecutionStatusChange(kdlib::ExecutionStatus executionStatus);
     virtual void onCurrentThreadChange(kdlib::THREAD_DEBUG_ID  threadid);
     virtual void onChangeLocalScope();
     virtual void onChangeBreakpoints();
     virtual void onDebugOutput(const std::wstring& text);
 
+
+
 private:
 
     PyThreadState*  m_pystate;
diff --git a/pykd/pykdver.h b/pykd/pykdver.h
index 84bb5db..d1aa436 100644
--- a/pykd/pykdver.h
+++ b/pykd/pykdver.h
@@ -2,7 +2,7 @@
 #define PYKD_VERSION_MAJOR      0
 #define PYKD_VERSION_MINOR      3
 #define PYKD_VERSION_SUBVERSION 0
-#define PYKD_VERSION_BUILDNO    18
+#define PYKD_VERSION_BUILDNO    19
 
 #define __VER_STR2__(x) #x
 #define __VER_STR1__(x) __VER_STR2__(x)
diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp
index be0dbdb..9dc0a66 100644
--- a/pykd/pymod.cpp
+++ b/pykd/pymod.cpp
@@ -186,6 +186,12 @@ BOOST_PYTHON_MODULE( pykd )
         "The target is executing a single instruction or--if that instruction is a subroutine call--subroutine" );
     python::def( "trace", pykd::targetStepIn,
         "The target is executing a single instruction" );
+    python::def("stepout", pykd::targetStepOut,
+        "The traget is executing while not returned from the current subroutine");
+    python::def("sourceStep", pykd::sourceStep,
+        "The target is executing a single source line");
+    python::def("sourceStepOver", pykd::sourceStepOver,
+        "The target is executing a single source line");
     python::def( "getExecutionStatus", pykd::targetExecutionStatus,
         "Return current execution status" );
 
@@ -969,7 +975,11 @@ BOOST_PYTHON_MODULE( pykd )
         .def("onChangeBreakpoints", &EventHandler::onChangeBreakpoints,
             "Breakpoints is changed for current process" )
         .def( "onDebugOutput", &EventHandler::onDebugOutput,
-            "Request debug output" );
+            "Request debug output" )
+        .def("onThreadStart", &EventHandler::onThreadStart,
+            "New thread is started in the current process" )
+        .def("onThreadStop", &EventHandler::onThreadStop,
+            "A thread is stopped in the current thread")
 
    //     .def( "onSymbolsLoaded", &EventHandlerWrap::onSymbolsLoaded,
    //         "Triggered debug symbols loaded. Parameter - module base or 0\n"