void LookupAppsOnDevice(char *udid)
{
	SDMMD_AMDeviceRef device = FindDeviceFromUDID(udid);
	if (device) {
		sdmmd_return_t result = SDMMD_AMDeviceConnect(device);
		if (SDM_MD_CallSuccessful(result)) {
			result = SDMMD_AMDeviceStartSession(device);
			if (SDM_MD_CallSuccessful(result)) {
				CFDictionaryRef response;

				//CFMutableArrayRef lookupValues = CFArrayCreateMutable(kCFAllocatorDefault, 0x0, &kCFTypeArrayCallBacks);
				//CFArrayAppendValue(lookupValues, CFSTR(kAppLookupKeyCFBundleIdentifier));
				//CFArrayAppendValue(lookupValues, CFSTR("SequenceNumber"));
				CFArrayRef lookupValues = SDMMD_ApplicationLookupDictionary();
				CFMutableDictionaryRef optionsDict = SDMMD_create_dict();
				CFDictionarySetValue(optionsDict, CFSTR("ReturnAttributes"), lookupValues);

				//CFDictionarySetValue(optionsDict, CFSTR("com.apple.mobile_installation.metadata"), kCFBooleanTrue);
				//CFDictionarySetValue(optionsDict, CFSTR("BundleIDs"), kCFBooleanTrue);

				result = SDMMD_AMDeviceLookupApplications(device, optionsDict, &response);
				if (SDM_MD_CallSuccessful(result)) {
					PrintCFDictionary(response);
				}
				SDMMD_AMDeviceStopSession(device);
			}
			SDMMD_AMDeviceDisconnect(device);
		}
	}
}
sdmmd_return_t SDMMD_AMDeviceLookupApplications(SDMMD_AMDeviceRef device, CFDictionaryRef options, CFDictionaryRef *response)
{
	sdmmd_return_t result = kAMDInvalidArgumentError;
	if (device) {
		if (options) {
			CFDictionaryRef options_dict = NULL;
			SDMMD_AMConnectionRef conn = SDMMD_AMDServiceConnectionCreate(0, NULL, options_dict);
			result = SDMMD_AMDeviceSecureStartService(device, CFSTR(AMSVC_INSTALLATION_PROXY), NULL, &conn);
			if (result == 0) {
				CFMutableDictionaryRef dict = SDMMD_create_dict();
				result = kAMDNoResourcesError;
				if (dict) {
					result = SDMMD_perform_command(conn, CFSTR("Browse"), 0, SDMMD_browse_callback, 2, dict, CFSTR("ClientOptions"), options);
					if (!result) {
						*response = dict;
					}
				}
			}
			else {
				printf("%s: Was unable to start the install service on the device: %i\n", __FUNCTION__, device->ivars.device_id);
			}
			//CFSafeRelease(conn);
		}
	}
	return result;
}
void InstallProfileToDevice(char *udid, char *path)
{
	SDMMD_AMDeviceRef device = FindDeviceFromUDID(udid);
	if (device) {
		SDMMD_AMDeviceConnect(device);
		SDMMD_AMDeviceStartSession(device);
		SDMMD_AMConnectionRef conn = NULL;
		SDMMD_AMDeviceStartService(device, CFSTR(AMSVC_MCINSTALL), NULL, &conn);
		CFDataRef config_data = CFDataCreateFromFilePath(path);

		CFMutableDictionaryRef request = SDMMD_create_dict();
		CFDictionaryAddValue(request, CFSTR("RequestType"), CFSTR("InstallProfile"));
		CFDictionaryAddValue(request, CFSTR("Payload"), config_data);

		SDMMD_ServiceSendMessage(SDMMD_TranslateConnectionToSocket(conn), request, kCFPropertyListXMLFormat_v1_0);
		CFSafeRelease(request);
		CFSafeRelease(config_data);

		CFPropertyListRef response = NULL;
		SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(conn), &response);
		CFSafeRelease(response);

		CFSafeRelease(conn);
		SDMMD_AMDeviceStopSession(device);
		SDMMD_AMDeviceDisconnect(device);
	}
}
void SpringboardQuery(char *udid) {
	SDMMD_AMDeviceRef device = FindDeviceFromUDID(udid);
	if (device) {
		//struct SpringboardDeviceInfo *info = CreateSpringboardInfoFromDevice(device);
		
		SDMMD_AMConnectionRef springboard = AttachToDeviceAndService(device, AMSVC_SPRINGBOARD_SERVICES);
		CFMutableDictionaryRef request = SDMMD_create_dict();
		CFDictionarySetValue(request, CFSTR(kCommand), CFSTR(kCommandGetIconState));
		CFDictionarySetValue(request, CFSTR(kFormatVersion), CFSTR("2"));
		SocketConnection socket = SDMMD_TranslateConnectionToSocket(springboard);
		sdmmd_return_t result = SDMMD_ServiceSendMessage(socket, request, kCFPropertyListBinaryFormat_v1_0);
		if (result == kAMDSuccess) {
			CFPropertyListRef response = NULL;
			result = SDMMD_ServiceReceiveMessage(socket, &response);
			if (result == kAMDSuccess && response) {
				PrintCFType(response);
			}
		}
		
		/*
		CFMutableDictionaryRef setrequest = SDMMD_create_dict();
		CFDictionarySetValue(setrequest, CFSTR(kCommand), CFSTR(kCommandSetIconState));
		CFDictionarySetValue(setrequest, CFSTR("iconState"), newformat);
		result = SDMMD_ServiceSendMessage(socket, setrequest, kCFPropertyListBinaryFormat_v1_0);
		if (result == kAMDSuccess) {
			CFPropertyListRef response = NULL;
			result = SDMMD_ServiceReceiveMessage(socket, &response);
			if (result == kAMDSuccess && response) {
				PrintCFType(response);
			}
		}
		*/
	}
}
kern_return_t test_sdm_AMDeviceLookupApplications(SDMMD_AMDeviceRef sdm, CFTypeRef *value) {
	CFDictionaryRef sdm_response = NULL;
	kern_return_t sdm_return = kAMDUndefinedError;
	kern_return_t result = SDMMD_AMDeviceConnect(sdm);
	if (SDM_MD_CallSuccessful(result)) {
		result = SDMMD_AMDeviceStartSession(sdm);
		if (SDM_MD_CallSuccessful(result)) {
			CFArrayRef lookupValues = SDMMD_ApplicationLookupDictionary();
			CFMutableDictionaryRef optionsDict = SDMMD_create_dict();
			CFDictionarySetValue(optionsDict, CFSTR("ReturnAttributes"), lookupValues);
			sdm_return = SDMMD_AMDeviceLookupApplications(sdm, optionsDict, &sdm_response);
			if (sdm_return != kAMDSuccess) {
				printf("\t\tSDMMD_AMDeviceLookupApplications: %08x %s\n",sdm_return,SDMMD_AMDErrorString(sdm_return));
			}
			else {
				*value = sdm_response;
			}
			CFSafeRelease(optionsDict);
			CFSafeRelease(lookupValues);
			SDMMD_AMDeviceStopSession(sdm);
		}
		SDMMD_AMDeviceDisconnect(sdm);
	}
	return sdm_return;
}
CFMutableDictionaryRef CreateEmptyFolder(CFStringRef name) {
	CFMutableDictionaryRef folder = SDMMD_create_dict();
	CFDictionarySetValue(folder, CFSTR(kDisplayName), name);
	CFMutableArrayRef apps = CFArrayCreateMutable(kCFAllocatorDefault, 0x0, &kCFTypeArrayCallBacks);
	CFDictionarySetValue(folder, CFSTR(kIconLists), apps);
	CFDictionarySetValue(folder, CFSTR(kListType), CFSTR("folder"));
	return folder;
}
sdmmd_return_t SDMMD_mount_image(SDMMD_AMConnectionRef connection, CFStringRef image_type, CFDataRef signature, bool *mounted)
{
	sdmmd_return_t result = kAMDSuccess;
	CFMutableDictionaryRef mountDict = SDMMD_create_dict();
	if (mountDict) {
		CFDictionarySetValue(mountDict, CFSTR("Command"), CFSTR("MountImage"));
		CFDictionarySetValue(mountDict, CFSTR("ImageType"), image_type);
		CFDictionarySetValue(mountDict, CFSTR("ImagePath"), CFSTR("/var/mobile/Media/PublicStaging/staging.dimage"));
		if (signature) {
			CFDictionarySetValue(mountDict, CFSTR("ImageSignature"), signature);
		}
		result = SDMMD_ServiceSendMessage(SDMMD_TranslateConnectionToSocket(connection), mountDict, kCFPropertyListXMLFormat_v1_0);
		CFSafeRelease(mountDict);
		CheckErrorAndReturn(result);

		CFDictionaryRef response;
		result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(connection), (CFPropertyListRef *)&response);
		CheckErrorAndReturn(result);

		if (response) {
			result = SDMMD__ErrorHandler(SDMMD_ImageMounterErrorConvert, response);

			CheckErrorAndReturn(result);

			CFTypeRef status = CFDictionaryGetValue(response, CFSTR("Status"));
			if (status) {
				if (CFEqual(status, CFSTR("Complete"))) {
					*mounted = true;
				}
				else {
					result = kAMDMissingDigestError;
				}
			}
		}
		else {
			result = kAMDReadError;
		}
	}
	else {
		result = kAMDReadError;
	}

	ExitLabelAndReturn(result);
}
Exemple #8
0
CFURLRef copy_device_app_url(SDMMD_AMDeviceRef device, CFStringRef identifier) {
	CFArrayRef values = SDMMD_ApplicationLookupDictionary();
	CFMutableDictionaryRef optionsDict = SDMMD_create_dict();
	CFDictionarySetValue(optionsDict, CFSTR("ReturnAttributes"), values);
	CFDictionaryRef response;
	SDMMD_AMDeviceConnect(device);
	SDMMD_AMDeviceStartSession(device);
    SDMMD_AMDeviceLookupApplications(device, optionsDict, &response);

    CFDictionaryRef app_dict = CFDictionaryGetValue(response, identifier);
    assert(app_dict != NULL);
	
    CFStringRef app_path = CFDictionaryGetValue(app_dict, CFSTR("Path"));
    assert(app_path != NULL);
	
    CFURLRef url = CFURLCreateWithFileSystemPath(NULL, app_path, kCFURLPOSIXPathStyle, true);
    CFRelease(response);
    return url;
}
sdmmd_return_t SDMMD_perform_command(SDMMD_AMConnectionRef conn, CFStringRef command, uint64_t code, void (*callback)(CFDictionaryRef dict, void* arg), uint32_t argsCount, void* paramStart, ...) {
	sdmmd_return_t result = 0x0;
	CFMutableDictionaryRef message = SDMMD_create_dict();
	if (message) {
		CFDictionarySetValue(message, CFSTR("Command"), command);
		va_list args;
		va_start(args, paramStart);
		CFTypeRef key, value;
		for (uint32_t i = 0; i < argsCount; i++) {
			key = va_arg(args, CFTypeRef);
			value = va_arg(args, CFTypeRef);
			CFDictionarySetValue(message, key, value);
			i++;
		}
		va_end(args);
		SocketConnection sock;
		if (conn->ivars.ssl)
			sock = (SocketConnection){true, {.ssl = conn->ivars.ssl}};
		else
sdmmd_return_t SDMMD__hangup_with_image_mounter_service(SDMMD_AMConnectionRef connection)
{
	sdmmd_return_t result = kAMDNoResourcesError;
	CFMutableDictionaryRef dict = SDMMD_create_dict();
	if (dict) {
		CFDictionarySetValue(dict, CFSTR("Command"), CFSTR("Hangup"));
	}
	if (connection) {
		SocketConnection socket = SDMMD_TranslateConnectionToSocket(connection);
		result = SDMMD_ServiceSendMessage(socket, dict, kCFPropertyListXMLFormat_v1_0);
		CheckErrorAndReturn(result);

		CFPropertyListRef response = NULL;
		result = SDMMD_ServiceReceiveMessage(socket, &response);
		PrintCFDictionary(response);
	}

ExitLabel:
	CFSafeRelease(dict);
	return result;
}
void WhatDoesThisDo(char *udid)
{
	SDMMD_AMDeviceRef device = FindDeviceFromUDID(udid);
	if (device) {
		sdmmd_return_t result = kAMDInvalidArgumentError;
		SDMMD_AMDeviceConnect(device);
		SDMMD_AMDeviceStartSession(device);
		CFDictionaryRef dict = NULL;
		SDMMD_AMConnectionRef conn = SDMMD_AMDServiceConnectionCreate(0, NULL, dict);
		result = SDMMD_AMDeviceSecureStartService(device, CFSTR(AMSVC_DIAG_RELAY), NULL, &conn);
		if (result == 0) {

			CFMutableDictionaryRef optionsDict = SDMMD_create_dict();
			CFDictionarySetValue(optionsDict, CFSTR("Request"), CFSTR("GasGauge"));

			result = SDMMD_ServiceSendMessage(SDMMD_TranslateConnectionToSocket(conn), optionsDict, kCFPropertyListXMLFormat_v1_0);

			CFMutableDictionaryRef response;
			result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(conn), (CFPropertyListRef *)&response);
			if (SDM_MD_CallSuccessful(result)) {
				PrintCFType(response);
			}

			result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(conn), (CFPropertyListRef *)&response);
			if (SDM_MD_CallSuccessful(result)) {
				PrintCFType(response);
			}

			result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(conn), (CFPropertyListRef *)&response);
			if (SDM_MD_CallSuccessful(result)) {
				PrintCFType(response);
			}
		}
		else {
			printf("%s: Was unable to start the service on the device: %i\n", __FUNCTION__, SDMMD_AMDeviceUSBDeviceID(device));
		}
	}
}
sdmmd_return_t SDMMD_AMDeviceMountImage(SDMMD_AMDeviceRef device, CFStringRef path, CFDictionaryRef dict, CallBack handle, void *unknown)
{
	sdmmd_return_t result = kAMDSuccess;
	if (dict) {
		SDMMD_AMConnectionRef connection = NULL;
		CFTypeRef digest = NULL;
		CFTypeRef signature = CFDictionaryGetValue(dict, CFSTR("ImageSignature"));
		CFStringRef image_type = CFDictionaryGetValue(dict, CFSTR("ImageType"));
		if (image_type) {
			unsigned char sum_digest[SHA1_HASH_LENGTH];
			result = SDMMD_AMDeviceDigestFile(path, PtrCast(&sum_digest, unsigned char **));
			CheckErrorAndReturn(result);

			SDMMD_AMDeviceRef device_copy = SDMMD_AMDeviceCreateCopy(device);
			if (SDMMD_AMDeviceIsValid(device_copy)) {
				result = SDMMD_AMDeviceSecureStartSessionedService(device, CFSTR(AMSVC_MOBILE_IMAGE_MOUNT), &connection);
				CheckErrorAndReturn(result);

				SDMMD_fire_callback(handle, unknown, CFSTR("LookingUpImage"));
				if (connection) {
					CFMutableDictionaryRef commandDict = SDMMD_create_dict();
					if (commandDict) {
						CFDictionarySetValue(commandDict, CFSTR("Command"), CFSTR("LookupImage"));
						CFDictionarySetValue(commandDict, CFSTR("ImageType"), image_type);
					}
					else {
						result = kAMDNoResourcesError;
					}

					CheckErrorAndReturn(result);

					result = SDMMD_ServiceSendMessage(SDMMD_TranslateConnectionToSocket(connection), commandDict, kCFPropertyListXMLFormat_v1_0);
					CFSafeRelease(commandDict);

					CheckErrorAndReturn(result);

					CFDictionaryRef response;
					result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(connection), (CFPropertyListRef *)&response);

					CheckErrorAndReturn(result);

					if (response) {
						result = SDMMD__ErrorHandler(SDMMD__ConvertServiceError, response);

						CheckErrorAndReturn(result);

						CFTypeRef image = CFDictionaryGetValue(response, CFSTR("ImagePresent"));
						if (image) {
							if (CFEqual(image, kCFBooleanTrue)) {
								digest = CFDictionaryGetValue(response, CFSTR("ImageDigest"));
							}
							else {
								result = kAMDMissingDigestError;
							}
						}
					}

					if (!digest) {
						bool use_stream = SDMMD_device_os_is_at_least(device, CFSTR("7.0"));
						if (use_stream) {
							SDMMD_fire_callback(handle, unknown, CFSTR("StreamingImage"));
							result = SDMMD_stream_image(connection, path, image_type);
						}
						else {
							SDMMD_fire_callback(handle, unknown, CFSTR("CopyingImage"));
							result = SDMMD_copy_image(device, path);
						}
					}

					CheckErrorAndReturn(result);

					bool mounted = false;
					SDMMD_fire_callback(handle, unknown, CFSTR("MountingImage"));
					result = SDMMD_mount_image(connection, image_type, signature, &mounted);

					if (mounted) {
						result = SDMMD__hangup_with_image_mounter_service(connection);
					}
				}
				CFSafeRelease(connection);
				CFSafeRelease(device_copy);
				CheckErrorAndReturn(result);
			}
			else {
				result = kAMDUndefinedError;
			}
		}
		else {
			result = kAMDMissingImageTypeError;
		}
	}
sdmmd_return_t SDMMD_stream_image(SDMMD_AMConnectionRef connection, CFStringRef path, CFStringRef image_type)
{
	sdmmd_return_t result = kAMDSuccess;
	char fspath[0x400] = {0};
	Boolean fsRep = CFStringGetFileSystemRepresentation(path, fspath, 0x400);
	if (fsRep) {
		struct stat fileStat;
		lstat(fspath, &fileStat);
		CFNumberRef size = CFNumberCreate(kCFAllocatorDefault, 0xb, &fileStat.st_size);
		CFMutableDictionaryRef streamDict = SDMMD_create_dict();
		CFDictionarySetValue(streamDict, CFSTR("Command"), CFSTR("ReceiveBytes"));
		CFDictionarySetValue(streamDict, CFSTR("ImageType"), image_type);
		CFDictionarySetValue(streamDict, CFSTR("ImageSize"), size);
		result = SDMMD_ServiceSendMessage(SDMMD_TranslateConnectionToSocket(connection), streamDict, kCFPropertyListXMLFormat_v1_0);
		CFSafeRelease(streamDict);
		CFSafeRelease(size);

		CheckErrorAndReturn(result);

		CFDictionaryRef response;
		result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(connection), (CFPropertyListRef *)&response);

		CheckErrorAndReturn(result);

		if (response) {
			result = SDMMD__ErrorHandler(SDMMD_ImageMounterErrorConvert, response);

			CheckErrorAndReturn(result);

			CFTypeRef status = CFDictionaryGetValue(response, CFSTR("Status"));
			if (status) {
				if (CFStringCompare(status, CFSTR("ReceiveBytesAck"), 0) == 0) {
					// block code
					CFDataRef image_file = CFDataCreateFromPath(path);
					uint64_t offset = 0;
					uint64_t remainder = 0;
					while (offset < fileStat.st_size) {
						remainder = (fileStat.st_size - offset);
						remainder = (remainder > kDeveloperImageStreamSize ? kDeveloperImageStreamSize : remainder);
						CFRange current_read = CFRangeMake((CFIndex)offset, (CFIndex)remainder);
						CFDataRef image_stream = CFDataCreateFromSubrangeOfData(image_file, current_read);
						result = SDMMD_DirectServiceSend(SDMMD_TranslateConnectionToSocket(connection), image_stream);
						CheckErrorAndReturn(result);
						offset += remainder;
						CFSafeRelease(image_stream);
					}
					CFDictionaryRef getStatus;
					result = SDMMD_ServiceReceiveMessage(SDMMD_TranslateConnectionToSocket(connection), (CFPropertyListRef *)&getStatus);

					if (result == 0) {
						result = SDMMD__ErrorHandler(SDMMD_ImageMounterErrorConvert, response);

						CheckErrorAndReturn(result);

						CFTypeRef streamStatus = CFDictionaryGetValue(getStatus, CFSTR("Status"));
						if (streamStatus) {
							if (CFStringCompare(streamStatus, CFSTR("Complete"), 0x0) == 0) {
								result = kAMDSuccess;
							}
						}
					}
					CFSafeRelease(getStatus);
					CFSafeRelease(image_file);
				}
			}
			else {
				result = kAMDUndefinedError;
			}
		}
		else {
			result = kAMDReadError;
		}
	}
	else {
		result = kAMDNoResourcesError;
	}

	ExitLabelAndReturn(result);
}
Exemple #14
0
void RunAppOnDeviceWithIdentifier(char *udid, char *identifier, bool waitForDebugger)
{
	SDMMD_AMDeviceRef device = FindDeviceFromUDID(udid);
	if (device) {
		sdmmd_return_t result = SDMMD_AMDeviceConnect(device);
		if (SDM_MD_CallSuccessful(result)) {
			result = SDMMD_AMDeviceStartSession(device);
			if (SDM_MD_CallSuccessful(result)) {
				CFDictionaryRef response;
				CFArrayRef lookupValues = SDMMD_ApplicationLookupDictionary();
				CFMutableDictionaryRef optionsDict = SDMMD_create_dict();
				CFDictionarySetValue(optionsDict, CFSTR("ReturnAttributes"), lookupValues);

				result = SDMMD_AMDeviceLookupApplications(device, optionsDict, &response);
				if (SDM_MD_CallSuccessful(result)) {
					CFStringRef bundleIdentifier = CFStringCreateWithCString(kCFAllocatorDefault, identifier, kCFStringEncodingUTF8);
					CFDictionaryRef details = NULL;
					if (CFDictionaryContainsKey(response, bundleIdentifier)) {
						details = CFDictionaryGetValue(response, bundleIdentifier);
					}
					CFSafeRelease(bundleIdentifier);
					if (details) {
						SDMMD_AMDeviceStopSession(device);
						SDMMD_AMDeviceDisconnect(device);
						SDMMD_AMDebugConnectionRef dconn = SDMMD_AMDebugConnectionCreateForDevice(device);
						sdmmd_return_t result = SDMMD_AMDebugConnectionStart(dconn);
						bool launchSuccess = false;
						if (SDM_MD_CallSuccessful(result)) {

							// setting max packet size
							CFMutableArrayRef maxPacketArgs = CFArrayCreateMutable(kCFAllocatorDefault, 0x0, &kCFTypeArrayCallBacks);
							CFArrayAppendValue(maxPacketArgs, CFSTR("1024"));
							DebuggerCommandRef maxPacket = SDMMD_CreateDebuggingCommand(kDebugQSetMaxPacketSize, NULL, maxPacketArgs);
							CFSafeRelease(maxPacketArgs);

							CFDataRef maxPacketResponse = NULL;
							result = SDMMD_DebuggingSend(dconn, maxPacket, &maxPacketResponse);
							CFSafeRelease(maxPacketResponse);
							SDMMD_DebuggingCommandRelease(maxPacket);

							// setting the working directory
							CFStringRef path = CFDictionaryGetValue(details, CFSTR("Path"));
							CFStringRef container = CFDictionaryGetValue(details, CFSTR("Container"));
							if (!container) {
								CFURLRef pathURL = CFURLCreateWithString(kCFAllocatorDefault, path, NULL);
								CFURLRef containerURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, pathURL);
								container = CFURLGetString(containerURL);
								CFSafeRelease(pathURL);
							}
							CFMutableArrayRef containerPathArgs = CFArrayCreateMutable(kCFAllocatorDefault, 0x0, &kCFTypeArrayCallBacks);
							CFArrayAppendValue(containerPathArgs, container);
							DebuggerCommandRef containerPath = SDMMD_CreateDebuggingCommand(kDebugQSetWorkingDir, NULL, containerPathArgs);
							CFSafeRelease(containerPathArgs);

							CFDataRef containerPathResponse = NULL;
							result = SDMMD_DebuggingSend(dconn, containerPath, &containerPathResponse);
							CFSafeRelease(containerPathResponse);
							SDMMD_DebuggingCommandRelease(containerPath);

							// setting launch args
							CFStringRef commandFormat = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("A%d,0,"), (uint32_t)CFStringGetLength(path) * 0x2);

							CFMutableArrayRef setLaunchArgsArgs = CFArrayCreateMutable(kCFAllocatorDefault, 0x0, &kCFTypeArrayCallBacks);
							CFArrayAppendValue(setLaunchArgsArgs, path);
							DebuggerCommandRef setLaunchArgs = SDMMD_CreateDebuggingCommand(kDebugCUSTOMCOMMAND, commandFormat, setLaunchArgsArgs);
							CFSafeRelease(setLaunchArgsArgs);
							CFSafeRelease(commandFormat);

							CFDataRef setLaunchArgsResponse = NULL;
							result = SDMMD_DebuggingSend(dconn, setLaunchArgs, &setLaunchArgsResponse);
							CFSafeRelease(setLaunchArgsResponse);
							SDMMD_DebuggingCommandRelease(setLaunchArgs);

							// Check for launch success
							CFMutableArrayRef launchSuccessArgs = CFArrayCreateMutable(kCFAllocatorDefault, 0x0, &kCFTypeArrayCallBacks);
							DebuggerCommandRef launchSuccessCommand = SDMMD_CreateDebuggingCommand(kDebugqLaunchSuccess, NULL, launchSuccessArgs);
							CFSafeRelease(launchSuccessArgs);

							CFDataRef launchSuccessResponse = NULL;
							result = SDMMD_DebuggingSend(dconn, launchSuccessCommand, &launchSuccessResponse);

							if (launchSuccessResponse) {
								char *launchSuccessResponseAsString = (char *)CFDataGetBytePtr(launchSuccessResponse);
								launchSuccess = !strncmp(launchSuccessResponseAsString, "OK", 2);

								if (!launchSuccess) {
									printf("Launch failure: %s\n", launchSuccessResponseAsString);
								}
							}

							CFSafeRelease(launchSuccessResponse);
							SDMMD_DebuggingCommandRelease(launchSuccessCommand);

							if (launchSuccess) {
								printf("Launch success\n");

								if (!waitForDebugger) {
									printf("Continuing with execution...\n");

									// setting thread to attach
									CFMutableArrayRef setThreadArgs = CFArrayCreateMutable(kCFAllocatorDefault, 0x0, &kCFTypeArrayCallBacks);
									CFArrayAppendValue(setThreadArgs, CFSTR(""));
									DebuggerCommandRef setThread = SDMMD_CreateDebuggingCommand(kDebugCUSTOMCOMMAND, CFSTR("Hc0"), setThreadArgs);
									CFSafeRelease(setThreadArgs);

									CFDataRef setThreadResponse = NULL;
									result = SDMMD_DebuggingSend(dconn, setThread, &setThreadResponse);
									CFSafeRelease(setThreadResponse);
									SDMMD_DebuggingCommandRelease(setThread);

									// setting continue with execution
									CFMutableArrayRef contArgs = CFArrayCreateMutable(kCFAllocatorDefault, 0x0, &kCFTypeArrayCallBacks);
									CFArrayAppendValue(contArgs, CFSTR(""));
									DebuggerCommandRef cont = SDMMD_CreateDebuggingCommand(kDebugc, NULL, contArgs);
									CFSafeRelease(contArgs);

									CFDataRef contResponse = NULL;
									result = SDMMD_DebuggingSend(dconn, cont, &contResponse);
									CFSafeRelease(contResponse);
									SDMMD_DebuggingCommandRelease(cont);
								}
								else {
									printf("Waiting for debugger to attach...\n");

									CFRunLoopRun();
								}
							}
						}
						/*
						sdmmd_return_t result = SDMMD_StartDebuggingSessionOnDevice(device, &connection);
						if (SDM_MD_CallSuccessful(result)) {
							bool launchSuccess = false;
							CFStringRef path = CFDictionaryGetValue(details, CFSTR("Path"));
							CFStringRef encodedPath = SDMMD_EncodeDebuggingString(path);
							CFStringRef container = CFDictionaryGetValue(details, CFSTR("Container"));
							if (!container) {
								CFURLRef pathURL = CFURLCreateWithString(kCFAllocatorDefault, path, NULL);
								CFURLRef containerURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, pathURL);
								container = CFURLGetString(containerURL);
								CFSafeRelease(pathURL);
								//CFSafeRelease(containerURL);
							}
							if (container) {
								CFStringRef containerPath = SDMMD_EncodeDebuggingString(container);
								sdmmd_debug_return_t dresult;
								CFStringRef maxPacket = SDMMD_EncodeDebuggingString(CFSTR("1024"));
								dresult = SDMMD_DebuggingSend(connection, KnownDebugCommands[kDebugQSetMaxPacketSize], maxPacket);
								CFSafeRelease(maxPacket);
								dresult = SDMMD_DebuggingSend(connection, KnownDebugCommands[kDebugQSetWorkingDir], containerPath);
								CFSafeRelease(containerPath);
								CFStringRef commandFormat = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d,0,%s"), (uint32_t)CFStringGetLength(encodedPath), CFStringGetCStringPtr(encodedPath, kCFStringEncodingUTF8));
								dresult = SDMMD_DebuggingSend(connection, KnownDebugCommands[kDebugA], commandFormat);
								CFSafeRelease(commandFormat);
								dresult = SDMMD_DebuggingSend(connection, KnownDebugCommands[kDebugH], CFSTR("c0"));
								dresult = SDMMD_DebuggingSend(connection, KnownDebugCommands[kDebugc], CFSTR(""));
								launchSuccess = true;
							}
							CFSafeRelease(encodedPath);
							if (launchSuccess) {
								CFRunLoopRun();
							}
						}
						*/
					}
				}
			}
		}
	}
}
CFDictionaryRef CreateSpringboardFolder(CFStringRef name, CFArrayRef contents) {
	CFMutableDictionaryRef value = SDMMD_create_dict();
	CFDictionarySetValue(value, CFSTR("Name"), name);
	CFDictionarySetValue(value, CFSTR("Contents"), contents);
	return CreateSpringboardItem(CFSTR("Folder"), value);
}
CFDictionaryRef CreateSpringboardItem(CFStringRef type, CFTypeRef value) {
	CFMutableDictionaryRef sbItem = SDMMD_create_dict();
	CFDictionarySetValue(sbItem, CFSTR("Type"), type);
	CFDictionarySetValue(sbItem, CFSTR("Contents"), value);
	return sbItem;
}
sdmmd_return_t SDMMD_perform_command(SDMMD_AMConnectionRef conn, CFStringRef command, uint64_t code, CallBack handle, uint32_t argsCount, void* paramStart, ...) {
	sdmmd_return_t result = kAMDSuccess;
	CFMutableDictionaryRef message = SDMMD_create_dict();
	
	if (message) {
		va_list args;

		CFDictionarySetValue(message, CFSTR("Command"), command);
		va_start(args, paramStart);
		CFTypeRef key, value;
		for (uint32_t i = 0; i < argsCount; i++) {
			key = va_arg(args, CFTypeRef);
			value = va_arg(args, CFTypeRef);
			CFDictionarySetValue(message, key, value);
			i++;
		}
		va_end(args);

		SocketConnection sock = SDMMD_TranslateConnectionToSocket(conn);
		result = SDMMD_ServiceSendStream(sock, message, kCFPropertyListXMLFormat_v1_0);
		CFSafeRelease(message);
		if (result == 0) {
			CFDictionaryRef response = NULL;
			result = SDMMD_ServiceReceiveStream(sock, (CFPropertyListRef*)&response);
			if (result == 0 && response) {
				while (result == 0) {
					result = SDMMD__ErrorHandler(SDMMD__ConvertServiceError, response);
					
					CheckErrorAndReturn(result);
					
					CFTypeRef status = CFDictionaryGetValue(response, CFSTR("Status"));
					if (status) {
						if (CFStringCompare(status, CFSTR("Complete"), 0) != 0) {
							CFArrayRef responses = CFDictionaryGetValue(response, CFSTR("CurrentList"));
							if (responses) {
								uint64_t count = CFArrayGetCount(responses);
								for (uint32_t i = 0; i < count; i++) {
									CFDictionaryRef value = CFArrayGetValueAtIndex(responses, i);
									handle(value, paramStart);
								}
							}
							else {
								handle(response, 0);
							}
						}
						else {
							break;
						}
					}
					SDMMD_ServiceReceiveStream(sock, (CFPropertyListRef*)&response);
				}
			}
			else {
				result = kAMDReceiveMessageError;
				printf("call_and_response: Could not receive response from proxy.\n");
			}
		}
		else {
			result = kAMDSendMessageError;
			printf("call_and_response: Could not send request to proxy.\n");
		}
	}
	else {
		result = kAMDUndefinedError;
	}
	
	ExitLabelAndReturn(result);
}