На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Использование библиотеки Interception
    Всем привет!

    Создал тему с целью разделения темы о разработке драйверов под Windows.
    Просто чтобы не было обсуждений в одной теме "все-обо-всем".

    Библиотека Interception реализует перехват и фильтрацию данных от клавиатуры или мыши
    не уровне системы с помощью собственного драйвера-фильтра. В обсуждении решается вопрос
    перехвата данных от КартРидера, который опознается в системе как HID Keyboard.
      Цитата JoeUser @
      Передо мной лежит устройство - USB Card Reader. В системе оно распознается как HID Keyboard. Мне нужно написать небольшую программу, которая будет пользоваться этим устройством. Но основной затык в том, что программа должна им пользоваться единолично! Т.е. каким-то образом его "захватить". И если будет активным другое приложение - весь вывод с устройства должен идти в мою программу. Без "захвата" устройство работает как обычная клава. К примеру, если будет активным окно ворда, после считывания магнитной карты, данные с устройства запишутся в ворд.

      Я тебе уже давал ссылку на библиотеку: Захват USB-клавиатуры
      Судя по всему, ты ее так и не попробовал проверить? :D
      У меня эта библиотека работала на 5+, захватывает мышь, клавиатуру, по твоему выбору(скорее всего даже джостик может захватить). Можно блокировать устройство так, чтоб дальше твоей программы - сообщения от устройства не шли.
      Я бы все таки попробовал проверить эту либу с твоим устройством. И если не поможет, уже тогда бы смотрел в сторону написания своего драйвера.

      Добавлено
      Хотя, если у тебя это устройство в системе распознается как "нераспознаное"(в смысле что на него не установлены драйвера), возможно эта библиотека и не подойдет, но мне кажется всетаки подойдет. Она свой драйвер ставит в систему. Т.е. по идее она должна видеть устройства даже без драйверов.

      Это сообщение было перенесено сюда или объединено из темы "Программирование драйверов Windows"
        Цитата Wound @
        Я тебе уже давал ссылку на библиотеку: Захват USB-клавиатуры
        Судя по всему, ты ее так и не попробовал проверить?

        Не пробовал. Пробежал по коду глазами, но так и не увидел в коде как указать от какой именно клавиатуры начать перехват. Когда я КартРидер включаю - у меня он виндой определяется как HID Keyboard. Ну это примерно тоже самое, как ести ты воткнешь в системник вторую USB-клаву - обе работать будут.

        Это сообщение было перенесено сюда или объединено из темы "Программирование драйверов Windows"
          Цитата JoeUser @
          Не пробовал. Пробежал по коду глазами, но так и не увидел в коде как указать от какой именно клавиатуры начать перехват. Когда я КартРидер включаю - у меня он виндой определяется как HID Keyboard. Ну это примерно тоже самое, как ести ты воткнешь в системник вторую USB-клаву - обе работать будут.


          Так там в доке все есть. Ты бы запустил тестовый пример хотя бы, который одну клаву обрабатывает, и поигрался бы ))
          Вот тут же есть куча примеров даже с описанием: http://www.oblita.com/interception.html

          Например:
          Цитата

          The following sample allows one to query for a device’s “hardware id”, which may help on disambiguation of device input.
          Just remember this hardware id’s are not required to be unique, but mostly will when you have at last two different device models.

          ExpandedWrap disabled
            #include <interception.h>
            #include "utils.h"
             
            #include <iostream>
             
            enum ScanCode
            {
                SCANCODE_ESC = 0x01
            };
             
            int main()
            {
                using namespace std;
             
                InterceptionContext context;
                InterceptionDevice device;
                InterceptionStroke stroke;
             
                wchar_t hardware_id[500];
             
                raise_process_priority();
             
                context = interception_create_context();
             
                interception_set_filter(context, interception_is_keyboard, INTERCEPTION_FILTER_KEY_DOWN | INTERCEPTION_FILTER_KEY_UP);
                interception_set_filter(context, interception_is_mouse, INTERCEPTION_FILTER_MOUSE_LEFT_BUTTON_DOWN);
             
                while(interception_receive(context, device = interception_wait(context), &stroke, 1) > 0)
                {
                    if(interception_is_keyboard(device))
                    {
                        InterceptionKeyStroke &keystroke = *(InterceptionKeyStroke *) &stroke;
             
                        if(keystroke.code == SCANCODE_ESC) break;
                    }
             
                    size_t length = interception_get_hardware_id(context, device, hardware_id, sizeof(hardware_id));
             
                    if(length > 0 && length < sizeof(hardware_id))
                        wcout << hardware_id << endl;
             
                    interception_send(context, device, &stroke, 1);
                }
             
                interception_destroy_context(context);
             
                return 0;
            }


          Это сообщение было перенесено сюда или объединено из темы "Программирование драйверов Windows"
            Цитата Wound @
            The following sample allows one to query for a device’s “hardware id”, which may help on disambiguation of device input.
            Just remember this hardware id’s are not required to be unique, but mostly will when you have at last two different device models.

            Хм ... интересно. Щяс заценим! :)

            Это сообщение было перенесено сюда или объединено из темы "Программирование драйверов Windows"
              Вот примеры: https://github.com/oblitum/Interception

              Добавлено
              Там вроде просто по порядковому номеру передавать нужно, я не помню точно. Я года два назад с этим работал. Но там точно можно захватывать выборочно устройства по IDшнику. Просто нужно почитать доку, посмотреть примеры. Установить драйвер у себя, взять либу, написать тестовый пример, который например работает с 1 кнопкой. И поиграться. И сразу станет понятно как там что и зачем и куда передается.

              Добавлено
              Цитата JoeUser @
              Хм ... интересно. Щяс заценим!

              Только на этот раз установи библиотеку и скомпилируй пример, проверь руками. А то ты уже 3 тему с этой USB клавиатурой создаешь. Поверь - быстрее, проверить вот это, чем писать свой драйвер, особенно если опыта в драйверописании у тебя 0.

              Добавлено
              Я вот щас исходник глянул этой библиотеки, она по умолчанию захватывает все устройства(клавиатура или мышь), а дальше, через InterceptionDevice - ты ей указываешь какое именно устройство ей нужно обрабатывать. Посмотри исходники: https://github.com/oblitum/Interception/blo.../interception.c
              Например, вот функция поссылки данных устройству:
              ExpandedWrap disabled
                int interception_send(InterceptionContext context, InterceptionDevice device, const InterceptionStroke *stroke, unsigned int nstroke)
                {
                    InterceptionDeviceArray device_array = (InterceptionDeviceArray)context;
                    DWORD strokeswritten = 0;
                 
                    if(context == 0 || nstroke == 0 || interception_is_invalid(device) || !device_array[device - 1].handle) return 0;
                 
                    if(interception_is_keyboard(device))
                    {
                        PKEYBOARD_INPUT_DATA rawstrokes = (PKEYBOARD_INPUT_DATA)HeapAlloc(GetProcessHeap(), 0, nstroke * sizeof(KEYBOARD_INPUT_DATA));
                        unsigned int i;
                 
                        if(!rawstrokes) return 0;
                 
                        for(i = 0; i < nstroke; ++i)
                        {
                            InterceptionKeyStroke *key_stroke = (InterceptionKeyStroke *) stroke;
                 
                            rawstrokes[i].UnitId = 0;
                            rawstrokes[i].MakeCode = key_stroke[i].code;
                            rawstrokes[i].Flags = key_stroke[i].state;
                            rawstrokes[i].Reserved = 0;
                            rawstrokes[i].ExtraInformation = key_stroke[i].information;
                        }
                 
                        DeviceIoControl(device_array[device - 1].handle, IOCTL_WRITE, rawstrokes,(DWORD)nstroke * sizeof(KEYBOARD_INPUT_DATA), NULL, 0, &strokeswritten, NULL);
                 
                        HeapFree(GetProcessHeap(), 0,  rawstrokes);
                 
                        strokeswritten /= sizeof(KEYBOARD_INPUT_DATA);
                    }
                    else
                    {
                        PMOUSE_INPUT_DATA rawstrokes = (PMOUSE_INPUT_DATA)HeapAlloc(GetProcessHeap(), 0, nstroke * sizeof(MOUSE_INPUT_DATA));
                        unsigned int i;
                 
                        if(!rawstrokes) return 0;
                 
                        for(i = 0; i < nstroke; ++i)
                        {
                            InterceptionMouseStroke *mouse_stroke = (InterceptionMouseStroke *) stroke;
                 
                            rawstrokes[i].UnitId = 0;
                            rawstrokes[i].Flags = mouse_stroke[i].flags;
                            rawstrokes[i].ButtonFlags = mouse_stroke[i].state;
                            rawstrokes[i].ButtonData = mouse_stroke[i].rolling;
                            rawstrokes[i].RawButtons = 0;
                            rawstrokes[i].LastX = mouse_stroke[i].x;
                            rawstrokes[i].LastY = mouse_stroke[i].y;
                            rawstrokes[i].ExtraInformation = mouse_stroke[i].information;
                        }
                 
                        DeviceIoControl(device_array[device - 1].handle, IOCTL_WRITE, rawstrokes, (DWORD)nstroke * sizeof(MOUSE_INPUT_DATA), NULL, 0, &strokeswritten, NULL);
                 
                        HeapFree(GetProcessHeap(), 0,  rawstrokes);
                 
                        strokeswritten /= sizeof(MOUSE_INPUT_DATA);
                    }
                 
                    return strokeswritten;
                }


              Это сообщение было перенесено сюда или объединено из темы "Программирование драйверов Windows"
              Сообщение отредактировано: Wound -
                Wound, в общем, затестил я предложенную тобою либу - не подходит, увы. Нет, картридер ловит и читает, выводит его ID в виде "HID\VID_0801&PID_0001&REV_0100". Тобишь читать keystroke из нужного девайса я могу. Но я немогу прочитанное не пускать дальше
                в систему. Иными словами, запускаю свою прогу, запускаю цикл чтения, переключаюсь на блокнот, и провожу карточку ... и моя прога
                ловит ввод, и в блокноте вываливается содержимое прочитанного. А по API библиотеки ничего не нахожу, чтобы не пустить "нажатие
                клавиши" дальше :-?

                Добавлено
                ADD: Хотя погоди ... там в коде есть вызов "interception_send(context, device, &stroke, 1);", возможно он далее "проталкивает" считанное :-? Ща еще поэксперементирую.

                Это сообщение было перенесено сюда или объединено из темы "Программирование драйверов Windows"
                  Цитата JoeUser @
                  Wound, в общем, затестил я предложенную тобою либу - не подходит, увы. Нет, картридер ловит и читает, выводит его ID в виде "HID\VID_0801&PID_0001&REV_0100". Тобишь читать keystroke из нужного девайса я могу. Но я немогу прочитанное не пускать дальше
                  в систему. Иными словами, запускаю свою прогу, запускаю цикл чтения, переключаюсь на блокнот, и провожу карточку ... и моя прога
                  ловит ввод, и в блокноте вываливается содержимое прочитанного. А по API библиотеки ничего не нахожу, чтобы не пустить "нажатие

                  Попробуй на обычной клавиатуре.
                  По идее, вот этот код из примера, первый по этой ссылке: http://www.oblita.com/interception.html
                  ExpandedWrap disabled
                    #include <interception.h>
                    #include "utils.h"
                     
                    enum ScanCode
                    {
                        SCANCODE_X   = 0x2D,
                        SCANCODE_Y   = 0x15,
                        SCANCODE_ESC = 0x01
                    };
                     
                    int main()
                    {
                        InterceptionContext context;
                        InterceptionDevice device;
                        InterceptionKeyStroke stroke;
                     
                        raise_process_priority();
                     
                        context = interception_create_context();
                     
                        interception_set_filter(context, interception_is_keyboard, INTERCEPTION_FILTER_KEY_DOWN | INTERCEPTION_FILTER_KEY_UP);
                     
                        while(interception_receive(context, device = interception_wait(context), (InterceptionStroke *)&stroke, 1) > 0)
                        {
                            if(stroke.code == SCANCODE_X) stroke.code = SCANCODE_Y;
                     
                            interception_send(context, device, (InterceptionStroke *)&stroke, 1);
                     
                            if(stroke.code == SCANCODE_ESC) break;
                        }
                     
                        interception_destroy_context(context);
                     
                        return 0;
                    }

                  Должен перехватывать все нажатия кнопок на клавиатуре и все отпускания. Затем если ты нажимаешь кнопку Х, он должен подменить ее на Y, если нажимаешь ESC - выход из проги, все остальные кнопки - вроде должен пропускать. Еще посмотри бота для рыбалки, которого я постил там в теме, там в нем автоматом клавиши нажимаются, при этом вроде сам не можешь нажать, кроме определенных клавишь. Т.е. кроме определеных он блокирует остальные.

                  Добавлено
                  Вот эта фигня: interception_set_filter(context, interception_is_keyboard, INTERCEPTION_FILTER_KEY_DOWN | INTERCEPTION_FILTER_KEY_UP); - ставит фильтр на отслеживание нажатых клавишь.
                  while(interception_receive(context, device = interception_wait(context), (InterceptionStroke *)&stroke, 1) > 0)- эта фигня по идее перехватывать нажатия/отпускания, заданные в фильтре.
                  interception_send(context, device, (InterceptionStroke *)&stroke, 1); - вот эта фигня - эмулирует нажатие клавишь.
                  Вроде бы так, но я точно не помню. Просто ты можешь перехватить клавишу, и как то ее выкинуть из буфера ввода/вывода.

                  Добавлено
                  По идее тебе нужно поставить фильтр, и ловить клавиши. Дальше - ты можешь их например посылать только определенной проге. Например там через SendMessage, или что то подобное. Хендл нужного окна можно вытащить из процесса.
                  Это если тебе нужно посылать именно туда куда нужно.

                  Добавлено
                  В общем попробуй сначало поиграть с клавиатурой, только сделай кнопку выхода обязательно, а то можешь вот так зависнуть. Или перехватывай только клаву, мышь не трогай. Чтоб закрыть прогу. Если с клавиатурой получится все(а там по идее должно получится), тогда уже пробуй с кардридером баловаться.

                  Это сообщение было перенесено сюда или объединено из темы "Программирование драйверов Windows"
                    Не не не, смотри:
                    user posted image
                    В позиции [1] мы читаем и по любому в позиции [2] пишем прочитанное.
                    Сення уже не буду, завтра сделаю так: если прочитанное с моего картридера (по Id) -
                    пишу в свою прогу и все, а если не с моего девайса - вызываю [2]. По идее должно
                    так заработать.

                    Это сообщение было перенесено сюда или объединено из темы "Программирование драйверов Windows"
                      По ходу возникло два вопроса:

                      1) Где можно найти соответствие скан-кодам клавиатуры и печатаемым символам?
                      2) Цикл опроса клавиатуры я хочу вынести в отдельную нить, какие средства синхронизации посоветуете (желательно языковые С++)?
                        Цитата JoeUser @
                        1) Где можно найти соответствие скан-кодам клавиатуры и печатаемым символам?

                        На википедии например: https://ru.wikipedia.org/wiki/%D0%A1%D0%BA%...%BA%D0%BE%D0%B4

                        Цитата JoeUser @
                        2) Цикл опроса клавиатуры я хочу вынести в отдельную нить, какие средства синхронизации посоветуете (желательно языковые С++)?

                        Мьютекс бери например :-?

                        Добавлено
                        Так а что там кстати, получилось не пускать прочитанное дальше?

                        Добавлено
                        Про отличие мьютексов от других средств синхронизации: Мьютексы С++11, С++14, С++17
                          Цитата Wound @
                          Так а что там кстати, получилось не пускать прочитанное дальше?

                          Еще в процессе, через часок засяду эксперементировать.
                            Цитата Wound @
                            Так а что там кстати, получилось не пускать прочитанное дальше?

                            В общем - облом! Смотри кусок кода:

                            ExpandedWrap disabled
                              void Widget_Main::SlotRun() {
                                  InterceptionContext context;
                                  InterceptionDevice device;
                                  InterceptionStroke stroke;
                                  wchar_t hardware_id[500];
                                  context = interception_create_context();
                                  interception_set_filter(context, interception_is_keyboard, INTERCEPTION_FILTER_KEY_DOWN | INTERCEPTION_FILTER_KEY_UP);
                                  while (interception_receive(context, device = interception_wait(context), &stroke, 1) > 0) {
                                      if (interception_is_keyboard(device)) {
                                          InterceptionKeyStroke& keystroke = *(InterceptionKeyStroke*) &stroke;
                                          if (keystroke.code == SCANCODE_ESC)
                                              break;
                                      }
                                      size_t length = interception_get_hardware_id(context, device, hardware_id, sizeof(hardware_id));
                                      if (length > 0 && length < sizeof(hardware_id))
                                          std::wcout << hardware_id << std::endl;
                                      // interception_send(context, device, &stroke, 1);  << ---------------------- видишь закомментил!
                                  }
                                  interception_destroy_context(context);
                                  T->append("Ups!");
                              }


                            И вот какая наблюдается ситуация:

                            1) Запускаю прогу, жму кнопку начала опроса карт-ридера
                            2) Переключаюсь на редактор фара
                            3) Провожу карточкой по карт-ридеру
                            4) Весь вывод из карточки гасится ... но в редакторе вставляется перевод строки :(

                            Откуда этот перевод строки берется, если я весь вывод погасил - не знаю.
                            Таким образом, фильтр "пропускает". Единственное, что еще не полностью убило
                            надежду, так это - посмотрю флаги установки фильтра.

                            Пока они "INTERCEPTION_FILTER_KEY_DOWN | INTERCEPTION_FILTER_KEY_UP"
                            Полез в исходники либы.

                            Добавлено
                            INTERCEPTION_FILTER_KEY_ALL :victory:

                            Уффф .... можно пробовать кодить дальше!
                              Ну и чего? Заработало оно у тебя? :huh:
                                Цитата Wound @
                                Ну и чего? Заработало оно у тебя?

                                Ну да, перехватывать ввод с карт-ридера и не отдавать его в систему - получилось!

                                Сейчас вот колдую над кодом, чтобы использовать interception_wait_with_timeout, потому как в недрах библиотеки эта кухня завязана на WaitForMultipleObjects, а с параметром INFINITE меня не устраивает. Т.к. очень не хочется использовать TerminateThread, это не по фэншую С++
                                  Ну норм, теперь обвязку сделать осталось над библиотекой мультипоточную и норм будет.

                                  Добавлено
                                  Странно что сообщение два раза вставилось. :blink:

                                  Добавлено
                                  Седня 1 апреля что ли? :scratch: На двух страницах одно и то же сообщение 2 раза :-?
                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                  0 пользователей:


                                  Рейтинг@Mail.ru
                                  [ Script execution time: 0,0543 ]   [ 19 queries used ]   [ Generated: 29.03.24, 14:05 GMT ]