diff --git a/.gitignore b/.gitignore index 048417b7d..ff66464d9 100755 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,9 @@ external/* # Documentation docs/api client/X11/xfreerdp.1 +client/X11/xfreerdp.1.xml +client/X11/xfreerdp-channels.1.xml +client/X11/xfreerdp-examples.1.xml # Mac OS X .DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 840a20581..a38dd3a19 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -417,12 +417,12 @@ set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}") set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp/extensions") # Include directories -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) # Configure files add_definitions("-DHAVE_CONFIG_H") -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/config.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) # RPATH configuration set(CMAKE_SKIP_BUILD_RPATH FALSE) @@ -447,8 +447,8 @@ if(BUILD_TESTING) endif() # WinPR -set(WINPR_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/winpr/include") -include_directories(${WINPR_INCLUDE_DIR}) +include_directories("${CMAKE_SOURCE_DIR}/winpr/include") +include_directories("${CMAKE_BINARY_DIR}/winpr/include") add_subdirectory(winpr) diff --git a/channels/client/CMakeLists.txt b/channels/client/CMakeLists.txt index 6aa60777a..fc42466bb 100644 --- a/channels/client/CMakeLists.txt +++ b/channels/client/CMakeLists.txt @@ -19,16 +19,16 @@ set(MODULE_NAME "freerdp-channels-client") set(MODULE_PREFIX "FREERDP_CHANNELS_CLIENT") set(${MODULE_PREFIX}_SRCS - tables.c - tables.h - addin.c - addin.h - init.c - init.h - open.c - open.h - channels.c - channels.h) + ${CMAKE_CURRENT_BINARY_DIR}/tables.c + ${CMAKE_CURRENT_SOURCE_DIR}/tables.h + ${CMAKE_CURRENT_SOURCE_DIR}/addin.c + ${CMAKE_CURRENT_SOURCE_DIR}/addin.h + ${CMAKE_CURRENT_SOURCE_DIR}/init.c + ${CMAKE_CURRENT_SOURCE_DIR}/init.h + ${CMAKE_CURRENT_SOURCE_DIR}/open.c + ${CMAKE_CURRENT_SOURCE_DIR}/open.h + ${CMAKE_CURRENT_SOURCE_DIR}/channels.c + ${CMAKE_CURRENT_SOURCE_DIR}/channels.h) list(REMOVE_DUPLICATES CHANNEL_STATIC_CLIENT_ENTRIES) @@ -96,7 +96,7 @@ foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES}) endforeach() set(CLIENT_STATIC_ADDIN_TABLE "${CLIENT_STATIC_ADDIN_TABLE}\n\t{ NULL, NULL, NULL }\n};") -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tables.c.in ${CMAKE_CURRENT_SOURCE_DIR}/tables.c) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tables.c.in ${CMAKE_CURRENT_BINARY_DIR}/tables.c) set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index 023bbf8e1..426475a64 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -87,14 +87,15 @@ void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIS if (!cliprdr->use_long_format_names) name_length = 32; - Stream_EnsureRemainingCapacity(body, Stream_Capacity(body) + 4 + name_length); + Stream_EnsureRemainingCapacity(body, 4 + name_length); Stream_Write_UINT32(body, cb_event->formats[i]); Stream_Write(body, name, name_length); } - s = cliprdr_packet_new(CB_FORMAT_LIST, 0, Stream_Capacity(body)); - Stream_Write(s, Stream_Buffer(body), Stream_Capacity(body)); + Stream_SealLength(body); + s = cliprdr_packet_new(CB_FORMAT_LIST, 0, Stream_Length(body)); + Stream_Write(s, Stream_Buffer(body), Stream_Length(body)); Stream_Free(body, TRUE); } @@ -290,16 +291,16 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { - /* where is this documented? */ -#if 0 + /* http://msdn.microsoft.com/en-us/library/hh872154.aspx */ wMessage* event; if ((msgFlags & CB_RESPONSE_FAIL) != 0) { - event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_MONITOR_READY, NULL, NULL); + /* In case of an error the clipboard will not be synchronized with the server. + * Post this event to restart format negociation and data transfer. */ + event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL); svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event); } -#endif } void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index 6e35c1ee9..16bf4bbb0 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -286,6 +286,7 @@ static void parallel_free(DEVICE* device) MessageQueue_PostQuit(parallel->queue, 0); WaitForSingleObject(parallel->thread, INFINITE); + Stream_Free(parallel->device.data, TRUE); MessageQueue_Free(parallel->queue); CloseHandle(parallel->thread); diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index 89e2ffb81..3826b7c3a 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -179,13 +179,16 @@ static void* printer_thread_func(void* arg) { IRP* irp; PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) arg; + HANDLE obj[] = {printer_dev->event, printer_dev->stopEvent}; while (1) { - WaitForSingleObject(printer_dev->event, INFINITE); + DWORD rc = WaitForMultipleObjects(2, obj, FALSE, INFINITE); - if (WaitForSingleObject(printer_dev->stopEvent, 0) == WAIT_OBJECT_0) + if (rc == WAIT_OBJECT_0 + 1) break; + else if( rc != WAIT_OBJECT_0 ) + continue; ResetEvent(printer_dev->event); diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index fb6b07915..d2ff16a48 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -323,29 +323,28 @@ static void* serial_thread_func(void* arg) IRP* irp; DWORD status; SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg; + HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue)}; while (1) { - if (WaitForSingleObject(serial->stopEvent, 0) == WAIT_OBJECT_0) - break; + status = WaitForMultipleObjects(2, ev, FALSE, 1); - status = WaitForSingleObject(Queue_Event(serial->queue), 10); - - if ((status != WAIT_OBJECT_0) && (status != WAIT_TIMEOUT)) + if (WAIT_OBJECT_0 == status) break; serial->nfds = 1; FD_ZERO(&serial->read_fds); FD_ZERO(&serial->write_fds); - serial->tv.tv_sec = 1; + serial->tv.tv_sec = 0; serial->tv.tv_usec = 0; serial->select_timeout = 0; - if (status == WAIT_OBJECT_0) + if (status == WAIT_OBJECT_0 + 1) { if ((irp = (IRP*) Queue_Dequeue(serial->queue))) serial_process_irp(serial, irp); + continue; } serial_check_fds(serial); @@ -367,10 +366,18 @@ static void serial_free(DEVICE* device) DEBUG_SVC("freeing device"); + /* Stop thread */ SetEvent(serial->stopEvent); + WaitForSingleObject(serial->thread, INFINITE); - /* TODO: free lists */ + serial_tty_free(serial->tty); + /* Clean up resources */ + Stream_Free(serial->device.data, TRUE); + Queue_Free(serial->queue); + list_free(serial->pending_irps); + CloseHandle(serial->stopEvent); + CloseHandle(serial->thread); free(serial); } @@ -383,6 +390,11 @@ static void serial_abort_single_io(SERIAL_DEVICE* serial, UINT32 file_id, UINT32 DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); tty = serial->tty; + if(!tty) + { + DEBUG_WARN("tty = %p", tty); + return; + } switch (abort_io) { @@ -433,6 +445,11 @@ static void serial_check_for_events(SERIAL_DEVICE* serial) SERIAL_TTY* tty; tty = serial->tty; + if(!tty) + { + DEBUG_WARN("tty = %p", tty); + return; + } DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); @@ -478,6 +495,11 @@ void serial_get_timeouts(SERIAL_DEVICE* serial, IRP* irp, UINT32* timeout, UINT3 DEBUG_SVC("length read %u", Length); tty = serial->tty; + if(!tty) + { + DEBUG_WARN("tty = %p", tty); + return; + } *timeout = (tty->read_total_timeout_multiplier * Length) + tty->read_total_timeout_constant; *interval_timeout = tty->read_interval_timeout; @@ -492,6 +514,11 @@ static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp) SERIAL_TTY* tty; tty = serial->tty; + if(!tty) + { + DEBUG_WARN("tty = %p", tty); + return; + } switch (irp->MajorFunction) { @@ -542,6 +569,11 @@ static void __serial_check_fds(SERIAL_DEVICE* serial) ZeroMemory(&serial->tv, sizeof(struct timeval)); tty = serial->tty; + if(!tty) + { + DEBUG_WARN("tty = %p", tty); + return; + } /* scan every pending */ irp = list_peek(serial->pending_irps); @@ -604,6 +636,11 @@ static void serial_set_fds(SERIAL_DEVICE* serial) DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); tty = serial->tty; + if(!tty) + { + DEBUG_WARN("tty = %p", tty); + return; + } irp = (IRP*) list_peek(serial->pending_irps); while (irp) @@ -705,7 +742,8 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) serial); - serial->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) serial_thread_func, (void*) serial, 0, NULL); + serial->thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) serial_thread_func, (void*) serial, 0, NULL); } return 0; diff --git a/channels/serial/client/serial_tty.c b/channels/serial/client/serial_tty.c index 23445b2ca..95bf375fe 100644 --- a/channels/serial/client/serial_tty.c +++ b/channels/serial/client/serial_tty.c @@ -412,7 +412,11 @@ BOOL serial_tty_read(SERIAL_TTY* tty, BYTE* buffer, UINT32* Length) status = read(tty->fd, buffer, *Length); if (status < 0) + { + DEBUG_WARN("failed with %zd, errno=[%d] %s\n", + status, errno, strerror(errno)); return FALSE; + } tty->event_txempty = status; *Length = status; @@ -456,6 +460,9 @@ void serial_tty_free(SERIAL_TTY* tty) { DEBUG_SVC("in"); + if(!tty) + return; + if (tty->fd >= 0) { if (tty->pold_termios) diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c index fa4dd0b3d..4efff88ff 100644 --- a/channels/smartcard/client/smartcard_main.c +++ b/channels/smartcard/client/smartcard_main.c @@ -44,8 +44,7 @@ static void smartcard_free(DEVICE* dev) SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) dev; SetEvent(smartcard->stopEvent); - CloseHandle(smartcard->thread); - CloseHandle(smartcard->irpEvent); + WaitForSingleObject(smartcard->thread, INFINITE); while ((irp = (IRP*) InterlockedPopEntrySList(smartcard->pIrpList)) != NULL) irp->Discard(irp); @@ -55,8 +54,14 @@ static void smartcard_free(DEVICE* dev) /* Begin TS Client defect workaround. */ while ((CompletionIdInfo = (COMPLETIONIDINFO*) list_dequeue(smartcard->CompletionIds)) != NULL) - free(CompletionIdInfo); + free(CompletionIdInfo); + CloseHandle(smartcard->thread); + CloseHandle(smartcard->irpEvent); + CloseHandle(smartcard->stopEvent); + CloseHandle(smartcard->CompletionIdsMutex); + + Stream_Free(smartcard->device.data, TRUE); list_free(smartcard->CompletionIds); /* End TS Client defect workaround. */ @@ -119,13 +124,16 @@ static void smartcard_process_irp_thread_func(SMARTCARD_IRP_WORKER* irpWorker) static void* smartcard_thread_func(void* arg) { SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg; + HANDLE ev[] = {smartcard->irpEvent, smartcard->stopEvent}; while (1) { - WaitForSingleObject(smartcard->irpEvent, INFINITE); + DWORD status = WaitForSingleObject(2, ev, FALSE, INFINITE); - if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0) + if (status == WAIT_OBJECT_0 + 1) break; + else if(status != WAIT_OBJECT_0) + continue; ResetEvent(smartcard->irpEvent); smartcard_process_irp_list(smartcard); diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index baecfe7a4..1ccfaea17 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -19,7 +19,7 @@ set(MODULE_NAME "xfreerdp-client") set(MODULE_PREFIX "FREERDP_CLIENT_X11_CONTROL") -include(FindXmlto) +include(FindDocBookXSL) include_directories(${X11_INCLUDE_DIRS}) set(${MODULE_PREFIX}_SRCS @@ -68,18 +68,43 @@ set(${MODULE_PREFIX}_LIBS ${CMAKE_DL_LIBS}) if(WITH_MANPAGES) - if(XMLTO_FOUND) + find_program( XSLTPROC_EXECUTABLE NAMES xsltproc) + + if(DOCBOOKXSL_FOUND AND XSLTPROC_EXECUTABLE) + + # We need the variable ${MAN_TODAY} to contain the current date in ISO + # format to replace it in the configure_file step. + include(today) + + TODAY(MAN_TODAY) + + configure_file(xfreerdp.1.xml.in xfreerdp.1.xml @ONLY IMMEDIATE) + + add_executable(generate_argument_docbook + generate_argument_docbook.c) + target_link_libraries(generate_argument_docbook winpr-utils freerdp-core freerdp-utils freerdp-client) + add_custom_command(OUTPUT xfreerdp.1 - COMMAND ${XMLTO_EXECUTABLE} man ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp.1.xml - DEPENDS xfreerdp.1.xml) + COMMAND generate_argument_docbook + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${XSLTPROC_EXECUTABLE} ${DOCBOOKXSL_DIR}/manpages/docbook.xsl xfreerdp.1.xml + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS + ${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml + generate_argument_docbook) add_custom_target(xfreerdp.manpage ALL DEPENDS xfreerdp.1) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1 DESTINATION share/man/man1) - else(XMLTO_FOUND) - message(WARNING "WITH_MANPAGES was set, but xmlto was not found. man-pages will not be installed") - endif(XMLTO_FOUND) + else(DOCBOOKXSL_FOUND AND XSLTPROC_EXECUTABLE) + message(WARNING "WITH_MANPAGES was set, but xsltproc was not found. man-pages will not be installed") + endif(DOCBOOKXSL_FOUND AND XSLTPROC_EXECUTABLE) endif(WITH_MANPAGES) set(XSHM_FEATURE_TYPE "REQUIRED") diff --git a/client/X11/generate_argument_docbook.c b/client/X11/generate_argument_docbook.c new file mode 100644 index 000000000..0c1da21a8 --- /dev/null +++ b/client/X11/generate_argument_docbook.c @@ -0,0 +1,177 @@ + +#include +#include +#include + +#include + +/* We need to include the command line c file to get access to + * the argument struct. */ +#include "../common/cmdline.c" + +LPSTR tmp = NULL; + +LPCSTR tr_esc_str(LPCSTR arg) +{ + size_t cs = 0, x, ds; + size_t s; + + if( NULL == arg ) + return NULL; + + s = strlen(arg); + + /* Find trailing whitespaces */ + while( (s > 0) && isspace(arg[s-1])) + s--; + + /* Prepare a initial buffer with the size of the result string. */ + tmp = malloc(s * sizeof(LPCSTR)); + if( NULL == tmp ) + { + fprintf(stderr, "Could not allocate string buffer."); + exit(-2); + } + + /* Copy character for character and check, if it is necessary to escape. */ + ds = s + 1; + for(x=0; x': + ds += 3; + tmp = realloc(tmp, ds * sizeof(LPCSTR)); + if( NULL == tmp ) + { + fprintf(stderr, "Could not reallocate string buffer."); + exit(-4); + } + tmp[cs++] = '&'; + tmp[cs++] = 'g'; + tmp[cs++] = 't'; + tmp[cs++] = ';'; + break; + case '\'': + ds += 5; + tmp = realloc(tmp, ds * sizeof(LPCSTR)); + if( NULL == tmp ) + { + fprintf(stderr, "Could not reallocate string buffer."); + exit(-5); + } + tmp[cs++] = '&'; + tmp[cs++] = 'a'; + tmp[cs++] = 'p'; + tmp[cs++] = 'o'; + tmp[cs++] = 's'; + tmp[cs++] = ';'; + break; + case '"': + ds += 5; + tmp = realloc(tmp, ds * sizeof(LPCSTR)); + if( NULL == tmp ) + { + fprintf(stderr, "Could not reallocate string buffer."); + exit(-6); + } + tmp[cs++] = '&'; + tmp[cs++] = 'q'; + tmp[cs++] = 'u'; + tmp[cs++] = 'o'; + tmp[cs++] = 't'; + tmp[cs++] = ';'; + break; + case '&': + ds += 4; + tmp = realloc(tmp, ds * sizeof(LPCSTR)); + if( NULL == tmp ) + { + fprintf(stderr, "Could not reallocate string buffer."); + exit(-7); + } + tmp[cs++] = '&'; + tmp[cs++] = 'a'; + tmp[cs++] = 'm'; + tmp[cs++] = 'p'; + tmp[cs++] = ';'; + break; + default: + tmp[cs++] = arg[x]; + break; + } + + /* Assure, the string is '\0' terminated. */ + tmp[ds-1] = '\0'; + } + + return tmp; +} + +int main(int argc, char *argv[]) +{ + size_t elements = sizeof(args)/sizeof(args[0]); + size_t x; + const char *fname = "xfreerdp-argument.1.xml"; + FILE *fp = NULL; + + /* Open output file for writing, truncate if existing. */ + fp = fopen(fname, "w"); + if( NULL == fp ) + { + fprintf(stderr, "Could not open '%s' for writing.", fname); + return -1; + } + + /* The tag used as header in the manpage */ + fprintf(fp, "\n"); + fprintf(fp, "\tOptions\n"); + fprintf(fp, "\t\t\n"); + + /* Iterate over argument struct and write data to docbook 4.5 + * compatible XML */ + if( elements < 2 ) + { + fprintf(stderr, "The argument array 'args' is empty, writing an empty file."); + elements = 1; + } + + for(x=0; x\n"); + if( COMMAND_LINE_VALUE_REQUIRED == arg->Flags ) + fprintf(fp, "\t\t\t\t %s\n", tr_esc_str(arg->Name), tr_esc_str(arg->Format) ); + else + fprintf(fp, "\t\t\t\t\n", tr_esc_str(arg->Name) ); + fprintf(fp, "\t\t\t\t\n"); + fprintf(fp, "\t\t\t\t\t%s\n", tr_esc_str(arg->Text)); + + fprintf(fp, "\t\t\t\t\n"); + fprintf(fp, "\t\t\t\n"); + } + + fprintf(fp, "\t\t\n"); + fprintf(fp, "\t\n"); + fclose(fp); + + if(NULL != tmp) + free(tmp); + + return 0; +} + diff --git a/client/X11/xfreerdp-channels.1.xml b/client/X11/xfreerdp-channels.1.xml new file mode 100644 index 000000000..e69de29bb diff --git a/client/X11/xfreerdp-examples.1.xml b/client/X11/xfreerdp-examples.1.xml new file mode 100644 index 000000000..462649f68 --- /dev/null +++ b/client/X11/xfreerdp-examples.1.xml @@ -0,0 +1,89 @@ + + Examples + + + xfreerdp connection.rdp /p:Pwd123! /f + + Connect in fullscreen mode using a stored configuration connection.rdp and the password Pwd123! + + + + xfreerdp /u:CONTOSO\\JohnDoe /p:Pwd123! /v:rdp.contoso.com + + Connect to host rdp.contoso.com with user CONTOSO\\JohnDoe and password Pwd123! + + + + xfreerdp /u:JohnDoe /p:Pwd123! /w:1366 /h:768 /v:192.168.1.100:4489 + + Connect to host 192.168.1.100 on port 4489 with user JohnDoe, password Pwd123!. The screen width is set to 1366 and the height to 768 + + + + xfreerdp /u:JohnDoe /p:Pwd123! /vmconnect:C824F53E-95D2-46C6-9A18-23A5BB403532 /v:192.168. 1.100 + + Establish a connection to host 192.168.1.100 with user JohnDoe, password Pwd123! and connect to Hyper-V console (use port 2179, disable negotiation) with VMID C824F53E-95D2-46C6-9A18-23A5BB403532 + + + + +clipboard + + Activate clipboard redirection + + + + /drive:home,/home/user + + Activate drive redirection of /home/user as home drive + + + + /smartcard:<device> + + Activate smartcard redirection for device device + + + + /printer:<device>,<driver> + + Activate printer redirection for printer device using driver driver + + + + /serial:<device> + + Activate serial port redirection for port device + + + + /parallel:<device> + + Activate parallel port redirection for port device + + + + /sound:sys:alsa + + Activate audio output redirection using device sys:alsa + + + + /microphone:sys:alsa + + Activate audio input redirection using device sys:alsa + + + + /multimedia:sys:alsa + + Activate multimedia redirection using device sys:alsa + + + + /usb:id,dev:054c:0268 + + Activate USB device redirection for the device identified by 054c:0268 + + + + diff --git a/client/X11/xfreerdp.1.xml b/client/X11/xfreerdp.1.xml deleted file mode 100644 index bf7f774e6..000000000 --- a/client/X11/xfreerdp.1.xml +++ /dev/null @@ -1,571 +0,0 @@ - - - - 2011-08-27 - - The FreeRDP Team - - - - xfreerdp - 1 - freerdp - xfreerdp - - - xfreerdp - FreeRDP X11 client - - - - 2011-08-27 - - - xfreerdp [options] server[:port] [[options] server[:port] …] - - - - - 2011-08-27 - - DESCRIPTION - - xfreerdp is an X11 Remote Desktop Protocol (RDP) - client which is part of the FreeRDP project. An RDP server is built-in - to many editions of Windows. Alternative servers included xrdp and VRDP (VirtualBox). - - - - OPTIONS - - - -0 - - - Attach to the admin console of the server. - - - - - -a bpp - - - Sets the color depth for the connection to bpp bits per pixel. - Valid values are 8, 15, 16, 24 and 32. The default value is the color depth of the FreeRDP-window. - - - - - -c dir - - - Sets the working-dir to dir. - This parameter is only used when an AlternateShell () is requested. - dir should contain the executable file specified in the AlternateShell. - - - - - -D - - - Removes the windows decorations. - - - - - -d - - - Domain used in authentication. - - - - - -f - - - start in full screen mode. This mode can always be en- and disabled using Ctrl-Alt-Enter. - - - - - -T text - - - Sets the window title to text. - - - - - -g geometry - - - Sets the size of the FreeRDP window (and of the remote desktop, when establishing a new connection). - geometry can have one of the following forms: - - - - WxH - - in this case the resulting window will be of - WxH pixels. - - - - - P% - - in this case the resulting window will be P% - of your screen. - - - - - The special keyword workarea - - in this case the resulting window will be of the same size as your workarea. - - - - - - - - -h - - - Print help. - - - - - -k id - - - Sets the keyboard-layout-id to id. - - - - - -K - - - Do not interfere with window manager bindings. Normally, xfreerdp captures all keystrokes while its window is focused. - - - - - -n hostname - - - Set the reported client hostname to hostname. - Default is to automatically detect the hostname. - - - - - -o - - - Play audio on the console instead of redirecting to the client. - - - - - -p password - - - Password used in authentication. - - - - - -s shell - - - Sets the startup-shell to shell. - This parameter should contain a complete path to the alternate shell. - If the alternete shell requires a different working directory use . - - - - - -t port - - - Connect to port, instead of the default 3389. - - - - - -u username - - - Username used in authentication. - - - - - -x flag - - - Set the experience performance flags. - flag can be one of: - - - - m - (modem): Equivalent to 15. - - - - - b - (broadband): Equivalent to 1. - - - - - l - (lan): Equivalent to 0. - - - - - num - A hexadecimal number that - represents a bit-mask, were numbers mean the following - Taken from - MS-RDPBCGR Section 2.2.1.11.1.1.1 - Extended Info Packet: - - - 1: Disable desktop wallpaper. - - - 2: Disable full-window drag (only the window outline is displayed when the window is moved). - - - 4: Disable menu animations. - - - 8: Disable user interface themes. - - - 20: Disable mouse cursor shadows. - - - 40: Disable cursor blinking. - - - 80: Enable font smoothing. - - - 100: Enable Desktop Composition. - - - - - - - - - - -X xid - - embed xfreerdp into window with xid. - - - - -z - - - Enable compression. - - - - - --app - - - initialize a RemoteApp connection. This implies -g workarea. - - - - - --no-auth - - - Skips authentication. This is useful e.g. for the current FreeRDP server that doesn't yet support server-side authentication. - - - - - --authonly - - - Only authenticates. This is useful to test your credentials (username and password). - Returns status code 0 if the client can connect, 1 otherwise. Requires a username, - password and connection host at the command line. - - - - - --bcv3 codec - - Use codec for bitmap cache v3 - - - - - --no-bmp-cache - - - Disable bitmap cache. - - - - - --certificate-name name - - - use name for the logon certificate, instead of the server name - - - - - --composition - - - Enable composition (RDVH only, not to be confused with remote composition). - - - - - --ext extname - - - load extension extname - - - - - --no-fastpath - - - Disables fast-path. Use slow-path packets instead, which have larger headers. - It might be good for debugging certain issues when you suspect it might be - linked to the parsing of one of the two header types. - - - - - --from-stdin - - Prompts for unspecified arguments -u username, -p - password, -d domain and connection host. This is useful to - hide arguments from ps. Also useful for scripts that will - feed these arguments to the client via (what else?) stdin. - - - - - --disable-full-window-drag - - - Disable full window drag. - - - - - --gdi backend - - - GDI (Graphics Device Interface) rendering backend. backend can be either sw (software) or hw (hardware). - - - - - --ignore-certificate - - - ignore verification of logon certificate. - - - - - --kbd-list - - - list all keyboard layout ids used by -k - - - - - --disable-menu-animations - - - Disable menu animations. - - - - - --no-motion - - - Don't send mouse motion events. - - - - - --no-nego - - disable negotiation of security layer and enforce highest enabled security protocol. - - - - - --no-nla - - - Disable network level authentication. - - - - - --nsc - - - Enable NSCodec. - - - - - --no-osb - - - Disable off screen bitmaps. - - - - - --pcb blob - - - Use preconnection blob. - - - - - --pcid id - - - Use preconnection id. - - - - - --plugin pluginname - - - load pluginname - - - - - --no-rdp - - - Disable Standard RDP encryption. - - - - - --rfx - - - Enable RemoteFX. - - - - - --rfx-mode - - - RemoteFX operational flags. flags can be either v[ideo], i[mage]), default is video. - - - - - --no-salted-checksum - - - disable salted checksums with Standard RDP encryption. - - - - - --ntlm - - - force NTLM protocol version. version can be one of 1 or 2. - - - - - --sec proto - - - force protocol security. proto can be one of rdp, tls or nla. - - - - - --disable-theming - - - Disable theming. - - - - - --no-tls - - - Disable TLS encryption. - - - - - --tsg -username -password -hostname - - - Use Terminal Server Gateway with -username -password -hostname. - - - - - --version - - - Print version information. - - - - - --disable-wallpaper - - - Disable wallpaper. - - - - - - - LINKS - - http://www.freerdp.com/ - - - diff --git a/client/X11/xfreerdp.1.xml.in b/client/X11/xfreerdp.1.xml.in new file mode 100644 index 000000000..4dbb42083 --- /dev/null +++ b/client/X11/xfreerdp.1.xml.in @@ -0,0 +1,60 @@ + + + + + ] +> + + + + @MAN_TODAY@ + + The FreeRDP Team + + + + xfreerdp + 1 + freerdp + xfreerdp + + + xfreerdp + FreeRDP X11 client + + + + @MAN_TODAY@ + + + xfreerdp [file] [options] [/v:server[:port]] + + + + + @MAN_TODAY@ + + DESCRIPTION + + xfreerdp is an X11 Remote Desktop Protocol (RDP) + client which is part of the FreeRDP project. An RDP server is built-in + to many editions of Windows. Alternative servers included xrdp and VRDP (VirtualBox). + + + + &syntax; + + &channels; + + &examples; + + + LINKS + + http://www.freerdp.com/ + + + diff --git a/client/common/CMakeLists.txt b/client/common/CMakeLists.txt index 954f3a46f..2b9841e5f 100644 --- a/client/common/CMakeLists.txt +++ b/client/common/CMakeLists.txt @@ -25,9 +25,10 @@ set(${MODULE_PREFIX}_SRCS compatibility.h file.c) -set(FREERDP_CHANNELS_CLIENT_PATH "../../channels/client") foreach(FREERDP_CHANNELS_CLIENT_SRC ${FREERDP_CHANNELS_CLIENT_SRCS}) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} "${FREERDP_CHANNELS_CLIENT_PATH}/${FREERDP_CHANNELS_CLIENT_SRC}") + get_filename_component(NINC ${FREERDP_CHANNELS_CLIENT_SRC} PATH) + include_directories(${NINC}) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} "${FREERDP_CHANNELS_CLIENT_SRC}") endforeach() if(MSVC) diff --git a/cmake/FindDocBookXSL.cmake b/cmake/FindDocBookXSL.cmake new file mode 100644 index 000000000..9192ef9b3 --- /dev/null +++ b/cmake/FindDocBookXSL.cmake @@ -0,0 +1,52 @@ +# Try to find DocBook XSL stylesheet +# Once done, it will define: +# +# DOCBOOKXSL_FOUND - system has the required DocBook XML DTDs +# DOCBOOKXSL_DIR - the directory containing the stylesheets +# used to process DocBook XML + +# Copyright (c) 2010, Luigi Toscano, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +set (STYLESHEET_PATH_LIST + share/xml/docbook/stylesheet/docbook-xsl + share/xml/docbook/xsl-stylesheets + share/sgml/docbook/xsl-stylesheets + share/xml/docbook/stylesheet/nwalsh/current + share/xml/docbook/stylesheet/nwalsh + share/xsl/docbook + share/xsl/docbook-xsl +) + +find_path (DOCBOOKXSL_DIR lib/lib.xsl + PATHS ${CMAKE_SYSTEM_PREFIX_PATH} + PATH_SUFFIXES ${STYLESHEET_PATH_LIST} +) + +if (NOT DOCBOOKXSL_DIR) + # hacks for systems that put the version in the stylesheet dirs + set (STYLESHEET_PATH_LIST) + foreach (STYLESHEET_PREFIX_ITER ${CMAKE_SYSTEM_PREFIX_PATH}) + file(GLOB STYLESHEET_SUFFIX_ITER RELATIVE ${STYLESHEET_PREFIX_ITER} + ${STYLESHEET_PREFIX_ITER}/share/xml/docbook/xsl-stylesheets-* + ) + if (STYLESHEET_SUFFIX_ITER) + list (APPEND STYLESHEET_PATH_LIST ${STYLESHEET_SUFFIX_ITER}) + endif () + endforeach () + + find_path (DOCBOOKXSL_DIR VERSION + PATHS ${CMAKE_SYSTEM_PREFIX_PATH} + PATH_SUFFIXES ${STYLESHEET_PATH_LIST} + ) +endif (NOT DOCBOOKXSL_DIR) + + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args (DocBookXSL + "Could NOT find DocBook XSL stylesheets" + DOCBOOKXSL_DIR) + +mark_as_advanced (DOCBOOKXSL_DIR) diff --git a/cmake/today.cmake b/cmake/today.cmake new file mode 100644 index 000000000..51d0031a8 --- /dev/null +++ b/cmake/today.cmake @@ -0,0 +1,16 @@ +# This script returns the current date in ISO format +# +# YYYY-MM-DD +# +MACRO (TODAY RESULT) + IF (WIN32) + EXECUTE_PROCESS(COMMAND "cmd" " /C date +%Y-%m-%d" OUTPUT_VARIABLE ${RESULT}) + string(REGEX REPLACE "(..)/(..)/..(..).*" "\\1/\\2/\\3" ${RESULT} ${${RESULT}}) + ELSEIF(UNIX) + EXECUTE_PROCESS(COMMAND "date" "+%Y-%m-%d" OUTPUT_VARIABLE ${RESULT}) + string(REGEX REPLACE "(..)/(..)/..(..).*" "\\1/\\2/\\3" ${RESULT} ${${RESULT}}) + ELSE (WIN32) + MESSAGE(SEND_ERROR "date not implemented") + SET(${RESULT} 000000) + ENDIF (WIN32) +ENDMACRO (TODAY) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index b42f23086..e2cfdc283 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -292,24 +292,38 @@ BOOL rdp_client_redirect(rdpRdp* rdp) rdp_client_disconnect(rdp); /* FIXME: this is a subset of rdp_free */ + /* --> this should really go into rdp.c */ crypto_rc4_free(rdp->rc4_decrypt_key); + rdp->rc4_decrypt_key = NULL ; crypto_rc4_free(rdp->rc4_encrypt_key); + rdp->rc4_encrypt_key = NULL; crypto_des3_free(rdp->fips_encrypt); + rdp->fips_encrypt = NULL ; crypto_des3_free(rdp->fips_decrypt); + rdp->fips_decrypt = NULL ; crypto_hmac_free(rdp->fips_hmac); + rdp->fips_hmac = NULL ; + + free(settings->ServerRandom); + settings->ServerRandom = NULL ; + free(settings->ServerCertificate); + settings->ServerCertificate = NULL ; + free(settings->ClientAddress); + settings->ClientAddress = NULL ; + + mppc_enc_free(rdp->mppc_enc); + mppc_dec_free(rdp->mppc_dec); mcs_free(rdp->mcs); nego_free(rdp->nego); license_free(rdp->license); transport_free(rdp->transport); - free(settings->ServerRandom); - free(settings->ServerCertificate); - free(settings->ClientAddress); - rdp->transport = transport_new(settings); rdp->license = license_new(rdp); rdp->nego = nego_new(rdp->transport); rdp->mcs = mcs_new(rdp->transport); + rdp->mppc_dec = mppc_dec_new(); + rdp->mppc_enc = mppc_enc_new(PROTO_RDP_50); rdp->transport->layer = TRANSPORT_LAYER_TCP; settings->RedirectedSessionId = redirection->sessionID; diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 03ffb2971..9aa30fd71 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -739,7 +739,11 @@ int transport_check_fds(rdpTransport** ptransport) recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra); - Stream_Release(received); + if (transport == *ptransport) + /* transport might now have been freed by rdp_client_redirect and a new rdp->transport created */ + /* so only release if still valid */ + Stream_Release(received); + if (recv_status < 0) status = -1; diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index 9e265095e..81904788c 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -63,11 +63,14 @@ endif() if(FREERDP_BUILD) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE) + include_directories(${CMAKE_CURRENT_BINARY_DIR}/include PARENT_SCOPE) else() include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) endif() -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/winpr/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/include/winpr/config.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/winpr/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/include/winpr/config.h) if(NOT WITH_WAYK) add_subdirectory(include) diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c index d488b0eea..a8d9aeff3 100644 --- a/winpr/libwinpr/synch/wait.c +++ b/winpr/libwinpr/synch/wait.c @@ -25,6 +25,8 @@ #include #endif +#include + #include #include @@ -43,6 +45,18 @@ #include "../handle/handle.h" +static void ts_add_ms(struct timespec *ts, DWORD dwMilliseconds) +{ + ts->tv_sec += dwMilliseconds / 1000L; + ts->tv_nsec += (dwMilliseconds % 1000L) * 1000000L; + + while(ts->tv_nsec >= 1000000000L) + { + ts->tv_sec ++; + ts->tv_nsec -= 1000000000L; + } +} + DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) { ULONG Type; @@ -53,18 +67,30 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) if (Type == HANDLE_TYPE_THREAD) { - int status; + int status = 0; WINPR_THREAD* thread; void* thread_status = NULL; - if (dwMilliseconds != INFINITE) - fprintf(stderr, "WaitForSingleObject: timeout not implemented for thread wait\n"); - thread = (WINPR_THREAD*) Object; if (thread->started) { - status = pthread_join(thread->thread, &thread_status); + if (dwMilliseconds != INFINITE) + { +#if _GNU_SOURCE + struct timespec timeout; + + clock_gettime(CLOCK_REALTIME, &timeout); + ts_add_ms(&timeout, dwMilliseconds); + + status = pthread_timedjoin_np(thread->thread, &thread_status, &timeout); +#else + fprintf(stderr, "[ERROR] %s: Thread timeouts not implemented.\n", __func__); + assert(0); +#endif + } + else + status = pthread_join(thread->thread, &thread_status); if (status != 0) fprintf(stderr, "WaitForSingleObject: pthread_join failure: %d\n", status); @@ -80,9 +106,16 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) mutex = (WINPR_MUTEX*) Object; if (dwMilliseconds != INFINITE) - fprintf(stderr, "WaitForSingleObject: timeout not implemented for mutex wait\n"); + { + struct timespec timeout; - pthread_mutex_lock(&mutex->mutex); + clock_gettime(CLOCK_REALTIME, &timeout); + ts_add_ms(&timeout, dwMilliseconds); + + pthread_mutex_timedlock(&mutex->mutex, &timeout); + } + else + pthread_mutex_lock(&mutex->mutex); } else if (Type == HANDLE_TYPE_EVENT) { @@ -213,6 +246,8 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable) { + fprintf(stderr, "[ERROR] %s: Function not implemented.\n", __func__); + assert(0); return WAIT_OBJECT_0; } @@ -235,7 +270,10 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl ZeroMemory(&timeout, sizeof(timeout)); if (bWaitAll) + { fprintf(stderr, "WaitForMultipleObjects: bWaitAll not yet implemented\n"); + assert(0); + } for (index = 0; index < nCount; index++) { @@ -336,11 +374,15 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl DWORD WaitForMultipleObjectsEx(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable) { + fprintf(stderr, "[ERROR] %s: Function not implemented.\n", __func__); + assert(0); return 0; } DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable) { + fprintf(stderr, "[ERROR] %s: Function not implemented.\n", __func__); + assert(0); return 0; } diff --git a/winpr/libwinpr/utils/collections/StreamPool.c b/winpr/libwinpr/utils/collections/StreamPool.c index 4df2fe8b3..dab11c0e2 100644 --- a/winpr/libwinpr/utils/collections/StreamPool.c +++ b/winpr/libwinpr/utils/collections/StreamPool.c @@ -44,7 +44,8 @@ void StreamPool_ShiftUsed(wStreamPool* pool, int index, int count) } else if (count < 0) { - MoveMemory(&pool->uArray[index], &pool->uArray[index - count], (pool->uSize - index) * sizeof(wStream*)); + if (pool->uSize - index + count > 0) + MoveMemory(&pool->uArray[index], &pool->uArray[index - count], (pool->uSize - index + count) * sizeof(wStream*)); pool->uSize += count; } } @@ -101,7 +102,8 @@ void StreamPool_ShiftAvailable(wStreamPool* pool, int index, int count) } else if (count < 0) { - MoveMemory(&pool->aArray[index], &pool->aArray[index - count], (pool->aSize - index) * sizeof(wStream*)); + if (pool->aSize - index + count > 0) + MoveMemory(&pool->aArray[index], &pool->aArray[index - count], (pool->aSize - index + count) * sizeof(wStream*)); pool->aSize += count; } }