09
May
09

[C++] Read External Treeview

After quite some time and a lot of research, I finally got it to work. The method is summarised below:

xProcess = eXternal Process
Find xProc Window
Find Treeview in window
Get xProcess ID
Set Debug Privelages
Open xProcess
Allocate Memory in xProc
Get Root Node
Loop:
	Create and fill TVITEM structure
	Write TVITEM to xprocess
	Send GET_ITEM to get Node name
	Read string from xprocess memory
	print
	Get Next Node
Free Memory
Close Handle

I also had some trouble in some processes with trying to open them, so the code includes a setDebug function that changes your privileges and is used in the printTreeviewNodes function before attempting to open the process. Below is the code, including an example of how to use it (Using Teamspeak 2 as a target program):

// Read External Treeview.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "commctrl.h"
#include <iostream>

using namespace std;

bool setDebug() {
	HANDLE hToken;
	if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
		TOKEN_PRIVILEGES tp;
		LUID luid;
		TOKEN_PRIVILEGES tpPrevious;
		DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
		if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
			tp.PrivilegeCount = 1;
			tp.Privileges[0].Luid = luid;
			tp.Privileges[0].Attributes = 0;
			if(AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious)) {
				tpPrevious.PrivilegeCount = 1;
				tpPrevious.Privileges[0].Luid = luid;
				tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
				if(AdjustTokenPrivileges( hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL )) {
					CloseHandle(hToken);
					return true;
				}
			}
		}
	}
	CloseHandle(hToken);
	return false;
}

void printTreeviewNodes(HWND treeview) {
	DWORD pID;
	GetWindowThreadProcessId(treeview, &pID);
	if(pID) {
		if(setDebug()) {
			HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pID);
			if(hProcess) {
			/*
				Memory allocation:
			   0---------|---------|----------------14F
				 TVITEM    rBuffer       pszText
				  (28)      (28)          (FF)
			*/
				DWORD remoteBuffer = (DWORD)::VirtualAllocEx(hProcess, NULL, 335, MEM_COMMIT, PAGE_READWRITE);
				if(remoteBuffer) {
					HTREEITEM Root = (HTREEITEM)::SendMessage(treeview, TVM_GETNEXTITEM, TVGN_ROOT, 0);
					while(Root) {
						TVITEM tvItem;
						tvItem.mask = TVIF_TEXT;
						tvItem.hItem = Root;
						tvItem.pszText = (LPWSTR)remoteBuffer + sizeof(TVITEM);
						tvItem.cchTextMax = 255;
						if(WriteProcessMemory(hProcess, (LPVOID)remoteBuffer, (LPCVOID)&tvItem, sizeof(TVITEM), 0)) {
							SendMessage(treeview, TVM_GETITEM, 0, remoteBuffer);
							wchar_t bytRtn[255];
							int rAdd = remoteBuffer + sizeof(TVITEM)*2;
							if(ReadProcessMemory(hProcess, (LPCVOID)rAdd, (LPVOID)&bytRtn, 255, 0)) {
								wcout << bytRtn << endl;
							}
							Root = (HTREEITEM)::SendMessage(treeview, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)Root);
						}
					}
					VirtualFreeEx(hProcess, (LPVOID)remoteBuffer, 335, MEM_RELEASE);
				}
			}
			CloseHandle(hProcess);
		}
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	HWND tsmhWnd = FindWindow(L"TMainForm", L"TeamSpeak 2");
	tsmhWnd = FindWindowEx(tsmhWnd, NULL, L"TPanel", NULL);
	HWND tsTVhWnd = FindWindowEx(tsmhWnd, NULL, L"TTreeView", NULL);
	printTreeviewNodes(tsTVhWnd);
	return 0;
}

If anybody has a better method than this or any comments, I’d be more than happy for input ^^

Advertisements

7 Responses to “[C++] Read External Treeview”


  1. 1 Qu4rry
    April 19, 2010 at 8:58 pm

    Thank you very much! I was Searching hours finding a working solution of getting external tree view data. Thats exactl I was looking for. And it works fine. 😉

  2. 2 tony
    April 26, 2010 at 5:34 am

    simon thanks for the code. Could you tell me how to compile this code . Is it possible that you release a vb6 version of same code ? Thanks looking forward for your reply.

    • 3 sim0n
      April 26, 2010 at 10:28 am

      To complie use a C++ compiler (I use Visual Studio, 2005,2008,2010,etc will be fine).
      I’ve never actually used VB6 but the code would be quite easily portable since its mainly just API calls which you can declare in vb6.
      I could write it in VB.net which would be similar to VB6 then you convert that?

  3. 4 jade
    March 11, 2012 at 5:48 am

    >>I could write it in VB.net which would be similar to VB6 then you convert that?
    Ok, Sir, we would be glad if you post the vb.net version of your code
    Thanks in advance

  4. 6 jade
    March 21, 2012 at 6:40 am

    thank you, thank you, thank you

  5. 7 jade
    May 15, 2012 at 7:21 pm

    hi
    The codes are too huge for my knowledge, I’m only want to lock a specific item in an external tree-view so anyone using the external tree-view will be stucked in a specific item.

    One example is the Epson Photo Print application, I want the users/employees to be stucked and they could not do the prints if they point to the other item.

    Can you specify or split which of the codes can be used for my project?

    Thanks again,
    Jade


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: