Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Callback dll return value

18K
19 июня 2012 года
imAlex
179 / / 29.07.2010
Добрый день.
У меня есть библиотека (на C++) с обратным вызовом, отслеживающая состояние хранителя экрана.
В дальнейшем данная библиотека будет работать с кодом c#.
Сейчас при активации хранителя в файл записывается тестовый текст.
Хочется получать ответ из dll в exe в виде булево значения. Я пересмотрел кучу примеров и на msdn-е, и на codeproject.com, и еще на многих сайтах, однако мне это не помогло. Все время упираюсь в логику конструкции самой dll-ки.
Что имеем на данный момент:
.dll
Код:
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <time.h>

#pragma argsused
//---------------------------------------------------------------------------


bool bSCRSAVEACTIVE;                  // Установлен ли ScreenSaver
//---------------------------------------------------------------------------
extern "C" __declspec(dllexport) LRESULT CALLBACK ScreenSaverHook(UINT,WPARAM,LPARAM);
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
   if(reason==DLL_PROCESS_ATTACH)                             // Проецируем на адр. простр.
   {
        if(!SystemParametersInfo(SPI_GETSCREENSAVEACTIVE,0, &bSCRSAVEACTIVE,0))
         MessageBox(0,"Не могу получить данные об установленном"
                   "хранителе экрана",
                       "Внимание!",MB_ICONERROR);
   }
    return 1;
}

void fileW()
{
        int bal;
        FILE *file;
        if ((file = fopen("3.txt","a")) != NULL)
        {
                fputs("Test DLL", file );
        }
        fclose(file);
        getch();
}
//---------------------------------------------------------------------------
LRESULT CALLBACK ScreenSaverHook(UINT nCode , WPARAM wParam, LPARAM lParam)
{
        MSG *msg = (MSG *)lParam;
        if ( msg->message == WM_SYSCOMMAND && msg->wParam == SC_SCREENSAVE)
        {                                                                      
                fileW();
        }
        return CallNextHookEx(ScreenSaverHook, nCode, wParam, lParam);
}
.exe

Код:
#include <windows.h>
#pragma hdrstop

#define MYWM_NOTIFY (WM_APP+100)
#define IDC_MYICON  1006

HINSTANCE hinst;                           // Описатель экземпляра приложения
NOTIFYICONDATA NotIconD;                                   // Для значка в Tray
HWND MainWnd;                              // Окно

HINSTANCE hLib;                            // Библиотека с ловушками

HHOOK hScreenSaverHook;


LRESULT CALLBACK (__stdcall *pScreenSaverHook)(int,WPARAM,LPARAM);
//---------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
InitApplication(HINSTANCE,int);                                    
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
void vfSetTrayIcon(HINSTANCE);
void vfResetTrayIcon();

#pragma argsused

WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
//----------------
    hLib=LoadLibrary("../DLL/dll.dll");
   if(hLib)
   {
       (void*)pScreenSaverHook=GetProcAddress(hLib,"ScreenSaverHook");
        hScreenSaverHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)(pScreenSaverHook), hLib,0);

//----------------
        if (InitApplication(hInstance,nCmdShow))
    {
            vfSetTrayIcon(hInstance);               // Создаём окна
            while (GetMessage(&msg,(HWND)(NULL),0,0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
//----------------
            UnhookWindowsHookEx(hScreenSaverHook);          // Завершаем
            FreeLibrary(hLib);
            vfResetTrayIcon();
            return 0;
       }
    }
    return 1;
}
//---------------------------------------------------------------------------
BOOL InitApplication(HINSTANCE hinstance,int nCmdShow)
{                                       // Создание главного окна
    WNDCLASS wcx;                                                           // Класс окна

    wcx.style=NULL;
    wcx.lpfnWndProc=MainWndProc;
    wcx.cbClsExtra=0;
    wcx.cbWndExtra=0;
    wcx.hInstance=hinstance;
    wcx.hIcon=LoadIcon(hinstance,"MAINICON");
    wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
    wcx.hbrBackground=(HBRUSH)(COLOR_APPWORKSPACE);
    wcx.lpszMenuName=NULL;
    wcx.lpszClassName="HookWndClass";

    if(RegisterClass(&wcx))                                                 // Создаём окно
   {
        MainWnd=CreateWindow("HookWndClass","SSHook", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/,
                                        CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
                            CW_USEDEFAULT,NULL,NULL,hinstance,NULL);

        if(!MainWnd)
            return FALSE;

        return TRUE;
   }
   return false;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK MainWndProc(HWND hwnd,UINT uMsg,WPARAM wParam, LPARAM lParam)
{                                       // Оконная процедура
    switch (uMsg)
    {
        case WM_DESTROY:
      {
            PostQuitMessage(0);
            break;
      }
//------------
      case MYWM_NOTIFY:
      {
            if(lParam==WM_RBUTTONUP)                                // Правый щелчок на значке - завершаем
                PostQuitMessage(0);
         break;
      }
        default:
            return DefWindowProc(hwnd,uMsg,wParam,lParam);
    }
    return 0;
}
//---------------------------------------------------------------------------
void vfSetTrayIcon(HINSTANCE hInst)
{                                       // Значок в Tray
   char* pszTip="Хранитель экрана";

   NotIconD.cbSize=sizeof(NOTIFYICONDATA);
   NotIconD.hWnd=MainWnd;
   NotIconD.uID=IDC_MYICON;
   NotIconD.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
    NotIconD.uCallbackMessage=MYWM_NOTIFY;
    NotIconD.hIcon=LoadIcon(hInst,"MAINICON");
    lstrcpyn(NotIconD.szTip,pszTip,sizeof(NotIconD.szTip));

    Shell_NotifyIcon(NIM_ADD,&NotIconD);
}
//---------------------------------------------------------------------------
void vfResetTrayIcon()
{                                       // Удаляем значок
    Shell_NotifyIcon(NIM_DELETE,&NotIconD);
}
Этот пример работает и записывает текст в файл.
Я пробовал конструкцию объявления обратного вызова:

 
Код:
HHOOK hHook=NULL;
HINSTANCE hMod=NULL;
extern "C" __declspec(dllexport) bool InstallHook(DWORD ThreadID){
    hHook=SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)ScreenSaverHook,(HINSTANCE) hMod, 0);
    return hHook ? true:false;
}
UINT WM_SCRNSVSTART = RegisterWindowMessage("ScreenSaverStarted");
Соответственно из exe вызывает:

 
Код:
typedef BOOL (*InstallHook)(DWORD ThreadID);
void load_and_call(void)
{
    HMODULE hmod = LoadLibrary(...);
        InstallHook func =  (InstallHook)GetProcAddress(hLib, "InstallHook");
        func(ThreadID);
}
Однако результата ноль.
Подскажите, как грамотно организовать конструкцию обратного вызова с возвратом значения.
Если есть пример, опишите его здесь.
277
19 июня 2012 года
arrjj
1.7K / / 26.01.2011
Указатель на функции?
Тыж сам используешь это.

В dll:
Код:
void (*callBack)(bool)=0;
.....
extern "C" __declspec(dllexport) bool InstallHook(/*Это лишнее DWORD ThreadID,*/void (*foo)(bool)){
    hHook=SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)ScreenSaverHook,(HINSTANCE) hMod, 0);
    callBack=foo;
    return hHook ? true:false;
}
...
LRESULT CALLBACK ScreenSaverHook(UINT nCode , WPARAM wParam, LPARAM lParam)
{
        MSG *msg = (MSG *)lParam;
        if ( msg->message == WM_SYSCOMMAND && msg->wParam == SC_SCREENSAVE)
        {                                                                      
                //fileW();
                (*callBack)(true);
        }
        return CallNextHookEx(ScreenSaverHook, nCode, wParam, lParam);
}
...
В exe:
Код:
typedef BOOL (*InstallHook)(/*Это лишнее DWORD ThreadID,*/ void (*)(bool));
static void myCallBack(bool hz)
{
if(hz)
    die();
else
    live();
}
void load_and_call(void)
{
    HMODULE hmod = LoadLibrary(...);
        InstallHook func =  (InstallHook)GetProcAddress(hLib, "InstallHook");
        func(/*Это лишнее ThreadID,*/&myCallBack);
}
18K
21 июня 2012 года
imAlex
179 / / 29.07.2010
хмм. Я попробовал. Выдает ошибку:
Project ...test.exe raised too many consecutive exceptions: 'access violation at 0x00000000: read of address 0x00000000'
При пошаговом прохождении заметил, что после установки крючка, он остается пустым.
InstallHook func = HULL. Видимо из-за этого программа вылетает на строке func(&myCallBack);
Мне кажется, что при проецировании адресного пространства в библиотеку не передаются параметры окна
18K
21 июня 2012 года
imAlex
179 / / 29.07.2010
Вот код целиком:
exe

Код:
#include <windows.h>
#include <stdio.h>
#include <time.h>
#pragma hdrstop
//////////////////////////////////////////////////////////////////////////
//                      Глобальные переменные   //
//////////////////////////////////////////////////////////////////////////
#define MYWM_NOTIFY (WM_APP+100)
#define IDC_MYICON  1006

HINSTANCE hinst;                                                // Описатель экземпляра приложения
NOTIFYICONDATA NotIconD;                                                        // Для значка в Tray
HWND MainWnd;                                                   // Окно

HINSTANCE hLib;                                                 // Библиотека с ловушками

HHOOK hMouseHook;
HHOOK hScreenSaverHook;


LRESULT CALLBACK (__stdcall *pScreenSaverHook)(int,WPARAM,LPARAM);
LRESULT CALLBACK (__stdcall *pMouseHook)(int,WPARAM,LPARAM);
//---------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
InitApplication(HINSTANCE,int);                                         // Прототипы
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
void vfSetTrayIcon(HINSTANCE);
void vfResetTrayIcon();
//////////////////////////////////////////////////////////////////////////
//          Функции                      //
//////////////////////////////////////////////////////////////////////////
#pragma argsused

void fileW()
{
        int bal;
        FILE *file;
        if ((file = fopen("3.txt","a")) != NULL)
        {
                fputs("Test DLL", file );
        }
        fclose(file);
}

typedef BOOL (*InstallHook)(void (*)(bool));
static void myCallBack(bool hz)
{
    if(hz)
    {
        fileW();
    }
}



WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
//----------------
    hLib=LoadLibrary("../DLL/dll.dll");
   if(hLib)
   {
            InstallHook func =  (InstallHook)GetProcAddress(hLib, "InstallHook");
            func(&myCallBack);

       //(void*)pScreenSaverHook=GetProcAddress(hLib,"ScreenSaverHook");
       //   hScreenSaverHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)(pScreenSaverHook), hLib,0);// Ставим ловушки

       (void*)pMouseHook=GetProcAddress(hLib,"MouseHook");
        hMouseHook=SetWindowsHookEx(WH_MOUSE,(HOOKPROC)(pMouseHook), hLib,0);
//----------------
        if (InitApplication(hInstance,nCmdShow))
    {
            vfSetTrayIcon(hInstance);               // Создаём окна
            while (GetMessage(&msg,(HWND)(NULL),0,0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
//----------------
            //UnhookWindowsHookEx(hScreenSaverHook);
            UnhookWindowsHookEx(hMouseHook);                        // Завершаем
            FreeLibrary(hLib);
            vfResetTrayIcon();
            return 0;
       }
    }
    return 1;
}
//---------------------------------------------------------------------------
BOOL InitApplication(HINSTANCE hinstance,int nCmdShow)
{                                       // Создание главного окна
    WNDCLASS wcx;                                                           // Класс окна

    wcx.style=NULL;
    wcx.lpfnWndProc=MainWndProc;
    wcx.cbClsExtra=0;
    wcx.cbWndExtra=0;
    wcx.hInstance=hinstance;
    wcx.hIcon=LoadIcon(hinstance,"MAINICON");
    wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
    wcx.hbrBackground=(HBRUSH)(COLOR_APPWORKSPACE);
    wcx.lpszMenuName=NULL;
    wcx.lpszClassName="HookWndClass";

    if(RegisterClass(&wcx))                                                 // Создаём окно
   {
        MainWnd=CreateWindow("HookWndClass","SSHook", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/,
                                        CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
                            CW_USEDEFAULT,NULL,NULL,hinstance,NULL);

        if(!MainWnd)
            return FALSE;

        return TRUE;
   }
   return false;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK MainWndProc(HWND hwnd,UINT uMsg,WPARAM wParam, LPARAM lParam)
{                                       // Оконная процедура
    switch (uMsg)
    {
        case WM_DESTROY:
                {
            PostQuitMessage(0);
                break;
                }
                case MYWM_NOTIFY:
                {
            if(lParam==WM_RBUTTONUP)                                // Правый щелчок на значке - завершаем
                PostQuitMessage(0);
                        break;
                }
        default:
            return DefWindowProc(hwnd,uMsg,wParam,lParam);
    }
    return 0;
}
//---------------------------------------------------------------------------
void vfSetTrayIcon(HINSTANCE hInst)
{                                       // Значок в Tray
   char* pszTip="Хранитель экрана";

   NotIconD.cbSize=sizeof(NOTIFYICONDATA);
   NotIconD.hWnd=MainWnd;
   NotIconD.uID=IDC_MYICON;
   NotIconD.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
    NotIconD.uCallbackMessage=MYWM_NOTIFY;
    NotIconD.hIcon=LoadIcon(hInst,"MAINICON");
    lstrcpyn(NotIconD.szTip,pszTip,sizeof(NotIconD.szTip));

    Shell_NotifyIcon(NIM_ADD,&NotIconD);
}
//---------------------------------------------------------------------------
void vfResetTrayIcon()
{                                       // Удаляем значок
    Shell_NotifyIcon(NIM_DELETE,&NotIconD);
}

dll

Код:
#include <windows.h>
#include <conio.h>
#pragma argsused
//---------------------------------------------------------------------------

bool bSCRSAVEACTIVE;                                                // Установлен ли ScreenSaver
MOUSEHOOKSTRUCT* psMouseHook;                                                   // Для анализа сообшений от мыши
HHOOK hHook=NULL;
HINSTANCE hMod=NULL;
//---------------------------------------------------------------------------
extern "C" __declspec(dllexport) LRESULT CALLBACK ScreenSaverHook(UINT,WPARAM,LPARAM);
extern "C" __declspec(dllexport) LRESULT CALLBACK MouseHook(UINT,WPARAM,LPARAM);

void (*callBack)(bool)=0;
extern "C" __declspec(dllexport) bool InstallHook(void (*foo)(bool))
{
    hHook=SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)ScreenSaverHook,(HINSTANCE) hMod, 0);
    callBack=foo;
    return hHook ? true:false;
}
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
   if(reason==DLL_PROCESS_ATTACH)                                           // Проецируем на адр. простр.
   {
        if(!SystemParametersInfo(SPI_GETSCREENSAVEACTIVE,0, &bSCRSAVEACTIVE,0))
         MessageBox(0,"Не могу получить данные об установленном"
                   "хранителе экрана",
                       "Внимание!",MB_ICONERROR);
   }
    return 1;
}
LRESULT CALLBACK MouseHook(UINT nCode,WPARAM wParam,LPARAM lParam)
{                                                               // Ловушка мыши - включает хранитель когда в углу
    if(wParam==WM_MOUSEMOVE || wParam==WM_NCMOUSEMOVE)
    {
        psMouseHook=(MOUSEHOOKSTRUCT*)(lParam);
                if(psMouseHook->pt.x==0 && psMouseHook->pt.y==0)
            if(bSCRSAVEACTIVE)
                        {
                PostMessage(psMouseHook->hwnd,WM_SYSCOMMAND,
                            SC_SCREENSAVE,0);
                        }
        }
    return 0;
}
LRESULT CALLBACK ScreenSaverHook(UINT nCode , WPARAM wParam, LPARAM lParam)
{
        MSG *msg = (MSG *)lParam;
        if ( msg->message == WM_SYSCOMMAND && msg->wParam == SC_SCREENSAVE)
        {
                (*callBack)(true);
        }
        return CallNextHookEx(ScreenSaverHook, nCode, wParam, lParam);
}
Здесь используется еще ловушка мыши - включает хранитель когда в углу.
65K
24 июня 2012 года
verholom
48 / / 29.08.2011
От объясните мне, зачем Вы ставите ловушку (хук), если вы создаете окно, которое по-любому получит нужные сообщения и в его оконной процедуре Вы их обработаете....
Это первое.

Второе: если уж так охота позаморачиваться с ДЛЛ, то конструкция может быть такая (уж очень упрощенно):

1. В DllMain делайте создание окна (возьмите туже STATIC, зачем Вам регистрировать еще один класс) и повесьте на него свою оконную функцию (SetWindowLong).
2. Длл подгружена в процесс (ваша, следящая ехе, неважно как, но DllMain сработала), экспортируйте из нее какую-нибудь функцию, принимающую адрес для уведомления (адрес функции, которую надо будет вызвать) и сохраните его к примеру как свойство окна...
3. В функции созданного Вами окна проверяйте нужные данные и вызывайте сохраненный адрес....
18K
25 июня 2012 года
imAlex
179 / / 29.07.2010
Verholom, спасибо за ответ.
Цитата: verholom
От объясните мне, зачем Вы ставите ловушку (хук)...


Я описывал в самом начале:

Цитата:
В дальнейшем данная библиотека будет работать с кодом c#.


а именно со службой написанной на c#.
На сколько мне известно, на c#-пе нельзя установить ловушку на сообщение от системы об активации хранителя экрана. Именно по этому я решил написать dll-ку, которая будет отслеживать данное событие и уведомлять об активации основной код.
Сейчас exe на с++ с целью тестирования и исключения ошибок при импорте в c#.

По поводу предложения, связанного с описанием окна внутри dll (если я все правильно понял):
я где-то читал о том, что если окно создавать прямо в dll, сообщение не будет отправятся если фокус будет на другом окне. Равно как и при инициализации ловушки в коде exe. Если я здесь не прав, то это даже лучше, так-как моя служба не имеет окна и мне не придется его создавать.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог