From 930d67ef22aad543870484359cce4bc653d9ee8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 9 Apr 2013 21:19:03 -0400 Subject: [PATCH 01/14] afreerdp: initial French translation (semi-automatic, still poor) --- .../FreeRDPCore/res/values-fr/strings.xml | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 client/Android/FreeRDPCore/res/values-fr/strings.xml diff --git a/client/Android/FreeRDPCore/res/values-fr/strings.xml b/client/Android/FreeRDPCore/res/values-fr/strings.xml new file mode 100644 index 000000000..ef37c104c --- /dev/null +++ b/client/Android/FreeRDPCore/res/values-fr/strings.xml @@ -0,0 +1,174 @@ + + + "Oui" + "Non" + "Annuler" + "Continuer" + "Se connecter" + "Déconnexion" + + "Quitter" + "À propos" + "Aide" + "Nouvelle connexion" + "Paramètres" + + "Connexion" + "Connexion" + "Éditer" + "Supprimer" + + "Clavier" + "Touches de fonction" + "Pointeur tactile" + "Accueil" + "Se déconnecter" + + "Connexions manuelles" + "Sessions actives" + + "Connexion à l'ordinateur" + + "Se connecter" + "Pas de serveurs" + "Connexion..." + "Déconnexion…" + "Perte de la connexion" + "Mot de passe incorrect" + "Nom d'utilisateur invalide" + "Ajouter une connexion" + + "Hôte" + "Étiquette" + "Hôte" + "Port" + "Authentifiant" + "Authentifiant" + "Nom d'utilisateur" + "Mot de passe" + "Domaine" + "Paramètres" + "Écran" + "Paramètres d'écran" + "Couleurs" + + "Hautes couleurs (16 bits)" + "Couleurs vraies (24 bits)" + "Haute qualité (32 bits)" + + + "16" + "24" + "32" + + "Résolution" + "Automatique" + "Personalisé" + + "Automatique" + "Personalisé" + "640x480" + "720x480" + "800x600" + "1024 x 768" + "1280x1024" + "1440x900" + "1920x1080" + "1920x1200" + + + "Automatique" + "Personalisé" + "640x480" + "720x480" + "800x600" + "1024 x 768" + "1280x1024" + "1440x900" + "1920x1080" + "1920x1200" + + "Largeur" + "Hauteur" + "Performance" + "Paramètres de performance" + "RemoteFX" + "Fond d'écran" + "Lissage de polices" + "Compositeur du bureau" + "Contenu de la fenêtre tout en faisant glisser" + "Animations de menu" + "Styles visuels" + "Avancé" + "Paramètres avancés" + "Réglages 3G" + "Écran 3G" + "Performance 3G" + "Securité" + + "Automatique" + "RDP" + "TLS" + "NLA" + + + "0" + "1" + "2" + "3" + + "Programme à distance" + "Répertoire de travail" + "Mode console" + + "*******" + "Valeur non définie" + "Interface utilisateur" + "Masquer la barre d'état" + "Masquer les contrôles zoom" + "Inverser les boutons de la souris" + "Inverser le défilement de la souris" + "Défilement automatique du pointeur tactile" + "Confirmer au moment de quitter" + "Economie d'énergie" + "Fermer les connexions inactives" + "Securité" + "Accepter tous les certificats" + "Vider la cache de certificats" + "Après %1$d minutes" + "Désactivé" + + "Paramètres de connexion" + "Paramètres" + "aFreeRDP - FreeRDP pour Android" + "Connexions RDP" + "Aide" + "À propos" + + "Annuler sans enregistrer?" + "Appuyez sur \"Annuler\" pour abandonner! \ NCliquez sur «Continuer» pour spécifier les champs obligatoires!" + "Impossible d'établir une connexion au serveur!" + + "Les paramètres de l'écran ont changé parce que le serveur ne prend pas en charge les paramètres que vous avez spécifiés!" + "La cache de certificats a été supprimée!" + "Impossible de supprimer la cache de certificat!" + + "Validation de certificat" + "L'identité de l'ordinateur distant ne peut pas être vérifiée. Voulez-vous poursuivre la connexion?" + "Veuillez entrer votre nom d'usager et mot de passe" + "Créer un raccourci" + "Nom du raccourci:" + "Connexion..." + "Connexion..." + "À propos de aFreeRDP" + "Version: %1$s \ n \ u00A9 2012 Technologies GmbH Thinstuff" + "Enregistrer les paramètres de connexion?" + "Vos paramètres de connexion n'ont pas été sauvegardés! Voulez-vous les enregistrer?" + "Enregistrer la connexion?" + "Voulez-vous enregistrer les modifications que vous avez apportées aux paramètres de connexion?" + "Ne plus demander" + "Quittez l'application?" + "Êtes-vous sûr de vouloir quitter l'application?" + "Êtes-vous sûrs de vouloir supprimer les certificats?" + "Êtes-vous sûr de vouloir supprimer tous les certificats mis en cache?" + \ No newline at end of file From 953716e907754ec6a8977eca65e9fa2701650686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 9 Apr 2013 21:51:07 -0400 Subject: [PATCH 02/14] afreerdp: fix missing translation points --- .../FreeRDPCore/res/values-fr/strings.xml | 22 +++++++++---------- .../res/xml/application_settings.xml | 1 - .../FreeRDPCore/res/xml/bookmark_settings.xml | 2 +- .../res/xml/credentials_settings.xml | 6 ++--- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/client/Android/FreeRDPCore/res/values-fr/strings.xml b/client/Android/FreeRDPCore/res/values-fr/strings.xml index ef37c104c..95f3d6490 100644 --- a/client/Android/FreeRDPCore/res/values-fr/strings.xml +++ b/client/Android/FreeRDPCore/res/values-fr/strings.xml @@ -30,7 +30,7 @@ "Connexion à l'ordinateur" "Se connecter" - "Pas de serveurs" + "Pas de connexion" "Connexion..." "Déconnexion…" "Perte de la connexion" @@ -46,7 +46,7 @@ "Authentifiant" "Nom d'utilisateur" "Mot de passe" - "Domaine" + "Nom de domaine" "Paramètres" "Écran" "Paramètres d'écran" @@ -70,7 +70,7 @@ "640x480" "720x480" "800x600" - "1024 x 768" + "1024x768" "1280x1024" "1440x900" "1920x1080" @@ -82,7 +82,7 @@ "640x480" "720x480" "800x600" - "1024 x 768" + "1024x768" "1280x1024" "1440x900" "1920x1080" @@ -94,14 +94,14 @@ "Paramètres de performance" "RemoteFX" "Fond d'écran" - "Lissage de polices" - "Compositeur du bureau" - "Contenu de la fenêtre tout en faisant glisser" + "Lissage des polices" + "Effets visuels Aero" + "Afficher le contenu des fenêtres en mouvement" "Animations de menu" "Styles visuels" "Avancé" "Paramètres avancés" - "Réglages 3G" + "Paramètres 3G" "Écran 3G" "Performance 3G" "Securité" @@ -117,7 +117,7 @@ "2" "3" - "Programme à distance" + "Lancement de programme" "Répertoire de travail" "Mode console" @@ -146,7 +146,7 @@ "À propos" "Annuler sans enregistrer?" - "Appuyez sur \"Annuler\" pour abandonner! \ NCliquez sur «Continuer» pour spécifier les champs obligatoires!" + "Appuyez sur \"Annuler\" pour annuler, ou cliquez sur «Continuer» pour spécifier les champs obligatoires." "Impossible d'établir une connexion au serveur!" "Les paramètres de l'écran ont changé parce que le serveur ne prend pas en charge les paramètres que vous avez spécifiés!" @@ -171,4 +171,4 @@ "Êtes-vous sûr de vouloir quitter l'application?" "Êtes-vous sûrs de vouloir supprimer les certificats?" "Êtes-vous sûr de vouloir supprimer tous les certificats mis en cache?" - \ No newline at end of file + diff --git a/client/Android/FreeRDPCore/res/xml/application_settings.xml b/client/Android/FreeRDPCore/res/xml/application_settings.xml index 9d7cc0a67..0df4ea126 100644 --- a/client/Android/FreeRDPCore/res/xml/application_settings.xml +++ b/client/Android/FreeRDPCore/res/xml/application_settings.xml @@ -29,5 +29,4 @@ - diff --git a/client/Android/FreeRDPCore/res/xml/bookmark_settings.xml b/client/Android/FreeRDPCore/res/xml/bookmark_settings.xml index c49d4272a..0564537d7 100644 --- a/client/Android/FreeRDPCore/res/xml/bookmark_settings.xml +++ b/client/Android/FreeRDPCore/res/xml/bookmark_settings.xml @@ -12,7 +12,7 @@ - + diff --git a/client/Android/FreeRDPCore/res/xml/credentials_settings.xml b/client/Android/FreeRDPCore/res/xml/credentials_settings.xml index 0247b66cd..a27be58c1 100644 --- a/client/Android/FreeRDPCore/res/xml/credentials_settings.xml +++ b/client/Android/FreeRDPCore/res/xml/credentials_settings.xml @@ -11,8 +11,8 @@ --> - - - + + + From e1e8194f770b4036ac1f453f47cbc5b087e86282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 10 Apr 2013 13:45:23 -0400 Subject: [PATCH 03/14] afreerdp: added Spanish translation --- .../FreeRDPCore/res/values-es/strings.xml | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 client/Android/FreeRDPCore/res/values-es/strings.xml diff --git a/client/Android/FreeRDPCore/res/values-es/strings.xml b/client/Android/FreeRDPCore/res/values-es/strings.xml new file mode 100644 index 000000000..2f9d36d8e --- /dev/null +++ b/client/Android/FreeRDPCore/res/values-es/strings.xml @@ -0,0 +1,175 @@ + + + + Si + No + Cancelar + Continuar + Ingresar + Salir + + Salida + Sobre + Ayuda + Nueva conexión + Configuracion + + Conexión + Conectar + Editar + Borrar + + Teclado + Funcion teclado + Puntero Tactil + Inicio + desconectart + + Conexión Manual + Sesiones Activas + + Connectarse a iWinCloud + + Login + No hay escritorios virtuales + Conectando ... + Desconectando ... + Conexión perdida + Contraseña equivocada + Usuario Invalido + Agregar escritorio virtual de iWinCloud + + Host + Su nombre + IP + Puerto + Credenciales de iWinCloud + Credenciales + Usuario + Contraseña + Dominio + Configuracion + Pantalla + Configuracion Pantalla + Colores + + Calidad Normal (16 Bit) + Calidad Optima (24 Bit) + Calidad maxima (32 Bit) + + + 16 + 24 + 32 + + Resolucion + Automatico + Manual + + Automatico + Manual + 640x480 + 720x480 + 800x600 + 1024x768 + 1280x1024 + 1440x900 + 1920x1080 + 1920x1200 + + + automatico + manual + 640x480 + 720x480 + 800x600 + 1024x768 + 1280x1024 + 1440x900 + 1920x1080 + 1920x1200 + + Ancho + Altura + Rendimiento + Configuracion Rendimiento + RemoteFX + Fondo escritorio + Fuente suave + Composicion escritorio + Contenidos de la ventana mientras se arrastra + Animacion del menu + Estilo visual + Avanzado + Configuracion Avanzada + Configuracion 3G + Pantalla 3G + Rendimiento 3G + Seguridad + + Automatico + RDP + TLS + NLA + + + 0 + 1 + 2 + 3 + + Programa Remoto + Directorio de trabajo + Modo Consola + + ******* + no configurado + Interfaze Usuario + Ocultar barra de estado + Ocultar controles de zoom + Intercambiar botones del mouse + invertir desplazamiento + Puntero táctil de desplazamiento automático + Mostrar cuadro de diálogo en la salida + Ahorro de energía + Cerrar las conexiones inactivas + Seguridad + Aceptar todos los certificados + Borrar el Cache de los certificados + Despues %1$d Minutos + Desabilitado + + Configuración de la conexión + Configuración + iWinCloud - iWinCloud para Android + Conexiones RDP + Ayuda + Sobre + + Cancelar sin guardar? + Pulse el botón "Cancelar" para abortar! \ NPulse "Continuar" para especificar los campos obligatorios! + No se pudo establecer una conexión con iWinCloud! + + Los ajustes de pantalla se han cambiado porque el escritorio virtual no es compatible con la configuración especificada! + Eliminado el cache del certificado! + No se pudo borrar el caché del certificado! + + verificar el certificado + La identidad de su escritorio de iWinCloud debe ser verificada. ¿Desea conectarse de todos modos? + Por favor, introduzca sus credenciales + Crear acceso directo + Nombre corto: + Conectando ... + Ingresando a ... + Sobre iWinCloud + Version: %1$s\n\u00A9 2012 iWinCloud LLc + Guardar configuración de conexión? + La configuración de conexión no se han guardado! ¿Quieres guardarlos? + Guardar Conexión + ¿Desea guardar los cambios realizados en la configuración de conexión? + No volver a preguntar + Salir del programa? + Esta seguro que desea salir del programa? + Borrar Certificados? + Esta seguro que desea borrar todos los certificados? + From bb733db683104e6836e05f623b628f8f0962051d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 10 Apr 2013 16:58:14 -0400 Subject: [PATCH 04/14] wfreerdp: integrating benoit's latest code --- client/Windows/wf_event.c | 78 +++++++++++++++++++++++++++---- client/Windows/wf_gdi.c | 42 ++++++++++++++++- client/Windows/wf_interface.c | 87 +++++++++++++++++++++++++++-------- client/Windows/wf_interface.h | 9 ++++ client/common/cmdline.c | 5 ++ include/freerdp/settings.h | 10 +++- 6 files changed, 200 insertions(+), 31 deletions(-) diff --git a/client/Windows/wf_event.c b/client/Windows/wf_event.c index a81c9f1ae..c96897fb5 100644 --- a/client/Windows/wf_event.c +++ b/client/Windows/wf_event.c @@ -37,6 +37,9 @@ static HWND g_focus_hWnd; #define X_POS(lParam) (lParam & 0xFFFF) #define Y_POS(lParam) ((lParam >> 16) & 0xFFFF) +BOOL wf_scale_blt(wfInfo* wfi, HDC hdc, int x, int y, int w, int h, HDC hdcSrc, int x1, int y1, DWORD rop); +void wf_scale_mouse_event(wfInfo* wfi, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); + LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam) { wfInfo* wfi; @@ -167,6 +170,10 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam switch (Msg) { + case WM_ERASEBKGND: + /* Say we handled it - prevents flickering */ + return (LRESULT) 1; + case WM_PAINT: hdc = BeginPaint(hWnd, &ps); @@ -175,31 +182,29 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam w = ps.rcPaint.right - ps.rcPaint.left + 1; h = ps.rcPaint.bottom - ps.rcPaint.top + 1; - //fprintf(stderr, "WM_PAINT: x:%d y:%d w:%d h:%d\n", x, y, w, h); - - BitBlt(hdc, x, y, w, h, wfi->primary->hdc, x - wfi->offset_x, y - wfi->offset_y, SRCCOPY); + wf_scale_blt(wfi, hdc, x, y, w, h, wfi->primary->hdc, x - wfi->offset_x, y - wfi->offset_y, SRCCOPY); EndPaint(hWnd, &ps); break; case WM_LBUTTONDOWN: - input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); + wf_scale_mouse_event(wfi, input,PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); break; case WM_LBUTTONUP: - input->MouseEvent(input, PTR_FLAGS_BUTTON1, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); + wf_scale_mouse_event(wfi, input, PTR_FLAGS_BUTTON1, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); break; case WM_RBUTTONDOWN: - input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); + wf_scale_mouse_event(wfi, input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); break; case WM_RBUTTONUP: - input->MouseEvent(input, PTR_FLAGS_BUTTON2, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); + wf_scale_mouse_event(wfi, input, PTR_FLAGS_BUTTON2, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); break; case WM_MOUSEMOVE: - input->MouseEvent(input, PTR_FLAGS_MOVE, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); + wf_scale_mouse_event(wfi, input, PTR_FLAGS_MOVE, X_POS(lParam) - wfi->offset_x, Y_POS(lParam) - wfi->offset_y); break; case WM_MOUSEWHEEL: @@ -257,3 +262,60 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam return 0; } + +BOOL wf_scale_blt(wfInfo* wfi, HDC hdc, int x, int y, int w, int h, HDC hdcSrc, int x1, int y1, DWORD rop) +{ + int ww, wh, dw, dh; + + if (!wfi->client_width) + wfi->client_width = wfi->width; + + if (!wfi->client_height) + wfi->client_height = wfi->height; + + ww = wfi->client_width; + wh = wfi->client_height; + dw = wfi->instance->settings->DesktopWidth; + dh = wfi->instance->settings->DesktopHeight; + + if (!ww) + ww = dw; + + if (!wh) + wh = dh; + + if (!wfi->instance->settings->SmartSizing || (ww == dw && wh == dh)) + { + return BitBlt(hdc, x, y, w, h, wfi->primary->hdc, x1, y1, SRCCOPY); + } + else + { + SetStretchBltMode(hdc, HALFTONE); + SetBrushOrgEx(hdc, 0, 0, NULL); + + return StretchBlt(hdc, x * ww / dw, y * wh / dh, ww, wh, wfi->primary->hdc, x1, y1, dw, dh, SRCCOPY); + } + + return TRUE; +} + +void wf_scale_mouse_event(wfInfo* wfi, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +{ + int ww, wh, dw, dh; + + if (!wfi->client_width) + wfi->client_width = wfi->width; + + if (!wfi->client_height) + wfi->client_height = wfi->height; + + ww = wfi->client_width; + wh = wfi->client_height; + dw = wfi->instance->settings->DesktopWidth; + dh = wfi->instance->settings->DesktopHeight; + + if ((ww == dw) && (wh == dh)) + input->MouseEvent(input, flags, x, y); + else + input->MouseEvent(input, flags, x * dw / ww, y * dh / wh); +} diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index 39c590f1c..3a15fe26a 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -166,14 +166,54 @@ HBRUSH wf_create_brush(wfInfo * wfi, rdpBrush* brush, UINT32 color, int bpp) return br; } +void wf_scale_rect(wfInfo* wfi, RECT* source) +{ + int ww, wh, dw, dh; + + if (!wfi->client_width) + wfi->client_width = wfi->width; + + if (!wfi->client_height) + wfi->client_height = wfi->height; + + ww = wfi->client_width; + wh = wfi->client_height; + dw = wfi->instance->settings->DesktopWidth; + dh = wfi->instance->settings->DesktopHeight; + + if (!ww) + ww = dw; + + if (!wh) + wh = dh; + + if (wfi->instance->settings->SmartSizing && (ww != dw || wh != dh)) + { + source->bottom = MIN(dh, MAX(0, source->bottom * wh / dh + 2)); + source->top = MIN(dh, MAX(0, source->top * wh / dh - 2)); + source->left = MIN(dw, MAX(0, source->left * ww / dw - 2)); + source->right = MIN(dw, MAX(0, source->right * ww / dw + 2)); + } +} + void wf_invalidate_region(wfInfo* wfi, int x, int y, int width, int height) { + RECT rect; + wfi->update_rect.left = x + wfi->offset_x; wfi->update_rect.top = y + wfi->offset_y; wfi->update_rect.right = wfi->update_rect.left + width; wfi->update_rect.bottom = wfi->update_rect.top + height; + + wf_scale_rect(wfi, &(wfi->update_rect)); InvalidateRect(wfi->hwnd, &(wfi->update_rect), FALSE); - gdi_InvalidateRegion(wfi->hdc, x, y, width, height); + + rect.left = x; + rect.right = width; + rect.top = y; + rect.bottom = height; + wf_scale_rect(wfi, &rect); + gdi_InvalidateRegion(wfi->hdc, rect.left, rect.top, rect.right, rect.bottom); } void wf_update_offset(wfInfo* wfi) diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index 055f93591..09c465e88 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -534,6 +534,8 @@ DWORD WINAPI wf_thread(LPVOID lpParam) int index; int rcount; int wcount; + int width; + int height; BOOL msg_ret; int quit_msg; void* rfds[32]; @@ -626,7 +628,30 @@ DWORD WINAPI wf_thread(LPVOID lpParam) { msg_ret = GetMessage(&msg, NULL, 0, 0); - if (msg_ret == 0 || msg_ret == -1) + if (instance->settings->EmbeddedWindow) + { + if ((msg.message == WM_SETFOCUS) && (msg.lParam == 1)) + { + PostMessage(((wfContext*) instance->context)->wfi->hwnd, WM_SETFOCUS, 0, 0); + } + else if ((msg.message == WM_KILLFOCUS) && (msg.lParam == 1)) + { + PostMessage(((wfContext*) instance->context)->wfi->hwnd, WM_KILLFOCUS, 0, 0); + } + } + + if (msg.message == WM_SIZE) + { + width = LOWORD(msg.lParam); + height = HIWORD(msg.lParam); + + ((wfContext*) instance->context)->wfi->client_width = width; + ((wfContext*) instance->context)->wfi->client_height = height; + + SetWindowPos(((wfContext*) instance->context)->wfi->hwnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED); + } + + if ((msg_ret == 0) || (msg_ret == -1)) { quit_msg = TRUE; break; @@ -721,11 +746,9 @@ int freerdp_client_global_uninit() wfInfo* freerdp_client_new(int argc, char** argv) { int index; + int status; wfInfo* wfi; freerdp* instance; - HINSTANCE hInstance; - - hInstance = GetModuleHandle(NULL); instance = freerdp_new(); instance->PreConnect = wf_pre_connect; @@ -745,16 +768,27 @@ wfInfo* freerdp_client_new(int argc, char** argv) wfi->client = instance->context->client; instance->context->argc = argc; - instance->context->argv = argv; - instance->context->argv = (char**) malloc(sizeof(char*) * argc); for (index = 0; index < argc; index++) - { instance->context->argv[index] = _strdup(argv[index]); - } - wfi->hWndParent = NULL; + status = freerdp_client_parse_command_line_arguments(instance->context->argc, instance->context->argv, instance->settings); + + return wfi; +} + +int freerdp_client_start(wfInfo* wfi) +{ + HWND hWndParent; + HINSTANCE hInstance; + freerdp* instance = wfi->instance; + + hInstance = GetModuleHandle(NULL); + hWndParent = (HWND) instance->settings->ParentWindowId; + instance->settings->EmbeddedWindow = (hWndParent) ? TRUE : FALSE; + + wfi->hWndParent = hWndParent; wfi->hInstance = hInstance; wfi->cursor = LoadCursor(NULL, IDC_ARROW); wfi->icon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1)); @@ -774,24 +808,14 @@ wfInfo* freerdp_client_new(int argc, char** argv) wfi->wndClass.hIconSm = wfi->icon; RegisterClassEx(&(wfi->wndClass)); - return wfi; -} - -int freerdp_client_start(wfInfo* wfi) -{ - int status; - freerdp* instance = wfi->instance; - wfi->keyboardThread = CreateThread(NULL, 0, wf_keyboard_thread, (void*) wfi, 0, NULL); if (!wfi->keyboardThread) return -1; - status = freerdp_client_parse_command_line_arguments(instance->context->argc, instance->context->argv, instance->settings); - freerdp_client_load_addins(instance->context->channels, instance->settings); - wfi->thread = CreateThread(NULL, 0, wf_thread, (void*) instance, 0, NULL); + wfi->thread = CreateThread(NULL, 0, wf_thread, (void*) instance, 0, &wfi->mainThreadId); if (!wfi->thread) return -1; @@ -801,6 +825,29 @@ int freerdp_client_start(wfInfo* wfi) int freerdp_client_stop(wfInfo* wfi) { + PostThreadMessage(wfi->mainThreadId, WM_QUIT, 0, 0); + return 0; +} + +int freerdp_client_focus_in(wfInfo* wfi) +{ + PostThreadMessage(wfi->mainThreadId, WM_SETFOCUS, 0, 1); + return 0; +} + +int freerdp_client_focus_out(wfInfo* wfi) +{ + PostThreadMessage(wfi->mainThreadId, WM_KILLFOCUS, 0, 1); + return 0; +} + +int wf_set_window_size(wfInfo* wfi, int width, int height) +{ + if ((width != wfi->client_width) || (height != wfi->client_height)) + { + PostThreadMessage(wfi->mainThreadId, WM_SIZE, SIZE_RESTORED, ((UINT) height << 16) | (UINT) width); + } + return 0; } diff --git a/client/Windows/wf_interface.h b/client/Windows/wf_interface.h index c9f8a3ef3..16891db82 100644 --- a/client/Windows/wf_interface.h +++ b/client/Windows/wf_interface.h @@ -81,6 +81,8 @@ struct wf_info int fullscreen; int percentscreen; char window_title[64]; + int client_width; + int client_height; HANDLE thread; HANDLE keyboardThread; @@ -105,8 +107,10 @@ struct wf_info HBRUSH brush; HBRUSH org_brush; RECT update_rect; + RECT scale_update_rect; wfBitmap* tile; + DWORD mainThreadId; RFX_CONTEXT* rfx_context; NSC_CONTEXT* nsc_context; @@ -125,6 +129,11 @@ FREERDP_API int freerdp_client_global_uninit(); FREERDP_API int freerdp_client_start(wfInfo* cfi); FREERDP_API int freerdp_client_stop(wfInfo* cfi); +FREERDP_API int freerdp_client_focus_in(wfInfo* cfi); +FREERDP_API int freerdp_client_focus_out(wfInfo* cfi); + +FREERDP_API int freerdp_client_set_window_size(wfInfo* cfi, int width, int height); + FREERDP_API cfInfo* freerdp_client_new(int argc, char** argv); FREERDP_API int freerdp_client_free(wfInfo* cfi); diff --git a/client/common/cmdline.c b/client/common/cmdline.c index e2927eb2a..5150a9a01 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -52,6 +52,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "workarea", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Work area" }, { "t", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, "title", "Window title" }, { "decorations", COMMAND_LINE_VALUE_BOOL, NULL, NULL, BoolValueTrue, -1, NULL, "Window decorations" }, + { "smart-sizing", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Scale remote desktop to window size" }, { "a", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, "addin", "Addin" }, { "vc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Static virtual channel" }, { "dvc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Dynamic virtual channel" }, @@ -1090,6 +1091,10 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin { settings->Decorations = arg->Value ? TRUE : FALSE; } + CommandLineSwitchCase(arg, "smart-sizing") + { + settings->SmartSizing = arg->Value ? TRUE : FALSE; + } CommandLineSwitchCase(arg, "bpp") { settings->ColorDepth = atoi(arg->Value); diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 9a3375c47..0a078c280 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -602,7 +602,11 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_AsyncInput 1544 #define FreeRDP_AsyncUpdate 1545 #define FreeRDP_AsyncChannels 1546 -#define FreeRDP_ToggleFullscreen 1547 +#define FreeRDP_AsyncTransport 1547 +#define FreeRDP_ToggleFullscreen 1548 +#define FreeRDP_WmClass 1549 +#define FreeRDP_EmbeddedWindow 1550 +#define FreeRDP_SmartSizing 1551 #define FreeRDP_SoftwareGdi 1601 #define FreeRDP_LocalConnection 1602 #define FreeRDP_AuthenticationOnly 1603 @@ -961,7 +965,9 @@ struct rdp_settings ALIGN64 BOOL AsyncTransport; /* 1547 */ ALIGN64 BOOL ToggleFullscreen; /* 1548 */ ALIGN64 char* WmClass; /* 1549 */ - UINT64 padding1600[1600 - 1550]; /* 1550 */ + ALIGN64 BOOL EmbeddedWindow; /* 1550 */ + ALIGN64 BOOL SmartSizing; /* 1551 */ + UINT64 padding1600[1600 - 1552]; /* 1552 */ /* Miscellaneous */ ALIGN64 BOOL SoftwareGdi; /* 1601 */ From f0a45f96f5e240b4f79b6962ca8934389f3a29f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com> Date: Wed, 10 Apr 2013 17:09:35 -0400 Subject: [PATCH 05/14] client: add CLIENT_INTERFACE_SHARED option forcing shared client libs with BUILD_SHARED_LIBS=off, making a single library --- client/Windows/CMakeLists.txt | 6 +++++- client/X11/CMakeLists.txt | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/client/Windows/CMakeLists.txt b/client/Windows/CMakeLists.txt index 678a9b5a1..0f2b26d65 100644 --- a/client/Windows/CMakeLists.txt +++ b/client/Windows/CMakeLists.txt @@ -37,7 +37,11 @@ set(${MODULE_PREFIX}_SRCS resource.h) if(WITH_CLIENT_INTERFACE) - add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + if(CLIENT_INTERFACE_SHARED) + add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS}) + else() + add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + endif() set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION} PREFIX "lib") else() set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} cli/wfreerdp.c cli/wfreerdp.h) diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index 0461a3550..7d08ea670 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -44,7 +44,11 @@ set(${MODULE_PREFIX}_SRCS xf_interface.h) if(WITH_CLIENT_INTERFACE) - add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + if(CLIENT_INTERFACE_SHARED) + add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS}) + else() + add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + endif() set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION} PREFIX "lib") else() set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} cli/xfreerdp.c cli/xfreerdp.h) From e7436a1a9d6e71233b5509b1b4b2a4056a1da4ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com> Date: Wed, 10 Apr 2013 21:15:38 -0400 Subject: [PATCH 06/14] wfreerdp: minor 64-bit fixes --- CMakeLists.txt | 4 ++++ winpr/libwinpr/interlocked/interlocked.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80531b497..22c361b1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,6 +111,10 @@ if(MSVC) message(STATUS "Random freeing errors are a common sign of runtime issues") endif() configure_msvc_runtime() + + if(NOT DEFINED CMAKE_SUPPRESS_REGENERATION) + set(CMAKE_SUPPRESS_REGENERATION ON) + endif() endif() # Compiler-specific flags diff --git a/winpr/libwinpr/interlocked/interlocked.c b/winpr/libwinpr/interlocked/interlocked.c index 9065376d3..044c36684 100644 --- a/winpr/libwinpr/interlocked/interlocked.c +++ b/winpr/libwinpr/interlocked/interlocked.c @@ -236,7 +236,11 @@ LONG InterlockedCompareExchange(LONG volatile *Destination, LONG Exchange, LONG #endif /* _WIN32 */ -#if (_WIN32 && (_WIN32_WINNT < 0x0502)) +#if defined(_WIN64) + +/* InterlockedCompareExchange64 already defined */ + +#elif (_WIN32 && (_WIN32_WINNT < 0x0502)) static volatile HANDLE mutex = NULL; From d0e989a549f0d05748afda038b0d2c26cab49c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com> Date: Thu, 11 Apr 2013 11:51:10 -0400 Subject: [PATCH 07/14] libfreerdp-core: add support for load balance info --- client/common/cmdline.c | 6 ++++++ client/common/file.c | 6 ++++++ libfreerdp/core/connection.c | 3 +++ libfreerdp/core/nego.c | 8 +++++--- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 5150a9a01..dc5e6a681 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -63,6 +63,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "gu", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Gateway username" }, { "gp", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Gateway password" }, { "gd", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Gateway domain" }, + { "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info string>", NULL, NULL, -1, NULL, "Load balance info" }, { "app", COMMAND_LINE_VALUE_REQUIRED, "||<alias> or <executable path>", NULL, NULL, -1, NULL, "Remote application program" }, { "app-name", COMMAND_LINE_VALUE_REQUIRED, "<app name>", NULL, NULL, -1, NULL, "Remote application name for user interface" }, { "app-icon", COMMAND_LINE_VALUE_REQUIRED, "<icon path>", NULL, NULL, -1, NULL, "Remote application icon for user interface" }, @@ -1214,6 +1215,11 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin settings->DisableWallpaper = TRUE; settings->DisableFullWindowDrag = TRUE; } + CommandLineSwitchCase(arg, "load-balance-info") + { + settings->LoadBalanceInfo = (BYTE*) _strdup(arg->Value); + settings->LoadBalanceInfoLength = strlen((char*) settings->LoadBalanceInfo); + } CommandLineSwitchCase(arg, "app-name") { settings->RemoteApplicationName = _strdup(arg->Value); diff --git a/client/common/file.c b/client/common/file.c index 755aa9391..a90a5fe81 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -517,6 +517,12 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (~((size_t) file->ShellWorkingDirectory)) settings->ShellWorkingDirectory = file->ShellWorkingDirectory; + if (~((size_t) file->LoadBalanceInfo)) + { + settings->LoadBalanceInfo = (BYTE*) _strdup(file->LoadBalanceInfo); + settings->LoadBalanceInfoLength = strlen((char*) settings->LoadBalanceInfo); + } + if (~file->ConnectionType) { freerdp_set_connection_type(settings, file->ConnectionType); diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index dabba597f..4b60d868b 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -135,6 +135,9 @@ BOOL rdp_client_connect(rdpRdp* rdp) nego_set_cookie_max_length(rdp->nego, settings->CookieMaxLength); + if (settings->LoadBalanceInfo) + nego_set_routing_token(rdp->nego, settings->LoadBalanceInfo, settings->LoadBalanceInfoLength); + if (!nego_connect(rdp->nego)) { fprintf(stderr, "Error: protocol security negotiation or connection failure\n"); diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c index 6ee58d9b7..b15730228 100644 --- a/libfreerdp/core/nego.c +++ b/libfreerdp/core/nego.c @@ -648,12 +648,14 @@ BOOL nego_send_negotiation_request(rdpNego* nego) stream_get_mark(s, bm); stream_seek(s, length); - if (nego->RoutingToken != NULL) + if (nego->RoutingToken) { stream_write(s, nego->RoutingToken, nego->RoutingTokenLength); - length += nego->RoutingTokenLength; + stream_write_BYTE(s, 0x0D); /* CR */ + stream_write_BYTE(s, 0x0A); /* LF */ + length += nego->RoutingTokenLength + 2; } - else if (nego->cookie != NULL) + else if (nego->cookie) { cookie_length = strlen(nego->cookie); From 0be8a12d78c954f246c273b4374b4d6521f20e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com> Date: Thu, 11 Apr 2013 16:27:12 -0400 Subject: [PATCH 08/14] winpr: fix string.h for C++ --- winpr/include/winpr/string.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/winpr/include/winpr/string.h b/winpr/include/winpr/string.h index 6bcae3eee..8cb2466f0 100644 --- a/winpr/include/winpr/string.h +++ b/winpr/include/winpr/string.h @@ -25,6 +25,10 @@ #include <winpr/winpr.h> #include <winpr/wtypes.h> +#ifdef __cplusplus +extern "C" { +#endif + #ifndef _WIN32 #define CSTR_LESS_THAN 1 @@ -174,4 +178,8 @@ WINPR_API int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteS WINPR_API int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR* lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar); +#ifdef __cplusplus +} +#endif + #endif /* WINPR_CRT_STRING_H */ From a89c75b3c2417010a9ce670e1e0aa51e200f771d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com> Date: Thu, 11 Apr 2013 18:09:28 -0400 Subject: [PATCH 09/14] mfreerdp: cleanup cmake script --- client/Mac/CMakeLists.txt | 41 +++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt index 2183eb9d2..80b03ca62 100644 --- a/client/Mac/CMakeLists.txt +++ b/client/Mac/CMakeLists.txt @@ -6,12 +6,10 @@ set(MODULE_PREFIX "FREERDP_CLIENT_MAC") set(FRAMEWORK_HEADERS_PATH /System/Library/Frameworks/Cocoa.framework/Versions/A/Headers/) include_directories(${FRAMEWORK_HEADERS_PATH} /System/Library/Frameworks) - -# set(CMAKE_OSX_SYSROOT MacOSX10.7.sdk) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mmacosx-version-min=10.4") set(GUI_TYPE MACOSX_BUNDLE) -# Import libraries find_library(FOUNDATION_LIBRARY Foundation) find_library(COCOA_LIBRARY Cocoa) find_library(APPKIT_LIBRARY AppKit) @@ -33,16 +31,32 @@ mark_as_advanced(COCOA_LIBRARY FOUNDATION_LIBRARY APPKIT_LIBRARY) set(EXTRA_LIBS ${COCOA_LIBRARY} ${FOUNDATION_LIBRARY} ${APPKIT_LIBRARY}) set(APP_TYPE MACOSX_BUNDLE) -# OS X Interface Builder files -file(GLOB ${MODULE_NAME}_XIBS *.xib) +set(${MODULE_NAME}_XIBS + MainMenu.xib + PasswordDialog.xib) -set(${MODULE_NAME}_RESOURCES ${${MODULE_NAME}_XIBS} ${MACOSX_BUNDLE_ICON_FILE}) +set(${MODULE_NAME}_RESOURCES + ${${MODULE_NAME}_XIBS} + ${MACOSX_BUNDLE_ICON_FILE}) -# Headers -file(GLOB ${MODULE_NAME}_HEADERS *.h) +set(${MODULE_NAME}_HEADERS + AppDelegate.h + MRDPCursor.h + MRDPRailView.h + MRDPRailWindow.h + MRDPView.h + MRDPWindow.h + PasswordDialog.h) -# Source -file(GLOB ${MODULE_NAME}_SOURCES *.m) +set(${MODULE_NAME}_SOURCES + main.m + AppDelegate.m + MRDPCursor.m + MRDPRailView.m + MRDPRailWindow.m + MRDPView.m + MRDPWindow.m + PasswordDialog.m) add_executable(${MODULE_NAME} ${APP_TYPE} @@ -63,13 +77,6 @@ set_target_properties(${MODULE_NAME} PROPERTIES RESOURCE "${${MODULE_NAME}_RESOU # Support for automatic reference counting requires non-fragile abi. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-nonfragile-abi") -# XCode project architecture to native architecture of build machine -# ----------------------------------------------------------------------------------------------------- -# Issue: Had some issues with FreeRDP project building only 64 bit and -# MacFreeRDP attempting to link to both 32 and 64 for dual target. -# In the future the FreeRDP Xcode project should be pulled in for a couple of reasons: -# 1) better step-into debugging 2) automatic dependency compilation and multi-arch compilation + linkage -# If you know the solutions for 1 and 2, please add below. set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_ARCHS "$(NATIVE_ARCH_ACTUAL)") # Set the info plist to the custom instance From f94f90c08b3110d4d48ee4897bed68ebb571955b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com> Date: Thu, 11 Apr 2013 21:59:02 -0400 Subject: [PATCH 10/14] winpr-utils: initial stream pool implementation --- winpr/include/winpr/collections.h | 1 + winpr/include/winpr/stream.h | 27 +++ winpr/libwinpr/utils/CMakeLists.txt | 1 + winpr/libwinpr/utils/collections/StreamPool.c | 197 ++++++++++++++++++ winpr/libwinpr/utils/test/CMakeLists.txt | 1 + winpr/libwinpr/utils/test/TestStreamPool.c | 70 +++++++ 6 files changed, 297 insertions(+) create mode 100644 winpr/libwinpr/utils/collections/StreamPool.c create mode 100644 winpr/libwinpr/utils/test/TestStreamPool.c diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index 32b412529..521e8578e 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -28,6 +28,7 @@ #include <winpr/wtypes.h> #include <winpr/synch.h> +#include <winpr/stream.h> typedef void* (*OBJECT_NEW_FN)(void); typedef void (*OBJECT_FREE_FN)(void* obj); diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h index 3c0924eb0..d2c151585 100644 --- a/winpr/include/winpr/stream.h +++ b/winpr/include/winpr/stream.h @@ -28,12 +28,17 @@ extern "C" { #endif +typedef struct _wStreamPool wStreamPool; + struct _wStream { BYTE* buffer; BYTE* pointer; size_t length; size_t capacity; + + DWORD count; + wStreamPool* pool; }; typedef struct _wStream wStream; @@ -337,6 +342,28 @@ static INLINE BOOL stream_skip(wStream* s, int sz) { return TRUE; } +/* StreamPool */ + +struct _wStreamPool +{ + int size; + int capacity; + wStream** array; + HANDLE mutex; + BOOL synchronized; +}; + +WINPR_API wStream* StreamPool_Take(wStreamPool* pool, size_t size); +WINPR_API void StreamPool_Return(wStreamPool* pool, wStream* s); + +WINPR_API void Stream_AddRef(wStream* s); +WINPR_API void Stream_Release(wStream* s); + +WINPR_API void StreamPool_Clear(wStreamPool* pool); + +WINPR_API wStreamPool* StreamPool_New(BOOL synchronized); +WINPR_API void StreamPool_Free(wStreamPool* pool); + #ifdef __cplusplus } #endif diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index d3f210838..50c6eaad7 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -29,6 +29,7 @@ set(${MODULE_PREFIX}_COLLECTIONS_SRCS collections/CountdownEvent.c collections/BufferPool.c collections/ObjectPool.c + collections/StreamPool.c collections/MessageQueue.c collections/MessagePipe.c) diff --git a/winpr/libwinpr/utils/collections/StreamPool.c b/winpr/libwinpr/utils/collections/StreamPool.c new file mode 100644 index 000000000..b15eb8a2a --- /dev/null +++ b/winpr/libwinpr/utils/collections/StreamPool.c @@ -0,0 +1,197 @@ +/** + * WinPR: Windows Portable Runtime + * Object Pool + * + * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * + * 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 <winpr/crt.h> + +#include <winpr/collections.h> + +/** + * Methods + */ + +/** + * Gets a stream from the pool. + */ + +wStream* StreamPool_Take(wStreamPool* pool, size_t size) +{ + wStream* s = NULL; + + if (pool->synchronized) + WaitForSingleObject(pool->mutex, INFINITE); + + if (pool->size > 0) + s = pool->array[--(pool->size)]; + + if (!s) + { + s = Stream_New(NULL, size); + s->pool = (void*) pool; + s->count = 1; + } + else + { + Stream_EnsureCapacity(s, size); + Stream_Pointer(s) = Stream_Buffer(s); + s->pool = (void*) pool; + s->count = 1; + } + + if (pool->synchronized) + ReleaseMutex(pool->mutex); + + return s; +} + +/** + * Returns an object to the pool. + */ + +void StreamPool_Return(wStreamPool* pool, wStream* s) +{ + if (pool->synchronized) + WaitForSingleObject(pool->mutex, INFINITE); + + if ((pool->size + 1) >= pool->capacity) + { + pool->capacity *= 2; + pool->array = (wStream**) realloc(pool->array, sizeof(wStream*) * pool->capacity); + } + + pool->array[(pool->size)++] = s; + + if (pool->synchronized) + ReleaseMutex(pool->mutex); +} + +/** + * Lock the stream pool + */ + +void StreamPool_Lock(wStreamPool* pool) +{ + WaitForSingleObject(pool->mutex, INFINITE); +} + +/** + * Unlock the stream pool + */ + +void StreamPool_Unlock(wStreamPool* pool) +{ + ReleaseMutex(pool->mutex); +} + +/** + * Increment stream reference count + */ + +void Stream_AddRef(wStream* s) +{ + if (s->pool) + { + StreamPool_Lock(s->pool); + s->count++; + StreamPool_Unlock(s->pool); + } +} + +/** + * Decrement stream reference count + */ + +void Stream_Release(wStream* s) +{ + DWORD count; + + if (s->pool) + { + StreamPool_Lock(s->pool); + count = --(s->count); + StreamPool_Unlock(s->pool); + + if (count == 0) + StreamPool_Return(s->pool, s); + } +} + +/** + * Releases the streams currently cached in the pool. + */ + +void StreamPool_Clear(wStreamPool* pool) +{ + if (pool->synchronized) + WaitForSingleObject(pool->mutex, INFINITE); + + while (pool->size > 0) + { + (pool->size)--; + Stream_Free(pool->array[pool->size], TRUE); + } + + if (pool->synchronized) + ReleaseMutex(pool->mutex); +} + +/** + * Construction, Destruction + */ + +wStreamPool* StreamPool_New(BOOL synchronized) +{ + wStreamPool* pool = NULL; + + pool = (wStreamPool*) malloc(sizeof(wStreamPool)); + + if (pool) + { + ZeroMemory(pool, sizeof(wStreamPool)); + + pool->synchronized = synchronized; + + if (pool->synchronized) + pool->mutex = CreateMutex(NULL, FALSE, NULL); + + pool->size = 0; + pool->capacity = 32; + pool->array = (wStream**) malloc(sizeof(wStream*) * pool->capacity); + } + + return pool; +} + +void StreamPool_Free(wStreamPool* pool) +{ + if (pool) + { + StreamPool_Clear(pool); + + if (pool->synchronized) + CloseHandle(pool->mutex); + + free(pool->array); + + free(pool); + } +} diff --git a/winpr/libwinpr/utils/test/CMakeLists.txt b/winpr/libwinpr/utils/test/CMakeLists.txt index cf967be4b..307aae204 100644 --- a/winpr/libwinpr/utils/test/CMakeLists.txt +++ b/winpr/libwinpr/utils/test/CMakeLists.txt @@ -9,6 +9,7 @@ set(${MODULE_PREFIX}_TESTS TestPrint.c TestArrayList.c TestCmdLine.c + TestStreamPool.c TestMessageQueue.c TestMessagePipe.c) diff --git a/winpr/libwinpr/utils/test/TestStreamPool.c b/winpr/libwinpr/utils/test/TestStreamPool.c new file mode 100644 index 000000000..29adf2eab --- /dev/null +++ b/winpr/libwinpr/utils/test/TestStreamPool.c @@ -0,0 +1,70 @@ + +#include <winpr/crt.h> +#include <winpr/stream.h> +#include <winpr/collections.h> + +#define BUFFER_SIZE 16384 + +int TestStreamPool(int argc, char* argv[]) +{ + wStream* s[5]; + wStreamPool* pool; + + pool = StreamPool_New(TRUE); + + s[0] = StreamPool_Take(pool, BUFFER_SIZE); + s[1] = StreamPool_Take(pool, BUFFER_SIZE); + s[2] = StreamPool_Take(pool, BUFFER_SIZE); + + printf("StreamPool: size: %d\n", pool->size); + + Stream_Release(s[0]); + Stream_Release(s[1]); + Stream_Release(s[2]); + + printf("StreamPool: size: %d\n", pool->size); + + s[3] = StreamPool_Take(pool, BUFFER_SIZE); + s[4] = StreamPool_Take(pool, BUFFER_SIZE); + + printf("StreamPool: size: %d\n", pool->size); + + Stream_Release(s[3]); + Stream_Release(s[4]); + + printf("StreamPool: size: %d\n", pool->size); + + s[2] = StreamPool_Take(pool, BUFFER_SIZE); + s[3] = StreamPool_Take(pool, BUFFER_SIZE); + s[4] = StreamPool_Take(pool, BUFFER_SIZE); + + printf("StreamPool: size: %d\n", pool->size); + + Stream_AddRef(s[2]); + + Stream_AddRef(s[3]); + Stream_AddRef(s[3]); + + Stream_AddRef(s[4]); + Stream_AddRef(s[4]); + Stream_AddRef(s[4]); + + Stream_Release(s[2]); + Stream_Release(s[2]); + + Stream_Release(s[3]); + Stream_Release(s[3]); + Stream_Release(s[3]); + + Stream_Release(s[4]); + Stream_Release(s[4]); + Stream_Release(s[4]); + Stream_Release(s[4]); + + printf("StreamPool: size: %d\n", pool->size); + + StreamPool_Free(pool); + + return 0; +} + From 0fded8c2d0188c8bdbb9a8477ec1f6f1427566bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com> Date: Fri, 12 Apr 2013 12:20:20 -0400 Subject: [PATCH 11/14] winpr-utils: fix StreamPool --- winpr/include/winpr/stream.h | 18 +- winpr/libwinpr/utils/collections/StreamPool.c | 162 ++++++++++++++++-- winpr/libwinpr/utils/test/TestStreamPool.c | 61 +++++-- 3 files changed, 204 insertions(+), 37 deletions(-) diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h index d2c151585..6910734a0 100644 --- a/winpr/include/winpr/stream.h +++ b/winpr/include/winpr/stream.h @@ -346,11 +346,17 @@ static INLINE BOOL stream_skip(wStream* s, int sz) { struct _wStreamPool { - int size; - int capacity; - wStream** array; + int aSize; + int aCapacity; + wStream** aArray; + + int uSize; + int uCapacity; + wStream** uArray; + HANDLE mutex; BOOL synchronized; + size_t defaultSize; }; WINPR_API wStream* StreamPool_Take(wStreamPool* pool, size_t size); @@ -359,9 +365,13 @@ WINPR_API void StreamPool_Return(wStreamPool* pool, wStream* s); WINPR_API void Stream_AddRef(wStream* s); WINPR_API void Stream_Release(wStream* s); +WINPR_API wStream* StreamPool_Find(wStreamPool* pool, BYTE* ptr); +WINPR_API void StreamPool_AddRef(wStreamPool* pool, BYTE* ptr); +WINPR_API void StreamPool_Release(wStreamPool* pool, BYTE* ptr); + WINPR_API void StreamPool_Clear(wStreamPool* pool); -WINPR_API wStreamPool* StreamPool_New(BOOL synchronized); +WINPR_API wStreamPool* StreamPool_New(BOOL synchronized, size_t defaultSize); WINPR_API void StreamPool_Free(wStreamPool* pool); #ifdef __cplusplus diff --git a/winpr/libwinpr/utils/collections/StreamPool.c b/winpr/libwinpr/utils/collections/StreamPool.c index b15eb8a2a..978b09799 100644 --- a/winpr/libwinpr/utils/collections/StreamPool.c +++ b/winpr/libwinpr/utils/collections/StreamPool.c @@ -29,6 +29,65 @@ * Methods */ +void StreamPool_ShiftUsed(wStreamPool* pool, int index, int count) +{ + if (count > 0) + { + if (pool->uSize + count > pool->uCapacity) + { + pool->uCapacity *= 2; + pool->uArray = (wStream**) realloc(pool->uArray, sizeof(wStream*) * pool->uCapacity); + } + + MoveMemory(&pool->uArray[index + count], &pool->uArray[index], (pool->uSize - index) * sizeof(wStream*)); + pool->uSize += count; + } + else if (count < 0) + { + MoveMemory(&pool->uArray[index], &pool->uArray[index - count], (pool->uSize + count) * sizeof(wStream*)); + pool->uSize += count; + } +} + +/** + * Adds a used stream to the pool. + */ + +void StreamPool_AddUsed(wStreamPool* pool, wStream* s) +{ + int index; + + if ((pool->uSize + 1) >= pool->uCapacity) + { + pool->uCapacity *= 2; + pool->uArray = (wStream**) realloc(pool->uArray, sizeof(wStream*) * pool->uCapacity); + } + + pool->uArray[(pool->uSize)++] = s; +} + +/** + * Removes a used stream from the pool. + */ + +void StreamPool_RemoveUsed(wStreamPool* pool, wStream* s) +{ + int index; + BOOL found = FALSE; + + for (index = 0; index < pool->uSize; index++) + { + if (pool->uArray[index] == s) + { + found = TRUE; + break; + } + } + + if (found) + StreamPool_ShiftUsed(pool, index, -1); +} + /** * Gets a stream from the pool. */ @@ -40,23 +99,27 @@ wStream* StreamPool_Take(wStreamPool* pool, size_t size) if (pool->synchronized) WaitForSingleObject(pool->mutex, INFINITE); - if (pool->size > 0) - s = pool->array[--(pool->size)]; + if (pool->aSize > 0) + s = pool->aArray[--(pool->aSize)]; + + if (size < 0) + size = pool->defaultSize; if (!s) { s = Stream_New(NULL, size); - s->pool = (void*) pool; - s->count = 1; } else { Stream_EnsureCapacity(s, size); Stream_Pointer(s) = Stream_Buffer(s); - s->pool = (void*) pool; - s->count = 1; } + s->pool = pool; + s->count = 1; + + StreamPool_AddUsed(pool, s); + if (pool->synchronized) ReleaseMutex(pool->mutex); @@ -72,13 +135,14 @@ void StreamPool_Return(wStreamPool* pool, wStream* s) if (pool->synchronized) WaitForSingleObject(pool->mutex, INFINITE); - if ((pool->size + 1) >= pool->capacity) + if ((pool->aSize + 1) >= pool->aCapacity) { - pool->capacity *= 2; - pool->array = (wStream**) realloc(pool->array, sizeof(wStream*) * pool->capacity); + pool->aCapacity *= 2; + pool->aArray = (wStream**) realloc(pool->aArray, sizeof(wStream*) * pool->aCapacity); } - pool->array[(pool->size)++] = s; + pool->aArray[(pool->aSize)++] = s; + StreamPool_RemoveUsed(pool, s); if (pool->synchronized) ReleaseMutex(pool->mutex); @@ -135,6 +199,62 @@ void Stream_Release(wStream* s) } } +/** + * Find stream in pool using pointer inside buffer + */ + +wStream* StreamPool_Find(wStreamPool* pool, BYTE* ptr) +{ + int index; + wStream* s = NULL; + BOOL found = FALSE; + + WaitForSingleObject(pool->mutex, INFINITE); + + for (index = 0; index < pool->uSize; index++) + { + s = pool->uArray[index]; + + if ((ptr >= s->buffer) && (ptr < (s->buffer + s->capacity))) + { + found = TRUE; + break; + } + } + + ReleaseMutex(pool->mutex); + + return (found) ? s : NULL; +} + +/** + * Find stream in pool and increment reference count + */ + +void StreamPool_AddRef(wStreamPool* pool, BYTE* ptr) +{ + wStream* s; + + s = StreamPool_Find(pool, ptr); + + if (s) + Stream_AddRef(s); +} + +/** + * Find stream in pool and decrement reference count + */ + +void StreamPool_Release(wStreamPool* pool, BYTE* ptr) +{ + wStream* s; + + s = StreamPool_Find(pool, ptr); + + if (s) + Stream_Release(s); +} + /** * Releases the streams currently cached in the pool. */ @@ -144,10 +264,10 @@ void StreamPool_Clear(wStreamPool* pool) if (pool->synchronized) WaitForSingleObject(pool->mutex, INFINITE); - while (pool->size > 0) + while (pool->aSize > 0) { - (pool->size)--; - Stream_Free(pool->array[pool->size], TRUE); + (pool->aSize)--; + Stream_Free(pool->aArray[pool->aSize], TRUE); } if (pool->synchronized) @@ -158,7 +278,7 @@ void StreamPool_Clear(wStreamPool* pool) * Construction, Destruction */ -wStreamPool* StreamPool_New(BOOL synchronized) +wStreamPool* StreamPool_New(BOOL synchronized, size_t defaultSize) { wStreamPool* pool = NULL; @@ -169,13 +289,18 @@ wStreamPool* StreamPool_New(BOOL synchronized) ZeroMemory(pool, sizeof(wStreamPool)); pool->synchronized = synchronized; + pool->defaultSize = defaultSize; if (pool->synchronized) pool->mutex = CreateMutex(NULL, FALSE, NULL); - pool->size = 0; - pool->capacity = 32; - pool->array = (wStream**) malloc(sizeof(wStream*) * pool->capacity); + pool->aSize = 0; + pool->aCapacity = 32; + pool->aArray = (wStream**) malloc(sizeof(wStream*) * pool->aCapacity); + + pool->uSize = 0; + pool->uCapacity = 32; + pool->uArray = (wStream**) malloc(sizeof(wStream*) * pool->uCapacity); } return pool; @@ -190,7 +315,8 @@ void StreamPool_Free(wStreamPool* pool) if (pool->synchronized) CloseHandle(pool->mutex); - free(pool->array); + free(pool->aArray); + free(pool->uArray); free(pool); } diff --git a/winpr/libwinpr/utils/test/TestStreamPool.c b/winpr/libwinpr/utils/test/TestStreamPool.c index 29adf2eab..d768e8c14 100644 --- a/winpr/libwinpr/utils/test/TestStreamPool.c +++ b/winpr/libwinpr/utils/test/TestStreamPool.c @@ -10,35 +10,35 @@ int TestStreamPool(int argc, char* argv[]) wStream* s[5]; wStreamPool* pool; - pool = StreamPool_New(TRUE); + pool = StreamPool_New(TRUE, BUFFER_SIZE); - s[0] = StreamPool_Take(pool, BUFFER_SIZE); - s[1] = StreamPool_Take(pool, BUFFER_SIZE); - s[2] = StreamPool_Take(pool, BUFFER_SIZE); + s[0] = StreamPool_Take(pool, -1); + s[1] = StreamPool_Take(pool, -1); + s[2] = StreamPool_Take(pool, -1); - printf("StreamPool: size: %d\n", pool->size); + printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); Stream_Release(s[0]); Stream_Release(s[1]); Stream_Release(s[2]); - printf("StreamPool: size: %d\n", pool->size); + printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); - s[3] = StreamPool_Take(pool, BUFFER_SIZE); - s[4] = StreamPool_Take(pool, BUFFER_SIZE); + s[3] = StreamPool_Take(pool, -1); + s[4] = StreamPool_Take(pool, -1); - printf("StreamPool: size: %d\n", pool->size); + printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); Stream_Release(s[3]); Stream_Release(s[4]); - printf("StreamPool: size: %d\n", pool->size); + printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); - s[2] = StreamPool_Take(pool, BUFFER_SIZE); - s[3] = StreamPool_Take(pool, BUFFER_SIZE); - s[4] = StreamPool_Take(pool, BUFFER_SIZE); + s[2] = StreamPool_Take(pool, -1); + s[3] = StreamPool_Take(pool, -1); + s[4] = StreamPool_Take(pool, -1); - printf("StreamPool: size: %d\n", pool->size); + printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); Stream_AddRef(s[2]); @@ -61,7 +61,38 @@ int TestStreamPool(int argc, char* argv[]) Stream_Release(s[4]); Stream_Release(s[4]); - printf("StreamPool: size: %d\n", pool->size); + printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); + + s[2] = StreamPool_Take(pool, -1); + s[3] = StreamPool_Take(pool, -1); + s[4] = StreamPool_Take(pool, -1); + + printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); + + StreamPool_AddRef(pool, s[2]->buffer + 1024); + + StreamPool_AddRef(pool, s[3]->buffer + 1024); + StreamPool_AddRef(pool, s[3]->buffer + 1024 * 2); + + StreamPool_AddRef(pool, s[4]->buffer + 1024); + StreamPool_AddRef(pool, s[4]->buffer + 1024 * 2); + StreamPool_AddRef(pool, s[4]->buffer + 1024 * 3); + + printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); + + StreamPool_Release(pool, s[2]->buffer + 2048); + StreamPool_Release(pool, s[2]->buffer + 2048 * 2); + + StreamPool_Release(pool, s[3]->buffer + 2048); + StreamPool_Release(pool, s[3]->buffer + 2048 * 2); + StreamPool_Release(pool, s[3]->buffer + 2048 * 3); + + StreamPool_Release(pool, s[4]->buffer + 2048); + StreamPool_Release(pool, s[4]->buffer + 2048 * 2); + StreamPool_Release(pool, s[4]->buffer + 2048 * 3); + StreamPool_Release(pool, s[4]->buffer + 2048 * 4); + + printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); StreamPool_Free(pool); From d04b76d005034a76eb6532ff537b4fdf433eca38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com> Date: Fri, 12 Apr 2013 13:44:23 -0400 Subject: [PATCH 12/14] libfreerdp-core: use stream pool --- client/X11/cli/xfreerdp.c | 3 +-- client/X11/xf_interface.c | 18 ++++++++++---- libfreerdp/core/freerdp.c | 4 +++- libfreerdp/core/transport.c | 24 +++++-------------- libfreerdp/core/transport.h | 2 +- winpr/libwinpr/utils/collections/StreamPool.c | 2 +- winpr/libwinpr/utils/test/TestStreamPool.c | 22 ++++++++--------- 7 files changed, 36 insertions(+), 39 deletions(-) diff --git a/client/X11/cli/xfreerdp.c b/client/X11/cli/xfreerdp.c index b242c11ee..a2911207e 100644 --- a/client/X11/cli/xfreerdp.c +++ b/client/X11/cli/xfreerdp.c @@ -49,8 +49,7 @@ int main(int argc, char* argv[]) GetExitCodeThread(xfi->thread, &dwExitCode); - freerdp_context_free(instance); - freerdp_free(instance); + freerdp_client_free(xfi); freerdp_client_global_uninit(); diff --git a/client/X11/xf_interface.c b/client/X11/xf_interface.c index c2d6d0a60..3d27a5b49 100644 --- a/client/X11/xf_interface.c +++ b/client/X11/xf_interface.c @@ -1382,9 +1382,6 @@ void* xf_thread(void* param) freerdp_channels_free(channels); freerdp_disconnect(instance); gdi_free(instance); - freerdp_client_free(xfi); - - exit_code = 123; ExitThread(exit_code); } @@ -1475,8 +1472,6 @@ xfInfo* freerdp_client_new(int argc, char** argv) freerdp_context_new(instance); instance->context->argc = argc; - instance->context->argv = argv; - instance->context->argv = (char**) malloc(sizeof(char*) * argc); for (index = 0; index < argc; index++) @@ -1544,12 +1539,25 @@ void freerdp_client_free(xfInfo* xfi) { if (xfi) { + int index; + rdpContext* context; + xf_window_free(xfi); free(xfi->bmp_codec_none); XCloseDisplay(xfi->display); + context = (rdpContext*) xfi->context; + + for (index = 0; index < context->argc; index++) + free(context->argv[index]); + + free(context->argv); + + freerdp_context_free(xfi->instance); + freerdp_free(xfi->instance); + free(xfi); } } diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index b1d05fb82..6770a1ab3 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -340,7 +340,7 @@ void freerdp_context_new(freerdp* instance) */ void freerdp_context_free(freerdp* instance) { - if (instance->context == NULL) + if (!instance->context) return; IFCALL(instance->ContextFree, instance, instance->context); @@ -348,6 +348,8 @@ void freerdp_context_free(freerdp* instance) rdp_free(instance->context->rdp); graphics_free(instance->context->graphics); + free(instance->context->client); + free(instance->context); instance->context = NULL; } diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 29f8e6297..458fca7fc 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -703,7 +703,7 @@ int transport_check_fds(rdpTransport** ptransport) } received = transport->ReceiveBuffer; - transport->ReceiveBuffer = ObjectPool_Take(transport->ReceivePool); + transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0); transport->ReceiveBuffer->pointer = transport->ReceiveBuffer->buffer; stream_set_pos(received, length); @@ -720,7 +720,7 @@ int transport_check_fds(rdpTransport** ptransport) recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra); - ObjectPool_Return(transport->ReceivePool, received); + StreamPool_Return(transport->ReceivePool, received); if (recv_status < 0) status = -1; @@ -799,16 +799,6 @@ static void* transport_client_thread(void* arg) return NULL; } -wStream* transport_receive_buffer_pool_new() -{ - wStream* pdu = NULL; - - pdu = stream_new(BUFFER_SIZE); - pdu->pointer = pdu->buffer; - - return pdu; -} - rdpTransport* transport_new(rdpSettings* settings) { rdpTransport* transport; @@ -826,12 +816,10 @@ rdpTransport* transport_new(rdpSettings* settings) /* a small 0.1ms delay when transport is blocking. */ transport->SleepInterval = 100; - transport->ReceivePool = ObjectPool_New(TRUE); - ObjectPool_Object(transport->ReceivePool)->fnObjectFree = (OBJECT_FREE_FN) stream_free; - ObjectPool_Object(transport->ReceivePool)->fnObjectNew = (OBJECT_NEW_FN) transport_receive_buffer_pool_new; + transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE); /* receive buffer for non-blocking read. */ - transport->ReceiveBuffer = ObjectPool_Take(transport->ReceivePool); + transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0); transport->ReceiveEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* buffers for blocking read/write */ @@ -851,9 +839,9 @@ void transport_free(rdpTransport* transport) if (transport != NULL) { if (transport->ReceiveBuffer) - ObjectPool_Return(transport->ReceivePool, transport->ReceiveBuffer); + StreamPool_Return(transport->ReceivePool, transport->ReceiveBuffer); - ObjectPool_Free(transport->ReceivePool); + StreamPool_Free(transport->ReceivePool); stream_free(transport->ReceiveStream); stream_free(transport->SendStream); diff --git a/libfreerdp/core/transport.h b/libfreerdp/core/transport.h index 0dc04122a..67a2e2783 100644 --- a/libfreerdp/core/transport.h +++ b/libfreerdp/core/transport.h @@ -69,7 +69,7 @@ struct rdp_transport HANDLE GatewayEvent; BOOL blocking; BOOL SplitInputOutput; - wObjectPool* ReceivePool; + wStreamPool* ReceivePool; HANDLE stopEvent; HANDLE thread; BOOL async; diff --git a/winpr/libwinpr/utils/collections/StreamPool.c b/winpr/libwinpr/utils/collections/StreamPool.c index 978b09799..96a491acf 100644 --- a/winpr/libwinpr/utils/collections/StreamPool.c +++ b/winpr/libwinpr/utils/collections/StreamPool.c @@ -102,7 +102,7 @@ wStream* StreamPool_Take(wStreamPool* pool, size_t size) if (pool->aSize > 0) s = pool->aArray[--(pool->aSize)]; - if (size < 0) + if (size == 0) size = pool->defaultSize; if (!s) diff --git a/winpr/libwinpr/utils/test/TestStreamPool.c b/winpr/libwinpr/utils/test/TestStreamPool.c index d768e8c14..ab8a371e4 100644 --- a/winpr/libwinpr/utils/test/TestStreamPool.c +++ b/winpr/libwinpr/utils/test/TestStreamPool.c @@ -12,9 +12,9 @@ int TestStreamPool(int argc, char* argv[]) pool = StreamPool_New(TRUE, BUFFER_SIZE); - s[0] = StreamPool_Take(pool, -1); - s[1] = StreamPool_Take(pool, -1); - s[2] = StreamPool_Take(pool, -1); + s[0] = StreamPool_Take(pool, 0); + s[1] = StreamPool_Take(pool, 0); + s[2] = StreamPool_Take(pool, 0); printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); @@ -24,8 +24,8 @@ int TestStreamPool(int argc, char* argv[]) printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); - s[3] = StreamPool_Take(pool, -1); - s[4] = StreamPool_Take(pool, -1); + s[3] = StreamPool_Take(pool, 0); + s[4] = StreamPool_Take(pool, 0); printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); @@ -34,9 +34,9 @@ int TestStreamPool(int argc, char* argv[]) printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); - s[2] = StreamPool_Take(pool, -1); - s[3] = StreamPool_Take(pool, -1); - s[4] = StreamPool_Take(pool, -1); + s[2] = StreamPool_Take(pool, 0); + s[3] = StreamPool_Take(pool, 0); + s[4] = StreamPool_Take(pool, 0); printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); @@ -63,9 +63,9 @@ int TestStreamPool(int argc, char* argv[]) printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); - s[2] = StreamPool_Take(pool, -1); - s[3] = StreamPool_Take(pool, -1); - s[4] = StreamPool_Take(pool, -1); + s[2] = StreamPool_Take(pool, 0); + s[3] = StreamPool_Take(pool, 0); + s[4] = StreamPool_Take(pool, 0); printf("StreamPool: aSize: %d uSize: %d\n", pool->aSize, pool->uSize); From d776a2d4ea30f7cfa8a619866148509b5ab3341e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com> Date: Fri, 12 Apr 2013 17:05:42 -0400 Subject: [PATCH 13/14] libfreerdp-core: start using stream pool --- libfreerdp/codec/rfx_decode.c | 4 +++- libfreerdp/core/fastpath.c | 9 ++++++--- libfreerdp/core/message.c | 30 ++++++++++++++++++++++++++++-- libfreerdp/core/surface.c | 6 +++--- libfreerdp/core/transport.c | 11 ++++++----- 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/libfreerdp/codec/rfx_decode.c b/libfreerdp/codec/rfx_decode.c index 15aa4cf00..1acffda27 100644 --- a/libfreerdp/codec/rfx_decode.c +++ b/libfreerdp/codec/rfx_decode.c @@ -202,11 +202,12 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, wStream* data_in, else #endif { - if (stream_get_left(data_in) < y_size+cb_size+cr_size) + if (stream_get_left(data_in) < y_size + cb_size + cr_size) { DEBUG_WARN("rfx_decode_rgb: packet too small for y_size+cb_size+cr_size"); return FALSE; } + rfx_decode_component(context, y_quants, stream_get_tail(data_in), y_size, pSrcDst[0]); /* YData */ stream_seek(data_in, y_size); @@ -230,5 +231,6 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, wStream* data_in, BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16); BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16); BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16); + return TRUE; } diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 56d06a983..8a680d7e7 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -169,20 +169,21 @@ static BOOL fastpath_recv_update_common(rdpFastPath* fastpath, wStream* s) rdpUpdate* update = fastpath->rdp->update; rdpContext* context = update->context; - if(stream_get_left(s) < 2) + if (stream_get_left(s) < 2) return FALSE; + stream_read_UINT16(s, updateType); /* updateType (2 bytes) */ switch (updateType) { case UPDATE_TYPE_BITMAP: - if(!update_read_bitmap(update, s, &update->bitmap_update)) + if (!update_read_bitmap(update, s, &update->bitmap_update)) return FALSE; IFCALL(update->BitmapUpdate, context, &update->bitmap_update); break; case UPDATE_TYPE_PALETTE: - if(!update_read_palette(update, s, &update->palette_update)) + if (!update_read_palette(update, s, &update->palette_update)) return FALSE; IFCALL(update->Palette, context, &update->palette_update); break; @@ -328,6 +329,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) } update_stream = NULL; + if (fragmentation == FASTPATH_FRAGMENT_SINGLE) { totalSize = size; @@ -340,6 +342,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) stream_check_size(fastpath->updateData, size); stream_copy(fastpath->updateData, comp_stream, size); + if (stream_get_length(fastpath->updateData) > rdp->settings->MultifragMaxRequestSize) { fprintf(stderr, "fastpath PDU is bigger than MultifragMaxRequestSize\n"); diff --git a/libfreerdp/core/message.c b/libfreerdp/core/message.c index 3e2900b03..3ccea28d3 100644 --- a/libfreerdp/core/message.c +++ b/libfreerdp/core/message.c @@ -21,11 +21,18 @@ #include "config.h" #endif +#include "rdp.h" #include "message.h" +#include "transport.h" + +#include <freerdp/freerdp.h> #include <winpr/crt.h> +#include <winpr/stream.h> #include <winpr/collections.h> +//#define WITH_STREAM_POOL 1 + /* Update */ static void update_message_BeginPaint(rdpContext* context) @@ -79,13 +86,15 @@ static void update_message_BitmapUpdate(rdpContext* context, BITMAP_UPDATE* bitm wParam->rectangles = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * wParam->number); CopyMemory(wParam->rectangles, bitmap->rectangles, sizeof(BITMAP_DATA) * wParam->number); - /* TODO: increment reference count to original stream instead of copying */ - for (index = 0; index < wParam->number; index++) { +#ifdef WITH_STREAM_POOL + StreamPool_AddRef(context->rdp->transport->ReceivePool, bitmap->rectangles[index].bitmapDataStream); +#else wParam->rectangles[index].bitmapDataStream = (BYTE*) malloc(wParam->rectangles[index].bitmapLength); CopyMemory(wParam->rectangles[index].bitmapDataStream, bitmap->rectangles[index].bitmapDataStream, wParam->rectangles[index].bitmapLength); +#endif } MessageQueue_Post(context->update->queue, (void*) context, @@ -160,8 +169,12 @@ static void update_message_SurfaceBits(rdpContext* context, SURFACE_BITS_COMMAND wParam = (SURFACE_BITS_COMMAND*) malloc(sizeof(SURFACE_BITS_COMMAND)); CopyMemory(wParam, surfaceBitsCommand, sizeof(SURFACE_BITS_COMMAND)); +#ifdef WITH_STREAM_POOL + StreamPool_AddRef(context->rdp->transport->ReceivePool, surfaceBitsCommand->bitmapData); +#else wParam->bitmapData = (BYTE*) malloc(wParam->bitmapDataLength); CopyMemory(wParam->bitmapData, surfaceBitsCommand->bitmapData, wParam->bitmapDataLength); +#endif MessageQueue_Post(context->update->queue, (void*) context, MakeMessageId(Update, SurfaceBits), (void*) wParam, NULL); @@ -952,7 +965,14 @@ int update_message_process_update_class(rdpUpdateProxy* proxy, wMessage* msg, in BITMAP_UPDATE* wParam = (BITMAP_UPDATE*) msg->wParam; for (index = 0; index < wParam->number; index++) + { +#ifdef WITH_STREAM_POOL + rdpContext* context = (rdpContext*) msg->context; + StreamPool_Release(context->rdp->transport->ReceivePool, wParam->rectangles[index].bitmapDataStream); +#else free(wParam->rectangles[index].bitmapDataStream); +#endif + } free(wParam); } @@ -993,9 +1013,15 @@ int update_message_process_update_class(rdpUpdateProxy* proxy, wMessage* msg, in case Update_SurfaceBits: IFCALL(proxy->SurfaceBits, msg->context, (SURFACE_BITS_COMMAND*) msg->wParam); { +#ifdef WITH_STREAM_POOL + rdpContext* context = (rdpContext*) msg->context; + SURFACE_BITS_COMMAND* wParam = (SURFACE_BITS_COMMAND*) msg->wParam; + StreamPool_Release(context->rdp->transport->ReceivePool, wParam->bitmapData); +#else SURFACE_BITS_COMMAND* wParam = (SURFACE_BITS_COMMAND*) msg->wParam; free(wParam->bitmapData); free(wParam); +#endif } break; diff --git a/libfreerdp/core/surface.c b/libfreerdp/core/surface.c index 1c961f5d9..42d39f1ab 100644 --- a/libfreerdp/core/surface.c +++ b/libfreerdp/core/surface.c @@ -25,7 +25,7 @@ #include "surface.h" -static int update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT32 *length) +static int update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT32* length) { int pos; SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command; @@ -50,11 +50,11 @@ static int update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT3 pos = stream_get_pos(s) + cmd->bitmapDataLength; cmd->bitmapData = stream_get_tail(s); - IFCALL(update->SurfaceBits, update->context, cmd); - stream_set_pos(s, pos); *length = 20 + cmd->bitmapDataLength; + IFCALL(update->SurfaceBits, update->context, cmd); + return 0; } diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 458fca7fc..c1033e225 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -704,7 +704,6 @@ int transport_check_fds(rdpTransport** ptransport) received = transport->ReceiveBuffer; transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0); - transport->ReceiveBuffer->pointer = transport->ReceiveBuffer->buffer; stream_set_pos(received, length); stream_seal(received); @@ -720,7 +719,7 @@ int transport_check_fds(rdpTransport** ptransport) recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra); - StreamPool_Return(transport->ReceivePool, received); + Stream_Release(received); if (recv_status < 0) status = -1; @@ -823,7 +822,7 @@ rdpTransport* transport_new(rdpSettings* settings) transport->ReceiveEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* buffers for blocking read/write */ - transport->ReceiveStream = stream_new(BUFFER_SIZE); + transport->ReceiveStream = StreamPool_Take(transport->ReceivePool, 0); transport->SendStream = stream_new(BUFFER_SIZE); transport->blocking = TRUE; @@ -839,11 +838,13 @@ void transport_free(rdpTransport* transport) if (transport != NULL) { if (transport->ReceiveBuffer) - StreamPool_Return(transport->ReceivePool, transport->ReceiveBuffer); + Stream_Release(transport->ReceiveBuffer); + + if (transport->ReceiveStream) + Stream_Release(transport->ReceiveStream); StreamPool_Free(transport->ReceivePool); - stream_free(transport->ReceiveStream); stream_free(transport->SendStream); CloseHandle(transport->ReceiveEvent); From 073c6fb98374d805bea5f388506be8c3cc039e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com> Date: Fri, 12 Apr 2013 18:03:56 -0400 Subject: [PATCH 14/14] libfreerdp-core: fix handling of SSL_CERT_NOT_ON_SERVER --- client/common/file.c | 28 +++++++++++++++------------- libfreerdp/core/nego.c | 13 ++++++++++--- libfreerdp/core/nego.h | 1 + libfreerdp/core/settings.c | 1 + 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/client/common/file.c b/client/common/file.c index a90a5fe81..a13ca239b 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -308,7 +308,7 @@ BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, BYTE* buffer, siz line = strtok_s((char*) buffer, "\r\n", &context); - while (line != NULL) + while (line) { length = strlen(line); @@ -458,8 +458,7 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, char* name) if (file_size < 1) return FALSE; - buffer = (BYTE*) malloc(file_size); - + buffer = (BYTE*) malloc(file_size + 2); read_size = fread(buffer, file_size, 1, fp); if (!read_size) @@ -475,6 +474,9 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, char* name) return FALSE; } + buffer[file_size] = '\0'; + buffer[file_size + 1] = '\0'; + return freerdp_client_parse_rdp_file_buffer(file, buffer, file_size); } @@ -497,7 +499,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (~file->ServerPort) settings->ServerPort = file->ServerPort; if (~((size_t) file->FullAddress)) - settings->ServerHostname = file->FullAddress; + settings->ServerHostname = _strdup(file->FullAddress); if (~file->DesktopWidth) settings->DesktopWidth = file->DesktopWidth; if (~file->DesktopHeight) @@ -513,9 +515,9 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (~file->EnableCredSSPSupport) settings->NlaSecurity = file->EnableCredSSPSupport; if (~((size_t) file->AlternateShell)) - settings->AlternateShell = file->AlternateShell; + settings->AlternateShell = _strdup(file->AlternateShell); if (~((size_t) file->ShellWorkingDirectory)) - settings->ShellWorkingDirectory = file->ShellWorkingDirectory; + settings->ShellWorkingDirectory = _strdup(file->ShellWorkingDirectory); if (~((size_t) file->LoadBalanceInfo)) { @@ -546,7 +548,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* } if (~((size_t) file->GatewayHostname)) - settings->GatewayHostname = file->GatewayHostname; + settings->GatewayHostname = _strdup(file->GatewayHostname); if (~file->GatewayUsageMethod) settings->GatewayUsageMethod = TRUE; if (~file->PromptCredentialOnce) @@ -555,17 +557,17 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (~file->RemoteApplicationMode) settings->RemoteApplicationMode = file->RemoteApplicationMode; if (~((size_t) file->RemoteApplicationProgram)) - settings->RemoteApplicationProgram = file->RemoteApplicationProgram; + settings->RemoteApplicationProgram = _strdup(file->RemoteApplicationProgram); if (~((size_t) file->RemoteApplicationName)) - settings->RemoteApplicationName = file->RemoteApplicationName; + settings->RemoteApplicationName = _strdup(file->RemoteApplicationName); if (~((size_t) file->RemoteApplicationIcon)) - settings->RemoteApplicationIcon = file->RemoteApplicationIcon; + settings->RemoteApplicationIcon = _strdup(file->RemoteApplicationIcon); if (~((size_t) file->RemoteApplicationFile)) - settings->RemoteApplicationFile = file->RemoteApplicationFile; + settings->RemoteApplicationFile = _strdup(file->RemoteApplicationFile); if (~((size_t) file->RemoteApplicationGuid)) - settings->RemoteApplicationGuid = file->RemoteApplicationGuid; + settings->RemoteApplicationGuid = _strdup(file->RemoteApplicationGuid); if (~((size_t) file->RemoteApplicationCmdLine)) - settings->RemoteApplicationCmdLine = file->RemoteApplicationCmdLine; + settings->RemoteApplicationCmdLine = _strdup(file->RemoteApplicationCmdLine); if (~file->SpanMonitors) settings->SpanMonitors = file->SpanMonitors; diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c index b15730228..0227620ae 100644 --- a/libfreerdp/core/nego.c +++ b/libfreerdp/core/nego.c @@ -490,7 +490,7 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra) if (length == 0) return -1; - if(!tpdu_read_connection_confirm(s, &li)) + if (!tpdu_read_connection_confirm(s, &li)) return -1; if (li > 6) @@ -563,7 +563,8 @@ BOOL nego_read_request(rdpNego* nego, wStream* s) BYTE type; tpkt_read_header(s); - if(!tpdu_read_connection_request(s, &li)) + + if (!tpdu_read_connection_request(s, &li)) return FALSE; if (li != stream_get_left(s) + 6) @@ -671,7 +672,7 @@ BOOL nego_send_negotiation_request(rdpNego* nego) DEBUG_NEGO("requested_protocols: %d", nego->requested_protocols); - if (nego->requested_protocols > PROTOCOL_RDP) + if ((nego->requested_protocols > PROTOCOL_RDP) || (nego->sendNegoData)) { /* RDP_NEG_DATA must be present for TLS and NLA */ stream_write_BYTE(s, TYPE_RDP_NEG_REQ); @@ -764,18 +765,24 @@ void nego_process_negotiation_failure(rdpNego* nego, wStream* s) case SSL_REQUIRED_BY_SERVER: DEBUG_NEGO("Error: SSL_REQUIRED_BY_SERVER"); break; + case SSL_NOT_ALLOWED_BY_SERVER: DEBUG_NEGO("Error: SSL_NOT_ALLOWED_BY_SERVER"); break; + case SSL_CERT_NOT_ON_SERVER: DEBUG_NEGO("Error: SSL_CERT_NOT_ON_SERVER"); + nego->sendNegoData = TRUE; break; + case INCONSISTENT_FLAGS: DEBUG_NEGO("Error: INCONSISTENT_FLAGS"); break; + case HYBRID_REQUIRED_BY_SERVER: DEBUG_NEGO("Error: HYBRID_REQUIRED_BY_SERVER"); break; + default: DEBUG_NEGO("Error: Unknown protocol security error %d", failureCode); break; diff --git a/libfreerdp/core/nego.h b/libfreerdp/core/nego.h index 48e3d0410..e8f429fb8 100644 --- a/libfreerdp/core/nego.h +++ b/libfreerdp/core/nego.h @@ -100,6 +100,7 @@ struct rdp_nego BOOL security_connected; UINT32 cookie_max_length; + BOOL sendNegoData; UINT32 selected_protocol; UINT32 requested_protocols; BOOL NegotiateSecurityLayer; diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index c44ae9667..8411b4b88 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -454,6 +454,7 @@ void freerdp_settings_free(rdpSettings* settings) free(settings->ConfigPath); free(settings->CurrentPath); free(settings->HomePath); + free(settings->LoadBalanceInfo); freerdp_device_collection_free(settings); freerdp_static_channel_collection_free(settings); freerdp_dynamic_channel_collection_free(settings);