Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.01.2010, 22:02   #1
HollyPaladin
Пользователь
 
Аватар для HollyPaladin
 
Регистрация: 29.11.2009
Сообщений: 51
По умолчанию Хук на GetMessage

Мне необходимо отслеживать изменения курсора в приложении, пытаюсь повесить хук на GetMessage.
Создал функцию и поместил ее в dll:
Код:
extern "C" LRESULT __export CursorHook(int nCode,WPARAM wParam,LPARAM lParam)
{ 
 MSG * st = (MSG*)lParam;
 if( st->message== WM_SETCURSOR )
 ShowMessage("Cursor changed");
 return 0;
}
Хук вешаю с помощью следущего кода:
Код:
 hLib=LoadLibrary("Project2.dll");
 (void*)pKeybHook=GetProcAddress(hLib,"_CursorHook");
  hKeybHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)(pKeybHook),hLib,0);
После загрузки длл и установки хука при изменении курсора ничего не происходит, а при получении фокуса приложением в котором мне не обходимо отслеживать изменения курсора появляется синий экран и комп перезагружается
Подскажите в чем моя ошибка.
HollyPaladin вне форума Ответить с цитированием
Старый 11.01.2010, 08:17   #2
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

потому что функция объявлена неправильно. Функция должна быть __stdcall. Посмотри здесь как надо объявлять.
rpy3uH вне форума Ответить с цитированием
Старый 11.01.2010, 20:45   #3
was
Пользователь
 
Регистрация: 28.07.2009
Сообщений: 13
По умолчанию

Конкретно подсказать не могу, но на основании своего опыта скажу. Перехватить сообщения можно только клавиатуры и мыши. Может еще что то, все не проверял. Но для того перехватывать сообщения в чужой программе, надо что бы эта программа загрузила эту DLL. Для этого надо надо узнать хендел этого процесса(программы (GetWindowThreadProcessId)), и с помощью соответствующих функций IP открыть (OpenProcess) запросить у него память(VirtualAllocEx). Затем следует разместить в этой памяти свою функцию, которая вызывает, или вернее загружает, нужную DLL. Ну а дальше все стандартно. И еще - когда вы работаете в чужой программе, следует помнить, что адресное пространство отличается от адресного пространства Вашей программы. То есть вот это
MSG * st = (MSG*)lParam;
совершенно не значит то что написано. Этот указатель указывает на структуру той программы, в которой Вы делаете перехват. Если Вы обратитесь к ней из своей программы, то получите синий экран.
Надо сначала получить эту структуру в выделенную память а затем с помощью ReadProcessMemory получить ее в свое адресное пространство. Ну а там уже делаете что хотите. Поищите в гугле по тем функциям API что я Вам написал, и найдете и информацию и примеры исходных кодов.
was вне форума Ответить с цитированием
Старый 12.01.2010, 14:58   #4
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

Цитата:
Сообщение от was Посмотреть сообщение
Конкретно подсказать не могу, но на основании своего опыта скажу. Перехватить сообщения можно только клавиатуры и мыши. Может еще что то, все не проверял.
не надо вводить людей в заблуждение. всё реально и всё проверено. ошибка в типе функции, она должна быть __stdcall
rpy3uH вне форума Ответить с цитированием
Старый 12.01.2010, 15:11   #5
was
Пользователь
 
Регистрация: 28.07.2009
Сообщений: 13
По умолчанию

Цитата:
Сообщение от rpy3uH Посмотреть сообщение
не надо вводить людей в заблуждение. всё реально и всё проверено. ошибка в типе функции, она должна быть __stdcall
И это тоже.

ЗЫ Увидел Вашу ссылку на освещение данного вопроса в Вашей редакции. Спасибо. Но с памятью я ничего не напутал. Ковыряясь в чужом процессе надо помнить о виртуальности.

Последний раз редактировалось was; 12.01.2010 в 15:34.
was вне форума Ответить с цитированием
Старый 12.01.2010, 18:45   #6
HollyPaladin
Пользователь
 
Аватар для HollyPaladin
 
Регистрация: 29.11.2009
Сообщений: 51
По умолчанию

rpy3uH,сделал функцию __stdcall - все равно не работает.Когда ставил хук на клавиатуру все работало и без __stdcall
was,насколько я понял из статьи про хуки , которую я прочитал, при глобальном хуке длл автоматически загружается во все процессы.Попробую использовать ReadProcessMemory.

Последний раз редактировалось HollyPaladin; 12.01.2010 в 18:49.
HollyPaladin вне форума Ответить с цитированием
Старый 12.01.2010, 19:27   #7
HollyPaladin
Пользователь
 
Аватар для HollyPaladin
 
Регистрация: 29.11.2009
Сообщений: 51
По умолчанию

Вот проекты :
DLL.rar
HOOK.rar
Можете сами посмотреть.

Последний раз редактировалось HollyPaladin; 12.01.2010 в 19:40.
HollyPaladin вне форума Ответить с цитированием
Старый 12.01.2010, 23:06   #8
was
Пользователь
 
Регистрация: 28.07.2009
Сообщений: 13
По умолчанию

У меня проекты не запустились на исполнение. Нет компоненты (насколько я понял Билдера). Давным давно пользовался BC 5.0, но теперь в винде перешел чисто на VC.

Кстати если пользоваться чисто Сишной программой, то extern "C" будет работать. А вот если из Дельфей вызывать, то надо уже для них делать __stdcall
Прикол лишь в том в каком порядке будут читаться из стека данные.



Вот кусок моего кода, где я в чужой программе читаю данные из статусной строки.
Код:
DWORD lpdwProcessId = 0;
GetWindowThreadProcessId(h1,&lpdwProcessId);// h1 это HWND нужного окна
if(lpdwProcessId == 0)
 {
  WindowPutsStr("Error GetWindowThreadProcessId");
 }
 else
 {
  // Открываем процесс
  HANDLE  hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE,   pdwProcessId);
  if(hProcess == 0)
  {
   WindowPutsStr("Error OpenProcess");
  }
  else
 {
  struct STR 
 {
  char str[12];
 } st, *uk;

  // Выделяем в нем память под текстовый буффер
   uk = (struct STR *)VirtualAllocEx(hProcess, NULL, sizeof(STR),MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
   if(uk == NULL)
  {
    WindowPutsStr("Error VirtualAllocEx");
    CloseHandle(hProcess);
  }
  else
  {
   int res;
   while(Rabota != 2)// в цикле читаю значение статусной строки (мой алгоритм не в DLL применяется, поэтому сделано без события)
  {
    res = SendMessage(h2, SB_GETTEXT,(WPARAM)1, (LPARAM)uk->str);
     DWORD er = GetLastError();
    if(er)
    {
     Regym = 0;
     TrayMessage(NIM_MODIFY,Regym);// это я иконку в трее разными цветами подсвечиваю
     EscapeCommFunction(hCom, CLRRTS); // Управление статусными битами сом порта.
     break;
   }
   else
   {
     // Читаем результат
     ZeroMemory(st.str, sizeof(st.str));
     dwBytesWriten = 0;
     BOOL rez = ReadProcessMemory(hProcess, uk,&st, sizeof(st), &dwBytesWriten);
     if(rez == FALSE)
    {
      WindowPutsStr("Error ReadProcessMemory");
       Regym = 0;
       TrayMessage(NIM_MODIFY,Regym);
       EscapeCommFunction(hCom, CLRRTS); 
       break;
     }
    else
   {
    if(strstr(st.str,"RX"))
   {
     if(Regym !=1)
    {
      Regym = 1;
      TrayMessage(NIM_MODIFY,Regym);
      EscapeCommFunction(hCom, CLRRTS); 
     }
   }
   else
  {
    if(Regym !=2)
   {
    Regym = 2;
    TrayMessage(NIM_MODIFY,Regym);
     EscapeCommFunction(hCom, SETRTS);
   }
  }
 }
}
  Sleep(50);
  }


  // Освобождаем ранее выделенную память
  VirtualFreeEx(hProcess, (void *)uk, 0, MEM_RELEASE);

  // Закрываем описатель процесса
  CloseHandle(hProcess);
Всегда когда нужная функция возвращает(передает) данные через указатель на память, нужно проводить вышеописанный геморрой. Если данные возвращаются(передаются) через стек, то делать этого не надо.

Последний раз редактировалось rpy3uH; 15.01.2010 в 09:19.
was вне форума Ответить с цитированием
Старый 13.01.2010, 10:27   #9
maxionans
Форумчанин
 
Аватар для maxionans
 
Регистрация: 02.01.2010
Сообщений: 254
По умолчанию

Лично у меня подозрение вызывает использование функции ShowMessage в обработчике хука. Попробуй заменить на MessageBox - вероятнее всего поможет.
maxionans вне форума Ответить с цитированием
Старый 14.01.2010, 18:42   #10
HollyPaladin
Пользователь
 
Аватар для HollyPaladin
 
Регистрация: 29.11.2009
Сообщений: 51
По умолчанию

was,я удалил из проеков tds файлы чтобы размер уменьшить(Builder создает их при компиляции) вот проекты и не запустились.
Полные версии проектов:
DLL.rar
HOOK.rar
Я тут обнаружил если заменить в dll WM_SETCURSOR на WM_KEYDOWN , то хук работает, правда устанавливается со второго раза только(при первой установке GetLastError возвращает код 126) и снимается хук тоже не с первого раза. Значит дело именно в WM_SETCURSOR.
При установке хука на WM_SETCURSOR попробовал подвигать курсор в браузуре, при клике правой кнопкой мыши выдало ошибку Acess violation user32.dll.
maxionans,убрал ShowMessage,сделал вот так:
Код:
extern "C" LRESULT __export CursorHook(int nCode,WPARAM wParam,LPARAM lParam)
{ 
 MSG * st = (MSG*)lParam;
 if( st->message== WM_SETCURSOR );
 return 0;
}
Результат остался тот же.
HollyPaladin вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Хук и потоки Murzilka153 Общие вопросы C/C++ 0 16.10.2009 11:59
Сервис и хук francyz26rus Win Api 0 19.08.2009 13:51
Хук на комбинацию W0LF Win Api 9 26.07.2009 10:33
Хук на клаву HellMercenaries Общие вопросы Delphi 3 23.07.2009 21:23
хук rpy3uH Win Api 0 30.10.2006 20:47