#pragma once #include #include using namespace std; #include "SCPatchPrivate.h" #include "SCPatchContext.h" #include "SCPatchRecord.h" #include "SCPatchMessenger.h" // Mac to Mach error morphing. #define err_mac err_system(0xf) /* Mac (Carbon) errors */ #define mac_err(CODE) SCmac_err_FromOSErr((CODE)) #define oserr(CODE) SCOSErrFrom_mac_err((CODE)) mach_error_t SCmac_err_FromOSErr(OSErr err); OSErr SCOSErrFrom_mac_err(mach_error_t error); typedef OSErr (*SCPatchIterationProc)(ProcessSerialNumber *inPSN, OSType inCreator, UInt32 inFlags, void *data); class SCPatchController : public SCPatchMessenger { public: SCPatchController(void); SCPatchController(CFStringRef bundleIdentifier); ~SCPatchController(void); // Use these to tell the controller where to find the patches void AddPatch(CFStringRef patchBundleIdentifier, CFStringRef subPath, CFStringRef name); // Inject the patches into running applications and start watching app launches OSErr InstallPatches(void); // Patch a single process (ignoring return value of ShouldPatchProcess) mach_error_t PatchProcess(ProcessSerialNumber *psn); // Overload these to customize patch loading and notification (note that // UnpatchNotification is only called when the process dies, since the patches // are not removable). virtual Boolean ShouldPatchProcess(ProcessSerialNumber * /* inPSN */, OSType /* inCreator */, OSType /* type */, CFStringRef /* name */, UInt32 /* flags */) { return false; } virtual void PatchNotification(ProcessSerialNumber * /* inPSN */, OSType /* inCreator */, OSType /* type */, CFStringRef /* name */, UInt32 /* flags */) {} virtual void UnpatchNotification(ProcessSerialNumber * /* inPSN */, OSType /* inCreator */, OSType /* type */, CFStringRef /* name */, UInt32 /* flags */) {} // You must also overload this method in SCPatchMessenger to receive messages. // virtual void ReceiveMessage(const AppleEvent *theAE) = 0; // Get info and keep tabs on patched processes Boolean IsProcessPatched(ProcessSerialNumber *inPSN); UInt32 GetPatchFlags(ProcessSerialNumber *inPSN); void SetPatchFlags(ProcessSerialNumber *inPSN, UInt32 flags, UInt32 whichFlags); // Loop through each patched process and execute a function. Note that this will // not recognize patched processes until after you've called IsProcessPatched() on // them or called InstallPatches() (which calls IsProcessPatched on every process). OSErr ForEachPatchedProcess(SCPatchIterationProc proc, void *data); private: CFBundleRef mBundle; CFStringRef mApplicationBundleIdentifier; private: list mPatchList; SCPatchContextList mPatchContextList; OSErr HandleMessage(const AppleEvent *theAE); static pascal OSStatus ApplicationEventHandler(EventHandlerCallRef handlerRef, EventRef event, void *userData); mach_error_t InstallPatchesInProcess(ProcessSerialNumber *psn, bool onDemand=false); OSErr AddPatchToParams(CFStringRef bundleID, CFURLRef url, SCPatchLoaderParams **params); mach_error_t InjectPatches(ProcessSerialNumber *psn, SCPatchLoaderParams *params); OSErr RecordPatchAndNotify(ProcessSerialNumber *psn, ProcessInfoRec *info); };