Почему эта клавиатура не перехватывает расширение ядра?

StackOverflow https://stackoverflow.com/questions/2042795

Вопрос

мои коллеги -разработчики! Я очень надеюсь, что, по крайней мере, некоторые из вас не будут испугаться количеством текста, который содержит этот вопрос (я просто сделал все возможное, чтобы быть настолько описательным, насколько это гуманно возможно). :)

Тем, кто думает, что я задал этот вопрос написать вредоносное ПО или что -то в этом роде. Я хочу написать приложение, которое позволит пользователям выбирать приложения, которые будут запущены после завершения запуска ОС. Вся идея состоит в том, чтобы позволить пользователю выбирать эти приложения до того, как ОС завершила запуск, нажав Hotkeys, ранее подписавшиеся к приложениям. Например, пользователь включает свой Mac, типы SMTV и уходит, когда система заканчивает запуск моего приложения восстанавливает вход и запускает Safari, Mail, Tweetie и Vuze. Я новичок в этом, но я делаю все возможное, чтобы помочь другим, отвечая на их вопросы - я думаю, что могу ожидать то же самое взамен. Проверьте мой профиль и мою деятельность, и после этого начните кричать о вредоносном ПО.

Этот вопрос является продолжением вопроса Можно ли восстановить вход клавиатуры, который был сделан во время запуска Mac OS?.

Руководствоваться Совет Пекки, Я наткнулся на статью Перехватывает события клавиатуры Кристиан Старкджоханн, который описывает, как он и Объективная команда разработки удалось переназначить ключ изгнания CDROM от iBook от F12 в Shift+F12. Главная часть в том, что они на самом деле перехвачен События клавиатуры, что мне нужно. В конце концов Кристиан написал эту статью именно для разработчиков, таких как я, чтобы использовать идею ICECT в качестве прототипа для аналогичных функций.

Для начала я решил создать простое расширение ядра, чтобы просто зарегистрировать ввод клавиатуры пользователя в /var/log/kernel.log. Анкет Я начал новый проект расширения общего ядра в XCode, следовал инструкциям Привет ядра: Создание расширения ядра с XCODE Учебное пособие найдено в Концепции расширения ядра Mac Dev Center Чтобы создать проект Hello World, а затем набил его кодом, взятым из источников ICECT. Вот результаты:

Testkext.c

#include <sys/systm.h>
#include <mach/mach_types.h>


extern int HidHackLoad(void);
extern int HidHackUnload(void);


kern_return_t MacOSSCKEXT_start (kmod_info_t * ki, void * d) {
    return HidHackLoad() == 0 ? KERN_SUCCESS : KERN_FAILURE;
}


kern_return_t MacOSSCKEXT_stop (kmod_info_t * ki, void * d) {
    return HidHackUnload() == 0 ? KERN_SUCCESS : KERN_FAILURE;
}

Hidhack.h

#ifdef __cplusplus
extern "C" {
#endif

#include <mach/mach_types.h>
#include <sys/systm.h>

 extern int HidHackLoad(void);
 extern int HidHackUnload(void);

#ifdef __cplusplus
}
#endif

#include <IOKit/system.h>
#include <IOKit/assert.h>
#include <IOKit/hidsystem/IOHIDSystem.h>


class HIDHack : public IOHIDSystem {
public:
 virtual void keyboardEvent(unsigned   eventType,
          /* flags */            unsigned   flags,
          /* keyCode */          unsigned   key,
          /* charCode */         unsigned   charCode,
          /* charSet */          unsigned   charSet,
          /* originalCharCode */ unsigned   origCharCode,
          /* originalCharSet */  unsigned   origCharSet,
          /* keyboardType */     unsigned   keyboardType,
          /* repeat */           bool       repeat,
          /* atTime */           AbsoluteTime ts);

 virtual void keyboardSpecialEvent(unsigned   eventType,
           /* flags */        unsigned   flags,
           /* keyCode  */     unsigned   key,
           /* specialty */    unsigned   flavor,
           /* guid */         UInt64     guid,
           /* repeat */       bool       repeat,
           /* atTime */       AbsoluteTime ts);
};

Hidhack.cpp

#include "HIDHack.h"


static void *oldVtable = NULL;
static void *myVtable = NULL;


int HidHackLoad(void) {
 IOHIDSystem *p;
 HIDHack *sub;

 if (oldVtable != NULL) {
  printf("###0 KEXT is already loaded\n");
  return 1;
 }
 if (myVtable == NULL) {
  sub = new HIDHack();
  myVtable = *(void **)sub;
  sub->free();
 }
    p = IOHIDSystem::instance();
    oldVtable = *(void **)p;
    *(void **)p = myVtable;

 printf("###1 KEXT has been successfully loaded\n");

    return 0;
}

int HidHackUnload(void) {
 IOHIDSystem *p;

    if (oldVtable != NULL) {
        p = IOHIDSystem::instance();
  if (*(void **)p != myVtable) {
   printf("###2 KEXT is not loaded\n");

   return 1;
  }
        *(void **)p = oldVtable;
        oldVtable = NULL;
    }

 printf("###3 KEXT has been successfully unloaded\n");

 return 0;
}

void HIDHack::keyboardEvent(unsigned   eventType, unsigned   flags, unsigned   key, unsigned   charCode, unsigned   charSet, unsigned   origCharCode, unsigned   origCharSet, unsigned   keyboardType, bool repeat,
       AbsoluteTime ts) {
 printf("###4 hid event type %d flags 0x%x key %d kbdType %d\n", eventType, flags, key, keyboardType);

    IOHIDSystem::keyboardEvent(eventType, flags, key, charCode, charSet, origCharCode, origCharSet, keyboardType, repeat, ts);
}

void HIDHack::keyboardSpecialEvent(   unsigned   eventType,
          /* flags */        unsigned   flags,
          /* keyCode  */     unsigned   key,
          /* specialty */    unsigned   flavor,
          /* guid */         UInt64     guid,
          /* repeat */       bool       repeat,
          /* atTime */       AbsoluteTime ts) {
 printf("###5 special event type %d flags 0x%x key %d flavor %d\n", eventType, flags, key, flavor);

 IOHIDSystem::keyboardSpecialEvent(eventType, flags, key, flavor, guid, repeat, ts);
}

Полученное расширение ядра успешно загружается/выгружается программами Kextload/Kextunload, но на самом деле не перехватывает ни одно из событий клавиатуры. Я пытался сделать много вещей, чтобы заставить его работать, но без каких -либо ошибок или других проблем с ним так, как я не могу Google ничего полезного и обратиться за помощью.

Это было полезно?

Решение

Проблема не в том, как вы переоцениваете существующий экземпляр iohidsystem. Это работает просто отлично.

Проблема в том, что когда iohikeyboard открывается, это передается функции обратного вызова в иогидсистему для обработки событий. Обратный вызов является статической частной функцией iohidsystem, называемой _keyboardevent:

    success = ((IOHIKeyboard*)source)->open(this, kIOServiceSeize,0,
                (KeyboardEventCallback)        _keyboardEvent, 
                (KeyboardSpecialEventCallback) _keyboardSpecialEvent,
                (UpdateEventFlagsCallback)     _updateEventFlags);

Обратный вызов затем вызывает функцию keyboardevent в экземпляре iohidsystem:

    self->keyboardEvent(eventType, flags, key, charCode, charSet,
                            origCharCode, origCharSet, keyboardType, repeat, ts, sender);

Он не называет десяти параметров, который является виртуальным (и который вы переоцениваете). Вместо этого, что называется 11 параметром, не виртуальным. Таким образом, даже если вы попытаетесь переопределить 11 -параметр, он не будет работать, так как вызов никогда не проходит через VTAble.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top