sdmmd_return_t SDMMD_copy_image(SDMMD_AMDeviceRef device, CFStringRef path)
{
	sdmmd_return_t result = kAMDUndefinedError;
	if (device) {
		result = kAMDSuccess; //SDMMD_AMDeviceConnect(device);
		CheckErrorAndReturn(result);

		result = SDMMD_AMDeviceStartSession(device);
		CheckErrorAndReturn(result);

		SDMMD_AMConnectionRef copyConn = NULL;
		result = SDMMD_AMDeviceSecureStartService(device, CFSTR(AMSVC_AFC), NULL, &copyConn);
		CheckErrorAndReturn(result);

		SDMMD_AFCConnectionRef copyAFCConn = SDMMD_AFCConnectionCreate(copyConn);
		SDMMD_AFCOperationRef makeStaging = SDMMD_AFCOperationCreateMakeDirectory(CFSTR("PublicStaging"));
		result = SDMMD_AFCProcessOperation(copyAFCConn, &makeStaging);
		CheckErrorAndReturn(result);

		// SDM copy file AFC
		char *pathString = SDMCFStringGetString(path);
		result = SDMMD_AMDeviceCopyFile(SDMMD_Default_AFC_CopyFile_Callback, NULL, NULL, copyAFCConn, pathString, "PublicStaging/staging.dimage");
		Safe(free, pathString);

		CFSafeRelease(makeStaging);
		CFSafeRelease(copyAFCConn);

		CFSafeRelease(copyConn);
	}

	ExitLabelAndReturn(result);
}
sdmmd_return_t SDMMD_MB2SendFile(SDMMD_AMConnectionRef conn, CFStringRef path, CFDataRef file) {
	sdmmd_return_t result = kAMDSuccess;
	result = SDMMD_MB2SendFileStream(conn, path, file);
	CheckErrorAndReturn(result);
	result = SDMMD_MB2SendEndStream(conn);
	CheckErrorAndReturn(result);

	ExitLabelAndReturn(result);
}
sdmmd_return_t SDMMD_AMDebugConnectionStop(SDMMD_AMDebugConnectionRef dconn)
{
	sdmmd_return_t result = kAMDSuccess;
	CFSafeRelease(dconn->connection);

	result = SDMMD_AMDeviceStopSession(dconn->device);
	CheckErrorAndReturn(result);

	result = SDMMD_AMDeviceDisconnect(dconn->device);
	CheckErrorAndReturn(result);

	ExitLabelAndReturn(result);
}
sdmmd_return_t SDMMD_AMDeviceCopyApplication(SDMMD_AMDeviceRef device, CFStringRef path) {
	sdmmd_return_t result = kAMDNotConnectedError;
	SDMMD_AMConnectionRef connection = NULL;
	if (device) {
		result = SDMMD_AMDeviceConnect(device);
		CheckErrorAndReturn(result);
		
		result = SDMMD_AMDeviceStartSession(device);
		CheckErrorAndReturn(result);
		
		result = SDMMD_AMDeviceSecureStartService(device, CFSTR(AMSVC_AFC), NULL, &connection);
		CheckErrorAndReturn(result);
		
		result = SDMMD_AMDeviceTransferApplication(connection, path, NULL, SDMMD_Default_transfer_callback, NULL);
		CheckErrorAndReturn(result);
		
		result = SDMMD_AMDServiceConnectionInvalidate(connection);
		CheckErrorAndReturn(result);
		
		result = SDMMD_AMDeviceStopSession(device);
		CheckErrorAndReturn(result);
		
		result = SDMMD_AMDeviceDisconnect(device);
		CheckErrorAndReturn(result);
	}
	ExitLabelAndReturn(result);
}
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);
}
sdmmd_return_t SDMMD_AMDebugConnectionStart(SDMMD_AMDebugConnectionRef dconn)
{
	sdmmd_return_t result = SDMMD_AMDeviceConnect(dconn->device);
	CheckErrorAndReturn(result);

	result = SDMMD_AMDeviceStartSession(dconn->device);
	CheckErrorAndReturn(result);

	dconn->connection = SDMMD_AMDServiceConnectionCreate(0, NULL, NULL);
	result = SDMMD_AMDeviceStartService(dconn->device, CFSTR(AMSVC_DEBUG_SERVER), NULL, &(dconn->connection));
	CheckErrorAndReturn(result);

	result = SDMMD_AMDeviceStopSession(dconn->device);
	CheckErrorAndReturn(result);

	result = SDMMD_AMDeviceDisconnect(dconn->device);
	CheckErrorAndReturn(result);

	ExitLabelAndReturn(result);
}
sdmmd_return_t SDMMD_AMDeviceInstallApp(SDMMD_AMDeviceRef device, CFStringRef path) {
	sdmmd_return_t result = kAMDNotConnectedError;
	SDMMD_AMConnectionRef connection = NULL;
	if (device) {
		result = SDMMD_AMDeviceConnect(device);
		CheckErrorAndReturn(result);
		
		result = SDMMD_AMDeviceStartSession(device);
		CheckErrorAndReturn(result);
		
		result = SDMMD_AMDeviceSecureStartService(device, CFSTR(AMSVC_AFC), NULL, &connection);
		CheckErrorAndReturn(result);
		
		CFStringRef keys[] = { CFSTR("PackageType") };
		CFStringRef values[] = { CFSTR("Developer") };
		CFDictionaryRef options = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
		result = SDMMD_AMDeviceInstallApplication(device, path, options, SDMMD_Default_install_callback, NULL);
		CheckErrorAndReturn(result);
		
		result = SDMMD_AMDeviceStopSession(device);
		CheckErrorAndReturn(result);
		
		result = SDMMD_AMDeviceDisconnect(device);
		CheckErrorAndReturn(result);
	}
	ExitLabelAndReturn(result);
}
sdmmd_return_t SDMMD_MB2SendEndStream(SDMMD_AMConnectionRef conn) {
	sdmmd_return_t result = kAMDSuccess;
	
	uint32_t zero_stream = 0x0;
	CFDataRef stream_end = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)&zero_stream, sizeof(uint32_t));
	result = SDMMD_DirectServiceSend(SDMMD_TranslateConnectionToSocket(conn), stream_end);
	CFSafeRelease(stream_end);
	CheckErrorAndReturn(result);
	
	CFMutableArrayRef status_response = SDMMD_MB2StatusResponseMessage();
	result = SDMMD_ServiceSendMessage(SDMMD_TranslateConnectionToSocket(conn), status_response, kCFPropertyListBinaryFormat_v1_0);

	ExitLabelAndReturn(result);
}
sdmmd_return_t SDMMD_MB2SendFiles(SDMMD_AMConnectionRef conn, CFArrayRef paths, CFArrayRef files) {
	sdmmd_return_t result = kAMDSuccess;
	
	if (CFArrayGetCount(paths) == CFArrayGetCount(files)) {
		for (CFIndex index = 0; index < CFArrayGetCount(paths); index++) {
			CFStringRef path = CFArrayGetValueAtIndex(paths, index);
			CFDataRef file = CFArrayGetValueAtIndex(files, index);
			result = SDMMD_MB2SendFileStream(conn, path, file);
			CheckErrorAndReturn(result);
		}
		result = SDMMD_MB2SendEndStream(conn);
	}
	
	ExitLabelAndReturn(result);
}
sdmmd_return_t SDMMD_MB2SendFileStream(SDMMD_AMConnectionRef conn, CFStringRef path, CFDataRef file) {
	sdmmd_return_t result = kAMDSuccess;
	
	CFDataRef file_path = CFStringCreateExternalRepresentation(kCFAllocatorDefault, path, kCFStringEncodingUTF8, 0);
	result = SDMMD_ServiceSend(SDMMD_TranslateConnectionToSocket(conn), file_path);
	CFSafeRelease(file_path);
	CheckErrorAndReturn(result);
	
	char data_chunk[1] = { 0x0C };
	CFMutableDataRef data_separator = CFDataCreateMutable(kCFAllocatorDefault, 0);
	CFDataAppendBytes(data_separator, (const UInt8 *)data_chunk, sizeof(uint8_t));
	CFDataAppendBytes(data_separator, CFDataGetBytePtr(file), CFDataGetLength(file));
	result = SDMMD_ServiceSend(SDMMD_TranslateConnectionToSocket(conn), data_separator);
	CFSafeRelease(data_separator);
	CheckErrorAndReturn(result);
	
	char zero_chunk[1] = { 0x0 };
	CFDataRef data_end = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)zero_chunk, sizeof(uint8_t));
	result = SDMMD_ServiceSend(SDMMD_TranslateConnectionToSocket(conn), data_end);
	CFSafeRelease(data_end);
	CheckErrorAndReturn(result);
	
	ExitLabelAndReturn(result);
}
Esempio n. 11
0
sdmmd_return_t SDMMD_ServiceReceiveStream(SocketConnection handle, CFPropertyListRef *data) {
	CFDataRef dataBuffer = NULL;
	sdmmd_return_t result = SDMMD_ServiceReceive(handle, &dataBuffer);

	CheckErrorAndReturn(result);
	
	if (dataBuffer && CFDataGetLength(dataBuffer)) {
		CFReadStreamRef read = CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault, CFDataGetBytePtr(dataBuffer), CFDataGetLength(dataBuffer), kCFAllocatorNull);

		CFReadStreamOpen(read);
		*data = CFPropertyListCreateWithStream(kCFAllocatorDefault, read, CFDataGetLength(dataBuffer), kCFPropertyListMutableContainersAndLeaves, NULL, NULL);
		CFReadStreamClose(read);
		CFSafeRelease(read);
	}
	result = kAMDSuccess;
	
	CFSafeRelease(dataBuffer);
	ExitLabelAndReturn(result);
}
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;
}
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);
}
Esempio n. 15
0
sdmmd_return_t SDMMD_AMDeviceTransferApplication(SDMMD_AMConnectionRef conn, CFStringRef path, CFDictionaryRef options, CallBack transferCallback, void* unknown) {
	sdmmd_return_t result = kAMDInvalidArgumentError;
	if (path) {
		if (conn) {
			char *cpath = calloc(1, sizeof(char[1024]));
			ATR_UNUSED struct stat pathStat, remoteStat;
			Boolean status = CFStringGetCString(path, cpath, 1024, kCFStringEncodingUTF8);
			if (status) {
				CFURLRef deviceURL = SDMMD__AMDCFURLCreateFromFileSystemPathWithSmarts(path);
				if (deviceURL) {
					CFStringRef lastComp = CFURLCopyLastPathComponent(deviceURL);
					if (lastComp) {
						CFURLRef base = SDMMD__AMDCFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorDefault, CFSTR("PublicStaging"), 0, true);
						CFURLRef copy = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, base, lastComp, true);
						char *copyPath = calloc(1024, sizeof(char));
						SDMMD__AMDCFURLGetCStringForFileSystemPath(copy, copyPath);
						SDMMD_fire_callback_767f4(transferCallback, unknown, 0, CFSTR("PreflightingTransfer"));
						//SDMMD_preflight_transfer(&cpath, &pathStat, &remoteStat);
						SDMMD_fire_callback_767f4(transferCallback, unknown, 0, CFSTR("TransferingPackage"));
						SDMMD_AFCConnectionRef afcConn = SDMMD_AFCConnectionCreate(conn);//(r12, conn, 0x0, 0x0, &var_72);
						if (afcConn) {
							result = kAMDSuccess;
						}
						CheckErrorAndReturn(result);
						
						result = SDMMD_AMDeviceCopy(afcConn, cpath, copyPath);
						
						/*
						CFDataRef touchResponse;
						result = SDMMD_check_can_touch(afcConn, &touchResponse);
						CheckErrorAndReturn(result);
						
						CFURLRef parent = CFURLCreateCopyDeletingLastPathComponent(r12, r13);
						result = SDMMD_make_path(afcConn, parent);
						CheckErrorAndReturn(result);
									
						result = SDMMD_nuke_path(afcConn, r13);
						if ((result | 0x8) == 0x8) {
							int statResult = lstat(cpath, &pathStat);
							if (statResult != 0xff) {
								if ((var_84 & 0xffff & 0xf000) != 0xa000) {
									if (rax == 0x8000) {
										rbx = SDMMD_copy_touch_file(&remoteStat, transferCallback, unknown, afcConn, &cpath, &copyPath);
									}
									else {
										if (rax == 0x4000) {
											rbx = SDMMD_copy_directory(&remoteStat, transferCallback, unknown, afcConn, &cpath, &copyPath);
										}
										else {
											printf("transfer_package: Don't know how to copy this type of file: %s\n", cpath);
										}
									}
								}
								else {
									rbx = SDMMD_copy_symlink(afcConn, &cpath, &copyPath);
								}
							r14 = 0x0;
							if (rbx != 0x0) {
								r9 = SDMMD_AFCErrorString(rbx);
								printf("transfer_package: Could not copy %s to %s on the device.\n", cpath, copyPath);
								result = kAMDUndefinedError;
							}
							result = SDMMD_AFCConnectionClose(afcConn);
							if (result) {
								printf("transfer_package: Could not close AFC connection. error: %i\n", result);
							}
							CFSafeRelease(r12);
						}
						 */
						CFSafeRelease(base);
						CFSafeRelease(copy);
					}
					CFSafeRelease(lastComp);
				}
				CFSafeRelease(deviceURL);
			}
			else {
				result = kAMDUndefinedError;
			}
			Safe(free, cpath);
		}
	}
	
	ExitLabelAndReturn(result);
}
Esempio n. 16
0
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);
}