Solved

ListView_GetItem

Posted on 2002-04-12
19
1,479 Views
Last Modified: 2008-05-16
Hi.

I'm having real problems using the ListView_ macros in CommCtrl.pas

Can someone tell me what's wrong with this please?

////////////////////////// Delphi Code ////////////////////////////

procedure ShowItems;
var
  CPManager,
  ListView    : hWnd;
  TmpPC       : PChar;
  ListItem    : LV_ITEM;
  CurrentPos,
  ItemCount   : Integer;
begin
  CPManager:=FindWindow('TCPManager_MainWindow', 'CP Manager');
  ListView:=FindWindowEx(CPManager, 0, 'TListView', nil);
  GetMem(TmpPC, 255);
  ItemCount:=ListView_GetItemCount(ListView);
  for CurrentPos:=0 to ItemCount-1 do begin
    ListItem.mask:=LVIF_TEXT;
    ListItem.iItem:=CurrentPos;
    ListItem.iSubItem:=0;
    ListItem.pszText:=TmpPC;
    ListItem.cchTextMax:=255;
    if ListView_GetItem(ListView, ListItem) then
      ShowMessage(TmpPC);
  end;
  FreeMem(TmpPC);
end;

///////////////////////////////////////////////////////////////////


Thanks for any help,

MoonCalf
0
Comment
Question by:MoonCalf
  • 6
  • 6
  • 4
  • +3
19 Comments
 
LVL 1

Expert Comment

by:Alone
ID: 6937554
But what are you want to do?
0
 
LVL 2

Expert Comment

by:Tasomia
ID: 6937561
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 6937583
I don't know what exactly you are trying to do, but I do see one glaring problem. You VAR'ed TempPc as PChar and never initliazed it or assigned it a value before assigning ListItem.pszText equal to TempPc. And then you go on the show TempPc, which STILL doesn't have a value.


Good luck!!


BTW, you needn't use GetMem for Pchar... StrPcopy is cleaner. If you insist on using GetMem, you should free up that pointer with FreeMem.


GL

 
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 6937584
I don't know what exactly you are trying to do, but I do see one glaring problem. You VAR'ed TempPc as PChar and never initliazed it or assigned it a value before assigning ListItem.pszText equal to TempPc. And then you go on the show TempPc, which STILL doesn't have a value.


Good luck!!


BTW, you needn't use GetMem for Pchar... StrPcopy is cleaner. If you insist on using GetMem, you should free up that pointer with FreeMem.


GL

 
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 6937585
oops! G-g-g-got a little stutter there! S-S-S-S-Sooorry!

0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 6937590
I have to apologize again. I just noticed that you do in fact make a call to FreeMem. What can I say? It's been a long week! <g>

Good luck!!
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6939930
I guess you want to ask the list view of another process, right? I'm sorry to say, but the list view stuff works internally with messages. And most of them contain pointers. And in 32bit programming a pointer is private to each process. So this all doesn't work with list views of other processes.

The usual solution to your problem would be to put your list view loop into a little dll and inject this dll into the other process. There's also another solution, but it's undocumented...

Regards, Madshi.
0
 
LVL 1

Author Comment

by:MoonCalf
ID: 6941230
Hi Guys.

Thank you, everyone, for all comments.  Every comment is appreciated.

Madshi - "There's also another solution, but it's undocumented..."????

Could you explain it a little for me?

Thanks,

MoonCalf.
0
 
LVL 1

Author Comment

by:MoonCalf
ID: 6941255
BTW, Tasomia : Thanks for the example which is great, but I was hoping that by answering the question I could also learn to manipulate an external processeses ListView.  (For example, the Task Manager.)

Thanks,

MoonCalf.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 20

Expert Comment

by:Madshi
ID: 6941345
Well, you are sending a pointer to the list view of another process. The other process now wants to write the requested information to the address you gave in. But the other process writes the information in the address in its own memory/address context. Now in NT we can do the following:

(1) Allocate memory in the context of the other process by using VirtualAllocEx.
(2) Send the list view message, giving in the pointer you got from (1). Now the other process can correctly save the requested info to the requested address.
(3) But the info is now in the context of the other process, so we have to use ReadProcessMemory to get access to that info.
(4) Finally you should free the allocated memory from (1) by using VirtualFreeEx.

I'm using this logic quite often, it works absolutely fine. Unfortunately win9x doesn't support VirtualAllocEx/VirtualFreeEx, there comes the undocumented part: You can set up a memory mapped file (CreateFileMapping(-1, ...) + MapViewOfFile). The buffer will be in shared memory (which is shared between all processes system wide), so the other process can successfully write to the address and you can successfully read it - without even using ReadProcessMemory.

Regards, Madshi.
0
 
LVL 1

Author Comment

by:MoonCalf
ID: 6941354
Hi Madshi.  Thanks for the comment, but huh??

Could you do me an example please.  You're talking about something that I have absolutely no idea about!

Thanks,

MoonCalf.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6941362
Ehm, sorry, no time for a real tested example. Let me just hack a bit with your sources, maybe it helps you understanding what I mean:

procedure ShowItems;
var
 CPManager,
 ListView    : hWnd;
 TmpPC       : PChar;
 PListItem   : ^LV_ITEM;
 ListItem    : LV_ITEM;
 CurrentPos,
 ItemCount   : Integer;
 pid         : dword;  // process ID
 ph          : dword;  // process handle
 c1          : dword;  // dummy variable
 arrCh
begin
 CPManager:=FindWindow('TCPManager_MainWindow', 'CP Manager');
 ListView:=FindWindowEx(CPManager, 0, 'TListView', nil);

 // ask the process ID of the other process
 GetWindowThreadProcessID(ListView, @pid);

 // open the other process
 ph := OpenProcess(PROCESS_ALL_ACCESS, false, pid);

 // allocate memory in the other process
 TmpPC := VirtualAllocEx(ph, nil, 255, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 PListItem := VirtualAllocEx(ph, nil, sizeOf(LV_ITEM), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

 ItemCount:=ListView_GetItemCount(ListView);
 for CurrentPos:=0 to ItemCount-1 do begin
   ListItem.mask:=LVIF_TEXT;
   ListItem.iItem:=CurrentPos;
   ListItem.iSubItem:=0;
   ListItem.pszText:=TmpPC;
   ListItem.cchTextMax:=255;
   WriteProcessMemory(ph, PListItem, @ListItem, sizeOf(ListItem), c1);
   if ListView_GetItem(ListView, PListItem^) then begin
     ReadProcessMemory(
     ShowMessage(TmpPC);
   end;
 end;
 FreeMem(TmpPC);
end;
0
 
LVL 1

Author Comment

by:MoonCalf
ID: 6941366
Thanks.  I'll give it a try and get back.

MoonCalf.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6941368
Sorry, I accidently hit the submit button, was not ready yet. Real code comes in a few moment...
0
 
LVL 1

Author Comment

by:MoonCalf
ID: 6941370
ok
0
 
LVL 20

Accepted Solution

by:
Madshi earned 200 total points
ID: 6941375
I guess this one should work in NT/2k/XP, but it will not work in 95/98/ME, because VirtualAllocEx is not supported there. Sorry, but you have to care about the 9x solution yourself, I told you how to do it, that's all I can do now, have no more time...

procedure ShowItems;
var CPManager,
    ListView    : hWnd;
    TmpPC       : PChar;
    PListItem   : ^LV_ITEM;
    ListItem    : LV_ITEM;
    CurrentPos,
    ItemCount   : Integer;
    pid         : dword;  // process ID
    ph          : dword;  // process handle
    c1          : dword;  // dummy variable
    arrCh       : array [0..255] of char;
begin
  CPManager:=FindWindow('TCPManager_MainWindow', 'CP Manager');
  ListView:=FindWindowEx(CPManager, 0, 'TListView', nil);

  // ask the process ID of the other process
  GetWindowThreadProcessID(ListView, @pid);

  // open the other process
  ph := OpenProcess(PROCESS_ALL_ACCESS, false, pid);

  // allocate memory in the other process
  TmpPC := VirtualAllocEx(ph, nil, 255, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  PListItem := VirtualAllocEx(ph, nil, sizeOf(LV_ITEM), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

  ItemCount:=ListView_GetItemCount(ListView);
  for CurrentPos:=0 to ItemCount-1 do begin
    ListItem.mask:=LVIF_TEXT;
    ListItem.iItem:=CurrentPos;
    ListItem.iSubItem:=0;
    ListItem.pszText:=TmpPC;
    ListItem.cchTextMax:=255;

    // write the prepared item to the other process
    WriteProcessMemory(ph, PListItem, @ListItem, sizeOf(ListItem), c1);

    // ask the item content
    if ListView_GetItem(ListView, PListItem^) then begin

      // read the item string back from the other process and show it
      ReadProcessMemory(ph, TmpPC, @arrCh, 255, c1);
      ShowMessage(arrCh);
    end;
  end;
  // free the memory of the other process
  VirtualFreeEx(ph, TmpPC, 0, MEM_RELEASE);
  VirtualFreeEx(ph, PListItem, 0, MEM_RELEASE);

  // close handle
  CloseHandle(ph);
end;
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6941388
Madshi rulez! :)
0
 
LVL 1

Author Comment

by:MoonCalf
ID: 6941397
What can I say?

Thanks Madshi, that was perfect.

Thanks everyone else, but Madshi's example has give me enough insight into this to get on with the project and do all that other stuff myself.

MoonCalf.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6941413
Thanx, guys...   :-)
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now