Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.08.06;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.011 c
11-1131108788
MTsv DN
2005-11-04 15:53
2006.08.06
Transparent для Item a в ListView...


2-1152523701
filh
2006-07-10 13:28
2006.08.06
Подмена инфы о системе


15-1152509587
Ega23
2006-07-10 09:33
2006.08.06
С Днём рождения! 9 июля


1-1150925128
TechnoDreamer
2006-06-22 01:25
2006.08.06
Как определить в ANSI файл или в Unicode


15-1151876608
Dimedrol
2006-07-03 01:43
2006.08.06
HTML: Посмотрите на ошибку - никак не осилю





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский