Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.05.14;
Скачать: CL | DM;

Вниз

Ошибка с LISTVIEW   Найти похожие ветки 

 
Дубинка   (2006-02-19 20:46) [0]

var
 h1, h2, h3: HWND;
 lvFindInfo: LV_FINDINFO;

 h1 := FindWindow(nil, "Диспетчер задач Windows");
 h2 := FindWindowEx(h1, 0, nil, "");
 h3 := FindWindowEx(h2, 0, "SysListView32", "Процессы");
 ListView_FindItem(h3, -1, lvFindInfo);


Конечно понять для чего нужен этот код просто, я думаю, но вот понять почему он не канает - диспетчер задач завершается ошибкой - у меня мозгов не хватает понять....


 
begin...end ©   (2006-02-19 21:11) [1]

> Дубинка   (19.02.06 20:46)
> ListView_FindItem(h3, -1, lvFindInfo)

Здесь третьим параметром фактически передаётся указатель на структуру типа LV_FINDINFO, расположенную в памяти Вашего процесса. Оконная процедура "чужого" ListView"а, получив сообщение LVM_FINDITEM, а в качестве его параметра -- этот указатель, будет рассматривать последний как адрес структуры в адресном пространстве своего процесса. А там такой структуры нет -- отсюда и ошибка.


 
Дубинка   (2006-02-19 22:09) [2]

хе-хе.... я сразу почему-то до этого не допер(ла)....
Я вообще ноль в работе с чужими приложениями... по сути как засунуть по данному адресу во вражеский процесс пару байт я знаю, а вот как найти "чистый" кусок памяти для этого? ну чтоб я ему ничего не испортил... Ну и как соответственно отметить это самое изменение вы мне не подскажите?


 
Хинт ©   (2006-02-20 08:56) [3]

Вот кусок кода из одного моего проекта. Немного модифицировать и...
procedure GetText(ListWND: HWND; Lines: TStrings);
const
 PROCESS_ACCESS = PROCESS_VM_OPERATION or PROCESS_VM_READ or
   PROCESS_VM_WRITE;
type
 PProcData = ^TProcData;
 TProcData = record
   Item: TLVItemA;
   Txt: packed array[0..1023] of AnsiChar;
   ItemRect: TRect;
 end;
var
 Cnt, I,J: Integer;
 ProcID: DWORD;
 ProcessHandle: THandle;
 Data: TProcData;
 RemoteProcData: PProcData;
 Res: Boolean;
 LI: TListItem;
 ColWid: Integer;
 pt: TPoint;
 List:Array of record
   count,item:string;
   end;
begin
 ProcID := 0;
 GetWindowThreadProcessId(ListWND, ProcID);
 if ProcId = 0 then
 begin
   MessageDlg("Cannot retrieve process ID.", mtError, [mbOK], 0);
   Exit;
 end;

 ProcessHandle := OpenProcess(PROCESS_ACCESS, False, ProcID);
 if ProcessHandle = 0 then RaiseLastOSError;
 try
   RemoteProcData := VirtualAllocEx(ProcessHandle, nil,
     SizeOf(RemoteProcData^), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
   if RemoteProcData = nil then RaiseLastOSError;
   try
     Cnt := ListView_GetItemCount(ListWND);
     setlength(list,cnt);
     Lines.Clear;
     for I := 0 to Cnt - 1 do for j:=0 to 1 do
     begin
       FillChar(Data, SizeOf(Data), 0);
       with Data.Item do
       begin
         iSubItem := j;
         pszText := @RemoteProcData^.Txt;
         cchTextMax := SizeOf(RemoteProcData^.Txt) - 1;
       end;

       Res := WriteProcessMemory(ProcessHandle, RemoteProcData,
         @Data, SizeOf(Data), PLongWord(nil)^);
       if not Res then RaiseLastOSError;

       SendMessage(ListWND, LVM_GETITEMTEXT, I, LPARAM(@RemoteProcData^.Item));

       SendMessage(ListWND, LVM_GETITEMRECT, I, LPARAM(@RemoteProcData^.ItemRect));

       Res := ReadProcessMemory(ProcessHandle, RemoteProcData,
         @Data, SizeOf(Data), PLongWord(nil)^);
       if not Res then RaiseLastOSError;

       if j=0 then List[i].item:=data.Txt else
         begin
          List[i].count:=data.txt;
          Lines.Add(List[i].item+" - "+List[i].count);
         end;

     end;
   finally
     Res := LongBool(VirtualFreeEx(ProcessHandle, RemoteProcData,
       0, MEM_RELEASE));
     if not Res then RaiseLastOSError;
   end;
 finally
   CloseHandle(ProcessHandle);
 end;
end;


 
begin...end ©   (2006-02-20 08:59) [4]

> Дубинка   (19.02.06 22:09) [2]

Находить чистые куски самостоятельно не придётся. Нужно запросить нужный объём памяти в чужом процессе (предварительно получив дескриптор процесса) с помощью функции VirtualAllocEx, передав ей в качестве второго параметра (желаемого начального адреса региона) 0 -- это означает, что функция выделит память там, где посчитает нужным.

Если функция отработает успешно, она вернёт значение, отличное от нуля -- базовый адрес выделенной памяти в адресном пространстве чужого процесса. Теперь по этому адресу можно записывать то, что Вам нужно. Конкретно для данного примера нужно будет записать, во-первых, саму структуру LV_FINDINFO. Во-вторых, если предполагается использовать тип поиска LVFI_STRING (т.е. поиск элементов, заголовки которых полностью или частично совпадают с некоторой указанной строкой), то в LV_FINDINFO нужно будет инициализировать поле psz, а именно -- поместить туда указатель на строку-образец. Причём этот указатель тоже должен быть действителен именно в чужом процессе. А значит, выделять память в нём нужно не только под структуру LV_FINDINFO, но и под строку.

ОК, теперь память выделена, в неё записаны строка и структура LV_FINDINFO . Вот теперь можно посылать LVM_FINDITEM (или использовать ListView_FindItem), причём это уже можно делать из своего процесса.

А после того, как сообщение будет обработано, выделенную "чужую" память надо освободить (если она больше не понадобится).



Страницы: 1 вся ветка

Текущий архив: 2006.05.14;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.039 c
15-1143752553
__Иксик__
2006-03-31 01:02
2006.05.14
Любэ


6-1137857835
GanibalLector
2006-01-21 18:37
2006.05.14
(Berkeley-style sockets) теория


3-1142934088
SLP
2006-03-21 12:41
2006.05.14
Запись структурированных данных в поле таблицы


15-1145340053
Некто_
2006-04-18 10:00
2006.05.14
ГОСТ Р 41.52-2001 (Правила ЕЭК ООН № 52)


8-1134761568
Expl
2005-12-16 22:32
2006.05.14
движение TLabel