static BOOL android_post_connect(freerdp* instance) { rdpSettings* settings; rdpUpdate* update; if (!instance || !instance->settings || !instance->context || !instance->update) return FALSE; update = instance->update; settings = instance->settings; if (!gdi_init(instance, PIXEL_FORMAT_RGBA32)) return FALSE; if (!android_register_pointer(instance->context->graphics)) return FALSE; instance->update->BeginPaint = android_begin_paint; instance->update->EndPaint = android_end_paint; instance->update->DesktopResize = android_desktop_resize; pointer_cache_register_callbacks(update); freerdp_callback("OnSettingsChanged", "(IIII)V", instance, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth); freerdp_callback("OnConnectionSuccess", "(I)V", instance); return TRUE; }
static BOOL android_post_connect(freerdp* instance) { UINT32 gdi_flags; rdpSettings *settings = instance->settings; DEBUG_ANDROID("android_post_connect"); assert(instance); assert(settings); freerdp_callback("OnSettingsChanged", "(IIII)V", instance, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth); instance->context->cache = cache_new(settings); if (instance->settings->ColorDepth > 16) gdi_flags = CLRBUF_32BPP | CLRCONV_ALPHA | CLRCONV_INVERT; else gdi_flags = CLRBUF_16BPP; gdi_init(instance, gdi_flags, NULL); instance->update->BeginPaint = android_begin_paint; instance->update->EndPaint = android_end_paint; instance->update->DesktopResize = android_desktop_resize; freerdp_channels_post_connect(instance->context->channels, instance); freerdp_callback("OnConnectionSuccess", "(I)V", instance); return TRUE; }
BOOL android_post_connect(freerdp* instance) { DEBUG_ANDROID("android_post_connect"); freerdp_callback("OnSettingsChanged", "(IIII)V", instance, instance->settings->DesktopWidth, instance->settings->DesktopHeight, instance->settings->ColorDepth); instance->context->cache = cache_new(instance->settings); gdi_init(instance, CLRCONV_ALPHA | ((instance->settings->ColorDepth > 16) ? CLRBUF_32BPP : CLRBUF_16BPP), NULL); instance->update->BeginPaint = android_begin_paint; instance->update->EndPaint = android_end_paint; instance->update->DesktopResize = android_desktop_resize; android_cliprdr_init(instance); freerdp_channels_post_connect(instance->context->channels, instance); // send notifications freerdp_callback("OnConnectionSuccess", "(I)V", instance); return TRUE; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT android_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) { BYTE* data; UINT32 size; UINT32 index; UINT32 formatId; CLIPRDR_FORMAT* format = NULL; androidContext* afc = (androidContext*) cliprdr->custom; freerdp* instance = ((rdpContext*) afc)->instance; for (index = 0; index < afc->numServerFormats; index++) { if (afc->requestedFormatId == afc->serverFormats[index].formatId) format = &(afc->serverFormats[index]); } if (!format) { SetEvent(afc->clipboardRequestEvent); return ERROR_INTERNAL_ERROR; } if (format->formatName) formatId = ClipboardRegisterFormat(afc->clipboard, format->formatName); else formatId = format->formatId; size = formatDataResponse->dataLen; data = (BYTE*) malloc(size); CopyMemory(data, formatDataResponse->requestedFormatData, size); ClipboardSetData(afc->clipboard, formatId, data, size); SetEvent(afc->clipboardRequestEvent); if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT)) { JNIEnv* env; jstring jdata; jboolean attached; formatId = ClipboardRegisterFormat(afc->clipboard, "UTF8_STRING"); data = (void*) ClipboardGetData(afc->clipboard, formatId, &size); attached = jni_attach_thread(&env); jdata = jniNewStringUTF(env, data, size); freerdp_callback("OnRemoteClipboardChanged", "(ILjava/lang/String;)V", instance, jdata); (*env)->DeleteLocalRef(env, jdata); if (attached == JNI_TRUE) { jni_detach_thread(); } } return CHANNEL_RC_OK; }
void android_desktop_resize(rdpContext* context) { DEBUG_ANDROID("ui_desktop_resize"); rdpGdi *gdi = context->gdi; freerdp_callback("OnGraphicsResize", "(IIII)V", context->instance, gdi->width, gdi->height, gdi->dstBpp); }
JNIEXPORT jboolean JNICALL jni_freerdp_disconnect(JNIEnv *env, jclass cls, jint instance) { freerdp* inst = (freerdp*)instance; androidContext* ctx = (androidContext*)inst->context; ANDROID_EVENT* event = (ANDROID_EVENT*)android_event_disconnect_new(); if (!event) return JNI_FALSE; DEBUG_ANDROID("DISCONNECT!"); assert(inst); assert(ctx); assert(event); if (!android_push_event(inst, event)) { android_event_disconnect_free(event); return JNI_FALSE; } WaitForSingleObject(ctx->thread, INFINITE); CloseHandle(ctx->thread); ctx->thread = NULL; freerdp_callback("OnDisconnecting", "(I)V", instance); return (jboolean) JNI_TRUE; }
JNIEXPORT void JNICALL jni_freerdp_cancel_connection(JNIEnv *env, jclass cls, jint instance) { DEBUG_ANDROID("Cancelling connection ..."); freerdp* inst = (freerdp*)instance; ANDROID_EVENT* event = (ANDROID_EVENT*)android_event_disconnect_new(); android_push_event(inst, event); freerdp_callback("OnDisconnecting", "(I)V", instance); }
JNIEXPORT jboolean JNICALL jni_freerdp_disconnect(JNIEnv *env, jclass cls, jint instance) { freerdp* inst = (freerdp*)instance; ANDROID_EVENT* event = (ANDROID_EVENT*)android_event_disconnect_new(); android_push_event(inst, event); freerdp_callback("OnDisconnecting", "(I)V", instance); return (jboolean) JNI_TRUE; }
static BOOL android_end_paint(rdpContext* context) { int i; HGDI_WND hwnd; int ninvalid; rdpGdi* gdi; HGDI_RGN cinvalid; int x1, y1, x2, y2; androidContext* ctx = (androidContext*)context; rdpSettings* settings; if (!ctx || !context->instance) return FALSE; settings = context->instance->settings; if (!settings) return FALSE; gdi = context->gdi; if (!gdi || !gdi->primary || !gdi->primary->hdc) return FALSE; hwnd = ctx->rdpCtx.gdi->primary->hdc->hwnd; if (!hwnd) return FALSE; ninvalid = hwnd->ninvalid; if (ninvalid == 0) return TRUE; cinvalid = hwnd->cinvalid; if (!cinvalid) return FALSE; x1 = cinvalid[0].x; y1 = cinvalid[0].y; x2 = cinvalid[0].x + cinvalid[0].w; y2 = cinvalid[0].y + cinvalid[0].h; for (i = 0; i < ninvalid; i++) { x1 = MIN(x1, cinvalid[i].x); y1 = MIN(y1, cinvalid[i].y); x2 = MAX(x2, cinvalid[i].x + cinvalid[i].w); y2 = MAX(y2, cinvalid[i].y + cinvalid[i].h); } freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance, x1, y1, x2 - x1, y2 - y1); return TRUE; }
static BOOL android_desktop_resize(rdpContext* context) { if (!context || !context->instance || !context->settings) return FALSE; freerdp_callback("OnGraphicsResize", "(IIII)V", context->instance, context->settings->DesktopWidth, context->settings->DesktopHeight, context->settings->ColorDepth); return TRUE; }
static void* android_thread_func(void* param) { DWORD status = ERROR_BAD_ARGUMENTS; freerdp* instance = param; WLog_DBG(TAG, "Start..."); if (!instance || !instance->context) goto fail; if (freerdp_client_start(instance->context) != CHANNEL_RC_OK) goto fail; WLog_DBG(TAG, "Connect..."); if (!freerdp_connect(instance)) status = GetLastError(); else { status = android_freerdp_run(instance); WLog_DBG(TAG, "Disonnect..."); if (!freerdp_disconnect(instance)) status = GetLastError(); } WLog_DBG(TAG, "Stop..."); if (freerdp_client_stop(instance->context) != CHANNEL_RC_OK) goto fail; fail: WLog_DBG(TAG, "Session ended with %08lX", status); if (status == CHANNEL_RC_OK) freerdp_callback("OnDisconnected", "(I)V", instance); else freerdp_callback("OnConnectionFailure", "(I)V", instance); WLog_DBG(TAG, "Quit."); ExitThread(status); return NULL; }
void android_desktop_resize(rdpContext* context) { DEBUG_ANDROID("ui_desktop_resize"); assert(context); assert(context->settings); assert(context->instance); freerdp_callback("OnGraphicsResize", "(IIII)V", context->instance, context->settings->DesktopWidth, context->settings->DesktopHeight, context->settings->ColorDepth); }
static void android_cliprdr_process_cb_data_response_event(clipboardContext* cb, RDP_CB_DATA_RESPONSE_EVENT* event) { DEBUG_ANDROID("size=%d", event->size); if (event->size > 0) { if (cb->data) { free(cb->data); cb->data = NULL; cb->data_length = 0; } switch (cb->data_format) { case CB_FORMAT_RAW: case CB_FORMAT_PNG: case CB_FORMAT_JPEG: case CB_FORMAT_GIF: case CB_FORMAT_DIB: default: DEBUG_ANDROID("unsupported format\n"); break; case CB_FORMAT_TEXT: android_cliprdr_process_text(cb, event->data, event->size - 1); break; case CB_FORMAT_UNICODETEXT: android_cliprdr_process_unicodetext(cb, event->data, event->size - 2); break; case CB_FORMAT_HTML: android_cliprdr_process_html(cb, event->data, event->size); break; } DEBUG_ANDROID("computer_clipboard_data %s ", (char*)cb->data); if (cb->data) { //CALLBACK JNIEnv* env; jboolean attached = jni_attach_thread(&env); jstring jdata = jniNewStringUTF(env, cb->data, cb->data_length); freerdp_callback("OnRemoteClipboardChanged", "(ILjava/lang/String;)V", cb->instance, jdata); (*env)->DeleteLocalRef(env, jdata); if(attached == JNI_TRUE) { jni_detach_thread(); } } } }
void android_end_paint(rdpContext* context) { DEBUG_ANDROID("ui_update"); rdpGdi *gdi = context->gdi; if (gdi->primary->hdc->hwnd->invalid->null) return; int x = gdi->primary->hdc->hwnd->invalid->x; int y = gdi->primary->hdc->hwnd->invalid->y; int w = gdi->primary->hdc->hwnd->invalid->w; int h = gdi->primary->hdc->hwnd->invalid->h; DEBUG_ANDROID("ui_update: x:%d y:%d w:%d h:%d", x, y, w, h); freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance, x, y, w, h); }
void android_end_paint(rdpContext* context) { androidContext *ctx = (androidContext*)context; rdpSettings* settings = context->instance->settings; DEBUG_ANDROID("ui_update"); assert(ctx); assert(settings); assert(context->instance); DEBUG_ANDROID("width=%d, height=%d, bpp=%d", settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth); freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance, 0, 0, settings->DesktopWidth, settings->DesktopHeight); }
static BOOL android_end_paint(rdpContext* context) { int i; int ninvalid; HGDI_RGN cinvalid; int x1, y1, x2, y2; androidContext *ctx = (androidContext*)context; rdpSettings* settings = context->instance->settings; assert(ctx); assert(settings); assert(context->instance); ninvalid = ctx->rdpCtx.gdi->primary->hdc->hwnd->ninvalid; if (ninvalid == 0) { DEBUG_ANDROID("ui_update: ninvalid=%d", ninvalid); return TRUE; } cinvalid = ctx->rdpCtx.gdi->primary->hdc->hwnd->cinvalid; x1 = cinvalid[0].x; y1 = cinvalid[0].y; x2 = cinvalid[0].x + cinvalid[0].w; y2 = cinvalid[0].y + cinvalid[0].h; for (i = 0; i < ninvalid; i++) { x1 = MIN(x1, cinvalid[i].x); y1 = MIN(y1, cinvalid[i].y); x2 = MAX(x2, cinvalid[i].x + cinvalid[i].w); y2 = MAX(y2, cinvalid[i].y + cinvalid[i].h); } DEBUG_ANDROID("ui_update: ninvalid=%d x=%d, y=%d, width=%d, height=%d, bpp=%d", ninvalid, x1, y1, x2 - x1, y2 - y1, settings->ColorDepth); freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance, x1, y1, x2 - x1, y2 - y1); return TRUE; }
static int android_freerdp_run(freerdp* instance) { int i; int fds; int max_fds; int rcount; int wcount; int fd_input_event; HANDLE input_event = NULL; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; int select_status; struct timeval timeout; const rdpSettings* settings = instance->context->settings; HANDLE input_thread = NULL; HANDLE channels_thread = NULL; BOOL async_input = settings->AsyncInput; BOOL async_channels = settings->AsyncChannels; BOOL async_transport = settings->AsyncTransport; DEBUG_ANDROID("AsyncUpdate=%d", settings->AsyncUpdate); DEBUG_ANDROID("AsyncInput=%d", settings->AsyncInput); DEBUG_ANDROID("AsyncChannels=%d", settings->AsyncChannels); DEBUG_ANDROID("AsyncTransport=%d", settings->AsyncTransport); memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); if (!freerdp_connect(instance)) { freerdp_callback("OnConnectionFailure", "(I)V", instance); return 0; } if (async_input) { if (!(input_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) jni_input_thread, instance, 0, NULL))) { DEBUG_ANDROID("Failed to create async input thread\n"); goto disconnect; } } if (async_channels) { if (!(channels_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) jni_channels_thread, instance, 0, NULL))) { DEBUG_ANDROID("Failed to create async channels thread\n"); goto disconnect; } } ((androidContext*)instance->context)->is_connected = TRUE; while (!freerdp_shall_disconnect(instance)) { rcount = 0; wcount = 0; if (!async_transport) { if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get FreeRDP file descriptor\n"); break; } } if (!async_channels) { if (freerdp_channels_get_fds(instance->context->channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get channel manager file descriptor\n"); break; } } if (!async_input) { if (android_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get android file descriptor\n"); break; } } else { input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE); fd_input_event = GetEventFileDescriptor(input_event); rfds[rcount++] = (void*) (long) fd_input_event; } max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; timeout.tv_sec = 1; timeout.tv_usec = 0; select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout); if (select_status == 0) continue; else if (select_status == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { DEBUG_ANDROID("android_run: select failed\n"); break; } } if (freerdp_shall_disconnect(instance)) break; if (!async_transport) { if (freerdp_check_fds(instance) != TRUE) { DEBUG_ANDROID("Failed to check FreeRDP file descriptor\n"); break; } } if (!async_input) { if (android_check_fds(instance) != TRUE) { DEBUG_ANDROID("Failed to check android file descriptor\n"); break; } } else if (input_event) { if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0) { if (!freerdp_message_queue_process_pending_messages(instance, FREERDP_INPUT_MESSAGE_QUEUE)) { DEBUG_ANDROID("User Disconnect"); break; } } } if (!async_channels) { if (freerdp_channels_check_fds(instance->context->channels, instance) != TRUE) { DEBUG_ANDROID("Failed to check channel manager file descriptor\n"); break; } } } disconnect: DEBUG_ANDROID("Prepare shutdown..."); // issue another OnDisconnecting here in case the disconnect was initiated by the server and not our client freerdp_callback("OnDisconnecting", "(I)V", instance); DEBUG_ANDROID("Close channels..."); freerdp_channels_disconnect(instance->context->channels, instance); DEBUG_ANDROID("Cleanup threads..."); if (async_channels && channels_thread) { WaitForSingleObject(channels_thread, INFINITE); CloseHandle(channels_thread); } if (async_input && input_thread) { wMessageQueue* input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE); if (input_queue) { if (MessageQueue_PostQuit(input_queue, 0)) WaitForSingleObject(input_thread, INFINITE); } CloseHandle(input_thread); } DEBUG_ANDROID("run Disconnecting..."); freerdp_disconnect(instance); freerdp_callback("OnDisconnected", "(I)V", instance); DEBUG_ANDROID("run Quit."); return 0; }
int android_freerdp_run(freerdp* instance) { int i; int fds; int max_fds; int rcount; int wcount; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; int select_status; struct timeval timeout; assert(instance); memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); if (!freerdp_connect(instance)) { freerdp_callback("OnConnectionFailure", "(I)V", instance); return 0; } ((androidContext*)instance->context)->is_connected = TRUE; while (!freerdp_shall_disconnect(instance)) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get FreeRDP file descriptor\n"); break; } if (freerdp_channels_get_fds(instance->context->channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get channel manager file descriptor\n"); break; } if (android_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get android file descriptor\n"); break; } max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; timeout.tv_sec = 1; timeout.tv_usec = 0; select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout); if (select_status == 0) continue; else if (select_status == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { DEBUG_ANDROID("android_run: select failed\n"); break; } } if (freerdp_shall_disconnect(instance)) break; if (freerdp_check_fds(instance) != TRUE) { DEBUG_ANDROID("Failed to check FreeRDP file descriptor\n"); break; } if (android_check_fds(instance) != TRUE) { DEBUG_ANDROID("Failed to check android file descriptor\n"); break; } if (freerdp_channels_check_fds(instance->context->channels, instance) != TRUE) { DEBUG_ANDROID("Failed to check channel manager file descriptor\n"); break; } android_process_channel_event(instance->context->channels, instance); } // issue another OnDisconnecting here in case the disconnect was initiated by the sever and not our client freerdp_callback("OnDisconnecting", "(I)V", instance); freerdp_channels_close(instance->context->channels, instance); freerdp_disconnect(instance); gdi_free(instance); cache_free(instance->context->cache); android_cliprdr_uninit(instance); freerdp_callback("OnDisconnected", "(I)V", instance); return 0; }
static void android_post_disconnect(freerdp* instance) { freerdp_callback("OnDisconnecting", "(I)V", instance); gdi_free(instance); }
static BOOL android_pre_connect(freerdp* instance) { int rc; rdpSettings* settings; BOOL bitmap_cache; if (!instance) return FALSE; settings = instance->settings; if (!settings || !settings->OrderSupport) return FALSE; bitmap_cache = settings->BitmapCacheEnabled; settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE; settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE; settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE; settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE; settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE; settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE; settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE; settings->OrderSupport[NEG_LINETO_INDEX] = TRUE; settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE; settings->OrderSupport[NEG_MEMBLT_INDEX] = bitmap_cache; settings->OrderSupport[NEG_MEM3BLT_INDEX] = TRUE; settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = bitmap_cache; settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE; settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE; settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE; settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE; settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE; settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; rc = PubSub_SubscribeChannelConnected( instance->context->pubSub, (pChannelConnectedEventHandler) android_OnChannelConnectedEventHandler); if (rc != CHANNEL_RC_OK) { WLog_ERR(TAG, "Could not subscribe to connect event handler [%l08X]", rc); return FALSE; } rc = PubSub_SubscribeChannelDisconnected( instance->context->pubSub, (pChannelDisconnectedEventHandler) android_OnChannelDisconnectedEventHandler); if (rc != CHANNEL_RC_OK) { WLog_ERR(TAG, "Could not subscribe to disconnect event handler [%l08X]", rc); return FALSE; } if (!freerdp_client_load_addins(instance->context->channels, instance->settings)) { WLog_ERR(TAG, "Failed to load addins [%l08X]", GetLastError()); return FALSE; } freerdp_callback("OnPreConnect", "(I)V", instance); return TRUE; }