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

Вниз

Как по дескриптору окна или ещё чему-нить получить сам экземпляр   Найти похожие ветки 

 
Pashka.cool   (2006-07-18 12:53) [0]

Как по дескриптору окна или ещё чему-нить получить сам экземпляр. Например я могу получить методом GetClassName имя класса. Но необходим экземпляр.


 
Palladin ©   (2006-07-18 12:57) [1]

что значит экземпляр?


 
begin...end ©   (2006-07-18 12:58) [2]

FindControl


 
Desdechado ©   (2006-07-18 13:02) [3]

Может, озвучишь, что ты хочешь сделать?
А то ведь через хэндл многое можно.


 
Юрий Зотов ©   (2006-07-18 13:59) [4]

> Pashka.cool   (18.07.06 12:53)

В том же приложении -  см. [2]. В другом - никак.


 
begin...end ©   (2006-07-18 14:05) [5]

> Юрий Зотов ©   (18.07.06 13:59) [4]

Задача может оказаться решаемой и для другого приложения, если оно собрано в Delphi той же версии.


 
Юрий Зотов ©   (2006-07-18 16:03) [6]

> begin...end ©   (18.07.06 14:05) [5]

Спасибо за информацию.


 
DrPass ©   (2006-07-18 18:37) [7]


> Задача может оказаться решаемой и для другого приложения,
>  если оно собрано в Delphi той же версии.

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


 
begin...end ©   (2006-07-18 18:40) [8]

> DrPass ©   (18.07.06 18:37) [7]

Смысл заключается в полноценном его использовании. Внедрение в процесс ещё не отменили.


 
DrPass ©   (2006-07-18 18:54) [9]


> Внедрение в процесс ещё не отменили

Я так понимаю, речь о чужом адресном пространстве в таком случае не идет? :)


 
begin...end ©   (2006-07-18 19:01) [10]

> DrPass ©   (18.07.06 18:54) [9]

Речь идёт о чужом адресном пространстве, которое на время внедрения в процесс становится своим.


 
Юрий Зотов ©   (2006-07-18 21:08) [11]

> begin...end

1. То, что в [6] была шутка - это Вы, надеюсь, поняли. Поскольку очевидно, что модуль Controls смотрели не только Вы (причем давным-давно).

2. Для получения ссылки на чужой экземпляр TWinControl по хэндлу его окна идентичность версий Delphi даже не обязательна. Легко могу привести пример, в котором приложение, написанное на D7 получает совершенно правильную ссылку на TEdit, который находится в приложении, написанном на D6. Впрочем, даже и пример не обязателен - достаточно сравнить всего лишь одну строковую константу все в тех же модулях Controls.

3. Естественно, полученная из чужого АП ссылка валидна для чужого же АП. Естественно, в него можно и внедриться. Но вот за пример полноценного использования этой ссылки (как Вы утверждаете в [8]) был бы весьма признателен.

Примечание: слово "полноценное", естественно, означает, что во внедренном в чужой процесс коде с полученной ссылкой можно работать точно так же, как мы это делаем в "родном" коде. Включая работу с VMT и RTTI.


 
begin...end ©   (2006-07-19 18:00) [12]

> Юрий Зотов ©   (18.07.06 21:08) [11]

> То, что в [6] была шутка - это Вы, надеюсь, поняли.

То, что в [5] была НЕ шутка -- это Вы, надеюсь, тоже поняли.

> Для получения ссылки на чужой экземпляр TWinControl по хэндлу
> его окна идентичность версий Delphi даже не обязательна.

"Спасибо за информацию" (с). Я где-то утверждал, что для получения ссылки на экземпляр необходима идентичность версий Delphi? Плз, буду весьма признателен, если Вы укажете соответствующий номер поста. Я же, просмотрев ветку, вижу лишь одно моё упоминание об этом -- в [5], где ясно сказано, что идентичность необходима для решения задачи автора. Его задачей является получение самого экземпляра (и, вероятно, дальнейшая работа с ним), а не ссылки на него. Так вот -- для решения этой задачи идентичность версий Delphi действительно необходима.

> Легко могу привести пример, в котором приложение, написанное
> на D7 получает совершенно правильную ссылку на TEdit, который
> находится в приложении, написанном на D6.

Потрясён Вашими знаниями, однако смею заверить, что это, как ни странно, могу сделать и я.

> Но вот за пример полноценного использования этой ссылки
> (как Вы утверждаете в [8]) был бы весьма признателен.

Если целевое приложение и та программа, которую планируется использовать для решения авторской задачи, собраны в одной и той же версии Delphi, то, в полном согласии с моим утверждением [5], задача автора МОЖЕТ ОКАЗАТЬСЯ решаемой. Для того, чтобы она ОКАЗАЛАСЬ решаемой, необходимо выполнение ещё одного условия: оба приложения должны быть собраны с runtime-пакетами.

И такой пример полноценного (на мой взгляд) использования ссылки я приведу. Механизм примера довольно прост -- пишется DLL, которая хуком внедряется в ВАП целевого процесса. Если и DLL, и EXE-файл  процесса собраны в одинаковых версиях Delphi, причём с runtime-пакетами, никаких трудностей не возникнет -- например, при вызове одного и того же метода из EXE и DLL управление будет передаваться в одно и то же место пакета, отображённого на ВАП.

Код библиотеки таков:

library Project2;

uses
 SysUtils, Classes, Windows, Messages, Forms, TypInfo;

type
 THackForm = class(TForm);

var
 H: HHOOK;

function HookProc(code, wp, lp: Integer): LRESULT; stdcall;
var
 Message, Handle: Cardinal;
 I, PropCount: Integer;
 PropList: PPropList;
 Properties: string;
 SysDir: array[0..MAX_PATH] of Char;
 Self: TForm;
 Obj: TObject;
begin
 if PMsg(lp).message = WM_NULL then
 begin
   Handle := PMsg(lp).wParam;

   // Получение идентификатора сообщения RM_GETOBJECTINSTANCE
   GetSystemDirectory(SysDir, sizeof(SysDir));
   Message := RegisterWindowMessage(PChar(Format("ControlOfs%.8X%.8X", [GetModuleHandle(PChar(SysDir + "\vcl70.bpl")), GetCurrentThreadId])));

   // Получение указателя на экземпляр класса
   Self := TForm(SendMessage(Handle, Message, 0, 0));

   if Assigned(Self) then
   begin
     MessageBox(Handle, PChar(IntToHex(Integer(Self), 8)), "Адрес экземпляра в чужом ВАП", 0);

     // Проверка работы System._IsClass
     Obj := Self;
     if Obj is TComponent then
       MessageBox(Handle, PChar("Форма является потомком TComponent"), "_IsClass", 0);

     // Чтение свойства
     MessageBox(Handle, PChar(Self.Name), "Имя формы", 0);

     // Вызов классового метода
     MessageBox(Handle, PChar(String(Self.ClassName)), "Имя класса формы", 0);

     // Получение списка published-свойств
     PropCount := GetTypeData(Self.ClassInfo).PropCount;
     GetMem(PropList, PropCount * sizeof(PPropInfo));
     try
       GetPropList(Self, PropList);
       Properties := "";
       for I := 0 to Pred(PropCount) do
       begin
         if I mod 5 = 0 then
           Properties := Properties + sLineBreak;
         Properties := Properties + " " + PropList[I].Name;
       end;
       MessageBox(Handle, PChar(Properties), "Published-свойства", 0);
     finally
       FreeMem(PropList);
     end;

     // Вызов виртуального метода
     THackForm(Self).ChangeScale(1, 2);

     // Запись свойства
     Self.Caption := "Через 3 секунды форма будет скрыта";

     // Вызов статического метода
     Sleep(3000);
     Self.Hide;
     Sleep(2000);
     Self.Caption := "А сейчас она опять видна";
     Self.Show;
   end;
 end;
 Result := CallNextHookEx(0, code, wp, lp);
end;

procedure SetHook(FormHandle: Cardinal);
var
 ThreadId: Cardinal;
begin
 ThreadId := GetWindowThreadProcessId(FormHandle);
 H := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, HInstance, ThreadId);
 Win32Check((H <> 0) and PostThreadMessage(ThreadId, WM_NULL, FormHandle, 0));
end;

procedure RemoveHook;
begin
 UnhookWindowsHookEx(H);
end;

exports
 SetHook, RemoveHook;

begin
end.


С хост-приложением DLL общается с помощью двух функций -- SetHook и RemoveHook. После вызова SetHook с дескриптором окна "чужой" формы в качестве параметра библиотека сразу же делает всю работу -- демонстрирует значение полученной ссылки, вызовы статических методов, чтение и изменение свойств, работу с VMT и RTTI. Снимается ловушка вызовом RemoveHook.

Впрочем, чтение/запись свойств, вызов статических методов и корректный поиск в VMT можно, за исключением частных случаев, организовать и без пакетов. Например, в случае статического метода в ВАП процесса после внедрения DLL окажется ДВА аналогичных участка (аналогичных -- в силу идентичности версий) с кодом метода -- один из них будет вызываться из хост-приложения, другой -- из DLL. А вот с RTTI в отсутствие пакетов, разумеется, будут проблемы.

Пример написан на скорую руку (менее чем за час), поэтому тщательно я его не проверял, однако думаю, что свою задачу -- демонстрацию доступа к чужому экземпляру -- он выполняет.


 
begin...end ©   (2006-07-19 18:03) [13]

P.S. Пример написан для Delphi 7 и был проверен на Win2k.


 
Юрий Зотов ©   (2006-07-19 20:40) [14]

> begin...end ©   (19.07.06 18:03) [13]

Угу. Именно с run-time пакетами. Причем оба приложения. Причем именно с одними и теми же run-time пакетами. Естественно, одних и тех же версий. Естественно, включая и пакеты B>сторонних компонентов (а то вдруг там какой-нибудь TMyEdit используется?).

И все это, конечно же, о целевом приложении заранее известно - и то, что оно с пакетами собрано, и с какими именно пакетами, и каких версий эти пакеты. И тогда остается пустяк - собрать свой код с теми же самыми пакетами тех же самых версий. А самому внедренному коду остается всего лишь использовать RM_GETOBJECTINSTANCE (свежая мысль, что и говорить).

Поздравляю. Вне всяких сомнений, Вы очень помогли автору вопроса в решении его задачи. Это именно то, что он хотел. Таким образом, Ваш постинг [5] в контексте данной ветки был более чем уместен.


 
begin...end ©   (2006-07-19 21:26) [15]

> Юрий Зотов ©   (19.07.06 20:40) [14]

> И все это, конечно же, о целевом приложении заранее известно

Иногда бывает известно.

> А самому внедренному коду остается всего лишь использовать
> RM_GETOBJECTINSTANCE (свежая мысль, что и говорить).

Внедрённый код может использовать и FindControl. В [12] я его не использовал намеренно, т.к. мне показалось, что так сам механизм будет нагляднее -- хорошо видно, что ранее сообщение зарегистрировал именно пакет.

> Это именно то, что он хотел.

Вам, несомненно, виднее -- Вы ещё в [4] предположили, что автор может пытаться искать контрол в чужом процессе.

Подводя итог, скажу, что своё утверждение [5] по Вашей просьбе в [11] я подтвердил реальным кодом [12]. Правда, вместо обещанной признательности услышал в ответ неуместный сарказм -- объяснить это можно только Вашим нежеланием признать свою ошибку, которая в [4] всё же была (и [12] это подтверждает).

P.S. Ваше поздравление позвольте переадресовать обратно Вам -- в таких "поздравлениях" я не нуждаюсь.


 
Юрий Зотов ©   (2006-07-19 21:54) [16]

Уговорили, забираю поздравление назад. Действительно, поздравлять тут не с чем. Поскольку код столь же очевиден, сколь и бесполезен.

А насчет "ошибки" в [4] - Вы хоть поняли, почему был дан именно такой ответ?


 
begin...end ©   (2006-07-19 22:33) [17]

> Юрий Зотов ©   (19.07.06 21:54) [16]

> Поскольку код столь же очевиден, сколь и бесполезен.

Тем не менее, он является ответом на [11] -- Вы сами захотели его увидеть. Зачем просить то, что для Вас заведомо бесполезно, известно только Вам.

------------------------

В [4] Вы даёте ответ, который в общем случае неверен. Почему Вы даёте именно такой ответ -- известно, опять же, только Вам.

В [5] Вас поправляют. Без всяких наездов, крошения батонов и качения баллонов -- просто вносят уточнение в Ваш ответ.

В [6] Вы благодарите за уточнение.

В [11] (спустя полдня) Вы заявляете, что [6] -- это была шутка. Ну, шутка так шутка -- она, правда, совсем не смешная, ну да не важно. И одновременно с этим просите привести пример, подтверждающий уточнение [5] -- причём просите так, как будто сомневаетесь в том, что [5] вообще может быть верным.

В [12] Вы это подтверждение, тем не менее, получаете.

А в [16] заявляете, что это подтверждение бесполезно.

------------------------

Думаю, после ТАКОЙ цепочки событий комментарии излишни. Скажу лишь, что авторитет -- штука, конечно, хорошая, и поэтому терять его не хочется. Но иногда его может спасти честность. Чего Вам и желаю.


 
Юрий Зотов ©   (2006-07-19 22:52) [18]

Значит, так ничего и не поняли. Что ж, комментарии действительно излишни.


 
begin...end ©   (2006-07-19 22:56) [19]

> Юрий Зотов ©   (19.07.06 22:52) [18]

Предлагаю на этой пессимистической ноте закончить оффтопик. Начатый, кстати, Вами.


 
Leonid Troyanovsky ©   (2006-07-19 23:04) [20]


> begin...end ©   (19.07.06 18:00) [12]


>    // Получение идентификатора сообщения RM_GETOBJECTINSTANCE
>    GetSystemDirectory(SysDir, sizeof(SysDir));
>    Message := RegisterWindowMessage(PChar(Format("ControlOfs%.
> 8X%.8X", [GetModuleHandle(PChar(SysDir + "\vcl70.bpl")),
>  GetCurrentThreadId])));

А почему, собс-но, не тот же FindControl?
Кстати, что, в D7 оно уже не хранится aka property (GetProp)?

>  UnhookWindowsHookEx(H);

Здесь я б тоже добавил PostMessage(.., WM_NULL..),
чтобы длл реально отцепилась.

> ссылки, вызовы статических методов, чтение и изменение свойств,
>  работу с VMT и RTTI. Снимается ловушка вызовом RemoveHook.

Было б любопытно проанализировать, какие именно препятствия
мешают применению того же RTTI в условиях безпакетной компиляции.

Или, скажем по-другому, насколько ограничительны требование
использовать пакеты.
Например, сабклассируем искомое окно, вписываем в экзешник
некий универсальный thunk для вызова любых (или, наиболее
распространенных) методов и вызываем их, скажем, путем
SendMessage.

Хотя, конечно, это чисто академический интерес :)

--
Regards, LVT.


 
begin...end ©   (2006-07-19 23:14) [21]

> Leonid Troyanovsky ©   (19.07.06 23:04) [20]

> А почему, собс-но, не тот же FindControl?
Об этом написано в [15].

Сорри, но продолжать дискуссию в этой ветке настроения уже нет. Ещё раз извините.


 
Leonid Troyanovsky ©   (2006-07-19 23:25) [22]


> begin...end ©   (19.07.06 23:14) [21]

> Об этом написано в [15].


Честно говоря, более интересовало
> Кстати, что, в D7 оно уже не хранится aka property (GetProp)?

Потому, как со времен D3 туда (FindControl) не заглядывал.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2006-07-19 23:53) [23]


> Leonid Troyanovsky ©   (19.07.06 23:04) [20]

> некий универсальный thunk для вызова любых (или, наиболее


Утопия.
Бо, из dll нам не узнать, какой адрес в екзешнике имеет,
например SetString, т.к., наружу он не торчит.

--
Regards, LVT.


 
Johnmen ©   (2006-07-19 23:59) [24]

Удалено модератором
Примечание: Offtopic


 
Игорь Шевченко ©   (2006-07-19 23:59) [25]

Leonid Troyanovsky ©   (19.07.06 23:53) [23]

Некий Свен Шрайбер обходил подобные моменты (вызов неэкспортируемых функций) путем анализа файла символов целевого EXE-модуля. Правда, у него в качестве EXE-модуля выступал NTOSKRNL.EXE для которого получить файл символов было довольно легко, но если имеется map-файл целевого EXEшника на Delphi, то данный способ имеет право на существование.


 
Leonid Troyanovsky ©   (2006-07-20 00:28) [26]


> Игорь Шевченко ©   (19.07.06 23:59) [25]

>  но если имеется map-файл целевого EXEшника на Delphi, то
> данный способ имеет право на существование.


Да, конечно. Но тоже нехилое ограничение.

И вот, стало любопытно (никогда раньше не задумывался),
а вдруг, скажем, функции system компилируются
по одним и тем же адресам. Надо будет проверить :)

--
Regards, LVT.


 
Игорь Шевченко ©   (2006-07-20 10:19) [27]

Leonid Troyanovsky ©   (20.07.06 00:28) [26]


> а вдруг, скажем, функции system компилируются
> по одним и тем же адресам.


Проверялось. По разным. Из-за умного линкера, не включающего в окончательный код неиспользуемые функции :)



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

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

Наверх




Память: 0.56 MB
Время: 0.031 c
6-1143141281
Суслик
2006-03-23 22:14
2006.08.06
Просмотр HTTP трафика.


3-1149251071
Still Swamp
2006-06-02 16:24
2006.08.06
Посомтрим на проблему FB с другой стороны...


2-1153225334
DesperadO666
2006-07-18 16:22
2006.08.06
Новая сторока в DBGrid


3-1148977136
D@Nger
2006-05-30 12:18
2006.08.06
Как хранить изображения JPG в Paradox?


3-1149195967
Glivera
2006-06-02 01:06
2006.08.06
Количество записей выданных после запроса.