Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Функция-фильтр глобального хука, dll загружается и не работает 
:(
    Опции темы
Katko
Дата 28.3.2009, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 11.9.2007

Репутация: нет
Всего: нет



Доброго времени суток
Ставлю глобальный хук на окно приложения (функция-фильтр в dll). Надо записывать события мыши и клавиатуры для пересылки по сети и воспроизведения на другой машине. Пока работаю с записью. Прога и dll компилятся , но не работают как надо. Файл с полями структуры не создается. Помогите найти ошибку, буду очень благодарна.
Вот dll:
Код

#define _AFXDLL
#define EXPORT extern "C" __declspec(dllexport)
#include "afxwin.h"
#include "stdafx.h"
#include <windows.h>
#include <WinUser.h>
#include <stdio.h>

LPEVENTMSG EventMSG;
HHOOK hook;
__declspec(dllexport) LRESULT CALLBACK JournalRecordProc(int, WPARAM, LPEVENTMSG);
BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    break;

    case DLL_PROCESS_DETACH:
    break;

    default:
    return TRUE;
    }
return FALSE;
}
__declspec(dllexport) LRESULT CALLBACK JournalRecordProc (int nCode, WPARAM wp, LPEVENTMSG EventMSG)
{
    FILE* fp;
    fprintf (fp, "nCode = %d\n", nCode);
    if (nCode >= 0)
    {
    fp = fopen ("journal_temp.txt","a");
    fprintf(fp, "%d\n", EventMSG->message);
    fprintf(fp, "%d\n", EventMSG->paramL);
    fprintf(fp, "%d\n", EventMSG->paramH);
    fprintf(fp, "%s\n", EventMSG->time);
    fprintf(fp, "%s\n", EventMSG->hwnd);
    fprintf(fp, "%x\n", EventMSG->hwnd);
    fclose (fp);
    return CallNextHookEx(hook, nCode, wp, EventMSG);
    }
    else
    {
    fclose (fp);
    return CallNextHookEx(hook, nCode, wp, EventMSG);
    }
}


Вот прога:
Код

#pragma once
#define _AFXDLL
#define WINVER 0x0501
#include "afxwin.h"
#include <windows.h>
//#include "stdafx.h"
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
HBITMAP handle;
BITMAP bit;
CBitmap *bm;
/////////////////////////////////////////////////////////////////
HMODULE hdll;
HOOKPROC hkprc;
static HHOOK hook;
FILE *fp;
////////////////////////////////////////////////////////////////
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lParam)
{
    if(GetWindowThreadProcessId(hwnd, NULL) == GetCurrentThreadId())
    {
        *(HWND*)lParam = hwnd;
        return FALSE;
    }
    return TRUE;
}
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    fp = fopen ("file1.txt", "a");
    // загрузка библиотеки
    hdll = LoadLibrary ("hook_filtr.dll");
    if (hdll == 0)
        fprintf (fp, "SCUKKO!\n");
    else 
        fprintf (fp, "hdll = %d\n", hdll);
    MyRegisterClass(hInstance);
    InitInstance(hInstance, nCmdShow);    
    //hkprcSysMsg = (HOOKPROC)GetProcAddress(hdll, "JournalRecordProc");
    //hhookSysMsg = SetWindowsHookEx(WH_SYSMSGFILTER, hkprcSysMsg, hdll, 0);

    while(GetMessage(&msg, 0, 0, 0))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
UnhookWindowsHookEx(hook);
FreeLibrary (hdll);
return 0;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASS wcex;
    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = NULL;
    wcex.lpszClassName    = (LPCTSTR)"Class";
    return RegisterClass(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
   hInst = hInstance; // Store instance handle in our global variable
   handle = (HBITMAP)LoadImage(GetModuleHandle(0), "pict1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
   bm = CBitmap::FromHandle(handle);
   bm->GetBitmap(&bit);
   hWnd = CreateWindow((LPCTSTR)"Class", (LPCTSTR)"Title", WS_OVERLAPPEDWINDOW,
      0, 0, bit.bmWidth, bit.bmHeight, NULL, NULL, hInstance, NULL);
   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    BITMAP bmpInfo = {};
    WINDOWINFO w_info;
    switch (message)
    {
    case WM_CREATE:
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        {
           CClientDC cdc(NULL);
           CDC dc;
           dc.CreateCompatibleDC(&cdc);
           dc.SelectObject(bm);
           GetWindowInfo(hWnd, &w_info);
           cdc.StretchBlt (w_info.rcWindow.left, w_info.rcWindow.top, (w_info.rcWindow.right-w_info.rcWindow.left),
               (w_info.rcWindow.bottom-w_info.rcWindow.top), 
               &dc, 0, 0, bit.bmWidth, bit.bmHeight, SRCCOPY);
           dc.DeleteDC();
        }
        EndPaint(hWnd, &ps);
        hkprc = (HOOKPROC)GetProcAddress(hdll, "JournalRecordProc");
        fprintf (fp,"hkprc = %d\n", hkprc);
        fclose (fp);
        hook = SetWindowsHookEx(WH_JOURNALRECORD, hkprc, hdll, 0);
        break;
    case WM_DESTROY:
        //UnhookWindowsHookEx(hhook);
        //FreeLibrary (hdll);
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

PM MAIL   Вверх
Katko
Дата 29.3.2009, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 11.9.2007

Репутация: нет
Всего: нет



Одну решили - две родили  smile 
1. Подскажите, как отработать выпадение из хука? а то виснем чутка насмерть...
2. Где регистрировать хук? В цикле сообщений или раньше?
PM MAIL   Вверх
xvr
Дата 30.3.2009, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Хук написан неправильно:
  •  Строка 10 в dll - в эту переменную надо положит handle хука (из проги от SetWindowsHookEx)
  •  Регистрировать хук в WM_PAINT ТОЧНО не надо. Лучше это сделать сразу после загрузки dll в main
  •  Строка 30 в dll - куда пишет fprintf? fp еще не инициализирован (это делается только в 33й строке)
  •  Строка 35 в dll - fclose лишний - по этой ветке fp не открыт

PM MAIL   Вверх
Katko
Дата 30.3.2009, 20:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 11.9.2007

Репутация: нет
Всего: нет



xvr,
Цитата

# Строка 10 в dll - в эту переменную надо положит handle хука (из проги от SetWindowsHookEx)
#  Регистрировать хук в WM_PAINT ТОЧНО не надо. Лучше это сделать сразу после загрузки dll в main
#  Строка 30 в dll - куда пишет fprintf? fp еще не инициализирован (это делается только в 33й строке)
#  Строка 35 в dll - fclose лишний - по этой ветке fp не открыт

Вышеуказанные ошибки исправила.

Теперь и хук ставится и файл создается. Только сам файл пустой  smile 
Новый код dll:
Код

#include "stdafx.h"
#include <stdio.h>

#pragma data_seg (".sh_seg")
HHOOK hook;
#pragma data_seg()
FILE *fp;
LPEVENTMSG EventMSG;

__declspec (dllexport) BOOL WINAPI DestroyHooks(void);

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        {
        fp = fopen ("hook_dll.txt","a");
        MessageBox (0, "Загрузка библиотеки", "", MB_OK);
        break;
        }
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        {
        fclose (fp);
        MessageBox (0, "Выгрузка библиотеки", "", MB_OK);
        break;
        }
    }
    return TRUE;
}
__declspec (dllexport) LRESULT CALLBACK JournalRecordProc (int nCode, WPARAM wp, LPEVENTMSG EventMSG)
{

    //fprintf (fp, "nCode = %d\n", nCode);
    fprintf(fp, "%d\n", EventMSG->message);
    fprintf(fp, "%d\n", EventMSG->paramL);
    fprintf(fp, "%d\n", EventMSG->paramH);
    fprintf(fp, "%s\n", EventMSG->time);
    fprintf(fp, "%s\n", EventMSG->hwnd);
    fprintf(fp, "%x\n", EventMSG->hwnd);
    return CallNextHookEx(hook, nCode, wp, EventMSG);
}

При проходе пошаговым дебагером не все параметры инициализируются значениями.  hook в основном файле остается неопределенным и hwnd в цикле обработки сообщений тоже. Хотя, судя по отсутствию реакции на ввод, хук ставится:
Код

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    hdll = LoadLibrary ((LPCTSTR)"hook_dll.dll");
    // регистрация класса окна
    MyRegisterClass(hInstance);
    // инициализация и отображение окна
    InitInstance(hInstance, nCmdShow);
    jrp = (HOOKPROC)GetProcAddress(hdll, "JournalRecordProc");
    hook = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)jrp, hdll, 0);
    UnhookWindowsHookEx(hook);
    // осовной цикл окна - обработка поступающих сообщений
    while(GetMessage(&msg, 0, 0, 0))
    {
    // диспетчирезация сообщений
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
return 0;
}


PM MAIL   Вверх
xvr
Дата 30.3.2009, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Во первых - прога расчитанна на перехват ТОЛЬКО своих сообщений или всех в системе? Если первое, то ни .sh_seg ни отдельная dll не нужны. Если второе - то так работать с файлом нельзя - будут несколько открытых хэндлов на один и тот же файл, результаты записи непредсказуемы.
Теперь собственно по коду:
  •  В dll строка 5 должна быть HHOOK hook=0; Иначе переменная будет расположена в сегменте BSS, а на него действие прагмы data_seg не распространяется
  •  Переменную hook нужно проинициализировать ИМЕННО в dll, например сделав специальную функцию, которая присвоит в эту переменную свой параметр. И позвать ее из основной программы.
  •  Строка 10 и 11 в основной проге. В сроке 10 хук ставится, а в строке 11 - снимается. Т.е. хука нет  smile


Это сообщение отредактировал(а) xvr - 30.3.2009, 21:30
PM MAIL   Вверх
Katko
Дата 31.3.2009, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 11.9.2007

Репутация: нет
Всего: нет



xvr, спасибо  smile  Твои советы мне очень помогают.
События надо хватать на одной машине под одним пользователем, а воспроизводить на другой под другим. Что-то вроде Radmin'а должно получиться.
В MSDN я читала, что хук, который не в dll, только под одним профилем работает  smile  Если ставить локальный и потом инициализировать EventMSG на сервере из файла, то прокатит? Приложение, к которому JOURNALPLAYBACK прикрепляться будет, стороннее  smile 
Цитата

 Строка 10 и 11 в основной проге. В сроке 10 хук ставится, а в строке 11 - снимается. Т.е. хука нет 

При пошаговом дебаге на этой строке залипает, как при установке хука. А в ОС нет никаких задержек. Может лучше снятие хука в dll поместить?
PM MAIL   Вверх
xvr
Дата 31.3.2009, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(Katko @ 31.3.2009,  10:15)
xvr, спасибо  smile  Твои советы мне очень помогают.
События надо хватать на одной машине под одним пользователем, а воспроизводить на другой под другим. 

В одном приложении или в нескольких?
Цитата

В MSDN я читала, что хук, который не в dll, только под одним профилем работает  smile  
Не под одним профилем, а в одном приложении - в том, которое этот хук поставило.
Цитата

Приложение, к которому JOURNALPLAYBACK прикрепляться будет, стороннее  smile 
Это и есть ответ на вопрос - хук надо помещать в dll

Цитата

Цитата

 Строка 10 и 11 в основной проге. В сроке 10 хук ставится, а в строке 11 - снимается. Т.е. хука нет 

При пошаговом дебаге на этой строке залипает, как при установке хука. 
Угу, в 10й залипнет, в 11 разлипнет - и хука нет  smile 
Цитата

А в ОС нет никаких задержек. Может лучше снятие хука в dll поместить?
Угу, или в само приложение, которое его ставило, но только в КОНЦЕ работы приложения, сразу перед выходом (хук при этом снимется)

PM MAIL   Вверх
Katko
Дата 31.3.2009, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 11.9.2007

Репутация: нет
Всего: нет



А залипание ввода после установки JOURNALRECORD хука - это нормально или у меня руки не из того места растут? Я так поняла из MSDN, что при nCode = HC_ACTIOТ события обрабатываются как обычно и только после этого заносятся в EVENTMSG. Может вообще не этот хук надо использовать  smile 
PM MAIL   Вверх
xvr
Дата 31.3.2009, 16:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Вроде ничего залипать не должно. Если только процедура самого хука не подвисла

PM MAIL   Вверх
Katko
Дата 1.4.2009, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 11.9.2007

Репутация: нет
Всего: нет



Спасибо за помощь. smile
Стало понятней. Осталось жуков в коде выловить.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0863 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.