WWW.ИСХОДНИКИ.РУ cpp.sources.ru
java.sources.ru web.sources.ru soft.sources.ru
jdbc.sources.ru asp.sources.ru api.sources.ru

  Форум на исходниках
  C / C++ / Visual C++
  Процессы, сообщения и указатели

СПРОСИТЬ  ОТВЕТИТЬ
профайл | регистрация | faq

Автор Тема:   Процессы, сообщения и указатели
One опубликован 25-01-2002 17:43 MSK   Click Here to See the Profile for One   Click Here to Email One  
Хотелось бы продолжить начатую тему, т.к. я так и осталься в недоумении.

ADK писал:
>>Естественно, с указателями проблемы будут. А Вы что хотели? comctl32.dll грузится в каждый процесс и даёт указатели на адресное пространство родного процесса. А вот если дело в хуке происходит, то можно отследить, когда он выполняется в нужном процессе.

Вот как я понимаю работу виндов: при запуске процесса в него подгружаются все модули, процедуры и функции которых он использует (user32.dll, kernel32.dll и тп., в том числе и comctl32.dll, если его исползовать). В этом легко убедится с помощью ToolHelp32, просмотрев список модулей, запещенных процессом.

Теперь рассмотрим банальную ситуацию: берем произвольное окно либо контрол (кнопку, листбокс и тд.), не обязательно принадлежащее нашему процессу и посылаем ему WM_GETTEXT, предварительно выделив память под буффер для получения текста (нужно заметить, что память выделяется в адресном пространстве нашего процесса). В итоге получаем название окна либо контрола. фактически же в этом окне происходит вызов DefWindowProc, т.к. вряд ли оно переопределяет обработку сообщения WM_GETTEXT.
Фактически, такую обработку можно прописать в своей процедуре обработки сообщений, причем достаточно просто, и нужно заметить, никаких проблем с занесение текста в адресное пространство другого процесса не возникает.

Однако, лично я сталкнулся вот с чем: берем не родной LisView, и посылаем ему LVM_GETITEMTEXT, и сразу получаем ошибку, причем ошибку получаем не в нашем процессе, а в том, к которому мы обращались. Вопрос, почему? Ведь скорее всего, сообщение обрабатывается все той же DefWindowProc.

Естественно, M$ не когда не выдаст секретов DefWindowProc, иначе ситуция с ОС M$ будет напоминать ситуцию с Linux.
Однако, может быть кто-то имеет малейшее представление, что и почему там происходит, и попытается объяснить это мне.

Буду благодарен.

Glite опубликован 26-01-2002 04:38 MSK     Click Here to See the Profile for Glite  Click Here to Email Glite     
Поробую обяснить. Когда запускается процесс ось выделяет ему 4 гига виртуального адресного пространства, 2 из которых берёт под свои нужды. Два разных процесса работают в изолированных адресных пространствах. И, приложение не может выполнить физическую адресацию памяти в адресном пространстве другого процесса. Какой бы адресс оно не задало он всегда будет соответствовать одной из его собственных страниц. Т.е. адрес из одного процесса в другом ссылается совершенно на другой участок памяти.
Когда ты пытаешься передать указатель в другой процесс, то оно обращается к памяти в своём адресном пространстве, а что там - одному чорту известно. Отсюда и ругань вся. А, дллелины здесь вообще не при делах.
Обмен данными между процессами можно осуществить разными способами - socket, файлы отображаемые на память, dde.
frostbitten опубликован 26-01-2002 06:50 MSK     Click Here to See the Profile for frostbitten  Click Here to Email frostbitten     
Удивительного в том, что WM_GETTEXT работает, а LVM_GETITEMTEXT - нет - нет :).

Message Quеuе находиться под полным контролем USER, там же находятся и окна. Не сложно предположить, что USER знает о возможности меж процессного WM_GETTEXT поэтому услужливо делает грамотный мост - такой же как WM_COPYDATA, только в др. сторону...

Не сложно проверить, что адресс строки, кот ты указаваешь в LPARAM для WM_GETTEXT и тот, что получает обработчик (WndProc) _НЕ_ совпадают - его по пути следования подменил USER, а вот о существовании LVM_GETITEMTEXT USER как бы не знает :)... и передает указатель как ты его прописал - и ты получаешь пятый ексепшон. :)...

Бороться так как тебе посоветовали - хуками... В нём делать то, что USER делает с WM_GETTEXT... только более изощренно ты же не USER! :)

P.S.
К стати, по ходу WM_GETTEXT попадает в мою копилку изощренных средств IPC... Честно говоря не знал о такой возможности :)

Напр. можно у окна запрорсить закие-нить данные как:

::SendMessage(
hwnd ,
WM_GETTEXT ,
(WPARAM)(1000 +ID_PARAM_TO_RETRIEVE_x),
(LPARAM)s.GetBufferSetLength(...));
s.ReleaseBuffer();

А в обработчике соответственно возвращать заначение параметра ((int)wParam -1000)...

:))))))...

DenizK опубликован 26-01-2002 09:06 MSK     Click Here to See the Profile for DenizK  Click Here to Email DenizK     
Если я не ошибаюсь, то WM_GETTEXT так работает для совместимости с Win16.
One опубликован 28-01-2002 16:01 MSK     Click Here to See the Profile for One  Click Here to Email One     
2 Glite:

Извини, конечно, ты и прав... и не прав. Именно в этом весь вопрос: почему одни функции могут передавать указатели между потоками, а другие - нет? Тут я склонен согласиться с frostbitten, может быть действительно они как-то подменяются.
Вопрос, как? Почему я не могу их подменить (или не знаю как это сделать ;)).

Хотя я вот что подумал - окна обычно создаются с пользовательским классом, а для таких вещей как кнопки, ListView и другие контролы классы ужу определены системой.
А процедура обработки сообщений задается именно там. Т.е. либо M$ не стала развивать для стандартных контролов способность межпотокового обмена "памятью", либо одно из двух.

2 DenizK: Ты ошибаешься. GetWindowText именно через WM_GETTEXT и работает.

Flex Ferrum опубликован 28-01-2002 16:22 MSK     Click Here to See the Profile for Flex Ferrum  Click Here to Email Flex Ferrum     
Причина тут наверное вот в чем. В случае использования GetWindowText все определенно - возвращается текстовая строка изветсного размера. Маршаллинг для такой операции выполнить несложно. А вот с ListView, TreeView и т. п. все несколько сложнее. Между процессами необходимо передавать структуру целиком, со всеми внутренними указателями, объектами и т. д. и т. п. И если с хендлами все более-менее понятно, то вот с данными пользователя - гораздо сложней. По сему, ИМХО, ребята из Microsoft решили не заморачиваться и, если тебе нужно решить такую вот специфическую задачу, как манипуляция с ListView чужого процесса, решай ее сам с использованием хуков.
Кстати, здается мне, что если перегрузить обработчик WM_GETTEXT, то все это дело может милейшим образом рухнуть (в том смысле, что результат GetWindowText для такого окна из чужого процесса будет неопределенным).
One опубликован 28-01-2002 16:53 MSK     Click Here to See the Profile for One  Click Here to Email One     
2 Flex Ferrum:

Да, я согласен, что ребята из M$ решили не заморачиваться, но позволь не согласиться вот с этим:

>> Причина тут наверное вот в чем. В случае использования GetWindowText все определенно - возвращается текстовая строка изветсного размера. Маршаллинг для такой операции выполнить несложно. А вот с ListView, TreeView и т. п. все несколько сложнее. Между процессами необходимо передавать структуру целиком, со всеми внутренними указателями, объектами и т. д. и т. п.

И вот почему: отправляем сообщение LVM_GETITEMTEXT с одним указателем на строку и ее размером соответственно. Получаем exception. Хотя опять - операция не сложная. Никаких структур с из загонами.

Второе - если "перегрузить" значит переписать обработчик, то нет, я пробовал, все работает, никаких проблемм не возникает, в заголовоке окошка показывается тот текст, который мы возвращаем в ответ на WM_GETTEXT (т.е. винды при перерисовке окна вызывают GetWindowText).

Flex Ferrum опубликован 28-01-2002 17:00 MSK     Click Here to See the Profile for Flex Ferrum  Click Here to Email Flex Ferrum     
Не известно, что они там в нутрях намудрили. Предположим, что у тебя текст хранится не в структуре, а возвращается по LVN_GETDISPINFO... Вообщем, я думаю, что они просто решили не заморачиваться.
x опубликован 29-01-2002 11:29 MSK     Click Here to See the Profile for x  Click Here to Email x     
а я думаю вы оба неправы
дело скорре в том что comctl32 надстройка на GUI

user32 не смотря на то что вызывается через DLL скорее всего по традиции вин16 имеет доступ ко всем элементам=так проще всего и надежнее и быстрее=переклюцение колец защиты далеко не быстрая операция=а элементов согласитесь много

comctl был написан много позднее и скорее всего создает конторолы с монопольным доступом каждого процесса

тогда вопрос сам собой отпадает

One опубликован 29-01-2002 16:21 MSK     Click Here to See the Profile for One  Click Here to Email One     
2 x:
Вся проблемма в том, что нет там никакого монопольного доступа, т.к. любое сообщение, отпревленное данному контролу из другого потока, но не связанное с указателями, нормально обрабатывается (так, для ListView можно получать номерь выбранного Item'а, двигать иконки, если не стоит AutoArrange и т.п.)
frostbitten опубликован 29-01-2002 18:24 MSK     Click Here to See the Profile for frostbitten  Click Here to Email frostbitten     
Да не заморачивались они - это backward compatibility называется. И вопрос только в ней.

2Flex Ferrum: Перегрузить WM_GETTEXT очень хорошо получается - у меня получилось то о чем я говорил - IPC такой хитрый.

2One: "в заголовоке окошка показывается тот текст, который мы возвращаем в ответ на WM_GETTEXT (т.е. винды при перерисовке окна вызывают GetWindowText)." Это не всегда так - пусти Spy++ и посмотри капшон окошка, для кот. ты переопределил WM_GETTEXT, а на обработчик поставь брикпоинт... так вот он не вызовется...

x опубликован 29-01-2002 20:52 MSK     Click Here to See the Profile for x  Click Here to Email x     
слухай сюды

ты когда регаешь окошко RegisterClass() указываешь процесс
угу?
стандартные классы окон уже зареганы by user i think

а через какой процесс зареганы ListView и т.п. ?

чуешь к чему клоню да?

СПРОСИТЬ  ОТВЕТИТЬ
Перейти:


E-mail | WWW.ИСХОДНИКИ.RU

Powered by: Ultimate Bulletin Board, Freeware Version 5.10a
Purchase our Licensed Version- which adds many more features!
© Infopop Corporation (formerly Madrona Park, Inc.), 1998 - 2000.