Конференция "WinAPI" » Альтернатива SendMessage [D7, WinXP]
 
  • Rouse_ © (08.04.09 15:57) [20]

    > Так точно не получится, надо в другое приложение DLL внедрять

    Библиотеку то зачем?
  • аноним (08.04.09 19:00) [21]

    > Про маршаллинг сообщений.Некоторые структуры таки оказываются
    > "чудом" в чужом процессе. Все структуры сообщений, что меньше
    > WM_USER

    Тут как раз таки никакого волшебства, система про эти сообщения знает, знает размер структуры или строки и копирует в адресное пространство все это.
    В данном случае надо это делать самому, без магии все ручками
    ИМХО тут WM_COPYDATA лучший вариант
  • Rouse_ © (08.04.09 22:31) [22]
    Никак не могу понять, чем WM_COPYDATA (будучи упомянутой уже дважды в данной ветке) может помочь при отправке того-же DTM_SETSYSTEMTIME?
  • Игорь Шевченко © (08.04.09 22:51) [23]
    Rouse_ ©   (08.04.09 22:31) [22]


    > Никак не могу понять, чем WM_COPYDATA (будучи упомянутой
    > уже дважды в данной ветке) может помочь при отправке того-
    > же DTM_SETSYSTEMTIME?


    ну если DTM_SETSYSTEMTIME не получается, может DateTimePicker на WM_COPYDATA согласится...
  • Игорь404 (09.04.09 07:24) [24]
    С WM_COPYDATA у меня таки ничего не получилось. Да даже еслиб и получилось, то как в этом случае быть с TreeView?
  • clickmaker © (09.04.09 10:00) [25]
    > даже еслиб и получилось, то как в этом случае быть с TreeView?

    а почему тривью должно вдруг обрабатывать wm_copydata?
  • Rouse_ © (09.04.09 10:10) [26]

    > как в этом случае быть с TreeView?

    Вот тебе старый пример работы с CommCtrl окнами в удаленном процессе, делай по аналогии:

    ////////////////////////////////////////////////////////////////////////////////
    //
    //  ****************************************************************************
    //  * Unit Name : RemoteSysListView32
    //  * Purpose   : Демо работы с удаленным SysListView32
    //  * Author    : Александр (Rouse_) Багель
    //  * Copyright : © Fangorn Wizards Lab 1998 - 2007
    //  * Version   : 1.01
    //  * Home Page : http://rouse.drkb.ru
    //  ****************************************************************************
    //

    program RemoteSysListView32;

    {$APPTYPE CONSOLE}

    uses
     Windows,
     SysUtils,
     CommCtrl;

    var
     hwndRemoteSysListView: HWND = 0;
     hProcess: THandle = 0;
     dwProcessID: DWORD = 0;
     dwBytesWriten: DWORD;
     nItemCount: Integer = 0;
     I, nTextLength: Integer;
     cchTextMax: Integer = 255;
     plviRemoteLVItem: PLVItem = nil;
     lviRemoteLVItem: LV_ITEM;
     pszText: PChar = nil;
     svText: ShortString;
     ARect: TRect;
     pRemoteRect: Pointer = nil;

     function GetFirstChild(hwndValue: HWND): HWND;
     begin
       Result := GetWindow(hwndValue, GW_CHILD);
     end;

     function Translate(Value: String): String;
     begin
       SetLength(Result, Length(Value));
       AnsiToOem(@Value[1], @Result[1]);
     end;

    begin
     // Ищем SysListView32 рабочего стола
     hwndRemoteSysListView := GetFirstChild(GetFirstChild(FindWindow('ProgMan', nil)));
     if hwndRemoteSysListView = 0 then ExitProcess(GetLastError);

     // Получаем количество элементов (ярлыков на рабочем столе)
     nItemCount := ListView_GetItemCount(hwndRemoteSysListView);

     // Получаем ID процесса, которому принадлежит найденное окно
     GetWindowThreadProcessId(hwndRemoteSysListView, @dwProcessID);
     if dwProcessID = 0 then ExitProcess(GetLastError);

     // Открываем процесс
     hProcess := OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessID);
     if hProcess = 0 then ExitProcess(GetLastError);

     // Выделяем в нем память под текстовый буффер
     pszText := VirtualAllocEx(hProcess, nil, cchTextMax,
      MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
     if GetLastError <> 0 then ExitProcess(GetLastError);

     // Выделяем в нем память под структуру LVITEM
     plviRemoteLVItem := VirtualAllocEx(hProcess, nil, SizeOf(LV_ITEM),
      MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
     if GetLastError <> 0 then ExitProcess(GetLastError);

     // Заполняем структуру
     ZeroMemory(@lviRemoteLVItem, SizeOf(LV_ITEM));
     lviRemoteLVItem.mask := LVIF_TEXT;
     lviRemoteLVItem.pszText := pszText;
     lviRemoteLVItem.cchTextMax := cchTextMax;

     // Пишем ее в память удаленного процесса
     if not WriteProcessMemory(hProcess, plviRemoteLVItem, @lviRemoteLVItem,
       SizeOf(LV_ITEM), dwBytesWriten) then ExitProcess(GetLastError);

     // Выделяем в нем память под структуру TRect
     pRemoteRect := VirtualAllocEx(hProcess, nil, SizeOf(TRect),
      MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
     if GetLastError <> 0 then ExitProcess(GetLastError);

     // Получаем текст со всех элементов
     for I := 0 to nItemCount - 1 do
     begin
       // Отправляем сообщение с указателем на выделенный буффер под LVITEM
       nTextLength := SendMessage(hwndRemoteSysListView, LVM_GETITEMTEXT,
         I, Integer(plviRemoteLVItem));

       // Читаем результат
       ZeroMemory(@svText, cchTextMax);
       ReadProcessMemory(hProcess, lviRemoteLVItem.pszText,
         @svText[1], nTextLength, dwBytesWriten);

       // Чтобы получить координаты каждого элемента нужно подготовить структуру
       ZeroMemory(@ARect, SizeOf(TRect));
       ARect.Left := LVIR_ICON;
       if not WriteProcessMemory(hProcess, pRemoteRect, @ARect,
         SizeOf(TRect), dwBytesWriten) then ExitProcess(GetLastError);

       // Посылаем сообщение для получения координат каждого элемента
       SendMessage(hwndRemoteSysListView, LVM_GETITEMRECT,
         I, Integer(pRemoteRect));

       // Читаем результат
       ReadProcessMemory(hProcess, pRemoteRect,
         @ARect, SizeOf(TRect), dwBytesWriten);

       Writeln(Translate(PChar(@svText[1])));
       Writeln(Translate(
         Format('- координаты: Left = %d, Top = %d, Right = %d, Bottom = %d',
           [ARect.Left, ARect.Top, ARect.Right, ARect.Bottom])));

     end;

     // Освобождаем ранее выделенную память
     VirtualFreeEx(hProcess, pszText, 0, MEM_RELEASE);
     VirtualFreeEx(hProcess, plviRemoteLVItem, 0, MEM_RELEASE);

     // Закрываем описатель процесса
     CloseHandle(hProcess);

     Readln;
    end.

  • Игорь404 (09.04.09 13:26) [27]
    Дело в том, что элементов управления очень много и придется адаптировать код к каждому отдельно (или адаптировать ко всем сразу).

    Но вот на что я наткнулся
    "Внедрение библиотеки через CreateRemoteThread"
    http://delphisite.ru/faq/vnedrenie-biblioteki-cherez-createremotethread
    Выполнение собственного кода в чужом процессе.

    Осталось только взвесить эти два варианта на предмет трудоемкости и выбрать наиболее гибкое и легкореализуемое...
  • Rouse_ © (09.04.09 13:32) [28]
    Из пушки по воробьям :) Хотя... хозяин барин.

    ЗЫ: Если что - то этот пример (по ссылке) нормально выгружается только из своего собственного процесса, более полный вариант этой демки можешь взять тут: http://forum.sources.ru/index.php?showtopic=248156&st=0&#entry2057057
  • Игорь404 (09.04.09 14:19) [29]
    Наверное много времени бы потратил на отладку :)

    К счастью человек эволюционирует и на смену рогаткам, с чрезвычайно узким спектром применения, приходят мелкокалиберные винтовки, с ненамного большим, но однако же большим. И все это я к тому, что не факт что только по "воробьям", если ты меня понимаешь. :) В мое случае приложение должно быть достаточно гибким, чтобы в перспективе была возможноть оперативно изменять его согласно новым требованиям. Мне кажется в случае с DLL injection приложение будет обладать достаточной гибкостью и масштабируюмостью.
  • аноним (09.04.09 15:29) [30]

    > Никак не могу понять, чем WM_COPYDATA (будучи упомянутой
    > уже дважды в данной ветке) может помочь при отправке того-
    > же DTM_SETSYSTEMTIME?

    Привилегий хватит писать в память чужого процесса ? Как Виста на такое отреагирует и Вин7 (я точно не знаю)?
    Лучше переписать прогу чтобы она принимала WM_COPYDATA и не волноваться за будующее
  • Игорь Шевченко © (09.04.09 20:30) [31]

    > Лучше переписать прогу чтобы она принимала WM_COPYDATA и
    > не волноваться за будующее


    DateTimePicker переписать или TreeView ?
  • аноним (10.04.09 04:15) [32]

    > DateTimePicker переписать или TreeView ?

    Такие откровенные глупости писать не надо. Хорошо ?
    Я понимаю делфи и все такое, но есть же предел в конце концов.
  • Rouse_ © (10.04.09 09:11) [33]

    > Такие откровенные глупости писать не надо. Хорошо ?

    Хорошо, не будем - только и ты плз глупости не пиши о переписывании программы и читай внимательней, желательно с самого начала. Приложение чужое, поэтому у тебя и спрашивают, что именно в чужом приложении стоит переписать?
  • Игорь404 (10.04.09 11:41) [34]
    Возможно я ввел кого-то в заблуждение, но к коду тестируемого приложения доступа нет.
  • аноним (10.04.09 13:36) [35]

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

    Где там сказано, что код чужой ? Там сказано, что процесс другой.
  • Игорь404 (10.04.09 15:11) [36]
    Задача решена. Я внедрил DLL в процесс тестируемого приложения и передал ему
    SendMessage(handle, DTM_SETSYSTEMTIME, GDT_VALID, Longint(@dateTime));
    теперь все работает, не тестировал еще с TreView, но думаю и здесь проблем не будет.
    Осталось решить проблему с адаптированием DLLки к разным элементам управления, но это уже другая история.

    p.s. Ради таких минут мы и живем друзья, спасибо! :)
  • имя (13.07.09 13:10) [37]
    Удалено модератором
 
Конференция "WinAPI" » Альтернатива SendMessage [D7, WinXP]
Есть новые Нет новых   [134433   +23][b:0][p:0.004]