Форум: "Начинающим";
Текущий архив: 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.013 c