From aec86e1da8725bdaef2682679a444d37ab1211c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 18 Mar 2013 20:12:51 -0400 Subject: [PATCH] wfreerdp: start splitting CLI from client core --- .gitignore | 1 + channels/rdpsnd/client/alsa/CMakeLists.txt | 2 + channels/rdpsnd/client/mac/CMakeLists.txt | 2 + channels/rdpsnd/client/pulse/CMakeLists.txt | 2 + channels/rdpsnd/client/winmm/CMakeLists.txt | 2 + client/Windows/CMakeLists.txt | 2 + client/Windows/wf_interface.c | 693 ++++++++++++++++++++ client/Windows/wf_interface.h | 123 ++++ client/Windows/wfreerdp.c | 670 +------------------ 9 files changed, 835 insertions(+), 662 deletions(-) create mode 100644 client/Windows/wf_interface.c create mode 100644 client/Windows/wf_interface.h diff --git a/.gitignore b/.gitignore index cafaa421d..2b72aa942 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,7 @@ xcode *.dir Release Win32 +build/ default.log *Amplifier XE* diff --git a/channels/rdpsnd/client/alsa/CMakeLists.txt b/channels/rdpsnd/client/alsa/CMakeLists.txt index 0f2afc47b..2f5eb1df7 100644 --- a/channels/rdpsnd/client/alsa/CMakeLists.txt +++ b/channels/rdpsnd/client/alsa/CMakeLists.txt @@ -44,3 +44,5 @@ target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) if(NOT STATIC_CHANNELS) install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH}) endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/ALSA") diff --git a/channels/rdpsnd/client/mac/CMakeLists.txt b/channels/rdpsnd/client/mac/CMakeLists.txt index 4b04dff35..35d9247ec 100644 --- a/channels/rdpsnd/client/mac/CMakeLists.txt +++ b/channels/rdpsnd/client/mac/CMakeLists.txt @@ -48,3 +48,5 @@ target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) if(NOT STATIC_CHANNELS) install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH}) endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/Mac") diff --git a/channels/rdpsnd/client/pulse/CMakeLists.txt b/channels/rdpsnd/client/pulse/CMakeLists.txt index d14f5c85a..ab695b2c3 100644 --- a/channels/rdpsnd/client/pulse/CMakeLists.txt +++ b/channels/rdpsnd/client/pulse/CMakeLists.txt @@ -39,3 +39,5 @@ target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) if(NOT STATIC_CHANNELS) install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH}) endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/Pulse") diff --git a/channels/rdpsnd/client/winmm/CMakeLists.txt b/channels/rdpsnd/client/winmm/CMakeLists.txt index 4eca824d7..955fe6ba3 100644 --- a/channels/rdpsnd/client/winmm/CMakeLists.txt +++ b/channels/rdpsnd/client/winmm/CMakeLists.txt @@ -43,3 +43,5 @@ target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) if(NOT STATIC_CHANNELS) install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH}) endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/WinMM") diff --git a/client/Windows/CMakeLists.txt b/client/Windows/CMakeLists.txt index 92e75a532..b45bed5f5 100644 --- a/client/Windows/CMakeLists.txt +++ b/client/Windows/CMakeLists.txt @@ -31,6 +31,8 @@ set(${MODULE_PREFIX}_SRCS wf_window.h wf_rail.c wf_rail.h + wf_interface.c + wf_interface.h wfreerdp.c wfreerdp.h) diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c new file mode 100644 index 000000000..17eaed4cc --- /dev/null +++ b/client/Windows/wf_interface.c @@ -0,0 +1,693 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Windows Client + * + * Copyright 2009-2011 Jay Sorg + * Copyright 2010-2011 Vic Lee + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "wf_gdi.h" +#include "wf_graphics.h" +#include "wf_cliprdr.h" + +#include "wfreerdp.h" + +extern HANDLE g_done_event; +extern HINSTANCE g_hInstance; +extern HCURSOR g_default_cursor; +extern int g_thread_count; +extern LPCTSTR g_wnd_class_name; + +void wf_context_new(freerdp* instance, rdpContext* context) +{ + context->channels = freerdp_channels_new(); +} + +void wf_context_free(freerdp* instance, rdpContext* context) +{ + if (context->cache) + cache_free(context->cache); + + freerdp_channels_free(context->channels); +} + +int wf_create_console(void) +{ + if (!AllocConsole()) + return 1; + + freopen("CONOUT$", "w", stdout); + printf("Debug console created.\n"); + + return 0; +} + +void wf_sw_begin_paint(rdpContext* context) +{ + rdpGdi* gdi = context->gdi; + gdi->primary->hdc->hwnd->invalid->null = 1; + gdi->primary->hdc->hwnd->ninvalid = 0; +} + +void wf_sw_end_paint(rdpContext* context) +{ + int i; + rdpGdi* gdi; + wfInfo* wfi; + INT32 x, y; + UINT32 w, h; + int ninvalid; + RECT update_rect; + HGDI_RGN cinvalid; + + gdi = context->gdi; + wfi = ((wfContext*) context)->wfi; + + if (gdi->primary->hdc->hwnd->ninvalid < 1) + return; + + ninvalid = gdi->primary->hdc->hwnd->ninvalid; + cinvalid = gdi->primary->hdc->hwnd->cinvalid; + + for (i = 0; i < ninvalid; i++) + { + x = cinvalid[i].x; + y = cinvalid[i].y; + w = cinvalid[i].w; + h = cinvalid[i].h; + + update_rect.left = x; + update_rect.top = y; + update_rect.right = x + w - 1; + update_rect.bottom = y + h - 1; + + InvalidateRect(wfi->hwnd, &update_rect, FALSE); + } +} + +void wf_sw_desktop_resize(rdpContext* context) +{ + wfInfo* wfi; + rdpGdi* gdi; + rdpSettings* settings; + + wfi = ((wfContext*) context)->wfi; + settings = wfi->instance->settings; + gdi = context->gdi; + + wfi->width = settings->DesktopWidth; + wfi->height = settings->DesktopHeight; + gdi_resize(gdi, wfi->width, wfi->height); + + if (wfi->primary) + { + wf_image_free(wfi->primary); + wfi->primary = wf_image_new(wfi, wfi->width, wfi->height, wfi->dstBpp, gdi->primary_buffer); + } +} + +void wf_hw_begin_paint(rdpContext* context) +{ + wfInfo* wfi = ((wfContext*) context)->wfi; + wfi->hdc->hwnd->invalid->null = 1; + wfi->hdc->hwnd->ninvalid = 0; +} + +void wf_hw_end_paint(rdpContext* context) +{ + +} + +void wf_hw_desktop_resize(rdpContext* context) +{ + wfInfo* wfi; + BOOL same; + RECT rect; + rdpSettings* settings; + + wfi = ((wfContext*) context)->wfi; + settings = wfi->instance->settings; + + wfi->width = settings->DesktopWidth; + wfi->height = settings->DesktopHeight; + if (wfi->primary) + { + same = (wfi->primary == wfi->drawing) ? TRUE : FALSE; + + wf_image_free(wfi->primary); + + wfi->primary = wf_image_new(wfi, wfi->width, wfi->height, wfi->dstBpp, NULL); + + if (same) + wfi->drawing = wfi->primary; + } + if (wfi->fullscreen != TRUE) + { + if (wfi->hwnd) + SetWindowPos(wfi->hwnd, HWND_TOP, -1, -1, wfi->width + wfi->diff.x, wfi->height + wfi->diff.y, SWP_NOMOVE); + } + else + { + wf_update_offset(wfi); + GetWindowRect(wfi->hwnd, &rect); + InvalidateRect(wfi->hwnd, &rect, TRUE); + } +} + +BOOL wf_pre_connect(freerdp* instance) +{ + int i1; + wfInfo* wfi; + rdpFile* file; + wfContext* context; + rdpSettings* settings; + + wfi = (wfInfo*) malloc(sizeof(wfInfo)); + ZeroMemory(wfi, sizeof(wfInfo)); + + context = (wfContext*) instance->context; + wfi->instance = instance; + context->wfi = wfi; + + settings = instance->settings; + + settings = instance->settings; + + if (settings->ConnectionFile) + { + file = freerdp_client_rdp_file_new(); + + printf("Using connection file: %s\n", settings->ConnectionFile); + + freerdp_client_parse_rdp_file(file, settings->ConnectionFile); + freerdp_client_populate_settings_from_rdp_file(file, settings); + + freerdp_client_rdp_file_free(file); + } + + settings->OsMajorType = OSMAJORTYPE_WINDOWS; + settings->OsMinorType = OSMINORTYPE_WINDOWS_NT; + 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] = TRUE; + settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE; + settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; + settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = FALSE; + settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE; + settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE; + 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; + + settings->GlyphSupportLevel = GLYPH_SUPPORT_NONE; + + wfi->cursor = g_default_cursor; + + wfi->fullscreen = settings->Fullscreen; + wfi->fs_toggle = 1; + wfi->sw_gdi = settings->SoftwareGdi; + + wfi->clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); + ZeroMemory(wfi->clrconv, sizeof(CLRCONV)); + + wfi->clrconv->palette = NULL; + wfi->clrconv->alpha = FALSE; + + instance->context->cache = cache_new(settings); + + if (wfi->percentscreen > 0) + { + i1 = (GetSystemMetrics(SM_CXSCREEN) * wfi->percentscreen) / 100; + settings->DesktopWidth = i1; + + i1 = (GetSystemMetrics(SM_CYSCREEN) * wfi->percentscreen) / 100; + settings->DesktopHeight = i1; + } + + if (wfi->fullscreen) + { + settings->DesktopWidth = GetSystemMetrics(SM_CXSCREEN); + settings->DesktopHeight = GetSystemMetrics(SM_CYSCREEN); + } + + i1 = settings->DesktopWidth; + i1 = (i1 + 3) & (~3); + settings->DesktopWidth = i1; + + if ((settings->DesktopWidth < 64) || (settings->DesktopHeight < 64) || + (settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096)) + { + printf("wf_pre_connect: invalid dimensions %d %d\n", settings->DesktopWidth, settings->DesktopHeight); + return 1; + } + + settings->KeyboardLayout = (int) GetKeyboardLayout(0) & 0x0000FFFF; + freerdp_channels_pre_connect(instance->context->channels, instance); + + return TRUE; +} + +BOOL wf_post_connect(freerdp* instance) +{ + rdpGdi* gdi; + wfInfo* wfi; + rdpCache* cache; + wfContext* context; + wchar_t win_title[64]; + rdpSettings* settings; + + settings = instance->settings; + context = (wfContext*) instance->context; + cache = instance->context->cache; + wfi = context->wfi; + + wfi->dstBpp = 32; + wfi->width = settings->DesktopWidth; + wfi->height = settings->DesktopHeight; + + if (wfi->sw_gdi) + { + gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_32BPP, NULL); + gdi = instance->context->gdi; + wfi->hdc = gdi->primary->hdc; + wfi->primary = wf_image_new(wfi, wfi->width, wfi->height, wfi->dstBpp, gdi->primary_buffer); + } + else + { + wf_gdi_register_update_callbacks(instance->update); + wfi->srcBpp = instance->settings->ColorDepth; + wfi->primary = wf_image_new(wfi, wfi->width, wfi->height, wfi->dstBpp, NULL); + + wfi->hdc = gdi_GetDC(); + wfi->hdc->bitsPerPixel = wfi->dstBpp; + wfi->hdc->bytesPerPixel = wfi->dstBpp / 8; + + wfi->hdc->alpha = wfi->clrconv->alpha; + wfi->hdc->invert = wfi->clrconv->invert; + + wfi->hdc->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND)); + wfi->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0); + wfi->hdc->hwnd->invalid->null = 1; + + wfi->hdc->hwnd->count = 32; + wfi->hdc->hwnd->cinvalid = (HGDI_RGN) malloc(sizeof(GDI_RGN) * wfi->hdc->hwnd->count); + wfi->hdc->hwnd->ninvalid = 0; + + if (settings->RemoteFxCodec) + { + wfi->tile = wf_image_new(wfi, 64, 64, 32, NULL); + wfi->rfx_context = rfx_context_new(); + } + + if (settings->NSCodec) + wfi->nsc_context = nsc_context_new(); + } + + if (settings->WindowTitle != NULL) + _snwprintf(win_title, ARRAYSIZE(win_title), L"%S", settings->WindowTitle); + else if (settings->ServerPort == 3389) + _snwprintf(win_title, ARRAYSIZE(win_title), L"FreeRDP: %S", settings->ServerHostname); + else + _snwprintf(win_title, ARRAYSIZE(win_title), L"FreeRDP: %S:%d", settings->ServerHostname, settings->ServerPort); + + if (wfi->hwnd == 0) + { + wfi->hwnd = CreateWindowEx((DWORD) NULL, g_wnd_class_name, win_title, + 0, 0, 0, 0, 0, NULL, NULL, g_hInstance, NULL); + + SetWindowLongPtr(wfi->hwnd, GWLP_USERDATA, (LONG_PTR) wfi); + } + + wf_resize_window(wfi); + + BitBlt(wfi->primary->hdc, 0, 0, wfi->width, wfi->height, NULL, 0, 0, BLACKNESS); + wfi->drawing = wfi->primary; + + ShowWindow(wfi->hwnd, SW_SHOWNORMAL); + UpdateWindow(wfi->hwnd); + + if (wfi->sw_gdi) + { + instance->update->BeginPaint = wf_sw_begin_paint; + instance->update->EndPaint = wf_sw_end_paint; + instance->update->DesktopResize = wf_sw_desktop_resize; + } + else + { + instance->update->BeginPaint = wf_hw_begin_paint; + instance->update->EndPaint = wf_hw_end_paint; + instance->update->DesktopResize = wf_hw_desktop_resize; + } + + pointer_cache_register_callbacks(instance->update); + + if (wfi->sw_gdi != TRUE) + { + brush_cache_register_callbacks(instance->update); + bitmap_cache_register_callbacks(instance->update); + offscreen_cache_register_callbacks(instance->update); + } + + wf_register_graphics(instance->context->graphics); + + freerdp_channels_post_connect(instance->context->channels, instance); + + wf_cliprdr_init(wfi, instance->context->channels); + + return TRUE; +} + +static const char wfTargetName[] = "TARGET"; + +static CREDUI_INFOA wfUiInfo = +{ + sizeof(CREDUI_INFOA), + NULL, + "Enter your credentials", + "Remote Desktop Security", + NULL +}; + +BOOL wf_authenticate(freerdp* instance, char** username, char** password, char** domain) +{ + BOOL fSave; + DWORD status; + DWORD dwFlags; + char UserName[CREDUI_MAX_USERNAME_LENGTH + 1]; + char Password[CREDUI_MAX_PASSWORD_LENGTH + 1]; + char User[CREDUI_MAX_USERNAME_LENGTH + 1]; + char Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1]; + + fSave = FALSE; + ZeroMemory(UserName, sizeof(UserName)); + ZeroMemory(Password, sizeof(Password)); + dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES; + + status = CredUIPromptForCredentialsA(&wfUiInfo, wfTargetName, NULL, 0, + UserName, CREDUI_MAX_USERNAME_LENGTH + 1, + Password, CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags); + + if (status != NO_ERROR) + { + printf("CredUIPromptForCredentials unexpected status: 0x%08X\n", status); + return FALSE; + } + + ZeroMemory(User, sizeof(User)); + ZeroMemory(Domain, sizeof(Domain)); + + status = CredUIParseUserNameA(UserName, User, sizeof(User), Domain, sizeof(Domain)); + + //printf("User: %s Domain: %s Password: %s\n", User, Domain, Password); + + *username = _strdup(User); + + if (strlen(Domain) > 0) + *domain = _strdup(Domain); + + *password = _strdup(Password); + + return TRUE; +} + +BOOL wf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) +{ +#if 0 + DWORD mode; + int read_size; + DWORD read_count; + TCHAR answer[2]; + TCHAR* read_buffer; + HANDLE input_handle; +#endif + + printf("Certificate details:\n"); + printf("\tSubject: %s\n", subject); + printf("\tIssuer: %s\n", issuer); + printf("\tThumbprint: %s\n", fingerprint); + printf("The above X.509 certificate could not be verified, possibly because you do not have " + "the CA certificate in your certificate store, or the certificate has expired. " + "Please look at the documentation on how to create local certificate store for a private CA.\n"); + + /* TODO: ask for user validation */ +#if 0 + input_handle = GetStdHandle(STD_INPUT_HANDLE); + + GetConsoleMode(input_handle, &mode); + mode |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT; + SetConsoleMode(input_handle, mode); +#endif + + return TRUE; +} + +int wf_receive_channel_data(freerdp* instance, int channelId, BYTE* data, int size, int flags, int total_size) +{ + return freerdp_channels_data(instance, channelId, data, size, flags, total_size); +} + +void wf_process_channel_event(rdpChannels* channels, freerdp* instance) +{ + RDP_EVENT* event; + + event = freerdp_channels_pop_event(channels); + + if (event) + freerdp_event_free(event); +} + +BOOL wf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount) +{ + return TRUE; +} + +BOOL wf_check_fds(freerdp* instance) +{ + return TRUE; +} + +int wfreerdp_run(freerdp* instance) +{ + MSG msg; + int index; + int rcount; + int wcount; + BOOL msg_ret; + int quit_msg; + void* rfds[32]; + void* wfds[32]; + int fds_count; + HANDLE fds[64]; + rdpChannels* channels; + + memset(rfds, 0, sizeof(rfds)); + memset(wfds, 0, sizeof(wfds)); + + if (freerdp_connect(instance) != TRUE) + return 0; + + channels = instance->context->channels; + + while (1) + { + rcount = 0; + wcount = 0; + + if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) + { + printf("Failed to get FreeRDP file descriptor\n"); + break; + } + if (wf_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) + { + printf("Failed to get wfreerdp file descriptor\n"); + break; + } + if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) + { + printf("Failed to get channel manager file descriptor\n"); + break; + } + + fds_count = 0; + /* setup read fds */ + for (index = 0; index < rcount; index++) + { + fds[fds_count++] = rfds[index]; + } + /* setup write fds */ + for (index = 0; index < wcount; index++) + { + fds[fds_count++] = wfds[index]; + } + /* exit if nothing to do */ + if (fds_count == 0) + { + printf("wfreerdp_run: fds_count is zero\n"); + break; + } + + /* do the wait */ + if (MsgWaitForMultipleObjects(fds_count, fds, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED) + { + printf("wfreerdp_run: WaitForMultipleObjects failed: 0x%04X\n", GetLastError()); + break; + } + + if (freerdp_check_fds(instance) != TRUE) + { + printf("Failed to check FreeRDP file descriptor\n"); + break; + } + if (freerdp_shall_disconnect(instance)) + { + break; + } + if (wf_check_fds(instance) != TRUE) + { + printf("Failed to check wfreerdp file descriptor\n"); + break; + } + if (freerdp_channels_check_fds(channels, instance) != TRUE) + { + printf("Failed to check channel manager file descriptor\n"); + break; + } + wf_process_channel_event(channels, instance); + + quit_msg = FALSE; + while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) + { + msg_ret = GetMessage(&msg, NULL, 0, 0); + + if (msg_ret == 0 || msg_ret == -1) + { + quit_msg = TRUE; + break; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + if (quit_msg) + break; + } + + /* cleanup */ + + freerdp_channels_close(channels, instance); + freerdp_disconnect(instance); + + return 0; +} + +DWORD WINAPI thread_func(LPVOID lpParam) +{ + wfInfo* wfi; + freerdp* instance; + + instance = (freerdp*) lpParam; + + wfi = (wfInfo*) malloc(sizeof(wfInfo)); + ZeroMemory(wfi, sizeof(wfInfo)); + + ((wfContext*) instance->context)->wfi = wfi; + wfi->instance = instance; + + wfreerdp_run(instance); + + g_thread_count--; + + if (g_thread_count < 1) + SetEvent(g_done_event); + + return (DWORD) NULL; +} + +DWORD WINAPI kbd_thread_func(LPVOID lpParam) +{ + MSG msg; + BOOL status; + HHOOK hook_handle; + + hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, wf_ll_kbd_proc, g_hInstance, 0); + + if (hook_handle) + { + while ((status = GetMessage( &msg, NULL, 0, 0 )) != 0) + { + if (status == -1) + { + printf("keyboard thread error getting message\n"); + break; + } + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + UnhookWindowsHookEx(hook_handle); + } + else + { + printf("failed to install keyboard hook\n"); + } + + return (DWORD) NULL; +} diff --git a/client/Windows/wf_interface.h b/client/Windows/wf_interface.h new file mode 100644 index 000000000..3e6bcf553 --- /dev/null +++ b/client/Windows/wf_interface.h @@ -0,0 +1,123 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Windows Client + * + * Copyright 2009-2011 Jay Sorg + * Copyright 2010-2011 Vic Lee + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __WFREERDP_H +#define __WFREERDP_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wf_event.h" + +struct wf_bitmap +{ + rdpBitmap _bitmap; + HDC hdc; + HBITMAP bitmap; + HBITMAP org_bitmap; + BYTE* pdata; +}; +typedef struct wf_bitmap wfBitmap; + +struct wf_pointer +{ + rdpPointer pointer; + HCURSOR cursor; +}; +typedef struct wf_pointer wfPointer; + +typedef struct wf_info wfInfo; + +struct wf_context +{ + rdpContext _p; + + wfInfo* wfi; +}; +typedef struct wf_context wfContext; + +struct wf_info +{ + int width; + int height; + int offset_x; + int offset_y; + int fs_toggle; + int fullscreen; + int percentscreen; + char window_title[64]; + + HWND hwnd; + POINT diff; + HGDI_DC hdc; + UINT16 srcBpp; + UINT16 dstBpp; + freerdp* instance; + wfBitmap* primary; + wfBitmap* drawing; + HCLRCONV clrconv; + HCURSOR cursor; + HBRUSH brush; + HBRUSH org_brush; + RECT update_rect; + + wfBitmap* tile; + RFX_CONTEXT* rfx_context; + NSC_CONTEXT* nsc_context; + + BOOL sw_gdi; +}; + +int wf_create_console(void); + +void wf_context_new(freerdp* instance, rdpContext* context); +void wf_context_free(freerdp* instance, rdpContext* context); + +void wf_sw_begin_paint(rdpContext* context); +void wf_sw_end_paint(rdpContext* context); +void wf_sw_desktop_resize(rdpContext* context); + +void wf_hw_begin_paint(rdpContext* context); +void wf_hw_end_paint(rdpContext* context); +void wf_hw_desktop_resize(rdpContext* context); + +BOOL wf_pre_connect(freerdp* instance); +BOOL wf_post_connect(freerdp* instance); + +BOOL wf_authenticate(freerdp* instance, char** username, char** password, char** domain); +BOOL wf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint); + +int wf_receive_channel_data(freerdp* instance, int channelId, BYTE* data, int size, int flags, int total_size); + +DWORD WINAPI kbd_thread_func(LPVOID lpParam); +DWORD WINAPI thread_func(LPVOID lpParam); + +#endif diff --git a/client/Windows/wfreerdp.c b/client/Windows/wfreerdp.c index 6e786ba55..38326b432 100644 --- a/client/Windows/wfreerdp.c +++ b/client/Windows/wfreerdp.c @@ -28,17 +28,6 @@ #include #include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#include -#endif - #include #include #include @@ -49,663 +38,21 @@ #include #include -#include "wf_gdi.h" -#include "wf_graphics.h" -#include "wf_cliprdr.h" - -#include "wfreerdp.h" - -struct _thread_data -{ - freerdp* instance; -}; -typedef struct _thread_data thread_data; +#include "wf_interface.h" HANDLE g_done_event; HINSTANCE g_hInstance; HCURSOR g_default_cursor; -volatile int g_thread_count = 0; +int g_thread_count = 0; LPCTSTR g_wnd_class_name = L"wfreerdp"; -void wf_context_new(freerdp* instance, rdpContext* context) -{ - context->channels = freerdp_channels_new(); -} - -void wf_context_free(freerdp* instance, rdpContext* context) -{ - if (context->cache) - cache_free(context->cache); - freerdp_channels_free(context->channels); -} - -int wf_create_console(void) -{ - if (!AllocConsole()) - return 1; - - freopen("CONOUT$", "w", stdout); - printf("Debug console created.\n"); - - return 0; -} - -void wf_sw_begin_paint(rdpContext* context) -{ - rdpGdi* gdi = context->gdi; - gdi->primary->hdc->hwnd->invalid->null = 1; - gdi->primary->hdc->hwnd->ninvalid = 0; -} - -void wf_sw_end_paint(rdpContext* context) -{ - int i; - rdpGdi* gdi; - wfInfo* wfi; - INT32 x, y; - UINT32 w, h; - int ninvalid; - RECT update_rect; - HGDI_RGN cinvalid; - - gdi = context->gdi; - wfi = ((wfContext*) context)->wfi; - - if (gdi->primary->hdc->hwnd->ninvalid < 1) - return; - - ninvalid = gdi->primary->hdc->hwnd->ninvalid; - cinvalid = gdi->primary->hdc->hwnd->cinvalid; - - for (i = 0; i < ninvalid; i++) - { - x = cinvalid[i].x; - y = cinvalid[i].y; - w = cinvalid[i].w; - h = cinvalid[i].h; - - update_rect.left = x; - update_rect.top = y; - update_rect.right = x + w - 1; - update_rect.bottom = y + h - 1; - - InvalidateRect(wfi->hwnd, &update_rect, FALSE); - } -} - -void wf_sw_desktop_resize(rdpContext* context) -{ - wfInfo* wfi; - rdpGdi* gdi; - rdpSettings* settings; - - wfi = ((wfContext*) context)->wfi; - settings = wfi->instance->settings; - gdi = context->gdi; - - wfi->width = settings->DesktopWidth; - wfi->height = settings->DesktopHeight; - gdi_resize(gdi, wfi->width, wfi->height); - - if (wfi->primary) - { - wf_image_free(wfi->primary); - wfi->primary = wf_image_new(wfi, wfi->width, wfi->height, wfi->dstBpp, gdi->primary_buffer); - } -} - -void wf_hw_begin_paint(rdpContext* context) -{ - wfInfo* wfi = ((wfContext*) context)->wfi; - wfi->hdc->hwnd->invalid->null = 1; - wfi->hdc->hwnd->ninvalid = 0; -} - -void wf_hw_end_paint(rdpContext* context) -{ - -} - -void wf_hw_desktop_resize(rdpContext* context) -{ - wfInfo* wfi; - BOOL same; - RECT rect; - rdpSettings* settings; - - wfi = ((wfContext*) context)->wfi; - settings = wfi->instance->settings; - - wfi->width = settings->DesktopWidth; - wfi->height = settings->DesktopHeight; - if (wfi->primary) - { - same = (wfi->primary == wfi->drawing) ? TRUE : FALSE; - - wf_image_free(wfi->primary); - - wfi->primary = wf_image_new(wfi, wfi->width, wfi->height, wfi->dstBpp, NULL); - - if (same) - wfi->drawing = wfi->primary; - } - if (wfi->fullscreen != TRUE) - { - if (wfi->hwnd) - SetWindowPos(wfi->hwnd, HWND_TOP, -1, -1, wfi->width + wfi->diff.x, wfi->height + wfi->diff.y, SWP_NOMOVE); - } - else - { - wf_update_offset(wfi); - GetWindowRect(wfi->hwnd, &rect); - InvalidateRect(wfi->hwnd, &rect, TRUE); - } -} - -BOOL wf_pre_connect(freerdp* instance) -{ - int i1; - wfInfo* wfi; - rdpFile* file; - wfContext* context; - rdpSettings* settings; - - wfi = (wfInfo*) malloc(sizeof(wfInfo)); - ZeroMemory(wfi, sizeof(wfInfo)); - - context = (wfContext*) instance->context; - wfi->instance = instance; - context->wfi = wfi; - - settings = instance->settings; - - settings = instance->settings; - - if (settings->ConnectionFile) - { - file = freerdp_client_rdp_file_new(); - - printf("Using connection file: %s\n", settings->ConnectionFile); - - freerdp_client_parse_rdp_file(file, settings->ConnectionFile); - freerdp_client_populate_settings_from_rdp_file(file, settings); - - freerdp_client_rdp_file_free(file); - } - - settings->OsMajorType = OSMAJORTYPE_WINDOWS; - settings->OsMinorType = OSMINORTYPE_WINDOWS_NT; - 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] = TRUE; - settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE; - settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; - settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = FALSE; - settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE; - settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE; - 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; - - settings->GlyphSupportLevel = GLYPH_SUPPORT_NONE; - - wfi->cursor = g_default_cursor; - - wfi->fullscreen = settings->Fullscreen; - wfi->fs_toggle = 1; - wfi->sw_gdi = settings->SoftwareGdi; - - wfi->clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); - ZeroMemory(wfi->clrconv, sizeof(CLRCONV)); - - wfi->clrconv->palette = NULL; - wfi->clrconv->alpha = FALSE; - - instance->context->cache = cache_new(settings); - - if (wfi->percentscreen > 0) - { - i1 = (GetSystemMetrics(SM_CXSCREEN) * wfi->percentscreen) / 100; - settings->DesktopWidth = i1; - - i1 = (GetSystemMetrics(SM_CYSCREEN) * wfi->percentscreen) / 100; - settings->DesktopHeight = i1; - } - - if (wfi->fullscreen) - { - settings->DesktopWidth = GetSystemMetrics(SM_CXSCREEN); - settings->DesktopHeight = GetSystemMetrics(SM_CYSCREEN); - } - - i1 = settings->DesktopWidth; - i1 = (i1 + 3) & (~3); - settings->DesktopWidth = i1; - - if ((settings->DesktopWidth < 64) || (settings->DesktopHeight < 64) || - (settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096)) - { - printf("wf_pre_connect: invalid dimensions %d %d\n", settings->DesktopWidth, settings->DesktopHeight); - return 1; - } - - settings->KeyboardLayout = (int) GetKeyboardLayout(0) & 0x0000FFFF; - freerdp_channels_pre_connect(instance->context->channels, instance); - - return TRUE; -} - -BOOL wf_post_connect(freerdp* instance) -{ - rdpGdi* gdi; - wfInfo* wfi; - rdpCache* cache; - wfContext* context; - wchar_t win_title[64]; - rdpSettings* settings; - - settings = instance->settings; - context = (wfContext*) instance->context; - cache = instance->context->cache; - wfi = context->wfi; - - wfi->dstBpp = 32; - wfi->width = settings->DesktopWidth; - wfi->height = settings->DesktopHeight; - - if (wfi->sw_gdi) - { - gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_32BPP, NULL); - gdi = instance->context->gdi; - wfi->hdc = gdi->primary->hdc; - wfi->primary = wf_image_new(wfi, wfi->width, wfi->height, wfi->dstBpp, gdi->primary_buffer); - } - else - { - wf_gdi_register_update_callbacks(instance->update); - wfi->srcBpp = instance->settings->ColorDepth; - wfi->primary = wf_image_new(wfi, wfi->width, wfi->height, wfi->dstBpp, NULL); - - wfi->hdc = gdi_GetDC(); - wfi->hdc->bitsPerPixel = wfi->dstBpp; - wfi->hdc->bytesPerPixel = wfi->dstBpp / 8; - - wfi->hdc->alpha = wfi->clrconv->alpha; - wfi->hdc->invert = wfi->clrconv->invert; - - wfi->hdc->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND)); - wfi->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0); - wfi->hdc->hwnd->invalid->null = 1; - - wfi->hdc->hwnd->count = 32; - wfi->hdc->hwnd->cinvalid = (HGDI_RGN) malloc(sizeof(GDI_RGN) * wfi->hdc->hwnd->count); - wfi->hdc->hwnd->ninvalid = 0; - - if (settings->RemoteFxCodec) - { - wfi->tile = wf_image_new(wfi, 64, 64, 32, NULL); - wfi->rfx_context = rfx_context_new(); - } - - if (settings->NSCodec) - wfi->nsc_context = nsc_context_new(); - } - - if (settings->WindowTitle != NULL) - _snwprintf(win_title, ARRAYSIZE(win_title), L"%S", settings->WindowTitle); - else if (settings->ServerPort == 3389) - _snwprintf(win_title, ARRAYSIZE(win_title), L"FreeRDP: %S", settings->ServerHostname); - else - _snwprintf(win_title, ARRAYSIZE(win_title), L"FreeRDP: %S:%d", settings->ServerHostname, settings->ServerPort); - - if (wfi->hwnd == 0) - { - wfi->hwnd = CreateWindowEx((DWORD) NULL, g_wnd_class_name, win_title, - 0, 0, 0, 0, 0, NULL, NULL, g_hInstance, NULL); - - SetWindowLongPtr(wfi->hwnd, GWLP_USERDATA, (LONG_PTR) wfi); - } - - wf_resize_window(wfi); - - BitBlt(wfi->primary->hdc, 0, 0, wfi->width, wfi->height, NULL, 0, 0, BLACKNESS); - wfi->drawing = wfi->primary; - - ShowWindow(wfi->hwnd, SW_SHOWNORMAL); - UpdateWindow(wfi->hwnd); - - if (wfi->sw_gdi) - { - instance->update->BeginPaint = wf_sw_begin_paint; - instance->update->EndPaint = wf_sw_end_paint; - instance->update->DesktopResize = wf_sw_desktop_resize; - } - else - { - instance->update->BeginPaint = wf_hw_begin_paint; - instance->update->EndPaint = wf_hw_end_paint; - instance->update->DesktopResize = wf_hw_desktop_resize; - } - - pointer_cache_register_callbacks(instance->update); - - if (wfi->sw_gdi != TRUE) - { - brush_cache_register_callbacks(instance->update); - bitmap_cache_register_callbacks(instance->update); - offscreen_cache_register_callbacks(instance->update); - } - - wf_register_graphics(instance->context->graphics); - - freerdp_channels_post_connect(instance->context->channels, instance); - - wf_cliprdr_init(wfi, instance->context->channels); - - return TRUE; -} - -static const char wfTargetName[] = "TARGET"; - -static CREDUI_INFOA wfUiInfo = -{ - sizeof(CREDUI_INFOA), - NULL, - "Enter your credentials", - "Remote Desktop Security", - NULL -}; - -BOOL wf_authenticate(freerdp* instance, char** username, char** password, char** domain) -{ - BOOL fSave; - DWORD status; - DWORD dwFlags; - char UserName[CREDUI_MAX_USERNAME_LENGTH + 1]; - char Password[CREDUI_MAX_PASSWORD_LENGTH + 1]; - char User[CREDUI_MAX_USERNAME_LENGTH + 1]; - char Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1]; - - fSave = FALSE; - ZeroMemory(UserName, sizeof(UserName)); - ZeroMemory(Password, sizeof(Password)); - dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES; - - status = CredUIPromptForCredentialsA(&wfUiInfo, wfTargetName, NULL, 0, - UserName, CREDUI_MAX_USERNAME_LENGTH + 1, - Password, CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags); - - if (status != NO_ERROR) - { - printf("CredUIPromptForCredentials unexpected status: 0x%08X\n", status); - return FALSE; - } - - ZeroMemory(User, sizeof(User)); - ZeroMemory(Domain, sizeof(Domain)); - - status = CredUIParseUserNameA(UserName, User, sizeof(User), Domain, sizeof(Domain)); - - //printf("User: %s Domain: %s Password: %s\n", User, Domain, Password); - - *username = _strdup(User); - - if (strlen(Domain) > 0) - *domain = _strdup(Domain); - - *password = _strdup(Password); - - return TRUE; -} - -BOOL wf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) -{ -#if 0 - DWORD mode; - int read_size; - DWORD read_count; - TCHAR answer[2]; - TCHAR* read_buffer; - HANDLE input_handle; -#endif - - printf("Certificate details:\n"); - printf("\tSubject: %s\n", subject); - printf("\tIssuer: %s\n", issuer); - printf("\tThumbprint: %s\n", fingerprint); - printf("The above X.509 certificate could not be verified, possibly because you do not have " - "the CA certificate in your certificate store, or the certificate has expired. " - "Please look at the documentation on how to create local certificate store for a private CA.\n"); - - /* TODO: ask for user validation */ -#if 0 - input_handle = GetStdHandle(STD_INPUT_HANDLE); - - GetConsoleMode(input_handle, &mode); - mode |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT; - SetConsoleMode(input_handle, mode); -#endif - - return TRUE; -} - -int wf_receive_channel_data(freerdp* instance, int channelId, BYTE* data, int size, int flags, int total_size) -{ - return freerdp_channels_data(instance, channelId, data, size, flags, total_size); -} - -void wf_process_channel_event(rdpChannels* channels, freerdp* instance) -{ - RDP_EVENT* event; - - event = freerdp_channels_pop_event(channels); - - if (event) - freerdp_event_free(event); -} - -BOOL wf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount) -{ - return TRUE; -} - -BOOL wf_check_fds(freerdp* instance) -{ - return TRUE; -} - -int wfreerdp_run(freerdp* instance) -{ - MSG msg; - int index; - int rcount; - int wcount; - BOOL msg_ret; - int quit_msg; - void* rfds[32]; - void* wfds[32]; - int fds_count; - HANDLE fds[64]; - rdpChannels* channels; - - memset(rfds, 0, sizeof(rfds)); - memset(wfds, 0, sizeof(wfds)); - - if (freerdp_connect(instance) != TRUE) - return 0; - - channels = instance->context->channels; - - while (1) - { - rcount = 0; - wcount = 0; - - if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) - { - printf("Failed to get FreeRDP file descriptor\n"); - break; - } - if (wf_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) - { - printf("Failed to get wfreerdp file descriptor\n"); - break; - } - if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) - { - printf("Failed to get channel manager file descriptor\n"); - break; - } - - fds_count = 0; - /* setup read fds */ - for (index = 0; index < rcount; index++) - { - fds[fds_count++] = rfds[index]; - } - /* setup write fds */ - for (index = 0; index < wcount; index++) - { - fds[fds_count++] = wfds[index]; - } - /* exit if nothing to do */ - if (fds_count == 0) - { - printf("wfreerdp_run: fds_count is zero\n"); - break; - } - - /* do the wait */ - if (MsgWaitForMultipleObjects(fds_count, fds, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED) - { - printf("wfreerdp_run: WaitForMultipleObjects failed: 0x%04X\n", GetLastError()); - break; - } - - if (freerdp_check_fds(instance) != TRUE) - { - printf("Failed to check FreeRDP file descriptor\n"); - break; - } - if (freerdp_shall_disconnect(instance)) - { - break; - } - if (wf_check_fds(instance) != TRUE) - { - printf("Failed to check wfreerdp file descriptor\n"); - break; - } - if (freerdp_channels_check_fds(channels, instance) != TRUE) - { - printf("Failed to check channel manager file descriptor\n"); - break; - } - wf_process_channel_event(channels, instance); - - quit_msg = FALSE; - while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) - { - msg_ret = GetMessage(&msg, NULL, 0, 0); - - if (msg_ret == 0 || msg_ret == -1) - { - quit_msg = TRUE; - break; - } - - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - if (quit_msg) - break; - } - - /* cleanup */ - - freerdp_channels_close(channels, instance); - freerdp_disconnect(instance); - - return 0; -} - -static DWORD WINAPI thread_func(LPVOID lpParam) -{ - wfInfo* wfi; - freerdp* instance; - thread_data* data; - - data = (thread_data*) lpParam; - instance = data->instance; - - wfi = (wfInfo*) malloc(sizeof(wfInfo)); - ZeroMemory(wfi, sizeof(wfInfo)); - - ((wfContext*) instance->context)->wfi = wfi; - wfi->instance = instance; - - wfreerdp_run(instance); - - g_thread_count--; - - if (g_thread_count < 1) - SetEvent(g_done_event); - - return (DWORD) NULL; -} - -static DWORD WINAPI kbd_thread_func(LPVOID lpParam) -{ - MSG msg; - BOOL status; - HHOOK hook_handle; - - hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, wf_ll_kbd_proc, g_hInstance, 0); - - if (hook_handle) - { - while ((status = GetMessage( &msg, NULL, 0, 0 )) != 0) - { - if (status == -1) - { - printf("keyboard thread error getting message\n"); - break; - } - else - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - UnhookWindowsHookEx(hook_handle); - } - else - printf("failed to install keyboard hook\n"); - - return (DWORD) NULL; -} - - INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { freerdp* instance; - thread_data* data; WSADATA wsa_data; WNDCLASSEX wnd_cls; - if (NULL == getenv("HOME")) + if (!getenv("HOME")) { char home[MAX_PATH * 2] = "HOME="; strcat(home, getenv("HOMEDRIVE")); @@ -763,11 +110,6 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine { int status; - data = (thread_data*) malloc(sizeof(thread_data)); - ZeroMemory(data, sizeof(thread_data)); - - data->instance = instance; - freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); status = freerdp_client_parse_command_line_arguments(__argc, __argv, instance->settings); @@ -783,16 +125,20 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine exit(-1); } - if (CreateThread(NULL, 0, thread_func, data, 0, NULL) != 0) + if (CreateThread(NULL, 0, thread_func, instance, 0, NULL) != 0) g_thread_count++; } if (g_thread_count > 0) + { WaitForSingleObject(g_done_event, INFINITE); + } else + { MessageBox(GetConsoleWindow(), L"Failed to start wfreerdp.\n\nPlease check the debug output.", L"FreeRDP Error", MB_ICONSTOP); + } freerdp_context_free(instance); freerdp_free(instance);