From 9a34f3e1815bb8fa54681b556ad0e4271f705c10 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 29 Feb 2016 16:49:14 +0000 Subject: [PATCH] Imported Upstream version 2.0.0~gitb4b8239 --- CMakeLists.txt | 133 +- ChangeLog | 915 ++++++++- channels/audin/client/audin_main.c | 2 + .../audin/client/opensles/audin_opensl_es.c | 3 - channels/cliprdr/client/module.def | 3 - channels/disp/client/disp_main.c | 2 + channels/drdynvc/client/drdynvc_main.c | 5 +- channels/drive/client/dirent.h | 2 +- channels/drive/client/drive_main.c | 2 + channels/drive/client/module.def | 3 - channels/drive/client/statvfs.c | 13 +- channels/echo/client/echo_main.c | 2 + channels/parallel/client/parallel_main.c | 2 + channels/printer/client/printer_cups.c | 26 +- channels/printer/client/printer_main.c | 10 +- channels/printer/client/printer_main.h | 16 +- channels/printer/client/printer_win.c | 28 +- channels/printer/printer.h | 37 + channels/rdpdr/client/devman.c | 19 + channels/rdpdr/client/irp.c | 21 +- channels/rdpdr/client/irp.h | 2 +- channels/rdpdr/client/rdpdr_capabilities.c | 109 +- channels/rdpdr/client/rdpdr_capabilities.h | 2 +- channels/rdpdr/client/rdpdr_main.c | 362 ++-- channels/rdpei/client/rdpei_main.c | 2 + channels/rdpgfx/client/rdpgfx_main.c | 2 + channels/rdpsnd/client/mac/rdpsnd_mac.c | 124 +- channels/serial/client/serial_main.c | 2 + .../tsmf/client/gstreamer/tsmf_gstreamer.c | 3 +- channels/tsmf/client/tsmf_main.c | 2 + channels/tsmf/client/tsmf_media.c | 16 +- channels/urbdrc/client/urbdrc_main.c | 4 +- ci/cmake-preloads/config-windows.txt | 1 + client/FreeRDP-ClientConfig.cmake.in | 8 +- client/Wayland/CMakeLists.txt | 14 +- client/Wayland/wlf_display.c | 112 -- client/Wayland/wlf_display.h | 43 - client/Wayland/wlf_input.c | 204 +- client/Wayland/wlf_input.h | 25 +- client/Wayland/wlf_window.c | 220 -- client/Wayland/wlf_window.h | 58 - client/Wayland/wlfreerdp.c | 199 +- client/Wayland/wlfreerdp.h | 12 +- client/X11/xf_client.c | 161 +- client/X11/xf_cliprdr.c | 531 ++++- client/common/CMakeLists.txt | 2 +- client/common/client.c | 227 ++- client/common/cmdline.c | 376 ++-- client/common/file.c | 6 +- client/common/module.def | 3 - cmake/AndroidToolchain.cmake | 2 +- cmake/ConfigOptions.cmake | 2 + cmake/ConfigOptionsAndroid.cmake | 11 - cmake/FindWayland.cmake | 66 +- cmake/WindowsDLLVersion.rc.in | 2 +- config.h.in | 3 - docs/README.android | 221 +- include/freerdp/client.h | 12 + include/freerdp/client/cmdline.h | 19 +- include/freerdp/codec/region.h | 6 +- include/freerdp/crypto/crypto.h | 71 +- include/freerdp/crypto/tls.h | 2 +- include/freerdp/freerdp.h | 57 +- include/freerdp/locale/timezone.h | 37 - include/freerdp/server/shadow.h | 2 + include/freerdp/session.h | 48 + include/freerdp/settings.h | 41 +- include/freerdp/update.h | 9 +- libfreerdp/cache/glyph.c | 2 +- libfreerdp/codec/nsc.c | 4 - libfreerdp/codec/nsc_encode.c | 4 - libfreerdp/codec/region.c | 6 +- libfreerdp/codec/rfx.c | 4 - libfreerdp/common/assistance.c | 32 +- libfreerdp/common/settings.c | 38 + libfreerdp/core/activation.c | 25 + libfreerdp/core/autodetect.c | 6 +- libfreerdp/core/capabilities.c | 531 +++-- libfreerdp/core/capabilities.h | 4 +- libfreerdp/core/certificate.c | 95 +- libfreerdp/core/certificate.h | 1 + libfreerdp/core/connection.c | 89 +- libfreerdp/core/errconnect.c | 2 +- libfreerdp/core/errinfo.c | 2 +- libfreerdp/core/freerdp.c | 37 +- libfreerdp/core/gateway/ncacn_http.c | 2 - libfreerdp/core/gateway/ntlm.c | 1 - libfreerdp/core/gateway/rdg.c | 19 +- libfreerdp/core/gateway/rpc.c | 1 - libfreerdp/core/gateway/rts.c | 3 +- libfreerdp/core/gcc.c | 39 +- libfreerdp/core/info.c | 296 ++- libfreerdp/core/info.h | 20 +- libfreerdp/core/license.c | 57 +- libfreerdp/core/nego.c | 2 +- libfreerdp/core/nla.h | 3 +- libfreerdp/core/peer.c | 10 +- libfreerdp/core/rdp.c | 62 +- libfreerdp/core/rdp.h | 13 +- libfreerdp/core/security.c | 376 ++-- libfreerdp/core/settings.c | 21 +- libfreerdp/core/tcp.c | 6 +- libfreerdp/core/test/TestConnect.c | 2 +- libfreerdp/core/test/TestVersion.c | 4 + libfreerdp/core/timezone.c | 99 +- libfreerdp/core/timezone.h | 6 +- libfreerdp/core/transport.c | 67 +- libfreerdp/core/update.c | 3 + libfreerdp/crypto/crypto.c | 172 +- libfreerdp/crypto/tls.c | 165 +- libfreerdp/gdi/16bpp.c | 2 +- libfreerdp/gdi/8bpp.c | 2 +- libfreerdp/gdi/region.c | 4 +- libfreerdp/locale/CMakeLists.txt | 1 - libfreerdp/locale/timezone.c | 1770 ----------------- libfreerdp/primitives/prim_colors_opt.c | 4 +- packaging/deb/freerdp-nightly/rules | 1 + rdtk/CMakeLists.txt | 3 +- rdtk/librdtk/CMakeLists.txt | 2 +- scripts/android-build-common.sh | 252 +++ scripts/android-build-freerdp.sh | 140 ++ scripts/android-build-jpeg.sh | 41 + scripts/android-build-openh264.sh | 58 + scripts/android-build-openssl.sh | 121 ++ scripts/android-build.conf | 22 + scripts/android_setup_build_env.sh | 134 -- .../openssl-disable-library-versioning.patch | 24 + server/FreeRDP-ServerConfig.cmake.in | 8 +- server/Sample/sf_encomsp.c | 2 +- server/Windows/wf_interface.c | 16 +- server/common/CMakeLists.txt | 2 +- server/common/module.def | 3 - server/shadow/CMakeLists.txt | 92 +- server/shadow/FreeRDP-ShadowConfig.cmake.in | 10 + server/shadow/Mac/mac_shadow.c | 2 +- server/shadow/Win/win_rdp.c | 6 +- server/shadow/Win/win_shadow.c | 2 +- server/shadow/X11/x11_shadow.c | 2 +- server/shadow/freerdp-shadow.pc.in | 15 + server/shadow/shadow.c | 24 +- server/shadow/shadow_subsystem_builtin.c | 96 + uwac/CMakeLists.txt | 52 + uwac/include/CMakeLists.txt | 19 + uwac/include/uwac/uwac-tools.h | 60 + uwac/include/uwac/uwac.h | 486 +++++ uwac/libuwac/.gitignore | 7 + uwac/libuwac/CMakeLists.txt | 80 + uwac/libuwac/uwac-display.c | 631 ++++++ uwac/libuwac/uwac-input.c | 847 ++++++++ uwac/libuwac/uwac-os.c | 236 +++ uwac/libuwac/uwac-os.h | 45 + uwac/libuwac/uwac-output.c | 126 ++ uwac/libuwac/uwac-priv.h | 237 +++ uwac/libuwac/uwac-tools.c | 93 + uwac/libuwac/uwac-utils.c | 63 + uwac/libuwac/uwac-utils.h | 53 + uwac/libuwac/uwac-window.c | 620 ++++++ uwac/protocols/fullscreen-shell.xml | 206 ++ uwac/protocols/ivi-application.xml | 100 + uwac/protocols/xdg-shell.xml | 608 ++++++ uwac/uwac.pc.in | 15 + uwac/uwacConfig.cmake.in | 9 + uwac/uwacVersion.cmake | 46 + winpr/CMakeLists.txt | 13 +- winpr/include/CMakeLists.txt | 2 + winpr/include/winpr/comm.h | 12 +- winpr/include/winpr/crypto.h | 88 +- winpr/include/winpr/error.h | 1 + winpr/include/winpr/input.h | 49 +- winpr/include/winpr/nt.h | 1 + winpr/include/winpr/sspi.h | 9 +- winpr/include/winpr/string.h | 2 + winpr/include/winpr/user.h | 1 + winpr/include/winpr/winpr.h | 1 + winpr/include/winpr/wlog.h | 3 + winpr/include/winpr/wtypes.h.in | 26 +- winpr/libwinpr/CMakeLists.txt | 4 + winpr/libwinpr/asn1/module.def | 3 - winpr/libwinpr/com/module.def | 2 - winpr/libwinpr/comm/comm_serial_sys.c | 2 +- winpr/libwinpr/comm/module.def | 3 - winpr/libwinpr/credentials/module.def | 2 - winpr/libwinpr/credui/module.def | 2 - winpr/libwinpr/crt/module.def | 2 - winpr/libwinpr/crt/string.c | 39 + winpr/libwinpr/crypto/cipher.c | 114 +- winpr/libwinpr/crypto/crypto.c | 51 +- winpr/libwinpr/crypto/hash.c | 203 +- winpr/libwinpr/crypto/module.def | 3 - winpr/libwinpr/crypto/test/TestCryptoCipher.c | 29 +- winpr/libwinpr/crypto/test/TestCryptoHash.c | 105 +- winpr/libwinpr/dsparse/module.def | 3 - winpr/libwinpr/environment/module.def | 2 - winpr/libwinpr/error/module.def | 3 - winpr/libwinpr/file/file.c | 15 +- winpr/libwinpr/handle/module.def | 3 - winpr/libwinpr/heap/module.def | 2 - winpr/libwinpr/input/keycode.c | 4 +- winpr/libwinpr/input/virtualkey.c | 9 +- winpr/libwinpr/interlocked/module.def | 14 - winpr/libwinpr/io/module.def | 2 - winpr/libwinpr/library/module.def | 3 - .../library/test/TestLibraryA/CMakeLists.txt | 2 +- .../library/test/TestLibraryA/module.def | 4 - .../library/test/TestLibraryB/CMakeLists.txt | 2 +- .../library/test/TestLibraryB/module.def | 4 - winpr/libwinpr/locale/module.def | 2 - winpr/libwinpr/memory/module.def | 3 - winpr/libwinpr/nt/module.def | 3 - winpr/libwinpr/nt/nt.c | 29 +- winpr/libwinpr/nt/nt.h | 45 - winpr/libwinpr/path/shell.c | 5 - winpr/libwinpr/pipe/module.def | 3 - winpr/libwinpr/pool/module.def | 3 - winpr/libwinpr/registry/module.def | 2 - winpr/libwinpr/rpc/module.def | 3 - winpr/libwinpr/security/module.def | 2 - winpr/libwinpr/shell/CMakeLists.txt | 4 +- winpr/libwinpr/smartcard/module.def | 3 - winpr/libwinpr/smartcard/smartcard_pcsc.c | 2 +- winpr/libwinpr/sspi/NTLM/ntlm.c | 108 +- winpr/libwinpr/sspi/NTLM/ntlm.h | 4 +- winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c | 4 +- winpr/libwinpr/sspi/NTLM/ntlm_compute.c | 57 +- winpr/libwinpr/sspi/module.def | 34 - winpr/libwinpr/synch/wait.c | 4 +- winpr/libwinpr/sysinfo/module.def | 3 - winpr/libwinpr/thread/module.def | 3 - winpr/libwinpr/thread/thread.c | 3 +- winpr/libwinpr/timezone/timezone.c | 1731 +++++++++++++++- winpr/libwinpr/utils/image.c | 4 +- winpr/libwinpr/utils/lodepng/lodepng.c | 6 + winpr/libwinpr/utils/ntlm.c | 25 +- winpr/libwinpr/utils/test/TestVersion.c | 4 + winpr/libwinpr/utils/winpr.c | 17 +- winpr/libwinpr/utils/wlog/BinaryAppender.h | 2 +- winpr/libwinpr/utils/wlog/ConsoleAppender.c | 12 + winpr/libwinpr/utils/wlog/FileAppender.c | 2 +- winpr/libwinpr/utils/wlog/wlog.c | 156 +- winpr/libwinpr/winsock/module.def | 3 - winpr/libwinpr/wnd/module.def | 3 - winpr/winpr.pc.in | 2 +- 242 files changed, 12286 insertions(+), 5372 deletions(-) delete mode 100644 channels/cliprdr/client/module.def delete mode 100644 channels/drive/client/module.def create mode 100644 channels/printer/printer.h delete mode 100644 client/Wayland/wlf_display.c delete mode 100644 client/Wayland/wlf_display.h delete mode 100644 client/Wayland/wlf_window.c delete mode 100644 client/Wayland/wlf_window.h delete mode 100644 client/common/module.def delete mode 100644 include/freerdp/locale/timezone.h create mode 100644 include/freerdp/session.h delete mode 100644 libfreerdp/locale/timezone.c create mode 100644 scripts/android-build-common.sh create mode 100755 scripts/android-build-freerdp.sh create mode 100755 scripts/android-build-jpeg.sh create mode 100755 scripts/android-build-openh264.sh create mode 100755 scripts/android-build-openssl.sh create mode 100644 scripts/android-build.conf delete mode 100755 scripts/android_setup_build_env.sh create mode 100644 scripts/openssl-disable-library-versioning.patch delete mode 100644 server/common/module.def create mode 100644 server/shadow/FreeRDP-ShadowConfig.cmake.in create mode 100644 server/shadow/freerdp-shadow.pc.in create mode 100644 server/shadow/shadow_subsystem_builtin.c create mode 100644 uwac/CMakeLists.txt create mode 100644 uwac/include/CMakeLists.txt create mode 100644 uwac/include/uwac/uwac-tools.h create mode 100644 uwac/include/uwac/uwac.h create mode 100644 uwac/libuwac/.gitignore create mode 100644 uwac/libuwac/CMakeLists.txt create mode 100644 uwac/libuwac/uwac-display.c create mode 100644 uwac/libuwac/uwac-input.c create mode 100644 uwac/libuwac/uwac-os.c create mode 100644 uwac/libuwac/uwac-os.h create mode 100644 uwac/libuwac/uwac-output.c create mode 100644 uwac/libuwac/uwac-priv.h create mode 100644 uwac/libuwac/uwac-tools.c create mode 100644 uwac/libuwac/uwac-utils.c create mode 100644 uwac/libuwac/uwac-utils.h create mode 100644 uwac/libuwac/uwac-window.c create mode 100644 uwac/protocols/fullscreen-shell.xml create mode 100644 uwac/protocols/ivi-application.xml create mode 100644 uwac/protocols/xdg-shell.xml create mode 100644 uwac/uwac.pc.in create mode 100644 uwac/uwacConfig.cmake.in create mode 100644 uwac/uwacVersion.cmake delete mode 100644 winpr/libwinpr/asn1/module.def delete mode 100644 winpr/libwinpr/com/module.def delete mode 100644 winpr/libwinpr/comm/module.def delete mode 100644 winpr/libwinpr/credentials/module.def delete mode 100644 winpr/libwinpr/credui/module.def delete mode 100644 winpr/libwinpr/crt/module.def delete mode 100644 winpr/libwinpr/crypto/module.def delete mode 100644 winpr/libwinpr/dsparse/module.def delete mode 100644 winpr/libwinpr/environment/module.def delete mode 100644 winpr/libwinpr/error/module.def delete mode 100644 winpr/libwinpr/handle/module.def delete mode 100644 winpr/libwinpr/heap/module.def delete mode 100644 winpr/libwinpr/interlocked/module.def delete mode 100644 winpr/libwinpr/io/module.def delete mode 100644 winpr/libwinpr/library/module.def delete mode 100644 winpr/libwinpr/library/test/TestLibraryA/module.def delete mode 100644 winpr/libwinpr/library/test/TestLibraryB/module.def delete mode 100644 winpr/libwinpr/locale/module.def delete mode 100644 winpr/libwinpr/memory/module.def delete mode 100644 winpr/libwinpr/nt/module.def delete mode 100644 winpr/libwinpr/nt/nt.h delete mode 100644 winpr/libwinpr/pipe/module.def delete mode 100644 winpr/libwinpr/pool/module.def delete mode 100644 winpr/libwinpr/registry/module.def delete mode 100644 winpr/libwinpr/rpc/module.def delete mode 100644 winpr/libwinpr/security/module.def delete mode 100644 winpr/libwinpr/smartcard/module.def delete mode 100644 winpr/libwinpr/sspi/module.def delete mode 100644 winpr/libwinpr/sysinfo/module.def delete mode 100644 winpr/libwinpr/thread/module.def delete mode 100644 winpr/libwinpr/winsock/module.def delete mode 100644 winpr/libwinpr/wnd/module.def diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b7cd6b..13e41e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,17 +81,27 @@ else() endif() set(FREERDP_INCLUDE_DIR "include/freerdp${FREERDP_VERSION_MAJOR}/") +# Make paths absolute +if (CMAKE_INSTALL_PREFIX) + get_filename_component(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" ABSOLUTE) +endif() +if (FREERDP_EXTERNAL_PATH) + get_filename_component (FREERDP_EXTERNAL_PATH "${FREERDP_EXTERNAL_PATH}" ABSOLUTE) +endif() + # Allow to search the host machine for git if(ANDROID OR IOS) SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) endif(ANDROID OR IOS) + include(GetGitRevisionDescription) git_get_exact_tag(GIT_REVISION --tags --always) + if (${GIT_REVISION} STREQUAL "n/a") - git_rev_parse(GIT_REVISION --short) + git_rev_parse (GIT_REVISION --short) endif() if(ANDROID OR IOS) - SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) + SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) endif(ANDROID OR IOS) message(STATUS "Git Revision ${GIT_REVISION}") @@ -105,15 +115,17 @@ if(NOT CMAKE_BUILD_TYPE) endif() if(NOT DEFINED BUILD_SHARED_LIBS) - if(ANDROID OR IOS OR APPLE) + if(IOS OR APPLE) set(BUILD_SHARED_LIBS OFF) else() set(BUILD_SHARED_LIBS ON) endif() endif() -if(NOT DEFINED EXPORT_ALL_SYMBOLS) - set(EXPORT_ALL_SYMBOLS TRUE) +if(BUILD_TESTING) + set(EXPORT_ALL_SYMBOLS TRUE) +elseif(NOT DEFINED EXPORT_ALL_SYMBOLS) + set(EXPORT_ALL_SYMBOLS FALSE) endif() # BSD @@ -299,11 +311,11 @@ if(MSVC) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) - if(CMAKE_BUILD_TYPE STREQUAL "Release") - else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zi") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi") - endif() + if(CMAKE_BUILD_TYPE STREQUAL "Release") + else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zi") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi") + endif() endif() @@ -361,8 +373,6 @@ if(NOT IOS) check_include_files(fcntl.h HAVE_FCNTL_H) check_include_files(unistd.h HAVE_UNISTD_H) check_include_files(execinfo.h HAVE_EXECINFO_H) - check_include_files(stdint.h HAVE_STDINT_H) - check_include_files(stdbool.h HAVE_STDBOOL_H) check_include_files(inttypes.h HAVE_INTTYPES_H) check_include_files(sys/modem.h HAVE_SYS_MODEM_H) check_include_files(sys/filio.h HAVE_SYS_FILIO_H) @@ -373,8 +383,6 @@ if(NOT IOS) else() set(HAVE_FCNTL_H 1) set(HAVE_UNISTD_H 1) - set(HAVE_STDINT_H 1) - set(HAVE_STDBOOL_H 0) set(HAVE_INTTYPES_H 1) set(HAVE_SYS_FILIO_H 1) endif() @@ -406,9 +414,9 @@ if(APPLE) # Temporarily disabled, causes the cmake script to be reexecuted, causing the compilation to fail. # Workaround: specify the parameter in the command-line -# if(WITH_CLANG) -# set(CMAKE_C_COMPILER "clang") -# endif() +# if(WITH_CLANG) +# set(CMAKE_C_COMPILER "clang") +# endif() if (WITH_VERBOSE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -v") @@ -420,14 +428,18 @@ endif(APPLE) if(OPENBSD) set(WITH_MANPAGES "ON") set(WITH_ALSA "OFF") - set(WITH_PULSE "OFF") - set(WITH_OSS "ON") + set(WITH_PULSE "OFF") + set(WITH_OSS "ON") set(WITH_WAYLAND "OFF") endif() # Android if(ANDROID) - set(WITH_LIBRARY_VERSIONING "OFF") + set(WITH_LIBRARY_VERSIONING "OFF") + + if (${ANDROID_ABI} STREQUAL "armeabi") + set (WITH_NEON OFF) + endif() if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") add_definitions(-DNDK_DEBUG=1) @@ -439,40 +451,23 @@ if(ANDROID) endif() set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -llog") - if (NOT FREERDP_EXTERNAL_JPEG_PATH) - if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/external/jpeg8d") - set(FREERDP_EXTERNAL_JPEG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/external/jpeg8d") + if (NOT FREERDP_EXTERNAL_PATH) + if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/external/") + set (FREERDP_EXTERNAL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/external/") else() - message(STATUS "FREERDP_EXTERNAL_SSL_PATH not set! - Needs to be set if openssl is not found in the android NDK (which usually isn't)") + message(STATUS "FREERDP_EXTERNAL_PATH not set!") endif() endif() - if (NOT FREERDP_EXTERNAL_SSL_PATH) - if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/external/openssl") - set(FREERDP_EXTERNAL_SSL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/external/openssl") - else() - message(STATUS "FREERDP_EXTERNAL_SSL_PATH not set! - Needs to be set if openssl is not found in the android NDK (which usually isn't)") - endif() - if(WITH_GPROF) - if (NOT FREERDP_EXTERNAL_PROFILER_PATH) - if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/external/android-ndk-profiler") - set(FREERDP_EXTERNAL_PROFILER_PATH - "${CMAKE_CURRENT_SOURCE_DIR}/external/android-ndk-profiler") - else() - message(STATUS "FREERDP_EXTERNAL_PROFILER_PATH not set!") - endif() - endif() - endif() -endif() -set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_EXTERNAL_SSL_PATH} ${FREERDP_EXTERNAL_JPEG_PATH}) -set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_EXTERNAL_PROFILER_PATH}) - set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/client/Android/FreeRDPCore/jni/${ANDROID_ABI}) - CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/regenerate_jni_headers.sh.cmake - ${CMAKE_BINARY_DIR}/scripts/regenerate_jni_headers.sh @ONLY) + list (APPEND CMAKE_INCLUDE_PATH ${FREERDP_EXTERNAL_PATH}/include) + list (APPEND CMAKE_LIBRARY_PATH ${FREERDP_EXTERNAL_PATH}/${ANDROID_ABI}/ ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH ) + if (WITH_GPROF) - CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/gprof_generate.sh.cmake ${CMAKE_BINARY_DIR}/scripts/gprof_generate.sh @ONLY) + CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/gprof_generate.sh.cmake + ${CMAKE_BINARY_DIR}/scripts/gprof_generate.sh @ONLY) endif(WITH_GPROF) - endif() set(CMAKE_THREAD_PREFER_PTHREAD TRUE) @@ -486,9 +481,9 @@ if(NOT WIN32) endif() if(WITH_VALGRIND_MEMCHECK) - check_include_files(valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H) + check_include_files(valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H) else() - unset(HAVE_VALGRIND_MEMCHECK_H CACHE) + unset(HAVE_VALGRIND_MEMCHECK_H CACHE) endif() if(UNIX OR CYGWIN) @@ -626,6 +621,21 @@ if(APPLE) set(OPENSLES_FEATURE_TYPE "DISABLED") endif() +if(UNIX AND NOT ANDROID) + set(WLOG_SYSTEMD_JOURNAL_FEATURE_TYPE "RECOMMENDED") + set(WLOG_SYSTEMD_JOURNAL_FEATURE_PURPOSE "systemd journal appender") + set(WLOG_SYSTEMD_JOURNAL_FEATURE_DESCRIPTION "allows to export wLog to systemd journal") + + #include(Findlibsystemd) + find_feature(libsystemd ${WLOG_SYSTEMD_JOURNAL_FEATURE_TYPE} ${WLOG_SYSTEMD_JOURNAL_FEATURE_PURPOSE} ${WLOG_SYSTEMD_JOURNAL_FEATURE_DESCRIPTION}) + + if(LIBSYSTEMD_FOUND) + set(HAVE_JOURNALD_H TRUE) + else() + unset(HAVE_JOURNALD_H) + endif() +endif(UNIX AND NOT ANDROID) + if(ANDROID) set(X11_FEATURE_TYPE "DISABLED") set(WAYLAND_FEATURE_TYPE "DISABLED") @@ -641,21 +651,6 @@ if(ANDROID) set(OPENSLES_FEATURE_TYPE "REQUIRED") endif() -if(UNIX) - set(WLOG_SYSTEMD_JOURNAL_FEATURE_TYPE "RECOMMENDED") - set(WLOG_SYSTEMD_JOURNAL_FEATURE_PURPOSE "systemd journal appender") - set(WLOG_SYSTEMD_JOURNAL_FEATURE_DESCRIPTION "allows to export wLog to systemd journal") - - #include(Findlibsystemd) - find_feature(libsystemd ${WLOG_SYSTEMD_JOURNAL_FEATURE_TYPE} ${WLOG_SYSTEMD_JOURNAL_FEATURE_PURPOSE} ${WLOG_SYSTEMD_JOURNAL_FEATURE_DESCRIPTION}) - - if(LIBSYSTEMD_FOUND) - set(HAVE_JOURNALD_H TRUE) - else() - unset(HAVE_JOURNALD_H) - endif() -endif(UNIX) - find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION}) find_feature(Wayland ${WAYLAND_FEATURE_TYPE} ${WAYLAND_FEATURE_PURPOSE} ${WAYLAND_FEATURE_DESCRIPTION}) find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION}) @@ -728,8 +723,8 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DI # RPATH configuration if(CMAKE_SKIP_RPATH) - set(CMAKE_SKIP_RPATH FALSE) - set(CMAKE_SKIP_INSTALL_RPATH TRUE) + set(CMAKE_SKIP_RPATH FALSE) + set(CMAKE_SKIP_INSTALL_RPATH TRUE) endif() set(CMAKE_SKIP_BUILD_RPATH FALSE) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) @@ -796,6 +791,10 @@ include_directories("${CMAKE_BINARY_DIR}/rdtk/include") add_subdirectory(rdtk) +if(WAYLAND_FOUND) + add_subdirectory(uwac) +endif() + if(BSD) if(IS_DIRECTORY /usr/local/include) include_directories(/usr/local/include) diff --git a/ChangeLog b/ChangeLog index bc8832d..6e422d1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,883 @@ +2016-02-29 17:39:18 +0100 Norbert Federa (b4b8239) + + * Merge pull request #3176 from bmiklautz/shadow_subsystem (HEAD, + origin/master, origin/HEAD, master) + +2016-02-29 17:10:53 +0100 Bernhard Miklautz (014f31d) + + * Merge pull request #3171 from akallabeth/crypto_simplification + +2016-02-29 16:59:58 +0100 Bernhard Miklautz (2550634) + + * Merge pull request #3168 from akallabeth/visibility_fixes + +2016-02-29 16:25:04 +0100 Bernhard Miklautz (1688738) + + * ci: build server side on windows + +2016-02-29 16:22:24 +0100 Bernhard Miklautz (1b926f8) + + * build: export freerdp-shadow + +2016-02-29 16:02:13 +0100 Bernhard Miklautz (f15c050) + + * shadow/subsystem: fix windows build + +2016-02-29 16:00:35 +0100 Bernhard Miklautz (5a7ac96) + + * build/win32: fix DLL version information + +2016-02-29 15:24:07 +0100 Armin Novak (c182be0) + + * Removed module.def from build config. + +2016-02-29 15:21:22 +0100 Bernhard Miklautz (92de4cf) + + * Merge pull request #3167 from + realjiangms/shadow_export_default_subsystem + +2016-02-29 15:18:47 +0100 Armin Novak (68c402a) + + * Removed windows module.def files. + +2016-02-29 15:18:19 +0100 Armin Novak (5acd80d) + + * Exporting channel entry points. + +2016-02-29 14:43:33 +0100 Armin Novak (4e4d2e1) + + * Fixed crypto tests. + +2016-02-29 11:12:32 +0100 Armin Novak (19568c6) + + * Fixed indentation. + +2016-02-29 11:10:15 +0100 Armin Novak (7e65013) + + * Fixed memory leak. + +2016-02-29 10:31:50 +0100 Hardening (da9d9ed) + + * Merge pull request #3165 from akallabeth/printer_fix + +2016-02-29 09:00:02 +0100 Armin Novak (b429d23) + + * Refactored crypto *_New functions. + +2016-02-28 11:12:17 +0100 Armin Novak (92c1578) + + * Updated RC4 API, fixed crashing bug. + +2016-02-28 10:33:25 +0100 akallabeth (e2a8083) + + * Merge pull request #3169 from realjiangms/android_fix_sound + +2016-02-27 01:07:30 +0800 zihao.jiang (176ad52) + + * server/shadow: Export API to set built-in subsystem modules for + freerdp-shadow-subsystem + +2016-02-27 02:20:49 +0800 zihao.jiang (17139b9) + + * android: Fix sound redirection. After #3097, the java side pass + command line argument to JNI for freerdp settings. However + there's several issues need to be fixed: 1. The argument + /sound should be appended if freerdp is required to play + sound at local device 2. The option value for "audio-mode" + is not correct. It should match the definition in + client/common/cmdline.c /* Audio Mode */ define + AUDIO_MODE_REDIRECT 0 /* Bring to this computer */ + define AUDIO_MODE_PLAY_ON_SERVER 1 /* Leave at remote + computer */ define AUDIO_MODE_NONE 2 /* Do not + play */ 3. Uncomment support for WAVE_FORMAT_PCM in audin. + I tested on my android phone and Nokia N1 tablet. It works + on both device + +2016-02-27 23:28:49 +0100 Armin Novak (238ff3b) + + * Unified encryption functions. + +2016-02-27 22:39:45 +0100 Armin Novak (5805ba8) + + * Removed crypto_nonce. + +2016-02-27 22:13:59 +0100 Armin Novak (86436bc) + + * Added API export for uwac. + +2016-02-27 11:36:34 +0100 Armin Novak (11c4425) + + * Fixed dupliace FREERDP_API declarations. + +2016-02-26 19:25:49 +0100 Armin Novak (1036f1e) + + * Fixed default visibility. + +2016-02-26 18:53:45 +0100 akallabeth (9d21117) + + * Merge pull request #3157 from DavBfr/Fix-bad-malloc-size + +2016-02-12 11:32:18 -0800 David PHAM-VAN (8ebe5b9) + + * Fix bad malloc size in statvfs + +2016-02-26 15:21:19 +0100 Armin Novak (b7187d0) + + * Printer driver from command line now used. + +2016-02-26 14:50:27 +0100 Armin Novak (dccf40c) + + * Fixed duplicate loading of smartcard and printers. + +2016-02-26 09:57:35 +0100 Martin Fleisz (4f22682) + + * Merge pull request #3151 from akallabeth/timezone_refactor + +2016-02-26 09:52:43 +0100 Hardening (4217262) + + * Merge pull request #3156 from akallabeth/ssl_wrapper_merge + +2016-02-26 09:28:54 +0100 Armin Novak (fe8f5de) + + * Fixed indentation. + +2016-02-26 09:27:53 +0100 Armin Novak (7a253ba) + + * Replaced magic numbers with defines. + +2016-02-26 09:23:34 +0100 akallabeth (f44f339) + + * Merge pull request #3161 from bmiklautz/uwac_versioning + +2016-02-25 23:47:32 +0100 Bernhard Miklautz (d5a43dd) + + * uwac: generate .pc and cmake find-module + +2016-02-25 23:46:56 +0100 Bernhard Miklautz (167907e) + + * uwac: enable library versioning + +2016-02-25 23:38:53 +0100 Bernhard Miklautz (71836f6) + + * build winpr: export WINPR_API_VERSION + +2016-02-25 21:57:56 +0100 Bernhard Miklautz (541abee) + + * cmake/FindWayland: cleanup + +2016-02-25 16:57:48 +0100 akallabeth (16ba8f3) + + * Merge pull request #3159 from bmiklautz/disable_mipsel + +2016-02-25 16:57:34 +0100 Bernhard Miklautz (8bdad1e) + + * Merge pull request #3140 from hardening/printer_work + +2016-02-25 16:31:20 +0100 Bernhard Miklautz (ae6c235) + + * android: disable mips build + +2016-02-25 15:03:14 +0100 David FORT (aa7fe1d) + + * Fixed indentation + +2016-02-25 09:02:46 +0100 Armin Novak (fd415cd) + + * Fixed missing semicolon. + +2016-02-25 09:00:50 +0100 akallabeth (70f9ebe) + + * Merge pull request #3042 from hardening/uwac + +2016-02-25 00:41:19 +0100 David FORT (2b18d25) + + * Added some checks + +2016-02-24 21:45:09 +0100 Armin Novak (f997421) + + * Unified hmac functions. + +2016-02-24 20:39:49 +0100 Armin Novak (4ca6b9b) + + * Unified random functions and remaining MD5. + +2016-02-24 20:32:20 +0100 Armin Novak (6e8ea34) + + * Updated cryto wrapper API. + +2016-02-24 20:16:33 +0100 Armin Novak (95058c6) + + * Fixed argument checks and return values. + +2016-02-24 20:16:19 +0100 Armin Novak (0bfe5ba) + + * Fixed naming of static functions. + +2016-02-24 17:04:03 +0100 Armin Novak (ada2b16) + + * Unified RC4 functions. + +2016-02-24 16:46:25 +0100 Armin Novak (06da644) + + * Unified md5 functions. + +2016-02-24 16:36:15 +0100 Armin Novak (0e4ea39) + + * Unified sha1 functions. + +2016-02-24 09:43:53 +0100 Armin Novak (7795ebd) + + * Fixed return value for DST. + +2016-02-24 09:42:12 +0100 Armin Novak (495df6d) + + * Readded read timezone from link. + +2016-02-23 18:15:25 +0100 Armin Novak (1cd6697) + + * Implemented timezone detection for android + +2016-02-23 18:08:18 +0100 Armin Novak (447ac23) + + * Refactored timezone functions. + +2016-02-23 20:23:52 +0100 akallabeth (7c5fcc9) + + * Merge pull request #3149 from bmiklautz/feb22 + +2016-02-23 19:11:32 +0100 Bernhard Miklautz (ce51592) + + * Merge pull request #3150 from xhaakon/subsystem-lib + +2016-02-23 10:49:52 +0100 Jakub Adam (db44d27) + + * server/shadow: Build libraries for shadow subsystems + +2016-02-23 17:14:08 +0100 Bernhard Miklautz (738f55a) + + * Merge pull request #3119 from akallabeth/abort_event_reset + +2016-02-23 16:46:16 +0100 akallabeth (a53e4f4) + + * Merge pull request #3015 from bmiklautz/pull/2936 + +2016-02-23 15:58:48 +0100 Armin Novak (d28cb6a) + + * Removed function call with invalid arguments. + +2016-02-10 11:20:52 +0100 Armin Novak (24c93e4) + + * Resetting abortEvent only on connect and reconnect. + +2016-02-23 16:25:05 +0100 Bernhard Miklautz (dd93fd2) + + * timezon: add support for tz package + +2016-02-23 15:34:58 +0100 Bernhard Miklautz (be02849) + + * tcp: set the timeout to 9s + +2015-10-19 18:29:30 +0000 volth (8b9c402) + + * Increase TCP_USER_TIMEOUT to avoid disconnections. + +2016-02-23 14:09:14 +0100 David FORT (0bf2fae) + + * Fix compilation with out-of-tree builds + +2016-02-23 09:22:15 +0100 David FORT (c1c43f9) + + * Fixed detection of wayland libs + +2016-02-22 16:03:57 +0100 David FORT (5dcb3df) + + * Fix compilation and detection under debian/ubuntu + +2016-01-18 15:55:33 +0100 David FORT (87d6caa) + + * Integrate UWAC in to the FreeRDP source tree + +2016-01-12 22:29:38 +0100 David FORT (bc31c00) + + * Fixed detection of UWAC library + +2016-01-06 23:56:05 +0100 David FORT (ded17d9) + + * Move wayland client to UWAC + +2016-02-23 11:44:58 +0100 Bernhard Miklautz (35faa8b) + + * Merge pull request #3148 from mfleisz/win32_include_fix + +2016-02-23 09:56:17 +0100 akallabeth (05aa425) + + * Merge pull request #2851 from + ilammy/x11-cliprdr/improve-format-support + +2016-02-23 09:55:55 +0100 Martin Fleisz (1b881e4) + + * winpr/file: Add missing include (io.h) for windows builds + +2016-02-23 09:37:31 +0100 akallabeth (88fa29c) + + * Merge pull request #3145 from giox069/master + +2016-02-23 00:14:30 +0200 ilammy (93fc349) + + * client/X11: harden xf_cliprdr_parse_server_format_list() + +2016-02-22 17:01:43 +0100 Bernhard Miklautz (e6f013e) + + * fix spelling + +2016-02-22 13:54:08 +0100 akallabeth (4d85ade) + + * Merge pull request #3136 from bmiklautz/winpr_version + +2016-02-22 12:48:42 +0100 Bernhard Miklautz (8ac4998) + + * Merge pull request #3147 from akallabeth/win_debug_symbol_fix + +2016-02-22 10:27:50 +0100 Armin Novak (6c8de27) + + * Installing debug symbols only if activated. + +2016-02-21 17:52:52 +0100 Giovanni Panozzo (1dea980) + + * Fix char signedness in glyph offset calculation, fixes #2137 + +2016-02-19 13:27:13 +0100 Bernhard Miklautz (503399f) + + * Merge pull request #3143 from + akallabeth/deny_cert_if_cred_from_stdin + +2016-02-19 10:22:38 +0100 Armin Novak (ae4a1ee) + + * Abort certificate accept if password is read from stdin. + +2016-02-18 14:19:36 +0100 David FORT (1b2b1c4) + + * Add support for saveSessionInfo PDU + +2016-02-11 22:45:30 +0100 David FORT (a53cb81) + + * Added missing checks + +2016-02-03 10:26:59 +0100 David FORT (60fed9d) + + * Mutualize definitions for the printer channel + +2016-02-16 17:39:22 +0100 Bernhard Miklautz (12bd0ec) + + * winpr: BUMP the API version to 1.2 + +2016-02-15 13:52:47 +0100 Hardening (2a3e999) + + * Merge pull request #2710 from akallabeth/cert_temp_accept_v2 + +2016-02-14 14:18:26 +0100 Hardening (0092bcf) + + * Merge pull request #3130 from pxx02134/patch-1 + +2016-02-14 14:17:52 +0100 Hardening (f524c4c) + + * Merge pull request #3131 from pxx02134/patch-2 + +2016-02-12 21:19:13 +0100 Hardening (ef7c867) + + * Merge pull request #3124 from nathankidd/region16_rects-handle-null + +2016-02-11 19:34:48 -0500 Nathan Kidd (d68e58a) + + * libfreerdp-codec: Make region16_rects() handle NULL nbRects + +2016-02-12 10:43:25 +0100 Bernhard Miklautz (cf6ea23) + + * Merge pull request #3123 from nfedera/fix-keyboardtype-7 + +2016-02-11 22:21:33 +0100 Hardening (cbd1ffa) + + * Merge pull request #3110 from akallabeth/mac_os_ssl_warning_fix + +2016-02-11 21:40:50 +0100 Norbert Federa (92aa21c) + + * Several fixes for keyboard type 7 (japanese) + +2016-02-11 12:24:47 +0900 pxx02134 (2bf525d) + + * Update AndroidManifest.xml + +2016-02-11 12:21:11 +0900 pxx02134 (2178245) + + * Update BookmarkDB.java + +2016-02-10 11:17:34 +0100 Hardening (8bbbbf3) + + * Merge pull request #3116 from akallabeth/win_unicode_arg_fix + +2016-02-09 09:36:00 +0100 Armin Novak (8be7b25) + + * Printing help on invalid command line again. + +2016-02-08 14:36:31 +0100 Armin Novak (d67614a) + + * Reading unicode from command line. + +2016-02-08 13:10:50 +0100 Norbert Federa (bb3882b) + + * Merge pull request #3111 from colemickens/hidpi-cli + +2015-03-04 09:37:25 -0500 Isaac Richter (1f6ba79) + + * Enable display scaling in client + +2016-02-05 11:52:07 +0100 Armin Novak (f456829) + + * Fixed API for old openssl versions < 1.0.0 + +2016-02-05 11:12:48 +0100 Hardening (7534876) + + * Merge pull request #3113 from akallabeth/remove_broken_rdpdr_check + +2016-02-05 10:50:26 +0100 Armin Novak (c430d5e) + + * Removed broken check, fixes #3112 + +2016-02-05 02:32:47 +0100 Armin Novak (80d7d63) + + * Updated android API. + +2015-12-18 10:36:28 +0100 Armin Novak (6b406bd) + + * Not building GetLine on android and ios. + +2015-12-18 09:45:44 +0100 Armin Novak (5e46a6e) + + * Replaced getline with custom GetLine. + +2015-12-17 16:43:55 +0100 Armin Novak (b35f665) + + * Moved common code from cli clients to client lib. + +2015-12-17 16:43:49 +0100 Armin Novak (0e2208e) + + * Fixed warning. + +2015-12-14 14:02:49 +0100 Armin Novak (cbf2892) + + * Implemented temporary certificate accept. + +2015-12-14 14:01:12 +0100 Armin Novak (1669900) + + * Fixed allocation issue with common_name. + +2016-02-04 16:20:59 +0100 Martin Fleisz (56a0c4c) + + * Merge pull request #3097 from akallabeth/android_api_upgrade_v4 + +2016-02-04 16:09:49 +0100 Armin Novak (8fdf59a) + + * Removed android SDK dependency for native build. + +2016-02-04 15:05:07 +0100 Bernhard Miklautz (db77cff) + + * Merge pull request #3108 from akallabeth/log_leve_adjust + +2016-02-04 14:33:28 +0100 Armin Novak (1f81556) + + * Removed hardcoded debug mode. + +2016-02-04 13:56:33 +0100 Armin Novak (74f3ebf) + + * Fixed argument for freerdp source. + +2016-02-04 13:04:41 +0100 Norbert Federa (94565a0) + + * Merge pull request #3109 from nfedera/fix-x11-xdgh-types-collision + +2016-02-04 12:57:21 +0100 Armin Novak (b6b0f57) + + * Fixed compiler warning about cast. + +2016-02-04 12:55:11 +0100 Armin Novak (3b0f5b5) + + * Removed obsolete APPLE preprocessor switch. + +2016-02-03 21:32:55 +0100 Norbert Federa (099d488) + + * fix X11/Xdg.h typedef collision fix + +2016-02-04 11:41:54 +0100 Armin Novak (1b3ac98) + + * rdp_print_errinfo now uses INFO log level. + +2016-02-04 11:40:42 +0100 Armin Novak (cdadb58) + + * Function freerdp_set_error_info fix + +2016-02-04 11:39:57 +0100 Armin Novak (ad36a5c) + + * Disconnect log message now uses debug level. + +2016-02-04 09:56:52 +0100 akallabeth (eadfff8) + + * Merge pull request #3107 from ccpp/tls-sni + +2016-02-04 09:06:43 +0100 Hardening (13df05b) + + * Merge pull request #3079 from akallabeth/drive_hotplug_fix + +2016-02-04 08:34:51 +0100 Christian Plattner (c0226d6) + + * Enable support for SNI on client side + +2016-02-03 13:55:37 +0100 akallabeth (b769d84) + + * Merge pull request #3105 from nfedera/fix-cmake-include-names + +2016-02-03 13:37:35 +0100 Norbert Federa (24a2f2a) + + * appropriate names in server & client cmake exports + +2016-02-03 12:56:45 +0100 Norbert Federa (157d81b) + + * Merge pull request #3104 from akallabeth/sign_mismatch_fixes + +2016-02-03 12:46:02 +0100 Armin Novak (96bf6fc) + + * Fixed inverted check. + +2016-02-03 12:45:49 +0100 Armin Novak (f835744) + + * Removed unused variable. + +2016-02-03 12:45:31 +0100 Armin Novak (40519f0) + + * Fixed initialization warning. + +2016-02-03 12:11:27 +0100 akallabeth (c17c7de) + + * Merge pull request #3094 from DavBfr/mac-adpcm + +2016-02-03 11:55:23 +0100 Armin Novak (d267750) + + * Fixed flac caps creation. + +2016-02-03 11:51:31 +0100 Armin Novak (10956f3) + + * Fixed constant definition. + +2016-02-03 11:45:22 +0100 Armin Novak (22f704c) + + * Fixed _socket error check. + +2016-02-03 11:43:01 +0100 Armin Novak (c2d2ead) + + * Fixed error check. + +2016-02-03 11:30:15 +0100 Armin Novak (539be1f) + + * Fixed unsigned underflow. + +2016-02-03 11:23:41 +0100 Armin Novak (d1c59f7) + + * Fixed invalid boolean check. + +2016-02-03 11:22:27 +0100 Armin Novak (a1617c7) + + * Fixed unused check. + +2016-02-03 11:04:35 +0100 Armin Novak (511f9e8) + + * Use ERROR_INVALID_DATA for short buffers. + +2016-02-03 09:46:16 +0100 Martin Fleisz (9712509) + + * Merge pull request #3103 from llyzs/memfix + +2016-02-03 13:34:58 +0800 Vic Lee (73f895f) + + * gcc: assigned string must not be freed. + +2016-02-02 11:58:05 -0800 David PHAM-VAN (506749b) + + * Activate WITH_MACAUDIO flag if the build is for OS X + +2016-02-02 18:47:26 +0100 Martin Fleisz (220478e) + + * Merge pull request #3101 from akallabeth/stdbool_detection_fix + +2016-02-02 18:24:30 +0100 Armin Novak (9b0ef3a) + + * Fixed stdint.h and stdbool.h detection. + +2016-02-02 17:59:56 +0100 Armin Novak (96aecca) + + * Fixed length check issue. + +2016-02-02 16:10:33 +0100 Armin Novak (5c97075) + + * Fixed stdbool.h and stdint.h detection. + +2016-02-02 10:02:00 +0100 Martin Fleisz (c862ca3) + + * Merge pull request #3099 from akallabeth/mac_fullscreen + +2016-02-02 09:50:23 +0100 Armin Novak (c908b95) + + * Reformatted patch. + +2015-03-23 13:54:04 +0100 “John (8324b3d) + + * Mac Fullscreen + window title + +2016-02-01 16:01:32 +0100 Armin Novak (b8106a1) + + * Updated documentation and default build config. + +2016-02-01 15:25:40 +0100 Armin Novak (54a7d79) + + * Restructured client project, moved to gradle build. + +2016-02-01 15:22:10 +0100 Armin Novak (d04eb12) + + * Added new android build scripts. + +2016-02-01 15:21:07 +0100 Armin Novak (61633a1) + + * Fixed android build issues. + +2016-02-01 15:09:51 +0100 Armin Novak (cd05ea7) + + * Fixed error checks for command line parser. + +2016-02-01 13:02:38 +0100 Bernhard Miklautz (8ec3903) + + * Merge pull request #3076 from + akallabeth/remove_fixed_size_heap_strings + +2016-02-01 13:00:23 +0100 akallabeth (cccc8b1) + + * Merge pull request #3096 from bmiklautz/fix/nightlies + +2016-02-01 12:47:00 +0100 Bernhard Miklautz (7b9881e) + + * pkg/deb: fix nightly builds + +2016-01-29 09:58:48 -0800 David PHAM-VAN (3f5ce2d) + + * Refactor format_supported with a nice switch() statement + +2016-01-25 13:53:19 -0800 David PHAM-VAN (8ef64ae) + + * Add ADPCM codec for Mac client + +2016-01-28 15:26:04 +0100 MartinHaimberger (e83f97b) + + * Merge pull request #3093 from hardening/last_write_checks + +2016-01-28 15:23:24 +0100 MartinHaimberger (83b706c) + + * Merge pull request #3092 from akallabeth/get_build_config + +2016-01-28 15:12:26 +0100 David FORT (b6dd7bb) + + * Check more Stream_EnsureCapacity results when writing capabilities + +2016-01-28 14:36:50 +0100 MartinHaimberger (99c0a73) + + * Merge pull request #3091 from akallabeth/wlog_warning_fix + +2016-01-28 14:30:18 +0100 akallabeth (5a2a2b8) + + * Merge pull request #3090 from akallabeth/drdynvc_size_checks + +2016-01-28 14:28:51 +0100 Hardening (a2aa56e) + + * Merge pull request #3067 from akallabeth/reset_abort_event + +2016-01-28 14:26:50 +0100 Armin Novak (035f127) + + * Added get_build_config functions. + +2016-01-28 12:25:44 +0100 Armin Novak (d847993) + + * Using Stream_ReminingLength for read checks. + +2016-01-28 12:08:57 +0100 Armin Novak (c251534) + + * Fixed return value of WLog_FileAppender_WriteImageMessage + +2016-01-28 12:05:14 +0100 Armin Novak (6f50589) + + * Cleared up error code usage. + +2016-01-28 11:45:06 +0100 Armin Novak (8595e39) + + * Fixed size checks (thanks to @virtman) + +2016-01-28 11:12:20 +0100 Armin Novak (57f1e26) + + * Checking capability read return. Updated copyright headers. + +2016-01-28 10:33:17 +0100 Martin Fleisz (7294a7f) + + * Merge pull request #3078 from akallabeth/wlog_cmd_options + +2016-01-28 10:32:14 +0100 Martin Fleisz (81f5060) + + * Merge pull request #3088 from clangm/patch-1 + +2016-01-27 15:40:08 -0700 clangm (62a559a) + + * fix typo + +2016-01-27 23:02:11 +0100 Hardening (bb4a0c5) + + * Merge pull request #3087 from DavBfr/fix-png-load + +2016-01-13 15:09:03 -0800 David PHAM-VAN (3d22cbe) + + * Fix png image loading that needed write access + +2016-01-27 19:26:52 +0100 Armin Novak (e08ca73) + + * Improved error checks. + +2016-01-27 11:21:04 +0100 Armin Novak (06adbc9) + + * Fixed realloc check, renamed filter variable. + +2016-01-27 10:50:38 +0100 Hardening (d458bc2) + + * Merge pull request #3073 from davewheel/cert_key_in_memory + +2016-01-27 10:45:54 +0100 Hardening (7af1ec8) + + * Merge pull request #3083 from akallabeth/capability_set_fix + +2016-01-26 21:35:16 +0100 Armin Novak (974d2ef) + + * Fix #3081, client string encoding. + +2016-01-27 10:18:30 +0100 Martin Fleisz (a9e4ba0) + + * Merge pull request #3069 from davewheel/4upstream-1 + +2016-01-27 10:13:32 +0100 Martin Fleisz (b2744f8) + + * Merge pull request #3082 from + hardening/check_client_and_server_capabilities + +2016-01-26 16:14:48 +0100 David FORT (708d0cb) + + * Check server and client capabilities + +2016-01-26 09:56:01 +0100 Martin Fleisz (b6ad805) + + * Merge pull request #3080 from hardening/capa_write + +2016-01-26 09:34:22 +0100 Armin Novak (106479d) + + * Fixed clientNameLen initialization. + +2016-01-25 19:11:35 +0100 David FORT (137825e) + + * Stream_EnsureCapacity return value aren't checked in + capabilities_write + +2016-01-24 15:21:06 +0100 Armin Novak (deffd0d) + + * Fixed argument checks for drive channel. + +2016-01-23 15:16:13 +0100 Armin Novak (46a079f) + + * Added new command line options for logger. + +2016-01-23 14:42:20 +0100 Hardening (507fba0) + + * Merge pull request #3072 from giox069/master + +2016-01-20 12:22:32 +0100 Giovanni Panozzo (c5a4ce7) + + * Improve error logging after calling some BIO_ functions + +2016-01-23 00:00:18 +0100 Hardening (bbf5c77) + + * Merge pull request #3070 from davewheel/ntlm_attrs + +2016-01-21 21:29:42 +0100 Bernhard Miklautz (ef6cb2b) + + * Merge pull request #3075 from akallabeth/winpr_header_install_fix + +2016-01-21 14:47:10 +0100 Armin Novak (73ec3d6) + + * Removed fixed size strings. + +2016-01-21 15:26:32 +0100 Armin Novak (78d3f45) + + * Added cmake patch from @david-geiger + +2016-01-21 00:17:59 +0100 davewheel (d5b8585) + + * Allow to specify the raw content of crypto materials + +2016-01-20 22:21:05 +0100 davewheel (a971f9e) + + * Handle more NTLM attributes + +2016-01-20 16:54:15 +0100 davewheel (121a234) + + * Add better handling of monitors + +2016-01-14 21:00:41 +0100 davewheel (ca9e908) + + * Fix a security issue in monitors packet handling + +2016-01-19 09:28:40 +0100 Martin Fleisz (3e19791) + + * Merge pull request #3014 from bmiklautz/winpr_nt_file + +2016-01-19 09:27:50 +0100 Martin Fleisz (07d5d16) + + * Merge pull request #3059 from akallabeth/zlib_memleak_fix + +2016-01-19 09:25:42 +0100 Martin Fleisz (059286d) + + * Merge pull request #3066 from akallabeth/srccopy_fix + +2016-01-19 09:24:22 +0100 Martin Fleisz (90783c7) + + * Merge pull request #3068 from akallabeth/pkg_config_fix + +2016-01-18 22:45:40 +0100 Armin Novak (20ada7d) + + * Fix pkg-config generation. + +2016-01-18 10:08:12 +0100 Armin Novak (5542fef) + + * Resetting abort event on freerdp_connect. + +2016-01-18 09:32:34 +0100 Armin Novak (93f3c06) + + * Fixed memory overlap check. + +2016-01-18 09:18:42 +0100 Armin Novak (123cd52) + + * Fixed SRCCOPY, using memmove now. + 2016-01-15 16:32:54 +0100 akallabeth (e2dbe5e) - * Merge pull request #3062 from bmiklautz/build_fix (HEAD, - origin/master, origin/HEAD, master) + * Merge pull request #3062 from bmiklautz/build_fix 2016-01-15 13:23:45 +0100 Bernhard Miklautz (ede0da3) * build: fix a problem with cmake version 2.8.11 +2016-01-15 10:16:08 +0100 Armin Novak (d2ab276) + + * Fix memory leak in lodepng_zlib_compress + 2016-01-15 09:51:51 +0100 Martin Fleisz (2db8c7e) * Merge pull request #3052 from abma/fix3051 @@ -101,6 +972,10 @@ * Fixed broken duplicate define. +2015-12-16 16:25:09 +0100 Bernhard Miklautz (aa2709a) + + * winpr: create a specific winpr nt file handle + 2016-01-02 11:31:39 +0100 Bernhard Miklautz (c3ce0c3) * Merge pull request #2871 from realjiangms/shadow_stand_alone2 @@ -405,6 +1280,42 @@ * pkg: update version infos to 2.0 +2015-08-19 10:25:59 +0300 ilammy (7bce7ef) + + * client/X11: transfer raw clipboard format data + +2015-08-19 10:59:49 +0300 ilammy (391ed0d) + + * client/X11: transfer raw clipboard format lists + +2015-08-14 22:57:42 +0300 ilammy (626e40a) + + * client/X11: add raw clipboard transfer indication + +2015-08-18 17:07:38 +0300 ilammy (532371d) + + * client/X11: remove unused function + +2015-08-18 17:05:48 +0300 ilammy (46fb66e) + + * client/X11: send clipboard format data errors correctly + +2015-08-19 17:25:17 +0300 ilammy (d7c9a31) + + * client/X11: correctly trim terminating null bytes from strings + +2015-08-17 11:35:19 +0300 ilammy (b9a2973) + + * client/X11: improve named clipboard format support + +2015-08-16 11:56:36 +0300 ilammy (8434709) + + * client/X11: improve clipboard format search functions + +2015-08-15 00:15:44 +0300 ilammy (4b67513) + + * winpr/clipboard: add CF_RAW clipboard format ID + 2015-11-13 11:47:58 +0100 Armin Novak (f4a466b) * Added mac implementation. diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 373ae86..b036437 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -771,6 +771,8 @@ static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args) #ifdef STATIC_CHANNELS #define DVCPluginEntry audin_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/audin/client/opensles/audin_opensl_es.c b/channels/audin/client/opensles/audin_opensl_es.c index 51917e4..a9123c5 100644 --- a/channels/audin/client/opensles/audin_opensl_es.c +++ b/channels/audin/client/opensles/audin_opensl_es.c @@ -218,8 +218,6 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device, audinFormat* f switch (format->wFormatTag) { - /* TODO: Deactivated, untested */ -#if 0 case WAVE_FORMAT_PCM: /* PCM */ if (format->cbSize == 0 && (format->nSamplesPerSec <= 48000) && @@ -229,7 +227,6 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device, audinFormat* f return TRUE; } break; -#endif /* TODO: Deactivated format, does not work, find out why */ // case WAVE_FORMAT_ADPCM: /* IMA ADPCM */ case WAVE_FORMAT_DVI_ADPCM: diff --git a/channels/cliprdr/client/module.def b/channels/cliprdr/client/module.def deleted file mode 100644 index 7336368..0000000 --- a/channels/cliprdr/client/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "cliprdr" -EXPORTS - VirtualChannelEntry @1 diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c index d70f619..fb23d8b 100644 --- a/channels/disp/client/disp_main.c +++ b/channels/disp/client/disp_main.c @@ -340,6 +340,8 @@ UINT disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonitors, DI #ifdef STATIC_CHANNELS #define DVCPluginEntry disp_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 83e8497..29111fd 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -728,7 +728,7 @@ UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s) UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UINT32 dataSize) { wStream* data_out; - unsigned long pos = 0; + unsigned long pos; UINT32 cbChId; UINT32 cbLen; unsigned long chunkLength; @@ -747,9 +747,9 @@ UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UI Stream_SetPosition(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); + pos = Stream_GetPosition(data_out); if (dataSize == 0) { - pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x40 | cbChId); Stream_SetPosition(data_out, pos); @@ -758,7 +758,6 @@ UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UI } else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos) { - pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x30 | cbChId); Stream_SetPosition(data_out, pos); diff --git a/channels/drive/client/dirent.h b/channels/drive/client/dirent.h index 9a293da..d9efa36 100644 --- a/channels/drive/client/dirent.h +++ b/channels/drive/client/dirent.h @@ -286,7 +286,7 @@ static struct dirent *readdir(DIR *dirp) return NULL; } if (FindNextFileA (dirp->search_handle, &dirp->find_data) == FALSE) { - /* the very last entry has been processed or an error occured */ + /* the very last entry has been processed or an error occurred */ FindClose (dirp->search_handle); dirp->search_handle = INVALID_HANDLE_VALUE; return NULL; diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c index e2a5a39..39ed054 100644 --- a/channels/drive/client/drive_main.c +++ b/channels/drive/client/drive_main.c @@ -859,6 +859,8 @@ out_error: #ifdef STATIC_CHANNELS #define DeviceServiceEntry drive_DeviceServiceEntry +#else +#define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif UINT sys_code_page = 0; diff --git a/channels/drive/client/module.def b/channels/drive/client/module.def deleted file mode 100644 index 82b96df..0000000 --- a/channels/drive/client/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "drive" -EXPORTS - DeviceServiceEntry @1 diff --git a/channels/drive/client/statvfs.c b/channels/drive/client/statvfs.c index 60722a5..e92a975 100644 --- a/channels/drive/client/statvfs.c +++ b/channels/drive/client/statvfs.c @@ -3,6 +3,8 @@ * statvfs emulation for Windows * * Copyright 2012 Gerald Richter + * Copyright 2016 Inuvika Inc. + * Copyright 2016 David PHAM-VAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,17 +31,18 @@ int statvfs(const char *path, struct statvfs *buf) { BOOL res; int len; - LPWSTR unicodestr; + LPWSTR unicodestr = NULL; DWORD lpSectorsPerCluster; DWORD lpBytesPerSector; DWORD lpNumberOfFreeClusters; DWORD lpTotalNumberOfClusters; - len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0); - unicodestr = (LPWSTR) malloc(len); - MultiByteToWideChar(CP_ACP, 0, path, -1, unicodestr, len); + len = ConvertToUnicode(CP_ACP, 0, path, -1, &unicodestr, 0); + if (len <= 0) + return -1; - res = GetDiskFreeSpace(unicodestr, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters, &lpTotalNumberOfClusters); + res = GetDiskFreeSpaceW(unicodestr, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters, &lpTotalNumberOfClusters); + free(unicodestr); buf->f_bsize = lpBytesPerSector; /* file system block size */ buf->f_frsize = 0; /* fragment size */ diff --git a/channels/echo/client/echo_main.c b/channels/echo/client/echo_main.c index fe2d363..ba50aaa 100644 --- a/channels/echo/client/echo_main.c +++ b/channels/echo/client/echo_main.c @@ -162,6 +162,8 @@ static UINT echo_plugin_terminated(IWTSPlugin* pPlugin) #ifdef STATIC_CHANNELS #define DVCPluginEntry echo_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index 2bd90f2..58bc9c2 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -394,6 +394,8 @@ static UINT parallel_free(DEVICE* device) #ifdef STATIC_CHANNELS #define DeviceServiceEntry parallel_DeviceServiceEntry +#else +#define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif /** diff --git a/channels/printer/client/printer_cups.c b/channels/printer/client/printer_cups.c index d498ff6..9586f02 100644 --- a/channels/printer/client/printer_cups.c +++ b/channels/printer/client/printer_cups.c @@ -5,6 +5,7 @@ * Copyright 2010-2011 Vic Lee * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -229,10 +230,12 @@ static void printer_cups_free_printer(rdpPrinter* printer) cups_printer->printjob->printjob.Close((rdpPrintJob*) cups_printer->printjob); free(printer->name); + free(printer->driver); free(printer); } -static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, const char* name, BOOL is_default) +static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, + const char* name, const char* driverName, BOOL is_default) { rdpCupsPrinter* cups_printer; @@ -247,8 +250,17 @@ static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, c free(cups_printer); return NULL; } - /* This is a generic PostScript printer driver developed by MS, so it should be good in most cases */ - cups_printer->printer.driver = "MS Publisher Imagesetter"; + + if (driverName) + cups_printer->printer.driver = _strdup(driverName); + else + cups_printer->printer.driver = _strdup("MS Publisher Imagesetter"); + if (!cups_printer->printer.driver) + { + free(cups_printer->printer.name); + free(cups_printer); + return NULL; + } cups_printer->printer.is_default = is_default; cups_printer->printer.CreatePrintJob = printer_cups_create_printjob; @@ -279,7 +291,7 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver) if (dest->instance == NULL) { printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*) driver, - dest->name, dest->is_default); + dest->name, NULL, dest->is_default); } } cupsFreeDests(num_dests, dests); @@ -287,11 +299,13 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver) return printers; } -static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver, const char* name) +static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver, + const char* name, const char* driverName) { rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*) driver; - return printer_cups_new_printer(cups_driver, name, cups_driver->id_sequence == 1 ? TRUE : FALSE); + return printer_cups_new_printer(cups_driver, name, driverName, + cups_driver->id_sequence == 1 ? TRUE : FALSE); } static rdpCupsPrinterDriver* cups_driver = NULL; diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index 561c253..18d4db8 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -5,6 +5,7 @@ * Copyright 2010-2011 Vic Lee * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +37,8 @@ #include +#include "../printer.h" + #ifdef WITH_CUPS #include "printer_cups.h" #endif @@ -449,6 +452,8 @@ error_out: #ifdef STATIC_CHANNELS #define DeviceServiceEntry printer_DeviceServiceEntry +#else +#define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif /** @@ -487,7 +492,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) if (name && name[0]) { - printer = driver->GetPrinter(driver, name); + printer = driver->GetPrinter(driver, name, driver_name); if (!printer) { @@ -495,9 +500,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) return CHANNEL_RC_INITIALIZATION_ERROR; } - if (driver_name && driver_name[0]) - printer->driver = driver_name; - if ((error = printer_register(pEntryPoints, printer))) { WLog_ERR(TAG, "printer_register failed with error %lu!", error); diff --git a/channels/printer/client/printer_main.h b/channels/printer/client/printer_main.h index 8a2c850..3d9b75a 100644 --- a/channels/printer/client/printer_main.h +++ b/channels/printer/client/printer_main.h @@ -5,6 +5,7 @@ * Copyright 2010-2011 Vic Lee * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,25 +25,12 @@ #include -/* SERVER_PRINTER_CACHE_EVENT.cachedata */ -#define RDPDR_ADD_PRINTER_EVENT 0x00000001 -#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002 -#define RDPDR_DELETE_PRINTER_EVENT 0x00000003 -#define RDPDR_RENAME_PRINTER_EVENT 0x00000004 - -/* DR_PRN_DEVICE_ANNOUNCE.Flags */ -#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010 - typedef struct rdp_printer_driver rdpPrinterDriver; typedef struct rdp_printer rdpPrinter; typedef struct rdp_print_job rdpPrintJob; typedef rdpPrinter** (*pcEnumPrinters) (rdpPrinterDriver* driver); -typedef rdpPrinter* (*pcGetPrinter) (rdpPrinterDriver* driver, const char* name); +typedef rdpPrinter* (*pcGetPrinter) (rdpPrinterDriver* driver, const char* name, const char* driverName); struct rdp_printer_driver { diff --git a/channels/printer/client/printer_win.c b/channels/printer/client/printer_win.c index f30beeb..dc36642 100644 --- a/channels/printer/client/printer_win.c +++ b/channels/printer/client/printer_win.c @@ -5,6 +5,7 @@ * Copyright 2012 Gerald Richter * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -175,10 +176,12 @@ static void printer_win_free_printer(rdpPrinter* printer) win_printer->printjob->printjob.Close((rdpPrintJob*) win_printer->printjob); free(printer->name); + free(printer->driver); free(printer); } -static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, const char* name, const wchar_t* drivername, BOOL is_default) +static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, + const char* name, const WCHAR* drivername, BOOL is_default) { rdpWinPrinter* win_printer; wchar_t wname[256]; @@ -216,7 +219,10 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons } GetPrinter(win_printer->hPrinter, 2, (LPBYTE) prninfo, needed, &needed); - win_printer->printer.driver = malloc(1000); + if (drivername) + win_printer->printer.driver = _wcsdup(drivername); + else + win_printer->printer.driver = _wcsdup(prninfo->pDriverName); if (!win_printer->printer.driver) { GlobalFree(prninfo); @@ -224,7 +230,6 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons free(win_printer); return NULL; } - wcstombs_s(&charsConverted, win_printer->printer.driver, 1000, prninfo->pDriverName, _TRUNCATE); return (rdpPrinter*)win_printer; } @@ -274,13 +279,24 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver) return printers; } -static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver, const char* name) +static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver, + const char* name, const char* driverName) { + WCHAR* driverNameW = NULL; rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver; rdpPrinter *myPrinter = NULL; - myPrinter = printer_win_new_printer(win_driver, name, L"", win_driver->id_sequence == 1 ? TRUE : FALSE); - + if (driverName) + { + ConvertToUnicode(CP_UTF8, 0, driverName, -1, &driverNameW, 0); + if (!driverNameW) + return NULL; + } + + myPrinter = printer_win_new_printer(win_driver, name, driverNameW, + win_driver->id_sequence == 1 ? TRUE : FALSE); + free(driverNameW); + return myPrinter; } diff --git a/channels/printer/printer.h b/channels/printer/printer.h new file mode 100644 index 0000000..2373130 --- /dev/null +++ b/channels/printer/printer.h @@ -0,0 +1,37 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Definition for the printer channel + * + * Copyright 2016 David Fort + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CHANNELS_PRINTER_PRINTER_H_ +#define __CHANNELS_PRINTER_PRINTER_H_ + +/* SERVER_PRINTER_CACHE_EVENT.cachedata */ +#define RDPDR_ADD_PRINTER_EVENT 0x00000001 +#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002 +#define RDPDR_DELETE_PRINTER_EVENT 0x00000003 +#define RDPDR_RENAME_PRINTER_EVENT 0x00000004 + +/* DR_PRN_DEVICE_ANNOUNCE.Flags */ +#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010 + + +#endif /* __CHANNELS_PRINTER_PRINTER_H_ */ diff --git a/channels/rdpdr/client/devman.c b/channels/rdpdr/client/devman.c index 2e16662..60a5cb4 100644 --- a/channels/rdpdr/client/devman.c +++ b/channels/rdpdr/client/devman.c @@ -6,6 +6,7 @@ * Copyright 2010-2012 Marc-Andre Moreau * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +43,9 @@ void devman_device_free(DEVICE* device) { + if (!device) + return; + IFCALL(device->Free, device); } @@ -49,6 +53,9 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr) { DEVMAN* devman; + if (!rdpdr) + return NULL; + devman = (DEVMAN*) calloc(1, sizeof(DEVMAN)); if (!devman) @@ -84,6 +91,9 @@ void devman_unregister_device(DEVMAN* devman, void* key) { DEVICE* device; + if (!devman || !key) + return; + device = (DEVICE*) ListDictionary_Remove(devman->devices, key); if (device) @@ -99,6 +109,9 @@ static UINT devman_register_device(DEVMAN* devman, DEVICE* device) { void* key = NULL; + if (!devman || !device) + return ERROR_INVALID_PARAMETER; + device->id = devman->id_sequence++; key = (void*) (size_t) device->id; @@ -115,6 +128,9 @@ DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id) DEVICE* device = NULL; void* key = (void*) (size_t) id; + if (!devman) + return NULL; + device = (DEVICE*) ListDictionary_GetItemValue(devman->devices, key); return device; @@ -137,6 +153,9 @@ UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext DEVICE_SERVICE_ENTRY_POINTS ep; PDEVICE_SERVICE_ENTRY entry = NULL; + if (!devman || !device || !rdpcontext) + return ERROR_INVALID_PARAMETER; + if (device->Type == RDPDR_DTYP_FILESYSTEM) ServiceName = DRIVE_SERVICE_NAME; else if (device->Type == RDPDR_DTYP_PRINT) diff --git a/channels/rdpdr/client/irp.c b/channels/rdpdr/client/irp.c index 2d1f965..d8eaece 100644 --- a/channels/rdpdr/client/irp.c +++ b/channels/rdpdr/client/irp.c @@ -77,18 +77,28 @@ static UINT irp_complete(IRP* irp) return error; } -IRP* irp_new(DEVMAN* devman, wStream* s) +IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) { IRP* irp; DEVICE* device; UINT32 DeviceId; + if (Stream_GetRemainingLength(s) < 20) + { + if (error) + *error = ERROR_INVALID_DATA; + return NULL; + } + Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */ device = devman_get_device_by_id(devman, DeviceId); if (!device) { - WLog_ERR(TAG, "devman_get_device_by_id failed!"); + WLog_WARN(TAG, "devman_get_device_by_id failed!"); + if (error) + *error = CHANNEL_RC_OK; + return NULL; }; @@ -97,6 +107,8 @@ IRP* irp_new(DEVMAN* devman, wStream* s) if (!irp) { WLog_ERR(TAG, "_aligned_malloc failed!"); + if (error) + *error = CHANNEL_RC_NO_MEMORY; return NULL; } @@ -117,6 +129,8 @@ IRP* irp_new(DEVMAN* devman, wStream* s) { WLog_ERR(TAG, "Stream_New failed!"); _aligned_free(irp); + if (error) + *error = CHANNEL_RC_NO_MEMORY; return NULL; } Stream_Write_UINT16(irp->output, RDPDR_CTYP_CORE); /* Component (2 bytes) */ @@ -131,5 +145,8 @@ IRP* irp_new(DEVMAN* devman, wStream* s) irp->thread = NULL; irp->cancelled = FALSE; + if (error) + *error = CHANNEL_RC_OK; + return irp; } diff --git a/channels/rdpdr/client/irp.h b/channels/rdpdr/client/irp.h index d943663..17d75ac 100644 --- a/channels/rdpdr/client/irp.h +++ b/channels/rdpdr/client/irp.h @@ -23,6 +23,6 @@ #include "rdpdr_main.h" -IRP* irp_new(DEVMAN* devman, wStream* s); +IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error); #endif /* FREERDP_CHANNEL_RDPDR_CLIENT_IRP_H */ diff --git a/channels/rdpdr/client/rdpdr_capabilities.c b/channels/rdpdr/client/rdpdr_capabilities.c index 26f6d52..4ff3ef5 100644 --- a/channels/rdpdr/client/rdpdr_capabilities.c +++ b/channels/rdpdr/client/rdpdr_capabilities.c @@ -4,8 +4,9 @@ * * Copyright 2010-2011 Vic Lee * Copyright 2010-2012 Marc-Andre Moreau - * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015-2016 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,12 +61,21 @@ static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s) } /* Process device direction general capability set */ -static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + if (Stream_GetRemainingLength(s) < 2) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityLength); + + if (Stream_GetRemainingLength(s) < capabilityLength - 4) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4); + + return CHANNEL_RC_OK; } /* Output printer direction capability set */ @@ -75,12 +85,21 @@ static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* s) } /* Process printer direction capability set */ -static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + if (Stream_GetRemainingLength(s) < 2) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityLength); + + if (Stream_GetRemainingLength(s) < capabilityLength - 4) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4); + + return CHANNEL_RC_OK; } /* Output port redirection capability set */ @@ -90,12 +109,21 @@ static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* s) } /* Process port redirection capability set */ -static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + if (Stream_GetRemainingLength(s) < 2) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityLength); + + if (Stream_GetRemainingLength(s) < capabilityLength - 4) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4); + + return CHANNEL_RC_OK; } /* Output drive redirection capability set */ @@ -105,12 +133,21 @@ static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* s) } /* Process drive redirection capability set */ -static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + if (Stream_GetRemainingLength(s) < 2) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityLength); + + if (Stream_GetRemainingLength(s) < capabilityLength - 4) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4); + + return CHANNEL_RC_OK; } /* Output smart card redirection capability set */ @@ -120,53 +157,77 @@ static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) } /* Process smartcard redirection capability set */ -static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + if (Stream_GetRemainingLength(s) < 2) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityLength); + + if (Stream_GetRemainingLength(s) < capabilityLength - 4) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4); + + return CHANNEL_RC_OK; } -void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s) +UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s) { + UINT status = CHANNEL_RC_OK; UINT16 i; UINT16 numCapabilities; UINT16 capabilityType; + if (!rdpdr || !s) + return CHANNEL_RC_NULL_DATA; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, numCapabilities); Stream_Seek(s, 2); /* pad (2 bytes) */ for (i = 0; i < numCapabilities; i++) { + if (Stream_GetRemainingLength(s) < sizeof(UINT16)) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilityType); switch (capabilityType) { - case CAP_GENERAL_TYPE: - rdpdr_process_general_capset(rdpdr, s); - break; + case CAP_GENERAL_TYPE: + status = rdpdr_process_general_capset(rdpdr, s); + break; - case CAP_PRINTER_TYPE: - rdpdr_process_printer_capset(rdpdr, s); - break; + case CAP_PRINTER_TYPE: + status = rdpdr_process_printer_capset(rdpdr, s); + break; - case CAP_PORT_TYPE: - rdpdr_process_port_capset(rdpdr, s); - break; + case CAP_PORT_TYPE: + status = rdpdr_process_port_capset(rdpdr, s); + break; - case CAP_DRIVE_TYPE: - rdpdr_process_drive_capset(rdpdr, s); - break; + case CAP_DRIVE_TYPE: + status = rdpdr_process_drive_capset(rdpdr, s); + break; - case CAP_SMARTCARD_TYPE: - rdpdr_process_smartcard_capset(rdpdr, s); - break; + case CAP_SMARTCARD_TYPE: + status = rdpdr_process_smartcard_capset(rdpdr, s); + break; - default: - break; + default: + break; } + + if (status != CHANNEL_RC_OK) + return status; } + + return CHANNEL_RC_OK; } /** diff --git a/channels/rdpdr/client/rdpdr_capabilities.h b/channels/rdpdr/client/rdpdr_capabilities.h index bc2ef8b..d4e1ecb 100644 --- a/channels/rdpdr/client/rdpdr_capabilities.h +++ b/channels/rdpdr/client/rdpdr_capabilities.h @@ -25,7 +25,7 @@ #include "rdpdr_main.h" -void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s); +UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s); UINT rdpdr_send_capability_response(rdpdrPlugin* rdpdr); #endif /* FREERDP_CHANNEL_RDPDR_CLIENT_CAPABILITIES_H */ diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 30bd268..87ee6fb 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -4,8 +4,9 @@ * * Copyright 2010-2011 Vic Lee * Copyright 2010-2012 Marc-Andre Moreau - * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015-2016 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,7 +82,7 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou UINT32 i; wStream* s; - s = Stream_New(NULL, 256); + s = Stream_New(NULL, count * sizeof(UINT32) + 8); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -429,7 +430,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) BOOL dev_found = FALSE; device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]); - if (!device_ext) + if (!device_ext || !device_ext->path) continue; /* not plugable device */ @@ -496,7 +497,6 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) free(drive->Path); free(drive->Name); free(drive); - error = CHANNEL_RC_NO_MEMORY; goto cleanup; } } @@ -517,15 +517,15 @@ static void* drive_hotplug_thread_func(void* arg) struct timeval tv; int rv; UINT error; - DWORD status; + DWORD status; rdpdr = (rdpdrPlugin*) arg; if (!(rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { WLog_ERR(TAG, "CreateEvent failed!"); - error = ERROR_INTERNAL_ERROR; - goto out; + error = ERROR_INTERNAL_ERROR; + goto out; } mfd = open("/proc/mounts", O_RDONLY, 0); @@ -533,8 +533,8 @@ static void* drive_hotplug_thread_func(void* arg) if (mfd < 0) { WLog_ERR(TAG, "ERROR: Unable to open /proc/mounts."); - error = ERROR_INTERNAL_ERROR; - goto out; + error = ERROR_INTERNAL_ERROR; + goto out; } FD_ZERO(&rfds); @@ -545,18 +545,18 @@ static void* drive_hotplug_thread_func(void* arg) if ((error = handle_hotplug(rdpdr))) { WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); - goto out; + goto out; } while ((rv = select(mfd+1, NULL, NULL, &rfds, &tv)) >= 0) { - status = WaitForSingleObject(rdpdr->stopEvent, 0); - if (status == WAIT_FAILED) - { - error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); - goto out; - } + status = WaitForSingleObject(rdpdr->stopEvent, 0); + if (status == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); + goto out; + } if (status == WAIT_OBJECT_0) break; @@ -566,7 +566,7 @@ static void* drive_hotplug_thread_func(void* arg) if ((error = handle_hotplug(rdpdr))) { WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); - goto out; + goto out; } } @@ -577,11 +577,11 @@ static void* drive_hotplug_thread_func(void* arg) } out: - if (error && rdpdr->rdpcontext) - setChannelError(rdpdr->rdpcontext, error, "drive_hotplug_thread_func reported an error"); + if (error && rdpdr->rdpcontext) + setChannelError(rdpdr->rdpcontext, error, "drive_hotplug_thread_func reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread((DWORD)error); + return NULL; } /** @@ -591,21 +591,22 @@ out: */ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) { - UINT error; + UINT error; + if (rdpdr->hotplugThread) { if (rdpdr->stopEvent) SetEvent(rdpdr->stopEvent); if (WaitForSingleObject(rdpdr->hotplugThread, INFINITE) == WAIT_FAILED) - { - error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); - return error; - } + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); + return error; + } rdpdr->hotplugThread = NULL; } - return CHANNEL_RC_OK; + return CHANNEL_RC_OK; } #endif @@ -661,13 +662,18 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) return error; } -static void rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, wStream* s) { + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, rdpdr->versionMajor); Stream_Read_UINT16(s, rdpdr->versionMinor); Stream_Read_UINT32(s, rdpdr->clientID); rdpdr->sequenceId++; + + return CHANNEL_RC_OK; } /** @@ -683,7 +689,7 @@ static UINT rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr) if (!s) { WLog_ERR(TAG, "Stream_New failed!"); - return CHANNEL_RC_OK; + return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ @@ -733,12 +739,15 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr) return rdpdr_send(rdpdr, s); } -static void rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, wStream* s) +static UINT rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, wStream* s) { UINT16 versionMajor; UINT16 versionMinor; UINT32 clientID; + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, versionMajor); Stream_Read_UINT16(s, versionMinor); Stream_Read_UINT32(s, clientID); @@ -750,9 +759,9 @@ static void rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, wStream* s } if (clientID != rdpdr->clientID) - { rdpdr->clientID = clientID; - } + + return CHANNEL_RC_OK; } /** @@ -804,13 +813,13 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use */ if ((rdpdr->versionMinor == 0x0005) || - (device->type == RDPDR_DTYP_SMARTCARD) || userLoggedOn) + (device->type == RDPDR_DTYP_SMARTCARD) || userLoggedOn) { data_len = (int) (device->data == NULL ? 0 : Stream_GetPosition(device->data)); if (!Stream_EnsureRemainingCapacity(s, 20 + data_len)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); - return CHANNEL_RC_NO_MEMORY; + return ERROR_INVALID_DATA; } Stream_Write_UINT32(s, device->type); /* deviceType */ @@ -859,20 +868,20 @@ static UINT rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* s) IRP* irp; UINT error = CHANNEL_RC_OK; - irp = irp_new(rdpdr->devman, s); + irp = irp_new(rdpdr->devman, s, &error); if (!irp) { - WLog_ERR(TAG, "irp_new failed!"); - return CHANNEL_RC_NO_MEMORY; + WLog_ERR(TAG, "irp_new failed with %lu!", error); + return error; } IFCALLRET(irp->device->IRPRequest, error, irp->device, irp); - if (error) - WLog_ERR(TAG, "device->IRPRequest failed with error %lu", error); + if (error) + WLog_ERR(TAG, "device->IRPRequest failed with error %lu", error); - return error; + return error; } /** @@ -921,6 +930,12 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) UINT32 status; UINT error; + if (!rdpdr || !s) + return CHANNEL_RC_NULL_DATA; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, component); /* Component (2 bytes) */ Stream_Read_UINT16(s, packetId); /* PacketId (2 bytes) */ @@ -928,70 +943,77 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) { switch (packetId) { - case PAKID_CORE_SERVER_ANNOUNCE: - rdpdr_process_server_announce_request(rdpdr, s); - if ((error = rdpdr_send_client_announce_reply(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %lu", error); - return error; - } - if ((error = rdpdr_send_client_name_request(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %lu", error); - return error; - } - if ((error = rdpdr_process_init(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_process_init failed with error %lu", error); - return error; - } - break; + case PAKID_CORE_SERVER_ANNOUNCE: + if ((error = rdpdr_process_server_announce_request(rdpdr, s))) + return error; + if ((error = rdpdr_send_client_announce_reply(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %lu", error); + return error; + } + if ((error = rdpdr_send_client_name_request(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %lu", error); + return error; + } + if ((error = rdpdr_process_init(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_process_init failed with error %lu", error); + return error; + } + break; - case PAKID_CORE_SERVER_CAPABILITY: - rdpdr_process_capability_request(rdpdr, s); - if ((error = rdpdr_send_capability_response(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %lu", error); - return error; - } - break; + case PAKID_CORE_SERVER_CAPABILITY: + if ((error = rdpdr_process_capability_request(rdpdr, s))) + return error; + if ((error = rdpdr_send_capability_response(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %lu", error); + return error; + } + break; - case PAKID_CORE_CLIENTID_CONFIRM: - rdpdr_process_server_clientid_confirm(rdpdr, s); - if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) - { - WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu", error); - return error; - } - break; + case PAKID_CORE_CLIENTID_CONFIRM: + if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s))) + return error; - case PAKID_CORE_USER_LOGGEDON: - if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE))) - { - WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu", error); - return error; - } - break; + if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) + { + WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu", error); + return error; + } + break; - case PAKID_CORE_DEVICE_REPLY: - /* connect to a specific resource */ - Stream_Read_UINT32(s, deviceId); - Stream_Read_UINT32(s, status); - break; + case PAKID_CORE_USER_LOGGEDON: + if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE))) + { + WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %lu", error); + return error; + } + break; - case PAKID_CORE_DEVICE_IOREQUEST: - if ((error = rdpdr_process_irp(rdpdr, s))) - { - WLog_ERR(TAG, "rdpdr_process_irp failed with error %lu", error); - return error; - } - s = NULL; - break; - - default: - WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04X", packetId); + case PAKID_CORE_DEVICE_REPLY: + /* connect to a specific resource */ + if (Stream_GetRemainingLength(s) < 8) return ERROR_INVALID_DATA; - break; + + Stream_Read_UINT32(s, deviceId); + Stream_Read_UINT32(s, status); + break; + + case PAKID_CORE_DEVICE_IOREQUEST: + if ((error = rdpdr_process_irp(rdpdr, s))) + { + WLog_ERR(TAG, "rdpdr_process_irp failed with error %lu", error); + return error; + } + s = NULL; + break; + + default: + WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04X", packetId); + return ERROR_INVALID_DATA; + break; } } @@ -999,21 +1021,24 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) { switch (packetId) { - case PAKID_PRN_CACHE_DATA: - { - UINT32 eventID; - Stream_Read_UINT32(s, eventID); - WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_CACHE_DATA (EventID: 0x%04X)", eventID); - } - break; - - case PAKID_PRN_USING_XPS: - WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_USING_XPS"); - break; - - default: - WLog_ERR(TAG, "Unknown printing component packetID: 0x%04X", packetId); + case PAKID_PRN_CACHE_DATA: + { + UINT32 eventID; + if (Stream_GetRemainingLength(s) < 4) return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, eventID); + WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_CACHE_DATA (EventID: 0x%04X)", eventID); + } + break; + + case PAKID_PRN_USING_XPS: + WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_USING_XPS"); + break; + + default: + WLog_ERR(TAG, "Unknown printing component packetID: 0x%04X", packetId); + return ERROR_INVALID_DATA; } } else @@ -1132,14 +1157,15 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) UINT status; rdpdrPlugin* plugin = (rdpdrPlugin*) rdpdr; + if (!rdpdr || !s) + return CHANNEL_RC_NULL_DATA; + if (!plugin) - { status = CHANNEL_RC_BAD_INIT_HANDLE; - } else { status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle, - Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); + Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); } if (status != CHANNEL_RC_OK) @@ -1158,7 +1184,7 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) * @return 0 on success, otherwise a Win32 error code */ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, - void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) + void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* data_in; @@ -1190,7 +1216,7 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); - return CHANNEL_RC_NO_MEMORY; + return ERROR_INVALID_DATA; } Stream_Write(data_in, pData, dataLength); @@ -1216,14 +1242,14 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, } static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle, UINT event, - LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) + LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { rdpdrPlugin* rdpdr; UINT error = CHANNEL_RC_OK; rdpdr = (rdpdrPlugin*) rdpdr_get_open_handle_data(openHandle); - if (!rdpdr) + if (!rdpdr || !pData) { WLog_ERR(TAG, "rdpdr_virtual_channel_open_event: error no match"); return; @@ -1231,17 +1257,17 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle, UINT ev switch (event) { - case CHANNEL_EVENT_DATA_RECEIVED: - if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags))) - WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received failed with error %lu!", error ); - break; + case CHANNEL_EVENT_DATA_RECEIVED: + if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags))) + WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received failed with error %lu!", error ); + break; - case CHANNEL_EVENT_WRITE_COMPLETE: - Stream_Free((wStream*) pData, TRUE); - break; + case CHANNEL_EVENT_WRITE_COMPLETE: + Stream_Free((wStream*) pData, TRUE); + break; - case CHANNEL_EVENT_USER: - break; + case CHANNEL_EVENT_USER: + break; } if (error && rdpdr->rdpcontext) setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_open_event reported an error"); @@ -1256,6 +1282,12 @@ static void* rdpdr_virtual_channel_client_thread(void* arg) rdpdrPlugin* rdpdr = (rdpdrPlugin*) arg; UINT error; + if (!rdpdr) + { + ExitThread((DWORD) CHANNEL_RC_NULL_DATA); + return NULL; + } + if ((error = rdpdr_process_connect(rdpdr))) { WLog_ERR(TAG, "rdpdr_process_connect failed with error %lu!", error); @@ -1305,16 +1337,16 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pDa UINT error; status = rdpdr->channelEntryPoints.pVirtualChannelOpen(rdpdr->InitHandle, - &rdpdr->OpenHandle, rdpdr->channelDef.name, rdpdr_virtual_channel_open_event); + &rdpdr->OpenHandle, rdpdr->channelDef.name, rdpdr_virtual_channel_open_event); - if (status != CHANNEL_RC_OK) - { - WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]", - WTSErrorToString(status), status); - return status; - } + if (status != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]", + WTSErrorToString(status), status); + return status; + } - if ((error = rdpdr_add_open_handle_data(rdpdr->OpenHandle, rdpdr))) + if ((error = rdpdr_add_open_handle_data(rdpdr->OpenHandle, rdpdr))) { WLog_ERR(TAG, "rdpdr_add_open_handle_data failed with error %lu!", error); return error; @@ -1346,11 +1378,11 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) UINT error; if (MessageQueue_PostQuit(rdpdr->queue, 0) && (WaitForSingleObject(rdpdr->thread, INFINITE) == WAIT_FAILED)) - { - error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); - return error; - } + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); + return error; + } MessageQueue_Free(rdpdr->queue); CloseHandle(rdpdr->thread); @@ -1359,10 +1391,10 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) rdpdr->thread = NULL; if ((error = drive_hotplug_thread_terminate(rdpdr))) - { - WLog_ERR(TAG, "drive_hotplug_thread_terminate failed with error %lu!", error); - return error; - } + { + WLog_ERR(TAG, "drive_hotplug_thread_terminate failed with error %lu!", error); + return error; + } error = rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle); if (CHANNEL_RC_OK != error) @@ -1409,25 +1441,25 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT switch (event) { - case CHANNEL_EVENT_INITIALIZED: - break; - case CHANNEL_EVENT_CONNECTED: - if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength))) - WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %lu!", error); - break; + case CHANNEL_EVENT_INITIALIZED: + break; + case CHANNEL_EVENT_CONNECTED: + if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength))) + WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %lu!", error); + break; - case CHANNEL_EVENT_DISCONNECTED: - if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr))) - WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %lu!", error); - break; + case CHANNEL_EVENT_DISCONNECTED: + if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr))) + WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %lu!", error); + break; - case CHANNEL_EVENT_TERMINATED: - rdpdr_virtual_channel_event_terminated(rdpdr); - break; - default: - WLog_ERR(TAG, "unknown event %d!", event); - error = ERROR_INVALID_DATA; - break; + case CHANNEL_EVENT_TERMINATED: + rdpdr_virtual_channel_event_terminated(rdpdr); + break; + default: + WLog_ERR(TAG, "unknown event %d!", event); + error = ERROR_INVALID_DATA; + break; } if (error && rdpdr->rdpcontext) @@ -1444,7 +1476,6 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) rdpdrPlugin* rdpdr; CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; - rdpdr = (rdpdrPlugin*) calloc(1, sizeof(rdpdrPlugin)); if (!rdpdr) @@ -1473,7 +1504,6 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); - rc = rdpdr->channelEntryPoints.pVirtualChannelInit(&rdpdr->InitHandle, &rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpdr_virtual_channel_init_event); diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index d1cbb7c..6acfcc7 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -957,6 +957,8 @@ UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y, #ifdef STATIC_CHANNELS #define DVCPluginEntry rdpei_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 7da8c9f..07ec66c 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -1515,6 +1515,8 @@ void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cacheSlot) #ifdef STATIC_CHANNELS #define DVCPluginEntry rdpgfx_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/rdpsnd/client/mac/rdpsnd_mac.c b/channels/rdpsnd/client/mac/rdpsnd_mac.c index 00588f5..5867480 100644 --- a/channels/rdpsnd/client/mac/rdpsnd_mac.c +++ b/channels/rdpsnd/client/mac/rdpsnd_mac.c @@ -5,6 +5,8 @@ * Copyright 2012 Laxmikant Rashinkar * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Inuvika Inc. + * Copyright 2016 David PHAM-VAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,6 +56,12 @@ struct rdpsnd_mac_plugin AudioQueueRef audioQueue; AudioStreamBasicDescription audioFormat; AudioQueueBufferRef audioBuffers[MAC_AUDIO_QUEUE_NUM_BUFFERS]; + + Float64 lastStartTime; + + int wformat; + int block_size; + FREERDP_DSP_CONTEXT* dsp_context; }; typedef struct rdpsnd_mac_plugin rdpsndMacPlugin; @@ -69,6 +77,15 @@ static BOOL rdpsnd_mac_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* form mac->latency = (UINT32) latency; CopyMemory(&(mac->format), format, sizeof(AUDIO_FORMAT)); + mac->audioFormat.mSampleRate = format->nSamplesPerSec; + mac->audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; + mac->audioFormat.mFramesPerPacket = 1; + mac->audioFormat.mChannelsPerFrame = format->nChannels; + mac->audioFormat.mBitsPerChannel = format->wBitsPerSample; + mac->audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8; + mac->audioFormat.mBytesPerPacket = format->nBlockAlign; + mac->audioFormat.mReserved = 0; + switch (format->wFormatTag) { case WAVE_FORMAT_ALAW: @@ -83,6 +100,14 @@ static BOOL rdpsnd_mac_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* form mac->audioFormat.mFormatID = kAudioFormatLinearPCM; break; + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: + mac->audioFormat.mFormatID = kAudioFormatLinearPCM; + mac->audioFormat.mBitsPerChannel = 16; + mac->audioFormat.mBytesPerFrame = (16 * format->nChannels) / 8; + mac->audioFormat.mBytesPerPacket = mac->audioFormat.mFramesPerPacket * mac->audioFormat.mBytesPerFrame; + break; + case WAVE_FORMAT_GSM610: mac->audioFormat.mFormatID = kAudioFormatMicrosoftGSM; break; @@ -91,14 +116,8 @@ static BOOL rdpsnd_mac_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* form break; } - mac->audioFormat.mSampleRate = format->nSamplesPerSec; - mac->audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; - mac->audioFormat.mFramesPerPacket = 1; - mac->audioFormat.mChannelsPerFrame = format->nChannels; - mac->audioFormat.mBitsPerChannel = format->wBitsPerSample; - mac->audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8; - mac->audioFormat.mBytesPerPacket = format->nBlockAlign; - mac->audioFormat.mReserved = 0; + mac->wformat = format->wFormatTag; + mac->block_size = format->nBlockAlign; rdpsnd_print_audio_format(format); return TRUE; @@ -122,6 +141,8 @@ static BOOL rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in return FALSE; } + freerdp_dsp_context_reset_adpcm(mac->dsp_context); + status = AudioQueueNewOutput(&(mac->audioFormat), mac_audio_queue_output_cb, mac, NULL, NULL, 0, &(mac->audioQueue)); @@ -156,7 +177,9 @@ static BOOL rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, in return FALSE; } } - + + mac->lastStartTime = 0; + mac->isOpen = TRUE; return TRUE; } @@ -184,27 +207,24 @@ static void rdpsnd_mac_free(rdpsndDevicePlugin* device) device->Close(device); + freerdp_dsp_context_free(mac->dsp_context); + free(mac); } static BOOL rdpsnd_mac_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format) { - if (format->wFormatTag == WAVE_FORMAT_PCM) - { - return TRUE; - } - else if (format->wFormatTag == WAVE_FORMAT_ALAW) - { - return TRUE; - } - else if (format->wFormatTag == WAVE_FORMAT_MULAW) - { - return TRUE; - } - else if (format->wFormatTag == WAVE_FORMAT_GSM610) - { - return FALSE; - } + switch (format->wFormatTag) + { + case WAVE_FORMAT_PCM: + case WAVE_FORMAT_ALAW: + case WAVE_FORMAT_MULAW: + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: + return TRUE; + case WAVE_FORMAT_GSM610: + return FALSE; + } return FALSE; } @@ -258,10 +278,42 @@ static void rdpsnd_mac_start(rdpsndDevicePlugin* device) } } -static void rdpsnd_mac_play(rdpsndDevicePlugin* device, BYTE* data, int size) +static BOOL rdpsnd_mac_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wave) +{ + int length; + BYTE* data; + rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device; + + if (mac->wformat == WAVE_FORMAT_ADPCM) + { + mac->dsp_context->decode_ms_adpcm(mac->dsp_context, wave->data, wave->length, mac->format.nChannels, mac->block_size); + length = mac->dsp_context->adpcm_size; + data = mac->dsp_context->adpcm_buffer; + } + else if (mac->wformat == WAVE_FORMAT_DVI_ADPCM) + { + mac->dsp_context->decode_ima_adpcm(mac->dsp_context, wave->data, wave->length, mac->format.nChannels, mac->block_size); + length = mac->dsp_context->adpcm_size; + data = mac->dsp_context->adpcm_buffer; + } + else + { + length = wave->length; + data = wave->data; + } + + wave->data = (BYTE*) malloc(length); + CopyMemory(wave->data, data, length); + wave->length = length; + + return TRUE; +} + +static void rdpsnd_mac_waveplay(rdpsndDevicePlugin* device, RDPSND_WAVE* wave) { int length; AudioQueueBufferRef audioBuffer; + AudioTimeStamp outActualStartTime; rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device; if (!mac->isOpen) @@ -269,13 +321,18 @@ static void rdpsnd_mac_play(rdpsndDevicePlugin* device, BYTE* data, int size) audioBuffer = mac->audioBuffers[mac->audioBufferIndex]; - length = size > audioBuffer->mAudioDataBytesCapacity ? audioBuffer->mAudioDataBytesCapacity : size; + length = wave->length > audioBuffer->mAudioDataBytesCapacity ? audioBuffer->mAudioDataBytesCapacity : wave->length; - CopyMemory(audioBuffer->mAudioData, data, length); + CopyMemory(audioBuffer->mAudioData, wave->data, length); audioBuffer->mAudioDataByteSize = length; - - AudioQueueEnqueueBuffer(mac->audioQueue, audioBuffer, 0, 0); - + audioBuffer->mUserData = wave; + + AudioQueueEnqueueBufferWithParameters(mac->audioQueue, audioBuffer, 0, 0, 0, 0, 0, NULL, NULL, &outActualStartTime); + UInt64 startTimeDelta = (outActualStartTime.mSampleTime - mac->lastStartTime) / 100.0; + wave->wLocalTimeB = wave->wLocalTimeA + startTimeDelta + wave->wAudioLength; + wave->wTimeStampB = wave->wTimeStampA + wave->wLocalTimeB - wave->wLocalTimeA; + mac->lastStartTime = outActualStartTime.mSampleTime; + mac->audioBufferIndex++; if (mac->audioBufferIndex >= MAC_AUDIO_QUEUE_NUM_BUFFERS) @@ -308,10 +365,13 @@ UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS p mac->device.FormatSupported = rdpsnd_mac_format_supported; mac->device.SetFormat = rdpsnd_mac_set_format; mac->device.SetVolume = rdpsnd_mac_set_volume; - mac->device.Play = rdpsnd_mac_play; + mac->device.WaveDecode = rdpsnd_mac_wave_decode; + mac->device.WavePlay = rdpsnd_mac_waveplay; mac->device.Start = rdpsnd_mac_start; mac->device.Close = rdpsnd_mac_close; mac->device.Free = rdpsnd_mac_free; + + mac->dsp_context = freerdp_dsp_context_new(); pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac); diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index 548fa56..b9650a9 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -813,6 +813,8 @@ static UINT serial_free(DEVICE* device) #ifdef STATIC_CHANNELS #define DeviceServiceEntry serial_DeviceServiceEntry +#else +#define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif /** diff --git a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c index 87feb45..0e35f73 100644 --- a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c +++ b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c @@ -489,8 +489,7 @@ static BOOL tsmf_gstreamer_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* m NULL); break; case TSMF_SUB_TYPE_FLAC: - mdecoder->gst_caps = gst_caps_new_simple("audio/x-flac", - NULL); + mdecoder->gst_caps = gst_caps_new_simple("audio/x-flac", "", NULL); break; default: WLog_ERR(TAG, "unknown format:(%d).", media_type->SubType); diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index 6e373ec..bc202ea 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -527,6 +527,8 @@ static UINT tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) #ifdef STATIC_CHANNELS #define DVCPluginEntry tsmf_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c index f7906e2..2b1a574 100644 --- a/channels/tsmf/client/tsmf_media.c +++ b/channels/tsmf/client/tsmf_media.c @@ -548,6 +548,8 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample) int index = 0; for (index = 0; index < count; index++) { + UINT64 time_diff; + temp_stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index); if (temp_stream->major_type == TSMF_MAJOR_TYPE_AUDIO) { @@ -558,8 +560,14 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample) if (video_time < audio_time) max_adjust = -VIDEO_ADJUST_MAX; - sample->start_time += abs(video_time - audio_time) < VIDEO_ADJUST_MAX ? (video_time - audio_time) : max_adjust; - sample->end_time += abs(video_time - audio_time) < VIDEO_ADJUST_MAX ? (video_time - audio_time) : max_adjust; + if (video_time > audio_time) + time_diff = video_time - audio_time; + else + time_diff = audio_time - video_time; + + time_diff = time_diff < VIDEO_ADJUST_MAX ? time_diff : max_adjust; + sample->start_time += time_diff; + sample->end_time += time_diff; break; } @@ -1215,11 +1223,11 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id, error_add: SetEvent(stream->stopEvent); if (WaitForSingleObject(stream->ack_thread, INFINITE) == WAIT_FAILED) - WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); + WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); error_ack_thread: SetEvent(stream->stopEvent); if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED) - WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); + WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); error_play_thread: Queue_Free(stream->sample_ack_list); error_sample_ack_list: diff --git a/channels/urbdrc/client/urbdrc_main.c b/channels/urbdrc/client/urbdrc_main.c index 78cd77d..cbb9379 100644 --- a/channels/urbdrc/client/urbdrc_main.c +++ b/channels/urbdrc/client/urbdrc_main.c @@ -1026,7 +1026,7 @@ static void* urbdrc_search_usb_device(void* arg) } else { - WLog_ERR(TAG, "No Device from receive_device(). An error occured."); + WLog_ERR(TAG, "No Device from receive_device(). An error occurred."); } } } @@ -1541,6 +1541,8 @@ static UINT urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args) #ifdef STATIC_CHANNELS #define DVCPluginEntry urbdrc_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/ci/cmake-preloads/config-windows.txt b/ci/cmake-preloads/config-windows.txt index 980bcb2..0a84d88 100644 --- a/ci/cmake-preloads/config-windows.txt +++ b/ci/cmake-preloads/config-windows.txt @@ -1,3 +1,4 @@ message("PRELOADING windows cache") set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type") +set(WITH_SERVER "ON" CACHE BOOL "Build server binaries") #set (BUILD_TESTING ON CACHE BOOL "build testing") diff --git a/client/FreeRDP-ClientConfig.cmake.in b/client/FreeRDP-ClientConfig.cmake.in index ba3b8d1..779374c 100644 --- a/client/FreeRDP-ClientConfig.cmake.in +++ b/client/FreeRDP-ClientConfig.cmake.in @@ -1,10 +1,10 @@ @PACKAGE_INIT@ -set(FreeRDP_VERSION_MAJOR "@FREERDP_VERSION_MAJOR@") -set(FreeRDP_VERSION_MINOR "@FREERDP_VERSION_MINOR@") -set(FreeRDP_VERSION_REVISION "@FREERDP_VERSION_REVISION@") +set(FreeRDP-Client_VERSION_MAJOR "@FREERDP_VERSION_MAJOR@") +set(FreeRDP-Client_VERSION_MINOR "@FREERDP_VERSION_MINOR@") +set(FreeRDP-Client_VERSION_REVISION "@FREERDP_VERSION_REVISION@") -set_and_check(FreeRDP_INCLUDE_DIR "@PACKAGE_FREERDP_INCLUDE_DIR@") +set_and_check(FreeRDP-Client_INCLUDE_DIR "@PACKAGE_FREERDP_INCLUDE_DIR@") include("${CMAKE_CURRENT_LIST_DIR}/FreeRDP-ClientTargets.cmake") diff --git a/client/Wayland/CMakeLists.txt b/client/Wayland/CMakeLists.txt index 66cb0d1..315be7d 100644 --- a/client/Wayland/CMakeLists.txt +++ b/client/Wayland/CMakeLists.txt @@ -2,6 +2,7 @@ # FreeRDP Wayland Client cmake build script # # Copyright 2014 Manuel Bachmann +# Copyright 2015 David Fort # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,22 +19,19 @@ set(MODULE_NAME "wlfreerdp") set(MODULE_PREFIX "FREERDP_CLIENT_WAYLAND") -include_directories(${WAYLAND_INCLUDE_DIRS}) +include_directories(${CMAKE_SOURCE_DIR}/uwac/include) set(${MODULE_PREFIX}_SRCS - wlf_display.c - wlf_display.h - wlf_window.c - wlf_window.h + wlfreerdp.c + wlfreerdp.h wlf_input.c wlf_input.h - wlfreerdp.c - wlfreerdp.h) + ) add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CMAKE_DL_LIBS}) -set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${WAYLAND_LIBRARIES} freerdp-client freerdp) +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client freerdp uwac) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client) diff --git a/client/Wayland/wlf_display.c b/client/Wayland/wlf_display.c deleted file mode 100644 index 4ab9712..0000000 --- a/client/Wayland/wlf_display.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Wayland Displays - * - * Copyright 2014 Manuel Bachmann - * - * 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. - */ - -#include -#include - -#include "wlf_display.h" - -static void wl_registry_handle_global(void* data, struct wl_registry* registry, uint32_t id, const char *interface, uint32_t version) -{ - wlfDisplay* display = data; - - if (strcmp(interface, "wl_compositor") == 0) - display->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); - else if (strcmp(interface, "wl_shell") == 0) - display->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1); - else if (strcmp(interface, "wl_shm") == 0) - display->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); - else if (strcmp(interface, "wl_seat") == 0) - display->seat = wl_registry_bind(registry, id, &wl_seat_interface, 1); -} - -static void wl_registry_handle_global_remove(void* data, struct wl_registry* registry, uint32_t name) -{ - -} - -static const struct wl_registry_listener wl_registry_listener = -{ - wl_registry_handle_global, - wl_registry_handle_global_remove -}; - - -wlfDisplay* wlf_CreateDisplay(void) -{ - wlfDisplay* display; - - display = (wlfDisplay*) calloc(1, sizeof(wlfDisplay)); - - if (display) - { - display->display = wl_display_connect(NULL); - - if (!display->display) - { - WLog_ERR(TAG, "wl_pre_connect: failed to connect to Wayland compositor"); - WLog_ERR(TAG, "Please check that the XDG_RUNTIME_DIR environment variable is properly set."); - free(display); - return NULL; - } - - display->registry = wl_display_get_registry(display->display); - wl_registry_add_listener(display->registry, &wl_registry_listener, display); - wl_display_roundtrip(display->display); - - if (!display->compositor || !display->shell || !display->shm) - { - WLog_ERR(TAG, "wl_pre_connect: failed to find needed compositor interfaces"); - free(display); - return NULL; - } - } - - return display; -} - -BOOL wlf_RefreshDisplay(wlfDisplay* display) -{ - if (wl_display_dispatch(display->display) == -1) - return FALSE; - return TRUE; -} - -void wlf_DestroyDisplay(wlfContext* wlfc, wlfDisplay* display) -{ - if (display == NULL) - return; - - if (wlfc->display == display) - wlfc->display = NULL; - - if (display->seat) - wl_seat_destroy(display->seat); - if (display->shm) - wl_shm_destroy(display->shm); - if (display->shell) - wl_shell_destroy(display->shell); - if (display->compositor) - wl_compositor_destroy(display->compositor); - if (display->registry) - wl_registry_destroy(display->registry); - wl_display_disconnect(display->display); - - free(display); -} diff --git a/client/Wayland/wlf_display.h b/client/Wayland/wlf_display.h deleted file mode 100644 index d92d899..0000000 --- a/client/Wayland/wlf_display.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Wayland Displays - * - * Copyright 2014 Manuel Bachmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __WLF_DISPLAY_H -#define __WLF_DISPLAY_H - -#include - -typedef struct wlf_display wlfDisplay; - -#include "wlfreerdp.h" - -struct wlf_display -{ - struct wl_display* display; - struct wl_registry* registry; - struct wl_compositor* compositor; - struct wl_shell* shell; - struct wl_shm* shm; - struct wl_seat* seat; -}; - -wlfDisplay* wlf_CreateDisplay(void); -BOOL wlf_RefreshDisplay(wlfDisplay* display); -void wlf_DestroyDisplay(wlfContext* wlfc, wlfDisplay* display); - -#endif /* __WLF_DISPLAY_H */ diff --git a/client/Wayland/wlf_input.c b/client/Wayland/wlf_input.c index 76ab555..00435ff 100644 --- a/client/Wayland/wlf_input.c +++ b/client/Wayland/wlf_input.c @@ -3,6 +3,7 @@ * Wayland Input * * Copyright 2014 Manuel Bachmann + * Copyright 2015 David Fort * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,50 +25,30 @@ #include "wlf_input.h" -static void wl_pointer_enter(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t sx_w, wl_fixed_t sy_w) -{ +BOOL wlf_handle_pointer_enter(freerdp *instance, UwacPointerEnterLeaveEvent *ev) { + rdpInput* input = instance->input; + return input->MouseEvent(input, PTR_FLAGS_MOVE, ev->x, ev->y); } -static void wl_pointer_leave(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface) -{ - +BOOL wlf_handle_pointer_motion(freerdp *instance, UwacPointerMotionEvent *ev) { + rdpInput* input = instance->input; + + return input->MouseEvent(input, PTR_FLAGS_MOVE, ev->x, ev->y); } -static void wl_pointer_motion(void* data, struct wl_pointer* pointer, uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) -{ - wlfInput* input_w = data; +BOOL wlf_handle_pointer_buttons(freerdp *instance, UwacPointerButtonEvent *ev) { rdpInput* input; - UINT16 x; - UINT16 y; - - input = input_w->input; - - x = (UINT16) wl_fixed_to_int(sx_w); - y = (UINT16) wl_fixed_to_int(sy_w); - - input->MouseEvent(input, PTR_FLAGS_MOVE, x, y); - - input_w->last_x = x; - input_w->last_y = y; -} - -static void wl_pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) -{ - wlfInput* input_w = data; - rdpInput* input; - UINT16 x; - UINT16 y; UINT16 flags; - input = input_w->input; + input = instance->input; - if (state == WL_POINTER_BUTTON_STATE_PRESSED) + if (ev->state == WL_POINTER_BUTTON_STATE_PRESSED) flags = PTR_FLAGS_DOWN; else flags = 0; - switch (button) + switch (ev->button) { case BTN_LEFT: flags |= PTR_FLAGS_BUTTON1; @@ -79,175 +60,50 @@ static void wl_pointer_button(void* data, struct wl_pointer* pointer, uint32_t s flags |= PTR_FLAGS_BUTTON3; break; default: - return; + return TRUE; } - x = input_w->last_x; - y = input_w->last_y; - - input->MouseEvent(input, flags, x, y); + return input->MouseEvent(input, flags, ev->x, ev->y); } -static void wl_pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time, uint32_t axis, wl_fixed_t value) -{ - wlfInput* input_w = data; + +BOOL wlf_handle_pointer_axis(freerdp *instance, UwacPointerAxisEvent *ev) { rdpInput* input; UINT16 flags; int direction; - input = input_w->input; + input = instance->input; flags = PTR_FLAGS_WHEEL; - if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) + if (ev->axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { - direction = wl_fixed_to_int(value); + direction = wl_fixed_to_int(ev->value); if (direction < 0) flags |= 0x0078; else flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088; } - input->MouseEvent(input, flags, 0, 0); + return input->MouseEvent(input, flags, ev->x, ev->y); } -static const struct wl_pointer_listener wl_pointer_listener = -{ - wl_pointer_enter, - wl_pointer_leave, - wl_pointer_motion, - wl_pointer_button, - wl_pointer_axis -}; - -static void wl_keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format, int fd, uint32_t size) -{ - -} - -static void wl_keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface, struct wl_array* keys) -{ - wlfInput* input_w = data; - rdpInput* input; - UINT16 x; - UINT16 y; - - input = input_w->input; - - x = input_w->last_x; - y = input_w->last_y; - - input->FocusInEvent(input, 0); - input->MouseEvent(input, PTR_FLAGS_MOVE, x, y); -} - -static void wl_keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface) -{ - -} - -static void wl_keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) -{ - wlfInput* input_w = data; - rdpInput* input; - BOOL key_down; +BOOL wlf_handle_key(freerdp *instance, UwacKeyEvent *ev) { + rdpInput* input = instance->input; DWORD rdp_scancode; - input = input_w->input; - - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) - key_down = TRUE; - else - key_down = FALSE; - - rdp_scancode = (DWORD) key; + rdp_scancode = (DWORD) ev->raw_key; if (rdp_scancode == RDP_SCANCODE_UNKNOWN) - return; + return TRUE; - freerdp_input_send_keyboard_event_ex(input, key_down, rdp_scancode); + return freerdp_input_send_keyboard_event_ex(input, ev->pressed, rdp_scancode); } -static void wl_keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t mods_depr, uint32_t mods_latch, uint32_t mods_lock, uint32_t group) -{ +BOOL wlf_keyboard_enter(freerdp *instance, UwacKeyboardEnterLeaveEvent *ev) { + rdpInput* input = instance->input; + + return input->FocusInEvent(input, 0) && + input->MouseEvent(input, PTR_FLAGS_MOVE, 0, 0); } - -static const struct wl_keyboard_listener wl_keyboard_listener = -{ - wl_keyboard_keymap, - wl_keyboard_enter, - wl_keyboard_leave, - wl_keyboard_key, - wl_keyboard_modifiers -}; - -static void wl_seat_handle_capabilities(void* data, struct wl_seat* seat, enum wl_seat_capability capabilities) -{ - wlfInput* input = data; - struct wl_pointer* pointer; - struct wl_keyboard* keyboard; - - if (capabilities & WL_SEAT_CAPABILITY_POINTER) - { - pointer = wl_seat_get_pointer(seat); - - input->pointer = pointer; - wl_pointer_add_listener(pointer, &wl_pointer_listener, input); - } - - if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) - { - keyboard = wl_seat_get_keyboard(seat); - - input->keyboard = keyboard; - wl_keyboard_add_listener(keyboard, &wl_keyboard_listener, input); - } - -} - -static const struct wl_seat_listener wl_seat_listener = { - wl_seat_handle_capabilities -}; - - -wlfInput* wlf_CreateInput(wlfContext* wlfc) -{ - wlfInput* input; - struct wl_seat* seat; - - if (!wlfc->display) - return NULL; - if (!wlfc->display->seat) - return NULL; - seat = wlfc->display->seat; - - input = (wlfInput*) calloc(1, sizeof(wlfInput)); - - if (input) - { - input->input = wlfc->context.input; - input->last_x = 0; - input->last_y = 0; - - wl_seat_add_listener(seat, &wl_seat_listener, input); - } - - return input; -} - -void wlf_DestroyInput(wlfContext* wlfc, wlfInput* input) -{ - if (input == NULL) - return; - - if (wlfc->input == input) - wlfc->input = NULL; - - if (input->pointer) - wl_pointer_release(input->pointer); - if (input->keyboard) - wl_keyboard_release(input->keyboard); - - free(input); -} diff --git a/client/Wayland/wlf_input.h b/client/Wayland/wlf_input.h index 46f2447..0529f01 100644 --- a/client/Wayland/wlf_input.h +++ b/client/Wayland/wlf_input.h @@ -3,6 +3,7 @@ * Wayland Input * * Copyright 2014 Manuel Bachmann + * Copyright 2015 David Fort * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,23 +21,15 @@ #ifndef __WLF_INPUT_H #define __WLF_INPUT_H -#include +#include +#include -typedef struct wlf_input wlfInput; +BOOL wlf_handle_pointer_enter(freerdp* instance, UwacPointerEnterLeaveEvent *ev); +BOOL wlf_handle_pointer_motion(freerdp* instance, UwacPointerMotionEvent *ev); +BOOL wlf_handle_pointer_buttons(freerdp* instance, UwacPointerButtonEvent *ev); +BOOL wlf_handle_pointer_axis(freerdp* instance, UwacPointerAxisEvent *ev); -#include "wlfreerdp.h" - -struct wlf_input -{ - rdpInput* input; - UINT16 last_x; - UINT16 last_y; - - struct wl_pointer* pointer; - struct wl_keyboard* keyboard; -}; - -wlfInput* wlf_CreateInput(wlfContext* wlfc); -void wlf_DestroyInput(wlfContext* wlfc, wlfInput* input); +BOOL wlf_handle_key(freerdp* instance, UwacKeyEvent *ev); +BOOL wlf_keyboard_enter(freerdp *instance, UwacKeyboardEnterLeaveEvent *ev); #endif /* __WLF_INPUT_H */ diff --git a/client/Wayland/wlf_window.c b/client/Wayland/wlf_window.c deleted file mode 100644 index 72b57ea..0000000 --- a/client/Wayland/wlf_window.c +++ /dev/null @@ -1,220 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Wayland Windows - * - * Copyright 2014 Manuel Bachmann - * - * 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. - */ - -#include -#include -#include -#include -#include - -#include "wlf_window.h" - -static void wl_shell_surface_handle_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial) -{ - wl_shell_surface_pong(shell_surface, serial); -} - -static void wl_shell_surface_handle_configure(void* data, struct wl_shell_surface* shell_surface, unsigned int edges, int32_t width, int32_t height) -{ - wlfWindow* window = data; - - window->width = width; - window->height = height; -} - -static const struct wl_shell_surface_listener wl_shell_surface_listener = -{ - wl_shell_surface_handle_ping, - wl_shell_surface_handle_configure, - NULL -}; - -static void wl_buffer_release(void* data, struct wl_buffer* wl_buffer) -{ - wlfBuffer* buffer = data; - - buffer->busy = FALSE; -} - -static const struct wl_buffer_listener wl_buffer_listener = -{ - wl_buffer_release -}; - -static const struct wl_callback_listener wl_callback_listener; - -static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t time) -{ - wlfWindow* window = data; - wlfBuffer* buffer; - struct wl_shm_pool* shm_pool; - void* shm_data; - void* free_data; - int fd; - int fdt; - - if (!window->buffers[0].busy) - buffer = &window->buffers[0]; - else if (!window->buffers[1].busy) - buffer = &window->buffers[1]; - else - return; - - if (!buffer->buffer) { - fd = shm_open("/wlfreerdp_shm", O_CREAT | O_RDWR, 0666); - fdt = ftruncate(fd, window->width * window->height * 4); - if (fdt != 0) - { - WLog_ERR(TAG, "window_redraw: could not allocate memory"); - close(fd); - return; - } - - shm_data = mmap(NULL, window->width * window->height * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (shm_data == MAP_FAILED) - { - WLog_ERR(TAG, "window_redraw: failed to memory map buffer"); - close(fd); - return; - } - - shm_pool = wl_shm_create_pool(window->display->shm, fd, window->width * window->height * 4); - buffer->buffer = wl_shm_pool_create_buffer(shm_pool, 0, window->width, window->height, window->width* 4, WL_SHM_FORMAT_XRGB8888); - wl_buffer_add_listener(buffer->buffer, &wl_buffer_listener, buffer); - wl_shm_pool_destroy(shm_pool); - shm_unlink("/wlfreerdp_shm"); - close(fd); - - free_data = buffer->shm_data; - buffer->shm_data = shm_data; - munmap(free_data, window->width * window->height * 4); - } - - /* this is the real surface data */ - memcpy(buffer->shm_data, (void*) window->data, window->width * window->height * 4); - wl_surface_attach(window->surface, buffer->buffer, 0, 0); - wl_surface_damage(window->surface, 0, 0, window->width, window->height); - - if (callback) wl_callback_destroy(callback); - window->callback = wl_surface_frame(window->surface); - wl_callback_add_listener(window->callback, &wl_callback_listener, window); - wl_surface_commit(window->surface); - - buffer->busy = TRUE; -} - -static const struct wl_callback_listener wl_callback_listener = -{ - wl_callback_done -}; - - -wlfWindow* wlf_CreateDesktopWindow(wlfContext* wlfc, char* name, int width, int height, BOOL decorations) -{ - wlfWindow* window; - - window = (wlfWindow*) calloc(1, sizeof(wlfWindow)); - - if (window) - { - window->width = width; - window->height = height; - window->fullscreen = FALSE; - window->buffers[0].busy = FALSE; - window->buffers[1].busy = FALSE; - window->callback = NULL; - window->display = wlfc->display; - - window->surface = wl_compositor_create_surface(window->display->compositor); - window->shell_surface = wl_shell_get_shell_surface(window->display->shell, window->surface); - wl_shell_surface_add_listener(window->shell_surface, &wl_shell_surface_listener, window); - wl_shell_surface_set_toplevel(window->shell_surface); - - wlf_ResizeDesktopWindow(wlfc, window, width, height); - - wl_surface_damage(window->surface, 0, 0, window->width, window->height); - - wlf_SetWindowText(wlfc, window, name); - } - - return window; -} - -void wlf_ResizeDesktopWindow(wlfContext* wlfc, wlfWindow* window, int width, int height) -{ - window->width = width; - window->height = height; -} - -void wlf_SetWindowText(wlfContext* wlfc, wlfWindow* window, char* name) -{ - wl_shell_surface_set_title(window->shell_surface, name); -} - -void wlf_SetWindowFullscreen(wlfContext* wlfc, wlfWindow* window, BOOL fullscreen) -{ - if (fullscreen) - { - wl_shell_surface_set_fullscreen(window->shell_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); - window->fullscreen = TRUE; - } -} - -void wlf_ShowWindow(wlfContext* wlfc, wlfWindow* window, BYTE state) -{ - switch (state) - { - case WINDOW_HIDE: - case WINDOW_SHOW_MINIMIZED: - /* xdg_surface_set_minimized(window->xdg_surface); */ - break; - case WINDOW_SHOW_MAXIMIZED: - wl_shell_surface_set_maximized(window->shell_surface, NULL); - break; - case WINDOW_SHOW: - wl_shell_surface_set_toplevel(window->shell_surface); - break; - } -} - -void wlf_UpdateWindowArea(wlfContext* wlfc, wlfWindow* window, int x, int y, int width, int height) -{ - wl_callback_done(window, NULL, 0); -} - -void wlf_DestroyWindow(wlfContext* wlfc, wlfWindow* window) -{ - if (window == NULL) - return; - - if (wlfc->window == window) - wlfc->window = NULL; - - if (window->buffers[0].buffer) - wl_buffer_destroy(window->buffers[0].buffer); - if (window->buffers[1].buffer) - wl_buffer_destroy(window->buffers[1].buffer); - if (window->shell_surface) - wl_shell_surface_destroy(window->shell_surface); - if (window->surface) - wl_surface_destroy(window->surface); - - free(window->data); - free(window); -} diff --git a/client/Wayland/wlf_window.h b/client/Wayland/wlf_window.h deleted file mode 100644 index df36289..0000000 --- a/client/Wayland/wlf_window.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Wayland Windows - * - * Copyright 2014 Manuel Bachmann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __WLF_WINDOW_H -#define __WLF_WINDOW_H - -#include - -typedef struct wlf_window wlfWindow; - -#include "wlfreerdp.h" - -struct wlf_buffer -{ - struct wl_buffer* buffer; - void* shm_data; - BOOL busy; -}; -typedef struct wlf_buffer wlfBuffer; - -struct wlf_window -{ - int width; - int height; - struct wl_surface* surface; - struct wl_shell_surface* shell_surface; - struct wl_callback* callback; - wlfBuffer buffers[2]; - wlfDisplay* display; - void* data; - BOOL fullscreen; -}; - -wlfWindow* wlf_CreateDesktopWindow(wlfContext* wlfc, char* name, int width, int height, BOOL decorations); -void wlf_ResizeDesktopWindow(wlfContext* wlfc, wlfWindow* window, int width, int height); -void wlf_SetWindowText(wlfContext* wlfc, wlfWindow* window, char* name); -void wlf_SetWindowFullscreen(wlfContext* wlfc, wlfWindow* window, BOOL fullscree); -void wlf_ShowWindow(wlfContext* wlfc, wlfWindow* window, BYTE state); -void wlf_UpdateWindowArea(wlfContext* wlfc, wlfWindow* window, int x, int y, int width, int height); -void wlf_DestroyWindow(wlfContext* wlfc, wlfWindow* window); - -#endif /* __WLF_WINDOW_H */ diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 456e64a..308147c 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -23,8 +23,13 @@ #include #include #include +#include #include "wlfreerdp.h" +#include "wlf_input.h" + +UwacDisplay *g_display; +HANDLE g_displayHandle; static BOOL wl_context_new(freerdp* instance, rdpContext* context) { @@ -44,6 +49,18 @@ static void wl_context_free(freerdp* instance, rdpContext* context) } } +BOOL wl_update_content(wlfContext *context_w) +{ + if (!context_w->waitingFrameDone && context_w->haveDamage) + { + UwacWindowSubmitBuffer(context_w->window, true); + context_w->waitingFrameDone = TRUE; + context_w->haveDamage = FALSE; + } + + return TRUE; +} + static BOOL wl_begin_paint(rdpContext* context) { rdpGdi* gdi; @@ -53,12 +70,12 @@ static BOOL wl_begin_paint(rdpContext* context) return TRUE; } + static BOOL wl_end_paint(rdpContext* context) { rdpGdi* gdi; - wlfDisplay* display; - wlfWindow* window; - wlfContext* context_w; + char *data; + wlfContext *context_w; INT32 x, y; UINT32 w, h; int i; @@ -73,21 +90,28 @@ static BOOL wl_end_paint(rdpContext* context) h = gdi->primary->hdc->hwnd->invalid->h; context_w = (wlfContext*) context; - display = context_w->display; - window = context_w->window; + + data = UwacWindowGetDrawingBuffer(context_w->window); + if (!data) + return FALSE; for (i = 0; i < h; i++) - memcpy(window->data + ((i+y)*(gdi->width*4)) + x*4, + { + memcpy(data + ((i+y)*(gdi->width*4)) + x*4, gdi->primary_buffer + ((i+y)*(gdi->width*4)) + x*4, w*4); + } - return wlf_RefreshDisplay(display); + if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS) + return FALSE; + + context_w->haveDamage = TRUE; + return wl_update_content(context_w); } + static BOOL wl_pre_connect(freerdp* instance) { - wlfDisplay* display; - wlfInput* input; wlfContext* context; if (freerdp_channels_pre_connect(instance->context->channels, instance)) @@ -97,17 +121,7 @@ static BOOL wl_pre_connect(freerdp* instance) if (!context) return FALSE; - display = wlf_CreateDisplay(); - if (!display) - return FALSE; - - context->display = display; - - input = wlf_CreateInput(context); - if (!input) - return FALSE; - - context->input = input; + context->display = g_display; return TRUE; } @@ -115,7 +129,7 @@ static BOOL wl_pre_connect(freerdp* instance) static BOOL wl_post_connect(freerdp* instance) { rdpGdi* gdi; - wlfWindow* window; + UwacWindow* window; wlfContext* context; if (!gdi_init(instance, CLRCONV_ALPHA | CLRBUF_32BPP, NULL)) @@ -126,28 +140,23 @@ static BOOL wl_post_connect(freerdp* instance) return FALSE; context = (wlfContext*) instance->context; - window = wlf_CreateDesktopWindow(context, "FreeRDP", gdi->width, gdi->height, FALSE); + context->window = window = UwacCreateWindowShm(context->display, gdi->width, gdi->height, WL_SHM_FORMAT_XRGB8888); if (!window) return FALSE; - /* fill buffer with first image here */ - window->data = malloc (gdi->width * gdi->height *4); - if (!window->data) - return FALSE; + UwacWindowSetTitle(window, "FreeRDP"); - memcpy(window->data, (void*) gdi->primary_buffer, gdi->width * gdi->height * 4); instance->update->BeginPaint = wl_begin_paint; instance->update->EndPaint = wl_end_paint; - /* put Wayland data in the context here */ - context->window = window; - if (freerdp_channels_post_connect(instance->context->channels, instance) < 0) return FALSE; - wlf_UpdateWindowArea(context, window, 0, 0, gdi->width, gdi->height); - return TRUE; + memcpy(UwacWindowGetDrawingBuffer(context->window), gdi->primary_buffer, gdi->width * gdi->height * 4); + UwacWindowAddDamage(context->window, 0, 0, gdi->width, gdi->height); + context->haveDamage = TRUE; + return wl_update_content(context); } static void wl_post_disconnect(freerdp* instance) @@ -161,55 +170,67 @@ static void wl_post_disconnect(freerdp* instance) context = (wlfContext*) instance->context; - if (context->display) - wlf_DestroyDisplay(context, context->display); - - if (context->input) - wlf_DestroyInput(context, context->input); - gdi_free(instance); if (context->window) - wlf_DestroyWindow(context, context->window); + UwacDestroyWindow(&context->window); + + if (context->display) + UwacCloseDisplay(&context->display); + } -static BOOL wl_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) -{ - char answer; +static BOOL handle_uwac_events(freerdp* instance, UwacDisplay *display) { + UwacEvent event; + wlfContext *context; - printf("Certificate details:\n"); - printf("\tSubject: %s\n", subject); - printf("\tIssuer: %s\n", issuer); - printf("\tThumbprint: %s\n", fingerprint); - printf("The above X.509 certificate could not be verified, possibly because you do not have " - "the CA certificate in your certificate store, or the certificate has expired. " - "Please look at the documentation on how to create local certificate store for a private CA.\n"); + if (UwacDisplayDispatch(display, 1) < 0) + return FALSE; - while (1) + while (UwacHasEvent(display)) { - printf("Do you trust the above certificate? (Y/N) "); - answer = fgetc(stdin); - - if (feof(stdin)) - { - printf("\nError: Could not read answer from stdin."); - if (instance->settings->CredentialsFromStdin) - printf(" - Run without parameter \"--from-stdin\" to set trust."); - printf("\n"); + if (UwacNextEvent(display, &event) != UWAC_SUCCESS) return FALSE; - } - if (answer == 'y' || answer == 'Y') - { - return TRUE; - } - else if (answer == 'n' || answer == 'N') - { + /*printf("UWAC event type %d\n", event.type);*/ + switch (event.type) { + case UWAC_EVENT_FRAME_DONE: + if (!instance) + continue; + + context = (wlfContext *)instance->context; + context->waitingFrameDone = FALSE; + if (context->haveDamage && !wl_end_paint(instance->context)) + return FALSE; + break; + case UWAC_EVENT_POINTER_ENTER: + if (!wlf_handle_pointer_enter(instance, &event.mouse_enter_leave)) + return FALSE; + break; + case UWAC_EVENT_POINTER_MOTION: + if (!wlf_handle_pointer_motion(instance, &event.mouse_motion)) + return FALSE; + break; + case UWAC_EVENT_POINTER_BUTTONS: + if (!wlf_handle_pointer_buttons(instance, &event.mouse_button)) + return FALSE; + break; + case UWAC_EVENT_POINTER_AXIS: + if (!wlf_handle_pointer_axis(instance, &event.mouse_axis)) + return FALSE; + break; + case UWAC_EVENT_KEY: + if (!wlf_handle_key(instance, &event.key)) + return FALSE; + break; + case UWAC_EVENT_KEYBOARD_ENTER: + if (!wlf_keyboard_enter(instance, &event.keyboard_enter_leave)) + return FALSE; + break; + default: break; } - printf("\n"); } - - return FALSE; + return TRUE; } static int wlfreerdp_run(freerdp* instance) @@ -224,27 +245,39 @@ static int wlfreerdp_run(freerdp* instance) return -1; } + handle_uwac_events(instance, g_display); + while (!freerdp_shall_disconnect(instance)) { - count = freerdp_get_event_handles(instance->context, handles, 64); + handles[0] = g_displayHandle; + + count = freerdp_get_event_handles(instance->context, &handles[1], 63); if (!count) { printf("Failed to get FreeRDP file descriptor\n"); break; } - status = WaitForMultipleObjects(count, handles, FALSE, INFINITE); + status = WaitForMultipleObjects(count+1, handles, FALSE, INFINITE); if (WAIT_FAILED == status) { printf("%s: WaitForMultipleObjects failed\n", __FUNCTION__); break; } - if (freerdp_check_event_handles(instance->context) != TRUE) - { - printf("Failed to check FreeRDP file descriptor\n"); + if (!handle_uwac_events(instance, g_display)) { + printf("error handling UWAC events\n"); break; } + + //if (WaitForMultipleObjects(count, &handles[1], FALSE, INFINITE)) { + if (freerdp_check_event_handles(instance->context) != TRUE) + { + printf("Failed to check FreeRDP file descriptor\n"); + break; + } + //} + } freerdp_channels_disconnect(instance->context->channels, instance); @@ -255,14 +288,28 @@ static int wlfreerdp_run(freerdp* instance) int main(int argc, char* argv[]) { - int status; + UwacReturnCode status; freerdp* instance; + g_display = UwacOpenDisplay(NULL, &status); + if (!g_display) + exit(1); + + g_displayHandle = CreateFileDescriptorEvent(NULL, FALSE, FALSE, UwacDisplayGetFd(g_display), WINPR_FD_READ); + if (!g_displayHandle) + exit(1); + + //if (!handle_uwac_events(NULL, g_display)) + // exit(1); + instance = freerdp_new(); instance->PreConnect = wl_pre_connect; instance->PostConnect = wl_post_connect; instance->PostDisconnect = wl_post_disconnect; - instance->VerifyCertificate = wl_verify_certificate; + instance->Authenticate = client_cli_authenticate; + instance->GatewayAuthenticate = client_cli_gw_authenticate; + instance->VerifyCertificate = client_cli_verify_certificate; + instance->VerifyChangedCertificate = client_cli_verify_changed_certificate; instance->ContextSize = sizeof(wlfContext); instance->ContextNew = wl_context_new; diff --git a/client/Wayland/wlfreerdp.h b/client/Wayland/wlfreerdp.h index bf4da6f..575d7e4 100644 --- a/client/Wayland/wlfreerdp.h +++ b/client/Wayland/wlfreerdp.h @@ -23,22 +23,22 @@ #include #include #include +#include #define TAG CLIENT_TAG("wayland") typedef struct wlf_context wlfContext; -#include "wlf_display.h" -#include "wlf_window.h" -#include "wlf_input.h" struct wlf_context { rdpContext context; - wlfDisplay* display; - wlfWindow* window; - wlfInput* input; + UwacDisplay *display; + UwacWindow *window; + + BOOL waitingFrameDone; + BOOL haveDamage; }; #endif /* __WLFREERDP_H */ diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 8a885cf..baaf7e7 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -102,8 +102,6 @@ #include #define TAG CLIENT_TAG("x11") -static const size_t password_size = 512; - static int (*_def_error_handler)(Display*, XErrorEvent*); static int _xf_error_handler(Display* d, XErrorEvent* ev); static void xf_check_extensions(xfContext* context); @@ -1357,158 +1355,6 @@ static void xf_post_disconnect(freerdp* instance) xf_keyboard_free(xfc); } -/** Callback set in the rdp_freerdp structure, and used to get the user's password, - * if required to establish the connection. - * This function is actually called in credssp_ntlmssp_client_init() - * @see rdp_server_accept_nego() and rdp_check_fds() - * @param instance - pointer to the rdp_freerdp structure that contains the connection settings - * @param username - unused - * @param password - on return: pointer to a character string that will be filled by the password entered by the user. - * Note that this character string will be allocated inside the function, and needs to be deallocated by the caller - * using free(), even in case this function fails. - * @param domain - unused - * @return TRUE if a password was successfully entered. See freerdp_passphrase_read() for more details. - */ -static BOOL xf_authenticate_raw(freerdp* instance, BOOL gateway, char** username, - char** password, char** domain) -{ - const char* auth[] = - { - "Username: ", - "Domain: ", - "Password: " - }; - const char* gw[] = - { - "GatewayUsername: ", - "GatewayDomain: ", - "GatewayPassword: " - }; - const char** prompt = (gateway) ? gw : auth; - - if (!username || !password || !domain) - return FALSE; - - if (!*username) - { - size_t username_size = 0; - printf("%s", prompt[0]); - if (getline(username, &username_size, stdin) < 0) - { - WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); - goto fail; - } - - if (*username) - { - *username = StrSep(username, "\r"); - *username = StrSep(username, "\n"); - } - } - - if (!*domain) - { - size_t domain_size = 0; - printf("%s", prompt[1]); - if (getline(domain, &domain_size, stdin) < 0) - { - WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); - goto fail; - } - - if (*domain) - { - *domain = StrSep(domain, "\r"); - *domain = StrSep(domain, "\n"); - } - } - - if (!*password) - { - *password = calloc(password_size, sizeof(char)); - if (!*password) - goto fail; - - if (freerdp_passphrase_read(prompt[2], *password, password_size, - instance->settings->CredentialsFromStdin) == NULL) - goto fail; - } - - return TRUE; - -fail: - free(*username); - free(*domain); - free(*password); - - *username = NULL; - *domain = NULL; - *password = NULL; - - return FALSE; -} - -static BOOL xf_authenticate(freerdp* instance, char** username, char** password, char** domain) -{ - return xf_authenticate_raw(instance, FALSE, username, password, domain); -} - -static BOOL xf_gw_authenticate(freerdp* instance, char** username, char** password, char** domain) -{ - return xf_authenticate_raw(instance, TRUE, username, password, domain); -} - -/** Callback set in the rdp_freerdp structure, and used to make a certificate validation - * when the connection requires it. - * This function will actually be called by tls_verify_certificate(). - * @see rdp_client_connect() and tls_connect() - * @param instance - pointer to the rdp_freerdp structure that contains the connection settings - * @param subject - * @param issuer - * @param fingerprint - * @return TRUE if the certificate is trusted. FALSE otherwise. - */ -BOOL xf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) -{ - char answer; - - WLog_INFO(TAG, "Certificate details:"); - WLog_INFO(TAG, "\tSubject: %s", subject); - WLog_INFO(TAG, "\tIssuer: %s", issuer); - WLog_INFO(TAG, "\tThumbprint: %s", fingerprint); - WLog_INFO(TAG, "The above X.509 certificate could not be verified, possibly because you do not have " - "the CA certificate in your certificate store, or the certificate has expired. " - "Please look at the documentation on how to create local certificate store for a private CA."); - - while (1) - { - WLog_INFO(TAG, "Do you trust the above certificate? (Y/N) "); - answer = fgetc(stdin); - - if (feof(stdin)) - { - WLog_INFO(TAG, "Error: Could not read answer from stdin."); - if (instance->settings->CredentialsFromStdin) - WLog_INFO(TAG, " - Run without parameter \"--from-stdin\" to set trust."); - WLog_INFO(TAG, ""); - return FALSE; - } - - if (answer == 'y' || answer == 'Y') - { - return TRUE; - } - else if (answer == 'n' || answer == 'N') - { - break; - } - - WLog_INFO(TAG, ""); - } - - return FALSE; -} - int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type) { xfContext* xfc = (xfContext*) instance->context; @@ -1956,9 +1802,10 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context) instance->PreConnect = xf_pre_connect; instance->PostConnect = xf_post_connect; instance->PostDisconnect = xf_post_disconnect; - instance->Authenticate = xf_authenticate; - instance->GatewayAuthenticate = xf_gw_authenticate; - instance->VerifyCertificate = xf_verify_certificate; + instance->Authenticate = client_cli_authenticate; + instance->GatewayAuthenticate = client_cli_gw_authenticate; + instance->VerifyCertificate = client_cli_verify_certificate; + instance->VerifyChangedCertificate = client_cli_verify_changed_certificate; instance->LogonErrorInfo = xf_logon_error_info; settings = instance->settings; diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index c474e74..569f448 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -44,6 +44,8 @@ #define TAG CLIENT_TAG("x11") +#define MAX_CLIPBOARD_FORMATS 255 + struct xf_cliprdr_format { Atom atom; @@ -64,6 +66,9 @@ struct xf_clipboard Atom clipboard_atom; Atom property_atom; + Atom raw_transfer_atom; + Atom raw_format_list_atom; + int numClientFormats; xfCliprdrFormat clientFormats[20]; @@ -76,8 +81,9 @@ struct xf_clipboard int requestedFormatId; BYTE* data; - UINT32 data_format; - UINT32 data_alt_format; + BOOL data_raw_format; + UINT32 data_format_id; + const char* data_format_name; int data_length; XEvent* respond; @@ -122,9 +128,70 @@ static BOOL xf_cliprdr_is_self_owned(xfClipboard* clipboard) return XGetSelectionOwner(xfc->display, clipboard->clipboard_atom) == xfc->drawable; } -static xfCliprdrFormat* xf_cliprdr_get_format_by_id(xfClipboard* clipboard, UINT32 formatId) +static void xf_cliprdr_set_raw_transfer_enabled(xfClipboard* clipboard, BOOL enabled) { - UINT32 index; + UINT32 data = enabled; + xfContext* xfc = clipboard->xfc; + + XChangeProperty(xfc->display, xfc->drawable, clipboard->raw_transfer_atom, + XA_INTEGER, 32, PropModeReplace, (BYTE*) &data, 1); +} + +static BOOL xf_cliprdr_is_raw_transfer_available(xfClipboard* clipboard) +{ + Atom type; + int format; + int result = 0; + unsigned long length; + unsigned long bytes_left; + UINT32* data = NULL; + UINT32 is_enabled = 0; + Window owner = None; + xfContext* xfc = clipboard->xfc; + + owner = XGetSelectionOwner(xfc->display, clipboard->clipboard_atom); + + if (owner != None) + { + result = XGetWindowProperty(xfc->display, owner, + clipboard->raw_transfer_atom, 0, 4, 0, XA_INTEGER, + &type, &format, &length, &bytes_left, (BYTE**) &data); + } + + if (data) + { + is_enabled = *data; + XFree(data); + } + + if ((owner == None) || (owner == xfc->drawable)) + return FALSE; + + if (result != Success) + return FALSE; + + return is_enabled ? TRUE : FALSE; +} + +static BOOL xf_cliprdr_formats_equal(const CLIPRDR_FORMAT* server, const xfCliprdrFormat* client) +{ + if (server->formatName && client->formatName) + { + /* The server may be using short format names while we store them in full form. */ + return (0 == strncmp(server->formatName, client->formatName, strlen(server->formatName))); + } + + if (!server->formatName && !client->formatName) + { + return (server->formatId == client->formatId); + } + + return FALSE; +} + +static xfCliprdrFormat* xf_cliprdr_get_client_format_by_id(xfClipboard* clipboard, UINT32 formatId) +{ + int index; xfCliprdrFormat* format; for (index = 0; index < clipboard->numClientFormats; index++) @@ -138,25 +205,41 @@ static xfCliprdrFormat* xf_cliprdr_get_format_by_id(xfClipboard* clipboard, UINT return NULL; } -static xfCliprdrFormat* xf_cliprdr_get_format_by_atom(xfClipboard* clipboard, Atom atom) +static xfCliprdrFormat* xf_cliprdr_get_client_format_by_atom(xfClipboard* clipboard, Atom atom) { - int i, j; + int i; xfCliprdrFormat* format; for (i = 0; i < clipboard->numClientFormats; i++) { format = &(clipboard->clientFormats[i]); - if (format->atom != atom) - continue; - - if (format->formatId == 0) + if (format->atom == atom) return format; + } - for (j = 0; j < clipboard->numServerFormats; j++) + return NULL; +} + +static CLIPRDR_FORMAT* xf_cliprdr_get_server_format_by_atom(xfClipboard* clipboard, Atom atom) +{ + int i, j; + xfCliprdrFormat* client_format; + CLIPRDR_FORMAT* server_format; + + for (i = 0; i < clipboard->numClientFormats; i++) + { + client_format = &(clipboard->clientFormats[i]); + + if (client_format->atom == atom) { - if (clipboard->serverFormats[j].formatId == format->formatId) - return format; + for (j = 0; j < clipboard->numServerFormats; j++) + { + server_format = &(clipboard->serverFormats[j]); + + if (xf_cliprdr_formats_equal(server_format, client_format)) + return server_format; + } } } @@ -190,14 +273,170 @@ static UINT xf_cliprdr_send_data_response(xfClipboard* clipboard, BYTE* data, in ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE)); - response.msgFlags = CB_RESPONSE_OK; + response.msgFlags = (data) ? CB_RESPONSE_OK : CB_RESPONSE_FAIL; response.dataLen = size; response.requestedFormatData = data; return clipboard->context->ClientFormatDataResponse(clipboard->context, &response); } -static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) +static wStream* xf_cliprdr_serialize_server_format_list(xfClipboard* clipboard) +{ + UINT32 i; + UINT32 formatCount; + wStream* s = NULL; + + /* Typical MS Word format list is about 80 bytes long. */ + if (!(s = Stream_New(NULL, 128))) + { + WLog_ERR(TAG, "failed to allocate serialized format list"); + goto error; + } + + /* If present, the last format is always synthetic CF_RAW. Do not include it. */ + formatCount = (clipboard->numServerFormats > 0) ? clipboard->numServerFormats - 1 : 0; + + Stream_Write_UINT32(s, formatCount); + + for (i = 0; i < formatCount; i++) + { + CLIPRDR_FORMAT* format = &clipboard->serverFormats[i]; + size_t name_length = format->formatName ? strlen(format->formatName) : 0; + + if (!Stream_EnsureRemainingCapacity(s, sizeof(UINT32) + name_length + 1)) + { + WLog_ERR(TAG, "failed to expand serialized format list"); + goto error; + } + + Stream_Write_UINT32(s, format->formatId); + Stream_Write(s, format->formatName, name_length); + Stream_Write_UINT8(s, '\0'); + } + + Stream_SealLength(s); + + return s; + +error: + Stream_Free(s, TRUE); + return NULL; +} + +static CLIPRDR_FORMAT* xf_cliprdr_parse_server_format_list(BYTE* data, size_t length, UINT32* numFormats) +{ + UINT32 i; + wStream* s = NULL; + CLIPRDR_FORMAT* formats = NULL; + + if (!(s = Stream_New(data, length))) + { + WLog_ERR(TAG, "failed to allocate stream for parsing serialized format list"); + goto error; + } + + if (Stream_GetRemainingLength(s) < sizeof(UINT32)) + { + WLog_ERR(TAG, "too short serialized format list"); + goto error; + } + + Stream_Read_UINT32(s, *numFormats); + + if (*numFormats > MAX_CLIPBOARD_FORMATS) + { + WLog_ERR(TAG, "unexpectedly large number of formats: %u", *numFormats); + goto error; + } + + if (!(formats = (CLIPRDR_FORMAT*) calloc(*numFormats, sizeof(CLIPRDR_FORMAT)))) + { + WLog_ERR(TAG, "failed to allocate format list"); + goto error; + } + + for (i = 0; i < *numFormats; i++) + { + const char* formatName = NULL; + size_t formatNameLength = 0; + + if (Stream_GetRemainingLength(s) < sizeof(UINT32)) + { + WLog_ERR(TAG, "unexpected end of serialized format list"); + goto error; + } + + Stream_Read_UINT32(s, formats[i].formatId); + + formatName = (const char*) Stream_Pointer(s); + formatNameLength = strnlen(formatName, Stream_GetRemainingLength(s)); + + if (formatNameLength == Stream_GetRemainingLength(s)) + { + WLog_ERR(TAG, "missing terminating null byte, %zu bytes left to read", formatNameLength); + goto error; + } + + formats[i].formatName = strndup(formatName, formatNameLength); + Stream_Seek(s, formatNameLength + 1); + } + + Stream_Free(s, FALSE); + + return formats; + +error: + Stream_Free(s, FALSE); + free(formats); + *numFormats = 0; + return NULL; +} + +static void xf_cliprdr_free_formats(CLIPRDR_FORMAT* formats, UINT32 numFormats) +{ + UINT32 i; + + for (i = 0; i < numFormats; i++) + { + free(formats[i].formatName); + } + + free(formats); +} + +static CLIPRDR_FORMAT* xf_cliprdr_get_raw_server_formats(xfClipboard* clipboard, UINT32* numFormats) +{ + Atom type = None; + int format = 0; + unsigned long length = 0; + unsigned long remaining; + BYTE* data = NULL; + CLIPRDR_FORMAT* formats = NULL; + xfContext* xfc = clipboard->xfc; + + *numFormats = 0; + + XGetWindowProperty(xfc->display, clipboard->owner, clipboard->raw_format_list_atom, + 0, 4096, False, clipboard->raw_format_list_atom, &type, &format, + &length, &remaining, &data); + + if (data && length > 0 && format == 8 && type == clipboard->raw_format_list_atom) + { + formats = xf_cliprdr_parse_server_format_list(data, length, numFormats); + } + else + { + WLog_ERR(TAG, "failed to retrieve raw format list: data=%p, length=%lu, format=%d, type=%d (expected=%d)", + data, length, format, type, clipboard->raw_format_list_atom); + } + + if (data) + XFree(data); + + return formats; +} + +static CLIPRDR_FORMAT* xf_cliprdr_get_formats_from_targets(xfClipboard* clipboard, UINT32* numFormats) { int i; Atom atom; @@ -205,14 +444,11 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) int format_property; unsigned long length; unsigned long bytes_left; - UINT32 numFormats = 0; - CLIPRDR_FORMAT_LIST formatList; xfCliprdrFormat* format = NULL; CLIPRDR_FORMAT* formats = NULL; xfContext* xfc = clipboard->xfc; - if (!clipboard->numServerFormats) - return; /* server format list was not yet received */ + *numFormats = 0; XGetWindowProperty(xfc->display, xfc->drawable, clipboard->property_atom, 0, 200, 0, XA_ATOM, &atom, &format_property, &length, &bytes_left, &data); @@ -235,16 +471,73 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) { atom = ((Atom*) data)[i]; - format = xf_cliprdr_get_format_by_atom(clipboard, atom); + format = xf_cliprdr_get_client_format_by_atom(clipboard, atom); if (format) { - formats[numFormats].formatId = format->formatId; - formats[numFormats].formatName = format->formatName; - numFormats++; + formats[*numFormats].formatId = format->formatId; + formats[*numFormats].formatName = _strdup(format->formatName); + *numFormats += 1; } } +out: + if (data) + XFree(data); + + return formats; +} + +static CLIPRDR_FORMAT* xf_cliprdr_get_client_formats(xfClipboard* clipboard, UINT32* numFormats) +{ + CLIPRDR_FORMAT* formats = NULL; + + *numFormats = 0; + + if (xf_cliprdr_is_raw_transfer_available(clipboard)) + { + formats = xf_cliprdr_get_raw_server_formats(clipboard, numFormats); + } + + if (*numFormats == 0) + { + xf_cliprdr_free_formats(formats, *numFormats); + + formats = xf_cliprdr_get_formats_from_targets(clipboard, numFormats); + } + + return formats; +} + +static void xf_cliprdr_provide_server_format_list(xfClipboard* clipboard) +{ + wStream* formats = NULL; + xfContext* xfc = clipboard->xfc; + + formats = xf_cliprdr_serialize_server_format_list(clipboard); + + if (formats) + { + XChangeProperty(xfc->display, xfc->drawable, clipboard->raw_format_list_atom, + clipboard->raw_format_list_atom, 8, PropModeReplace, + Stream_Buffer(formats), Stream_Length(formats)); + } + else + { + XDeleteProperty(xfc->display, xfc->drawable, clipboard->raw_format_list_atom); + } + + Stream_Free(formats, TRUE); +} + +static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) +{ + UINT32 numFormats = 0; + CLIPRDR_FORMAT* formats = NULL; + CLIPRDR_FORMAT_LIST formatList; + + formats = xf_cliprdr_get_client_formats(clipboard, &numFormats); + ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST)); formatList.msgFlags = CB_RESPONSE_OK; @@ -253,10 +546,7 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) clipboard->context->ClientFormatList(clipboard->context, &formatList); -out: - if (data) - XFree(data); - free(formats); + xf_cliprdr_free_formats(formats, numFormats); } static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasData, BYTE* data, int size) @@ -264,8 +554,8 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa BOOL bSuccess; UINT32 SrcSize; UINT32 DstSize; - UINT32 formatId; - UINT32 altFormatId; + UINT32 srcFormatId; + UINT32 dstFormatId; BYTE* pSrcData = NULL; BYTE* pDstData = NULL; xfCliprdrFormat* format; @@ -273,7 +563,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa if (clipboard->incr_starts && hasData) return; - format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId); + format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId); if (!hasData || !data || !format) { @@ -281,25 +571,29 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa return; } - formatId = 0; - altFormatId = 0; + srcFormatId = 0; + dstFormatId = 0; switch (format->formatId) { + case CF_RAW: + srcFormatId = CF_RAW; + break; + case CF_TEXT: case CF_OEMTEXT: case CF_UNICODETEXT: size = strlen((char*) data) + 1; - formatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); + srcFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); break; case CF_DIB: - formatId = ClipboardGetFormatId(clipboard->system, "image/bmp"); + srcFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp"); break; case CB_FORMAT_HTML: size = strlen((char*) data) + 1; - formatId = ClipboardGetFormatId(clipboard->system, "text/html"); + srcFormatId = ClipboardGetFormatId(clipboard->system, "text/html"); break; } @@ -311,17 +605,24 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa CopyMemory(pSrcData, data, SrcSize); - bSuccess = ClipboardSetData(clipboard->system, formatId, (void*) pSrcData, SrcSize); + bSuccess = ClipboardSetData(clipboard->system, srcFormatId, (void*) pSrcData, SrcSize); if (!bSuccess) free(pSrcData); - altFormatId = clipboard->requestedFormatId; + if (format->formatName) + { + dstFormatId = ClipboardGetFormatId(clipboard->system, format->formatName); + } + else + { + dstFormatId = format->formatId; + } - if (bSuccess && altFormatId) + if (bSuccess) { DstSize = 0; - pDstData = (BYTE*) ClipboardGetData(clipboard->system, altFormatId, &DstSize); + pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize); } if (!pDstData) @@ -346,7 +647,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target) xfCliprdrFormat* format; xfContext* xfc = clipboard->xfc; - format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId); + format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId); if (!format || (format->atom != target)) { @@ -495,13 +796,14 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* int fmt; Atom type; UINT32 formatId; + const char* formatName; XEvent* respond; - UINT32 altFormatId; BYTE* data = NULL; BOOL delayRespond; + BOOL rawTransfer; unsigned long length; unsigned long bytes_left; - xfCliprdrFormat* format; + CLIPRDR_FORMAT* format; xfContext* xfc = clipboard->xfc; if (xevent->xselectionrequest.owner != xfc->drawable) @@ -535,14 +837,15 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* } else { - format = xf_cliprdr_get_format_by_atom(clipboard, xevent->xselectionrequest.target); + format = xf_cliprdr_get_server_format_by_atom(clipboard, xevent->xselectionrequest.target); if (format && (xevent->xselectionrequest.requestor != xfc->drawable)) { formatId = format->formatId; - altFormatId = formatId; + formatName = format->formatName; + rawTransfer = FALSE; - if (formatId == 0) + if (formatId == CF_RAW) { if (XGetWindowProperty(xfc->display, xevent->xselectionrequest.requestor, clipboard->property_atom, 0, 4, 0, XA_INTEGER, @@ -553,12 +856,13 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* if (data) { - CopyMemory(&altFormatId, data, 4); + rawTransfer = TRUE; + CopyMemory(&formatId, data, 4); XFree(data); } } - if ((clipboard->data != 0) && (formatId == clipboard->data_format) && (altFormatId == clipboard->data_alt_format)) + if ((clipboard->data != 0) && (formatId == clipboard->data_format_id) && (formatName == clipboard->data_format_name)) { /* Cached clipboard data available. Send it now */ respond->xselection.property = xevent->xselectionrequest.property; @@ -582,11 +886,12 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* respond->xselection.property = xevent->xselectionrequest.property; clipboard->respond = respond; - clipboard->data_format = formatId; - clipboard->data_alt_format = altFormatId; + clipboard->data_format_id = formatId; + clipboard->data_format_name = formatName; + clipboard->data_raw_format = rawTransfer; delayRespond = TRUE; - xf_cliprdr_send_data_request(clipboard, altFormatId); + xf_cliprdr_send_data_request(clipboard, formatId); } } } @@ -631,7 +936,7 @@ static BOOL xf_cliprdr_process_property_notify(xfClipboard* clipboard, XEvent* x else if ((xevent->xproperty.window == xfc->drawable) && (xevent->xproperty.state == PropertyNewValue) && clipboard->incr_starts) { - format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId); + format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId); if (format) xf_cliprdr_get_requested_data(clipboard, format->atom); @@ -787,24 +1092,6 @@ UINT xf_cliprdr_send_client_format_list_response(xfClipboard* clipboard, BOOL st return clipboard->context->ClientFormatListResponse(clipboard->context, &formatListResponse); } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -int xf_cliprdr_send_client_format_data_request(xfClipboard* clipboard, UINT32 formatId) -{ - CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; - - formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; - formatDataRequest.msgFlags = CB_RESPONSE_OK; - - formatDataRequest.requestedFormatId = formatId; - clipboard->requestedFormatId = formatId; - - return clipboard->context->ClientFormatDataRequest(clipboard->context, &formatDataRequest); -} - /** * Function description * @@ -856,6 +1143,9 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR clipboard->data = NULL; } + clipboard->data_format_id = -1; + clipboard->data_format_name = NULL; + if (clipboard->serverFormats) { for (i = 0; i < clipboard->numServerFormats; i++) @@ -867,14 +1157,11 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR clipboard->numServerFormats = 0; } - clipboard->numServerFormats = formatList->numFormats; + clipboard->numServerFormats = formatList->numFormats + 1; /* +1 for CF_RAW */ - if (clipboard->numServerFormats) - { - if (!(clipboard->serverFormats = (CLIPRDR_FORMAT*) calloc(clipboard->numServerFormats, sizeof(CLIPRDR_FORMAT)))) { - WLog_ERR(TAG, "failed to allocate %d CLIPRDR_FORMAT structs", clipboard->numServerFormats); - return CHANNEL_RC_NO_MEMORY; - } + if (!(clipboard->serverFormats = (CLIPRDR_FORMAT*) calloc(clipboard->numServerFormats, sizeof(CLIPRDR_FORMAT)))) { + WLog_ERR(TAG, "failed to allocate %d CLIPRDR_FORMAT structs", clipboard->numServerFormats); + return CHANNEL_RC_NO_MEMORY; } for (i = 0; i < formatList->numFormats; i++) @@ -897,6 +1184,13 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR } } + /* CF_RAW is always implicitly supported by the server */ + format = &clipboard->serverFormats[formatList->numFormats]; + format->formatId = CF_RAW; + format->formatName = NULL; + + xf_cliprdr_provide_server_format_list(clipboard); + clipboard->numTargets = 2; for (i = 0; i < formatList->numFormats; i++) @@ -905,7 +1199,7 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR for (j = 0; j < clipboard->numClientFormats; j++) { - if (format->formatId == clipboard->clientFormats[j].formatId) + if (xf_cliprdr_formats_equal(format, &clipboard->clientFormats[j])) { xf_cliprdr_append_target(clipboard, clipboard->clientFormats[j].atom); } @@ -940,25 +1234,28 @@ static UINT xf_cliprdr_server_format_list_response(CliprdrClientContext* context */ static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) { + BOOL rawTransfer; xfCliprdrFormat* format = NULL; UINT32 formatId = formatDataRequest->requestedFormatId; xfClipboard* clipboard = (xfClipboard*) context->custom; xfContext* xfc = clipboard->xfc; - if (xf_cliprdr_is_self_owned(clipboard)) + rawTransfer = xf_cliprdr_is_raw_transfer_available(clipboard); + + if (rawTransfer) { - format = xf_cliprdr_get_format_by_id(clipboard, 0); + format = xf_cliprdr_get_client_format_by_id(clipboard, CF_RAW); XChangeProperty(xfc->display, xfc->drawable, clipboard->property_atom, XA_INTEGER, 32, PropModeReplace, (BYTE*) &formatId, 1); } else - format = xf_cliprdr_get_format_by_id(clipboard, formatId); + format = xf_cliprdr_get_client_format_by_id(clipboard, formatId); if (!format) return xf_cliprdr_send_data_response(clipboard, NULL, 0); - clipboard->requestedFormatId = formatId; + clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId; XConvertSelection(xfc->display, clipboard->clipboard_atom, format->atom, clipboard->property_atom, xfc->drawable, CurrentTime); @@ -982,9 +1279,8 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context BYTE* pDstData; UINT32 DstSize; UINT32 SrcSize; - UINT32 formatId; - UINT32 altFormatId; - xfCliprdrFormat* format; + UINT32 srcFormatId; + UINT32 dstFormatId; BOOL nullTerminated = FALSE; UINT32 size = formatDataResponse->dataLen; BYTE* data = formatDataResponse->requestedFormatData; @@ -994,8 +1290,6 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context if (!clipboard->respond) return CHANNEL_RC_OK; - format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId); - if (clipboard->data) { free(clipboard->data); @@ -1005,39 +1299,50 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context pDstData = NULL; DstSize = 0; - formatId = 0; - altFormatId = 0; + srcFormatId = 0; + dstFormatId = 0; - switch (clipboard->data_format) + if (clipboard->data_raw_format) { + srcFormatId = CF_RAW; + dstFormatId = CF_RAW; + } + else if (clipboard->data_format_name) + { + if (strcmp(clipboard->data_format_name, "HTML Format") == 0) + { + srcFormatId = ClipboardGetFormatId(clipboard->system, "HTML Format"); + dstFormatId = ClipboardGetFormatId(clipboard->system, "text/html"); + nullTerminated = TRUE; + } + } + else + { + switch (clipboard->data_format_id) + { case CF_TEXT: - formatId = CF_TEXT; - altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); + srcFormatId = CF_TEXT; + dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); nullTerminated = TRUE; break; case CF_OEMTEXT: - formatId = CF_OEMTEXT; - altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); + srcFormatId = CF_OEMTEXT; + dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); nullTerminated = TRUE; break; case CF_UNICODETEXT: - formatId = CF_UNICODETEXT; - altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); + srcFormatId = CF_UNICODETEXT; + dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); nullTerminated = TRUE; break; case CF_DIB: - formatId = CF_DIB; - altFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp"); - break; - - case CB_FORMAT_HTML: - formatId = ClipboardGetFormatId(clipboard->system, "HTML Format"); - altFormatId = ClipboardGetFormatId(clipboard->system, "text/html"); - nullTerminated = TRUE; + srcFormatId = CF_DIB; + dstFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp"); break; + } } SrcSize = (UINT32) size; @@ -1048,18 +1353,21 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context CopyMemory(pSrcData, data, SrcSize); - bSuccess = ClipboardSetData(clipboard->system, formatId, (void*) pSrcData, SrcSize); + bSuccess = ClipboardSetData(clipboard->system, srcFormatId, (void*) pSrcData, SrcSize); if (!bSuccess) free (pSrcData); - if (bSuccess && altFormatId) + if (bSuccess) { DstSize = 0; - pDstData = (BYTE*) ClipboardGetData(clipboard->system, altFormatId, &DstSize); + pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize); - if ((DstSize > 1) && nullTerminated) - DstSize--; + if (nullTerminated) + { + while (DstSize > 0 && pDstData[DstSize - 1] == '\0') + DstSize--; + } } clipboard->data = pDstData; @@ -1111,6 +1419,11 @@ xfClipboard* xf_clipboard_new(xfContext* xfc) clipboard->property_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR", FALSE); + clipboard->raw_transfer_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_RAW", FALSE); + clipboard->raw_format_list_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_FORMATS", FALSE); + + xf_cliprdr_set_raw_transfer_enabled(clipboard, TRUE); + XSelectInput(xfc->display, clipboard->root_window, PropertyChangeMask); #ifdef WITH_XFIXES @@ -1140,7 +1453,7 @@ xfClipboard* xf_clipboard_new(xfContext* xfc) n = 0; clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "_FREERDP_RAW", False); - clipboard->clientFormats[n].formatId = 0; + clipboard->clientFormats[n].formatId = CF_RAW; n++; clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "UTF8_STRING", False); diff --git a/client/common/CMakeLists.txt b/client/common/CMakeLists.txt index 5502696..95c8e98 100644 --- a/client/common/CMakeLists.txt +++ b/client/common/CMakeLists.txt @@ -39,7 +39,7 @@ foreach(FREERDP_CHANNELS_CLIENT_SRC ${FREERDP_CHANNELS_CLIENT_SRCS}) endforeach() if(MSVC) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}) endif() # On windows create dll version information. diff --git a/client/common/client.c b/client/common/client.c index 7d2e5c8..a847c9b 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -21,21 +21,28 @@ #include "config.h" #endif +#include +#include + #include #include #include #include +#include #include #include -BOOL freerdp_client_common_new(freerdp* instance, rdpContext* context) +#include +#define TAG CLIENT_TAG("common") + +static BOOL freerdp_client_common_new(freerdp* instance, rdpContext* context) { RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints; return pEntryPoints->ClientNew(instance, context); } -void freerdp_client_common_free(freerdp* instance, rdpContext* context) +static void freerdp_client_common_free(freerdp* instance, rdpContext* context) { RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints; pEntryPoints->ClientFree(instance, context); @@ -152,7 +159,7 @@ static BOOL freerdp_client_settings_post_process(rdpSettings* settings) } } } - + /* Moved logic for Multimon and Span monitors to force fullscreen, so * that the rdp file also triggers this functionality */ if (settings->SpanMonitors) @@ -164,7 +171,7 @@ static BOOL freerdp_client_settings_post_process(rdpSettings* settings) { settings->Fullscreen = TRUE; } - + return TRUE; out_error: @@ -197,7 +204,7 @@ int freerdp_client_settings_parse_command_line(rdpSettings* settings, int argc, { status = freerdp_client_settings_parse_assistance_file(settings, settings->AssistanceFile); } - + /* Only call post processing if no status/error was returned*/ if (status < 0) return status; @@ -296,3 +303,213 @@ int freerdp_client_settings_parse_assistance_file(rdpSettings* settings, const c return 0; } +/** Callback set in the rdp_freerdp structure, and used to get the user's password, + * if required to establish the connection. + * This function is actually called in credssp_ntlmssp_client_init() + * @see rdp_server_accept_nego() and rdp_check_fds() + * @param instance - pointer to the rdp_freerdp structure that contains the connection settings + * @param username - unused + * @param password - on return: pointer to a character string that will be filled by the password entered by the user. + * Note that this character string will be allocated inside the function, and needs to be deallocated by the caller + * using free(), even in case this function fails. + * @param domain - unused + * @return TRUE if a password was successfully entered. See freerdp_passphrase_read() for more details. + */ +static BOOL client_cli_authenticate_raw(freerdp* instance, BOOL gateway, char** username, + char** password, char** domain) +{ + static const size_t password_size = 512; + const char* auth[] = + { + "Username: ", + "Domain: ", + "Password: " + }; + const char* gw[] = + { + "GatewayUsername: ", + "GatewayDomain: ", + "GatewayPassword: " + }; + const char** prompt = (gateway) ? gw : auth; + + if (!username || !password || !domain) + return FALSE; + + if (!*username) + { + size_t username_size = 0; + printf("%s", prompt[0]); + if (GetLine(username, &username_size, stdin) < 0) + { + WLog_ERR(TAG, "GetLine returned %s [%d]", strerror(errno), errno); + goto fail; + } + + if (*username) + { + *username = StrSep(username, "\r"); + *username = StrSep(username, "\n"); + } + } + + if (!*domain) + { + size_t domain_size = 0; + printf("%s", prompt[1]); + if (GetLine(domain, &domain_size, stdin) < 0) + { + WLog_ERR(TAG, "GetLine returned %s [%d]", strerror(errno), errno); + goto fail; + } + + if (*domain) + { + *domain = StrSep(domain, "\r"); + *domain = StrSep(domain, "\n"); + } + } + + if (!*password) + { + *password = calloc(password_size, sizeof(char)); + if (!*password) + goto fail; + + if (freerdp_passphrase_read(prompt[2], *password, password_size, + instance->settings->CredentialsFromStdin) == NULL) + goto fail; + } + + return TRUE; + +fail: + free(*username); + free(*domain); + free(*password); + + *username = NULL; + *domain = NULL; + *password = NULL; + + return FALSE; +} + +BOOL client_cli_authenticate(freerdp* instance, char** username, char** password, char** domain) +{ + return client_cli_authenticate_raw(instance, FALSE, username, password, domain); +} + +BOOL client_cli_gw_authenticate(freerdp* instance, char** username, char** password, char** domain) +{ + return client_cli_authenticate_raw(instance, TRUE, username, password, domain); +} + +static DWORD client_cli_accept_certificate(rdpSettings* settings) +{ + char answer; + + if (settings->CredentialsFromStdin) + return 0; + + while (1) + { + printf("Do you trust the above certificate? (Y/T/N) "); + answer = fgetc(stdin); + + if (feof(stdin)) + { + printf("\nError: Could not read answer from stdin."); + if (settings->CredentialsFromStdin) + printf(" - Run without parameter \"--from-stdin\" to set trust."); + printf("\n"); + return 0; + } + + switch(answer) + { + case 'y': + case 'Y': + return 1; + case 't': + case 'T': + return 2; + case 'n': + case 'N': + return 0; + default: + break; + } + printf("\n"); + } + + return 0; +} + +/** Callback set in the rdp_freerdp structure, and used to make a certificate validation + * when the connection requires it. + * This function will actually be called by tls_verify_certificate(). + * @see rdp_client_connect() and tls_connect() + * @param instance - pointer to the rdp_freerdp structure that contains the connection settings + * @param common_name + * @param subject + * @param issuer + * @param fingerprint + * @param host_mismatch Indicates the certificate host does not match. + * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. + */ +DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch) +{ + printf("Certificate details:\n"); + printf("\tSubject: %s\n", subject); + printf("\tIssuer: %s\n", issuer); + printf("\tThumbprint: %s\n", fingerprint); + printf("The above X.509 certificate could not be verified, possibly because you do not have\n" + "the CA certificate in your certificate store, or the certificate has expired.\n" + "Please look at the documentation on how to create local certificate store for a private CA.\n"); + + return client_cli_accept_certificate(instance->settings); +} + +/** Callback set in the rdp_freerdp structure, and used to make a certificate validation + * when a stored certificate does not match the remote counterpart. + * This function will actually be called by tls_verify_certificate(). + * @see rdp_client_connect() and tls_connect() + * @param instance - pointer to the rdp_freerdp structure that contains the connection settings + * @param common_name + * @param subject + * @param issuer + * @param fingerprint + * @param old_subject + * @param old_issuer + * @param old_fingerprint + * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. + */ +DWORD client_cli_verify_changed_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, + const char* old_subject, const char* old_issuer, + const char* old_fingerprint) +{ + printf("!!! Certificate has changed !!!\n"); + printf("\n"); + printf("New Certificate details:\n"); + printf("\tSubject: %s\n", subject); + printf("\tIssuer: %s\n", issuer); + printf("\tThumbprint: %s\n", fingerprint); + printf("\n"); + printf("Old Certificate details:\n"); + printf("\tSubject: %s\n", old_subject); + printf("\tIssuer: %s\n", old_issuer); + printf("\tThumbprint: %s\n", old_fingerprint); + printf("\n"); + printf("The above X.509 certificate does not match the certificate used for previous connections.\n" + "This may indicate that the certificate has been tampered with.\n" + "Please contact the administrator of the RDP server and clarify.\n"); + + return client_cli_accept_certificate(instance->settings); +} + + diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 517ee0e..76a5b8d 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -4,6 +4,7 @@ * * Copyright 2012 Marc-Andre Moreau * Copyright 2014 Norbert Federa + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,11 +22,11 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include "buildflags.h" #include #include +#include #include #include @@ -173,26 +174,30 @@ static COMMAND_LINE_ARGUMENT_A args[] = { "encryption-methods", COMMAND_LINE_VALUE_REQUIRED, "<40,56,128,FIPS>", NULL, NULL, -1, NULL, "RDP standard security encryption methods" }, { "from-stdin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Read credentials from stdin, do not use defaults." }, { "buildconfig", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_BUILDCONFIG, NULL, NULL, NULL, -1, NULL, "print the build configuration" }, + { "log-level", COMMAND_LINE_VALUE_REQUIRED, "[OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE]", NULL, NULL, -1, NULL, "Set the default log level" }, + { "log-filters", COMMAND_LINE_VALUE_REQUIRED, ":[, :][, ...]]", NULL, NULL, -1, NULL, "Set logger filters" }, + { "pwidth", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Physical width of display (in millimeters)" }, + { "pheight", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Physical height of display (in millimeters)" }, + { "orientation", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Orientation of display in degrees (0, 90, 180, 270)" }, + { "scale", COMMAND_LINE_VALUE_REQUIRED, "", "100", NULL, -1, NULL, "Scaling factor of the display (value of 100, 140, or 180)" }, + { "scale-desktop", COMMAND_LINE_VALUE_REQUIRED, "", "100", NULL, -1, NULL, "Scaling factor for desktop applications (value between 100 and 500)" }, + { "scale-device", COMMAND_LINE_VALUE_REQUIRED, "", "100", NULL, -1, NULL, "Scaling factor for app store applications (100, 140, or 180)" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -int freerdp_client_print_version() +BOOL freerdp_client_print_version() { printf("This is FreeRDP version %s (git %s)\n", FREERDP_VERSION_FULL, GIT_REVISION); - return 1; + return TRUE; } -int freerdp_client_print_buildconfig() +BOOL freerdp_client_print_buildconfig() { - printf("Build configuration: %s\n", BUILD_CONFIG); - printf("Build type: %s\n", BUILD_TYPE); - printf("CFLAGS: %s\n", CFLAGS); - printf("Compiler: %s, %s\n", COMPILER_ID, COMPILER_VERSION); - printf("Target architecture: %s\n", TARGET_ARCH); - return 1; + printf("%s", freerdp_get_build_config()); + return TRUE; } -int freerdp_client_print_command_line_help(int argc, char** argv) +BOOL freerdp_client_print_command_line_help(int argc, char** argv) { char* str; int length; @@ -231,7 +236,7 @@ int freerdp_client_print_command_line_help(int argc, char** argv) length = (int)(strlen(arg->Name) + strlen(arg->Format) + 2); str = (char*) calloc(length + 1UL, sizeof(char)); if (!str) - return -1; + return FALSE; sprintf_s(str, length + 1, "%s:%s", arg->Name, arg->Format); printf("%-20s", str); free(str); @@ -248,9 +253,9 @@ int freerdp_client_print_command_line_help(int argc, char** argv) length = (int) strlen(arg->Name) + 32; str = (char*) calloc(length + 1UL, sizeof(char)); if (!str) - return -1; + return FALSE; sprintf_s(str, length + 1, "%s (default:%s)", arg->Name, - arg->Default ? "on" : "off"); + arg->Default ? "on" : "off"); printf(" %s", arg->Default ? "-" : "+"); @@ -296,10 +301,10 @@ int freerdp_client_print_command_line_help(int argc, char** argv) printf("More documentation is coming, in the meantime consult source files\n"); printf("\n"); - return 1; + return TRUE; } -int freerdp_client_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv) +static int freerdp_client_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv) { if (index == 1) { @@ -336,21 +341,21 @@ int freerdp_client_command_line_pre_filter(void* context, int index, int argc, L return 0; } -int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** params) +BOOL freerdp_client_add_device_channel(rdpSettings* settings, int count, char** params) { if (strcmp(params[0], "drive") == 0) { RDPDR_DRIVE* drive; if (count < 3) - return -1; + return FALSE; settings->DeviceRedirection = TRUE; drive = (RDPDR_DRIVE*) calloc(1, sizeof(RDPDR_DRIVE)); if (!drive) - return -1; + return FALSE; drive->Type = RDPDR_DTYP_FILESYSTEM; @@ -359,7 +364,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p if (!(drive->Name = _strdup(params[1]))) { free(drive); - return -1; + return FALSE; } } @@ -369,7 +374,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p { free(drive->Name); free(drive); - return -1; + return FALSE; } } @@ -378,17 +383,17 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p free(drive->Path); free(drive->Name); free(drive); - return -1; + return FALSE; } - return 1; + return TRUE; } else if (strcmp(params[0], "printer") == 0) { RDPDR_PRINTER* printer; if (count < 1) - return -1; + return FALSE; settings->RedirectPrinters = TRUE; settings->DeviceRedirection = TRUE; @@ -398,7 +403,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p printer = (RDPDR_PRINTER*) calloc(1, sizeof(RDPDR_PRINTER)); if (!printer) - return -1; + return FALSE; printer->Type = RDPDR_DTYP_PRINT; @@ -407,7 +412,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p if (!(printer->Name = _strdup(params[1]))) { free(printer); - return -1; + return FALSE; } } @@ -417,7 +422,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p { free(printer->Name); free(printer); - return -1; + return FALSE; } } @@ -427,19 +432,19 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p free(printer->DriverName); free(printer->Name); free(printer); - return -1; + return FALSE; } } - return 1; + return TRUE; } else if (strcmp(params[0], "smartcard") == 0) { RDPDR_SMARTCARD* smartcard; if (count < 1) - return -1; + return FALSE; settings->RedirectSmartCards = TRUE; settings->DeviceRedirection = TRUE; @@ -449,7 +454,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD)); if (!smartcard) - return -1; + return FALSE; smartcard->Type = RDPDR_DTYP_SMARTCARD; @@ -458,7 +463,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p if (!(smartcard->Name = _strdup(params[1]))) { free(smartcard); - return -1; + return FALSE; } } @@ -468,7 +473,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p { free(smartcard->Name); free(smartcard); - return -1; + return FALSE; } } if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard)) @@ -476,18 +481,18 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p free(smartcard->Path); free(smartcard->Name); free(smartcard); - return -1; + return FALSE; } } - return 1; + return TRUE; } else if (strcmp(params[0], "serial") == 0) { RDPDR_SERIAL* serial; if (count < 1) - return -1; + return FALSE; settings->RedirectSerialPorts = TRUE; settings->DeviceRedirection = TRUE; @@ -495,7 +500,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p serial = (RDPDR_SERIAL*) calloc(1, sizeof(RDPDR_SERIAL)); if (!serial) - return -1; + return FALSE; serial->Type = RDPDR_DTYP_SERIAL; @@ -504,7 +509,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p if (!(serial->Name = _strdup(params[1]))) { free(serial); - return -1; + return FALSE; } } @@ -514,7 +519,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p { free(serial->Name); free(serial); - return -1; + return FALSE; } } @@ -525,7 +530,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p free(serial->Path); free(serial->Name); free(serial); - return -1; + return FALSE; } } @@ -537,7 +542,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p free(serial->Path); free(serial->Name); free(serial); - return -1; + return FALSE; } } @@ -548,17 +553,17 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p free(serial->Path); free(serial->Name); free(serial); - return -1; + return FALSE; } - return 1; + return TRUE; } else if (strcmp(params[0], "parallel") == 0) { RDPDR_PARALLEL* parallel; if (count < 1) - return -1; + return FALSE; settings->RedirectParallelPorts = TRUE; settings->DeviceRedirection = TRUE; @@ -566,7 +571,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p parallel = (RDPDR_PARALLEL*) calloc(1, sizeof(RDPDR_PARALLEL)); if (!parallel) - return -1; + return FALSE; parallel->Type = RDPDR_DTYP_PARALLEL; @@ -575,7 +580,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p if (!(parallel->Name = _strdup(params[1]))) { free(parallel); - return -1; + return FALSE; } } @@ -585,7 +590,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p { free(parallel->Name); free(parallel); - return -1; + return FALSE; } } @@ -594,23 +599,23 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p free(parallel->Path); free(parallel->Name); free(parallel); - return -1; + return FALSE; } - return 1; + return TRUE; } - return 0; + return FALSE; } -int freerdp_client_add_static_channel(rdpSettings* settings, int count, char** params) +BOOL freerdp_client_add_static_channel(rdpSettings* settings, int count, char** params) { int index; ADDIN_ARGV* args; args = (ADDIN_ARGV*) calloc(1, sizeof(ADDIN_ARGV)); if (!args) - return -1; + return FALSE; args->argc = count; args->argv = (char**) calloc(args->argc, sizeof(char*)); @@ -632,7 +637,7 @@ int freerdp_client_add_static_channel(rdpSettings* settings, int count, char** p if (!freerdp_static_channel_collection_add(settings, args)) goto error_argv_index; - return 0; + return TRUE; error_argv_index: for (index = 0; index < args->argc; index++) @@ -641,17 +646,17 @@ error_argv_strdup: free(args->argv); error_argv: free(args); - return -1; + return FALSE; } -int freerdp_client_add_dynamic_channel(rdpSettings* settings, int count, char** params) +BOOL freerdp_client_add_dynamic_channel(rdpSettings* settings, int count, char** params) { int index; ADDIN_ARGV* args; args = (ADDIN_ARGV*) malloc(sizeof(ADDIN_ARGV)); if (!args) - return -1; + return FALSE; args->argc = count; args->argv = (char**) calloc(args->argc, sizeof(char*)); @@ -673,7 +678,7 @@ int freerdp_client_add_dynamic_channel(rdpSettings* settings, int count, char** if (!freerdp_dynamic_channel_collection_add(settings, args)) goto error_argv_index; - return 0; + return TRUE; error_argv_index: for (index = 0; index < args->argc; index++) @@ -682,7 +687,7 @@ error_argv_strdup: free(args->argv); error_argv: free(args); - return -1; + return FALSE; } static char** freerdp_command_line_parse_comma_separated_values(char* list, int* count) @@ -745,21 +750,21 @@ static char** freerdp_command_line_parse_comma_separated_values_offset(char* lis return p; } -int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT_A* arg) +static int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT_A* arg) { rdpSettings* settings = (rdpSettings*) context; - int status = 0; + BOOL status = FALSE; CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "a") + CommandLineSwitchCase(arg, "a") { char** p; int count; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); - if (freerdp_client_add_device_channel(settings, count, p) > 0) + if ((status = freerdp_client_add_device_channel(settings, count, p))) { settings->DeviceRedirection = TRUE; } @@ -784,7 +789,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); - freerdp_client_add_dynamic_channel(settings, count, p); + status = freerdp_client_add_dynamic_channel(settings, count, p); free(p); } @@ -796,7 +801,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count); p[0] = "drive"; - freerdp_client_add_device_channel(settings, count, p); + status = freerdp_client_add_device_channel(settings, count, p); free(p); } @@ -808,7 +813,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count); p[0] = "serial"; - freerdp_client_add_device_channel(settings, count, p); + status = freerdp_client_add_device_channel(settings, count, p); free(p); } @@ -820,7 +825,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count); p[0] = "parallel"; - freerdp_client_add_device_channel(settings, count, p); + status = freerdp_client_add_device_channel(settings, count, p); free(p); } @@ -832,7 +837,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count); p[0] = "smartcard"; - freerdp_client_add_device_channel(settings, count, p); + status = freerdp_client_add_device_channel(settings, count, p); free(p); } @@ -846,7 +851,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count); p[0] = "printer"; - freerdp_client_add_device_channel(settings, count, p); + status = freerdp_client_add_device_channel(settings, count, p); free(p); } @@ -858,7 +863,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT count = 1; p[0] = "printer"; - freerdp_client_add_device_channel(settings, count, p); + status = freerdp_client_add_device_channel(settings, count, p); } } CommandLineSwitchCase(arg, "usb") @@ -869,7 +874,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count); p[0] = "urbdrc"; - freerdp_client_add_dynamic_channel(settings, count, p); + status = freerdp_client_add_dynamic_channel(settings, count, p); free(p); } @@ -924,7 +929,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count); p[0] = "audin"; - freerdp_client_add_dynamic_channel(settings, count, p); + status = freerdp_client_add_dynamic_channel(settings, count, p); free(p); } @@ -936,7 +941,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT count = 1; p[0] = "audin"; - freerdp_client_add_dynamic_channel(settings, count, p); + status = freerdp_client_add_dynamic_channel(settings, count, p); } } CommandLineSwitchCase(arg, "multimedia") @@ -949,7 +954,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count); p[0] = "tsmf"; - freerdp_client_add_dynamic_channel(settings, count, p); + status = freerdp_client_add_dynamic_channel(settings, count, p); free(p); } @@ -961,7 +966,7 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT count = 1; p[0] = "tsmf"; - freerdp_client_add_dynamic_channel(settings, count, p); + status = freerdp_client_add_dynamic_channel(settings, count, p); } } CommandLineSwitchCase(arg, "heartbeat") @@ -976,10 +981,10 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT CommandLineSwitchEnd(arg) - return status; + return status ? 1 : 0; } -int freerdp_parse_username(char* username, char** user, char** domain) +BOOL freerdp_parse_username(char* username, char** user, char** domain) { char* p; int length = 0; @@ -994,14 +999,14 @@ int freerdp_parse_username(char* username, char** user, char** domain) length = (int) (p - username); *user = _strdup(&p[1]); if (!*user) - return -1; + return FALSE; *domain = (char*) calloc(length + 1UL, sizeof(char)); if (!*domain) { free (*user); *user = NULL; - return -1; + return FALSE; } strncpy(*domain, username, length); @@ -1015,7 +1020,7 @@ int freerdp_parse_username(char* username, char** user, char** domain) */ *user = _strdup(username); if (!*user) - return -1; + return FALSE; *domain = _strdup("\0"); @@ -1023,16 +1028,16 @@ int freerdp_parse_username(char* username, char** user, char** domain) { free(*user); *user = NULL; - return -1; + return FALSE; } } else - return -1; + return FALSE; - return 0; + return TRUE; } -int freerdp_parse_hostname(char* hostname, char** host, int* port) +BOOL freerdp_parse_hostname(char* hostname, char** host, int* port) { char* p; int length; @@ -1045,7 +1050,7 @@ int freerdp_parse_hostname(char* hostname, char** host, int* port) *host = (char*) calloc(length + 1UL, sizeof(char)); if (!(*host)) - return -1; + return FALSE; CopyMemory(*host, hostname, length); (*host)[length] = '\0'; @@ -1056,15 +1061,15 @@ int freerdp_parse_hostname(char* hostname, char** host, int* port) *host = _strdup(hostname); if (!(*host)) - return -1; + return FALSE; *port = -1; } - return 0; + return TRUE; } -int freerdp_set_connection_type(rdpSettings* settings, int type) +BOOL freerdp_set_connection_type(rdpSettings* settings, int type) { settings->ConnectionType = type; @@ -1134,7 +1139,7 @@ int freerdp_set_connection_type(rdpSettings* settings, int type) settings->NetworkAutoDetect = TRUE; } - return 0; + return TRUE; } int freerdp_map_keyboard_layout_name_to_id(char* name) @@ -1191,7 +1196,7 @@ int freerdp_map_keyboard_layout_name_to_id(char* name) return 0; } -int freerdp_detect_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv) +static int freerdp_detect_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv) { int length; @@ -1220,7 +1225,7 @@ int freerdp_detect_command_line_pre_filter(void* context, int index, int argc, L } int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, - int* count, BOOL ignoreUnknown) + int* count, BOOL ignoreUnknown) { int status; DWORD flags; @@ -1240,7 +1245,7 @@ int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, CommandLineClearArgumentsA(args); status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags, - NULL, freerdp_detect_command_line_pre_filter, NULL); + NULL, freerdp_detect_command_line_pre_filter, NULL); if (status < 0) return status; @@ -1263,7 +1268,7 @@ int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, } int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv, - int* count, BOOL ignoreUnknown) + int* count, BOOL ignoreUnknown) { int status; DWORD flags; @@ -1284,7 +1289,7 @@ int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv, CommandLineClearArgumentsA(args); status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags, - NULL, freerdp_detect_command_line_pre_filter, NULL); + NULL, freerdp_detect_command_line_pre_filter, NULL); if (status < 0) return status; @@ -1307,7 +1312,7 @@ int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv, } static BOOL freerdp_client_detect_command_line(int argc, char** argv, - DWORD* flags, BOOL ignoreUnknown) + DWORD* flags, BOOL ignoreUnknown) { int old_cli_status; int old_cli_count; @@ -1350,7 +1355,7 @@ static BOOL freerdp_client_detect_command_line(int argc, char** argv, } WLog_DBG(TAG, "windows: %d/%d posix: %d/%d compat: %d/%d", windows_cli_status, windows_cli_count, - posix_cli_status, posix_cli_count, old_cli_status, old_cli_count); + posix_cli_status, posix_cli_count, old_cli_status, old_cli_count); return compatibility; } @@ -1422,7 +1427,7 @@ int freerdp_client_settings_command_line_status_print(rdpSettings* settings, int } int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, - int argc, char** argv, BOOL allowUnknown) + int argc, char** argv, BOOL allowUnknown) { char* p; char* user = NULL; @@ -1450,7 +1455,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, flags |= COMMAND_LINE_IGN_UNKNOWN_KEYWORD; } status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags, settings, - freerdp_client_command_line_pre_filter, freerdp_client_command_line_post_filter); + freerdp_client_command_line_pre_filter, freerdp_client_command_line_post_filter); if (status < 0) return status; @@ -1467,7 +1472,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "v") + CommandLineSwitchCase(arg, "v") { p = strchr(arg->Value, '['); /* ipv4 */ @@ -1499,7 +1504,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, length = p2 - p; if (!(settings->ServerHostname = (char*) calloc(length, sizeof(char)))) - return COMMAND_LINE_ERROR; + return COMMAND_LINE_ERROR_MEMORY; strncpy(settings->ServerHostname, p+1, length-1); if (*(p2 + 1) == ':') { @@ -1680,7 +1685,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { id = (unsigned long int) freerdp_map_keyboard_layout_name_to_id(arg->Value); if (id == -1) - WLog_ERR(TAG, "A problem occured while mapping the layout name to id"); + WLog_ERR(TAG, "A problem occurred while mapping the layout name to id"); else if (id == 0) { WLog_ERR(TAG, "Could not identify keyboard layout: %s", arg->Value); @@ -1923,14 +1928,15 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, else if (_stricmp(arg->Value, "lan") == 0) type = CONNECTION_TYPE_LAN; else if ((_stricmp(arg->Value, "autodetect") == 0) || - (_stricmp(arg->Value, "auto") == 0) || - (_stricmp(arg->Value, "detect") == 0)) + (_stricmp(arg->Value, "auto") == 0) || + (_stricmp(arg->Value, "detect") == 0)) { type = CONNECTION_TYPE_AUTODETECT; } } - freerdp_set_connection_type(settings, type); + if (!freerdp_set_connection_type(settings, type)) + return COMMAND_LINE_ERROR; } CommandLineSwitchCase(arg, "fonts") { @@ -2106,6 +2112,17 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { settings->CredentialsFromStdin = TRUE; } + CommandLineSwitchCase(arg, "log-level") + { + wLog* root = WLog_GetRoot(); + if (!WLog_SetStringLogLevel(root, arg->Value)) + return COMMAND_LINE_ERROR; + } + CommandLineSwitchCase(arg, "log-filters") + { + if (!WLog_AddStringLogFilters(arg->Value)) + return COMMAND_LINE_ERROR; + } CommandLineSwitchCase(arg, "sec-rdp") { settings->RdpSecurity = arg->Value ? TRUE : FALSE; @@ -2258,7 +2275,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, BYTE *base64; int length; crypto_base64_decode((const char *) (arg->Value), (int) strlen(arg->Value), - &base64, &length); + &base64, &length); if ((base64 != NULL) && (length == sizeof(ARC_SC_PRIVATE_PACKET))) { memcpy(settings->ServerAutoReconnectCookie, base64, length); @@ -2279,6 +2296,55 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (!(settings->RemoteAssistancePassword = _strdup(arg->Value))) return COMMAND_LINE_ERROR_MEMORY; } + CommandLineSwitchCase(arg, "pwidth") + { + settings->DesktopPhysicalWidth = atoi(arg->Value); + } + CommandLineSwitchCase(arg, "pheight") + { + settings->DesktopPhysicalHeight = atoi(arg->Value); + } + CommandLineSwitchCase(arg, "orientation") + { + settings->DesktopOrientation = atoi(arg->Value); + } + CommandLineSwitchCase(arg, "scale") + { + int scaleFactor = atoi(arg->Value); + if (scaleFactor == 100 || scaleFactor == 140 || scaleFactor == 180) { + settings->DesktopScaleFactor = scaleFactor; + settings->DeviceScaleFactor = scaleFactor; + } else { + WLog_ERR(TAG, "scale: invalid scale factor (%d)", scaleFactor); + return COMMAND_LINE_ERROR; + } + } + CommandLineSwitchCase(arg, "scale-desktop") + { + int desktopScaleFactor = atoi(arg->Value); + if (desktopScaleFactor >= 100 && desktopScaleFactor <= 500) + { + settings->DesktopScaleFactor = desktopScaleFactor; + } + else + { + WLog_ERR(TAG, "scale: invalid desktop scale factor (%d)", desktopScaleFactor); + return COMMAND_LINE_ERROR; + } + } + CommandLineSwitchCase(arg, "scale-device") + { + int deviceScaleFactor = atoi(arg->Value); + if (deviceScaleFactor == 100 || deviceScaleFactor == 140 || deviceScaleFactor == 180) + { + settings->DeviceScaleFactor = deviceScaleFactor; + } + else + { + WLog_ERR(TAG, "scale: invalid device scale factor (%d)", deviceScaleFactor); + return COMMAND_LINE_ERROR; + } + } CommandLineSwitchDefault(arg) { } @@ -2289,10 +2355,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (!settings->Domain && user) { - int ret; + BOOL ret; ret = freerdp_parse_username(user, &settings->Username, &settings->Domain); free(user); - if (ret != 0 ) + if (!ret) return COMMAND_LINE_ERROR; } else @@ -2300,11 +2366,11 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (!settings->GatewayDomain && gwUser) { - int ret; + BOOL ret; ret = freerdp_parse_username(gwUser, &settings->GatewayUsername, - &settings->GatewayDomain); + &settings->GatewayDomain); free(gwUser); - if (ret != 0) + if (!ret) return COMMAND_LINE_ERROR; } else @@ -2344,7 +2410,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, return status; } -int freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpSettings* settings, char* name, void* data) +static BOOL freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpSettings* settings, char* name, void* data) { void* entry; @@ -2355,20 +2421,20 @@ int freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpSettings* if (freerdp_channels_client_load(channels, settings, entry, data) == 0) { WLog_INFO(TAG, "loading channel %s", name); - return 0; + return TRUE; } } - return -1; + return FALSE; } -int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) +BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) { UINT32 index; ADDIN_ARGV* args; if ((freerdp_static_channel_collection_find(settings, "rdpsnd")) || - (freerdp_dynamic_channel_collection_find(settings, "tsmf"))) + (freerdp_dynamic_channel_collection_find(settings, "tsmf"))) { settings->DeviceRedirection = TRUE; /* rdpsnd requires rdpdr to be registered */ settings->AudioPlayback = TRUE; /* Both rdpsnd and tsmf require this flag to be set */ @@ -2380,14 +2446,14 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) } if (settings->NetworkAutoDetect || - settings->SupportHeartbeatPdu || - settings->SupportMultitransport) + settings->SupportHeartbeatPdu || + settings->SupportMultitransport) { settings->DeviceRedirection = TRUE; /* these RDP8 features require rdpdr to be registered */ } if (settings->RedirectDrives || settings->RedirectHomeDrive || settings->RedirectSerialPorts - || settings->RedirectSmartCards || settings->RedirectPrinters) + || settings->RedirectSmartCards || settings->RedirectPrinters) { settings->DeviceRedirection = TRUE; /* All of these features require rdpdr */ } @@ -2402,7 +2468,8 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) params[1] = "media"; params[2] = "*"; - freerdp_client_add_device_channel(settings, 3, (char**) params); + if (!freerdp_client_add_device_channel(settings, 3, (char**) params)) + return FALSE; } } @@ -2416,13 +2483,15 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) params[1] = "home"; params[2] = "%"; - freerdp_client_add_device_channel(settings, 3, (char**) params); + if (!freerdp_client_add_device_channel(settings, 3, (char**) params)) + return FALSE; } } if (settings->DeviceRedirection) { - freerdp_client_load_static_channel_addin(channels, settings, "rdpdr", settings); + if (!freerdp_client_load_static_channel_addin(channels, settings, "rdpdr", settings)) + return FALSE; if (!freerdp_static_channel_collection_find(settings, "rdpsnd")) { @@ -2431,7 +2500,8 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) params[0] = "rdpsnd"; params[1] = "sys:fake"; - freerdp_client_add_static_channel(settings, 2, (char**) params); + if (!freerdp_client_add_static_channel(settings, 2, (char**) params)) + return FALSE; } } @@ -2439,26 +2509,34 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) { RDPDR_SMARTCARD* smartcard; - smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD)); + if (!freerdp_device_collection_find_type(settings, RDPDR_DTYP_SMARTCARD)) + { + smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD)); - if (!smartcard) - return -1; + if (!smartcard) + return FALSE; - smartcard->Type = RDPDR_DTYP_SMARTCARD; - freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard); + smartcard->Type = RDPDR_DTYP_SMARTCARD; + if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard)) + return FALSE; + } } if (settings->RedirectPrinters) { RDPDR_PRINTER* printer; - printer = (RDPDR_PRINTER*) calloc(1, sizeof(RDPDR_PRINTER)); + if (!freerdp_device_collection_find_type(settings, RDPDR_DTYP_PRINT)) + { + printer = (RDPDR_PRINTER*) calloc(1, sizeof(RDPDR_PRINTER)); - if (!printer) - return -1; + if (!printer) + return FALSE; - printer->Type = RDPDR_DTYP_PRINT; - freerdp_device_collection_add(settings, (RDPDR_DEVICE*) printer); + printer->Type = RDPDR_DTYP_PRINT; + if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) printer)) + return FALSE; + } } if (settings->RedirectClipboard) @@ -2469,7 +2547,8 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) params[0] = "cliprdr"; - freerdp_client_add_static_channel(settings, 1, (char**) params); + if (!freerdp_client_add_static_channel(settings, 1, (char**) params)) + return FALSE; } } @@ -2487,20 +2566,28 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) } if (settings->EncomspVirtualChannel) - freerdp_client_load_static_channel_addin(channels, settings, "encomsp", settings); + { + if (!freerdp_client_load_static_channel_addin(channels, settings, "encomsp", settings)) + return FALSE; + } if (settings->RemdeskVirtualChannel) - freerdp_client_load_static_channel_addin(channels, settings, "remdesk", settings); + { + if (!freerdp_client_load_static_channel_addin(channels, settings, "remdesk", settings)) + return FALSE; + } for (index = 0; index < settings->StaticChannelCount; index++) { args = settings->StaticChannelArray[index]; - freerdp_client_load_static_channel_addin(channels, settings, args->argv[0], args); + if (!freerdp_client_load_static_channel_addin(channels, settings, args->argv[0], args)) + return FALSE; } if (settings->RemoteApplicationMode) { - freerdp_client_load_static_channel_addin(channels, settings, "rail", settings); + if (!freerdp_client_load_static_channel_addin(channels, settings, "rail", settings)) + return FALSE; } if (settings->MultiTouchInput) @@ -2511,7 +2598,8 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) count = 1; p[0] = "rdpei"; - freerdp_client_add_dynamic_channel(settings, count, p); + if (!freerdp_client_add_dynamic_channel(settings, count, p)) + return FALSE; } if (settings->SupportGraphicsPipeline) @@ -2522,7 +2610,8 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) count = 1; p[0] = "rdpgfx"; - freerdp_client_add_dynamic_channel(settings, count, p); + if (!freerdp_client_add_dynamic_channel(settings, count, p)) + return FALSE; } if (settings->SupportEchoChannel) @@ -2533,7 +2622,8 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) count = 1; p[0] = "echo"; - freerdp_client_add_dynamic_channel(settings, count, p); + if (!freerdp_client_add_dynamic_channel(settings, count, p)) + return FALSE; } if (settings->SupportDisplayControl) @@ -2544,7 +2634,8 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) count = 1; p[0] = "disp"; - freerdp_client_add_dynamic_channel(settings, count, p); + if (!freerdp_client_add_dynamic_channel(settings, count, p)) + return FALSE; } if (settings->DynamicChannelCount) @@ -2552,8 +2643,9 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) if (settings->SupportDynamicChannels) { - freerdp_client_load_static_channel_addin(channels, settings, "drdynvc", settings); + if (!freerdp_client_load_static_channel_addin(channels, settings, "drdynvc", settings)) + return FALSE; } - return 1; + return TRUE; } diff --git a/client/common/file.c b/client/common/file.c index f4b23fa..b662621 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -880,7 +880,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* char* user = NULL; char* domain = NULL; - if (freerdp_parse_username(file->Username, &user, &domain) != 0) + if (!freerdp_parse_username(file->Username, &user, &domain)) return FALSE; if (freerdp_set_param_string(settings, FreeRDP_Username, user) != 0) return FALSE; @@ -900,7 +900,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* int port = -1; char* host = NULL; - if (freerdp_parse_hostname(file->FullAddress, &host, &port) != 0) + if (!freerdp_parse_hostname(file->FullAddress, &host, &port)) return FALSE; if (freerdp_set_param_string(settings, FreeRDP_ServerHostname, host) != 0) @@ -1022,7 +1022,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* int port = -1; char* host = NULL; - if (freerdp_parse_hostname(file->GatewayHostname, &host, &port) != 0) + if (!freerdp_parse_hostname(file->GatewayHostname, &host, &port)) return FALSE; if (freerdp_set_param_string(settings, FreeRDP_GatewayHostname, host) != 0) diff --git a/client/common/module.def b/client/common/module.def deleted file mode 100644 index f54443e..0000000 --- a/client/common/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "freerdp-client" -EXPORTS - diff --git a/cmake/AndroidToolchain.cmake b/cmake/AndroidToolchain.cmake index dfbe39e..3752bbc 100644 --- a/cmake/AndroidToolchain.cmake +++ b/cmake/AndroidToolchain.cmake @@ -1627,7 +1627,7 @@ if(NOT _CMAKE_IN_TRY_COMPILE) else() set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) endif() - set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_OUTPUT_ABI_NAME}" CACHE PATH "path for android libs" ) + set( CMAKE_INSTALL_LIBDIR "${ANDROID_NDK_OUTPUT_ABI_NAME}" CACHE PATH "path for android libs" ) endif() # copy shaed stl library to build directory diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake index 47019f6..19db014 100644 --- a/cmake/ConfigOptions.cmake +++ b/cmake/ConfigOptions.cmake @@ -72,6 +72,8 @@ option(WITH_CHANNELS "Build virtual channel plugins" ON) cmake_dependent_option(WITH_CLIENT_CHANNELS "Build virtual channel plugins" ON "WITH_CLIENT_COMMON;WITH_CHANNELS" OFF) +cmake_dependent_option(WITH_MACAUDIO "Enable OSX sound backend" ON "APPLE;NOT IOS" OFF) + if(WITH_SERVER AND WITH_CHANNELS) option(WITH_SERVER_CHANNELS "Build virtual channel plugins" ON) endif() diff --git a/cmake/ConfigOptionsAndroid.cmake b/cmake/ConfigOptionsAndroid.cmake index 780b4e1..07dd604 100644 --- a/cmake/ConfigOptionsAndroid.cmake +++ b/cmake/ConfigOptionsAndroid.cmake @@ -15,19 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -set(JAVA_DEBUG_DEFAULT "off") -if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - set(JAVA_DEBUG_DEFAULT "on") -endif() - -option(WITH_DEBUG_ANDROID_JNI "Enable debug output for android jni bindings" ${DEFAULT_DEBUG_OPTION}) -option(WITH_ANDROID_DEBUG_MENU "Enable debug output for android jni bindings" ${DEFAULT_DEBUG_OPTION}) option(WITH_OPENSLES "Enable sound and microphone redirection using OpenSLES" ON) -option(ANDROID_BUILD_JAVA "Automatically android java code - build type depends on CMAKE_BUILD_TYPE" ON) -option(ANDROID_BUILD_JAVA_DEBUG "Create a android debug package" ${JAVA_DEBUG_DEFAULT}) -set(ANDROID_APP_VERSION 3 CACHE STRING "Application version") set(ANDROID_APP_TARGET_SDK 21 CACHE STRING "Application target android SDK") set(ANDROID_APP_MIN_SDK 14 CACHE STRING "Application minimum android SDK requirement") -set(ANDROID_APP_GOOGLE_TARGET_SDK "16" CACHE STRING "Application target google SDK") diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake index a34fdb2..ee217f6 100644 --- a/cmake/FindWayland.cmake +++ b/cmake/FindWayland.cmake @@ -1,19 +1,16 @@ -# - Find Wayland -# Find the Wayland libraries +# - Finds Wayland +# Find the Wayland libraries that are needed for UWAC # # This module defines the following variables: -# WAYLAND_FOUND - true if WAYLAND_INCLUDE_DIR & WAYLAND_LIBRARY are found -# WAYLAND_LIBRARIES - Set when WAYLAND_LIBRARY is found -# WAYLAND_INCLUDE_DIRS - Set when WAYLAND_INCLUDE_DIR is found -# -# WAYLAND_INCLUDE_DIR - where to find wayland-client.h, etc. -# WAYLAND_LIBRARY - the Wayland client library -# WAYLAND_VERSION - wayland client version if found and pkg-config was used +# WAYLAND_FOUND - true if UWAC has been found +# WAYLAND_LIBS - Set to the full path to wayland client libraries +# WAYLAND_INCLUDE_DIR - Set to the include directories for wayland +# XKBCOMMON_LIBS - Set to the full path to xkbcommon libraries +# XKBCOMMON_INCLUDE_DIR - Set to the include directories for xkbcommon # #============================================================================= -# Copyright 2014 Manuel Bachmann -# Copyright 2015 Bernhard Miklautz +# Copyright 2015 David Fort # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,38 +25,35 @@ # limitations under the License. #============================================================================= -set(REQUIRED_WAYLAND_CLIENT_VERSION 1.3.0) include(FindPkgConfig) if(PKG_CONFIG_FOUND) - pkg_check_modules(WAYLAND wayland-client) + pkg_check_modules(WAYLAND_SCANNER_PC wayland-scanner) + pkg_check_modules(WAYLAND_CLIENT_PC wayland-client) + pkg_check_modules(XKBCOMMON_PC xkbcommon) endif() -find_path(WAYLAND_INCLUDE_DIR NAMES wayland-client.h - PATHS ${WAYLAND_INCLUDE_DIRS} - DOC "The Wayland include directory" +find_program(WAYLAND_SCANNER wayland-scanner + HINTS "${WAYLAND_SCANNER_PC_PREFIX}/bin" ) -find_library(WAYLAND_LIBRARY NAMES wayland-client - PATHS ${WAYLAND_LIBRARY_DIRS} - DOC "The Wayland client library" +find_path(WAYLAND_INCLUDE_DIR wayland-client.h + HINTS ${WAYLAND_CLIENT_PC_INCLUDE_DIRS} +) + +find_library(WAYLAND_LIBS + NAMES "wayland-client" + HINTS "${WAYLAND_CLIENT_PC_LIBRARY_DIRS}" +) + +find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h + HINTS ${XKBCOMMON_PC_INCLUDE_DIRS} +) + +find_library(XKBCOMMON_LIBS + NAMES xkbcommon + HINTS "${XKBCOMMON_PC_LIBRARY_DIRS}" ) include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARY WAYLAND_INCLUDE_DIR) - -if(WAYLAND_VERSION) - if (${WAYLAND_VERSION} VERSION_LESS ${REQUIRED_WAYLAND_CLIENT_VERSION}) - message(WARNING "Installed wayland version ${WAYLAND_VERSION} is too old - minimum required version ${REQUIRED_WAYLAND_CLIENT_VERSION}") - set(WAYLAND_FOUND FALSE) - endif() -else() - message(WARNING "Couldn't detect wayland version - no version check is done") -endif() - -if(WAYLAND_FOUND) - set(WAYLAND_LIBRARIES ${WAYLAND_LIBRARY}) - set(WAYLAND_INCLUDE_DIRS ${WAYLAND_INCLUDE_DIR}) -endif() - -mark_as_advanced(WAYLAND_INCLUDE_DIR WAYLAND_LIBRARY WAYLAND_VERSION) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_SCANNER WAYLAND_INCLUDE_DIR WAYLAND_LIBS XKBCOMMON_INCLUDE_DIR XKBCOMMON_LIBS) diff --git a/cmake/WindowsDLLVersion.rc.in b/cmake/WindowsDLLVersion.rc.in index cebd5f2..5a0da5e 100644 --- a/cmake/WindowsDLLVersion.rc.in +++ b/cmake/WindowsDLLVersion.rc.in @@ -19,7 +19,7 @@ BEGIN BEGIN VALUE "CompanyName", "@RC_VERSION_VENDOR@" VALUE "FileDescription", "@RC_VERSION_DESCRIPTION@" - VALUE "FileVersion", "@RC_VERSION_MAJOR@,@RC_VERSION_MINOR@,@RC_VERSION_BUILD@,@RC_VERSION_PATCH@" + VALUE "FileVersion", "@RC_VERSION_MAJOR@,@RC_VERSION_MINOR@,@RC_VERSION_PATCH@,@RC_VERSION_BUILD@" VALUE "InternalName", "@RC_VERSION_FILE@" VALUE "LegalCopyright", "Copyright (C) 2011-@RC_VERSION_YEAR@" VALUE "OriginalFilename", "@RC_VERSION_FILE@" diff --git a/config.h.in b/config.h.in index 9dc44bd..b52fdb3 100644 --- a/config.h.in +++ b/config.h.in @@ -4,8 +4,6 @@ /* Include files */ #cmakedefine HAVE_FCNTL_H #cmakedefine HAVE_UNISTD_H -#cmakedefine HAVE_STDINT_H -#cmakedefine HAVE_STDBOOL_H #cmakedefine HAVE_INTTYPES_H #cmakedefine HAVE_SYS_MODEM_H #cmakedefine HAVE_SYS_FILIO_H @@ -89,6 +87,5 @@ #cmakedefine WITH_DEBUG_X11_CLIPRDR #cmakedefine WITH_DEBUG_X11_LOCAL_MOVESIZE #cmakedefine WITH_DEBUG_XV -#cmakedefine WITH_DEBUG_ANDROID_JNI #cmakedefine WITH_DEBUG_RINGBUFFER #endif diff --git a/docs/README.android b/docs/README.android index 32ee242..71c9bd1 100644 --- a/docs/README.android +++ b/docs/README.android @@ -1,16 +1,11 @@ Overview ======== -The FreeRDP Android port consists of two parts: the Android Java GUI (client/Android) -and the JNI bindings (client/Android/jni) which are written in C and wrap FreeRDP to -be used with Java. The JNI is directly integrated within FreeRDPs build system. -For building the GUI part there are three possibilities: -* integrated ant build - have cmake to operate ant and build everything -* manual ant build - build JNI with cmake and invoke ant manually for the GUI -* IDE builds using your favourite IDE - use cmake for building JNI and your IDE for GUI - -Manual build and IDE build are mostly used for development. - +The FreeRDP Android port consists of three parts: +* Android Java GUI (client/Android/Studio) +* FreeRDP library and its dependencies +* JNI bindings (client/Android/android_freerdp.c + and client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java) Build requirements ================= @@ -19,196 +14,64 @@ For the Android port some additional dependencies need to be fulfilled: * for JNI - Android NDK (>= r9) -- prebuild static openssl libraries (see below) +- prebuild openssl (optionally libjpeg and openh264) -* for the Java GUI (if build with ant) -- ant -- Android SDK Tools - version >= 21 -- Android Support Library (note: make sure ANDROID_APP_TARGET_SDK is set to be at - least the API level required by the support library) +* for the Java GUI +- Android SDK -FreeRDP requires openssl libraries for building but they are not part of the +FreeRDP requires openssl libraries for building but they are not part of the Android NDK and therefore they need to be prebuild manually. -Multiple source versions and builds of static openssl libraries are floating around. -At the time of writing we have tested and used: -https://github.com/bmiklautz/Android-external-openssl-ndk-static -https://github.com/akallabeth/openssl-android For jpeg support https://github.com/akallabeth/jpeg8d has been tested and used. However, any other static builds should work as well. -Build openssl and jpeg +Build native libraries: ====================== -Set up ANDROID_NDK and ANDROID_SDK to the absolute paths on your machine. -From the project root folder run './scripts/android_setup_build_env.sh' -This will set up openssl and gprof helper libraries as required for FreeRDP. +From the project root run the build script +./scripts/android-build-freerdp.sh --ndk --sdk +Set ANDROID_NDK and ANDROID_SDK to the absolute paths on your machine. +This will fetch sources from git and build OpenSSL, OpenH264, libJPEG. +The native FreeRDP libraries will also be build. +Currently the default script builds for: +* armeabi +* armeabi-v7a +* x86 +* mips -Building -======== +64 bit architectures will be added as soon as the OpenSSL build scripts +support the android build for those. -Integrated build ----------------- +When the script is finished the libraries are ready for android studio to +be picked up in client/Android/Studio/freeRDPCore/src/main/jniLibs -Run the following commands in the top level freerdp directory. Don't -forget to set ANDROID_NDK, ANDROID_SDK and FREERDP_EXTERNAL_SSL_PATH -to the absolut paths on your machine: +Building the APK (Android Studio) +================ -cmake -DCMAKE_TOOLCHAIN_FILE=cmake/AndroidToolchain.cmake \ --DANDROID_NDK="_your_ndk_path_here_" \ --DFREERDP_EXTERNAL_SSL_PATH="_your_ssl_build_root_path_" \ --DFREERDP_EXTERNAL_JPEG_PATH="_your_jpeg_build_root_path_" \ --DANDROID_SDK="_your_sdk_path_here_" \ --DCMAKE_BUILD_TYPE=Debug -make +* Import the folder client/Android/Studio in Android Studio +* You are ready to go -After that you should have a client/Android/bin/aFreeRDP-debug.apk. - -Manual ant builds ------------------ -First run cmake to prepare the build and build JNI. -Don't forget to set ANDROID_NDK, ANDROID_SDK and FREERDP_EXTERNAL_SSL_PATH -to the absolut paths on your machine: - -cmake -DCMAKE_TOOLCHAIN_FILE=cmake/AndroidToolchain.cmake \ --DANDROID_NDK="_your_ndk_path_here_" \ --DFREERDP_EXTERNAL_SSL_PATH="_your_ssl_build_root_path_" \ --DFREERDP_EXTERNAL_JPEG_PATH="_your_jpeg_build_root_path_" \ --DANDROID_SDK="_your_sdk_path_here_" -DANDROID_BUILD_JAVA=OFF \ --DCMAKE_BUILD_TYPE=Debug -make - -Now you can run your favourite ant command in client/Android like this: - -cd client/Android/aFreeRDP -ant debug install - -Using an IDE ------------- -Here is an example on how to use Eclipse for developing/building the Java GUI. -For this the "Android development tools for Eclipse" are required (available via -the eclipse marketplace). - -cmake -DCMAKE_TOOLCHAIN_FILE=cmake/AndroidToolchain.cmake \ --DANDROID_NDK="_your_ndk_path_here_" \ --DFREERDP_EXTERNAL_SSL_PATH="_your_ssl_build_root_path_" \ --DCMAKE_BUILD_TYPE=Debug -DANDROID_BUILD_JAVA=OFF -make - -Open Eclipse and choose: -File -> Import -> General -> Existing Projects into Workspace - -Browse to the client/Android directory in your FreeRDP folder and click finish. -If you get something like "Project 'aFreeRDP' is missing required source -folder: 'gen'" just build the project once and you are good to go. - -Side note: If you add -G "Eclipse CDT4 - Unix Makefiles" when running cmake -you can also import FreeRDP into Eclipse too. Then you have one Java project and one c/c++ -project you can work on. This requires CDT to be installed in Eclipse. - -Debugging native code ---------------------- - -All CMake builds created with -DCMAKE_BUILD_TYPE=Debug will be ready to -debug with ndk-gdb. - -Eclipse projects are already configured to allow debugging in either Java -or native code, no extra steps required. - -cmake variables -=============== - -JNI related ------------ - -CMAKE_TOOLCHAIN_FILE -* the toolchain file to use must be cmake/AndroidToolchain.cmake - -ANDROID_NDK (used from toolchain file) -* absolute path to the NDK - -ANDROID_ABI (used from toolchain file) -* Android ABI to build for (default is armeabi-v7a) - -FREERDP_EXTERNAL_SSL_PATH (used by FindOpenSSL) -* absolut root path to the prebuild static openssl libraries - -FREERDP_EXTERNAL_JPEG_PATH (used by FindJPEG) -* absolute root path to the prebuild static jpeg libraries - -WITH_DEBUG_ANDROID_JNI -- enable debugging for JNI - -The libraries must be located in obj/local/armeabi/ or obj/local/armeabi-v7a/. -Cmake searches in armeabi first then armeabi-v7a. It is possible to build FreeRDP -for armeabi-v7a and link against armeabi openssl but not the other way around. -Therefore it is suggested to build openssl for armeabi. - -Java GUI related ----------------- - -ANDROID_BUILD_JAVA (used by client/Android/CMakeLists.txt) -* can be ON/OFF (default OFF) whether or not to build the GUI with cmake - -ANDROID_SDK (used by client/Android/CMakeLists.txt) -* absolute path to the Android SDK to use - -ANDROID_NDK -* absolute path to the Android NDK to use. - -WITH_DEBUG_ANDROID_JNI -* enable logcat debug messages for JNI calls. - -WITH_ANDROID_DEBUG_MENU -* activate a debug menu in aFreeRDP to enable / disable runtime settings -* not available in release. - -WITH_OPENSLES -* Enables / disables sound and microphone support for android using OpenSLES - -ANDROID_BUILD_JAVA_DEBUG -* Enable / disable debugging code in the java parts of the application. - -ANDROID_APP_VERSION -* The version the aFreeRDP-release.apk / aFreeRDP-debug.apk will have. - -ANDROID_APP_TARGET_SDK -* The target SDK version of the project. - -ANDROID_APP_MIN_SDK -* The lowest supported SDK version - -ANDROID_NATIVE_API_LEVEL -* The native API level to compile the native code against. -* Should be equal to SDK level. - -This is used to generate local.properties needed by ant. Needs to be set -if you build manually with ant or do integrated builds. +Building the APK (gradle) +================ +* change to directory client/Android/Studio +* run ./gradlew build to build +* run ./gradlew tasks for other gradle options Development =========== -Updating JNI headers --------------------- +Updating JNI +------------ Whenever the FreeRDP API changes or you need some extra functionality in your Java -GUI the JNI needs to be updated. The JNI headers are generated from the compiled -Java classes: +GUI the JNI needs to be updated. -* edit client/Android/src/com/freerdp/afreerdp/services/LibFreeRDP.Java to +The JNI functions are defined in client/Android/android_freerdp.c +Add the new functions to the methods struct. + +* edit client/Android/src/com/freerdp/afreerdp/services/LibFreeRDP.Java to reflect your changes -* build the Android Java project as described above -* run ./scripts/regenerate_JNI_headers.sh from your FreeRDP checkout top level - directory +* edit client/Android/android_freerdp.c and adjust the methods struct to reflect + the changes made. -After that you need to implement the functionality in client/Android/jni/android_freerdp.c and add -the call to client/Android/jni/generated/android_freerdp_jni.c. -After that FreeRDP and the Android package need to be rebuilt to include the latest libfreerdp-android in the package. - -Android CMake related Variables -------------------------------- - -ANDROID_APP_TARGET_SDK ... specifies the desired android target SDK, currently 21 -ANDROID_APP_MIN_SDK ... specifies the minimum android SDK version supported, currently 14 -ANDROID_APP_GOOGLE_TARGET_SDK ... specifies the minimum google SDK requirement, currently 16 diff --git a/include/freerdp/client.h b/include/freerdp/client.h index 39708c7..f807b2f 100644 --- a/include/freerdp/client.h +++ b/include/freerdp/client.h @@ -94,6 +94,18 @@ FREERDP_API int freerdp_client_settings_write_connection_file(const rdpSettings* FREERDP_API int freerdp_client_settings_parse_assistance_file(rdpSettings* settings, const char* filename); +FREERDP_API BOOL client_cli_authenticate(freerdp* instance, char** username, char** password, char** domain); +FREERDP_API BOOL client_cli_gw_authenticate(freerdp* instance, char** username, char** password, char** domain); + +FREERDP_API DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch); + +FREERDP_API DWORD client_cli_verify_changed_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, + const char* old_subject, const char* old_issuer, + const char* old_fingerprint); #ifdef __cplusplus } #endif diff --git a/include/freerdp/client/cmdline.h b/include/freerdp/client/cmdline.h index 834ebeb..621a997 100644 --- a/include/freerdp/client/cmdline.h +++ b/include/freerdp/client/cmdline.h @@ -30,18 +30,19 @@ extern "C" { FREERDP_API int freerdp_client_settings_parse_command_line_arguments( rdpSettings* settings, int argc, char** argv, BOOL allowUnknown); FREERDP_API int freerdp_client_settings_command_line_status_print(rdpSettings* settings, int status, int argc, char** argv); -FREERDP_API int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings); +FREERDP_API BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings); -FREERDP_API int freerdp_client_print_version(void); -FREERDP_API int freerdp_client_print_command_line_help(int argc, char** argv); +FREERDP_API BOOL freerdp_client_print_version(void); +FREERDP_API BOOL freerdp_client_print_buildconfig(void); +FREERDP_API BOOL freerdp_client_print_command_line_help(int argc, char** argv); -FREERDP_API int freerdp_parse_username(char* username, char** user, char** domain); -FREERDP_API int freerdp_parse_hostname(char* hostname, char** host, int* port); -FREERDP_API int freerdp_set_connection_type(rdpSettings* settings, int type); +FREERDP_API BOOL freerdp_parse_username(char* username, char** user, char** domain); +FREERDP_API BOOL freerdp_parse_hostname(char* hostname, char** host, int* port); +FREERDP_API BOOL freerdp_set_connection_type(rdpSettings* settings, int type); -FREERDP_API int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** params); -FREERDP_API int freerdp_client_add_static_channel(rdpSettings* settings, int count, char** params); -FREERDP_API int freerdp_client_add_dynamic_channel(rdpSettings* settings, int count, char** params); +FREERDP_API BOOL freerdp_client_add_device_channel(rdpSettings* settings, int count, char** params); +FREERDP_API BOOL freerdp_client_add_static_channel(rdpSettings* settings, int count, char** params); +FREERDP_API BOOL freerdp_client_add_dynamic_channel(rdpSettings* settings, int count, char** params); #ifdef __cplusplus } diff --git a/include/freerdp/codec/region.h b/include/freerdp/codec/region.h index bced791..18b947c 100644 --- a/include/freerdp/codec/region.h +++ b/include/freerdp/codec/region.h @@ -73,10 +73,10 @@ FREERDP_API void region16_init(REGION16 *region); /** @return the number of rectangles of this region16 */ FREERDP_API int region16_n_rects(const REGION16 *region); -/** returns a pointer on rectangles and the number of rectangles in this region. - * nbRect can be set to NULL if not interested by the numnber of rectangles. +/** returns a pointer to rectangles and the number of rectangles in this region. + * nbRects can be set to NULL if not interested in the number of rectangles. * @param region the input region - * @param nbRects a pointer that will be filled with the number of rectangles + * @param nbRects if non-NULL returns the number of rectangles * @return a pointer on the rectangles */ FREERDP_API const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects); diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index 25d98bd..bcd5ee6 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -25,13 +25,8 @@ #include #include -#include -#include -#include -#include #include #include -#include #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f) #define D2I_X509_CONST const @@ -43,31 +38,7 @@ #include #include - -struct crypto_sha1_struct -{ - SHA_CTX sha_ctx; -}; - -struct crypto_md5_struct -{ - MD5_CTX md5_ctx; -}; - -struct crypto_rc4_struct -{ - RC4_KEY rc4_key; -}; - -struct crypto_des3_struct -{ - EVP_CIPHER_CTX des3_ctx; -}; - -struct crypto_hmac_struct -{ - HMAC_CTX hmac_ctx; -}; +#include struct crypto_cert_struct { @@ -79,47 +50,8 @@ struct crypto_cert_struct extern "C" { #endif -#define CRYPTO_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH -typedef struct crypto_sha1_struct* CryptoSha1; - -FREERDP_API CryptoSha1 crypto_sha1_init(void); -FREERDP_API void crypto_sha1_update(CryptoSha1 sha1, const BYTE* data, UINT32 length); -FREERDP_API void crypto_sha1_final(CryptoSha1 sha1, BYTE* out_data); - -#define CRYPTO_MD5_DIGEST_LENGTH MD5_DIGEST_LENGTH -typedef struct crypto_md5_struct* CryptoMd5; - -FREERDP_API CryptoMd5 crypto_md5_init(void); -FREERDP_API void crypto_md5_update(CryptoMd5 md5, const BYTE* data, UINT32 length); -FREERDP_API void crypto_md5_final(CryptoMd5 md5, BYTE* out_data); - -typedef struct crypto_rc4_struct* CryptoRc4; - -FREERDP_API CryptoRc4 crypto_rc4_init(const BYTE* key, UINT32 length); -FREERDP_API void crypto_rc4(CryptoRc4 rc4, UINT32 length, const BYTE* in_data, BYTE* out_data); -FREERDP_API void crypto_rc4_free(CryptoRc4 rc4); - -typedef struct crypto_des3_struct* CryptoDes3; - -FREERDP_API CryptoDes3 crypto_des3_encrypt_init(const BYTE* key, const BYTE* ivec); -FREERDP_API CryptoDes3 crypto_des3_decrypt_init(const BYTE* key, const BYTE* ivec); -FREERDP_API BOOL crypto_des3_encrypt(CryptoDes3 des3, UINT32 length, const BYTE *in_data, BYTE *out_data); -FREERDP_API BOOL crypto_des3_decrypt(CryptoDes3 des3, UINT32 length, const BYTE *in_data, BYTE* out_data); -FREERDP_API void crypto_des3_free(CryptoDes3 des3); - -typedef struct crypto_hmac_struct* CryptoHmac; - -FREERDP_API CryptoHmac crypto_hmac_new(void); -FREERDP_API BOOL crypto_hmac_sha1_init(CryptoHmac hmac, const BYTE *data, UINT32 length); -FREERDP_API BOOL crypto_hmac_md5_init(CryptoHmac hmac, const BYTE *data, UINT32 length); -FREERDP_API void crypto_hmac_update(CryptoHmac hmac, const BYTE *data, UINT32 length); -FREERDP_API void crypto_hmac_final(CryptoHmac hmac, BYTE *out_data, UINT32 length); -FREERDP_API void crypto_hmac_free(CryptoHmac hmac); - typedef struct crypto_cert_struct* CryptoCert; -#include - FREERDP_API CryptoCert crypto_cert_read(BYTE* data, UINT32 length); FREERDP_API char* crypto_cert_fingerprint(X509* xcert); FREERDP_API char* crypto_cert_subject(X509* xcert); @@ -146,7 +78,6 @@ FREERDP_API int crypto_rsa_public_decrypt(const BYTE* input, int length, UINT32 FREERDP_API int crypto_rsa_private_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output); FREERDP_API int crypto_rsa_private_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output); FREERDP_API void crypto_reverse(BYTE* data, int length); -FREERDP_API void crypto_nonce(BYTE* nonce, int size); FREERDP_API char* crypto_base64_encode(const BYTE* data, int length); FREERDP_API void crypto_base64_decode(const char* enc_data, int length, BYTE** dec_data, int* res_length); diff --git a/include/freerdp/crypto/tls.h b/include/freerdp/crypto/tls.h index 8d8daec..06dc97c 100644 --- a/include/freerdp/crypto/tls.h +++ b/include/freerdp/crypto/tls.h @@ -89,7 +89,7 @@ struct rdp_tls #endif FREERDP_API int tls_connect(rdpTls* tls, BIO *underlying); -FREERDP_API BOOL tls_accept(rdpTls* tls, BIO *underlying, const char* cert_file, const char* privatekey_file); +FREERDP_API BOOL tls_accept(rdpTls* tls, BIO *underlying, rdpSettings *settings); FREERDP_API BOOL tls_send_alert(rdpTls* tls); FREERDP_API int tls_write_all(rdpTls* tls, const BYTE* data, int length); diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index d2db002..22b2b35 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -65,13 +65,55 @@ typedef void (*pContextFree)(freerdp* instance, rdpContext* context); typedef BOOL (*pPreConnect)(freerdp* instance); typedef BOOL (*pPostConnect)(freerdp* instance); typedef void (*pPostDisconnect)(freerdp* instance); -typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain); -typedef BOOL (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint); -typedef BOOL (*pVerifyChangedCertificate)(freerdp* instance, char* subject, - char* issuer, char* new_fingerprint, - char* old_subject, char* old_issuer, - char* old_fingerprint); -typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, int length, const char* hostname, int port, DWORD flags); +typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, + char** password, char** domain); + +/** @brief Callback used if user interaction is required to accept + * an unknown certificate. + * + * @param common_name The certificate registered hostname. + * @param subject The common name of the certificate. + * @param issuer The issuer of the certificate. + * @param fingerprint The fingerprint of the certificate. + * @param host_mismatch A flag indicating the certificate + * subject does not match the host connecting to. + * + * @return 1 to accept and store a certificate, 2 to accept + * a certificate only for this session, 0 otherwise. + */ +typedef DWORD (*pVerifyCertificate)(freerdp* instance, + const char* common_name, + const char* subject, + const char* issuer, + const char* fingerprint, + BOOL host_mismatch); + +/** @brief Callback used if user interaction is required to accept + * a changed certificate. + * + * @param common_name The certificate registered hostname. + * @param subject The common name of the new certificate. + * @param issuer The issuer of the new certificate. + * @param fingerprint The fingerprint of the new certificate. + * @param old_subject The common name of the old certificate. + * @param old_issuer The issuer of the new certificate. + * @param old_fingerprint The fingerprint of the old certificate. + * + * @return 1 to accept and store a certificate, 2 to accept + * a certificate only for this session, 0 otherwise. + */ + +typedef DWORD (*pVerifyChangedCertificate)(freerdp* instance, + const char* common_name, + const char* subject, + const char* issuer, + const char* new_fingerprint, + const char* old_subject, + const char* old_issuer, + const char* old_fingerprint); +typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, + int length, const char* hostname, + int port, DWORD flags); typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type); @@ -272,6 +314,7 @@ FREERDP_API void freerdp_get_version(int* major, int* minor, int* revision); FREERDP_API const char* freerdp_get_version_string(void); FREERDP_API const char* freerdp_get_build_date(void); FREERDP_API const char* freerdp_get_build_revision(void); +FREERDP_API const char* freerdp_get_build_config(void); FREERDP_API freerdp* freerdp_new(void); FREERDP_API void freerdp_free(freerdp* instance); diff --git a/include/freerdp/locale/timezone.h b/include/freerdp/locale/timezone.h deleted file mode 100644 index 1d062c8..0000000 --- a/include/freerdp/locale/timezone.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Time Zone Redirection - * - * Copyright 2012 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FREERDP_LOCALE_TIMEZONE_H -#define FREERDP_LOCALE_TIMEZONE_H - -#include -#include -#include - -#ifdef __cplusplus - extern "C" { -#endif - -FREERDP_API void freerdp_time_zone_detect(TIME_ZONE_INFO* clientTimeZone); - -#ifdef __cplusplus - } -#endif - -#endif /* FREERDP_LOCALE_TIMEZONE_H */ diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index 5e8c71b..49bd056 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -277,7 +277,9 @@ typedef struct _SHADOW_MSG_OUT_AUDIO_OUT_VOLUME SHADOW_MSG_OUT_AUDIO_OUT_VOLUME; extern "C" { #endif +FREERDP_API void shadow_subsystem_set_entry_builtin(const char* name); FREERDP_API void shadow_subsystem_set_entry(pfnShadowSubsystemEntry pEntry); + FREERDP_API int shadow_subsystem_pointer_convert_alpha_pointer_data(BYTE* pixels, BOOL premultiplied, UINT32 width, UINT32 height, SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* pointerColor); diff --git a/include/freerdp/session.h b/include/freerdp/session.h new file mode 100644 index 0000000..9d7ed51 --- /dev/null +++ b/include/freerdp/session.h @@ -0,0 +1,48 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Client Session Info + * + * Copyright 2016 David FORT + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __FREERDP_SESSION_H__ +#define __FREERDP_SESSION_H__ + +#include + +/* Logon Information Types */ +#define INFO_TYPE_LOGON 0x00000000 +#define INFO_TYPE_LOGON_LONG 0x00000001 +#define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002 +#define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003 + +struct rdp_logon_info { + UINT32 sessionId; + char *username; + char *domain; +}; +typedef struct rdp_logon_info logon_info; + +struct rdp_logon_info_ex { + BOOL haveCookie; + UINT32 LogonId; + BYTE ArcRandomBits[16]; + + BOOL haveErrorInfo; + UINT32 ErrorNotificationType; + UINT32 ErrorNotificationData; +}; +typedef struct rdp_logon_info_ex logon_info_ex; + +#endif /* __FREERDP_SESSION_H__ */ diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index d96d352..210e711 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -4,6 +4,7 @@ * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2012 Marc-Andre Moreau + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +22,8 @@ #ifndef FREERDP_SETTINGS_H #define FREERDP_SETTINGS_H +#include + #include #include @@ -269,32 +272,6 @@ typedef struct _TARGET_NET_ADDRESS TARGET_NET_ADDRESS; #define ORIENTATION_LANDSCAPE_FLIPPED 180 #define ORIENTATION_PORTRAIT_FLIPPED 270 -/* SYSTEM_TIME */ -typedef struct -{ - UINT16 wYear; - UINT16 wMonth; - UINT16 wDayOfWeek; - UINT16 wDay; - UINT16 wHour; - UINT16 wMinute; - UINT16 wSecond; - UINT16 wMilliseconds; -} SYSTEM_TIME; - -/* TIME_ZONE_INFORMATION */ -struct _TIME_ZONE_INFO -{ - UINT32 bias; - char standardName[32]; - SYSTEM_TIME standardDate; - UINT32 standardBias; - char daylightName[32]; - SYSTEM_TIME daylightDate; - UINT32 daylightBias; -}; -typedef struct _TIME_ZONE_INFO TIME_ZONE_INFO; - /* ARC_CS_PRIVATE_PACKET */ typedef struct { @@ -655,6 +632,10 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_RdpServerRsaKey 1413 #define FreeRDP_RdpServerCertificate 1414 #define FreeRDP_ExternalCertificateManagement 1415 +#define FreeRDP_CertificateContent 1416 +#define FreeRDP_PrivateKeyContent 1417 +#define FreeRDP_RdpKeyContent 1418 + #define FreeRDP_Workarea 1536 #define FreeRDP_Fullscreen 1537 #define FreeRDP_PercentScreen 1538 @@ -973,7 +954,7 @@ struct rdp_settings UINT64 padding0896[896 - 837]; /* 837 */ /* Client Info (Time Zone) */ - ALIGN64 TIME_ZONE_INFO* ClientTimeZone; /* 896 */ + ALIGN64 LPTIME_ZONE_INFORMATION ClientTimeZone; /* 896 */ ALIGN64 char* DynamicDSTTimeZoneKeyName; /* 897 */ ALIGN64 BOOL DynamicDaylightTimeDisabled; /* 898 */ UINT64 padding0960[960 - 899]; /* 899 */ @@ -1071,7 +1052,10 @@ struct rdp_settings ALIGN64 rdpRsaKey* RdpServerRsaKey; /* 1413 */ ALIGN64 rdpCertificate* RdpServerCertificate; /* 1414 */ ALIGN64 BOOL ExternalCertificateManagement; /* 1415 */ - UINT64 padding1472[1472 - 1416]; /* 1416 */ + ALIGN64 char *CertificateContent; /* 1416 */ + ALIGN64 char *PrivateKeyContent; /* 1417 */ + ALIGN64 char* RdpKeyContent; /* 1418 */ + UINT64 padding1472[1472 - 1419]; /* 1419 */ UINT64 padding1536[1536 - 1472]; /* 1472 */ /** @@ -1452,6 +1436,7 @@ FREERDP_API int freerdp_addin_replace_argument_value(ADDIN_ARGV* args, char* pre FREERDP_API BOOL freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device); FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* name); +FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find_type(rdpSettings* settings, UINT32 type); FREERDP_API RDPDR_DEVICE* freerdp_device_clone(RDPDR_DEVICE* device); FREERDP_API void freerdp_device_collection_free(rdpSettings* settings); diff --git a/include/freerdp/update.h b/include/freerdp/update.h index 527d291..3847d7a 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -148,6 +148,7 @@ typedef BOOL (*pSetKeyboardIndicators)(rdpContext* context, UINT16 led_flags); typedef BOOL (*pRefreshRect)(rdpContext* context, BYTE count, RECTANGLE_16* areas); typedef BOOL (*pSuppressOutput)(rdpContext* context, BYTE allow, RECTANGLE_16* area); +typedef BOOL (*pRemoteMonitors)(rdpContext* context, UINT32 count, const MONITOR_DEF *monitors); typedef BOOL (*pSurfaceCommand)(rdpContext* context, wStream* s); typedef BOOL (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand); @@ -155,6 +156,8 @@ typedef BOOL (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* s typedef BOOL (*pSurfaceFrameBits)(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId); typedef BOOL (*pSurfaceFrameAcknowledge)(rdpContext* context, UINT32 frameId); +typedef BOOL (*pSaveSessionInfo)(rdpContext *context, UINT32 type, void *data); + struct rdp_update { rdpContext* context; /* 0 */ @@ -180,14 +183,16 @@ struct rdp_update pRefreshRect RefreshRect; /* 48 */ pSuppressOutput SuppressOutput; /* 49 */ - UINT32 paddingD[64 - 50]; /* 50 */ + pRemoteMonitors RemoteMonitors; /* 50 */ + UINT32 paddingD[64 - 51]; /* 51 */ pSurfaceCommand SurfaceCommand; /* 64 */ pSurfaceBits SurfaceBits; /* 65 */ pSurfaceFrameMarker SurfaceFrameMarker; /* 66 */ pSurfaceFrameBits SurfaceFrameBits; /* 67 */ pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 68 */ - UINT32 paddingE[80 - 69]; /* 69 */ + pSaveSessionInfo SaveSessionInfo; /* 69 */ + UINT32 paddingE[80 - 70]; /* 70 */ /* internal */ diff --git a/libfreerdp/cache/glyph.c b/libfreerdp/cache/glyph.c index 0157d40..412c114 100644 --- a/libfreerdp/cache/glyph.c +++ b/libfreerdp/cache/glyph.c @@ -57,7 +57,7 @@ void update_process_glyph(rdpContext* context, BYTE* data, int* index, if (offset & 0x80) { - offset = data[*index + 1] | ((int)((char)data[*index + 2]) << 8); + offset = data[*index + 1] | ((int)((signed char)data[*index + 2]) << 8); (*index)++; (*index)++; } diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c index 859a208..cff1768 100644 --- a/libfreerdp/codec/nsc.c +++ b/libfreerdp/codec/nsc.c @@ -26,10 +26,6 @@ #include #include -#ifdef HAVE_STDINT_H -#include -#endif - #include #include diff --git a/libfreerdp/codec/nsc_encode.c b/libfreerdp/codec/nsc_encode.c index c015025..2477c65 100644 --- a/libfreerdp/codec/nsc_encode.c +++ b/libfreerdp/codec/nsc_encode.c @@ -25,10 +25,6 @@ #include #include -#ifdef HAVE_STDINT_H -#include -#endif - #include #include diff --git a/libfreerdp/codec/region.c b/libfreerdp/codec/region.c index be023b5..b3f32af 100644 --- a/libfreerdp/codec/region.c +++ b/libfreerdp/codec/region.c @@ -94,17 +94,17 @@ const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects) REGION16_DATA *data; assert(region); - assert(region->data); data = region->data; if (!data) { if (nbRects) *nbRects = 0; - return 0; + return NULL; } - *nbRects = data->nbRects; + if (nbRects) + *nbRects = data->nbRects; return (RECTANGLE_16 *)(data + 1); } diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index cc8a61c..e3a36ba 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -28,10 +28,6 @@ #include #include -#ifdef HAVE_STDINT_H -#include -#endif - #include #include #include diff --git a/libfreerdp/common/assistance.c b/libfreerdp/common/assistance.c index 9e4702e..63970de 100644 --- a/libfreerdp/common/assistance.c +++ b/libfreerdp/common/assistance.c @@ -22,16 +22,13 @@ #endif #include +#include #include #include #include -#include -#include -#include #include #include -#include #include #include @@ -523,7 +520,7 @@ char* freerdp_assistance_generate_pass_stub(DWORD flags) * Example: WB^6HsrIaFmEpi */ - RAND_bytes((BYTE*) nums, sizeof(nums)); + winpr_RAND((BYTE*) nums, sizeof(nums)); passStub[0] = set1[nums[0] % sizeof(set1)]; /* character 0 */ passStub[1] = set2[nums[1] % sizeof(set2)]; /* character 1 */ @@ -547,11 +544,11 @@ char* freerdp_assistance_generate_pass_stub(DWORD flags) BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub, int* pEncryptedSize) { int status; - MD5_CTX md5Ctx; + WINPR_MD5_CTX md5Ctx; int cbPasswordW; int cbPassStubW; int EncryptedSize; - BYTE PasswordHash[16]; + BYTE PasswordHash[WINPR_MD5_DIGEST_LENGTH]; EVP_CIPHER_CTX rc4Ctx; BYTE* pbIn, *pbOut; int cbOut, cbIn, cbFinal; @@ -565,14 +562,29 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas cbPasswordW = (status - 1) * 2; - MD5_Init(&md5Ctx); - MD5_Update(&md5Ctx, PasswordW, cbPasswordW); - MD5_Final((void*) PasswordHash, &md5Ctx); + if (!winpr_MD5_Init(&md5Ctx)) + { + free (PasswordW); + return NULL; + } + if (!winpr_MD5_Update(&md5Ctx, (BYTE*)PasswordW, cbPasswordW)) + { + free (PasswordW); + return NULL; + } + if (!winpr_MD5_Final(&md5Ctx, (BYTE*) PasswordHash, sizeof(PasswordHash))) + { + free (PasswordW); + return NULL; + } status = ConvertToUnicode(CP_UTF8, 0, passStub, -1, &PassStubW, 0); if (status <= 0) + { + free (PasswordW); return NULL; + } cbPassStubW = (status - 1) * 2; diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index b31d3b2..bded9d0 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -3,6 +3,7 @@ * Settings Management * * Copyright 2012 Marc-Andre Moreau + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -208,6 +209,22 @@ RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* return NULL; } +RDPDR_DEVICE* freerdp_device_collection_find_type(rdpSettings* settings, UINT32 type) +{ + UINT32 index; + RDPDR_DEVICE* device; + + for (index = 0; index < settings->DeviceCount; index++) + { + device = (RDPDR_DEVICE*) settings->DeviceArray[index]; + + if (device->Type == type) + return device; + } + + return NULL; +} + RDPDR_DEVICE* freerdp_device_clone(RDPDR_DEVICE* device) { if (device->Type == RDPDR_DTYP_FILESYSTEM) @@ -2381,6 +2398,15 @@ char* freerdp_get_param_string(rdpSettings* settings, int id) case FreeRDP_RdpKeyFile: return settings->RdpKeyFile; + case FreeRDP_CertificateContent: + return settings->CertificateContent; + + case FreeRDP_PrivateKeyContent: + return settings->PrivateKeyContent; + + case FreeRDP_RdpKeyContent: + return settings->RdpKeyContent; + case FreeRDP_WindowTitle: return settings->WindowTitle; @@ -2551,6 +2577,18 @@ int freerdp_set_param_string(rdpSettings* settings, int id, const char* param) tmp = &settings->PrivateKeyFile; break; + case FreeRDP_CertificateContent: + tmp = &settings->CertificateContent; + break; + + case FreeRDP_PrivateKeyContent: + tmp = &settings->PrivateKeyContent; + break; + + case FreeRDP_RdpKeyContent: + tmp = &settings->RdpKeyContent; + break; + case FreeRDP_RdpKeyFile: tmp = &settings->RdpKeyFile; break; diff --git a/libfreerdp/core/activation.c b/libfreerdp/core/activation.c index 97ea426..2db0566 100644 --- a/libfreerdp/core/activation.c +++ b/libfreerdp/core/activation.c @@ -364,9 +364,34 @@ BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s) BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s) { + rdpSettings *settings = rdp->settings; + if (!rdp_recv_client_font_list_pdu(s)) return FALSE; + if (settings->SupportMonitorLayoutPdu && settings->MonitorCount) + { + /* client supports the monitorLayout PDU, let's send him the monitors if any */ + wStream *st; + BOOL r; + + st = rdp_data_pdu_init(rdp); + if (!st) + return FALSE; + + if (!rdp_write_monitor_layout_pdu(st, settings->MonitorCount, settings->MonitorDefArray)) + { + Stream_Free(st, TRUE); + return FALSE; + } + + r = rdp_send_data_pdu(rdp, st, DATA_PDU_TYPE_MONITOR_LAYOUT, 0); + Stream_Free(st, TRUE); + + if (!r) + return FALSE; + } + if (!rdp_send_server_font_map_pdu(rdp)) return FALSE; diff --git a/libfreerdp/core/autodetect.c b/libfreerdp/core/autodetect.c index 1a89737..178e989 100644 --- a/libfreerdp/core/autodetect.c +++ b/libfreerdp/core/autodetect.c @@ -21,6 +21,8 @@ #include "config.h" #endif +#include + #include "autodetect.h" #define RDP_RTT_REQUEST_TYPE_CONTINUOUS 0x0001 @@ -173,7 +175,7 @@ BOOL autodetect_send_bandwidth_measure_payload(rdpContext* context, UINT16 paylo return FALSE; } - RAND_bytes(buffer, payloadLength); + winpr_RAND(buffer, payloadLength); Stream_Write(s, buffer, payloadLength); bResult = rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ); @@ -225,7 +227,7 @@ static BOOL autodetect_send_bandwidth_measure_stop(rdpContext* context, UINT16 p return FALSE; } - RAND_bytes(buffer, payloadLength); + winpr_RAND(buffer, payloadLength); Stream_Write(s, buffer, payloadLength); } } diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index 32ea34d..114cfd2 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -31,8 +31,6 @@ #define TAG FREERDP_TAG("core.capabilities") -#ifdef WITH_DEBUG_CAPABILITIES - const char* const CAPSET_TYPE_STRINGS[] = { "Unknown", @@ -68,7 +66,13 @@ const char* const CAPSET_TYPE_STRINGS[] = "Frame Acknowledge" }; -#endif +static const char *get_capability_name(UINT16 type) +{ + if (type > CAPSET_TYPE_FRAME_ACKNOWLEDGE) + return ""; + + return CAPSET_TYPE_STRINGS[type]; +} BOOL rdp_print_capability_sets(wStream* s, UINT16 numberCapabilities, BOOL receiving); @@ -223,12 +227,13 @@ BOOL rdp_read_general_capability_set(wStream* s, UINT16 length, rdpSettings* set * @param settings settings */ -void rdp_write_general_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_general_capability_set(wStream* s, rdpSettings* settings) { int header; UINT16 extraFlags; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; header = rdp_capability_set_start(s); @@ -259,6 +264,7 @@ void rdp_write_general_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT8(s, settings->SuppressOutput); /* suppressOutputSupport (1 byte) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_GENERAL); + return TRUE; } BOOL rdp_print_general_capability_set(wStream* s, UINT16 length) @@ -372,13 +378,14 @@ BOOL rdp_read_bitmap_capability_set(wStream* s, UINT16 length, rdpSettings* sett * @param settings settings */ -void rdp_write_bitmap_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_bitmap_capability_set(wStream* s, rdpSettings* settings) { int header; BYTE drawingFlags = 0; UINT16 preferredBitsPerPixel; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; header = rdp_capability_set_start(s); @@ -421,6 +428,7 @@ void rdp_write_bitmap_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, 0); /* pad2OctetsB (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP); + return TRUE; } BOOL rdp_print_bitmap_capability_set(wStream* s, UINT16 length) @@ -543,19 +551,21 @@ BOOL rdp_read_order_capability_set(wStream* s, UINT16 length, rdpSettings* setti * @param settings settings */ -void rdp_write_order_capability_set(wStream* s, rdpSettings* settings) +static BOOL rdp_write_order_capability_set(wStream* s, rdpSettings* settings) { int header; UINT16 orderFlags; UINT16 orderSupportExFlags; - UINT16 textANSICodePage; + UINT16 textANSICodePage = 0; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; header = rdp_capability_set_start(s); /* see [MSDN-CP]: http://msdn.microsoft.com/en-us/library/dd317756 */ - textANSICodePage = 65001; /* Unicode (UTF-8) */ + if (!settings->ServerMode) + textANSICodePage = 65001; /* Unicode (UTF-8) */ orderSupportExFlags = 0; orderFlags = NEGOTIATE_ORDER_SUPPORT | ZERO_BOUNDS_DELTA_SUPPORT | COLOR_INDEX_SUPPORT; @@ -587,10 +597,11 @@ void rdp_write_order_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT32(s, 230400); /* desktopSaveSize (4 bytes) */ Stream_Write_UINT16(s, 0); /* pad2OctetsC (2 bytes) */ Stream_Write_UINT16(s, 0); /* pad2OctetsD (2 bytes) */ - Stream_Write_UINT16(s, 0); /* textANSICodePage (2 bytes) */ + Stream_Write_UINT16(s, textANSICodePage); /* textANSICodePage (2 bytes) */ Stream_Write_UINT16(s, 0); /* pad2OctetsE (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_ORDER); + return TRUE; } BOOL rdp_print_order_capability_set(wStream* s, UINT16 length) @@ -721,13 +732,14 @@ BOOL rdp_read_bitmap_cache_capability_set(wStream* s, UINT16 length, rdpSettings * @param settings settings */ -void rdp_write_bitmap_cache_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_bitmap_cache_capability_set(wStream* s, rdpSettings* settings) { int bpp; int header; UINT16 size; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; header = rdp_capability_set_start(s); @@ -753,6 +765,7 @@ void rdp_write_bitmap_cache_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, size); /* Cache2MaximumCellSize (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE); + return TRUE; } BOOL rdp_print_bitmap_cache_capability_set(wStream* s, UINT16 length) @@ -825,11 +838,12 @@ BOOL rdp_read_control_capability_set(wStream* s, UINT16 length, rdpSettings* set * @param settings settings */ -void rdp_write_control_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_control_capability_set(wStream* s, rdpSettings* settings) { int header; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -839,6 +853,7 @@ void rdp_write_control_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, 2); /* detachInterest (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_CONTROL); + return TRUE; } BOOL rdp_print_control_capability_set(wStream* s, UINT16 length) @@ -891,11 +906,12 @@ BOOL rdp_read_window_activation_capability_set(wStream* s, UINT16 length, rdpSet * @param settings settings */ -void rdp_write_window_activation_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_window_activation_capability_set(wStream* s, rdpSettings* settings) { int header; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -905,6 +921,7 @@ void rdp_write_window_activation_capability_set(wStream* s, rdpSettings* setting Stream_Write_UINT16(s, 0); /* windowManagerKeyFlag (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_ACTIVATION); + return TRUE; } BOOL rdp_print_window_activation_capability_set(wStream* s, UINT16 length) @@ -972,12 +989,13 @@ BOOL rdp_read_pointer_capability_set(wStream* s, UINT16 length, rdpSettings* set * @param settings settings */ -void rdp_write_pointer_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_pointer_capability_set(wStream* s, rdpSettings* settings) { int header; UINT16 colorPointerFlag; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -992,6 +1010,7 @@ void rdp_write_pointer_capability_set(wStream* s, rdpSettings* settings) } rdp_capability_set_finish(s, header, CAPSET_TYPE_POINTER); + return TRUE; } BOOL rdp_print_pointer_capability_set(wStream* s, UINT16 length) @@ -1039,12 +1058,13 @@ BOOL rdp_read_share_capability_set(wStream* s, UINT16 length, rdpSettings* setti * @param settings settings */ -void rdp_write_share_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_share_capability_set(wStream* s, rdpSettings* settings) { int header; UINT16 nodeId; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -1054,6 +1074,7 @@ void rdp_write_share_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_SHARE); + return TRUE; } BOOL rdp_print_share_capability_set(wStream* s, UINT16 length) @@ -1098,11 +1119,12 @@ BOOL rdp_read_color_cache_capability_set(wStream* s, UINT16 length, rdpSettings* * @param settings settings */ -void rdp_write_color_cache_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_color_cache_capability_set(wStream* s, rdpSettings* settings) { int header; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -1110,6 +1132,7 @@ void rdp_write_color_cache_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_COLOR_CACHE); + return TRUE; } BOOL rdp_print_color_cache_capability_set(wStream* s, UINT16 length) @@ -1158,12 +1181,13 @@ BOOL rdp_read_sound_capability_set(wStream* s, UINT16 length, rdpSettings* setti * @param settings settings */ -void rdp_write_sound_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_sound_capability_set(wStream* s, rdpSettings* settings) { int header; UINT16 soundFlags; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -1173,6 +1197,7 @@ void rdp_write_sound_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, 0); /* pad2OctetsA (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_SOUND); + return TRUE; } BOOL rdp_print_sound_capability_set(wStream* s, UINT16 length) @@ -1255,12 +1280,13 @@ BOOL rdp_read_input_capability_set(wStream* s, UINT16 length, rdpSettings* setti * @param settings settings */ -void rdp_write_input_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_input_capability_set(wStream* s, rdpSettings* settings) { int header; UINT16 inputFlags; - Stream_EnsureRemainingCapacity(s, 128); + if (!Stream_EnsureRemainingCapacity(s, 128)) + return FALSE; header = rdp_capability_set_start(s); @@ -1281,6 +1307,7 @@ void rdp_write_input_capability_set(wStream* s, rdpSettings* settings) Stream_Zero(s, 64); /* imeFileName (64 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_INPUT); + return TRUE; } BOOL rdp_print_input_capability_set(wStream* s, UINT16 length) @@ -1338,11 +1365,12 @@ BOOL rdp_read_font_capability_set(wStream* s, UINT16 length, rdpSettings* settin * @param settings settings */ -void rdp_write_font_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_font_capability_set(wStream* s, rdpSettings* settings) { int header; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -1350,6 +1378,7 @@ void rdp_write_font_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_FONT); + return TRUE; } BOOL rdp_print_font_capability_set(wStream* s, UINT16 length) @@ -1394,17 +1423,19 @@ BOOL rdp_read_brush_capability_set(wStream* s, UINT16 length, rdpSettings* setti * @param settings settings */ -void rdp_write_brush_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_brush_capability_set(wStream* s, rdpSettings* settings) { int header; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); Stream_Write_UINT32(s, BRUSH_COLOR_FULL); /* brushSupportLevel (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BRUSH); + return TRUE; } BOOL rdp_print_brush_capability_set(wStream* s, UINT16 length) @@ -1482,11 +1513,12 @@ BOOL rdp_read_glyph_cache_capability_set(wStream* s, UINT16 length, rdpSettings* * @param settings settings */ -void rdp_write_glyph_cache_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_glyph_cache_capability_set(wStream* s, rdpSettings* settings) { int header; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; header = rdp_capability_set_start(s); @@ -1508,6 +1540,7 @@ void rdp_write_glyph_cache_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_GLYPH_CACHE); + return TRUE; } BOOL rdp_print_glyph_cache_capability_set(wStream* s, UINT16 length) @@ -1584,12 +1617,13 @@ BOOL rdp_read_offscreen_bitmap_cache_capability_set(wStream* s, UINT16 length, r * @param settings settings */ -void rdp_write_offscreen_bitmap_cache_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_offscreen_bitmap_cache_capability_set(wStream* s, rdpSettings* settings) { int header; UINT32 offscreenSupportLevel = FALSE; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -1601,6 +1635,7 @@ void rdp_write_offscreen_bitmap_cache_capability_set(wStream* s, rdpSettings* se Stream_Write_UINT16(s, settings->OffscreenCacheEntries); /* offscreenCacheEntries (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_OFFSCREEN_CACHE); + return TRUE; } BOOL rdp_print_offscreen_bitmap_cache_capability_set(wStream* s, UINT16 length) @@ -1654,11 +1689,12 @@ BOOL rdp_read_bitmap_cache_host_support_capability_set(wStream* s, UINT16 length * @param settings settings */ -void rdp_write_bitmap_cache_host_support_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_bitmap_cache_host_support_capability_set(wStream* s, rdpSettings* settings) { int header; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -1667,6 +1703,7 @@ void rdp_write_bitmap_cache_host_support_capability_set(wStream* s, rdpSettings* Stream_Write_UINT16(s, 0); /* pad2 (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT); + return TRUE; } BOOL rdp_print_bitmap_cache_host_support_capability_set(wStream* s, UINT16 length) @@ -1749,12 +1786,13 @@ BOOL rdp_read_bitmap_cache_v2_capability_set(wStream* s, UINT16 length, rdpSetti * @param settings settings */ -void rdp_write_bitmap_cache_v2_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_bitmap_cache_v2_capability_set(wStream* s, rdpSettings* settings) { int header; UINT16 cacheFlags; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; header = rdp_capability_set_start(s); @@ -1774,6 +1812,7 @@ void rdp_write_bitmap_cache_v2_capability_set(wStream* s, rdpSettings* settings) Stream_Zero(s, 12); /* pad3 (12 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_V2); + return TRUE; } BOOL rdp_print_bitmap_cache_v2_capability_set(wStream* s, UINT16 length) @@ -1843,12 +1882,13 @@ BOOL rdp_read_virtual_channel_capability_set(wStream* s, UINT16 length, rdpSetti * @param settings settings */ -void rdp_write_virtual_channel_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_virtual_channel_capability_set(wStream* s, rdpSettings* settings) { int header; UINT32 flags; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -1858,6 +1898,7 @@ void rdp_write_virtual_channel_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT32(s, settings->VirtualChannelChunkSize); /* VCChunkSize (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_VIRTUAL_CHANNEL); + return TRUE; } BOOL rdp_print_virtual_channel_capability_set(wStream* s, UINT16 length) @@ -1914,12 +1955,13 @@ BOOL rdp_read_draw_nine_grid_cache_capability_set(wStream* s, UINT16 length, rdp * @param settings settings */ -void rdp_write_draw_nine_grid_cache_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_draw_nine_grid_cache_capability_set(wStream* s, rdpSettings* settings) { int header; UINT32 drawNineGridSupportLevel; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -1930,6 +1972,7 @@ void rdp_write_draw_nine_grid_cache_capability_set(wStream* s, rdpSettings* sett Stream_Write_UINT16(s, settings->DrawNineGridCacheEntries); /* drawNineGridCacheEntries (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_NINE_GRID_CACHE); + return TRUE; } void rdp_write_gdiplus_cache_entries(wStream* s, UINT16 gce, UINT16 bce, UINT16 pce, UINT16 ice, UINT16 ace) @@ -2012,13 +2055,14 @@ BOOL rdp_read_draw_gdiplus_cache_capability_set(wStream* s, UINT16 length, rdpSe * @param settings settings */ -void rdp_write_draw_gdiplus_cache_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_draw_gdiplus_cache_capability_set(wStream* s, rdpSettings* settings) { int header; UINT32 drawGDIPlusSupportLevel; UINT32 drawGdiplusCacheLevel; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; header = rdp_capability_set_start(s); @@ -2033,6 +2077,7 @@ void rdp_write_draw_gdiplus_cache_capability_set(wStream* s, rdpSettings* settin rdp_write_gdiplus_image_cache_properties(s, 4096, 256, 128); /* GdipImageCacheProperties (6 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_GDI_PLUS); + return TRUE; } BOOL rdp_print_draw_gdiplus_cache_capability_set(wStream* s, UINT16 length) @@ -2090,12 +2135,13 @@ BOOL rdp_read_remote_programs_capability_set(wStream* s, UINT16 length, rdpSetti * @param settings settings */ -void rdp_write_remote_programs_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_remote_programs_capability_set(wStream* s, rdpSettings* settings) { int header; UINT32 railSupportLevel; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; header = rdp_capability_set_start(s); @@ -2107,6 +2153,7 @@ void rdp_write_remote_programs_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_RAIL); + return TRUE; } BOOL rdp_print_remote_programs_capability_set(wStream* s, UINT16 length) @@ -2149,12 +2196,13 @@ BOOL rdp_read_window_list_capability_set(wStream* s, UINT16 length, rdpSettings* * @param settings settings */ -void rdp_write_window_list_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_window_list_capability_set(wStream* s, rdpSettings* settings) { int header; UINT32 wndSupportLevel; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -2165,6 +2213,7 @@ void rdp_write_window_list_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, settings->RemoteAppNumIconCacheEntries); /* numIconCacheEntries (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_WINDOW); + return TRUE; } BOOL rdp_print_window_list_capability_set(wStream* s, UINT16 length) @@ -2211,12 +2260,13 @@ BOOL rdp_read_desktop_composition_capability_set(wStream* s, UINT16 length, rdpS * @param settings settings */ -void rdp_write_desktop_composition_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_desktop_composition_capability_set(wStream* s, rdpSettings* settings) { int header; UINT16 compDeskSupportLevel; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -2225,6 +2275,7 @@ void rdp_write_desktop_composition_capability_set(wStream* s, rdpSettings* setti Stream_Write_UINT16(s, compDeskSupportLevel); /* compDeskSupportLevel (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_COMP_DESK); + return TRUE; } BOOL rdp_print_desktop_composition_capability_set(wStream* s, UINT16 length) @@ -2317,11 +2368,12 @@ BOOL rdp_read_multifragment_update_capability_set(wStream* s, UINT16 length, rdp * @param settings settings */ -void rdp_write_multifragment_update_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_multifragment_update_capability_set(wStream* s, rdpSettings* settings) { int header; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; if (settings->ServerMode) { @@ -2351,6 +2403,7 @@ void rdp_write_multifragment_update_capability_set(wStream* s, rdpSettings* sett Stream_Write_UINT32(s, settings->MultifragMaxRequestSize); /* MaxRequestSize (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_MULTI_FRAGMENT_UPDATE); + return TRUE; } BOOL rdp_print_multifragment_update_capability_set(wStream* s, UINT16 length) @@ -2395,12 +2448,13 @@ BOOL rdp_read_large_pointer_capability_set(wStream* s, UINT16 length, rdpSetting * @param settings settings */ -void rdp_write_large_pointer_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_large_pointer_capability_set(wStream* s, rdpSettings* settings) { int header; UINT16 largePointerSupportFlags; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -2409,6 +2463,7 @@ void rdp_write_large_pointer_capability_set(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, largePointerSupportFlags); /* largePointerSupportFlags (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_LARGE_POINTER); + return TRUE; } BOOL rdp_print_large_pointer_capability_set(wStream* s, UINT16 length) @@ -2455,12 +2510,13 @@ BOOL rdp_read_surface_commands_capability_set(wStream* s, UINT16 length, rdpSett * @param settings settings */ -void rdp_write_surface_commands_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_surface_commands_capability_set(wStream* s, rdpSettings* settings) { int header; UINT32 cmdFlags; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); @@ -2473,6 +2529,7 @@ void rdp_write_surface_commands_capability_set(wStream* s, rdpSettings* settings Stream_Write_UINT32(s, 0); /* reserved (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_SURFACE_COMMANDS); + return TRUE; } BOOL rdp_print_surface_commands_capability_set(wStream* s, UINT16 length) @@ -2785,12 +2842,13 @@ BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, UINT16 length, rdpSetting * @param s stream * @param settings settings */ -void rdp_write_rfx_client_capability_container(wStream* s, rdpSettings* settings) +BOOL rdp_write_rfx_client_capability_container(wStream* s, rdpSettings* settings) { UINT32 captureFlags; BYTE codecMode; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; captureFlags = settings->RemoteFxOnly ? 0 : CARDP_CAPS_CAPTURE_NON_CAC; codecMode = settings->RemoteFxCodecMode; @@ -2830,6 +2888,7 @@ void rdp_write_rfx_client_capability_container(wStream* s, rdpSettings* settings Stream_Write_UINT8(s, CLW_COL_CONV_ICT); /* colConvBits */ Stream_Write_UINT8(s, CLW_XFORM_DWT_53_A); /* transformBits */ Stream_Write_UINT8(s, CLW_ENTROPY_RLGR3); /* entropyBits */ + return TRUE; } /** @@ -2837,7 +2896,7 @@ void rdp_write_rfx_client_capability_container(wStream* s, rdpSettings* settings * @param s stream * @param settings settings */ -void rdp_write_nsc_client_capability_container(wStream* s, rdpSettings* settings) +BOOL rdp_write_nsc_client_capability_container(wStream* s, rdpSettings* settings) { BYTE colorLossLevel; BYTE fAllowSubsampling; @@ -2853,7 +2912,8 @@ void rdp_write_nsc_client_capability_container(wStream* s, rdpSettings* settings if (colorLossLevel > 7) colorLossLevel = 7; - Stream_EnsureRemainingCapacity(s, 8); + if (!Stream_EnsureRemainingCapacity(s, 8)) + return FALSE; Stream_Write_UINT16(s, 3); /* codecPropertiesLength */ @@ -2861,14 +2921,17 @@ void rdp_write_nsc_client_capability_container(wStream* s, rdpSettings* settings Stream_Write_UINT8(s, fAllowDynamicFidelity); /* fAllowDynamicFidelity (1 byte) */ Stream_Write_UINT8(s, fAllowSubsampling); /* fAllowSubsampling (1 byte) */ Stream_Write_UINT8(s, colorLossLevel); /* colorLossLevel (1 byte) */ + return TRUE; } -void rdp_write_jpeg_client_capability_container(wStream* s, rdpSettings* settings) +BOOL rdp_write_jpeg_client_capability_container(wStream* s, rdpSettings* settings) { - Stream_EnsureRemainingCapacity(s, 8); + if (!Stream_EnsureRemainingCapacity(s, 8)) + return FALSE; Stream_Write_UINT16(s, 1); /* codecPropertiesLength */ Stream_Write_UINT8(s, settings->JpegQuality); + return TRUE; } /** @@ -2876,20 +2939,24 @@ void rdp_write_jpeg_client_capability_container(wStream* s, rdpSettings* setting * @param s stream * @param settings settings */ -void rdp_write_rfx_server_capability_container(wStream* s, rdpSettings* settings) +BOOL rdp_write_rfx_server_capability_container(wStream* s, rdpSettings* settings) { - Stream_EnsureRemainingCapacity(s, 8); + if (!Stream_EnsureRemainingCapacity(s, 8)) + return FALSE; Stream_Write_UINT16(s, 4); /* codecPropertiesLength */ Stream_Write_UINT32(s, 0); /* reserved */ + return TRUE; } -void rdp_write_jpeg_server_capability_container(wStream* s, rdpSettings* settings) +BOOL rdp_write_jpeg_server_capability_container(wStream* s, rdpSettings* settings) { - Stream_EnsureRemainingCapacity(s, 8); + if (!Stream_EnsureRemainingCapacity(s, 8)) + return FALSE; Stream_Write_UINT16(s, 1); /* codecPropertiesLength */ Stream_Write_UINT8(s, 75); + return TRUE; } /** @@ -2897,12 +2964,14 @@ void rdp_write_jpeg_server_capability_container(wStream* s, rdpSettings* setting * @param s stream * @param settings settings */ -void rdp_write_nsc_server_capability_container(wStream* s, rdpSettings* settings) +BOOL rdp_write_nsc_server_capability_container(wStream* s, rdpSettings* settings) { - Stream_EnsureRemainingCapacity(s, 8); + if (!Stream_EnsureRemainingCapacity(s, 8)) + return FALSE; Stream_Write_UINT16(s, 4); /* codecPropertiesLength */ Stream_Write_UINT32(s, 0); /* reserved */ + return TRUE; } /** @@ -2912,12 +2981,13 @@ void rdp_write_nsc_server_capability_container(wStream* s, rdpSettings* settings * @param settings settings */ -void rdp_write_bitmap_codecs_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_bitmap_codecs_capability_set(wStream* s, rdpSettings* settings) { int header; BYTE bitmapCodecCount; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; header = rdp_capability_set_start(s); @@ -2941,12 +3011,14 @@ void rdp_write_bitmap_codecs_capability_set(wStream* s, rdpSettings* settings) if (settings->ServerMode) { Stream_Write_UINT8(s, 0); /* codecID is defined by the client */ - rdp_write_rfx_server_capability_container(s, settings); + if (!rdp_write_rfx_server_capability_container(s, settings)) + return FALSE; } else { Stream_Write_UINT8(s, RDP_CODEC_ID_REMOTEFX); /* codecID */ - rdp_write_rfx_client_capability_container(s, settings); + if (!rdp_write_rfx_client_capability_container(s, settings)) + return FALSE; } } @@ -2957,12 +3029,14 @@ void rdp_write_bitmap_codecs_capability_set(wStream* s, rdpSettings* settings) if (settings->ServerMode) { Stream_Write_UINT8(s, 0); /* codecID is defined by the client */ - rdp_write_nsc_server_capability_container(s, settings); + if (!rdp_write_nsc_server_capability_container(s, settings)) + return FALSE; } else { Stream_Write_UINT8(s, RDP_CODEC_ID_NSCODEC); /* codecID */ - rdp_write_nsc_client_capability_container(s, settings); + if (!rdp_write_nsc_client_capability_container(s, settings)) + return FALSE; } } @@ -2973,12 +3047,14 @@ void rdp_write_bitmap_codecs_capability_set(wStream* s, rdpSettings* settings) if (settings->ServerMode) { Stream_Write_UINT8(s, 0); /* codecID is defined by the client */ - rdp_write_jpeg_server_capability_container(s, settings); + if (!rdp_write_jpeg_server_capability_container(s, settings)) + return FALSE; } else { Stream_Write_UINT8(s, RDP_CODEC_ID_JPEG); /* codecID */ - rdp_write_jpeg_client_capability_container(s, settings); + if (!rdp_write_jpeg_client_capability_container(s, settings)) + return FALSE; } } @@ -2989,16 +3065,19 @@ void rdp_write_bitmap_codecs_capability_set(wStream* s, rdpSettings* settings) if (settings->ServerMode) { Stream_Write_UINT8(s, 0); /* codecID is defined by the client */ - rdp_write_rfx_server_capability_container(s, settings); + if (!rdp_write_rfx_server_capability_container(s, settings)) + return FALSE; } else { Stream_Write_UINT8(s, RDP_CODEC_ID_IMAGE_REMOTEFX); /* codecID */ - rdp_write_rfx_client_capability_container(s, settings); + if (!rdp_write_rfx_client_capability_container(s, settings)) + return FALSE; } } rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CODECS); + return TRUE; } BOOL rdp_print_bitmap_codecs_capability_set(wStream* s, UINT16 length) @@ -3074,17 +3153,19 @@ BOOL rdp_read_frame_acknowledge_capability_set(wStream* s, UINT16 length, rdpSet * @param settings settings */ -void rdp_write_frame_acknowledge_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_frame_acknowledge_capability_set(wStream* s, rdpSettings* settings) { int header; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); Stream_Write_UINT32(s, settings->FrameAcknowledge); /* (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_FRAME_ACKNOWLEDGE); + return TRUE; } BOOL rdp_print_frame_acknowledge_capability_set(wStream* s, UINT16 length) @@ -3112,16 +3193,18 @@ BOOL rdp_read_bitmap_cache_v3_codec_id_capability_set(wStream* s, UINT16 length, return TRUE; } -void rdp_write_bitmap_cache_v3_codec_id_capability_set(wStream* s, rdpSettings* settings) +BOOL rdp_write_bitmap_cache_v3_codec_id_capability_set(wStream* s, rdpSettings* settings) { int header; - Stream_EnsureRemainingCapacity(s, 32); + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); Stream_Write_UINT8(s, settings->BitmapCacheV3CodecId); rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_V3_CODEC_ID); + return TRUE; } BOOL rdp_print_bitmap_cache_v3_codec_id_capability_set(wStream* s, UINT16 length) @@ -3329,6 +3412,7 @@ BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCa UINT16 type; UINT16 length; BYTE *bm, *em; + BOOL treated; Stream_GetPointer(s, mark); count = numberCapabilities; @@ -3356,6 +3440,7 @@ BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCa return FALSE; } + treated = TRUE; switch (type) { case CAPSET_TYPE_GENERAL: @@ -3373,26 +3458,21 @@ BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCa return FALSE; break; - case CAPSET_TYPE_BITMAP_CACHE: - if (!rdp_read_bitmap_cache_capability_set(s, length, settings)) - return FALSE; - break; - - case CAPSET_TYPE_CONTROL: - if (!rdp_read_control_capability_set(s, length, settings)) - return FALSE; - break; - - case CAPSET_TYPE_ACTIVATION: - if (!rdp_read_window_activation_capability_set(s, length, settings)) - return FALSE; - break; - case CAPSET_TYPE_POINTER: if (!rdp_read_pointer_capability_set(s, length, settings)) return FALSE; break; + case CAPSET_TYPE_INPUT: + if (!rdp_read_input_capability_set(s, length, settings)) + return FALSE; + break; + + case CAPSET_TYPE_VIRTUAL_CHANNEL: + if (!rdp_read_virtual_channel_capability_set(s, length, settings)) + return FALSE; + break; + case CAPSET_TYPE_SHARE: if (!rdp_read_share_capability_set(s, length, settings)) return FALSE; @@ -3403,56 +3483,11 @@ BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCa return FALSE; break; - case CAPSET_TYPE_SOUND: - if (!rdp_read_sound_capability_set(s, length, settings)) - return FALSE; - break; - - case CAPSET_TYPE_INPUT: - if (!rdp_read_input_capability_set(s, length, settings)) - return FALSE; - break; - case CAPSET_TYPE_FONT: if (!rdp_read_font_capability_set(s, length, settings)) return FALSE; break; - case CAPSET_TYPE_BRUSH: - if (!rdp_read_brush_capability_set(s, length, settings)) - return FALSE; - break; - - case CAPSET_TYPE_GLYPH_CACHE: - if (!rdp_read_glyph_cache_capability_set(s, length, settings)) - return FALSE; - break; - - case CAPSET_TYPE_OFFSCREEN_CACHE: - if (!rdp_read_offscreen_bitmap_cache_capability_set(s, length, settings)) - return FALSE; - break; - - case CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT: - if (!rdp_read_bitmap_cache_host_support_capability_set(s, length, settings)) - return FALSE; - break; - - case CAPSET_TYPE_BITMAP_CACHE_V2: - if (!rdp_read_bitmap_cache_v2_capability_set(s, length, settings)) - return FALSE; - break; - - case CAPSET_TYPE_VIRTUAL_CHANNEL: - if (!rdp_read_virtual_channel_capability_set(s, length, settings)) - return FALSE; - break; - - case CAPSET_TYPE_DRAW_NINE_GRID_CACHE: - if (!rdp_read_draw_nine_grid_cache_capability_set(s, length, settings)) - return FALSE; - break; - case CAPSET_TYPE_DRAW_GDI_PLUS: if (!rdp_read_draw_gdiplus_cache_capability_set(s, length, settings)) return FALSE; @@ -3468,11 +3503,6 @@ BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCa return FALSE; break; - case CAPSET_TYPE_COMP_DESK: - if (!rdp_read_desktop_composition_capability_set(s, length, settings)) - return FALSE; - break; - case CAPSET_TYPE_MULTI_FRAGMENT_UPDATE: if (!rdp_read_multifragment_update_capability_set(s, length, settings)) return FALSE; @@ -3483,6 +3513,11 @@ BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCa return FALSE; break; + case CAPSET_TYPE_COMP_DESK: + if (!rdp_read_desktop_composition_capability_set(s, length, settings)) + return FALSE; + break; + case CAPSET_TYPE_SURFACE_COMMANDS: if (!rdp_read_surface_commands_capability_set(s, length, settings)) return FALSE; @@ -3504,10 +3539,84 @@ BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCa break; default: - WLog_ERR(TAG, "unknown capability type %d", type); + treated = FALSE; break; } + if (!treated) + { + if (settings->ServerMode) + { + /* treating capabilities that are supposed to be send only from the client */ + switch (type) + { + case CAPSET_TYPE_BITMAP_CACHE: + if (!rdp_read_bitmap_cache_capability_set(s, length, settings)) + return FALSE; + break; + + case CAPSET_TYPE_BITMAP_CACHE_V2: + if (!rdp_read_bitmap_cache_v2_capability_set(s, length, settings)) + return FALSE; + break; + + case CAPSET_TYPE_BRUSH: + if (!rdp_read_brush_capability_set(s, length, settings)) + return FALSE; + break; + + case CAPSET_TYPE_GLYPH_CACHE: + if (!rdp_read_glyph_cache_capability_set(s, length, settings)) + return FALSE; + break; + + case CAPSET_TYPE_OFFSCREEN_CACHE: + if (!rdp_read_offscreen_bitmap_cache_capability_set(s, length, settings)) + return FALSE; + break; + + case CAPSET_TYPE_SOUND: + if (!rdp_read_sound_capability_set(s, length, settings)) + return FALSE; + break; + + case CAPSET_TYPE_CONTROL: + if (!rdp_read_control_capability_set(s, length, settings)) + return FALSE; + break; + + case CAPSET_TYPE_ACTIVATION: + if (!rdp_read_window_activation_capability_set(s, length, settings)) + return FALSE; + break; + + case CAPSET_TYPE_DRAW_NINE_GRID_CACHE: + if (!rdp_read_draw_nine_grid_cache_capability_set(s, length, settings)) + return FALSE; + break; + + default: + WLog_ERR(TAG, "capability %s(%d) not expected from client", get_capability_name(type), type); + return FALSE; + } + } + else + { + /* treating capabilities that are supposed to be send only from the server */ + switch (type) + { + case CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT: + if (!rdp_read_bitmap_cache_host_support_capability_set(s, length, settings)) + return FALSE; + break; + + default: + WLog_ERR(TAG, "capability %s(%d) not expected from server", get_capability_name(type), type); + return FALSE; + } + } + } + if (s->pointer != em) { WLog_ERR(TAG, "incorrect offset, type:0x%02X actual:%d expected:%d", @@ -3645,13 +3754,14 @@ BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s) return TRUE; } -void rdp_write_demand_active(wStream* s, rdpSettings* settings) +BOOL rdp_write_demand_active(wStream* s, rdpSettings* settings) { int bm, em, lm; UINT16 numberCapabilities; UINT16 lengthCombinedCapabilities; - Stream_EnsureRemainingCapacity(s, 64); + if (!Stream_EnsureRemainingCapacity(s, 64)) + return FALSE; Stream_Write_UINT32(s, settings->ShareId); /* shareId (4 bytes) */ Stream_Write_UINT16(s, 4); /* lengthSourceDescriptor (2 bytes) */ @@ -3665,25 +3775,29 @@ void rdp_write_demand_active(wStream* s, rdpSettings* settings) Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ numberCapabilities = 14; - rdp_write_general_capability_set(s, settings); - rdp_write_bitmap_capability_set(s, settings); - rdp_write_order_capability_set(s, settings); - rdp_write_pointer_capability_set(s, settings); - rdp_write_input_capability_set(s, settings); - rdp_write_virtual_channel_capability_set(s, settings); - rdp_write_share_capability_set(s, settings); - rdp_write_font_capability_set(s, settings); - rdp_write_multifragment_update_capability_set(s, settings); - rdp_write_large_pointer_capability_set(s, settings); - rdp_write_desktop_composition_capability_set(s, settings); - rdp_write_surface_commands_capability_set(s, settings); - rdp_write_bitmap_codecs_capability_set(s, settings); - rdp_write_frame_acknowledge_capability_set(s, settings); + if (!rdp_write_general_capability_set(s, settings) || + !rdp_write_bitmap_capability_set(s, settings) || + !rdp_write_order_capability_set(s, settings) || + !rdp_write_pointer_capability_set(s, settings) || + !rdp_write_input_capability_set(s, settings) || + !rdp_write_virtual_channel_capability_set(s, settings) || + !rdp_write_share_capability_set(s, settings) || + !rdp_write_font_capability_set(s, settings) || + !rdp_write_multifragment_update_capability_set(s, settings) || + !rdp_write_large_pointer_capability_set(s, settings) || + !rdp_write_desktop_composition_capability_set(s, settings) || + !rdp_write_surface_commands_capability_set(s, settings) || + !rdp_write_bitmap_codecs_capability_set(s, settings) || + !rdp_write_frame_acknowledge_capability_set(s, settings)) + { + return FALSE; + } if (settings->BitmapCachePersistEnabled) { numberCapabilities++; - rdp_write_bitmap_cache_host_support_capability_set(s, settings); + if (!rdp_write_bitmap_cache_host_support_capability_set(s, settings)) + return FALSE; } em = Stream_GetPosition(s); @@ -3705,6 +3819,7 @@ void rdp_write_demand_active(wStream* s, rdpSettings* settings) Stream_SetPosition(s, em); Stream_Write_UINT32(s, 0); /* sessionId */ + return TRUE; } BOOL rdp_send_demand_active(rdpRdp* rdp) @@ -3719,9 +3834,8 @@ BOOL rdp_send_demand_active(rdpRdp* rdp) rdp->settings->ShareId = 0x10000 + rdp->mcs->userId; - rdp_write_demand_active(s, rdp->settings); - - status = rdp_send_pdu(rdp, s, PDU_TYPE_DEMAND_ACTIVE, rdp->mcs->userId); + status = rdp_write_demand_active(s, rdp->settings) && + rdp_send_pdu(rdp, s, PDU_TYPE_DEMAND_ACTIVE, rdp->mcs->userId); Stream_Free(s, TRUE); @@ -3798,12 +3912,13 @@ BOOL rdp_recv_confirm_active(rdpRdp* rdp, wStream* s) return status; } -void rdp_write_confirm_active(wStream* s, rdpSettings* settings) +BOOL rdp_write_confirm_active(wStream* s, rdpSettings* settings) { int bm, em, lm; UINT16 numberCapabilities; UINT16 lengthSourceDescriptor; UINT16 lengthCombinedCapabilities; + BOOL ret; lengthSourceDescriptor = sizeof(SOURCE_DESCRIPTOR); @@ -3821,37 +3936,46 @@ void rdp_write_confirm_active(wStream* s, rdpSettings* settings) /* Capability Sets */ numberCapabilities = 15; - rdp_write_general_capability_set(s, settings); - rdp_write_bitmap_capability_set(s, settings); - rdp_write_order_capability_set(s, settings); + if (!rdp_write_general_capability_set(s, settings) || + !rdp_write_bitmap_capability_set(s, settings) || + !rdp_write_order_capability_set(s, settings)) + return FALSE; if (settings->RdpVersion >= 5) - rdp_write_bitmap_cache_v2_capability_set(s, settings); + ret = rdp_write_bitmap_cache_v2_capability_set(s, settings); else - rdp_write_bitmap_cache_capability_set(s, settings); + ret = rdp_write_bitmap_cache_capability_set(s, settings); - rdp_write_pointer_capability_set(s, settings); - rdp_write_input_capability_set(s, settings); - rdp_write_brush_capability_set(s, settings); - rdp_write_glyph_cache_capability_set(s, settings); - rdp_write_virtual_channel_capability_set(s, settings); - rdp_write_sound_capability_set(s, settings); - rdp_write_share_capability_set(s, settings); - rdp_write_font_capability_set(s, settings); - rdp_write_control_capability_set(s, settings); - rdp_write_color_cache_capability_set(s, settings); - rdp_write_window_activation_capability_set(s, settings); + if (!ret) + return FALSE; + + if (!rdp_write_pointer_capability_set(s, settings) || + !rdp_write_input_capability_set(s, settings) || + !rdp_write_brush_capability_set(s, settings) || + !rdp_write_glyph_cache_capability_set(s, settings) || + !rdp_write_virtual_channel_capability_set(s, settings) || + !rdp_write_sound_capability_set(s, settings) || + !rdp_write_share_capability_set(s, settings) || + !rdp_write_font_capability_set(s, settings) || + !rdp_write_control_capability_set(s, settings) || + !rdp_write_color_cache_capability_set(s, settings) || + !rdp_write_window_activation_capability_set(s, settings)) + { + return FALSE; + } if (settings->OffscreenSupportLevel) { numberCapabilities++; - rdp_write_offscreen_bitmap_cache_capability_set(s, settings); + if (!rdp_write_offscreen_bitmap_cache_capability_set(s, settings)) + return FALSE; } if (settings->DrawNineGridEnabled) { numberCapabilities++; - rdp_write_draw_nine_grid_cache_capability_set(s, settings); + if (!rdp_write_draw_nine_grid_cache_capability_set(s, settings)) + return FALSE; } if (settings->ReceivedCapabilities[CAPSET_TYPE_LARGE_POINTER]) @@ -3859,33 +3983,38 @@ void rdp_write_confirm_active(wStream* s, rdpSettings* settings) if (settings->LargePointerFlag) { numberCapabilities++; - rdp_write_large_pointer_capability_set(s, settings); + if (!rdp_write_large_pointer_capability_set(s, settings)) + return FALSE; } } if (settings->RemoteApplicationMode) { numberCapabilities += 2; - rdp_write_remote_programs_capability_set(s, settings); - rdp_write_window_list_capability_set(s, settings); + if (!rdp_write_remote_programs_capability_set(s, settings) || + !rdp_write_window_list_capability_set(s, settings)) + return FALSE; } if (settings->ReceivedCapabilities[CAPSET_TYPE_MULTI_FRAGMENT_UPDATE]) { numberCapabilities++; - rdp_write_multifragment_update_capability_set(s, settings); + if (!rdp_write_multifragment_update_capability_set(s, settings)) + return FALSE; } if (settings->ReceivedCapabilities[CAPSET_TYPE_SURFACE_COMMANDS]) { numberCapabilities++; - rdp_write_surface_commands_capability_set(s, settings); + if (!rdp_write_surface_commands_capability_set(s, settings)) + return FALSE; } if (settings->ReceivedCapabilities[CAPSET_TYPE_BITMAP_CODECS]) { numberCapabilities++; - rdp_write_bitmap_codecs_capability_set(s, settings); + if (!rdp_write_bitmap_codecs_capability_set(s, settings)) + return FALSE; } if (!settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE]) @@ -3894,7 +4023,8 @@ void rdp_write_confirm_active(wStream* s, rdpSettings* settings) if (settings->FrameAcknowledge) { numberCapabilities++; - rdp_write_frame_acknowledge_capability_set(s, settings); + if (!rdp_write_frame_acknowledge_capability_set(s, settings)) + return FALSE; } if (settings->ReceivedCapabilities[CAPSET_TYPE_BITMAP_CACHE_V3_CODEC_ID]) @@ -3902,7 +4032,8 @@ void rdp_write_confirm_active(wStream* s, rdpSettings* settings) if (settings->BitmapCacheV3CodecId != 0) { numberCapabilities++; - rdp_write_bitmap_cache_v3_codec_id_capability_set(s, settings); + if (!rdp_write_bitmap_cache_v3_codec_id_capability_set(s, settings)) + return FALSE; } } @@ -3923,6 +4054,7 @@ void rdp_write_confirm_active(wStream* s, rdpSettings* settings) #endif Stream_SetPosition(s, em); + return TRUE; } BOOL rdp_send_confirm_active(rdpRdp* rdp) @@ -3935,9 +4067,8 @@ BOOL rdp_send_confirm_active(rdpRdp* rdp) rdp_init_stream_pdu(rdp, s); - rdp_write_confirm_active(s, rdp->settings); - - status = rdp_send_pdu(rdp, s, PDU_TYPE_CONFIRM_ACTIVE, rdp->mcs->userId); + status = rdp_write_confirm_active(s, rdp->settings) && + rdp_send_pdu(rdp, s, PDU_TYPE_CONFIRM_ACTIVE, rdp->mcs->userId); Stream_Free(s, TRUE); diff --git a/libfreerdp/core/capabilities.h b/libfreerdp/core/capabilities.h index 06ed108..14c147d 100644 --- a/libfreerdp/core/capabilities.h +++ b/libfreerdp/core/capabilities.h @@ -169,10 +169,10 @@ BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId); BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s); -void rdp_write_demand_active(wStream* s, rdpSettings* settings); +BOOL rdp_write_demand_active(wStream* s, rdpSettings* settings); BOOL rdp_send_demand_active(rdpRdp* rdp); BOOL rdp_recv_confirm_active(rdpRdp* rdp, wStream* s); -void rdp_write_confirm_active(wStream* s, rdpSettings* settings); +BOOL rdp_write_confirm_active(wStream* s, rdpSettings* settings); BOOL rdp_send_confirm_active(rdpRdp* rdp); #endif /* __CAPABILITIES_H */ diff --git a/libfreerdp/core/certificate.c b/libfreerdp/core/certificate.c index 3fde935..9ce68f3 100644 --- a/libfreerdp/core/certificate.c +++ b/libfreerdp/core/certificate.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -398,18 +399,17 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific const BYTE* sigdata, int sigdatalen, wStream* s, UINT32 siglen) { int i, sum; - CryptoMd5 md5ctx; + WINPR_MD5_CTX md5ctx; BYTE sig[TSSK_KEY_LENGTH]; BYTE encsig[TSSK_KEY_LENGTH + 8]; - BYTE md5hash[CRYPTO_MD5_DIGEST_LENGTH]; + BYTE md5hash[WINPR_MD5_DIGEST_LENGTH]; - md5ctx = crypto_md5_init(); - - if (!md5ctx) - return FALSE; - - crypto_md5_update(md5ctx, sigdata, sigdatalen); - crypto_md5_final(md5ctx, md5hash); + if (!winpr_MD5_Init(&md5ctx)) + return FALSE; + if (!winpr_MD5_Update(&md5ctx, sigdata, sigdatalen)) + return FALSE; + if (!winpr_MD5_Final(&md5ctx, md5hash, sizeof(md5hash))) + return FALSE; Stream_Read(s, encsig, siglen); /* Last 8 bytes shall be all zero. */ @@ -662,54 +662,22 @@ BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* serv return ret; } -rdpRsaKey* key_new(const char* keyfile) +rdpRsaKey* key_new_from_content(const char *keycontent, const char *keyfile) { BIO* bio = NULL; - FILE* fp = NULL; RSA* rsa = NULL; - int length; - BYTE* buffer = NULL; rdpRsaKey* key = NULL; key = (rdpRsaKey*) calloc(1, sizeof(rdpRsaKey)); - if (!key) return NULL; - fp = fopen(keyfile, "r+b"); - - if (!fp) - { - WLog_ERR(TAG, "unable to open RSA key file %s: %s.", keyfile, strerror(errno)); - goto out_free; - } - - if (fseek(fp, 0, SEEK_END) < 0) - goto out_free; - if ((length = ftell(fp)) < 0) - goto out_free; - if (fseek(fp, 0, SEEK_SET) < 0) - goto out_free; - - buffer = (BYTE*) malloc(length); - - if (!buffer) - goto out_free; - - if (fread((void*) buffer, length, 1, fp) != 1) - goto out_free; - fclose(fp); - fp = NULL; - - bio = BIO_new_mem_buf((void*) buffer, length); - + bio = BIO_new_mem_buf((void *)keycontent, strlen(keycontent)); if (!bio) goto out_free; rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); BIO_free(bio); - free(buffer); - buffer = NULL; if (!rsa) { @@ -764,11 +732,50 @@ out_free_modulus: free(key->Modulus); out_free_rsa: RSA_free(rsa); +out_free: + free(key); + return NULL; +} + + +rdpRsaKey* key_new(const char* keyfile) +{ + FILE* fp = NULL; + int length; + char* buffer = NULL; + rdpRsaKey* key = NULL; + + fp = fopen(keyfile, "r+b"); + if (!fp) + { + WLog_ERR(TAG, "unable to open RSA key file %s: %s.", keyfile, strerror(errno)); + goto out_free; + } + + if (fseek(fp, 0, SEEK_END) < 0) + goto out_free; + if ((length = ftell(fp)) < 0) + goto out_free; + if (fseek(fp, 0, SEEK_SET) < 0) + goto out_free; + + buffer = (char *)malloc(length + 1); + if (!buffer) + goto out_free; + + if (fread((void*) buffer, length, 1, fp) != 1) + goto out_free; + fclose(fp); + buffer[length] = '\0'; + + key = key_new_from_content(buffer, keyfile); + free(buffer); + return key; + out_free: if (fp) fclose(fp); free(buffer); - free(key); return NULL; } diff --git a/libfreerdp/core/certificate.h b/libfreerdp/core/certificate.h index 6b3195f..a48701b 100644 --- a/libfreerdp/core/certificate.h +++ b/libfreerdp/core/certificate.h @@ -59,6 +59,7 @@ rdpCertificate* certificate_new(void); void certificate_free(rdpCertificate* certificate); rdpRsaKey* key_new(const char *keyfile); +rdpRsaKey* key_new_from_content(const char *keycontent, const char *keyfile); void key_free(rdpRsaKey* key); #define CERTIFICATE_TAG FREERDP_TAG("core.certificate") diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 5047aad..99b2e59 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -31,6 +31,7 @@ #include "transport.h" #include +#include #include #include @@ -312,8 +313,6 @@ BOOL rdp_client_disconnect(rdpRdp* rdp) { BOOL status; - ResetEvent(rdp->context->abortEvent); - if (rdp->settingsCopy) { freerdp_settings_free(rdp->settingsCopy); @@ -438,7 +437,7 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) if (!settings->ClientRandom) return FALSE; - crypto_nonce(settings->ClientRandom, settings->ClientRandomLength); + winpr_RAND(settings->ClientRandom, settings->ClientRandomLength); key_len = settings->RdpServerCertificate->cert_info.ModulusLength; mod = settings->RdpServerCertificate->cert_info.Modulus; exp = settings->RdpServerCertificate->cert_info.exponent; @@ -491,20 +490,26 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { - rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); + rdp->fips_encrypt = winpr_Cipher_New( WINPR_CIPHER_DES_EDE3_CBC, + WINPR_ENCRYPT, + rdp->fips_encrypt_key, + fips_ivec); if (!rdp->fips_encrypt) { WLog_ERR(TAG, "unable to allocate des3 encrypt key"); goto end; } - rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); + rdp->fips_decrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC, + WINPR_DECRYPT, + rdp->fips_decrypt_key, + fips_ivec); if (!rdp->fips_decrypt) { WLog_ERR(TAG, "unable to allocate des3 decrypt key"); goto end; } - rdp->fips_hmac = crypto_hmac_new(); + rdp->fips_hmac = calloc(1, sizeof(WINPR_HMAC_CTX)); if (!rdp->fips_hmac) { WLog_ERR(TAG, "unable to allocate fips hmac"); @@ -514,22 +519,27 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) goto end; } - rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); - if (!rdp->rc4_decrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 decrypt key"); + rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len); + rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len); + if (!rdp->rc4_decrypt_key || !rdp->rc4_encrypt_key) goto end; - } - rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); - if (!rdp->rc4_encrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 encrypt key"); - goto end; - } ret = TRUE; end: free(crypt_client_random); + if (!ret) + { + winpr_Cipher_Free(rdp->fips_decrypt); + winpr_Cipher_Free(rdp->fips_encrypt); + winpr_RC4_Free(rdp->rc4_decrypt_key); + winpr_RC4_Free(rdp->rc4_encrypt_key); + + rdp->fips_decrypt = NULL; + rdp->fips_encrypt = NULL; + rdp->rc4_decrypt_key = NULL; + rdp->rc4_encrypt_key = NULL; + } + return ret; } @@ -586,12 +596,12 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) if (rand_len != key_len + 8) { WLog_ERR(TAG, "invalid encrypted client random length"); - goto end2; + goto end; } crypt_client_random = calloc(1, rand_len); if (!crypt_client_random) - goto end2; + goto end; Stream_Read(s, crypt_client_random, rand_len); mod = rdp->settings->RdpServerRsaKey->Modulus; @@ -600,29 +610,33 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(client_random, rdp)) - { goto end; - } rdp->do_crypt = TRUE; if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { - rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); + rdp->fips_encrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC, + WINPR_ENCRYPT, + rdp->fips_encrypt_key, + fips_ivec); if (!rdp->fips_encrypt) { WLog_ERR(TAG, "unable to allocate des3 encrypt key"); goto end; } - rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); + rdp->fips_decrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC, + WINPR_DECRYPT, + rdp->fips_decrypt_key, + fips_ivec); if (!rdp->fips_decrypt) { WLog_ERR(TAG, "unable to allocate des3 decrypt key"); goto end; } - rdp->fips_hmac = crypto_hmac_new(); + rdp->fips_hmac = calloc(1, sizeof(WINPR_HMAC_CTX)); if (!rdp->fips_hmac) { WLog_ERR(TAG, "unable to allocate fips hmac"); @@ -632,25 +646,28 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) goto end; } - rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); - if (!rdp->rc4_decrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 decrypt key"); + rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len); + rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len); + if (!rdp->rc4_decrypt_key || rdp->rc4_encrypt_key) goto end; - } - rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); - if (!rdp->rc4_encrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 encrypt key"); - goto end; - } ret = TRUE; end: free(crypt_client_random); -end2: free(client_random); + if (!ret) + { + winpr_Cipher_Free(rdp->fips_encrypt); + winpr_Cipher_Free(rdp->fips_decrypt); + winpr_RC4_Free(rdp->rc4_encrypt_key); + winpr_RC4_Free(rdp->rc4_decrypt_key); + + rdp->fips_encrypt = NULL; + rdp->fips_decrypt = NULL; + rdp->rc4_encrypt_key = NULL; + rdp->rc4_decrypt_key = NULL; + } return ret; } diff --git a/libfreerdp/core/errconnect.c b/libfreerdp/core/errconnect.c index a52912b..cd983b4 100644 --- a/libfreerdp/core/errconnect.c +++ b/libfreerdp/core/errconnect.c @@ -38,7 +38,7 @@ "A configuration error prevented a connection to be established." #define ERRCONNECT_CONNECT_UNDEFINED_STRING \ - "A undefined connection error occured." + "A undefined connection error occurred." #define ERRCONNECT_POST_CONNECT_FAILED_STRING \ "The connection attempt was aborted due to post connect configuration errors." diff --git a/libfreerdp/core/errinfo.c b/libfreerdp/core/errinfo.c index 5820163..91b71d9 100644 --- a/libfreerdp/core/errinfo.c +++ b/libfreerdp/core/errinfo.c @@ -569,7 +569,7 @@ void rdp_print_errinfo(UINT32 code) { if (code == errInfo->code) { - WLog_ERR(TAG, "%s (0x%08X):%s", errInfo->name, code, errInfo->info); + WLog_INFO(TAG, "%s (0x%08X):%s", errInfo->name, code, errInfo->info); return; } diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index cce07fe..0f45f12 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -30,6 +30,7 @@ #include "transport.h" #include "connection.h" #include "message.h" +#include "buildflags.h" #include @@ -71,6 +72,7 @@ BOOL freerdp_connect(freerdp* instance) connectErrorCode = 0; freerdp_set_last_error(instance->context, FREERDP_ERROR_SUCCESS); clearChannelError(instance->context); + ResetEvent(instance->context->abortEvent); rdp = instance->context->rdp; settings = instance->settings; @@ -381,6 +383,7 @@ BOOL freerdp_reconnect(freerdp* instance) BOOL status; rdpRdp* rdp = instance->context->rdp; + ResetEvent(instance->context->abortEvent); status = rdp_client_reconnect(rdp); return status; @@ -395,7 +398,7 @@ BOOL freerdp_shall_disconnect(freerdp* instance) return TRUE; } -FREERDP_API BOOL freerdp_focus_required(freerdp* instance) +BOOL freerdp_focus_required(freerdp* instance) { rdpRdp* rdp; BOOL bRetCode = FALSE; @@ -438,13 +441,23 @@ const char* freerdp_get_version_string(void) const char* freerdp_get_build_date(void) { - static char build_date[64]; - - sprintf_s(build_date, sizeof(build_date), "%s %s", __DATE__, __TIME__); + static char build_date[] = __DATE__ " " __TIME__; return build_date; } +const char* freerdp_get_build_config(void) +{ + static const char build_config[] = + "Build configuration: " BUILD_CONFIG "\n" + "Build type: " BUILD_TYPE "\n" + "CFLAGS: " CFLAGS "\n" + "Compiler: " COMPILER_ID ", " COMPILER_VERSION "\n" + "Target architecture: " TARGET_ARCH "\n"; + + return build_config; +} + const char* freerdp_get_build_revision(void) { return GIT_REVISION; @@ -615,7 +628,7 @@ UINT32 freerdp_error_info(freerdp* instance) } void freerdp_set_error_info(rdpRdp* rdp, UINT32 error) { - rdp->errorInfo = error; + rdp_set_error_info(rdp, error); } UINT32 freerdp_get_last_error(rdpContext* context) @@ -765,19 +778,19 @@ void freerdp_free(freerdp* instance) free(instance); } -FREERDP_API ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount) { +ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount) { ULONG written = context->rdp->transport->written; if (resetCount) context->rdp->transport->written = 0; return written; } -FREERDP_API HANDLE getChannelErrorEventHandle(rdpContext* context) +HANDLE getChannelErrorEventHandle(rdpContext* context) { return context->channelErrorEvent; } -FREERDP_API BOOL checkChannelErrorEvent(rdpContext* context) +BOOL checkChannelErrorEvent(rdpContext* context) { if (WaitForSingleObject( context->channelErrorEvent, 0) == WAIT_OBJECT_0) { @@ -792,24 +805,24 @@ FREERDP_API BOOL checkChannelErrorEvent(rdpContext* context) * * @return 0 on success, otherwise a Win32 error code */ -FREERDP_API UINT getChannelError(rdpContext* context) +UINT getChannelError(rdpContext* context) { return context->channelErrorNum; } -FREERDP_API const char* getChannelErrorDescription(rdpContext* context) +const char* getChannelErrorDescription(rdpContext* context) { return context->errorDescription; } -FREERDP_API void clearChannelError(rdpContext* context) +void clearChannelError(rdpContext* context) { context->channelErrorNum = 0; memset(context->errorDescription, 0, 500); ResetEvent(context->channelErrorEvent); } -FREERDP_API void setChannelError(rdpContext* context, UINT errorNum, char* description) +void setChannelError(rdpContext* context, UINT errorNum, char* description) { context->channelErrorNum = errorNum; strncpy(context->errorDescription, description, 499); diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c index 175aab3..f6f6801 100644 --- a/libfreerdp/core/gateway/ncacn_http.c +++ b/libfreerdp/core/gateway/ncacn_http.c @@ -29,8 +29,6 @@ #include #include -#include - #define TAG FREERDP_TAG("core.gateway.ntlm") wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, const char* method, int contentLength, SecBuffer* ntlmToken) diff --git a/libfreerdp/core/gateway/ntlm.c b/libfreerdp/core/gateway/ntlm.c index c9795b6..ce6925b 100644 --- a/libfreerdp/core/gateway/ntlm.c +++ b/libfreerdp/core/gateway/ntlm.c @@ -28,7 +28,6 @@ #include #include -#include #include "http.h" diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c index 4c355be..3f3bab8 100644 --- a/libfreerdp/core/gateway/rdg.c +++ b/libfreerdp/core/gateway/rdg.c @@ -198,14 +198,22 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) int i; wStream* s; BOOL status; - char* clientName = rdg->settings->ClientHostname; - UINT16 clientNameLen = strlen(clientName) + 1; - UINT32 packetSize = 12 + clientNameLen * 2; + WCHAR* clientName = NULL; + UINT16 clientNameLen; + UINT32 packetSize; + clientNameLen = ConvertToUnicode(CP_UTF8, 0, rdg->settings->ClientHostname, -1, &clientName, 0); + if (!clientName) + return FALSE; + + packetSize = 12 + clientNameLen * 2 + sizeof(WCHAR); s = Stream_New(NULL, packetSize); if (!s) + { + free(clientName); return FALSE; + } Stream_Write_UINT16(s, PKT_TYPE_TUNNEL_AUTH); /* Type (2 bytes) */ Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */ @@ -215,15 +223,16 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) Stream_Write_UINT16(s, clientNameLen * 2); /* Client name string length */ for (i = 0; i < clientNameLen; i++) - { Stream_Write_UINT16(s, clientName[i]); - } + + Stream_Write_UINT16(s, 0); Stream_SealLength(s); status = rdg_write_packet(rdg, s); Stream_Free(s, TRUE); + free(clientName); if (status) { diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c index 16f4af1..d7309b9 100644 --- a/libfreerdp/core/gateway/rpc.c +++ b/libfreerdp/core/gateway/rpc.c @@ -30,7 +30,6 @@ #include -#include #include #ifdef HAVE_VALGRIND_MEMCHECK_H diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c index 31edc86..df939b9 100644 --- a/libfreerdp/core/gateway/rts.c +++ b/libfreerdp/core/gateway/rts.c @@ -22,6 +22,7 @@ #endif #include +#include #include #include @@ -422,7 +423,7 @@ int rts_ping_traffic_sent_notify_command_write(BYTE* buffer, UINT32 PingTrafficS void rts_generate_cookie(BYTE* cookie) { - RAND_pseudo_bytes(cookie, 16); + winpr_RAND(cookie, 16); } /* CONN/A Sequence */ diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index 18bf20b..2d63fa7 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -24,6 +24,7 @@ #endif #include +#include #include @@ -591,9 +592,8 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL); Stream_Seek(s, 32); - sprintf_s(settings->ClientHostname, 31, "%s", str); - settings->ClientHostname[31] = 0; - free(str); + free(settings->ClientHostname); + settings->ClientHostname = str; str = NULL; Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType (4 bytes) */ @@ -649,8 +649,8 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL); Stream_Seek(s, 64); /* clientDigProductId (64 bytes) */ - sprintf_s(settings->ClientProductId, 32, "%s", str); - free(str); + free(settings->ClientProductId); + settings->ClientProductId = str; blockLength -= 64; if (blockLength < 1) @@ -761,6 +761,9 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) if (settings->SupportDynamicTimeZone) settings->SupportDynamicTimeZone = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE) ? TRUE : FALSE; + if (settings->SupportMonitorLayoutPdu) + settings->SupportMonitorLayoutPdu = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) ? TRUE : FALSE; + if (!(earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE)) connectionType = 0; @@ -866,6 +869,9 @@ void gcc_write_client_core_data(wStream* s, rdpMcs* mcs) if (settings->SupportDynamicTimeZone) earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE; + if (settings->SupportMonitorLayoutPdu) + earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU; + Stream_Write_UINT16(s, highColorDepth); /* highColorDepth */ Stream_Write_UINT16(s, supportedColorDepths); /* supportedColorDepths */ @@ -1173,7 +1179,7 @@ const BYTE tssk_exponent[] = BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs) { - CryptoMd5 md5; + WINPR_MD5_CTX md5; BYTE* sigData; int expLen, keyLen, sigDataLen; BYTE encryptedSignature[TSSK_KEY_LENGTH]; @@ -1343,7 +1349,7 @@ BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs) settings->ServerRandomLength = serverRandomLen; settings->ServerRandom = (BYTE*) malloc(serverRandomLen); - crypto_nonce(settings->ServerRandom, serverRandomLen); + winpr_RAND(settings->ServerRandom, serverRandomLen); Stream_Write(s, settings->ServerRandom, serverRandomLen); sigData = Stream_Pointer(s); @@ -1370,15 +1376,12 @@ BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs) memcpy(signature, initial_signature, sizeof(initial_signature)); - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, sigData, sigDataLen)) + return FALSE; + if (!winpr_MD5_Final(&md5, signature, sizeof(signature))) return FALSE; - } - - crypto_md5_update(md5, sigData, sigDataLen); - crypto_md5_final(md5, signature); crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH, tssk_modulus, tssk_privateExponent, encryptedSignature); @@ -1594,6 +1597,12 @@ BOOL gcc_read_client_monitor_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) Stream_Read_UINT32(s, flags); /* flags */ Stream_Read_UINT32(s, monitorCount); /* monitorCount */ + if (monitorCount > settings->MonitorDefArraySize) + { + WLog_ERR(TAG, "too many announced monitors(%d), clamping to %d", monitorCount, settings->MonitorDefArraySize); + monitorCount = settings->MonitorDefArraySize; + } + if (((blockLength - 8) / 20) < monitorCount) return FALSE; diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index 6fbff79..e7b2d46 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "timezone.h" @@ -44,7 +45,7 @@ static const char* const INFO_TYPE_LOGON_STRINGS[4] = BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp) { - CryptoHmac hmac; + WINPR_HMAC_CTX hmac; BYTE ClientRandom[32]; BYTE AutoReconnectRandom[32]; ARC_SC_PRIVATE_PACKET* serverCookie; @@ -67,18 +68,14 @@ BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp) if (settings->SelectedProtocol == PROTOCOL_RDP) CopyMemory(ClientRandom, settings->ClientRandom, settings->ClientRandomLength); - hmac = crypto_hmac_new(); - - if (!hmac) - return FALSE; - /* SecurityVerifier = HMAC_MD5(AutoReconnectRandom, ClientRandom) */ - if (!crypto_hmac_md5_init(hmac, AutoReconnectRandom, 16)) + if (!winpr_HMAC_Init(&hmac, WINPR_MD_MD5, AutoReconnectRandom, 16)) + return FALSE; + if (!winpr_HMAC_Update(&hmac, ClientRandom, 32)) + return FALSE; + if (!winpr_HMAC_Final(&hmac, clientCookie->securityVerifier, 16)) return FALSE; - crypto_hmac_update(hmac, ClientRandom, 32); - crypto_hmac_final(hmac, clientCookie->securityVerifier, 16); - crypto_hmac_free(hmac); return TRUE; } @@ -90,7 +87,7 @@ BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp) * @param settings settings */ -BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s) +BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s, logon_info_ex *info) { BYTE* p; ARC_SC_PRIVATE_PACKET* autoReconnectCookie; @@ -102,16 +99,16 @@ BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s) return FALSE; Stream_Read_UINT32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */ - Stream_Read_UINT32(s, autoReconnectCookie->version); /* Version (4 bytes) */ - Stream_Read_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */ - Stream_Read(s, autoReconnectCookie->arcRandomBits, 16); /* ArcRandomBits (16 bytes) */ - if (autoReconnectCookie->cbLen != 28) { WLog_ERR(TAG, "ServerAutoReconnectCookie.cbLen != 28"); return FALSE; } + Stream_Read_UINT32(s, autoReconnectCookie->version); /* Version (4 bytes) */ + Stream_Read_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */ + Stream_Read(s, autoReconnectCookie->arcRandomBits, 16); /* ArcRandomBits (16 bytes) */ + p = autoReconnectCookie->arcRandomBits; WLog_DBG(TAG, "ServerAutoReconnectCookie: Version: %d LogonId: %d SecurityVerifier: " @@ -120,6 +117,9 @@ BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s) p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); + info->LogonId = autoReconnectCookie->logonId; + CopyMemory(info->ArcRandomBits, p, 16); + if ((settings->PrintReconnectCookie) && (autoReconnectCookie->cbLen > 0)) { char* base64; @@ -660,31 +660,46 @@ BOOL rdp_send_client_info(rdpRdp* rdp) return status; } -BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s) +BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s, logon_info *info) { UINT32 cbDomain; UINT32 cbUserName; - UINT32 SessionId; if (Stream_GetRemainingLength(s) < 576) return FALSE; Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */ + if (cbDomain > 52) + return FALSE; + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE); + if (!info->domain) + return FALSE; Stream_Seek(s, 52); /* domain (52 bytes) */ - Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ - Stream_Seek(s, 512); /* userName (512 bytes) */ - Stream_Read_UINT32(s, SessionId); /* SessionId (4 bytes) */ - WLog_DBG(TAG, "LogonInfoV1: SessionId: 0x%04X", SessionId); + Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ + if (cbUserName > 512) + goto error_username; + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE); + if (!info->username) + goto error_username; + Stream_Seek(s, 512); /* userName (512 bytes) */ + + Stream_Read_UINT32(s, info->sessionId); /* SessionId (4 bytes) */ + + WLog_DBG(TAG, "LogonInfoV1: SessionId: 0x%04X", info->sessionId); return TRUE; + +error_username: + free(info->domain); + info->domain = NULL; + return FALSE; } -BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s) +BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info *info) { UINT16 Version; UINT32 Size; - UINT32 SessionId; UINT32 cbDomain; UINT32 cbUserName; @@ -693,7 +708,7 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s) Stream_Read_UINT16(s, Version); /* Version (2 bytes) */ Stream_Read_UINT32(s, Size); /* Size (4 bytes) */ - Stream_Read_UINT32(s, SessionId); /* SessionId (4 bytes) */ + Stream_Read_UINT32(s, info->sessionId); /* SessionId (4 bytes) */ Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */ Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ Stream_Seek(s, 558); /* pad (558 bytes) */ @@ -701,10 +716,21 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s) if (Stream_GetRemainingLength(s) < (cbDomain + cbUserName)) return FALSE; + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE); + if (!info->domain) + return FALSE; Stream_Seek(s, cbDomain); /* domain */ + + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE); + if (!info->username) + { + free(info->domain); + info->domain = NULL; + return FALSE; + } Stream_Seek(s, cbUserName); /* userName */ - WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X", SessionId); + WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X", info->sessionId); return TRUE; } @@ -721,7 +747,7 @@ BOOL rdp_recv_logon_plain_notify(rdpRdp* rdp, wStream* s) return TRUE; } -BOOL rdp_recv_logon_error_info(rdpRdp* rdp, wStream* s) +BOOL rdp_recv_logon_error_info(rdpRdp* rdp, wStream* s, logon_info_ex *info) { UINT32 errorNotificationType; UINT32 errorNotificationData; @@ -737,10 +763,12 @@ BOOL rdp_recv_logon_error_info(rdpRdp* rdp, wStream* s) IFCALL(rdp->instance->LogonErrorInfo, rdp->instance, errorNotificationData, errorNotificationType); + info->ErrorNotificationType = errorNotificationType; + info->ErrorNotificationData = errorNotificationData; return TRUE; } -BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s) +BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s, logon_info_ex *info) { UINT32 cbFieldData; UINT32 fieldsPresent; @@ -752,7 +780,7 @@ BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s) Stream_Read_UINT16(s, Length); /* Length (2 bytes) */ Stream_Read_UINT32(s, fieldsPresent); /* fieldsPresent (4 bytes) */ - if (Stream_GetRemainingLength(s) < (Length - 6)) + if ((Length < 6) || (Stream_GetRemainingLength(s) < (Length - 6))) return FALSE; WLog_DBG(TAG, "LogonInfoExtended: fieldsPresent: 0x%04X", fieldsPresent); @@ -764,20 +792,28 @@ BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s) if (Stream_GetRemainingLength(s) < 4) return FALSE; + info->haveCookie = TRUE; Stream_Read_UINT32(s, cbFieldData); /* cbFieldData (4 bytes) */ - if (!rdp_read_server_auto_reconnect_cookie(rdp, s)) + if (Stream_GetRemainingLength(s) < cbFieldData) + return FALSE; + + if (!rdp_read_server_auto_reconnect_cookie(rdp, s, info)) return FALSE; } if (fieldsPresent & LOGON_EX_LOGONERRORS) { + info->haveErrorInfo = TRUE; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, cbFieldData); /* cbFieldData (4 bytes) */ - if (!rdp_recv_logon_error_info(rdp, s)) + if (Stream_GetRemainingLength(s) < cbFieldData) + return FALSE; + + if (!rdp_recv_logon_error_info(rdp, s, info)) return FALSE; } @@ -792,7 +828,11 @@ BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s) BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s) { UINT32 infoType; - BOOL status = FALSE; + BOOL status; + logon_info logonInfo; + logon_info_ex logonInfoEx; + rdpContext *context = rdp->context; + rdpUpdate *update = rdp->context->update; if (Stream_GetRemainingLength(s) < 4) return FALSE; @@ -802,22 +842,39 @@ BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s) switch (infoType) { case INFO_TYPE_LOGON: - status = rdp_recv_logon_info_v1(rdp, s); + ZeroMemory(&logonInfo, sizeof(logonInfo)); + status = rdp_recv_logon_info_v1(rdp, s, &logonInfo); + if (status && update->SaveSessionInfo) + status = update->SaveSessionInfo(context, infoType, &logonInfo); + free(logonInfo.domain); + free(logonInfo.username); break; case INFO_TYPE_LOGON_LONG: - status = rdp_recv_logon_info_v2(rdp, s); + ZeroMemory(&logonInfo, sizeof(logonInfo)); + status = rdp_recv_logon_info_v2(rdp, s, &logonInfo); + if (status && update->SaveSessionInfo) + status = update->SaveSessionInfo(context, infoType, &logonInfo); + free(logonInfo.domain); + free(logonInfo.username); break; case INFO_TYPE_LOGON_PLAIN_NOTIFY: status = rdp_recv_logon_plain_notify(rdp, s); + if (status && update->SaveSessionInfo) + status = update->SaveSessionInfo(context, infoType, NULL); break; case INFO_TYPE_LOGON_EXTENDED_INF: - status = rdp_recv_logon_info_extended(rdp, s); + ZeroMemory(&logonInfoEx, sizeof(logonInfoEx)); + status = rdp_recv_logon_info_extended(rdp, s, &logonInfoEx); + if (status && update->SaveSessionInfo) + status = update->SaveSessionInfo(context, infoType, &logonInfoEx); break; default: + WLog_ERR(TAG, "Unhandled saveSessionInfo type 0x%x", infoType); + status = TRUE; break; } @@ -830,3 +887,174 @@ BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s) return status; } +static BOOL rdp_write_logon_info_v1(wStream *s, logon_info *info) +{ + int sz = 4 + 52 + 4 + 512 + 4; + int len; + WCHAR *wString = NULL; + + if (!Stream_EnsureRemainingCapacity(s, sz)) + return FALSE; + + /* domain */ + len = ConvertToUnicode(CP_UTF8, 0, info->domain, -1, &wString, 0); + if (len < 0) + return FALSE; + len *= 2; + if (len > 52) + return FALSE; + + Stream_Write_UINT32(s, len); + Stream_Write(s, wString, len); + Stream_Seek(s, 52 - len); + free(wString); + + /* username */ + len = ConvertToUnicode(CP_UTF8, 0, info->username, -1, &wString, 0); + if (len < 0) + return FALSE; + + len *= 2; + if (len > 512) + return FALSE; + + Stream_Write_UINT32(s, len); + Stream_Write(s, wString, len); + Stream_Seek(s, 512 - len); + free(wString); + + /* sessionId */ + Stream_Write_UINT32(s, info->sessionId); + + return TRUE; +} + +static BOOL rdp_write_logon_info_v2(wStream *s, logon_info *info) +{ + int Size = 2 + 4 + 4 + 4 + 4 + 558; + int domainLen, usernameLen, len; + WCHAR *wString; + + if (!Stream_EnsureRemainingCapacity(s, Size)) + return FALSE; + + Stream_Write_UINT16(s, SAVE_SESSION_PDU_VERSION_ONE); + Stream_Write_UINT32(s, Size); + Stream_Write_UINT32(s, info->sessionId); + + domainLen = strlen(info->domain); + Stream_Write_UINT32(s, (domainLen + 1) * 2); + + usernameLen = strlen(info->username); + Stream_Write_UINT32(s, (usernameLen + 1) * 2); + + Stream_Seek(s, 558); + + len = ConvertToUnicode(CP_UTF8, 0, info->domain, -1, &wString, 0); + if (len < 0) + return FALSE; + + Stream_Write(s, wString, len * 2); + free(wString); + + len = ConvertToUnicode(CP_UTF8, 0, info->username, -1, &wString, 0); + if (len < 0) + return FALSE; + + Stream_Write(s, wString, len * 2); + free(wString); + return TRUE; +} + +static BOOL rdp_write_logon_info_plain(wStream *s) +{ + if (!Stream_EnsureRemainingCapacity(s, 576)) + return FALSE; + + Stream_Seek(s, 576); + return TRUE; +} + +static BOOL rdp_write_logon_info_ex(wStream *s, logon_info_ex *info) +{ + UINT32 FieldsPresent = 0; + UINT16 Size = 2 + 4 + 570; + + if (info->haveCookie) + { + FieldsPresent |= LOGON_EX_AUTORECONNECTCOOKIE; + Size += 28; + } + + if (info->haveErrorInfo) + { + FieldsPresent |= LOGON_EX_LOGONERRORS; + Size += 8; + } + + if (!Stream_EnsureRemainingCapacity(s, Size)) + return FALSE; + + Stream_Write_UINT16(s, Size); + Stream_Write_UINT32(s, FieldsPresent); + + if (info->haveCookie) + { + Stream_Write_UINT32(s, 28); /* cbFieldData (4 bytes) */ + + Stream_Write_UINT32(s, 28); /* cbLen (4 bytes) */ + Stream_Write_UINT32(s, AUTO_RECONNECT_VERSION_1); /* Version (4 bytes) */ + Stream_Write_UINT32(s, info->LogonId); /* LogonId (4 bytes) */ + Stream_Write(s, info->ArcRandomBits, 16); /* ArcRandomBits (16 bytes) */ + } + + if (info->haveErrorInfo) + { + Stream_Write_UINT32(s, 8); /* cbFieldData (4 bytes) */ + + Stream_Write_UINT32(s, info->ErrorNotificationType); /* ErrorNotificationType (4 bytes) */ + Stream_Write_UINT32(s, info->ErrorNotificationData); /* ErrorNotificationData (4 bytes) */ + } + + Stream_Seek(s, 570); + return TRUE; +} + +BOOL rdp_send_save_session_info(rdpContext *context, UINT32 type, void *data) +{ + wStream *s; + BOOL status; + rdpRdp *rdp = context->rdp; + + s = rdp_data_pdu_init(rdp); + if (!s) + return FALSE; + + Stream_Write_UINT32(s, type); + + switch (type) + { + case INFO_TYPE_LOGON: + status = rdp_write_logon_info_v1(s, (logon_info *)data); + break; + case INFO_TYPE_LOGON_LONG: + status = rdp_write_logon_info_v2(s, (logon_info *)data); + break; + case INFO_TYPE_LOGON_PLAIN_NOTIFY: + status = rdp_write_logon_info_plain(s); + break; + case INFO_TYPE_LOGON_EXTENDED_INF: + status = rdp_write_logon_info_ex(s, (logon_info_ex *)data); + break; + default: + WLog_ERR(TAG, "saveSessionInfo type 0x%x not handled", type); + status = FALSE; + break; + } + + if (status) + status = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SAVE_SESSION_INFO, rdp->mcs->userId); + else + Stream_Free(s, TRUE); + return status; +} diff --git a/libfreerdp/core/info.h b/libfreerdp/core/info.h index 82bc9da..631fbc7 100644 --- a/libfreerdp/core/info.h +++ b/libfreerdp/core/info.h @@ -26,11 +26,6 @@ #include -#define INFO_TYPE_LOGON 0x00000000 -#define INFO_TYPE_LOGON_LONG 0x00000001 -#define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002 -#define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003 - /* Client Address Family */ #define ADDRESS_FAMILY_INET 0x0002 #define ADDRESS_FAMILY_INET6 0x0017 @@ -56,23 +51,13 @@ #define INFO_VIDEO_DISABLE 0x00400000 #define INFO_HIDEF_RAIL_SUPPORTED 0x02000000 -/* Logon Information Types */ -#define INFO_TYPE_LOGON 0x00000000 -#define INFO_TYPE_LOGON_LONG 0x00000001 -#define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002 -#define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003 - /* Extended Logon Info */ #define LOGON_EX_AUTORECONNECTCOOKIE 0x00000001 #define LOGON_EX_LOGONERRORS 0x00000002 -/* Logon Error Info */ -#define LOGON_FAILED_BAD_PASSWORD 0x00000000 -#define LOGON_FAILED_UPDATE_PASSWORD 0x00000001 -#define LOGON_FAILED_OTHER 0x00000002 -#define LOGON_WARNING 0x00000003 +#define SAVE_SESSION_PDU_VERSION_ONE 0x0001 + -BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s); BOOL rdp_read_client_auto_reconnect_cookie(rdpRdp* rdp, wStream* s); void rdp_write_client_auto_reconnect_cookie(rdpRdp* rdp, wStream* s); void rdp_write_auto_reconnect_cookie(rdpRdp* rdp, wStream* s); @@ -83,5 +68,6 @@ void rdp_write_info_packet(rdpRdp* rdp, wStream* s); BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s); BOOL rdp_send_client_info(rdpRdp* rdp); BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s); +BOOL rdp_send_save_session_info(rdpContext *context, UINT32 type, void *data); #endif /* __INFO_H */ diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index 23de184..055a2dc 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -23,6 +23,7 @@ #endif #include +#include #include #include "redirection.h" @@ -328,10 +329,10 @@ void license_generate_randoms(rdpLicense* license) ZeroMemory(license->ClientRandom, CLIENT_RANDOM_LENGTH); /* ClientRandom */ ZeroMemory(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */ #ifndef LICENSE_NULL_CLIENT_RANDOM - crypto_nonce(license->ClientRandom, CLIENT_RANDOM_LENGTH); /* ClientRandom */ + winpr_RAND(license->ClientRandom, CLIENT_RANDOM_LENGTH); /* ClientRandom */ #endif #ifndef LICENSE_NULL_PREMASTER_SECRET - crypto_nonce(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */ + winpr_RAND(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */ #endif } @@ -384,22 +385,19 @@ BOOL license_generate_keys(rdpLicense* license) BOOL license_generate_hwid(rdpLicense* license) { - CryptoMd5 md5; + WINPR_MD5_CTX md5; BYTE macAddress[6]; ZeroMemory(macAddress, sizeof(macAddress)); ZeroMemory(license->HardwareId, HWID_LENGTH); - md5 = crypto_md5_init(); - - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, macAddress, sizeof(macAddress))) + return FALSE; + if (!winpr_MD5_Final(&md5, &license->HardwareId[HWID_PLATFORM_ID_LENGTH], WINPR_MD5_DIGEST_LENGTH)) return FALSE; - } - crypto_md5_update(md5, macAddress, sizeof(macAddress)); - crypto_md5_final(md5, &license->HardwareId[HWID_PLATFORM_ID_LENGTH]); return TRUE; } @@ -460,28 +458,23 @@ BOOL license_encrypt_premaster_secret(rdpLicense* license) BOOL license_decrypt_platform_challenge(rdpLicense* license) { - CryptoRc4 rc4; + BOOL rc; + WINPR_RC4_CTX* rc4; license->PlatformChallenge->data = (BYTE *)malloc(license->EncryptedPlatformChallenge->length); if (!license->PlatformChallenge->data) return FALSE; license->PlatformChallenge->length = license->EncryptedPlatformChallenge->length; - rc4 = crypto_rc4_init(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH); - if (!rc4) - { - WLog_ERR(TAG, "unable to allocate a rc4"); - free(license->PlatformChallenge->data); - license->PlatformChallenge->data = NULL; + if ((rc4 = winpr_RC4_New(license->LicensingEncryptionKey, + LICENSING_ENCRYPTION_KEY_LENGTH)) == NULL) return FALSE; - } - - crypto_rc4(rc4, license->EncryptedPlatformChallenge->length, + rc = winpr_RC4_Update(rc4, license->EncryptedPlatformChallenge->length, license->EncryptedPlatformChallenge->data, license->PlatformChallenge->data); - crypto_rc4_free(rc4); - return TRUE; + winpr_RC4_Free(rc4); + return rc; } /** @@ -1025,7 +1018,7 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license) wStream* s; int length; BYTE* buffer; - CryptoRc4 rc4; + WINPR_RC4_CTX* rc4; BYTE mac_data[16]; BOOL status; @@ -1046,19 +1039,23 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license) if (!status) return FALSE; - rc4 = crypto_rc4_init(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH); + rc4 = winpr_RC4_New(license->LicensingEncryptionKey, + LICENSING_ENCRYPTION_KEY_LENGTH); if (!rc4) - { - WLog_ERR(TAG, "unable to allocate a rc4"); return FALSE; - } buffer = (BYTE*) malloc(HWID_LENGTH); if (!buffer) return FALSE; - crypto_rc4(rc4, HWID_LENGTH, license->HardwareId, buffer); - crypto_rc4_free(rc4); + status = winpr_RC4_Update(rc4, HWID_LENGTH, license->HardwareId, buffer); + winpr_RC4_Free(rc4); + if (!status) + { + free(buffer); + return FALSE; + } + license->EncryptedHardwareId->type = BB_DATA_BLOB; license->EncryptedHardwareId->data = buffer; license->EncryptedHardwareId->length = HWID_LENGTH; diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c index 67fcb63..7cb6209 100644 --- a/libfreerdp/core/nego.c +++ b/libfreerdp/core/nego.c @@ -1086,7 +1086,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego) settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } - if (!settings->RdpServerRsaKey && !settings->RdpKeyFile) + if (!settings->RdpServerRsaKey && !settings->RdpKeyFile && !settings->RdpKeyContent) { WLog_ERR(TAG, "Missing server certificate"); return FALSE; diff --git a/libfreerdp/core/nla.h b/libfreerdp/core/nla.h index 774bcc9..b1afeba 100644 --- a/libfreerdp/core/nla.h +++ b/libfreerdp/core/nla.h @@ -27,6 +27,7 @@ typedef struct rdp_nla rdpNla; #include #include +#include #include #include @@ -75,7 +76,7 @@ struct rdp_nla SecBuffer authInfo; SecBuffer PublicKey; SecBuffer tsCredentials; - CryptoRc4 rc4SealState; + WINPR_RC4_CTX rc4SealState; LPTSTR ServicePrincipalName; SEC_WINNT_AUTH_IDENTITY* identity; PSecurityFunctionTable table; diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 84b4dc9..8318c4d 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -219,13 +219,21 @@ static BOOL freerdp_peer_initialize(freerdp_peer* client) if (settings->RdpKeyFile) { settings->RdpServerRsaKey = key_new(settings->RdpKeyFile); - if (!settings->RdpServerRsaKey) { WLog_ERR(TAG, "invalid RDP key file %s", settings->RdpKeyFile); return FALSE; } } + else if (settings->RdpKeyContent) + { + settings->RdpServerRsaKey = key_new_from_content(settings->RdpKeyContent, NULL); + if (!settings->RdpServerRsaKey) + { + WLog_ERR(TAG, "invalid RDP key content"); + return FALSE; + } + } return TRUE; } diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index f49ae99..61a44dc 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -204,8 +204,7 @@ static int rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header) int rdp_init_stream(rdpRdp* rdp, wStream* s) { Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH); - rdp_security_stream_init(rdp, s, FALSE); - return 0; + return rdp_security_stream_init(rdp, s, FALSE); } wStream* rdp_send_stream_init(rdpRdp* rdp) @@ -340,10 +339,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId) return FALSE; if (!rdp->instance) - { - freerdp_abort_connect(rdp->instance); return FALSE; - } context = rdp->instance->context; @@ -363,7 +359,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId) rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT); } - WLog_ERR(TAG, "DisconnectProviderUltimatum: reason: %d", reason); + WLog_DBG(TAG, "DisconnectProviderUltimatum: reason: %d", reason); freerdp_abort_connect(rdp->instance); EventArgsInit(&e, "freerdp"); @@ -671,8 +667,7 @@ BOOL rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, wStream* s) return FALSE; Stream_Read_UINT32(s, errorInfo); /* errorInfo (4 bytes) */ - rdp_set_error_info(rdp, errorInfo); - return TRUE; + return rdp_set_error_info(rdp, errorInfo); } BOOL rdp_recv_server_auto_reconnect_status_pdu(rdpRdp* rdp, wStream* s) @@ -706,13 +701,14 @@ BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s) UINT32 monitorCount; MONITOR_DEF* monitor; MONITOR_DEF* monitorDefArray; + BOOL ret = TRUE; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, monitorCount); /* monitorCount (4 bytes) */ - if (Stream_GetRemainingLength(s) < (monitorCount * 20)) + if ((Stream_GetRemainingLength(s) / 20) < monitorCount) return FALSE; monitorDefArray = (MONITOR_DEF*) calloc(monitorCount, sizeof(MONITOR_DEF)); @@ -720,9 +716,8 @@ BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s) if (!monitorDefArray) return FALSE; - for (index = 0; index < monitorCount; index++) + for (monitor = monitorDefArray, index = 0; index < monitorCount; index++, monitor++) { - monitor = &(monitorDefArray[index]); Stream_Read_UINT32(s, monitor->left); /* left (4 bytes) */ Stream_Read_UINT32(s, monitor->top); /* top (4 bytes) */ Stream_Read_UINT32(s, monitor->right); /* right (4 bytes) */ @@ -730,27 +725,30 @@ BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s) Stream_Read_UINT32(s, monitor->flags); /* flags (4 bytes) */ } + IFCALLRET(rdp->update->RemoteMonitors, ret, rdp->context, monitorCount, monitorDefArray); + free(monitorDefArray); - return TRUE; + return ret; } -BOOL rdp_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount, MONITOR_DEF* monitorDefArray) +BOOL rdp_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount, const rdpMonitor* monitorDefArray) { UINT32 index; - MONITOR_DEF* monitor; + const rdpMonitor* monitor; + if (!Stream_EnsureRemainingCapacity(s, 4 + (monitorCount * 20))) return FALSE; + Stream_Write_UINT32(s, monitorCount); /* monitorCount (4 bytes) */ - for (index = 0; index < monitorCount; index++) + for (index = 0, monitor = monitorDefArray; index < monitorCount; index++, monitor++) { - monitor = &(monitorDefArray[index]); - Stream_Write_UINT32(s, monitor->left); /* left (4 bytes) */ - Stream_Write_UINT32(s, monitor->top); /* top (4 bytes) */ - Stream_Write_UINT32(s, monitor->right); /* right (4 bytes) */ - Stream_Write_UINT32(s, monitor->bottom); /* bottom (4 bytes) */ - Stream_Write_UINT32(s, monitor->flags); /* flags (4 bytes) */ + Stream_Write_UINT32(s, monitor->x); /* left (4 bytes) */ + Stream_Write_UINT32(s, monitor->y); /* top (4 bytes) */ + Stream_Write_UINT32(s, monitor->x + monitor->width - 1); /* right (4 bytes) */ + Stream_Write_UINT32(s, monitor->y + monitor->height - 1); /* bottom (4 bytes) */ + Stream_Write_UINT32(s, monitor->is_primary ? 0x01 : 0x00); /* flags (4 bytes) */ } return TRUE; @@ -1412,6 +1410,8 @@ BOOL rdp_send_error_info(rdpRdp* rdp) return TRUE; s = rdp_data_pdu_init(rdp); + if (!s) + return FALSE; Stream_Write_UINT32(s, rdp->errorInfo); /* error id (4 bytes) */ @@ -1590,31 +1590,31 @@ void rdp_reset(rdpRdp* rdp) if (rdp->rc4_decrypt_key) { - crypto_rc4_free(rdp->rc4_decrypt_key); + winpr_RC4_Free(rdp->rc4_decrypt_key); rdp->rc4_decrypt_key = NULL; } if (rdp->rc4_encrypt_key) { - crypto_rc4_free(rdp->rc4_encrypt_key); + winpr_RC4_Free(rdp->rc4_encrypt_key); rdp->rc4_encrypt_key = NULL; } if (rdp->fips_encrypt) { - crypto_des3_free(rdp->fips_encrypt); + winpr_Cipher_Free(rdp->fips_encrypt); rdp->fips_encrypt = NULL; } if (rdp->fips_decrypt) { - crypto_des3_free(rdp->fips_decrypt); + winpr_Cipher_Free(rdp->fips_decrypt); rdp->fips_decrypt = NULL; } if (rdp->fips_hmac) { - crypto_hmac_free(rdp->fips_hmac); + free(rdp->fips_hmac); rdp->fips_hmac = NULL; } @@ -1661,11 +1661,11 @@ void rdp_free(rdpRdp* rdp) { if (rdp) { - crypto_rc4_free(rdp->rc4_decrypt_key); - crypto_rc4_free(rdp->rc4_encrypt_key); - crypto_des3_free(rdp->fips_encrypt); - crypto_des3_free(rdp->fips_decrypt); - crypto_hmac_free(rdp->fips_hmac); + winpr_RC4_Free(rdp->rc4_decrypt_key); + winpr_RC4_Free(rdp->rc4_encrypt_key); + winpr_Cipher_Free(rdp->fips_encrypt); + winpr_Cipher_Free(rdp->fips_decrypt); + free(rdp->fips_hmac); freerdp_settings_free(rdp->settings); freerdp_settings_free(rdp->settingsCopy); transport_free(rdp->transport); diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index f756220..ef8e0dc 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -51,6 +51,7 @@ #include #include +#include /* Security Header Flags */ #define SEC_EXCHANGE_PKT 0x0001 @@ -147,15 +148,15 @@ struct rdp_rdp rdpAutoDetect* autodetect; rdpHeartbeat* heartbeat; rdpMultitransport* multitransport; - struct crypto_rc4_struct* rc4_decrypt_key; + WINPR_RC4_CTX* rc4_decrypt_key; int decrypt_use_count; int decrypt_checksum_use_count; - struct crypto_rc4_struct* rc4_encrypt_key; + WINPR_RC4_CTX* rc4_encrypt_key; int encrypt_use_count; int encrypt_checksum_use_count; - struct crypto_des3_struct* fips_encrypt; - struct crypto_des3_struct* fips_decrypt; - struct crypto_hmac_struct* fips_hmac; + WINPR_CIPHER_CTX* fips_encrypt; + WINPR_CIPHER_CTX* fips_decrypt; + WINPR_HMAC_CTX* fips_hmac; UINT32 sec_flags; BOOL do_crypt; BOOL do_crypt_license; @@ -214,6 +215,8 @@ int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s); void rdp_read_flow_control_pdu(wStream* s, UINT16* type); +BOOL rdp_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount, const rdpMonitor* monitorDefArray); + int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra); int rdp_check_fds(rdpRdp* rdp); diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index 44c7190..e415786 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -25,6 +25,7 @@ #include "security.h" #include +#include #define TAG FREERDP_TAG("core") @@ -126,35 +127,35 @@ fips_oddparity_table[256] = static BOOL security_salted_hash(const BYTE* salt, const BYTE* input, int length, const BYTE* salt1, const BYTE* salt2, BYTE* output) { - CryptoMd5 md5; - CryptoSha1 sha1; - BYTE sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; + WINPR_MD5_CTX md5; + WINPR_SHA1_CTX sha1; + BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1(Input + Salt + Salt1 + Salt2)) */ /* SHA1_Digest = SHA1(Input + Salt + Salt1 + Salt2) */ - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, input, length)) /* Input */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, salt, 48)) /* Salt (48 bytes) */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, salt1, 32)) /* Salt1 (32 bytes) */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, salt2, 32)) /* Salt2 (32 bytes) */ + return FALSE; + if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest))) return FALSE; - } - crypto_sha1_update(sha1, input, length); /* Input */ - crypto_sha1_update(sha1, salt, 48); /* Salt (48 bytes) */ - crypto_sha1_update(sha1, salt1, 32); /* Salt1 (32 bytes) */ - crypto_sha1_update(sha1, salt2, 32); /* Salt2 (32 bytes) */ - crypto_sha1_final(sha1, sha1_digest); /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */ - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, salt, 48)) /* Salt (48 bytes) */ + return FALSE; + if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ + return FALSE; + if (!winpr_MD5_Final(&md5, output, WINPR_MD5_DIGEST_LENGTH)) return FALSE; - } - crypto_md5_update(md5, salt, 48); /* Salt (48 bytes) */ - crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - crypto_md5_final(md5, output); return TRUE; } @@ -199,18 +200,18 @@ void security_mac_salt_key(const BYTE* session_key_blob, const BYTE* client_rand BOOL security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE* in2, BYTE* output) { - CryptoMd5 md5; + WINPR_MD5_CTX md5; - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, in0, 16)) + return FALSE; + if (!winpr_MD5_Update(&md5, in1, 32)) + return FALSE; + if (!winpr_MD5_Update(&md5, in2, 32)) + return FALSE; + if (!winpr_MD5_Final(&md5, output, WINPR_MD5_DIGEST_LENGTH)) return FALSE; - } - crypto_md5_update(md5, in0, 16); - crypto_md5_update(md5, in1, 32); - crypto_md5_update(md5, in2, 32); - crypto_md5_final(md5, output); return TRUE; } @@ -232,76 +233,78 @@ void security_UINT32_le(BYTE* output, UINT32 value) BOOL security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length, BYTE* output) { - CryptoMd5 md5; - CryptoSha1 sha1; + WINPR_MD5_CTX md5; + WINPR_SHA1_CTX sha1; BYTE length_le[4]; - BYTE sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; + BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; /* MacData = MD5(MacSaltKey + pad2 + SHA1(MacSaltKey + pad1 + length + data)) */ security_UINT32_le(length_le, length); /* length must be little-endian */ /* SHA1_Digest = SHA1(MacSaltKey + pad1 + length + data) */ - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, mac_salt_key, 16)) /* MacSaltKey */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) /* pad1 */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, length_le, sizeof(length_le))) /* length */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, data, length)) /* data */ + return FALSE; + if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest))) return FALSE; - } - crypto_sha1_update(sha1, mac_salt_key, 16); /* MacSaltKey */ - crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ - crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ - crypto_sha1_update(sha1, data, length); /* data */ - crypto_sha1_final(sha1, sha1_digest); /* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */ - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, mac_salt_key, 16)) /* MacSaltKey */ + return FALSE; + if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) /* pad2 */ + return FALSE; + if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ + return FALSE; + if (!winpr_MD5_Final(&md5, output, WINPR_MD5_DIGEST_LENGTH)) return FALSE; - } - crypto_md5_update(md5, mac_salt_key, 16); /* MacSaltKey */ - crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ - crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - crypto_md5_final(md5, output); return TRUE; } BOOL security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* output) { - CryptoMd5 md5; - CryptoSha1 sha1; + WINPR_MD5_CTX md5; + WINPR_SHA1_CTX sha1; BYTE length_le[4]; - BYTE md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; - BYTE sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; + BYTE md5_digest[WINPR_MD5_DIGEST_LENGTH]; + BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; security_UINT32_le(length_le, length); /* length must be little-endian */ /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) /* pad1 */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, length_le, sizeof(length_le))) /* length */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, data, length)) /* data */ + return FALSE; + if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest))) return FALSE; - } - crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ - crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ - crypto_sha1_update(sha1, data, length); /* data */ - crypto_sha1_final(sha1, sha1_digest); /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ + return FALSE; + if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) /* pad2 */ + return FALSE; + if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ + return FALSE; + if (!winpr_MD5_Final(&md5, md5_digest, sizeof(md5_digest))) return FALSE; - } - crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ - crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - crypto_md5_final(md5, md5_digest); memcpy(output, md5_digest, 8); return TRUE; @@ -310,12 +313,12 @@ BOOL security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BOOL encryption, BYTE* output) { - CryptoMd5 md5; - CryptoSha1 sha1; + WINPR_MD5_CTX md5; + WINPR_SHA1_CTX sha1; BYTE length_le[4]; BYTE use_count_le[4]; - BYTE md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; - BYTE sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; + BYTE md5_digest[WINPR_MD5_DIGEST_LENGTH]; + BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; security_UINT32_le(length_le, length); /* length must be little-endian */ @@ -333,30 +336,32 @@ BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, } /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) /* pad1 */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, length_le, sizeof(length_le))) /* length */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, data, length)) /* data */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, use_count_le, sizeof(use_count_le))) /* encryptionCount */ + return FALSE; + if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest))) return FALSE; - } - crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ - crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ - crypto_sha1_update(sha1, data, length); /* data */ - crypto_sha1_update(sha1, use_count_le, sizeof(use_count_le)); /* encryptionCount */ - crypto_sha1_final(sha1, sha1_digest); /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ + return FALSE; + if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) /* pad2 */ + return FALSE; + if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ + return FALSE; + if (!winpr_MD5_Final(&md5, md5_digest, sizeof(md5_digest))) return FALSE; - } - crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ - crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - crypto_md5_final(md5, md5_digest); memcpy(output, md5_digest, 8); return TRUE; @@ -428,40 +433,38 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { - CryptoSha1 sha1; - BYTE client_encrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1]; - BYTE client_decrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1]; - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); + WINPR_SHA1_CTX sha1; + BYTE client_encrypt_key_t[WINPR_SHA1_DIGEST_LENGTH + 1]; + BYTE client_decrypt_key_t[WINPR_SHA1_DIGEST_LENGTH + 1]; + + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, client_random + 16, 16)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, server_random + 16, 16)) + return FALSE; + if (!winpr_SHA1_Final(&sha1, client_encrypt_key_t, sizeof(client_encrypt_key_t))) return FALSE; - } - crypto_sha1_update(sha1, client_random + 16, 16); - crypto_sha1_update(sha1, server_random + 16, 16); - crypto_sha1_final(sha1, client_encrypt_key_t); client_encrypt_key_t[20] = client_encrypt_key_t[0]; - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, client_random, 16)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, server_random, 16)) + return FALSE; + if (!winpr_SHA1_Final(&sha1, client_decrypt_key_t, sizeof(client_decrypt_key_t))) return FALSE; - } - crypto_sha1_update(sha1, client_random, 16); - crypto_sha1_update(sha1, server_random, 16); - crypto_sha1_final(sha1, client_decrypt_key_t); client_decrypt_key_t[20] = client_decrypt_key_t[0]; - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, client_decrypt_key_t, WINPR_SHA1_DIGEST_LENGTH)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, client_encrypt_key_t, WINPR_SHA1_DIGEST_LENGTH)) + return FALSE; + if (!winpr_SHA1_Final(&sha1, rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH)) return FALSE; - } - crypto_sha1_update(sha1, client_decrypt_key_t, 20); - crypto_sha1_update(sha1, client_encrypt_key_t, 20); - crypto_sha1_final(sha1, rdp->fips_sign_key); if (rdp->settings->ServerMode) { @@ -532,42 +535,42 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) { - BYTE sha1h[CRYPTO_SHA1_DIGEST_LENGTH]; - CryptoMd5 md5; - CryptoSha1 sha1; - CryptoRc4 rc4; + BYTE sha1h[WINPR_SHA1_DIGEST_LENGTH]; + WINPR_MD5_CTX md5; + WINPR_SHA1_CTX sha1; + WINPR_RC4_CTX* rc4; + BOOL rc; BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */ - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, update_key, key_len)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) + return FALSE; + if (!winpr_SHA1_Update(&sha1, key, key_len)) + return FALSE; + if (!winpr_SHA1_Final(&sha1, sha1h, sizeof(sha1h))) return FALSE; - } - crypto_sha1_update(sha1, update_key, key_len); - crypto_sha1_update(sha1, pad1, sizeof(pad1)); - crypto_sha1_update(sha1, key, key_len); - crypto_sha1_final(sha1, sha1h); - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, update_key, key_len)) + return FALSE; + if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) + return FALSE; + if (!winpr_MD5_Update(&md5, sha1h, sizeof(sha1h))) + return FALSE; + if (!winpr_MD5_Final(&md5, key, WINPR_MD5_DIGEST_LENGTH)) return FALSE; - } - crypto_md5_update(md5, update_key, key_len); - crypto_md5_update(md5, pad2, sizeof(pad2)); - crypto_md5_update(md5, sha1h, sizeof(sha1h)); - crypto_md5_final(md5, key); - rc4 = crypto_rc4_init(key, key_len); - if (!rc4) - { - WLog_ERR(TAG, "unable to allocate a rc4"); + if ((rc4 = winpr_RC4_New(key, key_len)) == NULL) + return FALSE; + rc = winpr_RC4_Update(rc4, key_len, key, key); + winpr_RC4_Free(rc4); + + if (!rc) return FALSE; - } - crypto_rc4(rc4, key_len, key, key); - crypto_rc4_free(rc4); if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT) memcpy(key, salt, 3); @@ -584,17 +587,16 @@ BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp) if (!security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len, rdp)) return FALSE; - crypto_rc4_free(rdp->rc4_encrypt_key); - rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); + winpr_RC4_Free(rdp->rc4_encrypt_key); + rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len); if (!rdp->rc4_encrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 encrypt key"); return FALSE; - } + rdp->encrypt_use_count = 0; } - crypto_rc4(rdp->rc4_encrypt_key, length, data, data); + if (!winpr_RC4_Update(rdp->rc4_encrypt_key, length, data, data)) + return FALSE; rdp->encrypt_use_count++; rdp->encrypt_checksum_use_count++; return TRUE; @@ -609,17 +611,16 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp) { if (!security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len, rdp)) return FALSE; - crypto_rc4_free(rdp->rc4_decrypt_key); - rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); + winpr_RC4_Free(rdp->rc4_decrypt_key); + rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, + rdp->rc4_key_len); if (!rdp->rc4_decrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 decrypt key"); return FALSE; - } rdp->decrypt_use_count = 0; } - crypto_rc4(rdp->rc4_decrypt_key, length, data, data); + if (!winpr_RC4_Update(rdp->rc4_decrypt_key, length, data, data)) + return FALSE; rdp->decrypt_use_count += 1; rdp->decrypt_checksum_use_count++; return TRUE; @@ -627,17 +628,20 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp) BOOL security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp* rdp) { - BYTE buf[20]; + BYTE buf[WINPR_SHA1_DIGEST_LENGTH]; BYTE use_count_le[4]; security_UINT32_le(use_count_le, rdp->encrypt_use_count); - if (!crypto_hmac_sha1_init(rdp->fips_hmac, rdp->fips_sign_key, 20)) + if (!winpr_HMAC_Init(rdp->fips_hmac, WINPR_MD_SHA1, + rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH)) + return FALSE; + if (!winpr_HMAC_Update(rdp->fips_hmac, data, length)) + return FALSE; + if (!winpr_HMAC_Update(rdp->fips_hmac, use_count_le, 4)) + return FALSE; + if (!winpr_HMAC_Final(rdp->fips_hmac, buf, WINPR_SHA1_DIGEST_LENGTH)) return FALSE; - - crypto_hmac_update(rdp->fips_hmac, data, length); - crypto_hmac_update(rdp->fips_hmac, use_count_le, 4); - crypto_hmac_final(rdp->fips_hmac, buf, 20); memmove(output, buf, 8); return TRUE; @@ -645,7 +649,9 @@ BOOL security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp* BOOL security_fips_encrypt(BYTE* data, int length, rdpRdp* rdp) { - if (!crypto_des3_encrypt(rdp->fips_encrypt, length, data, data)) + size_t olen; + + if (!winpr_Cipher_Update(rdp->fips_encrypt, data, length, data, &olen)) return FALSE; rdp->encrypt_use_count++; return TRUE; @@ -653,21 +659,29 @@ BOOL security_fips_encrypt(BYTE* data, int length, rdpRdp* rdp) BOOL security_fips_decrypt(BYTE* data, int length, rdpRdp* rdp) { - return crypto_des3_decrypt(rdp->fips_decrypt, length, data, data); + size_t olen; + + if (!winpr_Cipher_Update(rdp->fips_decrypt, data, length, data, &olen)) + return FALSE; + return TRUE; } BOOL security_fips_check_signature(const BYTE* data, int length, const BYTE* sig, rdpRdp* rdp) { - BYTE buf[20]; + BYTE buf[WINPR_SHA1_DIGEST_LENGTH]; BYTE use_count_le[4]; security_UINT32_le(use_count_le, rdp->decrypt_use_count); - if (!crypto_hmac_sha1_init(rdp->fips_hmac, rdp->fips_sign_key, 20)) + if (!winpr_HMAC_Init(rdp->fips_hmac, WINPR_MD_SHA1, + rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH)) + return FALSE; + if (!winpr_HMAC_Update(rdp->fips_hmac, data, length)) + return FALSE; + if (!winpr_HMAC_Update(rdp->fips_hmac, use_count_le, 4)) + return FALSE; + if (!winpr_HMAC_Final(rdp->fips_hmac, buf, WINPR_SHA1_DIGEST_LENGTH)) return FALSE; - crypto_hmac_update(rdp->fips_hmac, data, length); - crypto_hmac_update(rdp->fips_hmac, use_count_le, 4); - crypto_hmac_final(rdp->fips_hmac, buf, 20); rdp->decrypt_use_count++; diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index 0ddd7d2..1002d17 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -295,6 +295,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) if (!settings->ChannelDefArray) goto out_fail; + settings->SupportMonitorLayoutPdu = TRUE; settings->MonitorCount = 0; settings->MonitorDefArraySize = 32; settings->MonitorDefArray = (rdpMonitor*) calloc(settings->MonitorDefArraySize, sizeof(rdpMonitor)); @@ -471,7 +472,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) if (!settings->ServerAutoReconnectCookie) goto out_fail; - settings->ClientTimeZone = (TIME_ZONE_INFO*) calloc(1,sizeof(TIME_ZONE_INFO)); + settings->ClientTimeZone = (LPTIME_ZONE_INFORMATION) calloc(1,sizeof(TIME_ZONE_INFORMATION)); if (!settings->ClientTimeZone) goto out_fail; @@ -597,6 +598,9 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings) CHECKED_STRDUP(CertificateFile); /* 1410 */ CHECKED_STRDUP(PrivateKeyFile); /* 1411 */ CHECKED_STRDUP(RdpKeyFile); /* 1412 */ + CHECKED_STRDUP(CertificateContent); /* 1416 */ + CHECKED_STRDUP(PrivateKeyContent); /* 1417 */ + CHECKED_STRDUP(RdpKeyContent); /* 1418 */ CHECKED_STRDUP(WindowTitle); /* 1542 */ CHECKED_STRDUP(WmClass); /* 1549 */ CHECKED_STRDUP(ComputerName); /* 1664 */ @@ -728,14 +732,12 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings) CopyMemory(_settings->ReceivedCapabilities, settings->ReceivedCapabilities, 32); CopyMemory(_settings->OrderSupport, settings->OrderSupport, 32); - _settings->ClientHostname = malloc(32); + _settings->ClientHostname = _strdup(settings->ClientHostname); if (!_settings->ClientHostname) goto out_fail; - _settings->ClientProductId = malloc(32); + _settings->ClientProductId = _strdup(settings->ClientProductId); if (!_settings->ClientProductId) goto out_fail; - CopyMemory(_settings->ClientHostname, settings->ClientHostname, 32); - CopyMemory(_settings->ClientProductId, settings->ClientProductId, 32); _settings->BitmapCacheV2CellInfo = (BITMAP_CACHE_V2_CELL_INFO*) malloc(sizeof(BITMAP_CACHE_V2_CELL_INFO) * 6); if (!_settings->BitmapCacheV2CellInfo) @@ -760,10 +762,10 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings) CopyMemory(_settings->ClientAutoReconnectCookie, settings->ClientAutoReconnectCookie, sizeof(ARC_CS_PRIVATE_PACKET)); CopyMemory(_settings->ServerAutoReconnectCookie, settings->ServerAutoReconnectCookie, sizeof(ARC_SC_PRIVATE_PACKET)); - _settings->ClientTimeZone = (TIME_ZONE_INFO*) malloc(sizeof(TIME_ZONE_INFO)); + _settings->ClientTimeZone = (LPTIME_ZONE_INFORMATION) malloc(sizeof(TIME_ZONE_INFORMATION)); if (!_settings->ClientTimeZone) goto out_fail; - CopyMemory(_settings->ClientTimeZone, settings->ClientTimeZone, sizeof(TIME_ZONE_INFO)); + CopyMemory(_settings->ClientTimeZone, settings->ClientTimeZone, sizeof(TIME_ZONE_INFORMATION)); _settings->TargetNetAddressCount = settings->TargetNetAddressCount; @@ -813,7 +815,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings) goto out_fail; } - if (_settings->DeviceArraySize < _settings->DeviceCount) + if (_settings->DeviceArraySize < _settings->DeviceCount) { _settings->DeviceCount = 0; _settings->DeviceArraySize = 0; @@ -924,6 +926,9 @@ void freerdp_settings_free(rdpSettings* settings) free(settings->ServerCertificate); free(settings->RdpKeyFile); certificate_free(settings->RdpServerCertificate); + free(settings->CertificateContent); + free(settings->PrivateKeyContent); + free(settings->RdpKeyContent); free(settings->ClientAutoReconnectCookie); free(settings->ServerAutoReconnectCookie); free(settings->ClientTimeZone); diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index ce026ce..7be7a41 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -489,7 +489,7 @@ static int transport_bio_buffered_write(BIO* bio, const char* buf, int num) */ if (buf && num && !ringbuffer_write(&ptr->xmitBuffer, (const BYTE*) buf, num)) { - WLog_ERR(TAG, "an error occured when writing (num: %d)", num); + WLog_ERR(TAG, "an error occurred when writing (num: %d)", num); return -1; } @@ -877,7 +877,7 @@ static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames, sockfds[index] = _socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); - if (sockfds[index] < 0) + if (sockfds[index] == INVALID_SOCKET) { freeaddrinfo(result); sockfds[index] = 0; @@ -1027,7 +1027,7 @@ BOOL freerdp_tcp_set_keep_alive_mode(int sockfd) #endif #ifdef TCP_USER_TIMEOUT - optval = 4000; + optval = 9000; optlen = sizeof(optval); if (setsockopt(sockfd, SOL_TCP, TCP_USER_TIMEOUT, (void*) &optval, optlen) < 0) diff --git a/libfreerdp/core/test/TestConnect.c b/libfreerdp/core/test/TestConnect.c index 5dec3e7..91f6b02 100644 --- a/libfreerdp/core/test/TestConnect.c +++ b/libfreerdp/core/test/TestConnect.c @@ -22,7 +22,7 @@ static int runInstance(int argc, char* argv[], freerdp** inst) if (freerdp_client_settings_parse_command_line(instance->settings, argc, argv, FALSE) < 0) goto finish; - if (freerdp_client_load_addins(instance->context->channels, instance->settings) != 1) + if (!freerdp_client_load_addins(instance->context->channels, instance->settings)) goto finish; if (s_sync) diff --git a/libfreerdp/core/test/TestVersion.c b/libfreerdp/core/test/TestVersion.c index 3203088..146e81f 100644 --- a/libfreerdp/core/test/TestVersion.c +++ b/libfreerdp/core/test/TestVersion.c @@ -33,6 +33,10 @@ int TestVersion(int argc, char* argv[]) if (!build) return -1; + build = freerdp_get_build_config(); + if (!build) + return -1; + return 0; } diff --git a/libfreerdp/core/timezone.c b/libfreerdp/core/timezone.c index 95f06a3..48374fe 100644 --- a/libfreerdp/core/timezone.c +++ b/libfreerdp/core/timezone.c @@ -22,9 +22,13 @@ #endif #include +#include #include "timezone.h" +static void rdp_read_system_time(wStream* s, SYSTEMTIME* system_time); +static void rdp_write_system_time(wStream* s, SYSTEMTIME* system_time); + /** * Read SYSTEM_TIME structure (TS_SYSTEMTIME).\n * @msdn{cc240478} @@ -32,7 +36,7 @@ * @param system_time system time structure */ -void rdp_read_system_time(wStream* s, SYSTEM_TIME* system_time) +void rdp_read_system_time(wStream* s, SYSTEMTIME* system_time) { Stream_Read_UINT16(s, system_time->wYear); /* wYear, must be set to 0 */ Stream_Read_UINT16(s, system_time->wMonth); /* wMonth */ @@ -51,7 +55,7 @@ void rdp_read_system_time(wStream* s, SYSTEM_TIME* system_time) * @param system_time system time structure */ -void rdp_write_system_time(wStream* s, SYSTEM_TIME* system_time) +void rdp_write_system_time(wStream* s, SYSTEMTIME* system_time) { Stream_Write_UINT16(s, system_time->wYear); /* wYear, must be set to 0 */ Stream_Write_UINT16(s, system_time->wMonth); /* wMonth */ @@ -76,34 +80,31 @@ void rdp_write_system_time(wStream* s, SYSTEM_TIME* system_time) BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings) { - char* str = NULL; - TIME_ZONE_INFO* clientTimeZone; + LPTIME_ZONE_INFORMATION tz; + + if (!s || !settings) + return FALSE; if (Stream_GetRemainingLength(s) < 172) return FALSE; - clientTimeZone = settings->ClientTimeZone; + tz = settings->ClientTimeZone; + if (!tz) + return FALSE; - Stream_Read_UINT32(s, clientTimeZone->bias); /* Bias */ + Stream_Read_UINT32(s, tz->Bias); /* Bias */ /* standardName (64 bytes) */ - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL); - Stream_Seek(s, 64); - strncpy(clientTimeZone->standardName, str, sizeof(clientTimeZone->standardName)); - free(str); - str = NULL; + Stream_Read(s, tz->StandardName, sizeof(tz->StandardName)); - rdp_read_system_time(s, &clientTimeZone->standardDate); /* StandardDate */ - Stream_Read_UINT32(s, clientTimeZone->standardBias); /* StandardBias */ + rdp_read_system_time(s, &tz->StandardDate); /* StandardDate */ + Stream_Read_UINT32(s, tz->StandardBias); /* StandardBias */ /* daylightName (64 bytes) */ - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL); - Stream_Seek(s, 64); - strncpy(clientTimeZone->daylightName, str, sizeof(clientTimeZone->daylightName)); - free(str); + Stream_Read(s, tz->DaylightName, sizeof(tz->DaylightName)); - rdp_read_system_time(s, &clientTimeZone->daylightDate); /* DaylightDate */ - Stream_Read_UINT32(s, clientTimeZone->daylightBias); /* DaylightBias */ + rdp_read_system_time(s, &tz->DaylightDate); /* DaylightDate */ + Stream_Read_UINT32(s, tz->DaylightBias); /* DaylightBias */ return TRUE; } @@ -115,55 +116,45 @@ BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings) * @param settings settings */ -void rdp_write_client_time_zone(wStream* s, rdpSettings* settings) +BOOL rdp_write_client_time_zone(wStream* s, rdpSettings* settings) { - WCHAR* standardName = NULL; - WCHAR* daylightName = NULL; - int standardNameLength; - int daylightNameLength; - TIME_ZONE_INFO* clientTimeZone; + LPTIME_ZONE_INFORMATION tz; + DWORD rc; - clientTimeZone = settings->ClientTimeZone; - freerdp_time_zone_detect(clientTimeZone); + tz = settings->ClientTimeZone; + if (!tz) + return FALSE; - standardNameLength = ConvertToUnicode(CP_UTF8, 0, clientTimeZone->standardName, -1, &standardName, 0) * 2; - daylightNameLength = ConvertToUnicode(CP_UTF8, 0, clientTimeZone->daylightName, -1, &daylightName, 0) * 2; + rc = GetTimeZoneInformation(tz); - if (standardNameLength > 62) - standardNameLength = 62; - - if (daylightNameLength > 62) - daylightNameLength = 62; - - /* Bias */ - Stream_Write_UINT32(s, clientTimeZone->bias); + /* Bias */ + Stream_Write_UINT32(s, tz->Bias); /* standardName (64 bytes) */ - Stream_Write(s, standardName, standardNameLength); - Stream_Zero(s, 64 - standardNameLength); + Stream_Write(s, tz->StandardName, sizeof(tz->StandardName)); - /* StandardDate */ - rdp_write_system_time(s, &clientTimeZone->standardDate); + /* StandardDate */ + rdp_write_system_time(s, &tz->StandardDate); - DEBUG_TIMEZONE("bias=%d stdName='%s' dlName='%s'", clientTimeZone->bias, clientTimeZone->standardName, clientTimeZone->daylightName); + DEBUG_TIMEZONE("bias=%d stdName='%s' dlName='%s'", tz->Bias, + tz->StandardName, tz->DaylightName); /* Note that StandardBias is ignored if no valid standardDate is provided. */ - /* StandardBias */ - Stream_Write_UINT32(s, clientTimeZone->standardBias); - DEBUG_TIMEZONE("StandardBias=%d", clientTimeZone->standardBias); + /* StandardBias */ + Stream_Write_UINT32(s, tz->StandardBias); + DEBUG_TIMEZONE("StandardBias=%d", tz->StandardBias); /* daylightName (64 bytes) */ - Stream_Write(s, daylightName, daylightNameLength); - Stream_Zero(s, 64 - daylightNameLength); + Stream_Write(s, tz->DaylightName, sizeof(tz->DaylightName)); - /* DaylightDate */ - rdp_write_system_time(s, &clientTimeZone->daylightDate); + /* DaylightDate */ + rdp_write_system_time(s, &tz->DaylightDate); /* Note that DaylightBias is ignored if no valid daylightDate is provided. */ - /* DaylightBias */ - Stream_Write_UINT32(s, clientTimeZone->daylightBias); - DEBUG_TIMEZONE("DaylightBias=%d", clientTimeZone->daylightBias); + /* DaylightBias */ + Stream_Write_UINT32(s, tz->DaylightBias); + DEBUG_TIMEZONE("DaylightBias=%d", tz->DaylightBias); - free(standardName); - free(daylightName); + return TRUE; } + diff --git a/libfreerdp/core/timezone.h b/libfreerdp/core/timezone.h index a45cd44..92b2c7a 100644 --- a/libfreerdp/core/timezone.h +++ b/libfreerdp/core/timezone.h @@ -28,15 +28,11 @@ #include #include -#include #include -void rdp_read_system_time(wStream* s, SYSTEM_TIME* system_time); -void rdp_write_system_time(wStream* s, SYSTEM_TIME* system_time); -void rdp_get_client_time_zone(wStream* s, rdpSettings* settings); BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings); -void rdp_write_client_time_zone(wStream* s, rdpSettings* settings); +BOOL rdp_write_client_time_zone(wStream* s, rdpSettings* settings); #define TIMEZONE_TAG FREERDP_TAG("core.timezone") #ifdef WITH_DEBUG_TIMEZONE diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 0d132fe..6f928cc 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -322,7 +322,7 @@ BOOL transport_accept_tls(rdpTransport* transport) transport->layer = TRANSPORT_LAYER_TLS; - if (!tls_accept(transport->tls, transport->frontBio, settings->CertificateFile, settings->PrivateKeyFile)) + if (!tls_accept(transport->tls, transport->frontBio, settings)) return FALSE; transport->frontBio = transport->tls->bio; @@ -340,7 +340,7 @@ BOOL transport_accept_nla(rdpTransport* transport) transport->layer = TRANSPORT_LAYER_TLS; - if (!tls_accept(transport->tls, transport->frontBio, settings->CertificateFile, settings->PrivateKeyFile)) + if (!tls_accept(transport->tls, transport->frontBio, settings)) return FALSE; transport->frontBio = transport->tls->bio; @@ -371,6 +371,53 @@ BOOL transport_accept_nla(rdpTransport* transport) return TRUE; } +#define WLog_ERR_BIO(tag, biofunc, bio) \ + transport_bio_error_log(tag, biofunc, bio, __FILE__, __FUNCTION__, __LINE__) + +static void transport_bio_error_log(LPCSTR tag, LPCSTR biofunc, BIO* bio, + LPCSTR file, LPCSTR func, DWORD line) +{ + unsigned long sslerr; + char *buf; + wLog* log; + wLogMessage log_message; + int saveerrno; + + saveerrno = errno; + + log = WLog_Get(tag); + if (!log) + return; + + log_message.Level = WLOG_ERROR; + if (log_message.Level < WLog_GetLogLevel(log)) + return; + + log_message.Type = WLOG_MESSAGE_TEXT; + log_message.LineNumber = line; + log_message.FileName = file; + log_message.FunctionName = func; + + if (ERR_peek_error() == 0) + { + log_message.FormatString = "%s returned a system error %d: %s"; + WLog_PrintMessage(log, &log_message, biofunc, saveerrno, strerror(saveerrno)); + return; + } + + buf = malloc(120); + if (buf) + { + while((sslerr = ERR_get_error())) + { + ERR_error_string_n(sslerr, buf, 120); + log_message.FormatString = "%s returned an error: %s"; + WLog_PrintMessage(log, &log_message, biofunc, buf); + } + free(buf); + } +} + int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes) { int read = 0; @@ -391,6 +438,12 @@ int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes) if (!transport->frontBio || !BIO_should_retry(transport->frontBio)) { /* something unexpected happened, let's close */ + if (!transport->frontBio) + { + WLog_ERR(TAG, "BIO_read: transport->frontBio null"); + return -1; + } + WLog_ERR_BIO(TAG, "BIO_read", transport->frontBio); transport->layer = TRANSPORT_LAYER_CLOSED; return -1; } @@ -402,7 +455,7 @@ int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes) /* blocking means that we can't continue until we have read the number of requested bytes */ if (BIO_wait_read(transport->frontBio, 100) < 0) { - WLog_ERR(TAG, "error when selecting for read"); + WLog_ERR_BIO(TAG, "BIO_wait_read", transport->frontBio); return -1; } @@ -625,15 +678,21 @@ int transport_write(rdpTransport* transport, wStream* s) * is a SSL or TSG BIO in the chain. */ if (!BIO_should_retry(transport->frontBio)) + { + WLog_ERR_BIO(TAG, "BIO_should_retry", transport->frontBio); goto out_cleanup; + } /* non-blocking can live with blocked IOs */ if (!transport->blocking) + { + WLog_ERR_BIO(TAG, "BIO_write", transport->frontBio); goto out_cleanup; + } if (BIO_wait_write(transport->frontBio, 100) < 0) { - WLog_ERR(TAG, "error when selecting for write"); + WLog_ERR_BIO(TAG, "BIO_wait_write", transport->frontBio); status = -1; goto out_cleanup; } diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index 90e183e..f8b2dad 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -30,11 +30,13 @@ #include "update.h" #include "surface.h" #include "message.h" +#include "info.h" #include #include #include + #define TAG FREERDP_TAG("core.update") const char* const UPDATE_TYPE_STRINGS[] = @@ -1905,6 +1907,7 @@ void update_register_server_callbacks(rdpUpdate* update) update->SurfaceFrameBits = update_send_surface_frame_bits; update->PlaySound = update_send_play_sound; update->SetKeyboardIndicators = update_send_set_keyboard_indicators; + update->SaveSessionInfo = rdp_send_save_session_info; update->primary->DstBlt = update_send_dstblt; update->primary->PatBlt = update_send_patblt; update->primary->ScrBlt = update_send_scrblt; diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 26c69fd..85a28b8 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -22,168 +22,13 @@ #endif #include +#include #include #include #define TAG FREERDP_TAG("crypto") -CryptoSha1 crypto_sha1_init(void) -{ - CryptoSha1 sha1 = malloc(sizeof(*sha1)); - if (!sha1) - return NULL; - SHA1_Init(&sha1->sha_ctx); - return sha1; -} - -void crypto_sha1_update(CryptoSha1 sha1, const BYTE* data, UINT32 length) -{ - SHA1_Update(&sha1->sha_ctx, data, length); -} - -void crypto_sha1_final(CryptoSha1 sha1, BYTE* out_data) -{ - SHA1_Final(out_data, &sha1->sha_ctx); - free(sha1); -} - -CryptoMd5 crypto_md5_init(void) -{ - CryptoMd5 md5 = malloc(sizeof(*md5)); - if (!md5) - return NULL; - MD5_Init(&md5->md5_ctx); - return md5; -} - -void crypto_md5_update(CryptoMd5 md5, const BYTE* data, UINT32 length) -{ - MD5_Update(&md5->md5_ctx, data, length); -} - -void crypto_md5_final(CryptoMd5 md5, BYTE* out_data) -{ - MD5_Final(out_data, &md5->md5_ctx); - free(md5); -} - -CryptoRc4 crypto_rc4_init(const BYTE* key, UINT32 length) -{ - CryptoRc4 rc4 = malloc(sizeof(*rc4)); - if (!rc4) - return NULL; - RC4_set_key(&rc4->rc4_key, length, key); - return rc4; -} - -void crypto_rc4(CryptoRc4 rc4, UINT32 length, const BYTE* in_data, BYTE* out_data) -{ - RC4(&rc4->rc4_key, length, in_data, out_data); -} - -void crypto_rc4_free(CryptoRc4 rc4) -{ - free(rc4); -} - -CryptoDes3 crypto_des3_encrypt_init(const BYTE* key, const BYTE* ivec) -{ - CryptoDes3 des3 = malloc(sizeof(*des3)); - if (!des3) - return NULL; - - EVP_CIPHER_CTX_init(&des3->des3_ctx); - EVP_EncryptInit_ex(&des3->des3_ctx, EVP_des_ede3_cbc(), NULL, key, ivec); - EVP_CIPHER_CTX_set_padding(&des3->des3_ctx, 0); - return des3; -} - -CryptoDes3 crypto_des3_decrypt_init(const BYTE* key, const BYTE* ivec) -{ - CryptoDes3 des3 = malloc(sizeof(*des3)); - if (!des3) - return NULL; - - EVP_CIPHER_CTX_init(&des3->des3_ctx); - EVP_DecryptInit_ex(&des3->des3_ctx, EVP_des_ede3_cbc(), NULL, key, ivec); - EVP_CIPHER_CTX_set_padding(&des3->des3_ctx, 0); - return des3; -} - -BOOL crypto_des3_encrypt(CryptoDes3 des3, UINT32 length, const BYTE* in_data, BYTE* out_data) -{ - int len; - return EVP_EncryptUpdate(&des3->des3_ctx, out_data, &len, in_data, length) == 1; -} - -BOOL crypto_des3_decrypt(CryptoDes3 des3, UINT32 length, const BYTE* in_data, BYTE* out_data) -{ - int len; - int ret = EVP_DecryptUpdate(&des3->des3_ctx, out_data, &len, in_data, length); - - if (length != len) - abort(); /* TODO */ - return ret == 1; -} - -void crypto_des3_free(CryptoDes3 des3) -{ - if (des3 == NULL) - return; - EVP_CIPHER_CTX_cleanup(&des3->des3_ctx); - free(des3); -} - -CryptoHmac crypto_hmac_new(void) -{ - CryptoHmac hmac = malloc(sizeof(*hmac)); - if (!hmac) - return NULL; - - HMAC_CTX_init(&hmac->hmac_ctx); - return hmac; -} - -BOOL crypto_hmac_sha1_init(CryptoHmac hmac, const BYTE* data, UINT32 length) -{ -#if (OPENSSL_VERSION_NUMBER >= 0x00909000) - return HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_sha1(), NULL) == 1; -#else - HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_sha1(), NULL); - return TRUE; -#endif -} - -BOOL crypto_hmac_md5_init(CryptoHmac hmac, const BYTE* data, UINT32 length) -{ -#if (OPENSSL_VERSION_NUMBER >= 0x00909000) - return HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_md5(), NULL) == 1; -#else - HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_md5(), NULL); - return TRUE; -#endif -} - -void crypto_hmac_update(CryptoHmac hmac, const BYTE* data, UINT32 length) -{ - HMAC_Update(&hmac->hmac_ctx, data, length); -} - -void crypto_hmac_final(CryptoHmac hmac, BYTE* out_data, UINT32 length) -{ - HMAC_Final(&hmac->hmac_ctx, out_data, &length); -} - -void crypto_hmac_free(CryptoHmac hmac) -{ - if (hmac == NULL) - return; - - HMAC_CTX_cleanup(&hmac->hmac_ctx); - free(hmac); -} - CryptoCert crypto_cert_read(BYTE* data, UINT32 length) { CryptoCert cert = malloc(sizeof(*cert)); @@ -347,11 +192,6 @@ void crypto_reverse(BYTE* data, int length) } } -void crypto_nonce(BYTE* nonce, int size) -{ - RAND_bytes((void*) nonce, size); -} - char* crypto_cert_fingerprint(X509* xcert) { int i = 0; @@ -404,7 +244,8 @@ char* crypto_cert_subject(X509* xcert) char* crypto_cert_subject_common_name(X509* xcert, int* length) { int index; - BYTE* common_name; + BYTE* common_name_raw; + char* common_name; X509_NAME* subject_name; X509_NAME_ENTRY* entry; ASN1_STRING* entry_data; @@ -429,15 +270,18 @@ char* crypto_cert_subject_common_name(X509* xcert, int* length) if (entry_data == NULL) return NULL; - *length = ASN1_STRING_to_UTF8(&common_name, entry_data); + *length = ASN1_STRING_to_UTF8(&common_name_raw, entry_data); if (*length < 0) return NULL; + common_name = _strdup((char*)common_name_raw); + OPENSSL_free(common_name_raw); + return (char*) common_name; } -FREERDP_API void crypto_cert_subject_alt_name_free(int count, int *lengths, +void crypto_cert_subject_alt_name_free(int count, int *lengths, char** alt_name) { int i; diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index 90de48b..ba10e0d 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -589,11 +589,10 @@ out_free: return NULL; } - -#if defined(__APPLE__) -BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method, int options, BOOL clientMode) +#if OPENSSL_VERSION_NUMBER >= 0x010000000L +static BOOL tls_prepare(rdpTls* tls, BIO* underlying, const SSL_METHOD* method, int options, BOOL clientMode) #else -BOOL tls_prepare(rdpTls* tls, BIO* underlying, const SSL_METHOD* method, int options, BOOL clientMode) +static BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method, int options, BOOL clientMode) #endif { rdpSettings* settings = tls->settings; @@ -807,6 +806,10 @@ int tls_connect(rdpTls* tls, BIO* underlying) if (!tls_prepare(tls, underlying, SSLv23_client_method(), options, TRUE)) return FALSE; +#ifndef OPENSSL_NO_TLSEXT + SSL_set_tlsext_host_name(tls->ssl, tls->hostname); +#endif + return tls_do_handshake(tls, TRUE); } @@ -823,9 +826,12 @@ static void tls_openssl_tlsext_debug_callback(SSL *s, int client_server, } #endif -BOOL tls_accept(rdpTls* tls, BIO* underlying, const char* cert_file, const char* privatekey_file) +BOOL tls_accept(rdpTls* tls, BIO* underlying, rdpSettings *settings) { long options = 0; + BIO *bio; + RSA *rsa; + X509 *x509; /** * SSL_OP_NO_SSLv2: @@ -867,16 +873,85 @@ BOOL tls_accept(rdpTls* tls, BIO* underlying, const char* cert_file, const char* if (!tls_prepare(tls, underlying, SSLv23_server_method(), options, FALSE)) return FALSE; - if (SSL_use_RSAPrivateKey_file(tls->ssl, privatekey_file, SSL_FILETYPE_PEM) <= 0) + if (settings->PrivateKeyFile) { - WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed"); - WLog_ERR(TAG, "PrivateKeyFile: %s", privatekey_file); + bio = BIO_new_file(settings->PrivateKeyFile, "rb+"); + if (!bio) + { + WLog_ERR(TAG, "BIO_new_file failed for private key %s", settings->PrivateKeyFile); + return FALSE; + } + } + else if (settings->PrivateKeyContent) + { + bio = BIO_new_mem_buf(settings->PrivateKeyContent, strlen(settings->PrivateKeyContent)); + if (!bio) + { + WLog_ERR(TAG, "BIO_new_mem_buf failed for private key"); + return FALSE; + } + } + else + { + WLog_ERR(TAG, "no private key defined"); return FALSE; } - if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) + rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); + BIO_free(bio); + + if (!rsa) + { + WLog_ERR(TAG, "invalid private key"); + return FALSE; + } + + if (SSL_use_RSAPrivateKey(tls->ssl, rsa) <= 0) + { + WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed"); + RSA_free(rsa); + return FALSE; + } + + + if (settings->CertificateFile) + { + bio = BIO_new_file(settings->CertificateFile, "rb+"); + if (!bio) + { + WLog_ERR(TAG, "BIO_new_file failed for certificate %s", settings->CertificateFile); + return FALSE; + } + } + else if (settings->CertificateContent) + { + bio = BIO_new_mem_buf(settings->CertificateContent, strlen(settings->CertificateContent)); + if (!bio) + { + WLog_ERR(TAG, "BIO_new_mem_buf failed for certificate"); + return FALSE; + } + } + else + { + WLog_ERR(TAG, "no certificate defined"); + return FALSE; + } + + x509 = PEM_read_bio_X509(bio, NULL, NULL, 0); + BIO_free(bio); + + if (!x509) + { + WLog_ERR(TAG, "invalid certificate"); + return FALSE; + } + + + if (SSL_use_certificate(tls->ssl, x509) <= 0) { WLog_ERR(TAG, "SSL_use_certificate_file failed"); + X509_free(x509); return FALSE; } @@ -1171,31 +1246,16 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por /* if the certificate is valid and the certificate name matches, verification succeeds */ if (certificate_status && hostname_match) - { - if (common_name) - { - free(common_name); - common_name = NULL; - } - verification_status = TRUE; /* success! */ - } - - /* if the certificate is valid but the certificate name does not match, warn user, do not accept */ - if (certificate_status && !hostname_match) - tls_print_certificate_name_mismatch_error(hostname, port, - common_name, alt_names, - alt_names_count); /* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */ - - if (!certificate_status) + if (!certificate_status || !hostname_match) { char* issuer; char* subject; char* fingerprint; freerdp* instance = (freerdp*) tls->settings->instance; - BOOL accept_certificate = FALSE; + DWORD accept_certificate = 0; issuer = crypto_cert_issuer(cert->px509); subject = crypto_cert_subject(cert->px509); @@ -1214,19 +1274,23 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por alt_names_count); if (instance->VerifyCertificate) - { - accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint); - } + accept_certificate = instance->VerifyCertificate(instance, common_name, + subject, issuer, fingerprint, !hostname_match); - if (!accept_certificate) + switch(accept_certificate) { - /* user did not accept, abort and do not add entry in known_hosts file */ - verification_status = FALSE; /* failure! */ - } - else - { - /* user accepted certificate, add entry in known_hosts file */ - verification_status = certificate_data_print(tls->certificate_store, certificate_data); + case 1: + /* user accepted certificate, add entry in known_hosts file */ + verification_status = certificate_data_print(tls->certificate_store, certificate_data); + break; + case 2: + /* user did accept temporaty, do not add to known hosts file */ + verification_status = TRUE; + break; + default: + /* user did not accept, abort and do not add entry in known_hosts file */ + verification_status = FALSE; /* failure! */ + break; } } else if (match == -1) @@ -1248,28 +1312,31 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por if (instance->VerifyChangedCertificate) { accept_certificate = instance->VerifyChangedCertificate( - instance, subject, issuer, + instance, common_name, subject, issuer, fingerprint, old_subject, old_issuer, old_fingerprint); } free(old_fingerprint); - if (!accept_certificate) + switch(accept_certificate) { - /* user did not accept, abort and do not change known_hosts file */ - verification_status = FALSE; /* failure! */ - } - else - { - /* user accepted new certificate, add replace fingerprint for this host in known_hosts file */ - verification_status = certificate_data_replace(tls->certificate_store, certificate_data); + case 1: + /* user accepted certificate, add entry in known_hosts file */ + verification_status = certificate_data_replace(tls->certificate_store, certificate_data); + break; + case 2: + /* user did accept temporaty, do not add to known hosts file */ + verification_status = TRUE; + break; + default: + /* user did not accept, abort and do not add entry in known_hosts file */ + verification_status = FALSE; /* failure! */ + break; } } else if (match == 0) - { verification_status = TRUE; /* success! */ - } free(issuer); free(subject); @@ -1278,9 +1345,7 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por certificate_data_free(certificate_data); -#ifndef _WIN32 free(common_name); -#endif if (alt_names) crypto_cert_subject_alt_name_free(alt_names_count, alt_names_lengths, diff --git a/libfreerdp/gdi/16bpp.c b/libfreerdp/gdi/16bpp.c index e292d7c..858056a 100644 --- a/libfreerdp/gdi/16bpp.c +++ b/libfreerdp/gdi/16bpp.c @@ -160,7 +160,7 @@ static BOOL BitBlt_SRCCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nW dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) - memcpy(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } return TRUE; diff --git a/libfreerdp/gdi/8bpp.c b/libfreerdp/gdi/8bpp.c index 1303bbc..1f90b60 100644 --- a/libfreerdp/gdi/8bpp.c +++ b/libfreerdp/gdi/8bpp.c @@ -105,7 +105,7 @@ static BOOL BitBlt_SRCCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); if (srcp != 0 && dstp != 0) - memcpy(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + memmove(dstp, srcp, nWidth * hdcDest->bytesPerPixel); } return TRUE; diff --git a/libfreerdp/gdi/region.c b/libfreerdp/gdi/region.c index 888a848..a749320 100644 --- a/libfreerdp/gdi/region.c +++ b/libfreerdp/gdi/region.c @@ -234,8 +234,8 @@ INLINE BOOL gdi_CopyOverlap(int x, int y, int width, int height, int srcx, int s gdi_CRgnToRect(x, y, width, height, &dst); gdi_CRgnToRect(srcx, srcy, width, height, &src); - return (dst.right > src.left && dst.left < src.right && - dst.bottom > src.top && dst.top < src.bottom) ? TRUE : FALSE; + return (dst.right >= src.left && dst.left <= src.right && + dst.bottom >= src.top && dst.top <= src.bottom) ? TRUE : FALSE; } /** diff --git a/libfreerdp/locale/CMakeLists.txt b/libfreerdp/locale/CMakeLists.txt index f6bdf73..e418e0c 100644 --- a/libfreerdp/locale/CMakeLists.txt +++ b/libfreerdp/locale/CMakeLists.txt @@ -22,7 +22,6 @@ set(${MODULE_PREFIX}_SRCS keyboard_layout.c keyboard.c locale.c - timezone.c liblocale.h) set(${MODULE_PREFIX}_X11_SRCS diff --git a/libfreerdp/locale/timezone.c b/libfreerdp/locale/timezone.c deleted file mode 100644 index 5735049..0000000 --- a/libfreerdp/locale/timezone.c +++ /dev/null @@ -1,1770 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Time Zone Redirection - * - * Copyright 2012 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#define __USE_XOPEN -#include - -#ifndef _WIN32 -#include -#endif - -#include "liblocale.h" - -#include -#include - -#define TAG FREERDP_TAG("locale") - -/* Time Zone Redirection table generated with TimeZones.cs script */ - - -struct _SYSTEM_TIME_ENTRY -{ - UINT16 wYear; - UINT16 wMonth; - UINT16 wDayOfWeek; - UINT16 wDay; - UINT16 wHour; - UINT16 wMinute; - UINT16 wSecond; - UINT16 wMilliseconds; -}; -typedef struct _SYSTEM_TIME_ENTRY SYSTEM_TIME_ENTRY; - -struct _TIME_ZONE_RULE_ENTRY -{ - UINT64 TicksStart; - UINT64 TicksEnd; - INT32 DaylightDelta; - SYSTEM_TIME_ENTRY StandardDate; - SYSTEM_TIME_ENTRY DaylightDate; -}; -typedef struct _TIME_ZONE_RULE_ENTRY TIME_ZONE_RULE_ENTRY; - -struct _TIME_ZONE_ENTRY -{ - const char* Id; - UINT32 Bias; - BOOL SupportsDST; - const char* DisplayName; - const char* StandardName; - const char* DaylightName; - TIME_ZONE_RULE_ENTRY* RuleTable; - UINT32 RuleTableCount; -}; -typedef struct _TIME_ZONE_ENTRY TIME_ZONE_ENTRY; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_3[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_4[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_5[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_7[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_8[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_10[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_11[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_14[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_15[] = -{ - { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_17[] = -{ - { 633662964000000000ULL, 180000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 9, 6, 1, 23, 59 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_18[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_19[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 2, 0, 1, 2, 0 }, { 0, 11, 0, 1, 0, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 0, 1, 0, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_21[] = -{ - { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 5, 6, 1, 23, 59 }, { 0, 8, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_22[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 0, 1 }, { 0, 4, 0, 1, 0, 1 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 0, 1 }, }, - { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_23[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 2, 0, 1, 2, 0 }, { 0, 11, 0, 1, 0, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 0, 1, 0, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_24[] = -{ - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 1, 1, 1, 0, 0 }, { 0, 12, 0, 1, 0, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 1, 4, 1, 0, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_26[] = -{ - { 633662964000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_27[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 9, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 10, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_28[] = -{ - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 1, 6, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_30[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_31[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_33[] = -{ - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 8, 0, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 5, 0, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 8, 6, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 7, 6, 1, 23, 59 }, { 0, 4, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_35[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 0, 1, 1, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_37[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_38[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_39[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_40[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_42[] = -{ - { 634293684000000000ULL, 180000000000ULL, -60, { 0, 9, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 634294548000000000ULL, 60, { 0, 4, 0, 1, 2, 0 }, { 0, 9, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_43[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 9, 5, 1, 1, 0 }, { 0, 3, 4, 1, 0, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 10, 5, 1, 1, 0 }, { 0, 3, 4, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_44[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_45[] = -{ - { 633978324000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 0, 0 }, { 0, 3, 0, 1, 0, 0 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_46[] = -{ - { 632716020000000000ULL, 180000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 5, 1, 0, 0 }, }, - { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 5, 1, 0, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_47[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 9, 3, 1, 23, 59 }, { 0, 3, 5, 1, 23, 59 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 11, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 5, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, - { 3155378292000000000ULL, 636188436000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_49[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_50[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 1, 1, 3, 0 }, }, - { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_51[] = -{ - { 632716020000000000ULL, 632401524000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, - { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_52[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_53[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 4, 0, 1, 3, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 10, 1, 1, 4, 0 }, { 0, 4, 0, 1, 3, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_54[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_57[] = -{ - { 632716020000000000ULL, 180000000000ULL, 60, { 0, 9, 2, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 9, 6, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, - { 3155378292000000000ULL, 633663828000000000ULL, 60, { 0, 9, 1, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_59[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 5, 0 }, { 0, 3, 0, 1, 4, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_60[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_61[] = -{ - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 1, 2, 1, 0, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 1, 4, 1, 0, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_63[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_65[] = -{ - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 5, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 4, 2, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_71[] = -{ - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 12, 4, 1, 23, 59 }, { 0, 6, 5, 1, 23, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_72[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_75[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_77[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_79[] = -{ - { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 1, 0, 1, 0, 0 }, { 0, 12, 0, 1, 2, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 1, 4, 1, 0, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_82[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_85[] = -{ - { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_88[] = -{ - { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_90[] = -{ - { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_91[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_93[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_94[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 9, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 9, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_96[] = -{ - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 1, 4, 1, 0, 0 }, { 0, 11, 0, 1, 2, 0 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 1, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 634926132000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_97[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_98[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_100[] = -{ - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 1, 5, 1, 0, 0 }, { 0, 9, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 634294548000000000ULL, 60, { 0, 4, 0, 1, 1, 0 }, { 0, 9, 0, 1, 0, 0 }, } -}; - -static const TIME_ZONE_ENTRY TimeZoneTable[] = -{ - { - "Dateline Standard Time", 720, FALSE, "(UTC-12:00) International Date Line West", - "Dateline Standard Time", "Dateline Daylight Time", - NULL, 0 - }, - { - "UTC-11", 780, FALSE, "(UTC-11:00) Coordinated Universal Time-11", - "UTC-11", "UTC-11", - NULL, 0 - }, - { - "Hawaiian Standard Time", 840, FALSE, "(UTC-10:00) Hawaii", - "Hawaiian Standard Time", "Hawaiian Daylight Time", - NULL, 0 - }, - { - "Alaskan Standard Time", 900, TRUE, "(UTC-09:00) Alaska", - "Alaskan Standard Time", "Alaskan Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_3, 2 - }, - { - "Pacific Standard Time (Mexico)", 960, TRUE, "(UTC-08:00) Baja California", - "Pacific Standard Time (Mexico)", "Pacific Daylight Time (Mexico)", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_4, 1 - }, - { - "Pacific Standard Time", 960, TRUE, "(UTC-08:00) Pacific Time (US & Canada)", - "Pacific Standard Time", "Pacific Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_5, 2 - }, - { - "US Mountain Standard Time", 1020, FALSE, "(UTC-07:00) Arizona", - "US Mountain Standard Time", "US Mountain Daylight Time", - NULL, 0 - }, - { - "Mountain Standard Time (Mexico)", 1020, TRUE, "(UTC-07:00) Chihuahua, La Paz, Mazatlan", - "Mountain Standard Time (Mexico)", "Mountain Daylight Time (Mexico)", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_7, 1 - }, - { - "Mountain Standard Time", 1020, TRUE, "(UTC-07:00) Mountain Time (US & Canada)", - "Mountain Standard Time", "Mountain Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_8, 2 - }, - { - "Central America Standard Time", 1080, FALSE, "(UTC-06:00) Central America", - "Central America Standard Time", "Central America Daylight Time", - NULL, 0 - }, - { - "Central Standard Time", 1080, TRUE, "(UTC-06:00) Central Time (US & Canada)", - "Central Standard Time", "Central Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_10, 2 - }, - { - "Central Standard Time (Mexico)", 1080, TRUE, "(UTC-06:00) Guadalajara, Mexico City, Monterrey", - "Central Standard Time (Mexico)", "Central Daylight Time (Mexico)", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_11, 1 - }, - { - "Canada Central Standard Time", 1080, FALSE, "(UTC-06:00) Saskatchewan", - "Canada Central Standard Time", "Canada Central Daylight Time", - NULL, 0 - }, - { - "SA Pacific Standard Time", 1140, FALSE, "(UTC-05:00) Bogota, Lima, Quito", - "SA Pacific Standard Time", "SA Pacific Daylight Time", - NULL, 0 - }, - { - "Eastern Standard Time", 1140, TRUE, "(UTC-05:00) Eastern Time (US & Canada)", - "Eastern Standard Time", "Eastern Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_14, 2 - }, - { - "US Eastern Standard Time", 1140, TRUE, "(UTC-05:00) Indiana (East)", - "US Eastern Standard Time", "US Eastern Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_15, 2 - }, - { - "Venezuela Standard Time", 1170, FALSE, "(UTC-04:30) Caracas", - "Venezuela Standard Time", "Venezuela Daylight Time", - NULL, 0 - }, - { - "Paraguay Standard Time", 1200, TRUE, "(UTC-04:00) Asuncion", - "Paraguay Standard Time", "Paraguay Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_17, 14 - }, - { - "Atlantic Standard Time", 1200, TRUE, "(UTC-04:00) Atlantic Time (Canada)", - "Atlantic Standard Time", "Atlantic Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_18, 2 - }, - { - "Central Brazilian Standard Time", 1200, TRUE, "(UTC-04:00) Cuiaba", - "Central Brazilian Standard Time", "Central Brazilian Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_19, 35 - }, - { - "SA Western Standard Time", 1200, FALSE, "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", - "SA Western Standard Time", "SA Western Daylight Time", - NULL, 0 - }, - { - "Pacific SA Standard Time", 1200, TRUE, "(UTC-04:00) Santiago", - "Pacific SA Standard Time", "Pacific SA Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_21, 6 - }, - { - "Newfoundland Standard Time", 1230, TRUE, "(UTC-03:30) Newfoundland", - "Newfoundland Standard Time", "Newfoundland Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_22, 7 - }, - { - "E. South America Standard Time", 1260, TRUE, "(UTC-03:00) Brasilia", - "E. South America Standard Time", "E. South America Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_23, 35 - }, - { - "Argentina Standard Time", 1260, TRUE, "(UTC-03:00) Buenos Aires", - "Argentina Standard Time", "Argentina Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_24, 3 - }, - { - "SA Eastern Standard Time", 1260, FALSE, "(UTC-03:00) Cayenne, Fortaleza", - "SA Eastern Standard Time", "SA Eastern Daylight Time", - NULL, 0 - }, - { - "Greenland Standard Time", 1260, TRUE, "(UTC-03:00) Greenland", - "Greenland Standard Time", "Greenland Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_26, 14 - }, - { - "Montevideo Standard Time", 1260, TRUE, "(UTC-03:00) Montevideo", - "Montevideo Standard Time", "Montevideo Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_27, 2 - }, - { - "Bahia Standard Time", 1260, TRUE, "(UTC-03:00) Salvador", - "Bahia Standard Time", "Bahia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_28, 30 - }, - { - "UTC-02", 1320, FALSE, "(UTC-02:00) Coordinated Universal Time-02", - "UTC-02", "UTC-02", - NULL, 0 - }, - { - "Mid-Atlantic Standard Time", 1320, TRUE, "(UTC-02:00) Mid-Atlantic", - "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_30, 1 - }, - { - "Azores Standard Time", 1380, TRUE, "(UTC-01:00) Azores", - "Azores Standard Time", "Azores Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_31, 1 - }, - { - "Cape Verde Standard Time", 1380, FALSE, "(UTC-01:00) Cape Verde Is.", - "Cape Verde Standard Time", "Cape Verde Daylight Time", - NULL, 0 - }, - { - "Morocco Standard Time", 0, TRUE, "(UTC) Casablanca", - "Morocco Standard Time", "Morocco Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_33, 4 - }, - { - "UTC", 0, FALSE, "(UTC) Coordinated Universal Time", - "Coordinated Universal Time", "Coordinated Universal Time", - NULL, 0 - }, - { - "GMT Standard Time", 0, TRUE, "(UTC) Dublin, Edinburgh, Lisbon, London", - "GMT Standard Time", "GMT Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_35, 1 - }, - { - "Greenwich Standard Time", 0, FALSE, "(UTC) Monrovia, Reykjavik", - "Greenwich Standard Time", "Greenwich Daylight Time", - NULL, 0 - }, - { - "W. Europe Standard Time", 60, TRUE, "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", - "W. Europe Standard Time", "W. Europe Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_37, 1 - }, - { - "Central Europe Standard Time", 60, TRUE, "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", - "Central Europe Standard Time", "Central Europe Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_38, 1 - }, - { - "Romance Standard Time", 60, TRUE, "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", - "Romance Standard Time", "Romance Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_39, 1 - }, - { - "Central European Standard Time", 60, TRUE, "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", - "Central European Standard Time", "Central European Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_40, 1 - }, - { - "W. Central Africa Standard Time", 60, FALSE, "(UTC+01:00) West Central Africa", - "W. Central Africa Standard Time", "W. Central Africa Daylight Time", - NULL, 0 - }, - { - "Namibia Standard Time", 60, TRUE, "(UTC+01:00) Windhoek", - "Namibia Standard Time", "Namibia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_42, 2 - }, - { - "Jordan Standard Time", 120, TRUE, "(UTC+02:00) Amman", - "Jordan Standard Time", "Jordan Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_43, 2 - }, - { - "GTB Standard Time", 120, TRUE, "(UTC+02:00) Athens, Bucharest, Istanbul", - "GTB Standard Time", "GTB Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_44, 1 - }, - { - "Middle East Standard Time", 120, TRUE, "(UTC+02:00) Beirut", - "Middle East Standard Time", "Middle East Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_45, 13 - }, - { - "Egypt Standard Time", 120, TRUE, "(UTC+02:00) Cairo", - "Egypt Standard Time", "Egypt Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_46, 6 - }, - { - "Syria Standard Time", 120, TRUE, "(UTC+02:00) Damascus", - "Syria Standard Time", "Syria Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_47, 12 - }, - { - "South Africa Standard Time", 120, FALSE, "(UTC+02:00) Harare, Pretoria", - "South Africa Standard Time", "South Africa Daylight Time", - NULL, 0 - }, - { - "FLE Standard Time", 120, TRUE, "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", - "FLE Standard Time", "FLE Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_49, 1 - }, - { - "Turkey Standard Time", 120, TRUE, "(UTC+02:00) Istanbul", - "Turkey Standard Time", "Turkey Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_50, 3 - }, - { - "Israel Standard Time", 120, TRUE, "(UTC+02:00) Jerusalem", - "Jerusalem Standard Time", "Jerusalem Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_51, 18 - }, - { - "E. Europe Standard Time", 120, TRUE, "(UTC+02:00) Nicosia", - "E. Europe Standard Time", "E. Europe Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_52, 1 - }, - { - "Arabic Standard Time", 180, TRUE, "(UTC+03:00) Baghdad", - "Arabic Standard Time", "Arabic Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_53, 2 - }, - { - "Kaliningrad Standard Time", 180, TRUE, "(UTC+03:00) Kaliningrad, Minsk", - "Kaliningrad Standard Time", "Kaliningrad Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_54, 1 - }, - { - "Arab Standard Time", 180, FALSE, "(UTC+03:00) Kuwait, Riyadh", - "Arab Standard Time", "Arab Daylight Time", - NULL, 0 - }, - { - "E. Africa Standard Time", 180, FALSE, "(UTC+03:00) Nairobi", - "E. Africa Standard Time", "E. Africa Daylight Time", - NULL, 0 - }, - { - "Iran Standard Time", 210, TRUE, "(UTC+03:30) Tehran", - "Iran Standard Time", "Iran Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_57, 3 - }, - { - "Arabian Standard Time", 240, FALSE, "(UTC+04:00) Abu Dhabi, Muscat", - "Arabian Standard Time", "Arabian Daylight Time", - NULL, 0 - }, - { - "Azerbaijan Standard Time", 240, TRUE, "(UTC+04:00) Baku", - "Azerbaijan Standard Time", "Azerbaijan Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_59, 1 - }, - { - "Russian Standard Time", 240, TRUE, "(UTC+04:00) Moscow, St. Petersburg, Volgograd", - "Russian Standard Time", "Russian Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_60, 1 - }, - { - "Mauritius Standard Time", 240, TRUE, "(UTC+04:00) Port Louis", - "Mauritius Standard Time", "Mauritius Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_61, 2 - }, - { - "Georgian Standard Time", 240, FALSE, "(UTC+04:00) Tbilisi", - "Georgian Standard Time", "Georgian Daylight Time", - NULL, 0 - }, - { - "Caucasus Standard Time", 240, TRUE, "(UTC+04:00) Yerevan", - "Caucasus Standard Time", "Caucasus Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_63, 1 - }, - { - "Afghanistan Standard Time", 270, FALSE, "(UTC+04:30) Kabul", - "Afghanistan Standard Time", "Afghanistan Daylight Time", - NULL, 0 - }, - { - "Pakistan Standard Time", 300, TRUE, "(UTC+05:00) Islamabad, Karachi", - "Pakistan Standard Time", "Pakistan Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_65, 2 - }, - { - "West Asia Standard Time", 300, FALSE, "(UTC+05:00) Tashkent", - "West Asia Standard Time", "West Asia Daylight Time", - NULL, 0 - }, - { - "India Standard Time", 330, FALSE, "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", - "India Standard Time", "India Daylight Time", - NULL, 0 - }, - { - "Sri Lanka Standard Time", 330, FALSE, "(UTC+05:30) Sri Jayawardenepura", - "Sri Lanka Standard Time", "Sri Lanka Daylight Time", - NULL, 0 - }, - { - "Nepal Standard Time", 345, FALSE, "(UTC+05:45) Kathmandu", - "Nepal Standard Time", "Nepal Daylight Time", - NULL, 0 - }, - { - "Central Asia Standard Time", 360, FALSE, "(UTC+06:00) Astana", - "Central Asia Standard Time", "Central Asia Daylight Time", - NULL, 0 - }, - { - "Bangladesh Standard Time", 360, TRUE, "(UTC+06:00) Dhaka", - "Bangladesh Standard Time", "Bangladesh Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_71, 1 - }, - { - "Ekaterinburg Standard Time", 360, TRUE, "(UTC+06:00) Ekaterinburg", - "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_72, 1 - }, - { - "Myanmar Standard Time", 390, FALSE, "(UTC+06:30) Yangon (Rangoon)", - "Myanmar Standard Time", "Myanmar Daylight Time", - NULL, 0 - }, - { - "SE Asia Standard Time", 420, FALSE, "(UTC+07:00) Bangkok, Hanoi, Jakarta", - "SE Asia Standard Time", "SE Asia Daylight Time", - NULL, 0 - }, - { - "N. Central Asia Standard Time", 420, TRUE, "(UTC+07:00) Novosibirsk", - "N. Central Asia Standard Time", "N. Central Asia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_75, 1 - }, - { - "China Standard Time", 480, FALSE, "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", - "China Standard Time", "China Daylight Time", - NULL, 0 - }, - { - "North Asia Standard Time", 480, TRUE, "(UTC+08:00) Krasnoyarsk", - "North Asia Standard Time", "North Asia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_77, 1 - }, - { - "Singapore Standard Time", 480, FALSE, "(UTC+08:00) Kuala Lumpur, Singapore", - "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time", - NULL, 0 - }, - { - "W. Australia Standard Time", 480, TRUE, "(UTC+08:00) Perth", - "W. Australia Standard Time", "W. Australia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_79, 4 - }, - { - "Taipei Standard Time", 480, FALSE, "(UTC+08:00) Taipei", - "Taipei Standard Time", "Taipei Daylight Time", - NULL, 0 - }, - { - "Ulaanbaatar Standard Time", 480, FALSE, "(UTC+08:00) Ulaanbaatar", - "Ulaanbaatar Standard Time", "Ulaanbaatar Daylight Time", - NULL, 0 - }, - { - "North Asia East Standard Time", 540, TRUE, "(UTC+09:00) Irkutsk", - "North Asia East Standard Time", "North Asia East Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_82, 1 - }, - { - "Tokyo Standard Time", 540, FALSE, "(UTC+09:00) Osaka, Sapporo, Tokyo", - "Tokyo Standard Time", "Tokyo Daylight Time", - NULL, 0 - }, - { - "Korea Standard Time", 540, FALSE, "(UTC+09:00) Seoul", - "Korea Standard Time", "Korea Daylight Time", - NULL, 0 - }, - { - "Cen. Australia Standard Time", 570, TRUE, "(UTC+09:30) Adelaide", - "Cen. Australia Standard Time", "Cen. Australia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_85, 2 - }, - { - "AUS Central Standard Time", 570, FALSE, "(UTC+09:30) Darwin", - "AUS Central Standard Time", "AUS Central Daylight Time", - NULL, 0 - }, - { - "E. Australia Standard Time", 600, FALSE, "(UTC+10:00) Brisbane", - "E. Australia Standard Time", "E. Australia Daylight Time", - NULL, 0 - }, - { - "AUS Eastern Standard Time", 600, TRUE, "(UTC+10:00) Canberra, Melbourne, Sydney", - "AUS Eastern Standard Time", "AUS Eastern Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_88, 2 - }, - { - "West Pacific Standard Time", 600, FALSE, "(UTC+10:00) Guam, Port Moresby", - "West Pacific Standard Time", "West Pacific Daylight Time", - NULL, 0 - }, - { - "Tasmania Standard Time", 600, TRUE, "(UTC+10:00) Hobart", - "Tasmania Standard Time", "Tasmania Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_90, 2 - }, - { - "Yakutsk Standard Time", 600, TRUE, "(UTC+10:00) Yakutsk", - "Yakutsk Standard Time", "Yakutsk Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_91, 1 - }, - { - "Central Pacific Standard Time", 660, FALSE, "(UTC+11:00) Solomon Is., New Caledonia", - "Central Pacific Standard Time", "Central Pacific Daylight Time", - NULL, 0 - }, - { - "Vladivostok Standard Time", 660, TRUE, "(UTC+11:00) Vladivostok", - "Vladivostok Standard Time", "Vladivostok Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_93, 1 - }, - { - "New Zealand Standard Time", 720, TRUE, "(UTC+12:00) Auckland, Wellington", - "New Zealand Standard Time", "New Zealand Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_94, 3 - }, - { - "UTC+12", 720, FALSE, "(UTC+12:00) Coordinated Universal Time+12", - "UTC+12", "UTC+12", - NULL, 0 - }, - { - "Fiji Standard Time", 720, TRUE, "(UTC+12:00) Fiji", - "Fiji Standard Time", "Fiji Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_96, 5 - }, - { - "Magadan Standard Time", 720, TRUE, "(UTC+12:00) Magadan", - "Magadan Standard Time", "Magadan Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_97, 1 - }, - { - "Kamchatka Standard Time", 720, TRUE, "(UTC+12:00) Petropavlovsk-Kamchatsky - Old", - "Kamchatka Standard Time", "Kamchatka Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_98, 1 - }, - { - "Tonga Standard Time", 780, FALSE, "(UTC+13:00) Nuku'alofa", - "Tonga Standard Time", "Tonga Daylight Time", - NULL, 0 - }, - { - "Samoa Standard Time", 780, TRUE, "(UTC+13:00) Samoa", - "Samoa Standard Time", "Samoa Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_100, 2 - } -}; - -/* Table generated with WindowsZones.cs */ - -struct _WINDOWS_TZID_ENTRY -{ - const char* windows; - const char* tzid; -}; -typedef struct _WINDOWS_TZID_ENTRY WINDOWS_TZID_ENTRY; - -const WINDOWS_TZID_ENTRY WindowsTimeZoneIdTable[] = -{ - { "Afghanistan Standard Time", "Asia/Kabul" }, - { "Alaskan Standard Time", "America/Anchorage America/Juneau " - "America/Nome America/Sitka America/Yakutat" }, - { "Alaskan Standard Time", "America/Anchorage" }, - { "Arab Standard Time", "Asia/Aden" }, - { "Arab Standard Time", "Asia/Bahrain" }, - { "Arab Standard Time", "Asia/Kuwait" }, - { "Arab Standard Time", "Asia/Qatar" }, - { "Arab Standard Time", "Asia/Riyadh" }, - { "Arabian Standard Time", "Asia/Dubai" }, - { "Arabian Standard Time", "Asia/Muscat" }, - { "Arabian Standard Time", "Etc/GMT-4" }, - { "Arabic Standard Time", "Asia/Baghdad" }, - { "Argentina Standard Time", "America/Buenos_Aires America/Argentina/La_Rioja " - "America/Argentina/Rio_Gallegos America/Argentina/Salta " - "America/Argentina/San_Juan America/Argentina/San_Luis " - "America/Argentina/Tucuman America/Argentina/Ushuaia America/Catamarca " - "America/Cordoba America/Jujuy America/Mendoza" }, - { "Argentina Standard Time", "America/Buenos_Aires" }, - { "Atlantic Standard Time", "America/Halifax America/Glace_Bay " - "America/Goose_Bay America/Moncton" }, - { "Atlantic Standard Time", "America/Halifax" }, - { "Atlantic Standard Time", "America/Thule" }, - { "Atlantic Standard Time", "Atlantic/Bermuda" }, - { "AUS Central Standard Time", "Australia/Darwin" }, - { "AUS Eastern Standard Time", "Australia/Sydney Australia/Melbourne" }, - { "AUS Eastern Standard Time", "Australia/Sydney" }, - { "Azerbaijan Standard Time", "Asia/Baku" }, - { "Azores Standard Time", "America/Scoresbysund" }, - { "Azores Standard Time", "Atlantic/Azores" }, - { "Bahia Standard Time", "America/Bahia" }, - { "Bangladesh Standard Time", "Asia/Dhaka" }, - { "Bangladesh Standard Time", "Asia/Thimphu" }, - { "Canada Central Standard Time", "America/Regina America/Swift_Current" }, - { "Canada Central Standard Time", "America/Regina" }, - { "Cape Verde Standard Time", "Atlantic/Cape_Verde" }, - { "Cape Verde Standard Time", "Etc/GMT+1" }, - { "Caucasus Standard Time", "Asia/Yerevan" }, - { "Cen. Australia Standard Time", "Australia/Adelaide Australia/Broken_Hill" }, - { "Cen. Australia Standard Time", "Australia/Adelaide" }, - { "Central America Standard Time", "America/Belize" }, - { "Central America Standard Time", "America/Costa_Rica" }, - { "Central America Standard Time", "America/El_Salvador" }, - { "Central America Standard Time", "America/Guatemala" }, - { "Central America Standard Time", "America/Managua" }, - { "Central America Standard Time", "America/Tegucigalpa" }, - { "Central America Standard Time", "Etc/GMT+6" }, - { "Central America Standard Time", "Pacific/Galapagos" }, - { "Central Asia Standard Time", "Antarctica/Vostok" }, - { "Central Asia Standard Time", "Asia/Almaty Asia/Qyzylorda" }, - { "Central Asia Standard Time", "Asia/Almaty" }, - { "Central Asia Standard Time", "Asia/Bishkek" }, - { "Central Asia Standard Time", "Etc/GMT-6" }, - { "Central Asia Standard Time", "Indian/Chagos" }, - { "Central Brazilian Standard Time", "America/Cuiaba America/Campo_Grande" }, - { "Central Brazilian Standard Time", "America/Cuiaba" }, - { "Central Europe Standard Time", "Europe/Belgrade" }, - { "Central Europe Standard Time", "Europe/Bratislava" }, - { "Central Europe Standard Time", "Europe/Budapest" }, - { "Central Europe Standard Time", "Europe/Ljubljana" }, - { "Central Europe Standard Time", "Europe/Podgorica" }, - { "Central Europe Standard Time", "Europe/Prague" }, - { "Central Europe Standard Time", "Europe/Tirane" }, - { "Central European Standard Time", "Europe/Sarajevo" }, - { "Central European Standard Time", "Europe/Skopje" }, - { "Central European Standard Time", "Europe/Warsaw" }, - { "Central European Standard Time", "Europe/Zagreb" }, - { "Central Pacific Standard Time", "Antarctica/Macquarie" }, - { "Central Pacific Standard Time", "Etc/GMT-11" }, - { "Central Pacific Standard Time", "Pacific/Efate" }, - { "Central Pacific Standard Time", "Pacific/Guadalcanal" }, - { "Central Pacific Standard Time", "Pacific/Noumea" }, - { "Central Pacific Standard Time", "Pacific/Ponape Pacific/Kosrae" }, - { "Central Standard Time (Mexico)", "America/Mexico_City America/Bahia_Banderas " - "America/Cancun America/Merida America/Monterrey" }, - { "Central Standard Time (Mexico)", "America/Mexico_City" }, - { "Central Standard Time", "America/Chicago America/Indiana/Knox " - "America/Indiana/Tell_City America/Menominee " - "America/North_Dakota/Beulah America/North_Dakota/Center " - "America/North_Dakota/New_Salem" }, - { "Central Standard Time", "America/Chicago" }, - { "Central Standard Time", "America/Matamoros" }, - { "Central Standard Time", "America/Winnipeg America/Rainy_River " - "America/Rankin_Inlet America/Resolute" }, - { "Central Standard Time", "CST6CDT" }, - { "China Standard Time", "Asia/Hong_Kong" }, - { "China Standard Time", "Asia/Macau" }, - { "China Standard Time", "Asia/Shanghai Asia/Chongqing Asia/Harbin Asia/Kashgar Asia/Urumqi" }, - { "China Standard Time", "Asia/Shanghai" }, - { "Dateline Standard Time", "Etc/GMT+12" }, - { "E. Africa Standard Time", "Africa/Addis_Ababa" }, - { "E. Africa Standard Time", "Africa/Asmera" }, - { "E. Africa Standard Time", "Africa/Dar_es_Salaam" }, - { "E. Africa Standard Time", "Africa/Djibouti" }, - { "E. Africa Standard Time", "Africa/Juba" }, - { "E. Africa Standard Time", "Africa/Kampala" }, - { "E. Africa Standard Time", "Africa/Khartoum" }, - { "E. Africa Standard Time", "Africa/Mogadishu" }, - { "E. Africa Standard Time", "Africa/Nairobi" }, - { "E. Africa Standard Time", "Antarctica/Syowa" }, - { "E. Africa Standard Time", "Etc/GMT-3" }, - { "E. Africa Standard Time", "Indian/Antananarivo" }, - { "E. Africa Standard Time", "Indian/Comoro" }, - { "E. Africa Standard Time", "Indian/Mayotte" }, - { "E. Australia Standard Time", "Australia/Brisbane Australia/Lindeman" }, - { "E. Australia Standard Time", "Australia/Brisbane" }, - { "E. Europe Standard Time", "Asia/Nicosia" }, - { "E. South America Standard Time", "America/Sao_Paulo" }, - { "Eastern Standard Time", "America/Grand_Turk" }, - { "Eastern Standard Time", "America/Nassau" }, - { "Eastern Standard Time", "America/New_York America/Detroit " - "America/Indiana/Petersburg America/Indiana/Vincennes " - "America/Indiana/Winamac America/Kentucky/Monticello America/Louisville" }, - { "Eastern Standard Time", "America/New_York" }, - { "Eastern Standard Time", "America/Toronto America/Iqaluit America/Montreal " - "America/Nipigon America/Pangnirtung America/Thunder_Bay" }, - { "Eastern Standard Time", "EST5EDT" }, - { "Egypt Standard Time", "Africa/Cairo" }, - { "Egypt Standard Time", "Asia/Gaza Asia/Hebron" }, - { "Ekaterinburg Standard Time", "Asia/Yekaterinburg" }, - { "Fiji Standard Time", "Pacific/Fiji" }, - { "FLE Standard Time", "Europe/Helsinki" }, - { "FLE Standard Time", "Europe/Kiev Europe/Simferopol Europe/Uzhgorod Europe/Zaporozhye" }, - { "FLE Standard Time", "Europe/Kiev" }, - { "FLE Standard Time", "Europe/Mariehamn" }, - { "FLE Standard Time", "Europe/Riga" }, - { "FLE Standard Time", "Europe/Sofia" }, - { "FLE Standard Time", "Europe/Tallinn" }, - { "FLE Standard Time", "Europe/Vilnius" }, - { "Georgian Standard Time", "Asia/Tbilisi" }, - { "GMT Standard Time", "Atlantic/Canary" }, - { "GMT Standard Time", "Atlantic/Faeroe" }, - { "GMT Standard Time", "Europe/Dublin" }, - { "GMT Standard Time", "Europe/Guernsey" }, - { "GMT Standard Time", "Europe/Isle_of_Man" }, - { "GMT Standard Time", "Europe/Jersey" }, - { "GMT Standard Time", "Europe/Lisbon Atlantic/Madeira" }, - { "GMT Standard Time", "Europe/London" }, - { "Greenland Standard Time", "America/Godthab" }, - { "Greenwich Standard Time", "Africa/Abidjan" }, - { "Greenwich Standard Time", "Africa/Accra" }, - { "Greenwich Standard Time", "Africa/Bamako" }, - { "Greenwich Standard Time", "Africa/Banjul" }, - { "Greenwich Standard Time", "Africa/Bissau" }, - { "Greenwich Standard Time", "Africa/Conakry" }, - { "Greenwich Standard Time", "Africa/Dakar" }, - { "Greenwich Standard Time", "Africa/El_Aaiun" }, - { "Greenwich Standard Time", "Africa/Freetown" }, - { "Greenwich Standard Time", "Africa/Lome" }, - { "Greenwich Standard Time", "Africa/Monrovia" }, - { "Greenwich Standard Time", "Africa/Nouakchott" }, - { "Greenwich Standard Time", "Africa/Ouagadougou" }, - { "Greenwich Standard Time", "Africa/Sao_Tome" }, - { "Greenwich Standard Time", "Atlantic/Reykjavik" }, - { "Greenwich Standard Time", "Atlantic/St_Helena" }, - { "GTB Standard Time", "Europe/Athens" }, - { "GTB Standard Time", "Europe/Bucharest" }, - { "GTB Standard Time", "Europe/Chisinau" }, - { "GTB Standard Time", "Europe/Istanbul" }, - { "Hawaiian Standard Time", "Etc/GMT+10" }, - { "Hawaiian Standard Time", "Pacific/Fakaofo" }, - { "Hawaiian Standard Time", "Pacific/Honolulu" }, - { "Hawaiian Standard Time", "Pacific/Johnston" }, - { "Hawaiian Standard Time", "Pacific/Rarotonga" }, - { "Hawaiian Standard Time", "Pacific/Tahiti" }, - { "India Standard Time", "Asia/Calcutta Asia/Kolkata" }, - { "Iran Standard Time", "Asia/Tehran" }, - { "Israel Standard Time", "Asia/Jerusalem" }, - { "Jordan Standard Time", "Asia/Amman" }, - { "Kaliningrad Standard Time", "Europe/Kaliningrad" }, - { "Kaliningrad Standard Time", "Europe/Minsk" }, - { "Korea Standard Time", "Asia/Pyongyang" }, - { "Korea Standard Time", "Asia/Seoul" }, - { "Magadan Standard Time", "Asia/Magadan Asia/Anadyr Asia/Kamchatka" }, - { "Magadan Standard Time", "Asia/Magadan" }, - { "Mauritius Standard Time", "Indian/Mahe" }, - { "Mauritius Standard Time", "Indian/Mauritius" }, - { "Mauritius Standard Time", "Indian/Reunion" }, - { "Middle East Standard Time", "Asia/Beirut" }, - { "Montevideo Standard Time", "America/Montevideo" }, - { "Morocco Standard Time", "Africa/Casablanca" }, - { "Mountain Standard Time (Mexico)", "America/Chihuahua America/Mazatlan" }, - { "Mountain Standard Time (Mexico)", "America/Chihuahua" }, - { "Mountain Standard Time", "America/Denver America/Boise America/Shiprock" }, - { "Mountain Standard Time", "America/Denver" }, - { "Mountain Standard Time", "America/Edmonton " - "America/Cambridge_Bay America/Inuvik America/Yellowknife" }, - { "Mountain Standard Time", "America/Ojinaga" }, - { "Mountain Standard Time", "MST7MDT" }, - { "Myanmar Standard Time", "Asia/Rangoon" }, - { "Myanmar Standard Time", "Indian/Cocos" }, - { "N. Central Asia Standard Time", "Asia/Novosibirsk Asia/Novokuznetsk Asia/Omsk" }, - { "N. Central Asia Standard Time", "Asia/Novosibirsk" }, - { "Namibia Standard Time", "Africa/Windhoek" }, - { "Nepal Standard Time", "Asia/Katmandu Asia/Kathmandu" }, - { "New Zealand Standard Time", "Antarctica/South_Pole Antarctica/McMurdo" }, - { "New Zealand Standard Time", "Pacific/Auckland" }, - { "Newfoundland Standard Time", "America/St_Johns" }, - { "North Asia East Standard Time", "Asia/Irkutsk" }, - { "North Asia Standard Time", "Asia/Krasnoyarsk" }, - { "Pacific SA Standard Time", "America/Santiago" }, - { "Pacific SA Standard Time", "Antarctica/Palmer" }, - { "Pacific Standard Time (Mexico)", "America/Santa_Isabel" }, - { "Pacific Standard Time", "America/Los_Angeles" }, - { "Pacific Standard Time", "America/Tijuana America/Ensenada" }, - { "Pacific Standard Time", "America/Vancouver America/Dawson America/Whitehorse" }, - { "Pacific Standard Time", "PST8PDT" }, - { "Pakistan Standard Time", "Asia/Karachi" }, - { "Paraguay Standard Time", "America/Asuncion" }, - { "Romance Standard Time", "Europe/Brussels" }, - { "Romance Standard Time", "Europe/Copenhagen" }, - { "Romance Standard Time", "Europe/Madrid Africa/Ceuta" }, - { "Romance Standard Time", "Europe/Paris" }, - { "Russian Standard Time", "Europe/Moscow Europe/Samara Europe/Volgograd" }, - { "Russian Standard Time", "Europe/Moscow" }, - { "SA Eastern Standard Time", "America/Cayenne" }, - { "SA Eastern Standard Time", "America/Fortaleza America/Araguaina " - "America/Belem America/Maceio America/Recife America/Santarem" }, - { "SA Eastern Standard Time", "America/Paramaribo" }, - { "SA Eastern Standard Time", "Antarctica/Rothera" }, - { "SA Eastern Standard Time", "Etc/GMT+3" }, - { "SA Pacific Standard Time", "America/Bogota" }, - { "SA Pacific Standard Time", "America/Cayman" }, - { "SA Pacific Standard Time", "America/Coral_Harbour" }, - { "SA Pacific Standard Time", "America/Guayaquil" }, - { "SA Pacific Standard Time", "America/Jamaica" }, - { "SA Pacific Standard Time", "America/Lima" }, - { "SA Pacific Standard Time", "America/Panama" }, - { "SA Pacific Standard Time", "America/Port-au-Prince" }, - { "SA Pacific Standard Time", "Etc/GMT+5" }, - { "SA Western Standard Time", "America/Anguilla" }, - { "SA Western Standard Time", "America/Antigua" }, - { "SA Western Standard Time", "America/Aruba" }, - { "SA Western Standard Time", "America/Barbados" }, - { "SA Western Standard Time", "America/Blanc-Sablon" }, - { "SA Western Standard Time", "America/Curacao" }, - { "SA Western Standard Time", "America/Dominica" }, - { "SA Western Standard Time", "America/Grenada" }, - { "SA Western Standard Time", "America/Guadeloupe" }, - { "SA Western Standard Time", "America/Guyana" }, - { "SA Western Standard Time", "America/La_Paz" }, - { "SA Western Standard Time", "America/Manaus America/Boa_Vista " - "America/Eirunepe America/Porto_Velho America/Rio_Branco" }, - { "SA Western Standard Time", "America/Marigot" }, - { "SA Western Standard Time", "America/Martinique" }, - { "SA Western Standard Time", "America/Montserrat" }, - { "SA Western Standard Time", "America/Port_of_Spain" }, - { "SA Western Standard Time", "America/Puerto_Rico" }, - { "SA Western Standard Time", "America/Santo_Domingo" }, - { "SA Western Standard Time", "America/St_Barthelemy" }, - { "SA Western Standard Time", "America/St_Kitts" }, - { "SA Western Standard Time", "America/St_Lucia" }, - { "SA Western Standard Time", "America/St_Thomas" }, - { "SA Western Standard Time", "America/St_Vincent" }, - { "SA Western Standard Time", "America/Tortola" }, - { "SA Western Standard Time", "Etc/GMT+4" }, - { "Samoa Standard Time", "Pacific/Apia Pacific/Samoa" }, - { "SE Asia Standard Time", "Antarctica/Davis" }, - { "SE Asia Standard Time", "Asia/Bangkok" }, - { "SE Asia Standard Time", "Asia/Hovd" }, - { "SE Asia Standard Time", "Asia/Jakarta Asia/Pontianak" }, - { "SE Asia Standard Time", "Asia/Phnom_Penh" }, - { "SE Asia Standard Time", "Asia/Saigon Asia/Ho_Chi_Minh" }, - { "SE Asia Standard Time", "Asia/Vientiane" }, - { "SE Asia Standard Time", "Etc/GMT-7" }, - { "SE Asia Standard Time", "Indian/Christmas" }, - { "Singapore Standard Time", "Asia/Brunei" }, - { "Singapore Standard Time", "Asia/Kuala_Lumpur Asia/Kuching" }, - { "Singapore Standard Time", "Asia/Makassar" }, - { "Singapore Standard Time", "Asia/Manila" }, - { "Singapore Standard Time", "Asia/Singapore" }, - { "Singapore Standard Time", "Etc/GMT-8" }, - { "South Africa Standard Time", "Africa/Blantyre" }, - { "South Africa Standard Time", "Africa/Bujumbura" }, - { "South Africa Standard Time", "Africa/Gaborone" }, - { "South Africa Standard Time", "Africa/Harare" }, - { "South Africa Standard Time", "Africa/Johannesburg" }, - { "South Africa Standard Time", "Africa/Kigali" }, - { "South Africa Standard Time", "Africa/Lubumbashi" }, - { "South Africa Standard Time", "Africa/Lusaka" }, - { "South Africa Standard Time", "Africa/Maputo" }, - { "South Africa Standard Time", "Africa/Maseru" }, - { "South Africa Standard Time", "Africa/Mbabane" }, - { "South Africa Standard Time", "Africa/Tripoli" }, - { "South Africa Standard Time", "Etc/GMT-2" }, - { "Sri Lanka Standard Time", "Asia/Colombo" }, - { "Syria Standard Time", "Asia/Damascus" }, - { "Taipei Standard Time", "Asia/Taipei" }, - { "Tasmania Standard Time", "Australia/Hobart Australia/Currie" }, - { "Tasmania Standard Time", "Australia/Hobart" }, - { "Tokyo Standard Time", "Asia/Dili" }, - { "Tokyo Standard Time", "Asia/Jayapura" }, - { "Tokyo Standard Time", "Asia/Tokyo" }, - { "Tokyo Standard Time", "Etc/GMT-9" }, - { "Tokyo Standard Time", "Pacific/Palau" }, - { "Tonga Standard Time", "Etc/GMT-13" }, - { "Tonga Standard Time", "Pacific/Enderbury" }, - { "Tonga Standard Time", "Pacific/Tongatapu" }, - /* { "Turkey Standard Time", "Europe/Istanbul" }, */ - { "Ulaanbaatar Standard Time", "Asia/Ulaanbaatar Asia/Choibalsan" }, - { "Ulaanbaatar Standard Time", "Asia/Ulaanbaatar" }, - { "US Eastern Standard Time", "America/Indianapolis " - "America/Indiana/Marengo America/Indiana/Vevay" }, - { "US Eastern Standard Time", "America/Indianapolis" }, - { "US Mountain Standard Time", "America/Dawson_Creek" }, - { "US Mountain Standard Time", "America/Hermosillo" }, - { "US Mountain Standard Time", "America/Phoenix" }, - { "US Mountain Standard Time", "Etc/GMT+7" }, - { "UTC", "America/Danmarkshavn" }, - { "UTC", "Etc/GMT" }, - { "UTC+12", "Etc/GMT-12" }, - { "UTC+12", "Pacific/Funafuti" }, - { "UTC+12", "Pacific/Majuro Pacific/Kwajalein" }, - { "UTC+12", "Pacific/Nauru" }, - { "UTC+12", "Pacific/Tarawa" }, - { "UTC+12", "Pacific/Wake" }, - { "UTC+12", "Pacific/Wallis" }, - { "UTC-02", "America/Noronha" }, - { "UTC-02", "Atlantic/South_Georgia" }, - { "UTC-02", "Etc/GMT+2" }, - { "UTC-11", "Etc/GMT+11" }, - { "UTC-11", "Pacific/Midway" }, - { "UTC-11", "Pacific/Niue" }, - { "UTC-11", "Pacific/Pago_Pago" }, - { "Venezuela Standard Time", "America/Caracas" }, - { "Vladivostok Standard Time", "Asia/Vladivostok Asia/Sakhalin" }, - { "Vladivostok Standard Time", "Asia/Vladivostok" }, - { "W. Australia Standard Time", "Antarctica/Casey" }, - { "W. Australia Standard Time", "Australia/Perth" }, - { "W. Central Africa Standard Time", "Africa/Algiers" }, - { "W. Central Africa Standard Time", "Africa/Bangui" }, - { "W. Central Africa Standard Time", "Africa/Brazzaville" }, - { "W. Central Africa Standard Time", "Africa/Douala" }, - { "W. Central Africa Standard Time", "Africa/Kinshasa" }, - { "W. Central Africa Standard Time", "Africa/Lagos" }, - { "W. Central Africa Standard Time", "Africa/Libreville" }, - { "W. Central Africa Standard Time", "Africa/Luanda" }, - { "W. Central Africa Standard Time", "Africa/Malabo" }, - { "W. Central Africa Standard Time", "Africa/Ndjamena" }, - { "W. Central Africa Standard Time", "Africa/Niamey" }, - { "W. Central Africa Standard Time", "Africa/Porto-Novo" }, - { "W. Central Africa Standard Time", "Africa/Tunis" }, - { "W. Central Africa Standard Time", "Etc/GMT-1" }, - { "W. Europe Standard Time", "Arctic/Longyearbyen" }, - { "W. Europe Standard Time", "Europe/Amsterdam" }, - { "W. Europe Standard Time", "Europe/Andorra" }, - { "W. Europe Standard Time", "Europe/Berlin" }, - { "W. Europe Standard Time", "Europe/Gibraltar" }, - { "W. Europe Standard Time", "Europe/Luxembourg" }, - { "W. Europe Standard Time", "Europe/Malta" }, - { "W. Europe Standard Time", "Europe/Monaco" }, - { "W. Europe Standard Time", "Europe/Oslo" }, - { "W. Europe Standard Time", "Europe/Rome" }, - { "W. Europe Standard Time", "Europe/San_Marino" }, - { "W. Europe Standard Time", "Europe/Stockholm" }, - { "W. Europe Standard Time", "Europe/Vaduz" }, - { "W. Europe Standard Time", "Europe/Vatican" }, - { "W. Europe Standard Time", "Europe/Vienna" }, - { "W. Europe Standard Time", "Europe/Zurich" }, - { "West Asia Standard Time", "Antarctica/Mawson" }, - { "West Asia Standard Time", "Asia/Ashgabat" }, - { "West Asia Standard Time", "Asia/Dushanbe" }, - { "West Asia Standard Time", "Asia/Oral Asia/Aqtau Asia/Aqtobe" }, - { "West Asia Standard Time", "Asia/Tashkent Asia/Samarkand" }, - { "West Asia Standard Time", "Asia/Tashkent" }, - { "West Asia Standard Time", "Etc/GMT-5" }, - { "West Asia Standard Time", "Indian/Kerguelen" }, - { "West Asia Standard Time", "Indian/Maldives" }, - { "West Pacific Standard Time", "Antarctica/DumontDUrville" }, - { "West Pacific Standard Time", "Etc/GMT-10" }, - { "West Pacific Standard Time", "Pacific/Guam" }, - { "West Pacific Standard Time", "Pacific/Port_Moresby" }, - { "West Pacific Standard Time", "Pacific/Saipan" }, - { "West Pacific Standard Time", "Pacific/Truk" }, - { "Yakutsk Standard Time", "Asia/Yakutsk" } -}; - -static UINT64 freerdp_windows_gmtime() -{ - time_t unix_time; - UINT64 windows_time; - - time(&unix_time); - windows_time = unix_time; - windows_time *= 10000000; - windows_time += 621355968000000000ULL; - - return windows_time; -} - -char* freerdp_get_unix_timezone_identifier() -{ -#ifndef _WIN32 - FILE* fp; - ssize_t len; - char* tz_env; - size_t length; - char* tzid = NULL; - char buf[1024]; - - tz_env = getenv("TZ"); - - if (tz_env != NULL) - { - tzid = _strdup(tz_env); - return tzid; - } - -#if defined(__FreeBSD__) || defined(__OpenBSD__) - fp = fopen("/var/db/zoneinfo", "r"); -#else - fp = fopen("/etc/timezone", "r"); -#endif - if (fp != NULL) - { - fseek(fp, 0, SEEK_END); - length = ftell(fp); - fseek(fp, 0, SEEK_SET); - - if (length < 2) - { - fclose(fp) ; - return NULL; - } - - tzid = (char*) malloc(length + 1); - if (!tzid) - { - fclose(fp); - return NULL; - } - - if (fread(tzid, length, 1, fp) != 1) - { - free(tzid); - fclose(fp); - return NULL; - } - tzid[length] = '\0'; - - if (tzid[length - 1] == '\n') - tzid[length - 1] = '\0'; - - fclose(fp); - - return tzid; - } - - /* - * On linux distros such as Redhat or Archlinux, a symlink at /etc/localtime - * will point to /usr/share/zoneinfo/region/place where region/place could be - * America/Montreal for example. - */ - - if ((len = readlink("/etc/localtime", buf, sizeof(buf) - 1)) != -1) - { - int num = 0; - int pos = len; - - buf[len] = '\0'; - - /* find the position of the 2nd to last "/" */ - - while (num < 2) - { - if (pos == 0) - break; - - pos -= 1; - - if (buf[pos] == '/') - num++; - } - - tzid = (char*) malloc(len - pos + 1); - if (!tzid) - return NULL; - - strncpy(tzid, buf + pos + 1, len - pos); - - return tzid; - } - - WLog_ERR(TAG, "Unable to detect time zone"); - return tzid; -#else - return 0; -#endif -} - -BOOL freerdp_match_unix_timezone_identifier_with_list(const char* tzid, const char* list) -{ - char* p; - char* list_copy; - - list_copy = _strdup(list); - if (!list_copy) - return FALSE; - - p = strtok(list_copy, " "); - - while (p != NULL) - { - if (strcmp(p, tzid) == 0) - { - free(list_copy); - return TRUE; - } - - p = strtok(NULL, " "); - } - - free(list_copy); - - return FALSE; -} - -TIME_ZONE_ENTRY* freerdp_detect_windows_time_zone(UINT32 bias) -{ - int i, j; - char* tzid; - TIME_ZONE_ENTRY* timezone; - - tzid = freerdp_get_unix_timezone_identifier(); - - if (tzid == NULL) - return NULL; - - for (i = 0; i < ARRAYSIZE(TimeZoneTable); i++) - { - for (j = 0; j < ARRAYSIZE(WindowsTimeZoneIdTable); j++) - { - if (strcmp(TimeZoneTable[i].Id, WindowsTimeZoneIdTable[j].windows) != 0) - continue; - - if (freerdp_match_unix_timezone_identifier_with_list(tzid, WindowsTimeZoneIdTable[j].tzid)) - { - free(tzid); - - timezone = (TIME_ZONE_ENTRY*) malloc(sizeof(TIME_ZONE_ENTRY)); - if (!timezone) - return NULL; - memcpy((void*) timezone, (void*) &TimeZoneTable[i], sizeof(TIME_ZONE_ENTRY)); - timezone->Bias = bias; - return timezone; - } - } - } - - WLog_ERR(TAG, "Unable to find a match for unix timezone: %s", tzid); - free(tzid); - return NULL; -} - -TIME_ZONE_RULE_ENTRY* freerdp_get_current_time_zone_rule(TIME_ZONE_RULE_ENTRY* rules, UINT32 count) -{ - int i; - UINT64 windows_time; - - windows_time = freerdp_windows_gmtime(); - - for (i = 0; i < (int) count; i++) - { - if ((rules[i].TicksStart >= windows_time) && (windows_time >= rules[i].TicksEnd)) - { - /*WLog_ERR(TAG, "Got rule %d from table at %p with count %u", i, rules, count);*/ - return &rules[i]; - } - } - - WLog_ERR(TAG, "Unable to get current timezone rule"); - return NULL; -} - -void freerdp_time_zone_detect(TIME_ZONE_INFO* clientTimeZone) -{ - time_t t; - TIME_ZONE_ENTRY* tz; - struct tm* local_time; - - clientTimeZone->standardBias = 0; - - time(&t); - local_time = localtime(&t); - -#ifdef HAVE_TM_GMTOFF - #if defined(__FreeBSD__) || defined(__OpenBSD__) - if (local_time->tm_gmtoff >= 0) - clientTimeZone->bias = (UINT32) (local_time->tm_gmtoff / 60); - else - clientTimeZone->bias = (UINT32) (1440 + (INT32) (local_time->tm_gmtoff / 60)); - #else - clientTimeZone->bias = timezone / 60; - #endif - DEBUG_TIMEZONE("tzname[std]: %s, tzname[dst]: %s, timezone: %ld, Daylight: %d", tzname[0], tzname[1], timezone, daylight); -#elif defined(sun) - if (local_time->tm_isdst > 0) - clientTimeZone->bias = (UINT32) (altzone / 3600); - else - clientTimeZone->bias = (UINT32) (timezone / 3600); -#else - clientTimeZone->bias = 0; -#endif - - tz = freerdp_detect_windows_time_zone(clientTimeZone->bias); - - if (tz!= NULL) - { - DEBUG_TIMEZONE("tz: Id='%s' Bias=%d DST=%d dn='%s' sn='%s' dln='%s'", - tz->Id, tz->Bias, tz->SupportsDST, tz->DisplayName, - tz->StandardName, tz->DaylightName); - - sprintf(clientTimeZone->standardName, "%s", tz->StandardName); - sprintf(clientTimeZone->daylightName, "%s", tz->DaylightName); - - if ((tz->SupportsDST) && (tz->RuleTableCount > 0)) - { - TIME_ZONE_RULE_ENTRY* rule; - rule = freerdp_get_current_time_zone_rule(tz->RuleTable, tz->RuleTableCount); - - if (rule != NULL) - { - clientTimeZone->daylightBias = -rule->DaylightDelta; - - clientTimeZone->standardDate.wYear = rule->StandardDate.wYear; - clientTimeZone->standardDate.wMonth = rule->StandardDate.wMonth; - clientTimeZone->standardDate.wDayOfWeek = rule->StandardDate.wDayOfWeek; - clientTimeZone->standardDate.wDay = rule->StandardDate.wDay; - clientTimeZone->standardDate.wHour = rule->StandardDate.wHour; - clientTimeZone->standardDate.wMinute = rule->StandardDate.wMinute; - clientTimeZone->standardDate.wSecond = rule->StandardDate.wSecond; - clientTimeZone->standardDate.wMilliseconds = rule->StandardDate.wMilliseconds; - - clientTimeZone->daylightDate.wYear = rule->DaylightDate.wYear; - clientTimeZone->daylightDate.wMonth = rule->DaylightDate.wMonth; - clientTimeZone->daylightDate.wDayOfWeek = rule->DaylightDate.wDayOfWeek; - clientTimeZone->daylightDate.wDay = rule->DaylightDate.wDay; - clientTimeZone->daylightDate.wHour = rule->DaylightDate.wHour; - clientTimeZone->daylightDate.wMinute = rule->DaylightDate.wMinute; - clientTimeZone->daylightDate.wSecond = rule->DaylightDate.wSecond; - clientTimeZone->daylightDate.wMilliseconds = rule->DaylightDate.wMilliseconds; - } - } - free(tz); - } - else - { - /* could not detect timezone, fallback to using GMT */ - DEBUG_TIMEZONE("tz not found, using GMT."); - sprintf(clientTimeZone->standardName, "%s", "GMT Standard Time"); - sprintf(clientTimeZone->daylightName, "%s", "GMT Daylight Time"); - } -} diff --git a/libfreerdp/primitives/prim_colors_opt.c b/libfreerdp/primitives/prim_colors_opt.c index 0d3dd4d..e9505da 100644 --- a/libfreerdp/primitives/prim_colors_opt.c +++ b/libfreerdp/primitives/prim_colors_opt.c @@ -232,8 +232,8 @@ pstatus_t sse2_RGBToYCbCr_16s16s_P3P3( pDst, dstStep, roi); } - min = _mm_set1_epi16(-128 << 5); - max = _mm_set1_epi16(127 << 5); + min = _mm_set1_epi16(-128 * 32); + max = _mm_set1_epi16(127 * 32); r_buf = (__m128i*) (pSrc[0]); g_buf = (__m128i*) (pSrc[1]); diff --git a/packaging/deb/freerdp-nightly/rules b/packaging/deb/freerdp-nightly/rules index 963cbbf..c9e0a96 100755 --- a/packaging/deb/freerdp-nightly/rules +++ b/packaging/deb/freerdp-nightly/rules @@ -36,6 +36,7 @@ override_dh_strip: override_dh_install: mkdir -p debian/tmp/opt/freerdp-nightly/lib/cmake/ + rm -rf debian/tmp/opt/freerdp-nightly/lib/freerdp/*.a dh_install --fail-missing diff --git a/rdtk/CMakeLists.txt b/rdtk/CMakeLists.txt index 6faea30..08b7648 100644 --- a/rdtk/CMakeLists.txt +++ b/rdtk/CMakeLists.txt @@ -73,6 +73,7 @@ if(WITH_SAMPLE) endif() # Exporting +set(RDTK_INCLUDE_DIR "include/rdtk${RDTK_VERSION_MAJOR}") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rdtk.pc.in ${CMAKE_CURRENT_BINARY_DIR}/rdtk${RDTK_VERSION_MAJOR}.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/rdtk${RDTK_VERSION_MAJOR}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) @@ -81,8 +82,6 @@ if(${CMAKE_VERSION} VERSION_GREATER "2.8.10") set(RDTK_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/RdTk${RDTK_VERSION_MAJOR}") - set(RDTK_INCLUDE_DIR "include/rdtk${RDTK_VERSION_MAJOR}") - configure_package_config_file(RdTkConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/RdTkConfig.cmake INSTALL_DESTINATION ${RDTK_CMAKE_INSTALL_DIR} PATH_VARS RDTK_INCLUDE_DIR) diff --git a/rdtk/librdtk/CMakeLists.txt b/rdtk/librdtk/CMakeLists.txt index e12f162..b6caf80 100644 --- a/rdtk/librdtk/CMakeLists.txt +++ b/rdtk/librdtk/CMakeLists.txt @@ -65,7 +65,7 @@ endif() target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT RdTkTargets) -if (MSVC AND BUILD_SHARED_LIBS) +if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS) install(FILES ${CMAKE_PDB_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols) endif() diff --git a/scripts/android-build-common.sh b/scripts/android-build-common.sh new file mode 100644 index 0000000..5a2bcfb --- /dev/null +++ b/scripts/android-build-common.sh @@ -0,0 +1,252 @@ +#!/bin/bash + +if [ -z $BUILD_ARCH ]; then + BUILD_ARCH="armeabi armeabi-v7a mips mips64 x86 x86_64 arm64-v8a" +fi + +if [ -z $NDK_TARGET ]; then + NDK_TARGET=21 +fi + +if [ -z $ANDROID_NDK ]; then + ANDROID_NDK="missing" +fi + +if [ -z $BUILD_DST ]; then + BUILD_DST=$(pwd)/libs +fi + +if [ -z $BUILD_SRC ]; then + BUILD_SRC=$(pwd)/src +fi + +if [ -z $SCM_URL ]; then + SCM_URL="missing" +fi + +if [ -z $SCM_TAG ]; then + SCM_TAG=master +fi + +CLEAN_BUILD_DIR=0 + +function common_help { + echo "$(BASHSOURCE[0]) supports the following arguments:" + echo " --ndk The base directory of your android NDK defa" + echo " ANDROID_NDK=$ANDROID_NDK" + echo " --arch A list of architectures to build" + echo " BUILD_ARCH=$BUILD_ARCH" + echo " --dst The destination directory for include and library files" + echo " BUILD_DST=$BUILD_DST" + echo " --src The source directory for SCM checkout" + echo " BUILD_SRC=$BUILD_SRC" + echo " --url The SCM source url" + echo " SCM_URL=$SCM_URL" + echo " --tag The SCM branch or tag to check out" + echo " SCM_TAG=$SCM_TAG" + echo " --clean Clean the destination before build" + echo " --help Display this help" + exit 0 +} + +function common_run { + echo "[RUN] $@" + "$@" + RES=$? + if [[ $RES -ne 0 ]]; + then + echo "[ERROR] $@ retured $RES" + exit 1 + fi +} + +function common_parse_arguments { + while [[ $# > 0 ]] + do + key="$1" + case $key in + --conf) + source "$2" + shift + ;; + + --ndk) + ANDROID_NDK="$2" + shift + ;; + + --arch) + BUILD_ARCH="$2" + shift + ;; + + --dst) + BUILD_DST="$2" + shift + ;; + + --src) + BUILD_SRC="$2" + shift + ;; + + --url) + SCM_URL="$2" + shift + ;; + + --tag) + SCM_TAG="$2" + shift + ;; + + --clean) + CLEAN_BUILD_DIR=1 + shift + ;; + + --help) + common_help + shift + ;; + + *) # Unknown + ;; + esac + shift + done +} + +function common_check_requirements { + if [[ ! -d $ANDROID_NDK ]]; + then + echo "export ANDROID_NDK to point to your NDK location." + exit 1 + fi + + if [[ -z $BUILD_DST ]]; + then + echo "Destination directory not valid" + exit 1 + fi + + if [[ -z $BUILD_SRC ]]; + then + echo "Source directory not valid" + exit 1 + fi + + if [[ -z $SCM_URL ]]; + then + echo "Source URL not defined! Define SCM_URL" + exit 1 + fi + + if [[ -z $SCM_TAG ]]; + then + echo "SCM TAG / BRANCH not defined! Define SCM_TAG" + exit 1 + fi + + if [[ -z $NDK_TARGET ]]; + then + echo "Android platform NDK_TARGET not defined" + exit 1 + fi + + if [ -x $ANDROID_NDK/ndk-build ]; then + NDK_BUILD=$ANDROID_NDK/ndk-build + else + echo "ndk-build not found in NDK directory $ANDROID_NDK" + echo "assuming ndk-build is in path..." + NDK_BUILD=ndk-build + fi + + if [[ -z $NDK_BUILD ]]; + then + echo "Android ndk-build not detected" + exit 1 + fi + + for CMD in make git cmake $NDK_BUILD + do + if ! type $CMD >/dev/null; then + echo "Command $CMD not found. Install and add it to the PATH." + exit 1 + fi + done + + if [ "${BUILD_SRC:0:1}" != "/" ]; + then + BUILD_SRC=$(pwd)/$BUILD_SRC + fi + if [ "${BUILD_DST:0:1}" != "/" ]; + then + BUILD_DST=$(pwd)/$BUILD_DST + fi +} + +function common_update { + if [ $# -ne 3 ]; + then + echo "Invalid arguments to update function $@" + exit 1 + fi + + echo "Preparing checkout..." + BASE=$(pwd) + if [[ ! -d $3 ]]; + then + common_run mkdir -p $3 + common_run cd $3 + common_run git clone $1 $3 + fi + + common_run cd $BASE + common_run cd $3 + common_run git fetch + common_run git reset --hard HEAD + common_run git checkout $2 + common_run cd $BASE +} + +function common_clean { + if [ $CLEAN_BUILD_DIR -ne 1 ]; + then + return + fi + + if [ $# -ne 1 ]; + then + echo "Invalid arguments to clean function $@" + exit 1 + fi + + echo "Cleaning up $1..." + common_run rm -rf $1 +} + +function common_copy { + if [ $# -ne 2 ]; + then + echo "Invalid arguments to copy function $@" + exit 1 + fi + if [ ! -d $1 ] || [ ! -d $1/include ] || [ ! -d $1/libs ]; + then + echo "Invalid source $1" + exit 1 + fi + if [ -z $2 ]; + then + echo "Invalid destination $2" + exit 1 + fi + + if [ ! -d $2 ]; + then + common_run mkdir -p $2 + fi + common_run cp -L -r $1/include $2 + common_run cp -L -r $1/libs/* $2 +} diff --git a/scripts/android-build-freerdp.sh b/scripts/android-build-freerdp.sh new file mode 100755 index 0000000..a522f86 --- /dev/null +++ b/scripts/android-build-freerdp.sh @@ -0,0 +1,140 @@ +#!/bin/bash + +JPEG_TAG=master +OPENH264_TAG=master +OPENSSL_TAG=master + +WITH_JPEG=0 +WITH_OPENH264=0 +WITH_OPENSSL=0 + +SRC_DIR=$(pwd) +BUILD_SRC=$(pwd) +BUILD_DST=$(pwd) + +CMAKE_BUILD_TYPE=Debug +BUILD_DEPS=0 + +SCRIPT_PATH=$(dirname "${BASH_SOURCE[0]}") +source $SCRIPT_PATH/android-build-common.sh +source $SCRIPT_PATH/android-build.conf + +# Parse arguments. +REMAINING="" +while [[ $# > 0 ]] +do + key="$1" + case $key in + --freerdp-src) + SRC_DIR="$2" + shift + ;; + --jpeg) + WITH_JPEG=1 + shift + ;; + --openh264) + WITH_OPENH264=1 + shift + ;; + --openssl) + WITH_OPENSSL=1 + shift + ;; + --debug) + CMAKE_BUILD_TYPE=Debug + shift + ;; + --release) + CMAKE_BUILD_TYPE=Release + shift + ;; + --relWithDebug) + CMAKE_BUILD_TYPE=RelWithDebug + shift + ;; + --build-deps) + BUILD_DEPS=1 + shift + ;; + *) + REMAINING="$REMAINING $key" + shift + ;; + esac +done +common_parse_arguments $REMAINING + +# clean up top +if [ -d $BUILD_SRC ]; +then + common_clean $BUILD_SRC +fi + +if [ -d $BUILD_DST ]; +then + common_run mkdir -p $BUILD_DST +fi + +# Prepare the environment +common_run mkdir -p $BUILD_SRC + +CMAKE_CMD_ARGS="-DANDROID_NDK=$ANDROID_NDK \ + -DCMAKE_TOOLCHAIN_FILE=$SRC_DIR/cmake/AndroidToolchain.cmake \ + -DCMAKE_INSTALL_PREFIX=$BUILD_DST \ + -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE \ + -DFREERDP_EXTERNAL_PATH=$BUILD_DST" + +BASE=$(pwd) +for ARCH in $BUILD_ARCH +do + # build dependencies. + if [ $WITH_JPEG -ne 0 ]; + then + if [ $BUILD_DEPS -ne 0 ]; + then + common_run bash $SCRIPT_PATH/android-build-jpeg.sh \ + --src $BUILD_SRC/jpeg --dst $BUILD_DST \ + --ndk $ANDROID_NDK \ + --arch $ARCH \ + --tag $JPEG_TAG + fi + CMAKE_CMD_ARGS="$CMAKE_CMD_ARGS -DWITH_JPEG=ON" + fi + if [ $WITH_OPENH264 -ne 0 ]; + then + if [ $BUILD_DEPS -ne 0 ]; + then + common_run bash $SCRIPT_PATH/android-build-openh264.sh \ + --src $BUILD_SRC/openh264 --dst $BUILD_DST \ + --ndk $ANDROID_NDK \ + --arch $ARCH \ + --tag $OPENH264_TAG + fi + CMAKE_CMD_ARGS="$CMAKE_CMD_ARGS -DWITH_OPENH264=ON" + fi + if [ $WITH_OPENSSL -ne 0 ]; + then + if [ $BUILD_DEPS -ne 0 ]; + then + common_run bash $SCRIPT_PATH/android-build-openssl.sh \ + --src $BUILD_SRC/openssl --dst $BUILD_DST \ + --ndk $ANDROID_NDK \ + --arch $ARCH \ + --tag $OPENSSL_TAG + fi + fi + + # Build and install the library. + common_run cd $BASE + common_run mkdir -p $BUILD_SRC/freerdp-build/$ARCH + common_run cd $BUILD_SRC/freerdp-build/$ARCH + common_run export ANDROID_NDK=$ANDROID_NDK + common_run cmake $CMAKE_CMD_ARGS \ + -DANDROID_ABI=$ARCH \ + $SRC_DIR + echo $(pwd) + common_run cmake --build . --target install +done + +echo "Successfully build library for architectures $BUILD_ARCH" diff --git a/scripts/android-build-jpeg.sh b/scripts/android-build-jpeg.sh new file mode 100755 index 0000000..7b06adf --- /dev/null +++ b/scripts/android-build-jpeg.sh @@ -0,0 +1,41 @@ +#!/bin/bash +SCM_URL=https://github.com/akallabeth/jpeg8d.git +SCM_TAG=master + +source $(dirname "${BASH_SOURCE[0]}")/android-build-common.sh + +function usage { + echo $0 [arguments] + echo "\tThe script checks out the OpenH264 git repository" + echo "\tto a local source directory, builds and installs" + echo "\tthe library for all architectures defined to" + echo "\tthe destination directory." + echo "" + echo "\t[-s|--source-dir ]" + echo "\t[-d|--destination-dir ]" + echo "\t[-a|--arch ]" + echo "\t[-t|--tag ]" + echo "\t[--scm-url ]" + echo "\t[--ndk ]" + echo "\t[--sdk ]" + exit 1 +} + +function build { + echo "Building architectures $BUILD_ARCH..." + BASE=$(pwd) + common_run cd $BUILD_SRC + common_run $NDK_BUILD V=1 APP_ABI="${BUILD_ARCH}" -j clean + common_run $NDK_BUILD V=1 APP_ABI="${BUILD_ARCH}" -j + common_run cd $BASE +} + +# Run the main program. +common_parse_arguments $@ +common_check_requirements +common_update $SCM_URL $SCM_TAG $BUILD_SRC +common_clean $BUILD_DST + +build + +common_copy $BUILD_SRC $BUILD_DST diff --git a/scripts/android-build-openh264.sh b/scripts/android-build-openh264.sh new file mode 100755 index 0000000..78a08ab --- /dev/null +++ b/scripts/android-build-openh264.sh @@ -0,0 +1,58 @@ +#!/bin/bash +SCM_URL=https://github.com/cisco/openh264 +SCM_TAG=master + +source $(dirname "${BASH_SOURCE[0]}")/android-build-common.sh + +function build { + echo "Building architecture $1..." + BASE=$(pwd) + common_run cd $BUILD_SRC + PATH=$ANDROID_NDK:$PATH + MAKE="make PATH=$PATH OS=android NDKROOT=$ANDROID_NDK TARGET=android-$2 NDKLEVEL=$2 ARCH=$1 -j libraries" + common_run git clean -xdf + common_run $MAKE + # Install creates a non optimal directory layout, fix that + common_run $MAKE PREFIX=$BUILD_SRC/libs/$1 install + common_run cd $BASE +} + +# Run the main program. +common_parse_arguments $@ +common_check_requirements +common_update $SCM_URL $SCM_TAG $BUILD_SRC +common_clean $BUILD_DST + +for ARCH in $BUILD_ARCH +do + case $ARCH in + "armeabi") + OARCH="arm" + ;; + "armeabi-v7a") + OARCH="arm" + ;; + "arm64-v8a") + OARCH="arm64" + ;; + *) + OARCH=$ARCH + ;; + esac + + echo "$ARCH=$OARCH" + + build $OARCH $NDK_TARGET + + if [ ! -d $BUILD_DST/include ]; + then + common_run mkdir -p $BUILD_DST/include + fi + + common_run cp -L -r $BUILD_SRC/libs/$OARCH/include/ $BUILD_DST/ + if [ ! -d $BUILD_DST/$ARCH ]; + then + common_run mkdir -p $BUILD_DST/$ARCH + fi + common_run cp -L $BUILD_SRC/libs/$OARCH/lib/*.so $BUILD_DST/$ARCH/ +done diff --git a/scripts/android-build-openssl.sh b/scripts/android-build-openssl.sh new file mode 100755 index 0000000..3e376fe --- /dev/null +++ b/scripts/android-build-openssl.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +SCM_URL=https://github.com/openssl/openssl +SCM_TAG=master + +COMPILER=4.9 + +source $(dirname "${BASH_SOURCE[0]}")/android-build-common.sh + +function build { + if [ $# -ne 5 ]; + then + echo "Invalid arguments $@" + exit 1 + fi + + CONFIG=$1 + ARCH_PREFIX=$2 + DST_PREFIX=$3 + TOOLCHAIN_PREFIX=$4 + PLATFORM_PREFIX=$5 + + TMP_DIR=$ANDROID_NDK/toolchains/$TOOLCHAIN_PREFIX$COMPILER/prebuilt/ + HOST_PLATFORM=$(ls $TMP_DIR) + if [ ! -d $TMP_DIR$HOST_POLATFORM ]; + then + echo "could not determine NDK host platform in $ANDROID_NDK/toolchains/$TOOLCHAIN_PREFIX$COMPILER/prebuilt/" + exit 1 + fi + + common_run export CROSS_SYSROOT=$ANDROID_NDK/platforms/android-$NDK_TARGET/$PLATFORM_PREFIX + common_run export ANDROID_DEV=$ANDROID_NDK/platforms/android-$NDK_TARGET/$PLATFORM_PREFIX/usr + common_run export CROSS_COMPILE=$ARCH_PREFIX + common_run export PATH=$ANDROID_NDK/toolchains/$TOOLCHAIN_PREFIX$COMPILER/prebuilt/$HOST_PLATFORM/bin/:$ORG_PATH + + echo "CONFIG=$CONFIG" + echo "ARCH_PREFIX=$ARCH_PREFIX" + echo "DST_PREFIX=$DST_PREFIX" + echo "TOOLCHAIN_PREFIX=$TOOLCHAIN_PREFIX" + echo "PLATFORM_PREFIX=$PLATFORM_PREFIX" + echo "CROSS_SYSROOT=$CROSS_SYSROOT" + echo "CROSS_COMPILE=$CROSS_COMPILE" + echo "PATH=$PATH" + + BASE=$(pwd) + DST_DIR=$BUILD_DST/$DST_PREFIX + common_run cd $BUILD_SRC + common_run git clean -xdf + common_run ./Configure --openssldir=$DST_DIR $CONFIG shared + common_run make -j build_libs + + if [ ! -d $DST_DIR ]; + then + common_run mkdir -p $DST_DIR + fi + + common_run cp -L libssl.so $DST_DIR + common_run cp -L libcrypto.so $DST_DIR + common_run cd $BASE +} + +# Run the main program. +common_parse_arguments $@ +common_check_requirements +common_update $SCM_URL $SCM_TAG $BUILD_SRC +common_clean $BUILD_DST + +# Patch openssl +BASE=$(pwd) +common_run cd $BUILD_SRC +common_run git am $(dirname "${BASH_SOURCE[0]}")/openssl-disable-library-versioning.patch +common_run cd $BASE + +ORG_PATH=$PATH +for ARCH in $BUILD_ARCH +do + + case $ARCH in + "armeabi") + build "android" "arm-linux-androideabi-" \ + $ARCH "arm-linux-androideabi-" "arch-arm" + ;; + "armeabi-v7a") + build "android-armv7" "arm-linux-androideabi-" \ + $ARCH "arm-linux-androideabi-" "arch-arm" + ;; + "mips") + build "android-mips" "mipsel-linux-android-" \ + $ARCH "mipsel-linux-android-" "arch-mips" + ;; + "mips64") + echo "[WARNING] Skipping unsupported architecture $ARCH" + continue + build "android-mips" "mipsel-linux-android-" \ + $ARCH "mipsel-linux-android-" "arch-mips" + ;; + "x86") + build "android-x86" "i686-linux-android-" \ + $ARCH "x86-" "arch-x86" + ;; + "arm64-v8a") + build "android64-aarch64" "aarch64-linux-android-" \ + $ARCH "aarch64-linux-android-" "arch-arm64" + ;; + "x86_64") + build "android64" "x86_64-linux-android-" \ + $ARCH "x86_64-" "arch-x86_64" + ;; + *) + echo "[WARNING] Skipping unsupported architecture $ARCH" + continue + ;; + esac +done + +if [ ! -d $BUILD_DST/include ]; +then + common_run mkdir -p $BUILD_DST/include +fi +common_run cp -L -r $BUILD_SRC/include/openssl $BUILD_DST/include/ + diff --git a/scripts/android-build.conf b/scripts/android-build.conf new file mode 100644 index 0000000..fff1ab2 --- /dev/null +++ b/scripts/android-build.conf @@ -0,0 +1,22 @@ +#!/bin/bash +# +# Android build confguration +SCRIPT_PATH=$(dirname "${BASH_SOURCE[0]}") +SCRIPT_PATH=$(realpath "$SCRIPT_PATH") + +WITH_JPEG=1 +WITH_OPENH264=1 +WITH_OPENSSL=1 +BUILD_DEPS=1 + +JPEG_TAG=master +OPENH264_TAG=v1.5.0 +OPENSSL_TAG=OpenSSL_1_0_2f + +SRC_DIR=$SCRIPT_PATH/.. +BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs +BUILD_SRC=$SRC_DIR/build + +CMAKE_BUILD_TYPE=Debug + +BUILD_ARCH="armeabi armeabi-v7a x86" diff --git a/scripts/android_setup_build_env.sh b/scripts/android_setup_build_env.sh deleted file mode 100755 index 9d0fd27..0000000 --- a/scripts/android_setup_build_env.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/bin/sh -# -# This script checks out or updates and builds third party libraries -# required for the android build. -# -# Specifically these are: -# - OpenSSL -# - Android NDK Profiler -# - Jpeg library -# -# Usage: -# android_setup_build_env.sh - -OPENSSL_SCM=https://github.com/akallabeth/openssl-android.git -OPENSSL_TAG=1.0.1h-fips-2.0.7 -NDK_PROFILER_SCM=https://github.com/richq/android-ndk-profiler.git -JPEG_LIBRARY_SCM=https://github.com/akallabeth/jpeg8d.git - -SCRIPT_NAME=$(basename $0) - -if [ -x $ANDROID_NDK/ndk-build ]; then - NDK_BUILD=$ANDROID_NDK/ndk-build -else - echo "ndk-build not found in NDK directory $ANDROID_NDK" - echo "assuming ndk-build is in path..." - NDK_BUILD=ndk-build -fi - -if [ $# -ne 1 ]; then - - echo "Missing command line argument, current directory as root." - ROOT=`pwd` - ROOT=$ROOT/external -else - ROOT=`readlink -f $1` -fi - -if [ ! -d $ROOT ]; then - echo "Argument '$ROOT' is not a directory." - exit -2 -fi -echo "Using '$ROOT' as root." - -echo "Preparing OpenSSL..." -OPENSSL_SRC=$ROOT/openssl-build -if [ -d $OPENSSL_SRC ]; then - cd $OPENSSL_SRC - git fetch - RETVAL=$? -else - git clone $OPENSSL_SCM $OPENSSL_SRC - RETVAL=$? -fi -if [ $RETVAL -ne 0 ]; then - echo "Failed to execute git command [$RETVAL]" - exit -3 -fi -cd $OPENSSL_SRC - -# We want to build a specific TAG -git checkout $OPENSSL_TAG - -make clean -# The makefile has a bug, which aborts during -# first compilation. Rerun make to build the whole lib. -make -RETVAL=$? -if [ $RETVAL -ne 0 ]; then - echo "Failed to execute make command [$RETVAL]" - exit -4 -fi -# Copy the created library to the default openssl directory, -# so that CMake will detect it automatically. -SSL_ROOT=`find $OPENSSL_SRC -type d -name "openssl-?.?.*"` -if [ -z "$SSL_ROOT" ]; then - echo "OpenSSL was not build successfully, aborting." - exit -42 -fi -mkdir -p $SSL_ROOT/lib -cp $SSL_ROOT/*.a $SSL_ROOT/lib/ - -rm -f $ROOT/openssl -ln -s $SSL_ROOT $ROOT/openssl - -echo "Preparing NDK profiler..." -NDK_PROFILER_SRC=$ROOT/android-ndk-profiler -if [ -d $NDK_PROFILER_SRC ]; then - cd $NDK_PROFILER_SRC - git pull - RETVAL=$? -else - git clone $NDK_PROFILER_SCM $NDK_PROFILER_SRC - RETVAL=$? -fi -if [ $RETVAL -ne 0 ]; then - echo "Failed to execute git command [$RETVAL]" - exit -5 -fi -cd $NDK_PROFILER_SRC -$NDK_BUILD V=1 APP_ABI=armeabi-v7a clean -$NDK_BUILD V=1 APP_ABI=armeabi-v7a -RETVAL=$? -if [ $RETVAL -ne 0 ]; then - echo "Failed to execute $NDK_BUILD command [$RETVAL]" - exit -6 -fi - -echo "Preparing JPEG library..." -JPEG_LIBRARY_SRC=$ROOT/jpeg8d -if [ -d $JPEG_LIBRARY_SRC ]; then - cd $JPEG_LIBRARY_SRC - git pull - RETVAL=$? -else - git clone $JPEG_LIBRARY_SCM $JPEG_LIBRARY_SRC - RETVAL=$? -fi -if [ $RETVAL -ne 0 ]; then - echo "Failed to execute git command [$RETVAL]" - exit -6 -fi -cd $JPEG_LIBRARY_SRC -$NDK_BUILD V=1 APP_ABI=armeabi-v7a clean -$NDK_BUILD V=1 APP_ABI=armeabi-v7a -RETVAL=$? -if [ $RETVAL -ne 0 ]; then - echo "Failed to execute $NDK_BUILD command [$RETVAL]" - exit -7 -fi -mkdir -p $JPEG_LIBRARY_SRC/lib -cp $JPEG_LIBRARY_SRC/obj/local/armeabi-v7a/*.a $JPEG_LIBRARY_SRC/lib/ - -echo "Prepared external libraries, you can now build the application." -exit 0 diff --git a/scripts/openssl-disable-library-versioning.patch b/scripts/openssl-disable-library-versioning.patch new file mode 100644 index 0000000..9f2f691 --- /dev/null +++ b/scripts/openssl-disable-library-versioning.patch @@ -0,0 +1,24 @@ +From 12f0521bbb3f046db8c7854364135d8247cf982e Mon Sep 17 00:00:00 2001 +From: Armin Novak +Date: Fri, 29 Jan 2016 17:04:12 +0100 +Subject: [PATCH] Disabled library versioning. + +--- + Makefile.shared | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/Makefile.shared b/Makefile.shared +index e753f44..5cffcc2 100644 +--- a/Makefile.shared ++++ b/Makefile.shared +@@ -81,7 +81,6 @@ CALC_VERSIONS= \ + prev=""; \ + for v in `echo "$(LIBVERSION) $(LIBCOMPATVERSIONS)" | cut -d';' -f1`; do \ + SHLIB_SOVER_NODOT=$$v; \ +- SHLIB_SOVER=.$$v; \ + if [ -n "$$prev" ]; then \ + SHLIB_COMPAT="$$SHLIB_COMPAT .$$prev"; \ + fi; \ +-- +2.1.4 + diff --git a/server/FreeRDP-ServerConfig.cmake.in b/server/FreeRDP-ServerConfig.cmake.in index 2f2788b..b9edb55 100644 --- a/server/FreeRDP-ServerConfig.cmake.in +++ b/server/FreeRDP-ServerConfig.cmake.in @@ -1,10 +1,10 @@ @PACKAGE_INIT@ -set(FreeRDP_VERSION_MAJOR "@FREERDP_VERSION_MAJOR@") -set(FreeRDP_VERSION_MINOR "@FREERDP_VERSION_MINOR@") -set(FreeRDP_VERSION_REVISION "@FREERDP_VERSION_REVISION@") +set(FreeRDP-Server_VERSION_MAJOR "@FREERDP_VERSION_MAJOR@") +set(FreeRDP-Server_VERSION_MINOR "@FREERDP_VERSION_MINOR@") +set(FreeRDP-Server_VERSION_REVISION "@FREERDP_VERSION_REVISION@") -set_and_check(FreeRDP_INCLUDE_DIR "@PACKAGE_FREERDP_INCLUDE_DIR@") +set_and_check(FreeRDP-Server_INCLUDE_DIR "@PACKAGE_FREERDP_INCLUDE_DIR@") include("${CMAKE_CURRENT_LIST_DIR}/FreeRDP-ServerTargets.cmake") diff --git a/server/Sample/sf_encomsp.c b/server/Sample/sf_encomsp.c index 00a5a86..6fdad03 100644 --- a/server/Sample/sf_encomsp.c +++ b/server/Sample/sf_encomsp.c @@ -33,7 +33,7 @@ BOOL sf_peer_encomsp_init(testPeerContext* context) if (!context->encomsp) return FALSE; - if (context->encomsp->Start(context->encomsp) < 0) + if (context->encomsp->Start(context->encomsp) != CHANNEL_RC_OK) return FALSE; return TRUE; diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index 0dc8def..6a158b1 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -212,7 +212,7 @@ void wfreerdp_server_free(wfServer* server) WSACleanup(); } -FREERDP_API BOOL wfreerdp_server_is_running(wfServer* server) +BOOL wfreerdp_server_is_running(wfServer* server) { DWORD tStatus; BOOL bRet; @@ -229,7 +229,7 @@ FREERDP_API BOOL wfreerdp_server_is_running(wfServer* server) return FALSE; } -FREERDP_API UINT32 wfreerdp_server_num_peers() +UINT32 wfreerdp_server_num_peers() { wfInfo* wfi; @@ -239,7 +239,7 @@ FREERDP_API UINT32 wfreerdp_server_num_peers() return wfi->peerCount; } -FREERDP_API UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr) +UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr) { wfInfo* wfi; freerdp_peer* peer; @@ -264,7 +264,7 @@ FREERDP_API UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr) } } -FREERDP_API BOOL wfreerdp_server_peer_is_local(int pId) +BOOL wfreerdp_server_peer_is_local(int pId) { wfInfo* wfi; freerdp_peer* peer; @@ -284,7 +284,7 @@ FREERDP_API BOOL wfreerdp_server_peer_is_local(int pId) } } -FREERDP_API BOOL wfreerdp_server_peer_is_connected(int pId) +BOOL wfreerdp_server_peer_is_connected(int pId) { wfInfo* wfi; freerdp_peer* peer; @@ -305,7 +305,7 @@ FREERDP_API BOOL wfreerdp_server_peer_is_connected(int pId) } } -FREERDP_API BOOL wfreerdp_server_peer_is_activated(int pId) +BOOL wfreerdp_server_peer_is_activated(int pId) { wfInfo* wfi; freerdp_peer* peer; @@ -325,7 +325,7 @@ FREERDP_API BOOL wfreerdp_server_peer_is_activated(int pId) } } -FREERDP_API BOOL wfreerdp_server_peer_is_authenticated(int pId) +BOOL wfreerdp_server_peer_is_authenticated(int pId) { wfInfo* wfi; freerdp_peer* peer; @@ -345,7 +345,7 @@ FREERDP_API BOOL wfreerdp_server_peer_is_authenticated(int pId) } } -FREERDP_API void wfreerdp_server_register_callback_event(cbCallback cb) +void wfreerdp_server_register_callback_event(cbCallback cb) { cbEvent = cb; } diff --git a/server/common/CMakeLists.txt b/server/common/CMakeLists.txt index d5b9906..009d566 100644 --- a/server/common/CMakeLists.txt +++ b/server/common/CMakeLists.txt @@ -33,7 +33,7 @@ foreach(FREERDP_CHANNELS_SERVER_SRC ${FREERDP_CHANNELS_SERVER_SRCS}) endforeach() if(MSVC) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}) endif() diff --git a/server/common/module.def b/server/common/module.def deleted file mode 100644 index 17f1473..0000000 --- a/server/common/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "freerdp-server" -EXPORTS - diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index 421d4bd..3eb741d 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -15,11 +15,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +# freerdp-shadow library + set(MODULE_NAME "freerdp-shadow") set(MODULE_PREFIX "FREERDP_SERVER_SHADOW") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(${MODULE_PREFIX}_SRCS shadow_client.c shadow_client.h @@ -75,7 +75,6 @@ list(APPEND ${MODULE_PREFIX}_LIBS freerdp) list(APPEND ${MODULE_PREFIX}_LIBS freerdp-server) list(APPEND ${MODULE_PREFIX}_LIBS winpr) list(APPEND ${MODULE_PREFIX}_LIBS winpr-makecert-tool) - list(APPEND ${MODULE_PREFIX}_LIBS rdtk) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) @@ -84,7 +83,7 @@ if (WITH_LIBRARY_VERSIONING) set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION}) endif() -install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server) +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server EXPORT FreeRDP-ShadowTargets) if (WITH_DEBUG_SYMBOLS AND MSVC) install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols) @@ -92,10 +91,13 @@ endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") -# command-line executable +# subsystem library -set(MODULE_NAME "freerdp-shadow-cli") -set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_CLI") +set(MODULE_NAME "freerdp-shadow-subsystem") +set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_SUBSYSTEM") + +set(${MODULE_PREFIX}_SRCS + shadow_subsystem_builtin.c) if(WIN32) set(WITH_SHADOW_WIN 1) @@ -105,6 +107,20 @@ elseif(APPLE AND NOT IOS) set(WITH_SHADOW_MAC 1) endif() +if (WIN32) + set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR}) + set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR}) + set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION}) + set (RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}" ) + + configure_file( + ${CMAKE_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/version.rc + @ONLY) + + set ( ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc) +endif() + # Authentication if(WITH_SHADOW_X11 OR WITH_SHADOW_MAC) @@ -216,18 +232,15 @@ if(WITH_SHADOW_X11) include_directories(${XRANDR_INCLUDE_DIRS}) list(APPEND ${MODULE_PREFIX}_X11_LIBS ${XRANDR_LIBRARIES}) endif() -endif() - -if(WITH_SHADOW_MAC) +elseif(WITH_SHADOW_MAC) find_library(IOKIT IOKit) find_library(IOSURFACE IOSurface) find_library(CARBON Carbon) list(APPEND ${MODULE_PREFIX}_MAC_LIBS ${IOKIT} ${IOSURFACE} ${CARBON}) +elseif(WITH_SHADOW_WIN) + list(APPEND ${MODULE_PREFIX}_WIN_LIBS freerdp-client) endif() -set(${MODULE_PREFIX}_SRCS - shadow.c) - set(${MODULE_PREFIX}_WIN_SRCS Win/win_rdp.c Win/win_rdp.h @@ -262,7 +275,34 @@ endif() list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_AUTH_LIBS}) - # On windows create dll version information. +add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +if (WITH_LIBRARY_VERSIONING) + set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION}) +endif() + +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server EXPORT FreeRDP-ShadowTargets) + +if (WITH_DEBUG_SYMBOLS AND MSVC) + install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT symbols) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") + +# command-line executable + +set(MODULE_NAME "freerdp-shadow-cli") +set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_CLI") + +set(${MODULE_PREFIX}_SRCS + shadow.c) + +# On windows create dll version information. # Vendor, product and year are already set in top level CMakeLists.txt if (WIN32) set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR}) @@ -280,7 +320,7 @@ endif() add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) -set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow) +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow-subsystem) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) @@ -291,3 +331,25 @@ if (WITH_DEBUG_SYMBOLS AND MSVC) endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp-shadow.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp-shadow${FREERDP_VERSION_MAJOR}.pc @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp-shadow${FREERDP_VERSION_MAJOR}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + +if(${CMAKE_VERSION} VERSION_GREATER "2.8.10") + + export(PACKAGE freerdp-shadow) + + set(FREERDP_SERVER_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/FreeRDP-Shadow${FREERDP_VERSION_MAJOR}") + + configure_package_config_file(FreeRDP-ShadowConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ShadowConfig.cmake + INSTALL_DESTINATION ${FREERDP_SERVER_CMAKE_INSTALL_DIR} + PATH_VARS FREERDP_INCLUDE_DIR) + + write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ShadowConfigVersion.cmake + VERSION ${FREERDP_VERSION} COMPATIBILITY SameMajorVersion) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ShadowConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ShadowConfigVersion.cmake + DESTINATION ${FREERDP_SERVER_CMAKE_INSTALL_DIR}) + + install(EXPORT FreeRDP-ShadowTargets DESTINATION ${FREERDP_SERVER_CMAKE_INSTALL_DIR}) +endif() diff --git a/server/shadow/FreeRDP-ShadowConfig.cmake.in b/server/shadow/FreeRDP-ShadowConfig.cmake.in new file mode 100644 index 0000000..1eb11e0 --- /dev/null +++ b/server/shadow/FreeRDP-ShadowConfig.cmake.in @@ -0,0 +1,10 @@ + +@PACKAGE_INIT@ + +set(FreeRDP-Shadow_VERSION_MAJOR "@FREERDP_VERSION_MAJOR@") +set(FreeRDP-Shadow_VERSION_MINOR "@FREERDP_VERSION_MINOR@") +set(FreeRDP-Shadow_VERSION_REVISION "@FREERDP_VERSION_REVISION@") + +set_and_check(FreeRDP-Shadow_INCLUDE_DIR "@PACKAGE_FREERDP_INCLUDE_DIR@") + +include("${CMAKE_CURRENT_LIST_DIR}/FreeRDP-ShadowTargets.cmake") diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index 2fd5f96..10508c9 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -660,7 +660,7 @@ macShadowSubsystem* mac_shadow_subsystem_new() return subsystem; } -int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) +FREERDP_API int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { pEntryPoints->New = (pfnShadowSubsystemNew) mac_shadow_subsystem_new; pEntryPoints->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free; diff --git a/server/shadow/Win/win_rdp.c b/server/shadow/Win/win_rdp.c index d9e0b34..b254f2a 100644 --- a/server/shadow/Win/win_rdp.c +++ b/server/shadow/Win/win_rdp.c @@ -99,9 +99,11 @@ BOOL shw_authenticate(freerdp* instance, char** username, char** password, char* return TRUE; } -BOOL shw_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) +static DWORD shw_verify_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch) { - return TRUE; + return 1; } int shw_verify_x509_certificate(freerdp* instance, BYTE* data, int length, const char* hostname, int port, DWORD flags) diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c index d1dbc58..0f23b9c 100644 --- a/server/shadow/Win/win_shadow.c +++ b/server/shadow/Win/win_shadow.c @@ -519,7 +519,7 @@ winShadowSubsystem* win_shadow_subsystem_new() return subsystem; } -int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) +FREERDP_API int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { pEntryPoints->New = (pfnShadowSubsystemNew) win_shadow_subsystem_new; pEntryPoints->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free; diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 9a16662..7abb218 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -1437,7 +1437,7 @@ void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem) free(subsystem); } -int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) +FREERDP_API int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { pEntryPoints->New = (pfnShadowSubsystemNew) x11_shadow_subsystem_new; pEntryPoints->Free = (pfnShadowSubsystemFree) x11_shadow_subsystem_free; diff --git a/server/shadow/freerdp-shadow.pc.in b/server/shadow/freerdp-shadow.pc.in new file mode 100644 index 0000000..49449e8 --- /dev/null +++ b/server/shadow/freerdp-shadow.pc.in @@ -0,0 +1,15 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=${prefix}/@FREERDP_INCLUDE_DIR@ +libs=-lfreerdp-shadow + +Name: FreeRDP shadow +Description: FreeRDP: A Remote Desktop Protocol Implementation +URL: http://www.freerdp.com/ +Version: @FREERDP_VERSION@ +Requires: +Requires.private: @WINPR_PKG_CONFIG_FILENAME@ freerdp@FREERDP_VERSION_MAJOR@ freerdp-shadow@FREERDP_VERSION_MAJOR@ +Libs: -L${libdir} ${libs} +Libs.private: -ldl -lpthread +Cflags: -I${includedir} diff --git a/server/shadow/shadow.c b/server/shadow/shadow.c index 83a834b..bc98519 100644 --- a/server/shadow/shadow.c +++ b/server/shadow/shadow.c @@ -37,18 +37,6 @@ static BOOL g_MessagePump = FALSE; #include -#ifdef WITH_SHADOW_X11 -extern int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); -#endif - -#ifdef WITH_SHADOW_MAC -extern int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); -#endif - -#ifdef WITH_SHADOW_WIN -extern int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); -#endif - int main(int argc, char** argv) { MSG msg; @@ -56,17 +44,7 @@ int main(int argc, char** argv) DWORD dwExitCode; rdpShadowServer* server; -#ifdef WITH_SHADOW_X11 - shadow_subsystem_set_entry(X11_ShadowSubsystemEntry); -#endif - -#ifdef WITH_SHADOW_MAC - shadow_subsystem_set_entry(Mac_ShadowSubsystemEntry); -#endif - -#ifdef WITH_SHADOW_WIN - shadow_subsystem_set_entry(Win_ShadowSubsystemEntry); -#endif + shadow_subsystem_set_entry_builtin(NULL); server = shadow_server_new(); diff --git a/server/shadow/shadow_subsystem_builtin.c b/server/shadow/shadow_subsystem_builtin.c new file mode 100644 index 0000000..be143d7 --- /dev/null +++ b/server/shadow/shadow_subsystem_builtin.c @@ -0,0 +1,96 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2016 Jiang Zihao + * + * 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 + +struct _RDP_SHADOW_SUBSYSTEM +{ + const char* name; + pfnShadowSubsystemEntry entry; +}; +typedef struct _RDP_SHADOW_SUBSYSTEM RDP_SHADOW_SUBSYSTEM; + +#ifdef WITH_SHADOW_X11 +extern int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); +#endif + +#ifdef WITH_SHADOW_MAC +extern int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); +#endif + +#ifdef WITH_SHADOW_WIN +extern int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); +#endif + +static RDP_SHADOW_SUBSYSTEM g_Subsystems[] = +{ + +#ifdef WITH_SHADOW_X11 + { "X11", X11_ShadowSubsystemEntry }, +#endif + +#ifdef WITH_SHADOW_MAC + { "Mac", Mac_ShadowSubsystemEntry }, +#endif + +#ifdef WITH_SHADOW_WIN + { "Win", Win_ShadowSubsystemEntry }, +#endif + + { "", NULL } +}; + +static int g_SubsystemCount = (sizeof(g_Subsystems) / sizeof(g_Subsystems[0])); + +static pfnShadowSubsystemEntry shadow_subsystem_load_static_entry(const char* name) +{ + int index; + + if (!name) + { + for (index = 0; index < g_SubsystemCount; index++) + { + if (g_Subsystems[index].name) + return g_Subsystems[index].entry; + } + } + + for (index = 0; index < g_SubsystemCount; index++) + { + if (strcmp(name, g_Subsystems[index].name) == 0) + return g_Subsystems[index].entry; + } + + return NULL; +} + +void shadow_subsystem_set_entry_builtin(const char* name) +{ + pfnShadowSubsystemEntry entry; + + entry = shadow_subsystem_load_static_entry(name); + + if (entry) + shadow_subsystem_set_entry(entry); + + return; +} diff --git a/uwac/CMakeLists.txt b/uwac/CMakeLists.txt new file mode 100644 index 0000000..369ba2d --- /dev/null +++ b/uwac/CMakeLists.txt @@ -0,0 +1,52 @@ +# UWAC: Using Wayland As Client +# cmake build script +# +# Copyright 2015 David FORT +# +# 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. + +# Soname versioning +set(UWAC_VERSION_MAJOR "0") +set(UWAC_VERSION_MINOR "0") +set(UWAC_VERSION_REVISION "1") +set(UWAC_VERSION "${UWAC_VERSION_MAJOR}.${UWAC_VERSION_MINOR}.${UWAC_VERSION_REVISION}") +set(UWAC_VERSION_FULL "${UWAC_VERSION}") +set(UWAC_API_VERSION "${UWAC_VERSION_MAJOR}") + +add_subdirectory(include) +add_subdirectory(libuwac) + +set(UWAC_INCLUDE_DIR "include/uwac${UWAC_VERSION_MAJOR}") +# cmake package +if(${CMAKE_VERSION} VERSION_GREATER "2.8.10") + + export(PACKAGE uwac) + + set(UWAC_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/uwac${UWAC_VERSION_MAJOR}") + + + configure_package_config_file(uwacConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/uwacConfig.cmake + INSTALL_DESTINATION ${UWAC_CMAKE_INSTALL_DIR} + PATH_VARS UWAC_INCLUDE_DIR) + + write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/uwacConfigVersion.cmake + VERSION ${UWAC_VERSION} COMPATIBILITY SameMajorVersion) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/uwacConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/uwacConfigVersion.cmake + DESTINATION ${UWAC_CMAKE_INSTALL_DIR}) + + install(EXPORT uwac DESTINATION ${UWAC_CMAKE_INSTALL_DIR}) +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/uwac.pc.in ${CMAKE_CURRENT_BINARY_DIR}/uwac${UWAC_VERSION_MAJOR}.pc @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/uwac${UWAC_VERSION_MAJOR}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) diff --git a/uwac/include/CMakeLists.txt b/uwac/include/CMakeLists.txt new file mode 100644 index 0000000..6858728 --- /dev/null +++ b/uwac/include/CMakeLists.txt @@ -0,0 +1,19 @@ +# UWAC: Using Wayland As Client +# cmake build script +# +# Copyright 2015 David FORT +# +# 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. + +file(GLOB UWAC_HEADERS "uwac/*.h") +install(FILES ${UWAC_HEADERS} DESTINATION include/uwac${UWAC_API_VERSION}/uwac COMPONENT headers) diff --git a/uwac/include/uwac/uwac-tools.h b/uwac/include/uwac/uwac-tools.h new file mode 100644 index 0000000..07813fb --- /dev/null +++ b/uwac/include/uwac/uwac-tools.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2015 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef __UWAC_TOOLS_H_ +#define __UWAC_TOOLS_H_ + +#include +#include + +/** @brief */ +struct uwac_touch_point { + uint32_t id; + wl_fixed_t x, y; +}; +typedef struct uwac_touch_point UwacTouchPoint; + +struct uwac_touch_automata; +typedef struct uwac_touch_automata UwacTouchAutomata; + +/** + * + * @param automata + */ +UWAC_API void UwacTouchAutomataInit(UwacTouchAutomata *automata); + +/** + * + * @param automata + */ +UWAC_API void UwacTouchAutomataReset(UwacTouchAutomata *automata); + + +/** + * + * @param automata + * @param event + * @return + */ +UWAC_API bool UwacTouchAutomataInjectEvent(UwacTouchAutomata *automata, UwacEvent *event); + +#endif /* __UWAC_TOOLS_H_ */ diff --git a/uwac/include/uwac/uwac.h b/uwac/include/uwac/uwac.h new file mode 100644 index 0000000..fd422f4 --- /dev/null +++ b/uwac/include/uwac/uwac.h @@ -0,0 +1,486 @@ +/* + * Copyright © 2014-2015 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef __UWAC_H_ +#define __UWAC_H_ + +#include +#include + +#if __GNUC__ >= 4 + #define UWAC_API __attribute__ ((visibility("default"))) +#else + #define UWAC_API +#endif + +typedef struct uwac_size UwacSize; +typedef struct uwac_display UwacDisplay; +typedef struct uwac_output UwacOutput; +typedef struct uwac_window UwacWindow; +typedef struct uwac_seat UwacSeat; + + +/** @brief error codes */ +typedef enum { + UWAC_SUCCESS = 0, + UWAC_ERROR_NOMEMORY, + UWAC_ERROR_UNABLE_TO_CONNECT, + UWAC_ERROR_INVALID_DISPLAY, + UWAC_NOT_ENOUGH_RESOURCES, + UWAC_TIMEDOUT, + UWAC_NOT_FOUND, + UWAC_ERROR_CLOSED, + UWAC_ERROR_INTERNAL, + + UWAC_ERROR_LAST, +} UwacReturnCode; + +/** @brief input modifiers */ +enum { + UWAC_MOD_SHIFT_MASK = 0x01, + UWAC_MOD_ALT_MASK = 0x02, + UWAC_MOD_CONTROL_MASK = 0x04, +}; + +/** @brief a rectangle size measure */ +struct uwac_size { + int width; + int height; +}; + + +/** @brief event types */ +enum { + UWAC_EVENT_NEW_SEAT = 0, + UWAC_EVENT_REMOVED_SEAT, + UWAC_EVENT_NEW_OUTPUT, + UWAC_EVENT_CONFIGURE, + UWAC_EVENT_POINTER_ENTER, + UWAC_EVENT_POINTER_LEAVE, + UWAC_EVENT_POINTER_MOTION, + UWAC_EVENT_POINTER_BUTTONS, + UWAC_EVENT_POINTER_AXIS, + UWAC_EVENT_KEYBOARD_ENTER, + UWAC_EVENT_KEY, + UWAC_EVENT_TOUCH_FRAME_BEGIN, + UWAC_EVENT_TOUCH_UP, + UWAC_EVENT_TOUCH_DOWN, + UWAC_EVENT_TOUCH_MOTION, + UWAC_EVENT_TOUCH_CANCEL, + UWAC_EVENT_TOUCH_FRAME_END, + UWAC_EVENT_FRAME_DONE, + UWAC_EVENT_CLOSE, +}; + +/** @brief window states */ +enum { + UWAC_WINDOW_MAXIMIZED = 0x1, + UWAC_WINDOW_RESIZING = 0x2, + UWAC_WINDOW_FULLSCREEN = 0x4, + UWAC_WINDOW_ACTIVATED = 0x8, +}; + +struct uwac_new_output_event { + int type; + UwacOutput *output; +}; +typedef struct uwac_new_output_event UwacOutputNewEvent; + +struct uwac_new_seat_event { + int type; + UwacSeat *seat; +}; +typedef struct uwac_new_seat_event UwacSeatNewEvent; + +typedef struct uwac_new_seat_event UwacSeatRemovedEvent; + +struct uwac_keyboard_enter_event { + int type; + UwacWindow *window; + UwacSeat *seat; +}; +typedef struct uwac_keyboard_enter_event UwacKeyboardEnterLeaveEvent; + +struct uwac_pointer_enter_event { + int type; + UwacWindow *window; + UwacSeat *seat; + uint32_t x, y; +}; +typedef struct uwac_pointer_enter_event UwacPointerEnterLeaveEvent; + +struct uwac_pointer_motion_event { + int type; + UwacWindow *window; + UwacSeat *seat; + uint32_t x, y; +}; +typedef struct uwac_pointer_motion_event UwacPointerMotionEvent; + +struct uwac_pointer_button_event { + int type; + UwacWindow *window; + UwacSeat *seat; + uint32_t x, y; + uint32_t button; + enum wl_pointer_button_state state; +}; +typedef struct uwac_pointer_button_event UwacPointerButtonEvent; + +struct uwac_pointer_axis_event { + int type; + UwacWindow *window; + UwacSeat *seat; + uint32_t x, y; + uint32_t axis; + wl_fixed_t value; +}; +typedef struct uwac_pointer_axis_event UwacPointerAxisEvent; + +struct uwac_touch_frame_event { + int type; + UwacWindow *window; + UwacSeat *seat; +}; +typedef struct uwac_touch_frame_event UwacTouchFrameBegin; +typedef struct uwac_touch_frame_event UwacTouchFrameEnd; +typedef struct uwac_touch_frame_event UwacTouchCancel; + +struct uwac_touch_data { + int type; + UwacWindow *window; + UwacSeat *seat; + int32_t id; + wl_fixed_t x; + wl_fixed_t y; +}; +typedef struct uwac_touch_data UwacTouchUp; +typedef struct uwac_touch_data UwacTouchDown; +typedef struct uwac_touch_data UwacTouchMotion; + +struct uwac_frame_done_event { + int type; + UwacWindow *window; +}; +typedef struct uwac_frame_done_event UwacFrameDoneEvent; + +struct uwac_configure_event { + int type; + UwacWindow *window; + int32_t width; + int32_t height; + int states; +}; +typedef struct uwac_configure_event UwacConfigureEvent; + +struct uwac_key_event { + int type; + UwacWindow *window; + uint32_t raw_key; + uint32_t sym; + bool pressed; +}; +typedef struct uwac_key_event UwacKeyEvent; + +struct uwac_close_event { + int type; + UwacWindow *window; +}; +typedef struct uwac_close_event UwacCloseEvent; + + +/** @brief */ +union uwac_event { + int type; + UwacOutputNewEvent output_new; + UwacSeatNewEvent seat_new; + UwacPointerEnterLeaveEvent mouse_enter_leave; + UwacPointerMotionEvent mouse_motion; + UwacPointerButtonEvent mouse_button; + UwacPointerAxisEvent mouse_axis; + UwacKeyboardEnterLeaveEvent keyboard_enter_leave; + UwacKeyEvent key; + UwacTouchFrameBegin touchFrameBegin; + UwacTouchUp touchUp; + UwacTouchDown touchDown; + UwacTouchMotion touchMotion; + UwacTouchFrameEnd touchFrameEnd; + UwacTouchCancel touchCancel; + UwacFrameDoneEvent frame_done; + UwacConfigureEvent configure; + UwacCloseEvent close; +}; +typedef union uwac_event UwacEvent; + +typedef bool (*UwacErrorHandler)(UwacDisplay *d, UwacReturnCode code, const char *msg, ...); + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * install a handler that will be called when UWAC encounter internal errors. The + * handler is supposed to answer if the execution can continue. I can also be used + * to log things. + * + * @param handler + */ +UWAC_API void UwacInstallErrorHandler(UwacErrorHandler handler); + + +/** + * Opens the corresponding wayland display, using NULL you will open the default + * display. + * + * @param name the name of the display to open + * @return the created UwacDisplay object + */ +UWAC_API UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err); + +/** + * closes the corresponding UwacDisplay + * + * @param pdisplay a pointer on the display to close + * @return UWAC_SUCCESS if the operation was successful, the corresponding error otherwise + */ +UWAC_API UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay); + +/** + * Returns the file descriptor associated with the UwacDisplay, this is useful when + * you want to poll that file descriptor for activity. + * + * @param display an opened UwacDisplay + * @return the corresponding descriptor + */ +UWAC_API int UwacDisplayGetFd(UwacDisplay *display); + +/** + * Returns a human readable form of a Uwac error code + * + * @param error the error number + * @return the associated string + */ +UWAC_API const char *UwacErrorString(UwacReturnCode error); + +/** + * returns the last error that occurred on a display + * + * @param display the display + * @return the last error that have been set for this display + */ +UWAC_API UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display); + +/** + * retrieves the version of a given interface + * + * @param display the display connection + * @param name the name of the interface + * @param version the output variable for the version + * @return UWAC_SUCCESS if the interface was found, UWAC_NOT_FOUND otherwise + */ +UWAC_API UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, const char *name, uint32_t *version); + +/** + * returns the number SHM formats that have been reported by the compositor + * + * @param display a connected UwacDisplay + * @return the number of SHM formats supported + */ +UWAC_API uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display); + +/** + * returns the supported ShmFormats + * + * @param display a connected UwacDisplay + * @param formats a pointer on an array of wl_shm_format with enough place for formats_size items + * @param formats_size the size of the formats array + * @param filled the number of filled entries in the formats array + * @return UWAC_SUCCESS on success, an error otherwise + */ +UWAC_API UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_shm_format *formats, int formats_size, int *filled); + +/** + * returns the number of registered outputs + * + * @param display the display to query + * @return the number of outputs + */ +UWAC_API uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display); + +/** + * retrieve a particular UwacOutput object + * + * @param display the display to query + * @param index index of the output + * @return the given UwacOutput, NULL if something failed (so you should query UwacDisplayGetLastError() to have the reason) + */ +UWAC_API UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index); + +/** + * retrieve the resolution of a given UwacOutput + * + * @param output the UwacOutput + * @param resolution a pointer on the + * @return UWAC_SUCCESS on success + */ +UWAC_API UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution); + + +/** + * creates a window using a SHM surface + * + * @param display the display to attach the window to + * @param width the width of the window + * @param height the heigh of the window + * @param format format to use for the SHM surface + * @return the created UwacWindow, NULL if something failed (use UwacDisplayGetLastError() to know more about this) + */ +UWAC_API UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t height, enum wl_shm_format format); + +/** + * destroys the corresponding UwacWindow + * + * @param window a pointer on the UwacWindow to destroy + * @return if the operation completed successfully + */ +UWAC_API UwacReturnCode UwacDestroyWindow(UwacWindow **window); + +/** + * Sets the region that should be considered opaque to the compositor. + * + * @param window the UwacWindow + * @param x + * @param y + * @param width + * @param height + * @return UWAC_SUCCESS on success, an error otherwise + */ +UWAC_API UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); + +/** + * Sets the region of the window that can trigger input events + * + * @param window the UwacWindow + * @param x + * @param y + * @param width + * @param height + * @return + */ +UWAC_API UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); + +/** + * retrieves a pointer on the current window content to draw a frame + * @param window the UwacWindow + * @return a pointer on the current window content + */ +UWAC_API void *UwacWindowGetDrawingBuffer(UwacWindow *window); + +/** + * sets a rectangle as dirty for the next frame of a window + * + * @param window the UwacWindow + * @param x left coordinate + * @param y top coordinate + * @param width the width of the dirty rectangle + * @param height the height of the dirty rectangle + * @return UWAC_SUCCESS on success, an Uwac error otherwise + */ +UWAC_API UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); + +/** + * Sends a frame to the compositor with the content of the drawing buffer + * + * @param window the UwacWindow to refresh + * @param copyContentForNextFrame if true the content to display is copied in the next drawing buffer + * @return UWAC_SUCCESS if the operation was successful + */ +UWAC_API UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNextFrame); + +/** + * returns the geometry of the given UwacWindows + * + * @param window the UwacWindow + * @param geometry the geometry to fill + * @return UWAC_SUCCESS on success, an Uwac error otherwise + */ +UWAC_API UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry); + +/** + * Sets or unset the fact that the window is set fullscreen. After this call the + * application should get prepared to receive a configure event. The output is used + * only when going fullscreen, it is optional and not used when exiting fullscreen. + * + * @param window the UwacWindow + * @param output an optional UwacOutput to put the window fullscreen on + * @param isFullscreen set or unset fullscreen + * @return UWAC_SUCCESS if the operation was a success + */ +UWAC_API UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *output, bool isFullscreen); + +/** + * When possible (depending on the shell) sets the title of the UwacWindow + * + * @param window the UwacWindow + * @param name title + */ +UWAC_API void UwacWindowSetTitle(UwacWindow *window, const char *name); + +/** + * + * @param display + * @param timeout + * @return + */ +UWAC_API int UwacDisplayDispatch(UwacDisplay *display, int timeout); + +/** + * Returns if you have some pending events, and you can UwacNextEvent() without blocking + * + * @param display the UwacDisplay + * @return if there's some pending events + */ +UWAC_API bool UwacHasEvent(UwacDisplay *display); + +/** Waits until an event occurs, and when it's there copy the event from the queue to + * event. + * + * @param display the Uwac display + * @param event the event to fill + * @return if the operation completed successfully + */ +UWAC_API UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event); + + +/** + * returns the name of the given UwacSeat + * + * @param seat the UwacSeat + * @return the name of the seat + */ +UWAC_API const char *UwacSeatGetName(const UwacSeat *seat); + +#ifdef __cplusplus +} +#endif + +#endif /* __UWAC_H_ */ diff --git a/uwac/libuwac/.gitignore b/uwac/libuwac/.gitignore new file mode 100644 index 0000000..11b3543 --- /dev/null +++ b/uwac/libuwac/.gitignore @@ -0,0 +1,7 @@ +fullscreen-shell-client-protocol.h +fullscreen-shell-protocol.c +ivi-application-client-protocol.h +ivi-application-protocol.c +xdg-shell-client-protocol.h +xdg-shell-protocol.c + diff --git a/uwac/libuwac/CMakeLists.txt b/uwac/libuwac/CMakeLists.txt new file mode 100644 index 0000000..4de9325 --- /dev/null +++ b/uwac/libuwac/CMakeLists.txt @@ -0,0 +1,80 @@ +# UWAC: Using Wayland As Client +# +# Copyright 2015 David FORT +# +# 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. + +set(MODULE_NAME "uwac") +set(MODULE_PREFIX "UWAC") + + +set(GENERATED_SOURCES "") +macro(generate_protocol_file PROTO) + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-protocol.c" + COMMAND ${WAYLAND_SCANNER} code < ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml > ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-protocol.c + DEPENDS ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml + ) + + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-client-protocol.h" + COMMAND ${WAYLAND_SCANNER} client-header < ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml > ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-client-protocol.h + DEPENDS ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml + ) + + list(APPEND GENERATED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-client-protocol.h) + list(APPEND GENERATED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-protocol.c) +endmacro() + +generate_protocol_file(xdg-shell) +generate_protocol_file(ivi-application) +generate_protocol_file(fullscreen-shell) + +include_directories(${WAYLAND_INCLUDE_DIR}) +include_directories(${XKBCOMMON_INCLUDE_DIR}) +include_directories("${CMAKE_SOURCE_DIR}/uwac/include") +include_directories("${CMAKE_BINARY_DIR}/uwac/include") +include_directories("${CMAKE_BINARY_DIR}/uwac/libuwac") + +add_definitions(-DBUILD_IVI -DBUILD_FULLSCREEN_SHELL -DENABLE_XKBCOMMON) + +set(${MODULE_PREFIX}_SRCS + ${GENERATED_SOURCES} + uwac-display.c + uwac-input.c + uwac-os.c + uwac-os.h + uwac-output.c + uwac-priv.h + uwac-tools.c + uwac-utils.c + uwac-window.c) + + +add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + + +if (WITH_LIBRARY_VERSIONING) + set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${UWAC_VERSION} SOVERSION ${UWAC_API_VERSION}) +endif() + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS} ${WAYLAND_LIBS} ${XKBCOMMON_LIBS} freerdp) + +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT uwac) + + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "uwac") + +if(BUILD_TESTING) +# add_subdirectory(test) +endif() diff --git a/uwac/libuwac/uwac-display.c b/uwac/libuwac/uwac-display.c new file mode 100644 index 0000000..2fa20b4 --- /dev/null +++ b/uwac/libuwac/uwac-display.c @@ -0,0 +1,631 @@ +/* + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include "uwac-priv.h" +#include "uwac-utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uwac-os.h" + +#define TARGET_COMPOSITOR_INTERFACE 3 +#define TARGET_SHM_INTERFACE 1 +#define TARGET_SHELL_INTERFACE 1 +#define TARGET_DDM_INTERFACE 1 +#define TARGET_SEAT_INTERFACE 5 +#define TARGET_XDG_VERSION 5 /* The version of xdg-shell that we implement */ + +static const char *event_names[] = { + "new seat", + "removed seat", + "new output", + "configure", + "pointer enter", + "pointer leave", + "pointer motion", + "pointer buttons", + "pointer axis", + "keyboard enter", + "key", + "touch frame begin", + "touch up", + "touch down", + "touch motion", + "touch cancel", + "touch frame end", + "frame done", + "close", + NULL +}; + +bool uwac_default_error_handler(UwacDisplay *display, UwacReturnCode code, const char *msg, ...) { + va_list args; + va_start(args, msg); + + vfprintf(stderr, "%s", args); + return false; +} + +UwacErrorHandler uwacErrorHandler = uwac_default_error_handler; + +void UwacInstallErrorHandler(UwacErrorHandler handler) { + if (handler) + uwacErrorHandler = handler; + else + uwacErrorHandler = uwac_default_error_handler; +} + + +static void cb_shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) +{ + UwacDisplay *d = data; + + if (format == WL_SHM_FORMAT_RGB565) + d->has_rgb565 = true; + + d->shm_formats_nb++; + d->shm_formats = xrealloc((void *)d->shm_formats, sizeof(enum wl_shm_format) * d->shm_formats_nb); + d->shm_formats[d->shm_formats_nb - 1] = format; +} + + +struct wl_shm_listener shm_listener = { + cb_shm_format +}; + +static void xdg_shell_ping(void *data, struct xdg_shell *shell, uint32_t serial) +{ + xdg_shell_pong(shell, serial); +} + +static const struct xdg_shell_listener xdg_shell_listener = { + xdg_shell_ping, +}; + +#ifdef BUILD_FULLSCREEN_SHELL +static void fullscreen_capability(void *data, struct _wl_fullscreen_shell *_wl_fullscreen_shell, + uint32_t capabilty) +{ +} + +static const struct _wl_fullscreen_shell_listener fullscreen_shell_listener = { + fullscreen_capability, +}; +#endif + + +static UwacSeat *display_destroy_seat(UwacDisplay *d, uint32_t name) +{ + UwacSeat *seat; + + wl_list_for_each(seat, &d->seats, link) { + if (seat->seat_id == name) { + UwacSeatDestroy(seat); + return seat; + } + } + + return NULL; +} + +static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, + const char *interface, uint32_t version) +{ + UwacDisplay *d = data; + UwacGlobal *global; + + global = xmalloc(sizeof *global); + global->name = id; + global->interface = xstrdup(interface); + global->version = version; + wl_list_insert(d->globals.prev, &global->link); + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, min(TARGET_COMPOSITOR_INTERFACE, version)); + } else if (strcmp(interface, "wl_shm") == 0) { + d->shm = wl_registry_bind(registry, id, &wl_shm_interface, min(TARGET_SHM_INTERFACE, version)); + wl_shm_add_listener(d->shm, &shm_listener, d); + } else if (strcmp(interface, "wl_output") == 0) { + UwacOutput *output; + UwacOutputNewEvent *ev; + + output = UwacCreateOutput(d, id, version); + if (!output) { + assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create output\n")); + return; + } + + ev = (UwacOutputNewEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_OUTPUT); + if (ev) + ev->output = output; + + } else if (strcmp(interface, "wl_seat") == 0) { + UwacSeatNewEvent *ev; + UwacSeat *seat; + + seat = UwacSeatNew(d, id, min(version, TARGET_SEAT_INTERFACE)); + if (!seat) { + assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create new seat\n")); + return; + } + + ev = (UwacSeatNewEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_SEAT); + if (!ev) { + assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create new seat event\n")); + return; + } + + ev->seat = seat; + } else if (strcmp(interface, "wl_data_device_manager") == 0) { + d->data_device_manager = wl_registry_bind(registry, id, &wl_data_device_manager_interface, min(TARGET_DDM_INTERFACE, version)); + } else if (strcmp(interface, "wl_shell") == 0) { + d->shell = wl_registry_bind(registry, id, &wl_shell_interface, min(TARGET_SHELL_INTERFACE, version)); + } else if (strcmp(interface, "xdg_shell") == 0) { + d->xdg_shell = wl_registry_bind(registry, id, &xdg_shell_interface, 1); + xdg_shell_use_unstable_version(d->xdg_shell, TARGET_XDG_VERSION); + xdg_shell_add_listener(d->xdg_shell, &xdg_shell_listener, d); +#if BUILD_IVI + } else if (strcmp(interface, "ivi_application") == 0) { + d->ivi_application = wl_registry_bind(registry, id, &ivi_application_interface, 1); +#endif +#if BUILD_FULLSCREEN_SHELL + } else if (strcmp(interface, "_wl_fullscreen_shell") == 0) { + d->fullscreen_shell = wl_registry_bind(registry, id, &_wl_fullscreen_shell_interface, 1); + _wl_fullscreen_shell_add_listener(d->fullscreen_shell, &fullscreen_shell_listener, d); +#endif +#if 0 + } else if (strcmp(interface, "text_cursor_position") == 0) { + d->text_cursor_position = wl_registry_bind(registry, id, &text_cursor_position_interface, 1); + } else if (strcmp(interface, "workspace_manager") == 0) { + //init_workspace_manager(d, id); + } else if (strcmp(interface, "wl_subcompositor") == 0) { + d->subcompositor = wl_registry_bind(registry, id, &wl_subcompositor_interface, 1); +#endif + } +} + +static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { + UwacDisplay *d = data; + UwacGlobal *global; + UwacGlobal *tmp; + + wl_list_for_each_safe(global, tmp, &d->globals, link) { + if (global->name != name) + continue; + +#if 0 + if (strcmp(global->interface, "wl_output") == 0) + display_destroy_output(d, name); +#endif + + if (strcmp(global->interface, "wl_seat") == 0) { + UwacSeatRemovedEvent *ev; + UwacSeat *seat; + + seat = display_destroy_seat(d, name); + ev = (UwacSeatRemovedEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_REMOVED_SEAT); + if (ev) + ev->seat = seat; + } + + + wl_list_remove(&global->link); + free(global->interface); + free(global); + } +} + +void UwacDestroyGlobal(UwacGlobal *global) { + free(global->interface); + wl_list_remove(&global->link); + free(global); +} + +void *display_bind(UwacDisplay *display, uint32_t name, const struct wl_interface *interface, uint32_t version) { + return wl_registry_bind(display->registry, name, interface, version); +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + + +int UwacDisplayWatchFd(UwacDisplay *display, int fd, uint32_t events, UwacTask *task) { + struct epoll_event ep; + + ep.events = events; + ep.data.ptr = task; + return epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep); +} + +void UwacDisplayUnwatchFd(UwacDisplay *display, int fd) { + epoll_ctl(display->epoll_fd, EPOLL_CTL_DEL, fd, NULL); +} + +static void display_exit(UwacDisplay *display) { + display->running = false; +} + +static void display_dispatch_events(UwacTask *task, uint32_t events) +{ + UwacDisplay *display = container_of(task, UwacDisplay, dispatch_fd_task); + struct epoll_event ep; + int ret; + + display->display_fd_events = events; + + if ((events & EPOLLERR) || (events & EPOLLHUP)) { + display_exit(display); + return; + } + + if (events & EPOLLIN) { + ret = wl_display_dispatch(display->display); + if (ret == -1) { + display_exit(display); + return; + } + } + + if (events & EPOLLOUT) { + ret = wl_display_flush(display->display); + if (ret == 0) { + ep.events = EPOLLIN | EPOLLERR | EPOLLHUP; + ep.data.ptr = &display->dispatch_fd_task; + epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, display->display_fd, &ep); + } else if (ret == -1 && errno != EAGAIN) { + display_exit(display); + return; + } + } +} + + +UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err) { + UwacDisplay *ret; + + ret = (UwacDisplay *)calloc(1, sizeof(*ret)); + if (!ret) { + *err = UWAC_ERROR_NOMEMORY; + return NULL; + } + + wl_list_init(&ret->globals); + wl_list_init(&ret->seats); + wl_list_init(&ret->outputs); + wl_list_init(&ret->windows); + + ret->display = wl_display_connect(name); + if (ret->display == NULL) { + fprintf(stderr, "failed to connect to Wayland display %s: %m\n", name); + *err = UWAC_ERROR_UNABLE_TO_CONNECT; + goto out_free; + } + + ret->epoll_fd = uwac_os_epoll_create_cloexec(); + if (ret->epoll_fd < 0) { + *err = UWAC_NOT_ENOUGH_RESOURCES; + goto out_disconnect; + } + + ret->display_fd = wl_display_get_fd(ret->display); + + ret->registry = wl_display_get_registry(ret->display); + if (!ret->registry) { + *err = UWAC_ERROR_NOMEMORY; + goto out_close_epoll; + } + + wl_registry_add_listener(ret->registry, ®istry_listener, ret); + + if ((wl_display_roundtrip(ret->display) < 0) || (wl_display_roundtrip(ret->display) < 0)) { + uwacErrorHandler(ret, UWAC_ERROR_UNABLE_TO_CONNECT, "Failed to process Wayland connection: %m\n"); + *err = UWAC_ERROR_UNABLE_TO_CONNECT; + goto out_free_registry; + } + + ret->dispatch_fd_task.run = display_dispatch_events; + if (UwacDisplayWatchFd(ret, ret->display_fd, EPOLLIN | EPOLLERR | EPOLLHUP, &ret->dispatch_fd_task) < 0) { + uwacErrorHandler(ret, UWAC_ERROR_INTERNAL, "unable to watch display fd: %m\n"); + *err = UWAC_ERROR_INTERNAL; + goto out_free_registry; + } + + ret->running = true; + ret->last_error = *err = UWAC_SUCCESS; + return ret; + +out_free_registry: + wl_registry_destroy(ret->registry); +out_close_epoll: + close(ret->epoll_fd); +out_disconnect: + wl_display_disconnect(ret->display); +out_free: + free(ret); + return NULL; +} + +int UwacDisplayDispatch(UwacDisplay *display, int timeout) { + int ret, count, i; + UwacTask *task; + struct epoll_event ep[16]; + + wl_display_dispatch_pending(display->display); + + if (!display->running) + return 0; + + ret = wl_display_flush(display->display); + if (ret < 0 && errno == EAGAIN) { + ep[0].events = (EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP); + ep[0].data.ptr = &display->dispatch_fd_task; + + epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, display->display_fd, &ep[0]); + } else if (ret < 0) { + return -1; + } + + count = epoll_wait(display->epoll_fd, ep, ARRAY_LENGTH(ep), timeout); + for (i = 0; i < count; i++) { + task = ep[i].data.ptr; + task->run(task, ep[i].events); + } + + return 1; +} + + + +UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display) { + return display->last_error; +} + +UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay) { + UwacDisplay *display; + UwacSeat *seat, *tmpSeat; + UwacWindow *window, *tmpWindow; + UwacOutput *output, *tmpOutput; + UwacGlobal *global, *tmpGlobal; + + assert(pdisplay); + display = *pdisplay; + if (!display) + return UWAC_ERROR_INVALID_DISPLAY; + + /* destroy windows */ + wl_list_for_each_safe(window, tmpWindow, &display->windows, link) { + UwacDestroyWindow(&window); + } + + /* destroy seats */ + wl_list_for_each_safe(seat, tmpSeat, &display->seats, link) { + UwacSeatDestroy(seat); + } + + /* destroy output */ + wl_list_for_each_safe(output, tmpOutput, &display->outputs, link) { + UwacDestroyOutput(output); + } + + /* destroy globals */ + wl_list_for_each_safe(global, tmpGlobal, &display->globals, link) { + UwacDestroyGlobal(global); + } + + if (display->compositor) + wl_compositor_destroy(display->compositor); +#ifdef BUILD_FULLSCREEN_SHELL + if (display->fullscreen_shell) + _wl_fullscreen_shell_destroy(display->fullscreen_shell); +#endif +#ifdef BUILD_IVI + if (display->ivi_application) + ivi_application_destroy(display->ivi_application); +#endif + if (display->xdg_shell) + xdg_shell_destroy(display->xdg_shell); + if (display->shell) + wl_shell_destroy(display->shell); + if (display->shm) + wl_shm_destroy(display->shm); + if (display->subcompositor) + wl_subcompositor_destroy(display->subcompositor); + if (display->data_device_manager) + wl_data_device_manager_destroy(display->data_device_manager); + + free(display->shm_formats); + wl_registry_destroy(display->registry); + + close(display->epoll_fd); + + wl_display_disconnect(display->display); + + /* cleanup the event queue */ + while (display->push_queue) { + UwacEventListItem *item = display->push_queue; + + display->push_queue = item->tail; + free(item); + } + + free(display); + *pdisplay = NULL; + return UWAC_SUCCESS; +} + +int UwacDisplayGetFd(UwacDisplay *display) { + return display->epoll_fd; +} + +static const char *errorStrings[] = { + "success", + "out of memory error", + "unable to connect to wayland display", + "invalid UWAC display", + "not enough resources", + "timed out", + "not found", + "closed connection", + + "internal error", +}; + +const char *UwacErrorString(UwacReturnCode error) { + if (error < 0 || error >= UWAC_ERROR_LAST) + return "invalid error code"; + + return errorStrings[error]; +} + +UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, const char *name, uint32_t *version) { + const UwacGlobal *global; + + if (!display) + return UWAC_ERROR_INVALID_DISPLAY; + + wl_list_for_each(global, &display->globals, link) { + if (strcmp(global->interface, name) == 0) { + if (version) + *version = global->version; + return UWAC_SUCCESS; + } + } + + return UWAC_NOT_FOUND; +} + +uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display) { + if (!display) { + display->last_error = UWAC_ERROR_INVALID_DISPLAY; + return 0; + } + + if (!display->shm) { + display->last_error = UWAC_NOT_FOUND; + return 0; + } + + display->last_error = UWAC_SUCCESS; + return display->shm_formats_nb; +} + + +UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_shm_format *formats, int formats_size, int *filled) { + if (!display) + return UWAC_ERROR_INVALID_DISPLAY; + + *filled = min(display->shm_formats_nb, formats_size); + memcpy(formats, (const void *)display->shm_formats, *filled * sizeof(enum wl_shm_format)); + + return UWAC_SUCCESS; +} + +uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display) { + return wl_list_length(&display->outputs); +} + +UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index) { + struct wl_list *l; + int i; + + for (i = 0, l = &display->outputs; l && i < index; i++, l = l->next) + ; + + if (!l) { + display->last_error = UWAC_NOT_FOUND; + return NULL; + } + + display->last_error = UWAC_SUCCESS; + return container_of(l, UwacOutput, link); +} + +UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution) { + *resolution = output->resolution; + return UWAC_SUCCESS; +} + + +UwacEvent *UwacDisplayNewEvent(UwacDisplay *display, int type) { + UwacEventListItem *ret; + + if (!display) { + display->last_error = UWAC_ERROR_INVALID_DISPLAY; + return 0; + } + + ret = zalloc(sizeof(UwacEventListItem)); + if (!ret) { + assert(uwacErrorHandler(display, UWAC_ERROR_NOMEMORY, "unable to allocate a '%s' event", event_names[type])); + display->last_error = UWAC_ERROR_NOMEMORY; + return 0; + } + + ret->event.type = type; + ret->tail = display->push_queue; + if (ret->tail) + ret->tail->head = ret; + else + display->pop_queue = ret; + display->push_queue = ret; + return &ret->event; +} + +bool UwacHasEvent(UwacDisplay *display) { + return display->pop_queue != NULL; +} + + +UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event) { + UwacEventListItem *prevItem; + int ret; + + if (!display) + return UWAC_ERROR_INVALID_DISPLAY; + + while (!display->pop_queue) { + ret = UwacDisplayDispatch(display, 1 * 1000); + if (ret < 0) + return UWAC_ERROR_INTERNAL; + else if (ret == 0) + return UWAC_ERROR_CLOSED; + } + + prevItem = display->pop_queue->head; + *event = display->pop_queue->event; + free(display->pop_queue); + display->pop_queue = prevItem; + if (prevItem) + prevItem->tail = NULL; + else + display->push_queue = NULL; + return UWAC_SUCCESS; +} diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c new file mode 100644 index 0000000..76e2f5e --- /dev/null +++ b/uwac/libuwac/uwac-input.c @@ -0,0 +1,847 @@ +/* + * Copyright © 2014-2015 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include "uwac-priv.h" +#include "uwac-utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void keyboard_repeat_func(UwacTask *task, uint32_t events) +{ + UwacSeat *input = container_of(task, UwacSeat, repeat_task); + UwacWindow *window = input->keyboard_focus; + uint64_t exp; + + if (read(input->repeat_timer_fd, &exp, sizeof exp) != sizeof exp) + /* If we change the timer between the fd becoming + * readable and getting here, there'll be nothing to + * read and we get EAGAIN. */ + return; + + if (window) { + UwacKeyEvent *key; + + key = (UwacKeyEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEY); + if (!key) + return; + + key->window = window; + key->sym = input->repeat_sym; + key->pressed = true; + } + +} + +static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, + uint32_t format, int fd, uint32_t size) +{ + UwacSeat *input = data; + struct xkb_keymap *keymap; + struct xkb_state *state; + char *map_str; + + if (!data) { + close(fd); + return; + } + + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + close(fd); + return; + } + + map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map_str == MAP_FAILED) { + close(fd); + return; + } + + keymap = xkb_keymap_new_from_string(input->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); + munmap(map_str, size); + close(fd); + + if (!keymap) { + assert(uwacErrorHandler(input->display, UWAC_ERROR_INTERNAL, "failed to compile keymap\n")); + return; + } + + state = xkb_state_new(keymap); + if (!state) { + assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY, "failed to create XKB state\n")); + xkb_keymap_unref(keymap); + return; + } + + xkb_keymap_unref(input->xkb.keymap); + xkb_state_unref(input->xkb.state); + input->xkb.keymap = keymap; + input->xkb.state = state; + + input->xkb.control_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Control"); + input->xkb.alt_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Mod1"); + input->xkb.shift_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Shift"); +} + +static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t time, uint32_t key, + uint32_t state_w); + +static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, + struct wl_surface *surface, struct wl_array *keys) +{ + uint32_t *key, *pressedKey; + UwacSeat *input = (UwacSeat *)data; + int i, found; + UwacKeyboardEnterLeaveEvent *event; + + event = (UwacKeyboardEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEYBOARD_ENTER); + if (!event) + return; + + event->window = input->keyboard_focus = (UwacWindow *)wl_surface_get_user_data(surface); + + /* look for keys that have been released */ + found = false; + for (pressedKey = input->pressed_keys.data, i = 0; i < input->pressed_keys.size; i += sizeof(uint32_t)) { + wl_array_for_each(key, keys) { + if (*key == *pressedKey) { + found = true; + break; + } + } + + if (!found) { + keyboard_handle_key(data, keyboard, serial, 0, *pressedKey, WL_KEYBOARD_KEY_STATE_RELEASED); + } else { + pressedKey++; + } + } + + /* handle keys that are now pressed */ + wl_array_for_each(key, keys) { + keyboard_handle_key(data, keyboard, serial, 0, *key, WL_KEYBOARD_KEY_STATE_PRESSED); + } +} + +static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, + struct wl_surface *surface) +{ + struct itimerspec its; + UwacSeat *input; + UwacPointerEnterLeaveEvent *event; + + input = (UwacSeat *)data; + + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 0; + timerfd_settime(input->repeat_timer_fd, 0, &its, NULL); + + event = (UwacPointerEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_LEAVE); + if (!event) + return; + + event->window = input->keyboard_focus; +} + +static int update_key_pressed(UwacSeat *seat, uint32_t key) { + uint32_t *keyPtr; + + /* check if the key is not already pressed */ + wl_array_for_each(keyPtr, &seat->pressed_keys) { + if (*keyPtr == key) + return 1; + } + + keyPtr = wl_array_add(&seat->pressed_keys, sizeof(uint32_t)); + if (!keyPtr) + return -1; + + *keyPtr = key; + return 0; +} + +static int update_key_released(UwacSeat *seat, uint32_t key) { + uint32_t *keyPtr; + int i, toMove; + bool found = false; + + for (i = 0, keyPtr = seat->pressed_keys.data; i < seat->pressed_keys.size; i++, keyPtr++) { + if (*keyPtr == key) { + found = true; + break; + } + } + + if (found) { + toMove = seat->pressed_keys.size - ((i + 1) * sizeof(uint32_t)); + if (toMove) + memmove(keyPtr, keyPtr+1, toMove); + + seat->pressed_keys.size -= sizeof(uint32_t); + } + return 1; + +} + +static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t time, uint32_t key, + uint32_t state_w) +{ + UwacSeat *input = (UwacSeat *)data; + UwacWindow *window = input->keyboard_focus; + UwacKeyEvent *keyEvent; + + uint32_t code, num_syms; + enum wl_keyboard_key_state state = state_w; + const xkb_keysym_t *syms; + xkb_keysym_t sym; + struct itimerspec its; + + if (state_w == WL_KEYBOARD_KEY_STATE_PRESSED) + update_key_pressed(input, key); + else + update_key_released(input, key); + + input->display->serial = serial; + code = key + 8; + if (!window || !input->xkb.state) + return; + + /* We only use input grabs for pointer events for now, so just + * ignore key presses if a grab is active. We expand the key + * event delivery mechanism to route events to widgets to + * properly handle key grabs. In the meantime, this prevents + * key event delivery while a grab is active. */ + /*if (input->grab && input->grab_button == 0) + return;*/ + + num_syms = xkb_state_key_get_syms(input->xkb.state, code, &syms); + + sym = XKB_KEY_NoSymbol; + if (num_syms == 1) + sym = syms[0]; + + if (state == WL_KEYBOARD_KEY_STATE_RELEASED && key == input->repeat_key) { + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 0; + timerfd_settime(input->repeat_timer_fd, 0, &its, NULL); + } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED && xkb_keymap_key_repeats(input->xkb.keymap, code)) { + input->repeat_sym = sym; + input->repeat_key = key; + input->repeat_time = time; + its.it_interval.tv_sec = input->repeat_rate_sec; + its.it_interval.tv_nsec = input->repeat_rate_nsec; + its.it_value.tv_sec = input->repeat_delay_sec; + its.it_value.tv_nsec = input->repeat_delay_nsec; + timerfd_settime(input->repeat_timer_fd, 0, &its, NULL); + } + + keyEvent = (UwacKeyEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEY); + if (!keyEvent) + return; + + keyEvent->window = window; + keyEvent->sym = sym; + keyEvent->raw_key = key; + keyEvent->pressed = (state == WL_KEYBOARD_KEY_STATE_PRESSED); +} + +static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, + uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) +{ + UwacSeat *input = data; + xkb_mod_mask_t mask; + + /* If we're not using a keymap, then we don't handle PC-style modifiers */ + if (!input->xkb.keymap) + return; + + xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group); + mask = xkb_state_serialize_mods(input->xkb.state, XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + input->modifiers = 0; + if (mask & input->xkb.control_mask) + input->modifiers |= UWAC_MOD_CONTROL_MASK; + if (mask & input->xkb.alt_mask) + input->modifiers |= UWAC_MOD_ALT_MASK; + if (mask & input->xkb.shift_mask) + input->modifiers |= UWAC_MOD_SHIFT_MASK; +} + +static void set_repeat_info(UwacSeat *input, int32_t rate, int32_t delay) +{ + input->repeat_rate_sec = input->repeat_rate_nsec = 0; + input->repeat_delay_sec = input->repeat_delay_nsec = 0; + + /* a rate of zero disables any repeating, regardless of the delay's + * value */ + if (rate == 0) + return; + + if (rate == 1) + input->repeat_rate_sec = 1; + else + input->repeat_rate_nsec = 1000000000 / rate; + + input->repeat_delay_sec = delay / 1000; + delay -= (input->repeat_delay_sec * 1000); + input->repeat_delay_nsec = delay * 1000 * 1000; +} + + +static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard, + int32_t rate, int32_t delay) +{ + UwacSeat *input = data; + + set_repeat_info(input, rate, delay); +} + +static const struct wl_keyboard_listener keyboard_listener = { + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, + keyboard_handle_repeat_info +}; + +static bool touch_send_start_frame(UwacSeat *seat) { + UwacTouchFrameBegin *ev; + + ev = (UwacTouchFrameBegin *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_FRAME_BEGIN); + if (!ev) + return false; + + seat->touch_frame_started = true; + return true; +} + +static void touch_handle_down(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, struct wl_surface *surface, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + UwacSeat *seat = data; + UwacTouchDown *tdata; + + seat->display->serial = serial; + if (!seat->touch_frame_started && !touch_send_start_frame(seat)) + return; + + tdata = (UwacTouchDown *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_DOWN); + if (!tdata) + return; + + tdata->seat = seat; + tdata->id = id; + tdata->x = x_w; + tdata->y = y_w; + +#if 0 + struct widget *widget; + float sx = wl_fixed_to_double(x); + float sy = wl_fixed_to_double(y); + + + input->touch_focus = wl_surface_get_user_data(surface); + if (!input->touch_focus) { + DBG("Failed to find to touch focus for surface %p\n", surface); + return; + } + + if (surface != input->touch_focus->main_surface->surface) { + DBG("Ignoring input event from subsurface %p\n", surface); + input->touch_focus = NULL; + return; + } + + if (input->grab) + widget = input->grab; + else + widget = window_find_widget(input->touch_focus, + wl_fixed_to_double(x), + wl_fixed_to_double(y)); + if (widget) { + struct touch_point *tp = xmalloc(sizeof *tp); + if (tp) { + tp->id = id; + tp->widget = widget; + tp->x = sx; + tp->y = sy; + wl_list_insert(&input->touch_point_list, &tp->link); + + if (widget->touch_down_handler) + (*widget->touch_down_handler)(widget, input, + serial, time, id, + sx, sy, + widget->user_data); + } + } +#endif +} + +static void touch_handle_up(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, int32_t id) +{ + UwacSeat *seat = data; + UwacTouchUp *tdata; + + if (!seat->touch_frame_started && !touch_send_start_frame(seat)) + return; + + tdata = (UwacTouchUp *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_UP); + if (!tdata) + return; + + tdata->seat = seat; + tdata->id = id; + + +#if 0 + struct touch_point *tp, *tmp; + + if (!input->touch_focus) { + DBG("No touch focus found for touch up event!\n"); + return; + } + + wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) { + if (tp->id != id) + continue; + + if (tp->widget->touch_up_handler) + (*tp->widget->touch_up_handler)(tp->widget, input, serial, + time, id, + tp->widget->user_data); + + wl_list_remove(&tp->link); + free(tp); + + return; + } +#endif +} + +static void touch_handle_motion(void *data, struct wl_touch *wl_touch, + uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + UwacSeat *seat = data; + UwacTouchMotion *tdata; + + if (!seat->touch_frame_started && !touch_send_start_frame(seat)) + return; + + tdata = (UwacTouchMotion *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_MOTION); + if (!tdata) + return; + + tdata->seat = seat; + tdata->id = id; + tdata->x = x_w; + tdata->y = y_w; + +#if 0 + struct touch_point *tp; + float sx = wl_fixed_to_double(x); + float sy = wl_fixed_to_double(y); + + DBG("touch_handle_motion: %i %i\n", id, wl_list_length(&seat->touch_point_list)); + + if (!seat->touch_focus) { + DBG("No touch focus found for touch motion event!\n"); + return; + } + + wl_list_for_each(tp, &seat->touch_point_list, link) { + if (tp->id != id) + continue; + + tp->x = sx; + tp->y = sy; + if (tp->widget->touch_motion_handler) + (*tp->widget->touch_motion_handler)(tp->widget, seat, time, + id, sx, sy, + tp->widget->user_data); + return; + } +#endif +} + +static void touch_handle_frame(void *data, struct wl_touch *wl_touch) +{ + UwacSeat *seat = data; + UwacTouchFrameEnd *ev; + + ev = (UwacTouchFrameEnd *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_FRAME_END); + if (!ev) + return; + + ev->seat = seat; + seat->touch_frame_started = false; +} + +static void touch_handle_cancel(void *data, struct wl_touch *wl_touch) +{ + UwacSeat *seat = data; + UwacTouchCancel *ev; + + ev = (UwacTouchCancel *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_CANCEL); + if (!ev) + return; + + ev->seat = seat; + seat->touch_frame_started = false; + +#if 0 + struct touch_point *tp, *tmp; + + DBG("touch_handle_cancel\n"); + + if (!input->touch_focus) { + DBG("No touch focus found for touch cancel event!\n"); + return; + } + + wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) { + if (tp->widget->touch_cancel_handler) + (*tp->widget->touch_cancel_handler)(tp->widget, input, + tp->widget->user_data); + + wl_list_remove(&tp->link); + free(tp); + } +#endif +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel, +}; + + +static void pointer_handle_enter(void *data, struct wl_pointer *pointer, uint32_t serial, + struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + UwacSeat *input = data; + UwacWindow *window; + UwacPointerEnterLeaveEvent *event; + + float sx = wl_fixed_to_double(sx_w); + float sy = wl_fixed_to_double(sy_w); + + if (!surface) { + /* enter event for a window we've just destroyed */ + return; + } + + input->display->serial = serial; + window = wl_surface_get_user_data(surface); + if (window) + window->pointer_enter_serial = serial; + input->pointer_focus = window; + input->sx = sx; + input->sy = sy; + + event = (UwacPointerEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_ENTER); + if (!event) + return; + + event->seat = input; + event->window = window; + event->x = sx; + event->y = sy; +} + +static void pointer_handle_leave(void *data, struct wl_pointer *pointer, uint32_t serial, + struct wl_surface *surface) +{ + UwacPointerEnterLeaveEvent *event; + UwacWindow *window; + UwacSeat *input = data; + + input->display->serial = serial; + + event = (UwacPointerEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_LEAVE); + if (!event) + return; + + window = wl_surface_get_user_data(surface); + + event->seat = input; + event->window = window; + +#if 0 + input_remove_pointer_focus(input); +#endif +} + +static void pointer_handle_motion(void *data, struct wl_pointer *pointer, uint32_t time, + wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + UwacPointerMotionEvent *motion_event; + UwacSeat *input = data; + UwacWindow *window = input->pointer_focus; + + float sx = wl_fixed_to_double(sx_w); + float sy = wl_fixed_to_double(sy_w); + + if (!window) + return; + + input->sx = sx; + input->sy = sy; + + motion_event = (UwacPointerMotionEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_MOTION); + if (!motion_event) + return; + + motion_event->seat = input; + motion_event->window = window; + motion_event->x = wl_fixed_to_int(sx_w); + motion_event->y = wl_fixed_to_int(sy_w); +} + +static void pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, + uint32_t time, uint32_t button, uint32_t state_w) +{ + UwacPointerButtonEvent *event; + UwacSeat *seat = data; + UwacWindow *window = seat->pointer_focus; + + seat->display->serial = serial; + + event = (UwacPointerButtonEvent *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_BUTTONS); + if (!event) + return; + + event->seat = seat; + event->window = window; + event->x = seat->sx; + event->y = seat->sy; + event->button = button; + event->state = (enum wl_pointer_button_state)state_w; +} + +static void pointer_handle_axis(void *data, struct wl_pointer *pointer, uint32_t time, + uint32_t axis, wl_fixed_t value) +{ + UwacPointerAxisEvent *event; + UwacSeat *seat = data; + UwacWindow *window = seat->pointer_focus; + + if (!window) + return; + + event = (UwacPointerAxisEvent *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_AXIS); + if (!event) + return; + + event->seat = seat; + event->window = window; + event->x = seat->sx; + event->y = seat->sy; + event->axis = axis; + event->value = value; +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + + + +static void seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps) +{ + UwacSeat *input = data; + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) { + input->pointer = wl_seat_get_pointer(seat); + wl_pointer_set_user_data(input->pointer, input); + wl_pointer_add_listener(input->pointer, &pointer_listener, input); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) { +#ifdef WL_POINTER_RELEASE_SINCE_VERSION + if (input->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION) + wl_pointer_release(input->pointer); + else +#endif + wl_pointer_destroy(input->pointer); + input->pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) { + input->keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_set_user_data(input->keyboard, input); + wl_keyboard_add_listener(input->keyboard, &keyboard_listener, input); + } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) { +#ifdef WL_KEYBOARD_RELEASE_SINCE_VERSION + if (input->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION) + wl_keyboard_release(input->keyboard); + else +#endif + wl_keyboard_destroy(input->keyboard); + input->keyboard = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) { + input->touch = wl_seat_get_touch(seat); + wl_touch_set_user_data(input->touch, input); + wl_touch_add_listener(input->touch, &touch_listener, input); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) { +#ifdef WL_TOUCH_RELEASE_SINCE_VERSION + if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION) + wl_touch_release(input->touch); + else +#endif + wl_touch_destroy(input->touch); + input->touch = NULL; + } +} + +static void +seat_handle_name(void *data, struct wl_seat *seat, const char *name) +{ + UwacSeat *input = data; + if (input->name) + free(input->name); + + input->name = strdup(name); + if (!input->name) + assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY, "unable to strdup seat's name\n")); +} + +static const struct wl_seat_listener seat_listener = { + seat_handle_capabilities, + seat_handle_name, +}; + + +UwacSeat *UwacSeatNew(UwacDisplay *d, uint32_t id, uint32_t version) { + UwacSeat *ret; + + ret = zalloc(sizeof(UwacSeat)); + ret->display = d; + ret->seat_id = id; + ret->seat_version = version; + + wl_array_init(&ret->pressed_keys); + ret->xkb_context = xkb_context_new(0); + if (!ret->xkb_context) { + fprintf(stderr, "%s: unable to allocate a xkb_context\n", __FUNCTION__); + goto error_xkb_context; + } + + ret->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, version); + wl_seat_add_listener(ret->seat, &seat_listener, ret); + wl_seat_set_user_data(ret->seat, ret); + + ret->repeat_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + if (ret->repeat_timer_fd < 0) { + fprintf(stderr, "%s: error creating repeat timer\n", __FUNCTION__); + goto error_timer_fd; + } + ret->repeat_task.run = keyboard_repeat_func; + if (UwacDisplayWatchFd(d, ret->repeat_timer_fd, EPOLLIN, &ret->repeat_task) < 0) { + fprintf(stderr, "%s: error polling repeat timer\n", __FUNCTION__); + goto error_watch_timerfd; + } + + wl_list_insert(d->seats.prev, &ret->link); + return ret; + +error_watch_timerfd: + close(ret->repeat_timer_fd); +error_timer_fd: + wl_seat_destroy(ret->seat); +error_xkb_context: + free(ret); + return NULL; +} + +void UwacSeatDestroy(UwacSeat *s) { + if (s->seat) { +#ifdef WL_SEAT_RELEASE_SINCE_VERSION + if (s->seat_version >= WL_SEAT_RELEASE_SINCE_VERSION) + wl_seat_release(s->seat); + else +#endif + wl_seat_destroy(s->seat); + } + s->seat = NULL; + + free(s->name); + wl_array_release(&s->pressed_keys); + + xkb_state_unref(s->xkb.state); + xkb_context_unref(s->xkb_context); + + if (s->pointer) { +#ifdef WL_POINTER_RELEASE_SINCE_VERSION + if (s->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION) + wl_pointer_release(s->pointer); + else +#endif + wl_pointer_destroy(s->pointer); + } + + if (s->touch) { +#ifdef WL_TOUCH_RELEASE_SINCE_VERSION + if (s->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION) + wl_touch_release(s->touch); + else +#endif + wl_touch_destroy(s->touch); + } + + if (s->keyboard) { +#ifdef WL_KEYBOARD_RELEASE_SINCE_VERSION + if (s->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION) + wl_keyboard_release(s->keyboard); + else +#endif + wl_keyboard_destroy(s->keyboard); + } + + wl_list_remove(&s->link); + free(s); +} + +const char *UwacSeatGetName(const UwacSeat *seat) { + return seat->name; +} diff --git a/uwac/libuwac/uwac-os.c b/uwac/libuwac/uwac-os.c new file mode 100644 index 0000000..ec9efe4 --- /dev/null +++ b/uwac/libuwac/uwac-os.c @@ -0,0 +1,236 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * This file is an adaptation of src/wayland-os.h from the wayland project and + * shared/os-compatiblity.h from the weston project. + * + * Functions have been renamed just to prevent name clashes. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../config.h" +#include "uwac-os.h" + +static int set_cloexec_or_close(int fd) +{ + long flags; + + if (fd == -1) + return -1; + + flags = fcntl(fd, F_GETFD); + if (flags == -1) + goto err; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + goto err; + + return fd; + +err: + close(fd); + return -1; +} + +int uwac_os_socket_cloexec(int domain, int type, int protocol) +{ + int fd; + + fd = socket(domain, type | SOCK_CLOEXEC, protocol); + if (fd >= 0) + return fd; + if (errno != EINVAL) + return -1; + + fd = socket(domain, type, protocol); + return set_cloexec_or_close(fd); +} + +int uwac_os_dupfd_cloexec(int fd, long minfd) +{ + int newfd; + + newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd); + if (newfd >= 0) + return newfd; + if (errno != EINVAL) + return -1; + + newfd = fcntl(fd, F_DUPFD, minfd); + return set_cloexec_or_close(newfd); +} + +static ssize_t recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags) +{ + ssize_t len; + struct cmsghdr *cmsg; + unsigned char *data; + int *fd; + int *end; + + len = recvmsg(sockfd, msg, flags); + if (len == -1) + return -1; + + if (!msg->msg_control || msg->msg_controllen == 0) + return len; + + cmsg = CMSG_FIRSTHDR(msg); + for (; cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) { + if (cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) + continue; + + data = CMSG_DATA(cmsg); + end = (int *)(data + cmsg->cmsg_len - CMSG_LEN(0)); + for (fd = (int *)data; fd < end; ++fd) + *fd = set_cloexec_or_close(*fd); + } + + return len; +} + +ssize_t uwac_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags) +{ + ssize_t len; + + len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC); + if (len >= 0) + return len; + if (errno != EINVAL) + return -1; + + return recvmsg_cloexec_fallback(sockfd, msg, flags); +} + +int uwac_os_epoll_create_cloexec(void) +{ + int fd; + +#ifdef EPOLL_CLOEXEC + fd = epoll_create1(EPOLL_CLOEXEC); + if (fd >= 0) + return fd; + if (errno != EINVAL) + return -1; +#endif + + fd = epoll_create(1); + return set_cloexec_or_close(fd); +} + +static int create_tmpfile_cloexec(char *tmpname) +{ + int fd; + +#ifdef HAVE_MKOSTEMP + fd = mkostemp(tmpname, O_CLOEXEC); + if (fd >= 0) + unlink(tmpname); +#else + fd = mkstemp(tmpname); + if (fd >= 0) { + fd = set_cloexec_or_close(fd); + unlink(tmpname); + } +#endif + + return fd; +} + +/* + * Create a new, unique, anonymous file of the given size, and + * return the file descriptor for it. The file descriptor is set + * CLOEXEC. The file is immediately suitable for mmap()'ing + * the given size at offset zero. + * + * The file should not have a permanent backing store like a disk, + * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. + * + * The file name is deleted from the file system. + * + * The file is suitable for buffer sharing between processes by + * transmitting the file descriptor over Unix sockets using the + * SCM_RIGHTS methods. + * + * If the C library implements posix_fallocate(), it is used to + * guarantee that disk space is available for the file at the + * given size. If disk space is insufficient, errno is set to ENOSPC. + * If posix_fallocate() is not supported, program may receive + * SIGBUS on accessing mmap()'ed file contents instead. + */ +int uwac_create_anonymous_file(off_t size) +{ + static const char template[] = "/weston-shared-XXXXXX"; + const char *path; + char *name; + int fd; + int ret; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + name = malloc(strlen(path) + sizeof(template)); + if (!name) + return -1; + + strcpy(name, path); + strcat(name, template); + + fd = create_tmpfile_cloexec(name); + + free(name); + + if (fd < 0) + return -1; + +#ifdef HAVE_POSIX_FALLOCATE + ret = posix_fallocate(fd, 0, size); + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } +#else + ret = ftruncate(fd, size); + if (ret < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} diff --git a/uwac/libuwac/uwac-os.h b/uwac/libuwac/uwac-os.h new file mode 100644 index 0000000..be927df --- /dev/null +++ b/uwac/libuwac/uwac-os.h @@ -0,0 +1,45 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * This file is an adaptation of src/wayland-os.h from the wayland project and + * shared/os-compatiblity.h from the weston project. + * + * Functions have been renamed just to prevent name clashes. + */ + +#ifndef __UWAC_OS_H +#define __UWAC_OS_H + +#include + +int uwac_os_socket_cloexec(int domain, int type, int protocol); + +int uwac_os_dupfd_cloexec(int fd, long minfd); + +ssize_t uwac_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags); + +int uwac_os_epoll_create_cloexec(void); + +int uwac_create_anonymous_file(off_t size); +#endif /* __UWAC_OS_H */ diff --git a/uwac/libuwac/uwac-output.c b/uwac/libuwac/uwac-output.c new file mode 100644 index 0000000..0da871c --- /dev/null +++ b/uwac/libuwac/uwac-output.c @@ -0,0 +1,126 @@ +/* + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include "uwac-priv.h" +#include "uwac-utils.h" + +#include +#include +#include +#include + +#define TARGET_OUTPUT_INTERFACE 2 + +static void output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, + int physical_width, int physical_height, int subpixel, + const char *make, const char *model, int transform) +{ + UwacOutput *output = data; + +/* output->allocation.x = x; + output->allocation.y = y;*/ + output->transform = transform; + + if (output->make) + free(output->make); + output->make = strdup(make); + if (!output->make) { + assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup make\n", __FUNCTION__)); + } + + if (output->model) + free(output->model); + output->model = strdup(model); + if (!output->model) { + assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup model\n", __FUNCTION__)); + } +} + +static void output_handle_done(void *data, struct wl_output *wl_output) +{ + UwacOutput *output = data; + + output->doneReceived = true; +} + +static void output_handle_scale(void *data, struct wl_output *wl_output, int32_t scale) +{ + UwacOutput *output = data; + + output->scale = scale; +} + +static void output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, + int width, int height, int refresh) +{ + UwacOutput *output = data; + //UwacDisplay *display = output->display; + + if (output->doneNeeded && output->doneReceived) { + /* TODO: we should clear the mode list */ + } + + if (flags & WL_OUTPUT_MODE_CURRENT) { + output->resolution.width = width; + output->resolution.height = height; + /* output->allocation.width = width; + output->allocation.height = height; + if (display->output_configure_handler) + (*display->output_configure_handler)( + output, display->user_data);*/ + } +} + +static const struct wl_output_listener output_listener = { + output_handle_geometry, + output_handle_mode, + output_handle_done, + output_handle_scale +}; + +UwacOutput *UwacCreateOutput(UwacDisplay *d, uint32_t id, uint32_t version) { + UwacOutput *o; + + o = zalloc(sizeof *o); + if (!o) + return NULL; + + o->display = d; + o->server_output_id = id; + o->doneNeeded = (version > 1); + o->doneReceived = false; + o->output = wl_registry_bind(d->registry, id, &wl_output_interface, min(TARGET_OUTPUT_INTERFACE, version)); + wl_output_add_listener(o->output, &output_listener, o); + + wl_list_insert(d->outputs.prev, &o->link); + return o; +} + +int UwacDestroyOutput(UwacOutput *output) { + free(output->make); + free(output->model); + + wl_output_destroy(output->output); + wl_list_remove(&output->link); + free(output); + + return UWAC_SUCCESS; +} diff --git a/uwac/libuwac/uwac-priv.h b/uwac/libuwac/uwac-priv.h new file mode 100644 index 0000000..8b0324d --- /dev/null +++ b/uwac/libuwac/uwac-priv.h @@ -0,0 +1,237 @@ +/* + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef __UWAC_PRIV_H_ +#define __UWAC_PRIV_H_ + +#include "config.h" + +#include +#include +#include "xdg-shell-client-protocol.h" +#ifdef BUILD_IVI +#include "ivi-application-client-protocol.h" +#endif +#ifdef BUILD_FULLSCREEN_SHELL +#include "fullscreen-shell-client-protocol.h" +#endif + +#ifdef HAVE_PIXMAN_REGION +#include +#else +#include +#endif + +#include + +#include + + +extern UwacErrorHandler uwacErrorHandler; + +typedef struct uwac_task UwacTask; + +/** @brief */ +struct uwac_task { + void (*run)(UwacTask *task, uint32_t events); + struct wl_list link; +}; + +/** @brief a global registry object */ +struct uwac_global { + uint32_t name; + char *interface; + uint32_t version; + struct wl_list link; +}; +typedef struct uwac_global UwacGlobal; + +struct uwac_event_list_item; +typedef struct uwac_event_list_item UwacEventListItem; + +/** @brief */ +struct uwac_event_list_item { + UwacEvent event; + UwacEventListItem *tail, *head; +}; + + +/** @brief main connection object to a wayland display */ +struct uwac_display { + struct wl_list globals; + + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_subcompositor *subcompositor; + struct wl_shell *shell; + struct xdg_shell *xdg_shell; +#ifdef BUILD_IVI + struct ivi_application *ivi_application; +#endif +#ifdef BUILD_FULLSCREEN_SHELL + struct _wl_fullscreen_shell *fullscreen_shell; +#endif + + struct wl_shm *shm; + enum wl_shm_format *shm_formats; + uint32_t shm_formats_nb; + bool has_rgb565; + + struct wl_data_device_manager *data_device_manager; + struct text_cursor_position *text_cursor_position; + struct workspace_manager *workspace_manager; + + struct wl_list seats; + + int display_fd; + UwacReturnCode last_error; + uint32_t display_fd_events; + int epoll_fd; + bool running; + UwacTask dispatch_fd_task; + uint32_t serial; + + struct wl_cursor_theme *cursor_theme; + struct wl_cursor **cursors; + + struct wl_list windows; + + struct wl_list outputs; + + UwacEventListItem *push_queue, *pop_queue; +}; + +/** @brief an output on a wayland display */ +struct uwac_output { + UwacDisplay *display; + + bool doneNeeded; + bool doneReceived; + + UwacSize resolution; + int transform; + int scale; + char *make; + char *model; + uint32_t server_output_id; + struct wl_output *output; + + struct wl_list link; +}; + +/** @brief a seat attached to a wayland display */ +struct uwac_seat { + UwacDisplay *display; + char *name; + struct wl_seat *seat; + uint32_t seat_id; + uint32_t seat_version; + struct wl_pointer *pointer; + struct wl_keyboard *keyboard; + struct wl_touch *touch; + struct xkb_context *xkb_context; + + struct { + struct xkb_keymap *keymap; + struct xkb_state *state; + xkb_mod_mask_t control_mask; + xkb_mod_mask_t alt_mask; + xkb_mod_mask_t shift_mask; + } xkb; + uint32_t modifiers; + int32_t repeat_rate_sec, repeat_rate_nsec; + int32_t repeat_delay_sec, repeat_delay_nsec; + uint32_t repeat_sym, repeat_key, repeat_time; + + struct wl_array pressed_keys; + + UwacWindow *pointer_focus; + + UwacWindow *keyboard_focus; + + UwacWindow *touch_focus; + bool touch_frame_started; + + int repeat_timer_fd; + UwacTask repeat_task; + float sx, sy; + struct wl_list link; +}; + + +/** @brief a buffer used for drawing a surface frame */ +struct uwac_buffer { + bool used; +#ifdef HAVE_PIXMAN_REGION + pixman_region32_t damage; +#else + REGION16 damage; +#endif + struct wl_buffer *wayland_buffer; + void *data; +}; +typedef struct uwac_buffer UwacBuffer; + + +/** @brief a window */ +struct uwac_window { + UwacDisplay *display; + int width, height, stride; + int surfaceStates; + enum wl_shm_format format; + + int nbuffers; + UwacBuffer *buffers; + + struct wl_region *opaque_region; + struct wl_region *input_region; + struct wl_callback *frame_callback; + UwacBuffer *drawingBuffer, *pendingBuffer; + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + struct xdg_surface *xdg_surface; +#ifdef BUILD_IVI + struct ivi_surface *ivi_surface; +#endif + struct wl_list link; + + uint32_t pointer_enter_serial; + uint32_t pointer_cursor_serial; + int pointer_current_cursor; +}; + + +/* in uwa-display.c */ +UwacEvent *UwacDisplayNewEvent(UwacDisplay *d, int type); +int UwacDisplayWatchFd(UwacDisplay *display, int fd, uint32_t events, UwacTask *task); + + +/* in uwac-input.c */ +UwacSeat *UwacSeatNew(UwacDisplay *d, uint32_t id, uint32_t version); +void UwacSeatDestroy(UwacSeat *s); + +/* in uwac-output.c */ +UwacOutput *UwacCreateOutput(UwacDisplay *d, uint32_t id, uint32_t version); +int UwacDestroyOutput(UwacOutput *output); + +#endif /* __UWAC_PRIV_H_ */ diff --git a/uwac/libuwac/uwac-tools.c b/uwac/libuwac/uwac-tools.c new file mode 100644 index 0000000..73aff22 --- /dev/null +++ b/uwac/libuwac/uwac-tools.c @@ -0,0 +1,93 @@ +/* + * Copyright © 2015 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include +#include +#include + +/** @brief */ +struct uwac_touch_automata { + struct wl_array tp; +}; + +void UwacTouchAutomataInit(UwacTouchAutomata *automata) { + wl_array_init(&automata->tp); +} + +void UwacTouchAutomataReset(UwacTouchAutomata *automata) { + automata->tp.size = 0; +} + +bool UwacTouchAutomataInjectEvent(UwacTouchAutomata *automata, UwacEvent *event) { + + UwacTouchPoint *tp; + + switch (event->type) { + case UWAC_EVENT_TOUCH_FRAME_BEGIN: + break; + + case UWAC_EVENT_TOUCH_UP: { + UwacTouchUp *touchUp = &event->touchUp; + int toMove = automata->tp.size - sizeof(UwacTouchPoint); + + wl_array_for_each(tp, &automata->tp) { + if (tp->id == touchUp->id) { + if (toMove) + memmove(tp, tp+1, toMove); + return true; + } + + toMove -= sizeof(UwacTouchPoint); + } + break; + } + + case UWAC_EVENT_TOUCH_DOWN: { + UwacTouchDown *touchDown = &event->touchDown; + + wl_array_for_each(tp, &automata->tp) { + if (tp->id == touchDown->id) { + tp->x = touchDown->x; + tp->y = touchDown->y; + return true; + } + } + + tp = wl_array_add(&automata->tp, sizeof(UwacTouchPoint)); + if (!tp) + return false; + + tp->id = touchDown->id; + tp->x = touchDown->x; + tp->y = touchDown->y; + break; + } + + case UWAC_EVENT_TOUCH_FRAME_END: + break; + + default: + break; + } + + return true; +} diff --git a/uwac/libuwac/uwac-utils.c b/uwac/libuwac/uwac-utils.c new file mode 100644 index 0000000..c9c33f6 --- /dev/null +++ b/uwac/libuwac/uwac-utils.c @@ -0,0 +1,63 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * Copyright © 2008 Kristian Høgsberg + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "uwac-utils.h" + +/* + * This part is an adaptation of client/window.c from the weston project. + */ + +void *fail_on_null(void *p) { + if (p == NULL) { + fprintf(stderr, "out of memory\n"); + exit(EXIT_FAILURE); + } + + return p; +} + +void *xmalloc(size_t s) { + return fail_on_null(malloc(s)); +} + +void *xzalloc(size_t s) { + return fail_on_null(zalloc(s)); +} + +char *xstrdup(const char *s) { + return fail_on_null(strdup(s)); +} + +void *xrealloc(char *p, size_t s) { + return fail_on_null(realloc(p, s)); +} + + diff --git a/uwac/libuwac/uwac-utils.h b/uwac/libuwac/uwac-utils.h new file mode 100644 index 0000000..e305073 --- /dev/null +++ b/uwac/libuwac/uwac-utils.h @@ -0,0 +1,53 @@ +/* + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef __UWAC_UTILS_H_ +#define __UWAC_UTILS_H_ + +#include + +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + +#define container_of(ptr, type, member) ({ \ + const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + + + +void *xmalloc(size_t s); + +static inline void *zalloc(size_t size) { + return calloc(1, size); +} + +void *xzalloc(size_t s); + +char *xstrdup(const char *s); + +void *xrealloc(char *p, size_t s); + +#endif /* __UWAC_UTILS_H_ */ diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c new file mode 100644 index 0000000..b3fd370 --- /dev/null +++ b/uwac/libuwac/uwac-window.c @@ -0,0 +1,620 @@ +/* + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "uwac-priv.h" +#include "uwac-utils.h" +#include "uwac-os.h" + + +#define UWAC_INITIAL_BUFFERS 3 + + +static int bppFromShmFormat(enum wl_shm_format format) { + switch (format) { + case WL_SHM_FORMAT_ARGB8888: + case WL_SHM_FORMAT_XRGB8888: + default: + return 4; + } +} + + +static void buffer_release(void *data, struct wl_buffer *buffer) { + UwacBuffer *uwacBuffer = (UwacBuffer *)data; + + uwacBuffer->used = false; +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + +void UwacWindowDestroyBuffers(UwacWindow *w) { + int i; + + for (i = 0; i < w->nbuffers; i++) { + UwacBuffer *buffer = &w->buffers[i]; +#ifdef HAVE_PIXMAN_REGION + pixman_region32_fini(&buffer->damage); +#else + region16_uninit(&buffer->damage); +#endif + wl_buffer_destroy(buffer->wayland_buffer); + } + + w->nbuffers = 0; + free(w->buffers); + w->buffers = NULL; +} + + +int UwacWindowShmAllocBuffers(UwacWindow *w, int nbuffers, int allocSize, uint32_t width, + uint32_t height, enum wl_shm_format format); + +static void xdg_handle_configure(void *data, struct xdg_surface *surface, + int32_t width, int32_t height, + struct wl_array *states, uint32_t serial) +{ + UwacWindow *window = (UwacWindow *)data; + UwacConfigureEvent *event; + int ret, surfaceState; + enum xdg_surface_state *state; + + surfaceState = 0; + wl_array_for_each(state, states) { + switch (*state) { + case XDG_SURFACE_STATE_MAXIMIZED: + surfaceState |= UWAC_WINDOW_MAXIMIZED; + break; + case XDG_SURFACE_STATE_FULLSCREEN: + surfaceState |= UWAC_WINDOW_FULLSCREEN; + break; + case XDG_SURFACE_STATE_ACTIVATED: + surfaceState |= UWAC_WINDOW_ACTIVATED; + break; + case XDG_SURFACE_STATE_RESIZING: + surfaceState |= UWAC_WINDOW_RESIZING; + break; + default: + break; + } + } + + window->surfaceStates = surfaceState; + + event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE); + if(!event) { + assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n")); + goto ack; + } + + event->window = window; + event->states = surfaceState; + if (width && height) { + event->width = width; + event->height = height; + + UwacWindowDestroyBuffers(window); + + window->width = width; + window->stride = width * bppFromShmFormat(window->format); + window->height = height; + + ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height, + width, height, window->format); + if (ret != UWAC_SUCCESS) { + assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); + window->drawingBuffer = window->pendingBuffer = NULL; + goto ack; + } + window->drawingBuffer = window->pendingBuffer = &window->buffers[0]; + } else { + event->width = window->width; + event->height = window->height; + } + +ack: + xdg_surface_ack_configure(surface, serial); +} + +static void xdg_handle_close(void *data, struct xdg_surface *xdg_surface) +{ + UwacCloseEvent *event; + UwacWindow *window = (UwacWindow *)data; + + event = (UwacCloseEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CLOSE); + if(!event) { + assert(uwacErrorHandler(window->display, UWAC_ERROR_INTERNAL, "failed to allocate a close event\n")); + return; + } + + event->window = window; +} + +static const struct xdg_surface_listener xdg_surface_listener = { + xdg_handle_configure, + xdg_handle_close, +}; + +#if BUILD_IVI + +static void ivi_handle_configure(void *data, struct ivi_surface *surface, + int32_t width, int32_t height) +{ + UwacWindow *window = (UwacWindow *)data; + UwacConfigureEvent *event; + int ret; + + + event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE); + if(!event) { + assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n")); + return; + } + + event->window = window; + event->states = 0; + if (width && height) { + event->width = width; + event->height = height; + + UwacWindowDestroyBuffers(window); + + window->width = width; + window->stride = width * bppFromShmFormat(window->format); + window->height = height; + + ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height, + width, height, window->format); + if (ret != UWAC_SUCCESS) { + assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); + window->drawingBuffer = window->pendingBuffer = NULL; + return; + } + window->drawingBuffer = window->pendingBuffer = &window->buffers[0]; + } else { + event->width = window->width; + event->height = window->height; + } +} + +static const struct ivi_surface_listener ivi_surface_listener = { + ivi_handle_configure, +}; +#endif + +void shell_ping(void *data, struct wl_shell_surface *surface, uint32_t serial) +{ + wl_shell_surface_pong(surface, serial); +} + +void shell_configure(void *data, struct wl_shell_surface *surface, uint32_t edges, + int32_t width, int32_t height) +{ + UwacWindow *window = (UwacWindow *)data; + UwacConfigureEvent *event; + int ret; + + event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE); + if(!event) { + assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n")); + return; + } + + event->window = window; + event->states = 0; + if (width && height) { + event->width = width; + event->height = height; + + UwacWindowDestroyBuffers(window); + + window->width = width; + window->stride = width * bppFromShmFormat(window->format); + window->height = height; + + ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height, + width, height, window->format); + if (ret != UWAC_SUCCESS) { + assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); + window->drawingBuffer = window->pendingBuffer = NULL; + return; + } + window->drawingBuffer = window->pendingBuffer = &window->buffers[0]; + } else { + event->width = window->width; + event->height = window->height; + } + +} + + +void shell_popup_done(void *data, struct wl_shell_surface *surface) +{ +} + + +static const struct wl_shell_surface_listener shell_listener = { + shell_ping, + shell_configure, + shell_popup_done +}; + + +int UwacWindowShmAllocBuffers(UwacWindow *w, int nbuffers, int allocSize, uint32_t width, + uint32_t height, enum wl_shm_format format) +{ + int ret = UWAC_SUCCESS; + UwacBuffer *newBuffers; + int i, fd; + void *data; + struct wl_shm_pool *pool; + + newBuffers = realloc(w->buffers, (w->nbuffers + nbuffers) * sizeof(UwacBuffer)); + if (!newBuffers) + return UWAC_ERROR_NOMEMORY; + + w->buffers = newBuffers; + + memset(w->buffers + w->nbuffers, 0, sizeof(UwacBuffer) * nbuffers); + + fd = uwac_create_anonymous_file(allocSize * nbuffers); + if (fd < 0) { + return UWAC_ERROR_INTERNAL; + } + + data = mmap(NULL, allocSize * nbuffers, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { + ret = UWAC_ERROR_NOMEMORY; + goto error_mmap; + } + + pool = wl_shm_create_pool(w->display->shm, fd, allocSize * nbuffers); + if (!pool) { + ret = UWAC_ERROR_NOMEMORY; + goto error_mmap; + } + + for (i = 0; i < nbuffers; i++) { + UwacBuffer *buffer = &w->buffers[w->nbuffers + i]; +#ifdef HAVE_PIXMAN_REGION + pixman_region32_init(&buffer->damage); +#else + region16_init(&buffer->damage); +#endif + buffer->data = data + (allocSize * i); + + buffer->wayland_buffer = wl_shm_pool_create_buffer(pool, allocSize * i, width, height, w->stride, format); + wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, buffer); + + } + + wl_shm_pool_destroy(pool); + w->nbuffers += nbuffers; + +error_mmap: + close(fd); + return ret; +} + +UwacBuffer *UwacWindowFindFreeBuffer(UwacWindow *w) { + int i, ret; + + for (i = 0; i < w->nbuffers; i++) { + if (!w->buffers[i].used) { + w->buffers[i].used = true; + return &w->buffers[i]; + } + } + + ret = UwacWindowShmAllocBuffers(w, 2, w->stride * w->height, w->width, w->height, w->format); + if (ret != UWAC_SUCCESS) { + w->display->last_error = ret; + return NULL; + } + + w->buffers[i].used = true; + return &w->buffers[i]; +} + + +UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t height, enum wl_shm_format format) { + UwacWindow *w; + int allocSize, ret; + + if (!display) { + display->last_error = UWAC_ERROR_INVALID_DISPLAY; + return NULL; + } + + w = zalloc(sizeof(*w)); + if (!w) { + display->last_error = UWAC_ERROR_NOMEMORY; + return NULL; + } + + w->display = display; + w->format = format; + w->width = width; + w->height = height; + w->stride = width * bppFromShmFormat(format); + allocSize = w->stride * height; + + ret = UwacWindowShmAllocBuffers(w, UWAC_INITIAL_BUFFERS, allocSize, width, height, format); + if (ret != UWAC_SUCCESS) { + display->last_error = ret; + goto out_error_free; + } + + w->buffers[0].used = true; + w->drawingBuffer = &w->buffers[0]; + + w->surface = wl_compositor_create_surface(display->compositor); + if (!w->surface) { + display->last_error = UWAC_ERROR_NOMEMORY; + goto out_error_surface; + } + wl_surface_set_user_data(w->surface, w); + + if (display->xdg_shell) { + w->xdg_surface = xdg_shell_get_xdg_surface(display->xdg_shell, w->surface); + if (!w->xdg_surface) { + display->last_error = UWAC_ERROR_NOMEMORY; + goto out_error_shell; + } + + assert(w->xdg_surface); + + xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w); +#if BUILD_IVI + } else if (display->ivi_application) { + w->ivi_surface = ivi_application_surface_create(display->ivi_application, 1, w->surface); + + assert (w->ivi_surface); + + ivi_surface_add_listener(w->ivi_surface, &ivi_surface_listener, w); +#endif +#if BUILD_FULLSCREEN_SHELL + } else if (display->fullscreen_shell) { + _wl_fullscreen_shell_present_surface(display->fullscreen_shell, w->surface, + _WL_FULLSCREEN_SHELL_PRESENT_METHOD_CENTER, NULL); +#endif + } else { + w->shell_surface = wl_shell_get_shell_surface(display->shell, w->surface); + + assert(w->shell_surface); + + wl_shell_surface_add_listener(w->shell_surface, &shell_listener, w); + wl_shell_surface_set_toplevel(w->shell_surface); + } + + wl_list_insert(display->windows.prev, &w->link); + + display->last_error = UWAC_SUCCESS; + return w; + +out_error_shell: + wl_surface_destroy(w->surface); +out_error_surface: + UwacWindowDestroyBuffers(w); +out_error_free: + free(w); + return NULL; +} + + +UwacReturnCode UwacDestroyWindow(UwacWindow **pwindow) { + UwacWindow *w; + + assert (pwindow); + + w = *pwindow; + UwacWindowDestroyBuffers(w); + + if (w->frame_callback) + wl_callback_destroy(w->frame_callback); + + if (w->xdg_surface) + xdg_surface_destroy(w->xdg_surface); +#if BUILD_IVI + if (w->ivi_surface) + ivi_surface_destroy(w->ivi_surface); +#endif + + if (w->opaque_region) + wl_region_destroy(w->opaque_region); + + if (w->input_region) + wl_region_destroy(w->opaque_region); + + wl_surface_destroy(w->surface); + wl_list_remove(&w->link); + free(w); + + *pwindow = NULL; + return UWAC_SUCCESS; +} + + +UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, + uint32_t height) +{ + assert(window); + + if (window->opaque_region) + wl_region_destroy(window->opaque_region); + + window->opaque_region = wl_compositor_create_region(window->display->compositor); + if (!window->opaque_region) + return UWAC_ERROR_NOMEMORY; + + wl_region_add(window->opaque_region, x, y, width, height); + wl_surface_set_opaque_region(window->surface, window->opaque_region); + return UWAC_SUCCESS; +} + +UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { + assert(window); + + if (window->input_region) + wl_region_destroy(window->input_region); + + window->input_region = wl_compositor_create_region(window->display->compositor); + if (!window->input_region) + return UWAC_ERROR_NOMEMORY; + + wl_region_add(window->input_region, x, y, width, height); + wl_surface_set_input_region(window->surface, window->input_region); + return UWAC_SUCCESS; +} + + +void *UwacWindowGetDrawingBuffer(UwacWindow *window) { + return window->drawingBuffer->data; +} + +static void frame_done_cb(void *data, struct wl_callback *callback, uint32_t time); + +static const struct wl_callback_listener frame_listener = { + frame_done_cb +}; + + +static void UwacSubmitBufferPtr(UwacWindow *window, UwacBuffer *buffer) { + int nrects, i; +#ifdef HAVE_PIXMAN_REGION + const pixman_box32_t *box; +#else + const RECTANGLE_16 *box; +#endif + + wl_surface_attach(window->surface, buffer->wayland_buffer, 0, 0); + +#ifdef HAVE_PIXMAN_REGION + box = pixman_region32_rectangles(&buffer->damage, &nrects); + for (i = 0; i < nrects; i++, box++) + wl_surface_damage(window->surface, box->x1, box->y1, (box->x2 - box->x1), (box->y2 - box->y1)); +#else + box = region16_rects(&buffer->damage, &nrects); + for (i = 0; i < nrects; i++, box++) + wl_surface_damage(window->surface, box->left, box->top, (box->right - box->left), (box->bottom - box->top)); +#endif + + if (window->frame_callback) + wl_callback_destroy(window->frame_callback); + + window->frame_callback = wl_surface_frame(window->surface); + wl_callback_add_listener(window->frame_callback, &frame_listener, window); + + wl_surface_commit(window->surface); + +#ifdef HAVE_PIXMAN_REGION + pixman_region32_clear(&buffer->damage); +#else + region16_clear(&buffer->damage); +#endif +} + + +static void frame_done_cb(void *data, struct wl_callback *callback, uint32_t time) { + UwacWindow *window = (UwacWindow *)data; + UwacFrameDoneEvent *event; + + window->pendingBuffer = NULL; + event = (UwacFrameDoneEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE); + if(event) + event->window = window; +} + + +UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { +#ifdef HAVE_PIXMAN_REGION + if (!pixman_region32_union_rect(&window->drawingBuffer->damage, &window->drawingBuffer->damage, x, y, width, height)) +#else + RECTANGLE_16 box; + box.left = x; box.top = y; + box.right = x + width; box.bottom = y + height; + + if (!region16_union_rect(&window->drawingBuffer->damage, &window->drawingBuffer->damage, &box)) +#endif + return UWAC_ERROR_INTERNAL; + + return UWAC_SUCCESS; +} + + +UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNextFrame) { + UwacBuffer *drawingBuffer = window->drawingBuffer; + + if (window->pendingBuffer) { + /* we already have a pending frame, don't do anything*/ + return UWAC_SUCCESS; + } + + UwacSubmitBufferPtr(window, drawingBuffer); + + window->pendingBuffer = window->drawingBuffer; + window->drawingBuffer = UwacWindowFindFreeBuffer(window); + if (!window->drawingBuffer) + return UWAC_ERROR_NOMEMORY; + + if (copyContentForNextFrame) { + memcpy(window->drawingBuffer->data, window->pendingBuffer->data, window->stride * window->height); + } + + return UWAC_SUCCESS; +} + +UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry) { + assert(window); + assert(geometry); + + geometry->width = window->width; + geometry->height = window->height; + return UWAC_SUCCESS; +} + + +UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *output, bool isFullscreen) { + if (window->xdg_surface) { + if (isFullscreen) { + xdg_surface_set_fullscreen(window->xdg_surface, output ? output->output : NULL); + } else { + xdg_surface_unset_fullscreen(window->xdg_surface); + } + } + return UWAC_SUCCESS; +} + +void UwacWindowSetTitle(UwacWindow *window, const char *name) { + if (window->xdg_surface) + xdg_surface_set_title(window->xdg_surface, name); + else if (window->shell_surface) + wl_shell_surface_set_title(window->shell_surface, name); +} diff --git a/uwac/protocols/fullscreen-shell.xml b/uwac/protocols/fullscreen-shell.xml new file mode 100644 index 0000000..e2b994b --- /dev/null +++ b/uwac/protocols/fullscreen-shell.xml @@ -0,0 +1,206 @@ + + + + Displays a single surface per output. + + This interface provides a mechanism for a single client to display + simple full-screen surfaces. While there technically may be multiple + clients bound to this interface, only one of those clients should be + shown at a time. + + To present a surface, the client uses either the present_surface or + present_surface_for_mode requests. Presenting a surface takes effect + on the next wl_surface.commit. See the individual requests for + details about scaling and mode switches. + + The client can have at most one surface per output at any time. + Requesting a surface be presented on an output that already has a + surface replaces the previously presented surface. Presenting a null + surface removes its content and effectively disables the output. + Exactly what happens when an output is "disabled" is + compositor-specific. The same surface may be presented on multiple + outputs simultaneously. + + Once a surface is presented on an output, it stays on that output + until either the client removes it or the compositor destroys the + output. This way, the client can update the output's contents by + simply attaching a new buffer. + + + + + Release the binding from the wl_fullscreen_shell interface + + This destroys the server-side object and frees this binding. If + the client binds to wl_fullscreen_shell multiple times, it may wish + to free some of those bindings. + + + + + + Various capabilities that can be advertised by the compositor. They + are advertised one-at-a-time when the wl_fullscreen_shell interface is + bound. See the wl_fullscreen_shell.capability event for more details. + + ARBITRARY_MODE: + This is a hint to the client that indicates that the compositor is + capable of setting practically any mode on its outputs. If this + capability is provided, wl_fullscreen_shell.present_surface_for_mode + will almost never fail and clients should feel free to set whatever + mode they like. If the compositor does not advertise this, it may + still support some modes that are not advertised through wl_global.mode + but it is less likely. + + CURSOR_PLANE: + This is a hint to the client that indicates that the compositor can + handle a cursor surface from the client without actually compositing. + This may be because of a hardware cursor plane or some other mechanism. + If the compositor does not advertise this capability then setting + wl_pointer.cursor may degrade performance or be ignored entirely. If + CURSOR_PLANE is not advertised, it is recommended that the client draw + its own cursor and set wl_pointer.cursor(NULL). + + + + + + + + Advertises a single capability of the compositor. + + When the wl_fullscreen_shell interface is bound, this event is emitted + once for each capability advertised. Valid capabilities are given by + the wl_fullscreen_shell.capability enum. If clients want to take + advantage of any of these capabilities, they should use a + wl_display.sync request immediately after binding to ensure that they + receive all the capability events. + + + + + + + Hints to indicate to the compositor how to deal with a conflict + between the dimensions of the surface and the dimensions of the + output. The compositor is free to ignore this parameter. + + + + + + + + + + + Present a surface on the given output. + + If the output is null, the compositor will present the surface on + whatever display (or displays) it thinks best. In particular, this + may replace any or all surfaces currently presented so it should + not be used in combination with placing surfaces on specific + outputs. + + The method parameter is a hint to the compositor for how the surface + is to be presented. In particular, it tells the compositor how to + handle a size mismatch between the presented surface and the + output. The compositor is free to ignore this parameter. + + The "zoom", "zoom_crop", and "stretch" methods imply a scaling + operation on the surface. This will override any kind of output + scaling, so the buffer_scale property of the surface is effectively + ignored. + + + + + + + + + Presents a surface on the given output for a particular mode. + + If the current size of the output differs from that of the surface, + the compositor will attempt to change the size of the output to + match the surface. The result of the mode-switch operation will be + returned via the provided wl_fullscreen_shell_mode_feedback object. + + If the current output mode matches the one requested or if the + compositor successfully switches the mode to match the surface, + then the mode_successful event will be sent and the output will + contain the contents of the given surface. If the compositor + cannot match the output size to the surface size, the mode_failed + will be sent and the output will contain the contents of the + previously presented surface (if any). If another surface is + presented on the given output before either of these has a chance + to happen, the present_cancelled event will be sent. + + Due to race conditions and other issues unknown to the client, no + mode-switch operation is guaranteed to succeed. However, if the + mode is one advertised by wl_output.mode or if the compositor + advertises the ARBITRARY_MODES capability, then the client should + expect that the mode-switch operation will usually succeed. + + If the size of the presented surface changes, the resulting output + is undefined. The compositor may attempt to change the output mode + to compensate. However, there is no guarantee that a suitable mode + will be found and the client has no way to be notified of success + or failure. + + The framerate parameter specifies the desired framerate for the + output in mHz. The compositor is free to ignore this parameter. A + value of 0 indicates that the client has no preference. + + If the value of wl_output.scale differs from wl_surface.buffer_scale, + then the compositor may choose a mode that matches either the buffer + size or the surface size. In either case, the surface will fill the + output. + + + + + + + + + + These errors can be emitted in response to wl_fullscreen_shell requests + + + + + + + + + This event indicates that the attempted mode switch operation was + successful. A surface of the size requested in the mode switch + will fill the output without scaling. + + Upon receiving this event, the client should destroy the + wl_fullscreen_shell_mode_feedback object. + + + + + This event indicates that the attempted mode switch operation + failed. This may be because the requested output mode is not + possible or it may mean that the compositor does not want to allow it. + + Upon receiving this event, the client should destroy the + wl_fullscreen_shell_mode_feedback object. + + + + + This event indicates that the attempted mode switch operation was + cancelled. Most likely this is because the client requested a + second mode switch before the first one completed. + + Upon receiving this event, the client should destroy the + wl_fullscreen_shell_mode_feedback object. + + + + diff --git a/uwac/protocols/ivi-application.xml b/uwac/protocols/ivi-application.xml new file mode 100644 index 0000000..8f24226 --- /dev/null +++ b/uwac/protocols/ivi-application.xml @@ -0,0 +1,100 @@ + + + + + Copyright (C) 2013 DENSO CORPORATION + Copyright (c) 2013 BMW Car IT GmbH + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + + + + This removes link from ivi_id to wl_surface and destroys ivi_surface. + The ID, ivi_id, is free and can be used for surface_create again. + + + + + + The configure event asks the client to resize its surface. + + The size is a hint, in the sense that the client is free to + ignore it if it doesn't resize, pick a smaller size (to + satisfy aspect ratio or resize in steps of NxM pixels). + + The client is free to dismiss all but the last configure + event it received. + + The width and height arguments specify the size of the window + in surface local coordinates. + + + + + + + + + This interface is exposed as a global singleton. + This interface is implemented by servers that provide IVI-style user interfaces. + It allows clients to associate a ivi_surface with wl_surface. + + + + + + + + + + This request gives the wl_surface the role of an IVI Surface. Creating more than + one ivi_surface for a wl_surface is not allowed. Note, that this still allows the + following example: + + 1. create a wl_surface + 2. create ivi_surface for the wl_surface + 3. destroy the ivi_surface + 4. create ivi_surface for the wl_surface (with the same or another ivi_id as before) + + surface_create will create a interface:ivi_surface with numeric ID; ivi_id in + ivi compositor. These ivi_ids are defined as unique in the system to identify + it inside of ivi compositor. The ivi compositor implements business logic how to + set properties of the surface with ivi_id according to status of the system. + E.g. a unique ID for Car Navigation application is used for implementing special + logic of the application about where it shall be located. + The server regards following cases as protocol errors and disconnects the client. + - wl_surface already has an nother role. + - ivi_id is already assigned to an another wl_surface. + + If client destroys ivi_surface or wl_surface which is assigne to the ivi_surface, + ivi_id which is assigned to the ivi_surface is free for reuse. + + + + + + + + + diff --git a/uwac/protocols/xdg-shell.xml b/uwac/protocols/xdg-shell.xml new file mode 100644 index 0000000..f98e760 --- /dev/null +++ b/uwac/protocols/xdg-shell.xml @@ -0,0 +1,608 @@ + + + + + Copyright © 2008-2013 Kristian Høgsberg + Copyright © 2013 Rafael Antognolli + Copyright © 2013 Jasper St. Pierre + Copyright © 2010-2013 Intel Corporation + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + xdg_shell allows clients to turn a wl_surface into a "real window" + which can be dragged, resized, stacked, and moved around by the + user. Everything about this interface is suited towards traditional + desktop environments. + + + + + The 'current' member of this enum gives the version of the + protocol. Implementations can compare this to the version + they implement using static_assert to ensure the protocol and + implementation versions match. + + + + + + + + + + + + + + Destroy this xdg_shell object. + + Destroying a bound xdg_shell object while there are surfaces + still alive created by this xdg_shell object instance is illegal + and will result in a protocol error. + + + + + + Negotiate the unstable version of the interface. This + mechanism is in place to ensure client and server agree on the + unstable versions of the protocol that they speak or exit + cleanly if they don't agree. This request will go away once + the xdg-shell protocol is stable. + + + + + + + This creates an xdg_surface for the given surface and gives it the + xdg_surface role. A wl_surface can only be given an xdg_surface role + once. If get_xdg_surface is called with a wl_surface that already has + an active xdg_surface associated with it, or if it had any other role, + an error is raised. + + See the documentation of xdg_surface for more details about what an + xdg_surface is and how it is used. + + + + + + + + This creates an xdg_popup for the given surface and gives it the + xdg_popup role. A wl_surface can only be given an xdg_popup role + once. If get_xdg_popup is called with a wl_surface that already has + an active xdg_popup associated with it, or if it had any other role, + an error is raised. + + This request must be used in response to some sort of user action + like a button press, key press, or touch down event. + + See the documentation of xdg_popup for more details about what an + xdg_popup is and how it is used. + + + + + + + + + + + + + The ping event asks the client if it's still alive. Pass the + serial specified in the event back to the compositor by sending + a "pong" request back with the specified serial. + + Compositors can use this to determine if the client is still + alive. It's unspecified what will happen if the client doesn't + respond to the ping request, or in what timeframe. Clients should + try to respond in a reasonable amount of time. + + A compositor is free to ping in any way it wants, but a client must + always respond to any xdg_shell object it created. + + + + + + + A client must respond to a ping event with a pong request or + the client may be deemed unresponsive. + + + + + + + + An interface that may be implemented by a wl_surface, for + implementations that provide a desktop-style user interface. + + It provides requests to treat surfaces like windows, allowing to set + properties like maximized, fullscreen, minimized, and to move and resize + them, and associate metadata like title and app id. + + The client must call wl_surface.commit on the corresponding wl_surface + for the xdg_surface state to take effect. Prior to committing the new + state, it can set up initial configuration, such as maximizing or setting + a window geometry. + + Even without attaching a buffer the compositor must respond to initial + committed configuration, for instance sending a configure event with + expected window geometry if the client maximized its surface during + initialization. + + For a surface to be mapped by the compositor the client must have + committed both an xdg_surface state and a buffer. + + + + + Unmap and destroy the window. The window will be effectively + hidden from the user's point of view, and all state like + maximization, fullscreen, and so on, will be lost. + + + + + + Set the "parent" of this surface. This window should be stacked + above a parent. The parent surface must be mapped as long as this + surface is mapped. + + Parent windows should be set on dialogs, toolboxes, or other + "auxiliary" surfaces, so that the parent is raised when the dialog + is raised. + + + + + + + Set a short title for the surface. + + This string may be used to identify the surface in a task bar, + window list, or other user interface elements provided by the + compositor. + + The string must be encoded in UTF-8. + + + + + + + Set an application identifier for the surface. + + The app ID identifies the general class of applications to which + the surface belongs. The compositor can use this to group multiple + surfaces together, or to determine how to launch a new application. + + For D-Bus activatable applications, the app ID is used as the D-Bus + service name. + + The compositor shell will try to group application surfaces together + by their app ID. As a best practice, it is suggested to select app + ID's that match the basename of the application's .desktop file. + For example, "org.freedesktop.FooViewer" where the .desktop file is + "org.freedesktop.FooViewer.desktop". + + See the desktop-entry specification [0] for more details on + application identifiers and how they relate to well-known D-Bus + names and .desktop files. + + [0] http://standards.freedesktop.org/desktop-entry-spec/ + + + + + + + Clients implementing client-side decorations might want to show + a context menu when right-clicking on the decorations, giving the + user a menu that they can use to maximize or minimize the window. + + This request asks the compositor to pop up such a window menu at + the given position, relative to the local surface coordinates of + the parent surface. There are no guarantees as to what menu items + the window menu contains. + + This request must be used in response to some sort of user action + like a button press, key press, or touch down event. + + + + + + + + + + + Start an interactive, user-driven move of the surface. + + This request must be used in response to some sort of user action + like a button press, key press, or touch down event. The passed + serial is used to determine the type of interactive move (touch, + pointer, etc). + + The server may ignore move requests depending on the state of + the surface (e.g. fullscreen or maximized), or if the passed serial + is no longer valid. + + If triggered, the surface will lose the focus of the device + (wl_pointer, wl_touch, etc) used for the move. It is up to the + compositor to visually indicate that the move is taking place, such as + updating a pointer cursor, during the move. There is no guarantee + that the device focus will return when the move is completed. + + + + + + + + These values are used to indicate which edge of a surface + is being dragged in a resize operation. + + + + + + + + + + + + + + + Start a user-driven, interactive resize of the surface. + + This request must be used in response to some sort of user action + like a button press, key press, or touch down event. The passed + serial is used to determine the type of interactive resize (touch, + pointer, etc). + + The server may ignore resize requests depending on the state of + the surface (e.g. fullscreen or maximized). + + If triggered, the client will receive configure events with the + "resize" state enum value and the expected sizes. See the "resize" + enum value for more details about what is required. The client + must also acknowledge configure events using "ack_configure". After + the resize is completed, the client will receive another "configure" + event without the resize state. + + If triggered, the surface also will lose the focus of the device + (wl_pointer, wl_touch, etc) used for the resize. It is up to the + compositor to visually indicate that the resize is taking place, + such as updating a pointer cursor, during the resize. There is no + guarantee that the device focus will return when the resize is + completed. + + The edges parameter specifies how the surface should be resized, + and is one of the values of the resize_edge enum. The compositor + may use this information to update the surface position for + example when dragging the top left corner. The compositor may also + use this information to adapt its behavior, e.g. choose an + appropriate cursor image. + + + + + + + + + The different state values used on the surface. This is designed for + state values like maximized, fullscreen. It is paired with the + configure event to ensure that both the client and the compositor + setting the state can be synchronized. + + States set in this way are double-buffered. They will get applied on + the next commit. + + Desktop environments may extend this enum by taking up a range of + values and documenting the range they chose in this description. + They are not required to document the values for the range that they + chose. Ideally, any good extensions from a desktop environment should + make its way into standardization into this enum. + + The current reserved ranges are: + + 0x0000 - 0x0FFF: xdg-shell core values, documented below. + 0x1000 - 0x1FFF: GNOME + + + The surface is maximized. The window geometry specified in the configure + event must be obeyed by the client. + + + The surface is fullscreen. The window geometry specified in the configure + event must be obeyed by the client. + + + The surface is being resized. The window geometry specified in the + configure event is a maximum; the client cannot resize beyond it. + Clients that have aspect ratio or cell sizing configuration can use + a smaller size, however. + + + Client window decorations should be painted as if the window is + active. Do not assume this means that the window actually has + keyboard or pointer focus. + + + + + + The configure event asks the client to resize its surface or to + change its state. + + The width and height arguments specify a hint to the window + about how its surface should be resized in window geometry + coordinates. See set_window_geometry. + + If the width or height arguments are zero, it means the client + should decide its own window dimension. This may happen when the + compositor need to configure the state of the surface but doesn't + have any information about any previous or expected dimension. + + The states listed in the event specify how the width/height + arguments should be interpreted, and possibly how it should be + drawn. + + Clients should arrange their surface for the new size and + states, and then send a ack_configure request with the serial + sent in this configure event at some point before committing + the new surface. + + If the client receives multiple configure events before it + can respond to one, it is free to discard all but the last + event it received. + + + + + + + + + + + When a configure event is received, if a client commits the + surface in response to the configure event, then the client + must make a ack_configure request before the commit request, + passing along the serial of the configure event. + + For instance, the compositor might use this information to move + a surface to the top left only when the client has drawn itself + for the maximized or fullscreen state. + + If the client receives multiple configure events before it + can respond to one, it only has to ack the last configure event. + + + + + + + The window geometry of a window is its "visible bounds" from the + user's perspective. Client-side decorations often have invisible + portions like drop-shadows which should be ignored for the + purposes of aligning, placing and constraining windows. + + The window geometry is double buffered, and will be applied at the + time wl_surface.commit of the corresponding wl_surface is called. + + Once the window geometry of the surface is set once, it is not + possible to unset it, and it will remain the same until + set_window_geometry is called again, even if a new subsurface or + buffer is attached. + + If never set, the value is the full bounds of the surface, + including any subsurfaces. This updates dynamically on every + commit. This unset mode is meant for extremely simple clients. + + If responding to a configure event, the window geometry in here + must respect the sizing negotiations specified by the states in + the configure event. + + The arguments are given in the surface local coordinate space of + the wl_surface associated with this xdg_surface. + + The width and height must be greater than zero. + + + + + + + + + + Maximize the surface. + + After requesting that the surface should be maximized, the compositor + will respond by emitting a configure event with the "maximized" state + and the required window geometry. The client should then update its + content, drawing it in a maximized state, i.e. without shadow or other + decoration outside of the window geometry. The client must also + acknowledge the configure when committing the new content (see + ack_configure). + + It is up to the compositor to decide how and where to maximize the + surface, for example which output and what region of the screen should + be used. + + If the surface was already maximized, the compositor will still emit + a configure event with the "maximized" state. + + + + + + Unmaximize the surface. + + After requesting that the surface should be unmaximized, the compositor + will respond by emitting a configure event without the "maximized" + state. If available, the compositor will include the window geometry + dimensions the window had prior to being maximized in the configure + request. The client must then update its content, drawing it in a + regular state, i.e. potentially with shadow, etc. The client must also + acknowledge the configure when committing the new content (see + ack_configure). + + It is up to the compositor to position the surface after it was + unmaximized; usually the position the surface had before maximizing, if + applicable. + + If the surface was already not maximized, the compositor will still + emit a configure event without the "maximized" state. + + + + + + Make the surface fullscreen. + + You can specify an output that you would prefer to be fullscreen. + If this value is NULL, it's up to the compositor to choose which + display will be used to map this surface. + + If the surface doesn't cover the whole output, the compositor will + position the surface in the center of the output and compensate with + black borders filling the rest of the output. + + + + + + + + Request that the compositor minimize your surface. There is no + way to know if the surface is currently minimized, nor is there + any way to unset minimization on this surface. + + If you are looking to throttle redrawing when minimized, please + instead use the wl_surface.frame event for this, as this will + also work with live previews on windows in Alt-Tab, Expose or + similar compositor features. + + + + + + The close event is sent by the compositor when the user + wants the surface to be closed. This should be equivalent to + the user clicking the close button in client-side decorations, + if your application has any... + + This is only a request that the user intends to close your + window. The client may choose to ignore this request, or show + a dialog to ask the user to save their data... + + + + + + + A popup surface is a short-lived, temporary surface that can be + used to implement menus. It takes an explicit grab on the surface + that will be dismissed when the user dismisses the popup. This can + be done by the user clicking outside the surface, using the keyboard, + or even locking the screen through closing the lid or a timeout. + + When the popup is dismissed, a popup_done event will be sent out, + and at the same time the surface will be unmapped. The xdg_popup + object is now inert and cannot be reactivated, so clients should + destroy it. Explicitly destroying the xdg_popup object will also + dismiss the popup and unmap the surface. + + Clients will receive events for all their surfaces during this + grab (which is an "owner-events" grab in X11 parlance). This is + done so that users can navigate through submenus and other + "nested" popup windows without having to dismiss the topmost + popup. + + Clients that want to dismiss the popup when another surface of + their own is clicked should dismiss the popup using the destroy + request. + + The parent surface must have either an xdg_surface or xdg_popup + role. + + Specifying an xdg_popup for the parent means that the popups are + nested, with this popup now being the topmost popup. Nested + popups must be destroyed in the reverse order they were created + in, e.g. the only popup you are allowed to destroy at all times + is the topmost one. + + If there is an existing popup when creating a new popup, the + parent must be the current topmost popup. + + A parent surface must be mapped before the new popup is mapped. + + When compositors choose to dismiss a popup, they will likely + dismiss every nested popup as well. When a compositor dismisses + popups, it will follow the same dismissing order as required + from the client. + + The x and y arguments passed when creating the popup object specify + where the top left of the popup should be placed, relative to the + local surface coordinates of the parent surface. See + xdg_shell.get_xdg_popup. + + The client must call wl_surface.commit on the corresponding wl_surface + for the xdg_popup state to take effect. + + For a surface to be mapped by the compositor the client must have + committed both the xdg_popup state and a buffer. + + + + + This destroys the popup. Explicitly destroying the xdg_popup + object will also dismiss the popup, and unmap the surface. + + If this xdg_popup is not the "topmost" popup, a protocol error + will be sent. + + + + + + The popup_done event is sent out when a popup is dismissed by the + compositor. The client should destroy the xdg_popup object at this + point. + + + + + diff --git a/uwac/uwac.pc.in b/uwac/uwac.pc.in new file mode 100644 index 0000000..66b477e --- /dev/null +++ b/uwac/uwac.pc.in @@ -0,0 +1,15 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=${prefix}/@UWAC_INCLUDE_DIR@ +libs=-luwac + +Name: uwac +Description: uwac: using wayland as a client +URL: http://www.freerdp.com/ +Version: @UWAC_VERSION@ +Requires: +Requires.private: wayland-client xkbcommon freerdp@FREERDP_VERSION_MAJOR@ +Libs: -L${libdir} ${libs} +Libs.private: +Cflags: -I${includedir} diff --git a/uwac/uwacConfig.cmake.in b/uwac/uwacConfig.cmake.in new file mode 100644 index 0000000..2433842 --- /dev/null +++ b/uwac/uwacConfig.cmake.in @@ -0,0 +1,9 @@ +@PACKAGE_INIT@ + +set(UWAC_VERSION_MAJOR "@UWAC_VERSION_MAJOR@") +set(UWAC_VERSION_MINOR "@UWAC_VERSION_MINOR@") +set(UWAC_VERSION_REVISION "@UWAC_VERSION_REVISION@") + +set_and_check(UWAC_INCLUDE_DIR "@PACKAGE_UWAC_INCLUDE_DIR@") + +include("${CMAKE_CURRENT_LIST_DIR}/uwac.cmake") diff --git a/uwac/uwacVersion.cmake b/uwac/uwacVersion.cmake new file mode 100644 index 0000000..2a789d7 --- /dev/null +++ b/uwac/uwacVersion.cmake @@ -0,0 +1,46 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, +# but only if the requested major version is the same as the current one. +# The variable CVF_VERSION must be set before calling configure_file(). + + +set(PACKAGE_VERSION "0.0.1") + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + + if("0.0.1" MATCHES "^([0-9]+)\\.") + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + else() + set(CVF_VERSION_MAJOR "0.0.1") + endif() + + if("${PACKAGE_FIND_VERSION_MAJOR}" STREQUAL "${CVF_VERSION_MAJOR}") + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() + + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + math(EXPR installedBits "8 * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index c071b3b..2e3b673 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -49,15 +49,24 @@ include(CMakePackageConfigHelpers) # Soname versioning set(WINPR_VERSION_MAJOR "1") -set(WINPR_VERSION_MINOR "1") +set(WINPR_VERSION_MINOR "2") set(WINPR_VERSION_REVISION "0") set(WINPR_VERSION "${WINPR_VERSION_MAJOR}.${WINPR_VERSION_MINOR}.${WINPR_VERSION_REVISION}") set(WINPR_VERSION_FULL "${WINPR_VERSION}") set(WINPR_API_VERSION "${WINPR_VERSION_MAJOR}") +if(NOT IOS) + check_include_files(stdbool.h WINPR_HAVE_STDBOOL_H) + check_include_files(stdint.h WINPR_HAVE_STDINT_H) +else(NOT IOS) + set(WINPR_HAVE_STDBOOL_H 1) + set(WINPR_HAVE_STDINT_H 1) +endif(NOT IOS) + if(FREERDP_BUILD) set(WINPR_VERSION_FULL ${WINPR_VERSION_FULL} PARENT_SCOPE) set(WINPR_VERSION ${WINPR_VERSION} PARENT_SCOPE) + set(WINPR_API_VERSION ${WINPR_API_VERSION} PARENT_SCOPE) else() set(CMAKE_THREAD_PREFER_PTHREAD TRUE) @@ -70,7 +79,6 @@ else() check_include_files(fcntl.h HAVE_FCNTL_H) check_include_files(unistd.h HAVE_UNISTD_H) check_include_files(execinfo.h HAVE_EXECINFO_H) - check_include_files(stdint.h HAVE_STDINT_H) check_include_files(inttypes.h HAVE_INTTYPES_H) check_include_files(sys/modem.h HAVE_SYS_MODEM_H) check_include_files(sys/filio.h HAVE_SYS_FILIO_H) @@ -80,7 +88,6 @@ else() else() set(HAVE_FCNTL_H 1) set(HAVE_UNISTD_H 1) - set(HAVE_STDINT_H 1) set(HAVE_INTTYPES_H 1) set(HAVE_SYS_FILIO_H 1) endif() diff --git a/winpr/include/CMakeLists.txt b/winpr/include/CMakeLists.txt index 928f88f..452383d 100644 --- a/winpr/include/CMakeLists.txt +++ b/winpr/include/CMakeLists.txt @@ -21,4 +21,6 @@ set(WINPR_INSTALL_INCLUDE_DIR include/winpr${WINPR_VERSION_MAJOR}/winpr) file(GLOB WINPR_HEADERS "winpr/*.h") install(FILES ${WINPR_HEADERS} DESTINATION ${WINPR_INSTALL_INCLUDE_DIR} COMPONENT headers) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/winpr/version.h DESTINATION ${WINPR_INSTALL_INCLUDE_DIR} COMPONENT headers) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/winpr/wtypes.h DESTINATION ${WINPR_INSTALL_INCLUDE_DIR} COMPONENT headers) install(DIRECTORY winpr/tools DESTINATION ${WINPR_INSTALL_INCLUDE_DIR} COMPONENT headers FILES_MATCHING PATTERN "*.h") diff --git a/winpr/include/winpr/comm.h b/winpr/include/winpr/comm.h index 6f0a230..d4a33b3 100644 --- a/winpr/include/winpr/comm.h +++ b/winpr/include/winpr/comm.h @@ -523,37 +523,37 @@ static const _SERIAL_IOCTL_NAME _SERIAL_IOCTL_NAMES[] = /** * FIXME: got a proper function name and place */ -const char* _comm_serial_ioctl_name(ULONG number); +WINPR_API const char* _comm_serial_ioctl_name(ULONG number); /** * FIXME: got a proper function name and place */ -void _comm_setServerSerialDriver(HANDLE hComm, SERIAL_DRIVER_ID); +WINPR_API void _comm_setServerSerialDriver(HANDLE hComm, SERIAL_DRIVER_ID); /** * FIXME: got a proper function name and place * * permissive mode is disabled by default. */ -BOOL _comm_set_permissive(HANDLE hDevice, BOOL permissive); +WINPR_API BOOL _comm_set_permissive(HANDLE hDevice, BOOL permissive); /** * FIXME: to be moved in comm_ioctl.h */ -BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, +WINPR_API BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped); /** * FIXME: to be moved in comm_io.h */ -BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, +WINPR_API BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); /** * FIXME: to be moved in comm_io.h */ -BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, +WINPR_API BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped); #ifdef __cplusplus diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 7754700..54a12ac 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -500,9 +500,9 @@ WINPR_API PCCERT_CONTEXT CertFindCertificateInStore(HCERTSTORE hCertStore, DWORD WINPR_API PCCERT_CONTEXT CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext); -DWORD CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, +WINPR_API DWORD CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void* pvTypePara, LPWSTR pszNameString, DWORD cchNameString); -DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, +WINPR_API DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void* pvTypePara, LPSTR pszNameString, DWORD cchNameString); #ifdef __cplusplus @@ -642,14 +642,16 @@ union _WINPR_MD5_CTX }; typedef union _WINPR_MD5_CTX WINPR_MD5_CTX; +#define WINPR_MD5_DIGEST_LENGTH 16 + #ifdef __cplusplus extern "C" { #endif -WINPR_API void winpr_MD5_Init(WINPR_MD5_CTX* ctx); -WINPR_API void winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API void winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output); -WINPR_API void winpr_MD5(const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_MD5_Init(WINPR_MD5_CTX* ctx); +WINPR_API BOOL winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen); +WINPR_API BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output, size_t ilen); +WINPR_API BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -683,14 +685,16 @@ union _WINPR_MD4_CTX }; typedef union _WINPR_MD4_CTX WINPR_MD4_CTX; +#define WINPR_MD4_DIGEST_LENGTH 16 + #ifdef __cplusplus extern "C" { #endif -WINPR_API void winpr_MD4_Init(WINPR_MD4_CTX* ctx); -WINPR_API void winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API void winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output); -WINPR_API void winpr_MD4(const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_MD4_Init(WINPR_MD4_CTX* ctx); +WINPR_API BOOL winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen); +WINPR_API BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output, size_t ilen); +WINPR_API BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -700,6 +704,8 @@ WINPR_API void winpr_MD4(const BYTE* input, size_t ilen, BYTE* output); * SHA1 Hashing */ +#define WINPR_SHA1_DIGEST_LENGTH 20 + struct _OPENSSL_SHA1_CTX { UINT32 h0, h1, h2, h3, h4; @@ -728,10 +734,10 @@ typedef union _WINPR_SHA1_CTX WINPR_SHA1_CTX; extern "C" { #endif -WINPR_API void winpr_SHA1_Init(WINPR_SHA1_CTX* ctx); -WINPR_API void winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API void winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output); -WINPR_API void winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_SHA1_Init(WINPR_SHA1_CTX* ctx); +WINPR_API BOOL winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen); +WINPR_API BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output, size_t ilen); +WINPR_API BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -740,17 +746,19 @@ WINPR_API void winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output); /** * HMAC */ - -#define WINPR_MD_NONE 0 -#define WINPR_MD_MD2 1 -#define WINPR_MD_MD4 2 -#define WINPR_MD_MD5 3 -#define WINPR_MD_SHA1 4 -#define WINPR_MD_SHA224 5 -#define WINPR_MD_SHA256 6 -#define WINPR_MD_SHA384 7 -#define WINPR_MD_SHA512 8 -#define WINPR_MD_RIPEMD160 9 +typedef enum +{ + WINPR_MD_NONE = 0, + WINPR_MD_MD2 = 1, + WINPR_MD_MD4 = 2, + WINPR_MD_MD5 = 3, + WINPR_MD_SHA1 = 4, + WINPR_MD_SHA224 = 5, + WINPR_MD_SHA256 = 6, + WINPR_MD_SHA384 = 7, + WINPR_MD_SHA512 = 8, + WINPR_MD_RIPEMD160 = 9 +} WINPR_MD_TYPE; struct _OPENSSL_EVP_MD_CTX { @@ -793,10 +801,11 @@ typedef union _WINPR_HMAC_CTX WINPR_HMAC_CTX; extern "C" { #endif -WINPR_API int winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, int md, const BYTE* key, size_t keylen); -WINPR_API int winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API int winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output); -WINPR_API int winpr_HMAC(int md, const BYTE* key, size_t keylen, const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, size_t keylen); +WINPR_API BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen); +WINPR_API BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t ilen); +WINPR_API BOOL winpr_HMAC(WINPR_MD_TYPE md, const BYTE* key, size_t keylen, + const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -838,10 +847,10 @@ typedef union _WINPR_DIGEST_CTX WINPR_DIGEST_CTX; extern "C" { #endif -WINPR_API int winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, int md); -WINPR_API int winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API int winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output); -WINPR_API int winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md); +WINPR_API BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen); +WINPR_API BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t ilen); +WINPR_API BOOL winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -892,9 +901,9 @@ typedef union _WINPR_RC4_CTX WINPR_RC4_CTX; extern "C" { #endif -WINPR_API void winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen); -WINPR_API int winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output); -WINPR_API void winpr_RC4_Final(WINPR_RC4_CTX* ctx); +WINPR_API WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen); +WINPR_API BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output); +WINPR_API void winpr_RC4_Free(WINPR_RC4_CTX* ctx); #ifdef __cplusplus } @@ -1007,9 +1016,10 @@ typedef union _WINPR_CIPHER_CTX WINPR_CIPHER_CTX; extern "C" { #endif -WINPR_API int winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* key, const BYTE* iv); -WINPR_API int winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen); -WINPR_API int winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen); +WINPR_API WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BYTE* iv); +WINPR_API BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen); +WINPR_API BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen); +WINPR_API void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx); #ifdef __cplusplus } diff --git a/winpr/include/winpr/error.h b/winpr/include/winpr/error.h index e84b8f7..0a1511b 100644 --- a/winpr/include/winpr/error.h +++ b/winpr/include/winpr/error.h @@ -518,6 +518,7 @@ #define ERROR_DEVICE_ENUMERATION_ERROR 0x00000288 #define ERROR_MOUNT_POINT_NOT_RESOLVED 0x00000289 #define ERROR_INVALID_DEVICE_OBJECT_PARAMETER 0x0000028A +/* The following is not a typo. It's the same spelling as in the Microsoft headers */ #define ERROR_MCA_OCCURED 0x0000028B #define ERROR_DRIVER_DATABASE_ERROR 0x0000028C #define ERROR_SYSTEM_HIVE_TOO_LARGE 0x0000028D diff --git a/winpr/include/winpr/input.h b/winpr/include/winpr/input.h index 6779f30..3691884 100644 --- a/winpr/include/winpr/input.h +++ b/winpr/include/winpr/input.h @@ -80,8 +80,9 @@ #define VK_HANJA 0x19 /* IME Hanja mode */ #define VK_KANJI 0x19 /* IME Kanji mode */ -/* 0x1A is undefined */ +/* 0x1A is undefined, use it for missing Hiragana/Katakana Toggle */ +#define VK_HKTG 0x1A /* Hiragana/Katakana toggle */ #define VK_ESCAPE 0x1B /* ESC key */ #define VK_CONVERT 0x1C /* IME convert */ #define VK_NONCONVERT 0x1D /* IME nonconvert */ @@ -555,7 +556,7 @@ #define KBD7_T0A VK_KEY_9 #define KBD7_T0B VK_KEY_0 #define KBD7_T0C VK_OEM_MINUS -#define KBD7_T0D VK_OEM_7 /* NE */ +#define KBD7_T0D VK_OEM_PLUS #define KBD7_T0E VK_BACK #define KBD7_T0F VK_TAB #define KBD7_T10 VK_KEY_Q @@ -581,8 +582,8 @@ #define KBD7_T24 VK_KEY_J #define KBD7_T25 VK_KEY_K #define KBD7_T26 VK_KEY_L -#define KBD7_T27 VK_OEM_PLUS /* NE */ -#define KBD7_T28 VK_OEM_1 /* NE */ +#define KBD7_T27 VK_OEM_1 +#define KBD7_T28 VK_OEM_7 #define KBD7_T29 VK_OEM_3 /* NE */ #define KBD7_T2A VK_LSHIFT #define KBD7_T2B VK_OEM_5 /* NE */ @@ -600,7 +601,7 @@ #define KBD7_T37 VK_MULTIPLY #define KBD7_T38 VK_LMENU #define KBD7_T39 VK_SPACE -#define KBD7_T3A VK_DBE_ALPHANUMERIC /* NE */ +#define KBD7_T3A VK_CAPITAL #define KBD7_T3B VK_F1 #define KBD7_T3C VK_F2 #define KBD7_T3D VK_F3 @@ -613,22 +614,22 @@ #define KBD7_T44 VK_F10 #define KBD7_T45 VK_NUMLOCK #define KBD7_T46 VK_SCROLL -#define KBD7_T47 VK_HOME -#define KBD7_T48 VK_UP -#define KBD7_T49 VK_PRIOR +#define KBD7_T47 VK_NUMPAD7 /* VK_HOME */ +#define KBD7_T48 VK_NUMPAD8 /* VK_UP */ +#define KBD7_T49 VK_NUMPAD9 /* VK_PRIOR */ #define KBD7_T4A VK_SUBTRACT -#define KBD7_T4B VK_LEFT -#define KBD7_T4C VK_CLEAR -#define KBD7_T4D VK_RIGHT +#define KBD7_T4B VK_NUMPAD4 /* VK_LEFT */ +#define KBD7_T4C VK_NUMPAD5 /* VK_CLEAR */ +#define KBD7_T4D VK_NUMPAD6 /* VK_RIGHT */ #define KBD7_T4E VK_ADD -#define KBD7_T4F VK_END -#define KBD7_T50 VK_DOWN -#define KBD7_T51 VK_NEXT -#define KBD7_T52 VK_INSERT -#define KBD7_T53 VK_DELETE +#define KBD7_T4F VK_NUMPAD1 /* VK_END */ +#define KBD7_T50 VK_NUMPAD2 /* VK_DOWN */ +#define KBD7_T51 VK_NUMPAD3 /* VK_NEXT */ +#define KBD7_T52 VK_NUMPAD0 /* VK_INSERT */ +#define KBD7_T53 VK_DECIMAL /* VK_DELETE */ #define KBD7_T54 VK_SNAPSHOT #define KBD7_T55 VK_NONE -#define KBD7_T56 VK_NONE /* NE */ +#define KBD7_T56 VK_OEM_102 #define KBD7_T57 VK_F11 #define KBD7_T58 VK_F12 #define KBD7_T59 VK_CLEAR @@ -654,27 +655,27 @@ #define KBD7_T6D VK_F22 #define KBD7_T6E VK_F23 #define KBD7_T6F VK_NONE /* NE */ -#define KBD7_T70 VK_DBE_KATAKANA /* NE */ +#define KBD7_T70 VK_HKTG /* NE */ #define KBD7_T71 VK_NONE /* NE */ #define KBD7_T72 VK_NONE -#define KBD7_T73 VK_OEM_102 /* NE */ +#define KBD7_T73 VK_ABNT_C1 #define KBD7_T74 VK_NONE #define KBD7_T75 VK_NONE #define KBD7_T76 VK_F24 -#define KBD7_T77 VK_DBE_SBCSCHAR /* NE */ +#define KBD7_T77 VK_NONE #define KBD7_T78 VK_NONE #define KBD7_T79 VK_CONVERT /* NE */ #define KBD7_T7A VK_NONE #define KBD7_T7B VK_NONCONVERT /* NE */ #define KBD7_T7C VK_TAB -#define KBD7_T7D VK_NONE /* NE */ +#define KBD7_T7D VK_OEM_8 #define KBD7_T7E VK_ABNT_C2 #define KBD7_T7F VK_OEM_PA2 #define KBD7_X10 VK_MEDIA_PREV_TRACK #define KBD7_X19 VK_MEDIA_NEXT_TRACK #define KBD7_X1C VK_RETURN -#define KBD7_X1D VK_RCONTROL /* NE */ +#define KBD7_X1D VK_RCONTROL #define KBD7_X20 VK_VOLUME_MUTE #define KBD7_X21 VK_LAUNCH_APP2 #define KBD7_X22 VK_MEDIA_PLAY_PAUSE @@ -682,10 +683,10 @@ #define KBD7_X2E VK_VOLUME_DOWN #define KBD7_X30 VK_VOLUME_UP #define KBD7_X32 VK_BROWSER_HOME -#define KBD7_X33 VK_OEM_8 /* NE */ +#define KBD7_X33 VK_NONE #define KBD7_X35 VK_DIVIDE #define KBD7_X37 VK_SNAPSHOT -#define KBD7_X38 VK_DBE_HIRAGANA /* NE */ +#define KBD7_X38 VK_RMENU #define KBD7_X42 VK_NONE #define KBD7_X43 VK_NONE #define KBD7_X44 VK_NONE diff --git a/winpr/include/winpr/nt.h b/winpr/include/winpr/nt.h index d0761eb..68bccc6 100644 --- a/winpr/include/winpr/nt.h +++ b/winpr/include/winpr/nt.h @@ -977,6 +977,7 @@ #define STATUS_WAIT_FOR_OPLOCK ((NTSTATUS)0x00000367) #define STATUS_MOUNT_POINT_NOT_RESOLVED ((NTSTATUS)0xC0000368) #define STATUS_INVALID_DEVICE_OBJECT_PARAMETER ((NTSTATUS)0xC0000369) +/* The following is not a typo. It's the same spelling as in the Microsoft headers */ #define STATUS_MCA_OCCURED ((NTSTATUS)0xC000036A) #define STATUS_DRIVER_BLOCKED_CRITICAL ((NTSTATUS)0xC000036B) #define STATUS_DRIVER_BLOCKED ((NTSTATUS)0xC000036C) diff --git a/winpr/include/winpr/sspi.h b/winpr/include/winpr/sspi.h index 92e0aa3..8ce7831 100644 --- a/winpr/include/winpr/sspi.h +++ b/winpr/include/winpr/sspi.h @@ -999,8 +999,13 @@ extern "C" { #define SECPKG_ATTR_AUTH_NTLM_HASH 1003 #define SECPKG_ATTR_AUTH_NTLM_MESSAGE 1100 #define SECPKG_ATTR_AUTH_NTLM_TIMESTAMP 1101 -#define SECPKG_ATTR_AUTH_NTLM_CLIENT_CHALLENGE 1102 -#define SECPKG_ATTR_AUTH_NTLM_SERVER_CHALLENGE 1103 +#define SECPKG_ATTR_AUTH_NTLM_CLIENT_CHALLENGE 1102 +#define SECPKG_ATTR_AUTH_NTLM_SERVER_CHALLENGE 1103 +#define SECPKG_ATTR_AUTH_NTLM_NTPROOF_VALUE 1104 +#define SECPKG_ATTR_AUTH_NTLM_RANDKEY 1105 +#define SECPKG_ATTR_AUTH_NTLM_MIC 1106 +#define SECPKG_ATTR_AUTH_NTLM_MIC_VALUE 1107 + struct _SecPkgContext_AuthIdentity { diff --git a/winpr/include/winpr/string.h b/winpr/include/winpr/string.h index 555d053..439d713 100644 --- a/winpr/include/winpr/string.h +++ b/winpr/include/winpr/string.h @@ -189,6 +189,8 @@ WINPR_API char* ConvertLineEndingToCRLF(const char* str, int* size); WINPR_API char* StrSep(char** stringp, const char* delim); +WINPR_API INT64 GetLine(char** lineptr, size_t* size, FILE* stream); + #ifdef __cplusplus } #endif diff --git a/winpr/include/winpr/user.h b/winpr/include/winpr/user.h index 5edc6c8..29983ec 100644 --- a/winpr/include/winpr/user.h +++ b/winpr/include/winpr/user.h @@ -50,6 +50,7 @@ #define IDTIMEOUT 32000 #define IDASYNC 32001 +#define CF_RAW 0 #define CF_TEXT 1 #define CF_BITMAP 2 #define CF_METAFILEPICT 3 diff --git a/winpr/include/winpr/winpr.h b/winpr/include/winpr/winpr.h index 87cc17d..4e92509 100644 --- a/winpr/include/winpr/winpr.h +++ b/winpr/include/winpr/winpr.h @@ -51,5 +51,6 @@ WINPR_API void winpr_get_version(int* major, int* minor, int* revision); WINPR_API const char* winpr_get_version_string(void); WINPR_API const char* winpr_get_build_date(void); WINPR_API const char* winpr_get_build_revision(void); +WINPR_API const char* winpr_get_build_config(void); #endif /* WINPR_H */ diff --git a/winpr/include/winpr/wlog.h b/winpr/include/winpr/wlog.h index 7da8aa5..fc8a677 100644 --- a/winpr/include/winpr/wlog.h +++ b/winpr/include/winpr/wlog.h @@ -190,6 +190,9 @@ WINPR_API BOOL WLog_PrintMessageVA(wLog* log, wLogMessage* message, va_list args WINPR_API DWORD WLog_GetLogLevel(wLog* log); WINPR_API BOOL WLog_SetLogLevel(wLog* log, DWORD logLevel); +WINPR_API BOOL WLog_SetStringLogLevel(wLog* log, LPCSTR level); +WINPR_API BOOL WLog_AddStringLogFilters(LPCSTR filter); + WINPR_API BOOL WLog_SetLogAppenderType(wLog* log, DWORD logAppenderType); WINPR_API wLogAppender* WLog_GetLogAppender(wLog* log); diff --git a/winpr/include/winpr/wtypes.h.in b/winpr/include/winpr/wtypes.h.in index ffa94cf..1bfa553 100644 --- a/winpr/include/winpr/wtypes.h.in +++ b/winpr/include/winpr/wtypes.h.in @@ -21,9 +21,10 @@ #define WINPR_WTYPES_H /* Set by CMake during configuration. */ -#define WINPR_HAVE_STDINT_H @HAVE_STDINT_H@ +#cmakedefine01 WINPR_HAVE_STDINT_H + /* Set by CMake during configuration. */ -#define WINPR_HAVE_STDBOOL_H @HAVE_STDBOOL_H@ +#cmakedefine01 WINPR_HAVE_STDBOOL_H /* MSDN: Windows Data Types - http://msdn.microsoft.com/en-us/library/aa383751/ */ /* [MS-DTYP]: Windows Data Types - http://msdn.microsoft.com/en-us/library/cc230273/ */ @@ -100,6 +101,7 @@ #endif #endif +#ifndef XMD_H /* X11/Xmd.h typedef collision with BOOL */ #if WINPR_HAVE_STDBOOL_H && !defined(__OBJC__) typedef bool BOOL; #else @@ -107,7 +109,6 @@ typedef bool BOOL; #if defined(__APPLE__) typedef signed char BOOL; #else -#ifndef XMD_H typedef int BOOL; #endif #endif @@ -130,11 +131,14 @@ typedef unsigned long DWORD; typedef unsigned long ULONG; #endif +#ifndef XMD_H /* X11/Xmd.h typedef collision with BYTE */ #if WINPR_HAVE_STDINT_H -typedef uint8_t BYTE, *PBYTE, *LPBYTE; +typedef uint8_t BYTE; #else -typedef unsigned char BYTE, *PBYTE, *LPBYTE; +typedef unsigned char BYTE; #endif +#endif +typedef BYTE *PBYTE, *LPBYTE; typedef BYTE BOOLEAN, *PBOOLEAN; #if defined(wchar_t) @@ -190,6 +194,8 @@ typedef HANDLE HMENU; typedef DWORD HCALL; typedef int INT, *LPINT; + +#ifndef XMD_H /* X11/Xmd.h typedef collision with INT8, INT16, INT32 and INT64 */ #if WINPR_HAVE_STDINT_H typedef int8_t INT8; typedef int16_t INT16; @@ -198,11 +204,11 @@ typedef int64_t INT64; #else typedef signed char INT8; typedef signed short INT16; -#ifndef XMD_H typedef signed int INT32; typedef signed __int64 INT64; #endif #endif + typedef const WCHAR* LMCSTR; typedef WCHAR* LMSTR; typedef LONG *PLONG, *LPLONG; @@ -217,10 +223,14 @@ typedef __uint3264 ULONG_PTR, *PULONG_PTR; #if WINPR_HAVE_STDINT_H typedef int32_t LONG32; -typedef int64_t LONG64; #else typedef signed int LONG32; -#ifndef XMD_H +#endif + +#ifndef XMD_H /* X11/Xmd.h defines LONG64 */ +#if WINPR_HAVE_STDINT_H +typedef int64_t LONG64; +#else typedef signed __int64 LONG64; #endif #endif diff --git a/winpr/libwinpr/CMakeLists.txt b/winpr/libwinpr/CMakeLists.txt index 3ea073c..f49cb8d 100644 --- a/winpr/libwinpr/CMakeLists.txt +++ b/winpr/libwinpr/CMakeLists.txt @@ -73,6 +73,10 @@ macro (winpr_definition_add) set (WINPR_DEFINITIONS ${WINPR_DEFINITIONS} PARENT_SCOPE) endmacro() +if (ANDROID) + winpr_library_add(log) +endif() + # Level "1" API as defined for MinCore.lib set(WINPR_CORE synch locale library file comm pipe interlocked security environment crypto registry credentials path io memory input shell diff --git a/winpr/libwinpr/asn1/module.def b/winpr/libwinpr/asn1/module.def deleted file mode 100644 index eba1a91..0000000 --- a/winpr/libwinpr/asn1/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-asn1" -EXPORTS - diff --git a/winpr/libwinpr/com/module.def b/winpr/libwinpr/com/module.def deleted file mode 100644 index 4467b6c..0000000 --- a/winpr/libwinpr/com/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-com" -EXPORTS diff --git a/winpr/libwinpr/comm/comm_serial_sys.c b/winpr/libwinpr/comm/comm_serial_sys.c index 5c8b027..04e11da 100644 --- a/winpr/libwinpr/comm/comm_serial_sys.c +++ b/winpr/libwinpr/comm/comm_serial_sys.c @@ -1344,7 +1344,7 @@ static BOOL _get_commstatus(WINPR_COMM *pComm, SERIAL_STATUS *pCommstatus) } else { - /* FIXME: "is 80 percent full" from the specs is ambiguous, need to track when it previously occured? */ + /* FIXME: "is 80 percent full" from the specs is ambiguous, need to track when it previously * occurred? */ pComm->PendingEvents &= ~SERIAL_EV_RX80FULL; } diff --git a/winpr/libwinpr/comm/module.def b/winpr/libwinpr/comm/module.def deleted file mode 100644 index 44feb6f..0000000 --- a/winpr/libwinpr/comm/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr" -EXPORTS - diff --git a/winpr/libwinpr/credentials/module.def b/winpr/libwinpr/credentials/module.def deleted file mode 100644 index 1d5bc0e..0000000 --- a/winpr/libwinpr/credentials/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-credentials" -EXPORTS diff --git a/winpr/libwinpr/credui/module.def b/winpr/libwinpr/credui/module.def deleted file mode 100644 index 70ec496..0000000 --- a/winpr/libwinpr/credui/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-credui" -EXPORTS diff --git a/winpr/libwinpr/crt/module.def b/winpr/libwinpr/crt/module.def deleted file mode 100644 index 3c3c4ff..0000000 --- a/winpr/libwinpr/crt/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-crt" -EXPORTS diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c index da9185f..d6f4a1b 100644 --- a/winpr/libwinpr/crt/string.c +++ b/winpr/libwinpr/crt/string.c @@ -22,6 +22,7 @@ #endif #include +#include #include #include @@ -481,4 +482,42 @@ char* StrSep(char** stringp, const char* delim) return start; } +INT64 GetLine(char** lineptr, size_t* size, FILE* stream) +{ +#if defined(_WIN32) + char c; + char *n; + size_t step = 32; + size_t used = 0; + if (!lineptr || !size) + { + errno = EINVAL; + return -1; + } + + do + { + if (used + 2 >= *size) + { + *size += step; + n = realloc(*lineptr, *size); + if (!n) + { + return -1; + } + *lineptr = n; + } + c = fgetc(stream); + if (c != EOF) + (*lineptr)[used++] = c; + } while((c != '\n') && (c != '\r') && (c != EOF)); + (*lineptr)[used] = '\0'; + + return used; +#elif !defined(ANDROID) && !defined(IOS) + return getline(lineptr, size, stream); +#else + return -1; +#endif +} diff --git a/winpr/libwinpr/crypto/cipher.c b/winpr/libwinpr/crypto/cipher.c index 7eef590..f7dd835 100644 --- a/winpr/libwinpr/crypto/cipher.c +++ b/winpr/libwinpr/crypto/cipher.c @@ -43,33 +43,49 @@ * RC4 */ -void winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen) +WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen) { + WINPR_RC4_CTX* ctx = NULL; + + if (!key || (keylen == 0)) + return NULL; + + ctx = calloc(1, sizeof(WINPR_RC4_CTX)); + if (!ctx) + return NULL; + #if defined(WITH_OPENSSL) RC4_set_key((RC4_KEY*) ctx, keylen, key); #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) mbedtls_arc4_init((mbedtls_arc4_context*) ctx); mbedtls_arc4_setup((mbedtls_arc4_context*) ctx, key, keylen); #endif + return ctx; } -int winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output) +BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output) { #if defined(WITH_OPENSSL) RC4((RC4_KEY*) ctx, length, input, output); - return 0; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) - return mbedtls_arc4_crypt((mbedtls_arc4_context*) ctx, length, input, output); + if (mbedtls_arc4_crypt((mbedtls_arc4_context*) ctx, length, input, output) != 0) + return FALSE; #endif + + return TRUE; } -void winpr_RC4_Final(WINPR_RC4_CTX* ctx) +void winpr_RC4_Free(WINPR_RC4_CTX* ctx) { + if (!ctx) + return; + #if defined(WITH_OPENSSL) #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) mbedtls_arc4_free((mbedtls_arc4_context*) ctx); #endif + free(ctx); } /** @@ -496,81 +512,121 @@ mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher) } #endif -int winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* key, const BYTE* iv) +WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BYTE* iv) { + WINPR_CIPHER_CTX* ctx; #if defined(WITH_OPENSSL) int operation; const EVP_CIPHER* evp; - evp = winpr_openssl_get_evp_cipher(cipher); - - if (!evp) - return -1; - - operation = (op == WINPR_ENCRYPT) ? 1 : 0; - EVP_CIPHER_CTX_init((EVP_CIPHER_CTX*) ctx); - - if (EVP_CipherInit_ex((EVP_CIPHER_CTX*) ctx, evp, NULL, key, iv, operation) != 1) - return -1; + EVP_CIPHER_CTX* octx; #elif defined(WITH_MBEDTLS) int key_bitlen; mbedtls_operation_t operation; mbedtls_cipher_type_t cipher_type; const mbedtls_cipher_info_t* cipher_info; +#endif + + ctx = calloc(1, sizeof(WINPR_CIPHER_CTX)); + if (!ctx) + return NULL; + +#if defined(WITH_OPENSSL) + octx = (EVP_CIPHER_CTX*)ctx; + evp = winpr_openssl_get_evp_cipher(cipher); + + if (!evp) + { + free (ctx); + return NULL; + } + + operation = (op == WINPR_ENCRYPT) ? 1 : 0; + EVP_CIPHER_CTX_init(octx); + + if (EVP_CipherInit_ex(octx, evp, NULL, key, iv, operation) != 1) + { + EVP_CIPHER_CTX_cleanup(octx); + free (octx); + return NULL; + } + + EVP_CIPHER_CTX_set_padding(octx, 0); +#elif defined(WITH_MBEDTLS) cipher_type = winpr_mbedtls_get_cipher_type(cipher); cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (!cipher_info) - return -1; + { + free (ctx); + return NULL; + } operation = (op == WINPR_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT; mbedtls_cipher_init((mbedtls_cipher_context_t*) ctx); if (mbedtls_cipher_setup((mbedtls_cipher_context_t*) ctx, cipher_info) != 0) - return -1; + { + free (ctx); + return NULL; + } key_bitlen = mbedtls_cipher_get_key_bitlen((mbedtls_cipher_context_t*) ctx); if (mbedtls_cipher_setkey((mbedtls_cipher_context_t*) ctx, key, key_bitlen, operation) != 0) - return -1; + { + mbedtls_cipher_free((mbedtls_cipher_context_t*) ctx); + free (ctx); + return NULL; + } #endif - return 0; + return ctx; } -int winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen) +BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen) { #if defined(WITH_OPENSSL) int outl = (int) *olen; if (EVP_CipherUpdate((EVP_CIPHER_CTX*) ctx, output, &outl, input, ilen) != 1) - return -1; + return FALSE; *olen = (size_t) outl; #elif defined(WITH_MBEDTLS) if (mbedtls_cipher_update((mbedtls_cipher_context_t*) ctx, input, ilen, output, olen) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen) +BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen) { #if defined(WITH_OPENSSL) int outl = (int) *olen; if (EVP_CipherFinal_ex((EVP_CIPHER_CTX*) ctx, output, &outl) != 1) - return -1; + return FALSE; - EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX*) ctx); *olen = (size_t) outl; #elif defined(WITH_MBEDTLS) if (mbedtls_cipher_finish((mbedtls_cipher_context_t*) ctx, output, olen) != 0) - return -1; + return FALSE; +#endif + return TRUE; +} +void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx) +{ + if (!ctx) + return; + +#if defined(WITH_OPENSSL) + EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX*) ctx); +#elif defined(WITH_MBEDTLS) mbedtls_cipher_free((mbedtls_cipher_context_t*) ctx); #endif - return 0; } + /** * Key Generation */ diff --git a/winpr/libwinpr/crypto/crypto.c b/winpr/libwinpr/crypto/crypto.c index 9e3064e..4729a76 100644 --- a/winpr/libwinpr/crypto/crypto.c +++ b/winpr/libwinpr/crypto/crypto.c @@ -150,7 +150,7 @@ BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) { BYTE* pCipherText; size_t cbOut, cbFinal; - WINPR_CIPHER_CTX enc; + WINPR_CIPHER_CTX* enc; BYTE randomKey[256]; WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock; @@ -186,27 +186,35 @@ BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) pCipherText = (BYTE*) malloc(cbOut); if (!pCipherText) - { - free(pMemBlock); - return FALSE; - } + goto out; - winpr_Cipher_Init(&enc, WINPR_CIPHER_AES_256_CBC, WINPR_ENCRYPT, pMemBlock->key, pMemBlock->iv); - winpr_Cipher_Update(&enc, pMemBlock->pData, pMemBlock->cbData, pCipherText, &cbOut); - winpr_Cipher_Final(&enc, pCipherText + cbOut, &cbFinal); + if ((enc = winpr_Cipher_New(WINPR_CIPHER_AES_256_CBC, WINPR_ENCRYPT, + pMemBlock->key, pMemBlock->iv)) == NULL) + goto out; + if (!winpr_Cipher_Update(enc, pMemBlock->pData, pMemBlock->cbData, pCipherText, &cbOut)) + goto out; + if (!winpr_Cipher_Final(enc, pCipherText + cbOut, &cbFinal)) + goto out; + winpr_Cipher_Free(enc); CopyMemory(pMemBlock->pData, pCipherText, pMemBlock->cbData); free(pCipherText); return ListDictionary_Add(g_ProtectedMemoryBlocks, pData, pMemBlock); +out: + free (pMemBlock); + free (pCipherText); + winpr_Cipher_Free(enc); + + return FALSE; } BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) { - BYTE* pPlainText; + BYTE* pPlainText = NULL; size_t cbOut, cbFinal; - WINPR_CIPHER_CTX dec; - WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock; + WINPR_CIPHER_CTX* dec = NULL; + WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock = NULL; if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS) return FALSE; @@ -217,18 +225,23 @@ BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) pMemBlock = (WINPR_PROTECTED_MEMORY_BLOCK*) ListDictionary_GetItemValue(g_ProtectedMemoryBlocks, pData); if (!pMemBlock) - return FALSE; + goto out; cbOut = pMemBlock->cbData + 16 - 1; pPlainText = (BYTE*) malloc(cbOut); if (!pPlainText) - return FALSE; + goto out; - winpr_Cipher_Init(&dec, WINPR_CIPHER_AES_256_CBC, WINPR_DECRYPT, pMemBlock->key, pMemBlock->iv); - winpr_Cipher_Update(&dec, pMemBlock->pData, pMemBlock->cbData, pPlainText, &cbOut); - winpr_Cipher_Final(&dec, pPlainText + cbOut, &cbFinal); + if ((dec = winpr_Cipher_New(WINPR_CIPHER_AES_256_CBC, WINPR_DECRYPT, + pMemBlock->key, pMemBlock->iv)) == NULL) + goto out; + if (!winpr_Cipher_Update(dec, pMemBlock->pData, pMemBlock->cbData, pPlainText, &cbOut)) + goto out; + if (!winpr_Cipher_Final(dec, pPlainText + cbOut, &cbFinal)) + goto out; + winpr_Cipher_Free(dec); CopyMemory(pMemBlock->pData, pPlainText, pMemBlock->cbData); SecureZeroMemory(pPlainText, pMemBlock->cbData); @@ -239,6 +252,12 @@ BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) free(pMemBlock); return TRUE; + +out: + free(pPlainText); + free(pMemBlock); + winpr_Cipher_Free(dec); + return FALSE; } BOOL CryptProtectData(DATA_BLOB* pDataIn, LPCWSTR szDataDescr, DATA_BLOB* pOptionalEntropy, diff --git a/winpr/libwinpr/crypto/hash.c b/winpr/libwinpr/crypto/hash.c index ba7fdb7..70c4392 100644 --- a/winpr/libwinpr/crypto/hash.c +++ b/winpr/libwinpr/crypto/hash.c @@ -43,123 +43,167 @@ * MD5 */ -void winpr_MD5_Init(WINPR_MD5_CTX* ctx) +BOOL winpr_MD5_Init(WINPR_MD5_CTX* ctx) { #if defined(WITH_OPENSSL) - MD5_Init((MD5_CTX*) ctx); + if (MD5_Init((MD5_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C) mbedtls_md5_init((mbedtls_md5_context*) ctx); mbedtls_md5_starts((mbedtls_md5_context*) ctx); #endif + + return TRUE; } -void winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen) +BOOL winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) - MD5_Update((MD5_CTX*) ctx, input, ilen); + if (MD5_Update((MD5_CTX*) ctx, input, ilen) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C) mbedtls_md5_update((mbedtls_md5_context*) ctx, input, ilen); #endif + + return TRUE; } -void winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output) +BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output, size_t ilen) { + if (ilen < WINPR_MD5_DIGEST_LENGTH) + return FALSE; + #if defined(WITH_OPENSSL) - MD5_Final(output, (MD5_CTX*) ctx); + if (MD5_Final(output, (MD5_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C) mbedtls_md5_finish((mbedtls_md5_context*) ctx, output); mbedtls_md5_free((mbedtls_md5_context*) ctx); #endif + + return TRUE; } -void winpr_MD5(const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_MD5_CTX ctx; - winpr_MD5_Init(&ctx); - winpr_MD5_Update(&ctx, input, ilen); - winpr_MD5_Final(&ctx, output); + + if (!winpr_MD5_Init(&ctx)) + return FALSE; + if (!winpr_MD5_Update(&ctx, input, ilen)) + return FALSE; + return winpr_MD5_Final(&ctx, output, olen); } /** * MD4 */ -void winpr_MD4_Init(WINPR_MD4_CTX* ctx) +BOOL winpr_MD4_Init(WINPR_MD4_CTX* ctx) { #if defined(WITH_OPENSSL) - MD4_Init((MD4_CTX*) ctx); + if (MD4_Init((MD4_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C) mbedtls_md4_init((mbedtls_md4_context*) ctx); mbedtls_md4_starts((mbedtls_md4_context*) ctx); #endif + return TRUE; } -void winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen) +BOOL winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) - MD4_Update((MD4_CTX*) ctx, input, ilen); + if (MD4_Update((MD4_CTX*) ctx, input, ilen) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C) mbedtls_md4_update((mbedtls_md4_context*) ctx, input, ilen); #endif + + return TRUE; } -void winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output) +BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output, size_t olen) { + if (olen < WINPR_MD4_DIGEST_LENGTH) + return FALSE; + #if defined(WITH_OPENSSL) - MD4_Final(output, (MD4_CTX*) ctx); + if (MD4_Final(output, (MD4_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C) mbedtls_md4_finish((mbedtls_md4_context*) ctx, output); mbedtls_md4_free((mbedtls_md4_context*) ctx); #endif + + return TRUE; } -void winpr_MD4(const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_MD4_CTX ctx; - winpr_MD4_Init(&ctx); - winpr_MD4_Update(&ctx, input, ilen); - winpr_MD4_Final(&ctx, output); + + if (!winpr_MD4_Init(&ctx)) + return FALSE; + if (!winpr_MD4_Update(&ctx, input, ilen)) + return FALSE; + return winpr_MD4_Final(&ctx, output, olen); } /** * SHA1 */ -void winpr_SHA1_Init(WINPR_SHA1_CTX* ctx) +BOOL winpr_SHA1_Init(WINPR_SHA1_CTX* ctx) { #if defined(WITH_OPENSSL) - SHA1_Init((SHA_CTX*) ctx); + if (SHA1_Init((SHA_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C) mbedtls_sha1_init((mbedtls_sha1_context*) ctx); mbedtls_sha1_starts((mbedtls_sha1_context*) ctx); #endif + + return TRUE; } -void winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen) +BOOL winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) - SHA1_Update((SHA_CTX*) ctx, input, ilen); + if (SHA1_Update((SHA_CTX*) ctx, input, ilen) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C) mbedtls_sha1_update((mbedtls_sha1_context*) ctx, input, ilen); #endif + + return TRUE; } -void winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output) +BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output, size_t olen) { + if (olen < WINPR_SHA1_DIGEST_LENGTH) + return FALSE; + #if defined(WITH_OPENSSL) - SHA1_Final(output, (SHA_CTX*) ctx); + if (SHA1_Final(output, (SHA_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C) mbedtls_sha1_finish((mbedtls_sha1_context*) ctx, output); mbedtls_sha1_free((mbedtls_sha1_context*) ctx); #endif + + return TRUE; } -void winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_SHA1_CTX ctx; - winpr_SHA1_Init(&ctx); - winpr_SHA1_Update(&ctx, input, ilen); - winpr_SHA1_Final(&ctx, output); + + if (!winpr_SHA1_Init(&ctx)) + return FALSE; + if (!winpr_SHA1_Update(&ctx, input, ilen)) + return FALSE; + return winpr_SHA1_Final(&ctx, output, olen); } /** @@ -264,13 +308,13 @@ mbedtls_md_type_t winpr_mbedtls_get_md_type(int md) } #endif -int winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, int md, const BYTE* key, size_t keylen) +BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, size_t keylen) { #if defined(WITH_OPENSSL) const EVP_MD* evp = winpr_openssl_get_evp_md(md); if (!evp) - return -1; + return FALSE; HMAC_CTX_init((HMAC_CTX*) ctx); @@ -278,7 +322,7 @@ int winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, int md, const BYTE* key, size_t keylen) HMAC_Init_ex((HMAC_CTX*) ctx, key, keylen, evp, NULL); #else if (HMAC_Init_ex((HMAC_CTX*) ctx, key, keylen, evp, NULL) != 1) - return -1; + return FALSE; #endif #elif defined(WITH_MBEDTLS) @@ -287,143 +331,150 @@ int winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, int md, const BYTE* key, size_t keylen) md_info = mbedtls_md_info_from_type(md_type); if (!md_info) - return -1; + return FALSE; mbedtls_md_init((mbedtls_md_context_t*) ctx); if (mbedtls_md_setup((mbedtls_md_context_t*) ctx, md_info, 1) != 0) - return -1; + return FALSE; if (mbedtls_md_hmac_starts((mbedtls_md_context_t*) ctx, key, keylen) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen) +BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) #if (OPENSSL_VERSION_NUMBER < 0x10000000L) HMAC_Update((HMAC_CTX*) ctx, input, ilen); #else if (HMAC_Update((HMAC_CTX*) ctx, input, ilen) != 1) - return -1; + return FALSE; #endif #elif defined(WITH_MBEDTLS) if (mbedtls_md_hmac_update((mbedtls_md_context_t*) ctx, input, ilen) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output) +BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t olen) { + /* TODO + if (olen < ctx->digestLength) + return FALSE; + */ + #if defined(WITH_OPENSSL) #if (OPENSSL_VERSION_NUMBER < 0x10000000L) HMAC_Final((HMAC_CTX*) ctx, output, NULL); #else if (HMAC_Final((HMAC_CTX*) ctx, output, NULL) != 1) - return -1; + return FALSE; #endif HMAC_CTX_cleanup((HMAC_CTX*) ctx); #elif defined(WITH_MBEDTLS) if (mbedtls_md_hmac_finish((mbedtls_md_context_t*) ctx, output) != 0) - return -1; + return FALSE; mbedtls_md_free((mbedtls_md_context_t*) ctx); #endif - return 0; + return TRUE; } -int winpr_HMAC(int md, const BYTE* key, size_t keylen, const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_HMAC(WINPR_MD_TYPE md, const BYTE* key, size_t keylen, + const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_HMAC_CTX ctx; - if (winpr_HMAC_Init(&ctx, md, key, keylen) != 0) - return -1; + if (!winpr_HMAC_Init(&ctx, md, key, keylen)) + return FALSE; - if (winpr_HMAC_Update(&ctx, input, ilen) != 0) - return -1; + if (!winpr_HMAC_Update(&ctx, input, ilen)) + return FALSE; - if (winpr_HMAC_Final(&ctx, output) != 0) - return -1; + if (!winpr_HMAC_Final(&ctx, output, olen)) + return FALSE; - return 0; + return TRUE; } /** * Generic Digest API */ -int winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, int md) +BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md) { #if defined(WITH_OPENSSL) const EVP_MD* evp = winpr_openssl_get_evp_md(md); if (!evp) - return -1; + return FALSE; EVP_MD_CTX_init((EVP_MD_CTX*) ctx); if (EVP_DigestInit_ex((EVP_MD_CTX*) ctx, evp, NULL) != 1) - return -1; + return FALSE; #elif defined(WITH_MBEDTLS) const mbedtls_md_info_t* md_info; mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md); md_info = mbedtls_md_info_from_type(md_type); if (!md_info) - return -1; + return FALSE; mbedtls_md_init((mbedtls_md_context_t*) ctx); if (mbedtls_md_setup((mbedtls_md_context_t*) ctx, md_info, 0) != 0) - return -1; + return FALSE; if (mbedtls_md_starts((mbedtls_md_context_t*) ctx) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen) +BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) if (EVP_DigestUpdate((EVP_MD_CTX*) ctx, input, ilen) != 1) - return -1; + return FALSE; #elif defined(WITH_MBEDTLS) if (mbedtls_md_update((mbedtls_md_context_t*) ctx, input, ilen) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output) +BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t olen) { + // TODO: output length check #if defined(WITH_OPENSSL) if (EVP_DigestFinal_ex((EVP_MD_CTX*) ctx, output, NULL) != 1) - return -1; + return FALSE; #elif defined(WITH_MBEDTLS) if (mbedtls_md_finish((mbedtls_md_context_t*) ctx, output) != 0) - return -1; + return FALSE; mbedtls_md_free((mbedtls_md_context_t*) ctx); #endif - return 0; + return TRUE; } -int winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_DIGEST_CTX ctx; - if (winpr_Digest_Init(&ctx, md) != 0) - return -1; + if (!winpr_Digest_Init(&ctx, md)) + return FALSE; - if (winpr_Digest_Update(&ctx, input, ilen) != 0) - return -1; + if (!winpr_Digest_Update(&ctx, input, ilen)) + return FALSE; - if (winpr_Digest_Final(&ctx, output) != 0) - return -1; + if (!winpr_Digest_Final(&ctx, output, olen)) + return FALSE; - return 0; + return TRUE; } diff --git a/winpr/libwinpr/crypto/module.def b/winpr/libwinpr/crypto/module.def deleted file mode 100644 index d21b126..0000000 --- a/winpr/libwinpr/crypto/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-crypto" -EXPORTS - diff --git a/winpr/libwinpr/crypto/test/TestCryptoCipher.c b/winpr/libwinpr/crypto/test/TestCryptoCipher.c index 29aa925..cbf940d 100644 --- a/winpr/libwinpr/crypto/test/TestCryptoCipher.c +++ b/winpr/libwinpr/crypto/test/TestCryptoCipher.c @@ -7,22 +7,26 @@ static const BYTE* TEST_RC4_KEY = (BYTE*) "Key"; static const char* TEST_RC4_PLAINTEXT = "Plaintext"; static const BYTE* TEST_RC4_CIPHERTEXT = (BYTE*) "\xBB\xF3\x16\xE8\xD9\x40\xAF\x0A\xD3"; -BOOL test_crypto_cipher_rc4() +static BOOL test_crypto_cipher_rc4() { size_t len; - BYTE* text; - WINPR_RC4_CTX ctx; + BOOL rc = FALSE; + BYTE* text = NULL; + WINPR_RC4_CTX* ctx; len = strlen(TEST_RC4_PLAINTEXT); text = (BYTE*) calloc(1, len); if (!text) - return FALSE; + goto out; - winpr_RC4_Init(&ctx, TEST_RC4_KEY, strlen((char*) TEST_RC4_KEY)); - winpr_RC4_Update(&ctx, len, (BYTE*) TEST_RC4_PLAINTEXT, text); - winpr_RC4_Final(&ctx); + if ((ctx = winpr_RC4_New(TEST_RC4_KEY, strlen((char*) TEST_RC4_KEY))) == NULL) + goto out; + rc = winpr_RC4_Update(ctx, len, (BYTE*) TEST_RC4_PLAINTEXT, text); + winpr_RC4_Free(ctx); + if (!rc) + goto out; if (memcmp(text, TEST_RC4_CIPHERTEXT, len) != 0) { @@ -36,11 +40,14 @@ BOOL test_crypto_cipher_rc4() free(actual); free(expected); - - return FALSE; + goto out; } - return TRUE; + rc = TRUE; + +out: + free(text); + return rc; } static const BYTE* TEST_RAND_DATA = (BYTE*) @@ -56,7 +63,7 @@ static const BYTE* TEST_CIPHER_KEY = (BYTE*) static const BYTE* TEST_CIPHER_IV = (BYTE*) "\xFE\xE3\x9F\xF0\xD1\x5E\x37\x0C\xAB\xAB\x9B\x04\xF3\xDB\x99\x15"; -BOOL test_crypto_cipher_key() +static BOOL test_crypto_cipher_key() { int status; BYTE key[32]; diff --git a/winpr/libwinpr/crypto/test/TestCryptoHash.c b/winpr/libwinpr/crypto/test/TestCryptoHash.c index 8178469..ffdf3db 100644 --- a/winpr/libwinpr/crypto/test/TestCryptoHash.c +++ b/winpr/libwinpr/crypto/test/TestCryptoHash.c @@ -6,29 +6,32 @@ static const char* TEST_MD5_DATA = "test"; static const BYTE* TEST_MD5_HASH = (BYTE*) "\x09\x8f\x6b\xcd\x46\x21\xd3\x73\xca\xde\x4e\x83\x26\x27\xb4\xf6"; -BOOL test_crypto_hash_md5() +static BOOL test_crypto_hash_md5(void) { - BYTE hash[16]; + BYTE hash[WINPR_MD5_DIGEST_LENGTH]; WINPR_MD5_CTX ctx; - winpr_MD5_Init(&ctx); - winpr_MD5_Update(&ctx, (BYTE*) TEST_MD5_DATA, strlen(TEST_MD5_DATA)); - winpr_MD5_Final(&ctx, hash); + if (!winpr_MD5_Init(&ctx)) + return FALSE; + if (!winpr_MD5_Update(&ctx, (BYTE*) TEST_MD5_DATA, strlen(TEST_MD5_DATA))) + return FALSE; + if (!winpr_MD5_Final(&ctx, hash, sizeof(hash))) + return FALSE; - if (memcmp(hash, TEST_MD5_HASH, 16) != 0) + if (memcmp(hash, TEST_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, 16, FALSE); - expected = winpr_BinToHexString(TEST_MD5_HASH, 16, FALSE); + actual = winpr_BinToHexString(hash, WINPR_MD5_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_MD5_HASH, WINPR_MD5_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected MD5 hash: Actual: %s Expected: %s\n", actual, expected); free(actual); free(expected); - return -1; + return FALSE; } return TRUE; @@ -37,29 +40,32 @@ BOOL test_crypto_hash_md5() static const char* TEST_MD4_DATA = "test"; static const BYTE* TEST_MD4_HASH = (BYTE*) "\xdb\x34\x6d\x69\x1d\x7a\xcc\x4d\xc2\x62\x5d\xb1\x9f\x9e\x3f\x52"; -BOOL test_crypto_hash_md4() +static BOOL test_crypto_hash_md4(void) { - BYTE hash[16]; + BYTE hash[WINPR_MD4_DIGEST_LENGTH]; WINPR_MD4_CTX ctx; - winpr_MD4_Init(&ctx); - winpr_MD4_Update(&ctx, (BYTE*) TEST_MD4_DATA, strlen(TEST_MD4_DATA)); - winpr_MD4_Final(&ctx, hash); + if (!winpr_MD4_Init(&ctx)) + return FALSE; + if (!winpr_MD4_Update(&ctx, (BYTE*) TEST_MD4_DATA, strlen(TEST_MD4_DATA))) + return FALSE; + if (!winpr_MD4_Final(&ctx, hash, sizeof(hash))) + return FALSE; - if (memcmp(hash, TEST_MD4_HASH, 16) != 0) + if (memcmp(hash, TEST_MD4_HASH, WINPR_MD4_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, 16, FALSE); - expected = winpr_BinToHexString(TEST_MD4_HASH, 16, FALSE); + actual = winpr_BinToHexString(hash, WINPR_MD4_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_MD4_HASH, WINPR_MD4_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected MD4 hash: Actual: %s Expected: %s\n", actual, expected); free(actual); free(expected); - return -1; + return FALSE; } return TRUE; @@ -68,29 +74,32 @@ BOOL test_crypto_hash_md4() static const char* TEST_SHA1_DATA = "test"; static const BYTE* TEST_SHA1_HASH = (BYTE*) "\xa9\x4a\x8f\xe5\xcc\xb1\x9b\xa6\x1c\x4c\x08\x73\xd3\x91\xe9\x87\x98\x2f\xbb\xd3"; -BOOL test_crypto_hash_sha1() +static BOOL test_crypto_hash_sha1(void) { - BYTE hash[20]; + BYTE hash[WINPR_SHA1_DIGEST_LENGTH]; WINPR_SHA1_CTX ctx; - winpr_SHA1_Init(&ctx); - winpr_SHA1_Update(&ctx, (BYTE*) TEST_SHA1_DATA, strlen(TEST_SHA1_DATA)); - winpr_SHA1_Final(&ctx, hash); + if (!winpr_SHA1_Init(&ctx)) + return FALSE; + if (!winpr_SHA1_Update(&ctx, (BYTE*) TEST_SHA1_DATA, strlen(TEST_SHA1_DATA))) + return FALSE; + if (!winpr_SHA1_Final(&ctx, hash, sizeof(hash))) + return FALSE; - if (memcmp(hash, TEST_SHA1_HASH, 20) != 0) + if (memcmp(hash, TEST_SHA1_HASH, WINPR_MD5_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, 20, FALSE); - expected = winpr_BinToHexString(TEST_SHA1_HASH, 20, FALSE); + actual = winpr_BinToHexString(hash, WINPR_SHA1_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected SHA1 hash: Actual: %s Expected: %s\n", actual, expected); free(actual); free(expected); - return -1; + return FALSE; } return TRUE; @@ -100,29 +109,32 @@ static const char* TEST_HMAC_MD5_DATA = "Hi There"; static const BYTE* TEST_HMAC_MD5_KEY = (BYTE*) "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; static const BYTE* TEST_HMAC_MD5_HASH = (BYTE*) "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d"; -BOOL test_crypto_hash_hmac_md5() +static BOOL test_crypto_hash_hmac_md5(void) { - BYTE hash[16]; + BYTE hash[WINPR_MD5_DIGEST_LENGTH]; WINPR_HMAC_CTX ctx; - winpr_HMAC_Init(&ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, 16); - winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_MD5_DATA, strlen(TEST_HMAC_MD5_DATA)); - winpr_HMAC_Final(&ctx, hash); + if (!winpr_HMAC_Init(&ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, WINPR_MD5_DIGEST_LENGTH)) + return FALSE; + if (!winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_MD5_DATA, strlen(TEST_HMAC_MD5_DATA))) + return FALSE; + if (!winpr_HMAC_Final(&ctx, hash, sizeof(hash))) + return FALSE; - if (memcmp(hash, TEST_HMAC_MD5_HASH, 16) != 0) + if (memcmp(hash, TEST_HMAC_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, 16, FALSE); - expected = winpr_BinToHexString(TEST_HMAC_MD5_HASH, 16, FALSE); + actual = winpr_BinToHexString(hash, WINPR_MD5_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_HMAC_MD5_HASH, WINPR_MD5_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected HMAC-MD5 hash: Actual: %s Expected: %s\n", actual, expected); free(actual); free(expected); - return -1; + return FALSE; } return TRUE; @@ -132,29 +144,32 @@ static const char* TEST_HMAC_SHA1_DATA = "Hi There"; static const BYTE* TEST_HMAC_SHA1_KEY = (BYTE*) "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; static const BYTE* TEST_HMAC_SHA1_HASH = (BYTE*) "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"; -BOOL test_crypto_hash_hmac_sha1() +static BOOL test_crypto_hash_hmac_sha1(void) { - BYTE hash[20]; + BYTE hash[WINPR_SHA1_DIGEST_LENGTH]; WINPR_HMAC_CTX ctx; - winpr_HMAC_Init(&ctx, WINPR_MD_SHA1, TEST_HMAC_SHA1_KEY, 20); - winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_SHA1_DATA, strlen(TEST_HMAC_SHA1_DATA)); - winpr_HMAC_Final(&ctx, hash); + if (!winpr_HMAC_Init(&ctx, WINPR_MD_SHA1, TEST_HMAC_SHA1_KEY, WINPR_SHA1_DIGEST_LENGTH)) + return FALSE; + if (!winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_SHA1_DATA, strlen(TEST_HMAC_SHA1_DATA))) + return FALSE; + if (!winpr_HMAC_Final(&ctx, hash, sizeof(hash))) + return FALSE; - if (memcmp(hash, TEST_HMAC_SHA1_HASH, 20) != 0) + if (memcmp(hash, TEST_HMAC_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, 20, FALSE); - expected = winpr_BinToHexString(TEST_HMAC_SHA1_HASH, 20, FALSE); + actual = winpr_BinToHexString(hash, WINPR_SHA1_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_HMAC_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected HMAC-SHA1 hash: Actual: %s Expected: %s\n", actual, expected); free(actual); free(expected); - return -1; + return FALSE; } return TRUE; diff --git a/winpr/libwinpr/dsparse/module.def b/winpr/libwinpr/dsparse/module.def deleted file mode 100644 index 683aae8..0000000 --- a/winpr/libwinpr/dsparse/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-dsparse" -EXPORTS - diff --git a/winpr/libwinpr/environment/module.def b/winpr/libwinpr/environment/module.def deleted file mode 100644 index e46493a..0000000 --- a/winpr/libwinpr/environment/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-environment" -EXPORTS diff --git a/winpr/libwinpr/error/module.def b/winpr/libwinpr/error/module.def deleted file mode 100644 index be897a9..0000000 --- a/winpr/libwinpr/error/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-error" -EXPORTS - diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index 27332e2..862703b 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -24,7 +24,11 @@ #include -#ifndef _WIN32 +#ifdef _WIN32 + +#include + +#else /* _WIN32 */ #include "../log.h" #define TAG WINPR_TAG("file") @@ -194,9 +198,6 @@ static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrit if (io_status != 1) return FALSE; - if ((io_status < 0) && (errno == EWOULDBLOCK)) - io_status = 0; - *lpNumberOfBytesWritten = nNumberOfBytesToWrite; return TRUE; } @@ -580,9 +581,9 @@ BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle) HANDLE GetFileHandleForFileDescriptor(int fd) { -#ifdef WIN32 +#ifdef _WIN32 return (HANDLE)_get_osfhandle(fd); -#else /* WIN32 */ +#else /* _WIN32 */ WINPR_FILE *pFile; FILE* fp; int flags; @@ -610,7 +611,7 @@ HANDLE GetFileHandleForFileDescriptor(int fd) return INVALID_HANDLE_VALUE; return (HANDLE)pFile; -#endif /* WIN32 */ +#endif /* _WIN32 */ } diff --git a/winpr/libwinpr/handle/module.def b/winpr/libwinpr/handle/module.def deleted file mode 100644 index 5e4d32f..0000000 --- a/winpr/libwinpr/handle/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-handle" -EXPORTS - diff --git a/winpr/libwinpr/heap/module.def b/winpr/libwinpr/heap/module.def deleted file mode 100644 index 7b6e836..0000000 --- a/winpr/libwinpr/heap/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-heap" -EXPORTS diff --git a/winpr/libwinpr/input/keycode.c b/winpr/libwinpr/input/keycode.c index 3d445cb..1c628b2 100644 --- a/winpr/libwinpr/input/keycode.c +++ b/winpr/libwinpr/input/keycode.c @@ -405,7 +405,7 @@ DWORD KEYCODE_TO_VKCODE_EVDEV[256] = VK_DBE_KATAKANA, /* 98 */ VK_DBE_HIRAGANA, /* 99 */ VK_CONVERT, /* 100 */ - VK_DBE_HIRAGANA, /* 101 */ + VK_HKTG, /* 101 */ VK_NONCONVERT, /* 102 */ 0, /* 103 */ VK_RETURN | KBDEXT, /* 104 */ @@ -436,7 +436,7 @@ DWORD KEYCODE_TO_VKCODE_EVDEV[256] = VK_ABNT_C2, /* KEY_KPCOMMA 129 */ VK_HANGUL, /* 130 */ VK_HANJA, /* 131 */ - 0, /* 132 */ + VK_OEM_8, /* 132 */ VK_LWIN | KBDEXT, /* 133 */ VK_RWIN | KBDEXT, /* 134 */ VK_APPS | KBDEXT, /* 135 */ diff --git a/winpr/libwinpr/input/virtualkey.c b/winpr/libwinpr/input/virtualkey.c index 64f71f0..94d20fd 100644 --- a/winpr/libwinpr/input/virtualkey.c +++ b/winpr/libwinpr/input/virtualkey.c @@ -64,7 +64,7 @@ static const VIRTUAL_KEY_CODE VIRTUAL_KEY_CODE_TABLE[256] = { VK_JUNJA, "VK_JUNJA" }, { VK_FINAL, "VK_FINAL" }, { VK_KANJI, "VK_KANJI" }, /* also VK_HANJA */ - { 0, NULL }, + { VK_HKTG, "VK_HKTG" }, { VK_ESCAPE, "VK_ESCAPE" }, { VK_CONVERT, "VK_CONVERT" }, { VK_NONCONVERT, "VK_NONCONVERT" }, @@ -417,7 +417,7 @@ XKB_KEYNAME XKB_KEYNAME_TABLE[] = { "HENK", VK_CONVERT }, { "MUHE", VK_NONCONVERT }, - { "HKTG", VK_DBE_KATAKANA }, + { "HKTG", VK_HKTG }, // { "AE13", VK_BACKSLASH_JP }, // JP // { "LVL3", 0x54} @@ -425,9 +425,10 @@ XKB_KEYNAME XKB_KEYNAME_TABLE[] = char* GetVirtualKeyName(DWORD vkcode) { - char* vkname; + char* vkname = NULL; - vkname = (char*) VIRTUAL_KEY_CODE_TABLE[vkcode].name; + if (vkcode < ARRAYSIZE(VIRTUAL_KEY_CODE_TABLE)) + vkname = (char*) VIRTUAL_KEY_CODE_TABLE[vkcode].name; if (!vkname) vkname = "VK_NONE"; diff --git a/winpr/libwinpr/interlocked/module.def b/winpr/libwinpr/interlocked/module.def deleted file mode 100644 index 39f2951..0000000 --- a/winpr/libwinpr/interlocked/module.def +++ /dev/null @@ -1,14 +0,0 @@ -LIBRARY "libwinpr-interlocked" -EXPORTS - ; Not required on windows > 5.1 - ; InterlockedCompareExchange64 @1 - InitializeListHead @2 - IsListEmpty @3 - RemoveEntryList @4 - InsertHeadList @5 - RemoveHeadList @6 - InsertTailList @7 - RemoveTailList @8 - AppendTailList @9 - PushEntryList @10 - PopEntryList @11 diff --git a/winpr/libwinpr/io/module.def b/winpr/libwinpr/io/module.def deleted file mode 100644 index 1f984b5..0000000 --- a/winpr/libwinpr/io/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-io" -EXPORTS diff --git a/winpr/libwinpr/library/module.def b/winpr/libwinpr/library/module.def deleted file mode 100644 index c4a5071..0000000 --- a/winpr/libwinpr/library/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-library" -EXPORTS - diff --git a/winpr/libwinpr/library/test/TestLibraryA/CMakeLists.txt b/winpr/libwinpr/library/test/TestLibraryA/CMakeLists.txt index 3241f09..b7c0649 100644 --- a/winpr/libwinpr/library/test/TestLibraryA/CMakeLists.txt +++ b/winpr/libwinpr/library/test/TestLibraryA/CMakeLists.txt @@ -21,7 +21,7 @@ set(MODULE_PREFIX "TEST_LIBRARY_A") set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} TestLibraryA.c) if(MSVC) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}) endif() add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) diff --git a/winpr/libwinpr/library/test/TestLibraryA/module.def b/winpr/libwinpr/library/test/TestLibraryA/module.def deleted file mode 100644 index d49a3e4..0000000 --- a/winpr/libwinpr/library/test/TestLibraryA/module.def +++ /dev/null @@ -1,4 +0,0 @@ -LIBRARY "TestLibraryA" -EXPORTS - FunctionA @1 - FunctionB @2 diff --git a/winpr/libwinpr/library/test/TestLibraryB/CMakeLists.txt b/winpr/libwinpr/library/test/TestLibraryB/CMakeLists.txt index ec4e85c..c1cc32a 100644 --- a/winpr/libwinpr/library/test/TestLibraryB/CMakeLists.txt +++ b/winpr/libwinpr/library/test/TestLibraryB/CMakeLists.txt @@ -21,7 +21,7 @@ set(MODULE_PREFIX "TEST_LIBRARY_B") set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} TestLibraryB.c) if(MSVC) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}) endif() add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) diff --git a/winpr/libwinpr/library/test/TestLibraryB/module.def b/winpr/libwinpr/library/test/TestLibraryB/module.def deleted file mode 100644 index 19ab14d..0000000 --- a/winpr/libwinpr/library/test/TestLibraryB/module.def +++ /dev/null @@ -1,4 +0,0 @@ -LIBRARY "TestLibraryB" -EXPORTS - FunctionA @1 - FunctionB @2 diff --git a/winpr/libwinpr/locale/module.def b/winpr/libwinpr/locale/module.def deleted file mode 100644 index 593aba5..0000000 --- a/winpr/libwinpr/locale/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-locale" -EXPORTS diff --git a/winpr/libwinpr/memory/module.def b/winpr/libwinpr/memory/module.def deleted file mode 100644 index 14a9402..0000000 --- a/winpr/libwinpr/memory/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-memory" -EXPORTS - diff --git a/winpr/libwinpr/nt/module.def b/winpr/libwinpr/nt/module.def deleted file mode 100644 index b45c622..0000000 --- a/winpr/libwinpr/nt/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-nt" -EXPORTS - diff --git a/winpr/libwinpr/nt/nt.c b/winpr/libwinpr/nt/nt.c index b45509f..7b6d212 100644 --- a/winpr/libwinpr/nt/nt.c +++ b/winpr/libwinpr/nt/nt.c @@ -57,12 +57,25 @@ VOID _InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes, #ifndef _WIN32 -#include "nt.h" #include - #include +#include "../handle/handle.h" + +struct winpr_nt_file +{ + WINPR_HANDLE_DEF(); + + ACCESS_MASK DesiredAccess; + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG FileAttributes; + ULONG ShareAccess; + ULONG CreateDisposition; + ULONG CreateOptions; +}; +typedef struct winpr_nt_file WINPR_NT_FILE; + static pthread_once_t _TebOnceControl = PTHREAD_ONCE_INIT; static pthread_key_t _TebKey; @@ -210,9 +223,9 @@ NTSTATUS _NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength) { - WINPR_FILE* pFileHandle; + WINPR_NT_FILE* pFileHandle; - pFileHandle = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE)); + pFileHandle = (WINPR_NT_FILE*) calloc(1, sizeof(WINPR_NT_FILE)); if (!pFileHandle) return STATUS_NO_MEMORY; @@ -241,9 +254,9 @@ NTSTATUS _NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions) { - WINPR_FILE* pFileHandle; + WINPR_NT_FILE* pFileHandle; - pFileHandle = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE)); + pFileHandle = (WINPR_NT_FILE*) calloc(1, sizeof(WINPR_NT_FILE)); if (!pFileHandle) return STATUS_NO_MEMORY; @@ -298,12 +311,12 @@ NTSTATUS _NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event, NTSTATUS _NtClose(HANDLE Handle) { - WINPR_FILE* pFileHandle; + WINPR_NT_FILE* pFileHandle; if (!Handle) return 0; - pFileHandle = (WINPR_FILE*) Handle; + pFileHandle = (WINPR_NT_FILE*) Handle; free(pFileHandle); diff --git a/winpr/libwinpr/nt/nt.h b/winpr/libwinpr/nt/nt.h deleted file mode 100644 index 52eda2f..0000000 --- a/winpr/libwinpr/nt/nt.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * WinPR: Windows Portable Runtime - * Windows Native System Services - * - * Copyright 2013 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WINPR_NT_PRIVATE_H -#define WINPR_NT_PRIVATE_H - -#ifndef _WIN32 - -#include - -#include "../handle/handle.h" - -struct winpr_file -{ - WINPR_HANDLE_DEF(); - - ACCESS_MASK DesiredAccess; - OBJECT_ATTRIBUTES ObjectAttributes; - ULONG FileAttributes; - ULONG ShareAccess; - ULONG CreateDisposition; - ULONG CreateOptions; -}; -typedef struct winpr_file WINPR_FILE; - -#endif - -#endif /* WINPR_NT_PRIVATE_H */ - diff --git a/winpr/libwinpr/path/shell.c b/winpr/libwinpr/path/shell.c index dd52986..b35f629 100644 --- a/winpr/libwinpr/path/shell.c +++ b/winpr/libwinpr/path/shell.c @@ -76,11 +76,6 @@ static char* GetPath_HOME(void) #ifdef _WIN32 path = GetEnvAlloc("UserProfile"); -#elif defined(ANDROID) - path = malloc(2); - if (!path) - return NULL; - strcpy(path, "/"); #else path = GetEnvAlloc("HOME"); #endif diff --git a/winpr/libwinpr/pipe/module.def b/winpr/libwinpr/pipe/module.def deleted file mode 100644 index 8c4cc1e..0000000 --- a/winpr/libwinpr/pipe/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-pipe" -EXPORTS - diff --git a/winpr/libwinpr/pool/module.def b/winpr/libwinpr/pool/module.def deleted file mode 100644 index 1651b3c..0000000 --- a/winpr/libwinpr/pool/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-pool" -EXPORTS - diff --git a/winpr/libwinpr/registry/module.def b/winpr/libwinpr/registry/module.def deleted file mode 100644 index d65f455..0000000 --- a/winpr/libwinpr/registry/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-registry" -EXPORTS diff --git a/winpr/libwinpr/rpc/module.def b/winpr/libwinpr/rpc/module.def deleted file mode 100644 index 63efed1..0000000 --- a/winpr/libwinpr/rpc/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-rpc" -EXPORTS - diff --git a/winpr/libwinpr/security/module.def b/winpr/libwinpr/security/module.def deleted file mode 100644 index 9857be6..0000000 --- a/winpr/libwinpr/security/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-security" -EXPORTS diff --git a/winpr/libwinpr/shell/CMakeLists.txt b/winpr/libwinpr/shell/CMakeLists.txt index 4179670..24b47e3 100644 --- a/winpr/libwinpr/shell/CMakeLists.txt +++ b/winpr/libwinpr/shell/CMakeLists.txt @@ -15,4 +15,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -winpr_module_add(shell.c) +if (NOT ANDROID) + winpr_module_add(shell.c) +endif() diff --git a/winpr/libwinpr/smartcard/module.def b/winpr/libwinpr/smartcard/module.def deleted file mode 100644 index 3691a23..0000000 --- a/winpr/libwinpr/smartcard/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-smartcard" -EXPORTS - diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index 5256828..34cfc88 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -1996,7 +1996,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard, { if (pcchReaderLenAlloc) { -#ifdef __MAXOSX__ +#ifdef __MACOSX__ /** * Workaround for SCardStatus Bug in MAC OS X Yosemite */ diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c index 9b732a8..0602466 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm.c @@ -239,6 +239,8 @@ void ntlm_ContextFree(NTLM_CONTEXT* context) if (!context) return; + winpr_RC4_Free(context->SendRc4Seal); + winpr_RC4_Free(context->RecvRc4Seal); sspi_SecBufferFree(&context->NegotiateMessage); sspi_SecBufferFree(&context->ChallengeMessage); sspi_SecBufferFree(&context->AuthenticateMessage); @@ -685,6 +687,90 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, UL return SEC_E_OK; } + else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_NTPROOF_VALUE) + { + BYTE *blob; + SecBuffer *ntproof, *target; + + ntproof = (SecBuffer *)pBuffer; + target = &context->ChallengeTargetInfo; + + if (!sspi_SecBufferAlloc(ntproof, 36 + target->cbBuffer)) + return (SEC_E_INSUFFICIENT_MEMORY); + + blob = (BYTE *)ntproof->pvBuffer; + /* Server challenge. */ + CopyMemory(blob, context->ServerChallenge, 8); + /* Response version. */ + blob[8] = 1; + /* Highest response version understood by the client. */ + blob[9] = 1; + /* Reserved 6B. */ + /* Time. */ + CopyMemory(&blob[16], context->Timestamp, 8); + /* Client challenge. */ + CopyMemory(&blob[24], context->ClientChallenge, 8); + /* Reserved 4B. */ + /* Server name. */ + CopyMemory(&blob[36], target->pvBuffer, target->cbBuffer); + + return (SEC_E_OK); + } + else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_RANDKEY) + { + SecBuffer *randkey; + + randkey = (SecBuffer *) pBuffer; + if (!sspi_SecBufferAlloc(randkey, 16)) + return (SEC_E_INSUFFICIENT_MEMORY); + + CopyMemory(randkey->pvBuffer, context->EncryptedRandomSessionKey, 16); + + return (SEC_E_OK); + } + else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_MIC) + { + SecBuffer *mic; + NTLM_AUTHENTICATE_MESSAGE *message; + + mic = (SecBuffer *) pBuffer; + message = &context->AUTHENTICATE_MESSAGE; + + if (!sspi_SecBufferAlloc(mic, 16)) + return (SEC_E_INSUFFICIENT_MEMORY); + + CopyMemory(mic->pvBuffer, message->MessageIntegrityCheck, 16); + + return (SEC_E_OK); + } + else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_MIC_VALUE) + { + BYTE *blob; + SecBuffer *micvalue; + ULONG msgSize = context->NegotiateMessage.cbBuffer + context->ChallengeMessage.cbBuffer + + context->AuthenticateMessage.cbBuffer; + + micvalue = (SecBuffer *) pBuffer; + + if (!sspi_SecBufferAlloc(micvalue, msgSize)) + return (SEC_E_INSUFFICIENT_MEMORY); + + blob = (BYTE *) micvalue->pvBuffer; + + CopyMemory(blob, context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer); + blob += context->NegotiateMessage.cbBuffer; + + CopyMemory(blob, context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer); + blob += context->ChallengeMessage.cbBuffer; + + CopyMemory(blob, context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer); + + blob += context->MessageIntegrityCheckOffset; + ZeroMemory(blob, 16); + + return (SEC_E_OK); + } + return SEC_E_UNSUPPORTED_FUNCTION; } @@ -805,7 +891,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, int length; void* data; UINT32 SeqNo; - BYTE digest[16]; + BYTE digest[WINPR_MD5_DIGEST_LENGTH]; BYTE checksum[8]; BYTE* signature; ULONG version = 1; @@ -839,15 +925,15 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, CopyMemory(data, data_buffer->pvBuffer, length); /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */ - winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->SendSigningKey, 16); + winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->SendSigningKey, WINPR_MD5_DIGEST_LENGTH); winpr_HMAC_Update(&hmac, (void*) &(SeqNo), 4); winpr_HMAC_Update(&hmac, (void*) data, length); - winpr_HMAC_Final(&hmac, digest); + winpr_HMAC_Final(&hmac, digest, WINPR_MD5_DIGEST_LENGTH); /* Encrypt message using with RC4, result overwrites original buffer */ if (context->confidentiality) - winpr_RC4_Update(&context->SendRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer); + winpr_RC4_Update(context->SendRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer); else CopyMemory(data_buffer->pvBuffer, data, length); @@ -859,7 +945,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, #endif free(data); /* RC4-encrypt first 8 bytes of digest */ - winpr_RC4_Update(&context->SendRc4Seal, 8, digest, checksum); + winpr_RC4_Update(context->SendRc4Seal, 8, digest, checksum); signature = (BYTE*) signature_buffer->pvBuffer; /* Concatenate version, ciphertext and sequence number to build signature */ CopyMemory(signature, (void*) &version, 4); @@ -879,12 +965,12 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD int length; void* data; UINT32 SeqNo; - BYTE digest[16]; + BYTE digest[WINPR_MD5_DIGEST_LENGTH]; BYTE checksum[8]; UINT32 version = 1; WINPR_HMAC_CTX hmac; NTLM_CONTEXT* context; - BYTE expected_signature[16]; + BYTE expected_signature[WINPR_MD5_DIGEST_LENGTH]; PSecBuffer data_buffer = NULL; PSecBuffer signature_buffer = NULL; SeqNo = (UINT32) MessageSeqNo; @@ -916,15 +1002,15 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD /* Decrypt message using with RC4, result overwrites original buffer */ if (context->confidentiality) - winpr_RC4_Update(&context->RecvRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer); + winpr_RC4_Update(context->RecvRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer); else CopyMemory(data_buffer->pvBuffer, data, length); /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */ - winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->RecvSigningKey, 16); + winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->RecvSigningKey, WINPR_MD5_DIGEST_LENGTH); winpr_HMAC_Update(&hmac, (void*) &(SeqNo), 4); winpr_HMAC_Update(&hmac, (void*) data_buffer->pvBuffer, data_buffer->cbBuffer); - winpr_HMAC_Final(&hmac, digest); + winpr_HMAC_Final(&hmac, digest, WINPR_MD5_DIGEST_LENGTH); #ifdef WITH_DEBUG_NTLM WLog_DBG(TAG, "Encrypted Data Buffer (length = %d)", length); winpr_HexDump(TAG, WLOG_DEBUG, data, length); @@ -933,7 +1019,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD #endif free(data); /* RC4-encrypt first 8 bytes of digest */ - winpr_RC4_Update(&context->RecvRc4Seal, 8, digest, checksum); + winpr_RC4_Update(context->RecvRc4Seal, 8, digest, checksum); /* Concatenate version, ciphertext and sequence number to build signature */ CopyMemory(expected_signature, (void*) &version, 4); CopyMemory(&expected_signature[4], (void*) checksum, 8); diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.h b/winpr/libwinpr/sspi/NTLM/ntlm.h index bdccecd..8253f3d 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.h +++ b/winpr/libwinpr/sspi/NTLM/ntlm.h @@ -225,8 +225,8 @@ struct _NTLM_CONTEXT BYTE MachineID[32]; BOOL SendVersionInfo; BOOL confidentiality; - WINPR_RC4_CTX SendRc4Seal; - WINPR_RC4_CTX RecvRc4Seal; + WINPR_RC4_CTX* SendRc4Seal; + WINPR_RC4_CTX* RecvRc4Seal; BYTE* SendSigningKey; BYTE* RecvSigningKey; BYTE* SendSealingKey; diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c index d3b9802..96d3738 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c @@ -260,7 +260,7 @@ void ntlm_compute_channel_bindings(NTLM_CONTEXT* context) UINT32 ChannelBindingTokenLength; SEC_CHANNEL_BINDINGS* ChannelBindings; - ZeroMemory(context->ChannelBindingsHash, 16); + ZeroMemory(context->ChannelBindingsHash, WINPR_MD5_DIGEST_LENGTH); ChannelBindings = context->Bindings.Bindings; if (!ChannelBindings) @@ -275,7 +275,7 @@ void ntlm_compute_channel_bindings(NTLM_CONTEXT* context) ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbAcceptorLength); ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbApplicationDataLength); winpr_MD5_Update(&md5, (void*) ChannelBindingToken, ChannelBindingTokenLength); - winpr_MD5_Final(&md5, context->ChannelBindingsHash); + winpr_MD5_Final(&md5, context->ChannelBindingsHash, WINPR_MD5_DIGEST_LENGTH); } void ntlm_compute_single_host_data(NTLM_CONTEXT* context) diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c index b2973c4..8c18466 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c @@ -315,7 +315,7 @@ int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) { BYTE* response; - BYTE value[16]; + BYTE value[WINPR_MD5_DIGEST_LENGTH]; if (context->LmCompatibilityLevel < 2) { @@ -340,7 +340,9 @@ int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) response = (BYTE*) context->LmChallengeResponse.pvBuffer; /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */ - winpr_HMAC(WINPR_MD_MD5, (void*) context->NtlmV2Hash, 16, (BYTE*) value, 16, (BYTE*) response); + winpr_HMAC(WINPR_MD_MD5, (void*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) value, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) response, WINPR_MD5_DIGEST_LENGTH); /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */ CopyMemory(&response[16], context->ClientChallenge, 8); return 1; @@ -356,7 +358,7 @@ int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) { BYTE* blob; - BYTE nt_proof_str[16]; + BYTE nt_proof_str[WINPR_MD5_DIGEST_LENGTH]; SecBuffer ntlm_v2_temp; SecBuffer ntlm_v2_temp_chal; PSecBuffer TargetInfo; @@ -385,7 +387,7 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) WLog_DBG(TAG, "Workstation (length = %d)", context->Workstation.Length); winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) context->Workstation.Buffer, context->Workstation.Length); WLog_DBG(TAG, "NTOWFv2, NTLMv2 Hash"); - winpr_HexDump(TAG, WLOG_DEBUG, context->NtlmV2Hash, 16); + winpr_HexDump(TAG, WLOG_DEBUG, context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH); #endif /* Construct temp */ blob[0] = 1; /* RespType (1 byte) */ @@ -409,8 +411,9 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) blob = (BYTE*) ntlm_v2_temp_chal.pvBuffer; CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); - winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, 16, (BYTE*) ntlm_v2_temp_chal.pvBuffer, - ntlm_v2_temp_chal.cbBuffer, (BYTE*) nt_proof_str); + winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, + (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH); /* NtChallengeResponse, Concatenate NTProofStr with temp */ @@ -421,7 +424,9 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) CopyMemory(blob, nt_proof_str, 16); CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ - winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, 16, (BYTE*) nt_proof_str, 16, (BYTE*) context->SessionBaseKey); + winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) context->SessionBaseKey, WINPR_MD5_DIGEST_LENGTH); sspi_SecBufferFree(&ntlm_v2_temp); sspi_SecBufferFree(&ntlm_v2_temp_chal); return 1; @@ -437,10 +442,12 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) void ntlm_rc4k(BYTE* key, int length, BYTE* plaintext, BYTE* ciphertext) { - WINPR_RC4_CTX rc4; - winpr_RC4_Init(&rc4, (void*) key, 16); - winpr_RC4_Update(&rc4, length, (void*) plaintext, (void*) ciphertext); - winpr_RC4_Final(&rc4); + WINPR_RC4_CTX* rc4 = winpr_RC4_New(key, 16); + if (rc4) + { + winpr_RC4_Update(rc4, length, plaintext, ciphertext); + winpr_RC4_Free(rc4); + } } /** @@ -544,18 +551,18 @@ int ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic, BYTE* value; WINPR_MD5_CTX md5; - length = 16 + sign_magic->cbBuffer; + length = WINPR_MD5_DIGEST_LENGTH + sign_magic->cbBuffer; value = (BYTE*) malloc(length); if (!value) return -1; /* Concatenate ExportedSessionKey with sign magic */ - CopyMemory(value, exported_session_key, 16); - CopyMemory(&value[16], sign_magic->pvBuffer, sign_magic->cbBuffer); + CopyMemory(value, exported_session_key, WINPR_MD5_DIGEST_LENGTH); + CopyMemory(&value[WINPR_MD5_DIGEST_LENGTH], sign_magic->pvBuffer, sign_magic->cbBuffer); winpr_MD5_Init(&md5); winpr_MD5_Update(&md5, value, length); - winpr_MD5_Final(&md5, signing_key); + winpr_MD5_Final(&md5, signing_key, WINPR_MD5_DIGEST_LENGTH); free(value); return 1; } @@ -602,16 +609,16 @@ int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, WINPR_MD5_CTX md5; SecBuffer buffer; - if (!sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer)) + if (!sspi_SecBufferAlloc(&buffer, WINPR_MD5_DIGEST_LENGTH + seal_magic->cbBuffer)) return -1; p = (BYTE*) buffer.pvBuffer; /* Concatenate ExportedSessionKey with seal magic */ - CopyMemory(p, exported_session_key, 16); - CopyMemory(&p[16], seal_magic->pvBuffer, seal_magic->cbBuffer); + CopyMemory(p, exported_session_key, WINPR_MD5_DIGEST_LENGTH); + CopyMemory(&p[WINPR_MD5_DIGEST_LENGTH], seal_magic->pvBuffer, seal_magic->cbBuffer); winpr_MD5_Init(&md5); winpr_MD5_Update(&md5, buffer.pvBuffer, buffer.cbBuffer); - winpr_MD5_Final(&md5, sealing_key); + winpr_MD5_Final(&md5, sealing_key, WINPR_MD5_DIGEST_LENGTH); sspi_SecBufferFree(&buffer); return 1; } @@ -657,8 +664,8 @@ void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context) context->RecvSigningKey = context->ClientSigningKey; context->SendSealingKey = context->ClientSealingKey; context->RecvSealingKey = context->ServerSealingKey; - winpr_RC4_Init(&context->SendRc4Seal, context->ServerSealingKey, 16); - winpr_RC4_Init(&context->RecvRc4Seal, context->ClientSealingKey, 16); + context->SendRc4Seal = winpr_RC4_New(context->ServerSealingKey, 16); + context->RecvRc4Seal = winpr_RC4_New(context->ClientSealingKey, 16); } else { @@ -666,8 +673,8 @@ void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context) context->RecvSigningKey = context->ServerSigningKey; context->SendSealingKey = context->ServerSealingKey; context->RecvSealingKey = context->ClientSealingKey; - winpr_RC4_Init(&context->SendRc4Seal, context->ClientSealingKey, 16); - winpr_RC4_Init(&context->RecvRc4Seal, context->ServerSealingKey, 16); + context->SendRc4Seal = winpr_RC4_New(context->ClientSealingKey, 16); + context->RecvRc4Seal = winpr_RC4_New(context->ServerSealingKey, 16); } } @@ -679,9 +686,9 @@ void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context) * CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE) using the ExportedSessionKey */ - winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->ExportedSessionKey, 16); + winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->ExportedSessionKey, WINPR_MD5_DIGEST_LENGTH); winpr_HMAC_Update(&hmac, (BYTE*) context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer); winpr_HMAC_Update(&hmac, (BYTE*) context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer); winpr_HMAC_Update(&hmac, (BYTE*) context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer); - winpr_HMAC_Final(&hmac, context->MessageIntegrityCheck); + winpr_HMAC_Final(&hmac, context->MessageIntegrityCheck, WINPR_MD5_DIGEST_LENGTH); } diff --git a/winpr/libwinpr/sspi/module.def b/winpr/libwinpr/sspi/module.def deleted file mode 100644 index b08f897..0000000 --- a/winpr/libwinpr/sspi/module.def +++ /dev/null @@ -1,34 +0,0 @@ -LIBRARY "libwinpr-sspi" -EXPORTS - AcceptSecurityContext - AcquireCredentialsHandleA - AcquireCredentialsHandleW - ApplyControlToken - CompleteAuthToken - DecryptMessage - DeleteSecurityContext - EncryptMessage - EnumerateSecurityPackagesA - EnumerateSecurityPackagesW - ExportSecurityContext - FreeContextBuffer - FreeCredentialsHandle - ImpersonateSecurityContext - ImportSecurityContextA - ImportSecurityContextW - InitSecurityInterfaceA - InitSecurityInterfaceW - InitializeSecurityContextA - InitializeSecurityContextW - MakeSignature - QueryContextAttributesA - QueryContextAttributesW - QueryCredentialsAttributesA - QueryCredentialsAttributesW - QuerySecurityContextToken - QuerySecurityPackageInfoA - QuerySecurityPackageInfoW - RevertSecurityContext - VerifySignature - InitSecurityInterfaceExA - InitSecurityInterfaceExW diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c index 3192b43..41fa929 100644 --- a/winpr/libwinpr/synch/wait.c +++ b/winpr/libwinpr/synch/wait.c @@ -297,8 +297,8 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl unsigned long long diff; DWORD signalled; DWORD polled; - DWORD *poll_map; - BOOL *signalled_idx; + DWORD *poll_map = NULL; + BOOL *signalled_idx = NULL; int fd = -1; int index; int status; diff --git a/winpr/libwinpr/sysinfo/module.def b/winpr/libwinpr/sysinfo/module.def deleted file mode 100644 index 50f4066..0000000 --- a/winpr/libwinpr/sysinfo/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-sysinfo" -EXPORTS - diff --git a/winpr/libwinpr/thread/module.def b/winpr/libwinpr/thread/module.def deleted file mode 100644 index 688109b..0000000 --- a/winpr/libwinpr/thread/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-thread" -EXPORTS - diff --git a/winpr/libwinpr/thread/thread.c b/winpr/libwinpr/thread/thread.c index 54fd388..39eaa35 100644 --- a/winpr/libwinpr/thread/thread.c +++ b/winpr/libwinpr/thread/thread.c @@ -663,8 +663,7 @@ DWORD GetCurrentThreadId(VOID) /* Since pthread_t can be 64-bits on some systems, take just the */ /* lower 32-bits of it for the thread ID returned by this function. */ - tid = (long)tid & 0xffffffff; - return (DWORD) tid; + return (DWORD)tid & 0xffffffffUL; } DWORD ResumeThread(HANDLE hThread) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index d910eaa..79cb6f3 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -22,12 +22,1741 @@ #endif #include +#include +#include "../log.h" + +#define TAG WINPR_TAG("timezone") #ifndef _WIN32 +#include +#include + +struct _TIME_ZONE_RULE_ENTRY +{ + UINT64 TicksStart; + UINT64 TicksEnd; + INT32 DaylightDelta; + SYSTEMTIME StandardDate; + SYSTEMTIME DaylightDate; +}; +typedef struct _TIME_ZONE_RULE_ENTRY TIME_ZONE_RULE_ENTRY; + +struct _TIME_ZONE_ENTRY +{ + const char* Id; + UINT32 Bias; + BOOL SupportsDST; + const char* DisplayName; + const char* StandardName; + const char* DaylightName; + TIME_ZONE_RULE_ENTRY* RuleTable; + UINT32 RuleTableCount; +}; +typedef struct _TIME_ZONE_ENTRY TIME_ZONE_ENTRY; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_3[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_4[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_5[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_7[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_8[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_10[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_11[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_14[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_15[] = +{ + { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_17[] = +{ + { 633662964000000000ULL, 180000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 9, 6, 1, 23, 59 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_18[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_19[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 2, 0, 1, 2, 0 }, { 0, 11, 0, 1, 0, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 0, 1, 0, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_21[] = +{ + { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 5, 6, 1, 23, 59 }, { 0, 8, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_22[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 0, 1 }, { 0, 4, 0, 1, 0, 1 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 0, 1 }, }, + { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_23[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 2, 0, 1, 2, 0 }, { 0, 11, 0, 1, 0, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 0, 1, 0, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_24[] = +{ + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 1, 1, 1, 0, 0 }, { 0, 12, 0, 1, 0, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 1, 4, 1, 0, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_26[] = +{ + { 633662964000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_27[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 9, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 10, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_28[] = +{ + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 1, 6, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_30[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_31[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_33[] = +{ + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 8, 0, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 5, 0, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 8, 6, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 7, 6, 1, 23, 59 }, { 0, 4, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_35[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 0, 1, 1, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_37[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_38[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_39[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_40[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_42[] = +{ + { 634293684000000000ULL, 180000000000ULL, -60, { 0, 9, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 634294548000000000ULL, 60, { 0, 4, 0, 1, 2, 0 }, { 0, 9, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_43[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 9, 5, 1, 1, 0 }, { 0, 3, 4, 1, 0, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 10, 5, 1, 1, 0 }, { 0, 3, 4, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_44[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_45[] = +{ + { 633978324000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 0, 0 }, { 0, 3, 0, 1, 0, 0 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_46[] = +{ + { 632716020000000000ULL, 180000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 5, 1, 0, 0 }, }, + { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 5, 1, 0, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_47[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 9, 3, 1, 23, 59 }, { 0, 3, 5, 1, 23, 59 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 11, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 5, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, + { 3155378292000000000ULL, 636188436000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_49[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_50[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 1, 1, 3, 0 }, }, + { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_51[] = +{ + { 632716020000000000ULL, 632401524000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, + { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_52[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_53[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 4, 0, 1, 3, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 10, 1, 1, 4, 0 }, { 0, 4, 0, 1, 3, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_54[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_57[] = +{ + { 632716020000000000ULL, 180000000000ULL, 60, { 0, 9, 2, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 9, 6, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, + { 3155378292000000000ULL, 633663828000000000ULL, 60, { 0, 9, 1, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_59[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 5, 0 }, { 0, 3, 0, 1, 4, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_60[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_61[] = +{ + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 1, 2, 1, 0, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 1, 4, 1, 0, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_63[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_65[] = +{ + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 5, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 4, 2, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_71[] = +{ + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 12, 4, 1, 23, 59 }, { 0, 6, 5, 1, 23, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_72[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_75[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_77[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_79[] = +{ + { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 1, 0, 1, 0, 0 }, { 0, 12, 0, 1, 2, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 1, 4, 1, 0, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_82[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_85[] = +{ + { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_88[] = +{ + { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_90[] = +{ + { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_91[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_93[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_94[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 9, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 9, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_96[] = +{ + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 1, 4, 1, 0, 0 }, { 0, 11, 0, 1, 2, 0 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 1, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 634926132000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_97[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_98[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_100[] = +{ + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 1, 5, 1, 0, 0 }, { 0, 9, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 634294548000000000ULL, 60, { 0, 4, 0, 1, 1, 0 }, { 0, 9, 0, 1, 0, 0 }, } +}; + +static const TIME_ZONE_ENTRY TimeZoneTable[] = +{ + { + "Dateline Standard Time", 720, FALSE, "(UTC-12:00) International Date Line West", + "Dateline Standard Time", "Dateline Daylight Time", + NULL, 0 + }, + { + "UTC-11", 780, FALSE, "(UTC-11:00) Coordinated Universal Time-11", + "UTC-11", "UTC-11", + NULL, 0 + }, + { + "Hawaiian Standard Time", 840, FALSE, "(UTC-10:00) Hawaii", + "Hawaiian Standard Time", "Hawaiian Daylight Time", + NULL, 0 + }, + { + "Alaskan Standard Time", 900, TRUE, "(UTC-09:00) Alaska", + "Alaskan Standard Time", "Alaskan Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_3, 2 + }, + { + "Pacific Standard Time (Mexico)", 960, TRUE, "(UTC-08:00) Baja California", + "Pacific Standard Time (Mexico)", "Pacific Daylight Time (Mexico)", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_4, 1 + }, + { + "Pacific Standard Time", 960, TRUE, "(UTC-08:00) Pacific Time (US & Canada)", + "Pacific Standard Time", "Pacific Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_5, 2 + }, + { + "US Mountain Standard Time", 1020, FALSE, "(UTC-07:00) Arizona", + "US Mountain Standard Time", "US Mountain Daylight Time", + NULL, 0 + }, + { + "Mountain Standard Time (Mexico)", 1020, TRUE, "(UTC-07:00) Chihuahua, La Paz, Mazatlan", + "Mountain Standard Time (Mexico)", "Mountain Daylight Time (Mexico)", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_7, 1 + }, + { + "Mountain Standard Time", 1020, TRUE, "(UTC-07:00) Mountain Time (US & Canada)", + "Mountain Standard Time", "Mountain Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_8, 2 + }, + { + "Central America Standard Time", 1080, FALSE, "(UTC-06:00) Central America", + "Central America Standard Time", "Central America Daylight Time", + NULL, 0 + }, + { + "Central Standard Time", 1080, TRUE, "(UTC-06:00) Central Time (US & Canada)", + "Central Standard Time", "Central Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_10, 2 + }, + { + "Central Standard Time (Mexico)", 1080, TRUE, "(UTC-06:00) Guadalajara, Mexico City, Monterrey", + "Central Standard Time (Mexico)", "Central Daylight Time (Mexico)", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_11, 1 + }, + { + "Canada Central Standard Time", 1080, FALSE, "(UTC-06:00) Saskatchewan", + "Canada Central Standard Time", "Canada Central Daylight Time", + NULL, 0 + }, + { + "SA Pacific Standard Time", 1140, FALSE, "(UTC-05:00) Bogota, Lima, Quito", + "SA Pacific Standard Time", "SA Pacific Daylight Time", + NULL, 0 + }, + { + "Eastern Standard Time", 1140, TRUE, "(UTC-05:00) Eastern Time (US & Canada)", + "Eastern Standard Time", "Eastern Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_14, 2 + }, + { + "US Eastern Standard Time", 1140, TRUE, "(UTC-05:00) Indiana (East)", + "US Eastern Standard Time", "US Eastern Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_15, 2 + }, + { + "Venezuela Standard Time", 1170, FALSE, "(UTC-04:30) Caracas", + "Venezuela Standard Time", "Venezuela Daylight Time", + NULL, 0 + }, + { + "Paraguay Standard Time", 1200, TRUE, "(UTC-04:00) Asuncion", + "Paraguay Standard Time", "Paraguay Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_17, 14 + }, + { + "Atlantic Standard Time", 1200, TRUE, "(UTC-04:00) Atlantic Time (Canada)", + "Atlantic Standard Time", "Atlantic Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_18, 2 + }, + { + "Central Brazilian Standard Time", 1200, TRUE, "(UTC-04:00) Cuiaba", + "Central Brazilian Standard Time", "Central Brazilian Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_19, 35 + }, + { + "SA Western Standard Time", 1200, FALSE, "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", + "SA Western Standard Time", "SA Western Daylight Time", + NULL, 0 + }, + { + "Pacific SA Standard Time", 1200, TRUE, "(UTC-04:00) Santiago", + "Pacific SA Standard Time", "Pacific SA Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_21, 6 + }, + { + "Newfoundland Standard Time", 1230, TRUE, "(UTC-03:30) Newfoundland", + "Newfoundland Standard Time", "Newfoundland Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_22, 7 + }, + { + "E. South America Standard Time", 1260, TRUE, "(UTC-03:00) Brasilia", + "E. South America Standard Time", "E. South America Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_23, 35 + }, + { + "Argentina Standard Time", 1260, TRUE, "(UTC-03:00) Buenos Aires", + "Argentina Standard Time", "Argentina Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_24, 3 + }, + { + "SA Eastern Standard Time", 1260, FALSE, "(UTC-03:00) Cayenne, Fortaleza", + "SA Eastern Standard Time", "SA Eastern Daylight Time", + NULL, 0 + }, + { + "Greenland Standard Time", 1260, TRUE, "(UTC-03:00) Greenland", + "Greenland Standard Time", "Greenland Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_26, 14 + }, + { + "Montevideo Standard Time", 1260, TRUE, "(UTC-03:00) Montevideo", + "Montevideo Standard Time", "Montevideo Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_27, 2 + }, + { + "Bahia Standard Time", 1260, TRUE, "(UTC-03:00) Salvador", + "Bahia Standard Time", "Bahia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_28, 30 + }, + { + "UTC-02", 1320, FALSE, "(UTC-02:00) Coordinated Universal Time-02", + "UTC-02", "UTC-02", + NULL, 0 + }, + { + "Mid-Atlantic Standard Time", 1320, TRUE, "(UTC-02:00) Mid-Atlantic", + "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_30, 1 + }, + { + "Azores Standard Time", 1380, TRUE, "(UTC-01:00) Azores", + "Azores Standard Time", "Azores Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_31, 1 + }, + { + "Cape Verde Standard Time", 1380, FALSE, "(UTC-01:00) Cape Verde Is.", + "Cape Verde Standard Time", "Cape Verde Daylight Time", + NULL, 0 + }, + { + "Morocco Standard Time", 0, TRUE, "(UTC) Casablanca", + "Morocco Standard Time", "Morocco Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_33, 4 + }, + { + "UTC", 0, FALSE, "(UTC) Coordinated Universal Time", + "Coordinated Universal Time", "Coordinated Universal Time", + NULL, 0 + }, + { + "GMT Standard Time", 0, TRUE, "(UTC) Dublin, Edinburgh, Lisbon, London", + "GMT Standard Time", "GMT Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_35, 1 + }, + { + "Greenwich Standard Time", 0, FALSE, "(UTC) Monrovia, Reykjavik", + "Greenwich Standard Time", "Greenwich Daylight Time", + NULL, 0 + }, + { + "W. Europe Standard Time", 60, TRUE, "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", + "W. Europe Standard Time", "W. Europe Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_37, 1 + }, + { + "Central Europe Standard Time", 60, TRUE, "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", + "Central Europe Standard Time", "Central Europe Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_38, 1 + }, + { + "Romance Standard Time", 60, TRUE, "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", + "Romance Standard Time", "Romance Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_39, 1 + }, + { + "Central European Standard Time", 60, TRUE, "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", + "Central European Standard Time", "Central European Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_40, 1 + }, + { + "W. Central Africa Standard Time", 60, FALSE, "(UTC+01:00) West Central Africa", + "W. Central Africa Standard Time", "W. Central Africa Daylight Time", + NULL, 0 + }, + { + "Namibia Standard Time", 60, TRUE, "(UTC+01:00) Windhoek", + "Namibia Standard Time", "Namibia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_42, 2 + }, + { + "Jordan Standard Time", 120, TRUE, "(UTC+02:00) Amman", + "Jordan Standard Time", "Jordan Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_43, 2 + }, + { + "GTB Standard Time", 120, TRUE, "(UTC+02:00) Athens, Bucharest, Istanbul", + "GTB Standard Time", "GTB Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_44, 1 + }, + { + "Middle East Standard Time", 120, TRUE, "(UTC+02:00) Beirut", + "Middle East Standard Time", "Middle East Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_45, 13 + }, + { + "Egypt Standard Time", 120, TRUE, "(UTC+02:00) Cairo", + "Egypt Standard Time", "Egypt Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_46, 6 + }, + { + "Syria Standard Time", 120, TRUE, "(UTC+02:00) Damascus", + "Syria Standard Time", "Syria Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_47, 12 + }, + { + "South Africa Standard Time", 120, FALSE, "(UTC+02:00) Harare, Pretoria", + "South Africa Standard Time", "South Africa Daylight Time", + NULL, 0 + }, + { + "FLE Standard Time", 120, TRUE, "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", + "FLE Standard Time", "FLE Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_49, 1 + }, + { + "Turkey Standard Time", 120, TRUE, "(UTC+02:00) Istanbul", + "Turkey Standard Time", "Turkey Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_50, 3 + }, + { + "Israel Standard Time", 120, TRUE, "(UTC+02:00) Jerusalem", + "Jerusalem Standard Time", "Jerusalem Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_51, 18 + }, + { + "E. Europe Standard Time", 120, TRUE, "(UTC+02:00) Nicosia", + "E. Europe Standard Time", "E. Europe Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_52, 1 + }, + { + "Arabic Standard Time", 180, TRUE, "(UTC+03:00) Baghdad", + "Arabic Standard Time", "Arabic Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_53, 2 + }, + { + "Kaliningrad Standard Time", 180, TRUE, "(UTC+03:00) Kaliningrad, Minsk", + "Kaliningrad Standard Time", "Kaliningrad Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_54, 1 + }, + { + "Arab Standard Time", 180, FALSE, "(UTC+03:00) Kuwait, Riyadh", + "Arab Standard Time", "Arab Daylight Time", + NULL, 0 + }, + { + "E. Africa Standard Time", 180, FALSE, "(UTC+03:00) Nairobi", + "E. Africa Standard Time", "E. Africa Daylight Time", + NULL, 0 + }, + { + "Iran Standard Time", 210, TRUE, "(UTC+03:30) Tehran", + "Iran Standard Time", "Iran Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_57, 3 + }, + { + "Arabian Standard Time", 240, FALSE, "(UTC+04:00) Abu Dhabi, Muscat", + "Arabian Standard Time", "Arabian Daylight Time", + NULL, 0 + }, + { + "Azerbaijan Standard Time", 240, TRUE, "(UTC+04:00) Baku", + "Azerbaijan Standard Time", "Azerbaijan Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_59, 1 + }, + { + "Russian Standard Time", 240, TRUE, "(UTC+04:00) Moscow, St. Petersburg, Volgograd", + "Russian Standard Time", "Russian Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_60, 1 + }, + { + "Mauritius Standard Time", 240, TRUE, "(UTC+04:00) Port Louis", + "Mauritius Standard Time", "Mauritius Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_61, 2 + }, + { + "Georgian Standard Time", 240, FALSE, "(UTC+04:00) Tbilisi", + "Georgian Standard Time", "Georgian Daylight Time", + NULL, 0 + }, + { + "Caucasus Standard Time", 240, TRUE, "(UTC+04:00) Yerevan", + "Caucasus Standard Time", "Caucasus Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_63, 1 + }, + { + "Afghanistan Standard Time", 270, FALSE, "(UTC+04:30) Kabul", + "Afghanistan Standard Time", "Afghanistan Daylight Time", + NULL, 0 + }, + { + "Pakistan Standard Time", 300, TRUE, "(UTC+05:00) Islamabad, Karachi", + "Pakistan Standard Time", "Pakistan Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_65, 2 + }, + { + "West Asia Standard Time", 300, FALSE, "(UTC+05:00) Tashkent", + "West Asia Standard Time", "West Asia Daylight Time", + NULL, 0 + }, + { + "India Standard Time", 330, FALSE, "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", + "India Standard Time", "India Daylight Time", + NULL, 0 + }, + { + "Sri Lanka Standard Time", 330, FALSE, "(UTC+05:30) Sri Jayawardenepura", + "Sri Lanka Standard Time", "Sri Lanka Daylight Time", + NULL, 0 + }, + { + "Nepal Standard Time", 345, FALSE, "(UTC+05:45) Kathmandu", + "Nepal Standard Time", "Nepal Daylight Time", + NULL, 0 + }, + { + "Central Asia Standard Time", 360, FALSE, "(UTC+06:00) Astana", + "Central Asia Standard Time", "Central Asia Daylight Time", + NULL, 0 + }, + { + "Bangladesh Standard Time", 360, TRUE, "(UTC+06:00) Dhaka", + "Bangladesh Standard Time", "Bangladesh Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_71, 1 + }, + { + "Ekaterinburg Standard Time", 360, TRUE, "(UTC+06:00) Ekaterinburg", + "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_72, 1 + }, + { + "Myanmar Standard Time", 390, FALSE, "(UTC+06:30) Yangon (Rangoon)", + "Myanmar Standard Time", "Myanmar Daylight Time", + NULL, 0 + }, + { + "SE Asia Standard Time", 420, FALSE, "(UTC+07:00) Bangkok, Hanoi, Jakarta", + "SE Asia Standard Time", "SE Asia Daylight Time", + NULL, 0 + }, + { + "N. Central Asia Standard Time", 420, TRUE, "(UTC+07:00) Novosibirsk", + "N. Central Asia Standard Time", "N. Central Asia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_75, 1 + }, + { + "China Standard Time", 480, FALSE, "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", + "China Standard Time", "China Daylight Time", + NULL, 0 + }, + { + "North Asia Standard Time", 480, TRUE, "(UTC+08:00) Krasnoyarsk", + "North Asia Standard Time", "North Asia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_77, 1 + }, + { + "Singapore Standard Time", 480, FALSE, "(UTC+08:00) Kuala Lumpur, Singapore", + "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time", + NULL, 0 + }, + { + "W. Australia Standard Time", 480, TRUE, "(UTC+08:00) Perth", + "W. Australia Standard Time", "W. Australia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_79, 4 + }, + { + "Taipei Standard Time", 480, FALSE, "(UTC+08:00) Taipei", + "Taipei Standard Time", "Taipei Daylight Time", + NULL, 0 + }, + { + "Ulaanbaatar Standard Time", 480, FALSE, "(UTC+08:00) Ulaanbaatar", + "Ulaanbaatar Standard Time", "Ulaanbaatar Daylight Time", + NULL, 0 + }, + { + "North Asia East Standard Time", 540, TRUE, "(UTC+09:00) Irkutsk", + "North Asia East Standard Time", "North Asia East Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_82, 1 + }, + { + "Tokyo Standard Time", 540, FALSE, "(UTC+09:00) Osaka, Sapporo, Tokyo", + "Tokyo Standard Time", "Tokyo Daylight Time", + NULL, 0 + }, + { + "Korea Standard Time", 540, FALSE, "(UTC+09:00) Seoul", + "Korea Standard Time", "Korea Daylight Time", + NULL, 0 + }, + { + "Cen. Australia Standard Time", 570, TRUE, "(UTC+09:30) Adelaide", + "Cen. Australia Standard Time", "Cen. Australia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_85, 2 + }, + { + "AUS Central Standard Time", 570, FALSE, "(UTC+09:30) Darwin", + "AUS Central Standard Time", "AUS Central Daylight Time", + NULL, 0 + }, + { + "E. Australia Standard Time", 600, FALSE, "(UTC+10:00) Brisbane", + "E. Australia Standard Time", "E. Australia Daylight Time", + NULL, 0 + }, + { + "AUS Eastern Standard Time", 600, TRUE, "(UTC+10:00) Canberra, Melbourne, Sydney", + "AUS Eastern Standard Time", "AUS Eastern Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_88, 2 + }, + { + "West Pacific Standard Time", 600, FALSE, "(UTC+10:00) Guam, Port Moresby", + "West Pacific Standard Time", "West Pacific Daylight Time", + NULL, 0 + }, + { + "Tasmania Standard Time", 600, TRUE, "(UTC+10:00) Hobart", + "Tasmania Standard Time", "Tasmania Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_90, 2 + }, + { + "Yakutsk Standard Time", 600, TRUE, "(UTC+10:00) Yakutsk", + "Yakutsk Standard Time", "Yakutsk Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_91, 1 + }, + { + "Central Pacific Standard Time", 660, FALSE, "(UTC+11:00) Solomon Is., New Caledonia", + "Central Pacific Standard Time", "Central Pacific Daylight Time", + NULL, 0 + }, + { + "Vladivostok Standard Time", 660, TRUE, "(UTC+11:00) Vladivostok", + "Vladivostok Standard Time", "Vladivostok Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_93, 1 + }, + { + "New Zealand Standard Time", 720, TRUE, "(UTC+12:00) Auckland, Wellington", + "New Zealand Standard Time", "New Zealand Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_94, 3 + }, + { + "UTC+12", 720, FALSE, "(UTC+12:00) Coordinated Universal Time+12", + "UTC+12", "UTC+12", + NULL, 0 + }, + { + "Fiji Standard Time", 720, TRUE, "(UTC+12:00) Fiji", + "Fiji Standard Time", "Fiji Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_96, 5 + }, + { + "Magadan Standard Time", 720, TRUE, "(UTC+12:00) Magadan", + "Magadan Standard Time", "Magadan Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_97, 1 + }, + { + "Kamchatka Standard Time", 720, TRUE, "(UTC+12:00) Petropavlovsk-Kamchatsky - Old", + "Kamchatka Standard Time", "Kamchatka Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_98, 1 + }, + { + "Tonga Standard Time", 780, FALSE, "(UTC+13:00) Nuku'alofa", + "Tonga Standard Time", "Tonga Daylight Time", + NULL, 0 + }, + { + "Samoa Standard Time", 780, TRUE, "(UTC+13:00) Samoa", + "Samoa Standard Time", "Samoa Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_100, 2 + } +}; + +/* Table generated with WindowsZones.cs */ + +struct _WINDOWS_TZID_ENTRY +{ + const char* windows; + const char* tzid; +}; +typedef struct _WINDOWS_TZID_ENTRY WINDOWS_TZID_ENTRY; + +const WINDOWS_TZID_ENTRY WindowsTimeZoneIdTable[] = +{ + { "Afghanistan Standard Time", "Asia/Kabul" }, + { "Alaskan Standard Time", "America/Anchorage America/Juneau " + "America/Nome America/Sitka America/Yakutat" }, + { "Alaskan Standard Time", "America/Anchorage" }, + { "Arab Standard Time", "Asia/Aden" }, + { "Arab Standard Time", "Asia/Bahrain" }, + { "Arab Standard Time", "Asia/Kuwait" }, + { "Arab Standard Time", "Asia/Qatar" }, + { "Arab Standard Time", "Asia/Riyadh" }, + { "Arabian Standard Time", "Asia/Dubai" }, + { "Arabian Standard Time", "Asia/Muscat" }, + { "Arabian Standard Time", "Etc/GMT-4" }, + { "Arabic Standard Time", "Asia/Baghdad" }, + { "Argentina Standard Time", "America/Buenos_Aires America/Argentina/La_Rioja " + "America/Argentina/Rio_Gallegos America/Argentina/Salta " + "America/Argentina/San_Juan America/Argentina/San_Luis " + "America/Argentina/Tucuman America/Argentina/Ushuaia America/Catamarca " + "America/Cordoba America/Jujuy America/Mendoza" }, + { "Argentina Standard Time", "America/Buenos_Aires" }, + { "Atlantic Standard Time", "America/Halifax America/Glace_Bay " + "America/Goose_Bay America/Moncton" }, + { "Atlantic Standard Time", "America/Halifax" }, + { "Atlantic Standard Time", "America/Thule" }, + { "Atlantic Standard Time", "Atlantic/Bermuda" }, + { "AUS Central Standard Time", "Australia/Darwin" }, + { "AUS Eastern Standard Time", "Australia/Sydney Australia/Melbourne" }, + { "AUS Eastern Standard Time", "Australia/Sydney" }, + { "Azerbaijan Standard Time", "Asia/Baku" }, + { "Azores Standard Time", "America/Scoresbysund" }, + { "Azores Standard Time", "Atlantic/Azores" }, + { "Bahia Standard Time", "America/Bahia" }, + { "Bangladesh Standard Time", "Asia/Dhaka" }, + { "Bangladesh Standard Time", "Asia/Thimphu" }, + { "Canada Central Standard Time", "America/Regina America/Swift_Current" }, + { "Canada Central Standard Time", "America/Regina" }, + { "Cape Verde Standard Time", "Atlantic/Cape_Verde" }, + { "Cape Verde Standard Time", "Etc/GMT+1" }, + { "Caucasus Standard Time", "Asia/Yerevan" }, + { "Cen. Australia Standard Time", "Australia/Adelaide Australia/Broken_Hill" }, + { "Cen. Australia Standard Time", "Australia/Adelaide" }, + { "Central America Standard Time", "America/Belize" }, + { "Central America Standard Time", "America/Costa_Rica" }, + { "Central America Standard Time", "America/El_Salvador" }, + { "Central America Standard Time", "America/Guatemala" }, + { "Central America Standard Time", "America/Managua" }, + { "Central America Standard Time", "America/Tegucigalpa" }, + { "Central America Standard Time", "Etc/GMT+6" }, + { "Central America Standard Time", "Pacific/Galapagos" }, + { "Central Asia Standard Time", "Antarctica/Vostok" }, + { "Central Asia Standard Time", "Asia/Almaty Asia/Qyzylorda" }, + { "Central Asia Standard Time", "Asia/Almaty" }, + { "Central Asia Standard Time", "Asia/Bishkek" }, + { "Central Asia Standard Time", "Etc/GMT-6" }, + { "Central Asia Standard Time", "Indian/Chagos" }, + { "Central Brazilian Standard Time", "America/Cuiaba America/Campo_Grande" }, + { "Central Brazilian Standard Time", "America/Cuiaba" }, + { "Central Europe Standard Time", "Europe/Belgrade" }, + { "Central Europe Standard Time", "Europe/Bratislava" }, + { "Central Europe Standard Time", "Europe/Budapest" }, + { "Central Europe Standard Time", "Europe/Ljubljana" }, + { "Central Europe Standard Time", "Europe/Podgorica" }, + { "Central Europe Standard Time", "Europe/Prague" }, + { "Central Europe Standard Time", "Europe/Tirane" }, + { "Central European Standard Time", "Europe/Sarajevo" }, + { "Central European Standard Time", "Europe/Skopje" }, + { "Central European Standard Time", "Europe/Warsaw" }, + { "Central European Standard Time", "Europe/Zagreb" }, + { "Central Pacific Standard Time", "Antarctica/Macquarie" }, + { "Central Pacific Standard Time", "Etc/GMT-11" }, + { "Central Pacific Standard Time", "Pacific/Efate" }, + { "Central Pacific Standard Time", "Pacific/Guadalcanal" }, + { "Central Pacific Standard Time", "Pacific/Noumea" }, + { "Central Pacific Standard Time", "Pacific/Ponape Pacific/Kosrae" }, + { "Central Standard Time (Mexico)", "America/Mexico_City America/Bahia_Banderas " + "America/Cancun America/Merida America/Monterrey" }, + { "Central Standard Time (Mexico)", "America/Mexico_City" }, + { "Central Standard Time", "America/Chicago America/Indiana/Knox " + "America/Indiana/Tell_City America/Menominee " + "America/North_Dakota/Beulah America/North_Dakota/Center " + "America/North_Dakota/New_Salem" }, + { "Central Standard Time", "America/Chicago" }, + { "Central Standard Time", "America/Matamoros" }, + { "Central Standard Time", "America/Winnipeg America/Rainy_River " + "America/Rankin_Inlet America/Resolute" }, + { "Central Standard Time", "CST6CDT" }, + { "China Standard Time", "Asia/Hong_Kong" }, + { "China Standard Time", "Asia/Macau" }, + { "China Standard Time", "Asia/Shanghai Asia/Chongqing Asia/Harbin Asia/Kashgar Asia/Urumqi" }, + { "China Standard Time", "Asia/Shanghai" }, + { "Dateline Standard Time", "Etc/GMT+12" }, + { "E. Africa Standard Time", "Africa/Addis_Ababa" }, + { "E. Africa Standard Time", "Africa/Asmera" }, + { "E. Africa Standard Time", "Africa/Dar_es_Salaam" }, + { "E. Africa Standard Time", "Africa/Djibouti" }, + { "E. Africa Standard Time", "Africa/Juba" }, + { "E. Africa Standard Time", "Africa/Kampala" }, + { "E. Africa Standard Time", "Africa/Khartoum" }, + { "E. Africa Standard Time", "Africa/Mogadishu" }, + { "E. Africa Standard Time", "Africa/Nairobi" }, + { "E. Africa Standard Time", "Antarctica/Syowa" }, + { "E. Africa Standard Time", "Etc/GMT-3" }, + { "E. Africa Standard Time", "Indian/Antananarivo" }, + { "E. Africa Standard Time", "Indian/Comoro" }, + { "E. Africa Standard Time", "Indian/Mayotte" }, + { "E. Australia Standard Time", "Australia/Brisbane Australia/Lindeman" }, + { "E. Australia Standard Time", "Australia/Brisbane" }, + { "E. Europe Standard Time", "Asia/Nicosia" }, + { "E. South America Standard Time", "America/Sao_Paulo" }, + { "Eastern Standard Time", "America/Grand_Turk" }, + { "Eastern Standard Time", "America/Nassau" }, + { "Eastern Standard Time", "America/New_York America/Detroit " + "America/Indiana/Petersburg America/Indiana/Vincennes " + "America/Indiana/Winamac America/Kentucky/Monticello America/Louisville" }, + { "Eastern Standard Time", "America/New_York" }, + { "Eastern Standard Time", "America/Toronto America/Iqaluit America/Montreal " + "America/Nipigon America/Pangnirtung America/Thunder_Bay" }, + { "Eastern Standard Time", "EST5EDT" }, + { "Egypt Standard Time", "Africa/Cairo" }, + { "Egypt Standard Time", "Asia/Gaza Asia/Hebron" }, + { "Ekaterinburg Standard Time", "Asia/Yekaterinburg" }, + { "Fiji Standard Time", "Pacific/Fiji" }, + { "FLE Standard Time", "Europe/Helsinki" }, + { "FLE Standard Time", "Europe/Kiev Europe/Simferopol Europe/Uzhgorod Europe/Zaporozhye" }, + { "FLE Standard Time", "Europe/Kiev" }, + { "FLE Standard Time", "Europe/Mariehamn" }, + { "FLE Standard Time", "Europe/Riga" }, + { "FLE Standard Time", "Europe/Sofia" }, + { "FLE Standard Time", "Europe/Tallinn" }, + { "FLE Standard Time", "Europe/Vilnius" }, + { "Georgian Standard Time", "Asia/Tbilisi" }, + { "GMT Standard Time", "Atlantic/Canary" }, + { "GMT Standard Time", "Atlantic/Faeroe" }, + { "GMT Standard Time", "Europe/Dublin" }, + { "GMT Standard Time", "Europe/Guernsey" }, + { "GMT Standard Time", "Europe/Isle_of_Man" }, + { "GMT Standard Time", "Europe/Jersey" }, + { "GMT Standard Time", "Europe/Lisbon Atlantic/Madeira" }, + { "GMT Standard Time", "Europe/London" }, + { "Greenland Standard Time", "America/Godthab" }, + { "Greenwich Standard Time", "Africa/Abidjan" }, + { "Greenwich Standard Time", "Africa/Accra" }, + { "Greenwich Standard Time", "Africa/Bamako" }, + { "Greenwich Standard Time", "Africa/Banjul" }, + { "Greenwich Standard Time", "Africa/Bissau" }, + { "Greenwich Standard Time", "Africa/Conakry" }, + { "Greenwich Standard Time", "Africa/Dakar" }, + { "Greenwich Standard Time", "Africa/El_Aaiun" }, + { "Greenwich Standard Time", "Africa/Freetown" }, + { "Greenwich Standard Time", "Africa/Lome" }, + { "Greenwich Standard Time", "Africa/Monrovia" }, + { "Greenwich Standard Time", "Africa/Nouakchott" }, + { "Greenwich Standard Time", "Africa/Ouagadougou" }, + { "Greenwich Standard Time", "Africa/Sao_Tome" }, + { "Greenwich Standard Time", "Atlantic/Reykjavik" }, + { "Greenwich Standard Time", "Atlantic/St_Helena" }, + { "GTB Standard Time", "Europe/Athens" }, + { "GTB Standard Time", "Europe/Bucharest" }, + { "GTB Standard Time", "Europe/Chisinau" }, + { "GTB Standard Time", "Europe/Istanbul" }, + { "Hawaiian Standard Time", "Etc/GMT+10" }, + { "Hawaiian Standard Time", "Pacific/Fakaofo" }, + { "Hawaiian Standard Time", "Pacific/Honolulu" }, + { "Hawaiian Standard Time", "Pacific/Johnston" }, + { "Hawaiian Standard Time", "Pacific/Rarotonga" }, + { "Hawaiian Standard Time", "Pacific/Tahiti" }, + { "India Standard Time", "Asia/Calcutta Asia/Kolkata" }, + { "Iran Standard Time", "Asia/Tehran" }, + { "Israel Standard Time", "Asia/Jerusalem" }, + { "Jordan Standard Time", "Asia/Amman" }, + { "Kaliningrad Standard Time", "Europe/Kaliningrad" }, + { "Kaliningrad Standard Time", "Europe/Minsk" }, + { "Korea Standard Time", "Asia/Pyongyang" }, + { "Korea Standard Time", "Asia/Seoul" }, + { "Magadan Standard Time", "Asia/Magadan Asia/Anadyr Asia/Kamchatka" }, + { "Magadan Standard Time", "Asia/Magadan" }, + { "Mauritius Standard Time", "Indian/Mahe" }, + { "Mauritius Standard Time", "Indian/Mauritius" }, + { "Mauritius Standard Time", "Indian/Reunion" }, + { "Middle East Standard Time", "Asia/Beirut" }, + { "Montevideo Standard Time", "America/Montevideo" }, + { "Morocco Standard Time", "Africa/Casablanca" }, + { "Mountain Standard Time (Mexico)", "America/Chihuahua America/Mazatlan" }, + { "Mountain Standard Time (Mexico)", "America/Chihuahua" }, + { "Mountain Standard Time", "America/Denver America/Boise America/Shiprock" }, + { "Mountain Standard Time", "America/Denver" }, + { "Mountain Standard Time", "America/Edmonton " + "America/Cambridge_Bay America/Inuvik America/Yellowknife" }, + { "Mountain Standard Time", "America/Ojinaga" }, + { "Mountain Standard Time", "MST7MDT" }, + { "Myanmar Standard Time", "Asia/Rangoon" }, + { "Myanmar Standard Time", "Indian/Cocos" }, + { "N. Central Asia Standard Time", "Asia/Novosibirsk Asia/Novokuznetsk Asia/Omsk" }, + { "N. Central Asia Standard Time", "Asia/Novosibirsk" }, + { "Namibia Standard Time", "Africa/Windhoek" }, + { "Nepal Standard Time", "Asia/Katmandu Asia/Kathmandu" }, + { "New Zealand Standard Time", "Antarctica/South_Pole Antarctica/McMurdo" }, + { "New Zealand Standard Time", "Pacific/Auckland" }, + { "Newfoundland Standard Time", "America/St_Johns" }, + { "North Asia East Standard Time", "Asia/Irkutsk" }, + { "North Asia Standard Time", "Asia/Krasnoyarsk" }, + { "Pacific SA Standard Time", "America/Santiago" }, + { "Pacific SA Standard Time", "Antarctica/Palmer" }, + { "Pacific Standard Time (Mexico)", "America/Santa_Isabel" }, + { "Pacific Standard Time", "America/Los_Angeles" }, + { "Pacific Standard Time", "America/Tijuana America/Ensenada" }, + { "Pacific Standard Time", "America/Vancouver America/Dawson America/Whitehorse" }, + { "Pacific Standard Time", "PST8PDT" }, + { "Pakistan Standard Time", "Asia/Karachi" }, + { "Paraguay Standard Time", "America/Asuncion" }, + { "Romance Standard Time", "Europe/Brussels" }, + { "Romance Standard Time", "Europe/Copenhagen" }, + { "Romance Standard Time", "Europe/Madrid Africa/Ceuta" }, + { "Romance Standard Time", "Europe/Paris" }, + { "Russian Standard Time", "Europe/Moscow Europe/Samara Europe/Volgograd" }, + { "Russian Standard Time", "Europe/Moscow" }, + { "SA Eastern Standard Time", "America/Cayenne" }, + { "SA Eastern Standard Time", "America/Fortaleza America/Araguaina " + "America/Belem America/Maceio America/Recife America/Santarem" }, + { "SA Eastern Standard Time", "America/Paramaribo" }, + { "SA Eastern Standard Time", "Antarctica/Rothera" }, + { "SA Eastern Standard Time", "Etc/GMT+3" }, + { "SA Pacific Standard Time", "America/Bogota" }, + { "SA Pacific Standard Time", "America/Cayman" }, + { "SA Pacific Standard Time", "America/Coral_Harbour" }, + { "SA Pacific Standard Time", "America/Guayaquil" }, + { "SA Pacific Standard Time", "America/Jamaica" }, + { "SA Pacific Standard Time", "America/Lima" }, + { "SA Pacific Standard Time", "America/Panama" }, + { "SA Pacific Standard Time", "America/Port-au-Prince" }, + { "SA Pacific Standard Time", "Etc/GMT+5" }, + { "SA Western Standard Time", "America/Anguilla" }, + { "SA Western Standard Time", "America/Antigua" }, + { "SA Western Standard Time", "America/Aruba" }, + { "SA Western Standard Time", "America/Barbados" }, + { "SA Western Standard Time", "America/Blanc-Sablon" }, + { "SA Western Standard Time", "America/Curacao" }, + { "SA Western Standard Time", "America/Dominica" }, + { "SA Western Standard Time", "America/Grenada" }, + { "SA Western Standard Time", "America/Guadeloupe" }, + { "SA Western Standard Time", "America/Guyana" }, + { "SA Western Standard Time", "America/La_Paz" }, + { "SA Western Standard Time", "America/Manaus America/Boa_Vista " + "America/Eirunepe America/Porto_Velho America/Rio_Branco" }, + { "SA Western Standard Time", "America/Marigot" }, + { "SA Western Standard Time", "America/Martinique" }, + { "SA Western Standard Time", "America/Montserrat" }, + { "SA Western Standard Time", "America/Port_of_Spain" }, + { "SA Western Standard Time", "America/Puerto_Rico" }, + { "SA Western Standard Time", "America/Santo_Domingo" }, + { "SA Western Standard Time", "America/St_Barthelemy" }, + { "SA Western Standard Time", "America/St_Kitts" }, + { "SA Western Standard Time", "America/St_Lucia" }, + { "SA Western Standard Time", "America/St_Thomas" }, + { "SA Western Standard Time", "America/St_Vincent" }, + { "SA Western Standard Time", "America/Tortola" }, + { "SA Western Standard Time", "Etc/GMT+4" }, + { "Samoa Standard Time", "Pacific/Apia Pacific/Samoa" }, + { "SE Asia Standard Time", "Antarctica/Davis" }, + { "SE Asia Standard Time", "Asia/Bangkok" }, + { "SE Asia Standard Time", "Asia/Hovd" }, + { "SE Asia Standard Time", "Asia/Jakarta Asia/Pontianak" }, + { "SE Asia Standard Time", "Asia/Phnom_Penh" }, + { "SE Asia Standard Time", "Asia/Saigon Asia/Ho_Chi_Minh" }, + { "SE Asia Standard Time", "Asia/Vientiane" }, + { "SE Asia Standard Time", "Etc/GMT-7" }, + { "SE Asia Standard Time", "Indian/Christmas" }, + { "Singapore Standard Time", "Asia/Brunei" }, + { "Singapore Standard Time", "Asia/Kuala_Lumpur Asia/Kuching" }, + { "Singapore Standard Time", "Asia/Makassar" }, + { "Singapore Standard Time", "Asia/Manila" }, + { "Singapore Standard Time", "Asia/Singapore" }, + { "Singapore Standard Time", "Etc/GMT-8" }, + { "South Africa Standard Time", "Africa/Blantyre" }, + { "South Africa Standard Time", "Africa/Bujumbura" }, + { "South Africa Standard Time", "Africa/Gaborone" }, + { "South Africa Standard Time", "Africa/Harare" }, + { "South Africa Standard Time", "Africa/Johannesburg" }, + { "South Africa Standard Time", "Africa/Kigali" }, + { "South Africa Standard Time", "Africa/Lubumbashi" }, + { "South Africa Standard Time", "Africa/Lusaka" }, + { "South Africa Standard Time", "Africa/Maputo" }, + { "South Africa Standard Time", "Africa/Maseru" }, + { "South Africa Standard Time", "Africa/Mbabane" }, + { "South Africa Standard Time", "Africa/Tripoli" }, + { "South Africa Standard Time", "Etc/GMT-2" }, + { "Sri Lanka Standard Time", "Asia/Colombo" }, + { "Syria Standard Time", "Asia/Damascus" }, + { "Taipei Standard Time", "Asia/Taipei" }, + { "Tasmania Standard Time", "Australia/Hobart Australia/Currie" }, + { "Tasmania Standard Time", "Australia/Hobart" }, + { "Tokyo Standard Time", "Asia/Dili" }, + { "Tokyo Standard Time", "Asia/Jayapura" }, + { "Tokyo Standard Time", "Asia/Tokyo" }, + { "Tokyo Standard Time", "Etc/GMT-9" }, + { "Tokyo Standard Time", "Pacific/Palau" }, + { "Tonga Standard Time", "Etc/GMT-13" }, + { "Tonga Standard Time", "Pacific/Enderbury" }, + { "Tonga Standard Time", "Pacific/Tongatapu" }, + /* { "Turkey Standard Time", "Europe/Istanbul" }, */ + { "Ulaanbaatar Standard Time", "Asia/Ulaanbaatar Asia/Choibalsan" }, + { "Ulaanbaatar Standard Time", "Asia/Ulaanbaatar" }, + { "US Eastern Standard Time", "America/Indianapolis " + "America/Indiana/Marengo America/Indiana/Vevay" }, + { "US Eastern Standard Time", "America/Indianapolis" }, + { "US Mountain Standard Time", "America/Dawson_Creek" }, + { "US Mountain Standard Time", "America/Hermosillo" }, + { "US Mountain Standard Time", "America/Phoenix" }, + { "US Mountain Standard Time", "Etc/GMT+7" }, + { "UTC", "America/Danmarkshavn" }, + { "UTC", "Etc/GMT" }, + { "UTC+12", "Etc/GMT-12" }, + { "UTC+12", "Pacific/Funafuti" }, + { "UTC+12", "Pacific/Majuro Pacific/Kwajalein" }, + { "UTC+12", "Pacific/Nauru" }, + { "UTC+12", "Pacific/Tarawa" }, + { "UTC+12", "Pacific/Wake" }, + { "UTC+12", "Pacific/Wallis" }, + { "UTC-02", "America/Noronha" }, + { "UTC-02", "Atlantic/South_Georgia" }, + { "UTC-02", "Etc/GMT+2" }, + { "UTC-11", "Etc/GMT+11" }, + { "UTC-11", "Pacific/Midway" }, + { "UTC-11", "Pacific/Niue" }, + { "UTC-11", "Pacific/Pago_Pago" }, + { "Venezuela Standard Time", "America/Caracas" }, + { "Vladivostok Standard Time", "Asia/Vladivostok Asia/Sakhalin" }, + { "Vladivostok Standard Time", "Asia/Vladivostok" }, + { "W. Australia Standard Time", "Antarctica/Casey" }, + { "W. Australia Standard Time", "Australia/Perth" }, + { "W. Central Africa Standard Time", "Africa/Algiers" }, + { "W. Central Africa Standard Time", "Africa/Bangui" }, + { "W. Central Africa Standard Time", "Africa/Brazzaville" }, + { "W. Central Africa Standard Time", "Africa/Douala" }, + { "W. Central Africa Standard Time", "Africa/Kinshasa" }, + { "W. Central Africa Standard Time", "Africa/Lagos" }, + { "W. Central Africa Standard Time", "Africa/Libreville" }, + { "W. Central Africa Standard Time", "Africa/Luanda" }, + { "W. Central Africa Standard Time", "Africa/Malabo" }, + { "W. Central Africa Standard Time", "Africa/Ndjamena" }, + { "W. Central Africa Standard Time", "Africa/Niamey" }, + { "W. Central Africa Standard Time", "Africa/Porto-Novo" }, + { "W. Central Africa Standard Time", "Africa/Tunis" }, + { "W. Central Africa Standard Time", "Etc/GMT-1" }, + { "W. Europe Standard Time", "Arctic/Longyearbyen" }, + { "W. Europe Standard Time", "Europe/Amsterdam" }, + { "W. Europe Standard Time", "Europe/Andorra" }, + { "W. Europe Standard Time", "Europe/Berlin" }, + { "W. Europe Standard Time", "Europe/Gibraltar" }, + { "W. Europe Standard Time", "Europe/Luxembourg" }, + { "W. Europe Standard Time", "Europe/Malta" }, + { "W. Europe Standard Time", "Europe/Monaco" }, + { "W. Europe Standard Time", "Europe/Oslo" }, + { "W. Europe Standard Time", "Europe/Rome" }, + { "W. Europe Standard Time", "Europe/San_Marino" }, + { "W. Europe Standard Time", "Europe/Stockholm" }, + { "W. Europe Standard Time", "Europe/Vaduz" }, + { "W. Europe Standard Time", "Europe/Vatican" }, + { "W. Europe Standard Time", "Europe/Vienna" }, + { "W. Europe Standard Time", "Europe/Zurich" }, + { "West Asia Standard Time", "Antarctica/Mawson" }, + { "West Asia Standard Time", "Asia/Ashgabat" }, + { "West Asia Standard Time", "Asia/Dushanbe" }, + { "West Asia Standard Time", "Asia/Oral Asia/Aqtau Asia/Aqtobe" }, + { "West Asia Standard Time", "Asia/Tashkent Asia/Samarkand" }, + { "West Asia Standard Time", "Asia/Tashkent" }, + { "West Asia Standard Time", "Etc/GMT-5" }, + { "West Asia Standard Time", "Indian/Kerguelen" }, + { "West Asia Standard Time", "Indian/Maldives" }, + { "West Pacific Standard Time", "Antarctica/DumontDUrville" }, + { "West Pacific Standard Time", "Etc/GMT-10" }, + { "West Pacific Standard Time", "Pacific/Guam" }, + { "West Pacific Standard Time", "Pacific/Port_Moresby" }, + { "West Pacific Standard Time", "Pacific/Saipan" }, + { "West Pacific Standard Time", "Pacific/Truk" }, + { "Yakutsk Standard Time", "Asia/Yakutsk" } +}; + +static UINT64 winpr_windows_gmtime() +{ + time_t unix_time; + UINT64 windows_time; + + time(&unix_time); + windows_time = unix_time; + windows_time *= 10000000; + windows_time += 621355968000000000ULL; + + return windows_time; +} + +static char* winpr_read_unix_timezone_identifier_from_file(FILE* fp) +{ + long length; + char* tzid = NULL; + + if (fseek(fp, 0, SEEK_END) != 0) + return NULL; + length = ftell(fp); + if (fseek(fp, 0, SEEK_SET) != 0) + return NULL; + + if (length < 2) + return NULL; + + tzid = (char*) malloc(length + 1); + if (!tzid) + return NULL; + + if (fread(tzid, length, 1, fp) != 1) + { + free(tzid); + return NULL; + } + + tzid[length] = '\0'; + if (tzid[length - 1] == '\n') + tzid[length - 1] = '\0'; + + return tzid; +} + +static char* winpr_get_timezone_from_link(void) +{ + const char* links[] = + { + "/etc/localtime", + "/etc/TZ" + }; + size_t x; + ssize_t len; + char buf[1024]; + char* tzid = NULL; + + /* + * On linux distros such as Redhat or Archlinux, a symlink at /etc/localtime + * will point to /usr/share/zoneinfo/region/place where region/place could be + * America/Montreal for example. + * Some distributions do have to symlink at /etc/TZ. + */ + + for (x=0; xBias = bias; + return timezone; + } + } + } + + WLog_ERR(TAG, "Unable to find a match for unix timezone: %s", tzid); + free(tzid); + return NULL; +} + +static TIME_ZONE_RULE_ENTRY* winpr_get_current_time_zone_rule(TIME_ZONE_RULE_ENTRY* rules, UINT32 count) +{ + int i; + UINT64 windows_time; + + windows_time = winpr_windows_gmtime(); + + for (i = 0; i < (int) count; i++) + { + if ((rules[i].TicksStart >= windows_time) && (windows_time >= rules[i].TicksEnd)) + { + /*WLog_ERR(TAG, "Got rule %d from table at %p with count %u", i, rules, count);*/ + return &rules[i]; + } + } + + WLog_ERR(TAG, "Unable to get current timezone rule"); + return NULL; +} + DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) { - return 0; + time_t t; + struct tm* local_time; + TIME_ZONE_ENTRY* dtz; + LPTIME_ZONE_INFORMATION tz = lpTimeZoneInformation; + + lpTimeZoneInformation->StandardBias = 0; + + time(&t); + local_time = localtime(&t); + + memset(tz, 0, sizeof(TIME_ZONE_INFORMATION)); + +#ifdef HAVE_TM_GMTOFF + #if defined(__FreeBSD__) || defined(__OpenBSD__) + if (local_time->tm_gmtoff >= 0) + tz->Bias = (UINT32) (local_time->tm_gmtoff / 60); + else + tz->Bias = (UINT32) (1440 + (INT32) (local_time->tm_gmtoff / 60)); + #else + tz->Bias = (UINT32) (local_time->tm_gmtoff / 60); + #endif +#else + tz->Bias = 0; +#endif + WLog_DBG(TAG, "tzname[std]: %s, tzname[dst]: %s, timezone: %ld, Daylight: %d", + tzname[0], tzname[1], timezone, daylight); + + dtz = winpr_detect_windows_time_zone(tz->Bias); + + if (dtz!= NULL) + { + WLog_DBG(TAG, "tz: Bias=%d sn='%s' dln='%s'", + dtz->Bias, dtz->StandardName, dtz->DaylightName); + + tz->Bias = dtz->Bias; + tz->StandardBias = dtz->Bias; + tz->DaylightBias = dtz->Bias; + + ConvertToUnicode(CP_UTF8, 0, dtz->StandardName, sizeof(dtz->StandardName), + (WCHAR**)&tz->StandardName, sizeof(tz->StandardName)/sizeof(WCHAR)); + ConvertToUnicode(CP_UTF8, 0, dtz->DaylightName, sizeof(dtz->DaylightName), + (WCHAR**)&tz->DaylightName, sizeof(tz->DaylightName)/sizeof(WCHAR)); + + if ((dtz->SupportsDST) && (dtz->RuleTableCount > 0)) + { + TIME_ZONE_RULE_ENTRY* rule; + rule = winpr_get_current_time_zone_rule(dtz->RuleTable, dtz->RuleTableCount); + + if (rule != NULL) + { + tz->DaylightBias = -rule->DaylightDelta; + + tz->StandardDate = rule->StandardDate; + tz->DaylightDate = rule->DaylightDate; + } + } + free(dtz); + + /* 1 ... TIME_ZONE_ID_STANDARD + * 2 ... TIME_ZONE_ID_DAYLIGHT */ + return local_time->tm_isdst ? 2 : 1; + } + else + { + /* could not detect timezone, fallback to using GMT */ + WLog_DBG(TAG, "tz not found, using GMT."); + memcpy(tz->StandardName, L"GMT Standard Time", sizeof(tz->StandardName)); + memcpy(tz->DaylightName, L"GMT Daylight Time", sizeof(tz->DaylightName)); + return 0; /* TIME_ZONE_ID_UNKNOWN */ + } } BOOL SetTimeZoneInformation(const TIME_ZONE_INFORMATION* lpTimeZoneInformation) diff --git a/winpr/libwinpr/utils/image.c b/winpr/libwinpr/utils/image.c index ea8bc97..ece3867 100644 --- a/winpr/libwinpr/utils/image.c +++ b/winpr/libwinpr/utils/image.c @@ -3,6 +3,8 @@ * Image Utils * * Copyright 2014 Marc-Andre Moreau + * Copyright 2016 Inuvika Inc. + * Copyright 2016 David PHAM-VAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -308,7 +310,7 @@ int winpr_image_read(wImage* image, const char* filename) BYTE sig[8]; int status = -1; - fp = fopen(filename, "r+b"); + fp = fopen(filename, "rb"); if (!fp) { diff --git a/winpr/libwinpr/utils/lodepng/lodepng.c b/winpr/libwinpr/utils/lodepng/lodepng.c index a970f00..61f5ce3 100644 --- a/winpr/libwinpr/utils/lodepng/lodepng.c +++ b/winpr/libwinpr/utils/lodepng/lodepng.c @@ -2208,6 +2208,12 @@ unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsig *out = outv.data; *outsize = outv.size; } + else + { + *out = NULL; + *outsize = 0; + ucvector_cleanup(&outv); + } return error; } diff --git a/winpr/libwinpr/utils/ntlm.c b/winpr/libwinpr/utils/ntlm.c index 709d4d8..be1deae 100644 --- a/winpr/libwinpr/utils/ntlm.c +++ b/winpr/libwinpr/utils/ntlm.c @@ -42,9 +42,12 @@ BYTE* NTOWFv1W(LPWSTR Password, UINT32 PasswordLength, BYTE* NtHash) if (!NtHash && !(NtHash = malloc(16))) return NULL; - winpr_MD4_Init(&md4); - winpr_MD4_Update(&md4, (BYTE*) Password, (size_t) PasswordLength); - winpr_MD4_Final(&md4, NtHash); + if (!winpr_MD4_Init(&md4)) + return NULL; + if (!winpr_MD4_Update(&md4, (BYTE*) Password, (size_t) PasswordLength)) + return NULL; + if (!winpr_MD4_Final(&md4, NtHash, WINPR_MD4_DIGEST_LENGTH)) + return NULL; return NtHash; } @@ -77,11 +80,12 @@ BYTE* NTOWFv2W(LPWSTR Password, UINT32 PasswordLength, LPWSTR User, { BYTE* buffer; BYTE NtHashV1[16]; + BYTE* result = NtHash; if ((!User) || (!Password)) return NULL; - if (!NtHash && !(NtHash = (BYTE*) malloc(16))) + if (!NtHash && !(NtHash = (BYTE*) malloc(WINPR_MD4_DIGEST_LENGTH))) return NULL; if (!NTOWFv1W(Password, PasswordLength, NtHashV1)) @@ -103,11 +107,12 @@ BYTE* NTOWFv2W(LPWSTR Password, UINT32 PasswordLength, LPWSTR User, CopyMemory(&buffer[UserLength], Domain, DomainLength); /* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is the NTLMv2 hash */ - winpr_HMAC(WINPR_MD_MD5, NtHashV1, 16, buffer, UserLength + DomainLength, NtHash); + if (!winpr_HMAC(WINPR_MD_MD5, NtHashV1, 16, buffer, UserLength + DomainLength, NtHash, WINPR_MD4_DIGEST_LENGTH)) + result = NULL; free(buffer); - return NtHash; + return result; } BYTE* NTOWFv2A(LPSTR Password, UINT32 PasswordLength, LPSTR User, @@ -141,11 +146,12 @@ out_fail: BYTE* NTOWFv2FromHashW(BYTE* NtHashV1, LPWSTR User, UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength, BYTE* NtHash) { BYTE* buffer; + BYTE* result = NtHash; if (!User) return NULL; - if (!NtHash && !(NtHash = (BYTE*) malloc(16))) + if (!NtHash && !(NtHash = (BYTE*) malloc(WINPR_MD4_DIGEST_LENGTH))) return NULL; if (!(buffer = (BYTE*) malloc(UserLength + DomainLength))) @@ -165,11 +171,12 @@ BYTE* NTOWFv2FromHashW(BYTE* NtHashV1, LPWSTR User, UINT32 UserLength, LPWSTR Do } /* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is the NTLMv2 hash */ - winpr_HMAC(WINPR_MD_MD5, NtHashV1, 16, buffer, UserLength + DomainLength, NtHash); + if (!winpr_HMAC(WINPR_MD_MD5, NtHashV1, 16, buffer, UserLength + DomainLength, NtHash, WINPR_MD4_DIGEST_LENGTH)) + result = NULL; free(buffer); - return NtHash; + return result; } BYTE* NTOWFv2FromHashA(BYTE* NtHashV1, LPSTR User, UINT32 UserLength, LPSTR Domain, UINT32 DomainLength, BYTE* NtHash) diff --git a/winpr/libwinpr/utils/test/TestVersion.c b/winpr/libwinpr/utils/test/TestVersion.c index cef5728..60c4f90 100644 --- a/winpr/libwinpr/utils/test/TestVersion.c +++ b/winpr/libwinpr/utils/test/TestVersion.c @@ -36,6 +36,10 @@ int TestVersion(int argc, char* argv[]) if (!build) return -1; + build = winpr_get_build_config(); + if (!build) + return -1; + return 0; } diff --git a/winpr/libwinpr/utils/winpr.c b/winpr/libwinpr/utils/winpr.c index e6dbd90..4093689 100644 --- a/winpr/libwinpr/utils/winpr.c +++ b/winpr/libwinpr/utils/winpr.c @@ -22,6 +22,8 @@ #include "config.h" #endif +#include "buildflags.h" + #include #include #include @@ -46,9 +48,7 @@ const char* winpr_get_version_string(void) const char* winpr_get_build_date(void) { - static char build_date[64]; - - sprintf_s(build_date, sizeof(build_date), "%s %s", __DATE__, __TIME__); + static char build_date[] = __DATE__ " " __TIME__; return build_date; } @@ -58,3 +58,14 @@ const char* winpr_get_build_revision(void) return GIT_REVISION; } +const char* winpr_get_build_config(void) +{ + static const char build_config[] = + "Build configuration: " BUILD_CONFIG "\n" + "Build type: " BUILD_TYPE "\n" + "CFLAGS: " CFLAGS "\n" + "Compiler: " COMPILER_ID ", " COMPILER_VERSION "\n" + "Target architecture: " TARGET_ARCH "\n"; + + return build_config; +} diff --git a/winpr/libwinpr/utils/wlog/BinaryAppender.h b/winpr/libwinpr/utils/wlog/BinaryAppender.h index 22f1075..31a9341 100644 --- a/winpr/libwinpr/utils/wlog/BinaryAppender.h +++ b/winpr/libwinpr/utils/wlog/BinaryAppender.h @@ -22,6 +22,6 @@ #include "wlog.h" -WINPR_API wLogAppender* WLog_BinaryAppender_New(wLog* log); +wLogAppender* WLog_BinaryAppender_New(wLog* log); #endif /* WINPR_WLOG_BINARY_APPENDER_PRIVATE_H */ diff --git a/winpr/libwinpr/utils/wlog/ConsoleAppender.c b/winpr/libwinpr/utils/wlog/ConsoleAppender.c index a150ae6..5b57143 100644 --- a/winpr/libwinpr/utils/wlog/ConsoleAppender.c +++ b/winpr/libwinpr/utils/wlog/ConsoleAppender.c @@ -146,6 +146,9 @@ static int g_DataId = 0; static BOOL WLog_ConsoleAppender_WriteDataMessage(wLog* log, wLogAppender* appender, wLogMessage* message) { +#if defined(ANDROID) + return FALSE; +#else int DataId; char* FullFileName; @@ -157,12 +160,16 @@ static BOOL WLog_ConsoleAppender_WriteDataMessage(wLog* log, wLogAppender* appen free(FullFileName); return TRUE; +#endif } static int g_ImageId = 0; static BOOL WLog_ConsoleAppender_WriteImageMessage(wLog* log, wLogAppender* appender, wLogMessage* message) { +#if defined(ANDROID) + return FALSE; +#else int ImageId; char* FullFileName; @@ -175,12 +182,16 @@ static BOOL WLog_ConsoleAppender_WriteImageMessage(wLog* log, wLogAppender* appe free(FullFileName); return TRUE; +#endif } static int g_PacketId = 0; static BOOL WLog_ConsoleAppender_WritePacketMessage(wLog* log, wLogAppender* appender, wLogMessage* message) { +#if defined(ANDROID) + return FALSE; +#else int PacketId; char* FullFileName; @@ -198,6 +209,7 @@ static BOOL WLog_ConsoleAppender_WritePacketMessage(wLog* log, wLogAppender* app message->PacketData, message->PacketLength, message->PacketFlags); return TRUE; +#endif } static BOOL WLog_ConsoleAppender_Set(wLogAppender* appender, const char *setting, void *value) { diff --git a/winpr/libwinpr/utils/wlog/FileAppender.c b/winpr/libwinpr/utils/wlog/FileAppender.c index 5768416..8c92128 100644 --- a/winpr/libwinpr/utils/wlog/FileAppender.c +++ b/winpr/libwinpr/utils/wlog/FileAppender.c @@ -172,7 +172,7 @@ static BOOL WLog_FileAppender_WriteDataMessage(wLog* log, wLogAppender* appender static int g_ImageId = 0; -static int WLog_FileAppender_WriteImageMessage(wLog* log, wLogAppender* appender, wLogMessage* message) +static BOOL WLog_FileAppender_WriteImageMessage(wLog* log, wLogAppender* appender, wLogMessage* message) { int ImageId; char* FullFileName; diff --git a/winpr/libwinpr/utils/wlog/wlog.c b/winpr/libwinpr/utils/wlog/wlog.c index 5526e69..e00421e 100644 --- a/winpr/libwinpr/utils/wlog/wlog.c +++ b/winpr/libwinpr/utils/wlog/wlog.c @@ -55,7 +55,7 @@ typedef struct _wLogFilter wLogFilter; * http://docs.python.org/2/library/logging.html */ -const char* WLOG_LEVELS[7] = +LPCSTR WLOG_LEVELS[7] = { "TRACE", "DEBUG", @@ -69,13 +69,16 @@ const char* WLOG_LEVELS[7] = static DWORD g_FilterCount = 0; static wLogFilter* g_Filters = NULL; -static BOOL log_recursion(const char* file, const char* fkt, int line) +static int WLog_ParseLogLevel(LPCSTR level); +static BOOL WLog_ParseFilter(wLogFilter* filter, LPCSTR name); + +static BOOL log_recursion(LPCSTR file, LPCSTR fkt, int line) { char** msg; size_t used, i; void* bt = winpr_backtrace(20); #if defined(ANDROID) - const char* tag = WINPR_TAG("utils.wlog"); + LPCSTR tag = WINPR_TAG("utils.wlog"); #endif if (!bt) @@ -302,6 +305,88 @@ DWORD WLog_GetLogLevel(wLog* log) } } +BOOL WLog_SetStringLogLevel(wLog* log, LPCSTR level) +{ + int lvl; + if (!log || !level) + return FALSE; + + lvl = WLog_ParseLogLevel(level); + if (lvl < 0) + return FALSE; + + return WLog_SetLogLevel(log, lvl); +} + +BOOL WLog_AddStringLogFilters(LPCSTR filter) +{ + DWORD pos; + DWORD size; + DWORD count; + LPSTR p; + LPSTR filterStr; + LPSTR cp; + wLogFilter* tmp; + + if (!filter) + return FALSE; + + count = 1; + p = (LPSTR)filter; + + while ((p = strchr(p, ',')) != NULL) + { + count++; + p++; + } + + pos = g_FilterCount; + size = g_FilterCount + count; + tmp = (wLogFilter*) realloc(g_Filters, size * sizeof(wLogFilter)); + + if (!tmp) + return FALSE; + + g_Filters = tmp; + + cp = (LPSTR)_strdup(filter); + if (!cp) + return FALSE; + + p = cp; + filterStr = cp; + + do + { + p = strchr(p, ','); + if (p) + *p = '\0'; + + if (pos < size) + { + if (!WLog_ParseFilter(&g_Filters[pos++], filterStr)) + { + free (cp); + return FALSE; + } + } + else + break; + + if (p) + { + filterStr = p + 1; + p++; + } + } + while (p != NULL); + + g_FilterCount = size; + free (cp); + + return TRUE; +} + BOOL WLog_SetLogLevel(wLog* log, DWORD logLevel) { if (!log) @@ -316,7 +401,7 @@ BOOL WLog_SetLogLevel(wLog* log, DWORD logLevel) return TRUE; } -int WLog_ParseLogLevel(const char* level) +int WLog_ParseLogLevel(LPCSTR level) { int iLevel = -1; @@ -418,12 +503,12 @@ BOOL WLog_ParseFilter(wLogFilter* filter, LPCSTR name) BOOL WLog_ParseFilters() { - char* p; + BOOL res; char* env; - DWORD count; DWORD nSize; - int status; - LPCSTR* strs; + + g_Filters = NULL; + g_FilterCount = 0; nSize = GetEnvironmentVariableA("WLOG_FILTER", NULL, 0); @@ -438,62 +523,11 @@ BOOL WLog_ParseFilters() if (!GetEnvironmentVariableA("WLOG_FILTER", env, nSize)) return FALSE; - count = 1; - p = env; + res = WLog_AddStringLogFilters(env); - while ((p = strchr(p, ',')) != NULL) - { - count++; - p++; - } - - g_FilterCount = count; - p = env; - - count = 0; - strs = (LPCSTR*) calloc(g_FilterCount, sizeof(LPCSTR)); - - if (!strs) - { - free(env); - return FALSE; - } - - strs[count++] = p; - - while ((p = strchr(p, ',')) != NULL) - { - if (count < g_FilterCount) - strs[count++] = p + 1; - *p = '\0'; - p++; - } - - g_Filters = calloc(g_FilterCount, sizeof(wLogFilter)); - - if (!g_Filters) - { - free(strs); - free(env); - return FALSE; - } - - for (count = 0; count < g_FilterCount; count++) - { - status = WLog_ParseFilter(&g_Filters[count], strs[count]); - - if (status < 0) - { - free(strs); - free(env); - return FALSE; - } - } - - free(strs); free(env); - return TRUE; + return res; } int WLog_GetFilterLogLevel(wLog* log) diff --git a/winpr/libwinpr/winsock/module.def b/winpr/libwinpr/winsock/module.def deleted file mode 100644 index e4d0419..0000000 --- a/winpr/libwinpr/winsock/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-winsock" -EXPORTS - diff --git a/winpr/libwinpr/wnd/module.def b/winpr/libwinpr/wnd/module.def deleted file mode 100644 index de91bf1..0000000 --- a/winpr/libwinpr/wnd/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-wnd" -EXPORTS - diff --git a/winpr/winpr.pc.in b/winpr/winpr.pc.in index 58dc08a..4c30637 100644 --- a/winpr/winpr.pc.in +++ b/winpr/winpr.pc.in @@ -1,7 +1,7 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=@CMAKE_INSTALL_FULL_LIBDIR@ -includedir=${libdir}/@WINPR_INCLUDE_DIR@ +includedir=${prefix}/@WINPR_INCLUDE_DIR@ libs=-lwinpr Name: WinPR