function GetTreeViewText(hTVwnd: HWND; memo1, memo2: TMemo): pchar;
const
MAX_TEXT = 256;
type
TVITEM = TTVITEM;
var
lpBuf:
array[0..MAX_TEXT - 1]
of char;
tvi: TVITEM;
dwPId: DWORD;
hProc: THANDLE;
pText, pAddr: pointer;
dwTmp: DWORD;
i, i2, nCount, size: integer;
chan: integer;
is_chan: boolean;
// ret, ret_usr, res: TStringList;
begin
// Get ThreadID and ProzessID
if BOOL(GetWindowThreadProcessId(hTVwnd, @dwPId))
then
// Get a handle to the process with the needed access
hProc := OpenProcess(PROCESS_VM_OPERATION
or PROCESS_VM_READ
or PROCESS_VM_WRITE, FALSE, dwPId);
if hProc <> 0
then
begin
// Allocate memory for thet text to hold in the target process ...
pText := VirtualAllocEx(hProc,
nil, MAX_TEXT, MEM_RESERVE
or MEM_COMMIT, PAGE_READWRITE);
// Allocate memory for the TVITEM structure in target process ...
pAddr := VirtualAllocEx(hProc,
nil, sizeof(tvi), MEM_RESERVE
or MEM_COMMIT, PAGE_READWRITE);
// Get number of nodes in the target treeview ...
nCount := SendMessage(hTVwnd, TVM_GETCOUNT, 0, 0);
// We want the text only ... set some flags in structure
tvi.mask := TVIF_TEXT;
tvi.pszText := pText;
tvi.cchTextMax := MAX_TEXT - 1;
// Get root item handle ...
tvi.hItem := HTREEITEM(SendMessage(hTVwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0));
// Iterate through the whole treeview and collapse all root child items
// (to avoid flickering and stuff)
for i := 0
to nCount - 1
do
begin
// Write our structure (with flags) to the process
if WriteProcessMemory(hProc, pAddr, @tvi, sizeof(tvi), dwTmp)
and
// Get the stuff we need back
(SendMessage(hTVwnd, TVM_GETITEM, 0, Integer(pAddr)) <> 0)
and
// Read the text from the pointer we got ... respect MAX_TEXT
ReadProcessMemory(hProc, pText, @lpBuf, MAX_TEXT, dwTmp)
then
begin
// If successful and not root item, collapse it.
if (i > 0)
then
// Collapse the item ... next visible item will be a child item of the root, too
SendMessage(hTVwnd, TVM_EXPAND, TVE_COLLAPSE, Integer(tvi.hItem));
// Get handle to next visible item ...
tvi.hItem := HTREEITEM(SendMessage(hTVwnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, Integer(tvi.hItem)));
// Break here if we face the last visible item ...
if tvi.hItem = HTREEITEM(0)
then break;
end
// If not successful break here ...
else
break;
end;
// Get root item again
tvi.hItem := HTREEITEM(SendMessage(hTVwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0));
// ... and iterate through the treeview once more ...
for i := 0
to (nCount - 1)
do
begin
// Write our structure (with flags) to the process
if WriteProcessMemory(hProc, pAddr, @tvi, sizeof(TV_ITEM), dwTmp)
and
// Get the stuff we need back
(SendMessage(hTVwnd, TVM_GETITEM, 0, Integer(pAddr)) <> 0)
and
// Read the text from the pointer we got ... respect MAX_TEXT
ReadProcessMemory(hProc, pText, @lpBuf, MAX_TEXT, dwTmp)
then
begin
// If successful and not root item, get text ...
if (i > 0)
then
memo1.Lines.Append(
string(lpBuf));
// Get handle to next visible item ...
tvi.hItem := HTREEITEM(SendMessage(hTVwnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, Integer(tvi.hItem)));
end else break;
end;
// Get root item again
tvi.hItem := HTREEITEM(SendMessage(hTVwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0));
// ... and iterate through the treeview once more ...
for i := 0
to (nCount - 1)
do
begin
if WriteProcessMemory(hProc, pAddr, @tvi, sizeof(TV_ITEM), dwTmp)
and
(SendMessage(hTVwnd, TVM_GETITEM, 0, Integer(pAddr)) <> 0)
and
ReadProcessMemory(hProc, pText, @lpBuf, MAX_TEXT, dwTmp)
then
begin
if (i > 0)
then SendMessage(hTVwnd, TVM_EXPAND, TVE_EXPAND, Integer(tvi.hItem));
tvi.hItem := HTREEITEM(SendMessage(hTVwnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, Integer(tvi.hItem)));
end else break;
end;
// Get Items
tvi.hItem := HTREEITEM(SendMessage(hTVwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0));
for i := 0
to (nCount - 1)
do
begin
if WriteProcessMemory(hProc, pAddr, @tvi, sizeof(TV_ITEM), dwTmp)
and
(SendMessage(hTVwnd, TVM_GETITEM, 0, Integer(pAddr)) <> 0)
and
ReadProcessMemory(hProc, pText, @lpBuf, MAX_TEXT, dwTmp)
then
begin
if (i > 0)
then
memo2.lines.Append(
string(lpBuf));
tvi.hItem := HTREEITEM(SendMessage(hTVwnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, Integer(tvi.hItem)));
end else break;
end;
end;
// else: "could not get process handle"
if Assigned(pAddr)
then
VirtualFreeEx(hProc, pAddr, 0, MEM_RELEASE);
if Assigned(pText)
then
VirtualFreeEx(hProc, pText, 0, MEM_RELEASE);
CloseHandle(hProc);
end;