mirror of https://github.com/opa334/TrollStore.git
146 lines
5.1 KiB
Objective-C
146 lines
5.1 KiB
Objective-C
@import Foundation;
|
|
|
|
#ifndef __XPC_H__
|
|
// Types
|
|
typedef NSObject* xpc_object_t;
|
|
typedef xpc_object_t xpc_connection_t;
|
|
typedef void (^xpc_handler_t)(xpc_object_t object);
|
|
|
|
// Communication
|
|
extern xpc_connection_t xpc_connection_create_mach_service(const char* name, dispatch_queue_t targetq, uint64_t flags);
|
|
extern void xpc_connection_set_event_handler(xpc_connection_t connection, xpc_handler_t handler);
|
|
extern void xpc_connection_resume(xpc_connection_t connection);
|
|
extern void xpc_connection_send_message_with_reply(xpc_connection_t connection, xpc_object_t message, dispatch_queue_t replyq, xpc_handler_t handler);
|
|
extern xpc_object_t xpc_connection_send_message_with_reply_sync(xpc_connection_t connection, xpc_object_t message);
|
|
extern xpc_object_t xpc_dictionary_get_value(xpc_object_t xdict, const char *key);
|
|
#endif
|
|
|
|
// Serialization
|
|
extern CFTypeRef _CFXPCCreateCFObjectFromXPCObject(xpc_object_t xpcattrs);
|
|
extern xpc_object_t _CFXPCCreateXPCObjectFromCFObject(CFTypeRef attrs);
|
|
extern xpc_object_t _CFXPCCreateXPCMessageWithCFObject(CFTypeRef obj);
|
|
extern CFTypeRef _CFXPCCreateCFObjectFromXPCMessage(xpc_object_t obj);
|
|
|
|
|
|
typedef enum {
|
|
kAMFIActionArm = 0, // Trigger a prompt asking the user to enable developer mode on the next reboot
|
|
// (regardless of current state)
|
|
kAMFIActionDisable = 1, // Disable developer mode if it's currently enabled. Takes effect immediately.
|
|
kAMFIActionStatus = 2, // Returns a dict: {success: bool, status: bool, armed: bool}
|
|
} AMFIXPCAction;
|
|
|
|
xpc_connection_t startConnection(void) {
|
|
xpc_connection_t connection = xpc_connection_create_mach_service("com.apple.amfi.xpc", NULL, 0);
|
|
if (!connection) {
|
|
NSLog(@"[startXPCConnection] Failed to create XPC connection to amfid");
|
|
return nil;
|
|
}
|
|
xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
|
|
});
|
|
xpc_connection_resume(connection);
|
|
return connection;
|
|
}
|
|
|
|
NSDictionary* sendXPCRequest(xpc_connection_t connection, AMFIXPCAction action) {
|
|
xpc_object_t message = _CFXPCCreateXPCMessageWithCFObject((__bridge CFDictionaryRef) @{@"action": @(action)});
|
|
xpc_object_t replyMsg = xpc_connection_send_message_with_reply_sync(connection, message);
|
|
if (!replyMsg) {
|
|
NSLog(@"[sendXPCRequest] got no reply from amfid");
|
|
return nil;
|
|
}
|
|
|
|
xpc_object_t replyObj = xpc_dictionary_get_value(replyMsg, "cfreply");
|
|
if (!replyObj) {
|
|
NSLog(@"[sendXPCRequest] got reply but no cfreply");
|
|
return nil;
|
|
}
|
|
|
|
NSDictionary* asCF = (__bridge NSDictionary*)_CFXPCCreateCFObjectFromXPCMessage(replyObj);
|
|
return asCF;
|
|
}
|
|
|
|
BOOL getDeveloperModeState(xpc_connection_t connection) {
|
|
NSDictionary* reply = sendXPCRequest(connection, kAMFIActionStatus);
|
|
if (!reply) {
|
|
NSLog(@"[getDeveloperModeState] failed to get reply");
|
|
return NO;
|
|
}
|
|
|
|
NSLog(@"[getDeveloperModeState] got reply %@", reply);
|
|
|
|
NSObject* success = reply[@"success"];
|
|
if (!success || ![success isKindOfClass:[NSNumber class]] || ![(NSNumber*)success boolValue]) {
|
|
NSLog(@"[getDeveloperModeState] request failed with error %@", reply[@"error"]);
|
|
return NO;
|
|
}
|
|
|
|
NSObject* status = reply[@"status"];
|
|
if (!status || ![status isKindOfClass:[NSNumber class]]) {
|
|
NSLog(@"[getDeveloperModeState] request succeeded but no status");
|
|
return NO;
|
|
}
|
|
|
|
return [(NSNumber*)status boolValue];
|
|
}
|
|
|
|
BOOL setDeveloperModeState(xpc_connection_t connection, BOOL enable) {
|
|
NSDictionary* reply = sendXPCRequest(connection, enable ? kAMFIActionArm : kAMFIActionDisable);
|
|
if (!reply) {
|
|
NSLog(@"[setDeveloperModeState] failed to get reply");
|
|
return NO;
|
|
}
|
|
|
|
NSObject* success = reply[@"success"];
|
|
if (!success || ![success isKindOfClass:[NSNumber class]] || ![(NSNumber*)success boolValue]) {
|
|
NSLog(@"[setDeveloperModeState] request failed with error %@", reply[@"error"]);
|
|
return NO;
|
|
}
|
|
|
|
return YES;
|
|
}
|
|
|
|
BOOL checkDeveloperMode(void) {
|
|
// Developer mode does not exist before iOS 16
|
|
if (@available(iOS 16, *)) {
|
|
xpc_connection_t connection = startConnection();
|
|
if (!connection) {
|
|
NSLog(@"[checkDeveloperMode] failed to start connection");
|
|
// Assume it's disabled
|
|
return NO;
|
|
}
|
|
|
|
return getDeveloperModeState(connection);
|
|
} else {
|
|
return YES;
|
|
}
|
|
}
|
|
|
|
BOOL armDeveloperMode(BOOL* alreadyEnabled) {
|
|
// Developer mode does not exist before iOS 16
|
|
if (@available(iOS 16, *)) {
|
|
xpc_connection_t connection = startConnection();
|
|
if (!connection) {
|
|
NSLog(@"[armDeveloperMode] failed to start connection");
|
|
return NO;
|
|
}
|
|
|
|
BOOL enabled = getDeveloperModeState(connection);
|
|
if (alreadyEnabled) {
|
|
*alreadyEnabled = enabled;
|
|
}
|
|
|
|
if (enabled) {
|
|
// NSLog(@"[armDeveloperMode] already enabled");
|
|
return YES;
|
|
}
|
|
|
|
BOOL success = setDeveloperModeState(connection, YES);
|
|
if (!success) {
|
|
NSLog(@"[armDeveloperMode] failed to arm");
|
|
return NO;
|
|
}
|
|
}
|
|
|
|
return YES;
|
|
}
|