我的开发人员!我希望至少你们中的一些人不会对这个问题所包含的文字感到恐惧(我只是尽我所能地描述了人文可能的描述)。 :)

对于那些认为我已经要求这个问题写恶意软件或其他内容的人。我想编写一个应用程序,该应用程序将允许用户选择在OS完成启动后启动应用程序。整个想法是允许用户在OS完成启动之前选择这些应用程序,然后按以前绑定到应用程序的Hotkeys。例如,用户打开他的Mac,键入SMTV并消失,当系统完成我的应用程序时,将恢复输入并启动Safari,Mail,Tweetie和Vuze。我是新手,但我会尽力通过回答他们的问题来帮助他人 - 我认为我可以期待同样的回报。检查我的个人资料和活动,然后开始尖叫恶意软件。

这个问题是问题的后续 是否可以恢复Mac OS启动时完成的键盘输入?.

由...来指导 佩卡的建议, ,我偶然发现了一篇文章 拦截键盘事件 由克里斯蒂安·斯塔克霍恩(Christian Starkjohann)描述了他和 客观开发团队 成功地将iBook的CDROM弹出密钥从F12重新分配到Shift+F12。主要部分是他们实际上 拦截 键盘事件,这是我需要的。最后,克里斯蒂安(Christian)将这篇文章撰写为像我这样的开发人员,将iject的想法用作类似功能的原型。

首先,我决定创建一个简单的内核扩展程序,以简单地将用户的键盘输入记录到 /var/log/kernel.log. 。我在Xcode中启动了一个新的通用内核扩展项目,遵循 Hello bernel:使用Xcode创建内核扩展 找到教程 Mac Dev Center的内核扩展概念 要创建一个Hello World项目,然后将其从Iject源中获取的代码填充。这是结果:

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 Google有用的方式并寻求您的帮助。

有帮助吗?

解决方案

问题不是您如何覆盖现有的iohidsystem实例。这很好。

问题是,当打开iohikeyboard时,它会将回调函数传递给iohidsystem进行处理事件。回调是iohidsystem的静态私人函数,称为_keyboardEvent:

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

然后,回调在iohidsystem实例中调用keyboardEvent函数:

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

它不称为“十个参数”,该参数是虚拟的(您正在覆盖的参数)。相反,所谓的11个参数非虚拟词。因此,即使您试图覆盖11个参数ONE,它也无法使用,因为该调用永远不会通过VTable。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top