123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- #ifndef __APPLE_API_PRIVATE
- #define __APPLE_API_PRIVATE
- #include "sandbox.h"
- #undef __APPLE_API_PRIVATE
- #else
- #include "sandbox.h"
- #endif
- #ifndef LIGHTMESSAGING_USE_ROCKETBOOTSTRAP
- #define LIGHTMESSAGING_USE_ROCKETBOOTSTRAP 1
- #endif
- #ifndef LIGHTMESSAGING_TIMEOUT
- #define LIGHTMESSAGING_TIMEOUT MACH_MSG_TIMEOUT_NONE
- #define _LIGHTMESSAGING_TIMEOUT_FLAGS 0
- #else
- #define _LIGHTMESSAGING_TIMEOUT_FLAGS (MACH_SEND_TIMEOUT | MACH_RCV_TIMEOUT)
- #endif
- #import <CoreGraphics/CoreGraphics.h>
- #import <ImageIO/ImageIO.h>
- #include <mach/mach.h>
- #include <mach/mach_init.h>
- #if LIGHTMESSAGING_USE_ROCKETBOOTSTRAP
- #include "../rocketbootstrap/rocketbootstrap.h"
- #else
- #include "bootstrap.h"
- #endif
- #ifdef __OBJC__
- #ifndef __has_feature
- #define __has_feature(x) 0
- #endif
- #if __has_feature(objc_arc)
- #define LMBridgedCast_(a, b) (__bridge a)(b)
- #else
- #define LMBridgedCast_(a, b) (a)(b)
- #endif
- #endif
- typedef struct {
- mach_port_t serverPort;
- name_t serverName;
- } LMConnection;
- typedef LMConnection *LMConnectionRef;
- #define __LMMaxInlineSize 4096 + sizeof(LMMessage)
- typedef struct __LMMessage {
- mach_msg_header_t head;
- mach_msg_body_t body;
- union {
- struct {
- mach_msg_ool_descriptor_t descriptor;
- } out_of_line;
- struct {
- uint32_t length;
- uint8_t bytes[0];
- } in_line;
- } data;
- } LMMessage;
- typedef struct __LMResponseBuffer {
- LMMessage message;
- uint8_t slack[__LMMaxInlineSize - sizeof(LMMessage) + MAX_TRAILER_SIZE];
- } LMResponseBuffer;
- static inline uint32_t LMBufferSizeForLength(uint32_t length)
- {
- if (length + sizeof(LMMessage) > __LMMaxInlineSize)
- return sizeof(LMMessage);
- else
- return ((sizeof(LMMessage) + length) + 3) & ~0x3;
- }
- static inline void LMMessageCopyInline(LMMessage *message, const void *data, uint32_t length)
- {
- message->data.in_line.length = length;
- if (data) {
- memcpy(message->data.in_line.bytes, data, length);
- }
- }
- static inline void LMMessageAssignOutOfLine(LMMessage *message, const void *data, uint32_t length)
- {
- message->head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
- message->body.msgh_descriptor_count = 1;
- message->data.out_of_line.descriptor.type = MACH_MSG_OOL_DESCRIPTOR;
- message->data.out_of_line.descriptor.copy = MACH_MSG_VIRTUAL_COPY;
- message->data.out_of_line.descriptor.deallocate = false;
- message->data.out_of_line.descriptor.address = (void *)data;
- message->data.out_of_line.descriptor.size = length;
- }
- static inline void LMMessageAssignData(LMMessage *message, const void *data, uint32_t length)
- {
- if (length == 0) {
- message->body.msgh_descriptor_count = 0;
- message->data.in_line.length = length;
- } else if (message->head.msgh_size != sizeof(LMMessage)) {
- message->body.msgh_descriptor_count = 0;
- message->data.in_line.length = length;
- memcpy(message->data.in_line.bytes, data, length);
- } else {
- LMMessageAssignOutOfLine(message, data, length);
- }
- }
- static inline void *LMMessageGetData(LMMessage *message)
- {
- if (message->body.msgh_descriptor_count)
- return message->data.out_of_line.descriptor.address;
- if (message->data.in_line.length == 0)
- return NULL;
- return &message->data.in_line.bytes;
- }
- static inline uint32_t LMMessageGetDataLength(LMMessage *message)
- {
- if (message->body.msgh_descriptor_count)
- return message->data.out_of_line.descriptor.size;
- uint32_t result = message->data.in_line.length;
- // Clip to the maximum size of a message buffer, prevents clients from forcing reads outside the region
- if (result > __LMMaxInlineSize - offsetof(LMMessage, data.in_line.bytes))
- return __LMMaxInlineSize - offsetof(LMMessage, data.in_line.bytes);
- // Client specified the right size, yay!
- return result;
- }
- static inline mach_msg_return_t LMMachMsg(LMConnection *connection, mach_msg_header_t *msg, mach_msg_option_t option, mach_msg_size_t send_size, mach_msg_size_t rcv_size, mach_port_name_t rcv_name, mach_msg_timeout_t timeout, mach_port_name_t notify)
- {
- for (;;) {
- kern_return_t err;
- if (connection->serverPort == MACH_PORT_NULL) {
- mach_port_t selfTask = mach_task_self();
- if ((kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_5_0) && (kCFCoreFoundationVersionNumber < 800.0)) {
- int sandbox_result = sandbox_check(getpid(), "mach-lookup", (enum sandbox_filter_type)(SANDBOX_FILTER_LOCAL_NAME | SANDBOX_CHECK_NO_REPORT), connection->serverName);
- if (sandbox_result) {
- return sandbox_result;
- }
- }
- // Lookup remote port
- mach_port_t bootstrap = MACH_PORT_NULL;
- task_get_bootstrap_port(selfTask, &bootstrap);
- #if LIGHTMESSAGING_USE_ROCKETBOOTSTRAP
- err = rocketbootstrap_look_up(bootstrap, connection->serverName, &connection->serverPort);
- #else
- err = bootstrap_look_up(bootstrap, connection->serverName, &connection->serverPort);
- #endif
- if (err)
- return err;
- }
- msg->msgh_remote_port = connection->serverPort;
- err = mach_msg(msg, option, send_size, rcv_size, rcv_name, timeout, notify);
- if (err != MACH_SEND_INVALID_DEST)
- return err;
- mach_port_deallocate(mach_task_self(), msg->msgh_remote_port);
- connection->serverPort = MACH_PORT_NULL;
- }
- }
- static inline kern_return_t LMConnectionSendOneWay(LMConnectionRef connection, SInt32 messageId, const void *data, uint32_t length)
- {
- // Send message
- uint32_t size = LMBufferSizeForLength(length);
- uint8_t buffer[size];
- LMMessage *message = (LMMessage *)&buffer[0];
- memset(message, 0, sizeof(LMMessage));
- message->head.msgh_id = messageId;
- message->head.msgh_size = size;
- message->head.msgh_local_port = MACH_PORT_NULL;
- message->head.msgh_reserved = 0;
- message->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
- LMMessageAssignData(message, data, length);
- return LMMachMsg(connection, &message->head, MACH_SEND_MSG, size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- }
- static inline kern_return_t LMConnectionSendEmptyOneWay(LMConnectionRef connection, SInt32 messageId)
- {
- // TODO: Optimize so we don't use the additional stack space
- uint32_t size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t);
- LMMessage message;
- memset(&message, 0, size);
- message.head.msgh_id = messageId;
- message.head.msgh_size = size;
- message.head.msgh_local_port = MACH_PORT_NULL;
- message.head.msgh_reserved = 0;
- message.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
- return LMMachMsg(connection, &message.head, MACH_SEND_MSG, size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- }
- static inline kern_return_t LMConnectionSendTwoWay(LMConnectionRef connection, SInt32 messageId, const void *data, uint32_t length, LMResponseBuffer *responseBuffer)
- {
- // Create a reply port
- mach_port_t selfTask = mach_task_self();
- mach_port_name_t replyPort = MACH_PORT_NULL;
- int err = mach_port_allocate(selfTask, MACH_PORT_RIGHT_RECEIVE, &replyPort);
- if (err) {
- responseBuffer->message.body.msgh_descriptor_count = 0;
- return err;
- }
- // Send message
- uint32_t size = LMBufferSizeForLength(length);
- LMMessage *message = &responseBuffer->message;
- memset(message, 0, sizeof(LMMessage));
- message->head.msgh_id = messageId;
- message->head.msgh_size = size;
- message->head.msgh_local_port = replyPort;
- message->head.msgh_reserved = 0;
- message->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
- LMMessageAssignData(message, data, length);
- err = LMMachMsg(connection, &message->head, MACH_SEND_MSG | MACH_RCV_MSG | _LIGHTMESSAGING_TIMEOUT_FLAGS, size, sizeof(LMResponseBuffer), replyPort, LIGHTMESSAGING_TIMEOUT, MACH_PORT_NULL);
- if (err)
- responseBuffer->message.body.msgh_descriptor_count = 0;
- // Cleanup
- mach_port_mod_refs(selfTask, replyPort, MACH_PORT_RIGHT_RECEIVE, -1);
- return err;
- }
- static inline void LMResponseBufferFree(LMResponseBuffer *responseBuffer)
- {
- if (responseBuffer->message.body.msgh_descriptor_count != 0 && responseBuffer->message.data.out_of_line.descriptor.type == MACH_MSG_OOL_DESCRIPTOR) {
- vm_deallocate(mach_task_self(), (vm_address_t)responseBuffer->message.data.out_of_line.descriptor.address, responseBuffer->message.data.out_of_line.descriptor.size);
- responseBuffer->message.body.msgh_descriptor_count = 0;
- }
- }
- #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- static inline kern_return_t LMStartServiceWithUserInfo(name_t serverName, CFRunLoopRef runLoop, CFMachPortCallBack callback, void *userInfo)
- {
- // TODO: Figure out what the real interface is, implement service stopping, handle failures correctly
- mach_port_t bootstrap = MACH_PORT_NULL;
- task_get_bootstrap_port(mach_task_self(), &bootstrap);
- CFMachPortContext context = { 0, userInfo, NULL, NULL, NULL };
- CFMachPortRef machPort = CFMachPortCreate(kCFAllocatorDefault, callback, &context, NULL);
- CFRunLoopSourceRef machPortSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, machPort, 0);
- CFRunLoopAddSource(runLoop, machPortSource, kCFRunLoopCommonModes);
- mach_port_t port = CFMachPortGetPort(machPort);
- #if LIGHTMESSAGING_USE_ROCKETBOOTSTRAP
- rocketbootstrap_unlock(serverName);
- #endif
- return bootstrap_register(bootstrap, serverName, port);
- }
- #pragma GCC diagnostic warning "-Wdeprecated-declarations"
- static inline kern_return_t LMStartService(name_t serverName, CFRunLoopRef runLoop, CFMachPortCallBack callback)
- {
- return LMStartServiceWithUserInfo(serverName, runLoop, callback, NULL);
- }
- static inline kern_return_t LMCheckInService(name_t serverName, CFRunLoopRef runLoop, CFMachPortCallBack callback, void *userInfo)
- {
- // TODO: Figure out what the real interface is, implement service stopping, handle failures correctly
- mach_port_t bootstrap = MACH_PORT_NULL;
- task_get_bootstrap_port(mach_task_self(), &bootstrap);
- CFMachPortContext context = { 0, userInfo, NULL, NULL, NULL };
- mach_port_t port = MACH_PORT_NULL;
- kern_return_t result = bootstrap_check_in(bootstrap, serverName, &port);
- if (result)
- return result;
- CFMachPortRef machPort = CFMachPortCreateWithPort(kCFAllocatorDefault, port, callback, &context, NULL);
- CFRunLoopSourceRef machPortSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, machPort, 0);
- CFRunLoopAddSource(runLoop, machPortSource, kCFRunLoopCommonModes);
- #if LIGHTMESSAGING_USE_ROCKETBOOTSTRAP
- rocketbootstrap_unlock(serverName);
- #endif
- return 0;
- }
- static inline bool LMDataWithSizeIsValidMessage(const void *data, CFIndex size)
- {
- if (size < sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t))
- return false;
- const LMMessage *message = (const LMMessage *)data;
- if (message->body.msgh_descriptor_count)
- return size >= sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t) + sizeof(mach_msg_ool_descriptor_t);
- if (size < sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t) + sizeof(uint32_t))
- return false;
- if (size < sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t) + sizeof(uint32_t) + message->data.in_line.length)
- return false;
- return true;
- }
- static inline kern_return_t LMSendReply(mach_port_t replyPort, const void *data, uint32_t length)
- {
- if (replyPort == MACH_PORT_NULL)
- return 0;
- uint32_t size = LMBufferSizeForLength(length);
- uint8_t buffer[size];
- memset(buffer, 0, sizeof(LMMessage));
- LMMessage *response = (LMMessage *)&buffer[0];
- response->head.msgh_id = 0;
- response->head.msgh_size = size;
- response->head.msgh_remote_port = replyPort;
- response->head.msgh_local_port = MACH_PORT_NULL;
- response->head.msgh_reserved = 0;
- response->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0);
- LMMessageAssignData(response, data, length);
- // Send message
- kern_return_t err = mach_msg(&response->head, MACH_SEND_MSG, size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- if (err) {
- // Cleanup leaked SEND_ONCE
- mach_port_mod_refs(mach_task_self(), replyPort, MACH_PORT_RIGHT_SEND_ONCE, -1);
- }
- return err;
- }
- static inline kern_return_t LMSendIntegerReply(mach_port_t replyPort, int integer)
- {
- return LMSendReply(replyPort, &integer, sizeof(integer));
- }
- static inline kern_return_t LMSendCFDataReply(mach_port_t replyPort, CFDataRef data)
- {
- if (data) {
- return LMSendReply(replyPort, CFDataGetBytePtr(data), CFDataGetLength(data));
- } else {
- return LMSendReply(replyPort, NULL, 0);
- }
- }
- #ifdef __OBJC__
- #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- static inline id LMPropertyListForData(NSData *data)
- {
- if ([NSPropertyListSerialization respondsToSelector:@selector(propertyListWithData:options:format:error:)])
- return [NSPropertyListSerialization propertyListWithData:data options:0 format:NULL error:NULL];
- return [NSPropertyListSerialization propertyListFromData:data mutabilityOption:0 format:NULL errorDescription:NULL];
- }
- static inline NSData *LMDataForPropertyList(id propertyList)
- {
- if ([NSPropertyListSerialization respondsToSelector:@selector(dataWithPropertyList:options:format:error:)])
- return [NSPropertyListSerialization dataWithPropertyList:propertyList format:NSPropertyListBinaryFormat_v1_0 options:0 error:NULL];
- return [NSPropertyListSerialization dataFromPropertyList:propertyList format:NSPropertyListBinaryFormat_v1_0 errorDescription:NULL];
- }
- #pragma GCC diagnostic warning "-Wdeprecated-declarations"
- static inline kern_return_t LMSendNSDataReply(mach_port_t replyPort, NSData *data)
- {
- return LMSendReply(replyPort, [data bytes], [data length]);
- }
- static inline kern_return_t LMSendPropertyListReply(mach_port_t replyPort, id propertyList)
- {
- if (propertyList)
- return LMSendNSDataReply(replyPort, LMDataForPropertyList(propertyList));
- else
- return LMSendReply(replyPort, NULL, 0);
- }
- #endif
- // Remote functions
- static inline bool LMConnectionSendOneWayData(LMConnectionRef connection, SInt32 messageId, CFDataRef data)
- {
- if (data)
- return LMConnectionSendOneWay(connection, messageId, CFDataGetBytePtr(data), CFDataGetLength(data)) == 0;
- else
- return LMConnectionSendOneWay(connection, messageId, NULL, 0) == 0;
- }
- static inline kern_return_t LMConnectionSendTwoWayData(LMConnectionRef connection, SInt32 messageId, CFDataRef data, LMResponseBuffer *buffer)
- {
- if (data)
- return LMConnectionSendTwoWay(connection, messageId, CFDataGetBytePtr(data), CFDataGetLength(data), buffer);
- else
- return LMConnectionSendTwoWay(connection, messageId, NULL, 0, buffer);
- }
- static inline int32_t LMResponseConsumeInteger(LMResponseBuffer *buffer)
- {
- int32_t result = LMMessageGetDataLength(&buffer->message) == sizeof(int32_t) ? *(int32_t *)buffer->message.data.in_line.bytes : 0;
- LMResponseBufferFree(buffer);
- return result;
- }
- #ifdef __OBJC__
- static inline kern_return_t LMConnectionSendTwoWayPropertyList(LMConnectionRef connection, SInt32 messageId, id propertyList, LMResponseBuffer *buffer)
- {
- return LMConnectionSendTwoWayData(connection, messageId, propertyList ? LMBridgedCast_(CFDataRef, LMDataForPropertyList(propertyList)) : NULL, buffer);
- }
- static inline id LMResponseConsumePropertyList(LMResponseBuffer *buffer)
- {
- uint32_t length = LMMessageGetDataLength(&buffer->message);
- id result;
- if (length) {
- CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)LMMessageGetData(&buffer->message), length, kCFAllocatorNull);
- result = LMPropertyListForData(LMBridgedCast_(NSData *, data));
- CFRelease(data);
- } else {
- result = nil;
- }
- LMResponseBufferFree(buffer);
- return result;
- }
- #ifdef UIKIT_EXTERN
- #import <UIKit/UIImage.h>
- typedef struct __attribute__((aligned(0x1))) __attribute__((packed)) {
- uint32_t width;
- uint32_t height;
- uint32_t bitsPerComponent;
- uint32_t bitsPerPixel;
- uint32_t bytesPerRow;
- CGBitmapInfo bitmapInfo;
- float scale;
- UIImageOrientation orientation;
- } LMImageHeader;
- typedef struct {
- LMMessage response;
- LMImageHeader imageHeader;
- } LMImageMessage;
- static void LMCGDataProviderReleaseCallback(void *info, const void *data, size_t size)
- {
- vm_deallocate(mach_task_self(), (vm_address_t)data, size);
- }
- static inline UIImage *LMResponseConsumeImage(LMResponseBuffer *buffer)
- {
- if (buffer->message.body.msgh_descriptor_count != 0 && buffer->message.data.out_of_line.descriptor.type == MACH_MSG_OOL_DESCRIPTOR) {
- const void *bytes = buffer->message.data.out_of_line.descriptor.address;
- const LMImageMessage *message = (const LMImageMessage *)buffer;
- const LMImageHeader *header = &message->imageHeader;
- CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bytes, buffer->message.data.out_of_line.descriptor.size, LMCGDataProviderReleaseCallback);
- if (provider) {
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- CGImageRef cgImage = CGImageCreate(header->width, header->height, header->bitsPerComponent, header->bitsPerPixel, header->bytesPerRow, colorSpace, header->bitmapInfo, provider, NULL, false, kCGRenderingIntentDefault);
- CGColorSpaceRelease(colorSpace);
- CGDataProviderRelease(provider);
- if (cgImage) {
- UIImage *image;
- if ([UIImage respondsToSelector:@selector(imageWithCGImage:scale:orientation:)]) {
- image = [UIImage imageWithCGImage:cgImage scale:header->scale orientation:header->orientation];
- } else {
- image = [UIImage imageWithCGImage:cgImage];
- }
- CGImageRelease(cgImage);
- return image;
- }
- return nil;
- }
- }
- LMResponseBufferFree(buffer);
- return nil;
- }
- typedef struct CGAccessSession *CGAccessSessionRef;
- CGAccessSessionRef CGAccessSessionCreate(CGDataProviderRef provider);
- void *CGAccessSessionGetBytePointer(CGAccessSessionRef session);
- size_t CGAccessSessionGetBytes(CGAccessSessionRef session,void *buffer,size_t bytes);
- void CGAccessSessionRelease(CGAccessSessionRef session);
- static inline kern_return_t LMSendImageReply(mach_port_t replyPort, UIImage *image)
- {
- if (replyPort == MACH_PORT_NULL)
- return 0;
- LMImageMessage buffer;
- memset(&buffer, 0, sizeof(buffer));
- buffer.response.head.msgh_id = 0;
- buffer.response.head.msgh_size = sizeof(buffer);
- buffer.response.head.msgh_remote_port = replyPort;
- buffer.response.head.msgh_local_port = MACH_PORT_NULL;
- buffer.response.head.msgh_reserved = 0;
- buffer.response.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0);
- CFDataRef imageData = NULL;
- CGAccessSessionRef accessSession = NULL;
- if (image) {
- CGImageRef cgImage = image.CGImage;
- if (cgImage) {
- buffer.imageHeader.width = CGImageGetWidth(cgImage);
- buffer.imageHeader.height = CGImageGetHeight(cgImage);
- buffer.imageHeader.bitsPerComponent = CGImageGetBitsPerComponent(cgImage);
- buffer.imageHeader.bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
- buffer.imageHeader.bytesPerRow = CGImageGetBytesPerRow(cgImage);
- buffer.imageHeader.bitmapInfo = CGImageGetBitmapInfo(cgImage);
- buffer.imageHeader.scale = [image respondsToSelector:@selector(scale)] ? [image scale] : 1.0f;
- buffer.imageHeader.orientation = image.imageOrientation;
- CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage);
- bool hasLoadedData = false;
- if (&CGAccessSessionCreate != NULL) {
- accessSession = CGAccessSessionCreate(dataProvider);
- if (accessSession) {
- void *pointer = CGAccessSessionGetBytePointer(accessSession);
- if (pointer) {
- LMMessageAssignOutOfLine(&buffer.response, pointer, buffer.imageHeader.bytesPerRow * buffer.imageHeader.height);
- hasLoadedData = true;
- }
- }
- }
- if (!hasLoadedData) {
- if (accessSession) {
- CGAccessSessionRelease(accessSession);
- accessSession = NULL;
- }
- imageData = CGDataProviderCopyData(dataProvider);
- if (imageData) {
- LMMessageAssignOutOfLine(&buffer.response, CFDataGetBytePtr(imageData), CFDataGetLength(imageData));
- }
- }
- }
- }
- // Send message
- kern_return_t err = mach_msg(&buffer.response.head, MACH_SEND_MSG, sizeof(buffer), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- if (err) {
- // Cleanup leaked SEND_ONCE
- mach_port_mod_refs(mach_task_self(), replyPort, MACH_PORT_RIGHT_SEND_ONCE, -1);
- }
- if (imageData) {
- CFRelease(imageData);
- }
- if (accessSession) {
- CGAccessSessionRelease(accessSession);
- }
- return err;
- }
- #endif
- #endif
|