From ea4a18f54ba0b519e86203931ff58766c8c86375 Mon Sep 17 00:00:00 2001
From: "SND\\kernelnet_cp"
 <SND\kernelnet_cp@9b283d60-5439-405e-af05-b73fd8c4d996>
Date: Thu, 15 Sep 2011 14:16:20 +0000
Subject: [PATCH] [0.1.x] added : dbgClient class

git-svn-id: https://pykd.svn.codeplex.com/svn@69780 9b283d60-5439-405e-af05-b73fd8c4d996
---
 pykd/dbgclient.cpp                 | 88 ++++++++++++++++++++++++++++++
 pykd/dbgclient.h                   | 47 ++++++++++++++++
 pykd/dbgexcept.cpp                 |  5 ++
 pykd/dbgexcept.h                   | 40 ++++++++++++++
 pykd/dbgext.cpp                    | 24 ++++++--
 pykd/{dbgmodule.cpp => module.cpp} |  0
 pykd/{dbgmodule.h => module.h}     | 17 ++++++
 pykd/pykd.def                      |  2 -
 pykd/pykd_2008.vcproj              | 28 ++++++++++
 pykd/stdafx.h                      | 18 +++---
 test/scripts/basetest.py           | 13 +++--
 test/scripts/pykdtest.py           | 13 +++--
 test/targetapp/targetapp.vcproj    |  4 ++
 13 files changed, 275 insertions(+), 24 deletions(-)
 create mode 100644 pykd/dbgclient.cpp
 rename pykd/{dbgmodule.cpp => module.cpp} (100%)
 rename pykd/{dbgmodule.h => module.h} (89%)

diff --git a/pykd/dbgclient.cpp b/pykd/dbgclient.cpp
new file mode 100644
index 0000000..0d4e3c7
--- /dev/null
+++ b/pykd/dbgclient.cpp
@@ -0,0 +1,88 @@
+#include "stdafx.h"
+
+#include "dbgclient.h"
+#include <vector>
+
+using namespace pykd;
+
+///////////////////////////////////////////////////////////////////////////////////
+
+DebugClient::DebugClient()
+{
+    HRESULT    hres;
+    hres = DebugCreate( __uuidof(IDebugClient4), (void **)&m_client );
+    if ( FAILED( hres ) )
+        throw DbgException("DebugCreate failed");
+
+    hres = m_client->QueryInterface( __uuidof(IDebugControl4), (void**)&m_control );
+    if ( FAILED( hres ) )
+        throw DbgException("QueryInterface IDebugControl4  failed");     
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+void DebugClient::loadDump( const std::wstring &fileName )
+{
+    HRESULT     hres;
+     
+    hres = m_client->OpenDumpFileWide( fileName.c_str(), NULL );
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugClient4::OpenDumpFileWide failed" );
+        
+    hres = m_control->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugControl::WaitForEvent failed" );
+ 
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+void DebugClient::startProcess( const std::wstring  &processName )
+{
+    HRESULT     hres;
+        
+    ULONG       opt;
+    hres = m_control->GetEngineOptions( &opt );
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugControl::GetEngineOptions failed" );
+
+    opt |= DEBUG_ENGOPT_INITIAL_BREAK;
+    hres = m_control->SetEngineOptions( opt );
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugControl::SetEngineOptions failed" );
+
+    std::vector< std::wstring::value_type>      cmdLine( processName.size() + 1 );
+    wcscpy_s( &cmdLine[0], cmdLine.size(), processName.c_str() );
+
+    hres = m_client->CreateProcessWide( 0, &cmdLine[0], DEBUG_PROCESS | DETACHED_PROCESS );
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugClient4::CreateProcessWide failed" );
+
+    hres = m_control->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugControl::WaitForEvent failed" );
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+void DebugClient::attachProcess( ULONG  processId )
+{
+    HRESULT     hres;
+    
+    hres = m_client->AttachProcess( 0, processId, 0 );
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugClient::AttachProcess failed" );
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+void DebugClient::attachKernel( const std::wstring  &param )
+{
+    HRESULT     hres;
+
+    hres = m_client->AttachKernelWide( DEBUG_ATTACH_KERNEL_CONNECTION, param.c_str() );
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugClient5::AttachKernelWide failed" );
+}
+
+///////////////////////////////////////////////////////////////////////////////////
\ No newline at end of file
diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h
index c971f10..e684d7e 100644
--- a/pykd/dbgclient.h
+++ b/pykd/dbgclient.h
@@ -1,5 +1,52 @@
 #pragma once
 
+#include <string>
+#include <dbgeng.h>
+#include <dbghelp.h>
+
+#include "dbgexcept.h"
+
+/////////////////////////////////////////////////////////////////////////////////
+
+namespace pykd {
+
+/////////////////////////////////////////////////////////////////////////////////
+
+class DebugClient {
+
+public:
+
+    DebugClient();
+
+    virtual ~DebugClient() {}
+
+    void loadDump( const std::wstring &fileName );
+
+    void startProcess( const std::wstring  &processName );
+
+    void attachProcess( ULONG  processId );
+
+    void attachKernel( const std::wstring  &param );
+
+private:
+
+    CComPtr<IDebugClient5>      m_client;     
+    CComPtr<IDebugControl4>     m_control;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+
+};  // namespace pykd
+
+
+
+
+
+
+
+
+
+
 //#include "dbgext.h"
 //#include "dbgeventcb.h"
 //
diff --git a/pykd/dbgexcept.cpp b/pykd/dbgexcept.cpp
index 35cfeb3..9e7b8bf 100644
--- a/pykd/dbgexcept.cpp
+++ b/pykd/dbgexcept.cpp
@@ -1,4 +1,9 @@
 #include "stdafx.h"
+
+
+
+
+
 //#include "dbgexcept.h"
 //
 ///////////////////////////////////////////////////////////////////////////////////
diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h
index da906a2..9758371 100644
--- a/pykd/dbgexcept.h
+++ b/pykd/dbgexcept.h
@@ -1,5 +1,45 @@
 #pragma once
 
+#include <exception>
+#include <string>
+
+namespace pykd {
+
+/////////////////////////////////////////////////////////////////////////////////
+
+class DbgException : public std::exception
+{
+public:
+
+    DbgException( const std::string  &desc ) :
+        std::exception( desc.c_str() )
+        {}
+
+    const char* getDesc() const {
+        return what();
+    }
+
+    static
+    void
+    exceptionTranslate(const DbgException &e );
+};
+
+///////////////////////////////////////////////////////////////////////////////////
+
+extern  PyObject  *baseExceptionType;
+
+///////////////////////////////////////////////////////////////////////////////////
+
+}; // namespace pykd
+
+///////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+
 //#include <exception>
 //#include <string>
 //
diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp
index 99f5ecf..989565f 100644
--- a/pykd/dbgext.cpp
+++ b/pykd/dbgext.cpp
@@ -2,6 +2,12 @@
 
 #include <dbgeng.h>
 
+#include "module.h"
+#include "diawrapper.h"
+#include "dbgclient.h"
+
+namespace python = boost::python;
+
 ////////////////////////////////////////////////////////////////////////////////
 
 HRESULT
@@ -44,11 +50,18 @@ pycmd( PDEBUG_CLIENT4 client, PCSTR args )
 
 ////////////////////////////////////////////////////////////////////////////////
 
-HRESULT 
-CALLBACK
-info( PDEBUG_CLIENT4 client, PCSTR args )
+BOOST_PYTHON_MODULE( pykd )
 {
-    return S_OK;
+    python::class_<pykd::DebugClient>("dbgClient", "Class representing a debugging session" )
+        .def( "loadDump", &pykd::DebugClient::loadDump, "Load crash dump" )
+        .def( "startProcess", &pykd::DebugClient::startProcess, "Start process for debugging" )
+        .def( "attachProcess", &pykd::DebugClient::attachProcess, "Attach debugger to a exsisting process" )
+        .def( "attachKernel", &pykd::DebugClient::attachKernel, "Attach debugger to a target's kernel" );
+
+    python::class_<pykd::Module>("module", "Class representing executable module", python::no_init )
+        .def( python::init<std::string>( "constructor" ) );
+
+   // python::class_<pykd::DiaWrapper>("dia", "class wrapper for MS DIA" );
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -61,6 +74,9 @@ info( PDEBUG_CLIENT4 client, PCSTR args )
 
 
 
+
+
+
 //#include <wdbgexts.h>
 //
 //#include <string>
diff --git a/pykd/dbgmodule.cpp b/pykd/module.cpp
similarity index 100%
rename from pykd/dbgmodule.cpp
rename to pykd/module.cpp
diff --git a/pykd/dbgmodule.h b/pykd/module.h
similarity index 89%
rename from pykd/dbgmodule.h
rename to pykd/module.h
index cc6e59a..b7ccb6a 100644
--- a/pykd/dbgmodule.h
+++ b/pykd/module.h
@@ -1,5 +1,22 @@
 #pragma once
 
+namespace pykd {
+
+///////////////////////////////////////////////////////////////////////////////////
+
+class Module {
+
+public:
+
+    Module( const std::string  &moduleName )
+    {}
+};
+
+///////////////////////////////////////////////////////////////////////////////////
+
+};
+
+
 //#include <string>
 //#include <map>
 //
diff --git a/pykd/pykd.def b/pykd/pykd.def
index 17ee93b..4c23f5e 100644
--- a/pykd/pykd.def
+++ b/pykd/pykd.def
@@ -1,7 +1,5 @@
 EXPORTS
 	DebugExtensionInitialize
 	DebugExtensionUninitialize
-
-	info
 	py
 	pycmd
diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj
index 6e2b4b6..d8c8fb4 100644
--- a/pykd/pykd_2008.vcproj
+++ b/pykd/pykd_2008.vcproj
@@ -349,10 +349,22 @@
 			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
+			<File
+				RelativePath=".\dbgclient.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\dbgexcept.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\dbgext.cpp"
 				>
 			</File>
+			<File
+				RelativePath=".\module.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\pykd.def"
 				>
@@ -399,6 +411,22 @@
 			Filter="h;hpp;hxx;hm;inl;inc;xsd"
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
+			<File
+				RelativePath=".\dbgclient.h"
+				>
+			</File>
+			<File
+				RelativePath=".\dbgexcept.h"
+				>
+			</File>
+			<File
+				RelativePath=".\diawrapper.h"
+				>
+			</File>
+			<File
+				RelativePath=".\module.h"
+				>
+			</File>
 			<File
 				RelativePath=".\resource.h"
 				>
diff --git a/pykd/stdafx.h b/pykd/stdafx.h
index deeb631..52a9e8f 100644
--- a/pykd/stdafx.h
+++ b/pykd/stdafx.h
@@ -30,20 +30,22 @@
 #include <windows.h>
 #include <atlbase.h>
 
+
 //
 //#ifndef  __field_ecount_opt
 //#define  __field_ecount_opt(x)  
 //#endif // __field_ecount_opt
 //
 //
-//#define BOOST_PYTHON_STATIC_LIB
-//
-//#pragma warning(push)
-//// 'return' : conversion from 'Py_ssize_t' to 'unsigned int', possible loss of data
-//#pragma warning(disable:4244)
-//#include <boost/python.hpp>
-//#include <boost/python/object.hpp>
-//#pragma warning(pop)
+#define BOOST_PYTHON_STATIC_LIB
+
+#pragma warning(push)
+// 'return' : conversion from 'Py_ssize_t' to 'unsigned int', possible loss of data
+#pragma warning(disable:4244)
+#include <boost/python.hpp>
+#include <boost/python/object.hpp>
+#include <boost/python/module.hpp>
+#pragma warning(pop)
 //
 //#include <vector>
 //
diff --git a/test/scripts/basetest.py b/test/scripts/basetest.py
index bc7b552..e0fc3c0 100644
--- a/test/scripts/basetest.py
+++ b/test/scripts/basetest.py
@@ -4,11 +4,12 @@
 
 import unittest
 import target
+import pykd
 
 class BaseTest( unittest.TestCase ):
-
-    def test1( self ):
-        self.assertNotEqual( target.module, None )
-   
-    
-    
\ No newline at end of file
+      
+    def testImport( self ):
+        self.assertNotEqual( None, pykd.module )
+        self.assertNotEqual( None, pykd.dbgClient )
+        
+#        self.assertNotEqual( None, pykd.dia )
diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py
index f0f6820..63d861a 100644
--- a/test/scripts/pykdtest.py
+++ b/test/scripts/pykdtest.py
@@ -5,7 +5,6 @@
 import sys
 import os
 import unittest
-import fnmatch
 
 # Dynamically append current pykd.pyd path to PYTHONPATH
 sys.path.append(os.path.dirname(sys.argv[1]))
@@ -15,11 +14,15 @@ import target
 import basetest
 import typeinfo 
 import regtest
+import moduletest
+
+print dir(pykd)
 
 def getTestSuite( singleName = "" ):
     if singleName == "":
         return unittest.TestSuite(
            [   unittest.TestLoader().loadTestsFromTestCase( basetest.BaseTest ),
+               unittest.TestLoader().loadTestsFromTestCase( moduletest.ModuleTest ),
 #               unittest.TestLoader().loadTestsFromTestCase( typeinfo.TypeInfoTest ),
 #               unittest.TestLoader().loadTestsFromTestCase( regtest.CpuRegTest )
            ] ) 
@@ -34,10 +37,12 @@ if __name__ == "__main__":
     target.moduleName = os.path.splitext(os.path.basename(targetAppPath))[0]
     print "\nTest module: %s" % targetAppPath
     
-    pykd.startProcess( targetAppPath )
-    pykd.go()
+    dbg = pykd.dbgClient()
+    
+    dbg.startProcess( targetAppPath )
+#    pykd.go()
 
-    target.module = pykd.loadModule( target.moduleName )
+#    target.module = pykd.loadModule( target.moduleName )
     
     suite = getTestSuite()
    
diff --git a/test/targetapp/targetapp.vcproj b/test/targetapp/targetapp.vcproj
index cf9ba53..fbcff0c 100644
--- a/test/targetapp/targetapp.vcproj
+++ b/test/targetapp/targetapp.vcproj
@@ -404,6 +404,10 @@
 				RelativePath="..\scripts\basetest.py"
 				>
 			</File>
+			<File
+				RelativePath="..\scripts\moduletest.py"
+				>
+			</File>
 			<File
 				RelativePath="..\scripts\pykdtest.py"
 				>