Frage

meine Mitentwickler! Ich hoffe sehr, dass zumindest einige von Ihnen nicht vor der Menge an Text erschrecken werden, die diese Frage enthält (ich habe einfach mein Bestes getan, um so beschreibend wie menschlich möglich zu sein). :)

Für diejenigen, die denken, ich habe diese Frage gestellt, um Malware oder so etwas zu schreiben. Ich möchte eine Anwendung schreiben, mit der Benutzer nach dem Start des Betriebssystems die Auswahl von Anwendungen aus auswählen können. Die gesamte Idee besteht darin, den Benutzer zu ermöglichen, diese Apps auszuwählen, bevor das Betriebssystem das Start beendet hat, indem Sie Hotkeys zuvor für die Apps gedrückt haben. Zum Beispiel schaltet der Benutzer seinen Mac ein, tippt SMTV ein und verschwindet, wenn das System das Starten meiner App abschließt und die Eingabe erholt und Safari, Mail, Tweetie und Vuze startet. Ich bin neu bei so, aber ich tue mein Bestes, um anderen zu helfen, indem ich ihre Fragen beantwortet - ich denke, ich kann dasselbe erwarten. Überprüfen Sie mein Profil und meine Aktivitäten und beginnen Sie danach über Malware zu schreien.

Diese Frage ist eine Folge der Frage Ist es möglich, die Tastatureingabe wiederherzustellen, die während des Starts von Mac OS ausgeführt wurde?.

Geführt durch Pekkas Rat, Ich bin auf einen Artikel gestoßen Tastaturereignisse abfangen von Christian Starkjohann, der beschreibt, wie er und die Zielentwicklungsteam Es war erfolgreich, den Cdrom -Eject -Schlüssel von iBook von F12 zu einer Verschiebung+F12 neu zuzuweisen. Der Hauptteil ist, dass sie tatsächlich tatsächlich abgefangen Tastaturereignisse, was ich brauche. Am Ende hat Christian diesen Artikel genau für Entwickler wie mich geschrieben, um die Idee des Ijekts als Prototyp für ähnliche Funktionen zu verwenden.

Zunächst habe ich beschlossen, eine einfache Kernel -Erweiterung zu erstellen, um einfach die Tastatureingabe des Benutzers zu protokollieren /var/log/kernel.log. Ich habe ein neues generisches Kernel -Erweiterungsprojekt in Xcode gestartet, gefolgt von den Anweisungen der Hallo Kernel: Erstellen einer Kernel -Erweiterung mit Xcode Tutorial gefunden in Kernel -Erweiterungskonzepte des Mac Dev Center Um ein Hello World -Projekt zu erstellen und es dann mit Code aus iject -Quellen zu stopfen. Hier sind die Ergebnisse:

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);
}

Die resultierende Kernel -Erweiterung wird durch Kextload/Kextunload -Programme erfolgreich geladen/entladen, fängt jedoch keine der Tastaturereignisse ab. Ich habe versucht, viele Dinge zu tun, um es zum Laufen zu bringen, aber ohne Fehler oder andere Probleme damit, wie ich nichts Nützliches googeln kann und Ihre Hilfe frage.

War es hilfreich?

Lösung

Das Problem besteht nicht darin, wie Sie die vorhandene IOHIDSystem -Instanz überschreiben. Das funktioniert gut.

Das Problem ist, dass beim Öffnen von Iohikeyboard eine Rückruffunktion an das IOHIDSystem zur Verarbeitung von Ereignissen übergeben wird. Der Rückruf ist eine statische private Funktion von iohidsystem, genannt _KeyboardEvent:

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

Der Rückruf ruft dann in der IOHIDSystem -Instanz die Funktion von KeyboarEvent auf:

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

Es wird nicht den zehn Parameter eins aufgerufen, der virtuell ist (und das Sie überschreiben). Stattdessen wird das genannte 11 Parameter nicht virtuell genannt. Selbst wenn Sie versucht haben, den 11 -Parameter 1 zu überschreiben, würde er nicht funktionieren, da der Anruf niemals die VTable durchläuft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top