|
Hi. I'm trying to convert to C# but I got a null buffer (all items are \0).
Please, can someone help me?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
IntPtr mainWindowHwnd;
IntPtr lvwHwnd = (IntPtr)0;
try
{
mainWindowHwnd = FindWindow(null, "Stealing Program's memory: ListView");
lvwHwnd = FindWindowEx(mainWindowHwnd, IntPtr.Zero, "SysListView32", IntPtr.Zero);
if (lvwHwnd == (IntPtr)0)
throw new Win32Exception();
}
catch(Exception ex)
{
MessageBox.Show("[" + Marshal.GetLastWin32Error().ToString() + "] - Não foi possível obter o handle do controle filho.\n\n" + ex.ToString(), "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
int lvwItem = 0;
IntPtr pid = (IntPtr)0;
GetWindowThreadProcessId(lvwHwnd, ref pid);
IntPtr _lvi;
IntPtr _subitem = IntPtr.Zero;
IntPtr process = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, false, pid.ToInt32());
LVITEM lvi = new LVITEM();
//process = (IntPtr)(process.ToInt32() - 1);
_lvi = VirtualAllocEx(process, IntPtr.Zero, Marshal.SizeOf(typeof(LVITEM)), MEM_COMMIT, PAGE_READWRITE);
_subitem = VirtualAllocEx(process, IntPtr.Zero, 512, MEM_COMMIT, PAGE_READWRITE);
if(_lvi == IntPtr.Zero)
throw new SystemException("Failed to allocate memory in remote process");
bool bsuccess;
lvi.cchTextMax = 512;
lvi.iSubItem = 1;
lvi.pszText = _subitem;
bsuccess = WriteProcessMemory(process, _lvi, ref lvi, Marshal.SizeOf(typeof(LVITEM)), IntPtr.Zero);
SendMessage(lvwHwnd, LVM_GETITEMTEXT, lvwItem, _lvi);
IntPtr lpBuffer;
lpBuffer = Marshal.AllocHGlobal(512);
string sRet;
IntPtr bytesReaded;
byte[] buffer = new byte[512];
ReadProcessMemory(process, _subitem, buffer, 512, out bytesReaded);
//sRet = Marshal.PtrToStringAnsi(lpBuffer, 512);
VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _subitem, 0, MEM_RELEASE);
}
[DllImport("user32.dll",
CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindowEx(IntPtr parent /*HWND*/,
IntPtr next /*HWND*/,
string sClassName,
IntPtr sWindowTitle);
//'''''''''''''''''''''''''''''''''''''''''''''''
//' Used by the OpenProcess API call
private const long STANDARD_RIGHTS_REQUIRED = 0xF0000;
private const long SYNCHRONIZE = 0x100000;
private const int PROCESS_TERMINATE = 0x1;
private const int PROCESS_CREATE_THREAD = 0x2;
private const int PROCESS_SET_SESSIONID = 0x4;
private const int PROCESS_VM_OPERATION = 0x8;
private const int PROCESS_VM_READ = 0x10;
private const int PROCESS_VM_WRITE = 0x20;
private const long PROCESS_DUP_HANDLE = 0x40;
private const long PROCESS_CREATE_PROCESS = 0x80;
private const long PROCESS_SET_QUOTA = 0x100;
private const long PROCESS_SET_INFORMATION = 0x200;
private const int PROCESS_QUERY_INFORMATION = 0x400;
private const long PROCESS_SUSPEND_RESUME = 0x800;
private const long PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF;
[DllImport("kernel32")]
public static extern IntPtr OpenProcess(int dwDesiredAccess,
bool bInheritHandle,
int dwProcessID);
//'''''''''''''''''''''''''''''''''''''''''''''''
const uint MEM_COMMIT = 0x1000;
const uint MEM_RELEASE = 0x8000;
const uint PAGE_READWRITE = 0x4;
[DllImport("kernel32")]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
int dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
ref LVITEM buffer, int dwSize, IntPtr lpNumberOfBytesWritten);
//Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal msg As Int32, ByVal wParam As IntPtr, ByRef lParam As IntPtr) As Boolean
[DllImport("user32.dll")]
static extern bool SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);
private const int LVM_FIRST = 0x1000;
private const long LVM_GETSELECTEDCOUNT = (LVM_FIRST + 50);
private const long LVM_GETITEMSTATE = (LVM_FIRST + 44);
public const int LVM_GETITEMTEXT = (LVM_FIRST + 45);
public const long LVM_GETITEMCOUNT = LVM_FIRST + 4;
private const long LVIF_TEXT = 0x1;
//'Public Const LVM_GETITEMA = (LVM_FIRST + 5)
//'Public Const LVM_GETITEMW = (LVM_FIRST + 75)
public const long LVM_GETITEM = (LVM_FIRST + 5);
[StructLayout(LayoutKind.Sequential)]
private struct LVITEM
{
public Int16 mask;
public Int16 iItem;
public Int16 iSubItem;
public Int16 state;
public Int16 stateMask;
public IntPtr pszText;
public Int16 cchTextMax;
public Int16 iImage;
}
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
//[In, Out] byte[] buffer,
IntPtr buffer,
UInt32 size,
out IntPtr lpNumberOfBytesRead
);
[DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[In, Out] byte[] buffer,
UInt32 size,
out IntPtr lpNumberOfBytesRead
);
[DllImport("kernel32")]
static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize,
uint dwFreeType);
[DllImport("user32")]
private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd,
ref IntPtr lpdwProcessId);
}
}
|
|
|
|
|
Hallo!
Only the declaration of LVITEM ist wrong!
[StructLayout(LayoutKind.Sequential)]
private struct LVITEM
{
public int mask;
public int iItem;
public int iSubItem;
public int state;
public int stateMask;
public IntPtr pszText;
public int cchTextMax;
public int iImage;
internal int lParam;
internal int iIndent;
}
Best Regards - Kalle
|
|
|
|
|
Here's a cleaner version in a function format. The corresponding C code is in comments. You'll have to cut and paste the constants, dll imports, etc from Marco's code above.
<br />
<br />
public string[,] ReadListView(IntPtr ParentHWND, IntPtr ListViewHWND)<br />
{<br />
string[,] ReturnString = new string[200, 2];<br />
int ReturnStringIndex = 0;<br />
<br />
<br />
<br />
int ListViewItemCount = (int)SendMessage(ListViewHWND, LVM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero);<br />
<br />
if (ListViewItemCount > 200)<br />
ListViewItemCount = 199;<br />
<br />
<br />
<br />
LVITEM ListViewItem = new LVITEM();<br />
IntPtr ListViewItemPointer = IntPtr.Zero;<br />
byte[] ListViewItemBuffer = new byte[512]; byte[] ListViewSubItemBuffer = new byte[512];<br />
IntPtr ListViewPointer_item = IntPtr.Zero; IntPtr ListViewPointer_subitem = IntPtr.Zero;<br />
uint ProcessID=0;<br />
IntPtr ListViewProcessPointer = IntPtr.Zero;<br />
<br />
<br />
GetWindowThreadProcessId(ListViewHWND, out ProcessID);<br />
ListViewProcessPointer = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, false, ProcessID);<br />
<br />
<br />
<br />
ListViewItemPointer = VirtualAllocEx(ListViewProcessPointer, IntPtr.Zero, (uint)Marshal.SizeOf(typeof(LVITEM)), MEM_COMMIT, PAGE_READWRITE);<br />
ListViewPointer_item = VirtualAllocEx(ListViewProcessPointer, IntPtr.Zero, 512, MEM_COMMIT, PAGE_READWRITE);<br />
ListViewPointer_subitem = VirtualAllocEx(ListViewProcessPointer, IntPtr.Zero, 512, MEM_COMMIT, PAGE_READWRITE);<br />
<br />
ListViewItem.cchTextMax = 512;<br />
<br />
<br />
for (int index = 0; index < ListViewItemCount; index++)<br />
{<br />
<br />
<br />
ListViewItem.SubItem = 0;<br />
ListViewItem.pszText = ListViewPointer_item;<br />
WriteProcessMemory(ListViewProcessPointer, ListViewItemPointer, ref ListViewItem, Marshal.SizeOf(typeof(LVITEM)), IntPtr.Zero);<br />
SendMessage(ListViewHWND, LVM_GETITEMTEXT, (IntPtr)index, ListViewItemPointer);<br />
<br />
<br />
ListViewItem.SubItem = 1;<br />
ListViewItem.pszText = ListViewPointer_subitem;<br />
WriteProcessMemory(ListViewProcessPointer, ListViewItemPointer, ref ListViewItem, Marshal.SizeOf(typeof(LVITEM)), IntPtr.Zero);<br />
SendMessage(ListViewHWND, LVM_GETITEMTEXT, (IntPtr)index, ListViewItemPointer);<br />
<br />
<br />
IntPtr bytesReaded;<br />
ReadProcessMemory(ListViewProcessPointer, ListViewPointer_item, ListViewItemBuffer, 512, out bytesReaded);<br />
ReadProcessMemory(ListViewProcessPointer, ListViewPointer_subitem, ListViewSubItemBuffer, 512, out bytesReaded);<br />
<br />
ReturnString[ReturnStringIndex, 0] = Encoding.ASCII.GetString(ListViewItemBuffer);<br />
ReturnString[ReturnStringIndex, 1] = Encoding.ASCII.GetString(ListViewSubItemBuffer);<br />
ReturnStringIndex++;<br />
<br />
}<br />
<br />
<br />
VirtualFreeEx(ListViewProcessPointer, ListViewItemPointer, (UIntPtr)0, MEM_RELEASE);<br />
VirtualFreeEx(ListViewProcessPointer, ListViewPointer_item, (UIntPtr)0, MEM_RELEASE);<br />
VirtualFreeEx(ListViewProcessPointer, ListViewPointer_subitem, (UIntPtr)0, MEM_RELEASE);<br />
<br />
return ReturnString;<br />
<br />
}<br />
<br />
|
|
|
|
|
This save my time of searching solution. Before found this article I nearly go to the hooking that I'm not fully understand. This article explain clearly and easy to follow.
|
|
|
|
|
I use the code and change it a bit.
The code below retrieves text on statusbar "msctls_statusbar32".
I use SB_GETTEXT to send message and retrieves text.
But on statusbar "StatusBar20WndClass", i am getting null string.
I need help on this. Thank you for your suggestions.
Status Bar in a Dialog - Nish for CP - http://www.codeproject.com/statusbar/dlgstatbar01.asp[]
Code:
HWND hwnd=FindWindow(NULL, "TEST");<br />
HWND hStatusBar=FindWindowEx(hwnd, NULL, "StatusBar20WndClass", NULL);<br />
unsigned long pid;<br />
HANDLE process;<br />
char *_item;<br />
char item[512];<br />
GetWindowThreadProcessId(hStatusBar, &pid);<br />
process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_QUERY_INFORMATION, FALSE, pid);<br />
_item=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT, PAGE_READWRITE);<br />
SendMessage(hStatusBar, SB_GETTEXT, (WPARAM)0, (LPARAM)_item);<br />
ReadProcessMemory(process, _item, &item, 512, NULL);<br />
printf("%s",item);<br />
VirtualFreeEx(process, _item, 0, MEM_RELEASE);<br />
return 0;
|
|
|
|
|
Hello doenoe,
I had to adress this problem with the VB StatusBar (StatusBar20WndClass) a long time ago, too. Have you achieved to get this working?
I found out that it works if the statusbar is in its simple mode. But if it is in the "normal", e.g. multiple panel mode it returns an empty string. Sending SB_GETTEXTLENGTH gives SBT_OWNERDRAW as result, e.g. the VB control draws the text itself. The MSDN says that in this case sending SB_GETTEXT gives a 32bit number associated with the string. This seems to be correct, e.g. I get this number. Do you have any idea how to get this text associated with the given number? It is not a memory address. Thus using ReadProcessMemory with this value instead of _item doesn't work...
|
|
|
|
|
Great job with the code, I’ve got some information from Outlook’s Express List View thanks to it. Now I would like to do the same thing but with Microsoft Outlook’s SUPERGRID. I’ve done the same thing as before – Localized SUPERGRID with FindWindowEx(…) and then , because SUPERGRID (from what I know)is derived from CListCtrl which encapsulates the functionality of a "list view” control, I tried to send some LVM_.... messages with SendMessage(…) to get any kind of information. Of course it didn’t work …. any ideas?
|
|
|
|
|
Using similar code I can get a handle to the component but of course the messages do not work. I want to fetch the data from a TStringGrid belonging to a different application. Any ideas?
|
|
|
|
|
can we write some text to list view?
|
|
|
|
|
To write text add the following code after the ReadProcessMemory bit:
<br />
strcopy(item, _T("Bananas"));<br />
WriteProcessMemory(hProcess, _item, &item, 512, NULL);<br />
<br />
SendMessage(ListView, LVM_SETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);<br />
|
|
|
|
|
i think
CloseHandle(process);
is missing there somewhere
|
|
|
|
|
Hi, Very nice code - worked inside 5 minutes on ALL of my apps with any listviews in.
However the actual app I am interested in reading the list view from (a third party windows app with three listviews in) cannot access the list. The valid hadle (from Spy++) for the listview32 comes back with nothing at all count=0 even though I know the listview in question has items in!
Is there any way this code won't work on any windows app if it was written and obfruscated/secured?
Any help appreciated
Clive
|
|
|
|
|
Hi
I am replying to your post in "Stealing Program's Memory" The actual phrase that caught my attention was "However the actual app I am interested in reading the list view from (a third party windows app with three listviews in) cannot access the list
Did you ever find the solution to that? I have an app that doesn't want to behave either
Best Regards Charles
|
|
|
|
|
Is there a way to select an item of a list or set text of a list? Basically the reverse of what was shown here?
|
|
|
|
|
|
|
|
|
Hi,
I'm working on a kind of macro-tool, and want to retrieve the Name of the selected object. But what's even more important: I want to be able to find the control back by this Name!
Is this possible in the way you do this to listviews?
|
|
|
|
|
I have been trying to access the text from a listview today and worked out this little work around.
//-----------------------------
//----------------------------
int index;
HWND ListViewhwnd,LVEditWnd;
TCHAR buf[512];
1.index = ListView_GetHotItem(ListViewhwnd) //returns index of currently selected iteam -1 if none selcted
2.LVEditWnd = ListView_EditLabel(listviewhwnd,index);//place selected item in edit mode which creates an edit control with the label
3.SendMessage(LVEditWnd,WM_GETTEXT,sizeof(buf)/sizeof(TCHAR),(LPARAM)(void*)buf);//get Edit controls text
4. ListView_EditLabel(listviewhwnd,-1);//sending -1 cancels edit mode
//-------------------------------
buf = text of selected item
this gets the text of the currently selected item "what i wanted and you if i read your article correctly" . You could call ListView_GetItemCount() and then loop through the indexs capturing the text in the same way without GetHotItem.
Any one any other ideas ?
|
|
|
|
|
Interesting. Unfortunately it won’t help me bacuse I’m trying to get the column labels instead of cell contents.
--
Synetech
|
|
|
|
|
Here's my Adaptation... it gets all of the columns in the ListView.
I'm primarily a VB programmer so please excuse any blatent errors. :]
I pass the function the handle to the ListView and it returns the data in a member variable (m_strTEXT).
Do you know how to do this with the TreeView?
I'm working on it but haven't gotten very far.
James
-------
void CTestDlg::GETLVTEXT(const HWND hWnd) {
int count=(int)::SendMessage(hWnd, LVM_GETITEMCOUNT, 0, 0);
int i, col=0;
LVITEM lvi, *_lvi;
TCHAR item[512], subitem[512], strTmp[1050];
TCHAR* _item, *_subitem;
unsigned long pid;
HANDLE process;
m_strTEXT.Empty();
GetWindowThreadProcessId(hWnd, &pid);
process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);
_lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
_item=(TCHAR*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT, PAGE_READWRITE);
_subitem=(TCHAR*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT, PAGE_READWRITE);
lvi.cchTextMax=512;
for(i=0; i<count; i++) {
col=0;
lvi.iSubItem=col;
lvi.pszText=_item;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hWnd, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
ReadProcessMemory(process, _item, item, 512, NULL);
m_strTEXT += item;
do
{
col++;
lvi.iSubItem=col;
lvi.pszText=_subitem;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hWnd, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
ReadProcessMemory(process, _subitem, subitem, 512, NULL);
if(_tcscmp(item,subitem) != 0) {
m_strTEXT += _T(",");
m_strTEXT += subitem;
} else {
col = 0;
}
} while(col != 0);
m_strTEXT += strTmp;
m_strTEXT += _T("\x0d\x0a");
}
VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _item, 0, MEM_RELEASE);
VirtualFreeEx(process, _subitem, 0, MEM_RELEASE);
}
|
|
|
|
|
Check it out... I got it... Not bad for a VB guy eh?
James
---------
Here's the main function.
void CTestDlg::GETTVTEXT(const HWND hWnd) {
int i, col=0, count=0;
long lret;
TV_ITEM tvi, *_tvi;
HTREEITEM hItem, hItemChild, hItemSibling;
TCHAR item[MAXTEXTLEN], strTmp[MAXTEXTLEN];
TCHAR *_item;
unsigned long pid;
HANDLE process;
m_strTEXT.Empty();
GetWindowThreadProcessId(hWnd, &pid);
process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);
_tvi=(TV_ITEM*)VirtualAllocEx(process, NULL, sizeof(TV_ITEM), MEM_COMMIT, PAGE_READWRITE);
_item=(TCHAR*)VirtualAllocEx(process, NULL, MAXTEXTLEN, MEM_COMMIT, PAGE_READWRITE);
tvi.cchTextMax=MAXTEXTLEN;
count = (int)::SendMessage(hWnd, TVM_GETCOUNT, 0, 0);
hItem = (HTREEITEM)::SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
while (hItem != NULL)
{
tvi.hItem = hItem;
tvi.mask = TVIF_TEXT | TVIF_CHILDREN;
tvi.pszText=_item;
tvi.cchTextMax = MAXTEXTLEN;
WriteProcessMemory(process, _tvi, &tvi, sizeof(TVITEMEX), NULL);
::SendMessage(hWnd, TVM_GETITEM, 0, (LPARAM)_tvi);
lret = ReadProcessMemory(process, _item, item, MAXTEXTLEN, NULL);
m_strTEXT += item;
m_strTEXT += _T("\x0d\x0a");
if (tvi.cChildren)
{
hItemChild = (HTREEITEM)::SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
tvi.hItem = hItemChild;
tvi.mask = TVIF_TEXT | TVIF_CHILDREN;
tvi.pszText=_item;
tvi.cchTextMax = MAXTEXTLEN;
WriteProcessMemory(process, _tvi, &tvi, sizeof(TVITEMEX), NULL);
::SendMessage(hWnd, TVM_GETITEM, 0, (LPARAM)_tvi);
lret = ReadProcessMemory(process, _item, item, MAXTEXTLEN, NULL);
m_strTEXT += _T("-");
m_strTEXT += item;
m_strTEXT += _T("\x0d\x0a");
if (tvi.cChildren && hItemChild != NULL)
GETTVChildren(hWnd, hItemChild, 2);
hItemSibling = (HTREEITEM)::SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItemChild);
while(hItemSibling != NULL)
{
tvi.hItem = hItemSibling;
tvi.mask = TVIF_TEXT | TVIF_CHILDREN;
tvi.pszText=_item;
tvi.cchTextMax = MAXTEXTLEN;
WriteProcessMemory(process, _tvi, &tvi, sizeof(TVITEMEX), NULL);
::SendMessage(hWnd, TVM_GETITEM, 0, (LPARAM)_tvi);
ReadProcessMemory(process, _item, item, MAXTEXTLEN, NULL);
m_strTEXT += _T("-");
m_strTEXT += item;
m_strTEXT += _T("\x0d\x0a");
if (tvi.cChildren && hItemSibling != NULL)
GETTVChildren(hWnd, hItemSibling, 2);
hItemSibling = (HTREEITEM)::SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItemSibling);
}
}
hItem = (HTREEITEM)::SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
}
VirtualFreeEx(process, _tvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _item, 0, MEM_RELEASE);
}
|
|
|
|
|
Could you post GETTVChildren too?
|
|
|
|
|
void CTestDlg::GETTVChildren(const HWND hWnd, HTREEITEM hItem, long lLevel) {
int i, col=0, count=0;
TV_ITEM tvi, *_tvi;
HTREEITEM hItemChild, hItemSibling;
TCHAR item[MAXTEXTLEN], strTmp[MAXTEXTLEN];
TCHAR *_item;
unsigned long pid;
HANDLE process;
GetWindowThreadProcessId(hWnd, &pid);
process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);
_tvi=(TV_ITEM*)VirtualAllocEx(process, NULL, sizeof(TV_ITEM), MEM_COMMIT, PAGE_READWRITE);
_item=(TCHAR*)VirtualAllocEx(process, NULL, MAXTEXTLEN, MEM_COMMIT, PAGE_READWRITE);
tvi.cchTextMax=MAXTEXTLEN;
hItemChild = (HTREEITEM)::SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
tvi.hItem = hItemChild;
tvi.mask = TVIF_TEXT | TVIF_CHILDREN;
tvi.pszText=_item;
tvi.cchTextMax = MAXTEXTLEN;
WriteProcessMemory(process, _tvi, &tvi, sizeof(TVITEMEX), NULL);
::SendMessage(hWnd, TVM_GETITEM, 0, (LPARAM)_tvi);
ReadProcessMemory(process, _item, item, MAXTEXTLEN, NULL);
if (hItemChild != NULL) {
for(count=0;count<lLevel;count++)
m_strTEXT += _T("-");
m_strTEXT += item;
m_strTEXT += _T("\x0d\x0a");
if (tvi.cChildren)
GETTVChildren(hWnd, hItemChild, lLevel+1);
}
hItemSibling = (HTREEITEM)::SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItemChild);
while(hItemSibling != NULL)
{
tvi.hItem = hItemSibling;
tvi.mask = TVIF_TEXT | TVIF_CHILDREN;
tvi.pszText=_item;
tvi.cchTextMax = MAXTEXTLEN;
WriteProcessMemory(process, _tvi, &tvi, sizeof(TVITEMEX), NULL);
::SendMessage(hWnd, TVM_GETITEM, 0, (LPARAM)_tvi);
ReadProcessMemory(process, _item, item, MAXTEXTLEN, NULL);
if (hItemSibling != NULL) {
for(count=0;count<lLevel;count++)
m_strTEXT += _T("-");
m_strTEXT += item;
m_strTEXT += _T("\x0d\x0a");
if (tvi.cChildren)
GETTVChildren(hWnd, hItemSibling, lLevel+1);
}
hItemSibling = (HTREEITEM)::SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItemSibling);
}
VirtualFreeEx(process, _tvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _item, 0, MEM_RELEASE);
}
|
|
|
|
|