Can the following Function be used "as is" as Remo

delphi package - getting into other processes

Can the following Function be used "as is" as Remo

Postby vmars » Sun Feb 20, 2005 5:09 am

Can the following Function be used "as is" as:
a MadRemote thread function, which will be copied to and then executed in the context of another process.
If not, please what will need to be changed?
Thanks!

function LB_GetAllItems(hWnd: THandle; sl: TStrings): string; stdcall;
var
RetBuffer: string;
i, x, y: Integer;
begin
x := SendMessage(hWnd, LB_GETCOUNT, 0, 0);
for i := 0 to x - 1 do
begin
y := SendMessage(hWnd, LB_GETTEXTLEN, i, 0);
SetLength(RetBuffer, y);
SendMessage(hWnd, WM_GETTEXT, i, lParam(PChar(RetBuffer)));
sl.Add(RetBuffer);
end;
end;

...Vern
vmars
 
Posts: 12
Joined: Sat Jan 22, 2005 8:15 am
Location: Keaau, Hi

Postby madshi » Mon Feb 21, 2005 7:32 am

No, that doesn't work. Using "string" ends up in calling all kinds of Delphi magic RTL functions, which are not available in the other process. TStrings methods are also not available in the other process.

You can use a different solution, though:

(1) LB_GETCOUNT and LB_GETTEXTLEN work directly without any fancy stuff, anyway.
(2) Allocate memory in the other process by using madRemote.AllocMemEx.
(3) Use SendMessage from your program, but give in the buffer you just allocated in (2).
(4) Use ReadProcessMemory to copy the content of the buffer to your own process.
(5) Use madRemote.FreeMemEx to free the memory in the other process again.

Done.
madshi
Site Admin
 
Posts: 9338
Joined: Sun Mar 21, 2004 5:25 pm

Postby vmars » Tue Feb 22, 2005 2:33 am

Still same old battle:
LB_GETCOUNT works fine.
But LB_GETTEXTLEN and WM_GETTEXT rquire that i be attached to that process somehow. As is, LB_GETTEXTLEN always returns a length of 4 (length of pointer).
So, as you say, i've got to change Tstrings and Strings to some thing else:
Will type RECORDS work, and pass stuff back and forth
one line at a time?
I am hoping to whittle it down to your
function GetCmdLineThread(buffer: pchar) : dword; stdcall;
example, one line at a time.
Thanks!...Vern


function LB_GetAllItems(hWnd: THandle; sl: TStrings): string;
var
RetBuffer: string;
i, x, y: Integer;
params : pointer; pid, processHandle: dword;
begin
x := SendMessage(hWnd, LB_GETCOUNT, 0, 0);
If x > 0 Then
Begin
GetWindowThreadProcessID(hWnd, @pid);
processHandle := OpenProcess(PROCESS_ALL_ACCESS, false, pid);
params := AllocMemEx(MAX_PATH, processHandle);
for i := 0 to x - 1 do
begin
y := SendMessage(hWnd, LB_GETTEXTLEN, i, 0);
SetLength(RetBuffer, y);
SendMessage(hWnd, WM_GETTEXT, i, lParam(PChar(params)));
RetBuffer := PChar(params);
ShowMessage('RetBuffer = ' + RetBuffer);
sl.Add(RetBuffer);
end; // for i := 0 to x - 1 do
CloseHandle(processHandle);
FreeMemEx(params, processHandle);
end; // If x > 0 Then
end;
vmars
 
Posts: 12
Joined: Sat Jan 22, 2005 8:15 am
Location: Keaau, Hi

Postby madshi » Tue Feb 22, 2005 7:36 am

There are a few errors in your code:

(1) You shouldn't use WM_GETTEXT on a list box. Use LB_GETTEXT instead.
(2) You can't use "RetBuffer := PChar(params)", because params is a pointer which is valid only in the other process. Instead use ReadProcessMemory to copy the content of params to RetBuffer.
(3) The following code is obviously wrong:

CloseHandle(processHandle);
FreeMemEx(params, processHandle);

You can't close a process handle and then use it one line later!
madshi
Site Admin
 
Posts: 9338
Joined: Sun Mar 21, 2004 5:25 pm

Postby vmars » Tue Feb 22, 2005 10:59 am

1 Ok, i was switching them back and forth, trying to get one or other to work. Will stick with LB.
2. Instead use ReadProcessMemory to copy the content of params to RetBuffer.
Aha, that's where ReadProcessMemory comes in.
3. Oops.
Thanks!

What i would like to do in your
function GetCmdLineThread(buffer: pchar) : dword; stdcall;
Is to add another parameter:

function GetCmdLineThread(buffer: pchar; GetLineNum: Integer) : dword; stdcall;

But can't get passed:
th := CreateRemoteThreadEx(processHandle, nil, 0, entryPoint, params, 0, tid);
In function GetProcessCmdLine
When i change it to this:
th := CreateRemoteThreadEx(processHandle, nil, 0, entryPoint, (params, pLineNum), 0, tid);

Please, how would i do this?
Thanks!
vmars
 
Posts: 12
Joined: Sat Jan 22, 2005 8:15 am
Location: Keaau, Hi

Postby madshi » Tue Feb 22, 2005 11:05 am

You can't. Remote threads only accept one parameter. You could allocate a memory block in the other process and store all parameters there and then pass the address to that block to the remote thread.

But why using remote threads at all? The solution I suggested should definately work - without remote threads. It's faster and better that way.
madshi
Site Admin
 
Posts: 9338
Joined: Sun Mar 21, 2004 5:25 pm

Owner Drawn ListBox

Postby vmars » Wed Feb 23, 2005 8:37 pm

The code below runs, but ReadProcessMemory always returns #0(s) in RetBuffer.
LB_GETTEXTLEN always returns 4 in y , so i plugged 'len' with 260 to match RemoteBuff.
I believe LB_GETTEXTLEN must run in remote process; hWnd is OwnerDrawn ListBox,
which is why i have been leaning toward converting your 'RemoteCmdLine.dpr'.


Function LB_GetAllItems(hWnd: THandle; sl: TStrings): string;
var
RetBuffer: string;
i, x, y : Integer; len : dword;
RemoteBuff : pointer; pid, processHandle: dword;
begin
x := SendMessage(hWnd, LB_GETCOUNT, 0, 0);
If x > 0 Then
Begin
GetWindowThreadProcessID(hWnd, @pid);
// hWnd is OwnerDrawn ListBox
processHandle := OpenProcess(PROCESS_ALL_ACCESS, false, pid);
RemoteBuff := AllocMemEx(MAX_PATH, processHandle);
for i := 0 to x - 1 do
begin
len := 260;
y := SendMessage(hWnd, LB_GETTEXTLEN, i, 0);
SetLength(RetBuffer, 260);
SendMessage(hWnd, LB_GETTEXT, i, lParam(PChar(RemoteBuff)));
ReadProcessMemory(processHandle, RemoteBuff, pointer(RetBuffer), len, len);
// ShowMessage('RetBuffer = ' + RetBuffer);
sl.Add(RetBuffer);
end; // for i := 0 to x - 1 do
FreeMemEx(RemoteBuff, processHandle);
CloseHandle(processHandle);
end; // If x > 0 Then
end;

procedure TForm1.GetAllItemsClick(Sender: TObject);
var
sl: TStringList;
ListBox_Handle: THandle;
begin
ListBox_Handle := hWnd; // listbox handle global
sl := TStringList.Create;
try
LB_GetAllItems(ListBox_Handle, sl);
finally
ListBox1.Lines.Text := sl.Text;
sl.Free;
end;
end;
vmars
 
Posts: 12
Joined: Sat Jan 22, 2005 8:15 am
Location: Keaau, Hi

Re: Owner Drawn ListBox

Postby madshi » Wed Feb 23, 2005 9:35 pm

vmars wrote:I believe LB_GETTEXTLEN must run in remote process

Wrong.

vmars wrote:hWnd is OwnerDrawn ListBox

Oh, then forget it. LB_GETTEXTLEN won't work in that case, regardless from which process you call it. "RemoteCmdLine" won't help, either.

The only thing which might work is hooking TextOutA/W and ExtTextOutA/W and then invalidating the listbox, hoping that it's not double buffered. For that purpose you must use madCodeHook and put all the hooking code into a hook dll. That's gonna be difficult.
madshi
Site Admin
 
Posts: 9338
Joined: Sun Mar 21, 2004 5:25 pm


Return to madRemote

Who is online

Users browsing this forum: No registered users and 1 guest