From 4a50b8b5632a61a5ee9372a876ac056345266729 Mon Sep 17 00:00:00 2001
From: "SND\\kernelnet_cp"
 <SND\kernelnet_cp@9b283d60-5439-405e-af05-b73fd8c4d996>
Date: Fri, 21 Dec 2012 14:34:47 +0000
Subject: [PATCH] [0.2.x] added: getProcessThreads ( Get all process's threads
 ( user mode only ) )

git-svn-id: https://pykd.svn.codeplex.com/svn@81956 9b283d60-5439-405e-af05-b73fd8c4d996
---
 pykd/dbgengine.h                |   1 +
 pykd/{ => python}/pymod.cpp     |   5 +-
 pykd/python/pysupport.cpp       |  30 ++++++
 pykd/python/pysupport.h         |  14 +++
 pykd/win/dbgeng.cpp             |  55 +++++++++++
 test/targetapp/targetapp.vcproj | 161 +++++++++++++++++++++++++++++++-
 6 files changed, 264 insertions(+), 2 deletions(-)
 rename pykd/{ => python}/pymod.cpp (97%)
 create mode 100644 pykd/python/pysupport.cpp
 create mode 100644 pykd/python/pysupport.h

diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h
index 4ae318c..4e68874 100644
--- a/pykd/dbgengine.h
+++ b/pykd/dbgengine.h
@@ -141,6 +141,7 @@ ULONG64 getCurrentProcess();
 ULONG64 getImplicitThread();
 void setCurrentProcess( ULONG64 processAddr );
 void setImplicitThread( ULONG64 threadAddr );
+void getAllProcessThreads( std::vector<ULONG64> &threadsArray );
 
 // Symbol path
 std::string getSymbolPath();
diff --git a/pykd/pymod.cpp b/pykd/python/pymod.cpp
similarity index 97%
rename from pykd/pymod.cpp
rename to pykd/python/pymod.cpp
index f55a0c5..ecd7afc 100644
--- a/pykd/pymod.cpp
+++ b/pykd/python/pymod.cpp
@@ -21,13 +21,14 @@
 #include "stkframe.h"
 #include "bpoint.h"
 #include "eventhandler.h"
+#include "pysupport.h"
 
 #include "win/dbgio.h"
 #include "win/windbg.h"
 
 using namespace pykd;
 
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 
 static const std::string pykdVersion = PYKD_VERSION_BUILD_STR
 #ifdef _DEBUG
@@ -281,6 +282,8 @@ BOOST_PYTHON_MODULE( pykd )
         "Set current process by address" );
     python::def( "setImplicitThread", &setImplicitThread, 
         "Set implicit thread for current process" );
+    python::def( "getProcessThreads", &pysupport::getProcessThreads,
+        "Get all process's threads ( user mode only )" );
     
     // symbol path
     python::def( "getSymbolPath", &getSymbolPath, "Returns current symbol path");
diff --git a/pykd/python/pysupport.cpp b/pykd/python/pysupport.cpp
new file mode 100644
index 0000000..e3b188c
--- /dev/null
+++ b/pykd/python/pysupport.cpp
@@ -0,0 +1,30 @@
+#include "stdafx.h"
+#include "pysupport.h"
+
+#include "dbgengine.h"
+#include <vector>
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace pykd {
+namespace pysupport {
+
+///////////////////////////////////////////////////////////////////////////////
+
+python::list getProcessThreads()
+{
+    std::vector<ULONG64>  threads;
+    getAllProcessThreads( threads );
+
+    python::list  threadsLst;
+
+    std::vector<ULONG64>::iterator  it;
+    for ( it = threads.begin(); it != threads.end(); ++it )
+        threadsLst.append( *it );
+
+    return threadsLst;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} } //pykd::support namespace end
\ No newline at end of file
diff --git a/pykd/python/pysupport.h b/pykd/python/pysupport.h
new file mode 100644
index 0000000..f9a2139
--- /dev/null
+++ b/pykd/python/pysupport.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <boost/python/list.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace pykd {
+namespace pysupport {
+
+python::list getProcessThreads();
+
+} } //pykd::support namespace end
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp
index 48c387c..ddaacc3 100644
--- a/pykd/win/dbgeng.cpp
+++ b/pykd/win/dbgeng.cpp
@@ -1365,6 +1365,61 @@ void setImplicitThread( ULONG64 threadAddr )
 
 ///////////////////////////////////////////////////////////////////////////////
 
+void getAllProcessThreads( std::vector<ULONG64> &threadsArray )
+{
+    PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
+
+    HRESULT     hres;
+    ULONG       debugClass, debugQualifier;
+    
+    hres = g_dbgEng->control->GetDebuggeeType( &debugClass, &debugQualifier );
+    
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugControl::GetDebuggeeType  failed" );   
+         
+    if  ( debugClass != DEBUG_CLASS_USER_WINDOWS )
+        throw DbgException( "getAllProcessThreads routine only for usermode" );
+
+    ULONG  threadsNumber = 0;
+
+    hres = g_dbgEng->system->GetNumberThreads( &threadsNumber );
+    if ( FAILED(hres) )
+        throw DbgException( "IDebugSystemObjects::GetNumberThreads failed" );
+
+    std::vector<ULONG>  ids(threadsNumber);
+
+    hres = g_dbgEng->system->GetThreadIdsByIndex( 0, threadsNumber, &ids[0], NULL );
+    if ( FAILED(hres) )
+        throw DbgException( "IDebugSystemObjects::GetThreadIdsByIndex failed" );
+
+    ULONG  currentThreadId;
+    hres = g_dbgEng->system->GetCurrentThreadId( &currentThreadId );
+    if ( FAILED(hres) )
+        throw DbgException( "IDebugSystemObjects::GetCurrentThreadId failed" );
+
+    threadsArray.resize( threadsNumber );
+    for ( size_t i = 0; i < threadsNumber; ++i )
+    {
+        hres = g_dbgEng->system->SetCurrentThreadId( ids[i] );
+        if ( FAILED(hres) )
+        {   
+            g_dbgEng->system->SetCurrentThreadId( currentThreadId );
+            throw DbgException( "IDebugSystemObjects::SetCurrentThreadId failed" );
+        }
+
+        hres = g_dbgEng->system->GetCurrentThreadTeb( &threadsArray[i] );
+        if ( FAILED(hres) )
+        {   
+            g_dbgEng->system->SetCurrentThreadId( currentThreadId );
+            throw DbgException( "IDebugSystemObjects::GetCurrentThreadTeb failed" );
+        }
+    }
+
+     g_dbgEng->system->SetCurrentThreadId( currentThreadId );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 ULONG64 loadExtension(const std::wstring &extPath )
 {
     PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
diff --git a/test/targetapp/targetapp.vcproj b/test/targetapp/targetapp.vcproj
index 226ad86..da0801f 100644
--- a/test/targetapp/targetapp.vcproj
+++ b/test/targetapp/targetapp.vcproj
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="windows-1251"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="9.00"
+	Version="9,00"
 	Name="targetapp"
 	ProjectGUID="{C6254E16-AB8E-41EE-887D-31458E93FC68}"
 	RootNamespace="targetapp"
@@ -315,6 +315,149 @@
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
+		<Configuration
+			Name="Debug_2.7|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug_2.7|x64"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
 	</Configurations>
 	<References>
 	</References>
@@ -359,6 +502,22 @@
 						UsePrecompiledHeader="1"
 					/>
 				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_2.7|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_2.7|x64"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
 			</File>
 			<File
 				RelativePath=".\targetapp.cpp"