GetWindowLong Доступ запрещен

Я пытаюсь использовать функцию API GetWindowLong, чтобы получить адрес windowproc (GWL_WNDPROC) другого окна в другом адресном пространстве, но эта функция возвращает 0, а GetLastErro равен 5 (доступ запрещен). Я запустил программу как администратор и снова столкнулся с этой проблемой, пожалуйста, помогите мне?

ОС: Win7 x86

1 ответ

Если вы имеете в виду другой "процесс", то это не разрешено. Посмотрите здесь.

Вам нужно

Глава 22 - Внедрение DLL и перехват API

Внедрение DLL с помощью хуков Windows

а также

https://docs.microsoft.com/en-us/windows/win32/winmsg/hooks

сформируйте книгу выше:

Допустим, вы хотите создать подкласс экземпляра окна, созданного другим процессом. Вы можете вспомнить, что создание подклассов позволяет вам изменять поведение окна. Для этого вы просто вызываете SetWindowLongPtr, чтобы изменить адрес оконной процедуры в блоке памяти окна, чтобы он указывал на новый (ваш собственный) WndProc. В документации Platform SDK указано, что приложение не может создать подкласс окна, созданного другим процессом. Это не совсем так. Проблема с подклассом окна другого процесса действительно связана с границами адресного пространства процесса.

Когда вы вызываете SetWindowLongPtr для создания подкласса окна, как показано ниже, вы сообщаете системе, что все сообщения, отправленные или отправленные в окно, указанное hWnd, должны быть направлены в MySubclassProc вместо обычной оконной процедуры окна:

SetWindowLongPtr(hWnd, GWLP_WNDPROC, MySubclassProc);

Другими словами, когда системе необходимо отправить сообщение в WndProc указанного окна, она ищет адрес и затем делает прямой вызов WndProc. В этом примере система видит, что адрес функции MySubclassProc связан с окном, и вместо этого выполняет прямой вызов MySubclassProc.

Проблема с подклассом окна, созданного другим процессом, заключается в том, что процедура подкласса находится в другом адресном пространстве. На рисунке 22-1 показано упрощенное представление того, как оконная процедура получает сообщения. Процесс A запущен и создал окно. Файл User32.dll отображается в адресное пространство процесса A. Это отображение User32.dll отвечает за получение и отправку всех отправленных и отправленных сообщений, предназначенных для любого окна, созданного любым потоком, запущенным в процессе A. Когда это отображение User32.dll обнаруживает сообщение, сначала он определяет адрес WndProc окна, а затем вызывает его, передавая дескриптор окна, сообщение и значения wParam и lParam. После того, как WndProc обработает сообщение, User32.dll возвращается в цикл и ожидает обработки другого оконного сообщения.

Теперь предположим, что ваш процесс - это процесс B, и вы хотите создать подкласс окна, созданного потоком в процессе A. Ваш код в процессе B должен сначала определить дескриптор окна, которое вы хотите создать подкласс. Это может произойти по-разному. Пример, показанный на рис. 22-1, просто вызывает FindWindow для получения желаемого окна. Затем поток в Процессе B вызывает SetWindowLongPtr в попытке изменить адрес WndProc окна. Обратите внимание, что я сказал "попытка". Этот вызов ничего не делает и просто возвращает NULL. Код в SetWindowLongPtr проверяет, пытается ли один процесс изменить адрес WndProc для окна, созданного другим процессом, и просто игнорирует вызов.

Что, если бы функция SetWindowLongPtr могла изменить WndProc окна? Система свяжет адрес MySubclassProc с указанным окном. Затем, когда в это окно было отправлено сообщение, код User32 в процессе A извлечет сообщение, получит адрес MySubclassProc и попытается вызвать этот адрес. Но тогда у вас возникнут большие проблемы. MySubclassProc будет в адресном пространстве процесса B, но процесс A будет активным процессом. Очевидно, что если User32 вызовет этот адрес, он будет вызывать адрес в адресном пространстве процесса A, и это, вероятно, приведет к нарушению доступа к памяти.

Чтобы избежать этой проблемы, вы хотите, чтобы система знала, что MySubclassProc находится в адресном пространстве процесса B, а затем попросила систему выполнить переключение контекста перед вызовом процедуры подкласса. Microsoft не реализовала эту дополнительную функцию по нескольким причинам:

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

Переключение активных процессов очень дорого с точки зрения процессорного времени.

Поток в процессе B должен будет выполнить код в MySubclassProc. Какой поток система должна попытаться использовать? Существующая тема или новая тема?

Как User32.dll сможет определить, был ли адрес, связанный с окном, для процедуры в другом процессе или в том же процессе?

Поскольку для этих проблем нет хороших решений, Microsoft решила не позволять SetWindowLongPtr изменять оконную процедуру окна, созданного другим процессом.

Однако вы можете создать подкласс окна, созданного другим процессом - вы просто делаете это по-другому. На самом деле вопрос не в подклассах, а в границах адресного пространства процесса. Если бы вы могли каким-то образом получить код процедуры своего подкласса в адресном пространстве процесса A, вы могли бы легко вызвать SetWindowLongPtr и передать адрес процесса A в MySubclassProc. Я называю этот метод "внедрением" библиотеки DLL в адресное пространство процесса.

Другие вопросы по тегам