From dd2138393c5d68fca63585df63122840f7378cc0 Mon Sep 17 00:00:00 2001
From: "SND\\kernelnet_cp"
 <SND\kernelnet_cp@9b283d60-5439-405e-af05-b73fd8c4d996>
Date: Tue, 20 Jan 2015 08:45:25 +0000
Subject: [PATCH] [0.3.x] added : class targetProcess ( representing process in
 the target system ) [0.3.x] added : class targetThread ( representing process
 in the target system )

git-svn-id: https://pykd.svn.codeplex.com/svn@89654 9b283d60-5439-405e-af05-b73fd8c4d996
---
 pykd/pykd_vc110.vcxproj         |  1 +
 pykd/pykd_vc110.vcxproj.filters |  3 ++
 pykd/pymod.cpp                  | 26 +++++++++++-
 pykd/pyprocess.h                | 71 +++++++++++++++++++++++++++++++++
 test/scripts/pykdtest.py        |  3 ++
 test/scripts/pykdtest.pyproj    |  1 +
 test/scripts/targetprocess.py   | 40 +++++++++++++++++++
 7 files changed, 144 insertions(+), 1 deletion(-)
 create mode 100644 pykd/pyprocess.h
 create mode 100644 test/scripts/targetprocess.py

diff --git a/pykd/pykd_vc110.vcxproj b/pykd/pykd_vc110.vcxproj
index cbce213..ddba87d 100644
--- a/pykd/pykd_vc110.vcxproj
+++ b/pykd/pykd_vc110.vcxproj
@@ -178,6 +178,7 @@
     <ClInclude Include="pykdver.h" />
     <ClInclude Include="pymemaccess.h" />
     <ClInclude Include="pymodule.h" />
+    <ClInclude Include="pyprocess.h" />
     <ClInclude Include="pysymengine.h" />
     <ClInclude Include="pythreadstate.h" />
     <ClInclude Include="pytypedvar.h" />
diff --git a/pykd/pykd_vc110.vcxproj.filters b/pykd/pykd_vc110.vcxproj.filters
index a5dbeca..268443f 100644
--- a/pykd/pykd_vc110.vcxproj.filters
+++ b/pykd/pykd_vc110.vcxproj.filters
@@ -75,6 +75,9 @@
     <ClInclude Include="pyevents.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="pyprocess.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="stdafx.cpp">
diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp
index 42b15bf..e76e090 100644
--- a/pykd/pymod.cpp
+++ b/pykd/pymod.cpp
@@ -20,6 +20,7 @@
 #include "pytypedvar.h"
 #include "pytypeinfo.h"
 #include "pycpucontext.h"
+#include "pyprocess.h"
 
 using namespace pykd;
 
@@ -499,6 +500,30 @@ BOOST_PYTHON_MODULE( pykd )
 
         NumVariantAdaptor::registerNumConvertion();
 
+    python::class_<kdlib::TargetProcess, kdlib::TargetProcessPtr,  boost::noncopyable>("targetProcess", "Class representing process in the target system", python::no_init )
+        .def("getNumber", TargetProcessAdapter::getNumberProcesses,
+            "Return number of processes" ).staticmethod("getNumber")
+        .def("getCurrent", TargetProcessAdapter::getCurrent,
+            "Return a current process" ).staticmethod("getCurrent")
+        .def("getProcess", TargetProcessAdapter::getProcess,
+            "Return process by index").staticmethod("getProcess")
+        .def("systemID", TargetProcessAdapter::getSystemId,
+            "Retrun system process ID ( PID )" )
+        .def("peb", TargetProcessAdapter::getPebOffset,
+            "Return PEB address" )
+        .def("getNumberThreads", TargetProcessAdapter::getNumberThreads,
+            "Return number of threads for this process" )
+        .def("thread", TargetProcessAdapter::getThreadByIndex,
+            "Return thread by its index" )
+        ;
+
+    python::class_<kdlib::TargetThread, kdlib::TargetThreadPtr, boost::noncopyable>("targetThread", "Class representing process in the target system", python::no_init )
+        .def("systemID", TargetThreadAdapter::getSystemId,
+            "Retrun system thread ID ( TID )" )
+        .def("teb", TargetThreadAdapter::getTebOffset,
+            "Return TEB address" )
+        ;
+
     python::class_<kdlib::Module, kdlib::ModulePtr, python::bases<kdlib::NumBehavior>, boost::noncopyable>("module", "Class representing executable module", python::no_init )
         .def("__init__", python::make_constructor(&ModuleAdapter::loadModuleByName ) )
         .def("__init__", python::make_constructor(&ModuleAdapter::loadModuleByOffset) )
@@ -559,7 +584,6 @@ BOOST_PYTHON_MODULE( pykd )
             "Return address of the symbol" )
         .def( "__str__", &ModuleAdapter::print );
 
-
     python::class_<kdlib::TypeInfo, kdlib::TypeInfoPtr, python::bases<kdlib::NumBehavior>, boost::noncopyable >("typeInfo", "Class representing typeInfo", python::no_init )
         .def("__init__", python::make_constructor( pykd::getTypeInfoByName ) )
         .def( "name", TypeInfoAdapter::getName,
diff --git a/pykd/pyprocess.h b/pykd/pyprocess.h
new file mode 100644
index 0000000..4226eb4
--- /dev/null
+++ b/pykd/pyprocess.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include <kdlib/process.h>
+
+#include "pythreadstate.h"
+
+namespace pykd {
+
+struct TargetProcessAdapter {
+
+    static kdlib::TargetProcessPtr getCurrent()
+    {
+        AutoRestorePyState  pystate;
+        return kdlib::TargetProcess::getCurrent();
+    }
+
+    static kdlib::TargetProcessPtr getProcess(unsigned long index)
+    {
+        AutoRestorePyState  pystate;
+        return kdlib::TargetProcess::getByIndex(index);
+    }
+
+    static unsigned long getNumberProcesses() 
+    {
+        AutoRestorePyState  pystate;
+        return kdlib::TargetProcess::getNumber();
+    }
+
+    static kdlib::PROCESS_ID getSystemId(kdlib::TargetProcess& process )
+    {
+        AutoRestorePyState  pystate;
+        return process.getSystemId();
+    }
+
+    static kdlib::MEMOFFSET_64 getPebOffset(kdlib::TargetProcess& process )
+    {
+        AutoRestorePyState  pystate;
+        return process.getPebOffset();
+    }
+
+    static unsigned long getNumberThreads(kdlib::TargetProcess& process )
+    {
+        AutoRestorePyState  pystate;
+        return process.getNumberThreads();
+    }
+
+    static kdlib::TargetThreadPtr getThreadByIndex(kdlib::TargetProcess& process, unsigned long index) 
+    {
+        AutoRestorePyState  pystate;
+        return process.getThreadByIndex(index);
+    }
+};
+
+
+struct TargetThreadAdapter {
+
+    static kdlib::THREAD_ID getSystemId(kdlib::TargetThread& thread )
+    {
+        AutoRestorePyState  pystate;
+        return thread.getSystemId();
+    }
+
+    static kdlib::MEMOFFSET_64 getTebOffset(kdlib::TargetThread& thread )
+    {
+        AutoRestorePyState  pystate;
+        return thread.getTebOffset();
+    }
+};
+
+} // pykd namespace
+
diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py
index 67c4a92..54d3d82 100644
--- a/test/scripts/pykdtest.py
+++ b/test/scripts/pykdtest.py
@@ -24,6 +24,7 @@ import stacktest
 import customtypestest
 import mspdbtest
 import excepttest
+import targetprocess
 
 pykd.initialize()
 
@@ -59,6 +60,8 @@ def getTestSuite( singleName = "" ):
                 unittest.TestLoader().loadTestsFromTestCase( breakpoint.BreakpointTest ),
                 unittest.TestLoader().loadTestsFromTestCase( stacktest.StackTest ),
                 unittest.TestLoader().loadTestsFromTestCase( mspdbtest.MsPdbTest ),
+                unittest.TestLoader().loadTestsFromTestCase( targetprocess.ProcessTest ),
+
                 #unittest.TestLoader().loadTestsFromTestCase( excepttest.ExceptionTest ),
             ] ) 
     else:
diff --git a/test/scripts/pykdtest.pyproj b/test/scripts/pykdtest.pyproj
index 0ef356f..3647e4e 100644
--- a/test/scripts/pykdtest.pyproj
+++ b/test/scripts/pykdtest.pyproj
@@ -53,6 +53,7 @@
     <Compile Include="stacktest.py" />
     <Compile Include="synsymtest.py" />
     <Compile Include="target.py" />
+    <Compile Include="targetprocess.py" />
     <Compile Include="testutils.py" />
     <Compile Include="thrdctxtest.py" />
     <Compile Include="typedvar.py" />
diff --git a/test/scripts/targetprocess.py b/test/scripts/targetprocess.py
new file mode 100644
index 0000000..e01203c
--- /dev/null
+++ b/test/scripts/targetprocess.py
@@ -0,0 +1,40 @@
+import unittest
+import pykd
+import target
+import time
+
+class ProcessTest(unittest.TestCase):
+
+    def setUp(self):
+        pykd.startProcess( target.appPath )
+        pykd.startProcess( target.appPath )
+        pykd.startProcess( target.appPath )
+
+    def tearDown(self):
+        pykd.killAllProcesses()
+
+    def testGetCurrentProcess(self):
+        proc = pykd.targetProcess.getCurrent()
+        self.assertNotEqual(0, proc.systemID() )
+        self.assertNotEqual(0, proc.peb() )
+
+    def testEnumThreads(self):
+        proc = pykd.targetProcess.getCurrent()
+        threadNumber = proc.getNumberThreads()
+        self.assertLess(0, threadNumber)
+        for i in xrange(threadNumber):
+            thread = proc.thread(i)
+            self.assertNotEqual(0, thread.systemID() )
+            self.assertNotEqual(0, thread.teb() )
+
+    def testEnumProcesses(self):
+        processNumber = pykd.targetProcess.getNumber()
+        for i in xrange(processNumber):
+            proc = pykd.targetProcess.getProcess(i)
+            self.assertNotEqual(0, proc.systemID() )
+            self.assertNotEqual(0, proc.peb() )
+
+
+
+
+