1 Востаннє редагувалося vtorgashov (26.01.2018 18:53:17)

Тема: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

Маю я либу awesomium (браузер в програмi) i я намагаюся викликати в нього функцiю InjectKeyboardEvent.
В яку треба передавати msg, wParam, lParam.
Але як що це зробити напряму з WndProc то буде краш.
Через те що либа ініціалізована в одному потоцi а WndProc викликає iнший потiк.
Сорцiв лiби я не маю а навiть як би мав... Поняття не маю як це виправити.
Пiдкажiть як можна отримувати повiдомлення в тому же потоцi в якому ініціалізована либа.

Нагуглив ось таке.... Але щось воно не хоче працювати.

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

LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam);

KeyboardHook* KeyboardHook::instance = 0;

KeyboardHook::KeyboardHook(HookListener* listener) : listener(listener)
{
    instance = this;
    HINSTANCE hInstance = GetModuleHandle(0);
    printf("HOOK");
    getMsgHook = SetWindowsHookEx(WH_GETMESSAGE, GetMessageProc, hInstance, GetCurrentThreadId());
}

KeyboardHook::~KeyboardHook()
{
    UnhookWindowsHookEx(getMsgHook);
    instance = 0;
}

void KeyboardHook::handleHook(UINT msg, HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_KEYDOWN:
        case WM_KEYUP:
        case WM_CHAR:
        case WM_DEADCHAR:
        case WM_SYSKEYDOWN:
        case WM_SYSKEYUP:
        case WM_SYSDEADCHAR:
        case WM_SYSCHAR:
        case WM_IME_CHAR:
        case WM_IME_COMPOSITION:
        case WM_IME_COMPOSITIONFULL:
        case WM_IME_CONTROL:
        case WM_IME_ENDCOMPOSITION:
        case WM_IME_KEYDOWN:
        case WM_IME_KEYUP:
        case WM_IME_NOTIFY:
        case WM_IME_REQUEST:
        case WM_IME_SELECT:
        case WM_IME_SETCONTEXT:
        case WM_IME_STARTCOMPOSITION:
        case WM_HELP:
        case WM_CANCELMODE:
        {
            if (listener)
                listener->handleKeyMessage(hwnd, msg, wParam, lParam);
            break;
        }
    }
}

LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    printf("YESSS WORK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
    if (nCode == HC_ACTION)
    {
        MSG *msg = (MSG*)lParam;
        if (wParam & PM_REMOVE)
            KeyboardHook::instance->handleHook(msg->message, msg->hwnd, msg->wParam, msg->lParam);
    }
    return CallNextHookEx(KeyboardHook::instance->getMsgHook, nCode, wParam, lParam);
}

PS: Я поняття не маю як це можна реалiзувати...
А ще як плюс читав що наче тут справа не в потокобезпецi.

2

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

Вам точно треба саме InjectKeyboardEvent зробити, а не, скажімо, відправити за допомогою SendMessage?

Подякували: 0xDADA11C7, Torbins2

3 Востаннє редагувалося vtorgashov (26.01.2018 19:27:34)

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

koala написав:

Вам точно треба саме InjectKeyboardEvent зробити, а не, скажімо, відправити за допомогою SendMessage?

Точно... Бо SendMessage вiдправить же повiдомлення у вiкно...
А менi треба передати либе що була натиснута кнопка.
А це робиться через
WebView->InjectKeyboardEvent(WebKeyboardEvent(mesage, wParam, lParam));
Ось посилання:
http://wiki.awesomium.com/general-use/w … views.html
Там написано що через InjectKeyboardEvent

4

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

Я  там бачу багато, але нічого подібного до цього:

    getMsgHook = SetWindowsHookEx(WH_GETMESSAGE, GetMessageProc, hInstance, GetCurrentThreadId());

Не потикайтесь до вінапі взагалі, поки не можете читати документацію. Робота з адресним простром чужого процеса заскладна штука для початківця.

Говорила баба діду: «Я поїду к Білодіду, Ізучу двомовну мову І вернусь обратно знову». А дід бабі: «Не *изди, К Білодіду нєт їзди, — Туди не ходять поїзди»
Подякували: leofun011

5

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

0xDADA11C7 написав:

Я  там бачу багато, але нічого подібного до цього:

    getMsgHook = SetWindowsHookEx(WH_GETMESSAGE, GetMessageProc, hInstance, GetCurrentThreadId());

Не потикайтесь до вінапі взагалі, поки не можете читати документацію. Робота з адресним простром чужого процеса заскладна штука для початківця.

Той код я з гiту взяв.
А як це зробити я не знаю...

6

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

Точно... Бо SendMessage вiдправить же повiдомлення у вiкно...
А менi треба передати либе що була натиснута кнопка.

Ви розумієте що таке віконне повідомлення? Ви написали бодай одне вікно на вінапі щоби зрозуміти принцип роботи з вікнами у вінді?

Говорила баба діду: «Я поїду к Білодіду, Ізучу двомовну мову І вернусь обратно знову». А дід бабі: «Не *изди, К Білодіду нєт їзди, — Туди не ходять поїзди»
Подякували: cheappi3861

7 Востаннє редагувалося vtorgashov (26.01.2018 20:09:05)

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

0xDADA11C7 написав:

Точно... Бо SendMessage вiдправить же повiдомлення у вiкно...
А менi треба передати либе що була натиснута кнопка.

Ви розумієте що таке віконне повідомлення? Ви написали бодай одне вікно на вінапі щоби зрозуміти принцип роботи з вікнами у вінді?

Ну трохи розумiю...
Натиснута кномка = WM_KEYDOWN
Створення вiкна = WM_CREATE
i т.д.
Менi потрiбно отримати то повiдомлення щоб взнати яка кнопка натиснута.
Не в змiнну же писати msg, wParam, lParam...
Бо тодi будуть пропуски повiдомлень

8

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

то чому ви городите щось там з хуками?

Говорила баба діду: «Я поїду к Білодіду, Ізучу двомовну мову І вернусь обратно знову». А дід бабі: «Не *изди, К Білодіду нєт їзди, — Туди не ходять поїзди»

9 Востаннє редагувалося vtorgashov (26.01.2018 20:10:48)

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

0xDADA11C7 написав:

то чому ви городите щось там з хуками?

Ну "getMsgHook = SetWindowsHookEx(WH_GETMESSAGE, GetMessageProc, hInstance, GetCurrentThreadId());"
Я просто знайшов...
А так то хукаю я WndProc тому що вiкно гри. Гра не моя....
Ось то код який в мене написаний

LONG origProc;
D3DHook* d3dHook = NULL;

LRESULT CALLBACK WindowProc(HWND hWnd, UINT mesage, WPARAM wParam, LPARAM lParam)
{
    if (*(PBYTE)ADDR_MENU == 1)
    {
        return CallWindowProcA(WNDPROC(origProc), hWnd, mesage, wParam, lParam);
    }
        //Всерединi методу сидить InjectKeyboardEvent
        //Якщо вiн тут то краш
    d3dHook->WndProcEvent(NULL, WM_KEYDOWN, 0, 0);
    return CallWindowProcA(WNDPROC(origProc), hWnd, mesage, wParam, lParam);
}
HANDLE Game::samp_base;
void Game::Init() 
{
    samp_base = NULL;
    _beginthread(Game::Thread, 0, NULL);
}

void Game::Thread(VOID*)
{
    printf("Start Thread\n");
    while (*(PDWORD)ADDR_ENTRY < 7) { Sleep(200); }
    origProc = SetWindowLongA(*(HWND*)0xC8CF88, GWL_WNDPROC, (LONG)WindowProc);
    d3dHook = new D3DHook(HOOK_ADDR);
    HOOK_ADDR = d3dHook;
    while (*(PDWORD)ADDR_ENTRY != 8) { Sleep(200); }
    printf("End\n");
    while (true)
    {
                //Всерединi методу сидить InjectKeyboardEvent
                //Якщо вiн тут то проблем нема
        d3dHook->WndProcEvent(NULL, WM_KEYDOWN, 0, 0);
        d3dHook->Update();
    }
}

d3dHook то таблиця методiв directx + 2 методи WndProcEvent i Update + ініціалізація либи

Подякували: leofun011

10

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

Чіти для SAMP пишете, чи що?

Yml0Y29pbjoxNmVTc0NyOXJySHBTV
DlGVmZjamV5djh5ZEtHM1NuNFNaCm
RvZ2Vjb2luOkROdXhrWExCaEh6eE1
wajFwbWhSdGlKWXZvWXJRckNiQjc=
Подякували: vtorgashov1

11 Востаннє редагувалося vtorgashov (26.01.2018 20:20:50)

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

/KIT\ написав:

Чіти для SAMP пишете, чи що?

Майже... Я би не став так морочити собi голову заради чита.
Хук RPC повiдомлення + перевiрка чи то команда (/active припустимо) = активацiя чита.
Або ImGUI взяв би... Вже готова либа.

Прихований текст
Хоча це досить весело...
Пiдiйшли такi копи i просять паспорт а у вас 6 зiрок а ви такий берете i чекаєте поки воно грузить сторiнку з функцiями чита...
Поки дочекалися вас вже посадили. xD

12

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

От є у вас в Game::Thread код, який виконується в потоці. А у ньому безкінечний цикл обробки повідомлень. От у цей цикл треба запхнути прийом і переадресацію потрібних вам повідомлень. Можна це робити через PostThreadMessage/PeekMessage, але простіше мабуть буде використати потоко-безпечну чергу. В основному потоці ви додаєте в неї елементи, а у додатковому забираєте.

Подякували: Betterthanyou, leofun012

13 Востаннє редагувалося vtorgashov (27.01.2018 00:31:43)

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

Torbins написав:

От є у вас в Game::Thread код, який виконується в потоці. А у ньому безкінечний цикл обробки повідомлень. От у цей цикл треба запхнути прийом і переадресацію потрібних вам повідомлень. Можна це робити через PostThreadMessage/PeekMessage, але простіше мабуть буде використати потоко-безпечну чергу. В основному потоці ви додаєте в неї елементи, а у додатковому забираєте.

Але потокобезпека потрiбна щоб не було крашу через те що 2 потоки одночасно хочуть звернутися кудись там ?
А тут проблема в тому що навiть якщо "Game::Thread" нiчого не робить все одно буде краш

14 Востаннє редагувалося Betterthanyou (27.01.2018 02:43:08)

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

Не знаю чи допоможе..., але якщо хочете, то прочитайте

У вас є awesomium і вам потрібно викликати InjectKeyboardEvent у WndProc ?
Якщо ви розробляєте програму у Visual Studio, то можна скористатися програмою Spy++ (Tools->Spy++) для того щоб знайти вікно яке вам потрібно
Наприклад: потрібно написати 'nnnnnnnnnnn' у notepad (стандартна програма віндовс), для цього:
Відкрити Spy++ і знайти вікно з відповідною назвою (або натиснути пошук і ввести назву потрібного вікна). Ввід ('nnnnnnnnnnn') потрібно здійснювати не у вікно, а в спеціальний елемент який знаходиться у вікні, тому потрібно натиснути '+' біля назви вікна (у Spy++), і знати цей елемент, у моєму випадку це Edit, тепер потрібно дізнатися назву класу вікна і елемента в який буде здійснюватися ввід, для цього ПКМ->Properties->Class->Class Name

Якщо відомий HANDLE, то звісно не потрібно його шукати

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//натиснення відбувається в WindowProc
//тепер можна викликати InjectKeyboardEvent замість WinApi функції
    return PostMessage(hwnd, uMsg, wParam, lParam);
}

int main()
{
    LRESULT wp;//Результат, не обов'язково
//Шукаю вікно по класу (який був взятий у spy++)
    HWND fh = FindWindowExW(
        NULL,
        NULL,
        L"Notepad",
        NULL
    );
    //перевіряю чи знайшов
    if (fh == nullptr) 
    { 
        cout << "I Cannot Find The Window\n"; 
        getchar();
        return 0;
    }
    else
    {
        cout << "I Found The Window\n";
    }
//Шукаю елемент редагування, у вікні 'fh'
    HWND fh2 = FindWindowExW(
        fh,
        NULL,
        L"Edit",
        NULL
    );
//перевіряю чи знайшов
    if (fh2 == nullptr)
    {
        cout << "I Cannot Find The Handle\n";
        getchar();
        return 0;
    }
    else
    {
        cout << "I Found The Handle\n";
    }
//натискаю клавішу 'n'
    wp = WindowProc(fh2, WM_KEYDOWN, 0x4E, MapVirtualKey(0x4E, MAPVK_VK_TO_VSC));
    cout << wp << '\n';


    cout << "Press any key...";
    getchar();
    return 0;
}

Робить навіть у згорненому вікні, але на всякий випадок можна сфокусуватися перед викликом WindowProc за допомогою SetForegroundWindow(fh2);

Так само можна знайти у Spy++ процес або поток, якщо ви можете знайти поток в якому "либа" ініціалізована, тоді має вийти...

Подякували: leofun01, vtorgashov2

15 Востаннє редагувалося vtorgashov (27.01.2018 13:17:14)

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

Betterthanyou написав:

Не знаю чи допоможе..., але якщо хочете, то прочитайте

У вас є awesomium і вам потрібно викликати InjectKeyboardEvent у WndProc ?
Якщо ви розробляєте програму у Visual Studio, то можна скористатися програмою Spy++ (Tools->Spy++) для того щоб знайти вікно яке вам потрібно
Наприклад: потрібно написати 'nnnnnnnnnnn' у notepad (стандартна програма віндовс), для цього:
Відкрити Spy++ і знайти вікно з відповідною назвою (або натиснути пошук і ввести назву потрібного вікна). Ввід ('nnnnnnnnnnn') потрібно здійснювати не у вікно, а в спеціальний елемент який знаходиться у вікні, тому потрібно натиснути '+' біля назви вікна (у Spy++), і знати цей елемент, у моєму випадку це Edit, тепер потрібно дізнатися назву класу вікна і елемента в який буде здійснюватися ввід, для цього ПКМ->Properties->Class->Class Name

Якщо відомий HANDLE, то звісно не потрібно його шукати

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//натиснення відбувається в WindowProc
//тепер можна викликати InjectKeyboardEvent замість WinApi функції
    return PostMessage(hwnd, uMsg, wParam, lParam);
}

int main()
{
    LRESULT wp;//Результат, не обов'язково
//Шукаю вікно по класу (який був взятий у spy++)
    HWND fh = FindWindowExW(
        NULL,
        NULL,
        L"Notepad",
        NULL
    );
    //перевіряю чи знайшов
    if (fh == nullptr) 
    { 
        cout << "I Cannot Find The Window\n"; 
        getchar();
        return 0;
    }
    else
    {
        cout << "I Found The Window\n";
    }
//Шукаю елемент редагування, у вікні 'fh'
    HWND fh2 = FindWindowExW(
        fh,
        NULL,
        L"Edit",
        NULL
    );
//перевіряю чи знайшов
    if (fh2 == nullptr)
    {
        cout << "I Cannot Find The Handle\n";
        getchar();
        return 0;
    }
    else
    {
        cout << "I Found The Handle\n";
    }
//натискаю клавішу 'n'
    wp = WindowProc(fh2, WM_KEYDOWN, 0x4E, MapVirtualKey(0x4E, MAPVK_VK_TO_VSC));
    cout << wp << '\n';


    cout << "Press any key...";
    getchar();
    return 0;
}

Робить навіть у згорненому вікні, але на всякий випадок можна сфокусуватися перед викликом WindowProc за допомогою SetForegroundWindow(fh2);

Так само можна знайти у Spy++ процес або поток, якщо ви можете знайти поток в якому "либа" ініціалізована, тоді має вийти...

Ну ваш код я так розумiю пише n в notepad...
Дякую звичайно що вiдповiли.

Передавати даннi через глобальну(з локом на час читання/запису) пам'ять це не дуже погана iдея ?

Ну вийшло ось так
https://i.imgur.com/qKE5IwG.jpg

16

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

е чувак полегше... з іншого потока процедурки не викликаються. Організуй протокол обміну даними через змінну-порт. розумієш- перемінна - порт. Структура. Ти туди- воно обратно.

17

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

Alchimic написав:

е чувак полегше... з іншого потока процедурки не викликаються. Організуй протокол обміну даними через змінну-порт. розумієш- перемінна - порт. Структура. Ти туди- воно обратно.

What ?

18

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

vtorgashov написав:
Alchimic написав:

е чувак полегше... з іншого потока процедурки не викликаються. Організуй протокол обміну даними через змінну-порт. розумієш- перемінна - порт. Структура. Ти туди- воно обратно.

What ?

Не звертайте уваги, це якийсь просунутий бот. Аналізує написане ще сяк-так, а от спілкуватися не вміє.

Подякували: vtorgashov, sensei, leofun013

19

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

koala написав:
vtorgashov написав:
Alchimic написав:

е чувак полегше... з іншого потока процедурки не викликаються. Організуй протокол обміну даними через змінну-порт. розумієш- перемінна - порт. Структура. Ти туди- воно обратно.

What ?

Не звертайте уваги, це якийсь просунутий бот. Аналізує написане ще сяк-так, а от спілкуватися не вміє.

Не надто розумний для бота ?

20

Re: Як отримати повiдомлання (тi якi iдуть у wndproc) ?

vtorgashov написав:
koala написав:
vtorgashov написав:

What ?

Не звертайте уваги, це якийсь просунутий бот. Аналізує написане ще сяк-так, а от спілкуватися не вміє.

Не надто розумний для бота ?

https://goo.gl/e1bsjz