From 0b837fff17e2497a581559c01db2b3efd74de229 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Wed, 9 May 2018 21:47:06 +0200 Subject: [PATCH 01/11] New upstream version 2.0.0~git20180411.1.7a7b1802+dfsg1 --- .travis.yml | 54 + CMakeLists.txt | 181 +- ChangeLog | 3006 +++++++++++++++++ README | 6 +- channels/audin/client/alsa/audin_alsa.c | 8 +- channels/audin/client/audin_main.c | 284 +- .../audin/client/opensles/audin_opensl_es.c | 8 +- channels/audin/client/oss/audin_oss.c | 22 +- channels/audin/client/pulse/audin_pulse.c | 15 +- channels/audin/client/winmm/audin_winmm.c | 5 +- channels/audin/server/audin.c | 9 +- channels/cliprdr/client/cliprdr_format.c | 2 +- channels/cliprdr/client/cliprdr_main.c | 78 +- channels/cliprdr/server/cliprdr_main.c | 15 +- channels/disp/client/disp_main.c | 40 +- channels/drdynvc/client/drdynvc_main.c | 254 +- channels/drdynvc/server/drdynvc_main.c | 9 +- channels/drive/client/drive_file.c | 62 +- channels/drive/client/drive_file.h | 4 +- channels/drive/client/drive_main.c | 224 +- channels/echo/server/echo_main.c | 13 +- channels/encomsp/client/encomsp_main.c | 9 +- channels/encomsp/server/encomsp_main.c | 8 +- channels/geometry/CMakeLists.txt | 22 + channels/geometry/ChannelOptions.cmake | 11 + channels/geometry/client/CMakeLists.txt | 39 + channels/geometry/client/geometry_main.c | 481 +++ channels/geometry/client/geometry_main.h | 34 + channels/parallel/client/parallel_main.c | 18 +- channels/printer/client/printer_main.c | 9 +- channels/rail/client/rail_main.c | 166 +- channels/rail/client/rail_orders.c | 274 +- channels/rail/client/rail_orders.h | 19 +- channels/rail/rail_common.c | 11 +- channels/rdpdr/client/irp.c | 4 +- channels/rdpdr/client/rdpdr_main.c | 80 +- channels/rdpdr/server/rdpdr_main.c | 20 +- channels/rdpei/client/rdpei_main.c | 10 +- channels/rdpgfx/client/rdpgfx_codec.c | 7 +- channels/rdpgfx/client/rdpgfx_main.c | 106 +- channels/rdpgfx/server/rdpgfx_main.c | 39 +- channels/rdpsnd/client/mac/rdpsnd_mac.c | 23 +- channels/rdpsnd/client/oss/rdpsnd_oss.c | 45 +- channels/rdpsnd/client/pulse/rdpsnd_pulse.c | 9 + channels/rdpsnd/client/rdpsnd_main.c | 59 +- channels/rdpsnd/server/rdpsnd_main.c | 15 +- channels/remdesk/client/remdesk_main.c | 9 +- channels/remdesk/server/remdesk_main.c | 8 +- channels/serial/client/serial_main.c | 77 +- channels/smartcard/client/smartcard_main.c | 73 +- channels/smartcard/client/smartcard_main.h | 3 - .../smartcard/client/smartcard_operations.c | 171 +- channels/smartcard/client/smartcard_pack.c | 56 +- channels/smartcard/client/smartcard_pack.h | 4 +- channels/sshagent/CMakeLists.txt | 27 + channels/sshagent/ChannelOptions.cmake | 13 + channels/sshagent/client/CMakeLists.txt | 34 + channels/sshagent/client/sshagent_main.c | 408 +++ channels/sshagent/client/sshagent_main.h | 42 + channels/sshagent/server/CMakeLists.txt | 31 + channels/sshagent/server/sshagent_main.c | 422 +++ channels/tsmf/client/alsa/tsmf_alsa.c | 2 +- channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c | 200 +- channels/tsmf/client/gstreamer/tsmf_X11.c | 8 + .../tsmf/client/gstreamer/tsmf_gstreamer.c | 8 + channels/tsmf/client/oss/tsmf_oss.c | 2 +- channels/tsmf/client/pulse/tsmf_pulse.c | 2 +- channels/tsmf/client/tsmf_ifman.c | 2 +- channels/tsmf/client/tsmf_main.c | 2 +- channels/tsmf/client/tsmf_media.c | 16 +- .../urbdrc/client/libusb/libusb_udevice.c | 734 ++-- .../urbdrc/client/libusb/libusb_udevman.c | 132 +- channels/urbdrc/client/urbdrc_main.c | 692 ++-- channels/video/CMakeLists.txt | 22 + channels/video/ChannelOptions.cmake | 12 + channels/video/client/CMakeLists.txt | 39 + channels/video/client/video_main.c | 1168 +++++++ channels/video/client/video_main.h | 35 + ci/cmake-preloads/config-android.txt | 1 + ci/cmake-preloads/config-debian-squeeze.txt | 3 +- ci/cmake-preloads/config-ios.txt | 7 +- ci/cmake-preloads/config-linux-all.txt | 3 +- ci/cmake-preloads/config-macosx.txt | 1 + ci/cmake-preloads/config-ubuntu-1204.txt | 3 +- ci/cmake-preloads/config-windows.txt | 3 +- client/DirectFB/dfreerdp.c | 10 +- client/Sample/freerdp.c | 24 +- client/Wayland/wlf_channels.c | 12 +- client/Wayland/wlf_channels.h | 4 +- client/Wayland/wlf_input.c | 2 +- client/Wayland/wlfreerdp.1.in | 2 +- client/Wayland/wlfreerdp.c | 29 +- client/X11/CMakeLists.txt | 42 +- client/X11/generate_argument_docbook.c | 115 +- client/X11/xf_channels.c | 49 +- client/X11/xf_channels.h | 7 +- client/X11/xf_client.c | 267 +- client/X11/xf_cliprdr.c | 116 +- client/X11/xf_disp.c | 333 ++ client/X11/xf_disp.h | 36 + client/X11/xf_event.c | 333 +- client/X11/xf_gdi.c | 71 +- client/X11/xf_gfx.c | 66 +- client/X11/xf_graphics.c | 27 +- client/X11/xf_input.c | 21 +- client/X11/xf_keyboard.c | 12 +- client/X11/xf_monitor.c | 275 +- client/X11/xf_rail.c | 43 +- client/X11/xf_video.c | 110 + client/X11/xf_video.h | 34 + client/X11/xf_window.c | 197 +- client/X11/xf_window.h | 2 +- client/X11/xfreerdp-examples.1.xml | 6 + client/X11/xfreerdp.h | 27 +- client/common/client.c | 6 +- client/common/cmdline.c | 1064 +++--- client/common/cmdline.h | 184 + client/common/compatibility.c | 101 +- client/common/file.c | 296 +- client/common/test/TestClientCmdLine.c | 167 +- cmake/AutoVersioning.cmake | 55 - cmake/CheckCmakeCompat.cmake | 1 + cmake/ClangToolchain.cmake | 16 + cmake/ConfigOptions.cmake | 14 +- cmake/FindGSSAPI.cmake | 448 +++ cmake/FindGStreamer_1_0.cmake | 2 +- cmake/FindKRB5.cmake | 28 - cmake/FindOpenSSL.cmake | 8 + cmake/compat_3.7.0/FindICU.cmake | 349 ++ config.h.in | 74 +- docs/README.android | 2 +- docs/README.macOS | 7 + include/freerdp/channels/geometry.h | 64 + include/freerdp/channels/video.h | 118 + include/freerdp/client/cmdline.h | 19 +- include/freerdp/client/disp.h | 3 + include/freerdp/client/file.h | 3 + include/freerdp/client/geometry.h | 76 + include/freerdp/client/rdpgfx.h | 2 +- include/freerdp/client/sshagent.h | 87 + include/freerdp/client/video.h | 61 + include/freerdp/codec/color.h | 24 +- include/freerdp/codec/h264.h | 13 +- include/freerdp/codec/yuv.h | 48 + include/freerdp/crypto/ber.h | 46 +- include/freerdp/error.h | 42 +- include/freerdp/event.h | 19 + include/freerdp/gdi/gdi.h | 11 +- include/freerdp/gdi/region.h | 36 +- include/freerdp/gdi/video.h | 43 + include/freerdp/primitives.h | 1 + include/freerdp/settings.h | 31 +- include/freerdp/update.h | 44 +- include/freerdp/utils/pcap.h | 2 +- include/freerdp/utils/profiler.h | 33 +- libfreerdp/CMakeLists.txt | 56 +- libfreerdp/cache/glyph.c | 1 - libfreerdp/cache/offscreen.c | 5 +- libfreerdp/codec/bitmap.c | 14 +- libfreerdp/codec/clear.c | 10 +- libfreerdp/codec/color.c | 14 +- libfreerdp/codec/h264.c | 112 +- libfreerdp/codec/h264.h | 31 + libfreerdp/codec/h264_ffmpeg.c | 512 ++- libfreerdp/codec/h264_mf.c | 204 +- libfreerdp/codec/h264_openh264.c | 117 +- libfreerdp/codec/h264_x264.c | 2 +- libfreerdp/codec/interleaved.c | 8 +- libfreerdp/codec/ncrush.c | 337 +- libfreerdp/codec/nsc.c | 37 +- libfreerdp/codec/nsc_encode.c | 35 +- libfreerdp/codec/nsc_sse2.c | 15 +- libfreerdp/codec/nsc_types.h | 8 +- libfreerdp/codec/planar.c | 53 +- libfreerdp/codec/progressive.c | 38 +- libfreerdp/codec/rfx.c | 141 +- libfreerdp/codec/rfx_decode.c | 28 +- libfreerdp/codec/rfx_encode.c | 32 +- libfreerdp/codec/rfx_types.h | 30 +- .../codec/test/TestFreeRDPCodecNCrush.c | 38 +- .../codec/test/TestFreeRDPCodecPlanar.c | 9 +- .../codec/test/TestFreeRDPCodecProgressive.c | 13 +- libfreerdp/codec/test/TestFreeRDPCodecZGfx.c | 70 +- libfreerdp/codec/test/TestFreeRDPRegion.c | 1 + libfreerdp/codec/yuv.c | 182 + libfreerdp/codec/zgfx.c | 94 +- libfreerdp/common/addin.c | 13 +- libfreerdp/common/assistance.c | 211 +- libfreerdp/common/settings.c | 39 +- libfreerdp/core/CMakeLists.txt | 8 +- libfreerdp/core/capabilities.c | 66 +- libfreerdp/core/certificate.c | 175 +- libfreerdp/core/certificate.h | 12 - libfreerdp/core/channels.c | 1 + libfreerdp/core/client.c | 44 +- libfreerdp/core/client.h | 2 +- libfreerdp/core/connection.c | 19 + libfreerdp/core/errconnect.c | 36 + libfreerdp/core/fastpath.c | 108 +- libfreerdp/core/freerdp.c | 39 +- libfreerdp/core/gateway/http.c | 498 ++- libfreerdp/core/gateway/http.h | 16 +- libfreerdp/core/gateway/ncacn_http.c | 35 +- libfreerdp/core/gateway/ntlm.c | 86 +- libfreerdp/core/gateway/rdg.c | 407 ++- libfreerdp/core/gateway/rdg.h | 3 +- libfreerdp/core/gateway/rpc.c | 108 +- libfreerdp/core/gateway/rpc.h | 5 +- libfreerdp/core/gateway/rpc_client.c | 19 +- libfreerdp/core/gateway/rpc_fault.c | 59 +- libfreerdp/core/gateway/rpc_fault.h | 1 - libfreerdp/core/gateway/rts.c | 92 +- libfreerdp/core/gateway/rts.h | 74 - libfreerdp/core/gateway/rts_signature.c | 201 +- libfreerdp/core/gateway/tsg.c | 46 +- libfreerdp/core/gateway/tsg.h | 8 - libfreerdp/core/gcc.c | 43 +- libfreerdp/core/graphics.c | 7 - libfreerdp/core/info.c | 3 + libfreerdp/core/input.c | 72 +- libfreerdp/core/input.h | 30 - libfreerdp/core/license.c | 17 +- libfreerdp/core/listener.c | 37 +- libfreerdp/core/mcs.c | 20 +- libfreerdp/core/message.c | 30 +- libfreerdp/core/nego.c | 8 +- libfreerdp/core/nla.c | 842 ++++- libfreerdp/core/nla.h | 9 +- libfreerdp/core/orders.c | 73 +- libfreerdp/core/peer.c | 2 +- libfreerdp/core/proxy.c | 14 +- libfreerdp/core/rdp.c | 25 +- libfreerdp/core/security.c | 146 +- libfreerdp/core/settings.c | 4 + libfreerdp/core/surface.c | 185 +- libfreerdp/core/surface.h | 5 +- libfreerdp/core/tcp.c | 75 +- libfreerdp/core/test/TestConnect.c | 41 +- libfreerdp/core/tpdu.c | 4 +- libfreerdp/core/transport.c | 40 +- libfreerdp/core/update.c | 89 +- libfreerdp/core/update.h | 3 - libfreerdp/crypto/ber.c | 81 +- libfreerdp/crypto/certificate.c | 4 +- libfreerdp/crypto/crypto.c | 4 +- libfreerdp/crypto/per.c | 8 +- libfreerdp/crypto/test/TestKnownHosts.c | 16 +- libfreerdp/crypto/tls.c | 38 +- libfreerdp/gdi/CMakeLists.txt | 1 + libfreerdp/gdi/bitmap.c | 6 +- libfreerdp/gdi/gdi.c | 626 ++-- libfreerdp/gdi/gfx.c | 106 +- libfreerdp/gdi/graphics.c | 4 + libfreerdp/gdi/line.c | 4 +- libfreerdp/gdi/pen.c | 2 +- libfreerdp/gdi/region.c | 30 +- libfreerdp/gdi/shape.c | 3 +- libfreerdp/gdi/test/TestGdiBitBlt.c | 8 +- libfreerdp/gdi/test/TestGdiClip.c | 88 +- libfreerdp/gdi/test/TestGdiCreate.c | 222 +- libfreerdp/gdi/test/TestGdiEllipse.c | 2 +- libfreerdp/gdi/test/TestGdiLine.c | 7 +- libfreerdp/gdi/test/TestGdiRect.c | 62 +- libfreerdp/gdi/test/TestGdiRop3.c | 4 - libfreerdp/gdi/test/helpers.c | 6 +- libfreerdp/gdi/video.c | 159 + libfreerdp/locale/CMakeLists.txt | 4 + libfreerdp/locale/keyboard.c | 4 +- libfreerdp/locale/keyboard_sun.c | 28 +- libfreerdp/primitives/prim_YUV.c | 970 +++++- libfreerdp/primitives/prim_YUV_neon.c | 771 +++++ .../{prim_YUV_opt.c => prim_YUV_ssse3.c} | 1396 +++----- libfreerdp/primitives/prim_internal.h | 14 +- libfreerdp/primitives/primitives.c | 30 +- .../primitives/test/TestPrimitivesAlphaComp.c | 8 +- .../primitives/test/TestPrimitivesColors.c | 30 +- .../primitives/test/TestPrimitivesYCbCr.c | 64 +- .../primitives/test/TestPrimitivesYCoCg.c | 30 +- .../primitives/test/TestPrimitivesYUV.c | 431 ++- libfreerdp/utils/pcap.c | 9 +- packaging/deb/freerdp-nightly/control | 1 + .../freerdp-nightly/freerdp-nightly.install | 5 +- packaging/deb/freerdp-nightly/rules | 7 +- packaging/rpm/freerdp-nightly.spec | 35 +- .../scripts/prepare_deb_freerdp-nightly.sh | 1 + .../scripts/prepare_rpm_freerdp-nightly.sh | 3 + rdtk/CMakeLists.txt | 1 - rdtk/librdtk/rdtk_font.c | 100 +- rdtk/librdtk/rdtk_nine_patch.c | 8 +- rdtk/sample/rdtk_x11.c | 6 +- scripts/.gitignore | 2 + scripts/TimeZones.cs | 230 -- scripts/TimeZones.csx | 221 ++ scripts/WindowsZones.cs | 90 - scripts/WindowsZones.csx | 84 + scripts/android-build-32.conf | 4 +- scripts/android-build-64.conf | 4 +- scripts/android-build-openh264.sh | 2 +- scripts/android-build.conf | 4 +- scripts/blacklist-address-sanitizer.txt | 0 scripts/blacklist-memory-sanitizer.txt | 1 + scripts/blacklist-thread-sanitizer.txt | 0 scripts/format_code.sh | 23 +- server/CMakeLists.txt | 2 +- server/Mac/mf_info.c | 5 +- server/Mac/mf_input.c | 117 +- server/Mac/mf_input.h | 18 +- server/Mac/mf_peer.c | 156 +- server/Mac/mf_peer.h | 17 - server/Mac/mf_rdpsnd.c | 146 +- server/Sample/sfreerdp.c | 76 +- server/Windows/cli/wfreerdp.c | 39 +- server/Windows/wf_directsound.c | 2 +- server/Windows/wf_interface.c | 2 +- server/Windows/wf_peer.c | 4 +- server/Windows/wf_wasapi.c | 2 +- server/shadow/Mac/mac_shadow.c | 11 +- server/shadow/Win/win_rdp.c | 59 +- server/shadow/Win/win_shadow.c | 122 +- server/shadow/Win/win_shadow.h | 2 +- server/shadow/X11/x11_shadow.c | 54 +- server/shadow/freerdp-shadow-cli.1.in | 18 +- server/shadow/shadow_client.c | 122 +- server/shadow/shadow_encoder.c | 10 +- server/shadow/shadow_server.c | 60 +- uwac/libuwac/uwac-input.c | 8 +- winpr/CMakeLists.txt | 1 - winpr/include/winpr/cmdline.h | 16 +- winpr/include/winpr/crt.h | 59 +- winpr/include/winpr/crypto.h | 6 +- winpr/include/winpr/pool.h | 56 +- winpr/include/winpr/smartcard.h | 5 - winpr/include/winpr/ssl.h | 3 + winpr/include/winpr/sspi.h | 244 +- winpr/include/winpr/stream.h | 32 + winpr/include/winpr/tchar.h | 2 + winpr/include/winpr/winpr.h | 2 + winpr/include/winpr/wlog.h | 2 + winpr/include/winpr/wtsapi.h | 2 +- winpr/include/winpr/wtypes.h.in | 58 +- winpr/libwinpr/CMakeLists.txt | 10 +- winpr/libwinpr/clipboard/posix.c | 134 +- winpr/libwinpr/clipboard/synthetic.c | 262 +- winpr/libwinpr/comm/comm.c | 65 +- winpr/libwinpr/comm/comm.h | 1 + winpr/libwinpr/comm/comm_io.c | 14 +- winpr/libwinpr/comm/comm_serial_sys.c | 16 +- winpr/libwinpr/crt/CMakeLists.txt | 21 +- winpr/libwinpr/crt/unicode.c | 100 +- winpr/libwinpr/crypto/cipher.c | 88 +- winpr/libwinpr/crypto/hash.c | 127 +- winpr/libwinpr/dsparse/test/TestDsMakeSpn.c | 30 +- .../TestEnvironmentMergeEnvironmentStrings.c | 6 +- .../error/test/TestErrorSetLastError.c | 6 +- winpr/libwinpr/file/file.c | 213 +- winpr/libwinpr/file/generic.c | 30 +- .../file/test/TestFileFindFirstFile.c | 14 +- .../libwinpr/file/test/TestFileFindNextFile.c | 23 +- winpr/libwinpr/input/keycode.c | 15 + winpr/libwinpr/io/device.c | 2 +- winpr/libwinpr/nt/nt.c | 3 +- winpr/libwinpr/nt/test/TestNtCreateFile.c | 20 +- winpr/libwinpr/path/test/TestPathShell.c | 86 +- winpr/libwinpr/pipe/pipe.c | 10 +- .../pipe/test/TestPipeCreateNamedPipe.c | 22 +- .../test/TestPipeCreateNamedPipeOverlapped.c | 18 +- winpr/libwinpr/pool/cleanup_group.c | 72 +- winpr/libwinpr/pool/pool.c | 8 +- winpr/libwinpr/pool/pool.h | 7 +- winpr/libwinpr/pool/test/TestPoolWork.c | 82 +- winpr/libwinpr/pool/work.c | 39 +- winpr/libwinpr/registry/registry_reg.c | 81 +- winpr/libwinpr/smartcard/smartcard.c | 68 +- winpr/libwinpr/smartcard/smartcard.h | 23 - winpr/libwinpr/smartcard/smartcard_pcsc.c | 819 ++--- winpr/libwinpr/smartcard/smartcard_pcsc.h | 1 - winpr/libwinpr/smartcard/smartcard_winscard.c | 3 +- .../smartcard/test/TestSmartCardStatus.c | 166 + winpr/libwinpr/sspi/CMakeLists.txt | 18 +- winpr/libwinpr/sspi/CredSSP/credssp.c | 91 +- winpr/libwinpr/sspi/Kerberos/kerberos.c | 807 +++++ winpr/libwinpr/sspi/Kerberos/kerberos.h | 37 + winpr/libwinpr/sspi/NTLM/ntlm.c | 92 +- winpr/libwinpr/sspi/NTLM/ntlm.h | 8 +- winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c | 2 - winpr/libwinpr/sspi/NTLM/ntlm_compute.c | 129 +- winpr/libwinpr/sspi/NTLM/ntlm_message.c | 10 +- winpr/libwinpr/sspi/Negotiate/negotiate.c | 305 +- winpr/libwinpr/sspi/Negotiate/negotiate.h | 4 +- winpr/libwinpr/sspi/Schannel/schannel.c | 122 +- winpr/libwinpr/sspi/sspi.c | 2 + winpr/libwinpr/sspi/sspi.h | 57 +- winpr/libwinpr/sspi/sspi_gss.c | 1033 ++++++ winpr/libwinpr/sspi/sspi_gss.h | 886 +++++ winpr/libwinpr/sspi/sspi_winpr.c | 449 ++- .../sspi/test/TestAcquireCredentialsHandle.c | 43 +- .../sspi/test/TestInitializeSecurityContext.c | 74 +- winpr/libwinpr/sspi/test/TestNTLM.c | 159 +- .../sspi/test/TestQuerySecurityPackageInfo.c | 19 +- winpr/libwinpr/sspi/test/TestSchannel.c | 42 +- winpr/libwinpr/synch/critical.c | 23 +- winpr/libwinpr/synch/event.c | 10 +- winpr/libwinpr/synch/semaphore.c | 2 +- winpr/libwinpr/synch/synch.h | 18 +- winpr/libwinpr/synch/test/TestSynchBarrier.c | 2 +- winpr/libwinpr/synch/test/TestSynchCritical.c | 37 +- winpr/libwinpr/synch/test/TestSynchInit.c | 16 +- .../synch/test/TestSynchMultipleThreads.c | 7 +- winpr/libwinpr/synch/test/TestSynchMutex.c | 14 +- winpr/libwinpr/synch/test/TestSynchThread.c | 13 +- .../synch/test/TestSynchWaitableTimer.c | 31 +- .../synch/test/TestSynchWaitableTimerAPC.c | 16 +- winpr/libwinpr/synch/timer.c | 293 +- .../sysinfo/cpufeatures/cpu-features.c | 1 + winpr/libwinpr/thread/argv.c | 4 +- .../thread/test/TestThreadExitThread.c | 6 +- winpr/libwinpr/thread/thread.c | 12 +- winpr/libwinpr/timezone/timezone.c | 9 +- winpr/libwinpr/utils/CMakeLists.txt | 2 +- winpr/libwinpr/utils/cmdline.c | 134 +- winpr/libwinpr/utils/collections/HashTable.c | 26 +- .../libwinpr/utils/collections/MessageQueue.c | 2 + winpr/libwinpr/utils/collections/PubSub.c | 4 +- winpr/libwinpr/utils/debug.c | 4 +- winpr/libwinpr/utils/image.c | 233 +- winpr/libwinpr/utils/ini.c | 157 +- winpr/libwinpr/utils/lodepng/lodepng.c | 7 +- winpr/libwinpr/utils/sam.c | 88 +- winpr/libwinpr/utils/ssl.c | 65 +- winpr/libwinpr/utils/test/TestBacktrace.c | 13 +- winpr/libwinpr/utils/test/TestBipBuffer.c | 9 +- winpr/libwinpr/utils/test/TestCmdLine.c | 28 +- winpr/libwinpr/utils/test/TestHashTable.c | 87 +- winpr/libwinpr/utils/test/TestImage.c | 54 +- winpr/libwinpr/utils/test/TestMessagePipe.c | 12 +- winpr/libwinpr/utils/test/TestMessageQueue.c | 6 +- winpr/libwinpr/utils/test/TestStream.c | 6 +- winpr/libwinpr/utils/test/TestWLog.c | 4 - winpr/libwinpr/utils/test/TestWLogCallback.c | 3 - winpr/libwinpr/utils/winpr.c | 6 + winpr/libwinpr/utils/wlog/PacketMessage.c | 9 +- winpr/libwinpr/utils/wlog/wlog.c | 191 +- winpr/tools/hash-cli/hash.c | 17 +- winpr/tools/makecert-cli/CMakeLists.txt | 2 +- winpr/tools/makecert-cli/winpr-makecert.1.in | 4 +- winpr/tools/makecert/CMakeLists.txt | 2 +- winpr/tools/makecert/makecert.c | 49 +- 447 files changed, 27815 insertions(+), 11383 deletions(-) create mode 100644 .travis.yml create mode 100644 channels/geometry/CMakeLists.txt create mode 100644 channels/geometry/ChannelOptions.cmake create mode 100644 channels/geometry/client/CMakeLists.txt create mode 100644 channels/geometry/client/geometry_main.c create mode 100644 channels/geometry/client/geometry_main.h create mode 100644 channels/sshagent/CMakeLists.txt create mode 100644 channels/sshagent/ChannelOptions.cmake create mode 100644 channels/sshagent/client/CMakeLists.txt create mode 100644 channels/sshagent/client/sshagent_main.c create mode 100644 channels/sshagent/client/sshagent_main.h create mode 100644 channels/sshagent/server/CMakeLists.txt create mode 100644 channels/sshagent/server/sshagent_main.c create mode 100644 channels/video/CMakeLists.txt create mode 100644 channels/video/ChannelOptions.cmake create mode 100644 channels/video/client/CMakeLists.txt create mode 100755 channels/video/client/video_main.c create mode 100644 channels/video/client/video_main.h create mode 100644 client/X11/xf_disp.c create mode 100644 client/X11/xf_disp.h create mode 100644 client/X11/xf_video.c create mode 100644 client/X11/xf_video.h create mode 100644 client/common/cmdline.h delete mode 100644 cmake/AutoVersioning.cmake create mode 100644 cmake/ClangToolchain.cmake create mode 100644 cmake/FindGSSAPI.cmake delete mode 100644 cmake/FindKRB5.cmake create mode 100644 cmake/compat_3.7.0/FindICU.cmake create mode 100644 docs/README.macOS create mode 100644 include/freerdp/channels/geometry.h create mode 100644 include/freerdp/channels/video.h create mode 100644 include/freerdp/client/geometry.h create mode 100644 include/freerdp/client/sshagent.h create mode 100644 include/freerdp/client/video.h create mode 100644 include/freerdp/codec/yuv.h create mode 100644 include/freerdp/gdi/video.h create mode 100644 libfreerdp/codec/h264.h create mode 100644 libfreerdp/codec/yuv.c create mode 100644 libfreerdp/gdi/video.c create mode 100644 libfreerdp/primitives/prim_YUV_neon.c rename libfreerdp/primitives/{prim_YUV_opt.c => prim_YUV_ssse3.c} (53%) create mode 100755 packaging/scripts/prepare_rpm_freerdp-nightly.sh delete mode 100644 scripts/TimeZones.cs create mode 100644 scripts/TimeZones.csx delete mode 100644 scripts/WindowsZones.cs create mode 100644 scripts/WindowsZones.csx create mode 100644 scripts/blacklist-address-sanitizer.txt create mode 100644 scripts/blacklist-memory-sanitizer.txt create mode 100644 scripts/blacklist-thread-sanitizer.txt create mode 100644 winpr/libwinpr/smartcard/test/TestSmartCardStatus.c create mode 100644 winpr/libwinpr/sspi/Kerberos/kerberos.c create mode 100644 winpr/libwinpr/sspi/Kerberos/kerberos.h create mode 100644 winpr/libwinpr/sspi/sspi_gss.c create mode 100644 winpr/libwinpr/sspi/sspi_gss.h diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2dba29b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,54 @@ +sudo: required +dist: trusty + +os: linux + +language: c + +compiler: + - gcc + +matrix: + include: + - os: linux + compiler: gcc + - os: linux + compiler: clang + exclude: + - compiler: gcc + +addons: + apt: + packages: + - gdb + - libx11-dev + - libxrandr-dev + - libxi-dev + - libxv-dev + - libcups2-dev + - libxdamage-dev + - libxcursor-dev + - libxext-dev + - libxinerama-dev + - libxkbcommon-dev + - libxkbfile-dev + - libxml2-dev + - libasound2-dev + - libgstreamer1.0-dev + - libgstreamer-plugins-base1.0-dev + - libpulse-dev + - libpcsclite-dev + - libgsm1-dev + - libavcodec-dev + - libavutil-dev + - libx264-dev + - libxext-dev + +before_script: + - ulimit -c unlimited -S + +script: + - sudo hostname travis-ci.local + - cmake -G "Unix Makefiles" -C ci/cmake-preloads/config-linux-all.txt -D CMAKE_BUILD_TYPE=Debug -DWITH_LIBSYSTEMD=OFF -DWITH_WAYLAND=OFF . + - make + - make test diff --git a/CMakeLists.txt b/CMakeLists.txt index 0971718..16368ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,6 @@ include(FindPkgConfig) include(TestBigEndian) include(FindFeature) -include(AutoVersioning) include(ConfigOptions) include(ComplexLibrary) include(FeatureSummary) @@ -68,6 +67,7 @@ include(CheckCXXCompilerFlag) include(GNUInstallDirsWrapper) include(CMakePackageConfigHelpers) include(InstallFreeRDPMan) +include(GetGitRevisionDescription) # Soname versioning set(BUILD_NUMBER 0) @@ -75,10 +75,24 @@ if ($ENV{BUILD_NUMBER}) set(BUILD_NUMBER $ENV{BUILD_NUMBER}) endif() set(WITH_LIBRARY_VERSIONING "ON") -set(FREERDP_VERSION_MAJOR "2") -set(FREERDP_VERSION_MINOR "0") -set(FREERDP_VERSION_REVISION "0") -set(FREERDP_VERSION_SUFFIX "dev") + +set(RAW_VERSTION_STRING "2.0.0-rc2") +if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") + file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSTION_STRING) +elseif(USE_VERSION_FROM_GIT_TAG) + git_get_exact_tag(_GIT_TAG --tags --always) + if (NOT ${_GIT_TAG} STREQUAL "n/a") + set(RAW_VERSTION_STRING ${_GIT_TAG}) + endif() +endif() +string(STRIP ${RAW_VERSTION_STRING} RAW_VERSTION_STRING) + +set(VERSION_REGEX "^.?([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)") +string(REGEX REPLACE "${VERSION_REGEX}" "\\1" FREERDP_VERSION_MAJOR "${RAW_VERSTION_STRING}") +string(REGEX REPLACE "${VERSION_REGEX}" "\\2" FREERDP_VERSION_MINOR "${RAW_VERSTION_STRING}") +string(REGEX REPLACE "${VERSION_REGEX}" "\\3" FREERDP_VERSION_REVISION "${RAW_VERSTION_STRING}") +string(REGEX REPLACE "${VERSION_REGEX}" "\\4" FREERDP_VERSION_SUFFIX "${RAW_VERSTION_STRING}") + set(FREERDP_API_VERSION "${FREERDP_VERSION_MAJOR}") set(FREERDP_VERSION "${FREERDP_VERSION_MAJOR}.${FREERDP_VERSION_MINOR}.${FREERDP_VERSION_REVISION}") if (FREERDP_VERSION_SUFFIX) @@ -86,6 +100,8 @@ if (FREERDP_VERSION_SUFFIX) else() set(FREERDP_VERSION_FULL "${FREERDP_VERSION}") endif() +message("FREERDP_VERSION=${FREERDP_VERSION_FULL}") + set(FREERDP_INCLUDE_DIR "include/freerdp${FREERDP_VERSION_MAJOR}/") # Compatibility options @@ -102,26 +118,42 @@ if (FREERDP_EXTERNAL_PATH) get_filename_component (FREERDP_EXTERNAL_PATH "${FREERDP_EXTERNAL_PATH}" ABSOLUTE) endif() -# Allow to search the host machine for git +# Allow to search the host machine for git/ccache if(CMAKE_CROSSCOMPILING) SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) endif(CMAKE_CROSSCOMPILING) find_program(CCACHE ccache) if(CCACHE AND WITH_CCACHE) - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE}) - set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE}) + if(CMAKE_VERSION VERSION_GREATER 3.3.2) + if(NOT DEFINED CMAKE_C_COMPILER_LAUNCHER) + SET(CMAKE_C_COMPILER_LAUNCHER ${CCACHE}) + endif(NOT DEFINED CMAKE_C_COMPILER_LAUNCHER) + if(NOT DEFINED CMAKE_CXX_COMPILER_LAUNCHER) + SET(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE}) + endif(NOT DEFINED CMAKE_CXX_COMPILER_LAUNCHER) + else() + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE}) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE}) + endif() endif(CCACHE AND WITH_CCACHE) -include(GetGitRevisionDescription) -git_get_exact_tag(GIT_REVISION --tags --always) +if(EXISTS "${CMAKE_SOURCE_DIR}/.source_version" ) + file(READ ${CMAKE_SOURCE_DIR}/.source_version GIT_REVISION) -if (${GIT_REVISION} STREQUAL "n/a") - git_rev_parse (GIT_REVISION --short) + string(STRIP ${GIT_REVISION} GIT_REVISION) +else() + git_get_exact_tag(GIT_REVISION --tags --always) + + if (${GIT_REVISION} STREQUAL "n/a") + git_rev_parse (GIT_REVISION --short) + endif() endif() + if(CMAKE_CROSSCOMPILING) SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) endif(CMAKE_CROSSCOMPILING) +# /Allow to search the host machine for git/ccache message(STATUS "Git Revision ${GIT_REVISION}") @@ -158,6 +190,9 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "BSD") if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") set(FREEBSD TRUE) endif() + if(${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD") + set(KFREEBSD TRUE) + endif() if(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") set(OPENBSD TRUE) endif() @@ -189,6 +224,11 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") add_definitions("-D_FILE_OFFSET_BITS=64") endif() +# Use Standard conforming getpwnam_r() on Solaris. +if("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS") + add_definitions("-D_POSIX_PTHREAD_SEMANTICS") +endif() + # Compiler-specific flags if(CMAKE_COMPILER_IS_GNUCC) if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "i686") @@ -252,9 +292,6 @@ if(CMAKE_COMPILER_IS_GNUCC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") endif() - if(WITH_SSE2) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2") - endif() endif() # When building with Unix Makefiles and doing any release builds @@ -278,9 +315,7 @@ if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-macros -Wno-padded") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-c11-extensions -Wno-gnu") - if(WITH_SSE2) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mssse3") - endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-command-line-argument") CHECK_C_COMPILER_FLAG(-Wno-deprecated-declarations Wno-deprecated-declarations) if(Wno-deprecated-declarations) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations") @@ -300,7 +335,14 @@ if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCC) set(CMAKE_REQUIRED_FLAGS "-fsanitize=address") CHECK_C_COMPILER_FLAG ("-fsanitize=address" fsanitize-address) if(fsanitize-address) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") + if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-address-sanitizer.txt") + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") + else() + message(FATAL_ERROR "Missing support for address sanitizer!") endif() if (DEFINED SAVE_CMAKE_REQUIRED_FLAGS) set(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS}) @@ -312,14 +354,47 @@ if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCC) if(fno-omit-frame-pointer) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer") endif() - elseif(WITH_SANITIZE_LEAK) + elseif(WITH_SANITIZE_MEMORY) if (DEFINED CMAKE_REQUIRED_FLAGS) set(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) endif() - set(CMAKE_REQUIRED_FLAGS "-fsanitize=leak") - CHECK_C_COMPILER_FLAG ("-fsanitize=leak" fsanitize-leak) - if(fsanitize-leak) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=leak") + set(CMAKE_REQUIRED_FLAGS "-fsanitize=memory") + CHECK_C_COMPILER_FLAG ("-fsanitize=memory" fsanitize-memory) + if(fsanitize-memory) + if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-memory-sanitizer.txt") + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fsanitize-memory-use-after-dtor") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=memory") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=memory") + else() + message(FATAL_ERROR "Missing support for memory sanitizer!") + endif() + if (DEFINED SAVE_CMAKE_REQUIRED_FLAGS) + set(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS}) + else() + unset(CMAKE_REQUIRED_FLAGS) + endif() + + CHECK_C_COMPILER_FLAG ("-fno-omit-frame-pointer" fno-omit-frame-pointer) + if(fno-omit-frame-pointer) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer") + endif() + elseif(WITH_SANITIZE_THREAD) + if (DEFINED CMAKE_REQUIRED_FLAGS) + set(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + endif() + set(CMAKE_REQUIRED_FLAGS "-fsanitize=thread") + CHECK_C_COMPILER_FLAG ("-fsanitize=thread" fsanitize-thread) + if(fsanitize-thread) + if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-thread-sanitizer.txt") + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=thread") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread") + else() + message(FATAL_ERROR "Missing support for thread sanitizer!") endif() if (DEFINED SAVE_CMAKE_REQUIRED_FLAGS) set(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS}) @@ -399,7 +474,7 @@ if(WIN32) elseif (${CMAKE_GENERATOR} MATCHES "Visual Studio*") set(CMAKE_PDB_BINARY_DIR "${CMAKE_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}") else() - message(FATAL "Unknown generator ${CMAKE_GENERATOR}") + message(FATAL_ERROR "Unknown generator ${CMAKE_GENERATOR}") endif() # Set product and vendor for dll and exe version information. @@ -566,12 +641,12 @@ else() endif() if(UNIX OR CYGWIN) - check_include_files(sys/eventfd.h HAVE_AIO_H) - check_include_files(sys/eventfd.h HAVE_EVENTFD_H) - if (HAVE_EVENTFD_H) + check_include_files(aio.h HAVE_AIO_H) + check_include_files(sys/eventfd.h HAVE_SYS_EVENTFD_H) + if (HAVE_SYS_EVENTFD_H) check_symbol_exists(eventfd_read sys/eventfd.h WITH_EVENTFD_READ_WRITE) endif() - check_include_files(sys/timerfd.h HAVE_TIMERFD_H) + check_include_files(sys/timerfd.h HAVE_SYS_TIMERFD_H) check_include_files(poll.h HAVE_POLL_H) list(APPEND CMAKE_REQUIRED_LIBRARIES m) check_symbol_exists(ceill math.h HAVE_MATH_C99_LONG_DOUBLE) @@ -637,6 +712,10 @@ set(FFMPEG_FEATURE_TYPE "RECOMMENDED") set(FFMPEG_FEATURE_PURPOSE "multimedia") set(FFMPEG_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback") +set(VAAPI_FEATURE_TYPE "OPTIONAL") +set(VAAPI_FEATURE_PURPOSE "multimedia") +set(VAAPI_FEATURE_DESCRIPTION "VA-API hardware acceleration for video playback") + set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL") set(GSTREAMER_0_10_FEATURE_PURPOSE "multimedia") set(GSTREAMER_0_10_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback, gstreamer 0.10 version") @@ -661,14 +740,14 @@ set(OPENH264_FEATURE_TYPE "OPTIONAL") set(OPENH264_FEATURE_PURPOSE "codec") set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library") -set(KRB5_FEATURE_TYPE "OPTIONAL") -set(KRB5_FEATURE_PURPOSE "auth") -set(KRB5_FEATURE_DESCRIPTION "add kerberos support") - set(GSM_FEATURE_TYPE "OPTIONAL") set(GSM_FEATURE_PURPOSE "codec") set(GSM_FEATURE_DESCRIPTION "GSM audio codec library") +set(GSSAPI_FEATURE_TYPE "OPTIONAL") +set(GSSAPI_FEATURE_PURPOSE "auth") +set(GSSAPI_FEATURE_DESCRIPTION "add kerberos support") + if(WIN32) set(X11_FEATURE_TYPE "DISABLED") set(WAYLAND_FEATURE_TYPE "DISABLED") @@ -680,6 +759,7 @@ if(WIN32) set(CUPS_FEATURE_TYPE "DISABLED") set(PCSC_FEATURE_TYPE "DISABLED") set(FFMPEG_FEATURE_TYPE "DISABLED") + set(VAAPI_FEATURE_TYPE "DISABLED") set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED") set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL") set(OPENSLES_FEATURE_TYPE "DISABLED") @@ -688,6 +768,7 @@ endif() if(APPLE) set(DIRECTFB_FEATURE_TYPE "DISABLED") set(FFMPEG_FEATURE_TYPE "OPTIONAL") + set(VAAPI_FEATURE_TYPE "DISABLED") set(GSTREAMER_1_0_FEATURE_TYPE "OPTIONAL") set(X11_FEATURE_TYPE "OPTIONAL") set(WAYLAND_FEATURE_TYPE "DISABLED") @@ -729,6 +810,7 @@ if(ANDROID) set(CUPS_FEATURE_TYPE "DISABLED") set(PCSC_FEATURE_TYPE "DISABLED") set(FFMPEG_FEATURE_TYPE "DISABLED") + set(VAAPI_FEATURE_TYPE "DISABLED") set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED") set(GSTREAMER_0_10_FEATURE_TYPE "DISABLED") set(OPENSLES_FEATURE_TYPE "REQUIRED") @@ -762,7 +844,25 @@ find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DE find_feature(x264 ${X264_FEATURE_TYPE} ${X264_FEATURE_PURPOSE} ${X264_FEATURE_DESCRIPTION}) find_feature(OpenH264 ${OPENH264_FEATURE_TYPE} ${OPENH264_FEATURE_PURPOSE} ${OPENH264_FEATURE_DESCRIPTION}) find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION}) -find_feature(KRB5 ${KRB5_FEATURE_TYPE} ${KRB5_FEATURE_PURPOSE} ${KRB5_FEATURE_DESCRIPTION}) + +find_feature(GSSAPI ${GSSAPI_FEATURE_TYPE} ${GSSAPI_FEATURE_PURPOSE} ${GSSAPI_FEATURE_DESCRIPTION}) + +if ( (WITH_GSSAPI) AND (NOT GSS_FOUND)) + message(WARNING "-DWITH_GSSAPI=ON is set, but not GSSAPI implementation was found, disabling") +elseif(WITH_GSSAPI) + if(GSS_FLAVOUR STREQUAL "MIT") + add_definitions("-DWITH_GSSAPI -DWITH_GSSAPI_MIT") + if(GSS_VERSION_1_13) + add_definitions("-DHAVE_AT_LEAST_KRB_V1_13") + endif() + include_directories(${_GSS_INCLUDE_DIR}) + elseif(GSS_FLAVOUR STREQUAL "Heimdal") + add_definitions("-DWITH_GSSAPI -DWITH_GSSAPI_HEIMDAL") + include_directories(${_GSS_INCLUDE_DIR}) + else() + message(WARNING "Kerberos version not detected") + endif() +endif() if(TARGET_ARCH MATCHES "x86|x64") if (NOT APPLE) @@ -819,14 +919,15 @@ add_definitions("-DHAVE_CONFIG_H") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) # RPATH configuration -if(CMAKE_SKIP_RPATH) - 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) -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/..") +if (APPLE) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) + set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks") +else (APPLE) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/..") +endif(APPLE) if (BUILD_SHARED_LIBS) set(CMAKE_MACOSX_RPATH ON) diff --git a/ChangeLog b/ChangeLog index b9eb78a..64ceaa2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,2997 @@ +2018-04-11 13:25:31 +0200 Martin Fleisz (7a7b18027) + + * Merge pull request #4560 from bmiklautz/200rc2 + +2018-04-11 12:44:06 +0200 Bernhard Miklautz (c98a90ea6) + + * release: version 2.0.0-rc2 + +2018-04-11 11:01:38 +0200 Bernhard Miklautz (6383b2e33) + + * Merge pull request #3542 from akallabeth/thread_sanitizer + +2018-04-11 10:59:27 +0200 Bernhard Miklautz (f85563de4) + + * Merge pull request #4558 from mfleisz/openssl11_fix_win + +2018-04-11 10:49:44 +0200 Bernhard Miklautz (c0afb8bd6) + + * Merge pull request #4322 from akallabeth/rail_fixes + +2018-04-11 10:18:46 +0200 Martin Fleisz (dfd269e20) + + * cmake: Fix finding OpenSSL 1.1.0 libs on Windows platforms + +2018-04-10 11:12:31 +0200 Martin Fleisz (04b29575f) + + * Merge pull request #4552 from perkerk/win-10-cursors-again + +2018-04-10 02:55:15 -0500 Eric Brown (ee87b9885) + + * Fix issues found by build bot + +2018-04-09 13:59:42 -0500 Eric Brown (71c949f61) + + * Fix Windows 10 cursors drawing as black + +2018-04-09 19:00:48 +0200 akallabeth (09c766cde) + + * Merge pull request #4551 from oshogbo/nego_0 + +2018-04-09 17:13:22 +0200 Mariusz Zaborski (480abdde9) + + * Fix setting of negotiated security protocol. + +2018-04-09 16:26:18 +0200 Bernhard Miklautz (e818dd567) + + * Merge pull request #4549 from oshogbo/krb + +2018-04-09 15:04:52 +0200 Mariusz Zaborski (dc2c826ed) + + * Fix checking of krb in encrypt public key echo. + +2018-04-09 09:22:18 +0200 David Fort (62f540812) + + * Merge pull request #4540 from akallabeth/warning_fixes_v2 + +2018-04-06 11:34:24 +0200 Armin Novak (3762e0671) + + * Fixed RDP debug message invalid function. + +2016-10-10 19:17:21 +0200 Armin Novak (ef6a03128) + + * Added memory and thread sanitizer. + +2018-04-05 10:49:24 +0200 Armin Novak (b5668e35b) + + * Fixed format string mismatch. + +2018-04-05 10:48:45 +0200 Armin Novak (72d574b31) + + * Fixed type mismatches with H264 backend buffer pointers. + +2018-04-05 10:47:50 +0200 Armin Novak (26d995760) + + * Fix pointer type mismatch struct sockaddr_storage* and struct + sockaddr* + +2018-04-05 10:20:43 +0200 MartinHaimberger (a9ecd6a6c) + + * Merge pull request #4535 from akallabeth/warning_fixes + +2018-04-05 10:17:51 +0200 MartinHaimberger (0af63d4c6) + + * Merge pull request #4481 from akallabeth/fastpath_fix + +2018-04-05 07:35:40 +0200 akallabeth (7f6103e1a) + + * Merge pull request #4538 from mfleisz/win_ipv6_fix + +2018-04-04 17:19:18 +0200 Martin Fleisz (ff8b2c1b0) + + * core: Fix IPv6 handling on Windows + +2018-04-04 13:23:14 +0200 Armin Novak (e47d7eb96) + + * Simplified fastpath buffer handling. + +2018-03-13 09:32:14 +0100 Armin Novak (f840150a5) + + * Fixed missing return value checks. + +2018-04-04 12:52:39 +0200 MartinHaimberger (55973288f) + + * Merge pull request #4514 from akallabeth/com_lpt_fix + +2018-04-04 10:46:14 +0200 Armin Novak (c70bf8329) + + * Fixed XPixmap checks. + +2018-04-04 10:45:57 +0200 Armin Novak (065a92449) + + * Fixed format string types. + +2018-04-04 10:45:32 +0200 Armin Novak (3f1ef0efc) + + * Removed unnecessary range check. + +2018-04-04 10:45:07 +0200 Armin Novak (2bda3a30b) + + * Fixed integer to float type cast. + +2018-04-04 10:44:51 +0200 Armin Novak (842707b10) + + * Fixed printf format string. + +2018-04-04 10:43:31 +0200 Armin Novak (b0fe19906) + + * Fixed intrinsic integer overflow. + +2018-04-04 10:35:47 +0200 akallabeth (b37a98182) + + * Merge pull request #4457 from RangeeGmbH/fix_custom_sizes + +2018-04-04 10:12:04 +0200 MartinHaimberger (1a8234c74) + + * Merge pull request #4472 from akallabeth/win_mouse_button + +2018-04-04 10:06:07 +0200 MartinHaimberger (c73c54a62) + + * Merge pull request #4477 from akallabeth/command_line_fix + +2018-04-04 10:04:58 +0200 MartinHaimberger (08271709e) + + * Merge pull request #4416 from akallabeth/audin_fix + +2018-04-04 09:32:46 +0200 Martin Fleisz (edce38613) + + * Merge pull request #4529 from akallabeth/wlog_cleanup_fix + +2018-04-03 15:52:35 +0200 akallabeth (807fe0413) + + * Merge pull request #4519 from mfleisz/cssp_nonce_fix + +2018-04-03 15:04:32 +0200 akallabeth (d8b09fedc) + + * Merge pull request #4532 from RangeeGmbH/cmdline_spelling + +2018-04-03 12:12:58 +0000 Kai Harms (2dffc3ef9) + + * Fix spelling of network commandline values + +2018-04-03 14:04:22 +0200 Armin Novak (b260937ca) + + * Use __attribute__((destructor)) on non windows systems. + +2018-04-03 13:06:41 +0200 Armin Novak (e0d112d54) + + * Removed all calls to WLog_Init and WLog_Uninit + +2018-04-03 12:55:17 +0200 Armin Novak (d24933570) + + * Removed winpr_exit + +2018-04-03 10:22:08 +0200 akallabeth (a51e5a908) + + * Merge pull request #4527 from jkaivo/master + +2018-04-03 09:59:42 +0200 Armin Novak (e1b53a282) + + * Fix #4524: Initialize with cleanup handler + +2018-03-31 22:15:39 -0400 Jakob Kaivo (3a1d70d9b) + + * add support for the "pcb" block in .rdp files provided by Project + Honolulu in the VM interface + +2018-03-30 17:20:50 +0200 Bernhard Miklautz (e03333477) + + * Merge pull request #4522 from UndefBehavior/fix_SCardStatusW + +2018-03-30 07:11:24 -0700 UndefBehavior (08e7217c1) + + * Fix SCardStatusW function + +2018-03-29 15:50:16 +0200 Martin Fleisz (5c59b5f2b) + + * cssp: Fix handling of nonce + +2018-02-26 14:38:16 +0000 Kai Harms (222bf9245) + + * Fix /size: /w: /h: with /monitor: (Fix custom sizes) + +2018-02-09 14:04:10 +0100 Armin Novak (0c49152a3) + + * Fixed #4412: memory corruption in audin channel. + +2018-02-09 13:49:58 +0100 Armin Novak (c53d72211) + + * Audin channel use dynamic logger where possible. + +2018-03-26 14:31:14 +0200 Bernhard Miklautz (a42f6d6aa) + + * Merge pull request #4513 from chipitsine/travis-new + +2018-03-26 13:09:11 +0200 akallabeth (5b52ad912) + + * Merge pull request #4512 from chipitsine/master + +2018-03-25 21:38:46 +0500 Ilya Shipitsin (1d73d2d30) + + * initial travis-ci support + +2018-03-24 17:46:39 +0500 Ilya Shipitsin (14c15c680) + + * resolve several possible null pointer dereference + +2018-03-23 14:12:19 +0100 akallabeth (68c4bab68) + + * Merge pull request #4510 from mfleisz/cssp_version_fix + +2018-03-23 12:12:08 +0100 Martin Fleisz (eb1f693fc) + + * cssp: Separate client/server version handling (#4502) + +2018-03-23 11:21:13 +0100 Armin Novak (a266147dd) + + * Added debug message. + +2018-03-23 10:44:32 +0100 Armin Novak (1316b828c) + + * Removed reserved COM and LPT check. + +2018-03-22 17:03:52 +0100 Bernhard Miklautz (1adbc389a) + + * Merge pull request #4508 from h3xx/fix-ccache-support + +2018-03-21 11:57:36 -0500 Dan Church (3af9c4d35) + + * Fix ccache support + +2018-03-21 14:19:51 +0100 David Fort (15fb91726) + + * Merge pull request #4469 from akallabeth/win_server_fix + +2018-03-21 13:36:46 +0100 akallabeth (f11ff9a63) + + * Merge pull request #4504 from mfleisz/cssp_warnings + +2018-03-21 11:30:02 +0100 Martin Fleisz (e9ba4b58e) + + * cssp: Fix warnings (#4503) + +2018-03-21 12:34:46 +0100 akallabeth (31a687a24) + + * Merge pull request #4505 from bmiklautz/nightlies_bionic + +2018-03-21 12:00:01 +0100 Bernhard Miklautz (8b73612fe) + + * pkg freerdp-nightly: fix build on bionic + +2018-03-20 11:02:40 +0100 akallabeth (de83f4df2) + + * Merge pull request #4499 from mfleisz/cssp_v6 + +2018-03-20 09:57:30 +0100 Martin Fleisz (8df96364f) + + * cssp: Add support for protocol version 6 + +2018-03-19 19:12:02 +0100 David Fort (103686eb1) + + * Merge pull request #4497 from akallabeth/kwin_multimon + +2018-03-19 11:54:06 +0100 Armin Novak (338e74a6f) + + * Fix #2707: Set fullscreen first + +2018-03-17 17:07:48 +0100 David Fort (980bc9cef) + + * Merge pull request #4495 from akallabeth/header_fix + +2018-03-17 15:25:06 +0100 Armin Novak (87ebdf005) + + * Fixed #4493: duplicate typedef. + +2018-03-14 14:34:01 +0100 akallabeth (f8baeb724) + + * Merge pull request #4487 from bmiklautz/KB4088776 + +2018-03-14 13:39:23 +0100 Bernhard Miklautz (e7ae3f6ba) + + * fix nla: don't use server version + +2018-03-12 16:11:48 +0100 Martin Fleisz (8cd156afd) + + * Merge pull request #4473 from akallabeth/mac_timer + +2018-03-08 13:46:46 +0100 Armin Novak (9bd13c25c) + + * Added WaitableTimer implementation for mac OS. + +2018-03-09 14:25:45 +0100 Armin Novak (f430b55ab) + + * Detect command line flags in case RDP or MSINCIDENT files are used. + +2018-03-08 10:58:47 +0100 Armin Novak (d1fc0e92b) + + * Added additional mouse mappings. + +2018-03-06 15:52:24 +0100 Armin Novak (1c72127c6) + + * Do not clear invalid region if no client connected. + +2018-03-06 15:43:54 +0100 Armin Novak (2ad5b3510) + + * Fixed windows shadow server update copy. + +2018-03-07 15:13:22 +0100 Martin Fleisz (14997f96e) + + * Merge pull request #4471 from akallabeth/thread_function_fix + +2018-03-07 14:47:06 +0100 Armin Novak (44eebbb6e) + + * Fixed compiler warnings. + +2018-03-07 12:42:17 +0100 Armin Novak (66cc038c9) + + * Fixed threadpool work function return and arguments. + +2018-03-07 12:03:10 +0100 Armin Novak (2517755d2) + + * Fixed thread function return and parameters. + +2018-03-07 14:05:22 +0100 akallabeth (dd538ccd4) + + * Merge pull request #4470 from mfleisz/misc_fixes + +2018-03-07 13:47:23 +0100 akallabeth (ce61ec1d3) + + * Merge pull request #4464 from perkerk/misc-windows-client + +2018-03-07 04:40:18 -0600 Eric Brown (e3adeb105) + + * Remove NULL check before _aligned_free call + +2018-03-07 04:30:15 -0600 Eric Brown (2e0253ae3) + + * Clean up mf_uninit + +2018-03-07 10:17:17 +0100 Martin Fleisz (91ee4c2e9) + + * Merge pull request #4454 from akallabeth/nightly + +2018-03-06 16:35:56 +0100 Martin Fleisz (2396e37d8) + + * rdpei: Fix possible NULL ptr access + +2018-03-06 16:34:36 +0100 Martin Fleisz (9b4de7903) + + * drive: Fix possible NULL ptr access + +2018-03-06 16:32:36 +0100 Martin Fleisz (900aa9479) + + * debug: Fix broken format specifiers + +2018-03-06 16:03:13 +0100 Martin Fleisz (ffa5fb07c) + + * drdynvc: Fix possible NULL pointer accesses + +2018-03-06 16:02:28 +0100 Martin Fleisz (0599a3cdb) + + * codec: Another realloc fix + +2018-03-06 15:52:34 +0100 Martin Fleisz (811406382) + + * core: Fix possible out-of-bounds read + +2018-03-06 15:39:03 +0100 Martin Fleisz (07f05c5cb) + + * nla: Add NULL pointer check + +2018-03-06 15:34:55 +0100 Martin Fleisz (ba5ad2e2f) + + * codec: Prevent invalid mem access on realloc failure + +2018-03-06 15:32:04 +0100 Martin Fleisz (21eeea2ce) + + * codec: Fix broken reallocs + +2018-03-06 15:08:57 +0100 Bernhard Miklautz (01388c17e) + + * Merge pull request #4468 from akallabeth/transport_fix_handle + +2018-03-06 13:58:40 +0100 Armin Novak (a419677e8) + + * Fix invalid handle offset. + +2018-03-05 13:20:41 -0600 Eric Brown (930ccb6b7) + + * Fix memory leak of Decompress buffer in client wf_Bitmap_Free + +2018-03-05 12:32:42 -0600 Eric Brown (d8151c03d) + + * Remove unnecessary WM_SETCURSOR handling from wf_event_proc + +2018-03-02 12:42:04 -0600 Eric Brown (0c24ade66) + + * Misc fixes for Windows clients + +2018-03-02 12:39:59 -0600 Eric Brown (4c099866e) + + * Support EmbeddedWindow in wf_resize_window + +2018-03-02 12:39:28 -0600 Eric Brown (3c52e3dd7) + + * Fix H.264 codec init access violation on Windows N/KN systems + +2018-03-01 12:39:29 +0100 Armin Novak (47110a723) + + * Removed duplicate checks, more functions static. + +2018-03-01 12:08:47 +0100 Martin Fleisz (4d401b44c) + + * Merge pull request #4459 from akallabeth/surface_cmd_fix + +2018-02-28 10:10:09 +0100 Armin Novak (1f7d33a2f) + + * Fixed read/write of surface bits command. + +2018-02-21 16:56:55 +0100 Martin Fleisz (8e5d5fa8e) + + * Merge pull request #4450 from akallabeth/assist_fix + +2018-02-21 13:14:45 +0100 Armin Novak (62f06ed11) + + * Use a custom command to generate helper tool + +2018-02-20 11:10:57 +0100 Martin Fleisz (ffcee7307) + + * Merge pull request #4451 from akallabeth/gsm_leak_fix + +2018-02-19 17:28:32 +0100 Martin Fleisz (3cfa837b0) + + * Merge pull request #4441 from akallabeth/paa + +2018-02-19 14:03:49 +0100 Armin Novak (6623927fe) + + * Free gsmBuffer on channel close. + +2018-02-19 13:05:53 +0100 Armin Novak (3b67190d1) + + * Clean up GSM context on channel close. + +2018-02-19 10:00:54 +0100 Armin Novak (68641f109) + + * Fixed .rdp and .msrcIncident checks. + +2018-02-19 10:00:23 +0100 Armin Novak (212a448a3) + + * Added assistance file name NULL check. + +2018-02-16 15:45:01 +0100 MartinHaimberger (c27600528) + + * Merge pull request #4448 from akallabeth/nightly_manpage_fix + +2018-02-16 13:45:18 +0100 Armin Novak (b9e90bc25) + + * Reenable -DWITH_SANITIZE_ADDRESS=ON for i386 builds. + +2018-02-16 13:42:10 +0100 Armin Novak (b2428767b) + + * manpage helper tool generation fixes + +2018-02-16 10:54:03 +0100 Martin Fleisz (5077e8868) + + * Merge pull request #4447 from akallabeth/apple_rpath_namespace + +2018-02-16 10:05:28 +0100 Armin Novak (c68e34b10) + + * Fixed apple rpath settings. + +2018-02-16 10:05:11 +0100 Armin Novak (10aabdd63) + + * Removed apple flat-namespace hack. + +2018-02-16 09:30:27 +0100 David Fort (420f34f63) + + * Merge pull request #4446 from akallabeth/sam_crash_fix + +2018-02-16 08:57:05 +0100 Armin Novak (e36d87b55) + + * Fix #4445: Do not call fclose on NULL file. + +2018-02-15 12:22:50 +0100 Martin Fleisz (3c4385e1f) + + * Merge pull request #4440 from akallabeth/silence_unused_profiler + +2018-02-15 10:19:15 +0100 Armin Novak (1a902c249) + + * Fix PROFILER_* macros + +2018-02-15 11:02:37 +0100 Martin Fleisz (5d1ff02d0) + + * Merge pull request #4414 from akallabeth/pthread_cleanup_fix + +2018-02-13 16:40:23 +0100 Jacco Braat (2af67baea) + + * Modified RDG connection setup using PAA Cookie. Skip NTLM auth on + the IN/OUT channels. Add PAACookie to TUNNEL_CREATE. + +2018-02-13 14:59:33 +0100 Jacco Braat (b59268473) + + * Added to rdp file parsing: gatewayaccesstoken:s: Added to + commandline parsing: /gat: Added GatewayAccessToken + to sings + +2018-02-15 10:39:33 +0100 Martin Fleisz (19a00f209) + + * Merge pull request #4325 from akallabeth/fixes_com + +2018-02-15 10:06:05 +0100 Martin Fleisz (6283ce8a2) + + * Merge pull request #4415 from akallabeth/drdynvc_dyn_log + +2018-02-14 15:54:13 +0100 Martin Fleisz (13be71381) + + * Merge pull request #4434 from akallabeth/winpr_digest_param + +2018-02-14 15:02:53 +0100 Martin Fleisz (dae62c050) + + * Merge pull request #4438 from akallabeth/gw_doublefree_fix + +2018-02-14 14:09:12 +0100 Armin Novak (92c62b1db) + + * Fixed #4436: double free of http response. Fixed #4436: reset of + token split. + +2018-02-14 14:13:52 +0100 Martin Fleisz (159210eb1) + + * Merge pull request #4435 from akallabeth/refguid_static + +2018-02-14 13:16:36 +0100 Armin Novak (89859d4c5) + + * Fixed missing error return. + +2018-02-14 13:05:39 +0100 Armin Novak (77a9e2edf) + + * Do not export internal variables. + +2018-02-14 12:58:48 +0100 Martin Fleisz (0a35c0613) + + * Merge pull request #4432 from akallabeth/pubsub_fix + +2018-02-14 12:44:12 +0100 Armin Novak (5903d5b37) + + * Fixed winpr digest type. + +2018-02-14 11:18:26 +0100 Armin Novak (fca5df896) + + * Fixed broken extern C + +2018-02-14 10:14:33 +0100 Armin Novak (990b8c23a) + + * Fixed PubSub function pointer casts. + +2018-02-14 10:52:24 +0100 akallabeth (ed4f54ab4) + + * Merge pull request #4428 from hardening/video_fixes + +2018-02-14 10:15:51 +0100 David Fort (6e5d86f33) + + * http: fix compilation with valgrind memcheck helpers + +2018-02-14 10:12:32 +0100 David Fort (441975a4a) + + * video, geometry: fix prototypes for timer callbacks + +2018-02-13 15:55:17 +0100 David Fort (484abe056) + + * video: fix invalid geometry and invalid argument passing to time + pubsub + +2018-02-13 17:50:10 +0100 Bernhard Miklautz (e88d1e944) + + * Merge pull request #4430 from bmiklautz/rpmversion + +2018-02-13 16:36:20 +0100 Bernhard Miklautz (7358c425c) + + * pkg rpm: fix perapre script for freerdp-nightly + +2018-02-13 16:32:49 +0100 Bernhard Miklautz (8379fd833) + + * pkg rpm: add version information to freerdp-nightly + +2018-02-13 16:04:48 +0100 Bernhard Miklautz (50f3d1a16) + + * pkg rpm: add prepare script for freerdp-nightly + +2018-02-13 15:26:44 +0100 Bernhard Miklautz (8566021a1) + + * Merge pull request #4425 from akallabeth/windows_nego_fix + +2018-02-13 14:37:13 +0100 Martin Fleisz (bc4b57c08) + + * Merge pull request #4426 from akallabeth/pointer_null_fix + +2018-02-13 13:48:45 +0100 Martin Fleisz (b8599b08f) + + * Merge pull request #4364 from akallabeth/gateway_refactor + +2018-02-09 13:13:16 +0100 Armin Novak (a6a57e361) + + * Prefer dynamic logger in dynamic channel. + +2018-02-13 13:43:21 +0100 Martin Fleisz (8a2b5eaa0) + + * Merge pull request #4376 from hardening/ms-rdpevor + +2018-02-13 13:38:02 +0100 Armin Novak (7274ffe6a) + + * Check if xfreerdp window != NULL + +2018-02-13 11:00:56 +0100 Armin Novak (53d2150e0) + + * Fixed windows unicode authentication. + +2018-02-12 15:32:56 +0100 Armin Novak (af8286b97) + + * Added missing FREERDP_API function export. + +2018-02-08 09:47:41 +0100 Armin Novak (79d9ae877) + + * Fixed gemoetry mapping. + +2018-02-08 09:45:35 +0100 Armin Novak (d9277b7fb) + + * Fixed copy offset issue. + +2018-02-08 08:55:27 +0100 Armin Novak (3eb004042) + + * Fixed code duplication. + +2018-02-08 08:44:46 +0100 Armin Novak (c7d701bdf) + + * Added software decoding fallback for RDPVOR + +2018-02-08 07:49:50 +0100 Armin Novak (11f11a876) + + * Fixed scaled drawing of video content. + +2018-02-07 17:13:14 +0100 David Fort (73bef4ca2) + + * video, geometry: fixed geometry handling + +2018-02-02 10:32:21 +0100 David Fort (b8e3b232d) + + * video: mutualize things in the common channel code + +2018-01-30 17:57:45 +0100 David Fort (0743559d9) + + * video: do cleanups in post_connect + +2018-01-30 11:36:17 +0100 David Fort (73eb4ba77) + + * drdynvc: fixed stream leak on error + +2018-01-30 11:35:23 +0100 David Fort (731ef4f8c) + + * geometry: drop server-side option for geometry + +2018-01-30 11:34:27 +0100 David Fort (ca4f75ccd) + + * video: fixed uninit of channel + +2018-01-26 15:21:49 +0100 David Fort (4b240dad0) + + * video+geometry: fixed leaks, a segfault and concurrent accesses + +2018-01-23 16:09:21 +0100 David Fort (6e022ae07) + + * video: fix prototype and cleanup at exit + +2017-12-15 11:15:24 +0100 David Fort (a07efb73e) + + * video: an implementation of MS-RDPEVOR for X11 + +2017-12-07 22:50:29 +0100 David Fort (b84839b21) + + * video: a skeleton for MS-RDPEVOR client + +2017-12-15 11:16:34 +0100 David Fort (adac409d1) + + * geometry: change the channel API to mutualize things + +2018-02-13 10:43:49 +0100 David Fort (c44605299) + + * Merge pull request #4423 from akallabeth/double_free + +2018-02-13 10:18:43 +0100 Armin Novak (2cf10cc35) + + * bitmap free now always deallocating all resources. + +2018-02-12 13:51:57 +0100 David Fort (90f60c7ce) + + * Merge pull request #4421 from akallabeth/x11_asan_fix_v2 + +2018-02-12 11:14:54 +0100 Armin Novak (62607e3b0) + + * Fixed accidental free of XImage data. + +2018-02-09 12:25:45 +0100 Armin Novak (2d58e96dc) + + * Exit main thread with winpr_exit to trigger resource cleanup. + +2018-02-12 10:27:19 +0100 MartinHaimberger (3293b4247) + + * Merge pull request #4420 from akallabeth/x11_memleak_fix + +2018-02-12 10:02:35 +0100 Armin Novak (7c0a33632) + + * Fixed #4412: XImage must be freed with XDestroyImage + +2018-02-09 12:42:43 +0100 Martin Fleisz (2bc9869c8) + + * Merge pull request #4413 from akallabeth/memlead_queue_fixes + +2018-02-09 12:08:39 +0100 Armin Novak (7e26c5486) + + * Set up and tear down WLog + +2018-02-09 11:42:18 +0100 Armin Novak (1b9da0161) + + * Fixed cleanup of xfc->drawable. + +2018-02-09 11:41:53 +0100 Armin Novak (50c7777bb) + + * Prevent malloc of size 0 + +2018-02-09 10:39:46 +0100 Armin Novak (8c7fe93cc) + + * Added client channel queue object free function. + +2018-02-09 10:29:31 +0100 Armin Novak (1ec1c9b7a) + + * Add dynamic channel queue object free function. + +2018-02-09 10:29:18 +0100 Armin Novak (855dc9aba) + + * Clear message queue on free. + +2018-02-09 10:23:48 +0100 Armin Novak (25076cfce) + + * Fixed a memory leak. + +2018-02-09 09:40:00 +0100 Martin Fleisz (eb2da0844) + + * Merge pull request #4411 from akallabeth/resolve_ipv6_fix + +2018-02-09 09:35:26 +0100 Armin Novak (d181c7946) + + * Fixed rail window cleanup. + +2018-02-08 16:31:26 +0100 Armin Novak (78de329f1) + + * Fixed IPv4/IPv6 to string + +2018-02-08 16:53:09 +0100 Armin Novak (6950d95af) + + * Fix #4398: Ignore min/max info for non existing window. + +2018-02-08 16:25:21 +0100 Norbert Federa (5b2d803e3) + + * Merge pull request #4380 from akallabeth/output_suppress_minimize + +2018-02-08 13:55:36 +0100 Armin Novak (ed9d86b1a) + + * Fixed GFX output expose. + +2018-02-08 10:34:49 +0100 Armin Novak (c0ec81c3c) + + * Do not update client if output suppressed. + +2018-02-08 11:55:57 +0100 Armin Novak (253beda33) + + * Fixed formatting. + +2018-01-24 16:26:27 +0100 Armin Novak (17b17d609) + + * Fixed SuppressOutput update. + +2018-02-07 15:19:16 +0100 Bernhard Miklautz (a4a151aa1) + + * Merge pull request #4408 from vinzent/rpm_spec_rhel7 + +2018-02-07 15:03:35 +0100 Martin Fleisz (f1a471751) + + * Merge pull request #4347 from akallabeth/h264_log + +2018-02-07 14:33:02 +0100 David Fort (4a21c3b28) + + * Merge pull request #4409 from akallabeth/init_once_return + +2018-02-07 13:32:01 +0100 Armin Novak (fde818c6f) + + * Fixed FFMPEG log messages. + +2018-02-07 10:45:28 +0100 Armin Novak (fac61bf48) + + * Use dynamic logger in MediaFoundation backend + +2018-01-19 14:26:04 +0100 Armin Novak (aff9a2236) + + * Fixed obsolete TAG definitions and use. + +2018-01-17 15:35:11 +0100 Armin Novak (77d0c77ed) + + * Fix OpenH264 trace logging, set up context first + +2018-01-09 17:22:56 +0100 Armin Novak (7adc384d9) + + * Using dynamic logger for GFX-H264 backend. + +2018-02-07 13:13:02 +0100 Armin Novak (c586a300c) + + * Fixed init once return. + +2018-02-07 09:33:44 +0100 Thomas Mueller (24720b614) + + * Update rpm spec to support RHEL 7 + +2018-02-07 13:00:00 +0100 Norbert Federa (1a377ba97) + + * Merge pull request #4392 from akallabeth/yuv_asm + +2018-02-07 12:56:31 +0100 Bernhard Miklautz (db8519fd8) + + * Merge pull request #4397 from SriRamanujam/vaapi + +2018-02-07 12:34:27 +0100 Bernhard Miklautz (c7f1656ea) + + * Merge pull request #4400 from hardening/defines_clean + +2018-02-07 10:17:10 +0100 Armin Novak (1d99696db) + + * Fixed AVC444 YUV conversion matrix + +2018-02-02 08:45:13 +0100 Armin Novak (53cdd95de) + + * Refactored RGB to AVC444v2 + +2018-01-31 11:33:55 +0100 Armin Novak (eb8e9cb41) + + * Added SSSE3 UV average to AVC444v1 + +2018-01-30 16:16:39 +0100 Armin Novak (46159c4ca) + + * Added UV average to AVC444v1 + +2018-02-07 10:34:18 +0100 David Fort (7ceb85c7a) + + * Merge pull request #4340 from akallabeth/init_once + +2018-02-07 10:33:33 +0100 MartinHaimberger (71bd654fd) + + * Merge pull request #4395 from akallabeth/afreerdp_clipboard_fix + +2018-02-07 10:32:05 +0100 MartinHaimberger (5e7b94530) + + * Merge pull request #4387 from akallabeth/hotplug_fix + +2018-02-07 10:30:26 +0100 MartinHaimberger (175361b01) + + * Merge pull request #4394 from akallabeth/shadow_avc444 + +2018-02-07 08:34:49 +0100 akallabeth (6299a3e3c) + + * Merge pull request #4406 from rozhuk-im/master + +2018-02-07 03:15:58 +0300 rim (6ce9fb555) + + * Fix: #define ConvertColor FreeRDPFreeRDPConvertColor -> + FreeRDPConvertColor + +2018-02-05 14:34:49 +0100 David Fort (6c64aa4e2) + + * fixed include path + +2018-02-04 23:16:12 +0100 David Fort (917bc4b55) + + * set some define consistency + +2018-02-02 15:49:59 -0500 Sri Ramanujam (26eee4aec) + + * TO BE SQUASHED: use hw_frames_ctx to set up vaapi on older versions + of libavcodec + +2018-02-02 14:30:31 -0500 Sri Ramanujam (edf9c52c6) + + * TO BE SQUASHED: initial changes from code review + +2018-02-02 13:57:00 +0100 Armin Novak (bb061cedb) + + * Increased target bitrate for shadow server. + +2018-02-02 11:03:27 +0100 Armin Novak (bc33fa8b1) + + * Tuned FFMPEG encoder settings. + +2018-02-02 10:41:20 +0100 Armin Novak (92811ea5b) + + * Added return checks. + +2018-02-02 08:13:44 +0100 Armin Novak (5f439f06b) + + * Fixed AVC444v2 detection. + +2018-02-02 08:06:32 +0100 Armin Novak (9f57e07a2) + + * Align YUV buffer strides and height. + +2018-01-31 15:08:11 +0100 Armin Novak (3b70d1178) + + * Added AVC444 chroma support to shadow server. + +2018-01-27 01:10:51 -0500 Sri Ramanujam (bedc1ac4c) + + * Use libavcodec's VA-API decoding. + +2018-02-01 18:43:15 +0100 David Fort (a90be5609) + + * Merge pull request #4396 from bmiklautz/fix_nightlies + +2018-02-01 17:10:36 +0100 Bernhard Miklautz (1e842d268) + + * fix deb/freerdp-nightly: disable ASAN on i386 + +2018-02-01 16:59:55 +0100 Bernhard Miklautz (db2d1ffcc) + + * cmdline refactor: move cmd struct to extra file + +2018-02-01 09:34:07 +0100 Armin Novak (7183c5019) + + * Check length of string returned by ClipboardGetData + +2018-01-31 13:31:21 +0100 Norbert Federa (d5ef9629a) + + * Merge pull request #4393 from + nfedera/fix-remove-expensive-channel-send-debug + +2018-01-31 12:44:45 +0100 Norbert Federa (46f03d5e7) + + * disabled expensive debug call in channel send + +2018-01-30 16:16:44 +0100 David Fort (bfd370a9a) + + * Merge pull request #4391 from akallabeth/yuv_asm + +2018-01-30 14:51:56 +0100 Armin Novak (c82610c30) + + * Deactiveate optimized primitives if no implementation compiled. + +2018-01-26 12:53:08 +0100 Armin Novak (8f7bc7990) + + * Added SSE optimized RGB to AVC444 frame split and test. + +2018-01-26 12:52:16 +0100 Armin Novak (ce10e22b8) + + * Added optimized C function for specific color format. + +2018-01-25 09:43:48 +0100 Armin Novak (f27ee2e3a) + + * Split optimized YUV implementations to separate files. + +2018-01-29 08:44:13 +0100 akallabeth (28db3a69a) + + * Merge pull request #4389 from hardening/primitives + +2018-01-28 22:15:54 +0100 David Fort (5e4866469) + + * primitives: use INIT_ONCE instead of static booleans + +2018-01-25 15:43:53 +0100 Armin Novak (64cfd750f) + + * Fixed #4384: Drive hotplug detection + +2018-01-24 17:42:23 +0100 akallabeth (670573920) + + * Merge pull request #4381 from bmiklautz/suse_asan + +2018-01-24 16:56:03 +0100 Bernhard Miklautz (cca597804) + + * fix freerdp-nightly on suse: disable asan + +2018-01-24 15:57:33 +0100 Bernhard Miklautz (f0a1e7309) + + * Merge pull request #4379 from akallabeth/memleak_fix + +2018-01-24 14:11:33 +0100 Armin Novak (60ab8cc72) + + * Fixed memory leak. + +2018-01-23 17:57:47 +0100 Bernhard Miklautz (32cc6e16e) + + * Merge pull request #4328 from akallabeth/nightly_sanitize_address + +2018-01-22 23:00:40 +0100 David Fort (bdcb1a349) + + * Merge pull request #4375 from akallabeth/memleak + +2018-01-22 15:45:27 +0100 Armin Novak (7f75b57fd) + + * Fixed memory leak. + +2018-01-19 10:59:10 +0100 Armin Novak (0fc19e559) + + * Functions static where appropriate. + +2018-01-19 10:34:08 +0100 Martin Fleisz (bab902f59) + + * Merge pull request #4373 from akallabeth/warning_fixes2 + +2018-01-19 09:13:40 +0100 Armin Novak (e1c00b878) + + * Fixes argument size type, function static where appropriate. + +2018-01-17 19:31:29 +0100 Bernhard Miklautz (3c45a6089) + + * Merge pull request #4367 from akallabeth/android_version_next + +2018-01-17 19:29:09 +0100 Bernhard Miklautz (30ed6aaa2) + + * Merge pull request #4369 from akallabeth/openh264_update + +2018-01-17 15:26:33 +0100 Armin Novak (45abdc94d) + + * Updated OpenSSL version for android. + +2018-01-17 15:23:19 +0100 Armin Novak (1f12b2af6) + + * Updated to OpenH264 1.7 and relocatable binaries. + +2018-01-17 12:03:05 +0100 Armin Novak (91280b3ea) + + * Updated gradle build version and dependencies. + +2018-01-17 11:05:04 +0100 David Fort (e81b554ab) + + * Merge pull request #4365 from + akallabeth/negociate_context_reset_fix + +2018-01-17 09:09:58 +0100 Armin Novak (29f2d2d9b) + + * Fixed missing packageName setup in server NLA + +2018-01-17 08:17:33 +0100 Armin Novak (0e1a07338) + + * Simplified package name comparisons. + +2018-01-17 08:12:54 +0100 Armin Novak (dc3d53639) + + * Changed length arguments and return to size_t + +2018-01-16 11:34:07 +0100 Armin Novak (dc48c4292) + + * Refactored NTLM, functions static where approprate + +2018-01-16 10:58:30 +0100 Armin Novak (1611ec16b) + + * Refactored kerberos SSPI * Functions static where approrpriate * + Variables static const where appropriate + +2018-01-16 10:37:19 +0100 Armin Novak (609a4eb6a) + + * Fixed ICU support for CP_ACP + +2018-01-16 10:31:08 +0100 Armin Novak (c62fde53a) + + * Fix #4306: * Do not reset context when changing package. * All + functions not exported static. + +2018-01-16 08:15:34 +0100 Armin Novak (20b4b286f) + + * Fixed strtoull not supported on windows. + +2018-01-15 16:50:01 +0100 Armin Novak (a49a2299b) + + * Refactored http parser + +2018-01-15 12:43:37 +0100 Armin Novak (c3f008c36) + + * Functions static where appropriate. + +2018-01-15 11:18:59 +0100 Martin Fleisz (8f52c7ed8) + + * Merge pull request #4362 from akallabeth/ifdef_fix + +2018-01-15 10:18:03 +0100 Armin Novak (59e8b6728) + + * Fixed broken #ifdef + +2018-01-15 10:13:26 +0100 akallabeth (3b719ae7d) + + * Merge pull request #4359 from MartinHaimberger/yuvfix + +2018-01-15 09:57:23 +0100 David Fort (2304f76eb) + + * Merge pull request #4358 from akallabeth/ntlm_debug_fix + +2018-01-12 09:00:59 +0100 Armin Novak (97cc55dee) + + * Fixed bitmap capability debug. + +2018-01-12 08:57:20 +0100 Armin Novak (5550f6ffe) + + * Fixed #4357: NTLM debug message. + +2018-01-12 00:08:56 -0800 Martin Haimberger (94a58bd18) + + * YUV conversation: fixed luma frame creation + +2018-01-11 17:46:12 +0100 akallabeth (792a75c46) + + * Merge pull request #4355 from + jukeks/topic/smartcard_status_cbAtrLen + +2018-01-11 16:19:02 +0200 Jukka-Pekka Virtanen (2e8f2c693) + + * [MS-RDPESC] 2.2.2.18 Status_Call.cbAtrLen: Unused. MUST be ignored + upon receipt. + +2018-01-10 15:33:13 +0100 MartinHaimberger (b6a1af0ba) + + * Merge pull request #4349 from akallabeth/primitives_update + +2018-01-10 09:16:59 +0100 Armin Novak (23e1afb44) + + * Added new and optimized YUV primitives. + +2018-01-10 09:57:54 +0100 David Fort (ab94f6a5f) + + * Merge pull request #4339 from akallabeth/gdi_sw_crash_fix + +2017-12-20 16:16:33 +0100 Armin Novak (51e59e1f2) + + * Check argument, xfc->window is NULL in RAILS mode + +2017-12-20 16:15:22 +0100 Armin Novak (e23af1d2f) + + * Fixed missing argument checks. + +2017-12-20 16:13:42 +0100 Armin Novak (ac1d6e815) + + * Fixed #3676, #4269: Screen update for RAIL with GFX + +2017-12-20 15:00:21 +0100 Armin Novak (4dd0ccd70) + + * Added argument checks. + +2017-12-20 14:52:28 +0100 Armin Novak (674fae5ce) + + * Refactored function visibility. + +2018-01-08 13:07:11 +0100 Armin Novak (9804d5a4a) + + * SamOpen return NULL if file was not opened. + +2018-01-08 13:03:06 +0100 Armin Novak (5140ee09b) + + * Reduced log priority in gdi_CRgnToRect + +2018-01-08 10:44:51 +0100 Armin Novak (899666ee1) + + * Fixed #2006: Use InitOnceExecuteOnce + +2018-01-08 10:37:48 +0100 Armin Novak (d03f9858a) + + * Fixed #2006: Use InitOnceExecuteOnce + +2018-01-08 11:16:21 +0100 David Fort (e1cc60196) + + * Merge pull request #4323 from akallabeth/scanbuild_fixes + +2018-01-08 10:01:50 +0100 akallabeth (f7f52c4b6) + + * Merge pull request #4338 from 2asoft/2asoft/fix-html-clipboard + +2018-01-08 09:29:25 +0100 David Fort (88c9b1fac) + + * Merge pull request #4333 from akallabeth/drive_param_check_fix + +2018-01-08 09:21:53 +0100 akallabeth (900ec855d) + + * Merge pull request #4334 from h3xx/fix-ffmpeg-support + +2018-01-08 09:20:56 +0100 akallabeth (4077d55a6) + + * Merge pull request #4332 from hardening/xrandr_and_fixes + +2018-01-08 08:57:45 +0100 Armin Novak (bcf3babca) + + * Fixed #4336: Initialize rectangle. + +2018-01-06 18:45:22 -0800 Anton Afanasyev (ed2e4e576) + + * StartHTML and EndHTML values can be left-padded with 0 characters. + strtol and friends treat this as base-8 if base is + specified as 0. Because these values are always sent in + base-10, fix is to always use base-10 + +2018-01-04 16:56:47 -0500 Mike Gilbert (db5628f6f) + + * Merge pull request #4335 from floppym/ssse3 + +2017-12-29 14:00:24 -0500 Mike Gilbert (51cdd8df1) + + * codec/nsc_sse2: add runtime CPU feature check + +2017-12-29 13:44:33 -0500 Mike Gilbert (082aac83a) + + * cmake: do not add -msse2/-msse3 globally + +2017-12-24 16:58:07 -0500 Mike Gilbert (9bfe2fcfb) + + * cmake: rework logic to apply -msse2, -msse3, -mssse3 to specific + files + +2017-12-29 10:59:45 -0600 Dan Church (ed571e74a) + + * Provide support for older versions of libavcodec + +2017-12-29 10:29:02 +0100 David Fort (4889652c1) + + * Merge pull request #4327 from akallabeth/disconnect_fix + +2017-12-28 19:53:15 +0100 David Fort (4e421793b) + + * Merge pull request #4329 from akallabeth/sw_gdi_fix + +2017-12-28 09:41:45 -0600 Dan Church (78df32c77) + + * Fix future ffmpeg support + +2017-12-28 14:05:11 +0100 akallabeth (27aac21c0) + + * Fixed drive redirection argument check + +2017-12-23 13:50:54 +0100 David Fort (191b8f950) + + * Fix for #4330 + +2017-12-23 10:27:38 +0100 David Fort (58b5573c8) + + * Use more xrandr attributes when available and preserve + [desktop|device]ScaleFactor + +2017-12-23 10:26:25 +0100 David Fort (158840429) + + * micro code style changes + +2017-12-22 17:55:48 +0100 David Fort (5e2d6ea02) + + * zgfx: add a check + +2017-12-22 13:43:37 +0100 Armin Novak (cf899eb5b) + + * Fix #4299: gdi_CRgnToRect + +2017-12-22 11:42:31 +0100 Armin Novak (ff474939d) + + * Activated address sanitizer for nightly builds. + +2017-12-22 11:09:23 +0100 Armin Novak (5144e6e60) + + * Exit client thread if freerdp_connect fails + +2017-12-22 10:37:04 +0100 Armin Novak (c60c355a9) + + * Added ROP to primary order debug message. + +2017-12-22 10:25:05 +0100 Armin Novak (b293b17ac) + + * Added ROP to string functions for log messages. + +2017-12-21 15:19:29 +0100 Armin Novak (4483751e0) + + * Fixed help for /parallel + +2017-12-21 15:16:24 +0100 Armin Novak (d823586c3) + + * Fixed parallel channel argument checks + +2017-12-21 14:39:43 +0100 Armin Novak (04708b37e) + + * Fixed serious issues with SAM file parser + +2017-12-21 14:39:32 +0100 Armin Novak (6f1b8f04c) + + * Fixed check for reserved com devices. + +2017-12-21 11:34:44 +0100 Armin Novak (1d01582a8) + + * Fixed dead store warnings. + +2017-12-21 11:30:21 +0100 Armin Novak (a0b49f4e0) + + * Removed unused functions, fixed feature define guards + +2017-12-21 11:27:08 +0100 Armin Novak (50a0968c6) + + * Removed unused variables. + +2017-12-21 11:25:39 +0100 David Fort (7c3d75bf1) + + * Merge pull request #4319 from akallabeth/fullscreen_legacy_fix + +2017-12-21 11:04:50 +0100 Armin Novak (9c93c6cbf) + + * Fixed unused variable warnings. + +2017-12-21 11:04:32 +0100 Armin Novak (e4766c656) + + * Fixed missing initialization warnings. + +2017-12-21 10:45:55 +0100 Armin Novak (bb7ba6ff2) + + * Fixed smartcard related scanbuild warnings. + +2017-12-21 09:51:33 +0100 Martin Fleisz (2ba49722c) + + * Merge pull request #4321 from akallabeth/rdp_parser_fix + +2017-12-21 09:34:35 +0100 Armin Novak (6a21bdae3) + + * Fixed various scanbuild warnings. + +2017-12-20 17:01:58 +0100 akallabeth (e3e65734e) + + * Merge pull request #4303 from + krisztian-kovacs-balabit/use-redirection-password + +2017-12-20 12:02:23 +0100 Armin Novak (1628045f6) + + * Fullscreen without _NET_WM_FULLSCREEN_MONITORS + +2017-12-20 14:17:20 +0100 Martin Fleisz (80a49f46d) + + * Merge pull request #4320 from ondrejholy/coverity-fixes + +2017-12-20 13:43:14 +0100 Armin Novak (a20247642) + + * Fixed RDP file parser for unicode. + +2017-12-20 13:43:22 +0100 Martin Fleisz (ec027bf46) + + * Merge pull request #4318 from hardening/display_improvement + +2017-12-20 12:38:38 +0100 Martin Fleisz (bfe8359b5) + + * Merge pull request #4239 from akallabeth/test_memleak_fixes + +2017-12-19 15:16:14 +0100 David Fort (ce89a9096) + + * disp: improve window resizing + +2017-12-19 09:38:24 +0100 David Fort (2a6c9e1b8) + + * Add an activated event and a Timer event + +2017-12-19 14:42:06 +0100 Ondrej Holy (9f5d0d4c4) + + * crypto: Improve PER OID calculations + +2017-12-19 13:49:02 +0100 akallabeth (71fd6f311) + + * Merge pull request #4313 from hardening/dyn_res_update + +2017-12-19 13:02:55 +0100 Ondrej Holy (4791970c0) + + * core: Remove redundant stream position changes + +2017-12-19 12:21:34 +0100 Ondrej Holy (e2f9a0810) + + * tsmf: Prevent string overflow and unterminated strings + +2017-12-19 10:21:03 +0100 Ondrej Holy (0389cb129) + + * core: Fix array overrunning during FIPS keys generation + +2017-12-18 09:42:28 +0100 akallabeth (2b320ea0f) + + * Merge pull request #4315 from MrCsabaToth/patch-1 + +2017-12-16 11:37:32 -0800 Csaba Toth (04a626510) + + * Documentation copy-paste error fix when referring to the Android 64 + bit config + +2017-12-14 16:56:29 +0100 akallabeth (097f8edd9) + + * Merge pull request #4312 from bmiklautz/smartcard-cleanup + +2017-12-14 16:21:19 +0100 Bernhard Miklautz (36c647862) + + * fix client/smartcard: indentation and return value + +2017-12-14 15:46:14 +0100 Bernhard Miklautz (5a1c0081c) + + * fix smartcard: SCardStatus unicode handling + +2017-11-29 10:26:04 +0100 David Fort (80dab90f1) + + * disp: implement dynamic resolution for X11 + +2017-12-13 17:24:41 +0100 Martin Fleisz (5cec90c78) + + * Merge pull request #4305 from hardening/xrandr_fix + +2017-12-13 16:57:53 +0100 Bernhard Miklautz (94b35cb4f) + + * fix channel/smartcard: leak in Connect[AW] + +2017-12-13 15:50:33 +0100 Bernhard Miklautz (bff9b98e6) + + * feat winpr/smartcard: add test for SCardStatus + +2017-12-13 15:46:50 +0100 Bernhard Miklautz (9fc754170) + + * fix channel/smartcard: SCardStatus + +2017-12-11 16:25:46 +0100 Bernhard Miklautz (bc8bdc3e5) + + * fix channel/smartcard: compiler warnings + +2017-12-11 15:49:03 +0100 Bernhard Miklautz (6b691948c) + + * refactor winpr/smartcard/pcsc: reader/group naming + +2017-12-11 15:15:02 +0100 Bernhard Miklautz (389b7f218) + + * feat winpr: add WINPR_UNUSED macro + +2017-12-11 14:31:19 +0100 Bernhard Miklautz (e3d45c458) + + * fix channel/smartcard: remove SCardAddReaderName + +2017-12-11 14:00:09 +0100 Bernhard Miklautz (1e6fea7fa) + + * fix channel/smartcard: simplify channel variables + +2017-12-11 10:33:28 +0100 Bernhard Miklautz (6e63c6afd) + + * fix channel/smartcard: remove status mappings + +2017-12-04 16:16:59 +0100 Bernhard Miklautz (f8a3e7acd) + + * fix channel/smartcard: GetStatusChange return code + +2017-12-04 15:22:07 +0100 Bernhard Miklautz (46a753832) + + * fix channel/smartcard: async request handling + +2017-12-04 12:31:10 +0100 Bernhard Miklautz (3dc4e283d) + + * fix channel/smartcard: return value handling + +2017-12-04 12:17:57 +0100 Bernhard Miklautz (99c69cde2) + + * fix channel/smartcard: error handling + +2017-12-13 09:58:14 +0100 Martin Fleisz (f6b8a6eaa) + + * Merge pull request #4276 from akallabeth/big_endian_more + +2017-12-13 09:09:33 +0100 Martin Fleisz (6aa914363) + + * Merge pull request #4301 from hardening/geometry + +2017-12-12 11:41:43 +0100 Armin Novak (2f35c4b15) + + * Fixed remaining color renaming issues. + +2017-12-12 10:47:17 +0100 Armin Novak (ae2a96293) + + * Cleanup and initialization checks. + +2017-11-15 09:11:12 +0100 Armin Novak (730582812) + + * Fix #4239: Various memory leaks + +2017-12-12 10:40:14 +0100 David Fort (3b670703f) + + * Merge pull request #4277 from akallabeth/mac_server + +2017-12-12 10:35:02 +0100 Armin Novak (0a9ef97a5) + + * Fixed uninitialized variable. + +2017-12-11 10:25:21 +0100 David Fort (41823080f) + + * Fix users of Stream_GetPosition() that returns size_t + +2017-12-06 13:51:45 +0100 David Fort (a6cfd3c49) + + * geometry: a skeleton for the MS-RDPEGT channel + +2017-12-08 10:45:50 +0100 David Fort (11ee81be6) + + * Fix XRandr for old systems and MacOSX + +2017-12-06 16:32:56 +0100 KOVACS Krisztian (7f5f40d39) + + * core/nla: use RedirectionPassword if set in settings + +2017-12-06 16:30:57 +0100 KOVACS Krisztian (3c56300af) + + * winpr/sspi: add possibility to set auth identity with Unicode + password + +2017-12-06 14:58:34 +0100 KOVACS Krisztian (6518e36c7) + + * Revert "core/connection: use redirection password when + reconnecting" + +2017-12-05 14:40:03 +0100 Martin Fleisz (876a7697b) + + * Merge pull request #4297 from akallabeth/cmd_parser_hardening + +2017-12-05 11:19:59 +0100 Martin Fleisz (5931fd4fe) + + * Merge pull request #4294 from akallabeth/shadow_fix + +2017-12-05 10:56:14 +0100 Martin Fleisz (ed9a4b7d4) + + * Merge pull request #4288 from hardening/disp_channel + +2017-12-02 16:09:43 +0100 Bernhard Miklautz (22c71c003) + + * Merge pull request #4298 from myfreeweb/libressl-fix-fips + +2017-12-01 18:34:48 +0300 Greg V (bfe3af4c7) + + * Fix LibreSSL build + +2017-11-28 15:32:15 +0100 David Fort (1e48405d1) + + * drdynvc: fix invalid check + +2017-11-24 14:53:39 +0100 David Fort (e73da4a65) + + * display control channel: add a callback called when we receive + capabilities + +2017-11-30 16:56:45 +0100 Armin Novak (78a0c4c61) + + * Fix #4296: Hardened command line post filter. + +2017-12-01 11:24:50 +0100 akallabeth (0cb590766) + + * Merge pull request #4275 from ondrejholy/big-endian-fixes + +2017-11-29 15:28:37 +0100 David Fort (d2cb79ce9) + + * Merge pull request #4292 from daixj-shterm/master + +2017-11-29 14:17:27 +0100 Armin Novak (877f16146) + + * Reset errno in X11 monitor enumeration + +2017-11-29 14:13:50 +0100 Armin Novak (33271415f) + + * Fixed /monitors argument checks. + +2017-11-29 05:12:40 -0500 daixj (d10448fde) + + * Fix #4291: xfreerdp segfault when connecting freerdp-shadow-cli + +2017-11-24 14:06:35 +0100 David Fort (e064aa6a9) + + * xfreerdp: when available use xrandr to get display infos + +2017-11-28 16:36:32 +0100 akallabeth (2f15b806f) + + * Merge pull request #4287 from bmiklautz/dev2 + +2017-11-28 15:33:03 +0100 Bernhard Miklautz (1cda26274) + + * client/android: increase version + +2017-11-28 15:29:17 +0100 Bernhard Miklautz (ac9b6d15f) + + * 2.0.0-dev2 - start rc2 development cycle + +2017-11-28 15:26:30 +0100 akallabeth (84f816189) + + * Merge pull request #4286 from bmiklautz/rc1 + +2017-11-28 15:03:09 +0100 Bernhard Miklautz (8244370bf) + + * Version 2.0.0-rc1 + +2017-11-28 10:48:53 +0100 David Fort (cf33966f2) + + * Merge pull request #4282 from akallabeth/force_ipv6 + +2017-11-28 10:47:27 +0100 Bernhard Miklautz (cb4b6267e) + + * Merge pull request #4284 from akallabeth/channel_count_fix_v2 + +2017-11-28 09:40:04 +0100 Armin Novak (3e4c274cc) + + * Fixed channel count exceed checks + +2017-11-28 09:19:58 +0100 akallabeth (ae0fb6465) + + * Merge pull request #4283 from bmiklautz/kfreebsd + +2017-11-27 22:46:23 +0100 David Fort (2f4a2f859) + + * Merge pull request #4272 from akallabeth/static_channel_checks + +2017-10-23 10:32:51 +0200 Bernhard Miklautz (0da2fb691) + + * fix/build: handle GNU/kFreeBSD like other BSDs + +2017-10-23 10:31:55 +0200 Mike Gabriel (d4af7eaa5) + + * fix/build: GNU/kFreeBSD is not FreeBSD + +2017-11-27 11:49:46 +0100 Bernhard Miklautz (50105c815) + + * Merge pull request #3991 from akallabeth/stream_string_helper + +2017-11-27 11:46:54 +0100 Bernhard Miklautz (baf52f529) + + * Merge pull request #4261 from akallabeth/doc_ssl_store + +2017-11-27 10:54:49 +0100 Armin Novak (2cc64298f) + + * Fix #4281: Added option to prefer IPv6 over IPv4 + +2017-11-27 10:57:26 +0100 Bernhard Miklautz (73533230a) + + * Merge pull request #4220 from akallabeth/version_from_file_or_tag + +2017-11-27 10:41:06 +0100 Bernhard Miklautz (52c297e50) + + * Merge pull request #4273 from akallabeth/issue_template + +2017-11-27 10:40:44 +0100 Bernhard Miklautz (cd0b05500) + + * Merge pull request #4270 from akallabeth/mac_clipboard_fix + +2017-11-27 10:06:30 +0100 Bernhard Miklautz (640b3e199) + + * Merge pull request #4280 from akallabeth/snd_parser_fix + +2017-11-27 10:03:49 +0100 Armin Novak (153e21ece) + + * Added mailing list address. + +2017-11-27 09:06:31 +0100 Armin Novak (72f2ae571) + + * Added reminder to delete template before submit + +2017-11-23 16:44:00 +0100 Armin Novak (1f0a8480c) + + * Added pull request template. + +2017-11-23 16:34:17 +0100 Armin Novak (8651996cd) + + * Added issue template. + +2017-11-26 14:59:37 +0100 Armin Novak (f96a46acd) + + * Fix #4278: Fix nasty range check bug + +2017-11-24 15:51:46 +0100 David Fort (8f8ce70f3) + + * Merge pull request #4229 from akallabeth/from_stdin_args + +2017-11-24 15:44:15 +0100 Bernhard Miklautz (aa47c8ebe) + + * Merge pull request #4268 from akallabeth/big_endian_fixes + +2017-11-24 13:19:48 +0100 Armin Novak (57958cb17) + + * Fixed #3810: Renamed color functions + +2017-11-24 13:10:30 +0100 Armin Novak (8f27b1a51) + + * Added missing channel defines. + +2017-11-24 12:46:01 +0100 Armin Novak (8eaba5b00) + + * Fixed mac server compilation. + +2017-11-23 12:00:52 +0100 Armin Novak (c91900dfb) + + * Fixed big endian issues with bitmap read. + +2017-11-23 10:47:56 +0100 Armin Novak (13e0d5657) + + * Fixed endianess issues with ncrush. + +2017-11-24 11:14:17 +0100 David Fort (27807bea2) + + * Merge pull request #4271 from akallabeth/surface_c + +2017-11-24 10:43:53 +0100 akallabeth (3ba862d54) + + * Merge pull request #4274 from hardening/clipboard_checks + +2017-11-24 10:24:47 +0100 Ondrej Holy (90000fd36) + + * client/common: Fix two memory leaks in RDP file processing + +2017-11-23 19:51:57 +0100 Ondrej Holy (e5574f276) + + * winpr/nt: Fix wide char string on big endian + +2017-11-23 18:22:48 +0100 Ondrej Holy (5dcd1ebb0) + + * client/common: Fix RDP file processing on big endian + +2017-11-23 17:37:55 +0100 David Fort (a5af2cc86) + + * clipboard: add some checks for the message + +2017-11-23 16:18:44 +0100 Armin Novak (377bfeb22) + + * Fix #3378: 31 static channels are supported. + +2017-11-23 15:35:52 +0100 David Fort (d982cf0e9) + + * Merge pull request #4255 from akallabeth/rfx_fix + +2017-11-23 15:10:42 +0100 Armin Novak (f68bc07a2) + + * Fixed return value check for callbacks. + +2017-11-23 12:53:39 +0100 Armin Novak (65a97b13c) + + * Fixed #1536: Clipboard data size. + +2017-11-23 10:49:15 +0100 akallabeth (71e38a4ce) + + * Merge pull request #4267 from ondrejholy/autofips + +2017-11-22 19:41:35 +0100 Ondrej Holy (74bbbdb5c) + + * Remove unused variable + +2017-11-22 19:25:32 +0100 Ondrej Holy (6973b14ee) + + * Enable FIPS mode automatically + +2017-11-21 17:32:54 +0100 Armin Novak (dbdc4f493) + + * Fixed endianess issues of zgfx decoder. + +2017-11-23 09:22:02 +0100 David Fort (a834ef824) + + * Merge pull request #4251 from akallabeth/openssl_warn_fixes + +2017-11-22 12:23:04 +0100 Martin Fleisz (2f281c06b) + + * Merge pull request #4244 from akallabeth/drivestoredirect + +2017-11-22 12:06:55 +0100 Martin Fleisz (a8208530e) + + * Merge pull request #4258 from akallabeth/kbd_parse_fix + +2017-11-08 14:22:38 +0100 Armin Novak (e4cf04586) + + * Extract version from file or git tag. + +2017-11-21 08:46:29 +0100 Armin Novak (718318932) + + * Fix #4257: Proper error checks for /kbd argument + +2017-11-22 09:24:16 +0100 Martin Fleisz (e6e5daea0) + + * Merge pull request #4263 from + akallabeth/rdp_parser_mem_corruption_fix + +2017-11-21 19:10:28 +0100 akallabeth (77a921240) + + * Testing argument to end with file extension. + +2017-11-21 17:25:25 +0100 Martin Fleisz (59d1f61e4) + + * Merge pull request #4264 from cedrozor/upstream-master + +2017-11-21 16:36:47 +0100 cedrozor (49f4b2a42) + + * Fixed NLA for Negotiate and NTLM authentication (regression due to + the recent addition of kerberos support) + +2017-11-21 13:47:28 +0100 Armin Novak (65482ee9b) + + * Fixed #4249: Corruption due to recursive parser + +2017-11-21 11:47:33 +0100 Armin Novak (12a9b9a0b) + + * Fix #3890: Point to OpenSSL doc for private CA + +2017-11-21 11:37:42 +0100 Armin Novak (a376656b3) + + * Disabled ceritficate signature check. + +2017-11-20 14:02:41 +0100 Armin Novak (d81e2ec35) + + * Fixed X11 stride on screen update. + +2017-11-20 13:42:40 +0100 Armin Novak (b1d2053ad) + + * Fix #4101: Rfx decode tile width. + +2017-11-21 11:02:25 +0100 Martin Fleisz (785c42f46) + + * Merge pull request #4252 from akallabeth/mac_kbd_sync + +2017-11-21 10:55:18 +0100 Martin Fleisz (ca4d204c7) + + * Merge pull request #4256 from akallabeth/15bpp_fix + +2017-11-17 14:03:57 +0100 Armin Novak (6504b81b9) + + * Fix parsing of drivestoredirect (#3267) + +2017-11-20 16:30:54 +0100 Bernhard Miklautz (cbb8650b3) + + * Merge pull request #4254 from akallabeth/doc_update + +2017-11-20 15:00:09 +0100 Armin Novak (24233b299) + + * Fix #4111: 15bpp color handling for brush. + +2017-11-20 14:11:15 +0100 Bernhard Miklautz (c3acaad46) + + * Merge pull request #4253 from akallabeth/win_return + +2017-11-20 13:21:50 +0100 Armin Novak (a3fb3270d) + + * Fix #3509: Added Ctrl+Alt+Enter description + +2017-11-20 13:16:49 +0100 Armin Novak (59df2688f) + + * Fix #3211: Return freerdp error from main. + +2017-11-20 11:46:32 +0100 Armin Novak (3ce9d6d92) + + * Fixed keyboard state sync. + +2017-11-20 11:46:09 +0100 Armin Novak (feda4e07d) + + * Removed linux specific include. + +2017-11-20 10:11:35 +0100 Armin Novak (4fe12b0ea) + + * Fix #4247: warnings introduced with #3904 + +2017-11-17 15:23:24 +0100 David Fort (b5d257864) + + * Merge pull request #4243 from akallabeth/man_fix + +2017-11-17 13:44:56 +0100 Armin Novak (d593b3ef5) + + * Better description for drive redirection (Fix #3513) + +2017-11-17 13:31:43 +0100 akallabeth (b156b937f) + + * Merge pull request #3904 from bjcollins/master + +2017-11-17 13:02:46 +0100 Martin Fleisz (4ff125148) + + * Merge pull request #4236 from akallabeth/scan_fix_remastered + +2017-11-17 12:41:18 +0100 Armin Novak (1bb4f121b) + + * Fixed formatting. + +2017-04-12 14:03:20 -0500 Brent Collins (9ca9df1ea) + + * Make the new winpr_Digest*MD5_Allow_FIPS functions more generic to + no longer be MD5 specific in design. This way the FIPS + override could easily be extended to more digests in the + future. For now, an attempt to use these functions with + anything other than MD5 will not work. + +2017-04-11 12:04:25 -0500 Brent Collins (e21f9e359) + + * Initialize SSL directly in the sample server, instead of relying on + the SSL initialize logic in the tls code as it was removed + in a previous patch due to its redundancy. + +2017-04-11 12:02:17 -0500 Brent Collins (922a0fa49) + + * Fix checks for openssl version numbers around fips changes, they + were using an incorrect version matching 1.1.0 and not + 1.0.1 Simplify the logic to enable openssl fips mode + +2017-04-11 11:57:39 -0500 Brent Collins (e47123f05) + + * Do not initialize SSL in freerdp_context_new, it is too early to + detect the fips enabled flag and is redundant since it is + initialized later before actually using SSL. + +2017-04-10 14:20:50 -0500 Brent Collins (a0526317e) + + * Fix the return values of the winpr_Digest_Init functions which were + accidentally removed during rework in previous checkin. + +2017-04-10 14:19:43 -0500 Brent Collins (112963461) + + * Move the disabling nla and setting the fips encryption mode based + on fips mode to happen after argument parsing to ensure it + always enforced. + +2017-04-10 14:03:39 -0500 Brent Collins (68ab485e6) + + * Fix logic error in reworked MD5 call for establishing keys, and fix + some minor whitespace issues. + +2017-04-10 13:33:37 -0500 Brent Collins (7aa9e7a97) + + * Fix variable definition placement to adhere to older C standard. + +2017-04-10 13:19:59 -0500 Brent Collins (5284100bb) + + * FIPS_mode() and FIPS_mode_set() does not exist in OpenSSL versions + before 1.0.1 + +2017-04-10 13:06:04 -0500 Brent Collins (2dddae738) + + * Change initialization of EVP_CIPHER_CTX to use API function instead + of trying to calloc(). Fix some warnings noted from build + output. + +2017-04-10 11:08:40 -0500 Brent Collins (497ba442b) + + * Workaround for missing EVP_CIPH_FLAG_FIPS_NON_ALLOW flag in openssl + 1.0.0. + +2017-04-07 16:54:08 -0500 Brent Collins (d98b88642) + + * Add new command-line option to force xfreerdp into a fips compliant + mode. + +2017-11-17 09:36:50 +0100 David Fort (80cb1dd23) + + * Merge pull request #4242 from ccpp/afreerdp_versioncode_11 + +2017-11-17 08:58:07 +0100 Christian Plattner (a5f67d120) + + * Increase versionCode for aFreeRDP 2.0-rc1 + +2017-11-16 15:26:03 +0100 David Fort (666656449) + + * Merge pull request #4186 from RangeeGmbH/multimonitor_primary_fix + +2017-11-16 13:26:01 +0100 David Fort (0d92c725c) + + * Merge pull request #4000 from akallabeth/ign_keyword_fix + +2017-11-16 12:07:07 +0100 akallabeth (668e34781) + + * Merge pull request #4034 from blino/wayland-keymap + +2017-11-10 11:52:23 +0100 Armin Novak (ac0a912a2) + + * Option to force password prompt before connection + +2017-11-16 09:39:04 +0100 Martin Fleisz (af0ac6daf) + + * Merge pull request #4237 from akallabeth/remove_atoi + +2017-11-14 11:22:07 +0100 Armin Novak (4ab26a334) + + * Fixed resource cleanup. + +2017-11-14 14:02:53 +0100 Armin Novak (77134d9de) + + * Fixed formatting. + +2017-11-14 14:01:46 +0100 Armin Novak (f39346ebe) + + * Fixed leaks and formatting. + +2017-11-14 14:00:32 +0100 Armin Novak (ceda3d3f4) + + * Fixed color for drawing rectangles. + +2017-11-14 13:59:15 +0100 Armin Novak (536ffbc31) + + * Fixed missing function return check. + +2017-11-14 13:58:55 +0100 Armin Novak (dbe418062) + + * Fixed missing parameter checks. + +2017-11-14 13:58:31 +0100 Armin Novak (bd7e4cd35) + + * Fixed uninitialized variables. + +2017-11-14 13:58:08 +0100 Armin Novak (032c0164d) + + * Fixed missing error check. + +2017-11-14 13:57:48 +0100 Armin Novak (99f6c2748) + + * Fixed uninitialized arguments. + +2017-11-14 13:57:00 +0100 Armin Novak (7b58495e7) + + * Fixed warnings and formatting. + +2017-11-14 13:56:19 +0100 Armin Novak (1fd6308ef) + + * Functions static, warnings fixed. + +2017-11-14 13:55:58 +0100 Armin Novak (90e1d39fe) + + * Fixed formatting and warnings. + +2017-11-14 13:55:24 +0100 Armin Novak (44dfaf784) + + * Fixed dead store warning. + +2017-11-14 13:54:59 +0100 Armin Novak (3baba6f9c) + + * Removed unused argument. + +2017-11-14 13:54:26 +0100 Armin Novak (f24158fe0) + + * Fixed missing function return check. + +2017-11-14 13:54:05 +0100 Armin Novak (0aa5a8353) + + * Fixed multiple warnings in parser + +2017-11-14 13:52:52 +0100 Armin Novak (26d079e53) + + * Fixed compile warnings. + +2017-11-14 13:52:19 +0100 Armin Novak (7fd5b6f4a) + + * Fixed warnings and test return values. + +2017-11-14 13:51:37 +0100 Armin Novak (5ffde1688) + + * Fixed NULL arguments and compile warnings. + +2017-11-14 13:50:30 +0100 Armin Novak (9859cfb73) + + * Fixed dead store. + +2017-11-14 16:10:52 +0100 Armin Novak (4eb5b8e34) + + * Replaced atoi + +2017-11-15 15:47:35 +0100 David Fort (7fe8648ab) + + * Merge pull request #3940 from akallabeth/custom_help_arguments + +2017-11-15 15:37:27 +0100 David Fort (88ce5aa5f) + + * Merge pull request #4235 from akallabeth/avcodec_encode_video_fix + +2017-05-04 14:46:58 +0200 Armin Novak (8c2bd951a) + + * Allow printing of custom arguments in help. + +2017-11-14 09:15:43 +0100 Armin Novak (e4873fe2c) + + * Added encoder path for libavcodec versions <1.0 + +2017-11-13 17:39:27 +0100 David Fort (f4f23454c) + + * Merge pull request #4233 from akallabeth/kerberos_rebased + +2017-11-13 17:09:48 +0100 David Fort (6f2b849f2) + + * Merge pull request #4232 from akallabeth/ffmpeg_compat + +2017-11-13 15:50:28 +0100 David Fort (7bbc3cb8b) + + * Fix logic in nla_read_ts_credentials + +2017-07-18 11:38:59 +0200 Armin Novak (65f4c560d) + + * Fixed uninitialized values and leaks. + +2017-08-18 19:18:02 +0200 dodo040 (60406794c) + + * fix Kerberos flavour's detection (MIT/Heimdal) and double free for + MIT<1.13 + +2017-07-27 17:02:06 +0200 dodo040 (2ed4acb0a) + + * fix typo + +2017-07-12 11:59:39 +0200 dodo040 (1d97286a7) + + * fix undeclared identifier on Windows + +2017-07-11 17:32:28 +0200 dodo040 (335de159b) + + * use SSIZE_T instead of ssize_t + +2017-07-11 11:30:44 +0200 dodo040 (9adb97118) + + * handle missing ssize_t on Windows + +2017-07-10 16:51:41 +0200 dodo040 (3e897a63c) + + * remove useless includes + +2017-07-03 12:47:56 +0200 dodo040 (e0a9999fb) + + * fix: GSS API init, enterprise name management, variable names and + format code + +2017-05-17 11:36:36 +0200 dodo040 (0a3c61d30) + + * fix undefined symbol references at linking stage + +2017-05-11 18:51:45 +0200 dodo040 (b81f168f0) + + * initial commit for kerberos support + +2017-11-13 11:28:43 +0100 Armin Novak (5cd89a3bc) + + * Added compat define for missing format. + +2017-11-13 10:01:01 +0100 akallabeth (ff59cf028) + + * Merge pull request #4122 from ben-cohen/sshagent + +2017-11-13 09:30:28 +0100 David Fort (b85287fb6) + + * Merge pull request #4212 from SriRamanujam/ffmpeg_encoder_fixes + +2017-11-12 17:31:22 -0500 Sri Ramanujam (fef3865ff) + + * Fallback #ifdefs for older versions of libavcodec + +2017-11-10 20:09:49 +0000 Ben Cohen (8d54945b9) + + * Remove underscores from define in sshagent_main.h + +2017-11-09 21:45:12 +0000 Ben Cohen (6093ec62e) + + * Fix comments at the start of these files and adjust copyrights + +2017-09-08 20:05:06 +0100 Ben Cohen (badb70174) + + * Add server side plugin [UNTESTED] + +2017-09-08 18:00:34 +0100 Ben Cohen (c27541e9a) + + * Add rdpcontext so read thread can report channel error + +2017-09-08 17:09:50 +0100 Ben Cohen (639930869) + + * Remove EAGAIN/EWOULDBLOCK from blocking read/write + +2017-09-08 16:52:14 +0100 Ben Cohen (7e262213c) + + * Fix socket fd leak and other changes + +2017-06-26 21:16:22 +0100 Ben Cohen (0e90841a1) + + * Forward ssh-agent data between ssh-agent and RDP + +2017-11-10 09:32:39 +0100 akallabeth (fcc941992) + + * Merge pull request #4225 from + krisztian-kovacs-balabit/use-redirection-pdu-password-on-reconnect + +2017-11-09 18:11:12 +0100 David Fort (dcafd4dac) + + * Merge pull request #4226 from + krisztian-kovacs-balabit/open-x509-keyfile-readonly + +2017-08-18 13:19:44 -0400 Sri Ramanujam (66c925c9e) + + * Fix libavcodec encoding errors and set tunables. + +2017-09-28 14:00:18 +0200 KOVACS Krisztian (c13c9035e) + + * libfreerdp/core/certificate: open key file for reading only + +2017-11-09 16:24:46 +0100 Martin Fleisz (7717a42f6) + + * Merge pull request #4224 from + krisztian-kovacs-balabit/nsc-memory-corruption-fix + +2017-11-09 15:26:06 +0100 David Fort (da6562aca) + + * Merge pull request #4163 from rjcorrig/tzscripts + +2017-11-09 15:24:27 +0100 David Fort (960b992f7) + + * Merge pull request #4151 from ondrejholy/manpages-update-master + +2017-11-07 16:06:01 +0100 KOVACS Krisztian (70c65e70d) + + * core/connection: use redirection password when reconnecting + +2017-11-07 13:52:09 +0100 KOVACS Krisztian (d39625886) + + * codec/nsc: fix memory corruption in case of chroma subsampling + +2017-11-09 13:35:56 +0100 David Fort (518981493) + + * Merge pull request #4223 from akallabeth/mac_client_crash_fix + +2017-11-09 10:22:16 +0100 Armin Novak (83bcdc56b) + + * Added missing pointer callback. + +2017-11-09 09:37:18 +0100 Martin Fleisz (d5344c339) + + * Merge pull request #4219 from akallabeth/various_fixes + +2017-11-08 13:34:26 +0100 Martin Fleisz (ed1934caf) + + * Merge pull request #4211 from akallabeth/silence_duplicate_warnings + +2017-11-08 13:04:04 +0100 Martin Fleisz (bd218470f) + + * Merge pull request #4214 from hardening/serial_fixes + +2017-11-08 12:37:23 +0100 Armin Novak (5dc8763b2) + + * Fixed compilation errors with old FFMPEG versions. + +2017-11-08 11:30:32 +0100 Armin Novak (b86c0ba54) + + * Fixed NLA default error to FREERDP_ERROR_AUTHENTICATION_FAILED + +2017-11-07 10:11:29 +0000 Kai Harms (e2c651bce) + + * FreeRDP multimonitor: Use first command line element, then primary, + then fallback to 0,0 + +2017-11-06 22:23:07 +0100 David Fort (de7d7e43c) + + * serial redirection: implement event char + +2017-11-06 22:09:01 +0100 David Fort (ff8f7e947) + + * Disambiguate USB error messages and fix a typo + +2017-11-06 21:58:10 +0100 David Fort (2aa71ea7e) + + * Added some checks for the serial redirection channel + +2017-11-06 14:23:50 +0100 David Fort (b216e91cd) + + * Merge pull request #4210 from akallabeth/nla_errors_extended + +2017-11-06 14:02:22 +0100 Armin Novak (ce00f4dd8) + + * Silence WLog_ERR messages if last error is set. + +2017-11-06 11:25:48 +0100 David Fort (504b77168) + + * Merge pull request #4053 from akallabeth/ffmpeg_encoder + +2017-11-06 10:22:37 +0100 akallabeth (6845974cc) + + * Merge pull request #4200 from cedrozor/upstream-master + +2017-11-06 10:02:07 +0100 akallabeth (e7b8833e9) + + * Merge pull request #4187 from hardening/multimon_fix + +2017-11-06 09:49:03 +0100 Armin Novak (7a73a0eb1) + + * Added additional NLA error mappings. + +2017-11-03 21:34:18 +0100 David Fort (c4aaf5bc6) + + * Merge pull request #4206 from akallabeth/x_window_title + +2017-10-31 18:00:15 +0100 Armin Novak (afb08c9df) + + * X11 window title fix + +2017-10-31 17:17:43 +0100 Martin Fleisz (5416c2724) + + * Merge pull request #4205 from akallabeth/WIN32_FIND_DATA + +2017-10-31 12:02:29 +0100 Armin Novak (269c78802) + + * Fixed #4199: ConvertFindDataAToW string length + +2017-10-31 15:36:22 +0100 akallabeth (716ce5feb) + + * Merge pull request #4159 from aleksei-klv/dex + +2017-10-31 11:42:58 +0100 Martin Fleisz (3f6b8b786) + + * Merge pull request #4179 from akallabeth/android_cleanup_fix + +2017-10-31 09:55:43 +0100 Martin Fleisz (b52a6f7b3) + + * Merge pull request #4204 from lunixoid/master + +2017-10-31 00:11:25 +0300 Roman Kalashnikov (40d84d4be) + + * Fixed twice assigned values + +2017-10-30 12:29:58 -0400 Mike Gilbert (5b34c033a) + + * Merge pull request #4203 from floppym/mkdir-error + +2017-10-29 20:26:53 -0400 Mike Gilbert (5cd230ac7) + + * winpr: _IoCreateDeviceEx: fix mkdir error check + +2017-10-30 15:47:02 +0100 akallabeth (edd6ca0d7) + + * Merge pull request #4201 from kakaroto/listener-unlink-bugfix + +2017-10-29 17:52:19 +0100 David Fort (20e6d9923) + + * Merge pull request #4202 from lunixoid/master + +2017-10-28 11:59:23 +0300 Roman Kalashnikov (612e8b071) + + * Update semaphore.c + +2017-10-28 01:48:41 +0300 Roman Kalashnikov (4db363f10) + + * Fixed Expression 'pComm != NULL' is always true + +2017-10-28 01:46:06 +0300 Roman Kalashnikov (67a97612e) + + * Fixed duplicated assigne + +2017-10-27 14:38:35 -0400 Youness Alaoui (02e4f1f25) + + * Do not delete the listener socket right after creating it. + +2017-10-27 14:30:00 +0200 cedrozor (b4b9ed6ce) + + * fixed hdc initialization into wf_begin_paint so the region + invalidation into wf_end_paint applies to the same hdc the + objective is that only the updated region(s) are refreshed + instead of the whole screen it's not much a problem for + normal FreeRDP usage but becomes a serious issue if the + display is processed, forwarded and rendered remotely, as + done by web gateways such as Guacamole, FreeRDP-WebConnect + and Myrtille (I'm the author of the latter) + +2017-10-26 15:36:53 +0300 Aleksei Kliuev (ba6f5ea6d) + + * remove temporary hack + +2017-10-26 00:17:03 +0200 David Fort (510bf8219) + + * Merge pull request #4198 from akallabeth/nla_error_fix + +2017-10-25 09:56:39 +0200 Armin Novak (367bddd7a) + + * Added better error mapping for NEGO results. + +2017-10-23 09:48:52 +0200 Armin Novak (b35561652) + + * Fixed possible race condition on resource cleanup. + +2017-10-19 13:15:04 +0200 David Fort (86bb1e07a) + + * Merge pull request #4195 from nfedera/fix-sse3-yuv444pixel + +2017-10-19 11:55:13 +0200 Norbert Federa (eea2f306d) + + * primitives/yuv: fix endianess issue + +2017-10-18 10:24:35 +0200 Norbert Federa (c297d8486) + + * Merge pull request #4190 from akallabeth/media_foundation_fix_win7 + +2017-10-18 09:52:41 +0200 Armin Novak (5d96fc9b1) + + * Removed unused function pointer + +2017-10-17 21:33:16 +0200 Norbert Federa (16d910459) + + * Merge pull request #4189 from nfedera/fix-h264-init + +2017-10-17 19:28:54 +0200 Norbert Federa (456ce9661) + + * codec/h264: fix potential segfault and mf_init + +2017-10-17 14:31:11 +0200 David Fort (46c7097a8) + + * multimon: flag the primary monitor according to the /monitors + option + +2017-10-17 14:07:23 +0200 David Fort (f90fe19fc) + + * multimon: correctly set the primary monitor + +2017-10-17 09:12:27 +0200 Armin Novak (e7884aec2) + + * Added default return if instance not in list. + +2017-10-16 17:21:35 +0200 akallabeth (acd97ccdd) + + * Merge pull request #4177 from rjcorrig/tabfix + +2017-10-13 13:13:33 +0200 Armin Novak (f1e8fdeb5) + + * Ensure native session is disconnected before resource free. + +2017-10-12 12:56:34 -0400 Robert Corrigan (55a4ca1bc) + + * Fix tab key mapping for hardware keyboard + +2017-10-12 12:12:43 +0200 Martin Fleisz (9b400bfb6) + + * Merge pull request #4175 from akallabeth/time_fix + +2017-10-12 12:12:08 +0200 Martin Fleisz (3f78c88f3) + + * Merge pull request #4172 from hardening/egfx_cache + +2017-10-12 11:27:32 +0200 Armin Novak (3840b2794) + + * Fixed file timestamps. + +2017-10-10 17:12:16 +0200 David Fort (5d5376faa) + + * egfx: fix disconnection caused by invalid cache entries due to + wrong announced cache size + +2017-10-09 13:25:41 +0200 Martin Fleisz (50d324655) + + * Merge pull request #4164 from akallabeth/ak/mac_audio_refactor + +2017-10-09 09:19:19 +0200 akallabeth (d7154444f) + + * Merge pull request #4167 from bmiklautz/buildversion + +2017-10-06 15:02:46 +0200 Bernhard Miklautz (ae8260c3b) + + * feat freerdp-nighlty/deb: create .source_version + +2017-10-06 13:52:10 +0200 Bernhard Miklautz (1aec784f7) + + * feat: add support for .source_version + +2017-10-05 15:13:30 +0200 Bernhard Miklautz (73647adb5) + + * Merge pull request #4162 from hardening/misc_fix2 + +2017-10-05 12:05:09 +0200 Armin Novak (7058a9add) + + * Pause playback on queue empty, free buffers on close. + +2017-10-04 21:12:29 -0400 Robert Corrigan (5fa2426fd) + + * Download windowsZones.xml directly from unicode.org + +2017-10-04 20:29:02 -0400 Robert Corrigan (b92636e90) + + * .gitignore generated time zone files + +2017-10-04 20:27:07 -0400 Robert Corrigan (2cc181fb3) + + * Convert WindowsZones.cs to C# script + +2017-10-04 20:18:38 -0400 Robert Corrigan (3f650e97e) + + * Convert TimeZones.cs to C# script + +2017-10-02 21:28:02 +0200 David Fort (a13292237) + + * Add checks for DR channel + +2017-10-02 20:57:27 +0200 David Fort (b624ecbfc) + + * Fix for #4161 + +2017-09-19 15:50:35 +0300 Aleksei Kliuev (c7be2089d) + + * fix crashing app in dex mode + +2017-09-11 17:54:19 +0300 Aleksei Kliuev (84eea9c55) + + * fix right click + +2017-09-11 14:23:28 +0300 Aleksei Kliuev (7554ab9a0) + + * revert gradle + +2017-09-11 14:03:30 +0300 Aleksei Kliuev (5931e61ad) + + * Add Samsung DeX support + +2017-09-27 14:56:21 +0200 akallabeth (e6d66d9d8) + + * Merge pull request #4154 from hardening/misc_fixes + +2017-09-25 13:15:31 +0200 Ondrej Holy (c5ae72972) + + * cmdline: Sort arguments list + +2017-09-25 12:41:40 +0200 Ondrej Holy (362593629) + + * client/X11: Mention also aliases in man page + +2017-09-25 11:44:07 +0200 Ondrej Holy (d0dfa9353) + + * cmdline: Improve /help output + +2017-09-25 11:37:43 +0200 Ondrej Holy (7538c86ce) + + * client/X11: Improve man page generation + +2017-09-25 11:33:03 +0200 Ondrej Holy (a49c856d7) + + * client/X11: Remove const qualifier + +2017-09-22 14:17:10 +0200 Ondrej Holy (cf1fbf55d) + + * cmdline: Improve arguments list + +2017-09-27 11:14:39 +0200 akallabeth (8f98cc9ee) + + * Merge pull request #4144 from bmiklautz/clipboardon + +2017-09-23 15:16:17 +0200 Bernhard Miklautz (15c7cb8cb) + + * Enable clipboard channel per default + +2017-09-26 09:21:28 +0200 David Fort (9ac54ede6) + + * Fix displaying of raw surfaces + +2017-09-26 09:20:38 +0200 David Fort (ddca8f3a3) + + * Check return value of malloc + +2017-09-26 13:52:37 +0200 David Fort (782e5df2b) + + * Merge pull request #4156 from + akallabeth/test_connect_extend_timeout + +2017-09-26 12:03:57 +0200 Armin Novak (9f26f7370) + + * Added delay for connect abort + +2017-09-26 11:26:35 +0200 David Fort (416d756ef) + + * Merge pull request #4155 from + akallabeth/test_connect_extend_timeout + +2017-09-26 10:52:13 +0200 Armin Novak (ef9444bd3) + + * TestConnect: Extend timeout, only listen locally + +2017-09-26 09:40:30 +0200 David Fort (64858d18b) + + * Merge pull request #4152 from akallabeth/dynamic_channel_test_fix + +2017-09-25 13:30:05 +0200 Armin Novak (ac454628a) + + * Fixed TestConnect with dynamic channels. + +2017-09-25 13:29:23 +0200 Armin Novak (2e83abb90) + + * Fixed client context setup with default initializer. + +2017-09-25 13:28:16 +0200 Armin Novak (bcfa434da) + + * Fixed resizing of PubSub + +2017-09-25 13:17:32 +0200 David Fort (b48a73729) + + * Merge pull request #4150 from akallabeth/server_file_handle_leak + +2017-09-25 10:35:24 +0200 Armin Novak (884e87fde) + + * Unlink file after binding to it. + +2017-09-25 09:35:49 +0200 Bernhard Miklautz (4592deee7) + + * extend /size to allow width or height percentages (#4146) + +2017-09-25 09:33:58 +0200 David Fort (babeb34d8) + + * Merge pull request #4060 from akallabeth/icu_support + +2017-09-25 09:12:35 +0200 David Fort (0e0df75ee) + + * Merge pull request #4142 from bmiklautz/macOS + +2017-09-25 09:09:55 +0200 David Fort (db3fe812b) + + * Merge pull request #4143 from bmiklautz/pass_is_sc_pin + +2017-09-23 14:26:38 +0200 Jukka-Pekka Virtanen (509059f8e) + + * Expose PasswordIsSmartcardPin settings from cmdline via + password-is-pin arg + +2017-09-14 13:34:09 +0300 Jukka-Pekka Virtanen (ad1425e14) + + * Using PasswordIsSmartcardPin option when sending TS_INFO_PACKET + +2017-09-23 14:08:05 +0200 Bernhard Miklautz (fe36cd90e) + + * macOS: add a README file + +2017-09-23 13:57:57 +0200 Bernhard Miklautz (3626676ac) + + * winpr/makecert: fix linking against libcrypto + +2017-09-23 13:31:34 +0200 Bernhard Miklautz (630945983) + + * macOS: add a workaround to build with newer SDKs + +2017-09-22 17:22:00 +0200 Bernhard Miklautz (bbd11eef1) + + * Merge pull request #4045 from akallabeth/drive_fixes_overlayfs + +2017-09-22 09:52:27 +0200 David Fort (b587daa41) + + * Merge pull request #4136 from tditsch/master + +2017-09-21 14:50:34 +0200 Bernhard Miklautz (aa9ff8497) + + * Merge pull request #4116 from ChickenPeanut/patch-1 + +2017-09-19 13:51:09 +0200 Martin Fleisz (904250997) + + * Merge pull request #4138 from akallabeth/ak/nla_free_fix + +2017-09-19 12:33:33 +0200 Armin Novak (bdae33926) + + * Check and invalidate handles on free. + +2017-09-19 10:18:41 +0200 tditsch (a16d9a2ad) + + * refactored Bugfix + +2017-09-18 17:29:16 +0200 tditsch (feca6d975) + + * Fixed endless loop when RDP Server sends SERVER_DENIED_CONNECTION + +2017-09-18 10:47:56 +0200 Ondrej Holy (3137caebf) + + * Fix colors on big endian (#4135) + +2017-09-18 10:17:43 +0200 David Fort (a514ae963) + + * Merge pull request #4121 from ondrejholy/setsurface-segfault-fix + +2017-09-12 23:16:39 +0200 David Fort (dbc5584a6) + + * Merge pull request #4052 from akallabeth/mac_fixes + +2017-09-11 16:34:24 +0200 MartinHaimberger (f6e0b438a) + + * Merge pull request #4127 from mfleisz/avc420 + +2017-09-11 12:05:03 +0200 Martin Fleisz (e28ea4555) + + * channels: Don't send gfx capversion 10 if AVC420 is requested + +2017-09-05 10:25:15 +0200 Ondrej Holy (e9ffff56b) + + * cache: Use Bitmap_Free instead of free + +2017-09-05 09:56:00 +0200 Ondrej Holy (9cccd4888) + + * orders: Fix OFFSCREEN_DELETE_LIST allocation size + +2017-09-05 08:58:37 +0200 Ondrej Holy (048e7f264) + + * orders: Fix ORDER_TYPE_GDIPLUS_END check + +2017-09-04 18:48:25 +0200 Ondrej Holy (5d6e2078c) + + * cache: Check return value from offscreen_cache_get + +2017-09-04 18:22:49 +0200 Ondrej Holy (4239660e3) + + * client/X11: Check arguments in xf_Bitmap_SetSurface + +2017-09-03 18:52:34 -0400 ChickenPeanut (0efb07bc6) + + * Fixed BadValue with XCreateWindow + +2017-08-31 10:22:43 +0200 David Fort (3b8352690) + + * Merge pull request #4079 from akallabeth/channel_pubsub_fix + +2017-08-31 09:57:49 +0200 Armin Novak (d3df6ed40) + + * Removed unused variable. + +2017-08-31 09:06:59 +0200 Armin Novak (8a5c78bde) + + * Unified dynamic channel cleanup code. + +2017-08-30 10:19:12 +0200 David Fort (5115ecd94) + + * Merge pull request #4063 from akallabeth/auth_fixes + +2017-08-29 11:06:13 +0200 David Fort (5258a980f) + + * Merge pull request #4104 from abma/master + +2017-08-29 10:35:45 +0200 Bernhard Miklautz (6a83a1e7f) + + * Merge pull request #4050 from + akallabeth/rdpefs_server_client_name_fix + +2017-08-29 09:09:38 +0200 Bernhard Miklautz (52fbfb7b1) + + * fix clang warnings, directly include wtypes.h (#4097) + +2017-08-26 10:17:02 +0200 David Fort (9a81531cb) + + * Merge pull request #4100 from mmeyer724/wayland-opaque + +2017-08-26 10:13:42 +0200 David Fort (c26a7a9ca) + + * Merge pull request #4099 from mmeyer724/wayland-fullscreen + +2017-08-22 22:42:58 +0200 abma (165de9128) + + * Revert "Possible fix for #4081 and #2707 (#4087)" + +2017-08-17 17:32:26 -0400 Michael Meyer (65daae019) + + * wlfreerdp: improve performance by making the window opaque + +2017-08-17 13:33:44 -0400 Michael Meyer (e695645a7) + + * wlfreerdp: mirror display resolution in fullscreen mode + +2017-08-17 15:18:04 +0200 Bernhard Miklautz (f9a47a346) + + * Merge pull request #4098 from akallabeth/fix_rsa_generation + +2017-08-17 13:16:32 +0200 Armin Novak (7e32e90d4) + + * Fixed RSA generation for OpenSSL >= 1.1 + +2017-08-17 10:46:16 +0200 Bernhard Miklautz (5f80636b3) + + * Merge pull request #4095 from mmeyer724/wayland-scrolling + +2017-08-16 17:54:45 +0000 Michael Meyer (c01442da2) + + * Fixes scrolling crash in wlfreerdp + +2017-08-16 15:40:45 +0200 Armin Novak (f143fcc29) + + * Fixed data type, eliminate warning. + +2017-08-16 15:09:33 +0200 Armin Novak (47feecf8d) + + * Added FindICU from CMake 3.7 for backward compatibility + +2017-08-16 13:28:11 +0200 Bernhard Miklautz (1e54fdb5c) + + * android: fix a regression with remote program (#4091) + +2017-08-16 13:26:47 +0200 Bernhard Miklautz (ba9227d80) + + * Merge pull request #4092 from + akallabeth/afreerdp_no_client_name_escape + +2017-08-16 11:31:33 +0200 Armin Novak (eb0bf411a) + + * Do not add quotes to client hostname. + +2017-08-16 10:25:23 +0200 Armin Novak (9ebfbc1fc) + + * FindNextFileAx, continue if a inalid file is found. + +2017-08-16 10:04:13 +0200 Bernhard Miklautz (ed36f55f3) + + * Merge pull request #4088 from akallabeth/file_api_64bit_fixes + +2017-08-16 08:09:31 +0200 Bernhard Miklautz (03c95e22a) + + * Merge pull request #4085 from akallabeth/file_warn_fix + +2017-08-14 16:16:14 +0800 Jiang, Zihao (790c48017) + + * Client/X11: Fix h264 context leak when DeleteSurface (#4089) + +2017-08-14 10:10:53 +0200 Kai (6b7b60237) + + * Possible fix for #4081 and #2707 (#4087) + +2017-08-11 10:07:46 +0200 Armin Novak (c3d4b7d26) + + * fseeko and ftello for 64bit file support. + +2017-08-10 17:39:34 +0200 Bernhard Miklautz (b34b32bea) + + * Merge pull request #4084 from psumbera/master + +2017-08-10 16:51:55 +0200 Armin Novak (82d9ebc38) + + * Fixed FileSetFilePointer warnings + +2017-08-10 07:36:25 -0700 Petr Sumbera (e5c925b63) + + * On Solaris use standard conforming getpwnam_r(). + +2017-08-09 10:35:37 +0200 MartinHaimberger (80ed23779) + + * Merge pull request #4076 from akallabeth/SetFilePointer_fix + +2017-08-08 21:17:01 +0200 Bernhard Miklautz (8c891ae30) + + * Merge pull request #4070 from yurashek/master + +2017-08-08 10:52:11 +0200 Armin Novak (32de218c3) + + * Fixed file seek. + +2017-08-08 10:51:50 +0200 Armin Novak (7d7e5487a) + + * Fixed SetFilePointer, added SetFilePointerEx + +2017-08-02 04:52:45 -0700 Jura Sasek (a84c5cbfb) + + * Sun keyboard + +2017-08-04 09:01:13 +0200 Armin Novak (efe697189) + + * Skip FIFO files in listings. + +2017-08-03 14:45:19 +0200 Armin Novak (0a23bdf61) + + * Abort CreateFile for existing files of type FIFO + +2017-08-03 14:38:20 +0200 Armin Novak (436829142) + + * Mapped ENOTCONN to ERROR_FILE_NOT_FOUND + +2017-08-03 09:32:29 +0200 David Fort (9a00b25ad) + + * Merge pull request #4071 from bmiklautz/debian_fixes + +2017-08-03 08:41:50 +0200 Mike Gabriel (dc075fb13) + + * Fix warning in man pages + +2017-08-03 08:38:05 +0200 Mike Gabriel (c045bddf3) + + * Fix typos in some error messages + +2017-08-02 11:25:08 +0200 David Fort (b29658a85) + + * Merge pull request #4066 from akallabeth/input_event_fixes + +2017-08-02 09:53:38 +0200 David Fort (c84065f40) + + * Merge pull request #4069 from yurashek/master + +2017-08-02 09:42:04 +0200 Armin Novak (8a0cec946) + + * Added AVC420 in AVC444 shadow encoding + +2017-08-02 08:53:03 +0200 Armin Novak (a63b2c5a4) + + * Use encoder context for old libavcodec. + +2017-07-31 12:16:47 +0200 Armin Novak (d2d621106) + + * Fixed capability checks for mouse and unicode input. + +2017-07-29 08:33:33 +0200 David Fort (473044b91) + + * Merge pull request #4064 from floppym/gst-detect + +2017-07-28 16:31:41 -0400 Mike Gilbert (368989526) + + * Fix gstreamer-1.0 detection + +2017-07-18 14:37:46 +0200 Armin Novak (523a88166) + + * Channels with a context must free it themselves. + +2017-07-18 13:23:22 +0200 Armin Novak (11fa9f675) + + * Free credentials on exit. + +2017-07-18 12:54:00 +0200 Armin Novak (b0411d4fa) + + * Unexported internal NLA functions. + +2017-07-18 12:43:55 +0200 Armin Novak (c301f2d56) + + * Fixed certificate check return. + +2017-07-18 11:38:59 +0200 Armin Novak (ceda24416) + + * Fixed uninitialized values and leaks. + +2017-07-27 10:55:00 +0200 David Fort (7891a0f91) + + * Merge pull request #4061 from vakartel/master + +2017-07-26 17:12:14 +0300 Valery Kartel (9bf9ff9e8) + + * Fix build with LibreSSL + +2017-07-26 12:58:34 +0200 Armin Novak (1868acb0a) + + * Using ICU instead of custom unicode conversion. + +2017-07-26 11:02:55 +0200 Armin Novak (c8f97efb4) + + * Added EROFS mapping. + +2017-07-24 15:47:49 +0200 Bernhard Miklautz (f8c9f4384) + + * Merge pull request #4056 from akallabeth/disable_jpeg + +2017-07-24 15:23:36 +0200 Armin Novak (dd4b5ea12) + + * Disable JPEG codec support if not compiled in. + +2017-07-24 15:08:44 +0200 Armin Novak (2beaf2c61) + + * Added error message in case of unmapped ERRNO value. + +2017-07-24 15:05:48 +0200 Armin Novak (d1ebc39b0) + + * Fixed file errno mapping. + +2017-07-17 13:00:03 +0200 Armin Novak (9a2c9c47d) + + * Fixed buffer read. + +2017-07-17 12:32:14 +0200 Armin Novak (06f6c0f8c) + + * Removed STANDARD_RIGHTS_WRITE from writeable check. + +2017-07-17 12:31:45 +0200 Armin Novak (41f919b8b) + + * Fixed integer size warnings. + +2017-07-17 12:31:13 +0200 Armin Novak (6a06c8d99) + + * Additional error checks for drive channel. + 2017-07-24 10:46:54 +0200 Norbert Federa (1648deb43) * Merge pull request #4055 from akallabeth/talos_v3 +2017-06-02 08:54:06 +0200 Armin Novak (2d1826753) + + * Stream convenience functions to read/write strings. + +2017-07-24 08:53:21 +0200 Armin Novak (931870729) + + * Added return check for ConvertFromUnicode. + +2017-07-20 12:46:04 +0200 Armin Novak (3501f82e9) + + * Implemented FFMPEG based encoder. + +2017-07-20 12:35:43 +0200 Armin Novak (3586f8502) + + * Fixed missing unicode conversion for mac drive redirection. + +2017-07-20 12:33:56 +0200 Armin Novak (d5a582f91) + + * Ignore gdi_resize if not initialized. + 2017-07-17 15:21:58 +0200 Bernhard Miklautz (f23e10f64) * clipboard: fix possible invalid memory access @@ -80,6 +3070,10 @@ * Don't use an option for WITH_GFX_H264 +2017-07-19 09:41:58 +0200 Armin Novak (0e6a44faf) + + * Mask out ignored bits from UnicodeFlag. + 2017-07-18 08:27:14 +0200 Armin Novak (61ab600c1) * Always use software GFX for windows client. @@ -178,6 +3172,10 @@ * Fix clipboard POSIX build because of basename conflict +2017-07-03 19:45:59 +0200 Olivier Blin (3e5f8c6bd) + + * Reuse evdev/X11 keymap for wayland + 2017-07-03 19:09:01 +0200 Olivier Blin (a57197a73) * Support fullscreen setting in wayland client @@ -324,6 +3322,10 @@ * Fixed shadow server mouse wheel mapping on MacOS +2017-06-12 12:23:10 +0200 Armin Novak (33a153c07) + + * Command line ignore empty if flag set + 2017-06-10 13:59:42 +0200 David Fort (1dbd2d28d) * Merge pull request #3989 from akallabeth/avc444_alignment_fix @@ -404,6 +3406,10 @@ * x11/cliprdr: make callbacks static +2017-05-17 09:30:13 -0700 Jura Sasek (4edb5cf7e) + + * Build for Solaris + 2017-05-22 11:12:05 +0200 David Fort (48163a27d) * Merge pull request #3906 from akallabeth/addin_cast_fix diff --git a/README b/README index f40c20c..0144d87 100644 --- a/README +++ b/README @@ -11,9 +11,9 @@ Resources Project website: http://www.freerdp.com/ Issue tracker: https://github.com/FreeRDP/FreeRDP/issues Sources: https://github.com/FreeRDP/FreeRDP/ +Downloads: https://pub.freerdp.com/releases/ Wiki: https://github.com/FreeRDP/FreeRDP/wiki -Downloads and other resources: http://pub.freerdp.com -API doc: http://pub.freerdp.com/api/ +API documentation: https://pub.freerdp.com/api/ IRC channel: #freerdp @ irc.freenode.net Mailing list: https://lists.sourceforge.net/lists/listinfo/freerdp-devel @@ -32,5 +32,3 @@ Compilation Instructions on how to get started compiling FreeRDP can be found on the wiki: https://github.com/FreeRDP/FreeRDP/wiki/Compilation - - diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c index a9566a5..d821710 100644 --- a/channels/audin/client/alsa/audin_alsa.c +++ b/channels/audin/client/alsa/audin_alsa.c @@ -219,7 +219,7 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, return ret; } -static void* audin_alsa_thread_func(void* arg) +static DWORD WINAPI audin_alsa_thread_func(LPVOID arg) { long error; BYTE* buffer; @@ -300,8 +300,8 @@ out: setChannelError(alsa->rdpcontext, error, "audin_alsa_thread_func reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -427,7 +427,7 @@ static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive, } if (!(alsa->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL))) + audin_alsa_thread_func, alsa, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); goto error_out; diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 5ee2fea..b04c258 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -24,6 +24,7 @@ #include "config.h" #endif +#include #include #include #include @@ -31,10 +32,10 @@ #include #include +#include +#include #include - -#include #include #include "audin_main.h" @@ -70,7 +71,7 @@ struct _AUDIN_CHANNEL_CALLBACK * Open PDU and Format Change PDU */ audinFormat* formats; - int formats_count; + UINT32 formats_count; }; typedef struct _AUDIN_PLUGIN AUDIN_PLUGIN; @@ -92,37 +93,45 @@ struct _AUDIN_PLUGIN rdpContext* rdpcontext; BOOL attached; + wLog* log; }; static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args); +static UINT audin_write_and_free_stream(AUDIN_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT error = ERROR_INTERNAL_ERROR; + const size_t length = Stream_GetPosition(s); + const BYTE* data = Stream_Buffer(s); + + if (callback && callback->channel && callback->channel->Write) + error = callback->channel->Write(callback->channel, length, data, NULL); + + Stream_Free(s, TRUE); + return error; +} /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) +static UINT audin_process_version(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s) { - UINT error; wStream* out; UINT32 Version; - AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; Stream_Read_UINT32(s, Version); DEBUG_DVC("Version=%"PRIu32"", Version); out = Stream_New(NULL, 5); if (!out) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!"); return ERROR_OUTOFMEMORY; } Stream_Write_UINT8(out, MSG_SNDIN_VERSION); Stream_Write_UINT32(out, Version); - error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out), - Stream_Buffer(out), NULL); - Stream_Free(out, TRUE); - return error; + return audin_write_and_free_stream(callback, out); } /** @@ -130,11 +139,13 @@ static UINT audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCallback) +static UINT audin_send_incoming_data_pdu(AUDIN_CHANNEL_CALLBACK* callback) { - BYTE out_data[1]; - AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; - out_data[0] = MSG_SNDIN_DATA_INCOMING; + BYTE out_data[1] = { MSG_SNDIN_DATA_INCOMING }; + + if (!callback || !callback->channel || !callback->channel->Write) + return ERROR_INTERNAL_ERROR; + return callback->channel->Write(callback->channel, 1, out_data, NULL); } @@ -143,23 +154,25 @@ static UINT audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCal * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) +static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s) { - AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; UINT32 i; BYTE* fm; UINT error; wStream* out; UINT32 NumFormats; audinFormat format; - UINT32 cbSizeFormatsPacket; + size_t cbSizeFormatsPacket; + + if (Stream_GetRemainingLength(s) < 8) + return ERROR_NO_DATA; + Stream_Read_UINT32(s, NumFormats); DEBUG_DVC("NumFormats %"PRIu32"", NumFormats); if ((NumFormats < 1) || (NumFormats > 1000)) { - WLog_ERR(TAG, "bad NumFormats %"PRIu32"", NumFormats); + WLog_Print(audin->log, WLOG_ERROR, "bad NumFormats %"PRIu32"", NumFormats); return ERROR_INVALID_DATA; } @@ -168,7 +181,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, if (!callback->formats) { - WLog_ERR(TAG, "calloc failed!"); + WLog_Print(audin->log, WLOG_ERROR, "calloc failed!"); return ERROR_INVALID_DATA; } @@ -177,7 +190,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, if (!out) { error = CHANNEL_RC_NO_MEMORY; - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!"); goto out; } @@ -186,6 +199,9 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, /* SoundFormats (variable) */ for (i = 0; i < NumFormats; i++) { + if (Stream_GetRemainingLength(s) < 18) + return ERROR_NO_DATA; + Stream_GetPointer(s, fm); Stream_Read_UINT16(s, format.wFormatTag); Stream_Read_UINT16(s, format.nChannels); @@ -195,6 +211,10 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, Stream_Read_UINT16(s, format.wBitsPerSample); Stream_Read_UINT16(s, format.cbSize); format.data = Stream_Pointer(s); + + if (Stream_GetRemainingLength(s) < format.cbSize) + return ERROR_NO_DATA; + Stream_Seek(s, format.cbSize); DEBUG_DVC("wFormatTag=%"PRIu16" nChannels=%"PRIu16" nSamplesPerSec=%"PRIu32" " "nBlockAlign=%"PRIu16" wBitsPerSample=%"PRIu16" cbSize=%"PRIu16"", @@ -220,7 +240,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, if (!Stream_EnsureRemainingCapacity(out, 18 + format.cbSize)) { error = CHANNEL_RC_NO_MEMORY; - WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + WLog_Print(audin->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); goto out; } @@ -228,18 +248,19 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, } } - if ((error = audin_send_incoming_data_pdu(pChannelCallback))) + if ((error = audin_send_incoming_data_pdu(callback))) { - WLog_ERR(TAG, "audin_send_incoming_data_pdu failed!"); + WLog_Print(audin->log, WLOG_ERROR, "audin_send_incoming_data_pdu failed!"); goto out; } - cbSizeFormatsPacket = (UINT32) Stream_GetPosition(out); + cbSizeFormatsPacket = Stream_GetPosition(out); Stream_SetPosition(out, 0); Stream_Write_UINT8(out, MSG_SNDIN_FORMATS); /* Header (1 byte) */ Stream_Write_UINT32(out, callback->formats_count); /* NumFormats (4 bytes) */ Stream_Write_UINT32(out, cbSizeFormatsPacket); /* cbSizeFormatsPacket (4 bytes) */ - error = callback->channel->Write(callback->channel, cbSizeFormatsPacket, Stream_Buffer(out), NULL); + Stream_SetPosition(out, cbSizeFormatsPacket); + error = audin_write_and_free_stream(callback, out); out: if (error != CHANNEL_RC_OK) @@ -248,7 +269,6 @@ out: callback->formats = NULL; } - Stream_Free(out, TRUE); return error; } @@ -257,25 +277,20 @@ out: * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCallback, +static UINT audin_send_format_change_pdu(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, UINT32 NewFormat) { - UINT error; - wStream* out; - AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; - out = Stream_New(NULL, 5); + wStream* out = Stream_New(NULL, 5); if (!out) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_OK; } Stream_Write_UINT8(out, MSG_SNDIN_FORMATCHANGE); Stream_Write_UINT32(out, NewFormat); - error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL); - Stream_Free(out, TRUE); - return error; + return audin_write_and_free_stream(callback, out); } /** @@ -283,24 +298,20 @@ static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCal * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallback, UINT32 Result) +static UINT audin_send_open_reply_pdu(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, + UINT32 Result) { - UINT error; - wStream* out; - AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; - out = Stream_New(NULL, 5); + wStream* out = Stream_New(NULL, 5); if (!out) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT8(out, MSG_SNDIN_OPEN_REPLY); Stream_Write_UINT32(out, Result); - error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL); - Stream_Free(out, TRUE); - return error; + return audin_write_and_free_stream(callback, out); } /** @@ -326,9 +337,9 @@ static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data) if (!audin->attached) return CHANNEL_RC_OK; - if ((error = audin_send_incoming_data_pdu((IWTSVirtualChannelCallback*) callback))) + if ((error = audin_send_incoming_data_pdu(callback))) { - WLog_ERR(TAG, "audin_send_incoming_data_pdu failed!"); + WLog_Print(audin->log, WLOG_ERROR, "audin_send_incoming_data_pdu failed!"); return error; } @@ -336,16 +347,13 @@ static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data) if (!out) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!"); return ERROR_NOT_ENOUGH_MEMORY; } Stream_Write_UINT8(out, MSG_SNDIN_DATA); Stream_Write(out, data, size); - error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out), - Stream_Buffer(out), NULL); - Stream_Free(out, TRUE); - return error; + return audin_write_and_free_stream(callback, out); } /** @@ -353,14 +361,19 @@ static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data) * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) +static UINT audin_process_open(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s) { - AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; audinFormat* format; UINT32 initialFormat; UINT32 FramesPerPacket; UINT error = CHANNEL_RC_OK; + + if (!audin || !callback || !s) + return ERROR_INTERNAL_ERROR; + + if (Stream_GetRemainingLength(s) < 8) + return ERROR_NO_DATA; + Stream_Read_UINT32(s, FramesPerPacket); Stream_Read_UINT32(s, initialFormat); DEBUG_DVC("FramesPerPacket=%"PRIu32" initialFormat=%"PRIu32"", @@ -368,8 +381,8 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt if (initialFormat >= (UINT32) callback->formats_count) { - WLog_ERR(TAG, "invalid format index %"PRIu32" (total %d)", - initialFormat, callback->formats_count); + WLog_Print(audin->log, WLOG_ERROR, "invalid format index %"PRIu32" (total %d)", + initialFormat, callback->formats_count); return ERROR_INVALID_DATA; } @@ -381,7 +394,7 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error); + WLog_Print(audin->log, WLOG_ERROR, "SetFormat failed with errorcode %"PRIu32"", error); return error; } @@ -389,19 +402,19 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error); + WLog_Print(audin->log, WLOG_ERROR, "Open failed with errorcode %"PRIu32"", error); return error; } } - if ((error = audin_send_format_change_pdu(pChannelCallback, initialFormat))) + if ((error = audin_send_format_change_pdu(audin, callback, initialFormat))) { - WLog_ERR(TAG, "audin_send_format_change_pdu failed!"); + WLog_Print(audin->log, WLOG_ERROR, "audin_send_format_change_pdu failed!"); return error; } - if ((error = audin_send_open_reply_pdu(pChannelCallback, 0))) - WLog_ERR(TAG, "audin_send_open_reply_pdu failed!"); + if ((error = audin_send_open_reply_pdu(audin, callback, 0))) + WLog_Print(audin->log, WLOG_ERROR, "audin_send_open_reply_pdu failed!"); return error; } @@ -411,20 +424,26 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallback, wStream* s) +static UINT audin_process_format_change(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, + wStream* s) { - AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; UINT32 NewFormat; audinFormat* format; UINT error = CHANNEL_RC_OK; + + if (!audin || !callback || !s) + return ERROR_INTERNAL_ERROR; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_NO_DATA; + Stream_Read_UINT32(s, NewFormat); DEBUG_DVC("NewFormat=%"PRIu32"", NewFormat); - if (NewFormat >= (UINT32) callback->formats_count) + if (NewFormat >= callback->formats_count) { - WLog_ERR(TAG, "invalid format index %"PRIu32" (total %d)", - NewFormat, callback->formats_count); + WLog_Print(audin->log, WLOG_ERROR, "invalid format index %"PRIu32" (total %d)", + NewFormat, callback->formats_count); return ERROR_INVALID_DATA; } @@ -436,7 +455,7 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error); + WLog_Print(audin->log, WLOG_ERROR, "Close failed with errorcode %"PRIu32"", error); return error; } @@ -444,7 +463,7 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error); + WLog_Print(audin->log, WLOG_ERROR, "SetFormat failed with errorcode %"PRIu32"", error); return error; } @@ -452,13 +471,13 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error); + WLog_Print(audin->log, WLOG_ERROR, "Open failed with errorcode %"PRIu32"", error); return error; } } - if ((error = audin_send_format_change_pdu(pChannelCallback, NewFormat))) - WLog_ERR(TAG, "audin_send_format_change_pdu failed!"); + if ((error = audin_send_format_change_pdu(audin, callback, NewFormat))) + WLog_Print(audin->log, WLOG_ERROR, "audin_send_format_change_pdu failed!"); return error; } @@ -472,29 +491,43 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, { UINT error; BYTE MessageId; + AUDIN_PLUGIN* audin; + AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; + + if (!callback || !data) + return ERROR_INVALID_PARAMETER; + + audin = (AUDIN_PLUGIN*) callback->plugin; + + if (!audin) + return ERROR_INTERNAL_ERROR; + + if (Stream_GetRemainingCapacity(data) < 1) + return ERROR_NO_DATA; + Stream_Read_UINT8(data, MessageId); DEBUG_DVC("MessageId=0x%02"PRIx8"", MessageId); switch (MessageId) { case MSG_SNDIN_VERSION: - error = audin_process_version(pChannelCallback, data); + error = audin_process_version(audin, callback, data); break; case MSG_SNDIN_FORMATS: - error = audin_process_formats(pChannelCallback, data); + error = audin_process_formats(audin, callback, data); break; case MSG_SNDIN_OPEN: - error = audin_process_open(pChannelCallback, data); + error = audin_process_open(audin, callback, data); break; case MSG_SNDIN_FORMATCHANGE: - error = audin_process_format_change(pChannelCallback, data); + error = audin_process_format_change(audin, callback, data); break; default: - WLog_ERR(TAG, "unknown MessageId=0x%02"PRIx8"", MessageId); + WLog_Print(audin->log, WLOG_ERROR, "unknown MessageId=0x%02"PRIx8"", MessageId); error = ERROR_INVALID_DATA; break; } @@ -519,7 +552,7 @@ static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) IFCALLRET(audin->device->Close, error, audin->device); if (error != CHANNEL_RC_OK) - WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error); + WLog_Print(audin->log, WLOG_ERROR, "Close failed with errorcode %"PRIu32"", error); } free(callback->formats); @@ -537,13 +570,19 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb IWTSVirtualChannelCallback** ppCallback) { AUDIN_CHANNEL_CALLBACK* callback; + AUDIN_PLUGIN* audin; AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback; + + if (!listener_callback || !listener_callback->plugin) + return ERROR_INTERNAL_ERROR; + + audin = (AUDIN_PLUGIN*) listener_callback->plugin; DEBUG_DVC("..."); callback = (AUDIN_CHANNEL_CALLBACK*) calloc(1, sizeof(AUDIN_CHANNEL_CALLBACK)); if (!callback) { - WLog_ERR(TAG, "calloc failed!"); + WLog_Print(audin->log, WLOG_ERROR, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -569,7 +608,7 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag if (!audin->listener_callback) { - WLog_ERR(TAG, "calloc failed!"); + WLog_Print(audin->log, WLOG_ERROR, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -597,7 +636,7 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin) if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "Free failed with errorcode %"PRIu32"", error); + WLog_Print(audin->log, WLOG_ERROR, "Free failed with errorcode %"PRIu32"", error); // dont stop on error } @@ -648,7 +687,7 @@ static UINT audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi if (audin->device) { - WLog_ERR(TAG, "existing device, abort."); + WLog_Print(audin->log, WLOG_ERROR, "existing device, abort."); return ERROR_ALREADY_EXISTS; } @@ -662,38 +701,34 @@ static UINT audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args) +static UINT audin_load_device_plugin(AUDIN_PLUGIN* audin, char* name, ADDIN_ARGV* args) { PFREERDP_AUDIN_DEVICE_ENTRY entry; FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints; - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin; UINT error; - - if (!audin_process_addin_args(audin, args)) - return CHANNEL_RC_INITIALIZATION_ERROR; - - entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL, + entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", name, NULL, 0); if (entry == NULL) { - WLog_ERR(TAG, "freerdp_load_channel_addin_entry did not return any function pointers for %s ", - name); + WLog_Print(audin->log, WLOG_ERROR, + "freerdp_load_channel_addin_entry did not return any function pointers for %s ", + name); return ERROR_INVALID_FUNCTION; } - entryPoints.plugin = pPlugin; + entryPoints.plugin = (IWTSPlugin*) audin; entryPoints.pRegisterAudinDevice = audin_register_device_plugin; entryPoints.args = args; - entryPoints.rdpcontext = ((AUDIN_PLUGIN*)pPlugin)->rdpcontext; + entryPoints.rdpcontext = audin->rdpcontext; if ((error = entry(&entryPoints))) { - WLog_ERR(TAG, "%s entry returned error %"PRIu32".", name, error); + WLog_Print(audin->log, WLOG_ERROR, "%s entry returned error %"PRIu32".", name, error); return error; } - WLog_INFO(TAG, "Loaded %s backend for audin", name); + WLog_Print(audin->log, WLOG_INFO, "Loaded %s backend for audin", name); return CHANNEL_RC_OK; } @@ -702,14 +737,14 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem) +static UINT audin_set_subsystem(AUDIN_PLUGIN* audin, const char* subsystem) { free(audin->subsystem); audin->subsystem = _strdup(subsystem); if (!audin->subsystem) { - WLog_ERR(TAG, "_strdup failed!"); + WLog_Print(audin->log, WLOG_ERROR, "_strdup failed!"); return ERROR_NOT_ENOUGH_MEMORY; } @@ -728,7 +763,7 @@ static UINT audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name) if (!audin->device_name) { - WLog_ERR(TAG, "_strdup failed!"); + WLog_Print(audin->log, WLOG_ERROR, "_strdup failed!"); return ERROR_NOT_ENOUGH_MEMORY; } @@ -763,6 +798,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args) return FALSE; arg = audin_args; + errno = 0; do { @@ -774,7 +810,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args) { if ((error = audin_set_subsystem(audin, arg->Value))) { - WLog_ERR(TAG, "audin_set_subsystem failed with error %"PRIu32"!", error); + WLog_Print(audin->log, WLOG_ERROR, "audin_set_subsystem failed with error %"PRIu32"!", error); return FALSE; } } @@ -782,21 +818,34 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args) { if ((error = audin_set_device_name(audin, arg->Value))) { - WLog_ERR(TAG, "audin_set_device_name failed with error %"PRIu32"!", error); + WLog_Print(audin->log, WLOG_ERROR, "audin_set_device_name failed with error %"PRIu32"!", error); return FALSE; } } CommandLineSwitchCase(arg, "format") { - audin->fixed_format = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT16_MAX)) + return FALSE; + + audin->fixed_format = val; } CommandLineSwitchCase(arg, "rate") { - audin->fixed_rate = atoi(arg->Value); + long val = strtol(arg->Value, NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + return FALSE; + + audin->fixed_rate = val; } CommandLineSwitchCase(arg, "channel") { - audin->fixed_channel = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT16_MAX)) + audin->fixed_channel = val; } CommandLineSwitchDefault(arg) { @@ -867,6 +916,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) return CHANNEL_RC_NO_MEMORY; } + audin->log = WLog_Get(TAG); audin->attached = TRUE; audin->iface.Initialize = audin_plugin_initialize; audin->iface.Connected = NULL; @@ -886,10 +936,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) if (audin->subsystem) { - if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) + if ((error = audin_load_device_plugin(audin, audin->subsystem, args))) { - WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %"PRIu32"!", - audin->subsystem, error); + WLog_Print(audin->log, WLOG_ERROR, "audin_load_device_plugin %s failed with error %"PRIu32"!", + audin->subsystem, error); goto out; } } @@ -899,18 +949,18 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { if ((error = audin_set_subsystem(audin, entry->subsystem))) { - WLog_ERR(TAG, "audin_set_subsystem for %s failed with error %"PRIu32"!", - entry->subsystem, error); + WLog_Print(audin->log, WLOG_ERROR, "audin_set_subsystem for %s failed with error %"PRIu32"!", + entry->subsystem, error); } else if ((error = audin_set_device_name(audin, entry->device))) { - WLog_ERR(TAG, "audin_set_device_name for %s failed with error %"PRIu32"!", - entry->subsystem, error); + WLog_Print(audin->log, WLOG_ERROR, "audin_set_device_name for %s failed with error %"PRIu32"!", + entry->subsystem, error); } - else if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) + else if ((error = audin_load_device_plugin(audin, audin->subsystem, args))) { - WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %"PRIu32"!", - entry->subsystem, error); + WLog_Print(audin->log, WLOG_ERROR, "audin_load_device_plugin %s failed with error %"PRIu32"!", + entry->subsystem, error); } entry++; @@ -918,7 +968,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) } if (audin->device == NULL) - WLog_ERR(TAG, "no sound device."); + WLog_Print(audin->log, WLOG_ERROR, "no sound device."); error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin); out: diff --git a/channels/audin/client/opensles/audin_opensl_es.c b/channels/audin/client/opensles/audin_opensl_es.c index e196916..8a11aff 100644 --- a/channels/audin/client/opensles/audin_opensl_es.c +++ b/channels/audin/client/opensles/audin_opensl_es.c @@ -70,7 +70,7 @@ typedef struct _AudinOpenSLESDevice rdpContext* rdpcontext; } AudinOpenSLESDevice; -static void* audin_opensles_thread_func(void* arg) +static DWORD WINAPI audin_opensles_thread_func(LPVOID arg) { union { @@ -173,8 +173,8 @@ out: if (error && opensles->rdpcontext) setChannelError(opensles->rdpcontext, error, "audin_opensles_thread_func reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -356,7 +356,7 @@ static UINT audin_opensles_open(IAudinDevice* device, AudinReceive receive, goto error_out; } if (!(opensles->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) audin_opensles_thread_func, + audin_opensles_thread_func, opensles, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c index 9e166b0..fb72ea2 100644 --- a/channels/audin/client/oss/audin_oss.c +++ b/channels/audin/client/oss/audin_oss.c @@ -173,7 +173,7 @@ static UINT audin_oss_set_format(IAudinDevice* device, audinFormat* format, return CHANNEL_RC_OK; } -static void* audin_oss_thread_func(void* arg) +static DWORD WINAPI audin_oss_thread_func(LPVOID arg) { char dev_name[PATH_MAX] = "/dev/dsp"; char mixer_name[PATH_MAX] = "/dev/mixer"; @@ -352,8 +352,8 @@ err_out: } free(buffer); - ExitThread(0); - return NULL; + ExitThread(error); + return error; } /** @@ -374,8 +374,7 @@ static UINT audin_oss_open(IAudinDevice* device, AudinReceive receive, return ERROR_INTERNAL_ERROR; } - if (!(oss->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL))) + if (!(oss->thread = CreateThread(NULL, 0, audin_oss_thread_func, oss, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(oss->stopEvent); @@ -471,6 +470,7 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args) return ERROR_INVALID_PARAMETER; arg = audin_oss_args; + errno = 0; do { @@ -488,7 +488,17 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args) return CHANNEL_RC_NO_MEMORY; } - oss->dev_unit = strtol(str_num, &eptr, 10); + { + long val = strtol(str_num, &eptr, 10); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + { + free(str_num); + return CHANNEL_RC_NULL_DATA; + } + + oss->dev_unit = val; + } if (oss->dev_unit < 0 || *eptr != '\0') oss->dev_unit = -1; diff --git a/channels/audin/client/pulse/audin_pulse.c b/channels/audin/client/pulse/audin_pulse.c index da12128..e3b163e 100644 --- a/channels/audin/client/pulse/audin_pulse.c +++ b/channels/audin/client/pulse/audin_pulse.c @@ -400,14 +400,15 @@ static UINT audin_pulse_close(IAudinDevice* device) { AudinPulseDevice* pulse = (AudinPulseDevice*) device; - if (!pulse->context || !pulse->stream) - return ERROR_INVALID_PARAMETER; + if (pulse->stream) + { + pa_threaded_mainloop_lock(pulse->mainloop); + pa_stream_disconnect(pulse->stream); + pa_stream_unref(pulse->stream); + pulse->stream = NULL; + pa_threaded_mainloop_unlock(pulse->mainloop); + } - pa_threaded_mainloop_lock(pulse->mainloop); - pa_stream_disconnect(pulse->stream); - pa_stream_unref(pulse->stream); - pulse->stream = NULL; - pa_threaded_mainloop_unlock(pulse->mainloop); pulse->receive = NULL; pulse->user_data = NULL; diff --git a/channels/audin/client/winmm/audin_winmm.c b/channels/audin/client/winmm/audin_winmm.c index 519d8fa..aff631c 100644 --- a/channels/audin/client/winmm/audin_winmm.c +++ b/channels/audin/client/winmm/audin_winmm.c @@ -94,7 +94,7 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance setChannelError(winmm->rdpcontext, error, "waveInProc reported an error"); } -static DWORD audin_winmm_thread_func(void* arg) +static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) { AudinWinmmDevice* winmm = (AudinWinmmDevice*) arg; char *buffer; @@ -332,8 +332,7 @@ static UINT audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* u return ERROR_INTERNAL_ERROR; } - if (!(winmm->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) audin_winmm_thread_func, winmm, 0, NULL))) + if (!(winmm->thread = CreateThread(NULL, 0, audin_winmm_thread_func, winmm, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(winmm->stopEvent); diff --git a/channels/audin/server/audin.c b/channels/audin/server/audin.c index 106eb86..fc42fe1 100644 --- a/channels/audin/server/audin.c +++ b/channels/audin/server/audin.c @@ -401,7 +401,7 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, return success; } -static void* audin_server_thread_func(void* arg) +static DWORD WINAPI audin_server_thread_func(LPVOID arg) { wStream* s; void* buffer; @@ -596,8 +596,8 @@ out: setChannelError(audin->context.rdpcontext, error, "audin_server_thread_func reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } static BOOL audin_server_open(audin_server_context* context) @@ -632,8 +632,7 @@ static BOOL audin_server_open(audin_server_context* context) return FALSE; } - if (!(audin->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL))) + if (!(audin->thread = CreateThread(NULL, 0, audin_server_thread_func, (void*) audin, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(audin->stopEvent); diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index 12ffdce..a97a584 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -42,7 +42,7 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { UINT32 index; - UINT32 position; + size_t position; BOOL asciiNames; int formatNameLength; char* szFormatName; diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 5be5719..6fe05dd 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -34,6 +34,7 @@ #include "cliprdr_main.h" #include "cliprdr_format.h" +#ifdef WITH_DEBUG_CLIPRDR static const char* const CB_MSG_TYPE_STRINGS[] = { "", @@ -49,6 +50,7 @@ static const char* const CB_MSG_TYPE_STRINGS[] = "CB_LOCK_CLIPDATA", "CB_UNLOCK_CLIPDATA" }; +#endif CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr) { @@ -87,7 +89,7 @@ static wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, */ static UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s) { - UINT32 pos; + size_t pos; UINT32 dataLen; UINT status = CHANNEL_RC_OK; pos = Stream_GetPosition(s); @@ -160,6 +162,9 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, return ERROR_INTERNAL_ERROR; } + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(s, version); /* version (4 bytes) */ Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ DEBUG_CLIPRDR("Version: %"PRIu32"", version); @@ -218,15 +223,25 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 cCapabilitiesSets; UINT16 capabilitySetType; UINT error = CHANNEL_RC_OK; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ Stream_Seek_UINT16(s); /* pad1 (2 bytes) */ WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerCapabilities"); for (index = 0; index < cCapabilitiesSets; index++) { + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */ + if (lengthCapability < 4 || Stream_GetRemainingLength(s) < lengthCapability-4) + return ERROR_INVALID_DATA; + switch (capabilitySetType) { case CB_CAPSTYPE_GENERAL: @@ -448,8 +463,7 @@ static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA; unlockClipboardData.msgFlags = flags; unlockClipboardData.dataLen = length; - Stream_Read_UINT32(s, - unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */ + Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */ IFCALLRET(context->ServerUnlockClipboardData, error, context, &unlockClipboardData); @@ -470,9 +484,17 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s) UINT16 msgFlags; UINT32 dataLen; UINT error; + + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + Stream_Read_UINT16(s, msgType); /* msgType (2 bytes) */ Stream_Read_UINT16(s, msgFlags); /* msgFlags (2 bytes) */ Stream_Read_UINT32(s, dataLen); /* dataLen (4 bytes) */ + + if (Stream_GetRemainingLength(s) < dataLen) + return ERROR_INVALID_DATA; + #ifdef WITH_DEBUG_CLIPRDR WLog_DBG(TAG, "msgType: %s (%"PRIu16"), msgFlags: %"PRIu16" dataLen: %"PRIu32"", CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); @@ -500,40 +522,35 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s) break; case CB_FORMAT_LIST_RESPONSE: - if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen, - msgFlags))) + if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_format_list_response failed with error %"PRIu32"!", error); break; case CB_FORMAT_DATA_REQUEST: - if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen, - msgFlags))) + if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_format_data_request failed with error %"PRIu32"!", error); break; case CB_FORMAT_DATA_RESPONSE: - if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen, - msgFlags))) + if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_format_data_response failed with error %"PRIu32"!", error); break; case CB_FILECONTENTS_REQUEST: - if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen, - msgFlags))) + if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_filecontents_request failed with error %"PRIu32"!", error); break; case CB_FILECONTENTS_RESPONSE: - if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen, - msgFlags))) + if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_filecontents_response failed with error %"PRIu32"!", error); @@ -586,12 +603,9 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context, Stream_Write_UINT16(s, 1); /* cCapabilitiesSets */ Stream_Write_UINT16(s, 0); /* pad1 */ - generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*) - capabilities->capabilitySets; - Stream_Write_UINT16(s, - generalCapabilitySet->capabilitySetType); /* capabilitySetType */ - Stream_Write_UINT16(s, - generalCapabilitySet->capabilitySetLength); /* lengthCapability */ + generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*)capabilities->capabilitySets; + Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetType); /* capabilitySetType */ + Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetLength); /* lengthCapability */ Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */ Stream_Write_UINT32(s, generalCapabilitySet->generalFlags); /* generalFlags */ WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientCapabilities"); @@ -618,9 +632,7 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context, return ERROR_INTERNAL_ERROR; } - length = ConvertToUnicode(CP_UTF8, 0, tempDirectory->szTempDir, -1, &wszTempDir, - 0); - + length = ConvertToUnicode(CP_UTF8, 0, tempDirectory->szTempDir, -1, &wszTempDir, 0); if (length < 0) return ERROR_INTERNAL_ERROR; @@ -796,8 +808,7 @@ static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context, return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, - lockClipboardData->clipDataId); /* clipDataId (4 bytes) */ + Stream_Write_UINT32(s, lockClipboardData->clipDataId); /* clipDataId (4 bytes) */ WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientLockClipboardData: clipDataId: 0x%08"PRIX32"", lockClipboardData->clipDataId); @@ -822,8 +833,7 @@ static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context, return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, - unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */ + Stream_Write_UINT32(s, unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */ WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientUnlockClipboardData: clipDataId: 0x%08"PRIX32"", unlockClipboardData->clipDataId); @@ -852,8 +862,7 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context, return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, - formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */ + Stream_Write_UINT32(s, formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */ WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataRequest"); return cliprdr_packet_send(cliprdr, s); } @@ -1048,7 +1057,7 @@ static VOID VCAPITYPE cliprdr_virtual_channel_open_event_ex(LPVOID lpUserParam, "cliprdr_virtual_channel_open_event_ex reported an error"); } -static void* cliprdr_virtual_channel_client_thread(void* arg) +static DWORD WINAPI cliprdr_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; @@ -1090,8 +1099,8 @@ static void* cliprdr_virtual_channel_client_thread(void* arg) setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_client_thread reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -1122,8 +1131,7 @@ static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr, return ERROR_NOT_ENOUGH_MEMORY; } - if (!(cliprdr->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) cliprdr_virtual_channel_client_thread, (void*) cliprdr, + if (!(cliprdr->thread = CreateThread(NULL, 0, cliprdr_virtual_channel_client_thread, (void*) cliprdr, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); @@ -1182,6 +1190,7 @@ static UINT cliprdr_virtual_channel_event_disconnected(cliprdrPlugin* cliprdr) static UINT cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprdr) { cliprdr->InitHandle = 0; + free(cliprdr->context); free(cliprdr); return CHANNEL_RC_OK; } @@ -1201,8 +1210,7 @@ static VOID VCAPITYPE cliprdr_virtual_channel_init_event_ex(LPVOID lpUserParam, switch (event) { case CHANNEL_EVENT_CONNECTED: - if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData, - dataLength))) + if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData, dataLength))) WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %"PRIu32"!", error); diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c index 1b8268e..118c2b0 100644 --- a/channels/cliprdr/server/cliprdr_main.c +++ b/channels/cliprdr/server/cliprdr_main.c @@ -91,7 +91,7 @@ wStream* cliprdr_server_packet_new(UINT16 msgType, UINT16 msgFlags, */ UINT cliprdr_server_packet_send(CliprdrServerPrivate* cliprdr, wStream* s) { - UINT32 pos; + size_t pos; BOOL status; UINT32 dataLen; UINT32 written; @@ -628,7 +628,7 @@ static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, { UINT32 index; UINT32 dataLen; - UINT32 position; + size_t position; BOOL asciiNames; int formatNameLength; char* szFormatName; @@ -1185,7 +1185,7 @@ static UINT cliprdr_server_init(CliprdrServerContext* context) UINT cliprdr_server_read(CliprdrServerContext* context) { wStream* s; - int position; + size_t position; DWORD BytesToRead; DWORD BytesReturned; CLIPRDR_HEADER header; @@ -1319,7 +1319,7 @@ UINT cliprdr_server_read(CliprdrServerContext* context) return CHANNEL_RC_OK; } -static void* cliprdr_server_thread(void* arg) +static DWORD WINAPI cliprdr_server_thread(LPVOID arg) { DWORD status; DWORD nCount; @@ -1388,8 +1388,8 @@ out: setChannelError(context->rdpcontext, error, "cliprdr_server_thread reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -1478,8 +1478,7 @@ static UINT cliprdr_server_start(CliprdrServerContext* context) return ERROR_INTERNAL_ERROR; } - if (!(cliprdr->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) cliprdr_server_thread, (void*) context, 0, NULL))) + if (!(cliprdr->Thread = CreateThread(NULL, 0, cliprdr_server_thread, (void*) context, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(cliprdr->StopEvent); diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c index 98f8d1f..0555317 100755 --- a/channels/disp/client/disp_main.c +++ b/channels/disp/client/disp_main.c @@ -98,7 +98,6 @@ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callbac type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT; s = Stream_New(NULL, length); - if(!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -112,10 +111,9 @@ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callbac NumMonitors = disp->MaxNumMonitors; Stream_Write_UINT32(s, MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */ - Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */ - //WLog_ERR(TAG, "NumMonitors: %"PRIu32"", NumMonitors); + WLog_DBG(TAG, "disp_send_display_control_monitor_layout_pdu: NumMonitors=%"PRIu32"", NumMonitors); for (index = 0; index < NumMonitors; index++) { @@ -147,16 +145,11 @@ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callbac Stream_Write_UINT32(s, Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */ -#if 0 - WLog_DBG(TAG, "\t: Flags: 0x%08"PRIX32"", Monitors[index].Flags); - WLog_DBG(TAG, "\t: Left: %"PRId32"", Monitors[index].Left); - WLog_DBG(TAG, "\t: Top: %"PRId32"", Monitors[index].Top); - WLog_DBG(TAG, "\t: Width: %"PRIu32"", Monitors[index].Width); - WLog_DBG(TAG, "\t: Height: %"PRIu32"", Monitors[index].Height); - WLog_DBG(TAG, "\t: PhysicalWidth: %"PRIu32"", Monitors[index].PhysicalWidth); - WLog_DBG(TAG, "\t: PhysicalHeight: %"PRIu32"", Monitors[index].PhysicalHeight); - WLog_DBG(TAG, "\t: Orientation: %"PRIu32"", Monitors[index].Orientation); -#endif + WLog_DBG(TAG, "\t%d : Flags: 0x%08"PRIX32" Left/Top: (%"PRId32",%"PRId32") W/H=%"PRIu32"x%"PRIu32")", index, + Monitors[index].Flags, Monitors[index].Left, Monitors[index].Top, Monitors[index].Width, + Monitors[index].Height); + WLog_DBG(TAG, "\t PhysicalWidth: %"PRIu32" PhysicalHeight: %"PRIu32" Orientation: %"PRIu32"", + Monitors[index].PhysicalWidth, Monitors[index].PhysicalHeight, Monitors[index].Orientation); } Stream_SealLength(s); @@ -176,8 +169,11 @@ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callbac UINT disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s) { DISP_PLUGIN* disp; + DispClientContext *context; + UINT ret = CHANNEL_RC_OK; disp = (DISP_PLUGIN*) callback->plugin; + context = (DispClientContext *)disp->iface.pInterface; if (Stream_GetRemainingLength(s) < 12) { @@ -188,10 +184,11 @@ UINT disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream Stream_Read_UINT32(s, disp->MaxNumMonitors); /* MaxNumMonitors (4 bytes) */ Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorA); /* MaxMonitorAreaFactorA (4 bytes) */ Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorB); /* MaxMonitorAreaFactorB (4 bytes) */ - //WLog_ERR(TAG, "DisplayControlCapsPdu: MaxNumMonitors: %"PRIu32" MaxMonitorAreaFactorA: %"PRIu32" MaxMonitorAreaFactorB: %"PRIu32"", - // disp->MaxNumMonitors, disp->MaxMonitorAreaFactorA, disp->MaxMonitorAreaFactorB); - return CHANNEL_RC_OK; + if (context->DisplayControlCaps) + ret = context->DisplayControlCaps(context, disp->MaxNumMonitors, disp->MaxMonitorAreaFactorA, disp->MaxMonitorAreaFactorB); + + return ret; } /** @@ -360,11 +357,9 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) DispClientContext* context; disp = (DISP_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "disp"); - if (!disp) { disp = (DISP_PLUGIN*) calloc(1, sizeof(DISP_PLUGIN)); - if (!disp) { WLog_ERR(TAG, "calloc failed!"); @@ -375,9 +370,11 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) disp->iface.Connected = NULL; disp->iface.Disconnected = NULL; disp->iface.Terminated = disp_plugin_terminated; + disp->MaxNumMonitors = 16; + disp->MaxMonitorAreaFactorA = 8192; + disp->MaxMonitorAreaFactorB = 8192; context = (DispClientContext*) calloc(1, sizeof(DispClientContext)); - if (!context) { WLog_ERR(TAG, "calloc failed!"); @@ -386,15 +383,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) } context->handle = (void*) disp; - context->SendMonitorLayout = disp_send_monitor_layout; disp->iface.pInterface = (void*) context; - disp->MaxNumMonitors = 16; - disp->MaxMonitorAreaFactorA = 8192; - disp->MaxMonitorAreaFactorB = 8192; - error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*) disp); } else diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index acf873c..e7314ca 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -189,7 +189,7 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) if (!dvcman) { - WLog_ERR(TAG, "calloc failed!"); + WLog_Print(plugin->log, WLOG_ERROR, "calloc failed!"); return NULL; } @@ -201,7 +201,7 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) if (!dvcman->channels) { - WLog_ERR(TAG, "ArrayList_New failed!"); + WLog_Print(plugin->log, WLOG_ERROR, "ArrayList_New failed!"); free(dvcman); return NULL; } @@ -211,7 +211,7 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) if (!dvcman->pool) { - WLog_ERR(TAG, "StreamPool_New failed!"); + WLog_Print(plugin->log, WLOG_ERROR, "StreamPool_New failed!"); ArrayList_Free(dvcman->channels); free(dvcman); return NULL; @@ -225,13 +225,14 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, +static UINT dvcman_load_addin(drdynvcPlugin* drdynvc, + IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args, rdpSettings* settings) { DVCMAN_ENTRY_POINTS entryPoints; PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL; - WLog_INFO(TAG, "Loading Dynamic Virtual Channel %s", args->argv[0]); + WLog_Print(drdynvc->log, WLOG_INFO, "Loading Dynamic Virtual Channel %s", args->argv[0]); pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry( args->argv[0], NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC); @@ -251,16 +252,17 @@ static UINT dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, return ERROR_INVALID_FUNCTION; } -static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager* - pChannelMgr, +static DVCMAN_CHANNEL* dvcman_channel_new(drdynvcPlugin* drdynvc, + IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName) { DVCMAN_CHANNEL* channel; if (dvcman_find_channel_by_id(pChannelMgr, ChannelId)) { - WLog_ERR(TAG, "Protocol error: Duplicated ChannelId %"PRIu32" (%s)!", ChannelId, - ChannelName); + WLog_Print(drdynvc->log, WLOG_ERROR, "Protocol error: Duplicated ChannelId %"PRIu32" (%s)!", + ChannelId, + ChannelName); return NULL; } @@ -268,7 +270,7 @@ static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager* if (!channel) { - WLog_ERR(TAG, "calloc failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "calloc failed!"); return NULL; } @@ -278,14 +280,14 @@ static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager* if (!channel->channel_name) { - WLog_ERR(TAG, "_strdup failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "_strdup failed!"); free(channel); return NULL; } - if (!InitializeCriticalSectionEx(&(channel->lock), 0 , 0)) + if (!InitializeCriticalSectionEx(&(channel->lock), 0, 0)) { - WLog_ERR(TAG, "InitializeCriticalSectionEx failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "InitializeCriticalSectionEx failed!"); free(channel->channel_name); free(channel); return NULL; @@ -297,31 +299,49 @@ static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager* static void dvcman_channel_free(void* arg) { DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) arg; + UINT error = CHANNEL_RC_OK; - if (channel->channel_callback) + if (channel) { - channel->channel_callback->OnClose(channel->channel_callback); - channel->channel_callback = NULL; - } + if (channel->channel_callback) + { + IFCALL(channel->channel_callback->OnClose, + channel->channel_callback); + } - if (channel->dvc_data) - { - Stream_Release(channel->dvc_data); - channel->dvc_data = NULL; - } + if (channel->status == CHANNEL_RC_OK) + { + IWTSVirtualChannel* ichannel = (IWTSVirtualChannel*) channel; - DeleteCriticalSection(&(channel->lock)); + if (channel->dvcman && channel->dvcman->drdynvc) + { + DrdynvcClientContext* context = channel->dvcman->drdynvc->context; - if (channel->channel_name) - { + if (context) + { + IFCALLRET(context->OnChannelDisconnected, error, + context, channel->channel_name, + channel->pInterface); + } + } + + error = IFCALLRESULT(CHANNEL_RC_OK, ichannel->Close, ichannel); + + if (error != CHANNEL_RC_OK) + WLog_ERR(TAG, "Close failed with error %"PRIu32"!", error); + } + + if (channel->dvc_data) + Stream_Release(channel->dvc_data); + + DeleteCriticalSection(&(channel->lock)); free(channel->channel_name); - channel->channel_name = NULL; } free(channel); } -static void dvcman_free(IWTSVirtualChannelManager* pChannelMgr) +static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr) { int i; IWTSPlugin* pPlugin; @@ -345,7 +365,7 @@ static void dvcman_free(IWTSVirtualChannelManager* pChannelMgr) if (pPlugin->Terminated) if ((error = pPlugin->Terminated(pPlugin))) - WLog_ERR(TAG, "Terminated failed with error %"PRIu32"!", error); + WLog_Print(drdynvc->log, WLOG_ERROR, "Terminated failed with error %"PRIu32"!", error); } dvcman->num_plugins = 0; @@ -358,7 +378,7 @@ static void dvcman_free(IWTSVirtualChannelManager* pChannelMgr) * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_init(IWTSVirtualChannelManager* pChannelMgr) +static UINT dvcman_init(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr) { int i; IWTSPlugin* pPlugin; @@ -372,7 +392,7 @@ static UINT dvcman_init(IWTSVirtualChannelManager* pChannelMgr) if (pPlugin->Initialize) if ((error = pPlugin->Initialize(pPlugin, pChannelMgr))) { - WLog_ERR(TAG, "Initialize failed with error %"PRIu32"!", error); + WLog_Print(drdynvc->log, WLOG_ERROR, "Initialize failed with error %"PRIu32"!", error); return error; } } @@ -422,7 +442,8 @@ static UINT dvcman_close_channel_iface(IWTSVirtualChannel* pChannel) * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, +static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, + IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName) { int i; @@ -434,13 +455,13 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, DVCMAN* dvcman = (DVCMAN*) pChannelMgr; UINT error; - if (!(channel = dvcman_channel_new(pChannelMgr, ChannelId, ChannelName))) + if (!(channel = dvcman_channel_new(drdynvc, pChannelMgr, ChannelId, ChannelName))) { - WLog_ERR(TAG, "dvcman_channel_new failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_channel_new failed!"); return CHANNEL_RC_NO_MEMORY; } - channel->status = 1; + channel->status = ERROR_NOT_CONNECTED; ArrayList_Add(dvcman->channels, channel); for (i = 0; i < dvcman->num_listeners; i++) @@ -459,9 +480,9 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, (IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback)) == CHANNEL_RC_OK && bAccept) { - WLog_DBG(TAG, "listener %s created new channel %"PRIu32"", - listener->channel_name, channel->channel_id); - channel->status = 0; + WLog_Print(drdynvc->log, WLOG_DEBUG, "listener %s created new channel %"PRIu32"", + listener->channel_name, channel->channel_id); + channel->status = CHANNEL_RC_OK; channel->channel_callback = pCallback; channel->pInterface = listener->iface.pInterface; context = dvcman->drdynvc->context; @@ -469,7 +490,8 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, listener->iface.pInterface); if (error) - WLog_ERR(TAG, "context.ReceiveSamples failed with error %"PRIu32"", error); + WLog_Print(drdynvc->log, WLOG_ERROR, "context.OnChannelConnected failed with error %"PRIu32"", + error); return error; } @@ -477,12 +499,12 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, { if (error) { - WLog_ERR(TAG, "OnNewChannelConnection failed with error %"PRIu32"!", error); + WLog_Print(drdynvc->log, WLOG_ERROR, "OnNewChannelConnection failed with error %"PRIu32"!", error); return error; } else { - WLog_ERR(TAG, "OnNewChannelConnection returned with bAccept FALSE!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "OnNewChannelConnection returned with bAccept FALSE!"); return ERROR_INTERNAL_ERROR; } } @@ -497,7 +519,8 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, +static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, + IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId) { DVCMAN_CHANNEL* channel; @@ -507,7 +530,7 @@ static UINT dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, if (!channel) { - WLog_ERR(TAG, "ChannelId %"PRIu32" not found!", ChannelId); + WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); return ERROR_INTERNAL_ERROR; } @@ -517,11 +540,11 @@ static UINT dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, if ((pCallback->OnOpen) && (error = pCallback->OnOpen(pCallback))) { - WLog_ERR(TAG, "OnOpen failed with error %"PRIu32"!", error); + WLog_Print(drdynvc->log, WLOG_ERROR, "OnOpen failed with error %"PRIu32"!", error); return error; } - WLog_DBG(TAG, "open_channel: ChannelId %"PRIu32"", ChannelId); + WLog_Print(drdynvc->log, WLOG_DEBUG, "open_channel: ChannelId %"PRIu32"", ChannelId); } return CHANNEL_RC_OK; @@ -536,15 +559,13 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId) { DVCMAN_CHANNEL* channel; - IWTSVirtualChannel* ichannel; - DrdynvcClientContext* context; - DVCMAN* dvcman = (DVCMAN*) pChannelMgr; UINT error = CHANNEL_RC_OK; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { - //WLog_ERR(TAG, "ChannelId %"PRIu32" not found!", ChannelId); + //WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); /** * Windows 8 / Windows Server 2012 send close requests for channels that failed to be created. * Do not warn, simply return success here. @@ -552,30 +573,8 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, return CHANNEL_RC_OK; } - if (channel->status == CHANNEL_RC_OK) - { - context = dvcman->drdynvc->context; - IFCALLRET(context->OnChannelDisconnected, error, context, channel->channel_name, - channel->pInterface); - - if (error) - { - WLog_ERR(TAG, "OnChannelDisconnected returned with error %"PRIu32"!", error); - return error; - } - - WLog_DBG(TAG, "dvcman_close_channel: channel %"PRIu32" closed", ChannelId); - ichannel = (IWTSVirtualChannel*) channel; - - if ((ichannel->Close) && (error = ichannel->Close(ichannel))) - { - WLog_ERR(TAG, "Close failed with error %"PRIu32"!", error); - return error; - } - } - ArrayList_Remove(dvcman->channels, channel); - return CHANNEL_RC_OK; + return error; } /** @@ -583,8 +582,8 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager* - pChannelMgr, +static UINT dvcman_receive_channel_data_first(drdynvcPlugin* drdynvc, + IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length) { DVCMAN_CHANNEL* channel; @@ -596,7 +595,7 @@ static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager* * Windows Server 2012 R2 can send some messages over Microsoft::Windows::RDS::Geometry::v08.01 * even if the dynamic virtual channel wasn't registered on our side. Ignoring it works. */ - WLog_ERR(TAG, "ChannelId %"PRIu32" not found!", ChannelId); + WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); return CHANNEL_RC_OK; } @@ -607,7 +606,7 @@ static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager* if (!channel->dvc_data) { - WLog_ERR(TAG, "StreamPool_Take failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -620,7 +619,8 @@ static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager* * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, +static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc, + IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data) { UINT status = CHANNEL_RC_OK; @@ -632,7 +632,7 @@ static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, { /* Windows 8.1 tries to open channels not created. * Ignore cases like this. */ - WLog_ERR(TAG, "ChannelId %"PRIu32" not found!", ChannelId); + WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); return CHANNEL_RC_OK; } @@ -642,7 +642,7 @@ static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity( channel->dvc_data)) { - WLog_ERR(TAG, "data exceeding declared length!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!"); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; return ERROR_INVALID_DATA; @@ -712,8 +712,14 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s) switch (status) { case CHANNEL_RC_OK: - case CHANNEL_RC_NOT_CONNECTED: return CHANNEL_RC_OK; + case CHANNEL_RC_NOT_CONNECTED: + Stream_Free(s, TRUE); + return CHANNEL_RC_OK; + case CHANNEL_RC_BAD_CHANNEL_HANDLE: + Stream_Free(s, TRUE); + WLog_ERR(TAG, "VirtualChannelWriteEx failed with CHANNEL_RC_BAD_CHANNEL_HANDLE"); + return status; default: Stream_Free(s, TRUE); @@ -733,7 +739,7 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data, UINT32 dataSize) { wStream* data_out; - unsigned long pos; + size_t pos; UINT32 cbChId; UINT32 cbLen; unsigned long chunkLength; @@ -922,7 +928,7 @@ static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen) static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { - unsigned long pos; + size_t pos; UINT status; UINT32 ChannelId; wStream* data_out; @@ -954,11 +960,11 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%"PRIu32" ChannelName=%s", ChannelId, Stream_Pointer(s)); - channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, + channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); data_out = Stream_New(NULL, pos + 4); - if (!s) + if (!data_out) { WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; @@ -976,22 +982,21 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, else { WLog_Print(drdynvc->log, WLOG_DEBUG, "no listener"); - Stream_Write_UINT32(data_out, - (UINT32) 0xC0000001); /* same code used by mstsc */ + Stream_Write_UINT32(data_out, (UINT32)0xC0000001); /* same code used by mstsc */ } status = drdynvc_send(drdynvc, data_out); if (status != CHANNEL_RC_OK) { - WLog_ERR(TAG, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", - WTSErrorToString(status), status); + WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", + WTSErrorToString(status), status); return status; } if (channel_status == CHANNEL_RC_OK) { - if ((status = dvcman_open_channel(drdynvc->channel_mgr, ChannelId))) + if ((status = dvcman_open_channel(drdynvc, drdynvc->channel_mgr, ChannelId))) { WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_open_channel failed with error %"PRIu32"!", status); return status; @@ -1019,15 +1024,16 @@ static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, UINT32 ChannelId; ChannelId = drdynvc_read_variable_uint(s, cbChId); Length = drdynvc_read_variable_uint(s, Sp); - WLog_DBG(TAG, "process_data_first: Sp=%d cbChId=%d, ChannelId=%"PRIu32" Length=%"PRIu32"", Sp, - cbChId, ChannelId, Length); - status = dvcman_receive_channel_data_first(drdynvc->channel_mgr, ChannelId, + WLog_Print(drdynvc->log, WLOG_DEBUG, + "process_data_first: Sp=%d cbChId=%d, ChannelId=%"PRIu32" Length=%"PRIu32"", Sp, + cbChId, ChannelId, Length); + status = dvcman_receive_channel_data_first(drdynvc, drdynvc->channel_mgr, ChannelId, Length); if (status) return status; - return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s); + return dvcman_receive_channel_data(drdynvc, drdynvc->channel_mgr, ChannelId, s); } /** @@ -1043,7 +1049,7 @@ static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, WLog_Print(drdynvc->log, WLOG_TRACE, "process_data: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp, cbChId, ChannelId); - return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s); + return dvcman_receive_channel_data(drdynvc, drdynvc->channel_mgr, ChannelId, s); } /** @@ -1059,12 +1065,13 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, UINT32 ChannelId; wStream* data_out; ChannelId = drdynvc_read_variable_uint(s, cbChId); - WLog_DBG(TAG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp, - cbChId, ChannelId); + WLog_Print(drdynvc->log, WLOG_DEBUG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", + Sp, + cbChId, ChannelId); if ((error = dvcman_close_channel(drdynvc->channel_mgr, ChannelId))) { - WLog_ERR(TAG, "dvcman_close_channel failed with error %"PRIu32"!", error); + WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_close_channel failed with error %"PRIu32"!", error); return error; } @@ -1072,7 +1079,7 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, if (!data_out) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1082,8 +1089,8 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, error = drdynvc_send(drdynvc, data_out); if (error) - WLog_ERR(TAG, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", - WTSErrorToString(error), error); + WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", + WTSErrorToString(error), error); return error; } @@ -1123,7 +1130,7 @@ static UINT drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s) return drdynvc_process_close_request(drdynvc, Sp, cbChId, s); default: - WLog_ERR(TAG, "unknown drdynvc cmd 0x%x", Cmd); + WLog_Print(drdynvc->log, WLOG_ERROR, "unknown drdynvc cmd 0x%x", Cmd); return ERROR_INTERNAL_ERROR; } } @@ -1153,13 +1160,13 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, if (!(data_in = drdynvc->data_in)) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) { - WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); Stream_Free(drdynvc->data_in, TRUE); drdynvc->data_in = NULL; return ERROR_INTERNAL_ERROR; @@ -1171,7 +1178,7 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, { if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { - WLog_ERR(TAG, "drdynvc_plugin_process_received: read error"); + WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_plugin_process_received: read error"); return ERROR_INVALID_DATA; } @@ -1181,7 +1188,7 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, if (!MessageQueue_Post(drdynvc->queue, NULL, 0, (void*) data_in, NULL)) { - WLog_ERR(TAG, "MessageQueue_Post failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; } } @@ -1198,6 +1205,7 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam, if (!drdynvc || (drdynvc->OpenHandle != openHandle)) { WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match"); + Stream_Free((wStream*) pData, TRUE); return; } @@ -1206,7 +1214,8 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam, case CHANNEL_EVENT_DATA_RECEIVED: if ((error = drdynvc_virtual_channel_event_data_received(drdynvc, pData, dataLength, totalLength, dataFlags))) - WLog_ERR(TAG, "drdynvc_virtual_channel_event_data_received failed with error %"PRIu32"", error); + WLog_Print(drdynvc->log, WLOG_ERROR, + "drdynvc_virtual_channel_event_data_received failed with error %"PRIu32"", error); break; @@ -1222,7 +1231,7 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam, setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_open_event reported an error"); } -static void* drdynvc_virtual_channel_client_thread(void* arg) +static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; @@ -1232,7 +1241,7 @@ static void* drdynvc_virtual_channel_client_thread(void* arg) if (!drdynvc) { ExitThread((DWORD) CHANNEL_RC_BAD_CHANNEL_HANDLE); - return NULL; + return CHANNEL_RC_BAD_CHANNEL_HANDLE; } while (1) @@ -1289,7 +1298,21 @@ static void* drdynvc_virtual_channel_client_thread(void* arg) "drdynvc_virtual_channel_client_thread reported an error"); ExitThread((DWORD) error); - return NULL; + return error; +} + +static void drdynvc_queue_object_free(void* obj) +{ + wStream* s; + wMessage* msg = (wMessage*)obj; + + if (!msg || (msg->id != 0)) + return; + + s = (wStream*)msg->wParam; + + if (s) + Stream_Free(s, TRUE); } /** @@ -1328,6 +1351,7 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO goto error; } + drdynvc->queue->object.fnObjectFree = drdynvc_queue_object_free; drdynvc->channel_mgr = dvcman_new(drdynvc); if (!drdynvc->channel_mgr) @@ -1342,13 +1366,13 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO for (index = 0; index < settings->DynamicChannelCount; index++) { args = settings->DynamicChannelArray[index]; - error = dvcman_load_addin(drdynvc->channel_mgr, args, settings); + error = dvcman_load_addin(drdynvc, drdynvc->channel_mgr, args, settings); if (CHANNEL_RC_OK != error) goto error; } - if ((error = dvcman_init(drdynvc->channel_mgr))) + if ((error = dvcman_init(drdynvc, drdynvc->channel_mgr))) { WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_init failed with error %"PRIu32"!", error); goto error; @@ -1356,8 +1380,7 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO drdynvc->state = DRDYNVC_STATE_CAPABILITIES; - if (!(drdynvc->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) drdynvc_virtual_channel_client_thread, (void*) drdynvc, + if (!(drdynvc->thread = CreateThread(NULL, 0, drdynvc_virtual_channel_client_thread, (void*) drdynvc, 0, NULL))) { error = ERROR_INTERNAL_ERROR; @@ -1418,7 +1441,7 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc) if (drdynvc->channel_mgr) { - dvcman_free(drdynvc->channel_mgr); + dvcman_free(drdynvc, drdynvc->channel_mgr); drdynvc->channel_mgr = NULL; } @@ -1436,6 +1459,7 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; drdynvc->InitHandle = 0; + free(drdynvc->context); free(drdynvc); return CHANNEL_RC_OK; } @@ -1598,7 +1622,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI if (!context) { - WLog_ERR(TAG, "calloc failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "calloc failed!"); free(drdynvc); return FALSE; } @@ -1610,7 +1634,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI drdynvc->rdpcontext = pEntryPointsEx->context; } - drdynvc->log = WLog_Get("com.freerdp.channels.drdynvc.client"); + drdynvc->log = WLog_Get(TAG); WLog_Print(drdynvc->log, WLOG_DEBUG, "VirtualChannelEntryEx"); CopyMemory(&(drdynvc->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); drdynvc->InitHandle = pInitHandle; diff --git a/channels/drdynvc/server/drdynvc_main.c b/channels/drdynvc/server/drdynvc_main.c index bdbc0a8..b963970 100644 --- a/channels/drdynvc/server/drdynvc_main.c +++ b/channels/drdynvc/server/drdynvc_main.c @@ -33,7 +33,7 @@ #define TAG CHANNELS_TAG("drdynvc.server") -static void* drdynvc_server_thread(void* arg) +static DWORD WINAPI drdynvc_server_thread(LPVOID arg) { #if 0 wStream* s; @@ -56,7 +56,7 @@ static void* drdynvc_server_thread(void* arg) { WLog_ERR(TAG, "Stream_New failed!"); ExitThread((DWORD) CHANNEL_RC_NO_MEMORY); - return NULL; + return CHANNEL_RC_NO_MEMORY; } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, @@ -111,7 +111,7 @@ static void* drdynvc_server_thread(void* arg) #endif // WTF ... this code only reads data into the stream until there is no more memory ExitThread(0); - return NULL; + return 0; } /** @@ -136,8 +136,7 @@ static UINT drdynvc_server_start(DrdynvcServerContext* context) return ERROR_INTERNAL_ERROR; } - if (!(context->priv->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL))) + if (!(context->priv->Thread = CreateThread(NULL, 0, drdynvc_server_thread, (void*) context, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(context->priv->StopEvent); diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index 65586e9..253b588 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -181,8 +181,11 @@ static BOOL drive_file_remove_dir(const WCHAR* path) return ret; } -static void drive_file_set_fullpath(DRIVE_FILE* file, WCHAR* fullpath) +static BOOL drive_file_set_fullpath(DRIVE_FILE* file, WCHAR* fullpath) { + if (!file || !fullpath) + return FALSE; + free(file->fullpath); file->fullpath = fullpath; file->filename = _wcsrchr(file->fullpath, L'/'); @@ -191,9 +194,11 @@ static void drive_file_set_fullpath(DRIVE_FILE* file, WCHAR* fullpath) file->filename = file->fullpath; else file->filename += 1; + + return TRUE; } -BOOL drive_file_init(DRIVE_FILE* file) +static BOOL drive_file_init(DRIVE_FILE* file) { UINT CreateDisposition = 0; DWORD dwAttr = GetFileAttributesW(file->fullpath); @@ -315,6 +320,10 @@ DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 Pat UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess) { DRIVE_FILE* file; + + if (!base_path || !path) + return NULL; + file = (DRIVE_FILE*) calloc(1, sizeof(DRIVE_FILE)); if (!file) @@ -350,6 +359,7 @@ DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 Pat BOOL drive_file_free(DRIVE_FILE* file) { + BOOL rc = FALSE; if (!file) return FALSE; @@ -368,33 +378,32 @@ BOOL drive_file_free(DRIVE_FILE* file) if (file->delete_pending) { if (file->is_dir) - drive_file_remove_dir(file->fullpath); - else if (!DeleteFileW(file->fullpath)) { - free(file->fullpath); - free(file); - return FALSE; + if (!drive_file_remove_dir(file->fullpath)) + goto fail; } + else if (!DeleteFileW(file->fullpath)) + goto fail; } + rc = TRUE; + +fail: DEBUG_WSTR("Free %s", file->fullpath); free(file->fullpath); free(file); - return TRUE; + return rc; } BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset) { - LONG lDistHigh; - DWORD dwPtrLow; + LARGE_INTEGER loffset; if (!file) return FALSE; - lDistHigh = Offset >> 32; - DEBUG_WSTR("Seek %s", file->fullpath); - dwPtrLow = SetFilePointer(file->file_handle, Offset & 0xFFFFFFFF, &lDistHigh, FILE_BEGIN); - return dwPtrLow != INVALID_SET_FILE_POINTER; + loffset.QuadPart = Offset; + return SetFilePointerEx(file->file_handle, loffset, NULL, FILE_BEGIN); } BOOL drive_file_read(DRIVE_FILE* file, BYTE* buffer, UINT32* Length) @@ -552,6 +561,9 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN switch (FsInformationClass) { case FileBasicInformation: + if (Stream_GetRemainingLength(input) < 36) + return FALSE; + /* http://msdn.microsoft.com/en-us/library/cc232094.aspx */ Stream_Read_UINT64(input, liCreationTime.QuadPart); Stream_Read_UINT64(input, liLastAccessTime.QuadPart); @@ -611,6 +623,9 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN /* http://msdn.microsoft.com/en-us/library/cc232067.aspx */ case FileAllocationInformation: + if (Stream_GetRemainingLength(input) < 8) + return FALSE; + /* http://msdn.microsoft.com/en-us/library/cc232076.aspx */ Stream_Read_INT64(input, size); @@ -623,8 +638,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN liSize.QuadPart = size & 0xFFFFFFFF; - if (SetFilePointer(file->file_handle, liSize.LowPart, &liSize.HighPart, - FILE_BEGIN) == INVALID_SET_FILE_POINTER) + if (!SetFilePointerEx(file->file_handle, liSize, NULL, FILE_BEGIN)) { WLog_ERR(TAG, "Unable to truncate %s to %d (%"PRId32")", file->fullpath, size, GetLastError()); return FALSE; @@ -648,7 +662,12 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN break; /* TODO: SetLastError ??? */ if (Length) + { + if (Stream_GetRemainingLength(input) < 1) + return FALSE; + Stream_Read_UINT8(input, delete_pending); + } else delete_pending = 1; @@ -668,13 +687,19 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN break; case FileRenameInformation: + if (Stream_GetRemainingLength(input) < 6) + return FALSE; + /* http://msdn.microsoft.com/en-us/library/cc232085.aspx */ Stream_Read_UINT8(input, ReplaceIfExists); Stream_Seek_UINT8(input); /* RootDirectory */ Stream_Read_UINT32(input, FileNameLength); + + if (Stream_GetRemainingLength(input) < FileNameLength) + return FALSE; + fullpath = drive_file_combine_fullpath(file->basepath, (WCHAR*)Stream_Pointer(input), FileNameLength); - if (!fullpath) { WLog_ERR(TAG, "drive_file_combine_fullpath failed!"); @@ -695,7 +720,8 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN if (MoveFileExW(file->fullpath, fullpath, MOVEFILE_COPY_ALLOWED | (ReplaceIfExists ? MOVEFILE_REPLACE_EXISTING : 0))) { - drive_file_set_fullpath(file, fullpath); + if (!drive_file_set_fullpath(file, fullpath)) + return FALSE; } else { diff --git a/channels/drive/client/drive_file.h b/channels/drive/client/drive_file.h index 9b2eed4..b928187 100644 --- a/channels/drive/client/drive_file.h +++ b/channels/drive/client/drive_file.h @@ -66,6 +66,4 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery, const WCHAR* path, UINT32 PathLength, wStream* output); -extern UINT sys_code_page; - -#endif /* FREERDP_CHANNEL_DRIVE_CLIENT_FILE_H */ +#endif /* FREERDP_CHANNEL_DRIVE_FILE_H */ diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c index 1e6eca7..c78a8ec 100644 --- a/channels/drive/client/drive_main.c +++ b/channels/drive/client/drive_main.c @@ -64,6 +64,8 @@ struct _DRIVE_DEVICE rdpContext* rdpcontext; }; +static UINT sys_code_page = 0; + static DWORD drive_map_windows_err(DWORD fs_errno) { DWORD rc; @@ -89,6 +91,14 @@ static DWORD drive_map_windows_err(DWORD fs_errno) rc = STATUS_DEVICE_BUSY; break; + case ERROR_INVALID_DRIVE: + rc = STATUS_NO_SUCH_DEVICE; + break; + + case ERROR_NOT_READY: + rc = STATUS_NO_SUCH_DEVICE; + break; + case ERROR_FILE_EXISTS: case ERROR_ALREADY_EXISTS: rc = STATUS_OBJECT_NAME_COLLISION; @@ -116,7 +126,7 @@ static DWORD drive_map_windows_err(DWORD fs_errno) default: rc = STATUS_UNSUCCESSFUL; - WLog_ERR(TAG, "Error code not found: %"PRId32"", fs_errno); + WLog_ERR(TAG, "Error code not found: %"PRIu32"", fs_errno); break; } @@ -127,6 +137,10 @@ static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32 id) { DRIVE_FILE* file = NULL; void* key = (void*)(size_t) id; + + if (!drive) + return NULL; + file = (DRIVE_FILE*) ListDictionary_GetItemValue(drive->files, key); return file; } @@ -138,7 +152,6 @@ static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32 id) */ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp) { - void* key; UINT32 FileId; DRIVE_FILE* file; BYTE Information; @@ -148,14 +161,25 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp) UINT32 CreateDisposition; UINT32 CreateOptions; UINT32 PathLength; + UINT64 allocationSize; const WCHAR* path; + + if (!drive || !irp || !irp->devman || !irp->Complete) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(irp->input) < 6*4+8) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, DesiredAccess); - Stream_Seek(irp->input, 8); /* AllocationSize(8) */ + Stream_Read_UINT64(irp->input, allocationSize); Stream_Read_UINT32(irp->input, FileAttributes); Stream_Read_UINT32(irp->input, SharedAccess); Stream_Read_UINT32(irp->input, CreateDisposition); Stream_Read_UINT32(irp->input, CreateOptions); Stream_Read_UINT32(irp->input, PathLength); + if (Stream_GetRemainingLength(irp->input) < PathLength) + return ERROR_INVALID_DATA; + path = (WCHAR*) Stream_Pointer(irp->input); FileId = irp->devman->id_sequence++; file = drive_file_new(drive->path, path, PathLength, FileId, DesiredAccess, CreateDisposition, @@ -169,7 +193,7 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp) } else { - key = (void*)(size_t) file->id; + void* key = (void*)(size_t) file->id; if (!ListDictionary_Add(drive->files, key, file)) { @@ -214,13 +238,14 @@ static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp) { void* key; DRIVE_FILE* file; + if (!drive || !irp || !irp->Complete || !irp->output) + return ERROR_INVALID_PARAMETER; + file = drive_get_file_by_id(drive, irp->FileId); key = (void*)(size_t) irp->FileId; if (!file) - { irp->IoStatus = STATUS_UNSUCCESSFUL; - } else { ListDictionary_Remove(drive->files, key); @@ -245,11 +270,17 @@ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp) DRIVE_FILE* file; UINT32 Length; UINT64 Offset; - BYTE* buffer = NULL; + + if (!drive || !irp || !irp->output || !irp->Complete) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(irp->input) < 12) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); - file = drive_get_file_by_id(drive, irp->FileId); + file = drive_get_file_by_id(drive, irp->FileId); if (!file) { irp->IoStatus = STATUS_UNSUCCESSFUL; @@ -260,39 +291,29 @@ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp) irp->IoStatus = drive_map_windows_err(GetLastError()); Length = 0; } + + if (!Stream_EnsureRemainingCapacity(irp->output, Length + 4)) + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + return ERROR_INTERNAL_ERROR; + } + else if (Length == 0) + Stream_Write_UINT32(irp->output, 0); else { - buffer = (BYTE*) malloc(Length); - - if (!buffer) - { - WLog_ERR(TAG, "malloc failed!"); - return CHANNEL_RC_OK; - } - + BYTE* buffer = Stream_Pointer(irp->output) + sizeof(UINT32); if (!drive_file_read(file, buffer, &Length)) { irp->IoStatus = drive_map_windows_err(GetLastError()); - free(buffer); - buffer = NULL; - Length = 0; + Stream_Write_UINT32(irp->output, 0); } - } - - Stream_Write_UINT32(irp->output, Length); - - if (Length > 0) - { - if (!Stream_EnsureRemainingCapacity(irp->output, (int) Length)) + else { - WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); - return ERROR_INTERNAL_ERROR; + Stream_Write_UINT32(irp->output, Length); + Stream_Seek(irp->output, Length); } - - Stream_Write(irp->output, buffer, Length); } - free(buffer); return irp->Complete(irp); } @@ -306,11 +327,18 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp) DRIVE_FILE* file; UINT32 Length; UINT64 Offset; + + if (!drive || !irp || !irp->input || !irp->output || !irp->Complete) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(irp->input) < 32) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); Stream_Seek(irp->input, 20); /* Padding */ - file = drive_get_file_by_id(drive, irp->FileId); + file = drive_get_file_by_id(drive, irp->FileId); if (!file) { irp->IoStatus = STATUS_UNSUCCESSFUL; @@ -341,9 +369,16 @@ static UINT drive_process_irp_query_information(DRIVE_DEVICE* drive, IRP* irp) { DRIVE_FILE* file; UINT32 FsInformationClass; - Stream_Read_UINT32(irp->input, FsInformationClass); - file = drive_get_file_by_id(drive, irp->FileId); + if (!drive || !irp || !irp->Complete) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(irp->input) < 4) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(irp->input, FsInformationClass); + + file = drive_get_file_by_id(drive, irp->FileId); if (!file) { irp->IoStatus = STATUS_UNSUCCESSFUL; @@ -366,11 +401,18 @@ static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp) DRIVE_FILE* file; UINT32 FsInformationClass; UINT32 Length; + + if (!drive || !irp || !irp->Complete || !irp->input || !irp->output) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(irp->input) < 32) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, FsInformationClass); Stream_Read_UINT32(irp->input, Length); Stream_Seek(irp->input, 24); /* Padding */ - file = drive_get_file_by_id(drive, irp->FileId); + file = drive_get_file_by_id(drive, irp->FileId); if (!file) { irp->IoStatus = STATUS_UNSUCCESSFUL; @@ -398,7 +440,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp) { UINT32 FsInformationClass; - wStream* output = irp->output; + wStream* output = NULL; char* volumeLabel = {"FREERDP"}; char* diskType = {"FAT32"}; WCHAR* outStr = NULL; @@ -408,6 +450,15 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, DWORD lpNumberOfFreeClusters; DWORD lpTotalNumberOfClusters; WIN32_FILE_ATTRIBUTE_DATA wfad; + + if (!drive || !irp) + return ERROR_INVALID_PARAMETER; + + output = irp->output; + + if (Stream_GetRemainingLength(irp->input) < 4) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, FsInformationClass); GetDiskFreeSpaceW(drive->path, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters, &lpTotalNumberOfClusters); @@ -536,9 +587,16 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, static UINT drive_process_irp_silent_ignore(DRIVE_DEVICE* drive, IRP* irp) { UINT32 FsInformationClass; - wStream* output = irp->output; + + if (!drive || !irp || !irp->output || !irp->Complete) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(irp->input) < 4) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, FsInformationClass); - Stream_Write_UINT32(output, 0); /* Length */ + + Stream_Write_UINT32(irp->output, 0); /* Length */ return irp->Complete(irp); } @@ -554,13 +612,20 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp) BYTE InitialQuery; UINT32 PathLength; UINT32 FsInformationClass; + + if (!drive || !irp || !irp->Complete) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(irp->input) < 32) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, FsInformationClass); Stream_Read_UINT8(irp->input, InitialQuery); Stream_Read_UINT32(irp->input, PathLength); Stream_Seek(irp->input, 23); /* Padding */ path = (WCHAR*) Stream_Pointer(irp->input); - file = drive_get_file_by_id(drive, irp->FileId); + file = drive_get_file_by_id(drive, irp->FileId); if (file == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; @@ -582,21 +647,21 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp) */ static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp) { + if (!drive || !irp) + return ERROR_INVALID_PARAMETER; + switch (irp->MinorFunction) { case IRP_MN_QUERY_DIRECTORY: return drive_process_irp_query_directory(drive, irp); - break; case IRP_MN_NOTIFY_CHANGE_DIRECTORY: /* TODO */ return irp->Discard(irp); - break; default: irp->IoStatus = STATUS_NOT_SUPPORTED; Stream_Write_UINT32(irp->output, 0); /* Length */ return irp->Complete(irp); - break; } return CHANNEL_RC_OK; @@ -609,6 +674,9 @@ static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp) */ static UINT drive_process_irp_device_control(DRIVE_DEVICE* drive, IRP* irp) { + if (!drive || !irp) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */ return irp->Complete(irp); } @@ -621,6 +689,9 @@ static UINT drive_process_irp_device_control(DRIVE_DEVICE* drive, IRP* irp) static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp) { UINT error; + if (!drive || !irp) + return ERROR_INVALID_PARAMETER; + irp->IoStatus = STATUS_SUCCESS; switch (irp->MajorFunction) @@ -674,13 +745,19 @@ static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp) return error; } -static void* drive_thread_func(void* arg) +static DWORD WINAPI drive_thread_func(LPVOID arg) { IRP* irp; wMessage message; DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg; UINT error = CHANNEL_RC_OK; + if(!drive) + { + error = ERROR_INVALID_PARAMETER; + goto fail; + } + while (1) { if (!MessageQueue_Wait(drive->IrpQueue)) @@ -703,18 +780,21 @@ static void* drive_thread_func(void* arg) irp = (IRP*) message.wParam; if (irp) + { if ((error = drive_process_irp(drive, irp))) { WLog_ERR(TAG, "drive_process_irp failed with error %"PRIu32"!", error); break; } + } } - if (error && drive->rdpcontext) +fail: + if (error && drive && drive->rdpcontext) setChannelError(drive->rdpcontext, error, "drive_thread_func reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -726,6 +806,9 @@ static UINT drive_irp_request(DEVICE* device, IRP* irp) { DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device; + if (!drive) + return ERROR_INVALID_PARAMETER; + if (!MessageQueue_Post(drive->IrpQueue, NULL, 0, (void*) irp, NULL)) { WLog_ERR(TAG, "MessageQueue_Post failed!"); @@ -735,10 +818,11 @@ static UINT drive_irp_request(DEVICE* device, IRP* irp) return CHANNEL_RC_OK; } -static void drive_free_resources(DRIVE_DEVICE* drive) +static UINT drive_free_int(DRIVE_DEVICE* drive) { + UINT error = CHANNEL_RC_OK; if (!drive) - return; + return ERROR_INVALID_PARAMETER; CloseHandle(drive->thread); ListDictionary_Free(drive->files); @@ -746,6 +830,7 @@ static void drive_free_resources(DRIVE_DEVICE* drive) Stream_Free(drive->device.data, TRUE); free(drive->path); free(drive); + return error; } /** @@ -758,6 +843,9 @@ static UINT drive_free(DEVICE* device) DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device; UINT error = CHANNEL_RC_OK; + if (!drive) + return ERROR_INVALID_PARAMETER; + if (MessageQueue_PostQuit(drive->IrpQueue, 0) && (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED)) { @@ -766,8 +854,7 @@ static UINT drive_free(DEVICE* device) return error; } - drive_free_resources(drive); - return error; + return drive_free_int(drive); } /** @@ -775,10 +862,10 @@ static UINT drive_free(DEVICE* device) * * @return 0 on success, otherwise a Win32 error code */ -UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, +static UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char* name, char* path) { - int i, length; + size_t i, length; DRIVE_DEVICE* drive; UINT error; #ifdef WIN32 @@ -813,7 +900,7 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, drive->device.IRPRequest = drive_irp_request; drive->device.Free = drive_free; drive->rdpcontext = pEntryPoints->rdpcontext; - length = (int) strlen(name); + length = strlen(name); drive->device.data = Stream_New(NULL, length + 1); if (!drive->device.data) @@ -862,7 +949,7 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, goto out_error; } - if (!(drive->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_thread_func, drive, + if (!(drive->thread = CreateThread(NULL, 0, drive_thread_func, drive, CREATE_SUSPENDED, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); @@ -874,7 +961,7 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, return CHANNEL_RC_OK; out_error: - drive_free_resources(drive); + drive_free_int(drive); return error; } @@ -884,8 +971,6 @@ out_error: #define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif -UINT sys_code_page = 0; - /** * Function description * @@ -920,30 +1005,13 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) } else if (strcmp(drive->Path, "%") == 0) { - char* home_env = NULL; - /* home directory */ - home_env = getenv("HOME"); free(drive->Path); + drive->Path = GetKnownPath(KNOWN_PATH_HOME); - if (home_env) + if (!drive->Path) { - drive->Path = _strdup(home_env); - - if (!drive->Path) - { - WLog_ERR(TAG, "_strdup failed!"); - return CHANNEL_RC_NO_MEMORY; - } - } - else - { - drive->Path = _strdup("/"); - - if (!drive->Path) - { - WLog_ERR(TAG, "_strdup failed!"); - return CHANNEL_RC_NO_MEMORY; - } + WLog_ERR(TAG, "_strdup failed!"); + return CHANNEL_RC_NO_MEMORY; } } diff --git a/channels/echo/server/echo_main.c b/channels/echo/server/echo_main.c index a58793f..b3f8eb0 100644 --- a/channels/echo/server/echo_main.c +++ b/channels/echo/server/echo_main.c @@ -105,7 +105,7 @@ static UINT echo_server_open_channel(echo_server* echo) return echo->echo_channel ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } -static void* echo_server_thread_func(void* arg) +static DWORD WINAPI echo_server_thread_func(LPVOID arg) { wStream* s; void* buffer; @@ -206,8 +206,8 @@ static void* echo_server_thread_func(void* arg) { WLog_ERR(TAG, "Stream_New failed!"); WTSVirtualChannelClose(echo->echo_channel); - ExitThread((DWORD)ERROR_NOT_ENOUGH_MEMORY); - return NULL; + ExitThread(ERROR_NOT_ENOUGH_MEMORY); + return ERROR_NOT_ENOUGH_MEMORY; } while (ready) @@ -264,8 +264,8 @@ out: setChannelError(echo->context.rdpcontext, error, "echo_server_thread_func reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -285,8 +285,7 @@ static UINT echo_server_open(echo_server_context* context) return ERROR_INTERNAL_ERROR; } - if (!(echo->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) echo_server_thread_func, (void*) echo, 0, NULL))) + if (!(echo->thread = CreateThread(NULL, 0, echo_server_thread_func, (void*) echo, 0, NULL))) { WLog_ERR(TAG, "CreateEvent failed!"); CloseHandle(echo->stopEvent); diff --git a/channels/encomsp/client/encomsp_main.c b/channels/encomsp/client/encomsp_main.c index bd5bd2c..35c5756 100644 --- a/channels/encomsp/client/encomsp_main.c +++ b/channels/encomsp/client/encomsp_main.c @@ -1011,7 +1011,7 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event_ex(LPVOID lpUserParam, return; } -static void* encomsp_virtual_channel_client_thread(void* arg) +static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; @@ -1054,8 +1054,8 @@ static void* encomsp_virtual_channel_client_thread(void* arg) setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_client_thread reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -1087,7 +1087,7 @@ static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp, } if (!(encomsp->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) encomsp_virtual_channel_client_thread, (void*) encomsp, + encomsp_virtual_channel_client_thread, (void*) encomsp, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); @@ -1148,6 +1148,7 @@ static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp) static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp) { encomsp->InitHandle = 0; + free(encomsp->context); free(encomsp); return CHANNEL_RC_OK; } diff --git a/channels/encomsp/server/encomsp_main.c b/channels/encomsp/server/encomsp_main.c index d32a820..e1b2248 100644 --- a/channels/encomsp/server/encomsp_main.c +++ b/channels/encomsp/server/encomsp_main.c @@ -174,7 +174,7 @@ static UINT encomsp_server_receive_pdu(EncomspServerContext* context, return error; } -static void* encomsp_server_thread(void* arg) +static DWORD WINAPI encomsp_server_thread(LPVOID arg) { wStream* s; DWORD nCount; @@ -285,8 +285,8 @@ out: setChannelError(context->rdpcontext, error, "encomsp_server_thread reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -309,7 +309,7 @@ static UINT encomsp_server_start(EncomspServerContext* context) } if (!(context->priv->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) encomsp_server_thread, (void*) context, 0, NULL))) + encomsp_server_thread, (void*) context, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(context->priv->StopEvent); diff --git a/channels/geometry/CMakeLists.txt b/channels/geometry/CMakeLists.txt new file mode 100644 index 0000000..7ddea6d --- /dev/null +++ b/channels/geometry/CMakeLists.txt @@ -0,0 +1,22 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2017 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. + +define_channel("geometry") + +if(WITH_CLIENT_CHANNELS) + add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME}) +endif() diff --git a/channels/geometry/ChannelOptions.cmake b/channels/geometry/ChannelOptions.cmake new file mode 100644 index 0000000..8e8163b --- /dev/null +++ b/channels/geometry/ChannelOptions.cmake @@ -0,0 +1,11 @@ + +set(OPTION_DEFAULT OFF) +set(OPTION_CLIENT_DEFAULT ON) +set(OPTION_SERVER_DEFAULT OFF) + +define_channel_options(NAME "geometry" TYPE "dynamic" + DESCRIPTION "Geometry tracking Virtual Channel Extension" + SPECIFICATIONS "[MS-RDPEGT]" + DEFAULT ${OPTION_DEFAULT}) + +define_channel_client_options(${OPTION_CLIENT_DEFAULT}) diff --git a/channels/geometry/client/CMakeLists.txt b/channels/geometry/client/CMakeLists.txt new file mode 100644 index 0000000..ea28bff --- /dev/null +++ b/channels/geometry/client/CMakeLists.txt @@ -0,0 +1,39 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2017 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. + +define_channel_client("geometry") + +set(${MODULE_PREFIX}_SRCS + geometry_main.c + geometry_main.h) + +include_directories(..) + +add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry") + + + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + + +if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_LIBS) + install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client") diff --git a/channels/geometry/client/geometry_main.c b/channels/geometry/client/geometry_main.c new file mode 100644 index 0000000..5ef7def --- /dev/null +++ b/channels/geometry/client/geometry_main.c @@ -0,0 +1,481 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Geometry tracking Virtual Channel Extension + * + * Copyright 2017 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TAG CHANNELS_TAG("geometry.client") + +#include "geometry_main.h" + +struct _GEOMETRY_CHANNEL_CALLBACK +{ + IWTSVirtualChannelCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + IWTSVirtualChannel* channel; +}; +typedef struct _GEOMETRY_CHANNEL_CALLBACK GEOMETRY_CHANNEL_CALLBACK; + +struct _GEOMETRY_LISTENER_CALLBACK +{ + IWTSListenerCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + GEOMETRY_CHANNEL_CALLBACK* channel_callback; +}; +typedef struct _GEOMETRY_LISTENER_CALLBACK GEOMETRY_LISTENER_CALLBACK; + +struct _GEOMETRY_PLUGIN +{ + IWTSPlugin iface; + + IWTSListener* listener; + GEOMETRY_LISTENER_CALLBACK* listener_callback; + + GeometryClientContext* context; +}; +typedef struct _GEOMETRY_PLUGIN GEOMETRY_PLUGIN; + + +static UINT32 mappedGeometryHash(UINT64 *g) +{ + return (UINT32)((*g >> 32) + (*g & 0xffffffff)); +} + +static BOOL mappedGeometryKeyCompare(UINT64 *g1, UINT64 *g2) +{ + return *g1 == *g2; +} + +void mappedGeometryRef(MAPPED_GEOMETRY *g) +{ + InterlockedIncrement(&g->refCounter); +} + +void mappedGeometryUnref(MAPPED_GEOMETRY *g) +{ + if (InterlockedDecrement(&g->refCounter)) + return; + + g->MappedGeometryUpdate = NULL; + g->MappedGeometryClear = NULL; + g->custom = NULL; + free(g->geometry.rects); + free(g); +} + + +void freerdp_rgndata_reset(FREERDP_RGNDATA *data) +{ + data->nRectCount = 0; +} + +static UINT32 geometry_read_RGNDATA(wStream *s, UINT32 len, FREERDP_RGNDATA *rgndata) +{ + UINT32 dwSize, iType; + INT32 right, bottom; + + if (len < 32) + { + WLog_ERR(TAG, "invalid RGNDATA"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, dwSize); + + if (dwSize != 32) + { + WLog_ERR(TAG, "invalid RGNDATA dwSize"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, iType); + + if (iType != RDH_RECTANGLE) + { + WLog_ERR(TAG, "iType %"PRIu32" for RGNDATA is not supported", iType); + return ERROR_UNSUPPORTED_TYPE; + } + + Stream_Read_UINT32(s, rgndata->nRectCount); + Stream_Seek_UINT32(s); /* nRgnSize IGNORED */ + Stream_Read_INT32(s, rgndata->boundingRect.x); + Stream_Read_INT32(s, rgndata->boundingRect.y); + Stream_Read_INT32(s, right); + Stream_Read_INT32(s, bottom); + rgndata->boundingRect.width = right - rgndata->boundingRect.x; + rgndata->boundingRect.height = bottom - rgndata->boundingRect.y; + len -= 32; + + if (len / (4 * 4) < rgndata->nRectCount) + { + WLog_ERR(TAG, "not enough data for region rectangles"); + } + + if (rgndata->nRectCount) + { + int i; + RDP_RECT *tmp = realloc(rgndata->rects, rgndata->nRectCount * sizeof(RDP_RECT)); + + if (!tmp) + { + WLog_ERR(TAG, "unable to allocate memory for %"PRIu32" RECTs", rgndata->nRectCount); + return CHANNEL_RC_NO_MEMORY; + } + rgndata->rects = tmp; + + for (i = 0; i < rgndata->nRectCount; i++) + { + Stream_Read_INT32(s, rgndata->rects[i].x); + Stream_Read_INT32(s, rgndata->rects[i].y); + Stream_Read_INT32(s, right); + Stream_Read_INT32(s, bottom); + rgndata->rects[i].width = right - rgndata->rects[i].x; + rgndata->rects[i].height = bottom - rgndata->rects[i].y; + } + } + + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT32 length, cbGeometryBuffer; + MAPPED_GEOMETRY *mappedGeometry; + GEOMETRY_PLUGIN* geometry; + GeometryClientContext *context; + UINT ret = CHANNEL_RC_OK; + UINT32 version, updateType, geometryType; + UINT64 id; + + geometry = (GEOMETRY_PLUGIN*) callback->plugin; + context = (GeometryClientContext*)geometry->iface.pInterface; + + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "not enough remaining data"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, length); /* Length (4 bytes) */ + + if (length < 73 || Stream_GetRemainingLength(s) < (length - 4)) + { + WLog_ERR(TAG, "invalid packet length"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, version); + Stream_Read_UINT64(s, id); + Stream_Read_UINT32(s, updateType); + Stream_Seek_UINT32(s); /* flags */ + + mappedGeometry = HashTable_GetItemValue(context->geometries, &id); + + if (updateType == GEOMETRY_CLEAR ) + { + if (!mappedGeometry) + { + WLog_ERR(TAG, "geometry 0x%"PRIx64" not found here, ignoring clear command", id); + return CHANNEL_RC_OK; + } + + WLog_DBG(TAG, "clearing geometry 0x%"PRIx64"", id); + + if (mappedGeometry->MappedGeometryClear && !mappedGeometry->MappedGeometryClear(mappedGeometry)) + return ERROR_INTERNAL_ERROR; + + if (!HashTable_Remove(context->geometries, &id)) + WLog_ERR(TAG, "geometry not removed from geometries"); + } + else if (updateType == GEOMETRY_UPDATE) + { + BOOL newOne = FALSE; + + if (!mappedGeometry) + { + newOne = TRUE; + WLog_DBG(TAG, "creating geometry 0x%"PRIx64"", id); + mappedGeometry = calloc(1, sizeof(MAPPED_GEOMETRY)); + if (!mappedGeometry) + return CHANNEL_RC_NO_MEMORY; + + mappedGeometry->refCounter = 1; + mappedGeometry->mappingId = id; + + if (HashTable_Add(context->geometries, &(mappedGeometry->mappingId), mappedGeometry) < 0) + { + WLog_ERR(TAG, "unable to register geometry 0x%"PRIx64" in the table", id); + free(mappedGeometry); + return CHANNEL_RC_NO_MEMORY; + } + } + else + { + WLog_DBG(TAG, "updating geometry 0x%"PRIx64"", id); + } + + Stream_Read_UINT64(s, mappedGeometry->topLevelId); + + Stream_Read_INT32(s, mappedGeometry->left); + Stream_Read_INT32(s, mappedGeometry->top); + Stream_Read_INT32(s, mappedGeometry->right); + Stream_Read_INT32(s, mappedGeometry->bottom); + + Stream_Read_INT32(s, mappedGeometry->topLevelLeft); + Stream_Read_INT32(s, mappedGeometry->topLevelTop); + Stream_Read_INT32(s, mappedGeometry->topLevelRight); + Stream_Read_INT32(s, mappedGeometry->topLevelBottom); + + Stream_Read_UINT32(s, geometryType); + + Stream_Read_UINT32(s, cbGeometryBuffer); + if (Stream_GetRemainingLength(s) < cbGeometryBuffer) + { + WLog_ERR(TAG, "invalid packet length"); + return ERROR_INVALID_DATA; + } + + if (cbGeometryBuffer) + { + ret = geometry_read_RGNDATA(s, cbGeometryBuffer, &mappedGeometry->geometry); + if (ret != CHANNEL_RC_OK) + return ret; + } + else + { + freerdp_rgndata_reset(&mappedGeometry->geometry); + } + + if (newOne) + { + if (context->MappedGeometryAdded && !context->MappedGeometryAdded(context, mappedGeometry)) + { + WLog_ERR(TAG, "geometry added callback failed"); + ret = ERROR_INTERNAL_ERROR; + } + } + else + { + if (mappedGeometry->MappedGeometryUpdate && !mappedGeometry->MappedGeometryUpdate(mappedGeometry)) + { + WLog_ERR(TAG, "geometry update callback failed"); + ret = ERROR_INTERNAL_ERROR; + } + } + } + else + { + WLog_ERR(TAG, "unknown updateType=%"PRIu32"", updateType); + ret = CHANNEL_RC_OK; + } + + + return ret; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT geometry_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) +{ + GEOMETRY_CHANNEL_CALLBACK* callback = (GEOMETRY_CHANNEL_CALLBACK*) pChannelCallback; + return geometry_recv_pdu(callback, data); +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT geometry_on_close(IWTSVirtualChannelCallback* pChannelCallback) +{ + free(pChannelCallback); + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT geometry_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, + IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, + IWTSVirtualChannelCallback** ppCallback) +{ + GEOMETRY_CHANNEL_CALLBACK* callback; + GEOMETRY_LISTENER_CALLBACK* listener_callback = (GEOMETRY_LISTENER_CALLBACK*) pListenerCallback; + callback = (GEOMETRY_CHANNEL_CALLBACK*) calloc(1, sizeof(GEOMETRY_CHANNEL_CALLBACK)); + + if (!callback) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + callback->iface.OnDataReceived = geometry_on_data_received; + callback->iface.OnClose = geometry_on_close; + callback->plugin = listener_callback->plugin; + callback->channel_mgr = listener_callback->channel_mgr; + callback->channel = pChannel; + listener_callback->channel_callback = callback; + *ppCallback = (IWTSVirtualChannelCallback*) callback; + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT geometry_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) +{ + UINT status; + GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*) pPlugin; + geometry->listener_callback = (GEOMETRY_LISTENER_CALLBACK*) calloc(1, + sizeof(GEOMETRY_LISTENER_CALLBACK)); + + if (!geometry->listener_callback) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + geometry->listener_callback->iface.OnNewChannelConnection = geometry_on_new_channel_connection; + geometry->listener_callback->plugin = pPlugin; + geometry->listener_callback->channel_mgr = pChannelMgr; + status = pChannelMgr->CreateListener(pChannelMgr, GEOMETRY_DVC_CHANNEL_NAME, 0, + (IWTSListenerCallback*) geometry->listener_callback, &(geometry->listener)); + geometry->listener->pInterface = geometry->iface.pInterface; + return status; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT geometry_plugin_terminated(IWTSPlugin* pPlugin) +{ + GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*) pPlugin; + GeometryClientContext* context = (GeometryClientContext *)geometry->iface.pInterface; + + if (context) + HashTable_Free(context->geometries); + + free(geometry->listener_callback); + free(geometry->iface.pInterface); + free(pPlugin); + return CHANNEL_RC_OK; +} + +/** + * Channel Client Interface + */ + +#ifdef BUILTIN_CHANNELS +#define DVCPluginEntry geometry_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry +#endif + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) +{ + UINT error = CHANNEL_RC_OK; + GEOMETRY_PLUGIN* geometry; + GeometryClientContext* context; + geometry = (GEOMETRY_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "geometry"); + + if (!geometry) + { + geometry = (GEOMETRY_PLUGIN*) calloc(1, sizeof(GEOMETRY_PLUGIN)); + + if (!geometry) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + geometry->iface.Initialize = geometry_plugin_initialize; + geometry->iface.Connected = NULL; + geometry->iface.Disconnected = NULL; + geometry->iface.Terminated = geometry_plugin_terminated; + context = (GeometryClientContext*) calloc(1, sizeof(GeometryClientContext)); + + if (!context) + { + WLog_ERR(TAG, "calloc failed!"); + goto error_context; + } + + context->geometries = HashTable_New(FALSE); + context->geometries->hash = (HASH_TABLE_HASH_FN)mappedGeometryHash; + context->geometries->keyCompare = (HASH_TABLE_KEY_COMPARE_FN)mappedGeometryKeyCompare; + context->geometries->valueFree = (HASH_TABLE_VALUE_FREE_FN)mappedGeometryUnref; + + context->handle = (void*) geometry; + geometry->iface.pInterface = (void*) context; + geometry->context = context; + error = pEntryPoints->RegisterPlugin(pEntryPoints, "geometry", (IWTSPlugin*) geometry); + } + else + { + WLog_ERR(TAG, "could not get geometry Plugin."); + return CHANNEL_RC_BAD_CHANNEL; + } + + return error; + +error_context: + free(geometry); + return CHANNEL_RC_NO_MEMORY; + +} diff --git a/channels/geometry/client/geometry_main.h b/channels/geometry/client/geometry_main.h new file mode 100644 index 0000000..1fb5321 --- /dev/null +++ b/channels/geometry/client/geometry_main.h @@ -0,0 +1,34 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Geometry tracking virtual channel extension + * + * Copyright 2017 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_CHANNEL_GEOMETRY_CLIENT_MAIN_H +#define FREERDP_CHANNEL_GEOMETRY_CLIENT_MAIN_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + + +#endif /* FREERDP_CHANNEL_GEOMETRY_CLIENT_MAIN_H */ + diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index b8c8180..19ebce3 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -304,7 +304,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) return CHANNEL_RC_OK; } -static void* parallel_thread_func(void* arg) +static DWORD WINAPI parallel_thread_func(LPVOID arg) { IRP* irp; wMessage message; @@ -343,8 +343,8 @@ static void* parallel_thread_func(void* arg) setChannelError(parallel->rdpcontext, error, "parallel_thread_func reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -375,8 +375,8 @@ static UINT parallel_free(DEVICE* device) UINT error; PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; - if (MessageQueue_PostQuit(parallel->queue, 0) - && (WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED)) + if (!MessageQueue_PostQuit(parallel->queue, 0) + || (WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED)) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); @@ -405,7 +405,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) { char* name; char* path; - int i; + size_t i; size_t length; RDPDR_PARALLEL* device; PARALLEL_DEVICE* parallel; @@ -414,10 +414,10 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) name = device->Name; path = device->Path; - if (!name || (name[0] == '*')) + if (!name || (name[0] == '*') || !path) { /* TODO: implement auto detection of parallel ports */ - return CHANNEL_RC_OK; + return CHANNEL_RC_INITIALIZATION_ERROR; } if (name[0] && path[0]) @@ -466,7 +466,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) } if (!(parallel->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) parallel_thread_func, (void*) parallel, 0, NULL))) + parallel_thread_func, (void*) parallel, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); error = ERROR_INTERNAL_ERROR; diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index 741b9ae..5074ff1 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -231,7 +231,7 @@ static UINT printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp) return CHANNEL_RC_OK; } -static void* printer_thread_func(void* arg) +static DWORD WINAPI printer_thread_func(LPVOID arg) { IRP* irp; PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) arg; @@ -275,8 +275,8 @@ static void* printer_thread_func(void* arg) setChannelError(printer_dev->rdpcontext, error, "printer_thread_func reported an error"); - ExitThread((DWORD) error); - return NULL; + ExitThread(error); + return error; } /** @@ -445,8 +445,7 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, goto error_out; } - if (!(printer_dev->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) printer_thread_func, (void*) printer_dev, 0, NULL))) + if (!(printer_dev->thread = CreateThread(NULL, 0, printer_thread_func, (void*) printer_dev, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); error = ERROR_INTERNAL_ERROR; diff --git a/channels/rail/client/rail_main.c b/channels/rail/client/rail_main.c index 6ecaf7a..e14cb52 100644 --- a/channels/rail/client/rail_main.c +++ b/channels/rail/client/rail_main.c @@ -38,6 +38,10 @@ RailClientContext* rail_get_client_interface(railPlugin* rail) { RailClientContext* pInterface; + + if (!rail) + return NULL; + pInterface = (RailClientContext*) rail->channelEntryPoints.pInterface; return pInterface; } @@ -52,14 +56,10 @@ static UINT rail_send(railPlugin* rail, wStream* s) UINT status; if (!rail) - { - status = CHANNEL_RC_BAD_INIT_HANDLE; - } - else - { - status = rail->channelEntryPoints.pVirtualChannelWriteEx(rail->InitHandle, rail->OpenHandle, - Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); - } + return CHANNEL_RC_BAD_INIT_HANDLE; + + status = rail->channelEntryPoints.pVirtualChannelWriteEx(rail->InitHandle, rail->OpenHandle, + Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); if (status != CHANNEL_RC_OK) { @@ -79,6 +79,10 @@ static UINT rail_send(railPlugin* rail, wStream* s) UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length) { wStream* s = NULL; + + if (!rail || !data) + return ERROR_INVALID_PARAMETER; + s = Stream_New(NULL, length); if (!s) @@ -97,17 +101,15 @@ UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length) */ static void rail_client_clean_exec_order(RAIL_EXEC_ORDER* exec) { - if (!exec) - return; + if (!exec) + return; - free(exec->exeOrFile.string); - exec->exeOrFile.string = NULL; - - free(exec->workingDir.string); - exec->workingDir.string = NULL; - - free(exec->arguments.string); - exec->arguments.string = NULL; + free(exec->exeOrFile.string); + exec->exeOrFile.string = NULL; + free(exec->workingDir.string); + exec->workingDir.string = NULL; + free(exec->arguments.string); + exec->arguments.string = NULL; } /** @@ -124,13 +126,18 @@ static UINT rail_client_execute(RailClientContext* context, { char* exeOrFile; UINT error; - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !exec) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; exeOrFile = exec->RemoteApplicationProgram; if (!exeOrFile) return ERROR_INVALID_PARAMETER; - if (strlen(exeOrFile) >= 2) + if (strnlen(exeOrFile, MAX_PATH) >= 2) { if (strncmp(exeOrFile, "||", 2) != 0) exec->flags |= RAIL_EXEC_FLAG_FILE; @@ -155,7 +162,12 @@ static UINT rail_client_execute(RailClientContext* context, static UINT rail_client_activate(RailClientContext* context, RAIL_ACTIVATE_ORDER* activate) { - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !activate) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; return rail_send_client_activate_order(rail, activate); } @@ -168,10 +180,14 @@ static UINT rail_send_client_sysparam(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam) { wStream* s; - int length; - railPlugin* rail = (railPlugin*) context->handle; + size_t length = RAIL_SYSPARAM_ORDER_LENGTH; + railPlugin* rail; UINT error; - length = RAIL_SYSPARAM_ORDER_LENGTH; + + if (!context || !sysparam) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; switch (sysparam->param) { @@ -231,6 +247,9 @@ static UINT rail_client_system_param(RailClientContext* context, { UINT error = CHANNEL_RC_OK; + if (!context || !sysparam) + return ERROR_INVALID_PARAMETER; + if (sysparam->params & SPI_MASK_SET_HIGH_CONTRAST) { sysparam->param = SPI_SET_HIGH_CONTRAST; @@ -319,6 +338,9 @@ static UINT rail_client_system_param(RailClientContext* context, static UINT rail_server_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam) { + if (!context || !sysparam) + return ERROR_INVALID_PARAMETER; + return CHANNEL_RC_OK; /* stub - should be registered by client */ } @@ -330,7 +352,12 @@ static UINT rail_server_system_param(RailClientContext* context, static UINT rail_client_system_command(RailClientContext* context, RAIL_SYSCOMMAND_ORDER* syscommand) { - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !syscommand) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; return rail_send_client_syscommand_order(rail, syscommand); } @@ -342,7 +369,12 @@ static UINT rail_client_system_command(RailClientContext* context, static UINT rail_client_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* handshake) { - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !handshake) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; return rail_send_handshake_order(rail, handshake); } @@ -354,6 +386,9 @@ static UINT rail_client_handshake(RailClientContext* context, static UINT rail_server_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* handshake) { + if (!context || !handshake) + return ERROR_INVALID_PARAMETER; + return CHANNEL_RC_OK; /* stub - should be registered by client */ } @@ -365,7 +400,12 @@ static UINT rail_server_handshake(RailClientContext* context, static UINT rail_client_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDER* handshakeEx) { - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !handshakeEx) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; return rail_send_handshake_ex_order(rail, handshakeEx); } @@ -377,6 +417,9 @@ static UINT rail_client_handshake_ex(RailClientContext* context, static UINT rail_server_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDER* handshakeEx) { + if (!context || !handshakeEx) + return ERROR_INVALID_PARAMETER; + return CHANNEL_RC_OK; /* stub - should be registered by client */ } @@ -388,7 +431,12 @@ static UINT rail_server_handshake_ex(RailClientContext* context, static UINT rail_client_notify_event(RailClientContext* context, RAIL_NOTIFY_EVENT_ORDER* notifyEvent) { - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !notifyEvent) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; return rail_send_client_notify_event_order(rail, notifyEvent); } @@ -400,7 +448,12 @@ static UINT rail_client_notify_event(RailClientContext* context, static UINT rail_client_window_move(RailClientContext* context, RAIL_WINDOW_MOVE_ORDER* windowMove) { - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !windowMove) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; return rail_send_client_window_move_order(rail, windowMove); } @@ -412,6 +465,9 @@ static UINT rail_client_window_move(RailClientContext* context, static UINT rail_server_local_move_size(RailClientContext* context, RAIL_LOCALMOVESIZE_ORDER* localMoveSize) { + if (!context || !localMoveSize) + return ERROR_INVALID_PARAMETER; + return CHANNEL_RC_OK; /* stub - should be registered by client */ } @@ -423,6 +479,9 @@ static UINT rail_server_local_move_size(RailClientContext* context, static UINT rail_server_min_max_info(RailClientContext* context, RAIL_MINMAXINFO_ORDER* minMaxInfo) { + if (!context || !minMaxInfo) + return ERROR_INVALID_PARAMETER; + return CHANNEL_RC_OK; /* stub - should be registered by client */ } @@ -434,7 +493,12 @@ static UINT rail_server_min_max_info(RailClientContext* context, static UINT rail_client_information(RailClientContext* context, RAIL_CLIENT_STATUS_ORDER* clientStatus) { - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !clientStatus) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; return rail_send_client_status_order(rail, clientStatus); } @@ -446,7 +510,12 @@ static UINT rail_client_information(RailClientContext* context, static UINT rail_client_system_menu(RailClientContext* context, RAIL_SYSMENU_ORDER* sysmenu) { - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !sysmenu) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; return rail_send_client_sysmenu_order(rail, sysmenu); } @@ -458,7 +527,12 @@ static UINT rail_client_system_menu(RailClientContext* context, static UINT rail_client_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO_ORDER* langBarInfo) { - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !langBarInfo) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; return rail_send_client_langbar_info_order(rail, langBarInfo); } @@ -470,6 +544,9 @@ static UINT rail_client_language_bar_info(RailClientContext* context, static UINT rail_server_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO_ORDER* langBarInfo) { + if (!context || !langBarInfo) + return ERROR_INVALID_PARAMETER; + return CHANNEL_RC_OK; /* stub - should be registered by client */ } @@ -481,6 +558,9 @@ static UINT rail_server_language_bar_info(RailClientContext* context, static UINT rail_server_execute_result(RailClientContext* context, RAIL_EXEC_RESULT_ORDER* execResult) { + if (!context || !execResult) + return ERROR_INVALID_PARAMETER; + return CHANNEL_RC_OK; /* stub - should be registered by client */ } @@ -492,7 +572,12 @@ static UINT rail_server_execute_result(RailClientContext* context, static UINT rail_client_get_appid_request(RailClientContext* context, RAIL_GET_APPID_REQ_ORDER* getAppIdReq) { - railPlugin* rail = (railPlugin*) context->handle; + railPlugin* rail; + + if (!context || !getAppIdReq || !context->handle) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*) context->handle; return rail_send_client_get_appid_req_order(rail, getAppIdReq); } @@ -504,6 +589,9 @@ static UINT rail_client_get_appid_request(RailClientContext* context, static UINT rail_server_get_appid_response(RailClientContext* context, RAIL_GET_APPID_RESP_ORDER* getAppIdResp) { + if (!context || !getAppIdResp) + return ERROR_INVALID_PARAMETER; + return CHANNEL_RC_OK; /* stub - should be registered by client */ } @@ -606,7 +694,7 @@ static VOID VCAPITYPE rail_virtual_channel_open_event_ex(LPVOID lpUserParam, DWO return; } -static void* rail_virtual_channel_client_thread(void* arg) +static DWORD WINAPI rail_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; @@ -635,9 +723,9 @@ static void* rail_virtual_channel_client_thread(void* arg) if (message.id == 0) { data = (wStream*) message.wParam; - error = rail_order_recv(rail, data); Stream_Free(data, TRUE); + if (error) { WLog_ERR(TAG, "rail_order_recv failed with error %"PRIu32"!", error); @@ -650,8 +738,8 @@ static void* rail_virtual_channel_client_thread(void* arg) setChannelError(rail->rdpcontext, error, "rail_virtual_channel_client_thread reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -682,7 +770,7 @@ static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData, } if (!(rail->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) rail_virtual_channel_client_thread, (void*) rail, 0, + rail_virtual_channel_client_thread, (void*) rail, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); @@ -738,6 +826,7 @@ static UINT rail_virtual_channel_event_disconnected(railPlugin* rail) static void rail_virtual_channel_event_terminated(railPlugin* rail) { rail->InitHandle = 0; + free(rail->context); free(rail); } @@ -848,7 +937,6 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p isFreerdp = TRUE; } - WLog_Init(); rail->log = WLog_Get("com.freerdp.channels.rail.client"); WLog_Print(rail->log, WLOG_DEBUG, "VirtualChannelEntryEx"); CopyMemory(&(rail->channelEntryPoints), pEntryPoints, diff --git a/channels/rail/client/rail_orders.c b/channels/rail/client/rail_orders.c index 0cb6832..7e489e3 100644 --- a/channels/rail/client/rail_orders.c +++ b/channels/rail/client/rail_orders.c @@ -32,7 +32,6 @@ #include "rail_orders.h" - /** * Function description * @@ -40,6 +39,9 @@ */ static UINT rail_write_unicode_string(wStream* s, RAIL_UNICODE_STRING* unicode_string) { + if (!s || !unicode_string) + return ERROR_INVALID_PARAMETER; + if (!Stream_EnsureRemainingCapacity(s, 2 + unicode_string->length)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); @@ -58,6 +60,9 @@ static UINT rail_write_unicode_string(wStream* s, RAIL_UNICODE_STRING* unicode_s */ static UINT rail_write_unicode_string_value(wStream* s, RAIL_UNICODE_STRING* unicode_string) { + if (!s || !unicode_string) + return ERROR_INVALID_PARAMETER; + if (unicode_string->length > 0) { if (!Stream_EnsureRemainingCapacity(s, unicode_string->length)) @@ -80,6 +85,10 @@ static UINT rail_write_unicode_string_value(wStream* s, RAIL_UNICODE_STRING* uni UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType) { UINT16 orderLength; + + if (!rail || !s) + return ERROR_INVALID_PARAMETER; + orderLength = (UINT16) Stream_GetPosition(s); Stream_SetPosition(s, 0); rail_write_pdu_header(s, orderType, orderLength); @@ -94,8 +103,11 @@ UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType) * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_write_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* highContrast) +static UINT rail_write_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* highContrast) { + if (!s || !highContrast) + return ERROR_INVALID_PARAMETER; + highContrast->colorSchemeLength = highContrast->colorScheme.length + 2; Stream_Write_UINT32(s, highContrast->flags); /* flags (4 bytes) */ Stream_Write_UINT32(s, highContrast->colorSchemeLength); /* colorSchemeLength (4 bytes) */ @@ -107,8 +119,11 @@ UINT rail_write_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* highContrast) * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* execResult) +static UINT rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* execResult) { + if (!s || !execResult) + return ERROR_INVALID_PARAMETER; + if (Stream_GetRemainingLength(s) < 8) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); @@ -128,10 +143,13 @@ UINT rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* exec * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam) +static UINT rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam) { BYTE body; + if (!s || !sysparam) + return ERROR_INVALID_PARAMETER; + if (Stream_GetRemainingLength(s) < 5) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); @@ -163,8 +181,11 @@ UINT rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam) * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmaxinfo) +static UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmaxinfo) { + if (!s || !minmaxinfo) + return ERROR_INVALID_PARAMETER; + if (Stream_GetRemainingLength(s) < 20) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); @@ -188,10 +209,14 @@ UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmax * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_read_server_localmovesize_order(wStream* s, RAIL_LOCALMOVESIZE_ORDER* localMoveSize) +static UINT rail_read_server_localmovesize_order(wStream* s, + RAIL_LOCALMOVESIZE_ORDER* localMoveSize) { UINT16 isMoveSizeStart; + if (!s || !localMoveSize) + return ERROR_INVALID_PARAMETER; + if (Stream_GetRemainingLength(s) < 12) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); @@ -212,8 +237,12 @@ UINT rail_read_server_localmovesize_order(wStream* s, RAIL_LOCALMOVESIZE_ORDER* * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_read_server_get_appid_resp_order(wStream* s, RAIL_GET_APPID_RESP_ORDER* getAppidResp) +static UINT rail_read_server_get_appid_resp_order(wStream* s, + RAIL_GET_APPID_RESP_ORDER* getAppidResp) { + if (!s || !getAppidResp) + return ERROR_INVALID_PARAMETER; + if (Stream_GetRemainingLength(s) < 516) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); @@ -231,8 +260,11 @@ UINT rail_read_server_get_appid_resp_order(wStream* s, RAIL_GET_APPID_RESP_ORDER * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo) +static UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo) { + if (!s || !langbarInfo) + return ERROR_INVALID_PARAMETER; + if (Stream_GetRemainingLength(s) < 4) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); @@ -243,9 +275,13 @@ UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarIn return CHANNEL_RC_OK; } -void rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* clientStatus) +static UINT rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* clientStatus) { + if (!s || !clientStatus) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT32(s, clientStatus->flags); /* flags (4 bytes) */ + return ERROR_SUCCESS; } /** @@ -253,9 +289,13 @@ void rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* client * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_write_client_exec_order(wStream* s, RAIL_EXEC_ORDER* exec) +static UINT rail_write_client_exec_order(wStream* s, RAIL_EXEC_ORDER* exec) { UINT error; + + if (!s || !exec) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT16(s, exec->flags); /* flags (2 bytes) */ Stream_Write_UINT16(s, exec->exeOrFile.length); /* exeOrFileLength (2 bytes) */ Stream_Write_UINT16(s, exec->workingDir.length); /* workingDirLength (2 bytes) */ @@ -291,6 +331,10 @@ UINT rail_write_client_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam) { BYTE body; UINT error = CHANNEL_RC_OK; + + if (!s || !sysparam) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT32(s, sysparam->param); /* systemParam (4 bytes) */ switch (sysparam->param) @@ -344,51 +388,80 @@ UINT rail_write_client_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam) return error; } -void rail_write_client_activate_order(wStream* s, RAIL_ACTIVATE_ORDER* activate) +static UINT rail_write_client_activate_order(wStream* s, RAIL_ACTIVATE_ORDER* activate) { BYTE enabled; + + if (!s || !activate) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT32(s, activate->windowId); /* windowId (4 bytes) */ enabled = activate->enabled; Stream_Write_UINT8(s, enabled); /* enabled (1 byte) */ + return ERROR_SUCCESS; } -void rail_write_client_sysmenu_order(wStream* s, RAIL_SYSMENU_ORDER* sysmenu) +static UINT rail_write_client_sysmenu_order(wStream* s, RAIL_SYSMENU_ORDER* sysmenu) { + if (!s || !sysmenu) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT32(s, sysmenu->windowId); /* windowId (4 bytes) */ Stream_Write_UINT16(s, sysmenu->left); /* left (2 bytes) */ Stream_Write_UINT16(s, sysmenu->top); /* top (2 bytes) */ + return ERROR_SUCCESS; } -void rail_write_client_syscommand_order(wStream* s, RAIL_SYSCOMMAND_ORDER* syscommand) +static UINT rail_write_client_syscommand_order(wStream* s, RAIL_SYSCOMMAND_ORDER* syscommand) { + if (!s || !syscommand) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT32(s, syscommand->windowId); /* windowId (4 bytes) */ Stream_Write_UINT16(s, syscommand->command); /* command (2 bytes) */ + return ERROR_SUCCESS; } -void rail_write_client_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notifyEvent) +static UINT rail_write_client_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notifyEvent) { + if (!s || !notifyEvent) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT32(s, notifyEvent->windowId); /* windowId (4 bytes) */ Stream_Write_UINT32(s, notifyEvent->notifyIconId); /* notifyIconId (4 bytes) */ Stream_Write_UINT32(s, notifyEvent->message); /* notifyIconId (4 bytes) */ + return ERROR_SUCCESS; } -void rail_write_client_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* windowMove) +static UINT rail_write_client_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* windowMove) { + if (!s || !windowMove) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT32(s, windowMove->windowId); /* windowId (4 bytes) */ Stream_Write_UINT16(s, windowMove->left); /* left (2 bytes) */ Stream_Write_UINT16(s, windowMove->top); /* top (2 bytes) */ Stream_Write_UINT16(s, windowMove->right); /* right (2 bytes) */ Stream_Write_UINT16(s, windowMove->bottom); /* bottom (2 bytes) */ + return ERROR_SUCCESS; } -void rail_write_client_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* getAppidReq) +static UINT rail_write_client_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* getAppidReq) { + if (!s || !getAppidReq) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT32(s, getAppidReq->windowId); /* windowId (4 bytes) */ + return ERROR_SUCCESS; } -void rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo) +static UINT rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo) { + if (!s || !langbarInfo) + return ERROR_INVALID_PARAMETER; + Stream_Write_UINT32(s, langbarInfo->languageBarStatus); /* languageBarStatus (4 bytes) */ + return ERROR_SUCCESS; } /** @@ -396,11 +469,14 @@ void rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarI * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake, wStream* s) +static UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); UINT error; + if (!context || !handshake || !s) + return ERROR_INVALID_PARAMETER; + if ((error = rail_read_handshake_order(s, handshake))) { WLog_ERR(TAG, "rail_read_handshake_order failed with error %"PRIu32"!", error); @@ -423,12 +499,15 @@ UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* handshakeEx, - wStream* s) +static UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* handshakeEx, + wStream* s) { RailClientContext* context = rail_get_client_interface(rail); UINT error; + if (!context || !handshakeEx || !s) + return ERROR_INVALID_PARAMETER; + if ((error = rail_read_handshake_ex_order(s, handshakeEx))) { WLog_ERR(TAG, "rail_read_handshake_ex_order failed with error %"PRIu32"!", error); @@ -451,10 +530,15 @@ UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* han * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER* execResult, wStream* s) +static UINT rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER* execResult, + wStream* s) { RailClientContext* context = rail_get_client_interface(rail); UINT error; + + if (!context || !execResult || !s) + return ERROR_INVALID_PARAMETER; + ZeroMemory(execResult, sizeof(RAIL_EXEC_RESULT_ORDER)); if ((error = rail_read_server_exec_result_order(s, execResult))) @@ -479,11 +563,15 @@ UINT rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER* execR * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam, wStream* s) +static UINT rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam, + wStream* s) { RailClientContext* context = rail_get_client_interface(rail); UINT error; + if (!context || !sysparam || !s) + return ERROR_INVALID_PARAMETER; + if ((error = rail_read_server_sysparam_order(s, sysparam))) { WLog_ERR(TAG, "rail_read_server_sysparam_order failed with error %"PRIu32"!", error); @@ -506,12 +594,15 @@ UINT rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysp * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ORDER* minMaxInfo, - wStream* s) +static UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ORDER* minMaxInfo, + wStream* s) { RailClientContext* context = rail_get_client_interface(rail); UINT error; + if (!context || !minMaxInfo || !s) + return ERROR_INVALID_PARAMETER; + if ((error = rail_read_server_minmaxinfo_order(s, minMaxInfo))) { WLog_ERR(TAG, "rail_read_server_minmaxinfo_order failed with error %"PRIu32"!", error); @@ -534,12 +625,16 @@ UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ORDER* * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_recv_server_localmovesize_order(railPlugin* rail, RAIL_LOCALMOVESIZE_ORDER* localMoveSize, +static UINT rail_recv_server_localmovesize_order(railPlugin* rail, + RAIL_LOCALMOVESIZE_ORDER* localMoveSize, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); UINT error; + if (!context || !localMoveSize || !s) + return ERROR_INVALID_PARAMETER; + if ((error = rail_read_server_localmovesize_order(s, localMoveSize))) { WLog_ERR(TAG, "rail_read_server_localmovesize_order failed with error %"PRIu32"!", error); @@ -562,12 +657,15 @@ UINT rail_recv_server_localmovesize_order(railPlugin* rail, RAIL_LOCALMOVESIZE_O * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_recv_server_get_appid_resp_order(railPlugin* rail, +static UINT rail_recv_server_get_appid_resp_order(railPlugin* rail, RAIL_GET_APPID_RESP_ORDER* getAppIdResp, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); UINT error; + if (!context || !getAppIdResp || !s) + return ERROR_INVALID_PARAMETER; + if ((error = rail_read_server_get_appid_resp_order(s, getAppIdResp))) { WLog_ERR(TAG, "rail_read_server_get_appid_resp_order failed with error %"PRIu32"!", error); @@ -590,12 +688,15 @@ UINT rail_recv_server_get_appid_resp_order(railPlugin* rail, * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_recv_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORDER* langBarInfo, - wStream* s) +static UINT rail_recv_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORDER* langBarInfo, + wStream* s) { RailClientContext* context = rail_get_client_interface(rail); UINT error; + if (!context || !langBarInfo) + return ERROR_INVALID_PARAMETER; + if ((error = rail_read_langbar_info_order(s, langBarInfo))) { WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %"PRIu32"!", error); @@ -624,6 +725,9 @@ UINT rail_order_recv(railPlugin* rail, wStream* s) UINT16 orderLength; UINT error; + if (!rail || !s) + return ERROR_INVALID_PARAMETER; + if ((error = rail_read_pdu_header(s, &orderType, &orderLength))) { WLog_ERR(TAG, "rail_read_pdu_header failed with error %"PRIu32"!", error); @@ -688,7 +792,6 @@ UINT rail_order_recv(railPlugin* rail, wStream* s) default: WLog_ERR(TAG, "Unknown RAIL PDU order reveived."); return ERROR_INVALID_DATA; - break; } return CHANNEL_RC_OK; @@ -703,6 +806,10 @@ UINT rail_send_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake { wStream* s; UINT error; + + if (!rail || !handshake) + return ERROR_INVALID_PARAMETER; + s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH); if (!s) @@ -726,6 +833,10 @@ UINT rail_send_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* han { wStream* s; UINT error; + + if (!rail || !handshakeEx) + return ERROR_INVALID_PARAMETER; + s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH); if (!s) @@ -749,6 +860,10 @@ UINT rail_send_client_status_order(railPlugin* rail, RAIL_CLIENT_STATUS_ORDER* c { wStream* s; UINT error; + + if (!rail || !clientStatus) + return ERROR_INVALID_PARAMETER; + s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH); if (!s) @@ -757,8 +872,11 @@ UINT rail_send_client_status_order(railPlugin* rail, RAIL_CLIENT_STATUS_ORDER* c return CHANNEL_RC_NO_MEMORY; } - rail_write_client_status_order(s, clientStatus); - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_CLIENTSTATUS); + error = rail_write_client_status_order(s, clientStatus); + + if (error == ERROR_SUCCESS) + error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_CLIENTSTATUS); + Stream_Free(s, TRUE); return error; } @@ -773,6 +891,10 @@ UINT rail_send_client_exec_order(railPlugin* rail, RAIL_EXEC_ORDER* exec) wStream* s; UINT error; size_t length; + + if (!rail || !exec) + return ERROR_INVALID_PARAMETER; + length = RAIL_EXEC_ORDER_LENGTH + exec->exeOrFile.length + exec->workingDir.length + @@ -806,12 +928,14 @@ UINT rail_send_client_exec_order(railPlugin* rail, RAIL_EXEC_ORDER* exec) * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam) +static UINT rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam) { wStream* s; - int length; + size_t length = RAIL_SYSPARAM_ORDER_LENGTH; UINT error; - length = RAIL_SYSPARAM_ORDER_LENGTH; + + if (!rail || !sysparam) + return ERROR_INVALID_PARAMETER; switch (sysparam->param) { @@ -866,10 +990,13 @@ UINT rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysp * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam) +static UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam) { UINT error = CHANNEL_RC_OK; + if (!rail || !sysparam) + return ERROR_INVALID_PARAMETER; + if (sysparam->params & SPI_MASK_SET_HIGH_CONTRAST) { sysparam->param = SPI_SET_HIGH_CONTRAST; @@ -959,6 +1086,10 @@ UINT rail_send_client_activate_order(railPlugin* rail, RAIL_ACTIVATE_ORDER* acti { wStream* s; UINT error; + + if (!rail || !activate) + return ERROR_INVALID_PARAMETER; + s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH); if (!s) @@ -967,8 +1098,11 @@ UINT rail_send_client_activate_order(railPlugin* rail, RAIL_ACTIVATE_ORDER* acti return CHANNEL_RC_NO_MEMORY; } - rail_write_client_activate_order(s, activate); - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_ACTIVATE); + error = rail_write_client_activate_order(s, activate); + + if (error == ERROR_SUCCESS) + error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_ACTIVATE); + Stream_Free(s, TRUE); return error; } @@ -982,6 +1116,10 @@ UINT rail_send_client_sysmenu_order(railPlugin* rail, RAIL_SYSMENU_ORDER* sysmen { wStream* s; UINT error; + + if (!rail || !sysmenu) + return ERROR_INVALID_PARAMETER; + s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH); if (!s) @@ -990,8 +1128,11 @@ UINT rail_send_client_sysmenu_order(railPlugin* rail, RAIL_SYSMENU_ORDER* sysmen return CHANNEL_RC_NO_MEMORY; } - rail_write_client_sysmenu_order(s, sysmenu); - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSMENU); + error = rail_write_client_sysmenu_order(s, sysmenu); + + if (error == ERROR_SUCCESS) + error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSMENU); + Stream_Free(s, TRUE); return error; } @@ -1005,6 +1146,10 @@ UINT rail_send_client_syscommand_order(railPlugin* rail, RAIL_SYSCOMMAND_ORDER* { wStream* s; UINT error; + + if (!rail || !syscommand) + return ERROR_INVALID_PARAMETER; + s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH); if (!s) @@ -1013,8 +1158,11 @@ UINT rail_send_client_syscommand_order(railPlugin* rail, RAIL_SYSCOMMAND_ORDER* return CHANNEL_RC_NO_MEMORY; } - rail_write_client_syscommand_order(s, syscommand); - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSCOMMAND); + error = rail_write_client_syscommand_order(s, syscommand); + + if (error == ERROR_SUCCESS) + error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSCOMMAND); + Stream_Free(s, TRUE); return error; } @@ -1028,6 +1176,10 @@ UINT rail_send_client_notify_event_order(railPlugin* rail, RAIL_NOTIFY_EVENT_ORD { wStream* s; UINT error; + + if (!rail || !notifyEvent) + return ERROR_INVALID_PARAMETER; + s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH); if (!s) @@ -1036,8 +1188,11 @@ UINT rail_send_client_notify_event_order(railPlugin* rail, RAIL_NOTIFY_EVENT_ORD return CHANNEL_RC_NO_MEMORY; } - rail_write_client_notify_event_order(s, notifyEvent); - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_NOTIFY_EVENT); + error = rail_write_client_notify_event_order(s, notifyEvent); + + if (ERROR_SUCCESS == error) + error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_NOTIFY_EVENT); + Stream_Free(s, TRUE); return error; } @@ -1051,6 +1206,10 @@ UINT rail_send_client_window_move_order(railPlugin* rail, RAIL_WINDOW_MOVE_ORDER { wStream* s; UINT error; + + if (!rail || !windowMove) + return ERROR_INVALID_PARAMETER; + s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH); if (!s) @@ -1059,8 +1218,11 @@ UINT rail_send_client_window_move_order(railPlugin* rail, RAIL_WINDOW_MOVE_ORDER return CHANNEL_RC_NO_MEMORY; } - rail_write_client_window_move_order(s, windowMove); - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_WINDOWMOVE); + error = rail_write_client_window_move_order(s, windowMove); + + if (error == ERROR_SUCCESS) + error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_WINDOWMOVE); + Stream_Free(s, TRUE); return error; } @@ -1074,6 +1236,10 @@ UINT rail_send_client_get_appid_req_order(railPlugin* rail, RAIL_GET_APPID_REQ_O { wStream* s; UINT error; + + if (!rail || !getAppIdReq) + return ERROR_INVALID_PARAMETER; + s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH); if (!s) @@ -1082,8 +1248,11 @@ UINT rail_send_client_get_appid_req_order(railPlugin* rail, RAIL_GET_APPID_REQ_O return CHANNEL_RC_NO_MEMORY; } - rail_write_client_get_appid_req_order(s, getAppIdReq); - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_GET_APPID_REQ); + error = rail_write_client_get_appid_req_order(s, getAppIdReq); + + if (error == ERROR_SUCCESS) + error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_GET_APPID_REQ); + Stream_Free(s, TRUE); return error; } @@ -1097,6 +1266,10 @@ UINT rail_send_client_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORD { wStream* s; UINT error; + + if (!rail || !langBarInfo) + return ERROR_INVALID_PARAMETER; + s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH); if (!s) @@ -1105,8 +1278,11 @@ UINT rail_send_client_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORD return CHANNEL_RC_NO_MEMORY; } - rail_write_langbar_info_order(s, langBarInfo); - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_LANGBARINFO); + error = rail_write_langbar_info_order(s, langBarInfo); + + if (ERROR_SUCCESS == error) + error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_LANGBARINFO); + Stream_Free(s, TRUE); return error; } diff --git a/channels/rail/client/rail_orders.h b/channels/rail/client/rail_orders.h index dab414b..028286a 100644 --- a/channels/rail/client/rail_orders.h +++ b/channels/rail/client/rail_orders.h @@ -29,23 +29,7 @@ #define TAG CHANNELS_TAG("rail.client") -UINT rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* exec_result); -UINT rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam); -UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmaxinfo); -UINT rail_read_server_localmovesize_order(wStream* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize); -UINT rail_read_server_get_appid_resp_order(wStream* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp); -UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbar_info); - -void rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* client_status); -UINT rail_write_client_exec_order(wStream* s, RAIL_EXEC_ORDER* exec); UINT rail_write_client_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam); -void rail_write_client_activate_order(wStream* s, RAIL_ACTIVATE_ORDER* activate); -void rail_write_client_sysmenu_order(wStream* s, RAIL_SYSMENU_ORDER* sysmenu); -void rail_write_client_syscommand_order(wStream* s, RAIL_SYSCOMMAND_ORDER* syscommand); -void rail_write_client_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notify_event); -void rail_write_client_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* window_move); -void rail_write_client_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* get_appid_req); -void rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbar_info); UINT rail_order_recv(railPlugin* rail, wStream* s); UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType); @@ -54,11 +38,10 @@ UINT rail_send_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake UINT rail_send_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* handshakeEx); UINT rail_send_client_status_order(railPlugin* rail, RAIL_CLIENT_STATUS_ORDER* clientStatus); UINT rail_send_client_exec_order(railPlugin* rail, RAIL_EXEC_ORDER* exec); -UINT rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam); -UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam); UINT rail_send_client_activate_order(railPlugin* rail, RAIL_ACTIVATE_ORDER* activate); UINT rail_send_client_sysmenu_order(railPlugin* rail, RAIL_SYSMENU_ORDER* sysmenu); UINT rail_send_client_syscommand_order(railPlugin* rail, RAIL_SYSCOMMAND_ORDER* syscommand); + UINT rail_send_client_notify_event_order(railPlugin* rail, RAIL_NOTIFY_EVENT_ORDER* notifyEvent); UINT rail_send_client_window_move_order(railPlugin* rail, RAIL_WINDOW_MOVE_ORDER* windowMove); UINT rail_send_client_get_appid_req_order(railPlugin* rail, RAIL_GET_APPID_REQ_ORDER* getAppIdReq); diff --git a/channels/rail/rail_common.c b/channels/rail/rail_common.c index 3c05eb5..ea344c3 100644 --- a/channels/rail/rail_common.c +++ b/channels/rail/rail_common.c @@ -55,9 +55,7 @@ void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_st { WCHAR* buffer = NULL; int length = 0; - free(unicode_string->string); - unicode_string->string = NULL; unicode_string->length = 0; @@ -65,7 +63,6 @@ void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_st return; length = ConvertToUnicode(CP_UTF8, 0, string, -1, &buffer, 0) * 2; - unicode_string->string = (BYTE*) buffer; unicode_string->length = (UINT16) length; } @@ -77,12 +74,14 @@ void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_st */ UINT rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength) { + if (!s || !orderType || !orderLength) + return ERROR_INVALID_PARAMETER; + if (Stream_GetRemainingLength(s) < 4) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, *orderType); /* orderType (2 bytes) */ Stream_Read_UINT16(s, *orderLength); /* orderLength (2 bytes) */ - return CHANNEL_RC_OK; } @@ -96,8 +95,10 @@ wStream* rail_pdu_init(size_t length) { wStream* s; s = Stream_New(NULL, length + RAIL_PDU_HEADER_LENGTH); + if (!s) return NULL; + Stream_Seek(s, RAIL_PDU_HEADER_LENGTH); return s; } @@ -113,7 +114,6 @@ UINT rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake) return ERROR_INVALID_DATA; Stream_Read_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */ - return CHANNEL_RC_OK; } @@ -134,7 +134,6 @@ UINT rail_read_handshake_ex_order(wStream* s, RAIL_HANDSHAKE_EX_ORDER* handshake Stream_Read_UINT32(s, handshakeEx->buildNumber); /* buildNumber (4 bytes) */ Stream_Read_UINT32(s, handshakeEx->railHandshakeFlags); /* railHandshakeFlags (4 bytes) */ - return CHANNEL_RC_OK; } diff --git a/channels/rdpdr/client/irp.c b/channels/rdpdr/client/irp.c index d8eaece..21d4a46 100644 --- a/channels/rdpdr/client/irp.c +++ b/channels/rdpdr/client/irp.c @@ -59,13 +59,13 @@ static UINT irp_free(IRP* irp) */ static UINT irp_complete(IRP* irp) { - int pos; + size_t pos; rdpdrPlugin* rdpdr; UINT error; rdpdr = (rdpdrPlugin*) irp->devman->plugin; - pos = (int) Stream_GetPosition(irp->output); + pos = Stream_GetPosition(irp->output); Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4); Stream_Write_UINT32(irp->output, irp->IoStatus); /* IoStatus (4 bytes) */ Stream_SetPosition(irp->output, pos); diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index f679f8f..3f16ca9 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -118,9 +118,9 @@ void first_hotplug(rdpdrPlugin* rdpdr) { } -static void* drive_hotplug_thread_func(void* arg) +static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) { - return NULL; + return CHANNEL_RC_OK; } static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) @@ -280,7 +280,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) return DefWindowProc(hWnd, Msg, wParam, lParam); } -static void* drive_hotplug_thread_func(void* arg) +static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) { rdpdrPlugin* rdpdr; WNDCLASSEX wnd_cls; @@ -331,7 +331,7 @@ static void* drive_hotplug_thread_func(void* arg) } UnregisterDeviceNotification(hDevNotify); - return NULL; + return CHANNEL_RC_OK; } /** @@ -420,6 +420,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) for (j = 0; j < count; j++) { + char* path = NULL; BOOL dev_found = FALSE; device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue( rdpdr->devman->devices, (void*)keys[j]); @@ -430,13 +431,19 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) if (device_ext->path == NULL) continue; - /* not plugable device */ - if (strstr(device_ext->path, "/Volumes/") == NULL) + if (ConvertFromUnicode(CP_UTF8, 0, device_ext->path, 0, &path, 0, NULL, FALSE) <= 0) continue; + /* not plugable device */ + if (strstr(path, "/Volumes/") == NULL) + { + free(path); + continue; + } + for (i = 0; i < size; i++) { - if (strstr(device_ext->path, dev_array[i].path) != NULL) + if (strstr(path, dev_array[i].path) != NULL) { dev_found = TRUE; dev_array[i].to_add = FALSE; @@ -444,6 +451,8 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) } } + free(path); + if (!dev_found) { devman_unregister_device(rdpdr->devman, (void*)keys[j]); @@ -549,7 +558,7 @@ void first_hotplug(rdpdrPlugin* rdpdr) } } -static void* drive_hotplug_thread_func(void* arg) +static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) { rdpdrPlugin* rdpdr; FSEventStreamRef fsev; @@ -570,7 +579,7 @@ static void* drive_hotplug_thread_func(void* arg) FSEventStreamStop(fsev); FSEventStreamRelease(fsev); ExitThread(CHANNEL_RC_OK); - return NULL; + return CHANNEL_RC_OK; } @@ -914,7 +923,7 @@ static void first_hotplug(rdpdrPlugin* rdpdr) } } -static void* drive_hotplug_thread_func(void* arg) +static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) { rdpdrPlugin* rdpdr; int mfd; @@ -985,8 +994,8 @@ out: "drive_hotplug_thread_func reported an error"); CloseHandle(rdpdr->stopEvent); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -1051,18 +1060,23 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) { device = settings->DeviceArray[index]; - if (device->Name && (strcmp(device->Name, "*") == 0)) + if (device->Type == RDPDR_DTYP_FILESYSTEM) { - first_hotplug(rdpdr); + RDPDR_DRIVE* drive = (RDPDR_DRIVE*)device; - if (!(rdpdr->hotplugThread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) drive_hotplug_thread_func, rdpdr, 0, NULL))) + if (drive->Path && (strcmp(drive->Path, "*") == 0)) { - WLog_ERR(TAG, "CreateThread failed!"); - return ERROR_INTERNAL_ERROR; - } + first_hotplug(rdpdr); - continue; + if (!(rdpdr->hotplugThread = CreateThread(NULL, 0, + drive_hotplug_thread_func, rdpdr, 0, NULL))) + { + WLog_ERR(TAG, "CreateThread failed!"); + return ERROR_INTERNAL_ERROR; + } + + continue; + } } if ((error = devman_load_device_service(rdpdr->devman, device, @@ -1185,12 +1199,12 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, { int i; BYTE c; - int pos; + size_t pos; int index; wStream* s; UINT32 count; - int data_len; - int count_pos; + size_t data_len; + size_t count_pos; DEVICE* device; int keyCount; ULONG_PTR* pKeys; @@ -1204,7 +1218,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ Stream_Write_UINT16(s, PAKID_CORE_DEVICELIST_ANNOUNCE); /* PacketId (2 bytes) */ - count_pos = (int) Stream_GetPosition(s); + count_pos = Stream_GetPosition(s); count = 0; Stream_Seek_UINT32(s); /* deviceCount */ pKeys = NULL; @@ -1225,7 +1239,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, if ((rdpdr->versionMinor == 0x0005) || (device->type == RDPDR_DTYP_SMARTCARD) || userLoggedOn) { - data_len = (int)(device->data == NULL ? 0 : Stream_GetPosition(device->data)); + data_len = (device->data == NULL ? 0 : Stream_GetPosition(device->data)); if (!Stream_EnsureRemainingCapacity(s, 20 + data_len)) { @@ -1259,7 +1273,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, } free(pKeys); - pos = (int) Stream_GetPosition(s); + pos = Stream_GetPosition(s); Stream_SetPosition(s, count_pos); Stream_Write_UINT32(s, count); Stream_SetPosition(s, pos); @@ -1609,7 +1623,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event_ex(LPVOID lpUserParam, DW return; } -static void* rdpdr_virtual_channel_client_thread(void* arg) +static DWORD WINAPI rdpdr_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; @@ -1619,7 +1633,7 @@ static void* rdpdr_virtual_channel_client_thread(void* arg) if (!rdpdr) { ExitThread((DWORD) CHANNEL_RC_NULL_DATA); - return NULL; + return CHANNEL_RC_NULL_DATA; } if ((error = rdpdr_process_connect(rdpdr))) @@ -1630,8 +1644,8 @@ static void* rdpdr_virtual_channel_client_thread(void* arg) setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_client_thread reported an error"); - ExitThread((DWORD) error); - return NULL; + ExitThread(error); + return error; } while (1) @@ -1657,14 +1671,14 @@ static void* rdpdr_virtual_channel_client_thread(void* arg) "rdpdr_virtual_channel_client_thread reported an error"); ExitThread((DWORD) error); - return NULL; + return error; } } } } ExitThread(0); - return NULL; + return 0; } /** @@ -1695,7 +1709,7 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, } if (!(rdpdr->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) rdpdr_virtual_channel_client_thread, (void*) rdpdr, 0, + rdpdr_virtual_channel_client_thread, (void*) rdpdr, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c index 0e4abff..a8e7ec3 100644 --- a/channels/rdpdr/server/rdpdr_main.c +++ b/channels/rdpdr/server/rdpdr_main.c @@ -149,12 +149,9 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */ Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */ Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */ - - if (UnicodeFlag > 1) /* must be 0x00000000 or 0x00000001 */ - { - WLog_ERR(TAG, "invalid UnicodeFlag value: 0x%08"PRIX32"", UnicodeFlag); - return ERROR_INVALID_DATA; - } + /* UnicodeFlag is either 0 or 1, the other 31 bits must be ignored. + */ + UnicodeFlag = UnicodeFlag & 0x00000001; /** * Caution: ComputerNameLen is given *bytes*, @@ -768,7 +765,6 @@ static UINT rdpdr_server_receive_device_list_announce_request( UINT32 DeviceId; char PreferredDosName[9]; UINT32 DeviceDataLength; - BYTE* DeviceData; if (Stream_GetRemainingLength(s) < 4) { @@ -800,7 +796,6 @@ static UINT rdpdr_server_receive_device_list_announce_request( return ERROR_INVALID_DATA; } - DeviceData = Stream_Pointer(s); WLog_DBG(TAG, "Device %d Name: %s Id: 0x%08"PRIX32" DataLength: %"PRIu32"", i, PreferredDosName, DeviceId, DeviceDataLength); @@ -1134,7 +1129,7 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, return error; } -static void* rdpdr_server_thread(void* arg) +static DWORD WINAPI rdpdr_server_thread(LPVOID arg) { wStream* s; DWORD status; @@ -1150,7 +1145,6 @@ static void* rdpdr_server_thread(void* arg) buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; - s = Stream_New(NULL, 4096); if (!s) @@ -1239,8 +1233,8 @@ out: setChannelError(context->rdpcontext, error, "rdpdr_server_thread reported an error"); - ExitThread((DWORD) error); - return NULL; + ExitThread(error); + return error; } /** @@ -1266,7 +1260,7 @@ static UINT rdpdr_server_start(RdpdrServerContext* context) } if (!(context->priv->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) rdpdr_server_thread, (void*) context, 0, NULL))) + rdpdr_server_thread, (void*) context, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(context->priv->StopEvent); diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index 72de9e0..f668159 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -169,7 +169,7 @@ UINT rdpei_add_frame(RdpeiClientContext* context) return CHANNEL_RC_OK; } -static void* rdpei_schedule_thread(void* arg) +static DWORD WINAPI rdpei_schedule_thread(LPVOID arg) { DWORD status; RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) arg; @@ -228,12 +228,12 @@ static void* rdpei_schedule_thread(void* arg) out: - if (error && rdpei->rdpcontext) + if (error && rdpei && rdpei->rdpcontext) setChannelError(rdpei->rdpcontext, error, "rdpei_schedule_thread reported an error"); - ExitThread(0); - return NULL; + ExitThread(error); + return error; } /** @@ -653,7 +653,7 @@ static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, goto error_out; } - if (!(rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) + if (!(rdpei->thread = CreateThread(NULL, 0, rdpei_schedule_thread, (void*) rdpei, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); diff --git a/channels/rdpgfx/client/rdpgfx_codec.c b/channels/rdpgfx/client/rdpgfx_codec.c index 0ea15a3..a88c7d0 100644 --- a/channels/rdpgfx/client/rdpgfx_codec.c +++ b/channels/rdpgfx/client/rdpgfx_codec.c @@ -139,8 +139,8 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd wStream* s; RDPGFX_AVC420_BITMAP_STREAM h264; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; - s = Stream_New(cmd->data, cmd->length); + s = Stream_New(cmd->data, cmd->length); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -186,7 +186,6 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; s = Stream_New(cmd->data, cmd->length); - if (!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -275,7 +274,7 @@ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) { UINT error = CHANNEL_RC_OK; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; - PROFILER_ENTER(context->SurfaceProfiler); + PROFILER_ENTER(context->SurfaceProfiler) switch (cmd->codecId) { @@ -304,6 +303,6 @@ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) break; } - PROFILER_EXIT(context->SurfaceProfiler); + PROFILER_EXIT(context->SurfaceProfiler) return error; } diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index ec95015..0090db0 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -74,7 +74,10 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) if (gfx->ThinClient) capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; - if (gfx->SmallCache) + /* in CAPVERSION_8 the spec says that we should not have both + * thinclient and smallcache (and thinclient implies a small cache) + */ + if (gfx->SmallCache && !gfx->ThinClient) capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; capsSet = &capsSets[pdu.capsSetCount++]; @@ -92,27 +95,29 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED; #endif - capsSet = &capsSets[pdu.capsSetCount++]; - capsSet->version = RDPGFX_CAPVERSION_10; - capsSet->flags = 0; + if (!gfx->H264 || gfx->AVC444) + { + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_10; + capsSet->flags = 0; - if (gfx->SmallCache) - capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + if (gfx->SmallCache) + capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; #ifdef WITH_GFX_H264 - if (!gfx->AVC444) - capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; + if (!gfx->AVC444) + capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; #else - capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; + capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; #endif - capsSets[pdu.capsSetCount] = *capsSet; - capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102; - capsSets[pdu.capsSetCount] = *capsSet; - capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_103; + capsSets[pdu.capsSetCount] = *capsSet; + capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102; + capsSets[pdu.capsSetCount] = *capsSet; + capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_103; + } - header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * - RDPGFX_CAPSET_SIZE); + header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE); WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu %"PRIu16"", pdu.capsSetCount); s = Stream_New(NULL, header.pduLength); @@ -193,8 +198,8 @@ static UINT rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE; header.pduLength = RDPGFX_HEADER_SIZE + 12; WLog_Print(gfx->log, WLOG_DEBUG, "SendFrameAcknowledgePdu: %"PRIu32"", pdu->frameId); - s = Stream_New(NULL, header.pduLength); + s = Stream_New(NULL, header.pduLength); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -228,8 +233,8 @@ static UINT rdpgfx_send_qoe_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callb header.cmdId = RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE; header.pduLength = RDPGFX_HEADER_SIZE + 12; WLog_Print(gfx->log, WLOG_DEBUG, "SendQoeFrameAcknowledgePdu: %"PRIu32"", pdu->frameId); - s = Stream_New(NULL, header.pduLength); + s = Stream_New(NULL, header.pduLength); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -267,6 +272,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; UINT error = CHANNEL_RC_OK; + GraphicsResetEventArgs graphicsReset; if (Stream_GetRemainingLength(s) < 12) { @@ -284,9 +290,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, return ERROR_INVALID_DATA; } - pdu.monitorDefArray = (MONITOR_DEF*) calloc(pdu.monitorCount, - sizeof(MONITOR_DEF)); - + pdu.monitorDefArray = (MONITOR_DEF*) calloc(pdu.monitorCount, sizeof(MONITOR_DEF)); if (!pdu.monitorDefArray) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -332,6 +336,12 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, WLog_Print(gfx->log, WLOG_ERROR, "context->ResetGraphics failed with error %"PRIu32"", error); } + /* some listeners may be interested (namely the display channel) */ + EventArgsInit(&graphicsReset, "xfreerdp"); + graphicsReset.width = pdu.width; + graphicsReset.height = pdu.height; + PubSub_OnGraphicsReset(gfx->rdpcontext->pubSub, gfx->rdpcontext, &graphicsReset); + free(pdu.monitorDefArray); return error; } @@ -398,7 +408,6 @@ static UINT rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback } pdu.cacheSlots = (UINT16*) calloc(pdu.importedEntriesCount, sizeof(UINT16)); - if (!pdu.cacheSlots) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -810,8 +819,7 @@ static UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ - if ((error = rdpgfx_read_color32(s, - &(pdu.fillPixel)))) /* fillPixel (4 bytes) */ + if ((error = rdpgfx_read_color32(s, &(pdu.fillPixel)))) /* fillPixel (4 bytes) */ { WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_read_color32 failed with error %"PRIu32"!", error); return error; @@ -826,7 +834,6 @@ static UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea } pdu.fillRects = (RECTANGLE_16*) calloc(pdu.fillRectCount, sizeof(RECTANGLE_16)); - if (!pdu.fillRects) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -898,9 +905,7 @@ static UINT rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* return ERROR_INVALID_DATA; } - pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, - sizeof(RDPGFX_POINT16)); - + pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16)); if (!pdu.destPts) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -1015,9 +1020,7 @@ static UINT rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, return ERROR_INVALID_DATA; } - pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, - sizeof(RDPGFX_POINT16)); - + pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16)); if (!pdu.destPts) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -1135,7 +1138,7 @@ static UINT rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callb */ static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { - int beg, end; + size_t beg, end; RDPGFX_HEADER header; UINT error; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; @@ -1148,11 +1151,9 @@ static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) return error; } -#if 1 WLog_Print(gfx->log, WLOG_DEBUG, "cmdId: %s (0x%04"PRIX16") flags: 0x%04"PRIX16" pduLength: %"PRIu32"", rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags, header.pduLength); -#endif switch (header.cmdId) { @@ -1305,8 +1306,8 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback* RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; UINT error = CHANNEL_RC_OK; - status = zgfx_decompress(gfx->zgfx, Stream_Pointer(data), - Stream_GetRemainingLength(data), &pDstData, &DstSize, 0); + status = zgfx_decompress(gfx->zgfx, Stream_Pointer(data), Stream_GetRemainingLength(data), + &pDstData, &DstSize, 0); if (status < 0) { @@ -1315,7 +1316,6 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback* } s = Stream_New(pDstData, DstSize); - if (!s) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -1360,6 +1360,7 @@ static UINT rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback) RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + WLog_Print(gfx->log, WLOG_DEBUG, "OnClose"); free(callback); gfx->UnacknowledgedFrames = 0; @@ -1419,11 +1420,9 @@ static UINT rdpgfx_on_new_channel_connection(IWTSListenerCallback* IWTSVirtualChannelCallback** ppCallback) { RDPGFX_CHANNEL_CALLBACK* callback; - RDPGFX_LISTENER_CALLBACK* listener_callback = (RDPGFX_LISTENER_CALLBACK*) - pListenerCallback; - callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1, - sizeof(RDPGFX_CHANNEL_CALLBACK)); + RDPGFX_LISTENER_CALLBACK* listener_callback = (RDPGFX_LISTENER_CALLBACK*)pListenerCallback; + callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPGFX_CHANNEL_CALLBACK)); if (!callback) { WLog_ERR(TAG, "calloc failed!"); @@ -1451,17 +1450,15 @@ static UINT rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, { UINT error; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin; - gfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1, - sizeof(RDPGFX_LISTENER_CALLBACK)); + gfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1, sizeof(RDPGFX_LISTENER_CALLBACK)); if (!gfx->listener_callback) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; } - gfx->listener_callback->iface.OnNewChannelConnection = - rdpgfx_on_new_channel_connection; + gfx->listener_callback->iface.OnNewChannelConnection = rdpgfx_on_new_channel_connection; gfx->listener_callback->plugin = pPlugin; gfx->listener_callback->channel_mgr = pChannelMgr; error = pChannelMgr->CreateListener(pChannelMgr, RDPGFX_DVC_CHANNEL_NAME, 0, @@ -1598,6 +1595,7 @@ static UINT rdpgfx_get_surface_ids(RdpgfxClientContext* context, if (!pSurfaceIds) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); + free(pKeys); return CHANNEL_RC_NO_MEMORY; } @@ -1634,7 +1632,11 @@ static UINT rdpgfx_set_cache_slot_data(RdpgfxClientContext* context, RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; if (cacheSlot >= gfx->MaxCacheSlot) + { + WLog_ERR(TAG, "%s: invalid cache slot %"PRIu16" maxAllowed=%"PRIu16"", __FUNCTION__, + cacheSlot, gfx->MaxCacheSlot); return ERROR_INVALID_INDEX; + } gfx->CacheSlots[cacheSlot] = pData; return CHANNEL_RC_OK; @@ -1646,7 +1648,11 @@ static void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cac RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; if (cacheSlot >= gfx->MaxCacheSlot) + { + WLog_ERR(TAG, "%s: invalid cache slot %"PRIu16" maxAllowed=%"PRIu16"", __FUNCTION__, + cacheSlot, gfx->MaxCacheSlot); return NULL; + } pData = gfx->CacheSlots[cacheSlot]; return pData; @@ -1684,7 +1690,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) if (!gfx->log) { free(gfx); - WLog_ERR(TAG, "Failed to aquire reference to WLog %s", TAG); + WLog_ERR(TAG, "Failed to acquire reference to WLog %s", TAG); return ERROR_INTERNAL_ERROR; } @@ -1693,8 +1699,9 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) gfx->iface.Connected = NULL; gfx->iface.Disconnected = NULL; gfx->iface.Terminated = rdpgfx_plugin_terminated; - gfx->SurfaceTable = HashTable_New(TRUE); + gfx->rdpcontext = ((freerdp *)gfx->settings->instance)->context; + gfx->SurfaceTable = HashTable_New(TRUE); if (!gfx->SurfaceTable) { free(gfx); @@ -1713,12 +1720,9 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) if (gfx->H264) gfx->SmallCache = TRUE; - if (gfx->SmallCache) - gfx->ThinClient = FALSE; - - gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600; - context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext)); + gfx->MaxCacheSlot = gfx->SmallCache ? 4096 : 25600; + context = (RdpgfxClientContext *)calloc(1, sizeof(RdpgfxClientContext)); if (!context) { free(gfx); diff --git a/channels/rdpgfx/server/rdpgfx_main.c b/channels/rdpgfx/server/rdpgfx_main.c index 29ccfdb..e3e645c 100644 --- a/channels/rdpgfx/server/rdpgfx_main.c +++ b/channels/rdpgfx/server/rdpgfx_main.c @@ -508,6 +508,10 @@ static UINT rdpgfx_write_h264_metablock(wStream* s, RDPGFX_H264_METABLOCK* meta) RECTANGLE_16* regionRect; RDPGFX_H264_QUANT_QUALITY* quantQualityVal; UINT error = CHANNEL_RC_OK; + + if (!Stream_EnsureRemainingCapacity(s, 4 + meta->numRegionRects * 10)) + return ERROR_OUTOFMEMORY; + Stream_Write_UINT32(s, meta->numRegionRects); /* numRegionRects (4 bytes) */ for (index = 0; index < meta->numRegionRects; index++) @@ -552,6 +556,9 @@ static INLINE UINT rdpgfx_write_h264_avc420(wStream* s, return error; } + if (!Stream_EnsureRemainingCapacity(s, havc420->length)) + return ERROR_OUTOFMEMORY; + Stream_Write(s, havc420->data, havc420->length); return error; } @@ -584,7 +591,7 @@ static UINT rdpgfx_write_surface_command(wStream* s, break; default: - WLog_ERR(TAG, "Format %s not supported!", GetColorFormatName(cmd->format)); + WLog_ERR(TAG, "Format %s not supported!", FreeRDPGetColorFormatName(cmd->format)); return ERROR_INVALID_DATA; } @@ -623,12 +630,11 @@ static UINT rdpgfx_write_surface_command(wStream* s, return error; } } - else if (cmd->codecId == RDPGFX_CODECID_AVC444) + else if ((cmd->codecId == RDPGFX_CODECID_AVC444) || (cmd->codecId == RDPGFX_CODECID_AVC444v2)) { havc444 = (RDPGFX_AVC444_BITMAP_STREAM*)cmd->extra; - havc420 = &(havc444->bitstream[0]); - /* avc420EncodedBitstreamInfo (4 bytes) */ - Stream_Write_UINT32(s, havc420->length | (havc444->LC << 30UL)); + havc420 = &(havc444->bitstream[0]); /* avc420EncodedBitstreamInfo (4 bytes) */ + Stream_Write_UINT32(s, havc444->cbAvc420EncodedBitstream1 | (havc444->LC << 30UL)); /* avc420EncodedBitstream1 */ error = rdpgfx_write_h264_avc420(s, havc420); @@ -641,7 +647,7 @@ static UINT rdpgfx_write_surface_command(wStream* s, /* avc420EncodedBitstream2 */ if (havc444->LC == 0) { - havc420 = &(havc444->bitstream[0]); + havc420 = &(havc444->bitstream[1]); error = rdpgfx_write_h264_avc420(s, havc420); if (error != CHANNEL_RC_OK) @@ -656,7 +662,6 @@ static UINT rdpgfx_write_surface_command(wStream* s, Stream_Write(s, cmd->data, cmd->length); } - assert(Stream_GetPosition(s) <= Stream_Capacity(s)); /* Fill actual bitmap data length */ bitmapDataLength = Stream_GetPosition(s) - bitmapDataStart; Stream_SetPosition(s, bitmapDataStart - sizeof(UINT32)); @@ -1253,7 +1258,7 @@ static UINT rdpgfx_recv_qoe_frame_acknowledge_pdu(RdpgfxServerContext* context, */ static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s) { - int beg, end; + size_t beg, end; RDPGFX_HEADER header; UINT error = CHANNEL_RC_OK; beg = Stream_GetPosition(s); @@ -1273,28 +1278,28 @@ static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s) case RDPGFX_CMDID_FRAMEACKNOWLEDGE: if ((error = rdpgfx_recv_frame_acknowledge_pdu(context, s))) WLog_ERR(TAG, "rdpgfx_recv_frame_acknowledge_pdu " - "failed with error %"PRIu32"!", error); + "failed with error %"PRIu32"!", error); break; case RDPGFX_CMDID_CACHEIMPORTOFFER: if ((error = rdpgfx_recv_cache_import_offer_pdu(context, s))) WLog_ERR(TAG, "rdpgfx_recv_cache_import_offer_pdu " - "failed with error %"PRIu32"!", error); + "failed with error %"PRIu32"!", error); break; case RDPGFX_CMDID_CAPSADVERTISE: if ((error = rdpgfx_recv_caps_advertise_pdu(context, s))) WLog_ERR(TAG, "rdpgfx_recv_caps_advertise_pdu " - "failed with error %"PRIu32"!", error); + "failed with error %"PRIu32"!", error); break; case RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE: if ((error = rdpgfx_recv_qoe_frame_acknowledge_pdu(context, s))) WLog_ERR(TAG, "rdpgfx_recv_qoe_frame_acknowledge_pdu " - "failed with error %"PRIu32"!", error); + "failed with error %"PRIu32"!", error); break; @@ -1322,7 +1327,7 @@ static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s) return error; } -static void* rdpgfx_server_thread_func(void* arg) +static DWORD WINAPI rdpgfx_server_thread_func(LPVOID arg) { RdpgfxServerContext* context = (RdpgfxServerContext*) arg; RdpgfxServerPrivate* priv = context->priv; @@ -1333,7 +1338,6 @@ static void* rdpgfx_server_thread_func(void* arg) UINT error = CHANNEL_RC_OK; buffer = NULL; nCount = 0; - events[nCount++] = priv->stopEvent; events[nCount++] = priv->channelEvent; @@ -1365,8 +1369,8 @@ static void* rdpgfx_server_thread_func(void* arg) setChannelError(context->rdpcontext, error, "rdpgfx_server_thread_func reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } static BOOL rdpgfx_server_open(RdpgfxServerContext* context) @@ -1433,7 +1437,6 @@ static BOOL rdpgfx_server_open(RdpgfxServerContext* context) } if (!(priv->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) rdpgfx_server_thread_func, (void*) context, 0, NULL))) { @@ -1654,7 +1657,7 @@ UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context) if ((ret = rdpgfx_server_receive_pdu(context, s))) { WLog_ERR(TAG, "rdpgfx_server_receive_pdu " - "failed with error %"PRIu32"!", ret); + "failed with error %"PRIu32"!", ret); return ret; } } diff --git a/channels/rdpsnd/client/mac/rdpsnd_mac.c b/channels/rdpsnd/client/mac/rdpsnd_mac.c index a73f8ac..93e448f 100644 --- a/channels/rdpsnd/client/mac/rdpsnd_mac.c +++ b/channels/rdpsnd/client/mac/rdpsnd_mac.c @@ -54,7 +54,8 @@ struct rdpsnd_mac_plugin UINT32 latency; AUDIO_FORMAT format; - int audioBufferIndex; + size_t lastAudioBufferIndex; + size_t audioBufferIndex; AudioQueueRef audioQueue; AudioStreamBasicDescription audioFormat; @@ -70,7 +71,12 @@ typedef struct rdpsnd_mac_plugin rdpsndMacPlugin; static void mac_audio_queue_output_cb(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { - + rdpsndMacPlugin* mac = (rdpsndMacPlugin*)inUserData; + + if (inBuffer == mac->audioBuffers[mac->lastAudioBufferIndex]) { + AudioQueuePause(mac->audioQueue); + mac->isPlaying = FALSE; + } } static BOOL rdpsnd_mac_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) @@ -193,10 +199,16 @@ static void rdpsnd_mac_close(rdpsndDevicePlugin* device) if (mac->isOpen) { + size_t index; mac->isOpen = FALSE; AudioQueueStop(mac->audioQueue, true); + for (index = 0; index < MAC_AUDIO_QUEUE_NUM_BUFFERS; index++) + { + AudioQueueFreeBuffer(mac->audioQueue, mac->audioBuffers[index]); + } + AudioQueueDispose(mac->audioQueue, true); mac->audioQueue = NULL; @@ -338,12 +350,9 @@ static void rdpsnd_mac_waveplay(rdpsndDevicePlugin* device, RDPSND_WAVE* wave) wave->wTimeStampB = wave->wTimeStampA + wave->wLocalTimeB - wave->wLocalTimeA; mac->lastStartTime = outActualStartTime.mSampleTime; + mac->lastAudioBufferIndex = mac->audioBufferIndex; mac->audioBufferIndex++; - - if (mac->audioBufferIndex >= MAC_AUDIO_QUEUE_NUM_BUFFERS) - { - mac->audioBufferIndex = 0; - } + mac->audioBufferIndex %= MAC_AUDIO_QUEUE_NUM_BUFFERS; device->Start(device); } diff --git a/channels/rdpsnd/client/oss/rdpsnd_oss.c b/channels/rdpsnd/client/oss/rdpsnd_oss.c index 5209969..9a9d103 100644 --- a/channels/rdpsnd/client/oss/rdpsnd_oss.c +++ b/channels/rdpsnd/client/oss/rdpsnd_oss.c @@ -82,22 +82,25 @@ static int rdpsnd_oss_get_format(AUDIO_FORMAT* format) switch (format->wFormatTag) { case WAVE_FORMAT_PCM: - switch (format->wBitsPerSample) { case 8: return AFMT_S8; + case 16: return AFMT_S16_LE; } break; + case WAVE_FORMAT_ALAW: return AFMT_A_LAW; #if 0 /* This does not work on my desktop. */ + case WAVE_FORMAT_MULAW: return AFMT_MU_LAW; #endif + case WAVE_FORMAT_ADPCM: case WAVE_FORMAT_DVI_ADPCM: return AFMT_S16_LE; @@ -117,20 +120,19 @@ static BOOL rdpsnd_oss_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT switch (format->wFormatTag) { case WAVE_FORMAT_PCM: - if (format->cbSize != 0 || - format->nSamplesPerSec > 48000 || - (format->wBitsPerSample != 8 && format->wBitsPerSample != 16) || - (format->nChannels != 1 && format->nChannels != 2)) + format->nSamplesPerSec > 48000 || + (format->wBitsPerSample != 8 && format->wBitsPerSample != 16) || + (format->nChannels != 1 && format->nChannels != 2)) return FALSE; break; + case WAVE_FORMAT_ADPCM: case WAVE_FORMAT_DVI_ADPCM: - if (format->nSamplesPerSec > 48000 || - format->wBitsPerSample != 4 || - (format->nChannels != 1 && format->nChannels != 2)) + format->wBitsPerSample != 4 || + (format->nChannels != 1 && format->nChannels != 2)) return FALSE; break; @@ -379,17 +381,19 @@ static BOOL rdpsnd_oss_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wave { case WAVE_FORMAT_ADPCM: oss->dsp_context->decode_ms_adpcm(oss->dsp_context, - wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign); + wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign); wave->length = oss->dsp_context->adpcm_size; wave->data = oss->dsp_context->adpcm_buffer; break; + case WAVE_FORMAT_DVI_ADPCM: oss->dsp_context->decode_ima_adpcm(oss->dsp_context, - wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign); + wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign); wave->length = oss->dsp_context->adpcm_size; wave->data = oss->dsp_context->adpcm_buffer; break; } + return TRUE; } @@ -442,12 +446,14 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* a COMMAND_LINE_ARGUMENT_A* arg; rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device; flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; - status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, rdpsnd_oss_args, flags, oss, NULL, NULL); + status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, rdpsnd_oss_args, flags, + oss, NULL, NULL); if (status < 0) return status; arg = rdpsnd_oss_args; + errno = 0; do { @@ -458,10 +464,21 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* a CommandLineSwitchCase(arg, "dev") { str_num = _strdup(arg->Value); + if (!str_num) return ERROR_OUTOFMEMORY; - oss->dev_unit = strtol(str_num, &eptr, 10); + { + long val = strtol(str_num, &eptr, 10); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + { + free(str_num); + return CHANNEL_RC_NULL_DATA; + } + + oss->dev_unit = val; + } if (oss->dev_unit < 0 || *eptr != '\0') oss->dev_unit = -1; @@ -491,8 +508,10 @@ UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS p ADDIN_ARGV* args; rdpsndOssPlugin* oss; oss = (rdpsndOssPlugin*)calloc(1, sizeof(rdpsndOssPlugin)); + if (!oss) return CHANNEL_RC_NO_MEMORY; + oss->device.Open = rdpsnd_oss_open; oss->device.FormatSupported = rdpsnd_oss_format_supported; oss->device.SetFormat = rdpsnd_oss_set_format; @@ -508,6 +527,7 @@ UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS p args = pEntryPoints->args; rdpsnd_oss_parse_addin_args((rdpsndDevicePlugin*)oss, args); oss->dsp_context = freerdp_dsp_context_new(); + if (!oss->dsp_context) { free(oss); @@ -515,6 +535,5 @@ UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS p } pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)oss); - return CHANNEL_RC_OK; } diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index 2f93c64..2191ec9 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -191,6 +191,11 @@ static void rdpsnd_pulse_close(rdpsndDevicePlugin* device) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; +#ifdef WITH_GSM + if (pulse->gsm_context) + gsm_destroy(pulse->gsm_context); +#endif + if (!pulse->context || !pulse->stream) return; @@ -364,6 +369,10 @@ static void rdpsnd_pulse_free(rdpsndDevicePlugin* device) pulse->mainloop = NULL; } +#ifdef WITH_GSM + Stream_Free(pulse->gsmBuffer, TRUE); +#endif + free(pulse->device_name); freerdp_dsp_context_free(pulse->dsp_context); free(pulse); diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 172128d..4c327f7 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -102,7 +103,7 @@ struct rdpsnd_plugin */ static UINT rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave); -static void* rdpsnd_schedule_thread(void* arg) +static DWORD WINAPI rdpsnd_schedule_thread(LPVOID arg) { wMessage message; UINT16 wTimeDiff; @@ -182,8 +183,8 @@ static void* rdpsnd_schedule_thread(void* arg) setChannelError(rdpsnd->rdpcontext, error, "rdpsnd_schedule_thread reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -224,8 +225,8 @@ static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd) return; rdpsnd->ClientFormats = (AUDIO_FORMAT*) calloc( - rdpsnd->NumberOfServerFormats, - sizeof(AUDIO_FORMAT)); + rdpsnd->NumberOfServerFormats, + sizeof(AUDIO_FORMAT)); if (!rdpsnd->ClientFormats) return; @@ -871,6 +872,7 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args) return CHANNEL_RC_INITIALIZATION_ERROR; arg = rdpsnd_args; + errno = 0; do { @@ -890,23 +892,43 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args) } CommandLineSwitchCase(arg, "format") { - rdpsnd->fixedFormat = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT16_MAX)) + return CHANNEL_RC_INITIALIZATION_ERROR; + + rdpsnd->fixedFormat = val; } CommandLineSwitchCase(arg, "rate") { - rdpsnd->fixedRate = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return CHANNEL_RC_INITIALIZATION_ERROR; + + rdpsnd->fixedRate = val; } CommandLineSwitchCase(arg, "channel") { - rdpsnd->fixedChannel = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT16_MAX)) + return CHANNEL_RC_INITIALIZATION_ERROR; + + rdpsnd->fixedChannel = val; } CommandLineSwitchCase(arg, "latency") { - rdpsnd->latency = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > INT32_MAX)) + return CHANNEL_RC_INITIALIZATION_ERROR; + + rdpsnd->latency = val; } CommandLineSwitchCase(arg, "quality") { - int wQualityMode = DYNAMIC_QUALITY; + long wQualityMode = DYNAMIC_QUALITY; if (_stricmp(arg->Value, "dynamic") == 0) wQualityMode = DYNAMIC_QUALITY; @@ -915,7 +937,12 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args) else if (_stricmp(arg->Value, "high") == 0) wQualityMode = HIGH_QUALITY; else - wQualityMode = atoi(arg->Value); + { + wQualityMode = strtol(arg->Value, NULL, 0); + + if (errno != 0) + return CHANNEL_RC_INITIALIZATION_ERROR; + } if ((wQualityMode < 0) || (wQualityMode > 2)) wQualityMode = DYNAMIC_QUALITY; @@ -1088,7 +1115,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd) } rdpsnd->ScheduleThread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread, + rdpsnd_schedule_thread, (void*) rdpsnd, 0, NULL); if (!rdpsnd->ScheduleThread) @@ -1244,7 +1271,7 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_open_event_ex(LPVOID lpUserParam, D "rdpsnd_virtual_channel_open_event_ex reported an error"); } -static void* rdpsnd_virtual_channel_client_thread(void* arg) +static DWORD WINAPI rdpsnd_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; @@ -1295,8 +1322,8 @@ out: "rdpsnd_virtual_channel_client_thread reported an error"); rdpsnd_process_disconnect(rdpsnd); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -1328,7 +1355,7 @@ static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* rdpsnd, } rdpsnd->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) rdpsnd, + rdpsnd_virtual_channel_client_thread, (void*) rdpsnd, 0, NULL); if (!rdpsnd->thread) diff --git a/channels/rdpsnd/server/rdpsnd_main.c b/channels/rdpsnd/server/rdpsnd_main.c index 844a485..b144e53 100644 --- a/channels/rdpsnd/server/rdpsnd_main.c +++ b/channels/rdpsnd/server/rdpsnd_main.c @@ -42,7 +42,7 @@ */ UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s) { - int pos; + size_t pos; UINT16 i; BOOL status; ULONG written; @@ -239,7 +239,7 @@ out_free: return error; } -static void* rdpsnd_server_thread(void* arg) +static DWORD WINAPI rdpsnd_server_thread(LPVOID arg) { DWORD nCount, status; HANDLE events[8]; @@ -293,8 +293,8 @@ out: setChannelError(context->rdpcontext, error, "rdpsnd_server_thread reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -574,10 +574,11 @@ out: static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right) { - int pos; + size_t pos; BOOL status; ULONG written; wStream* s = context->priv->rdpsnd_pdu; + Stream_Write_UINT8(s, SNDC_SETVOLUME); Stream_Write_UINT8(s, 0); Stream_Seek_UINT16(s); @@ -600,7 +601,7 @@ static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, int left, */ static UINT rdpsnd_server_close(RdpsndServerContext* context) { - int pos; + size_t pos; BOOL status; ULONG written; wStream* s = context->priv->rdpsnd_pdu; @@ -700,7 +701,7 @@ static UINT rdpsnd_server_start(RdpsndServerContext* context) } context->priv->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL); + rdpsnd_server_thread, (void*) context, 0, NULL); if (!context->priv->Thread) { diff --git a/channels/remdesk/client/remdesk_main.c b/channels/remdesk/client/remdesk_main.c index ec3948c..d40c520 100644 --- a/channels/remdesk/client/remdesk_main.c +++ b/channels/remdesk/client/remdesk_main.c @@ -804,7 +804,7 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event_ex(LPVOID lpUserParam, "remdesk_virtual_channel_open_event_ex reported an error"); } -static void* remdesk_virtual_channel_client_thread(void* arg) +static DWORD WINAPI remdesk_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; @@ -847,8 +847,8 @@ static void* remdesk_virtual_channel_client_thread(void* arg) setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_client_thread reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -882,7 +882,7 @@ static UINT remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk, } remdesk->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk, + remdesk_virtual_channel_client_thread, (void*) remdesk, 0, NULL); if (!remdesk->thread) @@ -942,6 +942,7 @@ static UINT remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk) static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk) { remdesk->InitHandle = 0; + free(remdesk->context); free(remdesk); } diff --git a/channels/remdesk/server/remdesk_main.c b/channels/remdesk/server/remdesk_main.c index 3e226b8..16e7453 100644 --- a/channels/remdesk/server/remdesk_main.c +++ b/channels/remdesk/server/remdesk_main.c @@ -578,7 +578,7 @@ static UINT remdesk_server_receive_pdu(RemdeskServerContext* context, return error; } -static void* remdesk_server_thread(void* arg) +static DWORD WINAPI remdesk_server_thread(LPVOID arg) { wStream* s; DWORD status; @@ -700,8 +700,8 @@ out: setChannelError(context->rdpcontext, error, "remdesk_server_thread reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -727,7 +727,7 @@ static UINT remdesk_server_start(RemdeskServerContext* context) } if (!(context->priv->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) remdesk_server_thread, (void*) context, 0, NULL))) + remdesk_server_thread, (void*) context, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(context->priv->StopEvent); diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index cfbfe15..28853c1 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -124,20 +124,27 @@ static UINT32 _GetLastErrorToIoStatus(SERIAL_DEVICE* serial) return STATUS_UNSUCCESSFUL; } -static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) +static UINT serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) { DWORD DesiredAccess; DWORD SharedAccess; DWORD CreateDisposition; UINT32 PathLength; + + if (Stream_GetRemainingLength(irp->input) < 32) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, DesiredAccess); /* DesiredAccess (4 bytes) */ Stream_Seek_UINT64(irp->input); /* AllocationSize (8 bytes) */ Stream_Seek_UINT32(irp->input); /* FileAttributes (4 bytes) */ Stream_Read_UINT32(irp->input, SharedAccess); /* SharedAccess (4 bytes) */ - Stream_Read_UINT32(irp->input, - CreateDisposition); /* CreateDisposition (4 bytes) */ + Stream_Read_UINT32(irp->input, CreateDisposition); /* CreateDisposition (4 bytes) */ Stream_Seek_UINT32(irp->input); /* CreateOptions (4 bytes) */ Stream_Read_UINT32(irp->input, PathLength); /* PathLength (4 bytes) */ + + if (Stream_GetRemainingLength(irp->input) < PathLength) + return ERROR_INVALID_DATA; + Stream_Seek(irp->input, PathLength); /* Path (variable) */ assert(PathLength == 0); /* MS-RDPESP 2.2.2.2 */ #ifndef _WIN32 @@ -191,18 +198,21 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) /* dcb.fBinary = TRUE; */ /* SetCommState(serial->hComm, &dcb); */ assert(irp->FileId == 0); - irp->FileId = - irp->devman->id_sequence++; /* FIXME: why not ((WINPR_COMM*)hComm)->fd? */ + irp->FileId = irp->devman->id_sequence++; /* FIXME: why not ((WINPR_COMM*)hComm)->fd? */ irp->IoStatus = STATUS_SUCCESS; WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %"PRIu32", FileId: %"PRIu32") created.", serial->device.name, irp->device->id, irp->FileId); error_handle: Stream_Write_UINT32(irp->output, irp->FileId); /* FileId (4 bytes) */ Stream_Write_UINT8(irp->output, 0); /* Information (1 byte) */ + return CHANNEL_RC_OK; } -static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp) +static UINT serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp) { + if (Stream_GetRemainingLength(irp->input) < 32) + return ERROR_INVALID_DATA; + Stream_Seek(irp->input, 32); /* Padding (32 bytes) */ if (!CloseHandle(serial->hComm)) @@ -219,6 +229,7 @@ static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp) irp->IoStatus = STATUS_SUCCESS; error_handle: Stream_Zero(irp->output, 5); /* Padding (5 bytes) */ + return CHANNEL_RC_OK; } /** @@ -232,6 +243,10 @@ static UINT serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) UINT64 Offset; BYTE* buffer = NULL; DWORD nbRead = 0; + + if (Stream_GetRemainingLength(irp->input) < 32) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */ Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */ Stream_Seek(irp->input, 20); /* Padding (20 bytes) */ @@ -283,11 +298,15 @@ error_handle: return CHANNEL_RC_OK; } -static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp) +static UINT serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp) { UINT32 Length; UINT64 Offset; DWORD nbWritten = 0; + + if (Stream_GetRemainingLength(irp->input) < 32) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */ Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */ Stream_Seek(irp->input, 20); /* Padding (20 bytes) */ @@ -318,6 +337,7 @@ static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp) serial->device.name); Stream_Write_UINT32(irp->output, nbWritten); /* Length (4 bytes) */ Stream_Write_UINT8(irp->output, 0); /* Padding (1 byte) */ + return CHANNEL_RC_OK; } @@ -334,12 +354,18 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp) UINT32 OutputBufferLength; BYTE* OutputBuffer = NULL; DWORD BytesReturned = 0; - Stream_Read_UINT32(irp->input, - OutputBufferLength); /* OutputBufferLength (4 bytes) */ - Stream_Read_UINT32(irp->input, - InputBufferLength); /* InputBufferLength (4 bytes) */ + + if (Stream_GetRemainingLength(irp->input) < 32) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(irp->input, OutputBufferLength); /* OutputBufferLength (4 bytes) */ + Stream_Read_UINT32(irp->input, InputBufferLength); /* InputBufferLength (4 bytes) */ Stream_Read_UINT32(irp->input, IoControlCode); /* IoControlCode (4 bytes) */ Stream_Seek(irp->input, 20); /* Padding (20 bytes) */ + + if (Stream_GetRemainingLength(irp->input) < InputBufferLength) + return ERROR_INVALID_DATA; + OutputBuffer = (BYTE*)calloc(OutputBufferLength, sizeof(BYTE)); if (OutputBuffer == NULL) @@ -381,8 +407,7 @@ error_handle: * BytesReturned == OutputBufferLength when * CommDeviceIoControl returns FALSE */ assert(OutputBufferLength == BytesReturned); - Stream_Write_UINT32(irp->output, - BytesReturned); /* OutputBufferLength (4 bytes) */ + Stream_Write_UINT32(irp->output, BytesReturned); /* OutputBufferLength (4 bytes) */ if (BytesReturned > 0) { @@ -425,11 +450,11 @@ static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp) switch (irp->MajorFunction) { case IRP_MJ_CREATE: - serial_process_irp_create(serial, irp); + error = serial_process_irp_create(serial, irp); break; case IRP_MJ_CLOSE: - serial_process_irp_close(serial, irp); + error = serial_process_irp_close(serial, irp); break; case IRP_MJ_READ: @@ -439,7 +464,7 @@ static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp) break; case IRP_MJ_WRITE: - serial_process_irp_write(serial, irp); + error = serial_process_irp_write(serial, irp); break; case IRP_MJ_DEVICE_CONTROL: @@ -458,7 +483,7 @@ static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp) } -static void* irp_thread_func(void* arg) +static DWORD WINAPI irp_thread_func(LPVOID arg) { IRP_THREAD_DATA* data = (IRP_THREAD_DATA*)arg; UINT error; @@ -484,8 +509,8 @@ error_out: * the CompletionId whereas the thread is not yet * terminated */ free(data); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } @@ -617,7 +642,7 @@ static void create_irp_thread(SERIAL_DEVICE* serial, IRP* irp) /* data freed by irp_thread_func */ irpThread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE)irp_thread_func, + irp_thread_func, (void*)data, 0, NULL); @@ -672,7 +697,7 @@ static void terminate_pending_irp_threads(SERIAL_DEVICE* serial) } -static void* serial_thread_func(void* arg) +static DWORD WINAPI serial_thread_func(LPVOID arg) { IRP* irp; wMessage message; @@ -711,8 +736,8 @@ static void* serial_thread_func(void* arg) setChannelError(serial->rdpcontext, error, "serial_thread_func reported an error"); - ExitThread((DWORD) error); - return NULL; + ExitThread(error); + return error; } @@ -815,7 +840,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) if ((name && name[0]) && (path && path[0])) { wLog* log; - WLog_Init(); log = WLog_Get("com.freerdp.channel.serial.client"); WLog_Print(log, WLOG_DEBUG, "initializing"); #ifndef __linux__ /* to be removed */ @@ -827,7 +851,8 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) if (!DefineCommDevice(name /* eg: COM1 */, path /* eg: /dev/ttyS0 */)) { - WLog_ERR(TAG, "DefineCommDevice failed!"); + DWORD status = GetLastError(); + WLog_ERR(TAG, "DefineCommDevice failed with %08"PRIx32, status); return ERROR_INTERNAL_ERROR; } @@ -927,7 +952,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) if (!(serial->MainThread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) serial_thread_func, + serial_thread_func, (void*) serial, 0, NULL))) diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c index 0945206..7046a70 100644 --- a/channels/smartcard/client/smartcard_main.c +++ b/channels/smartcard/client/smartcard_main.c @@ -34,8 +34,9 @@ #include "smartcard_main.h" -void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext) +static DWORD WINAPI smartcard_context_thread(LPVOID arg) { + SMARTCARD_CONTEXT* pContext = (SMARTCARD_CONTEXT*)arg; DWORD nCount; LONG status = 0; DWORD waitStatus; @@ -107,8 +108,8 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext) setChannelError(smartcard->rdpcontext, error, "smartcard_context_thread reported an error"); - ExitThread((DWORD)status); - return NULL; + ExitThread(status); + return error; } SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, @@ -134,7 +135,7 @@ SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, } pContext->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) smartcard_context_thread, + smartcard_context_thread, pContext, 0, NULL); if (!pContext->thread) @@ -385,17 +386,17 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) asyncIrp = TRUE; - /** - * The following matches mstsc's behavior of processing - * only certain requests asynchronously while processing - * those expected to return fast synchronously. - */ - switch (operation->ioControlCode) { case SCARD_IOCTL_ESTABLISHCONTEXT: case SCARD_IOCTL_RELEASECONTEXT: case SCARD_IOCTL_ISVALIDCONTEXT: + case SCARD_IOCTL_CANCEL: + case SCARD_IOCTL_ACCESSSTARTEDEVENT: + case SCARD_IOCTL_RELEASESTARTEDEVENT: + asyncIrp = FALSE; + break; + case SCARD_IOCTL_LISTREADERGROUPSA: case SCARD_IOCTL_LISTREADERGROUPSW: case SCARD_IOCTL_LISTREADERSA: @@ -416,21 +417,14 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) case SCARD_IOCTL_LOCATECARDSW: case SCARD_IOCTL_LOCATECARDSBYATRA: case SCARD_IOCTL_LOCATECARDSBYATRW: - case SCARD_IOCTL_CANCEL: case SCARD_IOCTL_READCACHEA: case SCARD_IOCTL_READCACHEW: case SCARD_IOCTL_WRITECACHEA: case SCARD_IOCTL_WRITECACHEW: case SCARD_IOCTL_GETREADERICON: case SCARD_IOCTL_GETDEVICETYPEID: - asyncIrp = FALSE; - break; - case SCARD_IOCTL_GETSTATUSCHANGEA: case SCARD_IOCTL_GETSTATUSCHANGEW: - asyncIrp = TRUE; - break; - case SCARD_IOCTL_CONNECTA: case SCARD_IOCTL_CONNECTW: case SCARD_IOCTL_RECONNECT: @@ -447,11 +441,6 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) case SCARD_IOCTL_GETTRANSMITCOUNT: asyncIrp = TRUE; break; - - case SCARD_IOCTL_ACCESSSTARTEDEVENT: - case SCARD_IOCTL_RELEASESTARTEDEVENT: - asyncIrp = FALSE; - break; } pContext = ListDictionary_GetItemValue(smartcard->rgSCardContextList, @@ -506,7 +495,7 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) return CHANNEL_RC_OK; } -static void* smartcard_thread_func(void* arg) +static DWORD WINAPI smartcard_thread_func(LPVOID arg) { IRP* irp; DWORD nCount; @@ -657,8 +646,8 @@ out: setChannelError(smartcard->rdpcontext, error, "smartcard_thread_func reported an error"); - ExitThread((DWORD)error); - return NULL; + ExitThread(error); + return error; } /** @@ -689,17 +678,9 @@ static UINT smartcard_irp_request(DEVICE* device, IRP* irp) */ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) { - char* name; - char* path; size_t length; - int ck; - RDPDR_SMARTCARD* device; SMARTCARD_DEVICE* smartcard; - LONG status; UINT error = CHANNEL_RC_NO_MEMORY; - device = (RDPDR_SMARTCARD*) pEntryPoints->device; - name = device->Name; - path = device->Path; smartcard = (SMARTCARD_DEVICE*) calloc(1, sizeof(SMARTCARD_DEVICE)); if (!smartcard) @@ -724,30 +705,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) } Stream_Write(smartcard->device.data, "SCARD", 6); - smartcard->name = NULL; - smartcard->path = NULL; - - if (path) - { - smartcard->path = path; - smartcard->name = name; - } - else if (name) - { - if (1 == sscanf(name, "%d", &ck)) - smartcard->path = name; - else - smartcard->name = name; - } - - status = SCardAddReaderName(&smartcard->thread, (LPSTR) name); - - if (status != SCARD_S_SUCCESS) - { - WLog_ERR(TAG, "Failed to add reader name!"); - goto error_device_data; - } - smartcard->IrpQueue = MessageQueue_New(NULL); if (!smartcard->IrpQueue) @@ -790,7 +747,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) } smartcard->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) smartcard_thread_func, + smartcard_thread_func, smartcard, CREATE_SUSPENDED, NULL); if (!smartcard->thread) diff --git a/channels/smartcard/client/smartcard_main.h b/channels/smartcard/client/smartcard_main.h index 10cdb50..8451234 100644 --- a/channels/smartcard/client/smartcard_main.h +++ b/channels/smartcard/client/smartcard_main.h @@ -110,9 +110,6 @@ struct _SMARTCARD_DEVICE { DEVICE device; - char* name; - char* path; - HANDLE thread; HANDLE StartedEvent; wMessageQueue* IrpQueue; diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index a34cc0b..80dd4d0 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -581,28 +581,23 @@ static LONG smartcard_GetStatusChangeA_Decode(SMARTCARD_DEVICE* smartcard, static LONG smartcard_GetStatusChangeA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - LONG status; UINT32 index; GetStatusChange_Return ret; LPSCARD_READERSTATEA rgReaderState = NULL; IRP* irp = operation->irp; GetStatusChangeA_Call* call = operation->call; - status = ret.ReturnCode = SCardGetStatusChangeA(operation->hContext, - call->dwTimeOut, call->rgReaderStates, call->cReaders); - - if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED)) - { - call->cReaders = 0; - } - + ret.ReturnCode = SCardGetStatusChangeA(operation->hContext, call->dwTimeOut, call->rgReaderStates, + call->cReaders); ret.cReaders = call->cReaders; ret.rgReaderStates = NULL; if (ret.cReaders > 0) + { ret.rgReaderStates = (ReaderState_Return*) calloc(ret.cReaders, sizeof(ReaderState_Return)); - if (!ret.rgReaderStates) - return STATUS_NO_MEMORY; + if (!ret.rgReaderStates) + return STATUS_NO_MEMORY; + } for (index = 0; index < ret.cReaders; index++) { @@ -613,12 +608,7 @@ static LONG smartcard_GetStatusChangeA_Call(SMARTCARD_DEVICE* smartcard, } smartcard_trace_get_status_change_return(smartcard, &ret, FALSE); - - if ((status = smartcard_pack_get_status_change_return(smartcard, irp->output, &ret))) - { - WLog_ERR(TAG, "smartcard_pack_get_status_change_return failed with error %"PRId32"", status); - return status; - } + smartcard_pack_get_status_change_return(smartcard, irp->output, &ret); if (call->rgReaderStates) { @@ -657,28 +647,23 @@ static LONG smartcard_GetStatusChangeW_Decode(SMARTCARD_DEVICE* smartcard, static LONG smartcard_GetStatusChangeW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - LONG status; UINT32 index; GetStatusChange_Return ret; LPSCARD_READERSTATEW rgReaderState = NULL; IRP* irp = operation->irp; GetStatusChangeW_Call* call = operation->call; - status = ret.ReturnCode = SCardGetStatusChangeW(operation->hContext, call->dwTimeOut, - call->rgReaderStates, call->cReaders); - - if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED)) - { - call->cReaders = 0; - } - + ret.ReturnCode = SCardGetStatusChangeW(operation->hContext, call->dwTimeOut, + call->rgReaderStates, call->cReaders); ret.cReaders = call->cReaders; ret.rgReaderStates = NULL; if (ret.cReaders > 0) + { ret.rgReaderStates = (ReaderState_Return*) calloc(ret.cReaders, sizeof(ReaderState_Return)); - if (!ret.rgReaderStates) - return STATUS_NO_MEMORY; + if (!ret.rgReaderStates) + return STATUS_NO_MEMORY; + } for (index = 0; index < ret.cReaders; index++) { @@ -689,12 +674,7 @@ static LONG smartcard_GetStatusChangeW_Call(SMARTCARD_DEVICE* smartcard, } smartcard_trace_get_status_change_return(smartcard, &ret, TRUE); - - if ((status = smartcard_pack_get_status_change_return(smartcard, irp->output, &ret))) - { - WLog_ERR(TAG, "smartcard_pack_get_status_change_return failed with error %"PRId32"", status); - return status; - } + smartcard_pack_get_status_change_return(smartcard, irp->output, &ret); if (call->rgReaderStates) { @@ -787,17 +767,19 @@ static LONG smartcard_ConnectA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA if (status) { WLog_ERR(TAG, "SCardConnectA failed with error %"PRId32"", status); - return status; + goto out_fail; } if ((status = smartcard_pack_connect_return(smartcard, irp->output, &ret))) { WLog_ERR(TAG, "smartcard_pack_connect_return failed with error %"PRId32"", status); - return status; + goto out_fail; } + status = ret.ReturnCode; +out_fail: free(call->szReader); - return ret.ReturnCode; + return status; } static LONG smartcard_ConnectW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) @@ -843,17 +825,19 @@ static LONG smartcard_ConnectW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA if (status) { WLog_ERR(TAG, "SCardConnectW failed with error %"PRId32"", status); - return status; + goto out_fail; } if ((status = smartcard_pack_connect_return(smartcard, irp->output, &ret))) { WLog_ERR(TAG, "smartcard_pack_connect_return failed with error %"PRId32"", status); - return status; + goto out_fail; } + status = ret.ReturnCode; +out_fail: free(call->szReader); - return ret.ReturnCode; + return status; } static LONG smartcard_Reconnect_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) @@ -881,8 +865,8 @@ static LONG smartcard_Reconnect_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER Reconnect_Return ret; IRP* irp = operation->irp; Reconnect_Call* call = operation->call; - status = ret.ReturnCode = SCardReconnect(operation->hCard, call->dwShareMode, - call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol); + ret.ReturnCode = SCardReconnect(operation->hCard, call->dwShareMode, + call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol); smartcard_trace_reconnect_return(smartcard, &ret); if ((status = smartcard_pack_reconnect_return(smartcard, irp->output, &ret))) @@ -1064,23 +1048,34 @@ static LONG smartcard_StatusA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT LONG status; Status_Return ret = { 0 }; DWORD cchReaderLen = 0; + DWORD cbAtrLen = 0; LPSTR mszReaderNames = NULL; IRP* irp = operation->irp; Status_Call* call = operation->call; - - if (call->cbAtrLen > 32) - call->cbAtrLen = 32; - - ret.cbAtrLen = call->cbAtrLen; ZeroMemory(ret.pbAtr, 32); - cchReaderLen = SCARD_AUTOALLOCATE; - status = ret.ReturnCode = SCardStatusA(operation->hCard, (LPSTR) &mszReaderNames, &cchReaderLen, - &ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &ret.cbAtrLen); + + call->cbAtrLen = 32; + cbAtrLen = call->cbAtrLen; + + if (call->fmszReaderNamesIsNULL) + cchReaderLen = 0; + else + cchReaderLen = SCARD_AUTOALLOCATE; + + status = ret.ReturnCode = SCardStatusA(operation->hCard, + call->fmszReaderNamesIsNULL ? NULL : (LPSTR) &mszReaderNames, + &cchReaderLen, &ret.dwState, &ret.dwProtocol, + cbAtrLen ? (BYTE*) &ret.pbAtr : NULL, &cbAtrLen); if (status == SCARD_S_SUCCESS) { - ret.mszReaderNames = (BYTE*) mszReaderNames; + if (!call->fmszReaderNamesIsNULL) + ret.mszReaderNames = (BYTE*) mszReaderNames; + ret.cBytes = cchReaderLen; + + if (call->cbAtrLen) + ret.cbAtrLen = cbAtrLen; } smartcard_trace_status_return(smartcard, &ret, FALSE); @@ -1092,7 +1087,9 @@ static LONG smartcard_StatusA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT } if (mszReaderNames) + { SCardFreeMemory(operation->hContext, mszReaderNames); + } return ret.ReturnCode; } @@ -1124,17 +1121,33 @@ static LONG smartcard_StatusW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT LPWSTR mszReaderNames = NULL; IRP* irp = operation->irp; Status_Call* call = operation->call; + DWORD cbAtrLen; if (call->cbAtrLen > 32) call->cbAtrLen = 32; - ret.cbAtrLen = call->cbAtrLen; + if (call->fmszReaderNamesIsNULL) + cchReaderLen = 0; + else + cchReaderLen = SCARD_AUTOALLOCATE; + + cbAtrLen = call->cbAtrLen; ZeroMemory(ret.pbAtr, 32); - cchReaderLen = SCARD_AUTOALLOCATE; - status = ret.ReturnCode = SCardStatusW(operation->hCard, (LPWSTR) &mszReaderNames, &cchReaderLen, - &ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &ret.cbAtrLen); - ret.mszReaderNames = (BYTE*) mszReaderNames; - ret.cBytes = cchReaderLen * 2; + status = ret.ReturnCode = SCardStatusW(operation->hCard, + call->fmszReaderNamesIsNULL ? NULL : (LPWSTR) &mszReaderNames, + &cchReaderLen, &ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &cbAtrLen); + + if (status == SCARD_S_SUCCESS) + { + if (!call->fmszReaderNamesIsNULL) + ret.mszReaderNames = (BYTE*) mszReaderNames; + + ret.cBytes = cchReaderLen; + + if (call->cbAtrLen) + ret.cbAtrLen = cbAtrLen; + } + smartcard_trace_status_return(smartcard, &ret, TRUE); if ((status = smartcard_pack_status_return(smartcard, irp->output, &ret))) @@ -1190,8 +1203,8 @@ static LONG smartcard_Transmit_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA } ret.pioRecvPci = call->pioRecvPci; - status = ret.ReturnCode = SCardTransmit(operation->hCard, call->pioSendPci, call->pbSendBuffer, - call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength)); + ret.ReturnCode = SCardTransmit(operation->hCard, call->pioSendPci, call->pbSendBuffer, + call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength)); smartcard_trace_transmit_return(smartcard, &ret); if ((status = smartcard_pack_transmit_return(smartcard, irp->output, &ret))) @@ -1238,9 +1251,9 @@ static LONG smartcard_Control_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT if (!ret.pvOutBuffer) return SCARD_E_NO_MEMORY; - status = ret.ReturnCode = SCardControl(operation->hCard, - call->dwControlCode, call->pvInBuffer, call->cbInBufferSize, - ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize); + ret.ReturnCode = SCardControl(operation->hCard, + call->dwControlCode, call->pvInBuffer, call->cbInBufferSize, + ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize); smartcard_trace_control_return(smartcard, &ret); if ((status = smartcard_pack_control_return(smartcard, irp->output, &ret))) @@ -1297,8 +1310,8 @@ static LONG smartcard_GetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER } cbAttrLen = call->cbAttrLen; - status = ret.ReturnCode = SCardGetAttrib(operation->hCard, call->dwAttrId, - autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr, &cbAttrLen); + ret.ReturnCode = SCardGetAttrib(operation->hCard, call->dwAttrId, + autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr, &cbAttrLen); ret.cbAttrLen = cbAttrLen; smartcard_trace_get_attrib_return(smartcard, &ret, call->dwAttrId); @@ -1379,7 +1392,6 @@ static LONG smartcard_LocateCardsByATRA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - BOOL equal; DWORD i, j, k; GetStatusChange_Return ret; LPSCARD_READERSTATEA state = NULL; @@ -1412,21 +1424,15 @@ static LONG smartcard_LocateCardsByATRA_Call(SMARTCARD_DEVICE* smartcard, { for (j = 0; j < call->cReaders; j++) { - equal = TRUE; - for (k = 0; k < call->rgAtrMasks[i].cbAtr; k++) { if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) != (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k])) { - equal = FALSE; break; } - if (equal) - { - states[j].dwEventState |= SCARD_STATE_ATRMATCH; - } + states[j].dwEventState |= SCARD_STATE_ATRMATCH; } } } @@ -2022,13 +2028,12 @@ LONG smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP SCardGetErrorString(result), result); } - irp->IoStatus = 0; + irp->IoStatus = STATUS_SUCCESS; if ((result & 0xC0000000) == 0xC0000000) { /* NTSTATUS error */ irp->IoStatus = (UINT32)result; - Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH); WLog_WARN(TAG, "IRP failure: %s (0x%08"PRIX32"), ntstatus: 0x%08"PRIX32"", smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result); } @@ -2039,21 +2044,9 @@ LONG smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH); /* Device Control Response */ Stream_Write_UINT32(irp->output, outputBufferLength); /* OutputBufferLength (4 bytes) */ - - if ((result = smartcard_pack_common_type_header(smartcard, - irp->output))) /* CommonTypeHeader (8 bytes) */ - { - WLog_ERR(TAG, "smartcard_pack_common_type_header failed with error %"PRId32"", result); - return result; - } - - if ((result = smartcard_pack_private_type_header(smartcard, irp->output, - objectBufferLength))) /* PrivateTypeHeader (8 bytes) */ - { - WLog_ERR(TAG, "smartcard_pack_private_type_header failed with error %"PRId32"", result); - return result; - } - + smartcard_pack_common_type_header(smartcard, irp->output); /* CommonTypeHeader (8 bytes) */ + smartcard_pack_private_type_header(smartcard, irp->output, + objectBufferLength); /* PrivateTypeHeader (8 bytes) */ Stream_Write_UINT32(irp->output, result); /* Result (4 bytes) */ Stream_SetPosition(irp->output, Stream_Length(irp->output)); return SCARD_S_SUCCESS; diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c index 1f89d54..b2f3563 100644 --- a/channels/smartcard/client/smartcard_pack.c +++ b/channels/smartcard/client/smartcard_pack.c @@ -75,13 +75,12 @@ LONG smartcard_unpack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s return SCARD_S_SUCCESS; } -LONG smartcard_pack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s) +void smartcard_pack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s) { Stream_Write_UINT8(s, 1); /* Version (1 byte) */ Stream_Write_UINT8(s, 0x10); /* Endianness (1 byte) */ Stream_Write_UINT16(s, 8); /* CommonHeaderLength (2 bytes) */ Stream_Write_UINT32(s, 0xCCCCCCCC); /* Filler (4 bytes), should be 0xCCCCCCCC */ - return SCARD_S_SUCCESS; } LONG smartcard_unpack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s) @@ -116,12 +115,11 @@ LONG smartcard_unpack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* return SCARD_S_SUCCESS; } -LONG smartcard_pack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s, +void smartcard_pack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s, UINT32 objectBufferLength) { Stream_Write_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */ Stream_Write_UINT32(s, 0x00000000); /* Filler (4 bytes), should be 0x00000000 */ - return SCARD_S_SUCCESS; } LONG smartcard_unpack_read_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, UINT32 size, @@ -850,7 +848,7 @@ void smartcard_trace_list_readers_return(SMARTCARD_DEVICE* smartcard, ListReader CopyMemory(mszA, ret->msz, ret->cBytes); } - for (index = 0; index < length - 2; index++) + for (index = 0; index < length - 1; index++) { if (mszA[index] == '\0') mszA[index] = ','; @@ -1863,32 +1861,34 @@ void smartcard_trace_status_return(SMARTCARD_DEVICE* smartcard, Status_Return* r if (!WLog_IsLevelActive(WLog_Get(TAG), WLOG_DEBUG)) return; - if (unicode) + if (ret->mszReaderNames) { - length = ret->cBytes / 2; - - if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->mszReaderNames, (int)length, - &mszReaderNamesA, 0, NULL, NULL) < 1) + if (unicode) { - WLog_ERR(TAG, "ConvertFromUnicode failed"); - return; + length = ret->cBytes / 2; + + if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->mszReaderNames, (int) length, + &mszReaderNamesA, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "ConvertFromUnicode failed"); + return; + } + } + else + { + length = (int) ret->cBytes; + mszReaderNamesA = (char*) malloc(length); + + if (!mszReaderNamesA) + { + WLog_ERR(TAG, "malloc failed!"); + return; + } + + CopyMemory(mszReaderNamesA, ret->mszReaderNames, ret->cBytes); } } else - { - length = (int) ret->cBytes; - mszReaderNamesA = (char*) malloc(length); - - if (!mszReaderNamesA) - { - WLog_ERR(TAG, "malloc failed!"); - return; - } - - CopyMemory(mszReaderNamesA, ret->mszReaderNames, ret->cBytes); - } - - if (!mszReaderNamesA) length = 0; if (length > 2) @@ -2761,7 +2761,7 @@ LONG smartcard_unpack_locate_cards_by_atr_a_call(SMARTCARD_DEVICE* smartcard, wS return STATUS_BUFFER_TOO_SMALL; } - call->rgAtrMasks = (LocateCards_ATRMask*)calloc(call->cAtrs, sizeof(SCARD_ATRMASK)); + call->rgAtrMasks = (LocateCards_ATRMask*)calloc(call->cAtrs, sizeof(LocateCards_ATRMask)); if (!call->rgAtrMasks) { @@ -2789,7 +2789,7 @@ LONG smartcard_unpack_locate_cards_by_atr_a_call(SMARTCARD_DEVICE* smartcard, wS if (call->cReaders > 0) { - call->rgReaderStates = (ReaderStateA*)calloc(call->cReaders, sizeof(SCARD_READERSTATEA)); + call->rgReaderStates = (ReaderStateA*)calloc(call->cReaders, sizeof(ReaderStateA)); if (!call->rgReaderStates) { diff --git a/channels/smartcard/client/smartcard_pack.h b/channels/smartcard/client/smartcard_pack.h index 19c0954..f7bc083 100644 --- a/channels/smartcard/client/smartcard_pack.h +++ b/channels/smartcard/client/smartcard_pack.h @@ -452,10 +452,10 @@ void smartcard_scard_handle_native_to_redir(SMARTCARD_DEVICE* smartcard, REDIR_S SCARDHANDLE hCard); LONG smartcard_unpack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s); -LONG smartcard_pack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s); +void smartcard_pack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s); LONG smartcard_unpack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s); -LONG smartcard_pack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s, +void smartcard_pack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s, UINT32 objectBufferLength); LONG smartcard_unpack_redir_scard_context(SMARTCARD_DEVICE* smartcard, wStream* s, diff --git a/channels/sshagent/CMakeLists.txt b/channels/sshagent/CMakeLists.txt new file mode 100644 index 0000000..f3fa34e --- /dev/null +++ b/channels/sshagent/CMakeLists.txt @@ -0,0 +1,27 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# Copyright 2017 Ben Cohen +# +# 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. + +define_channel("sshagent") + +if(WITH_CLIENT_CHANNELS) + add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME}) +endif() + +if(WITH_SERVER_CHANNELS) + add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME}) +endif() diff --git a/channels/sshagent/ChannelOptions.cmake b/channels/sshagent/ChannelOptions.cmake new file mode 100644 index 0000000..083d8d5 --- /dev/null +++ b/channels/sshagent/ChannelOptions.cmake @@ -0,0 +1,13 @@ + +set(OPTION_DEFAULT OFF) +set(OPTION_CLIENT_DEFAULT OFF) +set(OPTION_SERVER_DEFAULT OFF) + +define_channel_options(NAME "sshagent" TYPE "dynamic" + DESCRIPTION "SSH Agent Forwarding Extension" + SPECIFICATIONS "" + DEFAULT ${OPTION_DEFAULT}) + +define_channel_client_options(${OPTION_CLIENT_DEFAULT}) +define_channel_server_options(${OPTION_SERVER_DEFAULT}) + diff --git a/channels/sshagent/client/CMakeLists.txt b/channels/sshagent/client/CMakeLists.txt new file mode 100644 index 0000000..7feea96 --- /dev/null +++ b/channels/sshagent/client/CMakeLists.txt @@ -0,0 +1,34 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# Copyright 2017 Ben Cohen +# +# 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. + +define_channel_client("sshagent") + +set(${MODULE_PREFIX}_SRCS + sshagent_main.c + sshagent_main.h) + +include_directories(..) + +add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry") + +if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_LIBS) + install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols) +endif() + +target_link_libraries(${MODULE_NAME} winpr) +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client") diff --git a/channels/sshagent/client/sshagent_main.c b/channels/sshagent/client/sshagent_main.c new file mode 100644 index 0000000..39d81aa --- /dev/null +++ b/channels/sshagent/client/sshagent_main.c @@ -0,0 +1,408 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * SSH Agent Virtual Channel Extension + * + * Copyright 2013 Christian Hofstaedtler + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2017 Ben Cohen + * + * 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. + */ + +/* + * sshagent_main.c: DVC plugin to forward queries from RDP to the ssh-agent + * + * This relays data to and from an ssh-agent program equivalent running on the + * RDP server to an ssh-agent running locally. Unlike the normal ssh-agent, + * which sends data over an SSH channel, the data is send over an RDP dynamic + * virtual channel. + * + * protocol specification: + * Forward data verbatim over RDP dynamic virtual channel named "sshagent" + * between a ssh client on the xrdp server and the real ssh-agent where + * the RDP client is running. Each connection by a separate client to + * xrdp-ssh-agent gets a separate DVC invocation. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "sshagent_main.h" +#include + +#define TAG CHANNELS_TAG("sshagent.client") + +typedef struct _SSHAGENT_LISTENER_CALLBACK SSHAGENT_LISTENER_CALLBACK; +struct _SSHAGENT_LISTENER_CALLBACK +{ + IWTSListenerCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + + rdpContext* rdpcontext; + const char* agent_uds_path; +}; + +typedef struct _SSHAGENT_CHANNEL_CALLBACK SSHAGENT_CHANNEL_CALLBACK; +struct _SSHAGENT_CHANNEL_CALLBACK +{ + IWTSVirtualChannelCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + IWTSVirtualChannel* channel; + + rdpContext* rdpcontext; + int agent_fd; + HANDLE thread; + CRITICAL_SECTION lock; +}; + +typedef struct _SSHAGENT_PLUGIN SSHAGENT_PLUGIN; +struct _SSHAGENT_PLUGIN +{ + IWTSPlugin iface; + + SSHAGENT_LISTENER_CALLBACK* listener_callback; + + rdpContext* rdpcontext; +}; + + +/** + * Function to open the connection to the sshagent + * + * @return The fd on success, otherwise -1 + */ +static int connect_to_sshagent(const char* udspath) +{ + int agent_fd = socket(AF_UNIX, SOCK_STREAM, 0); + + if (agent_fd == -1) + { + WLog_ERR(TAG, "Can't open Unix domain socket!"); + return -1; + } + + struct sockaddr_un addr; + + memset(&addr, 0, sizeof(addr)); + + addr.sun_family = AF_UNIX; + + strncpy(addr.sun_path, udspath, sizeof(addr.sun_path) - 1); + + int rc = connect(agent_fd, (struct sockaddr*)&addr, sizeof(addr)); + + if (rc != 0) + { + WLog_ERR(TAG, "Can't connect to Unix domain socket \"%s\"!", + udspath); + close(agent_fd); + return -1; + } + + return agent_fd; +} + + +/** + * Entry point for thread to read from the ssh-agent socket and forward + * the data to RDP + * + * @return NULL + */ +static DWORD WINAPI sshagent_read_thread(LPVOID data) +{ + SSHAGENT_CHANNEL_CALLBACK* callback = (SSHAGENT_CHANNEL_CALLBACK*)data; + BYTE buffer[4096]; + int going = 1; + UINT status = CHANNEL_RC_OK; + + while (going) + { + int bytes_read = read(callback->agent_fd, + buffer, + sizeof(buffer)); + + if (bytes_read == 0) + { + /* Socket closed cleanly at other end */ + going = 0; + } + else if (bytes_read < 0) + { + if (errno != EINTR) + { + WLog_ERR(TAG, + "Error reading from sshagent, errno=%d", + errno); + status = ERROR_READ_FAULT; + going = 0; + } + } + else + { + /* Something read: forward to virtual channel */ + status = callback->channel->Write(callback->channel, + bytes_read, + buffer, + NULL); + + if (status != CHANNEL_RC_OK) + { + going = 0; + } + } + } + + close(callback->agent_fd); + + if (status != CHANNEL_RC_OK) + setChannelError(callback->rdpcontext, status, + "sshagent_read_thread reported an error"); + + ExitThread(status); + return status; +} + +/** + * Callback for data received from the RDP server; forward this to ssh-agent + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT sshagent_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) +{ + SSHAGENT_CHANNEL_CALLBACK* callback = (SSHAGENT_CHANNEL_CALLBACK*) pChannelCallback; + BYTE* pBuffer = Stream_Pointer(data); + UINT32 cbSize = Stream_GetRemainingLength(data); + BYTE* pos = pBuffer; + /* Forward what we have received to the ssh agent */ + UINT32 bytes_to_write = cbSize; + errno = 0; + + while (bytes_to_write > 0) + { + int bytes_written = write(callback->agent_fd, pos, + bytes_to_write); + + if (bytes_written < 0) + { + if (errno != EINTR) + { + WLog_ERR(TAG, + "Error writing to sshagent, errno=%d", + errno); + return ERROR_WRITE_FAULT; + } + } + else + { + bytes_to_write -= bytes_written; + pos += bytes_written; + } + } + + /* Consume stream */ + Stream_Seek(data, cbSize); + return CHANNEL_RC_OK; +} + +/** + * Callback for when the virtual channel is closed + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT sshagent_on_close(IWTSVirtualChannelCallback* pChannelCallback) +{ + SSHAGENT_CHANNEL_CALLBACK* callback = (SSHAGENT_CHANNEL_CALLBACK*) pChannelCallback; + /* Call shutdown() to wake up the read() in sshagent_read_thread(). */ + shutdown(callback->agent_fd, SHUT_RDWR); + EnterCriticalSection(&callback->lock); + + if (WaitForSingleObject(callback->thread, INFINITE) == WAIT_FAILED) + { + UINT error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); + return error; + } + + CloseHandle(callback->thread); + LeaveCriticalSection(&callback->lock); + DeleteCriticalSection(&callback->lock); + free(callback); + return CHANNEL_RC_OK; +} + + +/** + * Callback for when a new virtual channel is opened + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT sshagent_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, + IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, + IWTSVirtualChannelCallback** ppCallback) +{ + SSHAGENT_CHANNEL_CALLBACK* callback; + SSHAGENT_LISTENER_CALLBACK* listener_callback = (SSHAGENT_LISTENER_CALLBACK*) pListenerCallback; + callback = (SSHAGENT_CHANNEL_CALLBACK*) calloc(1, sizeof(SSHAGENT_CHANNEL_CALLBACK)); + + if (!callback) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + /* Now open a connection to the local ssh-agent. Do this for each + * connection to the plugin in case we mess up the agent session. */ + callback->agent_fd + = connect_to_sshagent(listener_callback->agent_uds_path); + + if (callback->agent_fd == -1) + { + free(callback); + return CHANNEL_RC_INITIALIZATION_ERROR; + } + + InitializeCriticalSection(&callback->lock); + callback->iface.OnDataReceived = sshagent_on_data_received; + callback->iface.OnClose = sshagent_on_close; + callback->plugin = listener_callback->plugin; + callback->channel_mgr = listener_callback->channel_mgr; + callback->channel = pChannel; + callback->rdpcontext = listener_callback->rdpcontext; + callback->thread + = CreateThread(NULL, + 0, + sshagent_read_thread, + (void*) callback, + 0, + NULL); + + if (!callback->thread) + { + WLog_ERR(TAG, "CreateThread failed!"); + DeleteCriticalSection(&callback->lock); + free(callback); + return CHANNEL_RC_INITIALIZATION_ERROR; + } + + *ppCallback = (IWTSVirtualChannelCallback*) callback; + return CHANNEL_RC_OK; +} + +/** + * Callback for when the plugin is initialised + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT sshagent_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) +{ + SSHAGENT_PLUGIN* sshagent = (SSHAGENT_PLUGIN*) pPlugin; + sshagent->listener_callback = (SSHAGENT_LISTENER_CALLBACK*) calloc(1, + sizeof(SSHAGENT_LISTENER_CALLBACK)); + + if (!sshagent->listener_callback) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + sshagent->listener_callback->rdpcontext = sshagent->rdpcontext; + sshagent->listener_callback->iface.OnNewChannelConnection = sshagent_on_new_channel_connection; + sshagent->listener_callback->plugin = pPlugin; + sshagent->listener_callback->channel_mgr = pChannelMgr; + sshagent->listener_callback->agent_uds_path = getenv("SSH_AUTH_SOCK"); + + if (sshagent->listener_callback->agent_uds_path == NULL) + { + WLog_ERR(TAG, "Environment variable $SSH_AUTH_SOCK undefined!"); + free(sshagent->listener_callback); + sshagent->listener_callback = NULL; + return CHANNEL_RC_INITIALIZATION_ERROR; + } + + return pChannelMgr->CreateListener(pChannelMgr, "SSHAGENT", 0, + (IWTSListenerCallback*) sshagent->listener_callback, NULL); +} + +/** + * Callback for when the plugin is terminated + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT sshagent_plugin_terminated(IWTSPlugin* pPlugin) +{ + SSHAGENT_PLUGIN* sshagent = (SSHAGENT_PLUGIN*) pPlugin; + free(sshagent); + return CHANNEL_RC_OK; +} + +#ifdef BUILTIN_CHANNELS +#define DVCPluginEntry sshagent_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry +#endif + +/** + * Main entry point for sshagent DVC plugin + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) +{ + UINT status = CHANNEL_RC_OK; + SSHAGENT_PLUGIN* sshagent; + sshagent = (SSHAGENT_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "sshagent"); + + if (!sshagent) + { + sshagent = (SSHAGENT_PLUGIN*) calloc(1, sizeof(SSHAGENT_PLUGIN)); + + if (!sshagent) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + sshagent->iface.Initialize = sshagent_plugin_initialize; + sshagent->iface.Connected = NULL; + sshagent->iface.Disconnected = NULL; + sshagent->iface.Terminated = sshagent_plugin_terminated; + sshagent->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings( + pEntryPoints))->instance)->context; + status = pEntryPoints->RegisterPlugin(pEntryPoints, "sshagent", (IWTSPlugin*) sshagent); + } + + return status; +} + +/* vim: set sw=8:ts=8:noet: */ diff --git a/channels/sshagent/client/sshagent_main.h b/channels/sshagent/client/sshagent_main.h new file mode 100644 index 0000000..fc1ac15 --- /dev/null +++ b/channels/sshagent/client/sshagent_main.h @@ -0,0 +1,42 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * SSH Agent Virtual Channel Extension + * + * Copyright 2013 Christian Hofstaedtler + * Copyright 2017 Ben Cohen + * + * 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 SSHAGENT_MAIN_H +#define SSHAGENT_MAIN_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include + +#define DVC_TAG CHANNELS_TAG("sshagent.client") +#ifdef WITH_DEBUG_SSHAGENT +#define DEBUG_SSHAGENT(...) WLog_DBG(DVC_TAG, __VA_ARGS__) +#else +#define DEBUG_SSHAGENT(...) do { } while (0) +#endif + +#endif /* SSHAGENT_MAIN_H */ + diff --git a/channels/sshagent/server/CMakeLists.txt b/channels/sshagent/server/CMakeLists.txt new file mode 100644 index 0000000..9d62995 --- /dev/null +++ b/channels/sshagent/server/CMakeLists.txt @@ -0,0 +1,31 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# Copyright 2017 Ben Cohen +# +# 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. + +define_channel_server("sshagent") + +set(${MODULE_PREFIX}_SRCS + sshagent_main.c) + +add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "DVCPluginEntry") + + + +target_link_libraries(${MODULE_NAME} freerdp) + + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server") diff --git a/channels/sshagent/server/sshagent_main.c b/channels/sshagent/server/sshagent_main.c new file mode 100644 index 0000000..3bbd6d5 --- /dev/null +++ b/channels/sshagent/server/sshagent_main.c @@ -0,0 +1,422 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * SSH Agent Virtual Channel Extension + * + * Copyright 2012-2013 Jay Sorg + * Copyright 2012-2013 Laxmikant Rashinkar + * Copyright 2017 Ben Cohen + * + * 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. + */ + +/* + * Portions are from OpenSSH, under the following license: + * + * Author: Tatu Ylonen + * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland + * All rights reserved + * The authentication agent program. + * + * As far as I am concerned, the code I have written for this software + * can be used freely for any purpose. Any derived versions of this + * software must be clearly marked as such, and if the derived work is + * incompatible with the protocol description in the RFC file, it must be + * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * xrdp-ssh-agent.c: program to forward ssh-agent protocol from xrdp session + * + * This performs the equivalent function of ssh-agent on a server you connect + * to via ssh, but the ssh-agent protocol is over an RDP dynamic virtual + * channel and not an SSH channel. + * + * This will print out variables to set in your environment (specifically, + * $SSH_AUTH_SOCK) for ssh clients to find the agent's socket, then it will + * run in the background. This is suitable to run just as you would run the + * normal ssh-agent, e.g. in your Xsession or /etc/xrdp/startwm.sh. + * + * Your RDP client needs to be running a compatible client-side plugin + * that can see a local ssh-agent. + * + * usage (from within an xrdp session): + * xrdp-ssh-agent + * + * build instructions: + * gcc xrdp-ssh-agent.c -o xrdp-ssh-agent -L./.libs -lxrdpapi -Wall + * + * protocol specification: + * Forward data verbatim over RDP dynamic virtual channel named "sshagent" + * between a ssh client on the xrdp server and the real ssh-agent where + * the RDP client is running. Each connection by a separate client to + * xrdp-ssh-agent gets a separate DVC invocation. + */ + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#ifdef __WIN32__ +#include +#endif + +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _PATH_DEVNULL "/dev/null" + +char socket_name[PATH_MAX]; +char socket_dir[PATH_MAX]; +static int sa_uds_fd = -1; +static int is_going = 1; + + +/* Make a template filename for mk[sd]temp() */ +/* This is from mktemp_proto() in misc.c from openssh */ +void +mktemp_proto(char* s, size_t len) +{ + const char* tmpdir; + int r; + + if ((tmpdir = getenv("TMPDIR")) != NULL) + { + r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); + + if (r > 0 && (size_t)r < len) + return; + } + + r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); + + if (r < 0 || (size_t)r >= len) + { + fprintf(stderr, "%s: template string too short", __func__); + exit(1); + } +} + + +/* This uses parts of main() in ssh-agent.c from openssh */ +static void +setup_ssh_agent(struct sockaddr_un* addr) +{ + int rc; + /* Create private directory for agent socket */ + mktemp_proto(socket_dir, sizeof(socket_dir)); + + if (mkdtemp(socket_dir) == NULL) + { + perror("mkdtemp: private socket dir"); + exit(1); + } + + snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir, + (long)getpid()); + /* Create unix domain socket */ + unlink(socket_name); + sa_uds_fd = socket(AF_UNIX, SOCK_STREAM, 0); + + if (sa_uds_fd == -1) + { + fprintf(stderr, "sshagent: socket creation failed"); + exit(2); + } + + memset(addr, 0, sizeof(struct sockaddr_un)); + addr->sun_family = AF_UNIX; + strncpy(addr->sun_path, socket_name, sizeof(addr->sun_path)); + addr->sun_path[sizeof(addr->sun_path) - 1] = 0; + /* Create with privileges rw------- so other users can't access the UDS */ + mode_t umask_sav = umask(0177); + rc = bind(sa_uds_fd, (struct sockaddr*)addr, sizeof(struct sockaddr_un)); + + if (rc != 0) + { + fprintf(stderr, "sshagent: bind failed"); + close(sa_uds_fd); + unlink(socket_name); + exit(3); + } + + umask(umask_sav); + rc = listen(sa_uds_fd, /* backlog = */ 5); + + if (rc != 0) + { + fprintf(stderr, "listen failed\n"); + close(sa_uds_fd); + unlink(socket_name); + exit(1); + } + + /* Now fork: the child becomes the ssh-agent daemon and the parent prints + * out the pid and socket name. */ + pid_t pid = fork(); + + if (pid == -1) + { + perror("fork"); + exit(1); + } + else if (pid != 0) + { + /* Parent */ + close(sa_uds_fd); + printf("SSH_AUTH_SOCK=%s; export SSH_AUTH_SOCK;\n", socket_name); + printf("SSH_AGENT_PID=%d; export SSH_AGENT_PID;\n", pid); + printf("echo Agent pid %d;\n", pid); + exit(0); + } + + /* Child */ + + if (setsid() == -1) + { + fprintf(stderr, "setsid failed"); + exit(1); + } + + (void)chdir("/"); + int devnullfd; + + if ((devnullfd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) + { + /* XXX might close listen socket */ + (void)dup2(devnullfd, STDIN_FILENO); + (void)dup2(devnullfd, STDOUT_FILENO); + (void)dup2(devnullfd, STDERR_FILENO); + + if (devnullfd > 2) + close(devnullfd); + } + + /* deny core dumps, since memory contains unencrypted private keys */ + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = 0; + + if (setrlimit(RLIMIT_CORE, &rlim) < 0) + { + fprintf(stderr, "setrlimit RLIMIT_CORE: %s", strerror(errno)); + exit(1); + } +} + + +static void +handle_connection(int client_fd) +{ + int rdp_fd = -1; + int rc; + void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, + "SSHAGENT", + WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED); + + if (channel == NULL) + { + fprintf(stderr, "WTSVirtualChannelOpenEx() failed\n"); + } + + unsigned int retlen; + int* retdata; + rc = WTSVirtualChannelQuery(channel, + WTSVirtualFileHandle, + (void**)&retdata, + &retlen); + + if (!rc) + { + fprintf(stderr, "WTSVirtualChannelQuery() failed\n"); + } + + if (retlen != sizeof(rdp_fd)) + { + fprintf(stderr, "WTSVirtualChannelQuery() returned wrong length %d\n", + retlen); + } + + rdp_fd = *retdata; + int client_going = 1; + + while (client_going) + { + /* Wait for data from RDP or the client */ + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(client_fd, &readfds); + FD_SET(rdp_fd, &readfds); + select(FD_SETSIZE, &readfds, NULL, NULL, NULL); + + if (FD_ISSET(rdp_fd, &readfds)) + { + /* Read from RDP and write to the client */ + char buffer[4096]; + unsigned int bytes_to_write; + rc = WTSVirtualChannelRead(channel, + /* TimeOut = */ 5000, + buffer, + sizeof(buffer), + &bytes_to_write); + + if (rc == 1) + { + char* pos = buffer; + errno = 0; + + while (bytes_to_write > 0) + { + int bytes_written = send(client_fd, pos, bytes_to_write, 0); + + if (bytes_written > 0) + { + bytes_to_write -= bytes_written; + pos += bytes_written; + } + else if (bytes_written == 0) + { + fprintf(stderr, "send() returned 0!\n"); + } + else if (errno != EINTR) + { + /* Error */ + fprintf(stderr, "Error %d on recv\n", errno); + client_going = 0; + } + } + } + else + { + /* Error */ + fprintf(stderr, "WTSVirtualChannelRead() failed: %d\n", errno); + client_going = 0; + } + } + + if (FD_ISSET(client_fd, &readfds)) + { + /* Read from the client and write to RDP */ + char buffer[4096]; + ssize_t bytes_to_write = recv(client_fd, buffer, sizeof(buffer), 0); + + if (bytes_to_write > 0) + { + char* pos = buffer; + + while (bytes_to_write > 0) + { + unsigned int bytes_written; + int rc = WTSVirtualChannelWrite(channel, + pos, + bytes_to_write, + &bytes_written); + + if (rc == 0) + { + fprintf(stderr, "WTSVirtualChannelWrite() failed: %d\n", + errno); + client_going = 0; + } + else + { + bytes_to_write -= bytes_written; + pos += bytes_written; + } + } + } + else if (bytes_to_write == 0) + { + /* Client has closed connection */ + client_going = 0; + } + else + { + /* Error */ + fprintf(stderr, "Error %d on recv\n", errno); + client_going = 0; + } + } + } + + WTSVirtualChannelClose(channel); +} + + +int +main(int argc, char** argv) +{ + /* Setup the Unix domain socket and daemon process */ + struct sockaddr_un addr; + setup_ssh_agent(&addr); + + /* Wait for a client to connect to the socket */ + while (is_going) + { + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(sa_uds_fd, &readfds); + select(FD_SETSIZE, &readfds, NULL, NULL, NULL); + + /* If something connected then get it... + * (You can test this using "socat - UNIX-CONNECT:".) */ + if (FD_ISSET(sa_uds_fd, &readfds)) + { + socklen_t addrsize = sizeof(addr); + int client_fd = accept(sa_uds_fd, + (struct sockaddr*)&addr, + &addrsize); + handle_connection(client_fd); + close(client_fd); + } + } + + close(sa_uds_fd); + unlink(socket_name); + return 0; +} + +/* vim: set sw=4:ts=4:et: */ diff --git a/channels/tsmf/client/alsa/tsmf_alsa.c b/channels/tsmf/client/alsa/tsmf_alsa.c index 02f3941..78a0a66 100644 --- a/channels/tsmf/client/alsa/tsmf_alsa.c +++ b/channels/tsmf/client/alsa/tsmf_alsa.c @@ -72,7 +72,7 @@ static BOOL tsmf_alsa_open(ITSMFAudioDevice *audio, const char *device) } else { - strncpy(alsa->device, device, sizeof(alsa->device)); + strncpy(alsa->device, device, sizeof(alsa->device) - 1); } return tsmf_alsa_open_device(alsa); } diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c index 493cc93..5522eb7 100644 --- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -61,6 +61,11 @@ #define AV_CODEC_ID_AC3 CODEC_ID_AC3 #endif +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 34, 2) +#define AV_CODEC_CAP_TRUNCATED CODEC_CAP_TRUNCATED +#define AV_CODEC_FLAG_TRUNCATED CODEC_FLAG_TRUNCATED +#endif + #if LIBAVUTIL_VERSION_MAJOR < 52 #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P #endif @@ -75,12 +80,12 @@ typedef struct _TSMFFFmpegDecoder #else enum AVCodecID codec_id; #endif - AVCodecContext *codec_context; - AVCodec *codec; - AVFrame *frame; + AVCodecContext* codec_context; + AVCodec* codec; + AVFrame* frame; int prepared; - BYTE *decoded_data; + BYTE* decoded_data; UINT32 decoded_size; UINT32 decoded_size_max; } TSMFFFmpegDecoder; @@ -89,15 +94,17 @@ static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder* decoder) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec_context = avcodec_alloc_context3(NULL); + if (!mdecoder->codec_context) { WLog_ERR(TAG, "avcodec_alloc_context failed."); return FALSE; } + return TRUE; } -static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type) +static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec_context->width = media_type->Width; @@ -113,7 +120,7 @@ static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MED return TRUE; } -static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type) +static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec_context->sample_rate = media_type->SamplesPerSecond.Numerator; @@ -140,14 +147,14 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED return TRUE; } -static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type) +static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type) { - BYTE *p; + BYTE* p; UINT32 size; - const BYTE *s; + const BYTE* s; TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; - mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id); + if (!mdecoder->codec) { WLog_ERR(TAG, "avcodec_find_decoder failed."); @@ -156,16 +163,21 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP mdecoder->codec_context->codec_id = mdecoder->codec_id; mdecoder->codec_context->codec_type = mdecoder->media_type; - switch(mdecoder->media_type) + + switch (mdecoder->media_type) { case AVMEDIA_TYPE_VIDEO: if (!tsmf_ffmpeg_init_video_stream(decoder, media_type)) return FALSE; + break; + case AVMEDIA_TYPE_AUDIO: if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type)) return FALSE; + break; + default: WLog_ERR(TAG, "unknown media_type %d", mdecoder->media_type); break; @@ -176,11 +188,12 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP /* Add a padding to avoid invalid memory read in some codec */ mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8; mdecoder->codec_context->extradata = calloc(1, mdecoder->codec_context->extradata_size); + if (!mdecoder->codec_context->extradata) return FALSE; if (media_type->SubType == TSMF_SUB_TYPE_AVC1 && - media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO) + media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO) { /* The extradata format that FFmpeg uses is following CodecPrivate in Matroska. See http://haali.su/mkv/codecs.pdf */ @@ -207,62 +220,77 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP } } - if (mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED) - mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED; + if (mdecoder->codec->capabilities & AV_CODEC_CAP_TRUNCATED) + mdecoder->codec_context->flags |= AV_CODEC_FLAG_TRUNCATED; + return TRUE; } static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder* decoder) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; + if (avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0) { WLog_ERR(TAG, "avcodec_open2 failed."); return FALSE; } + mdecoder->prepared = 1; return TRUE; } -static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE *media_type) +static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; - switch(media_type->MajorType) + + switch (media_type->MajorType) { case TSMF_MAJOR_TYPE_VIDEO: mdecoder->media_type = AVMEDIA_TYPE_VIDEO; break; + case TSMF_MAJOR_TYPE_AUDIO: mdecoder->media_type = AVMEDIA_TYPE_AUDIO; break; + default: return FALSE; } - switch(media_type->SubType) + + switch (media_type->SubType) { case TSMF_SUB_TYPE_WVC1: mdecoder->codec_id = AV_CODEC_ID_VC1; break; + case TSMF_SUB_TYPE_WMA2: mdecoder->codec_id = AV_CODEC_ID_WMAV2; break; + case TSMF_SUB_TYPE_WMA9: mdecoder->codec_id = AV_CODEC_ID_WMAPRO; break; + case TSMF_SUB_TYPE_MP3: mdecoder->codec_id = AV_CODEC_ID_MP3; break; + case TSMF_SUB_TYPE_MP2A: mdecoder->codec_id = AV_CODEC_ID_MP2; break; + case TSMF_SUB_TYPE_MP2V: mdecoder->codec_id = AV_CODEC_ID_MPEG2VIDEO; break; + case TSMF_SUB_TYPE_WMV3: mdecoder->codec_id = AV_CODEC_ID_WMV3; break; + case TSMF_SUB_TYPE_AAC: mdecoder->codec_id = AV_CODEC_ID_AAC; + /* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data is at the end of it. See http://msdn.microsoft.com/en-us/library/dd757806.aspx */ @@ -271,32 +299,41 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE *medi media_type->ExtraData += 12; media_type->ExtraDataSize -= 12; } + break; + case TSMF_SUB_TYPE_H264: case TSMF_SUB_TYPE_AVC1: mdecoder->codec_id = AV_CODEC_ID_H264; break; + case TSMF_SUB_TYPE_AC3: mdecoder->codec_id = AV_CODEC_ID_AC3; break; + default: return FALSE; } + if (!tsmf_ffmpeg_init_context(decoder)) return FALSE; + if (!tsmf_ffmpeg_init_stream(decoder, media_type)) return FALSE; + if (!tsmf_ffmpeg_prepare(decoder)) return FALSE; + return TRUE; } -static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions) +static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size, + UINT32 extensions) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; int decoded; int len; - AVFrame *frame; + AVFrame* frame; BOOL ret = TRUE; #if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20) len = avcodec_decode_video(mdecoder->codec_context, mdecoder->frame, &decoded, data, data_size); @@ -304,13 +341,16 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UI { AVPacket pkt; av_init_packet(&pkt); - pkt.data = (BYTE *) data; + pkt.data = (BYTE*) data; pkt.size = data_size; + if (extensions & TSMM_SAMPLE_EXT_CLEANPOINT) pkt.flags |= AV_PKT_FLAG_KEY; + len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt); } #endif + if (len < 0) { WLog_ERR(TAG, "data_size %"PRIu32", avcodec_decode_video failed (%d)", data_size, len); @@ -324,14 +364,15 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UI else { DEBUG_TSMF("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d " - "pix_fmt %d width %d height %d", - mdecoder->frame->linesize[0], mdecoder->frame->linesize[1], - mdecoder->frame->linesize[2], mdecoder->frame->linesize[3], - mdecoder->codec_context->pix_fmt, - mdecoder->codec_context->width, mdecoder->codec_context->height); + "pix_fmt %d width %d height %d", + mdecoder->frame->linesize[0], mdecoder->frame->linesize[1], + mdecoder->frame->linesize[2], mdecoder->frame->linesize[3], + mdecoder->codec_context->pix_fmt, + mdecoder->codec_context->width, mdecoder->codec_context->height); mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt, - mdecoder->codec_context->width, mdecoder->codec_context->height); + mdecoder->codec_context->width, mdecoder->codec_context->height); mdecoder->decoded_data = calloc(1, mdecoder->decoded_size); + if (!mdecoder->decoded_data) return FALSE; @@ -341,151 +382,172 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UI frame = av_frame_alloc(); #endif avpicture_fill((AVPicture*) frame, mdecoder->decoded_data, - mdecoder->codec_context->pix_fmt, - mdecoder->codec_context->width, mdecoder->codec_context->height); + mdecoder->codec_context->pix_fmt, + mdecoder->codec_context->width, mdecoder->codec_context->height); av_picture_copy((AVPicture*) frame, (AVPicture*) mdecoder->frame, - mdecoder->codec_context->pix_fmt, - mdecoder->codec_context->width, mdecoder->codec_context->height); + mdecoder->codec_context->pix_fmt, + mdecoder->codec_context->width, mdecoder->codec_context->height); av_free(frame); } return ret; } -static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions) +static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size, + UINT32 extensions) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; int len; int frame_size; UINT32 src_size; - const BYTE *src; - BYTE *dst; + const BYTE* src; + BYTE* dst; int dst_offset; #if 0 WLog_DBG(TAG, ("tsmf_ffmpeg_decode_audio: data_size %"PRIu32"", data_size)); int i; - for(i = 0; i < data_size; i++) + + for (i = 0; i < data_size; i++) { WLog_DBG(TAG, ("%02"PRIX8"", data[i])); + if (i % 16 == 15) WLog_DBG(TAG, ("\n")); } + #endif + if (mdecoder->decoded_size_max == 0) mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16; mdecoder->decoded_data = calloc(1, mdecoder->decoded_size_max); + if (!mdecoder->decoded_data) return FALSE; /* align the memory for SSE2 needs */ - dst = (BYTE *)(((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F); + dst = (BYTE*)(((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F); dst_offset = dst - mdecoder->decoded_data; src = data; src_size = data_size; - while(src_size > 0) + + while (src_size > 0) { /* Ensure enough space for decoding */ if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE) { - BYTE *tmp_data; - + BYTE* tmp_data; tmp_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max * 2 + 16); + if (!tmp_data) return FALSE; + mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16; mdecoder->decoded_data = tmp_data; + dst = (BYTE*)(((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F); - dst = (BYTE *)(((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F); if (dst - mdecoder->decoded_data != dst_offset) { /* re-align the memory if the alignment has changed after realloc */ memmove(dst, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size); dst_offset = dst - mdecoder->decoded_data; } + dst += mdecoder->decoded_size; } + frame_size = mdecoder->decoded_size_max - mdecoder->decoded_size; #if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20) len = avcodec_decode_audio2(mdecoder->codec_context, - (int16_t *) dst, &frame_size, src, src_size); + (int16_t*) dst, &frame_size, src, src_size); #else { #if LIBAVCODEC_VERSION_MAJOR < 55 - AVFrame *decoded_frame = avcodec_alloc_frame(); + AVFrame* decoded_frame = avcodec_alloc_frame(); #else - AVFrame *decoded_frame = av_frame_alloc(); + AVFrame* decoded_frame = av_frame_alloc(); #endif int got_frame = 0; AVPacket pkt; av_init_packet(&pkt); - pkt.data = (BYTE *) src; + pkt.data = (BYTE*) src; pkt.size = src_size; len = avcodec_decode_audio4(mdecoder->codec_context, decoded_frame, &got_frame, &pkt); + if (len >= 0 && got_frame) { frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels, - decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1); + decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1); memcpy(dst, decoded_frame->data[0], frame_size); } else { frame_size = 0; } + av_free(decoded_frame); } #endif + if (len > 0) { src += len; src_size -= len; } - if(frame_size > 0) + + if (frame_size > 0) { mdecoder->decoded_size += frame_size; dst += frame_size; } } + if (mdecoder->decoded_size == 0) { free(mdecoder->decoded_data); mdecoder->decoded_data = NULL; } - else - if (dst_offset) - { - /* move the aligned decoded data to original place */ - memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size); - } + else if (dst_offset) + { + /* move the aligned decoded data to original place */ + memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size); + } + DEBUG_TSMF("data_size %"PRIu32" decoded_size %"PRIu32"", - data_size, mdecoder->decoded_size); + data_size, mdecoder->decoded_size); return TRUE; } -static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions) +static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size, + UINT32 extensions) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; + if (mdecoder->decoded_data) { free(mdecoder->decoded_data); mdecoder->decoded_data = NULL; } + mdecoder->decoded_size = 0; - switch(mdecoder->media_type) + + switch (mdecoder->media_type) { case AVMEDIA_TYPE_VIDEO: return tsmf_ffmpeg_decode_video(decoder, data, data_size, extensions); + case AVMEDIA_TYPE_AUDIO: return tsmf_ffmpeg_decode_audio(decoder, data, data_size, extensions); + default: WLog_ERR(TAG, "unknown media type."); return FALSE; } } -static BYTE *tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32 *size) +static BYTE* tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32* size) { - BYTE *buf; + BYTE* buf; TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; *size = mdecoder->decoded_size; buf = mdecoder->decoded_data; @@ -502,14 +564,15 @@ static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder* decoder) { case AV_PIX_FMT_YUV420P: return RDP_PIXFMT_I420; + default: WLog_ERR(TAG, "unsupported pixel format %u", - mdecoder->codec_context->pix_fmt); - return (UINT32) -1; + mdecoder->codec_context->pix_fmt); + return (UINT32) - 1; } } -static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32 *width, UINT32 *height) +static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32* width, UINT32* height) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; @@ -528,6 +591,7 @@ static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32 *wid static void tsmf_ffmpeg_free(ITSMFDecoder* decoder) { TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; + if (mdecoder->frame) av_free(mdecoder->frame); @@ -541,10 +605,16 @@ static void tsmf_ffmpeg_free(ITSMFDecoder* decoder) free(mdecoder->codec_context->extradata); av_free(mdecoder->codec_context); } + free(decoder); } -static BOOL initialized = FALSE; +static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT; +static BOOL CALLBACK InitializeAvCodecs(PINIT_ONCE once, PVOID param, PVOID* context) +{ + avcodec_register_all(); + return TRUE; +} #ifdef BUILTIN_CHANNELS #define freerdp_tsmf_client_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry @@ -555,15 +625,8 @@ static BOOL initialized = FALSE; ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void) { TSMFFFmpegDecoder* decoder; - - if (!initialized) - { - avcodec_register_all(); - initialized = TRUE; - } - + InitOnceExecuteOnce(&g_Initialized, InitializeAvCodecs, NULL, NULL); WLog_DBG(TAG, "TSMFDecoderEntry FFMPEG"); - decoder = (TSMFFFmpegDecoder*) calloc(1, sizeof(TSMFFFmpegDecoder)); if (!decoder) @@ -575,6 +638,5 @@ ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void) decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format; decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension; decoder->iface.Free = tsmf_ffmpeg_free; - return (ITSMFDecoder*) decoder; } diff --git a/channels/tsmf/client/gstreamer/tsmf_X11.c b/channels/tsmf/client/gstreamer/tsmf_X11.c index 3f6002a..b57b927 100644 --- a/channels/tsmf/client/gstreamer/tsmf_X11.c +++ b/channels/tsmf/client/gstreamer/tsmf_X11.c @@ -33,7 +33,15 @@ #include #include +#if __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wparentheses-equality" +#endif /* __clang__ */ #include +#if __clang__ +#pragma clang diagnostic pop +#endif /* __clang__ */ + #if GST_VERSION_MAJOR > 0 #include #else diff --git a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c index bd22e6a..0addbe7 100644 --- a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c +++ b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c @@ -33,7 +33,15 @@ #include +#if __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wparentheses-equality" +#endif /* __clang__ */ #include +#if __clang__ +#pragma clang diagnostic pop +#endif /* __clang__ */ + #include #include diff --git a/channels/tsmf/client/oss/tsmf_oss.c b/channels/tsmf/client/oss/tsmf_oss.c index 305f0ce..db88ddb 100644 --- a/channels/tsmf/client/oss/tsmf_oss.c +++ b/channels/tsmf/client/oss/tsmf_oss.c @@ -81,7 +81,7 @@ static BOOL tsmf_oss_open(ITSMFAudioDevice* audio, const char* device) } else { - strncpy(oss->dev_name, device, sizeof(oss->dev_name)); + strncpy(oss->dev_name, device, sizeof(oss->dev_name) - 1); } if ((oss->pcm_handle = open(oss->dev_name, O_WRONLY)) < 0) diff --git a/channels/tsmf/client/pulse/tsmf_pulse.c b/channels/tsmf/client/pulse/tsmf_pulse.c index b61f989..e6da925 100644 --- a/channels/tsmf/client/pulse/tsmf_pulse.c +++ b/channels/tsmf/client/pulse/tsmf_pulse.c @@ -115,7 +115,7 @@ static BOOL tsmf_pulse_open(ITSMFAudioDevice *audio, const char *device) TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio; if(device) { - strcpy(pulse->device, device); + strncpy(pulse->device, device, sizeof(pulse->device) - 1); } pulse->mainloop = pa_threaded_mainloop_new(); if(!pulse->mainloop) diff --git a/channels/tsmf/client/tsmf_ifman.c b/channels/tsmf/client/tsmf_ifman.c index 5af0e7b..9fcc620 100644 --- a/channels/tsmf/client/tsmf_ifman.c +++ b/channels/tsmf/client/tsmf_ifman.c @@ -482,7 +482,7 @@ UINT tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman) int num_rects = 0; UINT error = CHANNEL_RC_OK; int i; - int pos; + size_t pos; if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 32) return ERROR_INVALID_DATA; diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index 259eb55..a6339be 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -123,7 +123,7 @@ BOOL tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback, */ static UINT tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { - int length; + size_t length; wStream *input; wStream *output; UINT error = CHANNEL_RC_OK; diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c index 2609efb..ada248c 100644 --- a/channels/tsmf/client/tsmf_media.c +++ b/channels/tsmf/client/tsmf_media.c @@ -737,7 +737,7 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample) return ret; } -static void* tsmf_stream_ack_func(void* arg) +static DWORD WINAPI tsmf_stream_ack_func(LPVOID arg) { HANDLE hdl[2]; TSMF_STREAM* stream = (TSMF_STREAM*) arg; @@ -817,11 +817,11 @@ static void* tsmf_stream_ack_func(void* arg) "tsmf_stream_ack_func reported an error"); DEBUG_TSMF("out %"PRIu32"", stream->stream_id); - ExitThread(0); - return NULL; + ExitThread(error); + return error; } -static void* tsmf_stream_playback_func(void* arg) +static DWORD WINAPI tsmf_stream_playback_func(LPVOID arg) { HANDLE hdl[2]; TSMF_SAMPLE* sample = NULL; @@ -907,8 +907,8 @@ static void* tsmf_stream_playback_func(void* arg) "tsmf_stream_playback_func reported an error"); DEBUG_TSMF("out %"PRIu32"", stream->stream_id); - ExitThread(0); - return NULL; + ExitThread(error); + return error; } static BOOL tsmf_stream_start(TSMF_STREAM* stream) @@ -1259,13 +1259,13 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id, goto error_sample_ack_list; stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free; - stream->play_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, + stream->play_thread = CreateThread(NULL, 0, tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL); if (!stream->play_thread) goto error_play_thread; - stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, + stream->ack_thread = CreateThread(NULL, 0, tsmf_stream_ack_func, stream, CREATE_SUSPENDED, NULL); if (!stream->ack_thread) diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c index 62ddb78..94e1d04 100644 --- a/channels/urbdrc/client/libusb/libusb_udevice.c +++ b/channels/urbdrc/client/libusb/libusb_udevice.c @@ -26,31 +26,33 @@ #include #endif +#include + #include "libusb_udevice.h" #define BASIC_STATE_FUNC_DEFINED(_arg, _type) \ -static _type udev_get_##_arg (IUDEVICE* idev) \ -{ \ - UDEVICE* pdev = (UDEVICE*) idev; \ - return pdev->_arg; \ -} \ -static void udev_set_##_arg (IUDEVICE* idev, _type _t) \ -{ \ - UDEVICE* pdev = (UDEVICE*) idev; \ - pdev->_arg = _t; \ -} + static _type udev_get_##_arg (IUDEVICE* idev) \ + { \ + UDEVICE* pdev = (UDEVICE*) idev; \ + return pdev->_arg; \ + } \ + static void udev_set_##_arg (IUDEVICE* idev, _type _t) \ + { \ + UDEVICE* pdev = (UDEVICE*) idev; \ + pdev->_arg = _t; \ + } #define BASIC_POINT_FUNC_DEFINED(_arg, _type) \ -static _type udev_get_p_##_arg (IUDEVICE* idev) \ -{ \ - UDEVICE* pdev = (UDEVICE*) idev; \ - return pdev->_arg; \ -} \ -static void udev_set_p_##_arg (IUDEVICE* idev, _type _t) \ -{ \ - UDEVICE* pdev = (UDEVICE*) idev; \ - pdev->_arg = _t; \ -} + static _type udev_get_p_##_arg (IUDEVICE* idev) \ + { \ + UDEVICE* pdev = (UDEVICE*) idev; \ + return pdev->_arg; \ + } \ + static void udev_set_p_##_arg (IUDEVICE* idev, _type _t) \ + { \ + UDEVICE* pdev = (UDEVICE*) idev; \ + pdev->_arg = _t; \ + } #define BASIC_STATE_FUNC_REGISTER(_arg, _dev) \ _dev->iface.get_##_arg = udev_get_##_arg; \ @@ -70,11 +72,10 @@ struct _ISO_USER_DATA UINT32 start_frame; }; -static int get_next_timeout(libusb_context *ctx, struct timeval *tv, struct timeval *out) +static int get_next_timeout(libusb_context* ctx, struct timeval* tv, struct timeval* out) { int r; struct timeval timeout; - r = libusb_get_next_timeout(ctx, &timeout); if (r) @@ -93,39 +94,36 @@ static int get_next_timeout(libusb_context *ctx, struct timeval *tv, struct time { *out = *tv; } + return 0; } -/* +/* * a simple wrapper to implement libusb_handle_events_timeout_completed * function in libusb library git tree (1.0.9 later) */ -static int handle_events_completed(libusb_context *ctx, int *completed) +static int handle_events_completed(libusb_context* ctx, int* completed) { struct timeval tv; - tv.tv_sec = 60; tv.tv_usec = 0; - #ifdef HAVE_NEW_LIBUSB return libusb_handle_events_timeout_completed(ctx, &tv, completed); #else int r; struct timeval poll_timeout; - r = get_next_timeout(ctx, &tv, &poll_timeout); - retry: + if (libusb_try_lock_events(ctx) == 0) { if (completed == NULL || !*completed) { /* we obtained the event lock: do our own event handling */ - WLog_DBG(TAG,"doing our own event handling"); + WLog_DBG(TAG, "doing our own event handling"); r = libusb_handle_events_locked(ctx, &tv); } libusb_unlock_events(ctx); - return r; } @@ -141,13 +139,12 @@ retry: /* we hit a race: whoever was event handling earlier finished in the * time it took us to reach this point. try the cycle again. */ libusb_unlock_event_waiters(ctx); - WLog_DBG(TAG,"event handler was active but went away, retrying"); + WLog_DBG(TAG, "event handler was active but went away, retrying"); goto retry; } - WLog_DBG(TAG,"another thread is doing event handling"); + WLog_DBG(TAG, "another thread is doing event handling"); r = libusb_wait_for_event(ctx, &poll_timeout); - already_done: libusb_unlock_event_waiters(ctx); @@ -163,10 +160,11 @@ already_done: { return 0; } + #endif /* HAVE_NEW_LIBUSE */ } -static void func_iso_callback(struct libusb_transfer *transfer) +static void func_iso_callback(struct libusb_transfer* transfer) { ISO_USER_DATA* iso_user_data = (ISO_USER_DATA*) transfer->user_data; BYTE* data = iso_user_data->IsoPacket; @@ -175,30 +173,31 @@ static void func_iso_callback(struct libusb_transfer *transfer) UINT32 index = 0; UINT32 i, act_len; BYTE* b; - *completed = 1; - /* Fixme: currently fill the dummy frame number, tt needs to be + + /* Fixme: currently fill the dummy frame number, tt needs to be * filled a real frame number */ // urbdrc_get_mstime(iso_user_data->start_frame); if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && (!iso_user_data->noack)) { - for (i = 0; i < transfer->num_iso_packets; i++) + for (i = 0; i < transfer->num_iso_packets; i++) { act_len = transfer->iso_packet_desc[i].actual_length; data_write_UINT32(data + offset, index); data_write_UINT32(data + offset + 4, act_len); - data_write_UINT32(data + offset + 8, - transfer->iso_packet_desc[i].status); + data_write_UINT32(data + offset + 8, + transfer->iso_packet_desc[i].status); offset += 12; - if (transfer->iso_packet_desc[i].status == USBD_STATUS_SUCCESS) + if (transfer->iso_packet_desc[i].status == USBD_STATUS_SUCCESS) { b = libusb_get_iso_packet_buffer_simple(transfer, i); - if (act_len > 0) + if (act_len > 0) { if (iso_user_data->output_data + index != b) memcpy(iso_user_data->output_data + index, b, act_len); + index += act_len; } else @@ -206,19 +205,20 @@ static void func_iso_callback(struct libusb_transfer *transfer) //WLog_ERR(TAG, "actual length %"PRIu32"", act_len); //exit(EXIT_FAILURE); } - } - else + } + else { iso_user_data->error_count++; //print_transfer_status(transfer->iso_packet_desc[i].status); } } + transfer->actual_length = index; iso_user_data->iso_status = 1; } else if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && (iso_user_data->noack)) { - /* This situation occurs when we do not need to + /* This situation occurs when we do not need to * return any packet */ iso_user_data->iso_status = 1; } @@ -230,14 +230,13 @@ static void func_iso_callback(struct libusb_transfer *transfer) } static const LIBUSB_ENDPOINT_DESCEIPTOR* func_get_ep_desc(LIBUSB_CONFIG_DESCRIPTOR* LibusbConfig, - MSUSB_CONFIG_DESCRIPTOR* MsConfig, UINT32 EndpointAddress) + MSUSB_CONFIG_DESCRIPTOR* MsConfig, UINT32 EndpointAddress) { BYTE alt; int inum, pnum; MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces; const LIBUSB_INTERFACE* interface; const LIBUSB_ENDPOINT_DESCEIPTOR* endpoint; - MsInterfaces = MsConfig->MsInterfaces; interface = LibusbConfig->interface; @@ -245,7 +244,7 @@ static const LIBUSB_ENDPOINT_DESCEIPTOR* func_get_ep_desc(LIBUSB_CONFIG_DESCRIPT { alt = MsInterfaces[inum]->AlternateSetting; endpoint = interface[inum].altsetting[alt].endpoint; - + for (pnum = 0; pnum < MsInterfaces[inum]->NumberOfPipes; pnum++) { if (endpoint[pnum].bEndpointAddress == EndpointAddress) @@ -258,9 +257,9 @@ static const LIBUSB_ENDPOINT_DESCEIPTOR* func_get_ep_desc(LIBUSB_CONFIG_DESCRIPT return NULL; } -static void func_bulk_transfer_cb(struct libusb_transfer *transfer) +static void func_bulk_transfer_cb(struct libusb_transfer* transfer) { - int *completed = transfer->user_data; + int* completed = transfer->user_data; *completed = 1; /* caller interprets results and frees transfer */ } @@ -275,7 +274,7 @@ static int func_set_usbd_status(UDEVICE* pdev, UINT32* status, int err_result) case LIBUSB_ERROR_IO: *status = USBD_STATUS_STALL_PID; - WLog_ERR(TAG,"LIBUSB_ERROR_IO!!"); + WLog_ERR(TAG, "LIBUSB_ERROR_IO!!"); break; case LIBUSB_ERROR_INVALID_PARAM: @@ -288,14 +287,16 @@ static int func_set_usbd_status(UDEVICE* pdev, UINT32* status, int err_result) case LIBUSB_ERROR_NO_DEVICE: *status = USBD_STATUS_DEVICE_GONE; + if (pdev) { if (!(pdev->status & URBDRC_DEVICE_NOT_FOUND)) { pdev->status |= URBDRC_DEVICE_NOT_FOUND; - WLog_WARN(TAG,"LIBUSB_ERROR_NO_DEVICE!!"); + WLog_WARN(TAG, "LIBUSB_ERROR_NO_DEVICE!!"); } } + break; case LIBUSB_ERROR_NOT_FOUND: @@ -343,7 +344,7 @@ static int func_set_usbd_status(UDEVICE* pdev, UINT32* status, int err_result) } static void func_iso_data_init(ISO_USER_DATA* iso_user_data, UINT32 numPacket, UINT32 buffsize, - UINT32 noAck, BYTE* isoPacket, BYTE * buffer) + UINT32 noAck, BYTE* isoPacket, BYTE* buffer) { /* init struct iso_user_data */ iso_user_data->IsoPacket = isoPacket; @@ -354,13 +355,14 @@ static void func_iso_data_init(ISO_USER_DATA* iso_user_data, UINT32 numPacket, U urbdrc_get_mstime(iso_user_data->start_frame); } -static int func_config_release_all_interface(LIBUSB_DEVICE_HANDLE* libusb_handle, UINT32 NumInterfaces) +static int func_config_release_all_interface(LIBUSB_DEVICE_HANDLE* libusb_handle, + UINT32 NumInterfaces) { int i, ret; for (i = 0; i < NumInterfaces; i++) { - ret = libusb_release_interface (libusb_handle, i); + ret = libusb_release_interface(libusb_handle, i); if (ret < 0) { @@ -445,7 +447,7 @@ static void print_status(enum libusb_transfer_status status) case LIBUSB_TRANSFER_NO_DEVICE: WLog_ERR(TAG, "Transfer status: LIBUSB_TRANSFER_NO_DEVICE"); break; - case LIBUSB_TRANSFER_OVERFLOW: + case LIBUSB_TRANSFER_OVERFLOW: WLog_ERR(TAG, "Transfer status: LIBUSB_TRANSFER_OVERFLOW"); break; default: @@ -459,18 +461,16 @@ static LIBUSB_DEVICE* udev_get_libusb_dev(int bus_number, int dev_number) { ssize_t i, total_device; LIBUSB_DEVICE** libusb_list; - - total_device = libusb_get_device_list(NULL, &libusb_list); + total_device = libusb_get_device_list(NULL, &libusb_list); for (i = 0; i < total_device; i++) { if ((bus_number == libusb_get_bus_number(libusb_list[i])) && - (dev_number == libusb_get_device_address(libusb_list[i]))) + (dev_number == libusb_get_device_address(libusb_list[i]))) return libusb_list[i]; } libusb_free_device_list(libusb_list, 1); - return NULL; } @@ -478,9 +478,7 @@ static LIBUSB_DEVICE_DESCRIPTOR* udev_new_descript(LIBUSB_DEVICE* libusb_dev) { int ret; LIBUSB_DEVICE_DESCRIPTOR* descriptor; - descriptor = (LIBUSB_DEVICE_DESCRIPTOR*) malloc(sizeof(LIBUSB_DEVICE_DESCRIPTOR)); - ret = libusb_get_device_descriptor(libusb_dev, descriptor); if (ret < 0) @@ -489,40 +487,47 @@ static LIBUSB_DEVICE_DESCRIPTOR* udev_new_descript(LIBUSB_DEVICE* libusb_dev) free(descriptor); return NULL; } - + return descriptor; } /* Get HUB handle */ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) -static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_number) { +static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_number) +{ int error; ssize_t i, total_device, ports_cnt; uint8_t port_numbers[16]; - LIBUSB_DEVICE **libusb_list; - + LIBUSB_DEVICE** libusb_list; total_device = libusb_get_device_list(NULL, &libusb_list); /* Look for device. */ error = -1; + for (i = 0; i < total_device; i ++) { if ((bus_number != libusb_get_bus_number(libusb_list[i])) || (dev_number != libusb_get_device_address(libusb_list[i]))) continue; + error = libusb_open(libusb_list[i], &pdev->hub_handle); + if (error < 0) { - WLog_ERR(TAG,"libusb_open error: %i - %s", error, libusb_strerror(error)); + WLog_ERR(TAG, "libusb_open error: %i - %s", error, libusb_strerror(error)); break; } + /* get port number */ error = libusb_get_port_numbers(libusb_list[i], port_numbers, sizeof(port_numbers)); libusb_close(pdev->hub_handle); + if (error < 1) - { /* Prevent open hub, treat as error. */ - WLog_ERR(TAG,"libusb_get_port_numbers error: %i - %s", error, libusb_strerror(error)); + { + /* Prevent open hub, treat as error. */ + WLog_ERR(TAG, "libusb_get_port_numbers error: %i - %s", error, libusb_strerror(error)); break; } + pdev->port_number = port_numbers[(error - 1)]; error = 0; WLog_DBG(TAG, " Port: %d", pdev->port_number); @@ -531,26 +536,33 @@ static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_numb WLog_DBG(TAG, " DevPath: %s", pdev->path); break; } + /* Look for device hub. */ if (error == 0) { error = -1; + for (i = 0; i < total_device; i ++) { if ((bus_number != libusb_get_bus_number(libusb_list[i])) || (1 != libusb_get_device_address(libusb_list[i]))) /* Root hub allways first on bus. */ continue; + WLog_DBG(TAG, " Open hub: %"PRIu16"", bus_number); error = libusb_open(libusb_list[i], &pdev->hub_handle); + if (error < 0) - WLog_ERR(TAG,"libusb_open error: %i - %s", error, libusb_strerror(error)); + WLog_ERR(TAG, "libusb_open error: %i - %s", error, libusb_strerror(error)); + break; } } + libusb_free_device_list(libusb_list, 1); if (error < 0) return -1; + WLog_DBG(TAG, "libusb_open success!"); return 0; } @@ -563,12 +575,11 @@ static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_numb struct udev_list_entry* devices; struct udev_list_entry* dev_list_entry; struct udev_device* dev; - LIBUSB_DEVICE* libusb_dev; + LIBUSB_DEVICE* libusb_dev; int hub_found = 0; - int hub_bus = 0; - int hub_dev = 0; + unsigned long hub_bus = 0; + unsigned long hub_dev = 0; int error = 0; - udev = udev_new(); if (!udev) @@ -582,27 +593,33 @@ static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_numb udev_enumerate_add_match_property(enumerate, "DEVTYPE", "usb_device"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); - - udev_list_entry_foreach(dev_list_entry, devices) + udev_list_entry_foreach(dev_list_entry, devices) { - const char * path; - + const char* path; + errno = 0; path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev, path); if (!dev) continue; - int tmp_b = atoi(udev_device_get_property_value(dev,"BUSNUM")); - int tmp_d = atoi(udev_device_get_property_value(dev,"DEVNUM")); + unsigned long tmp_b, tmp_d; + tmp_b = strtoul(udev_device_get_property_value(dev, "BUSNUM"), NULL, 0); + + if (errno != 0) + continue; + + tmp_d = strtoul(udev_device_get_property_value(dev, "DEVNUM"), NULL, 0); + + if (errno != 0) + continue; if (bus_number == tmp_b && dev_number == tmp_d) { /* get port number */ - char *p1, *p2; + char* p1, *p2; const char* sysfs_path = - udev_device_get_property_value(dev,"DEVPATH"); - + udev_device_get_property_value(dev, "DEVPATH"); p1 = (char*) sysfs_path; do @@ -611,23 +628,29 @@ static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_numb p1 = strchr(p2, '.'); } while (p1 != NULL); - + if ((p2 - sysfs_path) < (strlen(sysfs_path) - 2)) { p1 = (char*) sysfs_path; do { - p2 = p1 + 1; p1 = strchr(p2, '-'); } while (p1 != NULL); } - pdev->port_number = atoi(p2); - WLog_DBG(TAG, " Port: %d", pdev->port_number); + errno = 0; + { + unsigned long val = strtoul(p2, NULL, 0); + if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + continue; + + pdev->port_number = val; + } + WLog_DBG(TAG, " Port: %d", pdev->port_number); /* get device path */ p1 = (char*) sysfs_path; @@ -640,31 +663,30 @@ static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_numb memset(pdev->path, 0, 17); strcpy(pdev->path, p2); - WLog_DBG(TAG," DevPath: %s", pdev->path); - + WLog_DBG(TAG, " DevPath: %s", pdev->path); /* query parent hub info */ dev = udev_device_get_parent(dev); if (dev != NULL) { hub_found = 1; - hub_bus = atoi(udev_device_get_property_value(dev,"BUSNUM")); - hub_dev = atoi(udev_device_get_property_value(dev,"DEVNUM")); + hub_bus = strtoul(udev_device_get_property_value(dev, "BUSNUM"), NULL, 0); + hub_dev = strtoul(udev_device_get_property_value(dev, "DEVNUM"), NULL, 0); WLog_DBG(TAG, " Hub BUS/DEV: %d %d", hub_bus, hub_dev); } udev_device_unref(dev); break; } + udev_device_unref(dev); } - udev_enumerate_unref(enumerate); udev_unref(udev); if (!hub_found) { - WLog_WARN(TAG,"hub was not found!"); + WLog_WARN(TAG, "hub was not found!"); return -1; } @@ -673,20 +695,19 @@ static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_numb if (libusb_dev == NULL) { - WLog_DBG(TAG,"get hub libusb_dev fail!"); + WLog_DBG(TAG, "get hub libusb_dev fail!"); return -1; } - error = libusb_open (libusb_dev, &pdev->hub_handle); + error = libusb_open(libusb_dev, &pdev->hub_handle); if (error < 0) { - WLog_DBG(TAG,"libusb_open error!"); + WLog_DBG(TAG, "libusb_open error!"); return -1; } - WLog_DBG(TAG,"libusb_open success!"); - + WLog_DBG(TAG, "libusb_open success!"); /* Success! */ return 0; } @@ -698,7 +719,6 @@ static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BY UDEVICE* pdev = (UDEVICE*) idev; MSUSB_CONFIG_DESCRIPTOR* MsConfig; MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces; - MsConfig = pdev->MsConfig; if (MsConfig) @@ -710,23 +730,24 @@ static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BY diff = 0; } } - + if (diff) { error = libusb_set_interface_alt_setting(pdev->libusb_handle, - InterfaceNumber, AlternateSetting); + InterfaceNumber, AlternateSetting); if (error < 0) { WLog_ERR(TAG, "Set interface altsetting get error num %d", - error); - } + error); + } } return error; } -static MSUSB_CONFIG_DESCRIPTOR* libusb_udev_complete_msconfig_setup(IUDEVICE* idev, MSUSB_CONFIG_DESCRIPTOR* MsConfig) +static MSUSB_CONFIG_DESCRIPTOR* libusb_udev_complete_msconfig_setup(IUDEVICE* idev, + MSUSB_CONFIG_DESCRIPTOR* MsConfig) { UDEVICE* pdev = (UDEVICE*) idev; MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces; @@ -741,17 +762,18 @@ static MSUSB_CONFIG_DESCRIPTOR* libusb_udev_complete_msconfig_setup(IUDEVICE* id const LIBUSB_ENDPOINT_DESCEIPTOR* LibusbEndpoint; BYTE LibusbNumEndpoint; int inum = 0, pnum = 0, MsOutSize = 0; - LibusbConfig = pdev->LibusbConfig; + if (LibusbConfig->bNumInterfaces != MsConfig->NumInterfaces) { WLog_ERR(TAG, "Select Configuration: Libusb NumberInterfaces(%"PRIu8") is different " - "with MsConfig NumberInterfaces(%"PRIu32")", - LibusbConfig->bNumInterfaces, MsConfig->NumInterfaces); + "with MsConfig NumberInterfaces(%"PRIu32")", + LibusbConfig->bNumInterfaces, MsConfig->NumInterfaces); } /* replace MsPipes for libusb */ MsInterfaces = MsConfig->MsInterfaces; + for (inum = 0; inum < MsConfig->NumInterfaces; inum++) { MsInterface = MsInterfaces[inum]; @@ -763,7 +785,7 @@ static MSUSB_CONFIG_DESCRIPTOR* libusb_udev_complete_msconfig_setup(IUDEVICE* id for (pnum = 0; pnum < LibusbNumEndpoint; pnum++) { - t_MsPipe = (MSUSB_PIPE_DESCRIPTOR *) malloc (sizeof(MSUSB_PIPE_DESCRIPTOR)); + t_MsPipe = (MSUSB_PIPE_DESCRIPTOR*) malloc(sizeof(MSUSB_PIPE_DESCRIPTOR)); memset(t_MsPipe, 0, sizeof(MSUSB_PIPE_DESCRIPTOR)); if (pnum < MsInterface->NumberOfPipes && MsInterface->MsPipes) @@ -779,18 +801,18 @@ static MSUSB_CONFIG_DESCRIPTOR* libusb_udev_complete_msconfig_setup(IUDEVICE* id t_MsPipe->MaximumTransferSize = 0xffffffff; t_MsPipe->PipeFlags = 0; } - + t_MsPipe->PipeHandle = 0; t_MsPipe->bEndpointAddress = 0; t_MsPipe->bInterval = 0; t_MsPipe->PipeType = 0; t_MsPipe->InitCompleted = 0; - t_MsPipes[pnum] = t_MsPipe; } msusb_mspipes_replace(MsInterface, t_MsPipes, LibusbNumEndpoint); } + /* setup configuration */ MsOutSize = 8; /* ConfigurationHandle: 4 bytes @@ -799,37 +821,36 @@ static MSUSB_CONFIG_DESCRIPTOR* libusb_udev_complete_msconfig_setup(IUDEVICE* id * || bus_number | dev_number | bConfigurationValue || * --------------------------------------------------------------- * ***********************/ - MsConfig->ConfigurationHandle = MsConfig->bConfigurationValue | - (pdev->bus_number << 24) | - (pdev->dev_number << 16); - + MsConfig->ConfigurationHandle = MsConfig->bConfigurationValue | + (pdev->bus_number << 24) | + (pdev->dev_number << 16); MsInterfaces = MsConfig->MsInterfaces; + for (inum = 0; inum < MsConfig->NumInterfaces; inum++) { MsOutSize += 16; MsInterface = MsInterfaces[inum]; /* get libusb's interface */ LibusbInterface = &LibusbConfig->interface[MsInterface->InterfaceNumber]; - LibusbAltsetting = &LibusbInterface->altsetting[MsInterface->AlternateSetting]; + LibusbAltsetting = &LibusbInterface->altsetting[MsInterface->AlternateSetting]; /* InterfaceHandle: 4 bytes * --------------------------------------------------------------- * ||<<< 1 byte >>>|<<< 1 byte >>>|<<< 1 byte >>>|<<< 1 byte >>>|| * || bus_number | dev_number | altsetting | interfaceNum || * --------------------------------------------------------------- * ***********************/ - MsInterface->InterfaceHandle = LibusbAltsetting->bInterfaceNumber - | (LibusbAltsetting->bAlternateSetting << 8) - | (pdev->dev_number << 16) - | (pdev->bus_number << 24); - + MsInterface->InterfaceHandle = LibusbAltsetting->bInterfaceNumber + | (LibusbAltsetting->bAlternateSetting << 8) + | (pdev->dev_number << 16) + | (pdev->bus_number << 24); MsInterface->Length = 16 + (MsInterface->NumberOfPipes * 20); MsInterface->bInterfaceClass = LibusbAltsetting->bInterfaceClass; MsInterface->bInterfaceSubClass = LibusbAltsetting->bInterfaceSubClass; MsInterface->bInterfaceProtocol = LibusbAltsetting->bInterfaceProtocol; MsInterface->InitCompleted = 1; - MsPipes = MsInterface->MsPipes; LibusbNumEndpoint = LibusbAltsetting->bNumEndpoints; + for (pnum = 0; pnum < LibusbNumEndpoint; pnum++) { MsOutSize += 20; @@ -842,16 +863,18 @@ static MSUSB_CONFIG_DESCRIPTOR* libusb_udev_complete_msconfig_setup(IUDEVICE* id * || bus_number | dev_number | bEndpointAddress || * --------------------------------------------------------------- * ***********************/ - MsPipe->PipeHandle = LibusbEndpoint->bEndpointAddress - | (pdev->dev_number << 16) - | (pdev->bus_number << 24); + MsPipe->PipeHandle = LibusbEndpoint->bEndpointAddress + | (pdev->dev_number << 16) + | (pdev->bus_number << 24); /* count endpoint max packet size */ int max = LibusbEndpoint->wMaxPacketSize & 0x07ff; BYTE attr = LibusbEndpoint->bmAttributes; + if ((attr & 0x3) == 1 || (attr & 0x3) == 3) { max *= (1 + ((LibusbEndpoint->wMaxPacketSize >> 11) & 3)); } + MsPipe->MaximumPacketSize = max; MsPipe->bEndpointAddress = LibusbEndpoint->bEndpointAddress; MsPipe->bInterval = LibusbEndpoint->bInterval; @@ -859,6 +882,7 @@ static MSUSB_CONFIG_DESCRIPTOR* libusb_udev_complete_msconfig_setup(IUDEVICE* id MsPipe->InitCompleted = 1; } } + MsConfig->MsOutSize = MsOutSize; MsConfig->InitCompleted = 1; @@ -875,30 +899,35 @@ static MSUSB_CONFIG_DESCRIPTOR* libusb_udev_complete_msconfig_setup(IUDEVICE* id static int libusb_udev_select_configuration(IUDEVICE* idev, UINT32 bConfigurationValue) { UDEVICE* pdev = (UDEVICE*) idev; - MSUSB_CONFIG_DESCRIPTOR * MsConfig = pdev->MsConfig; - LIBUSB_DEVICE_HANDLE * libusb_handle = pdev->libusb_handle; - LIBUSB_DEVICE * libusb_dev = pdev->libusb_dev; - LIBUSB_CONFIG_DESCRIPTOR ** LibusbConfig = &pdev->LibusbConfig; + MSUSB_CONFIG_DESCRIPTOR* MsConfig = pdev->MsConfig; + LIBUSB_DEVICE_HANDLE* libusb_handle = pdev->libusb_handle; + LIBUSB_DEVICE* libusb_dev = pdev->libusb_dev; + LIBUSB_CONFIG_DESCRIPTOR** LibusbConfig = &pdev->LibusbConfig; int ret = 0; - if (MsConfig->InitCompleted){ + if (MsConfig->InitCompleted) + { func_config_release_all_interface(libusb_handle, (*LibusbConfig)->bNumInterfaces); } + /* The configuration value -1 is mean to put the device in unconfigured state. */ if (bConfigurationValue == 0) - ret = libusb_set_configuration(libusb_handle, -1); + ret = libusb_set_configuration(libusb_handle, -1); else - ret = libusb_set_configuration(libusb_handle, bConfigurationValue); + ret = libusb_set_configuration(libusb_handle, bConfigurationValue); - if (ret < 0){ + if (ret < 0) + { WLog_ERR(TAG, "libusb_set_configuration: ERROR number %d!!", ret); func_claim_all_interface(libusb_handle, (*LibusbConfig)->bNumInterfaces); return -1; } else { - ret = libusb_get_active_config_descriptor (libusb_dev, LibusbConfig); - if (ret < 0){ + ret = libusb_get_active_config_descriptor(libusb_dev, LibusbConfig); + + if (ret < 0) + { WLog_ERR(TAG, "libusb_get_config_descriptor_by_value: ERROR number %d!!", ret); func_claim_all_interface(libusb_handle, (*LibusbConfig)->bNumInterfaces); return -1; @@ -906,41 +935,41 @@ static int libusb_udev_select_configuration(IUDEVICE* idev, UINT32 bConfiguratio } func_claim_all_interface(libusb_handle, (*LibusbConfig)->bNumInterfaces); - return 0; } static int libusb_udev_control_pipe_request(IUDEVICE* idev, UINT32 RequestId, - UINT32 EndpointAddress, UINT32* UsbdStatus, int command) + UINT32 EndpointAddress, UINT32* UsbdStatus, int command) { int error = 0; UDEVICE* pdev = (UDEVICE*) idev; + /* pdev->request_queue->register_request(pdev->request_queue, RequestId, NULL, 0); */ - switch (command){ + switch (command) + { case PIPE_CANCEL: /** cancel bulk or int transfer */ idev->cancel_all_transfer_request(idev); - //dummy_wait_s_obj(1); /** set feature to ep (set halt)*/ - error = libusb_control_transfer(pdev->libusb_handle, - LIBUSB_ENDPOINT_OUT | LIBUSB_RECIPIENT_ENDPOINT, - LIBUSB_REQUEST_SET_FEATURE, - ENDPOINT_HALT, - EndpointAddress, - NULL, - 0, - 1000); + error = libusb_control_transfer(pdev->libusb_handle, + LIBUSB_ENDPOINT_OUT | LIBUSB_RECIPIENT_ENDPOINT, + LIBUSB_REQUEST_SET_FEATURE, + ENDPOINT_HALT, + EndpointAddress, + NULL, + 0, + 1000); break; + case PIPE_RESET: idev->cancel_all_transfer_request(idev); - error = libusb_clear_halt(pdev->libusb_handle, EndpointAddress); - //func_set_usbd_status(pdev, UsbdStatus, error); break; + default: error = -0xff; break; @@ -955,42 +984,46 @@ static int libusb_udev_control_pipe_request(IUDEVICE* idev, UINT32 RequestId, } static int libusb_udev_control_query_device_text(IUDEVICE* idev, UINT32 TextType, - UINT32 LocaleId, - UINT32 * BufferSize, - BYTE * Buffer) + UINT32 LocaleId, + UINT32* BufferSize, + BYTE* Buffer) { UDEVICE* pdev = (UDEVICE*) idev; - LIBUSB_DEVICE_DESCRIPTOR * devDescriptor = pdev->devDescriptor; - char * strDesc = "Generic Usb String"; + LIBUSB_DEVICE_DESCRIPTOR* devDescriptor = pdev->devDescriptor; + char* strDesc = "Generic Usb String"; char deviceLocation[25]; BYTE bus_number; BYTE device_address; int ret = 0, i = 0; - switch (TextType){ + switch (TextType) + { case DeviceTextDescription: - ret = libusb_get_string_descriptor (pdev->libusb_handle, - devDescriptor->iProduct, - LocaleId, - Buffer, - *BufferSize); + ret = libusb_get_string_descriptor(pdev->libusb_handle, + devDescriptor->iProduct, + LocaleId, + Buffer, + *BufferSize); - for(i = 0; i < ret; i++) + for (i = 0; i < ret; i++) { - Buffer[i] = Buffer[i+2]; + Buffer[i] = Buffer[i + 2]; } + ret -= 2; - - if (ret <= 0 || ret < 4){ - WLog_DBG(TAG,"libusb_get_string_descriptor: " - "ERROR num %d, iProduct: %"PRIu8"!", ret, devDescriptor->iProduct); + + if (ret <= 0 || ret < 4) + { + WLog_DBG(TAG, "libusb_get_string_descriptor: " + "ERROR num %d, iProduct: %"PRIu8"!", ret, devDescriptor->iProduct); memcpy(Buffer, strDesc, strlen(strDesc)); Buffer[strlen(strDesc)] = '\0'; - *BufferSize = (strlen((char *)Buffer)) * 2; - for (i = strlen((char *)Buffer); i > 0; i--) + *BufferSize = (strlen((char*)Buffer)) * 2; + + for (i = strlen((char*)Buffer); i > 0; i--) { - Buffer[i*2] = Buffer[i]; - Buffer[(i*2)-1] = 0; + Buffer[i * 2] = Buffer[i]; + Buffer[(i * 2) - 1] = 0; } } else @@ -999,20 +1032,24 @@ static int libusb_udev_control_query_device_text(IUDEVICE* idev, UINT32 TextType } break; + case DeviceTextLocationInformation: bus_number = libusb_get_bus_number(pdev->libusb_dev); device_address = libusb_get_device_address(pdev->libusb_dev); sprintf(deviceLocation, "Port_#%04"PRIu8".Hub_#%04"PRIu8"", device_address, bus_number); - for(i=0;irequest_queue->register_request(pdev->request_queue, RequestId, NULL, 0); */ memset(ms_string_desc, 0, 0x13); - error = libusb_control_transfer(pdev->libusb_handle, - LIBUSB_ENDPOINT_IN | Recipient, - LIBUSB_REQUEST_GET_DESCRIPTOR, - 0x03ee, - 0, - ms_string_desc, - 0x12, - Timeout); + error = libusb_control_transfer(pdev->libusb_handle, + LIBUSB_ENDPOINT_IN | Recipient, + LIBUSB_REQUEST_GET_DESCRIPTOR, + 0x03ee, + 0, + ms_string_desc, + 0x12, + Timeout); + //WLog_ERR(TAG, "Get ms string: result number %d", error); if (error > 0) { @@ -1051,14 +1089,14 @@ static int libusb_udev_os_feature_descriptor_request(IUDEVICE* idev, UINT32 Requ data_read_BYTE(ms_string_desc + 16, bMS_Vendorcode); //WLog_ERR(TAG, "bMS_Vendorcode:0x%x", bMS_Vendorcode); /** get os descriptor */ - error = libusb_control_transfer(pdev->libusb_handle, - LIBUSB_ENDPOINT_IN |LIBUSB_REQUEST_TYPE_VENDOR | Recipient, - bMS_Vendorcode, - (InterfaceNumber << 8) | Ms_PageIndex, - Ms_featureDescIndex, - Buffer, - *BufferSize, - Timeout); + error = libusb_control_transfer(pdev->libusb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | Recipient, + bMS_Vendorcode, + (InterfaceNumber << 8) | Ms_PageIndex, + Ms_featureDescIndex, + Buffer, + *BufferSize, + Timeout); *BufferSize = error; } @@ -1066,6 +1104,7 @@ static int libusb_udev_os_feature_descriptor_request(IUDEVICE* idev, UINT32 Requ *UsbdStatus = USBD_STATUS_STALL_PID; else *UsbdStatus = USBD_STATUS_SUCCESS; + /* if(pdev->request_queue->unregister_request(pdev->request_queue, RequestId)) WLog_ERR(TAG, "request_queue_unregister_request: not fount request 0x%x", RequestId); @@ -1081,35 +1120,50 @@ static int libusb_udev_query_device_descriptor(IUDEVICE* idev, int offset) { case B_LENGTH: return pdev->devDescriptor->bLength; + case B_DESCRIPTOR_TYPE: return pdev->devDescriptor->bDescriptorType; + case BCD_USB: return pdev->devDescriptor->bcdUSB; + case B_DEVICE_CLASS: return pdev->devDescriptor->bDeviceClass; + case B_DEVICE_SUBCLASS: return pdev->devDescriptor->bDeviceSubClass; + case B_DEVICE_PROTOCOL: return pdev->devDescriptor->bDeviceProtocol; + case B_MAX_PACKET_SIZE0: return pdev->devDescriptor->bMaxPacketSize0; + case ID_VENDOR: return pdev->devDescriptor->idVendor; + case ID_PRODUCT: return pdev->devDescriptor->idProduct; + case BCD_DEVICE: return pdev->devDescriptor->bcdDevice; + case I_MANUFACTURER: return pdev->devDescriptor->iManufacturer; + case I_PRODUCT: return pdev->devDescriptor->iProduct; + case I_SERIAL_NUMBER: return pdev->devDescriptor->iSerialNumber; + case B_NUM_CONFIGURATIONS: return pdev->devDescriptor->bNumConfigurations; + default: return 0; } + return 0; } @@ -1119,17 +1173,19 @@ static void libusb_udev_detach_kernel_driver(IUDEVICE* idev) UDEVICE* pdev = (UDEVICE*) idev; if ((pdev->status & URBDRC_DEVICE_DETACH_KERNEL) == 0) - { + { for (i = 0; i < pdev->LibusbConfig->bNumInterfaces; i++) { - err = libusb_kernel_driver_active(pdev->libusb_handle , i); - WLog_DBG(TAG,"libusb_kernel_driver_active = %d", err); - if (err){ - err = libusb_detach_kernel_driver(pdev->libusb_handle , i); - WLog_DBG(TAG,"libusb_detach_kernel_driver = %d", err); + err = libusb_kernel_driver_active(pdev->libusb_handle, i); + WLog_DBG(TAG, "libusb_kernel_driver_active = %d", err); + + if (err) + { + err = libusb_detach_kernel_driver(pdev->libusb_handle, i); + WLog_DBG(TAG, "libusb_detach_kernel_driver = %d", err); } } - + pdev->status |= URBDRC_DEVICE_DETACH_KERNEL; } } @@ -1141,15 +1197,18 @@ static void libusb_udev_attach_kernel_driver(IUDEVICE* idev) for (i = 0; i < pdev->LibusbConfig->bNumInterfaces && err != LIBUSB_ERROR_NO_DEVICE; i++) { - err = libusb_release_interface (pdev->libusb_handle, i); - if (err < 0){ - WLog_DBG(TAG,"libusb_release_interface: error num %d = %d", i, err); + err = libusb_release_interface(pdev->libusb_handle, i); + + if (err < 0) + { + WLog_DBG(TAG, "libusb_release_interface: error num %d = %d", i, err); } + if (err != LIBUSB_ERROR_NO_DEVICE) { - err = libusb_attach_kernel_driver (pdev->libusb_handle , i); - WLog_DBG(TAG,"libusb_attach_kernel_driver if%d = %d", i, err); - } + err = libusb_attach_kernel_driver(pdev->libusb_handle, i); + WLog_DBG(TAG, "libusb_attach_kernel_driver if%d = %d", i, err); + } } } @@ -1212,10 +1271,9 @@ static int libusb_udev_wait_action_completion(IUDEVICE* idev) int error, sval; UDEVICE* pdev = (UDEVICE*) idev; - while(1) + while (1) { usleep(500000); - error = sem_getvalue(&pdev->sem_id, &sval); if (sval == 0) @@ -1234,7 +1292,7 @@ static void libusb_udev_push_action(IUDEVICE* idev) static void libusb_udev_complete_action(IUDEVICE* idev) { UDEVICE* pdev = (UDEVICE*) idev; - sem_trywait(&pdev->sem_id); + sem_trywait(&pdev->sem_id); } static int libusb_udev_wait_for_detach(IUDEVICE* idev) @@ -1261,7 +1319,7 @@ static int libusb_udev_wait_for_detach(IUDEVICE* idev) static void libusb_udev_lock_fifo_isoch(IUDEVICE* idev) { UDEVICE* pdev = (UDEVICE*) idev; - pthread_mutex_lock(&pdev->mutex_isoch); + pthread_mutex_lock(&pdev->mutex_isoch); } static void libusb_udev_unlock_fifo_isoch(IUDEVICE* idev) @@ -1270,30 +1328,31 @@ static void libusb_udev_unlock_fifo_isoch(IUDEVICE* idev) pthread_mutex_unlock(&pdev->mutex_isoch); } -static int libusb_udev_query_device_port_status(IUDEVICE* idev, UINT32* UsbdStatus, UINT32* BufferSize, BYTE* Buffer) +static int libusb_udev_query_device_port_status(IUDEVICE* idev, UINT32* UsbdStatus, + UINT32* BufferSize, BYTE* Buffer) { UDEVICE* pdev = (UDEVICE*) idev; int success = 0, ret; + WLog_DBG(TAG, "..."); - WLog_DBG(TAG,"..."); if (pdev->hub_handle != NULL) { - ret = idev->control_transfer(idev, 0xffff, 0, 0, - LIBUSB_ENDPOINT_IN - | LIBUSB_REQUEST_TYPE_CLASS - | LIBUSB_RECIPIENT_OTHER, - LIBUSB_REQUEST_GET_STATUS, - 0, pdev->port_number, UsbdStatus, BufferSize, Buffer, 1000); + ret = idev->control_transfer(idev, 0xffff, 0, 0, + LIBUSB_ENDPOINT_IN + | LIBUSB_REQUEST_TYPE_CLASS + | LIBUSB_RECIPIENT_OTHER, + LIBUSB_REQUEST_GET_STATUS, + 0, pdev->port_number, UsbdStatus, BufferSize, Buffer, 1000); if (ret < 0) { - WLog_DBG(TAG,"libusb_control_transfer: error num %d", ret); + WLog_DBG(TAG, "libusb_control_transfer: error num %d", ret); *BufferSize = 0; } else { - WLog_DBG(TAG,"PORT STATUS:0x%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"", - Buffer[3], Buffer[2], Buffer[1], Buffer[0]); + WLog_DBG(TAG, "PORT STATUS:0x%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"", + Buffer[3], Buffer[2], Buffer[1], Buffer[0]); success = 1; } } @@ -1312,18 +1371,16 @@ static int libusb_udev_request_queue_is_none(IUDEVICE* idev) } static int libusb_udev_isoch_transfer(IUDEVICE* idev, UINT32 RequestId, UINT32 EndpointAddress, - UINT32 TransferFlags, int NoAck, UINT32* ErrorCount, - UINT32* UrbdStatus, UINT32* StartFrame, UINT32 NumberOfPackets, - BYTE* IsoPacket, UINT32* BufferSize, BYTE* Buffer, int Timeout) + UINT32 TransferFlags, int NoAck, UINT32* ErrorCount, + UINT32* UrbdStatus, UINT32* StartFrame, UINT32 NumberOfPackets, + BYTE* IsoPacket, UINT32* BufferSize, BYTE* Buffer, int Timeout) { UINT32 iso_packet_size; UDEVICE* pdev = (UDEVICE*) idev; ISO_USER_DATA iso_user_data; struct libusb_transfer* iso_transfer = NULL; int status = 0, ret = 0, submit = 0; - iso_packet_size = *BufferSize / NumberOfPackets; - iso_transfer = libusb_alloc_transfer(NumberOfPackets); if (iso_transfer == NULL) @@ -1334,12 +1391,10 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, UINT32 RequestId, UINT32 E /** process URB_FUNCTION_IOSCH_TRANSFER */ func_iso_data_init(&iso_user_data, NumberOfPackets, *BufferSize, NoAck, IsoPacket, Buffer); - /** fill setting */ - libusb_fill_iso_transfer(iso_transfer, - pdev->libusb_handle, EndpointAddress, Buffer, *BufferSize, - NumberOfPackets, func_iso_callback, &iso_user_data, 2000); - + libusb_fill_iso_transfer(iso_transfer, + pdev->libusb_handle, EndpointAddress, Buffer, *BufferSize, + NumberOfPackets, func_iso_callback, &iso_user_data, 2000); libusb_set_iso_packet_lengths(iso_transfer, iso_packet_size); if (pdev->status & (URBDRC_DEVICE_SIGNAL_END | URBDRC_DEVICE_NOT_FOUND)) @@ -1353,38 +1408,47 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, UINT32 RequestId, UINT32 E if (submit < 0) { - WLog_DBG(TAG,"Error: Failed to submit transfer (ret = %d).", submit); + WLog_DBG(TAG, "Error: Failed to submit transfer (ret = %d).", submit); status = -1; - func_set_usbd_status(pdev, UrbdStatus, ret); + func_set_usbd_status(pdev, UrbdStatus, ret); } } #if ISOCH_FIFO + if (!NoAck) { idev->unlock_fifo_isoch(idev); } + #endif - while(pdev && iso_user_data.iso_status == 0 && status >= 0 && submit >= 0) + while (pdev && iso_user_data.iso_status == 0 && status >= 0 && submit >= 0) { - if (pdev->status & URBDRC_DEVICE_NOT_FOUND){ + if (pdev->status & URBDRC_DEVICE_NOT_FOUND) + { status = -1; break; } + ret = handle_events_completed(NULL, &iso_user_data.completed); - if (ret < 0) { - WLog_DBG(TAG,"Error: libusb_handle_events (ret = %d).", ret); + + if (ret < 0) + { + WLog_DBG(TAG, "Error: libusb_handle_events (ret = %d).", ret); status = -1; break; } + #if WAIT_COMPLETE_SLEEP + if (iso_user_data.iso_status == 0) { usleep(WAIT_COMPLETE_SLEEP); } + #endif - } + } if (iso_user_data.iso_status < 0) status = -1; @@ -1393,30 +1457,28 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, UINT32 RequestId, UINT32 E *StartFrame = iso_user_data.start_frame; *BufferSize = iso_transfer->actual_length; libusb_free_transfer(iso_transfer); - return status; } static int libusb_udev_control_transfer(IUDEVICE* idev, UINT32 RequestId, UINT32 EndpointAddress, - UINT32 TransferFlags, BYTE bmRequestType, BYTE Request, UINT16 Value, UINT16 Index, - UINT32* UrbdStatus, UINT32* BufferSize, BYTE* Buffer, UINT32 Timeout) + UINT32 TransferFlags, BYTE bmRequestType, BYTE Request, UINT16 Value, UINT16 Index, + UINT32* UrbdStatus, UINT32* BufferSize, BYTE* Buffer, UINT32 Timeout) { int status = 0; UDEVICE* pdev = (UDEVICE*) idev; - - status = libusb_control_transfer(pdev->libusb_handle, - bmRequestType, Request, Value, Index, Buffer, *BufferSize, Timeout); + status = libusb_control_transfer(pdev->libusb_handle, + bmRequestType, Request, Value, Index, Buffer, *BufferSize, Timeout); if (!(status < 0)) *BufferSize = status; - func_set_usbd_status(pdev, UrbdStatus, status); - + func_set_usbd_status(pdev, UrbdStatus, status); return status; } static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, UINT32 RequestId, - UINT32 EndpointAddress, UINT32 TransferFlags, UINT32* UsbdStatus, UINT32* BufferSize, BYTE* Buffer, UINT32 Timeout) + UINT32 EndpointAddress, UINT32 TransferFlags, UINT32* UsbdStatus, UINT32* BufferSize, BYTE* Buffer, + UINT32 Timeout) { UINT32 transfer_type; UDEVICE* pdev = (UDEVICE*) idev; @@ -1425,10 +1487,8 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, UINT32 Request TRANSFER_REQUEST* request = NULL; int completed = 0, status = 0, submit = 0; int transferDir = EndpointAddress & 0x80; - /* alloc memory for urb transfer */ - transfer = libusb_alloc_transfer(0); - + transfer = libusb_alloc_transfer(0); ep_desc = func_get_ep_desc(pdev->LibusbConfig, pdev->MsConfig, EndpointAddress); if (!ep_desc) @@ -1436,11 +1496,11 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, UINT32 Request WLog_ERR(TAG, "func_get_ep_desc: endpoint 0x%"PRIx32" is not found!!", EndpointAddress); return -1; } - transfer_type = (ep_desc->bmAttributes) & 0x3; - WLog_DBG(TAG,"urb_bulk_or_interrupt_transfer: ep:0x%"PRIx32" " - "transfer_type %"PRIu32" flag:%"PRIu32" OutputBufferSize:0x%"PRIx32"", - EndpointAddress, transfer_type, TransferFlags, *BufferSize); + transfer_type = (ep_desc->bmAttributes) & 0x3; + WLog_DBG(TAG, "urb_bulk_or_interrupt_transfer: ep:0x%"PRIx32" " + "transfer_type %"PRIu32" flag:%"PRIu32" OutputBufferSize:0x%"PRIx32"", + EndpointAddress, transfer_type, TransferFlags, *BufferSize); switch (transfer_type) { @@ -1450,52 +1510,53 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, UINT32 Request break; case INTERRUPT_TRANSFER: + /** Interrupt Transfer */ - /** Sometime, we may have receive a oversized transfer request, - * it make submit urb return error, so we set the length of - * request to wMaxPacketSize */ + /** Sometime, we may have receive a oversized transfer request, + * it make submit urb return error, so we set the length of + * request to wMaxPacketSize */ if (*BufferSize != (ep_desc->wMaxPacketSize)) { - WLog_DBG(TAG,"Interrupt Transfer(%s): " - "BufferSize is different than maxPacketsize(0x%x)", - ((transferDir)?"IN":"OUT"), ep_desc->wMaxPacketSize); - if((*BufferSize) > (ep_desc->wMaxPacketSize) && - transferDir == USBD_TRANSFER_DIRECTION_IN) + WLog_DBG(TAG, "Interrupt Transfer(%s): " + "BufferSize is different than maxPacketsize(0x%x)", + ((transferDir) ? "IN" : "OUT"), ep_desc->wMaxPacketSize); + + if ((*BufferSize) > (ep_desc->wMaxPacketSize) && + transferDir == USBD_TRANSFER_DIRECTION_IN) (*BufferSize) = ep_desc->wMaxPacketSize; } + Timeout = 0; break; default: - WLog_DBG(TAG,"urb_bulk_or_interrupt_transfer:" + WLog_DBG(TAG, "urb_bulk_or_interrupt_transfer:" " other transfer type 0x%"PRIX32"", transfer_type); return -1; break; } libusb_fill_bulk_transfer(transfer, pdev->libusb_handle, EndpointAddress, - Buffer, *BufferSize, func_bulk_transfer_cb, &completed, Timeout); - + Buffer, *BufferSize, func_bulk_transfer_cb, &completed, Timeout); transfer->type = (unsigned char) transfer_type; - /** Bug fixed in libusb-1.0-8 later: issue of memory crash */ submit = libusb_submit_transfer(transfer); if (submit < 0) { - WLog_DBG(TAG,"libusb_bulk_transfer: error num %d", status); + WLog_DBG(TAG, "libusb_bulk_transfer: error num %d", status); func_set_usbd_status(pdev, UsbdStatus, status); *BufferSize = 0; } else { request = pdev->request_queue->register_request( - pdev->request_queue, RequestId, transfer, EndpointAddress); - request->submit = 1; + pdev->request_queue, RequestId, transfer, EndpointAddress); + request->submit = 1; } if ((pdev && *UsbdStatus == 0) && (submit >= 0) && - (pdev->iface.isSigToEnd((IUDEVICE*) pdev) == 0)) + (pdev->iface.isSigToEnd((IUDEVICE*) pdev) == 0)) { while (!completed) { @@ -1512,16 +1573,23 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, UINT32 Request { if (handle_events_completed(NULL, &completed) < 0) break; + #if WAIT_COMPLETE_SLEEP + if (!completed) usleep(WAIT_COMPLETE_SLEEP); + #endif } + break; } + #if WAIT_COMPLETE_SLEEP + if (!completed) usleep(WAIT_COMPLETE_SLEEP); + #endif } @@ -1551,19 +1619,19 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, UINT32 Request func_set_usbd_status(pdev, UsbdStatus, LIBUSB_ERROR_OTHER); break; } - + *BufferSize = transfer->actual_length; } - WLog_DBG(TAG,"bulk or interrupt Transfer data size : 0x%"PRIx32"", *BufferSize); + + WLog_DBG(TAG, "bulk or interrupt Transfer data size : 0x%"PRIx32"", *BufferSize); if (request) { - if(pdev->request_queue->unregister_request(pdev->request_queue, RequestId)) + if (pdev->request_queue->unregister_request(pdev->request_queue, RequestId)) WLog_ERR(TAG, "request_queue_unregister_request: not fount request 0x%"PRIx32"", RequestId); } libusb_free_transfer(transfer); - return 0; } @@ -1573,18 +1641,16 @@ static void libusb_udev_cancel_all_transfer_request(IUDEVICE* idev) UDEVICE* pdev = (UDEVICE*) idev; REQUEST_QUEUE* request_queue = pdev->request_queue; TRANSFER_REQUEST* request = NULL; - pthread_mutex_lock(&request_queue->request_loading); - request_queue->rewind(request_queue); while (request_queue->has_next(request_queue)) { request = request_queue->get_next(request_queue); - + if ((!request) || (!request->transfer) || - (request->endpoint != request->transfer->endpoint) || - (request->transfer->endpoint == 0) || (request->submit != 1)) + (request->endpoint != request->transfer->endpoint) || + (request->transfer->endpoint == 0) || (request->submit != 1)) { continue; } @@ -1593,19 +1659,18 @@ static void libusb_udev_cancel_all_transfer_request(IUDEVICE* idev) if (status < 0) { - WLog_DBG(TAG,"libusb_cancel_transfer: error num %d!!", status); + WLog_DBG(TAG, "libusb_cancel_transfer: error num %d!!", status); } else { request->submit = -1; } - } pthread_mutex_unlock(&request_queue->request_loading); } -static int func_cancel_xact_request(TRANSFER_REQUEST *request) +static int func_cancel_xact_request(TRANSFER_REQUEST* request) { int status; @@ -1613,7 +1678,7 @@ static int func_cancel_xact_request(TRANSFER_REQUEST *request) return -1; if ((!request->transfer) || (request->endpoint != request->transfer->endpoint) || - (request->transfer->endpoint == 0) || (request->submit != 1)) + (request->transfer->endpoint == 0) || (request->submit != 1)) { return 0; } @@ -1622,14 +1687,14 @@ static int func_cancel_xact_request(TRANSFER_REQUEST *request) if (status < 0) { - WLog_DBG(TAG,"libusb_cancel_transfer: error num %d!!", status); + WLog_DBG(TAG, "libusb_cancel_transfer: error num %d!!", status); if (status == LIBUSB_ERROR_NOT_FOUND) - return -1; + return -1; } else { - WLog_DBG(TAG,"libusb_cancel_transfer: Success num:0x%x!!", request->RequestId); + WLog_DBG(TAG, "libusb_cancel_transfer: Success num:0x%x!!", request->RequestId); request->submit = -1; return 1; } @@ -1643,20 +1708,19 @@ static int libusb_udev_cancel_transfer_request(IUDEVICE* idev, UINT32 RequestId) REQUEST_QUEUE* request_queue = pdev->request_queue; TRANSFER_REQUEST* request = NULL; int status = 0, retry_times = 0; - cancel_retry: pthread_mutex_lock(&request_queue->request_loading); - request_queue->rewind(request_queue); while (request_queue->has_next(request_queue)) { request = request_queue->get_next(request_queue); + if (!request) continue; - WLog_DBG(TAG,"CancelId:0x%"PRIx32" RequestId:0x%x endpoint 0x%x!!", - RequestId, request->RequestId, request->endpoint); + WLog_DBG(TAG, "CancelId:0x%"PRIx32" RequestId:0x%x endpoint 0x%x!!", + RequestId, request->RequestId, request->endpoint); if (request->RequestId == (RequestId && retry_times <= 10)) { @@ -1676,17 +1740,17 @@ cancel_retry: { retry_times++; usleep(100000); - WLog_DBG(TAG,"urbdrc_process_cancel_request: go retry!!"); + WLog_DBG(TAG, "urbdrc_process_cancel_request: go retry!!"); goto cancel_retry; } else if ((status < 0) || (retry_times >= 10)) { /** END */ - WLog_DBG(TAG,"urbdrc_process_cancel_request: error go exit!!"); + WLog_DBG(TAG, "urbdrc_process_cancel_request: error go exit!!"); return -1; } - WLog_DBG(TAG,"urbdrc_process_cancel_request: success!!"); + WLog_DBG(TAG, "urbdrc_process_cancel_request: success!!"); return 0; } @@ -1696,17 +1760,16 @@ BASIC_STATE_FUNC_DEFINED(ReqCompletion, UINT32) BASIC_STATE_FUNC_DEFINED(bus_number, UINT16) BASIC_STATE_FUNC_DEFINED(dev_number, UINT16) BASIC_STATE_FUNC_DEFINED(port_number, int) -BASIC_STATE_FUNC_DEFINED(isoch_queue, void *) -BASIC_STATE_FUNC_DEFINED(MsConfig, MSUSB_CONFIG_DESCRIPTOR *) +BASIC_STATE_FUNC_DEFINED(isoch_queue, void*) +BASIC_STATE_FUNC_DEFINED(MsConfig, MSUSB_CONFIG_DESCRIPTOR*) -BASIC_POINT_FUNC_DEFINED(udev, void *) -BASIC_POINT_FUNC_DEFINED(prev, void *) -BASIC_POINT_FUNC_DEFINED(next, void *) +BASIC_POINT_FUNC_DEFINED(udev, void*) +BASIC_POINT_FUNC_DEFINED(prev, void*) +BASIC_POINT_FUNC_DEFINED(next, void*) static void udev_load_interface(UDEVICE* pdev) { /* load interface */ - /* Basic */ BASIC_STATE_FUNC_REGISTER(channel_id, pdev); BASIC_STATE_FUNC_REGISTER(UsbDevice, pdev); @@ -1716,11 +1779,9 @@ static void udev_load_interface(UDEVICE* pdev) BASIC_STATE_FUNC_REGISTER(port_number, pdev); BASIC_STATE_FUNC_REGISTER(isoch_queue, pdev); BASIC_STATE_FUNC_REGISTER(MsConfig, pdev); - BASIC_STATE_FUNC_REGISTER(p_udev, pdev); BASIC_STATE_FUNC_REGISTER(p_prev, pdev); BASIC_STATE_FUNC_REGISTER(p_next, pdev); - pdev->iface.isCompositeDevice = libusb_udev_is_composite_device; pdev->iface.isSigToEnd = libusb_udev_is_signal_end; pdev->iface.isExist = libusb_udev_is_exist; @@ -1730,12 +1791,10 @@ static void udev_load_interface(UDEVICE* pdev) pdev->iface.setAlreadySend = libusb_udev_set_already_send; pdev->iface.setChannelClosed = libusb_udev_channel_closed; pdev->iface.getPath = libusb_udev_get_path; - /* Transfer */ pdev->iface.isoch_transfer = libusb_udev_isoch_transfer; pdev->iface.control_transfer = libusb_udev_control_transfer; pdev->iface.bulk_or_interrupt_transfer = libusb_udev_bulk_or_interrupt_transfer; - pdev->iface.select_interface = libusb_udev_select_interface; pdev->iface.select_configuration = libusb_udev_select_configuration; pdev->iface.complete_msconfig_setup = libusb_udev_complete_msconfig_setup; @@ -1763,7 +1822,6 @@ static IUDEVICE* udev_init(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_number) LIBUSB_DEVICE_DESCRIPTOR* devDescriptor; LIBUSB_CONFIG_DESCRIPTOR* config_temp; LIBUSB_INTERFACE_DESCRIPTOR interface_temp; - /* Get HUB handle */ status = udev_get_hub_handle(pdev, bus_number, dev_number); @@ -1783,8 +1841,7 @@ static IUDEVICE* udev_init(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_number) } num = pdev->devDescriptor->bNumConfigurations; - - status = libusb_get_active_config_descriptor (pdev->libusb_dev, &pdev->LibusbConfig); + status = libusb_get_active_config_descriptor(pdev->libusb_dev, &pdev->LibusbConfig); if (status < 0) { @@ -1796,30 +1853,32 @@ static IUDEVICE* udev_init(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_number) config_temp = pdev->LibusbConfig; /* get the first interface and first altsetting */ interface_temp = config_temp->interface[0].altsetting[0]; - - WLog_DBG(TAG,"Regist Device: Vid: 0x%04"PRIX16" Pid: 0x%04"PRIX16"" - " InterfaceClass = 0x%02"PRIX8"", - pdev->devDescriptor->idVendor, - pdev->devDescriptor->idProduct, - interface_temp.bInterfaceClass); + WLog_DBG(TAG, "Registered Device: Vid: 0x%04"PRIX16" Pid: 0x%04"PRIX16"" + " InterfaceClass = 0x%02"PRIX8"", + pdev->devDescriptor->idVendor, + pdev->devDescriptor->idProduct, + interface_temp.bInterfaceClass); /* Denied list */ - switch(interface_temp.bInterfaceClass) + switch (interface_temp.bInterfaceClass) { case CLASS_RESERVE: + //case CLASS_COMMUNICATION_IF: //case CLASS_HID: //case CLASS_PHYSICAL: case CLASS_MASS_STORAGE: case CLASS_HUB: + //case CLASS_COMMUNICATION_DATA_IF: case CLASS_SMART_CARD: case CLASS_CONTENT_SECURITY: - //case CLASS_WIRELESS_CONTROLLER: - //case CLASS_ELSE_DEVICE: + //case CLASS_WIRELESS_CONTROLLER: + //case CLASS_ELSE_DEVICE: WLog_ERR(TAG, " Device is not supported!!"); zfree(pdev); return NULL; + default: break; } @@ -1828,14 +1887,14 @@ static IUDEVICE* udev_init(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_number) devDescriptor = pdev->devDescriptor; if ((devDescriptor->bNumConfigurations == 1) && - (config_temp->bNumInterfaces > 1) && - (devDescriptor->bDeviceClass == 0x0)) + (config_temp->bNumInterfaces > 1) && + (devDescriptor->bDeviceClass == 0x0)) { pdev->isCompositeDevice = 1; } else if ((devDescriptor->bDeviceClass == 0xef) && - (devDescriptor->bDeviceSubClass == 0x02) && - (devDescriptor->bDeviceProtocol == 0x01)) + (devDescriptor->bDeviceSubClass == 0x02) && + (devDescriptor->bDeviceProtocol == 0x01)) { pdev->isCompositeDevice = 1; } @@ -1844,11 +1903,10 @@ static IUDEVICE* udev_init(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_number) pdev->isCompositeDevice = 0; } - /* set device class to first interface class */ + /* set device class to first interface class */ devDescriptor->bDeviceClass = interface_temp.bInterfaceClass; devDescriptor->bDeviceSubClass = interface_temp.bInterfaceSubClass; devDescriptor->bDeviceProtocol = interface_temp.bInterfaceProtocol; - /* initialize pdev */ pdev->prev = NULL; pdev->next = NULL; @@ -1860,20 +1918,15 @@ static IUDEVICE* udev_init(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_number) pdev->request_queue = request_queue_new(); pdev->isoch_queue = NULL; sem_init(&pdev->sem_id, 0, 0); - /* set config of windows */ pdev->MsConfig = msusb_msconfig_new(); - pthread_mutex_init(&pdev->mutex_isoch, NULL); - - //deb_config_msg(pdev->libusb_dev, config_temp, devDescriptor->bNumConfigurations); - + //deb_config_msg(pdev->libusb_dev, config_temp, devDescriptor->bNumConfigurations); udev_load_interface(pdev); - return (IUDEVICE*) pdev; } -int udev_new_by_id(UINT16 idVendor, UINT16 idProduct, IUDEVICE*** devArray) +int udev_new_by_id(UINT16 idVendor, UINT16 idProduct, IUDEVICE** * devArray) { LIBUSB_DEVICE_DESCRIPTOR* descriptor; LIBUSB_DEVICE** libusb_list; @@ -1882,12 +1935,9 @@ int udev_new_by_id(UINT16 idVendor, UINT16 idProduct, IUDEVICE*** devArray) UINT16 dev_number; ssize_t i, total_device; int status, num = 0; - WLog_INFO(TAG, "VID: 0x%04"PRIX16", PID: 0x%04"PRIX16"", idVendor, idProduct); - array = (UDEVICE**) malloc(16 * sizeof(UDEVICE*)); - - total_device = libusb_get_device_list(NULL, &libusb_list); + total_device = libusb_get_device_list(NULL, &libusb_list); for (i = 0; i < total_device; i++) { @@ -1899,7 +1949,6 @@ int udev_new_by_id(UINT16 idVendor, UINT16 idProduct, IUDEVICE*** devArray) dev_number = 0; array[num] = (PUDEVICE) malloc(sizeof(UDEVICE)); array[num]->libusb_dev = libusb_list[i]; - status = libusb_open(libusb_list[i], &array[num]->libusb_handle); if (status < 0) @@ -1912,19 +1961,17 @@ int udev_new_by_id(UINT16 idVendor, UINT16 idProduct, IUDEVICE*** devArray) bus_number = libusb_get_bus_number(libusb_list[i]); dev_number = libusb_get_device_address(libusb_list[i]); - array[num] = (PUDEVICE) udev_init(array[num], bus_number, dev_number); if (array[num] != NULL) num++; } + zfree(descriptor); } libusb_free_device_list(libusb_list, 1); - *devArray = (IUDEVICE**) array; - return num; } @@ -1932,11 +1979,8 @@ IUDEVICE* udev_new_by_addr(int bus_number, int dev_number) { int status; UDEVICE* pDev; - - WLog_DBG(TAG,"bus:%d dev:%d", bus_number, dev_number); - + WLog_DBG(TAG, "bus:%d dev:%d", bus_number, dev_number); pDev = (PUDEVICE) malloc(sizeof(UDEVICE)); - pDev->libusb_dev = udev_get_libusb_dev(bus_number, dev_number); if (pDev->libusb_dev == NULL) diff --git a/channels/urbdrc/client/libusb/libusb_udevman.c b/channels/urbdrc/client/libusb/libusb_udevman.c index 311c278..2d15fed 100644 --- a/channels/urbdrc/client/libusb/libusb_udevman.c +++ b/channels/urbdrc/client/libusb/libusb_udevman.c @@ -35,16 +35,16 @@ int libusb_debug; #define BASIC_STATE_FUNC_DEFINED(_arg, _type) \ -static _type udevman_get_##_arg (IUDEVMAN* idevman) \ -{ \ - UDEVMAN * udevman = (UDEVMAN *) idevman; \ - return udevman->_arg; \ -} \ -static void udevman_set_##_arg (IUDEVMAN* idevman, _type _t) \ -{ \ - UDEVMAN * udevman = (UDEVMAN *) idevman; \ - udevman->_arg = _t; \ -} + static _type udevman_get_##_arg (IUDEVMAN* idevman) \ + { \ + UDEVMAN * udevman = (UDEVMAN *) idevman; \ + return udevman->_arg; \ + } \ + static void udevman_set_##_arg (IUDEVMAN* idevman, _type _t) \ + { \ + UDEVMAN * udevman = (UDEVMAN *) idevman; \ + udevman->_arg = _t; \ + } #define BASIC_STATE_FUNC_REGISTER(_arg, _man) \ _man->iface.get_##_arg = udevman_get_##_arg; \ @@ -90,17 +90,14 @@ static IUDEVICE* udevman_get_next(IUDEVMAN* idevman) { UDEVMAN* udevman = (UDEVMAN*) idevman; IUDEVICE* pdev; - pdev = udevman->idev; - udevman->idev = (IUDEVICE*) ((UDEVICE*) udevman->idev)->next; - + udevman->idev = (IUDEVICE*)((UDEVICE*) udevman->idev)->next; return pdev; } static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, int bus_number, int dev_number) { IUDEVICE* pdev; - idevman->loading_lock(idevman); idevman->rewind(idevman); @@ -117,23 +114,22 @@ static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, int bus_number, idevman->loading_unlock(idevman); WLog_WARN(TAG, "bus:%d dev:%d not exist in udevman", - bus_number, dev_number); + bus_number, dev_number); return NULL; } static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_number, - int UsbDevice, UINT16 idVendor, UINT16 idProduct, int flag) + int UsbDevice, UINT16 idVendor, UINT16 idProduct, int flag) { UDEVMAN* udevman = (UDEVMAN*) idevman; IUDEVICE* pdev = NULL; IUDEVICE** devArray; int i, num, addnum = 0; - pdev = (IUDEVICE*) udevman_get_udevice_by_addr(idevman, bus_number, dev_number); if (pdev != NULL) return 0; - + if (flag == UDEVMAN_FLAG_ADD_BY_ADDR) { pdev = udev_new_by_addr(bus_number, dev_number); @@ -171,8 +167,8 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n { pdev = devArray[i]; - if (udevman_get_udevice_by_addr(idevman, - pdev->get_bus_number(pdev), pdev->get_dev_number(pdev)) != NULL) + if (udevman_get_udevice_by_addr(idevman, + pdev->get_bus_number(pdev), pdev->get_dev_number(pdev)) != NULL) { zfree(pdev); continue; @@ -215,11 +211,9 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev_number) { UDEVMAN* udevman = (UDEVMAN*) idevman; - UDEVICE * pdev, * dev; + UDEVICE* pdev, * dev; int ret = 0, err = 0; - dev = (UDEVICE*) udevman_get_udevice_by_addr(idevman, bus_number, dev_number); - idevman->loading_lock(idevman); idevman->rewind(idevman); @@ -230,7 +224,6 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev if (pdev == dev) /* device exists */ { /* set previous device to point to next device */ - if (dev->prev != NULL) { /* unregistered device is not the head */ @@ -248,7 +241,7 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev if (dev->next != NULL) { /* unregistered device is not the tail */ - pdev = (UDEVICE *)dev->next; + pdev = (UDEVICE*)dev->next; pdev->prev = dev->prev; } else @@ -256,11 +249,12 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev /* unregistered device is the tail, update tail */ udevman->tail = (IUDEVICE*)dev->prev; } + udevman->device_num--; - - break; + break; } } + idevman->loading_unlock(idevman); if (dev) @@ -269,28 +263,31 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev if (err != LIBUSB_ERROR_NO_DEVICE) { ret = libusb_reset_device(dev->libusb_handle); - if (ret<0) + + if (ret < 0) { WLog_ERR(TAG, "libusb_reset_device: ERROR!!ret:%d", ret); } } - + /* release all interface and attach kernel driver */ - dev->iface.attach_kernel_driver((IUDEVICE*)dev); - - if(dev->request_queue) zfree(dev->request_queue); + dev->iface.attach_kernel_driver((IUDEVICE*)dev); + + if (dev->request_queue) zfree(dev->request_queue); + /* free the config descriptor that send from windows */ msusb_msconfig_free(dev->MsConfig); - - libusb_close (dev->libusb_handle); - libusb_close (dev->hub_handle); - + libusb_close(dev->libusb_handle); + libusb_close(dev->hub_handle); sem_destroy(&dev->sem_id); + /* free device info */ if (dev->devDescriptor) zfree(dev->devDescriptor); + if (dev) - zfree(dev); + zfree(dev); + return 1; /* unregistration successful */ } @@ -302,28 +299,22 @@ static void udevman_parse_device_addr(char* str, int* id1, int* id2, char sign) { char s1[8]; char* s2; - ZeroMemory(s1, sizeof(s1)); - - s2 = (strchr(str, sign)) + 1; + s2 = (strchr(str, sign)) + 1; strncpy(s1, str, strlen(str) - (strlen(s2) + 1)); - - *id1 = atoi(s1); - *id2 = atoi(s2); + *id1 = strtol(s1, NULL, 0); + *id2 = strtol(s2, NULL, 0); } static void udevman_parse_device_pid_vid(char* str, int* id1, int* id2, char sign) { char s1[8]; char* s2; - ZeroMemory(s1, sizeof(s1)); - - s2 = (strchr(str, sign)) + 1; + s2 = (strchr(str, sign)) + 1; strncpy(s1, str, strlen(str) - (strlen(s2) + 1)); - - *id1 = (int) strtol(s1, NULL, 16); - *id2 = (int) strtol(s2, NULL, 16); + *id1 = strtol(s1, NULL, 16); + *id2 = strtol(s2, NULL, 16); } static int udevman_check_device_exist_by_id(IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct) @@ -358,7 +349,6 @@ static IUDEVICE* udevman_get_udevice_by_UsbDevice_try_again(IUDEVMAN* idevman, U } idevman->loading_unlock(idevman); - return NULL; } @@ -380,9 +370,7 @@ static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbD } idevman->loading_unlock(idevman); - /* try again */ - pdev = (UDEVICE*) idevman->get_udevice_by_UsbDevice_try_again(idevman, UsbDevice); if (pdev) @@ -425,10 +413,8 @@ BASIC_STATE_FUNC_DEFINED(sem_timeout, int) static void udevman_free(IUDEVMAN* idevman) { UDEVMAN* udevman = (UDEVMAN*) idevman; - pthread_mutex_destroy(&udevman->devman_loading); sem_destroy(&udevman->sem_urb_lock); - libusb_exit(NULL); /* free udevman */ @@ -437,11 +423,10 @@ static void udevman_free(IUDEVMAN* idevman) zfree(udevman); } -static void udevman_load_interface(UDEVMAN * udevman) +static void udevman_load_interface(UDEVMAN* udevman) { /* standard */ udevman->iface.free = udevman_free; - /* manage devices */ udevman->iface.rewind = udevman_rewind; udevman->iface.get_next = udevman_get_next; @@ -449,18 +434,15 @@ static void udevman_load_interface(UDEVMAN * udevman) udevman->iface.register_udevice = udevman_register_udevice; udevman->iface.unregister_udevice = udevman_unregister_udevice; udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice; - udevman->iface.get_udevice_by_UsbDevice_try_again = - udevman_get_udevice_by_UsbDevice_try_again; - + udevman->iface.get_udevice_by_UsbDevice_try_again = + udevman_get_udevice_by_UsbDevice_try_again; /* Extension */ udevman->iface.check_device_exist_by_id = udevman_check_device_exist_by_id; udevman->iface.isAutoAdd = udevman_is_auto_add; - /* Basic state */ BASIC_STATE_FUNC_REGISTER(defUsbDevice, udevman); BASIC_STATE_FUNC_REGISTER(device_num, udevman); BASIC_STATE_FUNC_REGISTER(sem_timeout, udevman); - /* control semaphore or mutex lock */ udevman->iface.loading_lock = udevman_loading_lock; udevman->iface.loading_unlock = udevman_loading_unlock; @@ -502,7 +484,6 @@ static void urbdrc_udevman_register_devices(UDEVMAN* udevman, char* devices) dev_number = 0; idVendor = 0; idProduct = 0; - strcpy(hardware_id, token); token = strtok(NULL, "#"); @@ -510,14 +491,13 @@ static void urbdrc_udevman_register_devices(UDEVMAN* udevman, char* devices) { udevman_parse_device_pid_vid(hardware_id, &idVendor, &idProduct, ':'); success = udevman->iface.register_udevice((IUDEVMAN*) udevman, - 0, 0, UsbDevice, (UINT16) idVendor, (UINT16) idProduct, UDEVMAN_FLAG_ADD_BY_VID_PID); + 0, 0, UsbDevice, (UINT16) idVendor, (UINT16) idProduct, UDEVMAN_FLAG_ADD_BY_VID_PID); } else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR) { udevman_parse_device_addr(hardware_id, &bus_number, &dev_number, ':'); - success = udevman->iface.register_udevice((IUDEVMAN*) udevman, - bus_number, dev_number, UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR); + bus_number, dev_number, UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR); } if (success) @@ -532,12 +512,9 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args) int status; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; - status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, - urbdrc_udevman_args, flags, udevman, NULL, NULL); - + urbdrc_udevman_args, flags, udevman, NULL, NULL); arg = urbdrc_udevman_args; do @@ -546,7 +523,6 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args) continue; CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "dbg") { WLog_SetLogLevel(WLog_Get(TAG), WLOG_TRACE); @@ -569,9 +545,7 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args) } CommandLineSwitchDefault(arg) { - } - CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); @@ -587,34 +561,26 @@ int freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS p { UDEVMAN* udevman; ADDIN_ARGV* args = pEntryPoints->args; - libusb_init(NULL); - udevman = (PUDEVMAN) malloc(sizeof(UDEVMAN)); + if (!udevman) return -1; + udevman->device_num = 0; udevman->idev = NULL; udevman->head = NULL; - udevman->tail = NULL; + udevman->tail = NULL; udevman->sem_timeout = 0; udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID; - pthread_mutex_init(&udevman->devman_loading, NULL); sem_init(&udevman->sem_urb_lock, 0, MAX_URB_REQUSET_NUM); - /* load usb device service management */ udevman_load_interface(udevman); - /* set debug flag, to enable Debug message for usb data transfer */ - libusb_debug = 10; - urbdrc_udevman_parse_addin_args(udevman, args); - pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*) udevman); - WLog_DBG(TAG, "UDEVMAN device registered."); - return 0; } diff --git a/channels/urbdrc/client/urbdrc_main.c b/channels/urbdrc/client/urbdrc_main.c index 5410488..04aee67 100644 --- a/channels/urbdrc/client/urbdrc_main.c +++ b/channels/urbdrc/client/urbdrc_main.c @@ -24,6 +24,8 @@ #include #include #include +#include + #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) #include #include @@ -52,46 +54,42 @@ static int func_hardware_id_format(IUDEVICE* pdev, char(*HardwareIds)[DEVICE_HARDWARE_ID_SIZE]) { char str[DEVICE_HARDWARE_ID_SIZE]; - UINT16 idVendor, idProduct, bcdDevice; - + UINT16 idVendor, idProduct, bcdDevice; idVendor = (UINT16)pdev->query_device_descriptor(pdev, ID_VENDOR); idProduct = (UINT16)pdev->query_device_descriptor(pdev, ID_PRODUCT); bcdDevice = (UINT16)pdev->query_device_descriptor(pdev, BCD_DEVICE); - sprintf_s(str, sizeof(str), "USB\\VID_%04"PRIX16"&PID_%04"PRIX16"", idVendor, idProduct); - strcpy(HardwareIds[1], str); - + strcpy(HardwareIds[1], str); sprintf_s(str, sizeof(str), "%s&REV_%04"PRIX16"", HardwareIds[1], bcdDevice); strcpy(HardwareIds[0], str); - return 0; } -static int func_compat_id_format(IUDEVICE* pdev, char (*CompatibilityIds)[DEVICE_COMPATIBILITY_ID_SIZE]) +static int func_compat_id_format(IUDEVICE* pdev, + char (*CompatibilityIds)[DEVICE_COMPATIBILITY_ID_SIZE]) { char str[DEVICE_COMPATIBILITY_ID_SIZE]; UINT8 bDeviceClass, bDeviceSubClass, bDeviceProtocol; - bDeviceClass = (UINT8)pdev->query_device_descriptor(pdev, B_DEVICE_CLASS); bDeviceSubClass = (UINT8)pdev->query_device_descriptor(pdev, B_DEVICE_SUBCLASS); bDeviceProtocol = (UINT8)pdev->query_device_descriptor(pdev, B_DEVICE_PROTOCOL); - if(!(pdev->isCompositeDevice(pdev))) + if (!(pdev->isCompositeDevice(pdev))) { - sprintf_s(str, sizeof(str),"USB\\Class_%02"PRIX8"", bDeviceClass); + sprintf_s(str, sizeof(str), "USB\\Class_%02"PRIX8"", bDeviceClass); strcpy(CompatibilityIds[2], str); - sprintf_s(str, sizeof(str),"%s&SubClass_%02"PRIX8"", CompatibilityIds[2], bDeviceSubClass); + sprintf_s(str, sizeof(str), "%s&SubClass_%02"PRIX8"", CompatibilityIds[2], bDeviceSubClass); strcpy(CompatibilityIds[1], str); - sprintf_s(str, sizeof(str),"%s&Prot_%02"PRIX8"", CompatibilityIds[1], bDeviceProtocol); + sprintf_s(str, sizeof(str), "%s&Prot_%02"PRIX8"", CompatibilityIds[1], bDeviceProtocol); strcpy(CompatibilityIds[0], str); } else { - sprintf_s(str, sizeof(str),"USB\\DevClass_00"); + sprintf_s(str, sizeof(str), "USB\\DevClass_00"); strcpy(CompatibilityIds[2], str); - sprintf_s(str, sizeof(str),"%s&SubClass_00", CompatibilityIds[2]); + sprintf_s(str, sizeof(str), "%s&SubClass_00", CompatibilityIds[2]); strcpy(CompatibilityIds[1], str); - sprintf_s(str, sizeof(str),"%s&Prot_00", CompatibilityIds[1]); + sprintf_s(str, sizeof(str), "%s&Prot_00", CompatibilityIds[1]); strcpy(CompatibilityIds[0], str); } @@ -103,15 +101,12 @@ static void func_close_udevice(USB_SEARCHMAN* searchman, IUDEVICE* pdev) int idVendor = 0; int idProduct = 0; URBDRC_PLUGIN* urbdrc = searchman->urbdrc; - pdev->SigToEnd(pdev); idVendor = pdev->query_device_descriptor(pdev, ID_VENDOR); idProduct = pdev->query_device_descriptor(pdev, ID_PRODUCT); searchman->add(searchman, (UINT16) idVendor, (UINT16) idProduct); - pdev->cancel_all_transfer_request(pdev); pdev->wait_action_completion(pdev); - #if ISOCH_FIFO { /* free isoch queue */ @@ -121,10 +116,9 @@ static void func_close_udevice(USB_SEARCHMAN* searchman, IUDEVICE* pdev) isoch_queue->free(isoch_queue); } #endif - urbdrc->udevman->unregister_udevice(urbdrc->udevman, - pdev->get_bus_number(pdev), - pdev->get_dev_number(pdev)); + pdev->get_bus_number(pdev), + pdev->get_dev_number(pdev)); } static int fun_device_string_send_set(char* out_data, int out_offset, char* str) @@ -141,19 +135,16 @@ static int fun_device_string_send_set(char* out_data, int out_offset, char* str) data_write_UINT16(out_data + out_offset + offset, 0x0000); /* add "\0" */ offset += 2; - return offset + out_offset; } static int func_container_id_generate(IUDEVICE* pdev, char* strContainerId) { - char *p, *path; + char* p, *path; UINT8 containerId[17]; UINT16 idVendor, idProduct; - idVendor = (UINT16)pdev->query_device_descriptor(pdev, ID_VENDOR); idProduct = (UINT16)pdev->query_device_descriptor(pdev, ID_PRODUCT); - path = pdev->getPath(pdev); if (strlen(path) > 8) @@ -162,34 +153,30 @@ static int func_container_id_generate(IUDEVICE* pdev, char* strContainerId) p = path; ZeroMemory(containerId, sizeof(containerId)); - sprintf_s((char*)containerId, sizeof(containerId), "%04"PRIX16"%04"PRIX16"%s", idVendor, idProduct, p); - + sprintf_s((char*)containerId, sizeof(containerId), "%04"PRIX16"%04"PRIX16"%s", idVendor, idProduct, + p); /* format */ sprintf_s(strContainerId, DEVICE_CONTAINER_STR_SIZE, - "{%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"}", - containerId[0], containerId[1],containerId[2], containerId[3], - containerId[4], containerId[5], containerId[6], containerId[7], - containerId[8], containerId[9], containerId[10], containerId[11], - containerId[12], containerId[13], containerId[14], containerId[15]); - + "{%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"}", + containerId[0], containerId[1], containerId[2], containerId[3], + containerId[4], containerId[5], containerId[6], containerId[7], + containerId[8], containerId[9], containerId[10], containerId[11], + containerId[12], containerId[13], containerId[14], containerId[15]); return 0; } static int func_instance_id_generate(IUDEVICE* pdev, char* strInstanceId) { UINT8 instanceId[17]; - ZeroMemory(instanceId, sizeof(instanceId)); sprintf_s((char*)instanceId, sizeof(instanceId), "\\%s", pdev->getPath(pdev)); - /* format */ sprintf_s(strInstanceId, DEVICE_INSTANCE_STR_SIZE, - "%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"", - instanceId[0], instanceId[1],instanceId[2], instanceId[3], - instanceId[4], instanceId[5], instanceId[6], instanceId[7], - instanceId[8], instanceId[9], instanceId[10], instanceId[11], - instanceId[12], instanceId[13], instanceId[14], instanceId[15]); - + "%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"", + instanceId[0], instanceId[1], instanceId[2], instanceId[3], + instanceId[4], instanceId[5], instanceId[6], instanceId[7], + instanceId[8], instanceId[9], instanceId[10], instanceId[11], + instanceId[12], instanceId[13], instanceId[14], instanceId[15]); return 0; } @@ -209,16 +196,16 @@ static void func_lock_isoch_mutex(TRANSFER_DATA* transfer_data) data_read_UINT32(transfer_data->pBuffer + 4, FunctionId); if ((FunctionId == TRANSFER_IN_REQUEST || - FunctionId == TRANSFER_OUT_REQUEST) && - transfer_data->cbSize >= 16) + FunctionId == TRANSFER_OUT_REQUEST) && + transfer_data->cbSize >= 16) { data_read_UINT16(transfer_data->pBuffer + 14, URB_Function); if (URB_Function == URB_FUNCTION_ISOCH_TRANSFER && - transfer_data->cbSize >= 20) + transfer_data->cbSize >= 20) { data_read_UINT32(transfer_data->pBuffer + 16, RequestField); - noAck = (RequestField & 0x80000000)>>31; + noAck = (RequestField & 0x80000000) >> 31; if (!noAck) { @@ -237,21 +224,20 @@ static void func_lock_isoch_mutex(TRANSFER_DATA* transfer_data) * * @return 0 on success, otherwise a Win32 error code */ -static UINT urbdrc_process_capability_request(URBDRC_CHANNEL_CALLBACK* callback, char* data, UINT32 data_sizem, UINT32 MessageId) +static UINT urbdrc_process_capability_request(URBDRC_CHANNEL_CALLBACK* callback, char* data, + UINT32 data_sizem, UINT32 MessageId) { UINT32 InterfaceId; UINT32 Version; UINT32 out_size; - char * out_data; + char* out_data; UINT ret; - WLog_VRB(TAG, ""); data_read_UINT32(data + 0, Version); - - InterfaceId = ((STREAM_ID_NONE<<30) | CAPABILITIES_NEGOTIATOR); - + InterfaceId = ((STREAM_ID_NONE << 30) | CAPABILITIES_NEGOTIATOR); out_size = 16; - out_data = (char *) calloc(1, out_size); + out_data = (char*) calloc(1, out_size); + if (!out_data) return ERROR_OUTOFMEMORY; @@ -259,10 +245,8 @@ static UINT urbdrc_process_capability_request(URBDRC_CHANNEL_CALLBACK* callback, data_write_UINT32(out_data + 4, MessageId); /* message id */ data_write_UINT32(out_data + 8, Version); /* usb protocol version */ data_write_UINT32(out_data + 12, 0x00000000); /* HRESULT */ - ret = callback->channel->Write(callback->channel, out_size, (BYTE*) out_data, NULL); zfree(out_data); - return ret; } @@ -271,7 +255,8 @@ static UINT urbdrc_process_capability_request(URBDRC_CHANNEL_CALLBACK* callback, * * @return 0 on success, otherwise a Win32 error code */ -static UINT urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, char* data, UINT32 data_sizem, UINT32 MessageId) +static UINT urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, char* data, + UINT32 data_sizem, UINT32 MessageId) { UINT32 InterfaceId; UINT32 out_size; @@ -280,16 +265,14 @@ static UINT urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, cha UINT32 Capabilities; char* out_data; UINT ret; - WLog_VRB(TAG, ""); data_read_UINT32(data + 0, MajorVersion); data_read_UINT32(data + 4, MinorVersion); data_read_UINT32(data + 8, Capabilities); - - InterfaceId = ((STREAM_ID_PROXY<<30) | CLIENT_CHANNEL_NOTIFICATION); - + InterfaceId = ((STREAM_ID_PROXY << 30) | CLIENT_CHANNEL_NOTIFICATION); out_size = 24; out_data = (char*) calloc(1, out_size); + if (!out_data) return ERROR_OUTOFMEMORY; @@ -299,9 +282,8 @@ static UINT urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, cha data_write_UINT32(out_data + 12, MajorVersion); data_write_UINT32(out_data + 16, MinorVersion); data_write_UINT32(out_data + 20, Capabilities); /* capabilities version */ - ret = callback->channel->Write(callback->channel, out_size, (BYTE *)out_data, NULL); + ret = callback->channel->Write(callback->channel, out_size, (BYTE*)out_data, NULL); zfree(out_data); - return ret; } @@ -313,20 +295,15 @@ static int urdbrc_send_virtual_channel_add(IWTSVirtualChannel* channel, UINT32 M WLog_VRB(TAG, ""); assert(NULL != channel); assert(NULL != channel->Write); - - InterfaceId = ((STREAM_ID_PROXY<<30) | CLIENT_DEVICE_SINK); - + InterfaceId = ((STREAM_ID_PROXY << 30) | CLIENT_DEVICE_SINK); out_size = 12; out_data = (char*) malloc(out_size); memset(out_data, 0, out_size); - data_write_UINT32(out_data + 0, InterfaceId); /* interface */ data_write_UINT32(out_data + 4, MessageId); /* message id */ data_write_UINT32(out_data + 8, ADD_VIRTUAL_CHANNEL); /* function id */ - channel->Write(channel, out_size, (BYTE*) out_data, NULL); zfree(out_data); - return 0; } @@ -345,45 +322,41 @@ static UINT urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVI char strInstanceId[DEVICE_INSTANCE_STR_SIZE]; char* composite_str = "USB\\COMPOSITE"; int size, out_offset, cchCompatIds, bcdUSB; - ISOCH_CALLBACK_QUEUE *cb_queue; + ISOCH_CALLBACK_QUEUE* cb_queue; UINT ret; - WLog_VRB(TAG, ""); - InterfaceId = ((STREAM_ID_PROXY<<30) | CLIENT_DEVICE_SINK); - + InterfaceId = ((STREAM_ID_PROXY << 30) | CLIENT_DEVICE_SINK); /* USB kernel driver detach!! */ pdev->detach_kernel_driver(pdev); - #if ISOCH_FIFO /* create/initial isoch queue */ cb_queue = isoch_queue_new(); + if (!cb_queue) return ERROR_OUTOFMEMORY; - pdev->set_isoch_queue(pdev, (void *)cb_queue); -#endif + pdev->set_isoch_queue(pdev, (void*)cb_queue); +#endif func_hardware_id_format(pdev, HardwareIds); func_compat_id_format(pdev, CompatibilityIds); func_instance_id_generate(pdev, strInstanceId); func_container_id_generate(pdev, strContainerId); - cchCompatIds = strlen(CompatibilityIds[0]) + 1 + - strlen(CompatibilityIds[1]) + 1 + - strlen(CompatibilityIds[2]) + 2; + strlen(CompatibilityIds[1]) + 1 + + strlen(CompatibilityIds[2]) + 2; if (pdev->isCompositeDevice(pdev)) - cchCompatIds += strlen(composite_str)+1; + cchCompatIds += strlen(composite_str) + 1; out_offset = 24; size = 24; + size += (strlen(strInstanceId) + 1) * 2 + + (strlen(HardwareIds[0]) + 1) * 2 + 4 + + (strlen(HardwareIds[1]) + 1) * 2 + 2 + + 4 + (cchCompatIds) * 2 + + (strlen(strContainerId) + 1) * 2 + 4 + 28; + out_data = (char*)calloc(1, size); - size += (strlen(strInstanceId)+1) * 2 + - (strlen(HardwareIds[0]) + 1) * 2 + 4 + - (strlen(HardwareIds[1]) + 1) * 2 + 2 + - 4 + (cchCompatIds) * 2 + - (strlen(strContainerId) + 1) * 2 + 4 + 28; - - out_data = (char *)calloc(1, size); if (!out_data) return ERROR_OUTOFMEMORY; @@ -393,9 +366,7 @@ static UINT urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVI data_write_UINT32(out_data + 12, 0x00000001); /* NumUsbDevice */ data_write_UINT32(out_data + 16, pdev->get_UsbDevice(pdev)); /* UsbDevice */ data_write_UINT32(out_data + 20, 0x00000025); /* cchDeviceInstanceId */ - out_offset = fun_device_string_send_set(out_data, out_offset, strInstanceId); - data_write_UINT32(out_data + out_offset, 0x00000036); /* cchHwIds */ out_offset += 4; /* HardwareIds 1 */ @@ -404,7 +375,6 @@ static UINT urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVI out_offset = fun_device_string_send_set(out_data, out_offset, HardwareIds[1]); /*data_write_UINT16(out_data + out_offset, 0x0000);*/ /* add "\0" */ out_offset += 2; - data_write_UINT32(out_data + out_offset, cchCompatIds); /* cchCompatIds */ out_offset += 4; /* CompatibilityIds 1 */ @@ -419,33 +389,30 @@ static UINT urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVI /*data_write_UINT16(out_data + out_offset, 0x0000);*/ /* add "\0" */ out_offset += 2; - data_write_UINT32(out_data + out_offset, 0x00000027); /* cchContainerId */ out_offset += 4; /* ContainerId */ out_offset = fun_device_string_send_set(out_data, out_offset, strContainerId); - /* USB_DEVICE_CAPABILITIES 28 bytes */ data_write_UINT32(out_data + out_offset, 0x0000001c); /* CbSize */ data_write_UINT32(out_data + out_offset + 4, 2); /* UsbBusInterfaceVersion, 0 ,1 or 2 */ data_write_UINT32(out_data + out_offset + 8, 0x600); /* USBDI_Version, 0x500 or 0x600 */ - /* Supported_USB_Version, 0x110,0x110 or 0x200(usb2.0) */ bcdUSB = pdev->query_device_descriptor(pdev, BCD_USB); data_write_UINT32(out_data + out_offset + 12, bcdUSB); - data_write_UINT32(out_data + out_offset + 16, 0x00000000); /* HcdCapabilities, MUST always be zero */ + data_write_UINT32(out_data + out_offset + 16, + 0x00000000); /* HcdCapabilities, MUST always be zero */ if (bcdUSB < 0x200) data_write_UINT32(out_data + out_offset + 20, 0x00000000); /* DeviceIsHighSpeed */ else data_write_UINT32(out_data + out_offset + 20, 0x00000001); /* DeviceIsHighSpeed */ - data_write_UINT32(out_data + out_offset + 24, 0x50); /* NoAckIsochWriteJitterBufferSizeInMs, >=10 or <=512 */ + data_write_UINT32(out_data + out_offset + 24, + 0x50); /* NoAckIsochWriteJitterBufferSizeInMs, >=10 or <=512 */ out_offset += 28; - - ret = callback->channel->Write(callback->channel, out_offset, (BYTE *)out_data, NULL); + ret = callback->channel->Write(callback->channel, out_offset, (BYTE*)out_data, NULL); zfree(out_data); - return ret; } @@ -454,13 +421,12 @@ static UINT urdbrc_send_usb_device_add(URBDRC_CHANNEL_CALLBACK* callback, IUDEVI * * @return 0 on success, otherwise a Win32 error code */ -static UINT urbdrc_exchange_capabilities(URBDRC_CHANNEL_CALLBACK* callback, char* pBuffer, UINT32 cbSize) +static UINT urbdrc_exchange_capabilities(URBDRC_CHANNEL_CALLBACK* callback, char* pBuffer, + UINT32 cbSize) { UINT32 MessageId; UINT32 FunctionId; - UINT error = CHANNEL_RC_OK; - data_read_UINT32(pBuffer + 0, MessageId); data_read_UINT32(pBuffer + 4, FunctionId); @@ -471,7 +437,7 @@ static UINT urbdrc_exchange_capabilities(URBDRC_CHANNEL_CALLBACK* callback, char break; default: - WLog_ERR(TAG, "unknown FunctionId 0x%"PRIX32"", FunctionId); + WLog_ERR(TAG, "%s: unknown FunctionId 0x%"PRIX32"", __FUNCTION__, FunctionId); error = ERROR_NOT_FOUND; break; } @@ -480,15 +446,19 @@ static UINT urbdrc_exchange_capabilities(URBDRC_CHANNEL_CALLBACK* callback, char } #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) -static char *devd_get_val(char *buf, size_t buf_size, const char *val_name, size_t val_name_size, size_t *val_size) { - char *ret, *buf_end, *ptr; - +static char* devd_get_val(char* buf, size_t buf_size, const char* val_name, size_t val_name_size, + size_t* val_size) +{ + char* ret, *buf_end, *ptr; buf_end = (buf + buf_size); + for (ret = buf; ret != NULL && ret < buf_end;) { ret = memmem(ret, (buf_end - ret), val_name, val_name_size); + if (ret == NULL) return NULL; + /* Found. */ /* Check: space before or buf+1. */ if ((buf + 1) < ret && ret[-1] != ' ') @@ -496,58 +466,68 @@ static char *devd_get_val(char *buf, size_t buf_size, const char *val_name, size ret += val_name_size; continue; } + /* Check: = after name and size for value. */ ret += val_name_size; + if ((ret + 1) >= buf_end) return NULL; + if (ret[0] != '=') continue; + ret ++; break; } + if (ret == NULL || val_size == NULL) return ret; + /* Calc value data size. */ ptr = memchr(ret, ' ', (buf_end - ret)); + if (ptr == NULL) /* End of string/last value. */ ptr = buf_end; + (*val_size) = (ptr - ret); return ret; } -static void *urbdrc_search_usb_device(void *arg) { - USB_SEARCHMAN *searchman = (USB_SEARCHMAN*)arg; - URBDRC_PLUGIN *urbdrc = (URBDRC_PLUGIN*)searchman->urbdrc; - IUDEVMAN *udevman = urbdrc->udevman; - IWTSVirtualChannelManager *channel_mgr = urbdrc->listener_callback->channel_mgr; - IWTSVirtualChannel *dvc_channel; - USB_SEARCHDEV *sdev; - IUDEVICE *pdev; +static void* urbdrc_search_usb_device(void* arg) +{ + USB_SEARCHMAN* searchman = (USB_SEARCHMAN*)arg; + URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)searchman->urbdrc; + IUDEVMAN* udevman = urbdrc->udevman; + IWTSVirtualChannelManager* channel_mgr = urbdrc->listener_callback->channel_mgr; + IWTSVirtualChannel* dvc_channel; + USB_SEARCHDEV* sdev; + IUDEVICE* pdev; HANDLE listobj[2]; HANDLE mon_fd; int devd_skt; char buf[4096], *val, *ptr, *end_val; ssize_t data_size; size_t val_size, tm; - int idVendor, idProduct; - int busnum, devnum; + long idVendor, idProduct; + long busnum, devnum; int action, success, error, found, on_close; struct sockaddr_un sun; DWORD status; UINT32 error; - WLog_DBG(TAG, "urbdrc_search_usb_device - devd: start"); - devd_skt = socket(PF_LOCAL, SOCK_SEQPACKET, 0); + if (devd_skt == -1) { WLog_ERR(TAG, "Can't create devd socket: error = %i", errno); goto err_out; } + memset(&sun, 0, sizeof(sun)); sun.sun_family = PF_LOCAL; sun.sun_len = sizeof(sun); strlcpy(sun.sun_path, "/var/run/devd.seqpacket.pipe", sizeof(sun.sun_path)); + if (-1 == connect(devd_skt, (struct sockaddr*)&sun, sizeof(sun))) { WLog_ERR(TAG, "Can't connect devd socket: error = %i - %s", errno, strerror(errno)); @@ -562,185 +542,221 @@ static void *urbdrc_search_usb_device(void *arg) { while (WaitForMultipleObjects(2, listobj, FALSE, INFINITE) != WAIT_OBJECT_0) { + status = WaitForMultipleObjects(2, listobj, FALSE, INFINITE); - status = WaitForMultipleObjects(2, listobj, FALSE, INFINITE); + if (status == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); + return 0; + } - if (status == WAIT_FAILED) - { - error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); - return 0; - } - - if (status == WAIT_OBJECT_0) - break; + if (status == WAIT_OBJECT_0) + break; + errno = 0; WLog_DBG(TAG, "======= SEARCH ======= "); - /* !system=USB subsystem=DEVICE type=ATTACH ugen=ugen3.3 cdev=ugen3.3 vendor=0x046d product=0x082d devclass=0xef devsubclass=0x02 sernum="6E7D726F" release=0x0011 mode=host port=4 parent=ugen3.1 */ /* !system=USB subsystem=DEVICE type=DETACH ugen=ugen3.3 cdev=ugen3.3 vendor=0x046d product=0x082d devclass=0xef devsubclass=0x02 sernum="6E7D726F" release=0x0011 mode=host port=4 parent=ugen3.1 */ data_size = read(devd_skt, buf, (sizeof(buf) - 1)); + if (data_size == -1) { WLog_ERR(TAG, "devd socket read: error = %i", errno); break; } + buf[data_size] = 0; WLog_DBG(TAG, "devd event: %s", buf); - + if (buf[0] != '!') /* Skeep non notify events. */ continue; + /* Check: system=USB */ val = devd_get_val(buf, data_size, "system", 6, &val_size); + if (val == NULL || val_size != 3 || memcmp(val, "USB", 3) != 0) continue; + /* Check: subsystem=DEVICE */ val = devd_get_val(buf, data_size, "subsystem", 9, &val_size); + if (val == NULL || val_size != 6 || memcmp(val, "DEVICE", 6) != 0) continue; + /* Get event type. */ val = devd_get_val(buf, data_size, "type", 4, &val_size); + if (val == NULL || val_size != 6) continue; + action = -1; + if (memcmp(val, "ATTACH", 6) == 0) action = 0; + if (memcmp(val, "DETACH", 6) == 0) action = 1; + if (action == -1) continue; /* Skeep other actions. */ /* Get bus and dev num. */ /* ugen=ugen3.3 */ val = devd_get_val(buf, data_size, "ugen", 4, &val_size); + if (val == NULL || val_size < 7 || memcmp(val, "ugen", 4) != 0) continue; + val += 4; val_size -= 4; ptr = memchr(val, '.', val_size); + if (ptr == NULL) continue; + /* Prepare strings. */ ptr[0] = 0; ptr ++; val[val_size] = 0; /* Extract numbers. */ - busnum = atoi(val); - devnum = atoi(ptr); + busnum = strtol(val, NULL, 0); + + if (errno != 0) + continue; + + devnum = strtol(ptr, NULL, 0); + + if (errno != 0) + continue; + /* Restore spaces. */ ptr[-1] = ' '; val[val_size] = ' '; - /* Handle event. */ dvc_channel = NULL; switch (action) { - case 0: /* ATTACH */ - sdev = NULL; - success = 0; - found = 0; + case 0: /* ATTACH */ + sdev = NULL; + success = 0; + found = 0; + /* vendor=0x046d */ + val = devd_get_val(buf, data_size, "vendor", 6, &val_size); - /* vendor=0x046d */ - val = devd_get_val(buf, data_size, "vendor", 6, &val_size); - if (val == NULL || val_size < 1) - continue; - val[val_size] = 0; - idVendor = strtol(val, NULL, 16); - val[val_size] = ' '; + if (val == NULL || val_size < 1) + continue; - /* product=0x082d */ - val = devd_get_val(buf, data_size, "product", 7, &val_size); - if (val == NULL || val_size < 1) - continue; - val[val_size] = 0; - idProduct = strtol(val, NULL, 16); - val[val_size] = ' '; - - WLog_DBG(TAG, "ATTACH: bus: %i, dev: %i, ven: %i, prod: %i", busnum, devnum, idVendor, idProduct); + val[val_size] = 0; + idVendor = strtol(val, NULL, 16); - dvc_channel = channel_mgr->FindChannelById(channel_mgr, urbdrc->first_channel_id); - searchman->rewind(searchman); - while (dvc_channel && searchman->has_next(searchman)) - { - sdev = searchman->get_next(searchman); - if (sdev->idVendor == idVendor && - sdev->idProduct == idProduct) + if (errno != 0) + continue; + + val[val_size] = ' '; + /* product=0x082d */ + val = devd_get_val(buf, data_size, "product", 7, &val_size); + + if (val == NULL || val_size < 1) + continue; + + val[val_size] = 0; + idProduct = strtol(val, NULL, 16); + + if (errno != 0) + continue; + + val[val_size] = ' '; + WLog_DBG(TAG, "ATTACH: bus: %i, dev: %i, ven: %i, prod: %i", busnum, devnum, idVendor, idProduct); + dvc_channel = channel_mgr->FindChannelById(channel_mgr, urbdrc->first_channel_id); + searchman->rewind(searchman); + + while (dvc_channel && searchman->has_next(searchman)) { - WLog_VRB(TAG, "Searchman Found Device: %04"PRIx16":%04"PRIx16"", - sdev->idVendor, sdev->idProduct); - found = 1; - break; - } - } + sdev = searchman->get_next(searchman); - if (!found && udevman->isAutoAdd(udevman)) - { - WLog_VRB(TAG, "Auto Find Device: %04x:%04x ", - idVendor, idProduct); - found = 2; - } - - if (found) - { - success = udevman->register_udevice(udevman, busnum, devnum, - searchman->UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR); - } - - if (success) - { - searchman->UsbDevice ++; - - usleep(400000); - error = urdbrc_send_virtual_channel_add(dvc_channel, 0); - if (found == 1) - searchman->remove(searchman, sdev->idVendor, sdev->idProduct); - } - break; - case 1: /* DETACH */ - pdev = NULL; - on_close = 0; - WLog_DBG(TAG, "DETACH: bus: %i, dev: %i", busnum, devnum); - - usleep(500000); - udevman->loading_lock(udevman); - udevman->rewind(udevman); - while (udevman->has_next(udevman)) - { - pdev = udevman->get_next(udevman); - if (pdev->get_bus_number(pdev) == busnum && - pdev->get_dev_number(pdev) == devnum) - { - dvc_channel = channel_mgr->FindChannelById(channel_mgr, pdev->get_channel_id(pdev)); - - if (dvc_channel == NULL) + if (sdev->idVendor == idVendor && + sdev->idProduct == idProduct) { - WLog_ERR(TAG, "SEARCH: dvc_channel %d is NULL!!", pdev->get_channel_id(pdev)); - func_close_udevice(searchman, pdev); + WLog_VRB(TAG, "Searchman Found Device: %04"PRIx16":%04"PRIx16"", + sdev->idVendor, sdev->idProduct); + found = 1; break; } - - if (!pdev->isSigToEnd(pdev)) - { - dvc_channel->Write(dvc_channel, 0, NULL, NULL); - pdev->SigToEnd(pdev); - } - - on_close = 1; - break; } - } - udevman->loading_unlock(udevman); - usleep(300000); + if (!found && udevman->isAutoAdd(udevman)) + { + WLog_VRB(TAG, "Auto Find Device: %04x:%04x ", + idVendor, idProduct); + found = 2; + } - if (pdev && on_close && dvc_channel && - pdev->isSigToEnd(pdev) && - !(pdev->isChannelClosed(pdev))) - { - dvc_channel->Close(dvc_channel); - } - break; + if (found) + { + success = udevman->register_udevice(udevman, busnum, devnum, + searchman->UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR); + } + + if (success) + { + searchman->UsbDevice ++; + usleep(400000); + error = urdbrc_send_virtual_channel_add(dvc_channel, 0); + + if (found == 1) + searchman->remove(searchman, sdev->idVendor, sdev->idProduct); + } + + break; + + case 1: /* DETACH */ + pdev = NULL; + on_close = 0; + WLog_DBG(TAG, "DETACH: bus: %i, dev: %i", busnum, devnum); + usleep(500000); + udevman->loading_lock(udevman); + udevman->rewind(udevman); + + while (udevman->has_next(udevman)) + { + pdev = udevman->get_next(udevman); + + if (pdev->get_bus_number(pdev) == busnum && + pdev->get_dev_number(pdev) == devnum) + { + dvc_channel = channel_mgr->FindChannelById(channel_mgr, pdev->get_channel_id(pdev)); + + if (dvc_channel == NULL) + { + WLog_ERR(TAG, "SEARCH: dvc_channel %d is NULL!!", pdev->get_channel_id(pdev)); + func_close_udevice(searchman, pdev); + break; + } + + if (!pdev->isSigToEnd(pdev)) + { + dvc_channel->Write(dvc_channel, 0, NULL, NULL); + pdev->SigToEnd(pdev); + } + + on_close = 1; + break; + } + } + + udevman->loading_unlock(udevman); + usleep(300000); + + if (pdev && on_close && dvc_channel && + pdev->isSigToEnd(pdev) && + !(pdev->isChannelClosed(pdev))) + { + dvc_channel->Close(dvc_channel); + } + + break; } } @@ -749,8 +765,7 @@ err_out: close(devd_skt); sem_post(&searchman->sem_term); WLog_DBG(TAG, "urbdrc_search_usb_device - devd: end"); - - return 0; + return 0; } #endif #if defined (__linux__) @@ -766,18 +781,16 @@ static void* urbdrc_search_usb_device(void* arg) HANDLE listobj[2]; HANDLE mon_fd; int numobj, timeout; - int busnum, devnum; + long busnum, devnum; int success = 0, on_close = 0, found = 0; WLog_VRB(TAG, ""); channel_mgr = urbdrc->listener_callback->channel_mgr; DWORD status; DWORD dwError; - /* init usb monitor */ struct udev* udev; struct udev_device* dev; struct udev_monitor* mon; - udev = udev_new(); if (!udev) @@ -790,11 +803,11 @@ static void* urbdrc_search_usb_device(void* arg) mon = udev_monitor_new_from_netlink(udev, "udev"); udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_device"); udev_monitor_enable_receiving(mon); - /* Get the file descriptor (fd) for the monitor. This fd will get passed to select() */ mon_fd = CreateFileDescriptorEvent(NULL, TRUE, FALSE, - udev_monitor_get_fd(mon), WINPR_FD_READ); + udev_monitor_get_fd(mon), WINPR_FD_READ); + if (!mon_fd) goto fail_create_monfd_event; @@ -805,47 +818,45 @@ static void* urbdrc_search_usb_device(void* arg) devnum = 0; sdev = NULL; pdev = NULL; - dvc_channel = NULL; + dvc_channel = NULL; on_close = 0; listobj[0] = searchman->term_event; listobj[1] = mon_fd; numobj = 2; + status = WaitForMultipleObjects(numobj, listobj, FALSE, INFINITE); - status = WaitForMultipleObjects(numobj, listobj, FALSE, INFINITE); + if (status == WAIT_FAILED) + { + dwError = GetLastError(); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"!", dwError); + goto out; + } - if (status == WAIT_FAILED) - { - dwError = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"!", dwError); - goto out; - } + status = WaitForSingleObject(searchman->term_event, 0); - status = WaitForSingleObject(searchman->term_event, 0); + if (status == WAIT_FAILED) + { + dwError = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", dwError); + goto out; + } - if (status == WAIT_FAILED) - { - dwError = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", dwError); - goto out; - } + if (status == WAIT_OBJECT_0) + { + sem_post(&searchman->sem_term); + goto out; + } - if (status == WAIT_OBJECT_0) - { - sem_post(&searchman->sem_term); - goto out; - } + status = WaitForSingleObject(mon_fd, 0); - status = WaitForSingleObject(mon_fd, 0); + if (status == WAIT_FAILED) + { + dwError = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", dwError); + goto out; + } - if (status == WAIT_FAILED) - { - dwError = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", dwError); - goto out; - } - - - if (status == WAIT_OBJECT_0) + if (status == WAIT_OBJECT_0) { dev = udev_monitor_receive_device(mon); @@ -855,36 +866,48 @@ static void* urbdrc_search_usb_device(void* arg) if (strcmp(action, "add") == 0) { - int idVendor, idProduct; + long idVendor, idProduct; success = 0; found = 0; - idVendor = strtol(udev_device_get_sysattr_value(dev, "idVendor"), NULL, 16); + + if (errno != 0) + continue; + idProduct = strtol(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16); + if (errno != 0) + continue; + if (idVendor < 0 || idProduct < 0) { udev_device_unref(dev); continue; } - busnum = atoi(udev_device_get_property_value(dev,"BUSNUM")); - devnum = atoi(udev_device_get_property_value(dev,"DEVNUM")); + busnum = strtol(udev_device_get_property_value(dev, "BUSNUM"), NULL, 0); - dvc_channel = channel_mgr->FindChannelById(channel_mgr, - urbdrc->first_channel_id); + if (errno != 0) + continue; + devnum = strtol(udev_device_get_property_value(dev, "DEVNUM"), NULL, 0); + + if (errno != 0) + continue; + + dvc_channel = channel_mgr->FindChannelById(channel_mgr, + urbdrc->first_channel_id); searchman->rewind(searchman); - while(dvc_channel && searchman->has_next(searchman)) + while (dvc_channel && searchman->has_next(searchman)) { sdev = searchman->get_next(searchman); if (sdev->idVendor == idVendor && - sdev->idProduct == idProduct) + sdev->idProduct == idProduct) { WLog_VRB(TAG, "Searchman Find Device: %04"PRIx16":%04"PRIx16"", - sdev->idVendor, sdev->idProduct); + sdev->idVendor, sdev->idProduct); found = 1; break; } @@ -893,32 +916,29 @@ static void* urbdrc_search_usb_device(void* arg) if (!found && udevman->isAutoAdd(udevman)) { WLog_VRB(TAG, "Auto Find Device: %04x:%04x ", - idVendor, idProduct); + idVendor, idProduct); found = 2; } if (found) { success = udevman->register_udevice(udevman, busnum, devnum, - searchman->UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR); + searchman->UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR); } if (success) { searchman->UsbDevice++; - - /* when we send the usb device add request, - * we will detach the device driver at same - * time. But, if the time of detach the - * driver and attach driver is too close, - * the system will crash. workaround: we - * wait it for some time to avoid system + /* when we send the usb device add request, + * we will detach the device driver at same + * time. But, if the time of detach the + * driver and attach driver is too close, + * the system will crash. workaround: we + * wait it for some time to avoid system * crash. */ - listobj[0] = searchman->term_event; numobj = 1; timeout = 4000; /* milliseconds */ - status = WaitForMultipleObjects(numobj, listobj, FALSE, timeout); if (status == WAIT_FAILED) @@ -952,14 +972,21 @@ static void* urbdrc_search_usb_device(void* arg) } else if (strcmp(action, "remove") == 0) { - busnum = atoi(udev_device_get_property_value(dev,"BUSNUM")); - devnum = atoi(udev_device_get_property_value(dev,"DEVNUM")); + busnum = strtol(udev_device_get_property_value(dev, "BUSNUM"), NULL, 0); + + if (errno != 0) + goto out; + + devnum = strtol(udev_device_get_property_value(dev, "DEVNUM"), NULL, 0); + + if (errno != 0) + goto out; usleep(500000); udevman->loading_lock(udevman); udevman->rewind(udevman); - while(udevman->has_next(udevman)) + while (udevman->has_next(udevman)) { pdev = udevman->get_next(udevman); @@ -976,7 +1003,7 @@ static void* urbdrc_search_usb_device(void* arg) if (!pdev->isSigToEnd(pdev)) { - dvc_channel->Write(dvc_channel, 0, NULL, NULL); + dvc_channel->Write(dvc_channel, 0, NULL, NULL); pdev->SigToEnd(pdev); } @@ -986,11 +1013,9 @@ static void* urbdrc_search_usb_device(void* arg) } udevman->loading_unlock(udevman); - listobj[0] = searchman->term_event; numobj = 1; timeout = 3000; /* milliseconds */ - status = WaitForMultipleObjects(numobj, listobj, FALSE, timeout); if (status == WAIT_FAILED) @@ -1031,12 +1056,11 @@ static void* urbdrc_search_usb_device(void* arg) } } } + out: CloseHandle(mon_fd); - fail_create_monfd_event: sem_post(&searchman->sem_term); - return 0; } #endif @@ -1055,27 +1079,24 @@ void* urbdrc_new_device_create(void* arg) UINT32 MessageId; UINT32 FunctionId; int i = 0, found = 0; - WLog_DBG(TAG, "..."); - channel_mgr = urbdrc->listener_callback->channel_mgr; ChannelId = channel_mgr->GetChannelId(callback->channel); - data_read_UINT32(pBuffer + 0, MessageId); data_read_UINT32(pBuffer + 4, FunctionId); - int error = 0; switch (urbdrc->vchannel_status) { case INIT_CHANNEL_IN: urbdrc->first_channel_id = ChannelId; + if (!searchman->start(searchman, urbdrc_search_usb_device)) { WLog_ERR(TAG, "unable to start searchman thread"); return 0; } - + for (i = 0; i < udevman->get_device_num(udevman); i++) error = urdbrc_send_virtual_channel_add(callback->channel, MessageId); @@ -1086,7 +1107,7 @@ void* urbdrc_new_device_create(void* arg) udevman->loading_lock(udevman); udevman->rewind(udevman); - while(udevman->has_next(udevman)) + while (udevman->has_next(udevman)) { pdev = udevman->get_next(udevman); @@ -1098,26 +1119,26 @@ void* urbdrc_new_device_create(void* arg) break; } } + udevman->loading_unlock(udevman); - + if (found && pdev->isAlreadySend(pdev)) { - /* when we send the usb device add request, we will detach - * the device driver at same time. But, if the time of detach the + /* when we send the usb device add request, we will detach + * the device driver at same time. But, if the time of detach the * driver and attach driver is too close, the system will crash. * workaround: we wait it for some time to avoid system crash. */ - error = pdev->wait_for_detach(pdev); if (error >= 0) urdbrc_send_usb_device_add(callback, pdev); } - + break; default: WLog_ERR(TAG, "vchannel_status unknown value %"PRIu32"", - urbdrc->vchannel_status); + urbdrc->vchannel_status); break; } @@ -1129,16 +1150,15 @@ void* urbdrc_new_device_create(void* arg) * * @return 0 on success, otherwise a Win32 error code */ -static UINT urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callback, char* pBuffer, UINT32 cbSize) +static UINT urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callback, char* pBuffer, + UINT32 cbSize) { int i; UINT32 MessageId; UINT32 FunctionId; UINT error = CHANNEL_RC_OK; URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) callback->plugin; - WLog_DBG(TAG, "..."); - data_read_UINT32(pBuffer + 0, MessageId); data_read_UINT32(pBuffer + 4, FunctionId); @@ -1151,18 +1171,19 @@ static UINT urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callbac case RIMCALL_RELEASE: WLog_VRB(TAG, "recv RIMCALL_RELEASE"); pthread_t thread; - TRANSFER_DATA* transfer_data; - transfer_data = (TRANSFER_DATA*)malloc(sizeof(TRANSFER_DATA)); + if (!transfer_data) return ERROR_OUTOFMEMORY; + transfer_data->callback = callback; transfer_data->urbdrc = urbdrc; transfer_data->udevman = urbdrc->udevman; transfer_data->urbdrc = urbdrc; transfer_data->cbSize = cbSize; transfer_data->pBuffer = (BYTE*) malloc((cbSize)); + if (!transfer_data->pBuffer) { free(transfer_data); @@ -1180,14 +1201,16 @@ static UINT urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callbac free(transfer_data); return ERROR_INVALID_OPERATION; } + pthread_detach(thread); break; default: - WLog_VRB(TAG, "unknown FunctionId 0x%"PRIX32"", FunctionId); + WLog_VRB(TAG, "%s: unknown FunctionId 0x%"PRIX32"", __FUNCTION__, FunctionId); error = 1; break; } + return error; } @@ -1220,10 +1243,9 @@ static UINT urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback return 0; udevman = (IUDEVMAN*) urbdrc->udevman; - data_read_UINT32(pBuffer + 0, InterfaceTemp); InterfaceId = (InterfaceTemp & 0x0fffffff); - Mask = ((InterfaceTemp & 0xf0000000)>>30); + Mask = ((InterfaceTemp & 0xf0000000) >> 30); WLog_VRB(TAG, "Size=%"PRIu32" InterfaceId=0x%"PRIX32" Mask=0x%"PRIX32"", cbSize, InterfaceId, Mask); switch (InterfaceId) @@ -1240,8 +1262,8 @@ static UINT urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback WLog_VRB(TAG, "InterfaceId 0x%"PRIX32" Start matching devices list", InterfaceId); pthread_t thread; TRANSFER_DATA* transfer_data; + transfer_data = (TRANSFER_DATA*)malloc(sizeof(TRANSFER_DATA)); - transfer_data = (TRANSFER_DATA *)malloc(sizeof(TRANSFER_DATA)); if (!transfer_data) { WLog_ERR(TAG, "transfer_data is NULL!!"); @@ -1253,7 +1275,8 @@ static UINT urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback transfer_data->udevman = udevman; transfer_data->cbSize = cbSize - 4; transfer_data->UsbDevice = InterfaceId; - transfer_data->pBuffer = (BYTE *)malloc((cbSize - 4)); + transfer_data->pBuffer = (BYTE*)malloc((cbSize - 4)); + if (!transfer_data->pBuffer) { free(transfer_data); @@ -1261,16 +1284,14 @@ static UINT urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback } memcpy(transfer_data->pBuffer, pBuffer + 4, (cbSize - 4)); - /* To ensure that not too many urb requests at the same time */ udevman->wait_urb(udevman); - #if ISOCH_FIFO /* lock isoch mutex */ func_lock_isoch_mutex(transfer_data); #endif - error = pthread_create(&thread, 0, urbdrc_process_udev_data_transfer, transfer_data); + if (error != 0) { WLog_ERR(TAG, "Create Data Transfer Thread got error = %"PRIu32"", error); @@ -1291,7 +1312,7 @@ static UINT urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback * * @return 0 on success, otherwise a Win32 error code */ -static UINT urbdrc_on_close(IWTSVirtualChannelCallback * pChannelCallback) +static UINT urbdrc_on_close(IWTSVirtualChannelCallback* pChannelCallback) { URBDRC_CHANNEL_CALLBACK* callback = (URBDRC_CHANNEL_CALLBACK*) pChannelCallback; URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) callback->plugin; @@ -1300,13 +1321,12 @@ static UINT urbdrc_on_close(IWTSVirtualChannelCallback * pChannelCallback) IUDEVICE* pdev = NULL; UINT32 ChannelId = 0; int found = 0; - ChannelId = callback->channel_mgr->GetChannelId(callback->channel); WLog_INFO(TAG, "urbdrc_on_close: channel id %"PRIu32"", ChannelId); udevman->loading_lock(udevman); udevman->rewind(udevman); - while(udevman->has_next(udevman)) + while (udevman->has_next(udevman)) { pdev = udevman->get_next(udevman); @@ -1336,13 +1356,13 @@ static UINT urbdrc_on_close(IWTSVirtualChannelCallback * pChannelCallback) * @return 0 on success, otherwise a Win32 error code */ static UINT urbdrc_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel * pChannel, BYTE* pData, BOOL* pbAccept, IWTSVirtualChannelCallback** ppCallback) + IWTSVirtualChannel* pChannel, BYTE* pData, BOOL* pbAccept, IWTSVirtualChannelCallback** ppCallback) { URBDRC_LISTENER_CALLBACK* listener_callback = (URBDRC_LISTENER_CALLBACK*) pListenerCallback; URBDRC_CHANNEL_CALLBACK* callback; - WLog_VRB(TAG, ""); callback = (URBDRC_CHANNEL_CALLBACK*) calloc(1, sizeof(URBDRC_CHANNEL_CALLBACK)); + if (!callback) return ERROR_OUTOFMEMORY; @@ -1352,7 +1372,6 @@ static UINT urbdrc_on_new_channel_connection(IWTSListenerCallback* pListenerCall callback->channel_mgr = listener_callback->channel_mgr; callback->channel = pChannel; *ppCallback = (IWTSVirtualChannelCallback*) callback; - return CHANNEL_RC_OK; } @@ -1366,29 +1385,29 @@ static UINT urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) pPlugin; IUDEVMAN* udevman = NULL; USB_SEARCHMAN* searchman = NULL; - WLog_VRB(TAG, ""); urbdrc->listener_callback = (URBDRC_LISTENER_CALLBACK*) calloc(1, sizeof(URBDRC_LISTENER_CALLBACK)); + if (!urbdrc->listener_callback) return CHANNEL_RC_NO_MEMORY; urbdrc->listener_callback->iface.OnNewChannelConnection = urbdrc_on_new_channel_connection; urbdrc->listener_callback->plugin = pPlugin; urbdrc->listener_callback->channel_mgr = pChannelMgr; - /* Init searchman */ udevman = urbdrc->udevman; searchman = searchman_new((void*) urbdrc, udevman->get_defUsbDevice(udevman)); + if (!searchman) { free(urbdrc->listener_callback); urbdrc->listener_callback = NULL; return CHANNEL_RC_NO_MEMORY; } - urbdrc->searchman = searchman; + urbdrc->searchman = searchman; return pChannelMgr->CreateListener(pChannelMgr, "URBDRC", 0, - (IWTSListenerCallback*) urbdrc->listener_callback, NULL); + (IWTSListenerCallback*) urbdrc->listener_callback, NULL); } /** @@ -1401,7 +1420,6 @@ static UINT urbdrc_plugin_terminated(IWTSPlugin* pPlugin) URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) pPlugin; IUDEVMAN* udevman = urbdrc->udevman; USB_SEARCHMAN* searchman = urbdrc->searchman; - WLog_VRB(TAG, ""); if (searchman) @@ -1413,7 +1431,7 @@ static UINT urbdrc_plugin_terminated(IWTSPlugin* pPlugin) if (searchman->started) { struct timespec ts; - ts.tv_sec = time(NULL)+10; + ts.tv_sec = time(NULL) + 10; ts.tv_nsec = 0; sem_timedwait(&searchman->sem_term, &ts); } @@ -1431,7 +1449,7 @@ static UINT urbdrc_plugin_terminated(IWTSPlugin* pPlugin) if (urbdrc->listener_callback) zfree(urbdrc->listener_callback); - if(urbdrc) + if (urbdrc) zfree(urbdrc); return CHANNEL_RC_OK; @@ -1448,7 +1466,6 @@ static void urbdrc_register_udevman_addin(IWTSPlugin* pPlugin, IUDEVMAN* udevman } DEBUG_DVC("device registered."); - urbdrc->udevman = udevman; } @@ -1461,8 +1478,9 @@ static UINT urbdrc_load_udevman_addin(IWTSPlugin* pPlugin, const char* name, ADD { PFREERDP_URBDRC_DEVICE_ENTRY entry; FREERDP_URBDRC_SERVICE_ENTRY_POINTS entryPoints; + entry = (PFREERDP_URBDRC_DEVICE_ENTRY) freerdp_load_channel_addin_entry("urbdrc", (LPSTR) name, + NULL, 0); - entry = (PFREERDP_URBDRC_DEVICE_ENTRY) freerdp_load_channel_addin_entry("urbdrc", (LPSTR) name, NULL, 0); if (!entry) return ERROR_INVALID_OPERATION; @@ -1503,11 +1521,10 @@ static UINT urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args) int status; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; - status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, - urbdrc_args, flags, urbdrc, NULL, NULL); + urbdrc_args, flags, urbdrc, NULL, NULL); + if (status < 0) return ERROR_INVALID_DATA; @@ -1519,7 +1536,6 @@ static UINT urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args) continue; CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "dbg") { WLog_SetLogLevel(WLog_Get(TAG), WLOG_TRACE); @@ -1531,12 +1547,11 @@ static UINT urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args) } CommandLineSwitchDefault(arg) { - } - CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + return CHANNEL_RC_OK; } @@ -1556,13 +1571,13 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) UINT status = 0; ADDIN_ARGV* args; URBDRC_PLUGIN* urbdrc; - urbdrc = (URBDRC_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "urbdrc"); args = pEntryPoints->GetPluginData(pEntryPoints); if (urbdrc == NULL) { urbdrc = (URBDRC_PLUGIN*) calloc(1, sizeof(URBDRC_PLUGIN)); + if (!urbdrc) return CHANNEL_RC_NO_MEMORY; @@ -1572,13 +1587,14 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) urbdrc->iface.Terminated = urbdrc_plugin_terminated; urbdrc->searchman = NULL; urbdrc->vchannel_status = INIT_CHANNEL_IN; - status = pEntryPoints->RegisterPlugin(pEntryPoints, "urbdrc", (IWTSPlugin*) urbdrc); + if (status != CHANNEL_RC_OK) goto error_register; } status = urbdrc_process_addin_args(urbdrc, args); + if (status != CHANNEL_RC_OK) { /* TODO: we should unregister the plugin ? */ @@ -1586,7 +1602,6 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) //return status; } - if (!urbdrc->subsystem && !urbdrc_set_subsystem(urbdrc, "libusb")) { /* TODO: we should unregister the plugin ? */ @@ -1595,7 +1610,6 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) } return urbdrc_load_udevman_addin((IWTSPlugin*) urbdrc, urbdrc->subsystem, args); - error_register: free(urbdrc); return status; diff --git a/channels/video/CMakeLists.txt b/channels/video/CMakeLists.txt new file mode 100644 index 0000000..f03c851 --- /dev/null +++ b/channels/video/CMakeLists.txt @@ -0,0 +1,22 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2017 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. + +define_channel("video") + +if(WITH_CLIENT_CHANNELS) + add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME}) +endif() diff --git a/channels/video/ChannelOptions.cmake b/channels/video/ChannelOptions.cmake new file mode 100644 index 0000000..e7f9ce8 --- /dev/null +++ b/channels/video/ChannelOptions.cmake @@ -0,0 +1,12 @@ + +set(OPTION_DEFAULT OFF) +set(OPTION_CLIENT_DEFAULT ON) +set(OPTION_SERVER_DEFAULT OFF) + +define_channel_options(NAME "video" TYPE "dynamic" + DESCRIPTION "Video optimized remoting Virtual Channel Extension" + SPECIFICATIONS "[MS-RDPEVOR]" + DEFAULT ${OPTION_DEFAULT}) + +define_channel_client_options(${OPTION_CLIENT_DEFAULT}) + diff --git a/channels/video/client/CMakeLists.txt b/channels/video/client/CMakeLists.txt new file mode 100644 index 0000000..cbbe483 --- /dev/null +++ b/channels/video/client/CMakeLists.txt @@ -0,0 +1,39 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2018 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. + +define_channel_client("video") + +set(${MODULE_PREFIX}_SRCS + video_main.c + video_main.h) + +include_directories(..) + +add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry") + + + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + + +if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_LIBS) + install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client") diff --git a/channels/video/client/video_main.c b/channels/video/client/video_main.c new file mode 100755 index 0000000..20b4319 --- /dev/null +++ b/channels/video/client/video_main.c @@ -0,0 +1,1168 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Video Optimized Remoting Virtual Channel Extension + * + * Copyright 2017 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#define TAG CHANNELS_TAG("video") + +#include "video_main.h" + +struct _VIDEO_CHANNEL_CALLBACK +{ + IWTSVirtualChannelCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + IWTSVirtualChannel* channel; +}; +typedef struct _VIDEO_CHANNEL_CALLBACK VIDEO_CHANNEL_CALLBACK; + +struct _VIDEO_LISTENER_CALLBACK +{ + IWTSListenerCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + VIDEO_CHANNEL_CALLBACK* channel_callback; +}; +typedef struct _VIDEO_LISTENER_CALLBACK VIDEO_LISTENER_CALLBACK; + +struct _VIDEO_PLUGIN +{ + IWTSPlugin wtsPlugin; + + IWTSListener* controlListener; + IWTSListener* dataListener; + VIDEO_LISTENER_CALLBACK* control_callback; + VIDEO_LISTENER_CALLBACK* data_callback; + + VideoClientContext *context; +}; +typedef struct _VIDEO_PLUGIN VIDEO_PLUGIN; + + +#define XF_VIDEO_UNLIMITED_RATE 31 + +static const BYTE MFVideoFormat_H264[] = {'H', '2', '6', '4', + 0x00, 0x00, + 0x10, 0x00, + 0x80, 0x00, + 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}; + +typedef struct _PresentationContext PresentationContext; +typedef struct _VideoFrame VideoFrame; + + +/** @brief private data for the channel */ +struct _VideoClientContextPriv +{ + VideoClientContext *video; + GeometryClientContext *geometry; + wQueue *frames; + CRITICAL_SECTION framesLock; + wBufferPool *surfacePool; + UINT32 publishedFrames; + UINT32 droppedFrames; + UINT32 lastSentRate; + UINT64 nextFeedbackTime; + PresentationContext *currentPresentation; +}; + +/** @brief */ +struct _VideoFrame +{ + UINT64 publishTime; + UINT64 hnsDuration; + MAPPED_GEOMETRY *geometry; + UINT32 w, h; + BYTE *surfaceData; + PresentationContext *presentation; +}; + +/** @brief */ +struct _PresentationContext +{ + VideoClientContext *video; + BYTE PresentationId; + UINT32 SourceWidth, SourceHeight; + UINT32 ScaledWidth, ScaledHeight; + MAPPED_GEOMETRY *geometry; + + UINT64 startTimeStamp; + UINT64 publishOffset; + H264_CONTEXT *h264; + YUV_CONTEXT *yuv; + wStream *currentSample; + UINT64 lastPublishTime, nextPublishTime; + volatile LONG refCounter; + BYTE *surfaceData; + VideoSurface *surface; +}; + + +static const char *video_command_name(BYTE cmd) +{ + switch(cmd) + { + case TSMM_START_PRESENTATION: + return "start"; + case TSMM_STOP_PRESENTATION: + return "stop"; + default: + return ""; + } +} + +static BOOL yuv_to_rgb(PresentationContext *presentation, BYTE *dest) +{ + const BYTE* pYUVPoint[3]; + H264_CONTEXT *h264 = presentation->h264; + + BYTE** ppYUVData; + ppYUVData = h264->pYUVData; + + pYUVPoint[0] = ppYUVData[0]; + pYUVPoint[1] = ppYUVData[1]; + pYUVPoint[2] = ppYUVData[2]; + + if (!yuv_context_decode(presentation->yuv, pYUVPoint, h264->iStride, PIXEL_FORMAT_BGRX32, dest, h264->width * 4)) + { + WLog_ERR(TAG, "error in yuv_to_rgb conversion"); + return FALSE; + } + + return TRUE; +} + + +static void video_client_context_set_geometry(VideoClientContext *video, GeometryClientContext *geometry) +{ + video->priv->geometry = geometry; +} + +VideoClientContextPriv *VideoClientContextPriv_new(VideoClientContext *video) +{ + VideoClientContextPriv *ret = calloc(1, sizeof(*ret)); + if (!ret) + return NULL; + + ret->frames = Queue_New(TRUE, 10, 2); + if (!ret->frames) + { + WLog_ERR(TAG, "unable to allocate frames queue"); + goto error_frames; + } + + ret->surfacePool = BufferPool_New(FALSE, 0, 16); + if (!ret->surfacePool) + { + WLog_ERR(TAG, "unable to create surface pool"); + goto error_surfacePool; + } + + if (!InitializeCriticalSectionAndSpinCount(&ret->framesLock, 4 * 1000)) + { + WLog_ERR(TAG, "unable to initialize frames lock"); + goto error_spinlock; + } + + ret->video = video; + + /* don't set to unlimited so that we have the chance to send a feedback in + * the first second (for servers that want feedback directly) + */ + ret->lastSentRate = 30; + return ret; + +error_spinlock: + BufferPool_Free(ret->surfacePool); +error_surfacePool: + Queue_Free(ret->frames); +error_frames: + free(ret); + return NULL; +} + + +static PresentationContext *PresentationContext_new(VideoClientContext *video, BYTE PresentationId, + UINT32 x, UINT32 y, UINT32 width, UINT32 height) +{ + VideoClientContextPriv *priv = video->priv; + PresentationContext *ret = calloc(1, sizeof(*ret)); + if (!ret) + return NULL; + + ret->video = video; + ret->PresentationId = PresentationId; + + ret->h264 = h264_context_new(FALSE); + if (!ret->h264) + { + WLog_ERR(TAG, "unable to create a h264 context"); + goto error_h264; + } + h264_context_reset(ret->h264, width, height); + + ret->currentSample = Stream_New(NULL, 4096); + if (!ret->currentSample) + { + WLog_ERR(TAG, "unable to create current packet stream"); + goto error_currentSample; + } + + ret->surfaceData = BufferPool_Take(priv->surfacePool, width * height * 4); + if (!ret->surfaceData) + { + WLog_ERR(TAG, "unable to allocate surfaceData"); + goto error_surfaceData; + } + + ret->surface = video->createSurface(video, ret->surfaceData, x, y, width, height); + if (!ret->surface) + { + WLog_ERR(TAG, "unable to create surface"); + goto error_surface; + } + + ret->yuv = yuv_context_new(FALSE); + if (!ret->yuv) + { + WLog_ERR(TAG, "unable to create YUV decoder"); + goto error_yuv; + } + + yuv_context_reset(ret->yuv, width, height); + ret->refCounter = 1; + return ret; + +error_yuv: + video->deleteSurface(video, ret->surface); +error_surface: + BufferPool_Return(priv->surfacePool, ret->surfaceData); +error_surfaceData: + Stream_Free(ret->currentSample, TRUE); +error_currentSample: + h264_context_free(ret->h264); +error_h264: + free(ret); + return NULL; +} + + +static void PresentationContext_unref(PresentationContext *presentation) +{ + VideoClientContextPriv *priv; + MAPPED_GEOMETRY *geometry; + + if (!presentation) + return; + + if (InterlockedDecrement(&presentation->refCounter) != 0) + return; + + geometry = presentation->geometry; + if (geometry) + { + geometry->MappedGeometryUpdate = NULL; + geometry->MappedGeometryClear = NULL; + geometry->custom = NULL; + mappedGeometryUnref(geometry); + } + + priv = presentation->video->priv; + + h264_context_free(presentation->h264); + Stream_Free(presentation->currentSample, TRUE); + presentation->video->deleteSurface(presentation->video, presentation->surface); + BufferPool_Return(priv->surfacePool, presentation->surfaceData); + yuv_context_free(presentation->yuv); + free(presentation); +} + + +static void VideoFrame_free(VideoFrame **pframe) +{ + VideoFrame *frame = *pframe; + + mappedGeometryUnref(frame->geometry); + BufferPool_Return(frame->presentation->video->priv->surfacePool, frame->surfaceData); + PresentationContext_unref(frame->presentation); + free(frame); + *pframe = NULL; +} + + +static void VideoClientContextPriv_free(VideoClientContextPriv *priv) +{ + EnterCriticalSection(&priv->framesLock); + while (Queue_Count(priv->frames)) + { + VideoFrame *frame = Queue_Dequeue(priv->frames); + if (frame) + VideoFrame_free(&frame); + } + + Queue_Free(priv->frames); + LeaveCriticalSection(&priv->framesLock); + + DeleteCriticalSection(&priv->framesLock); + + if (priv->currentPresentation) + PresentationContext_unref(priv->currentPresentation); + + BufferPool_Free(priv->surfacePool); + free(priv); +} + + +static UINT video_control_send_presentation_response(VideoClientContext *context, TSMM_PRESENTATION_RESPONSE *resp) +{ + BYTE buf[12]; + wStream *s; + VIDEO_PLUGIN* video = (VIDEO_PLUGIN *)context->handle; + IWTSVirtualChannel* channel; + UINT ret; + + s = Stream_New(buf, 12); + if (!s) + return CHANNEL_RC_NO_MEMORY; + + Stream_Write_UINT32(s, 12); /* cbSize */ + Stream_Write_UINT32(s, TSMM_PACKET_TYPE_PRESENTATION_RESPONSE); /* PacketType */ + Stream_Write_UINT8(s, resp->PresentationId); + Stream_Zero(s, 3); + Stream_SealLength(s); + + channel = video->control_callback->channel_callback->channel; + ret = channel->Write(channel, 12, buf, NULL); + Stream_Free(s, FALSE); + + return ret; +} + +static BOOL video_onMappedGeometryUpdate(MAPPED_GEOMETRY *geometry) +{ + PresentationContext *presentation = (PresentationContext *)geometry->custom; + RDP_RECT *r = &geometry->geometry.boundingRect; + WLog_DBG(TAG, "geometry updated topGeom=(%d,%d-%dx%d) geom=(%d,%d-%dx%d) rects=(%d,%d-%dx%d)", + geometry->topLevelLeft, geometry->topLevelTop, + geometry->topLevelRight - geometry->topLevelLeft, geometry->topLevelBottom - geometry->topLevelTop, + + geometry->left, geometry->top, + geometry->right - geometry->left, geometry->bottom - geometry->top, + + r->x, r->y, r->width, r->height + ); + + presentation->surface->x = geometry->topLevelLeft + geometry->left; + presentation->surface->y = geometry->topLevelTop + geometry->top; + + return TRUE; +} + +static BOOL video_onMappedGeometryClear(MAPPED_GEOMETRY *geometry) +{ + PresentationContext *presentation = (PresentationContext *)geometry->custom; + + mappedGeometryUnref(presentation->geometry); + presentation->geometry = NULL; + return TRUE; +} + +static UINT video_PresentationRequest(VideoClientContext* video, TSMM_PRESENTATION_REQUEST *req) +{ + VideoClientContextPriv *priv = video->priv; + PresentationContext *presentation; + UINT ret = CHANNEL_RC_OK; + + presentation = priv->currentPresentation; + + if (req->Command == TSMM_START_PRESENTATION) + { + MAPPED_GEOMETRY *geom; + TSMM_PRESENTATION_RESPONSE resp; + + if (memcmp(req->VideoSubtypeId, MFVideoFormat_H264, 16) != 0) + { + WLog_ERR(TAG, "not a H264 video, ignoring request"); + return CHANNEL_RC_OK; + } + + if (presentation) + { + if (presentation->PresentationId == req->PresentationId) + { + WLog_ERR(TAG, "ignoring start request for existing presentation %d", req->PresentationId); + return CHANNEL_RC_OK; + } + + WLog_ERR(TAG, "releasing current presentation %d", req->PresentationId); + PresentationContext_unref(presentation); + presentation = priv->currentPresentation = NULL; + } + + if (!priv->geometry) + { + WLog_ERR(TAG, "geometry channel not ready, ignoring request"); + return CHANNEL_RC_OK; + } + + geom = HashTable_GetItemValue(priv->geometry->geometries, &(req->GeometryMappingId)); + if (!geom) + { + WLog_ERR(TAG, "geometry mapping 0x%"PRIx64" not registered", req->GeometryMappingId); + return CHANNEL_RC_OK; + } + + WLog_DBG(TAG, "creating presentation 0x%x", req->PresentationId); + presentation = PresentationContext_new(video, req->PresentationId, + geom->topLevelLeft + geom->left, + geom->topLevelTop + geom->top, + req->SourceWidth, req->SourceHeight); + if (!presentation) + { + WLog_ERR(TAG, "unable to create presentation video"); + return CHANNEL_RC_NO_MEMORY; + } + + mappedGeometryRef(geom); + presentation->geometry = geom; + + priv->currentPresentation = presentation; + presentation->video = video; + presentation->SourceWidth = req->SourceWidth; + presentation->SourceHeight = req->SourceHeight; + presentation->ScaledWidth = req->ScaledWidth; + presentation->ScaledHeight = req->ScaledHeight; + + geom->custom = presentation; + geom->MappedGeometryUpdate = video_onMappedGeometryUpdate; + geom->MappedGeometryClear = video_onMappedGeometryClear; + + /* send back response */ + resp.PresentationId = req->PresentationId; + ret = video_control_send_presentation_response(video, &resp); + } + else if (req->Command == TSMM_STOP_PRESENTATION) + { + WLog_DBG(TAG, "stopping presentation 0x%x", req->PresentationId); + if (!presentation) + { + WLog_ERR(TAG, "unknown presentation to stop %d", req->PresentationId); + return CHANNEL_RC_OK; + } + + priv->currentPresentation = NULL; + priv->droppedFrames = 0; + priv->publishedFrames = 0; + PresentationContext_unref(presentation); + } + + return CHANNEL_RC_OK; +} + + +static UINT video_read_tsmm_presentation_req(VideoClientContext *context, wStream *s) +{ + TSMM_PRESENTATION_REQUEST req; + + if (Stream_GetRemainingLength(s) < 60) + { + WLog_ERR(TAG, "not enough bytes for a TSMM_PRESENTATION_REQUEST"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT8(s, req.PresentationId); + Stream_Read_UINT8(s, req.Version); + Stream_Read_UINT8(s, req.Command); + Stream_Read_UINT8(s, req.FrameRate); /* FrameRate - reserved and ignored */ + + Stream_Seek_UINT16(s); /* AverageBitrateKbps reserved and ignored */ + Stream_Seek_UINT16(s); /* reserved */ + + Stream_Read_UINT32(s, req.SourceWidth); + Stream_Read_UINT32(s, req.SourceHeight); + Stream_Read_UINT32(s, req.ScaledWidth); + Stream_Read_UINT32(s, req.ScaledHeight); + Stream_Read_UINT64(s, req.hnsTimestampOffset); + Stream_Read_UINT64(s, req.GeometryMappingId); + Stream_Read(s, req.VideoSubtypeId, 16); + + Stream_Read_UINT32(s, req.cbExtra); + + if (Stream_GetRemainingLength(s) < req.cbExtra) + { + WLog_ERR(TAG, "not enough bytes for cbExtra of TSMM_PRESENTATION_REQUEST"); + return ERROR_INVALID_DATA; + } + + req.pExtraData = Stream_Pointer(s); + + WLog_DBG(TAG, "presentationReq: id:%"PRIu8" version:%"PRIu8" command:%s srcWidth/srcHeight=%"PRIu32"x%"PRIu32 + " scaled Width/Height=%"PRIu32"x%"PRIu32" timestamp=%"PRIu64" mappingId=%"PRIx64"", + req.PresentationId, req.Version, video_command_name(req.Command), + req.SourceWidth, req.SourceHeight, req.ScaledWidth, req.ScaledHeight, + req.hnsTimestampOffset, req.GeometryMappingId); + + return video_PresentationRequest(context, &req); +} + + + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT video_control_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *s) +{ + VIDEO_CHANNEL_CALLBACK* callback = (VIDEO_CHANNEL_CALLBACK*) pChannelCallback; + VIDEO_PLUGIN* video; + VideoClientContext *context; + UINT ret = CHANNEL_RC_OK; + UINT32 cbSize, packetType; + + video = (VIDEO_PLUGIN*) callback->plugin; + context = (VideoClientContext *)video->wtsPlugin.pInterface; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, cbSize); + if (cbSize < 8 || Stream_GetRemainingLength(s) < (cbSize-4)) + { + WLog_ERR(TAG, "invalid cbSize"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, packetType); + switch (packetType) + { + case TSMM_PACKET_TYPE_PRESENTATION_REQUEST: + ret = video_read_tsmm_presentation_req(context, s); + break; + default: + WLog_ERR(TAG, "not expecting packet type %"PRIu32"", packetType); + ret = ERROR_UNSUPPORTED_TYPE; + break; + } + + return ret; +} + +static UINT video_control_send_client_notification(VideoClientContext *context, TSMM_CLIENT_NOTIFICATION *notif) +{ + BYTE buf[100]; + wStream *s; + VIDEO_PLUGIN* video = (VIDEO_PLUGIN *)context->handle; + IWTSVirtualChannel* channel; + UINT ret; + UINT32 cbSize; + + s = Stream_New(buf, 30); + if (!s) + return CHANNEL_RC_NO_MEMORY; + + cbSize = 16; + Stream_Seek_UINT32(s); /* cbSize */ + Stream_Write_UINT32(s, TSMM_PACKET_TYPE_CLIENT_NOTIFICATION); /* PacketType */ + Stream_Write_UINT8(s, notif->PresentationId); + Stream_Write_UINT8(s, notif->NotificationType); + Stream_Zero(s, 2); + if (notif->NotificationType == TSMM_CLIENT_NOTIFICATION_TYPE_FRAMERATE_OVERRIDE) + { + Stream_Write_UINT32(s, 16); /* cbData */ + + /* TSMM_CLIENT_NOTIFICATION_FRAMERATE_OVERRIDE */ + Stream_Write_UINT32(s, notif->FramerateOverride.Flags); + Stream_Write_UINT32(s, notif->FramerateOverride.DesiredFrameRate); + Stream_Zero(s, 4 * 2); + + cbSize += 4 * 4; + } + else + { + Stream_Write_UINT32(s, 0); /* cbData */ + } + + Stream_SealLength(s); + Stream_SetPosition(s, 0); + Stream_Write_UINT32(s, cbSize); + Stream_Free(s, FALSE); + + channel = video->control_callback->channel_callback->channel; + ret = channel->Write(channel, cbSize, buf, NULL); + + return ret; +} + +static void video_timer(VideoClientContext *video, UINT64 now) +{ + PresentationContext *presentation; + VideoClientContextPriv *priv = video->priv; + VideoFrame *peekFrame, *frame = NULL; + + EnterCriticalSection(&priv->framesLock); + do + { + peekFrame = (VideoFrame *)Queue_Peek(priv->frames); + if (!peekFrame) + break; + + if (peekFrame->publishTime > now) + break; + + if (frame) + { + WLog_DBG(TAG, "dropping frame @%"PRIu64, frame->publishTime); + priv->droppedFrames++; + VideoFrame_free(&frame); + } + frame = peekFrame; + Queue_Dequeue(priv->frames); + } + while (1); + LeaveCriticalSection(&priv->framesLock); + + if (!frame) + goto treat_feedback; + + presentation = frame->presentation; + + priv->publishedFrames++; + memcpy(presentation->surfaceData, frame->surfaceData, frame->w * frame->h * 4); + + video->showSurface(video, presentation->surface); + + VideoFrame_free(&frame); + +treat_feedback: + if (priv->nextFeedbackTime < now) + { + /* we can compute some feedback only if we have some published frames and + * a current presentation + */ + if (priv->publishedFrames && priv->currentPresentation) + { + UINT32 computedRate; + + InterlockedIncrement(&priv->currentPresentation->refCounter); + + if (priv->droppedFrames) + { + /** + * some dropped frames, looks like we're asking too many frames per seconds, + * try lowering rate. We go directly from unlimited rate to 24 frames/seconds + * otherwise we lower rate by 2 frames by seconds + */ + if (priv->lastSentRate == XF_VIDEO_UNLIMITED_RATE) + computedRate = 24; + else + { + computedRate = priv->lastSentRate - 2; + if (!computedRate) + computedRate = 2; + } + } + else + { + /** + * we treat all frames ok, so either ask the server to send more, + * or stay unlimited + */ + if (priv->lastSentRate == XF_VIDEO_UNLIMITED_RATE) + computedRate = XF_VIDEO_UNLIMITED_RATE; /* stay unlimited */ + else + { + computedRate = priv->lastSentRate + 2; + if (computedRate > XF_VIDEO_UNLIMITED_RATE) + computedRate = XF_VIDEO_UNLIMITED_RATE; + } + } + + if (computedRate != priv->lastSentRate) + { + TSMM_CLIENT_NOTIFICATION notif; + notif.PresentationId = priv->currentPresentation->PresentationId; + notif.NotificationType = TSMM_CLIENT_NOTIFICATION_TYPE_FRAMERATE_OVERRIDE; + if (computedRate == XF_VIDEO_UNLIMITED_RATE) + { + notif.FramerateOverride.Flags = 0x01; + notif.FramerateOverride.DesiredFrameRate = 0x00; + } + else + { + notif.FramerateOverride.Flags = 0x02; + notif.FramerateOverride.DesiredFrameRate = computedRate; + } + + video_control_send_client_notification(video, ¬if); + priv->lastSentRate = computedRate; + + WLog_DBG(TAG, "server notified with rate %d published=%d dropped=%d", priv->lastSentRate, + priv->publishedFrames, priv->droppedFrames); + } + + PresentationContext_unref(priv->currentPresentation); + } + + WLog_DBG(TAG, "currentRate=%d published=%d dropped=%d", priv->lastSentRate, + priv->publishedFrames, priv->droppedFrames); + + priv->droppedFrames = 0; + priv->publishedFrames = 0; + priv->nextFeedbackTime = now + 1000; + } +} + + +static UINT video_VideoData(VideoClientContext* context, TSMM_VIDEO_DATA *data) +{ + VideoClientContextPriv *priv = context->priv; + PresentationContext *presentation; + int status; + + presentation = priv->currentPresentation; + if (!presentation) + { + WLog_ERR(TAG, "no current presentation"); + return CHANNEL_RC_OK; + } + + if (presentation->PresentationId != data->PresentationId) + { + WLog_ERR(TAG, "current presentation id=%d doesn't match data id=%d", presentation->PresentationId, + data->PresentationId); + return CHANNEL_RC_OK; + } + + if (!Stream_EnsureRemainingCapacity(presentation->currentSample, data->cbSample)) + { + WLog_ERR(TAG, "unable to expand the current packet"); + return CHANNEL_RC_NO_MEMORY; + } + + Stream_Write(presentation->currentSample, data->pSample, data->cbSample); + + if (data->CurrentPacketIndex == data->PacketsInSample) + { + H264_CONTEXT *h264 = presentation->h264; + UINT64 startTime = GetTickCount64(), timeAfterH264; + MAPPED_GEOMETRY *geom = presentation->geometry; + + Stream_SealLength(presentation->currentSample); + Stream_SetPosition(presentation->currentSample, 0); + + status = h264->subsystem->Decompress(h264, Stream_Pointer(presentation->currentSample), + Stream_Length(presentation->currentSample)); + if (status == 0) + return CHANNEL_RC_OK; + + if (status < 0) + return CHANNEL_RC_OK; + + timeAfterH264 = GetTickCount64(); + if (data->SampleNumber == 1) + { + presentation->lastPublishTime = startTime; + } + + presentation->lastPublishTime += (data->hnsDuration / 10000); + if (presentation->lastPublishTime <= timeAfterH264 + 10) + { + int dropped = 0; + + /* if the frame is to be published in less than 10 ms, let's consider it's now */ + yuv_to_rgb(presentation, presentation->surfaceData); + + context->showSurface(context, presentation->surface); + + priv->publishedFrames++; + + /* cleanup previously scheduled frames */ + EnterCriticalSection(&priv->framesLock); + while (Queue_Count(priv->frames) > 0) + { + VideoFrame *frame = Queue_Dequeue(priv->frames); + if (frame) + { + priv->droppedFrames++; + VideoFrame_free(&frame); + dropped++; + } + } + LeaveCriticalSection(&priv->framesLock); + + if (dropped) + WLog_DBG(TAG, "showing frame (%d dropped)", dropped); + } + else + { + BOOL enqueueResult; + VideoFrame *frame = calloc(1, sizeof(*frame)); + if (!frame) + { + WLog_ERR(TAG, "unable to create frame"); + return CHANNEL_RC_NO_MEMORY; + } + mappedGeometryRef(geom); + + frame->presentation = presentation; + frame->publishTime = presentation->lastPublishTime; + frame->geometry = geom; + frame->w = presentation->SourceWidth; + frame->h = presentation->SourceHeight; + + frame->surfaceData = BufferPool_Take(priv->surfacePool, frame->w * frame->h * 4); + if (!frame->surfaceData) + { + WLog_ERR(TAG, "unable to allocate frame data"); + mappedGeometryUnref(geom); + free(frame); + return CHANNEL_RC_NO_MEMORY; + } + + if (!yuv_to_rgb(presentation, frame->surfaceData)) + { + WLog_ERR(TAG, "error during YUV->RGB conversion"); + BufferPool_Return(priv->surfacePool, frame->surfaceData); + mappedGeometryUnref(geom); + free(frame); + return CHANNEL_RC_NO_MEMORY; + } + + InterlockedIncrement(&presentation->refCounter); + + EnterCriticalSection(&priv->framesLock); + enqueueResult = Queue_Enqueue(priv->frames, frame); + LeaveCriticalSection(&priv->framesLock); + + if (!enqueueResult) + { + WLog_ERR(TAG, "unable to enqueue frame"); + VideoFrame_free(&frame); + return CHANNEL_RC_NO_MEMORY; + } + + WLog_DBG(TAG, "scheduling frame in %"PRIu32" ms", (frame->publishTime-startTime)); + } + } + + return CHANNEL_RC_OK; +} + + + +static UINT video_data_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *s) +{ + VIDEO_CHANNEL_CALLBACK* callback = (VIDEO_CHANNEL_CALLBACK*) pChannelCallback; + VIDEO_PLUGIN* video; + VideoClientContext *context; + UINT32 cbSize, packetType; + TSMM_VIDEO_DATA data; + + video = (VIDEO_PLUGIN*) callback->plugin; + context = (VideoClientContext *)video->wtsPlugin.pInterface; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, cbSize); + if (cbSize < 8 || Stream_GetRemainingLength(s) < (cbSize-4)) + { + WLog_ERR(TAG, "invalid cbSize"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, packetType); + if (packetType != TSMM_PACKET_TYPE_VIDEO_DATA) + { + WLog_ERR(TAG, "only expecting VIDEO_DATA on the data channel"); + return ERROR_INVALID_DATA; + } + + if (Stream_GetRemainingLength(s) < 32) + { + WLog_ERR(TAG, "not enough bytes for a TSMM_VIDEO_DATA"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT8(s, data.PresentationId); + Stream_Read_UINT8(s, data.Version); + Stream_Read_UINT8(s, data.Flags); + Stream_Seek_UINT8(s); /* reserved */ + Stream_Read_UINT64(s, data.hnsTimestamp); + Stream_Read_UINT64(s, data.hnsDuration); + Stream_Read_UINT16(s, data.CurrentPacketIndex); + Stream_Read_UINT16(s, data.PacketsInSample); + Stream_Read_UINT32(s, data.SampleNumber); + Stream_Read_UINT32(s, data.cbSample); + data.pSample = Stream_Pointer(s); + +/* + WLog_DBG(TAG, "videoData: id:%"PRIu8" version:%"PRIu8" flags:0x%"PRIx8" timestamp=%"PRIu64" duration=%"PRIu64 + " curPacketIndex:%"PRIu16" packetInSample:%"PRIu16" sampleNumber:%"PRIu32" cbSample:%"PRIu32"", + data.PresentationId, data.Version, data.Flags, data.hnsTimestamp, data.hnsDuration, + data.CurrentPacketIndex, data.PacketsInSample, data.SampleNumber, data.cbSample); +*/ + + return video_VideoData(context, &data); +} + + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT video_control_on_close(IWTSVirtualChannelCallback* pChannelCallback) +{ + free(pChannelCallback); + return CHANNEL_RC_OK; +} + +static UINT video_data_on_close(IWTSVirtualChannelCallback* pChannelCallback) +{ + free(pChannelCallback); + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT video_control_on_new_channel_connection(IWTSListenerCallback* listenerCallback, + IWTSVirtualChannel* channel, BYTE* Data, BOOL* pbAccept, + IWTSVirtualChannelCallback** ppCallback) +{ + VIDEO_CHANNEL_CALLBACK* callback; + VIDEO_LISTENER_CALLBACK* listener_callback = (VIDEO_LISTENER_CALLBACK*) listenerCallback; + + callback = (VIDEO_CHANNEL_CALLBACK*) calloc(1, sizeof(VIDEO_CHANNEL_CALLBACK)); + if (!callback) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + callback->iface.OnDataReceived = video_control_on_data_received; + callback->iface.OnClose = video_control_on_close; + callback->plugin = listener_callback->plugin; + callback->channel_mgr = listener_callback->channel_mgr; + callback->channel = channel; + listener_callback->channel_callback = callback; + + *ppCallback = (IWTSVirtualChannelCallback*) callback; + + return CHANNEL_RC_OK; +} + +static UINT video_data_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, + IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, + IWTSVirtualChannelCallback** ppCallback) +{ + VIDEO_CHANNEL_CALLBACK* callback; + VIDEO_LISTENER_CALLBACK* listener_callback = (VIDEO_LISTENER_CALLBACK*) pListenerCallback; + + callback = (VIDEO_CHANNEL_CALLBACK*) calloc(1, sizeof(VIDEO_CHANNEL_CALLBACK)); + if (!callback) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + callback->iface.OnDataReceived = video_data_on_data_received; + callback->iface.OnClose = video_data_on_close; + callback->plugin = listener_callback->plugin; + callback->channel_mgr = listener_callback->channel_mgr; + callback->channel = pChannel; + listener_callback->channel_callback = callback; + + *ppCallback = (IWTSVirtualChannelCallback*) callback; + + return CHANNEL_RC_OK; +} + + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT video_plugin_initialize(IWTSPlugin* plugin, IWTSVirtualChannelManager* channelMgr) +{ + UINT status; + VIDEO_PLUGIN* video = (VIDEO_PLUGIN *)plugin; + VIDEO_LISTENER_CALLBACK *callback; + + video->control_callback = callback = (VIDEO_LISTENER_CALLBACK*) calloc(1, sizeof(VIDEO_LISTENER_CALLBACK)); + if (!callback) + { + WLog_ERR(TAG, "calloc for control callback failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + callback->iface.OnNewChannelConnection = video_control_on_new_channel_connection; + callback->plugin = plugin; + callback->channel_mgr = channelMgr; + + status = channelMgr->CreateListener(channelMgr, VIDEO_CONTROL_DVC_CHANNEL_NAME, 0, + (IWTSListenerCallback*)callback, &(video->controlListener)); + + if (status != CHANNEL_RC_OK) + return status; + video->controlListener->pInterface = video->wtsPlugin.pInterface; + + + video->data_callback = callback = (VIDEO_LISTENER_CALLBACK*) calloc(1, sizeof(VIDEO_LISTENER_CALLBACK)); + if (!callback) + { + WLog_ERR(TAG, "calloc for data callback failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + callback->iface.OnNewChannelConnection = video_data_on_new_channel_connection; + callback->plugin = plugin; + callback->channel_mgr = channelMgr; + + status = channelMgr->CreateListener(channelMgr, VIDEO_DATA_DVC_CHANNEL_NAME, 0, + (IWTSListenerCallback*)callback, &(video->dataListener)); + + if (status == CHANNEL_RC_OK) + video->dataListener->pInterface = video->wtsPlugin.pInterface; + + return status; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT video_plugin_terminated(IWTSPlugin* pPlugin) +{ + VIDEO_PLUGIN* video = (VIDEO_PLUGIN*) pPlugin; + + if (video->context) + VideoClientContextPriv_free(video->context->priv); + + free(video->control_callback); + free(video->data_callback); + free(video->wtsPlugin.pInterface); + free(pPlugin); + return CHANNEL_RC_OK; +} + +/** + * Channel Client Interface + */ + + +#ifdef BUILTIN_CHANNELS +#define DVCPluginEntry video_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry +#endif + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) +{ + UINT error = CHANNEL_RC_OK; + VIDEO_PLUGIN* videoPlugin; + VideoClientContext* videoContext; + VideoClientContextPriv *priv; + + videoPlugin = (VIDEO_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "video"); + if (!videoPlugin) + { + videoPlugin = (VIDEO_PLUGIN*) calloc(1, sizeof(VIDEO_PLUGIN)); + if (!videoPlugin) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + videoPlugin->wtsPlugin.Initialize = video_plugin_initialize; + videoPlugin->wtsPlugin.Connected = NULL; + videoPlugin->wtsPlugin.Disconnected = NULL; + videoPlugin->wtsPlugin.Terminated = video_plugin_terminated; + + videoContext = (VideoClientContext*) calloc(1, sizeof(VideoClientContext)); + if (!videoContext) + { + WLog_ERR(TAG, "calloc failed!"); + free(videoPlugin); + return CHANNEL_RC_NO_MEMORY; + } + + priv = VideoClientContextPriv_new(videoContext); + if (!priv) + { + WLog_ERR(TAG, "VideoClientContextPriv_new failed!"); + free(videoContext); + free(videoPlugin); + return CHANNEL_RC_NO_MEMORY; + } + + videoContext->handle = (void*) videoPlugin; + videoContext->priv = priv; + videoContext->timer = video_timer; + videoContext->setGeometry = video_client_context_set_geometry; + + videoPlugin->wtsPlugin.pInterface = (void*) videoContext; + videoPlugin->context = videoContext; + + error = pEntryPoints->RegisterPlugin(pEntryPoints, "video", (IWTSPlugin*) videoPlugin); + } + else + { + WLog_ERR(TAG, "could not get video Plugin."); + return CHANNEL_RC_BAD_CHANNEL; + } + + return error; +} diff --git a/channels/video/client/video_main.h b/channels/video/client/video_main.h new file mode 100644 index 0000000..f5e5ac9 --- /dev/null +++ b/channels/video/client/video_main.h @@ -0,0 +1,35 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Video Optimized Remoting Virtual Channel Extension + * + * Copyright 2017 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_CHANNEL_VIDEO_CLIENT_MAIN_H +#define FREERDP_CHANNEL_VIDEO_CLIENT_MAIN_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include + + +#endif /* FREERDP_CHANNEL_GEOMETRY_CLIENT_MAIN_H */ + diff --git a/ci/cmake-preloads/config-android.txt b/ci/cmake-preloads/config-android.txt index 5f5e368..38833e7 100644 --- a/ci/cmake-preloads/config-android.txt +++ b/ci/cmake-preloads/config-android.txt @@ -1,5 +1,6 @@ message("PRELOADING android cache") set(CMAKE_TOOLCHAIN_FILE "cmake/AndroidToolchain.cmake" CACHE PATH "ToolChain file") +set(WITH_SANITIZE_ADDRESS ON) set(FREERDP_EXTERNAL_SSL_PATH $ENV{ANDROID_SSL_PATH} CACHE PATH "android ssl") # ANDROID_NDK and ANDROID_SDK must be set as environment variable #set(ANDROID_NDK $ENV{ANDROID_SDK} CACHE PATH "Android NDK") diff --git a/ci/cmake-preloads/config-debian-squeeze.txt b/ci/cmake-preloads/config-debian-squeeze.txt index 483a52a..c7319cf 100644 --- a/ci/cmake-preloads/config-debian-squeeze.txt +++ b/ci/cmake-preloads/config-debian-squeeze.txt @@ -2,9 +2,10 @@ message("PRELOADING cache") set (WITH_MANPAGES OFF CACHE BOOL "man pages") set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type") set (WITH_CUPS OFF CACHE BOOL "CUPS printing") -set (WITH_KRB5 ON CACHE BOOL "Kerberos support") +set (WITH_GSSAPI ON CACHE BOOL "Kerberos support") set (WITH_ALSA OFF CACHE BOOL "alsa audio") set (WITH_FFMPEG OFF CACHE BOOL "ffmepg support") set (WITH_XV OFF CACHE BOOL "xvideo support") set (BUILD_TESTING ON CACHE BOOL "build testing") set (WITH_XSHM OFF CACHE BOOL "build with xshm support") +set (WITH_SANITIZE_ADDRESS ON) diff --git a/ci/cmake-preloads/config-ios.txt b/ci/cmake-preloads/config-ios.txt index b7ae2fe..d37eda6 100644 --- a/ci/cmake-preloads/config-ios.txt +++ b/ci/cmake-preloads/config-ios.txt @@ -1,5 +1,6 @@ message("PRELOADING android cache") -set(CMAKE_TOOLCHAIN_FILE "cmake/iOSToolchain.cmake" CACHE PATH "ToolChain file") -set(FREERDP_IOS_EXTERNAL_SSL_PATH $ENV{FREERDP_IOS_EXTERNAL_SSL_PATH} CACHE PATH "android ssl") +set (CMAKE_TOOLCHAIN_FILE "cmake/iOSToolchain.cmake" CACHE PATH "ToolChain file") +set (FREERDP_IOS_EXTERNAL_SSL_PATH $ENV{FREERDP_IOS_EXTERNAL_SSL_PATH} CACHE PATH "android ssl") set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type") -set(IOS_PLATFORM "SIMULATOR" CACHE STRING "iso platfrorm to build") +set (IOS_PLATFORM "SIMULATOR" CACHE STRING "iso platfrorm to build") +set (WITH_SANITIZE_ADDRESS ON) diff --git a/ci/cmake-preloads/config-linux-all.txt b/ci/cmake-preloads/config-linux-all.txt index dd3221b..16d3f9f 100644 --- a/ci/cmake-preloads/config-linux-all.txt +++ b/ci/cmake-preloads/config-linux-all.txt @@ -7,7 +7,7 @@ set (WITH_PULSE ON CACHE BOOL "pulse") set (WITH_CHANNELS ON CACHE BOOL "channels") set (BUILTIN_CHANNELS ON CACHE BOOL "static channels") set (WITH_CUPS ON CACHE BOOL "cups") -set (WITH_KRB5 ON CACHE BOOL "Kerberos support") +set (WITH_GSSAPI ON CACHE BOOL "Kerberos support") set (WITH_PCSC ON CACHE BOOL "PCSC") set (WITH_JPEG ON CACHE BOOL "jepg") set (WITH_GSTREAMER_0_10 ON CACHE BOOL "gstreamer") @@ -47,3 +47,4 @@ set (WITH_DEBUG_X11_LOCAL_MOVESIZE OFF CACHE BOOL "enable debug") set (WITH_DEBUG_XV OFF CACHE BOOL "enable debug") set (WITH_SAMPLE ON CACHE BOOL "samples") set (WITH_NO_UNDEFINED ON CACHE BOOL "don't link with undefined symbols") +set (WITH_SANITIZE_ADDRESS ON) diff --git a/ci/cmake-preloads/config-macosx.txt b/ci/cmake-preloads/config-macosx.txt index 78afd26..8c68aed 100644 --- a/ci/cmake-preloads/config-macosx.txt +++ b/ci/cmake-preloads/config-macosx.txt @@ -4,3 +4,4 @@ set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type") set (WITH_CUPS ON CACHE BOOL "CUPS printing") set (WITH_X11 ON CACHE BOOL "Enable X11") set (BUILD_TESTING ON CACHE BOOL "build testing") +set (WITH_SANITIZE_ADDRESS ON) diff --git a/ci/cmake-preloads/config-ubuntu-1204.txt b/ci/cmake-preloads/config-ubuntu-1204.txt index 483a52a..c7319cf 100644 --- a/ci/cmake-preloads/config-ubuntu-1204.txt +++ b/ci/cmake-preloads/config-ubuntu-1204.txt @@ -2,9 +2,10 @@ message("PRELOADING cache") set (WITH_MANPAGES OFF CACHE BOOL "man pages") set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type") set (WITH_CUPS OFF CACHE BOOL "CUPS printing") -set (WITH_KRB5 ON CACHE BOOL "Kerberos support") +set (WITH_GSSAPI ON CACHE BOOL "Kerberos support") set (WITH_ALSA OFF CACHE BOOL "alsa audio") set (WITH_FFMPEG OFF CACHE BOOL "ffmepg support") set (WITH_XV OFF CACHE BOOL "xvideo support") set (BUILD_TESTING ON CACHE BOOL "build testing") set (WITH_XSHM OFF CACHE BOOL "build with xshm support") +set (WITH_SANITIZE_ADDRESS ON) diff --git a/ci/cmake-preloads/config-windows.txt b/ci/cmake-preloads/config-windows.txt index 723f370..33dc8b4 100644 --- a/ci/cmake-preloads/config-windows.txt +++ b/ci/cmake-preloads/config-windows.txt @@ -1,4 +1,5 @@ message("PRELOADING windows cache") set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type") -set(WITH_SERVER "ON" CACHE BOOL "Build server binaries") +set (WITH_SERVER "ON" CACHE BOOL "Build server binaries") set (BUILD_TESTING ON CACHE BOOL "build testing") +set (WITH_SANITIZE_ADDRESS ON) diff --git a/client/DirectFB/dfreerdp.c b/client/DirectFB/dfreerdp.c index 5207dc7..34bbf23 100644 --- a/client/DirectFB/dfreerdp.c +++ b/client/DirectFB/dfreerdp.c @@ -220,7 +220,7 @@ BOOL df_verify_certificate(freerdp* instance, char* subject, char* issuer, 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."); + "Please look at the OpenSSL documentation on how to add a private CA to the store."); while (1) { @@ -422,7 +422,7 @@ int main(int argc, char* argv[]) if (!(g_sem = CreateSemaphore(NULL, 0, 1, NULL))) { WLog_ERR(TAG, "Failed to create semaphore"); - exit(1); + return 1; } instance = freerdp_new(); @@ -437,7 +437,7 @@ int main(int argc, char* argv[]) if (!freerdp_context_new(instance)) { WLog_ERR(TAG, "Failed to create FreeRDP context"); - exit(1); + return 1; } context = (dfContext*) instance->context; @@ -449,11 +449,11 @@ int main(int argc, char* argv[]) argv, FALSE); if (status < 0) - exit(0); + return 0; if (!freerdp_client_load_addins(instance->context->channels, instance->settings)) - exit(-1); + return -1; data = (struct thread_data*) malloc(sizeof(struct thread_data)); ZeroMemory(data, sizeof(sizeof(struct thread_data))); diff --git a/client/Sample/freerdp.c b/client/Sample/freerdp.c index d46f8d1..cfbc30e 100644 --- a/client/Sample/freerdp.c +++ b/client/Sample/freerdp.c @@ -113,8 +113,9 @@ static BOOL tf_post_connect(freerdp* instance) return TRUE; } -static void* tf_client_thread_proc(freerdp* instance) +static DWORD WINAPI tf_client_thread_proc(LPVOID arg) { + freerdp* instance = (freerdp*)arg; DWORD nCount; DWORD status; HANDLE handles[64]; @@ -122,7 +123,7 @@ static void* tf_client_thread_proc(freerdp* instance) if (!freerdp_connect(instance)) { WLog_ERR(TAG, "connection failure"); - return NULL; + return 0; } while (!freerdp_shall_disconnect(instance)) @@ -146,14 +147,16 @@ static void* tf_client_thread_proc(freerdp* instance) if (!freerdp_check_event_handles(instance->context)) { - WLog_ERR(TAG, "Failed to check FreeRDP event handles"); + if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS) + WLog_ERR(TAG, "Failed to check FreeRDP event handles"); + break; } } freerdp_disconnect(instance); ExitThread(0); - return NULL; + return 0; } int main(int argc, char* argv[]) @@ -166,7 +169,7 @@ int main(int argc, char* argv[]) if (!instance) { WLog_ERR(TAG, "Couldn't create instance"); - exit(1); + return 1; } instance->PreConnect = tf_pre_connect; @@ -174,13 +177,12 @@ int main(int argc, char* argv[]) instance->ContextSize = sizeof(tfContext); instance->ContextNew = tf_context_new; instance->ContextFree = tf_context_free; - freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); if (!freerdp_context_new(instance)) { WLog_ERR(TAG, "Couldn't create context"); - exit(1); + return 1; } status = freerdp_client_settings_parse_command_line(instance->settings, argc, @@ -188,16 +190,14 @@ int main(int argc, char* argv[]) if (status < 0) { - exit(0); + return 0; } - if (!freerdp_client_load_addins(instance->context->channels, instance->settings)) - exit(-1); + return -1; - if (!(thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) - tf_client_thread_proc, instance, 0, NULL))) + if (!(thread = CreateThread(NULL, 0, tf_client_thread_proc, instance, 0, NULL))) { WLog_ERR(TAG, "Failed to create client thread"); } diff --git a/client/Wayland/wlf_channels.c b/client/Wayland/wlf_channels.c index 32cdb6b..38d66ef 100644 --- a/client/Wayland/wlf_channels.c +++ b/client/Wayland/wlf_channels.c @@ -56,11 +56,11 @@ static void wlf_encomsp_uninit(wlfContext* wlf, EncomspClientContext* encomsp) } -void wlf_OnChannelConnectedEventHandler(rdpContext* context, +void wlf_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e) { wlfContext* wlf = (wlfContext*) context; - rdpSettings* settings = context->settings; + rdpSettings* settings = wlf->context.settings; if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) { @@ -72,7 +72,7 @@ void wlf_OnChannelConnectedEventHandler(rdpContext* context, else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { if (settings->SoftwareGdi) - gdi_graphics_pipeline_init(context->gdi, (RdpgfxClientContext*) e->pInterface); + gdi_graphics_pipeline_init(wlf->context.gdi, (RdpgfxClientContext*) e->pInterface); } else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0) { @@ -86,11 +86,11 @@ void wlf_OnChannelConnectedEventHandler(rdpContext* context, } } -void wlf_OnChannelDisconnectedEventHandler(rdpContext* context, +void wlf_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEventArgs* e) { wlfContext* wlf = (wlfContext*) context; - rdpSettings* settings = context->settings; + rdpSettings* settings = wlf->context.settings; if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) { @@ -102,7 +102,7 @@ void wlf_OnChannelDisconnectedEventHandler(rdpContext* context, else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { if (settings->SoftwareGdi) - gdi_graphics_pipeline_uninit(context->gdi, + gdi_graphics_pipeline_uninit(wlf->context.gdi, (RdpgfxClientContext*) e->pInterface); } else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0) diff --git a/client/Wayland/wlf_channels.h b/client/Wayland/wlf_channels.h index d3d47d2..1b6c591 100644 --- a/client/Wayland/wlf_channels.h +++ b/client/Wayland/wlf_channels.h @@ -34,9 +34,9 @@ int wlf_on_channel_connected(freerdp* instance, const char* name, int wlf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface); -void wlf_OnChannelConnectedEventHandler(rdpContext* context, +void wlf_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e); -void wlf_OnChannelDisconnectedEventHandler(rdpContext* context, +void wlf_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEventArgs* e); #endif /* FREERDP_CLIENT_WAYLAND_CHANNELS_H */ diff --git a/client/Wayland/wlf_input.c b/client/Wayland/wlf_input.c index 00435ff..7b43c4c 100644 --- a/client/Wayland/wlf_input.c +++ b/client/Wayland/wlf_input.c @@ -92,7 +92,7 @@ BOOL wlf_handle_key(freerdp *instance, UwacKeyEvent *ev) { rdpInput* input = instance->input; DWORD rdp_scancode; - rdp_scancode = (DWORD) ev->raw_key; + rdp_scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(ev->raw_key + 8); if (rdp_scancode == RDP_SCANCODE_UNKNOWN) return TRUE; diff --git a/client/Wayland/wlfreerdp.1.in b/client/Wayland/wlfreerdp.1.in index d576a09..c268546 100644 --- a/client/Wayland/wlfreerdp.1.in +++ b/client/Wayland/wlfreerdp.1.in @@ -1,7 +1,7 @@ .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. -.if \n[.g] .mso www.tmac)) +.if \n[.g] .mso www.tmac .TH wlfreerdp 1 2017-01-12 "@FREERDP_VERSION_FULL@" "FreeRDP" .SH NAME wlfreerdp \- FreeRDP wayland client diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 4dccc37..a68b7f7 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -103,6 +103,8 @@ static BOOL wl_pre_connect(freerdp* instance) { rdpSettings* settings; wlfContext* context; + UwacOutput* output; + UwacSize resolution; if (!instance) return FALSE; @@ -142,9 +144,25 @@ static BOOL wl_pre_connect(freerdp* instance) settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; PubSub_SubscribeChannelConnected(instance->context->pubSub, - (pChannelConnectedEventHandler) wlf_OnChannelConnectedEventHandler); + wlf_OnChannelConnectedEventHandler); PubSub_SubscribeChannelDisconnected(instance->context->pubSub, - (pChannelDisconnectedEventHandler) wlf_OnChannelDisconnectedEventHandler); + wlf_OnChannelDisconnectedEventHandler); + + if (settings->Fullscreen) + { + // Use the resolution of the first display output + output = UwacDisplayGetOutput(context->display, 1); + + if (output != NULL && UwacOutputGetResolution(output, &resolution) == UWAC_SUCCESS) + { + settings->DesktopWidth = (UINT32) resolution.width; + settings->DesktopHeight = (UINT32) resolution.height; + } + else + { + WLog_WARN(TAG, "Failed to get output resolution! Check your display settings"); + } + } if (!freerdp_client_load_addins(instance->context->channels, instance->settings)) @@ -176,15 +194,14 @@ static BOOL wl_post_connect(freerdp* instance) UwacWindowSetFullscreenState(window, NULL, instance->context->settings->Fullscreen); UwacWindowSetTitle(window, "FreeRDP"); + UwacWindowSetOpaqueRegion(context->window, 0, 0, gdi->width, gdi->height); instance->update->BeginPaint = wl_begin_paint; instance->update->EndPaint = wl_end_paint; memcpy(UwacWindowGetDrawingBuffer(context->window), gdi->primary_buffer, gdi->width * gdi->height * 4); UwacWindowAddDamage(context->window, 0, 0, gdi->width, gdi->height); context->haveDamage = TRUE; - freerdp_keyboard_init(instance->context->settings->KeyboardLayout); - return wl_update_content(context); } @@ -328,7 +345,9 @@ static int wlfreerdp_run(freerdp* instance) //if (WaitForMultipleObjects(count, &handles[1], FALSE, INFINITE)) { if (freerdp_check_event_handles(instance->context) != TRUE) { - printf("Failed to check FreeRDP file descriptor\n"); + if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS) + printf("Failed to check FreeRDP file descriptor\n"); + break; } diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index bde78f7..e38e9b9 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -44,10 +44,14 @@ set(${MODULE_PREFIX}_SRCS xf_cliprdr.h xf_monitor.c xf_monitor.h + xf_disp.c + xf_disp.h xf_graphics.c xf_graphics.h xf_keyboard.c xf_keyboard.h + xf_video.c + xf_video.h xf_window.c xf_window.h xf_client.c @@ -86,13 +90,19 @@ if(WITH_MANPAGES) configure_file(xfreerdp.1.xml.in xfreerdp.1.xml @ONLY IMMEDIATE) - add_executable(generate_argument_docbook generate_argument_docbook.c) - - set(GAD_LIBS freerdp-client) - target_link_libraries(generate_argument_docbook ${GAD_LIBS} freerdp winpr) + # Compile the helper tool with default compiler settings. + # We need the include paths though. + get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) + set(GENERATE_INCLUDES "") + foreach(dir ${dirs}) + set(GENERATE_INCLUDES ${GENERATE_INCLUDES} -I${dir}) + endforeach(dir) add_custom_command(OUTPUT xfreerdp.1 - COMMAND generate_argument_docbook + COMMAND ${CMAKE_C_COMPILER} ${GENERATE_INCLUDES} + ${CMAKE_CURRENT_SOURCE_DIR}/generate_argument_docbook.c + -o ${CMAKE_CURRENT_BINARY_DIR}/generate_argument_docbook + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/generate_argument_docbook COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E copy @@ -101,12 +111,11 @@ if(WITH_MANPAGES) ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-envvar.1.xml ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${XSLTPROC_EXECUTABLE} ${DOCBOOKXSL_DIR}/manpages/docbook.xsl xfreerdp.1.xml WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS - ${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1.xml - ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml - ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml - ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-envvar.1.xml - generate_argument_docbook) + DEPENDS + ${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-envvar.1.xml) add_custom_target(xfreerdp.manpage ALL DEPENDS xfreerdp.1) @@ -145,6 +154,10 @@ set(XRENDER_FEATURE_TYPE "RECOMMENDED") set(XRENDER_FEATURE_PURPOSE "rendering") set(XRENDER_FEATURE_DESCRIPTION "X11 render extension") +set(XRANDR_FEATURE_TYPE "RECOMMENDED") +set(XRANDR_FEATURE_PURPOSE "tracking output configuration") +set(XRANDR_FEATURE_DESCRIPTION "X11 randr extension") + set(XFIXES_FEATURE_TYPE "RECOMMENDED") set(XFIXES_FEATURE_PURPOSE "X11 xfixes extension") set(XFIXES_FEATURE_DESCRIPTION "Useful additions to the X11 core protocol") @@ -156,6 +169,7 @@ find_feature(Xcursor ${XCURSOR_FEATURE_TYPE} ${XCURSOR_FEATURE_PURPOSE} ${XCURSO find_feature(Xv ${XV_FEATURE_TYPE} ${XV_FEATURE_PURPOSE} ${XV_FEATURE_DESCRIPTION}) find_feature(Xi ${XI_FEATURE_TYPE} ${XI_FEATURE_PURPOSE} ${XI_FEATURE_DESCRIPTION}) find_feature(Xrender ${XRENDER_FEATURE_TYPE} ${XRENDER_FEATURE_PURPOSE} ${XRENDER_FEATURE_DESCRIPTION}) +find_feature(XRandR ${XRANDR_FEATURE_TYPE} ${XRANDR_FEATURE_PURPOSE} ${XRANDR_FEATURE_DESCRIPTION}) find_feature(Xfixes ${XFIXES_FEATURE_TYPE} ${XFIXES_FEATURE_PURPOSE} ${XFIXES_FEATURE_DESCRIPTION}) if(WITH_XINERAMA) @@ -194,6 +208,12 @@ if(WITH_XRENDER) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${XRENDER_LIBRARIES}) endif() +if(WITH_XRANDR) + add_definitions(-DWITH_XRANDR) + include_directories(${XRANDR_INCLUDE_DIRS}) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${XRANDR_LIBRARIES}) +endif() + if(WITH_XFIXES) add_definitions(-DWITH_XFIXES) include_directories(${XFIXES_INCLUDE_DIRS}) diff --git a/client/X11/generate_argument_docbook.c b/client/X11/generate_argument_docbook.c index 1d54c43..0dea546 100644 --- a/client/X11/generate_argument_docbook.c +++ b/client/X11/generate_argument_docbook.c @@ -1,18 +1,15 @@ - #include #include #include +#include -#include +#include "../common/cmdline.h" -/* We need to include the command line c file to get access to - * the argument struct. */ -#include "../common/cmdline.c" - -LPSTR tr_esc_str(LPCSTR arg) +#define TAG FREERDP_TAG("generate_argument_docbook") +LPSTR tr_esc_str(LPCSTR arg, bool format) { LPSTR tmp = NULL; - size_t cs = 0, x, ds; + size_t cs = 0, x, ds, len; size_t s; if(NULL == arg) return NULL; @@ -26,7 +23,7 @@ LPSTR tr_esc_str(LPCSTR arg) tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR)); if(NULL == tmp) { - WLog_ERR(TAG, "Could not allocate string buffer."); + fprintf(stderr, "Could not allocate string buffer.\n"); exit(-2); } /* Copy character for character and check, if it is necessary to escape. */ @@ -36,37 +33,41 @@ LPSTR tr_esc_str(LPCSTR arg) switch(arg[x]) { case '<': - ds += 3; + len = format ? 13 : 4; + ds += len - 1; tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR)); if(NULL == tmp) { - WLog_ERR(TAG, "Could not reallocate string buffer."); + fprintf(stderr, "Could not reallocate string buffer.\n"); exit(-3); } - tmp[cs++] = '&'; - tmp[cs++] = 'l'; - tmp[cs++] = 't'; - tmp[cs++] = ';'; + if (format) + strncpy (&tmp[cs], "", len); + else + strncpy (&tmp[cs], "<", len); + cs += len; break; case '>': - ds += 3; + len = format ? 14 : 4; + ds += len - 1; tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR)); if(NULL == tmp) { - WLog_ERR(TAG, "Could not reallocate string buffer."); + fprintf(stderr, "Could not reallocate string buffer.\n"); exit(-4); } - tmp[cs++] = '&'; - tmp[cs++] = 'g'; - tmp[cs++] = 't'; - tmp[cs++] = ';'; + if (format) + strncpy (&tmp[cs], "", len); + else + strncpy (&tmp[cs], "<", len); + cs += len; break; case '\'': ds += 5; tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR)); if(NULL == tmp) { - WLog_ERR(TAG, "Could not reallocate string buffer."); + fprintf(stderr, "Could not reallocate string buffer.\n"); exit(-5); } tmp[cs++] = '&'; @@ -81,7 +82,7 @@ LPSTR tr_esc_str(LPCSTR arg) tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR)); if(NULL == tmp) { - WLog_ERR(TAG, "Could not reallocate string buffer."); + fprintf(stderr, "Could not reallocate string buffer.\n"); exit(-6); } tmp[cs++] = '&'; @@ -96,7 +97,7 @@ LPSTR tr_esc_str(LPCSTR arg) tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR)); if(NULL == tmp) { - WLog_ERR(TAG, "Could not reallocate string buffer."); + fprintf(stderr, "Could not reallocate string buffer.\n"); exit(-7); } tmp[cs++] = '&'; @@ -125,7 +126,7 @@ int main(int argc, char *argv[]) fp = fopen(fname, "w"); if(NULL == fp) { - WLog_ERR(TAG, "Could not open '%s' for writing.", fname); + fprintf(stderr, "Could not open '%s' for writing.\n", fname); return -1; } /* The tag used as header in the manpage */ @@ -136,39 +137,71 @@ int main(int argc, char *argv[]) * compatible XML */ if(elements < 2) { - WLog_ERR(TAG, "The argument array 'args' is empty, writing an empty file."); + fprintf(stderr, "The argument array 'args' is empty, writing an empty file.\n"); elements = 1; } for(x=0; xName); - const char *format = tr_esc_str(arg->Format); - const char *text = tr_esc_str((LPSTR) arg->Text); + char *name = tr_esc_str((LPSTR) arg->Name, FALSE); + char *alias = tr_esc_str((LPSTR) arg->Alias, FALSE); + char *format = tr_esc_str(arg->Format, TRUE); + char *text = tr_esc_str((LPSTR) arg->Text, FALSE); + fprintf(fp, "\t\t\t\n"); - fprintf(fp, "\t\t\t\t", name); - if ((arg->Flags == COMMAND_LINE_VALUE_REQUIRED) && format) - fprintf(fp, " %s\n", format); - fprintf(fp, "\n"); + do + { + fprintf(fp, "\t\t\t\t", name); - if (format || text) + if (format) + { + if (arg->Flags == COMMAND_LINE_VALUE_OPTIONAL) + fprintf(fp, "["); + fprintf(fp, ":%s", format); + if (arg->Flags == COMMAND_LINE_VALUE_OPTIONAL) + fprintf(fp, "]"); + } + + fprintf(fp, "\n"); + + if (alias == name) + break; + + free (name); + name = alias; + } + while (alias); + + if (text) { fprintf(fp, "\t\t\t\t\n"); - fprintf(fp, "\t\t\t\t\t%s\n", format ? format : ""); + fprintf(fp, "\t\t\t\t\t"); + if (text) - { - if (format) - fprintf(fp, " - "); fprintf(fp, "%s", text); + + if (arg->Flags == COMMAND_LINE_VALUE_BOOL) + fprintf(fp, " (default:%s)", arg->Default ? "on" : "off"); + else if (arg->Default) + { + char *value = tr_esc_str((LPSTR) arg->Default, FALSE); + fprintf(fp, " (default:%s)", value); + free (value); } + fprintf(fp, "\n"); fprintf(fp, "\t\t\t\t\n"); } fprintf(fp, "\t\t\t\n"); - free((void*) name); - free((void*) format); - free((void*) text); + free(name); + free(format); + free(text); } fprintf(fp, "\t\t\n"); fprintf(fp, "\t\n"); diff --git a/client/X11/xf_channels.c b/client/X11/xf_channels.c index ab948f9..17029a5 100644 --- a/client/X11/xf_channels.c +++ b/client/X11/xf_channels.c @@ -21,6 +21,7 @@ #include "config.h" #endif +#include #include "xf_channels.h" #include "xf_client.h" @@ -30,11 +31,13 @@ #include "xf_tsmf.h" #include "xf_rail.h" #include "xf_cliprdr.h" +#include "xf_disp.h" +#include "xf_video.h" -void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e) +void xf_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e) { xfContext* xfc = (xfContext*) context; - rdpSettings* settings = context->settings; + rdpSettings* settings = xfc->context.settings; if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) { @@ -47,7 +50,7 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { if (settings->SoftwareGdi) - gdi_graphics_pipeline_init(context->gdi, (RdpgfxClientContext*) e->pInterface); + gdi_graphics_pipeline_init(xfc->context.gdi, (RdpgfxClientContext*) e->pInterface); else xf_graphics_pipeline_init(xfc, (RdpgfxClientContext*) e->pInterface); } @@ -63,12 +66,31 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven { xf_encomsp_init(xfc, (EncomspClientContext*) e->pInterface); } + else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) + { + xf_disp_init(xfc, (DispClientContext*)e->pInterface); + } + else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0) + { + gdi_video_geometry_init(xfc->context.gdi, (GeometryClientContext*)e->pInterface); + } + else if (strcmp(e->name, VIDEO_CONTROL_DVC_CHANNEL_NAME) == 0) + { + if (settings->SoftwareGdi) + gdi_video_control_init(xfc->context.gdi, (VideoClientContext*)e->pInterface); + else + xf_video_control_init(xfc, (VideoClientContext*)e->pInterface); + } + else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0) + { + gdi_video_data_init(xfc->context.gdi, (VideoClientContext*)e->pInterface); + } } -void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e) +void xf_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEventArgs* e) { xfContext* xfc = (xfContext*) context; - rdpSettings* settings = context->settings; + rdpSettings* settings = xfc->context.settings; if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) { @@ -81,7 +103,7 @@ void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnect else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { if (settings->SoftwareGdi) - gdi_graphics_pipeline_uninit(context->gdi, (RdpgfxClientContext*) e->pInterface); + gdi_graphics_pipeline_uninit(xfc->context.gdi, (RdpgfxClientContext*) e->pInterface); else xf_graphics_pipeline_uninit(xfc, (RdpgfxClientContext*) e->pInterface); } @@ -97,4 +119,19 @@ void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnect { xf_encomsp_uninit(xfc, (EncomspClientContext*) e->pInterface); } + else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0) + { + gdi_video_geometry_uninit(xfc->context.gdi, (GeometryClientContext*)e->pInterface); + } + else if (strcmp(e->name, VIDEO_CONTROL_DVC_CHANNEL_NAME) == 0) + { + if (settings->SoftwareGdi) + gdi_video_control_uninit(xfc->context.gdi, (VideoClientContext*)e->pInterface); + else + xf_video_control_uninit(xfc, (VideoClientContext*)e->pInterface); + } + else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0) + { + gdi_video_data_uninit(xfc->context.gdi, (VideoClientContext*)e->pInterface); + } } diff --git a/client/X11/xf_channels.h b/client/X11/xf_channels.h index 441ca99..ac91f84 100644 --- a/client/X11/xf_channels.h +++ b/client/X11/xf_channels.h @@ -28,11 +28,14 @@ #include #include #include +#include +#include +#include int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface); int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface); -void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e); -void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e); +void xf_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e); +void xf_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEventArgs* e); #endif /* FREERDP_CLIENT_X11_CHANNELS_H */ diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 6391ac8..fba5b4a 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -30,6 +30,7 @@ #include #include +#include #ifdef WITH_XRENDER #include @@ -86,6 +87,7 @@ #include #include #include +#include #include #include "xf_gdi.h" @@ -94,6 +96,8 @@ #include "xf_event.h" #include "xf_input.h" #include "xf_cliprdr.h" +#include "xf_disp.h" +#include "xf_video.h" #include "xf_monitor.h" #include "xf_graphics.h" #include "xf_keyboard.h" @@ -222,8 +226,7 @@ void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h) } #endif - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, - x, y); + XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y); } static BOOL xf_desktop_resize(rdpContext* context) @@ -259,8 +262,7 @@ static BOOL xf_desktop_resize(rdpContext* context) if (!xfc->fullscreen) { - xf_ResizeDesktopWindow(xfc, xfc->window, settings->DesktopWidth, - settings->DesktopHeight); + xf_ResizeDesktopWindow(xfc, xfc->window, settings->DesktopWidth, settings->DesktopHeight); } else { @@ -287,9 +289,6 @@ static BOOL xf_desktop_resize(rdpContext* context) static BOOL xf_sw_begin_paint(rdpContext* context) { - rdpGdi* gdi = context->gdi; - gdi->primary->hdc->hwnd->invalid->null = TRUE; - gdi->primary->hdc->hwnd->ninvalid = 0; return TRUE; } @@ -302,6 +301,10 @@ static BOOL xf_sw_end_paint(rdpContext* context) HGDI_RGN cinvalid; xfContext* xfc = (xfContext*) context; rdpGdi* gdi = context->gdi; + + if (gdi->suppressOutput) + return TRUE; + x = gdi->primary->hdc->hwnd->invalid->x; y = gdi->primary->hdc->hwnd->invalid->y; w = gdi->primary->hdc->hwnd->invalid->w; @@ -354,6 +357,8 @@ static BOOL xf_sw_end_paint(rdpContext* context) xf_unlock_x11(xfc, FALSE); } + gdi->primary->hdc->hwnd->invalid->null = TRUE; + gdi->primary->hdc->hwnd->ninvalid = 0; return TRUE; } @@ -381,6 +386,8 @@ static BOOL xf_sw_desktop_resize(rdpContext* context) goto out; } + xfc->image->byte_order = LSBFirst; + xfc->image->bitmap_bit_order = LSBFirst; ret = xf_desktop_resize(context); out: xf_unlock_x11(xfc, TRUE); @@ -389,9 +396,6 @@ out: static BOOL xf_hw_begin_paint(rdpContext* context) { - xfContext* xfc = (xfContext*) context; - xfc->hdc->hwnd->invalid->null = TRUE; - xfc->hdc->hwnd->ninvalid = 0; return TRUE; } @@ -401,6 +405,9 @@ static BOOL xf_hw_end_paint(rdpContext* context) UINT32 w, h; xfContext* xfc = (xfContext*) context; + if (xfc->context.gdi->suppressOutput) + return TRUE; + if (!xfc->remote_app) { if (!xfc->complex_regions) @@ -456,6 +463,8 @@ static BOOL xf_hw_end_paint(rdpContext* context) xf_unlock_x11(xfc, FALSE); } + xfc->hdc->hwnd->invalid->null = TRUE; + xfc->hdc->hwnd->ninvalid = 0; return TRUE; } @@ -628,6 +637,8 @@ BOOL xf_create_window(xfContext* xfc) ZPixmap, 0, (char*) gdi->primary_buffer, settings->DesktopWidth, settings->DesktopHeight, xfc->scanline_pad, gdi->stride); + xfc->image->byte_order = LSBFirst; + xfc->image->bitmap_bit_order = LSBFirst; } return TRUE; @@ -635,12 +646,6 @@ BOOL xf_create_window(xfContext* xfc) static void xf_window_free(xfContext* xfc) { - if (xfc->gc_mono) - { - XFreeGC(xfc->display, xfc->gc_mono); - xfc->gc_mono = 0; - } - if (xfc->window) { xf_DestroyDesktopWindow(xfc, xfc->window); @@ -672,6 +677,12 @@ static void xf_window_free(xfContext* xfc) xfc->bitmap_mono = 0; } + if (xfc->gc_mono) + { + XFreeGC(xfc->display, xfc->gc_mono); + xfc->gc_mono = 0; + } + if (xfc->primary) { XFreePixmap(xfc->display, xfc->primary); @@ -772,15 +783,6 @@ void xf_unlock_x11(xfContext* xfc, BOOL display) } } -static void xf_calculate_color_shifts(UINT32 mask, UINT8* rsh, UINT8* lsh) -{ - for (*lsh = 0; !(mask & 1); mask >>= 1) - (*lsh)++; - - for (*rsh = 8; mask; mask >>= 1) - (*rsh)--; -} - static BOOL xf_get_pixmap_info(xfContext* xfc) { int i; @@ -849,20 +851,13 @@ static BOOL xf_get_pixmap_info(xfContext* xfc) if (xfc->visual) { /* - * Detect if the server visual has an inverted colormap - * (BGR vs RGB, or red being the least significant byte) - */ + * Detect if the server visual has an inverted colormap + * (BGR vs RGB, or red being the least significant byte) + */ if (vi->red_mask & 0xFF) { - xfc->invert = TRUE; + xfc->invert = FALSE; } - - /* calculate color shifts required for rdp order color conversion */ - xf_calculate_color_shifts(vi->red_mask, &xfc->red_shift_r, &xfc->red_shift_l); - xf_calculate_color_shifts(vi->green_mask, &xfc->green_shift_r, - &xfc->green_shift_l); - xf_calculate_color_shifts(vi->blue_mask, &xfc->blue_shift_r, - &xfc->blue_shift_l); } XFree(vis); @@ -1124,9 +1119,9 @@ static BOOL xf_pre_connect(freerdp* instance) settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; PubSub_SubscribeChannelConnected(instance->context->pubSub, - (pChannelConnectedEventHandler) xf_OnChannelConnectedEventHandler); + xf_OnChannelConnectedEventHandler); PubSub_SubscribeChannelDisconnected(instance->context->pubSub, - (pChannelDisconnectedEventHandler) xf_OnChannelDisconnectedEventHandler); + xf_OnChannelDisconnectedEventHandler); if (!freerdp_client_load_addins(channels, instance->settings)) return FALSE; @@ -1278,15 +1273,19 @@ static BOOL xf_post_connect(freerdp* instance) update->SetKeyboardIndicators = xf_keyboard_set_indicators; update->SetKeyboardImeStatus = xf_keyboard_set_ime_status; - if (!(xfc->clipboard = xf_clipboard_new(xfc))) return FALSE; + if (!(xfc->xfDisp = xf_disp_new(xfc))) + { + xf_clipboard_free(xfc->clipboard); + return FALSE; + } + EventArgsInit(&e, "xfreerdp"); e.width = settings->DesktopWidth; e.height = settings->DesktopHeight; PubSub_OnResizeWindow(context->pubSub, xfc, &e); - return TRUE; } @@ -1308,6 +1307,17 @@ static void xf_post_disconnect(freerdp* instance) xfc->clipboard = NULL; } + if (xfc->xfDisp) + { + xf_disp_free(xfc->xfDisp); + xfc->xfDisp = NULL; + } + + if ((xfc->window != NULL) && (xfc->drawable == xfc->window->handle)) + xfc->drawable = 0; + else + xf_DestroyDummyWindow(xfc, xfc->drawable); + xf_window_free(xfc); xf_keyboard_free(xfc); } @@ -1315,15 +1325,14 @@ static void xf_post_disconnect(freerdp* instance) static int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type) { xfContext* xfc = (xfContext*) instance->context; - const char *str_data = freerdp_get_logon_error_info_data(data); - const char *str_type = freerdp_get_logon_error_info_type(type); + const char* str_data = freerdp_get_logon_error_info_data(data); + const char* str_type = freerdp_get_logon_error_info_type(type); WLog_INFO(TAG, "Logon Error Info %s [%s]", str_data, str_type); - xf_rail_disable_remoteapp_mode(xfc); return 1; } -static void* xf_input_thread(void* arg) +static DWORD WINAPI xf_input_thread(LPVOID arg) { BOOL running = TRUE; DWORD status; @@ -1402,7 +1411,7 @@ static void* xf_input_thread(void* arg) MessageQueue_PostQuit(queue, 0); ExitThread(0); - return NULL; + return 0; } static BOOL xf_auto_reconnect(freerdp* instance) @@ -1454,10 +1463,10 @@ static BOOL xf_auto_reconnect(freerdp* instance) * @param instance - pointer to the rdp_freerdp structure that contains the session's settings * @return A code from the enum XF_EXIT_CODE (0 if successful) */ -static void* xf_client_thread(void* param) +static DWORD WINAPI xf_client_thread(LPVOID param) { BOOL status; - int exit_code; + DWORD exit_code = 0; DWORD nCount; DWORD waitStatus; HANDLE handles[64]; @@ -1466,29 +1475,34 @@ static void* xf_client_thread(void* param) rdpContext* context; HANDLE inputEvent = NULL; HANDLE inputThread = NULL; + HANDLE timer = NULL; + LARGE_INTEGER due; rdpSettings* settings; - exit_code = 0; + TimerEventArgs timerEvent; + EventArgsInit(&timerEvent, "xfreerdp"); instance = (freerdp*) param; context = instance->context; status = freerdp_connect(instance); xfc = (xfContext*) instance->context; + if (!status) + { + if (freerdp_get_last_error(instance->context) == + FREERDP_ERROR_AUTHENTICATION_FAILED) + exit_code = XF_EXIT_AUTH_FAILURE; + else + exit_code = XF_EXIT_CONN_FAILED; + } + else + exit_code = XF_EXIT_SUCCESS; + + if (!status) + goto end; + /* --authonly ? */ if (instance->settings->AuthenticationOnly) { WLog_ERR(TAG, "Authentication only, exit status %"PRId32"", !status); - - if (!status) - { - if (freerdp_get_last_error(instance->context) == - FREERDP_ERROR_AUTHENTICATION_FAILED) - exit_code = XF_EXIT_AUTH_FAILURE; - else - exit_code = XF_EXIT_CONN_FAILED; - } - else - exit_code = XF_EXIT_SUCCESS; - goto disconnect; } @@ -1507,16 +1521,31 @@ static void* xf_client_thread(void* param) } settings = context->settings; + timer = CreateWaitableTimerA(NULL, FALSE, "mainloop-periodic-timer"); + + if (!timer) + { + WLog_ERR(TAG, "failed to create timer"); + goto disconnect; + } + + due.QuadPart = 0; + + if (!SetWaitableTimer(timer, &due, 20, NULL, NULL, FALSE)) + { + goto disconnect; + } + + handles[0] = timer; if (!settings->AsyncInput) { inputEvent = xfc->x11event; - handles[0] = inputEvent; + handles[1] = inputEvent; } else { - if (!(inputThread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) xf_input_thread, instance, 0, NULL))) + if (!(inputThread = CreateThread(NULL, 0, xf_input_thread, instance, 0, NULL))) { WLog_ERR(TAG, "async input: failed to create input thread"); exit_code = XF_EXIT_UNKNOWN; @@ -1527,17 +1556,17 @@ static void* xf_client_thread(void* param) while (!freerdp_shall_disconnect(instance)) { /* - * win8 and server 2k12 seem to have some timing issue/race condition - * when a initial sync request is send to sync the keyboard indicators - * sending the sync event twice fixed this problem - */ + * win8 and server 2k12 seem to have some timing issue/race condition + * when a initial sync request is send to sync the keyboard indicators + * sending the sync event twice fixed this problem + */ if (freerdp_focus_required(instance)) { xf_keyboard_focus_in(xfc); xf_keyboard_focus_in(xfc); } - nCount = (settings->AsyncInput) ? 0 : 1; + nCount = (settings->AsyncInput) ? 1 : 2; if (!settings->AsyncTransport) { @@ -1552,7 +1581,7 @@ static void* xf_client_thread(void* param) nCount += tmp; } - waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, 100); + waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); if (waitStatus == WAIT_FAILED) break; @@ -1564,7 +1593,9 @@ static void* xf_client_thread(void* param) if (xf_auto_reconnect(instance)) continue; - WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); + if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) + WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); + break; } } @@ -1577,6 +1608,12 @@ static void* xf_client_thread(void* param) break; } } + + if ((status != WAIT_TIMEOUT) && (waitStatus == WAIT_OBJECT_0)) + { + timerEvent.now = GetTickCount64(); + PubSub_OnTimer(context->pubSub, context, &timerEvent); + } } if (settings->AsyncInput) @@ -1589,9 +1626,14 @@ static void* xf_client_thread(void* param) exit_code = freerdp_error_info(instance); disconnect: + + if (timer) + CloseHandle(timer); + freerdp_disconnect(instance); +end: ExitThread(exit_code); - return NULL; + return exit_code; } DWORD xf_exit_code_from_disconnect_reason(DWORD reason) @@ -1612,17 +1654,18 @@ DWORD xf_exit_code_from_disconnect_reason(DWORD reason) return reason; } -static void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e) +static void xf_TerminateEventHandler(void* context, TerminateEventArgs* e) { - freerdp_abort_connect(context->instance); + rdpContext* ctx = (rdpContext*)context; + freerdp_abort_connect(ctx->instance); } #ifdef WITH_XRENDER -static void xf_ZoomingChangeEventHandler(rdpContext* context, +static void xf_ZoomingChangeEventHandler(void* context, ZoomingChangeEventArgs* e) { xfContext* xfc = (xfContext*) context; - rdpSettings* settings = context->settings; + rdpSettings* settings = xfc->context.settings; int w = xfc->scaledWidth + e->dx; int h = xfc->scaledHeight + e->dy; @@ -1643,11 +1686,11 @@ static void xf_ZoomingChangeEventHandler(rdpContext* context, xf_draw_screen(xfc, 0, 0, settings->DesktopWidth, settings->DesktopHeight); } -static void xf_PanningChangeEventHandler(rdpContext* context, +static void xf_PanningChangeEventHandler(void* context, PanningChangeEventArgs* e) { xfContext* xfc = (xfContext*) context; - rdpSettings* settings = context->settings; + rdpSettings* settings = xfc->context.settings; if (e->dx == 0 && e->dy == 0) return; @@ -1688,8 +1731,7 @@ static int xfreerdp_client_start(rdpContext* context) return -1; } - if (!(xfc->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) xf_client_thread, + if (!(xfc->thread = CreateThread(NULL, 0, xf_client_thread, context->instance, 0, NULL))) { WLog_ERR(TAG, "failed to create client thread"); @@ -1714,6 +1756,19 @@ static int xfreerdp_client_stop(rdpContext* context) return 0; } +static Atom get_supported_atom(xfContext* xfc, const char* atomName) +{ + unsigned long i; + const Atom atom = XInternAtom(xfc->display, atomName, False); + + for (i = 0; i < xfc->supportedAtomCount; i++) + { + if (xfc->supportedAtoms[i] == atom) + return atom; + } + + return None; +} static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context) { xfContext* xfc = (xfContext*) instance->context; @@ -1731,12 +1786,12 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context) instance->VerifyChangedCertificate = client_cli_verify_changed_certificate; instance->LogonErrorInfo = xf_logon_error_info; PubSub_SubscribeTerminate(context->pubSub, - (pTerminateEventHandler) xf_TerminateEventHandler); + xf_TerminateEventHandler); #ifdef WITH_XRENDER PubSub_SubscribeZoomingChange(context->pubSub, - (pZoomingChangeEventHandler) xf_ZoomingChangeEventHandler); + xf_ZoomingChangeEventHandler); PubSub_SubscribePanningChange(context->pubSub, - (pPanningChangeEventHandler) xf_PanningChangeEventHandler); + xf_PanningChangeEventHandler); #endif xfc->UseXThreads = TRUE; //xfc->debug = TRUE; @@ -1768,20 +1823,49 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context) goto fail_create_mutex; } + xfc->xfds = ConnectionNumber(xfc->display); + xfc->screen_number = DefaultScreen(xfc->display); + xfc->screen = ScreenOfDisplay(xfc->display, xfc->screen_number); + xfc->depth = DefaultDepthOfScreen(xfc->screen); + xfc->big_endian = (ImageByteOrder(xfc->display) == MSBFirst); + xfc->invert = TRUE; + xfc->complex_regions = TRUE; + xfc->_NET_SUPPORTED = XInternAtom(xfc->display, "_NET_SUPPORTED", True); + xfc->_NET_SUPPORTING_WM_CHECK = XInternAtom(xfc->display, "_NET_SUPPORTING_WM_CHECK", True); + + if ((xfc->_NET_SUPPORTED != None) && (xfc->_NET_SUPPORTING_WM_CHECK != None)) + { + Atom actual_type; + int actual_format; + unsigned long nitems, after; + unsigned char* data = NULL; + int status = XGetWindowProperty(xfc->display, RootWindowOfScreen(xfc->screen), + xfc->_NET_SUPPORTED, 0, 1024, False, XA_ATOM, + &actual_type, &actual_format, &nitems, &after, &data); + + if ((status == Success) && (actual_type == XA_ATOM) && (actual_format == 32)) + { + xfc->supportedAtomCount = nitems; + xfc->supportedAtoms = calloc(nitems, sizeof(Atom)); + memcpy(xfc->supportedAtoms, data, nitems * sizeof(Atom)); + } + + if (data) + XFree(data); + } + xfc->_NET_WM_ICON = XInternAtom(xfc->display, "_NET_WM_ICON", False); xfc->_MOTIF_WM_HINTS = XInternAtom(xfc->display, "_MOTIF_WM_HINTS", False); xfc->_NET_CURRENT_DESKTOP = XInternAtom(xfc->display, "_NET_CURRENT_DESKTOP", False); xfc->_NET_WORKAREA = XInternAtom(xfc->display, "_NET_WORKAREA", False); - xfc->_NET_WM_STATE = XInternAtom(xfc->display, "_NET_WM_STATE", False); - xfc->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfc->display, - "_NET_WM_STATE_FULLSCREEN", False); + xfc->_NET_WM_STATE = get_supported_atom(xfc, "_NET_WM_STATE"); + xfc->_NET_WM_STATE_FULLSCREEN = get_supported_atom(xfc, "_NET_WM_STATE_FULLSCREEN"); xfc->_NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); xfc->_NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False); - xfc->_NET_WM_FULLSCREEN_MONITORS = XInternAtom(xfc->display, - "_NET_WM_FULLSCREEN_MONITORS", False); + xfc->_NET_WM_FULLSCREEN_MONITORS = get_supported_atom(xfc, "_NET_WM_FULLSCREEN_MONITORS"); xfc->_NET_WM_NAME = XInternAtom(xfc->display, "_NET_WM_NAME", False); xfc->_NET_WM_PID = XInternAtom(xfc->display, "_NET_WM_PID", False); xfc->_NET_WM_WINDOW_TYPE = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE", @@ -1808,13 +1892,6 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context) xfc->WM_PROTOCOLS = XInternAtom(xfc->display, "WM_PROTOCOLS", False); xfc->WM_DELETE_WINDOW = XInternAtom(xfc->display, "WM_DELETE_WINDOW", False); xfc->WM_STATE = XInternAtom(xfc->display, "WM_STATE", False); - xfc->xfds = ConnectionNumber(xfc->display); - xfc->screen_number = DefaultScreen(xfc->display); - xfc->screen = ScreenOfDisplay(xfc->display, xfc->screen_number); - xfc->depth = DefaultDepthOfScreen(xfc->screen); - xfc->big_endian = (ImageByteOrder(xfc->display) == MSBFirst); - xfc->invert = (ImageByteOrder(xfc->display) == MSBFirst) ? FALSE : TRUE; - xfc->complex_regions = TRUE; xfc->x11event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, xfc->xfds, WINPR_FD_READ); @@ -1891,6 +1968,8 @@ static void xfreerdp_client_free(freerdp* instance, rdpContext* context) free(xfc->vscreen.monitors); xfc->vscreen.monitors = NULL; } + + free(xfc->supportedAtoms); } int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index e471385..e141e19 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -320,7 +320,10 @@ static wStream* xf_cliprdr_serialize_server_format_list(xfClipboard* clipboard) } Stream_Write_UINT32(s, format->formatId); - Stream_Write(s, format->formatName, name_length); + + if (format->formatName) + Stream_Write(s, format->formatName, name_length); + Stream_Write_UINT8(s, '\0'); } @@ -436,7 +439,8 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_raw_server_formats(xfClipboard* clipboard, { WLog_ERR(TAG, "failed to retrieve raw format list: data=%p, length=%lu, format=%d, type=%lu (expected=%lu)", - (void*) data, length, format, (unsigned long) type, (unsigned long) clipboard->raw_format_list_atom); + (void*) data, length, format, (unsigned long) type, + (unsigned long) clipboard->raw_format_list_atom); } if (data) @@ -630,15 +634,13 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, * to not process CF_RAW as a file list in case WinPR does not support file transfers. */ if (dstFormatId && - (dstFormatId == ClipboardGetFormatId(clipboard->system, "FileGroupDescriptorW"))) + (dstFormatId == ClipboardGetFormatId(clipboard->system, "FileGroupDescriptorW"))) { UINT error = NO_ERROR; FILEDESCRIPTOR* file_array = (FILEDESCRIPTOR*) pDstData; UINT32 file_count = DstSize / sizeof(FILEDESCRIPTOR); - pDstData = NULL; DstSize = 0; - error = cliprdr_serialize_file_list(file_array, file_count, &pDstData, &DstSize); if (error) @@ -817,6 +819,7 @@ static void xf_cliprdr_clear_cached_data(xfClipboard* clipboard) free(clipboard->data); clipboard->data = NULL; } + clipboard->data_length = 0; if (clipboard->data_raw) @@ -824,6 +827,7 @@ static void xf_cliprdr_clear_cached_data(xfClipboard* clipboard) free(clipboard->data_raw); clipboard->data_raw = NULL; } + clipboard->data_raw_length = 0; } @@ -904,7 +908,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, /* We can compare format names by pointer value here as they are both * taken from the same clipboard->serverFormats array */ matchingFormat = (formatId == clipboard->data_format_id) - && (formatName == clipboard->data_format_name); + && (formatName == clipboard->data_format_name); if (matchingFormat && (clipboard->data != 0) && !rawTransfer) { @@ -930,7 +934,6 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, * Response will be postponed after receiving the data */ xf_cliprdr_clear_cached_data(clipboard); - respond->xselection.property = xevent->xselectionrequest.property; clipboard->respond = respond; clipboard->data_format_id = formatId; @@ -1078,7 +1081,7 @@ static UINT xf_cliprdr_send_client_capabilities(xfClipboard* clipboard) if (clipboard->streams_supported && clipboard->file_formats_registered) generalCapabilitySet.generalFlags |= - CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS; + CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS; return clipboard->context->ClientCapabilities(clipboard->context, &capabilities); @@ -1180,7 +1183,6 @@ static UINT xf_cliprdr_server_capabilities(CliprdrClientContext* context, const CLIPRDR_GENERAL_CAPABILITY_SET* generalCaps; const BYTE* capsPtr = (const BYTE*) capabilities->capabilitySets; xfClipboard* clipboard = (xfClipboard*) context->custom; - clipboard->streams_supported = FALSE; for (i = 0; i < capabilities->cCapabilitiesSets; i++) @@ -1211,21 +1213,19 @@ static UINT xf_cliprdr_server_capabilities(CliprdrClientContext* context, static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList) { - int i, j; - CLIPRDR_FORMAT* format; + UINT32 i; + int j; xfClipboard* clipboard = (xfClipboard*) context->custom; xfContext* xfc = clipboard->xfc; UINT ret; - xf_cliprdr_clear_cached_data(clipboard); - clipboard->data_format_id = -1; clipboard->data_format_name = NULL; if (clipboard->serverFormats) { - for (i = 0; i < clipboard->numServerFormats; i++) - free(clipboard->serverFormats[i].formatName); + for (j = 0; j < clipboard->numServerFormats; j++) + free(clipboard->serverFormats[j].formatName); free(clipboard->serverFormats); clipboard->serverFormats = NULL; @@ -1244,7 +1244,7 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, for (i = 0; i < formatList->numFormats; i++) { - format = &formatList->formats[i]; + CLIPRDR_FORMAT* format = &formatList->formats[i]; clipboard->serverFormats[i].formatId = format->formatId; if (format->formatName) @@ -1253,8 +1253,10 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, if (!clipboard->serverFormats[i].formatName) { - for (--i; i >= 0; --i) - free(clipboard->serverFormats[i].formatName); + UINT32 k; + + for (k = 0; k < i; k++) + free(clipboard->serverFormats[k].formatName); clipboard->numServerFormats = 0; free(clipboard->serverFormats); @@ -1265,15 +1267,17 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, } /* CF_RAW is always implicitly supported by the server */ - format = &clipboard->serverFormats[formatList->numFormats]; - format->formatId = CF_RAW; - format->formatName = NULL; + { + CLIPRDR_FORMAT* 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++) { - format = &formatList->formats[i]; + CLIPRDR_FORMAT* format = &formatList->formats[i]; for (j = 0; j < clipboard->numClientFormats; j++) { @@ -1362,7 +1366,6 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* return CHANNEL_RC_OK; xf_cliprdr_clear_cached_data(clipboard); - pDstData = NULL; DstSize = 0; srcFormatId = 0; @@ -1430,11 +1433,11 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* * conversion again on subsequent requests */ clipboard->data = pDstData; clipboard->data_length = DstSize; - /* We have to copy the original data again, as pSrcData is now owned * by clipboard->system. Memory allocation failure is not fatal here * as this is only a cached value. */ clipboard->data_raw = (BYTE*) malloc(size); + if (clipboard->data_raw) { CopyMemory(clipboard->data_raw, data, size); @@ -1455,56 +1458,48 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* } static UINT xf_cliprdr_server_file_size_request(xfClipboard* clipboard, - const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) + const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) { wClipboardFileSizeRequest request; - ZeroMemory(&request, sizeof(request)); - request.streamId = fileContentsRequest->streamId; request.listIndex = fileContentsRequest->listIndex; if (fileContentsRequest->cbRequested != sizeof(UINT64)) { WLog_WARN(TAG, "unexpected FILECONTENTS_SIZE request: %"PRIu32" bytes", - fileContentsRequest->cbRequested); + fileContentsRequest->cbRequested); } return clipboard->delegate->ClientRequestFileSize(clipboard->delegate, &request); } static UINT xf_cliprdr_server_file_range_request(xfClipboard* clipboard, - const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) + const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) { wClipboardFileRangeRequest request; - ZeroMemory(&request, sizeof(request)); - request.streamId = fileContentsRequest->streamId; request.listIndex = fileContentsRequest->listIndex; request.nPositionLow = fileContentsRequest->nPositionLow; request.nPositionHigh = fileContentsRequest->nPositionHigh; request.cbRequested = fileContentsRequest->cbRequested; - return clipboard->delegate->ClientRequestFileRange(clipboard->delegate, &request); } static UINT xf_cliprdr_send_file_contents_failure(CliprdrClientContext* context, - const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) + const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) { CLIPRDR_FILE_CONTENTS_RESPONSE response; - ZeroMemory(&response, sizeof(response)); - response.msgFlags = CB_RESPONSE_FAIL; response.streamId = fileContentsRequest->streamId; response.dwFlags = fileContentsRequest->dwFlags; - return context->ClientFileContentsResponse(context, &response); } static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* context, - CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) + CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) { UINT error = NO_ERROR; xfClipboard* clipboard = context->custom; @@ -1514,10 +1509,9 @@ static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* contex * The FILECONTENTS_SIZE and FILECONTENTS_RANGE flags MUST NOT be set at the same time. */ if ((fileContentsRequest->dwFlags & (FILECONTENTS_SIZE | FILECONTENTS_RANGE)) == - (FILECONTENTS_SIZE | FILECONTENTS_RANGE)) + (FILECONTENTS_SIZE | FILECONTENTS_RANGE)) { WLog_ERR(TAG, "invalid CLIPRDR_FILECONTENTS_REQUEST.dwFlags"); - return xf_cliprdr_send_file_contents_failure(context, fileContentsRequest); } @@ -1530,7 +1524,6 @@ static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* contex if (error) { WLog_ERR(TAG, "failed to handle CLIPRDR_FILECONTENTS_REQUEST: 0x%08X", error); - return xf_cliprdr_send_file_contents_failure(context, fileContentsRequest); } @@ -1538,66 +1531,54 @@ static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* contex } static UINT xf_cliprdr_clipboard_file_size_success(wClipboardDelegate* delegate, - const wClipboardFileSizeRequest* request, UINT64 fileSize) + const wClipboardFileSizeRequest* request, UINT64 fileSize) { CLIPRDR_FILE_CONTENTS_RESPONSE response; xfClipboard* clipboard = delegate->custom; - ZeroMemory(&response, sizeof(response)); - response.msgFlags = CB_RESPONSE_OK; response.streamId = request->streamId; response.dwFlags = FILECONTENTS_SIZE; response.cbRequested = sizeof(UINT64); response.requestedData = (BYTE*) &fileSize; - return clipboard->context->ClientFileContentsResponse(clipboard->context, &response); } static UINT xf_cliprdr_clipboard_file_size_failure(wClipboardDelegate* delegate, - const wClipboardFileSizeRequest* request, UINT errorCode) + const wClipboardFileSizeRequest* request, UINT errorCode) { CLIPRDR_FILE_CONTENTS_RESPONSE response; xfClipboard* clipboard = delegate->custom; - ZeroMemory(&response, sizeof(response)); - response.msgFlags = CB_RESPONSE_FAIL; response.streamId = request->streamId; response.dwFlags = FILECONTENTS_SIZE; - return clipboard->context->ClientFileContentsResponse(clipboard->context, &response); } static UINT xf_cliprdr_clipboard_file_range_success(wClipboardDelegate* delegate, - const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size) + const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size) { CLIPRDR_FILE_CONTENTS_RESPONSE response; xfClipboard* clipboard = delegate->custom; - ZeroMemory(&response, sizeof(response)); - response.msgFlags = CB_RESPONSE_OK; response.streamId = request->streamId; response.dwFlags = FILECONTENTS_RANGE; response.cbRequested = size; response.requestedData = (BYTE*) data; - return clipboard->context->ClientFileContentsResponse(clipboard->context, &response); } static UINT xf_cliprdr_clipboard_file_range_failure(wClipboardDelegate* delegate, - const wClipboardFileRangeRequest* request, UINT errorCode) + const wClipboardFileRangeRequest* request, UINT errorCode) { CLIPRDR_FILE_CONTENTS_RESPONSE response; xfClipboard* clipboard = delegate->custom; - ZeroMemory(&response, sizeof(response)); - response.msgFlags = CB_RESPONSE_FAIL; response.streamId = request->streamId; response.dwFlags = FILECONTENTS_RANGE; - return clipboard->context->ClientFileContentsResponse(clipboard->context, &response); } @@ -1631,12 +1612,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); + 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 + if (XFixesQueryExtension(xfc->display, &clipboard->xfixes_event_base, &clipboard->xfixes_error_base)) { @@ -1662,40 +1642,34 @@ xfClipboard* xf_clipboard_new(xfContext* xfc) WLog_ERR(TAG, "Warning: Using clipboard redirection without XFIXES extension is strongly discouraged!"); #endif - clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "_FREERDP_RAW", False); clipboard->clientFormats[n].formatId = CF_RAW; n++; - clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "UTF8_STRING", False); clipboard->clientFormats[n].formatId = CF_UNICODETEXT; n++; - clipboard->clientFormats[n].atom = XA_STRING; clipboard->clientFormats[n].formatId = CF_TEXT; n++; - clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/png", False); clipboard->clientFormats[n].formatId = CB_FORMAT_PNG; n++; - clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/jpeg", False); clipboard->clientFormats[n].formatId = CB_FORMAT_JPEG; n++; - clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/gif", False); clipboard->clientFormats[n].formatId = CB_FORMAT_GIF; n++; - clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/bmp", False); clipboard->clientFormats[n].formatId = CF_DIB; n++; - clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "text/html", False); clipboard->clientFormats[n].formatId = CB_FORMAT_HTML; clipboard->clientFormats[n].formatName = _strdup("HTML Format"); + if (!clipboard->clientFormats[n].formatName) goto error; + n++; /* @@ -1710,8 +1684,10 @@ xfClipboard* xf_clipboard_new(xfContext* xfc) clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "text/uri-list", False); clipboard->clientFormats[n].formatId = CB_FORMAT_TEXTURILIST; clipboard->clientFormats[n].formatName = _strdup("FileGroupDescriptorW"); + if (!clipboard->clientFormats[n].formatName) goto error; + n++; } @@ -1720,24 +1696,20 @@ xfClipboard* xf_clipboard_new(xfContext* xfc) clipboard->targets[1] = XInternAtom(xfc->display, "TARGETS", FALSE); clipboard->numTargets = 2; clipboard->incr_atom = XInternAtom(xfc->display, "INCR", FALSE); - clipboard->delegate = ClipboardGetDelegate(clipboard->system); clipboard->delegate->custom = clipboard; clipboard->delegate->ClipboardFileSizeSuccess = xf_cliprdr_clipboard_file_size_success; clipboard->delegate->ClipboardFileSizeFailure = xf_cliprdr_clipboard_file_size_failure; clipboard->delegate->ClipboardFileRangeSuccess = xf_cliprdr_clipboard_file_range_success; clipboard->delegate->ClipboardFileRangeFailure = xf_cliprdr_clipboard_file_range_failure; - return clipboard; - error: + for (i = 0; i < n; i++) free(clipboard->clientFormats[i].formatName); ClipboardDestroy(clipboard->system); - free(clipboard); - return NULL; } diff --git a/client/X11/xf_disp.c b/client/X11/xf_disp.c new file mode 100644 index 0000000..49d9601 --- /dev/null +++ b/client/X11/xf_disp.c @@ -0,0 +1,333 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * X11 Display Control channel + * + * Copyright 2017 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. + */ + +#include +#include + +#ifdef WITH_XRANDR +#include +#include + +#if (RANDR_MAJOR * 100 + RANDR_MINOR) >= 105 +# define USABLE_XRANDR +#endif + +#endif + +#include "xf_disp.h" +#include "xf_monitor.h" + + +#define TAG CLIENT_TAG("x11disp") +#define RESIZE_MIN_DELAY 200 /* minimum delay in ms between two resizes */ + +struct _xfDispContext +{ + xfContext *xfc; + BOOL haveXRandr; + int eventBase, errorBase; + int lastSentWidth, lastSentHeight; + UINT64 lastSentDate; + int targetWidth, targetHeight; + BOOL activated; + BOOL waitingResize; +}; + + +static BOOL xf_disp_sendResize(xfDispContext *xfDisp, int width, int height) +{ + DISPLAY_CONTROL_MONITOR_LAYOUT layout; + xfContext *xfc = xfDisp->xfc; + rdpSettings *settings = xfc->context.settings; + + xfDisp->lastSentDate = GetTickCount64(); + xfDisp->lastSentWidth = width; + xfDisp->lastSentHeight = height; + xfDisp->waitingResize = TRUE; + + layout.Flags = DISPLAY_CONTROL_MONITOR_PRIMARY; + layout.Top = layout.Left = 0; + layout.Width = width; + layout.Height = height; + layout.Orientation = ORIENTATION_LANDSCAPE; + layout.DesktopScaleFactor = settings->DesktopScaleFactor; + layout.DeviceScaleFactor = settings->DeviceScaleFactor; + layout.PhysicalWidth = width; + layout.PhysicalHeight = height; + + return xfc->disp->SendMonitorLayout(xfc->disp, 1, &layout) == CHANNEL_RC_OK; +} + + +static BOOL xf_disp_set_window_resizable(xfDispContext *xfDisp) +{ + XSizeHints *size_hints; + + if (!(size_hints = XAllocSizeHints())) + return FALSE; + + size_hints->flags = PMinSize | PMaxSize | PWinGravity; + size_hints->win_gravity = NorthWestGravity; + size_hints->min_width = size_hints->min_height = 320; + size_hints->max_width = size_hints->max_height = 8192; + if (xfDisp->xfc->window) + XSetWMNormalHints(xfDisp->xfc->display, xfDisp->xfc->window->handle, size_hints); + XFree(size_hints); + return TRUE; +} + + +static void xf_disp_OnActivated(void* context, ActivatedEventArgs* e) +{ + xfContext *xfc = (xfContext *)context; + xfDispContext *xfDisp = xfc->xfDisp; + rdpSettings *settings = xfc->context.settings; + + xfDisp->waitingResize = FALSE; + + if (xfDisp->activated && !settings->Fullscreen) + { + xf_disp_set_window_resizable(xfDisp); + + if (e->firstActivation) + return; + + /* if a resize has been done recently don't do anything and let the timer + * perform the resize */ + if (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY) + return; + + if ((xfDisp->lastSentWidth != xfDisp->targetWidth) || (xfDisp->lastSentHeight != xfDisp->targetHeight)) + { + WLog_DBG(TAG, "performing delayed resize to %dx%d", xfDisp->targetWidth, xfDisp->targetHeight); + xf_disp_sendResize(xfDisp, xfDisp->targetWidth, xfDisp->targetHeight); + } + } +} + + +static void xf_disp_OnGraphicsReset(void* context, GraphicsResetEventArgs* e) +{ + xfContext *xfc = (xfContext *)context; + xfDispContext *xfDisp = xfc->xfDisp; + rdpSettings *settings = xfc->context.settings; + + xfDisp->waitingResize = FALSE; + + if (xfDisp->activated && !settings->Fullscreen) + { + xf_disp_set_window_resizable(xfDisp); + + /* if a resize has been done recently don't do anything and let the timer + * perform the resize */ + if (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY) + return; + + if ((xfDisp->lastSentWidth != xfDisp->targetWidth) || (xfDisp->lastSentHeight != xfDisp->targetHeight)) + { + WLog_DBG(TAG, "performing delayed resize to %dx%d", xfDisp->targetWidth, xfDisp->targetHeight); + xf_disp_sendResize(xfDisp, xfDisp->targetWidth, xfDisp->targetHeight); + } + } +} + +static void xf_disp_OnTimer(void* context, TimerEventArgs* e) +{ + xfContext *xfc = (xfContext *)context; + xfDispContext *xfDisp = xfc->xfDisp; + rdpSettings *settings = xfc->context.settings; + + if (!xfDisp->activated || settings->Fullscreen) + return; + + if (e->now - xfDisp->lastSentDate < RESIZE_MIN_DELAY) + return; + + if ((xfDisp->lastSentWidth != xfDisp->targetWidth) || (xfDisp->lastSentHeight != xfDisp->targetHeight)) + { + WLog_DBG(TAG, "timer performing delayed resize to %dx%d", xfDisp->targetWidth, xfDisp->targetHeight); + xf_disp_sendResize(xfDisp, xfDisp->targetWidth, xfDisp->targetHeight); + } +} + +xfDispContext *xf_disp_new(xfContext* xfc) +{ + xfDispContext *ret = calloc(1, sizeof(xfDispContext)); + if (!ret) + return NULL; + + ret->xfc = xfc; +#ifdef USABLE_XRANDR + if (XRRQueryExtension(xfc->display, &ret->eventBase, &ret->errorBase)) + { + ret->haveXRandr = TRUE; + } +#endif + ret->lastSentWidth = ret->targetWidth = xfc->context.settings->DesktopWidth; + ret->lastSentHeight = ret->targetHeight = xfc->context.settings->DesktopHeight; + + PubSub_SubscribeActivated(xfc->context.pubSub, xf_disp_OnActivated); + PubSub_SubscribeGraphicsReset(xfc->context.pubSub, xf_disp_OnGraphicsReset); + PubSub_SubscribeTimer(xfc->context.pubSub, xf_disp_OnTimer); + return ret; +} + +void xf_disp_free(xfDispContext *disp) +{ + PubSub_UnsubscribeActivated(disp->xfc->context.pubSub, xf_disp_OnActivated); + PubSub_UnsubscribeTimer(disp->xfc->context.pubSub, xf_disp_OnTimer); + free(disp); +} + +static UINT xf_disp_sendLayout(DispClientContext *disp, rdpMonitor *monitors, int nmonitors) +{ + UINT ret = CHANNEL_RC_OK; + DISPLAY_CONTROL_MONITOR_LAYOUT *layouts; + int i; + xfDispContext *xfDisp = (xfDispContext *)disp->custom; + rdpSettings *settings = xfDisp->xfc->context.settings; + + layouts = calloc(nmonitors, sizeof(DISPLAY_CONTROL_MONITOR_LAYOUT)); + if (!layouts) + return CHANNEL_RC_NO_MEMORY; + + for (i = 0; i < nmonitors; i++) + { + layouts[i].Flags = (monitors[i].is_primary ? DISPLAY_CONTROL_MONITOR_PRIMARY : 0); + layouts[i].Left = monitors[i].x; + layouts[i].Top = monitors[i].y; + layouts[i].Width = monitors[i].width; + layouts[i].Height = monitors[i].height; + layouts[i].Orientation = ORIENTATION_LANDSCAPE; + layouts[i].PhysicalWidth = monitors[i].attributes.physicalWidth; + layouts[i].PhysicalHeight = monitors[i].attributes.physicalHeight; + + switch(monitors[i].attributes.orientation) + { + case 90: + layouts[i].Orientation = ORIENTATION_PORTRAIT; + break; + case 180: + layouts[i].Orientation = ORIENTATION_LANDSCAPE_FLIPPED; + break; + case 270: + layouts[i].Orientation = ORIENTATION_PORTRAIT_FLIPPED; + break; + case 0: + default: + /* MS-RDPEDISP - 2.2.2.2.1: + * Orientation (4 bytes): A 32-bit unsigned integer that specifies the + * orientation of the monitor in degrees. Valid values are 0, 90, 180 + * or 270 + * + * So we default to ORIENTATION_LANDSCAPE + */ + layouts[i].Orientation = ORIENTATION_LANDSCAPE; + break; + } + layouts[i].DesktopScaleFactor = settings->DesktopScaleFactor; + layouts[i].DeviceScaleFactor = settings->DeviceScaleFactor; + } + + ret = disp->SendMonitorLayout(disp, nmonitors, layouts); + + free(layouts); + + return ret; +} + +BOOL xf_disp_handle_xevent(xfContext *xfc, XEvent *event) +{ + xfDispContext *xfDisp = xfc->xfDisp; + rdpSettings *settings = xfc->context.settings; + UINT32 maxWidth, maxHeight; + + if (!xfDisp->haveXRandr) + return TRUE; + +#ifdef USABLE_XRANDR + if (event->type != xfDisp->eventBase + RRScreenChangeNotify) + return TRUE; +#endif + + xf_detect_monitors(xfc, &maxWidth, &maxHeight); + return xf_disp_sendLayout(xfc->disp, settings->MonitorDefArray, settings->MonitorCount) == CHANNEL_RC_OK; +} + + +BOOL xf_disp_handle_configureNotify(xfContext *xfc, int width, int height) +{ + xfDispContext *xfDisp = xfc->xfDisp; + + if (xfDisp->lastSentWidth == width && xfDisp->lastSentHeight == height) + return TRUE; + + if (xfDisp->waitingResize || !xfDisp->activated || + (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY)) + { + WLog_DBG(TAG, "delaying resize to %dx%d", width, height); + xfDisp->targetWidth = width; + xfDisp->targetHeight = height; + return TRUE; + } + + WLog_DBG(TAG, "resizing on ConfigureNotify to %dx%d", width, height); + return xf_disp_sendResize(xfDisp, width, height); +} + + +UINT xf_DisplayControlCaps(DispClientContext *disp, UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB) +{ + /* we're called only if dynamic resolution update is activated */ + xfDispContext *xfDisp = (xfDispContext *)disp->custom; + rdpSettings *settings = xfDisp->xfc->context.settings; + + WLog_DBG(TAG, "DisplayControlCapsPdu: MaxNumMonitors: %"PRIu32" MaxMonitorAreaFactorA: %"PRIu32" MaxMonitorAreaFactorB: %"PRIu32"", + maxNumMonitors, maxMonitorAreaFactorA, maxMonitorAreaFactorB); + + xfDisp->activated = TRUE; + + if (settings->Fullscreen) + return CHANNEL_RC_OK; + + WLog_DBG(TAG, "DisplayControlCapsPdu: setting the window as resizeable"); + return xf_disp_set_window_resizable(xfDisp) ? CHANNEL_RC_OK : CHANNEL_RC_NO_MEMORY; +} + +BOOL xf_disp_init(xfContext* xfc, DispClientContext *disp) +{ + rdpSettings *settings = xfc->context.settings; + xfc->disp = disp; + disp->custom = (void*) xfc->xfDisp; + + if (settings->DynamicResolutionUpdate) + { + disp->DisplayControlCaps = xf_DisplayControlCaps; +#ifdef USABLE_XRANDR + if (settings->Fullscreen) + { + /* ask X11 to notify us of screen changes */ + XRRSelectInput(xfc->display, DefaultRootWindow(xfc->display), RRScreenChangeNotifyMask); + } +#endif + } + + return TRUE; +} + diff --git a/client/X11/xf_disp.h b/client/X11/xf_disp.h new file mode 100644 index 0000000..b730e32 --- /dev/null +++ b/client/X11/xf_disp.h @@ -0,0 +1,36 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * X11 Display Control channel + * + * Copyright 2017 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_CLIENT_X11_DISP_H +#define FREERDP_CLIENT_X11_DISP_H + +#include +#include + +#include "xf_client.h" +#include "xfreerdp.h" + +FREERDP_API BOOL xf_disp_init(xfContext* xfc, DispClientContext *disp); + +xfDispContext *xf_disp_new(xfContext* xfc); +void xf_disp_free(xfDispContext *disp); +BOOL xf_disp_handle_xevent(xfContext *xfc, XEvent *event); +BOOL xf_disp_handle_configureNotify(xfContext *xfc, int width, int height); +void xf_disp_resized(xfDispContext *disp); + +#endif /* FREERDP_CLIENT_X11_DISP_H */ diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index 4e1a8fa..3dca71e 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -30,6 +30,7 @@ #include "xf_rail.h" #include "xf_window.h" #include "xf_cliprdr.h" +#include "xf_disp.h" #include "xf_input.h" #include "xf_gfx.h" @@ -40,44 +41,116 @@ #define CLAMP_COORDINATES(x, y) if (x < 0) x = 0; if (y < 0) y = 0 -static const char* const X11_EVENT_STRINGS[] = +static const char* x11_event_string(int event) { - "", "", - "KeyPress", - "KeyRelease", - "ButtonPress", - "ButtonRelease", - "MotionNotify", - "EnterNotify", - "LeaveNotify", - "FocusIn", - "FocusOut", - "KeymapNotify", - "Expose", - "GraphicsExpose", - "NoExpose", - "VisibilityNotify", - "CreateNotify", - "DestroyNotify", - "UnmapNotify", - "MapNotify", - "MapRequest", - "ReparentNotify", - "ConfigureNotify", - "ConfigureRequest", - "GravityNotify", - "ResizeRequest", - "CirculateNotify", - "CirculateRequest", - "PropertyNotify", - "SelectionClear", - "SelectionRequest", - "SelectionNotify", - "ColormapNotify", - "ClientMessage", - "MappingNotify", - "GenericEvent", -}; + switch (event) + { + case KeyPress: + return "KeyPress"; + + case KeyRelease: + return "KeyRelease"; + + case ButtonPress: + return "ButtonPress"; + + case ButtonRelease: + return "ButtonRelease"; + + case MotionNotify: + return "MotionNotify"; + + case EnterNotify: + return "EnterNotify"; + + case LeaveNotify: + return "LeaveNotify"; + + case FocusIn: + return "FocusIn"; + + case FocusOut: + return "FocusOut"; + + case KeymapNotify: + return "KeymapNotify"; + + case Expose: + return "Expose"; + + case GraphicsExpose: + return "GraphicsExpose"; + + case NoExpose: + return "NoExpose"; + + case VisibilityNotify: + return "VisibilityNotify"; + + case CreateNotify: + return "CreateNotify"; + + case DestroyNotify: + return "DestroyNotify"; + + case UnmapNotify: + return "UnmapNotify"; + + case MapNotify: + return "MapNotify"; + + case MapRequest: + return "MapRequest"; + + case ReparentNotify: + return "ReparentNotify"; + + case ConfigureNotify: + return "ConfigureNotify"; + + case ConfigureRequest: + return "ConfigureRequest"; + + case GravityNotify: + return "GravityNotify"; + + case ResizeRequest: + return "ResizeRequest"; + + case CirculateNotify: + return "CirculateNotify"; + + case CirculateRequest: + return "CirculateRequest"; + + case PropertyNotify: + return "PropertyNotify"; + + case SelectionClear: + return "SelectionClear"; + + case SelectionRequest: + return "SelectionRequest"; + + case SelectionNotify: + return "SelectionNotify"; + + case ColormapNotify: + return "ColormapNotify"; + + case ClientMessage: + return "ClientMessage"; + + case MappingNotify: + return "MappingNotify"; + + case GenericEvent: + return "GenericEvent"; + + default: + return "UNKNOWN"; + }; +} #ifdef WITH_DEBUG_X11 #define DEBUG_X11(...) WLog_DBG(TAG, __VA_ARGS__) @@ -128,7 +201,6 @@ void xf_event_action_script_free(xfContext* xfc) xfc->xevents = NULL; } } - static BOOL xf_event_execute_action_script(xfContext* xfc, XEvent* event) { int index; @@ -143,10 +215,10 @@ static BOOL xf_event_execute_action_script(xfContext* xfc, XEvent* event) if (!xfc->actionScriptExists || !xfc->xevents) return FALSE; - if (event->type > (sizeof(X11_EVENT_STRINGS) / sizeof(const char*))) + if (event->type > LASTEvent) return FALSE; - xeventName = X11_EVENT_STRINGS[event->type]; + xeventName = x11_event_string(event->type); count = ArrayList_Count(xfc->xevents); for (index = 0; index < count; index++) @@ -178,7 +250,6 @@ static BOOL xf_event_execute_action_script(xfContext* xfc, XEvent* event) pclose(actionScript); return TRUE; } - void xf_event_adjust_coordinates(xfContext* xfc, int* x, int* y) { rdpSettings* settings; @@ -205,7 +276,6 @@ void xf_event_adjust_coordinates(xfContext* xfc, int* x, int* y) CLAMP_COORDINATES(*x, *y); } - static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) { int x, y; @@ -227,7 +297,7 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) h = event->xexpose.height; } - if (xfc->gfx) + if (xfc->context.gdi->gfx) { xf_OutputExpose(xfc, x, y, w, h); return TRUE; @@ -250,13 +320,11 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } - static BOOL xf_event_VisibilityNotify(xfContext* xfc, XEvent* event, BOOL app) { xfc->unobscured = event->xvisibility.state == VisibilityUnobscured; return TRUE; } - BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window window, BOOL app) { @@ -283,7 +351,7 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, } xf_event_adjust_coordinates(xfc, &x, &y); - input->MouseEvent(input, PTR_FLAGS_MOVE, x, y); + freerdp_input_send_mouse_event(input, PTR_FLAGS_MOVE, x, y); if (xfc->fullscreen && !app) { @@ -293,7 +361,6 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, return TRUE; } - static BOOL xf_event_MotionNotify(xfContext* xfc, XEvent* event, BOOL app) { if (xfc->use_xinput) @@ -302,7 +369,6 @@ static BOOL xf_event_MotionNotify(xfContext* xfc, XEvent* event, BOOL app) return xf_generic_MotionNotify(xfc, event->xmotion.x, event->xmotion.y, event->xmotion.state, event->xmotion.window, app); } - BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window window, BOOL app) { @@ -366,7 +432,7 @@ BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, { if (wheel) { - input->MouseEvent(input, flags, 0, 0); + freerdp_input_send_mouse_event(input, flags, 0, 0); } else { @@ -385,15 +451,14 @@ BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, xf_event_adjust_coordinates(xfc, &x, &y); if (extended) - input->ExtendedMouseEvent(input, flags, x, y); + freerdp_input_send_extended_mouse_event(input, flags, x, y); else - input->MouseEvent(input, flags, x, y); + freerdp_input_send_mouse_event(input, flags, x, y); } } return TRUE; } - static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app) { if (xfc->use_xinput) @@ -402,7 +467,6 @@ static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app) return xf_generic_ButtonPress(xfc, event->xbutton.x, event->xbutton.y, event->xbutton.button, event->xbutton.window, app); } - BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window window, BOOL app) { @@ -460,14 +524,13 @@ BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, xf_event_adjust_coordinates(xfc, &x, &y); if (extended) - input->ExtendedMouseEvent(input, flags, x, y); + freerdp_input_send_extended_mouse_event(input, flags, x, y); else - input->MouseEvent(input, flags, x, y); + freerdp_input_send_mouse_event(input, flags, x, y); } return TRUE; } - static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app) { if (xfc->use_xinput) @@ -476,7 +539,6 @@ static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app) return xf_generic_ButtonRelease(xfc, event->xbutton.x, event->xbutton.y, event->xbutton.button, event->xbutton.window, app); } - static BOOL xf_event_KeyPress(xfContext* xfc, XEvent* event, BOOL app) { KeySym keysym; @@ -485,18 +547,14 @@ static BOOL xf_event_KeyPress(xfContext* xfc, XEvent* event, BOOL app) xf_keyboard_key_press(xfc, event->xkey.keycode, keysym); return TRUE; } - static BOOL xf_event_KeyRelease(xfContext* xfc, XEvent* event, BOOL app) { - XEvent nextEvent; KeySym keysym; char str[256]; - XLookupString((XKeyEvent*) event, str, sizeof(str), &keysym, NULL); xf_keyboard_key_release(xfc, event->xkey.keycode, keysym); return TRUE; } - static BOOL xf_event_FocusIn(xfContext* xfc, XEvent* event, BOOL app) { if (event->xfocus.mode == NotifyGrab) @@ -524,7 +582,6 @@ static BOOL xf_event_FocusIn(xfContext* xfc, XEvent* event, BOOL app) xf_keyboard_focus_in(xfc); return TRUE; } - static BOOL xf_event_FocusOut(xfContext* xfc, XEvent* event, BOOL app) { if (event->xfocus.mode == NotifyUngrab) @@ -543,7 +600,6 @@ static BOOL xf_event_FocusOut(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } - static BOOL xf_event_MappingNotify(xfContext* xfc, XEvent* event, BOOL app) { if (event->xmapping.request == MappingModifier) @@ -556,7 +612,6 @@ static BOOL xf_event_MappingNotify(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } - static BOOL xf_event_ClientMessage(xfContext* xfc, XEvent* event, BOOL app) { if ((event->xclient.message_type == xfc->WM_PROTOCOLS) @@ -583,7 +638,6 @@ static BOOL xf_event_ClientMessage(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } - static BOOL xf_event_EnterNotify(xfContext* xfc, XEvent* event, BOOL app) { if (!app) @@ -613,7 +667,6 @@ static BOOL xf_event_EnterNotify(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } - static BOOL xf_event_LeaveNotify(xfContext* xfc, XEvent* event, BOOL app) { if (!app) @@ -624,7 +677,6 @@ static BOOL xf_event_LeaveNotify(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } - static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app) { Window childWindow; @@ -664,6 +716,15 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app) #endif } + if (settings->DynamicResolutionUpdate) + { + int alignedWidth, alignedHeight; + alignedWidth = (xfc->window->width / 2) * 2; + alignedHeight = (xfc->window->height / 2) * 2; + /* ask the server to resize using the display channel */ + xf_disp_handle_configureNotify(xfc, alignedWidth, alignedHeight); + } + return TRUE; } @@ -703,22 +764,12 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } - static BOOL xf_event_MapNotify(xfContext* xfc, XEvent* event, BOOL app) { - RECTANGLE_16 rect; xfAppWindow* appWindow; - rdpUpdate* update = xfc->context.update; - rdpSettings* settings = xfc->context.settings; if (!app) - { - rect.left = 0; - rect.top = 0; - rect.right = settings->DesktopWidth; - rect.bottom = settings->DesktopHeight; - update->SuppressOutput((rdpContext*) xfc, 1, &rect); - } + gdi_send_suppress_output(xfc->context.gdi, FALSE); else { appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); @@ -737,17 +788,13 @@ static BOOL xf_event_MapNotify(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } - static BOOL xf_event_UnmapNotify(xfContext* xfc, XEvent* event, BOOL app) { xfAppWindow* appWindow; - rdpUpdate* update = xfc->context.update; xf_keyboard_release_all_keypress(xfc); if (!app) - { - update->SuppressOutput((rdpContext*) xfc, 0, NULL); - } + gdi_send_suppress_output(xfc->context.gdi, TRUE); else { appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); @@ -760,7 +807,6 @@ static BOOL xf_event_UnmapNotify(xfContext* xfc, XEvent* event, BOOL app) return TRUE; } - static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) { /* @@ -768,70 +814,72 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) * when the window has been minimized, maximized, restored locally * ie. not using the buttons on the rail window itself */ - if (app) + if ((((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) + && (event->xproperty.state != PropertyDelete)) || + (((Atom) event->xproperty.atom == xfc->WM_STATE) + && (event->xproperty.state != PropertyDelete))) { - xfAppWindow* appWindow; - appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); + int i; + BOOL status; + BOOL maxVert = FALSE; + BOOL maxHorz = FALSE; + BOOL minimized = FALSE; + BOOL minimizedChanged = FALSE; + unsigned long nitems; + unsigned long bytes; + unsigned char* prop; - if (!appWindow) - return TRUE; - - if ((((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) - && (event->xproperty.state != PropertyDelete)) || - (((Atom) event->xproperty.atom == xfc->WM_STATE) - && (event->xproperty.state != PropertyDelete))) + if ((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) { - int i; - BOOL status; - BOOL maxVert = FALSE; - BOOL maxHorz = FALSE; - BOOL minimized = FALSE; - unsigned long nitems; - unsigned long bytes; - unsigned char* prop; + status = xf_GetWindowProperty(xfc, event->xproperty.window, + xfc->_NET_WM_STATE, 12, &nitems, &bytes, &prop); - if ((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) + if (status) { - status = xf_GetWindowProperty(xfc, event->xproperty.window, - xfc->_NET_WM_STATE, 12, &nitems, &bytes, &prop); - - if (status) + for (i = 0; i < nitems; i++) { - for (i = 0; i < nitems; i++) + if ((Atom)((UINT16**) prop)[i] == XInternAtom(xfc->display, + "_NET_WM_STATE_MAXIMIZED_VERT", False)) { - if ((Atom)((UINT16**) prop)[i] == XInternAtom(xfc->display, - "_NET_WM_STATE_MAXIMIZED_VERT", False)) - { - maxVert = TRUE; - } - - if ((Atom)((UINT16**) prop)[i] == XInternAtom(xfc->display, - "_NET_WM_STATE_MAXIMIZED_HORZ", False)) - { - maxHorz = TRUE; - } + maxVert = TRUE; } - XFree(prop); + if ((Atom)((UINT16**) prop)[i] == XInternAtom(xfc->display, + "_NET_WM_STATE_MAXIMIZED_HORZ", False)) + { + maxHorz = TRUE; + } } - } - if ((Atom) event->xproperty.atom == xfc->WM_STATE) + XFree(prop); + } + } + + if ((Atom) event->xproperty.atom == xfc->WM_STATE) + { + status = xf_GetWindowProperty(xfc, event->xproperty.window, + xfc->WM_STATE, 1, &nitems, &bytes, &prop); + + if (status) { - status = xf_GetWindowProperty(xfc, event->xproperty.window, - xfc->WM_STATE, 1, &nitems, &bytes, &prop); + /* If the window is in the iconic state */ + if (((UINT32) *prop == 3)) + minimized = TRUE; + else + minimized = FALSE; - if (status) - { - /* If the window is in the iconic state */ - if (((UINT32) *prop == 3)) - minimized = TRUE; - else - minimized = FALSE; - - XFree(prop); - } + minimizedChanged = TRUE; + XFree(prop); } + } + + if (app) + { + xfAppWindow* appWindow; + appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); + + if (!appWindow) + return TRUE; if (maxVert && maxHorz && !minimized && (appWindow->rail_state != WINDOW_SHOW_MAXIMIZED)) @@ -851,11 +899,12 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app) xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE); } } + else if (minimizedChanged) + gdi_send_suppress_output(xfc->context.gdi, minimized); } return TRUE; } - static BOOL xf_event_suppress_events(xfContext* xfc, xfAppWindow* appWindow, XEvent* event) { @@ -941,13 +990,12 @@ static BOOL xf_event_suppress_events(xfContext* xfc, xfAppWindow* appWindow, return FALSE; } - - BOOL xf_event_process(freerdp* instance, XEvent* event) { BOOL status = TRUE; xfAppWindow* appWindow; xfContext* xfc = (xfContext*) instance->context; + rdpSettings* settings = xfc->context.settings; if (xfc->remote_app) { @@ -966,8 +1014,10 @@ BOOL xf_event_process(freerdp* instance, XEvent* event) xf_event_execute_action_script(xfc, event); if (event->type != MotionNotify) - DEBUG_X11("%s Event(%d): wnd=0x%08lX", X11_EVENT_STRINGS[event->type], + { + DEBUG_X11("%s Event(%d): wnd=0x%08lX", x11_event_string(event->type), event->type, (unsigned long) event->xany.window); + } switch (event->type) { @@ -1047,10 +1097,15 @@ BOOL xf_event_process(freerdp* instance, XEvent* event) case PropertyNotify: status = xf_event_PropertyNotify(xfc, event, xfc->remote_app); break; + + default: + if (settings->SupportDisplayControl && xfc->xfDisp) + xf_disp_handle_xevent(xfc, event); + + break; } xf_cliprdr_handle_xevent(xfc, event); - xf_input_handle_event(xfc, event); XSync(xfc->display, FALSE); return status; diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 57a3e53..be255d0 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -241,9 +241,13 @@ static Pixmap xf_brush_new(xfContext* xfc, UINT32 width, UINT32 height, &xfc->context.gdi->palette, FREERDP_FLIP_NONE); image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*) cdata, width, height, xfc->scanline_pad, 0); + image->byte_order = LSBFirst; + image->bitmap_bit_order = LSBFirst; gc = XCreateGC(xfc->display, xfc->drawable, 0, NULL); XPutImage(xfc->display, bitmap, gc, image, 0, 0, 0, 0, width, height); - XFree(image); + + image->data = NULL; + XDestroyImage(image); if (cdata != data) _aligned_free(cdata); @@ -264,8 +268,11 @@ static Pixmap xf_mono_bitmap_new(xfContext* xfc, int width, int height, bitmap = XCreatePixmap(xfc->display, xfc->drawable, width, height, 1); image = XCreateImage(xfc->display, xfc->visual, 1, ZPixmap, 0, (char*) data, width, height, 8, scanline); + image->byte_order = LSBFirst; + image->bitmap_bit_order = LSBFirst; XPutImage(xfc->display, bitmap, xfc->gc_mono, image, 0, 0, 0, 0, width, height); - XFree(image); + image->data = NULL; + XDestroyImage(image); return bitmap; } @@ -365,7 +372,12 @@ static BOOL xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) case GDI_BS_PATTERN: if (brush->bpp > 1) { - Pixmap pattern = xf_brush_new(xfc, 8, 8, brush->bpp, brush->data); + UINT32 bpp = brush->bpp; + + if ((bpp == 16) && (context->settings->ColorDepth == 15)) + bpp = 15; + + Pixmap pattern = xf_brush_new(xfc, 8, 8, bpp, brush->data); XSetFillStyle(xfc->display, xfc->gc, FillTiled); XSetTile(xfc->display, xfc->gc, pattern); XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y); @@ -677,7 +689,12 @@ static BOOL xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) case GDI_BS_PATTERN: if (brush->bpp > 1) { - pattern = xf_brush_new(xfc, 8, 8, brush->bpp, brush->data); + UINT32 bpp = brush->bpp; + + if ((bpp == 16) && (context->settings->ColorDepth == 15)) + bpp = 15; + + pattern = xf_brush_new(xfc, 8, 8, bpp, brush->data); XSetFillStyle(xfc->display, xfc->gc, FillTiled); XSetTile(xfc->display, xfc->gc, pattern); XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y); @@ -850,7 +867,12 @@ static BOOL xf_gdi_polygon_cb(rdpContext* context, { if (brush->bpp > 1) { - pattern = xf_brush_new(xfc, 8, 8, brush->bpp, brush->data); + UINT32 bpp = brush->bpp; + + if ((bpp == 16) && (context->settings->ColorDepth == 15)) + bpp = 15; + + pattern = xf_brush_new(xfc, 8, 8, bpp, brush->data); XSetFillStyle(xfc->display, xfc->gc, FillTiled); XSetTile(xfc->display, xfc->gc, pattern); } @@ -975,6 +997,7 @@ static BOOL xf_gdi_update_screen(xfContext* xfc, const BYTE* pSrcData, XImage* image; UINT32 i, nbRects; const RECTANGLE_16* rects; + UINT32 bpp; if (!xfc || !pSrcData) return FALSE; @@ -982,6 +1005,12 @@ static BOOL xf_gdi_update_screen(xfContext* xfc, const BYTE* pSrcData, if (!(rects = region16_rects(pRegion, &nbRects))) return TRUE; + if (xfc->depth > 16) + bpp = 4; + else if (xfc->depth > 8) + bpp = 2; + else + bpp = 1; XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); @@ -991,15 +1020,19 @@ static BOOL xf_gdi_update_screen(xfContext* xfc, const BYTE* pSrcData, UINT32 top = rects[i].top; UINT32 width = rects[i].right - rects[i].left; UINT32 height = rects[i].bottom - rects[i].top; - const BYTE* src = pSrcData + top * scanline + 4 * left; + const BYTE* src = pSrcData + top * scanline + bpp * left; image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*) src, width, height, xfc->scanline_pad, scanline); if (!image) break; + image->byte_order = LSBFirst; + image->bitmap_bit_order = LSBFirst; + XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, left, top, width, height); - XFree(image); + image->data = NULL; + XDestroyImage(image); ret = xf_gdi_surface_update_frame(xfc, left, top, width, height); } @@ -1024,19 +1057,19 @@ static BOOL xf_gdi_surface_bits(rdpContext* context, region16_init(®ion); cmdRect.left = cmd->destLeft; cmdRect.top = cmd->destTop; - cmdRect.right = cmdRect.left + cmd->width; - cmdRect.bottom = cmdRect.top + cmd->height; + cmdRect.right = cmdRect.left + cmd->bmp.width; + cmdRect.bottom = cmdRect.top + cmd->bmp.height; gdi = context->gdi; xf_lock_x11(xfc, FALSE); - switch (cmd->codecID) + switch (cmd->bmp.codecID) { case RDP_CODEC_ID_REMOTEFX: - if (!rfx_process_message(context->codecs->rfx, cmd->bitmapData, - cmd->bitmapDataLength, cmd->destLeft, cmd->destTop, + if (!rfx_process_message(context->codecs->rfx, cmd->bmp.bitmapData, + cmd->bmp.bitmapDataLength, cmd->destLeft, cmd->destTop, gdi->primary_buffer, gdi->dstFormat, gdi->stride, gdi->height, ®ion)) goto fail; @@ -1044,21 +1077,21 @@ static BOOL xf_gdi_surface_bits(rdpContext* context, break; case RDP_CODEC_ID_NSCODEC: - if (!nsc_process_message(context->codecs->nsc, cmd->bpp, cmd->width, - cmd->height, cmd->bitmapData, cmd->bitmapDataLength, + if (!nsc_process_message(context->codecs->nsc, cmd->bmp.bpp, cmd->bmp.width, + cmd->bmp.height, cmd->bmp.bitmapData, cmd->bmp.bitmapDataLength, gdi->primary_buffer, gdi->dstFormat, gdi->stride, - 0, 0, cmd->width, cmd->height, FREERDP_FLIP_VERTICAL)) + 0, 0, cmd->bmp.width, cmd->bmp.height, FREERDP_FLIP_VERTICAL)) goto fail; region16_union_rect(®ion, ®ion, &cmdRect); break; case RDP_CODEC_ID_NONE: - pSrcData = cmd->bitmapData; - format = gdi_get_pixel_format(cmd->bpp); + pSrcData = cmd->bmp.bitmapData; + format = gdi_get_pixel_format(cmd->bmp.bpp); if (!freerdp_image_copy(gdi->primary_buffer, gdi->dstFormat, gdi->stride, - 0, 0, cmd->width, cmd->height, + cmd->destLeft, cmd->destTop, cmd->bmp.width, cmd->bmp.height, pSrcData, format, 0, 0, 0, &xfc->context.gdi->palette, FREERDP_FLIP_VERTICAL)) goto fail; @@ -1067,7 +1100,7 @@ static BOOL xf_gdi_surface_bits(rdpContext* context, break; default: - WLog_ERR(TAG, "Unsupported codecID %"PRIu32"", cmd->codecID); + WLog_ERR(TAG, "Unsupported codecID %"PRIu16"", cmd->bmp.codecID); ret = TRUE; goto fail; } diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index ff685e3..b68a297 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -25,6 +25,9 @@ #include #include "xf_gfx.h" +#include "xf_rail.h" + +#include #define TAG CLIENT_TAG("x11") @@ -46,7 +49,6 @@ static UINT xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface) XSetClipMask(xfc->display, xfc->gc, None); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); - region16_intersect_rect(&(surface->gdi.invalidRegion), &(surface->gdi.invalidRegion), &surfaceRect); @@ -73,22 +75,31 @@ static UINT xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface) goto fail; } -#ifdef WITH_XRENDER - - if (xfc->context.settings->SmartSizing - || xfc->context.settings->MultiTouchGestures) + if (xfc->remote_app) { - XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, - nXSrc, nYSrc, nXDst, nYDst, width, height); - xf_draw_screen(xfc, nXDst, nYDst, width, height); - } - else -#endif - { - XPutImage(xfc->display, xfc->drawable, xfc->gc, + XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, nXSrc, nYSrc, nXDst, nYDst, width, height); + xf_lock_x11(xfc, FALSE); + xf_rail_paint(xfc, nXDst, nYDst, nXDst + width, nYDst + height); + xf_unlock_x11(xfc, FALSE); } + else +#ifdef WITH_XRENDER + if (xfc->context.settings->SmartSizing + || xfc->context.settings->MultiTouchGestures) + { + XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, + nXSrc, nYSrc, nXDst, nYDst, width, height); + xf_draw_screen(xfc, nXDst, nYDst, width, height); + } + else +#endif + { + XPutImage(xfc->display, xfc->drawable, xfc->gc, + surface->image, nXSrc, nYSrc, + nXDst, nYDst, width, height); + } } rc = CHANNEL_RC_OK; @@ -115,6 +126,9 @@ static UINT xf_UpdateSurfaces(RdpgfxClientContext* context) if (!gdi->graphicsReset) return status; + if (gdi->suppressOutput) + return CHANNEL_RC_OK; + context->GetSurfaceIds(context, &pSurfaceIds, &count); for (index = 0; index < count; index++) @@ -145,7 +159,7 @@ UINT xf_OutputExpose(xfContext* xfc, UINT32 x, UINT32 y, RECTANGLE_16 surfaceRect; RECTANGLE_16 intersection; UINT16* pSurfaceIds = NULL; - RdpgfxClientContext* context = xfc->gfx; + RdpgfxClientContext* context = xfc->context.gdi->gfx; invalidRect.left = x; invalidRect.top = y; invalidRect.right = x + width; @@ -215,12 +229,13 @@ static UINT xf_CreateSurface(RdpgfxClientContext* context, xfGfxSurface* surface; rdpGdi* gdi = (rdpGdi*)context->custom; xfContext* xfc = (xfContext*) gdi->context; + surface = (xfGfxSurface*) calloc(1, sizeof(xfGfxSurface)); - surface = (xfGfxSurface *) calloc(1, sizeof(xfGfxSurface)); if (!surface) return CHANNEL_RC_NO_MEMORY; surface->gdi.codecs = gdi->context->codecs; + if (!surface->gdi.codecs) { WLog_ERR(TAG, "%s: global GDI codecs aren't set", __FUNCTION__); @@ -250,13 +265,14 @@ static UINT xf_CreateSurface(RdpgfxClientContext* context, surface->gdi.scanline = surface->gdi.width * GetBytesPerPixel(surface->gdi.format); surface->gdi.scanline = x11_pad_scanline(surface->gdi.scanline, xfc->scanline_pad); size = surface->gdi.scanline * surface->gdi.height; - surface->gdi.data = (BYTE*)_aligned_malloc(size, 16); + if (!surface->gdi.data) { WLog_ERR(TAG, "%s: unable to allocate GDI data", __FUNCTION__); goto out_free; } + ZeroMemory(surface->gdi.data, size); if (AreColorFormatsEqualNoAlpha(gdi->dstFormat, surface->gdi.format)) @@ -272,15 +288,15 @@ static UINT xf_CreateSurface(RdpgfxClientContext* context, surface->stageScanline = width * bytes; surface->stageScanline = x11_pad_scanline(surface->stageScanline, xfc->scanline_pad); size = surface->stageScanline * surface->gdi.height; - surface->stage = (BYTE*) _aligned_malloc(size, 16); + if (!surface->stage) { WLog_ERR(TAG, "%s: unable to allocate stage buffer", __FUNCTION__); goto out_free_gdidata; } - ZeroMemory(surface->stage, size); + ZeroMemory(surface->stage, size); surface->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*) surface->stage, surface->gdi.width, surface->gdi.height, @@ -293,17 +309,21 @@ static UINT xf_CreateSurface(RdpgfxClientContext* context, goto error_surface_image; } + surface->image->byte_order = LSBFirst; + surface->image->bitmap_bit_order = LSBFirst; surface->gdi.outputMapped = FALSE; region16_init(&surface->gdi.invalidRegion); + if (context->SetSurfaceData(context, surface->gdi.surfaceId, (void*) surface) != CHANNEL_RC_OK) { WLog_ERR(TAG, "%s: an error occurred during SetSurfaceData", __FUNCTION__); goto error_set_surface_data; } - return CHANNEL_RC_OK; + return CHANNEL_RC_OK; error_set_surface_data: - XFree(surface->image); + surface->image->data = NULL; + XDestroyImage(surface->image); error_surface_image: _aligned_free(surface->stage); out_free_gdidata: @@ -328,7 +348,11 @@ static UINT xf_DeleteSurface(RdpgfxClientContext* context, if (surface) { - XFree(surface->image); +#ifdef WITH_GFX_H264 + h264_context_free(surface->gdi.h264); +#endif + surface->image->data = NULL; + XDestroyImage(surface->image); _aligned_free(surface->gdi.data); _aligned_free(surface->stage); region16_uninit(&surface->gdi.invalidRegion); diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index e3f3f28..58453af 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -34,7 +34,6 @@ #include #include -#include #include "xf_graphics.h" #include "xf_gdi.h" @@ -145,10 +144,12 @@ static BOOL xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) xbitmap->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*) bitmap->data, bitmap->width, bitmap->height, xfc->scanline_pad, 0); - if (!xbitmap->image) goto unlock; + xbitmap->image->byte_order = LSBFirst; + xbitmap->image->bitmap_bit_order = LSBFirst; + XPutImage(xfc->display, xbitmap->pixmap, xfc->gc, xbitmap->image, 0, 0, 0, 0, bitmap->width, bitmap->height); } @@ -170,12 +171,21 @@ static void xf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap) xf_lock_x11(xfc, FALSE); if (xbitmap->pixmap != 0) + { XFreePixmap(xfc->display, xbitmap->pixmap); + xbitmap->pixmap = 0; + } if (xbitmap->image) - XFree(xbitmap->image); + { + xbitmap->image->data = NULL; + XDestroyImage(xbitmap->image); + xbitmap->image = NULL; + } xf_unlock_x11(xfc, FALSE); + _aligned_free(bitmap->data); + free(xbitmap); } static BOOL xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap) @@ -203,6 +213,10 @@ static BOOL xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary) { xfContext* xfc = (xfContext*) context; + + if (!context || (!bitmap && !primary)) + return FALSE; + xf_lock_x11(xfc, FALSE); if (primary) @@ -228,9 +242,9 @@ static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer) return FALSE; if (!xfc->invert) - CursorFormat = PIXEL_FORMAT_RGBA32; + CursorFormat = (!xfc->big_endian) ? PIXEL_FORMAT_RGBA32 : PIXEL_FORMAT_ABGR32; else - CursorFormat = PIXEL_FORMAT_BGRA32; + CursorFormat = (!xfc->big_endian) ? PIXEL_FORMAT_BGRA32 : PIXEL_FORMAT_ARGB32; xf_lock_x11(xfc, FALSE); ZeroMemory(&ci, sizeof(ci)); @@ -392,7 +406,8 @@ static BOOL xf_Glyph_New(rdpContext* context, const rdpGlyph* glyph) XInitImage(image); XPutImage(xfc->display, xf_glyph->pixmap, xfc->gc_mono, image, 0, 0, 0, 0, glyph->cx, glyph->cy); - XFree(image); + image->data = NULL; + XDestroyImage(image); xf_unlock_x11(xfc, FALSE); return TRUE; } diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c index ec08e9f..0bed66c 100644 --- a/client/X11/xf_input.c +++ b/client/X11/xf_input.c @@ -240,6 +240,7 @@ static void xf_input_detect_pan(xfContext* xfc) double py; double dist_x; double dist_y; + rdpContext* ctx = &xfc->context; if (active_contacts != 2) { @@ -266,10 +267,9 @@ static void xf_input_detect_pan(xfContext* xfc) EventArgsInit(&e, "xfreerdp"); e.dx = 5; e.dy = 0; - PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); + PubSub_OnPanningChange(ctx->pubSub, xfc, &e); } px_vector = 0; - px_vector = 0; py_vector = 0; z_vector = 0; } @@ -280,10 +280,9 @@ static void xf_input_detect_pan(xfContext* xfc) EventArgsInit(&e, "xfreerdp"); e.dx = -5; e.dy = 0; - PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); + PubSub_OnPanningChange(ctx->pubSub, xfc, &e); } px_vector = 0; - px_vector = 0; py_vector = 0; z_vector = 0; } @@ -298,11 +297,10 @@ static void xf_input_detect_pan(xfContext* xfc) EventArgsInit(&e, "xfreerdp"); e.dx = 0; e.dy = 5; - PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); + PubSub_OnPanningChange(ctx->pubSub, xfc, &e); } py_vector = 0; px_vector = 0; - py_vector = 0; z_vector = 0; } else if (py_vector < -PAN_THRESHOLD) @@ -312,11 +310,10 @@ static void xf_input_detect_pan(xfContext* xfc) EventArgsInit(&e, "xfreerdp"); e.dx = 0; e.dy = -5; - PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); + PubSub_OnPanningChange(ctx->pubSub, xfc, &e); } py_vector = 0; px_vector = 0; - py_vector = 0; z_vector = 0; } } @@ -327,6 +324,7 @@ static void xf_input_detect_pinch(xfContext* xfc) double dist; double delta; ZoomingChangeEventArgs e; + rdpContext* ctx = &xfc->context; if (active_contacts != 2) { @@ -346,7 +344,6 @@ static void xf_input_detect_pinch(xfContext* xfc) z_vector = 0; px_vector = 0; py_vector = 0; - z_vector = 0; } else { @@ -366,22 +363,20 @@ static void xf_input_detect_pinch(xfContext* xfc) { EventArgsInit(&e, "xfreerdp"); e.dx = e.dy = -10; - PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e); + PubSub_OnZoomingChange(ctx->pubSub, xfc, &e); z_vector = 0; px_vector = 0; py_vector = 0; - z_vector = 0; } if (z_vector < -ZOOM_THRESHOLD) { EventArgsInit(&e, "xfreerdp"); e.dx = e.dy = 10; - PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e); + PubSub_OnZoomingChange(ctx->pubSub, xfc, &e); z_vector = 0; px_vector = 0; py_vector = 0; - z_vector = 0; } } } diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c index 16a1f65..1eb63e5 100644 --- a/client/X11/xf_keyboard.c +++ b/client/X11/xf_keyboard.c @@ -447,6 +447,7 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) { XF_MODIFIER_KEYS mod = { 0 }; xk_keyboard_get_modifier_keys(xfc, &mod); + rdpContext* ctx = &xfc->context; // remember state of RightCtrl to ungrab keyboard if next action is release of RightCtrl // do not return anything such that the key could be used by client if ungrab is not the goal @@ -554,7 +555,7 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) EventArgsInit(&e, "xfreerdp"); e.dx = pdx; e.dy = pdy; - PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e); + PubSub_OnPanningChange(ctx->pubSub, xfc, &e); return TRUE; } @@ -564,7 +565,7 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) EventArgsInit(&e, "xfreerdp"); e.dx = zdx; e.dy = zdy; - PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e); + PubSub_OnZoomingChange(ctx->pubSub, xfc, &e); return TRUE; } } @@ -614,13 +615,14 @@ BOOL xf_keyboard_set_indicators(rdpContext* context, UINT16 led_flags) return TRUE; } -BOOL xf_keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode) +BOOL xf_keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState, + UINT32 imeConvMode) { if (!context) return FALSE; - WLog_WARN(TAG, "KeyboardSetImeStatus(unitId=%04"PRIx16", imeState=%08"PRIx32", imeConvMode=%08"PRIx32") ignored", + WLog_WARN(TAG, + "KeyboardSetImeStatus(unitId=%04"PRIx16", imeState=%08"PRIx32", imeConvMode=%08"PRIx32") ignored", imeId, imeState, imeConvMode); - return TRUE; } diff --git a/client/X11/xf_monitor.c b/client/X11/xf_monitor.c index 977ffce..d2d3f07 100644 --- a/client/X11/xf_monitor.c +++ b/client/X11/xf_monitor.c @@ -3,6 +3,8 @@ * X11 Monitor Handling * * Copyright 2011 Marc-Andre Moreau + * Copyright 2017 David Fort + * Copyright 2018 Kai Harms * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,17 +39,25 @@ #include #endif +#ifdef WITH_XRANDR +#include +#include + +#if (RANDR_MAJOR * 100 + RANDR_MINOR) >= 105 +# define USABLE_XRANDR +#endif + +#endif + #include "xf_monitor.h" /* See MSDN Section on Multiple Display Monitors: http://msdn.microsoft.com/en-us/library/dd145071 */ int xf_list_monitors(xfContext* xfc) { -#ifdef WITH_XINERAMA Display* display; int major, minor; int i, nmonitors = 0; - XineramaScreenInfo* screen = NULL; display = XOpenDisplay(NULL); if (!display) @@ -56,41 +66,54 @@ int xf_list_monitors(xfContext* xfc) return -1; } - if (XineramaQueryExtension(display, &major, &minor)) +#if defined(USABLE_XRANDR) + + if (XRRQueryExtension(xfc->display, &major, &minor) && + (XRRQueryVersion(xfc->display, &major, &minor) == True) && + (major * 100 + minor >= 105)) { - if (XineramaIsActive(display)) + XRRMonitorInfo* monitors = XRRGetMonitors(xfc->display, DefaultRootWindow(xfc->display), 1, + &nmonitors); + + for (i = 0; i < nmonitors; i++) { - screen = XineramaQueryScreens(display, &nmonitors); - - for (i = 0; i < nmonitors; i++) - { - printf(" %s [%d] %hdx%hd\t+%hd+%hd\n", - (i == 0) ? "*" : " ", i, - screen[i].width, screen[i].height, - screen[i].x_org, screen[i].y_org); - } - - XFree(screen); + printf(" %s [%d] %dx%d\t+%d+%d\n", + monitors[i].primary ? "*" : " ", i, + monitors[i].width, monitors[i].height, + monitors[i].x, monitors[i].y); } + + XRRFreeMonitors(monitors); } - - XCloseDisplay(display); -#else - Screen* screen; - Display* display; - display = XOpenDisplay(NULL); - - if (!display) - { - WLog_ERR(TAG, "failed to open X display"); - return -1; - } - - screen = ScreenOfDisplay(display, DefaultScreen(display)); - printf(" * [0] %dx%d\t+0+0\n", WidthOfScreen(screen), - HeightOfScreen(screen)); - XCloseDisplay(display); + else #endif +#ifdef WITH_XINERAMA + if (XineramaQueryExtension(display, &major, &minor)) + { + if (XineramaIsActive(display)) + { + XineramaScreenInfo* screen = XineramaQueryScreens(display, &nmonitors); + + for (i = 0; i < nmonitors; i++) + { + printf(" %s [%d] %hdx%hd\t+%hd+%hd\n", + (i == 0) ? "*" : " ", i, + screen[i].width, screen[i].height, + screen[i].x_org, screen[i].y_org); + } + + XFree(screen); + } + } + else +#else + { + Screen* screen = ScreenOfDisplay(display, DefaultScreen(display)); + printf(" * [0] %dx%d\t+0+0\n", WidthOfScreen(screen), HeightOfScreen(screen)); + } + +#endif + XCloseDisplay(display); return 0; } @@ -115,15 +138,20 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) { int i; int nmonitors = 0; - int primaryMonitorFound = FALSE; + int monitor_index = 0; + BOOL primaryMonitorFound = FALSE; VIRTUAL_SCREEN* vscreen; rdpSettings* settings = xfc->context.settings; int mouse_x, mouse_y, _dummy_i; Window _dummy_w; int current_monitor = 0; -#ifdef WITH_XINERAMA + Screen* screen; +#if defined WITH_XINERAMA || defined WITH_XRANDR int major, minor; - XineramaScreenInfo* screenInfo = NULL; +#endif +#if defined(USABLE_XRANDR) + XRRMonitorInfo* rrmonitors = NULL; + BOOL useXRandr = FALSE; #endif vscreen = &xfc->vscreen; *pMaxWidth = settings->DesktopWidth; @@ -135,13 +163,39 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) &_dummy_i, &_dummy_i, (void*) &_dummy_i)) mouse_x = mouse_y = 0; -#ifdef WITH_XINERAMA +#if defined(USABLE_XRANDR) - if (XineramaQueryExtension(xfc->display, &major, &minor)) + if (XRRQueryExtension(xfc->display, &major, &minor) && + (XRRQueryVersion(xfc->display, &major, &minor) == True) && + (major * 100 + minor >= 105)) { - if (XineramaIsActive(xfc->display)) + XRRMonitorInfo* rrmonitors = XRRGetMonitors(xfc->display, DefaultRootWindow(xfc->display), 1, + &vscreen->nmonitors); + + if (vscreen->nmonitors > 16) + vscreen->nmonitors = 0; + + if (vscreen->nmonitors) { - screenInfo = XineramaQueryScreens(xfc->display, &vscreen->nmonitors); + for (i = 0; i < vscreen->nmonitors; i++) + { + vscreen->monitors[i].area.left = rrmonitors[i].x; + vscreen->monitors[i].area.top = rrmonitors[i].y; + vscreen->monitors[i].area.right = rrmonitors[i].x + rrmonitors[i].width - 1; + vscreen->monitors[i].area.bottom = rrmonitors[i].y + rrmonitors[i].height - 1; + vscreen->monitors[i].primary = rrmonitors[i].primary > 0; + } + } + + XRRFreeMonitors(rrmonitors); + useXRandr = TRUE; + } + else +#endif +#ifdef WITH_XINERAMA + if (XineramaQueryExtension(xfc->display, &major, &minor) && XineramaIsActive(xfc->display)) + { + XineramaScreenInfo* screenInfo = XineramaQueryScreens(xfc->display, &vscreen->nmonitors); if (vscreen->nmonitors > 16) vscreen->nmonitors = 0; @@ -153,8 +207,7 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) vscreen->monitors[i].area.left = screenInfo[i].x_org; vscreen->monitors[i].area.top = screenInfo[i].y_org; vscreen->monitors[i].area.right = screenInfo[i].x_org + screenInfo[i].width - 1; - vscreen->monitors[i].area.bottom = screenInfo[i].y_org + screenInfo[i].height - - 1; + vscreen->monitors[i].area.bottom = screenInfo[i].y_org + screenInfo[i].height - 1; /* Determine which monitor that the mouse cursor is on */ if ((mouse_x >= vscreen->monitors[i].area.left) && @@ -167,7 +220,6 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) XFree(screenInfo); } - } #endif xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom = @@ -198,29 +250,49 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) } else if (settings->PercentScreen) { - *pMaxWidth = (xfc->workArea.width * settings->PercentScreen) / 100; - *pMaxHeight = (xfc->workArea.height * settings->PercentScreen) / 100; - /* If we have specific monitor information then limit the PercentScreen value * to only affect the current monitor vs. the entire desktop */ if (vscreen->nmonitors > 0) { - *pMaxWidth = ((vscreen->monitors[current_monitor].area.right - - vscreen->monitors[current_monitor].area.left + 1) * settings->PercentScreen) / - 100; - *pMaxHeight = ((vscreen->monitors[current_monitor].area.bottom - - vscreen->monitors[current_monitor].area.top + 1) * settings->PercentScreen) / - 100; + *pMaxWidth = vscreen->monitors[current_monitor].area.right - + vscreen->monitors[current_monitor].area.left + 1; + *pMaxHeight = vscreen->monitors[current_monitor].area.bottom - + vscreen->monitors[current_monitor].area.top + 1; + + if (settings->PercentScreenUseWidth) + *pMaxWidth = ((vscreen->monitors[current_monitor].area.right - + vscreen->monitors[current_monitor].area.left + 1) * settings->PercentScreen) / + 100; + + if (settings->PercentScreenUseHeight) + *pMaxHeight = ((vscreen->monitors[current_monitor].area.bottom - + vscreen->monitors[current_monitor].area.top + 1) * settings->PercentScreen) / + 100; } + else + { + *pMaxWidth = xfc->workArea.width; + *pMaxHeight = xfc->workArea.height; + + if (settings->PercentScreenUseWidth) + *pMaxWidth = (xfc->workArea.width * settings->PercentScreen) / 100; + + if (settings->PercentScreenUseHeight) + *pMaxHeight = (xfc->workArea.height * settings->PercentScreen) / 100; + } + } + else if (settings->DesktopWidth && settings->DesktopHeight) + { + *pMaxWidth = settings->DesktopWidth; + *pMaxHeight = settings->DesktopHeight; } if (!settings->Fullscreen && !settings->Workarea && !settings->UseMultimon) - return TRUE; + goto out; /* If single monitor fullscreen OR workarea without remote app */ - if ((settings->Fullscreen && !settings->UseMultimon && !settings->SpanMonitors) - || + if ((settings->Fullscreen && !settings->UseMultimon && !settings->SpanMonitors) || (settings->Workarea && !settings->RemoteApplicationMode)) { /* If no monitors were specified on the command-line then set the current monitor as active */ @@ -239,17 +311,38 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) /* Create array of all active monitors by taking into account monitors requested on the command-line */ for (i = 0; i < vscreen->nmonitors; i++) { + MONITOR_ATTRIBUTES* attrs; + if (!xf_is_monitor_id_active(xfc, i)) continue; settings->MonitorDefArray[nmonitors].x = vscreen->monitors[i].area.left; settings->MonitorDefArray[nmonitors].y = vscreen->monitors[i].area.top; - settings->MonitorDefArray[nmonitors].width = MIN(vscreen->monitors[i].area.right - - vscreen->monitors[i].area.left + 1, *pMaxWidth); - settings->MonitorDefArray[nmonitors].height = MIN( - vscreen->monitors[i].area.bottom - vscreen->monitors[i].area.top + 1, - *pMaxHeight); + settings->MonitorDefArray[nmonitors].width = + MIN(vscreen->monitors[i].area.right - vscreen->monitors[i].area.left + 1, *pMaxWidth); + settings->MonitorDefArray[nmonitors].height = + MIN(vscreen->monitors[i].area.bottom - vscreen->monitors[i].area.top + 1, *pMaxHeight); settings->MonitorDefArray[nmonitors].orig_screen = i; +#ifdef USABLE_XRANDR + + if (useXRandr && rrmonitors) + { + Rotation rot, ret; + attrs = &settings->MonitorDefArray[nmonitors].attributes; + attrs->physicalWidth = rrmonitors[i].mwidth; + attrs->physicalHeight = rrmonitors[i].mheight; + ret = XRRRotations(xfc->display, i, &rot); + attrs->orientation = rot; + } + +#endif + + if (i == settings->MonitorIds[0]) + { + settings->MonitorDefArray[nmonitors].is_primary = TRUE; + primaryMonitorFound = TRUE; + } + nmonitors++; } @@ -326,30 +419,49 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) vscreen->area.bottom = xfc->workArea.height + xfc->workArea.y - 1; } - /* If there are multiple monitors and we have not selected a primary */ if (!primaryMonitorFound) { - /* First lets try to see if there is a monitor with a 0,0 coordinate */ - for (i = 0; i < settings->MonitorCount; i++) + /* If we have a command line setting we should use it */ + if (settings->NumMonitorIds) { - if (!primaryMonitorFound && settings->MonitorDefArray[i].x == 0 - && settings->MonitorDefArray[i].y == 0) - { - settings->MonitorDefArray[i].is_primary = TRUE; - settings->MonitorLocalShiftX = settings->MonitorDefArray[i].x; - settings->MonitorLocalShiftY = settings->MonitorDefArray[i].y; - primaryMonitorFound = TRUE; - } + /* The first monitor is the first in the setting which should be used */ + monitor_index = settings->MonitorIds[0]; + } + else + { + /* This is the same as when we would trust the Xinerama results.. + and set the monitor index to zero. + The monitor listed with /monitor-list on index zero is always the primary + */ + screen = DefaultScreenOfDisplay(xfc->display); + monitor_index = XScreenNumberOfScreen(screen); } - /* If we still do not have a primary monitor then just arbitrarily choose first monitor */ - if (!primaryMonitorFound) + int j = monitor_index; + + /* If the "default" monitor is not 0,0 use it */ + if (settings->MonitorDefArray[j].x != 0 || settings->MonitorDefArray[j].y != 0) { - settings->MonitorDefArray[0].is_primary = TRUE; - settings->MonitorLocalShiftX = settings->MonitorDefArray[0].x; - settings->MonitorLocalShiftY = settings->MonitorDefArray[0].y; + settings->MonitorDefArray[j].is_primary = TRUE; + settings->MonitorLocalShiftX = settings->MonitorDefArray[j].x; + settings->MonitorLocalShiftY = settings->MonitorDefArray[j].y; primaryMonitorFound = TRUE; } + else + { + /* Lets try to see if there is a monitor with a 0,0 coordinate and use it as a fallback*/ + for (i = 0; i < settings->MonitorCount; i++) + { + if (!primaryMonitorFound && settings->MonitorDefArray[i].x == 0 + && settings->MonitorDefArray[i].y == 0) + { + settings->MonitorDefArray[i].is_primary = TRUE; + settings->MonitorLocalShiftX = settings->MonitorDefArray[i].x; + settings->MonitorLocalShiftY = settings->MonitorDefArray[i].y; + primaryMonitorFound = TRUE; + } + } + } } /* Subtract monitor shift from monitor variables for server-side use. @@ -371,5 +483,18 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight) *pMaxHeight = vscreen->area.bottom - vscreen->area.top + 1; } + /* some 2008 server freeze at logon if we announce support for monitor layout PDU with + * #monitors < 2. So let's announce it only if we have more than 1 monitor. + */ + if (settings->MonitorCount) + settings->SupportMonitorLayoutPdu = TRUE; + +out: +#ifdef USABLE_XRANDR + + if (rrmonitors) + XRRFreeMonitors(rrmonitors); + +#endif return TRUE; } diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c index d4fec54..61be3e4 100644 --- a/client/X11/xf_rail.c +++ b/client/X11/xf_rail.c @@ -185,7 +185,7 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow) appWindow->local_move.state = LMS_TERMINATING; } -void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion) +static void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion) { int index; int count; @@ -195,6 +195,7 @@ void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion) xfAppWindow* appWindow; const RECTANGLE_16* extents; REGION16 windowInvalidRegion; + region16_init(&windowInvalidRegion); count = HashTable_GetKeys(xfc->railWindows, &pKeys); @@ -517,16 +518,12 @@ static BOOL xf_rail_window_common(rdpContext* context, static BOOL xf_rail_window_delete(rdpContext* context, WINDOW_ORDER_INFO* orderInfo) { - xfAppWindow* appWindow = NULL; xfContext* xfc = (xfContext*) context; - appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, - (void*)(UINT_PTR) orderInfo->windowId); - if (!appWindow) - return TRUE; + if (!xfc) + return FALSE; HashTable_Remove(xfc->railWindows, (void*)(UINT_PTR) orderInfo->windowId); - xf_DestroyWindow(xfc, appWindow); return TRUE; } @@ -611,7 +608,7 @@ static BOOL xf_rail_non_monitored_desktop(rdpContext* context, return TRUE; } -void xf_rail_register_update_callbacks(rdpUpdate* update) +static void xf_rail_register_update_callbacks(rdpUpdate* update) { rdpWindowUpdate* window = update->window; window->WindowCreate = xf_rail_window_common; @@ -842,14 +839,15 @@ static UINT xf_rail_server_min_max_info(RailClientContext* context, appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*)(UINT_PTR) minMaxInfo->windowId); - if (!appWindow) - return ERROR_INTERNAL_ERROR; + if (appWindow) + { + xf_SetWindowMinMaxInfo(xfc, appWindow, + minMaxInfo->maxWidth, minMaxInfo->maxHeight, + minMaxInfo->maxPosX, minMaxInfo->maxPosY, + minMaxInfo->minTrackWidth, minMaxInfo->minTrackHeight, + minMaxInfo->maxTrackWidth, minMaxInfo->maxTrackHeight); + } - xf_SetWindowMinMaxInfo(xfc, appWindow, - minMaxInfo->maxWidth, minMaxInfo->maxHeight, - minMaxInfo->maxPosX, minMaxInfo->maxPosY, - minMaxInfo->minTrackWidth, minMaxInfo->minTrackHeight, - minMaxInfo->maxTrackWidth, minMaxInfo->maxTrackHeight); return CHANNEL_RC_OK; } @@ -875,9 +873,23 @@ static UINT xf_rail_server_get_appid_response(RailClientContext* context, return CHANNEL_RC_OK; } +static void rail_window_free(void* value) +{ + xfAppWindow* appWindow = (xfAppWindow*) value; + + if (!appWindow) + return; + + xf_DestroyWindow(appWindow->xfc, appWindow); +} + int xf_rail_init(xfContext* xfc, RailClientContext* rail) { rdpContext* context = (rdpContext*) xfc; + + if (!xfc || !rail) + return 0; + xfc->rail = rail; xf_rail_register_update_callbacks(context->update); rail->custom = (void*) xfc; @@ -894,6 +906,7 @@ int xf_rail_init(xfContext* xfc, RailClientContext* rail) if (!xfc->railWindows) return 0; + xfc->railWindows->valueFree = rail_window_free; return 1; } diff --git a/client/X11/xf_video.c b/client/X11/xf_video.c new file mode 100644 index 0000000..5fc8f2f --- /dev/null +++ b/client/X11/xf_video.c @@ -0,0 +1,110 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Video Optimized Remoting Virtual Channel Extension for X11 + * + * Copyright 2017 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. + */ + + +#include +#include +#include + +#include "xf_video.h" + +#define TAG CLIENT_TAG("video") + +typedef struct +{ + VideoSurface base; + XImage* image; +} xfVideoSurface; + +static VideoSurface* xfVideoCreateSurface(VideoClientContext* video, BYTE* data, UINT32 x, UINT32 y, + UINT32 width, UINT32 height) +{ + xfContext* xfc = (xfContext*)video->custom; + xfVideoSurface* ret = calloc(1, sizeof(*ret)); + + if (!ret) + return NULL; + + ret->base.data = data; + ret->base.x = x; + ret->base.y = y; + ret->base.w = width; + ret->base.h = height; + ret->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, + (char*)data, width, height, 8, width * 4); + + if (!ret->image) + { + WLog_ERR(TAG, "unable to create surface image"); + free(ret); + return NULL; + } + + return &ret->base; +} + + +static BOOL xfVideoShowSurface(VideoClientContext* video, VideoSurface* surface) +{ + xfVideoSurface* xfSurface = (xfVideoSurface*)surface; + xfContext* xfc = video->custom; +#ifdef WITH_XRENDER + + if (xfc->context.settings->SmartSizing + || xfc->context.settings->MultiTouchGestures) + { + XPutImage(xfc->display, xfc->primary, xfc->gc, xfSurface->image, + 0, 0, surface->x, surface->y, surface->w, surface->h); + xf_draw_screen(xfc, surface->x, surface->y, surface->w, surface->h); + } + else +#endif + { + XPutImage(xfc->display, xfc->drawable, xfc->gc, xfSurface->image, + 0, 0, + surface->x, surface->y, surface->w, surface->h); + } + + return TRUE; +} + +static BOOL xfVideoDeleteSurface(VideoClientContext* video, VideoSurface* surface) +{ + xfVideoSurface* xfSurface = (xfVideoSurface*)surface; + + if (xfSurface) + XFree(xfSurface->image); + + free(surface); + return TRUE; +} +void xf_video_control_init(xfContext* xfc, VideoClientContext* video) +{ + gdi_video_control_init(xfc->context.gdi, video); + video->custom = xfc; + video->createSurface = xfVideoCreateSurface; + video->showSurface = xfVideoShowSurface; + video->deleteSurface = xfVideoDeleteSurface; +} + + +void xf_video_control_uninit(xfContext* xfc, VideoClientContext* video) +{ + gdi_video_control_uninit(xfc->context.gdi, video); +} diff --git a/client/X11/xf_video.h b/client/X11/xf_video.h new file mode 100644 index 0000000..47af49c --- /dev/null +++ b/client/X11/xf_video.h @@ -0,0 +1,34 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Video Optimized Remoting Virtual Channel Extension for X11 + * + * Copyright 2017 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 CLIENT_X11_XF_VIDEO_H_ +#define CLIENT_X11_XF_VIDEO_H_ + +#include "xfreerdp.h" + +#include +#include + +void xf_video_control_init(xfContext* xfc, VideoClientContext* video); +void xf_video_control_uninit(xfContext* xfc, VideoClientContext* video); + +xfVideoContext* xf_video_new(xfContext* xfc); +void xf_video_free(xfVideoContext* context); + + +#endif /* CLIENT_X11_XF_VIDEO_H_ */ diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index 76a64f4..d28a34d 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -105,6 +105,16 @@ struct _PropMotifWmHints }; typedef struct _PropMotifWmHints PropMotifWmHints; +static void xf_SetWindowTitleText(xfContext* xfc, Window window, const char* name) +{ + const size_t i = strlen(name); + XStoreName(xfc->display, window, name); + Atom wm_Name = xfc->_NET_WM_NAME; + Atom utf8Str = xfc->UTF8_STRING; + XChangeProperty(xfc->display, window, wm_Name, utf8Str, 8, + PropModeReplace, (const unsigned char*)name, (int)i); +} + /** * Post an event from the client to the X server */ @@ -164,7 +174,7 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen) } /* Determine the x,y starting location for the fullscreen window */ - if (fullscreen && xfc->context.settings->MonitorCount) + if (fullscreen) { /* Initialize startX and startY with reasonable values */ startX = xfc->context.settings->MonitorDefArray[0].x; @@ -180,8 +190,30 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen) /* Lastly apply any monitor shift(translation from remote to local coordinate system) * to startX and startY values */ - startX = startX + xfc->context.settings->MonitorLocalShiftX; - startY = startY + xfc->context.settings->MonitorLocalShiftY; + startX += xfc->context.settings->MonitorLocalShiftX; + startY += xfc->context.settings->MonitorLocalShiftY; + } + + if (xfc->_NET_WM_FULLSCREEN_MONITORS != None) + { + xf_ResizeDesktopWindow(xfc, window, width, height); + + if (fullscreen) + { + /* enter full screen: move the window before adding NET_WM_STATE_FULLSCREEN */ + XMoveWindow(xfc->display, window->handle, startX, startY); + } + + /* Set the fullscreen state */ + xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, + fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE, + xfc->_NET_WM_STATE_FULLSCREEN, 0, 0); + + if (!fullscreen) + { + /* leave full screen: move the window after removing NET_WM_STATE_FULLSCREEN */ + XMoveWindow(xfc->display, window->handle, startX, startY); + } /* Set monitor bounds */ if (settings->MonitorCount > 1) @@ -194,24 +226,99 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen) 1); } } - - xf_ResizeDesktopWindow(xfc, window, width, height); - - if (fullscreen) + else { - /* enter full screen: move the window before adding NET_WM_STATE_FULLSCREEN */ - XMoveWindow(xfc->display, window->handle, startX, startY); - } + if (fullscreen) + { + xf_SetWindowDecorations(xfc, window->handle, FALSE); - /* Set the fullscreen state */ - xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, - fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE, - xfc->_NET_WM_STATE_FULLSCREEN, 0, 0); + if (xfc->fullscreenMonitors.top) + { + xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, + _NET_WM_STATE_ADD, + xfc->fullscreenMonitors.top, 0, 0); + } + else + { + XSetWindowAttributes xswa; + xswa.override_redirect = True; + XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &xswa); + XRaiseWindow(xfc->display, window->handle); + xswa.override_redirect = False; + XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &xswa); + } - if (!fullscreen) - { - /* leave full screen: move the window after removing NET_WM_STATE_FULLSCREEN */ - XMoveWindow(xfc->display, window->handle, startX, startY); + /* if window is in maximized state, save and remove */ + if (xfc->_NET_WM_STATE_MAXIMIZED_VERT != None) + { + BYTE state; + unsigned long nitems; + unsigned long bytes; + BYTE* prop; + + if (xf_GetWindowProperty(xfc, window->handle, xfc->_NET_WM_STATE, 255, &nitems, &bytes, &prop)) + { + state = 0; + + while (nitems-- > 0) + { + if (((Atom*) prop)[nitems] == xfc->_NET_WM_STATE_MAXIMIZED_VERT) + state |= 0x01; + + if (((Atom*) prop)[nitems] == xfc->_NET_WM_STATE_MAXIMIZED_HORZ) + state |= 0x02; + } + + if (state) + { + xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, + _NET_WM_STATE_REMOVE, xfc->_NET_WM_STATE_MAXIMIZED_VERT, + 0, 0); + xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, + _NET_WM_STATE_REMOVE, xfc->_NET_WM_STATE_MAXIMIZED_HORZ, + 0, 0); + xfc->savedMaximizedState = state; + } + + XFree(prop); + } + } + + width = xfc->vscreen.area.right - xfc->vscreen.area.left + 1; + height = xfc->vscreen.area.bottom - xfc->vscreen.area.top + 1; + xf_ResizeDesktopWindow(xfc, window, width, height); + XMoveWindow(xfc->display, window->handle, startX, startY); + } + else + { + xf_SetWindowDecorations(xfc, window->handle, window->decorations); + xf_ResizeDesktopWindow(xfc, window, width, height); + XMoveWindow(xfc->display, window->handle, startX, startY); + + if (xfc->fullscreenMonitors.top) + { + xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, + _NET_WM_STATE_REMOVE, + xfc->fullscreenMonitors.top, 0, 0); + } + + /* restore maximized state, if the window was maximized before setting fullscreen */ + if (xfc->savedMaximizedState & 0x01) + { + xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, + _NET_WM_STATE_ADD, xfc->_NET_WM_STATE_MAXIMIZED_VERT, + 0, 0); + } + + if (xfc->savedMaximizedState & 0x02) + { + xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, + _NET_WM_STATE_ADD, xfc->_NET_WM_STATE_MAXIMIZED_HORZ, + 0, 0); + } + + xfc->savedMaximizedState = 0; + } } } @@ -229,7 +336,7 @@ BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, return FALSE; status = XGetWindowProperty(xfc->display, window, - property, 0, length, FALSE, AnyPropertyType, + property, 0, length, False, AnyPropertyType, &actual_type, &actual_format, nitems, bytes, prop); if (status != Success) @@ -328,7 +435,7 @@ static void xf_SetWindowPID(xfContext* xfc, Window window, pid_t pid) 32, PropModeReplace, (BYTE*) &pid, 1); } -static const char* get_shm_id() +static const char* get_shm_id(void) { static char shm_id[64]; sprintf_s(shm_id, sizeof(shm_id), "/com.freerdp.xfreerdp.tsmf_%016X", @@ -336,13 +443,13 @@ static const char* get_shm_id() return shm_id; } -Window xf_CreateDummyWindow(xfContext *xfc) +Window xf_CreateDummyWindow(xfContext* xfc) { return XCreateSimpleWindow(xfc->display, DefaultRootWindow(xfc->display), - 0, 0, 1, 1, 0, 0, 0); + 0, 0, 1, 1, 0, 0, 0); } -void xf_DestroyDummyWindow(xfContext *xfc, Window window) +void xf_DestroyDummyWindow(xfContext* xfc, Window window) { if (window) XDestroyWindow(xfc->display, window); @@ -462,7 +569,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, settings->DesktopPosY); } - XStoreName(xfc->display, window->handle, name); + xf_SetWindowTitleText(xfc, window->handle, name); return window; } @@ -470,10 +577,13 @@ void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int height) { XSizeHints* size_hints; + rdpSettings* settings = NULL; if (!xfc || !window) return; + settings = xfc->context.settings; + if (!(size_hints = XAllocSizeHints())) return; @@ -485,11 +595,13 @@ void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, XResizeWindow(xfc->display, window->handle, width, height); #ifdef WITH_XRENDER - if (!xfc->context.settings->SmartSizing) + if (!settings->SmartSizing) #endif { if (!xfc->fullscreen) { + /* min == max is an hint for the WM to indicate that the window should + * not be resizable */ size_hints->min_width = size_hints->max_width = width; size_hints->min_height = size_hints->max_height = height; XSetWMNormalHints(xfc->display, window->handle, size_hints); @@ -576,34 +688,19 @@ void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, XA_ATOM, 32, PropModeReplace, (BYTE*) &window_type, 1); } -void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name) +void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, const char* name) { - const size_t i = strlen(name); - XStoreName(xfc->display, appWindow->handle, name); - Atom wm_Name = xfc->_NET_WM_NAME; - Atom utf8Str = xfc->UTF8_STRING; - XChangeProperty(xfc->display, appWindow->handle, wm_Name, utf8Str, 8, - PropModeReplace, (unsigned char*)name, i); + xf_SetWindowTitleText(xfc, appWindow->handle, name); } -void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, - int* height) +static void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, + int* height) { int vscreen_width; int vscreen_height; vscreen_width = xfc->vscreen.area.right - xfc->vscreen.area.left + 1; vscreen_height = xfc->vscreen.area.bottom - xfc->vscreen.area.top + 1; - if (*width < 1) - { - *width = 1; - } - - if (*height < 1) - { - *height = 1; - } - if (*x < xfc->vscreen.area.left) { *width += *x; @@ -625,6 +722,16 @@ void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, { *height = vscreen_height; } + + if (*width < 1) + { + *width = 1; + } + + if (*height < 1) + { + *height = 1; + } } int xf_AppWindowInit(xfContext* xfc, xfAppWindow* appWindow) @@ -958,7 +1065,7 @@ void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, { int ax, ay; - if (appWindow == NULL) + if (appWindow == NULL) return; ax = x + appWindow->windowOffsetX; diff --git a/client/X11/xf_window.h b/client/X11/xf_window.h index 44921cc..1fdbe2d 100644 --- a/client/X11/xf_window.h +++ b/client/X11/xf_window.h @@ -158,7 +158,7 @@ BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int leng void xf_SendClientEvent(xfContext* xfc, Window window, Atom atom, unsigned int numArgs, ...); int xf_AppWindowInit(xfContext* xfc, xfAppWindow* appWindow); -void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name); +void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, const char* name); void xf_MoveWindow(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height); void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state); //void xf_SetWindowIcon(xfContext* xfc, xfAppWindow* appWindow, rdpIcon* icon); diff --git a/client/X11/xfreerdp-examples.1.xml b/client/X11/xfreerdp-examples.1.xml index 0335660..3418143 100644 --- a/client/X11/xfreerdp-examples.1.xml +++ b/client/X11/xfreerdp-examples.1.xml @@ -7,6 +7,12 @@ Connect in fullscreen mode using a stored configuration connection.rdp and the password Pwd123! + + xfreerdp /u:USER /size:50%h /v:rdp.contoso.com + + Connect to host rdp.contoso.com with user USER and a size of 50 percent of the height. If width (w) is set instead of height (h) like /size:50%w. 50 percent of the width is used. + + xfreerdp /u:CONTOSO\\JohnDoe /p:Pwd123! /v:rdp.contoso.com diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 8cfcb24..04aabb0 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -81,6 +81,8 @@ struct xf_glyph typedef struct xf_glyph xfGlyph; typedef struct xf_clipboard xfClipboard; +typedef struct _xfDispContext xfDispContext; +typedef struct _xfVideoContext xfVideoContext; /* Value of the first logical button number in X11 which must be */ /* subtracted to go from a button number in X11 to an index into */ @@ -140,13 +142,6 @@ struct xf_context UINT16 frame_x2; UINT16 frame_y2; - UINT8 red_shift_l; - UINT8 red_shift_r; - UINT8 green_shift_l; - UINT8 green_shift_r; - UINT8 blue_shift_l; - UINT8 blue_shift_r; - int XInputOpcode; int savedWidth; @@ -164,7 +159,6 @@ struct xf_context BOOL focused; BOOL use_xinput; BOOL mouse_active; - BOOL suppress_output; BOOL fullscreen_toggle; BOOL controlToggle; UINT32 KeyboardLayout; @@ -178,9 +172,9 @@ struct xf_context BOOL complex_regions; VIRTUAL_SCREEN vscreen; void* xv_context; - TsmfClientContext* tsmf; - xfClipboard* clipboard; - CliprdrClientContext* cliprdr; + + Atom* supportedAtoms; + unsigned long supportedAtomCount; Atom UTF8_STRING; @@ -189,6 +183,9 @@ struct xf_context Atom _NET_CURRENT_DESKTOP; Atom _NET_WORKAREA; + Atom _NET_SUPPORTED; + ATOM _NET_SUPPORTING_WM_CHECK; + Atom _NET_WM_STATE; Atom _NET_WM_STATE_FULLSCREEN; Atom _NET_WM_STATE_MAXIMIZED_HORZ; @@ -216,9 +213,14 @@ struct xf_context Atom WM_DELETE_WINDOW; /* Channels */ + TsmfClientContext* tsmf; + xfClipboard* clipboard; + CliprdrClientContext* cliprdr; + xfVideoContext* xfVideo; RdpeiClientContext* rdpei; - RdpgfxClientContext* gfx; EncomspClientContext* encomsp; + xfDispContext* xfDisp; + DispClientContext* disp; RailClientContext* rail; wHashTable* railWindows; @@ -228,6 +230,7 @@ struct xf_context /* value to be sent over wire for each logical client mouse button */ int button_map[NUM_BUTTONS_MAPPED]; + BYTE savedMaximizedState; }; BOOL xf_create_window(xfContext* xfc); diff --git a/client/common/client.c b/client/common/client.c index ac2962a..2c8bbbb 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -39,13 +39,13 @@ static BOOL freerdp_client_common_new(freerdp* instance, rdpContext* context) { RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints; - return pEntryPoints->ClientNew(instance, context); + return IFCALLRESULT(TRUE, pEntryPoints->ClientNew, instance, context); } static void freerdp_client_common_free(freerdp* instance, rdpContext* context) { RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints; - pEntryPoints->ClientFree(instance, context); + IFCALL(pEntryPoints->ClientFree, instance, context); } /* Common API */ @@ -501,7 +501,7 @@ DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name, 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"); + "Please look at the OpenSSL documentation on how to add a private CA to the store.\n"); return client_cli_accept_certificate(instance->settings); } diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 147b9f9..801ef95 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -25,10 +25,11 @@ #include #include +#include #include #include -#include +#include #include #include @@ -36,197 +37,34 @@ #include #include +#include #include #include #include "compatibility.h" +#include "cmdline.h" #include #define TAG CLIENT_TAG("common.cmdline") -static COMMAND_LINE_ARGUMENT_A args[] = +BOOL freerdp_client_print_version(void) { - { "v", COMMAND_LINE_VALUE_REQUIRED, "[:port]", NULL, NULL, -1, NULL, "Server hostname" }, - { "port", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Server port" }, - { "w", COMMAND_LINE_VALUE_REQUIRED, "", "1024", NULL, -1, NULL, "Width" }, - { "h", COMMAND_LINE_VALUE_REQUIRED, "", "768", NULL, -1, NULL, "Height" }, - { "size", COMMAND_LINE_VALUE_REQUIRED, "x or %", "1024x768", NULL, -1, NULL, "Screen size" }, - { "f", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Fullscreen mode" }, - { "bpp", COMMAND_LINE_VALUE_REQUIRED, "", "16", NULL, -1, NULL, "Session bpp (color depth)" }, - { "kbd", COMMAND_LINE_VALUE_REQUIRED, "0x or ", NULL, NULL, -1, NULL, "Keyboard layout" }, - { "kbd-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL, "List keyboard layouts" }, - { "kbd-type", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Keyboard type" }, - { "kbd-subtype", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Keyboard subtype" }, - { "kbd-fn-key", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Keyboard function key count" }, - { "admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "console", "Admin (or console) session" }, - { "restricted-admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "restrictedAdmin", "Restricted admin mode" }, - { "pth", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" }, - { "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Client Hostname to send to server" }, - { "multimon", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Use multiple monitors" }, - { "span", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Span screen over multiple monitors" }, - { "workarea", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Use available work area" }, - { "monitors", COMMAND_LINE_VALUE_REQUIRED, "<0,1,2...>", NULL, NULL, -1, NULL, "Select monitors to use" }, - { "monitor-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL, "List detected monitors" }, - { "t", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, "title", "Window title" }, - { "decorations", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Window decorations" }, - { "smart-sizing", COMMAND_LINE_VALUE_OPTIONAL, "<width>x<height>", NULL, NULL, -1, NULL, "Scale remote desktop to window size" }, - { "a", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, "addin", "Addin" }, - { "vc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Static virtual channel" }, - { "dvc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Dynamic virtual channel" }, - { "u", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Username" }, - { "p", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Password" }, - { "d", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Domain" }, - { "g", COMMAND_LINE_VALUE_REQUIRED, "<gateway>[:port]", NULL, NULL, -1, NULL, "Gateway Hostname" }, - { "gu", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Gateway username" }, - { "gp", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Gateway password" }, - { "gd", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Gateway domain" }, - { "gt", COMMAND_LINE_VALUE_REQUIRED, "<rpc|http|auto>", NULL, NULL, -1, NULL, "Gateway transport type" }, - { "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "<direct|detect>", NULL, NULL, -1, "gum", "Gateway usage method" }, - { "proxy", COMMAND_LINE_VALUE_REQUIRED, "[<protocol>://]<host>:<port>", NULL, NULL, -1, NULL, "Proxy (see also environment variable below)" }, - { "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info string>", NULL, NULL, -1, NULL, "Load balance info" }, - { "app", COMMAND_LINE_VALUE_REQUIRED, "<executable path> or <||alias>", NULL, NULL, -1, NULL, "Remote application program" }, - { "app-name", COMMAND_LINE_VALUE_REQUIRED, "<app name>", NULL, NULL, -1, NULL, "Remote application name for user interface" }, - { "app-icon", COMMAND_LINE_VALUE_REQUIRED, "<icon path>", NULL, NULL, -1, NULL, "Remote application icon for user interface" }, - { "app-cmd", COMMAND_LINE_VALUE_REQUIRED, "<parameters>", NULL, NULL, -1, NULL, "Remote application command-line parameters" }, - { "app-file", COMMAND_LINE_VALUE_REQUIRED, "<file name>", NULL, NULL, -1, NULL, "File to open with remote application" }, - { "app-guid", COMMAND_LINE_VALUE_REQUIRED, "<app guid>", NULL, NULL, -1, NULL, "Remote application GUID" }, - { "compression", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, "z", "Enable compression" }, - { "compression-level", COMMAND_LINE_VALUE_REQUIRED, "<level>", NULL, NULL, -1, NULL, "Compression level (0,1,2)" }, - { "shell", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Alternate shell" }, - { "shell-dir", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Shell working directory" }, - { "sound", COMMAND_LINE_VALUE_OPTIONAL, "[sys][dev][format][rate][channel][latency][quality]", NULL, NULL, -1, "audio", "Audio output (sound)" }, - { "microphone", COMMAND_LINE_VALUE_OPTIONAL, "[sys][dev][format][rate][channel]", NULL, NULL, -1, "mic", "Audio input (microphone)" }, - { "audio-mode", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Audio output mode" }, - { "multimedia", COMMAND_LINE_VALUE_OPTIONAL, "[sys][dev][decoder]", NULL, NULL, -1, "mmr", "Redirect multimedia (video)" }, - { "network", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Network connection type" }, - { "drive", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect drive" }, - { "drives", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect all drives" }, - { "home-drive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect home drive" }, - { "clipboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect clipboard" }, - { "serial", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "tty", "Redirect serial device" }, - { "parallel", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect parallel device" }, - { "smartcard", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect smartcard device" }, - { "printer", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect printer device" }, - { "usb", COMMAND_LINE_VALUE_REQUIRED, "[dbg][dev][id|addr][auto]", NULL, NULL, -1, NULL, "Redirect USB device" }, - { "multitouch", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect multitouch input" }, - { "gestures", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Consume multitouch input locally" }, - { "unmap-buttons", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Let server see real physical pointer button"}, - { "echo", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "echo", "Echo channel" }, - { "disp", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Display control" }, - { "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Enable smooth fonts (ClearType)" }, - { "aero", COMMAND_LINE_VALUE_BOOL, NULL, NULL, BoolValueFalse, -1, NULL, "Enable desktop composition" }, - { "window-drag", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Enable full window drag" }, - { "menu-anims", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Enable menu animations" }, - { "themes", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable themes" }, - { "wallpaper", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable wallpaper" }, - { "gdi", COMMAND_LINE_VALUE_REQUIRED, "<sw|hw>", NULL, NULL, -1, NULL, "GDI rendering" }, -#ifdef WITH_GFX_H264 - { "gfx", COMMAND_LINE_VALUE_OPTIONAL, "<RFX|AVC420|AVC444>", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" }, -#else - { "gfx", COMMAND_LINE_VALUE_OPTIONAL, "<RFX>", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" }, -#endif - { "gfx-thin-client", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline using thin client mode" }, - { "gfx-small-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline using small cache mode" }, - { "gfx-progressive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline using progressive codec" }, -#ifdef WITH_GFX_H264 - { "gfx-h264", COMMAND_LINE_VALUE_OPTIONAL, "<AVC420|AVC444>", NULL, NULL, -1, NULL, "RDP8.1 graphics pipeline using H264 codec" }, -#endif - { "rfx", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "RemoteFX" }, - { "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "<image|video>", NULL, NULL, -1, NULL, "RemoteFX mode" }, - { "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Number of frame acknowledgement" }, - { "nsc", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "nscodec", "Enable NSCodec" }, - { "jpeg", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Enable JPEG codec" }, - { "jpeg-quality", COMMAND_LINE_VALUE_REQUIRED, "<percentage>", NULL, NULL, -1, NULL, "JPEG quality" }, - { "nego", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable protocol security negotiation" }, - { "sec", COMMAND_LINE_VALUE_REQUIRED, "<rdp|tls|nla|ext>", NULL, NULL, -1, NULL, "force specific protocol security" }, - { "sec-rdp", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "rdp protocol security" }, - { "sec-tls", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "tls protocol security" }, - { "sec-nla", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "nla protocol security" }, - { "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "nla extended protocol security" }, - { "tls-ciphers", COMMAND_LINE_VALUE_REQUIRED, "<netmon|ma|ciphers>", NULL, NULL, -1, NULL, "Allowed TLS ciphers" }, - { "cert-name", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "certificate name" }, - { "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "ignore certificate" }, - { "cert-tofu", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Automatically accept certificate on first connect" }, - { "pcb", COMMAND_LINE_VALUE_REQUIRED, "<blob>", NULL, NULL, -1, NULL, "Preconnection Blob" }, - { "pcid", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Preconnection Id" }, - { "spn-class", COMMAND_LINE_VALUE_REQUIRED, "<service class>", NULL, NULL, -1, NULL, "SPN authentication service class" }, - { "credentials-delegation", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Disable credentials delegation" }, - { "vmconnect", COMMAND_LINE_VALUE_OPTIONAL, "<vmid>", NULL, NULL, -1, NULL, "Hyper-V console (use port 2179, disable negotiation)" }, - { "authentication", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "authentication (hack!)" }, - { "encryption", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "encryption (hack!)" }, - { "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "grab keyboard" }, - { "toggle-fullscreen", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Alt+Ctrl+Enter toggles fullscreen" }, - { "mouse-motion", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "mouse-motion" }, - { "parent-window", COMMAND_LINE_VALUE_REQUIRED, "<window id>", NULL, NULL, -1, NULL, "Parent window id" }, - { "bitmap-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable bitmap cache" }, - { "offscreen-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable offscreen bitmap cache" }, - { "glyph-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Glyph cache (EXPERIMENTAL)" }, - { "codec-cache", COMMAND_LINE_VALUE_REQUIRED, "<rfx|nsc|jpeg>", NULL, NULL, -1, NULL, "bitmap codec cache" }, - { "fast-path", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable fast-path input/output" }, - { "max-fast-path-size", COMMAND_LINE_VALUE_OPTIONAL, "<size>", NULL, NULL, -1, NULL, "specify maximum fast-path update size" }, - { "max-loop-time", COMMAND_LINE_VALUE_REQUIRED, "<time>", NULL, NULL, -1, NULL, "specify maximum time in milliseconds spend treating packets"}, - { "async-input", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous input" }, - { "async-update", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous update" }, - { "async-transport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous transport (unstable)" }, - { "async-channels", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous channels (unstable)" }, - { "wm-class", COMMAND_LINE_VALUE_REQUIRED, "<class name>", NULL, NULL, -1, NULL, "set the WM_CLASS hint for the window instance" }, - { "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "print version" }, - { "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "print help" }, - { "play-rfx", COMMAND_LINE_VALUE_REQUIRED, "<pcap file>", NULL, NULL, -1, NULL, "Replay rfx pcap file" }, - { "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Authenticate only." }, - { "auto-reconnect", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Automatic reconnection" }, - { "auto-reconnect-max-retries", COMMAND_LINE_VALUE_REQUIRED, "<retries>", NULL, NULL, -1, NULL, "Automatic reconnection maximum retries, 0 for unlimited [0,1000]" }, - { "reconnect-cookie", COMMAND_LINE_VALUE_REQUIRED, "<base64 cookie>", NULL, NULL, -1, NULL, "Pass base64 reconnect cookie to the connection" }, - { "print-reconnect-cookie", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Print base64 reconnect cookie after connecting" }, - { "heartbeat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support heartbeat PDUs" }, - { "multitransport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support multitransport protocol" }, - { "assistance", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Remote assistance password" }, - { "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, see wLog(7) for details" }, - { "log-filters", COMMAND_LINE_VALUE_REQUIRED, "<logger tag>:<log level>[, <logger tag>:<log level>][, ...]]", NULL, NULL, -1, NULL, "Set logger filters, see wLog(7) for details" }, - { "pwidth", COMMAND_LINE_VALUE_REQUIRED, "<physical width (mm)>", NULL, NULL, -1, NULL, "Physical width of display (in millimeters)" }, - { "pheight", COMMAND_LINE_VALUE_REQUIRED, "<physical height (mm)>", NULL, NULL, -1, NULL, "Physical height of display (in millimeters)" }, - { "orientation", COMMAND_LINE_VALUE_REQUIRED, "<orientation>", NULL, NULL, -1, NULL, "Orientation of display in degrees (0, 90, 180, 270)" }, - { "scale", COMMAND_LINE_VALUE_REQUIRED, "<scale amount (%%)>", "100", NULL, -1, NULL, "Scaling factor of the display (value of 100, 140, or 180)" }, - { "scale-desktop", COMMAND_LINE_VALUE_REQUIRED, "<scale amount (%%)>", "100", NULL, -1, NULL, "Scaling factor for desktop applications (value between 100 and 500)" }, - { "scale-device", COMMAND_LINE_VALUE_REQUIRED, "<scale amount (%%)>", "100", NULL, -1, NULL, "Scaling factor for app store applications (100, 140, or 180)" }, - { "action-script", COMMAND_LINE_VALUE_REQUIRED, "<file name>", "~/.config/freerdp/action.sh", NULL, -1, NULL, "Action script" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } -}; - -BOOL freerdp_client_print_version() -{ - printf("This is FreeRDP version %s (git %s)\n", FREERDP_VERSION_FULL, + printf("This is FreeRDP version %s (%s)\n", FREERDP_VERSION_FULL, GIT_REVISION); return TRUE; } -BOOL freerdp_client_print_buildconfig() +BOOL freerdp_client_print_buildconfig(void) { printf("%s", freerdp_get_build_config()); return TRUE; } -BOOL freerdp_client_print_command_line_help(int argc, char** argv) +static void freerdp_client_print_command_line_args(COMMAND_LINE_ARGUMENT_A* arg) { - char* str; - int length; - COMMAND_LINE_ARGUMENT_A* arg; - printf("\n"); - printf("FreeRDP - A Free Remote Desktop Protocol Implementation\n"); - printf("See www.freerdp.com for more information\n"); - printf("\n"); - printf("Usage: %s [file] [options] [/v:<server>[:port]]\n", argv[0]); - printf("\n"); - printf("Syntax:\n"); - printf(" /flag (enables flag)\n"); - printf(" /option:<value> (specifies option with value)\n"); - printf(" +toggle -toggle (enables or disables toggle, where '/' is a synonym of '+')\n"); - printf("\n"); - arg = args; + if (!arg) + return; do { @@ -239,19 +77,23 @@ BOOL freerdp_client_print_command_line_help(int argc, char** argv) else if ((arg->Flags & COMMAND_LINE_VALUE_REQUIRED) || (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL)) { + BOOL overlong = FALSE; printf(" %s", "/"); if (arg->Format) { - length = (int)(strlen(arg->Name) + strlen(arg->Format) + 2); - str = (char*) calloc(length + 1UL, sizeof(char)); + size_t length = (strlen(arg->Name) + strlen(arg->Format) + 2); - if (!str) - return FALSE; + if (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL) + length += 2; - sprintf_s(str, length + 1, "%s:%s", arg->Name, arg->Format); - printf("%-20s", str); - free(str); + if (length >= 20 + 8 + 8) + overlong = TRUE; + + if (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL) + printf("%s[:%s]", arg->Name, overlong ? "..." : arg->Format); + else + printf("%s:%s", arg->Name, overlong ? "..." : arg->Format); } else { @@ -262,22 +104,35 @@ BOOL freerdp_client_print_command_line_help(int argc, char** argv) } else if (arg->Flags & COMMAND_LINE_VALUE_BOOL) { - length = (int) strlen(arg->Name) + 32; - str = (char*) calloc(length + 1UL, sizeof(char)); - - if (!str) - return FALSE; - - sprintf_s(str, length + 1, "%s (default:%s)", arg->Name, - arg->Default ? "on" : "off"); printf(" %s", arg->Default ? "-" : "+"); - printf("%-20s", str); - free(str); - printf("\t%s\n", arg->Text); + printf("%-20s", arg->Name); + printf("\t%s (default:%s)\n", arg->Text, arg->Default ? "on" : "off"); } } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); +} +BOOL freerdp_client_print_command_line_help(int argc, char** argv) +{ + return freerdp_client_print_command_line_help_ex(argc, argv, NULL); +} + +BOOL freerdp_client_print_command_line_help_ex(int argc, char** argv, + COMMAND_LINE_ARGUMENT_A* custom) +{ + printf("\n"); + printf("FreeRDP - A Free Remote Desktop Protocol Implementation\n"); + printf("See www.freerdp.com for more information\n"); + printf("\n"); + printf("Usage: %s [file] [options] [/v:<server>[:port]]\n", argv[0]); + printf("\n"); + printf("Syntax:\n"); + printf(" /flag (enables flag)\n"); + printf(" /option:<value> (specifies option with value)\n"); + printf(" +toggle -toggle (enables or disables toggle, where '/' is a synonym of '+')\n"); + printf("\n"); + freerdp_client_print_command_line_args(custom); + freerdp_client_print_command_line_args(args); printf("\n"); printf("Examples:\n"); printf(" xfreerdp connection.rdp /p:Pwd123! /f\n"); @@ -291,7 +146,7 @@ BOOL freerdp_client_print_command_line_help(int argc, char** argv) printf("Smartcard Redirection: /smartcard:<device>\n"); printf("Serial Port Redirection: /serial:<name>,<device>,[SerCx2|SerCx|Serial],[permissive]\n"); printf("Serial Port Redirection: /serial:COM1,/dev/ttyS0\n"); - printf("Parallel Port Redirection: /parallel:<device>\n"); + printf("Parallel Port Redirection: /parallel:<name>,<device>\n"); printf("Printer Redirection: /printer:<device>,<driver>\n"); printf("\n"); printf("Audio Output Redirection: /sound:sys:oss,dev:1,format:1\n"); @@ -303,7 +158,6 @@ BOOL freerdp_client_print_command_line_help(int argc, char** argv) printf("Multimedia Redirection: /multimedia:sys:alsa\n"); printf("USB Device Redirection: /usb:id,dev:054c:0268\n"); printf("\n"); - printf("For Gateways, the https_proxy environment variable is respected:\n"); #ifdef _WIN32 printf(" set HTTPS_PROXY=http://proxy.contoso.com:3128/\n"); @@ -312,7 +166,6 @@ BOOL freerdp_client_print_command_line_help(int argc, char** argv) #endif printf(" xfreerdp /g:rdp.contoso.com ...\n"); printf("\n"); - printf("More documentation is coming, in the meantime consult source files\n"); printf("\n"); return TRUE; @@ -336,10 +189,6 @@ static int freerdp_client_command_line_pre_filter(void* context, int index, if (!(settings->ConnectionFile = _strdup(argv[index]))) return COMMAND_LINE_ERROR_MEMORY; - if (freerdp_client_settings_parse_connection_file(settings, - settings->ConnectionFile)) - return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - return 1; } } @@ -353,10 +202,6 @@ static int freerdp_client_command_line_pre_filter(void* context, int index, if (!(settings->AssistanceFile = _strdup(argv[index]))) return COMMAND_LINE_ERROR_MEMORY; - if (freerdp_client_settings_parse_assistance_file(settings, - settings->AssistanceFile) < 0) - return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - return 1; } } @@ -394,7 +239,11 @@ BOOL freerdp_client_add_device_channel(rdpSettings* settings, int count, if (count > 2) { - if (!(drive->Path = _strdup(params[2]))) + const BOOL isPath = PathFileExistsA(params[2]); + const BOOL isSpecial = (strncmp(params[2], "*", 2) == 0) || + (strncmp(params[2], "%", 2) == 0) ? TRUE : FALSE; + + if ((!isPath && !isSpecial) || !(drive->Path = _strdup(params[2]))) { free(drive->Name); free(drive); @@ -470,44 +319,29 @@ BOOL freerdp_client_add_device_channel(rdpSettings* settings, int count, settings->RedirectSmartCards = TRUE; settings->DeviceRedirection = TRUE; + smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD)); - if (count > 1) + if (!smartcard) + return FALSE; + + smartcard->Type = RDPDR_DTYP_SMARTCARD; + + if (count > 1 && strlen(params[1])) { - smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD)); - - if (!smartcard) - return FALSE; - - smartcard->Type = RDPDR_DTYP_SMARTCARD; - - if (count > 1) + if (!(smartcard->Name = _strdup(params[1]))) { - if (!(smartcard->Name = _strdup(params[1]))) - { - free(smartcard); - return FALSE; - } - } - - if (count > 2) - { - if (!(smartcard->Path = _strdup(params[2]))) - { - free(smartcard->Name); - free(smartcard); - return FALSE; - } - } - - if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard)) - { - free(smartcard->Path); - free(smartcard->Name); free(smartcard); return FALSE; } } + if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard)) + { + free(smartcard->Name); + free(smartcard); + return FALSE; + } + return TRUE; } else if (strcmp(params[0], "serial") == 0) @@ -733,75 +567,103 @@ error_argv: return FALSE; } -static char** freerdp_command_line_parse_comma_separated_values(char* list, - int* count) +static char** freerdp_command_line_parse_comma_separated_values_ex(const char* name, + const char* list, + size_t* count) { char** p; char* str; - int nArgs; - int index; - int nCommas; + size_t nArgs; + size_t index; + size_t nCommas; + size_t prefix, len; nCommas = 0; assert(NULL != count); *count = 0; if (!list) - return NULL; + { + if (name) + { + p = (char**) calloc(1UL, sizeof(char*)); - for (index = 0; list[index]; index++) - nCommas += (list[index] == ',') ? 1 : 0; + if (p) + { + p[0] = name; + *count = 1; + return p; + } + } + + return NULL; + } + + { + const char* it = list; + + while ((it = strchr(it, ',')) != NULL) + { + it++; + nCommas++; + } + } nArgs = nCommas + 1; - p = (char**) calloc((nArgs + 1UL), sizeof(char*)); + + if (name) + nArgs++; + + prefix = (nArgs + 1UL) * sizeof(char*); + len = strlen(list); + p = (char**) calloc(len + prefix + 1, sizeof(char*)); if (!p) return NULL; - str = (char*) list; - p[0] = str; + str = &((char*)p)[prefix]; + memcpy(str, list, len); - for (index = 1; index < nArgs; index++) + if (name) + p[0] = (char*)name; + + for (index = name ? 1 : 0; index < nArgs; index++) { - p[index] = strchr(p[index - 1], ','); - *p[index] = '\0'; - p[index]++; + char* comma = strchr(str, ','); + p[index] = str; + + if (comma) + { + str = comma + 1; + *comma = '\0'; + } } - p[index] = str + strlen(str); *count = nArgs; return p; } -static char** freerdp_command_line_parse_comma_separated_values_offset( - char* list, int* count) +static char** freerdp_command_line_parse_comma_separated_values(char* list, + size_t* count) { - char** p; - char** t; - p = freerdp_command_line_parse_comma_separated_values(list, count); - t = (char**) realloc(p, sizeof(char*) * (*count + 1)); + return freerdp_command_line_parse_comma_separated_values_ex(NULL, list, count); +} - if (!t) - return NULL; - - p = t; - - if (*count) - MoveMemory(&p[1], p, sizeof(char*)** count); - - (*count)++; - return p; +static char** freerdp_command_line_parse_comma_separated_values_offset( + const char* name, char* list, size_t* count) +{ + return freerdp_command_line_parse_comma_separated_values_ex(name, list, count); } static int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT_A* arg) { rdpSettings* settings = (rdpSettings*) context; - BOOL status = FALSE; + BOOL status = TRUE; CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "a") { char** p; - int count; + size_t count; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); if ((status = freerdp_client_add_device_channel(settings, count, p))) @@ -814,7 +676,7 @@ static int freerdp_client_command_line_post_filter(void* context, CommandLineSwitchCase(arg, "vc") { char** p; - int count; + size_t count; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); status = freerdp_client_add_static_channel(settings, count, p); free(p); @@ -822,7 +684,7 @@ static int freerdp_client_command_line_post_filter(void* context, CommandLineSwitchCase(arg, "dvc") { char** p; - int count; + size_t count; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); status = freerdp_client_add_dynamic_channel(settings, count, p); free(p); @@ -830,82 +692,54 @@ static int freerdp_client_command_line_post_filter(void* context, CommandLineSwitchCase(arg, "drive") { char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset(arg->Name, arg->Value, &count); - p[0] = "drive"; status = freerdp_client_add_device_channel(settings, count, p); free(p); } CommandLineSwitchCase(arg, "serial") { char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset(arg->Name, arg->Value, &count); - p[0] = "serial"; status = freerdp_client_add_device_channel(settings, count, p); free(p); } CommandLineSwitchCase(arg, "parallel") { char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset(arg->Name, arg->Value, &count); - p[0] = "parallel"; status = freerdp_client_add_device_channel(settings, count, p); free(p); } CommandLineSwitchCase(arg, "smartcard") { - if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) - { - char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, - &count); - p[0] = "smartcard"; - status = freerdp_client_add_device_channel(settings, count, p); - free(p); - } - else - { - char* p[1]; - int count; - count = 1; - p[0] = "smartcard"; - status = freerdp_client_add_device_channel(settings, count, p); - } + char** p; + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset(arg->Name, arg->Value, + &count); + status = freerdp_client_add_device_channel(settings, count, p); + free(p); } CommandLineSwitchCase(arg, "printer") { - if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) - { - char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, - &count); - p[0] = "printer"; - status = freerdp_client_add_device_channel(settings, count, p); - free(p); - } - else - { - char* p[1]; - int count; - count = 1; - p[0] = "printer"; - status = freerdp_client_add_device_channel(settings, count, p); - } + char** p; + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset(arg->Name, arg->Value, + &count); + status = freerdp_client_add_device_channel(settings, count, p); + free(p); } CommandLineSwitchCase(arg, "usb") { char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset("urbdrc", arg->Value, &count); - p[0] = "urbdrc"; status = freerdp_client_add_dynamic_channel(settings, count, p); free(p); } @@ -921,72 +755,49 @@ static int freerdp_client_command_line_post_filter(void* context, { settings->SupportEchoChannel = TRUE; } + CommandLineSwitchCase(arg, "ssh-agent") + { + settings->SupportSSHAgentChannel = TRUE; + } CommandLineSwitchCase(arg, "disp") { settings->SupportDisplayControl = TRUE; } + CommandLineSwitchCase(arg, "geometry") + { + settings->SupportGeometryTracking = TRUE; + } + CommandLineSwitchCase(arg, "video") + { + settings->SupportGeometryTracking = TRUE; /* this requires geometry tracking */ + settings->SupportVideoOptimized = TRUE; + } CommandLineSwitchCase(arg, "sound") { - if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) - { - char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, - &count); - p[0] = "rdpsnd"; - status = freerdp_client_add_static_channel(settings, count, p); - free(p); - } - else - { - char* p[1]; - int count; - count = 1; - p[0] = "rdpsnd"; - status = freerdp_client_add_static_channel(settings, count, p); - } + char** p; + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset("rdpsnd", arg->Value, + &count); + status = freerdp_client_add_static_channel(settings, count, p); + free(p); } CommandLineSwitchCase(arg, "microphone") { - if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) - { - char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, - &count); - p[0] = "audin"; - status = freerdp_client_add_dynamic_channel(settings, count, p); - free(p); - } - else - { - char* p[1]; - int count; - count = 1; - p[0] = "audin"; - status = freerdp_client_add_dynamic_channel(settings, count, p); - } + char** p; + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset("audin", arg->Value, + &count); + status = freerdp_client_add_dynamic_channel(settings, count, p); + free(p); } CommandLineSwitchCase(arg, "multimedia") { - if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) - { - char** p; - int count; - p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, - &count); - p[0] = "tsmf"; - status = freerdp_client_add_dynamic_channel(settings, count, p); - free(p); - } - else - { - char* p[1]; - int count; - count = 1; - p[0] = "tsmf"; - status = freerdp_client_add_dynamic_channel(settings, count, p); - } + char** p; + size_t count; + p = freerdp_command_line_parse_comma_separated_values_offset("tsmf", arg->Value, + &count); + status = freerdp_client_add_dynamic_channel(settings, count, p); + free(p); } CommandLineSwitchCase(arg, "heartbeat") { @@ -998,11 +809,15 @@ static int freerdp_client_command_line_post_filter(void* context, settings->MultitransportFlags = (TRANSPORT_TYPE_UDP_FECR | TRANSPORT_TYPE_UDP_FECL | TRANSPORT_TYPE_UDP_PREFERRED); } + CommandLineSwitchCase(arg, "password-is-pin") + { + settings->PasswordIsSmartcardPin = TRUE; + } CommandLineSwitchEnd(arg) - return status ? 1 : 0; + return status ? 1 : -1; } -BOOL freerdp_parse_username(char* username, char** user, char** domain) +BOOL freerdp_parse_username(const char* username, char** user, char** domain) { char* p; int length = 0; @@ -1056,15 +871,21 @@ BOOL freerdp_parse_username(char* username, char** user, char** domain) return TRUE; } -BOOL freerdp_parse_hostname(char* hostname, char** host, int* port) +BOOL freerdp_parse_hostname(const char* hostname, char** host, int* port) { char* p; - int length; p = strrchr(hostname, ':'); if (p) { - length = (p - hostname); + unsigned long val; + SSIZE_T length = (p - hostname); + errno = 0; + val = strtoul(p + 1, NULL, 0); + + if ((errno != 0) || (val <= 0) || (val > UINT16_MAX)) + return FALSE; + *host = (char*) calloc(length + 1UL, sizeof(char)); if (!(*host)) @@ -1072,7 +893,7 @@ BOOL freerdp_parse_hostname(char* hostname, char** host, int* port) CopyMemory(*host, hostname, length); (*host)[length] = '\0'; - *port = atoi(p + 1); + *port = val; } else { @@ -1244,8 +1065,8 @@ static int freerdp_detect_command_line_pre_filter(void* context, int index, return 0; } -int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, - int* count, BOOL ignoreUnknown) +static int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, + size_t* count, BOOL ignoreUnknown) { int status; DWORD flags; @@ -1286,7 +1107,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) + size_t* count, BOOL ignoreUnknown) { int status; DWORD flags; @@ -1333,9 +1154,9 @@ static BOOL freerdp_client_detect_command_line(int argc, char** argv, int old_cli_status; int old_cli_count; int posix_cli_status; - int posix_cli_count; + size_t posix_cli_count; int windows_cli_status; - int windows_cli_count; + size_t windows_cli_count; BOOL compatibility = FALSE; windows_cli_status = freerdp_detect_windows_style_command_line_syntax(argc, argv, &windows_cli_count, ignoreUnknown); @@ -1379,6 +1200,13 @@ static BOOL freerdp_client_detect_command_line(int argc, char** argv, int freerdp_client_settings_command_line_status_print(rdpSettings* settings, int status, int argc, char** argv) +{ + return freerdp_client_settings_command_line_status_print_ex( + settings, status, argc, argv, NULL); +} + +int freerdp_client_settings_command_line_status_print_ex(rdpSettings* settings, + int status, int argc, char** argv, COMMAND_LINE_ARGUMENT_A* custom) { COMMAND_LINE_ARGUMENT_A* arg; @@ -1400,7 +1228,7 @@ int freerdp_client_settings_command_line_status_print(rdpSettings* settings, if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) { - int i; + DWORD i; RDP_KEYBOARD_LAYOUT* layouts; layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD); //if (!layouts) /* FIXME*/ @@ -1440,13 +1268,23 @@ int freerdp_client_settings_command_line_status_print(rdpSettings* settings, } else if (status < 0) { - freerdp_client_print_command_line_help(argc, argv); + freerdp_client_print_command_line_help_ex(argc, argv, custom); return COMMAND_LINE_STATUS_PRINT_HELP; } return 0; } +static BOOL ends_with(const char* str, const char* ext) +{ + const size_t strLen = strlen(str); + const size_t extLen = strlen(ext); + + if (strLen < extLen) + return FALSE; + + return strncmp(&str[strLen - extLen], ext, extLen) == 0; +} int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, int argc, char** argv, BOOL allowUnknown) { @@ -1454,13 +1292,30 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, char* user = NULL; char* gwUser = NULL; char* str; - int length; + size_t length; int status; - DWORD flags; - BOOL compatibility; + BOOL ext = FALSE; + BOOL assist = FALSE; + DWORD flags = 0; + BOOL promptForPassword = FALSE; + BOOL compatibility = FALSE; COMMAND_LINE_ARGUMENT_A* arg; - compatibility = freerdp_client_detect_command_line(argc, argv, &flags, - allowUnknown); + + /* Command line detection fails if only a .rdp or .msrcIncident file + * is supplied. Check this case first, only then try to detect + * legacy command line syntax. */ + if (argc > 1) + { + ext = ends_with(argv[1], ".rdp"); + assist = ends_with(argv[1], ".msrcIncident"); + } + + if (!ext && !assist) + compatibility = freerdp_client_detect_command_line(argc, argv, &flags, + allowUnknown); + else + compatibility = freerdp_client_detect_command_line(argc - 1, &argv[1], &flags, + allowUnknown); if (compatibility) { @@ -1469,13 +1324,23 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } else { - CommandLineClearArgumentsA(args); - if (allowUnknown) - { flags |= COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + + if (ext) + { + if (freerdp_client_settings_parse_connection_file(settings, argv[1])) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } + if (assist) + { + if (freerdp_client_settings_parse_assistance_file(settings, + argv[1]) < 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + + CommandLineClearArgumentsA(args); status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags, settings, freerdp_client_command_line_pre_filter, @@ -1487,6 +1352,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, CommandLineFindArgumentA(args, "v"); arg = args; + errno = 0; do { @@ -1507,8 +1373,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (p) { + unsigned long val = strtoul(&p[1], NULL, 0); + + if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + length = (int)(p - arg->Value); - settings->ServerPort = atoi(&p[1]); + settings->ServerPort = val; if (!(settings->ServerHostname = (char*) calloc(length + 1UL, sizeof(char)))) return COMMAND_LINE_ERROR_MEMORY; @@ -1539,7 +1410,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (*(p2 + 1) == ':') { - settings->ServerPort = atoi(&p2[2]); + unsigned long val = strtoul(&p2[2], NULL, 0); + + if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->ServerPort = val; } printf("hostname %s port %"PRIu32"\n", settings->ServerHostname, settings->ServerPort); @@ -1573,11 +1449,21 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "w") { - settings->DesktopWidth = atoi(arg->Value); + long val = strtol(arg->Value, NULL, 0); + + if ((errno != 0) || (val <= 0) || (val > UINT16_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->DesktopWidth = val; } CommandLineSwitchCase(arg, "h") { - settings->DesktopHeight = atoi(arg->Value); + long val = strtol(arg->Value, NULL, 0); + + if ((errno != 0) || (val <= 0) || (val > UINT16_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->DesktopHeight = val; } CommandLineSwitchCase(arg, "size") { @@ -1589,8 +1475,28 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (p) { *p = '\0'; - settings->DesktopWidth = atoi(str); - settings->DesktopHeight = atoi(&p[1]); + { + long val = strtol(str, NULL, 0); + + if ((errno != 0) || (val <= 0) || (val > UINT16_MAX)) + { + free(str); + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + + settings->DesktopWidth = val; + } + { + long val = strtol(&p[1], NULL, 0); + + if ((errno != 0) || (val <= 0) || (val > UINT16_MAX)) + { + free(str); + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + + settings->DesktopHeight = val; + } } else { @@ -1598,7 +1504,38 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (p) { - settings->PercentScreen = atoi(str); + BOOL partial = FALSE; + + if (strchr(p, 'w')) + { + settings->PercentScreenUseWidth = 1; + partial = TRUE; + } + + if (strchr(p, 'h')) + { + settings->PercentScreenUseHeight = 1; + partial = TRUE; + } + + if (!partial) + { + settings->PercentScreenUseWidth = 1; + settings->PercentScreenUseHeight = 1; + } + + *p = '\0'; + { + long val = strtol(str, NULL, 0); + + if ((errno != 0) || (val < 0) || (val > 100)) + { + free(str); + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + + settings->PercentScreen = val; + } } } @@ -1634,7 +1571,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { UINT32 i; char** p; - int count = 0; + size_t count = 0; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); if (!p) @@ -1647,7 +1584,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, for (i = 0; i < settings->NumMonitorIds; i++) { - settings->MonitorIds[i] = atoi(p[i]); + unsigned long val = strtoul(p[i], NULL, 0); + + if ((errno != 0) || (val > UINT16_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->MonitorIds[i] = val; } free(p); @@ -1668,8 +1610,25 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { settings->Decorations = arg->Value ? TRUE : FALSE; } + CommandLineSwitchCase(arg, "dynamic-resolution") + { + if (settings->SmartSizing) + { + WLog_ERR(TAG, "Smart sizing and dynamic resolution are mutually exclusive options"); + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + + settings->SupportDisplayControl = TRUE; + settings->DynamicResolutionUpdate = TRUE; + } CommandLineSwitchCase(arg, "smart-sizing") { + if (settings->DynamicResolutionUpdate) + { + WLog_ERR(TAG, "Smart sizing and dynamic resolution are mutually exclusive options"); + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + settings->SmartSizing = TRUE; if (arg->Value) @@ -1679,9 +1638,26 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if ((p = strchr(str, 'x'))) { + unsigned long w, h; *p = '\0'; - settings->SmartSizingWidth = atoi(str); - settings->SmartSizingHeight = atoi(&p[1]); + w = strtoul(str, NULL, 0); + + if ((errno != 0) || (w == 0) || (w > UINT16_MAX)) + { + free(str); + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + + h = strtoul(&p[1], NULL, 0); + + if ((errno != 0) || (h == 0) || (h > UINT16_MAX)) + { + free(str); + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + + settings->SmartSizingWidth = w; + settings->SmartSizingHeight = h; } free(str); @@ -1689,7 +1665,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "bpp") { - settings->ColorDepth = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if (errno != 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->ColorDepth = val; switch (settings->ColorDepth) { @@ -1731,42 +1712,52 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "kbd") { - unsigned long int id; - char* pEnd; - id = strtoul(arg->Value, &pEnd, 16); + unsigned long id = strtoul(arg->Value, NULL, 0); - if (pEnd != (arg->Value + strlen(arg->Value))) - id = 0; - - if (id == 0) + if ((errno != 0) || (id > UINT32_MAX) || (id == 0)) { - id = (unsigned long int) freerdp_map_keyboard_layout_name_to_id(arg->Value); + const int rc = freerdp_map_keyboard_layout_name_to_id(arg->Value); - if (id == -1) - WLog_ERR(TAG, "A problem occurred while mapping the layout name to id"); - else if (id == 0) + if (rc <= 0) { WLog_ERR(TAG, "Could not identify keyboard layout: %s", arg->Value); WLog_ERR(TAG, "Use /kbd-list to list available layouts"); + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; } - if (id <= 0) - return COMMAND_LINE_STATUS_PRINT; + /* Found a valid mapping, reset errno */ + id = (unsigned long)rc; + errno = 0; } settings->KeyboardLayout = (UINT32) id; } CommandLineSwitchCase(arg, "kbd-type") { - settings->KeyboardType = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->KeyboardType = val; } CommandLineSwitchCase(arg, "kbd-subtype") { - settings->KeyboardSubType = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->KeyboardSubType = val; } CommandLineSwitchCase(arg, "kbd-fn-key") { - settings->KeyboardFunctionKey = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->KeyboardFunctionKey = val; } CommandLineSwitchCase(arg, "u") { @@ -1796,8 +1787,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (p) { + unsigned long val = strtoul(&p[1], NULL, 0); + + if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + length = (int)(p - arg->Value); - settings->GatewayPort = atoi(&p[1]); + settings->GatewayPort = val; if (!(settings->GatewayHostname = (char*) calloc(length + 1UL, sizeof(char)))) return COMMAND_LINE_ERROR_MEMORY; @@ -1848,15 +1844,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (p) { - length = (int)(p - arg->Value); + unsigned long val = strtoul(&p[1], NULL, 0); - if (!isdigit(p[1])) - { - WLog_ERR(TAG, "Could not parse proxy port"); + if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - } - settings->ProxyPort = atoi(&p[1]); + length = (p - arg->Value); + settings->ProxyPort = val; settings->ProxyHostname = (char*) malloc(length + 1); strncpy(settings->ProxyHostname, arg->Value, length); settings->ProxyHostname[length] = '\0'; @@ -1912,12 +1906,22 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, settings->GatewayHttpTransport = TRUE; } } + CommandLineSwitchCase(arg, "gat") + { + free(settings->GatewayAccessToken); + + if (!(settings->GatewayAccessToken = _strdup(arg->Value))) + return COMMAND_LINE_ERROR_MEMORY; + } CommandLineSwitchCase(arg, "gateway-usage-method") { - int type; + long type; char* pEnd; type = strtol(arg->Value, &pEnd, 10); + if (errno != 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + if (type == 0) { if (_stricmp(arg->Value, "none") == 0) @@ -1996,7 +2000,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "compression-level") { - settings->CompressionLevel = atoi(arg->Value); + unsigned long val = strtol(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->CompressionLevel = val; } CommandLineSwitchCase(arg, "drives") { @@ -2006,6 +2015,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { settings->RedirectHomeDrive = arg->Value ? TRUE : FALSE; } + CommandLineSwitchCase(arg, "ipv6") + { + settings->PreferIPv6OverIPv4 = TRUE; + } CommandLineSwitchCase(arg, "clipboard") { settings->RedirectClipboard = arg->Value ? TRUE : FALSE; @@ -2026,8 +2039,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "audio-mode") { - int mode; - mode = atoi(arg->Value); + long mode = strtol(arg->Value, NULL, 0); + + if (errno != 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; if (mode == AUDIO_MODE_REDIRECT) { @@ -2045,10 +2060,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "network") { - int type; + long type; char* pEnd; type = strtol(arg->Value, &pEnd, 10); + if (errno != 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + if (type == 0) { if (_stricmp(arg->Value, "modem") == 0) @@ -2112,6 +2130,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (arg->Value) { #ifdef WITH_GFX_H264 + if (_strnicmp("AVC444", arg->Value, 6) == 0) { settings->GfxH264 = TRUE; @@ -2123,13 +2142,17 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } else #endif - if (_strnicmp("RFX", arg->Value, 3) != 0) - return COMMAND_LINE_ERROR; + if (_strnicmp("RFX", arg->Value, 3) != 0) + return COMMAND_LINE_ERROR; } } CommandLineSwitchCase(arg, "gfx-thin-client") { settings->GfxThinClient = arg->Value ? TRUE : FALSE; + + if (settings->GfxThinClient) + settings->GfxSmallCache = TRUE; + settings->SupportGraphicsPipeline = TRUE; } CommandLineSwitchCase(arg, "gfx-small-cache") @@ -2173,12 +2196,18 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "frame-ack") { - settings->FrameAcknowledge = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->FrameAcknowledge = val; } CommandLineSwitchCase(arg, "nsc") { settings->NSCodec = TRUE; } +#if defined(WITH_JPEG) CommandLineSwitchCase(arg, "jpeg") { settings->JpegCodec = TRUE; @@ -2186,8 +2215,14 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "jpeg-quality") { - settings->JpegQuality = atoi(arg->Value) % 100; + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > 100)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->JpegQuality = val; } +#endif CommandLineSwitchCase(arg, "nego") { settings->NegotiateSecurityLayer = arg->Value ? TRUE : FALSE; @@ -2202,8 +2237,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "pcid") { + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + settings->SendPreconnectionPdu = TRUE; - settings->PreconnectionId = atoi(arg->Value); + settings->PreconnectionId = val; } CommandLineSwitchCase(arg, "sec") { @@ -2247,7 +2287,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { UINT32 i; char** p; - int count = 0; + size_t count = 0; p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count); for (i = 0; i < count; i++) @@ -2270,6 +2310,14 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, CommandLineSwitchCase(arg, "from-stdin") { settings->CredentialsFromStdin = TRUE; + + if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) + { + promptForPassword = (strncmp(arg->Value, "force", 6) == 0); + + if (!promptForPassword) + return COMMAND_LINE_ERROR; + } } CommandLineSwitchCase(arg, "log-level") { @@ -2360,7 +2408,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "parent-window") { - settings->ParentWindowId = strtol(arg->Value, NULL, 0); + UINT64 val = _strtoui64(arg->Value, NULL, 0); + + if (errno != 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->ParentWindowId = val; } CommandLineSwitchCase(arg, "bitmap-cache") { @@ -2387,6 +2440,8 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { settings->NSCodec = TRUE; } + +#if defined(WITH_JPEG) else if (strcmp(arg->Value, "jpeg") == 0) { settings->JpegCodec = TRUE; @@ -2394,6 +2449,8 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (settings->JpegQuality == 0) settings->JpegQuality = 75; } + +#endif } CommandLineSwitchCase(arg, "fast-path") { @@ -2402,11 +2459,21 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "max-fast-path-size") { - settings->MultifragMaxRequestSize = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->MultifragMaxRequestSize = val; } CommandLineSwitchCase(arg, "max-loop-time") { - settings->MaxTimeInCheckLoop = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->MaxTimeInCheckLoop = val; if ((long) settings->MaxTimeInCheckLoop < 0) { @@ -2461,7 +2528,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "auto-reconnect-max-retries") { - settings->AutoReconnectMaxRetries = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->AutoReconnectMaxRetries = val; if (settings->AutoReconnectMaxRetries > 1000) return COMMAND_LINE_ERROR; @@ -2497,19 +2569,37 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "pwidth") { - settings->DesktopPhysicalWidth = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->DesktopPhysicalWidth = val; } CommandLineSwitchCase(arg, "pheight") { - settings->DesktopPhysicalHeight = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->DesktopPhysicalHeight = val; } CommandLineSwitchCase(arg, "orientation") { - settings->DesktopOrientation = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > INT16_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->DesktopOrientation = val; } CommandLineSwitchCase(arg, "scale") { - int scaleFactor = atoi(arg->Value); + unsigned long scaleFactor = strtoul(arg->Value, NULL, 0); + + if (errno != 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; if (scaleFactor == 100 || scaleFactor == 140 || scaleFactor == 180) { @@ -2524,7 +2614,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "scale-desktop") { - int desktopScaleFactor = atoi(arg->Value); + unsigned long desktopScaleFactor = strtoul(arg->Value, NULL, 0); + + if (errno != 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; if (desktopScaleFactor >= 100 && desktopScaleFactor <= 500) { @@ -2538,7 +2631,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, } CommandLineSwitchCase(arg, "scale-device") { - int deviceScaleFactor = atoi(arg->Value); + unsigned long deviceScaleFactor = strtoul(arg->Value, NULL, 0); + + if (errno != 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; if (deviceScaleFactor == 100 || deviceScaleFactor == 140 || deviceScaleFactor == 180) @@ -2558,6 +2654,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (!(settings->ActionScript = _strdup(arg->Value))) return COMMAND_LINE_ERROR_MEMORY; } + CommandLineSwitchCase(arg, "fipsmode") + { + settings->FIPSMode = TRUE; + } CommandLineSwitchDefault(arg) { } @@ -2602,6 +2702,36 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, settings->GatewayUsername = gwUser; } + if (promptForPassword) + { + const size_t size = 512; + + if (!settings->Password) + { + settings->Password = calloc(size, sizeof(char)); + + if (!settings->Password) + return COMMAND_LINE_ERROR; + + if (!freerdp_passphrase_read("Password: ", settings->Password, size, 1)) + return COMMAND_LINE_ERROR; + } + + if (settings->GatewayEnabled && !settings->GatewayUseSameCredentials) + { + if (!settings->GatewayPassword) + { + settings->GatewayPassword = calloc(size, sizeof(char)); + + if (!settings->GatewayPassword) + return COMMAND_LINE_ERROR; + + if (!freerdp_passphrase_read("Gateway Password: ", settings->GatewayPassword, size, 1)) + return COMMAND_LINE_ERROR; + } + } + } + freerdp_performance_flags_make(settings); if (settings->RemoteFxCodec || settings->NSCodec @@ -2617,7 +2747,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT) { - settings->ServerPort = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->ServerPort = val; } arg = CommandLineFindArgumentA(args, "p"); @@ -2867,6 +3002,17 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) return FALSE; } + if (settings->SupportSSHAgentChannel) + { + char* p[1]; + int count; + count = 1; + p[0] = "sshagent"; + + if (!freerdp_client_add_dynamic_channel(settings, count, p)) + return FALSE; + } + if (settings->SupportDisplayControl) { char* p[1]; @@ -2878,6 +3024,28 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) return FALSE; } + if (settings->SupportGeometryTracking) + { + char* p[1]; + int count; + count = 1; + p[0] = "geometry"; + + if (!freerdp_client_add_dynamic_channel(settings, count, p)) + return FALSE; + } + + if (settings->SupportVideoOptimized) + { + char* p[1]; + int count; + count = 1; + p[0] = "video"; + + if (!freerdp_client_add_dynamic_channel(settings, count, p)) + return FALSE; + } + if (settings->DynamicChannelCount) settings->SupportDynamicChannels = TRUE; diff --git a/client/common/cmdline.h b/client/common/cmdline.h new file mode 100644 index 0000000..8785ed6 --- /dev/null +++ b/client/common/cmdline.h @@ -0,0 +1,184 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Client Command-Line Interface + * + * Copyright 2018 Bernhard Miklautz <bernhard.miklautz@thincast.com> + * Copyright 2018 Thincast Technologies GmbH + * + * 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 CLIENT_COMMON_CMDLINE_H +#define CLIENT_COMMON_CMDLINE_H + +#include <winpr/cmdline.h> + +static COMMAND_LINE_ARGUMENT_A args[] = +{ + { "a", COMMAND_LINE_VALUE_REQUIRED, "<addin>[,<options>]", NULL, NULL, -1, "addin", "Addin" }, + { "action-script", COMMAND_LINE_VALUE_REQUIRED, "<file-name>", "~/.config/freerdp/action.sh", NULL, -1, NULL, "Action script" }, + { "admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "console", "Admin (or console) session" }, + { "aero", COMMAND_LINE_VALUE_BOOL, NULL, NULL, BoolValueFalse, -1, NULL, "Enable desktop composition" }, + { "app", COMMAND_LINE_VALUE_REQUIRED, "<path> or ||<alias>", NULL, NULL, -1, NULL, "Remote application program" }, + { "app-cmd", COMMAND_LINE_VALUE_REQUIRED, "<parameters>", NULL, NULL, -1, NULL, "Remote application command-line parameters" }, + { "app-file", COMMAND_LINE_VALUE_REQUIRED, "<file-name>", NULL, NULL, -1, NULL, "File to open with remote application" }, + { "app-guid", COMMAND_LINE_VALUE_REQUIRED, "<app-guid>", NULL, NULL, -1, NULL, "Remote application GUID" }, + { "app-icon", COMMAND_LINE_VALUE_REQUIRED, "<icon-path>", NULL, NULL, -1, NULL, "Remote application icon for user interface" }, + { "app-name", COMMAND_LINE_VALUE_REQUIRED, "<app-name>", NULL, NULL, -1, NULL, "Remote application name for user interface" }, + { "assistance", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Remote assistance password" }, + { "async-channels", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Asynchronous channels (experimental)" }, + { "async-input", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Asynchronous input" }, + { "async-transport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Asynchronous transport (experimental)" }, + { "async-update", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Asynchronous update" }, + { "audio-mode", COMMAND_LINE_VALUE_REQUIRED, "<mode>", NULL, NULL, -1, NULL, "Audio output mode" }, + { "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Authenticate only" }, + { "authentication", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Authentication (expermiental)" }, + { "auto-reconnect", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Automatic reconnection" }, + { "auto-reconnect-max-retries", COMMAND_LINE_VALUE_REQUIRED, "<retries>", NULL, NULL, -1, NULL, "Automatic reconnection maximum retries, 0 for unlimited [0,1000]" }, + { "bitmap-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable bitmap cache" }, + { "bpp", COMMAND_LINE_VALUE_REQUIRED, "<depth>", "16", NULL, -1, NULL, "Session bpp (color depth)" }, + { "buildconfig", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_BUILDCONFIG, NULL, NULL, NULL, -1, NULL, "Print the build configuration" }, + { "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Ignore certificate" }, + { "cert-name", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "Certificate name" }, + { "cert-tofu", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Automatically accept certificate on first connect" }, + { "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "Client Hostname to send to server" }, + { "clipboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Redirect clipboard" }, + { "codec-cache", COMMAND_LINE_VALUE_REQUIRED, "rfx|nsc|jpeg", NULL, NULL, -1, NULL, "Bitmap codec cache" }, + { "compression", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, "z", "Enable compression" }, + { "compression-level", COMMAND_LINE_VALUE_REQUIRED, "<level>", NULL, NULL, -1, NULL, "Compression level (0,1,2)" }, + { "credentials-delegation", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Disable credentials delegation" }, + { "d", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Domain" }, + { "decorations", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Window decorations" }, + { "disp", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Display control" }, + { "drive", COMMAND_LINE_VALUE_REQUIRED, "<name>,<path>", NULL, NULL, -1, NULL, "Redirect directory <path> as named share <name>" }, + { "drives", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect all mount points as shares" }, + { "dvc", COMMAND_LINE_VALUE_REQUIRED, "<channel>[,<options>]", NULL, NULL, -1, NULL, "Dynamic virtual channel" }, + { "dynamic-resolution", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Send resolution updates when the window is resized" }, + { "echo", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "echo", "Echo channel" }, + { "encryption", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Encryption (experimental)" }, + { "encryption-methods", COMMAND_LINE_VALUE_REQUIRED, "[40,][56,][128,][FIPS]", NULL, NULL, -1, NULL, "RDP standard security encryption methods" }, + { "f", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Fullscreen mode (<Ctrl>+<Alt>+<Enter> toggles fullscreen)" }, + { "fast-path", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable fast-path input/output" }, + { "fipsmode", COMMAND_LINE_VALUE_BOOL, NULL, NULL, NULL, -1, NULL, "Enable FIPS mode" }, + { "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Enable smooth fonts (ClearType)" }, + { "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Number of frame acknowledgement" }, + { "from-stdin", COMMAND_LINE_VALUE_OPTIONAL, "force", NULL, NULL, -1, NULL, "Read credentials from stdin. With <force> the prompt is done before connection, otherwise on server request." }, + { "g", COMMAND_LINE_VALUE_REQUIRED, "<gateway>[:<port>]", NULL, NULL, -1, NULL, "Gateway Hostname" }, + { "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "direct|detect", NULL, NULL, -1, "gum", "Gateway usage method" }, + { "gd", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Gateway domain" }, + { "gdi", COMMAND_LINE_VALUE_REQUIRED, "sw|hw", NULL, NULL, -1, NULL, "GDI rendering" }, + { "geometry", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Geometry tracking channel" }, + { "gestures", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Consume multitouch input locally" }, +#ifdef WITH_GFX_H264 + { "gfx", COMMAND_LINE_VALUE_OPTIONAL, "RFX|AVC420|AVC444", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" }, + { "gfx-h264", COMMAND_LINE_VALUE_OPTIONAL, "AVC420|AVC444", NULL, NULL, -1, NULL, "RDP8.1 graphics pipeline using H264 codec" }, +#else + { "gfx", COMMAND_LINE_VALUE_OPTIONAL, "RFX", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" }, +#endif + { "gfx-progressive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline using progressive codec" }, + { "gfx-small-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline using small cache mode" }, + { "gfx-thin-client", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline using thin client mode" }, + { "glyph-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Glyph cache (experimental)" }, + { "gp", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Gateway password" }, + { "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Grab keyboard" }, + { "gt", COMMAND_LINE_VALUE_REQUIRED, "rpc|http|auto", NULL, NULL, -1, NULL, "Gateway transport type" }, + { "gu", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Gateway username" }, + { "gat", COMMAND_LINE_VALUE_REQUIRED, "<access token>", NULL, NULL, -1, NULL, "Gateway Access Token" }, + { "h", COMMAND_LINE_VALUE_REQUIRED, "<height>", "768", NULL, -1, NULL, "Height" }, + { "heartbeat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support heartbeat PDUs" }, + { "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "Print help" }, + { "home-drive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect user home as share" }, + { "ipv6", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "6", "Prefer IPv6 AAA record over IPv4 A record"}, +#if defined(WITH_JPEG) + { "jpeg", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Enable JPEG codec" }, + { "jpeg-quality", COMMAND_LINE_VALUE_REQUIRED, "<percentage>", NULL, NULL, -1, NULL, "JPEG quality" }, +#endif + { "kbd", COMMAND_LINE_VALUE_REQUIRED, "0x<id> or <name>", NULL, NULL, -1, NULL, "Keyboard layout" }, + { "kbd-fn-key", COMMAND_LINE_VALUE_REQUIRED, "<value>", NULL, NULL, -1, NULL, "Function key value" }, + { "kbd-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL, "List keyboard layouts" }, + { "kbd-subtype", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Keyboard subtype" }, + { "kbd-type", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Keyboard type" }, + { "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info-string>", NULL, NULL, -1, NULL, "Load balance info" }, + { "log-filters", COMMAND_LINE_VALUE_REQUIRED, "<tag>:<level>[,<tag>:<level>[,...]]", NULL, NULL, -1, NULL, "Set logger filters, see wLog(7) for details" }, + { "log-level", COMMAND_LINE_VALUE_REQUIRED, "OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE", NULL, NULL, -1, NULL, "Set the default log level, see wLog(7) for details" }, + { "max-fast-path-size", COMMAND_LINE_VALUE_REQUIRED, "<size>", NULL, NULL, -1, NULL, "Specify maximum fast-path update size" }, + { "max-loop-time", COMMAND_LINE_VALUE_REQUIRED, "<time>", NULL, NULL, -1, NULL, "Specify maximum time in milliseconds spend treating packets"}, + { "menu-anims", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Enable menu animations" }, + { "microphone", COMMAND_LINE_VALUE_OPTIONAL, "[sys:<sys>,][dev:<dev>,][format:<format>,][rate:<rate>,][channel:<channel>]", NULL, NULL, -1, "mic", "Audio input (microphone)" }, + { "monitor-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL, "List detected monitors" }, + { "monitors", COMMAND_LINE_VALUE_REQUIRED, "<id>[,<id>[,...]]", NULL, NULL, -1, NULL, "Select monitors to use" }, + { "mouse-motion", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Send mouse motion" }, + { "multimedia", COMMAND_LINE_VALUE_OPTIONAL, "[sys:<sys>,][dev:<dev>,][decoder:<decoder>]", NULL, NULL, -1, "mmr", "Redirect multimedia (video)" }, + { "multimon", COMMAND_LINE_VALUE_OPTIONAL, "force", NULL, NULL, -1, NULL, "Use multiple monitors" }, + { "multitouch", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect multitouch input" }, + { "multitransport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support multitransport protocol" }, + { "nego", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable protocol security negotiation" }, + { "network", COMMAND_LINE_VALUE_REQUIRED, "modem|broadband|broadband-low|broadband-high|wan|lan|auto", NULL, NULL, -1, NULL, "Network connection type" }, + { "nsc", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "nscodec", "Enable NSCodec" }, + { "offscreen-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable offscreen bitmap cache" }, + { "orientation", COMMAND_LINE_VALUE_REQUIRED, "0|90|180|270", NULL, NULL, -1, NULL, "Orientation of display in degrees" }, + { "p", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Password" }, + { "parallel", COMMAND_LINE_VALUE_OPTIONAL, "<name>[,<path>]", NULL, NULL, -1, NULL, "Redirect parallel device" }, + { "parent-window", COMMAND_LINE_VALUE_REQUIRED, "<window-id>", NULL, NULL, -1, NULL, "Parent window id" }, + { "password-is-pin", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Use smart card authentication with password as smart card PIN"}, + { "pcb", COMMAND_LINE_VALUE_REQUIRED, "<blob>", NULL, NULL, -1, NULL, "Preconnection Blob" }, + { "pcid", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Preconnection Id" }, + { "pheight", COMMAND_LINE_VALUE_REQUIRED, "<height>", NULL, NULL, -1, NULL, "Physical height of display (in millimeters)" }, + { "play-rfx", COMMAND_LINE_VALUE_REQUIRED, "<pcap-file>", NULL, NULL, -1, NULL, "Replay rfx pcap file" }, + { "port", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Server port" }, + { "print-reconnect-cookie", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Print base64 reconnect cookie after connecting" }, + { "printer", COMMAND_LINE_VALUE_OPTIONAL, "<name>[,<driver>]", NULL, NULL, -1, NULL, "Redirect printer device" }, + { "proxy", COMMAND_LINE_VALUE_REQUIRED, "[<proto>://]<host>:<port>", NULL, NULL, -1, NULL, "Proxy (see also environment variable below)" }, + { "pth", COMMAND_LINE_VALUE_REQUIRED, "<password-hash>", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" }, + { "pwidth", COMMAND_LINE_VALUE_REQUIRED, "<width>", NULL, NULL, -1, NULL, "Physical width of display (in millimeters)" }, + { "reconnect-cookie", COMMAND_LINE_VALUE_REQUIRED, "<base64-cookie>", NULL, NULL, -1, NULL, "Pass base64 reconnect cookie to the connection" }, + { "restricted-admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "restrictedAdmin", "Restricted admin mode" }, + { "rfx", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "RemoteFX" }, + { "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "image|video", NULL, NULL, -1, NULL, "RemoteFX mode" }, + { "scale", COMMAND_LINE_VALUE_REQUIRED, "100|140|180", "100", NULL, -1, NULL, "Scaling factor of the display" }, + { "scale-desktop", COMMAND_LINE_VALUE_REQUIRED, "<percentage>", "100", NULL, -1, NULL, "Scaling factor for desktop applications (value between 100 and 500)" }, + { "scale-device", COMMAND_LINE_VALUE_REQUIRED, "100|140|180", "100", NULL, -1, NULL, "Scaling factor for app store applications" }, + { "sec", COMMAND_LINE_VALUE_REQUIRED, "rdp|tls|nla|ext", NULL, NULL, -1, NULL, "Force specific protocol security" }, + { "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "NLA extended protocol security" }, + { "sec-nla", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "NLA protocol security" }, + { "sec-rdp", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "RDP protocol security" }, + { "sec-tls", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "TLS protocol security" }, + { "serial", COMMAND_LINE_VALUE_OPTIONAL, "<name>[,<path>[,<driver>[,permissive]]]", NULL, NULL, -1, "tty", "Redirect serial device" }, + { "shell", COMMAND_LINE_VALUE_REQUIRED, "<shell>", NULL, NULL, -1, NULL, "Alternate shell" }, + { "shell-dir", COMMAND_LINE_VALUE_REQUIRED, "<dir>", NULL, NULL, -1, NULL, "Shell working directory" }, + { "size", COMMAND_LINE_VALUE_REQUIRED, "<width>x<height> or <percent>%[wh]", "1024x768", NULL, -1, NULL, "Screen size" }, + { "smart-sizing", COMMAND_LINE_VALUE_OPTIONAL, "<width>x<height>", NULL, NULL, -1, NULL, "Scale remote desktop to window size" }, + { "smartcard", COMMAND_LINE_VALUE_OPTIONAL, "<name>[,<path>]", NULL, NULL, -1, NULL, "Redirect smartcard device" }, + { "sound", COMMAND_LINE_VALUE_OPTIONAL, "[sys:<sys>,][dev:<dev>,][format:<format>,][rate:<rate>,][channel:<channel>,][latency:<latency>,][quality:<quality>]", NULL, NULL, -1, "audio", "Audio output (sound)" }, + { "span", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Span screen over multiple monitors" }, + { "spn-class", COMMAND_LINE_VALUE_REQUIRED, "<service-class>", NULL, NULL, -1, NULL, "SPN authentication service class" }, + { "ssh-agent", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "ssh-agent", "SSH Agent forwarding channel" }, + { "t", COMMAND_LINE_VALUE_REQUIRED, "<title>", NULL, NULL, -1, "title", "Window title" }, + { "themes", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable themes" }, + { "tls-ciphers", COMMAND_LINE_VALUE_REQUIRED, "netmon|ma|ciphers", NULL, NULL, -1, NULL, "Allowed TLS ciphers" }, + { "toggle-fullscreen", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Alt+Ctrl+Enter toggles fullscreen" }, + { "u", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Username" }, + { "unmap-buttons", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Let server see real physical pointer button"}, + { "usb", COMMAND_LINE_VALUE_REQUIRED, "[dbg,][dev:<dev>,][id|addr,][auto]", NULL, NULL, -1, NULL, "Redirect USB device" }, + { "v", COMMAND_LINE_VALUE_REQUIRED, "<server>[:port]", NULL, NULL, -1, NULL, "Server hostname" }, + { "vc", COMMAND_LINE_VALUE_REQUIRED, "<channel>[,<options>]", NULL, NULL, -1, NULL, "Static virtual channel" }, + { "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "Print version" }, + { "video", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Video optimized remoting channel" }, + { "vmconnect", COMMAND_LINE_VALUE_OPTIONAL, "<vmid>", NULL, NULL, -1, NULL, "Hyper-V console (use port 2179, disable negotiation)" }, + { "w", COMMAND_LINE_VALUE_REQUIRED, "<width>", "1024", NULL, -1, NULL, "Width" }, + { "wallpaper", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable wallpaper" }, + { "window-drag", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Enable full window drag" }, + { "wm-class", COMMAND_LINE_VALUE_REQUIRED, "<class-name>", NULL, NULL, -1, NULL, "Set the WM_CLASS hint for the window instance" }, + { "workarea", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Use available work area" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } +}; +#endif /* CLIENT_COMMON_CMDLINE_H */ diff --git a/client/common/compatibility.c b/client/common/compatibility.c index a95b6a3..468339a 100644 --- a/client/common/compatibility.c +++ b/client/common/compatibility.c @@ -23,6 +23,8 @@ #include "config.h" #endif +#include <errno.h> + #include <winpr/crt.h> #include <winpr/cmdline.h> @@ -39,7 +41,7 @@ #define TAG CLIENT_TAG("common.compatibility") -COMMAND_LINE_ARGUMENT_A old_args[] = +static COMMAND_LINE_ARGUMENT_A old_args[] = { { "0", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "connect to console session" }, { "a", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "set color depth in bits, default is 16" }, @@ -91,42 +93,66 @@ COMMAND_LINE_ARGUMENT_A old_args[] = { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -BOOL freerdp_client_old_parse_hostname(char* str, char** ServerHostname, UINT32* ServerPort) +static BOOL freerdp_client_old_parse_hostname(char* str, char** ServerHostname, UINT32* ServerPort) { char* p; + char* host = NULL; if (str[0] == '[' && (p = strchr(str, ']')) && (p[1] == 0 || (p[1] == ':' && !strchr(p + 2, ':')))) { /* Either "[...]" or "[...]:..." with at most one : after the brackets */ - if (!(*ServerHostname = _strdup(str + 1))) + if (!(host = _strdup(str + 1))) return FALSE; - if ((p = strchr((char*) *ServerHostname, ']'))) + if ((p = strchr(host, ']'))) { *p = 0; if (p[1] == ':') - *ServerPort = atoi(p + 2); + { + unsigned long val; + errno = 0; + val = strtoul(p + 2, NULL, 0); + + if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + { + free(host); + return FALSE; + } + + *ServerPort = val; + } } } else { /* Port number is cut off and used if exactly one : in the string */ - if (!(*ServerHostname = _strdup(str))) + if (!(host = _strdup(str))) return FALSE; - if ((p = strchr((char*) *ServerHostname, ':')) && !strchr(p + 1, ':')) + if ((p = strchr(host, ':')) && !strchr(p + 1, ':')) { + unsigned long val; + errno = 0; + val = strtoul(p + 1, NULL, 0); + + if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + { + free(host); + return FALSE; + } + *p = 0; - *ServerPort = atoi(p + 1); + *ServerPort = val; } } + *ServerHostname = host; return TRUE; } -int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args) +static int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args) { int args_handled = 0; @@ -205,8 +231,8 @@ int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args) return args_handled; } - -int freerdp_client_old_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv) +static int freerdp_client_old_command_line_pre_filter(void* context, int index, int argc, + LPCSTR* argv) { rdpSettings* settings = (rdpSettings*) context; @@ -374,12 +400,10 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg return 0; } - -int freerdp_client_old_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT_A* arg) +static int freerdp_client_old_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT_A* arg) { return 0; } - int freerdp_detect_old_command_line_syntax(int argc, char** argv, int* count) { int status; @@ -445,7 +469,6 @@ int freerdp_detect_old_command_line_syntax(int argc, char** argv, int* count) free(settings); return detect_status; } - int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSettings* settings) { char* p; @@ -481,6 +504,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe } arg = old_args; + errno = 0; do { @@ -495,7 +519,12 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe } CommandLineSwitchCase(arg, "a") { - settings->ColorDepth = atoi(arg->Value); + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > INT8_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->ColorDepth = val; WLog_WARN(TAG, "-a %s -> /bpp:%s", arg->Value, arg->Value); } CommandLineSwitchCase(arg, "c") @@ -538,9 +567,25 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe if (p) { + unsigned long h, w = strtoul(str, NULL, 0); + + if ((errno != 0) || (w == 0) || (w > UINT16_MAX)) + { + free(str); + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + + h = strtoul(&p[1], NULL, 0); + + if ((errno != 0) || (h == 0) || (h > UINT16_MAX)) + { + free(str); + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } + *p = '\0'; - settings->DesktopWidth = atoi(str); - settings->DesktopHeight = atoi(&p[1]); + settings->DesktopWidth = w; + settings->DesktopHeight = h; } free(str); @@ -587,7 +632,12 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe } CommandLineSwitchCase(arg, "t") { - settings->ServerPort = atoi(arg->Value); + unsigned long p = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (p == 0) || (p > UINT16_MAX)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + + settings->ServerPort = p; WLog_WARN(TAG, "-t %s -> /port:%s", arg->Value, arg->Value); } CommandLineSwitchCase(arg, "u") @@ -599,10 +649,13 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe } CommandLineSwitchCase(arg, "x") { - int type; + long type; char* pEnd; type = strtol(arg->Value, &pEnd, 16); + if (errno != 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + if (type == 0) { type = CONNECTION_TYPE_LAN; @@ -635,7 +688,11 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe } CommandLineSwitchCase(arg, "X") { - settings->ParentWindowId = strtol(arg->Value, NULL, 0); + settings->ParentWindowId = _strtoui64(arg->Value, NULL, 0); + + if (errno != 0) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + WLog_WARN(TAG, "-X %s -> /parent-window:%s", arg->Value, arg->Value); } CommandLineSwitchCase(arg, "z") @@ -806,5 +863,5 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe WLog_WARN(TAG, " /port:%"PRIu32"", settings->ServerPort); WLog_WARN(TAG, ""); - return 1; + return 0; } diff --git a/client/common/file.c b/client/common/file.c index ca1b9b7..ed43264 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -21,6 +21,7 @@ #include "config.h" #endif +#include <errno.h> #include <freerdp/client/file.h> #include <freerdp/client/cmdline.h> @@ -41,6 +42,7 @@ #include <unistd.h> #endif +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <freerdp/log.h> #define TAG CLIENT_TAG("common") @@ -48,7 +50,6 @@ //#define DEBUG_CLIENT_FILE 1 static BYTE BOM_UTF16_LE[2] = { 0xFF, 0xFE }; -static WCHAR CR_LF_STR_W[] = { '\r', '\n', '\0' }; #define INVALID_INTEGER_VALUE 0xFFFFFFFF @@ -218,47 +219,15 @@ static int freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, return standard; } -static BOOL freerdp_client_parse_rdp_file_integer_unicode(rdpFile* file, const WCHAR* name, - const WCHAR* value, int index) -{ - int length; - int ivalue; - char* nameA; - char* valueA; - BOOL ret = TRUE; - length = (int) _wcslen(name); - nameA = (char*) malloc(length + 1); - - if (!nameA) - return FALSE; - - WideCharToMultiByte(CP_UTF8, 0, name, length, nameA, length, NULL, NULL); - nameA[length] = '\0'; - length = (int) _wcslen(value); - valueA = (char*) malloc(length + 1); - - if (!valueA) - { - free(nameA); - return FALSE; - } - - WideCharToMultiByte(CP_UTF8, 0, value, length, valueA, length, NULL, NULL); - valueA[length] = '\0'; - ivalue = atoi(valueA); - - if (freerdp_client_rdp_file_set_integer(file, nameA, ivalue, index) < 0) - ret = FALSE; - - free(nameA); - free(valueA); - return ret; -} - -static BOOL freerdp_client_parse_rdp_file_integer_ascii(rdpFile* file, const char* name, +static BOOL freerdp_client_parse_rdp_file_integer(rdpFile* file, const char* name, const char* value, int index) { - int ivalue = atoi(value); + long ivalue; + errno = 0; + ivalue = strtol(value, NULL, 0); + + if ((errno != 0) || (ivalue < INT32_MIN) || (ivalue > INT32_MAX)) + return FALSE; if (freerdp_client_rdp_file_set_integer(file, name, ivalue, index) < 0) return FALSE; @@ -319,6 +288,8 @@ static int freerdp_client_rdp_file_set_string(rdpFile* file, const char* name, c tmp = &file->ShellWorkingDirectory; else if (_stricmp(name, "gatewayhostname") == 0) tmp = &file->GatewayHostname; + else if (_stricmp(name, "gatewayaccesstoken") == 0) + tmp = &file->GatewayAccessToken; else if (_stricmp(name, "kdcproxyname") == 0) tmp = &file->KdcProxyName; else if (_stricmp(name, "drivestoredirect") == 0) @@ -327,6 +298,8 @@ static int freerdp_client_rdp_file_set_string(rdpFile* file, const char* name, c tmp = &file->DevicesToRedirect; else if (_stricmp(name, "winposstr") == 0) tmp = &file->WinPosStr; + else if (_stricmp(name, "pcb") == 0) + tmp = &file->PreconnectionBlob; else standard = 1; @@ -415,67 +388,7 @@ static int freerdp_client_parse_rdp_file_add_line(rdpFile* file, char* line, int return index; } -static BOOL freerdp_client_parse_rdp_file_add_line_unicode(rdpFile* file, const WCHAR* line, - int index) -{ - char* lineA = NULL; - BOOL ret = TRUE; - ConvertFromUnicode(CP_UTF8, 0, line, -1, &lineA, 0, NULL, NULL); - - if (!lineA) - return FALSE; - - if (freerdp_client_parse_rdp_file_add_line(file, lineA, index) == -1) - ret = FALSE; - - free(lineA); - return ret; -} - -static BOOL freerdp_client_parse_rdp_file_add_line_ascii(rdpFile* file, char* line, int index) -{ - if (freerdp_client_parse_rdp_file_add_line(file, line, index) == -1) - return FALSE; - - return TRUE; -} - -static BOOL freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, const WCHAR* name, - const WCHAR* value, int index) -{ - int length; - char* nameA; - char* valueA; - BOOL ret = TRUE; - length = (int) _wcslen(name); - nameA = (char*) malloc(length + 1); - - if (!nameA) - return FALSE; - - WideCharToMultiByte(CP_UTF8, 0, name, length, nameA, length, NULL, NULL); - nameA[length] = '\0'; - length = (int) _wcslen(value); - valueA = (char*) malloc(length + 1); - - if (!valueA) - { - free(nameA); - return FALSE; - } - - WideCharToMultiByte(CP_UTF8, 0, value, length, valueA, length, NULL, NULL); - valueA[length] = '\0'; - - if (freerdp_client_rdp_file_set_string(file, nameA, valueA, index) == -1) - ret = FALSE; - - free(nameA); - free(valueA); - return ret; -} - -static BOOL freerdp_client_parse_rdp_file_string_ascii(rdpFile* file, char* name, char* value, +static BOOL freerdp_client_parse_rdp_file_string(rdpFile* file, char* name, char* value, int index) { BOOL ret = TRUE; @@ -491,62 +404,63 @@ static BOOL freerdp_client_parse_rdp_file_string_ascii(rdpFile* file, char* name return ret; } -static BOOL freerdp_client_parse_rdp_file_option_unicode(rdpFile* file, const WCHAR* option, - int index) -{ - char* optionA = NULL; - BOOL ret; - ConvertFromUnicode(CP_UTF8, 0, option, -1, &optionA, 0, NULL, NULL); - - if (!optionA) - return FALSE; - - ret = freerdp_client_add_option(file, optionA); - free(optionA); - return ret; -} - -static BOOL freerdp_client_parse_rdp_file_option_ascii(rdpFile* file, char* option, int index) +static BOOL freerdp_client_parse_rdp_file_option(rdpFile* file, char* option, int index) { return freerdp_client_add_option(file, option); } -static BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE* buffer, +BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, const BYTE* buffer, size_t size) { BOOL rc = FALSE; int index; - int length; + size_t length; char* line; char* type; char* context; char* d1, *d2; char* beg; char* name, *value; - char* copy = calloc(1, size + sizeof(BYTE)); + char* copy = NULL; - if (!copy) + if (size < 2) return FALSE; - memcpy(copy, buffer, size); + if ((buffer[0] == BOM_UTF16_LE[0]) && (buffer[1] == BOM_UTF16_LE[1])) + { + size = size / 2 - 1; + + if (ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR)(&buffer[2]), size, ©, 0, NULL, NULL) < 0) + return FALSE; + } + else + { + copy = calloc(1, size + sizeof(BYTE)); + + if (!copy) + return FALSE; + + memcpy(copy, buffer, size); + } + index = 0; line = strtok_s(copy, "\r\n", &context); while (line) { - length = (int) strlen(line); + length = strnlen(line, size); if (length > 1) { beg = line; - if (!freerdp_client_parse_rdp_file_add_line_ascii(file, line, index)) - return FALSE; + if (freerdp_client_parse_rdp_file_add_line(file, line, index) == -1) + goto fail; if (beg[0] == '/') { - if (!freerdp_client_parse_rdp_file_option_ascii(file, line, index)) - return FALSE; + if (!freerdp_client_parse_rdp_file_option(file, line, index)) + goto fail; goto next_line; /* FreeRDP option */ } @@ -573,13 +487,13 @@ static BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE if (*type == 'i') { /* integer type */ - if (!freerdp_client_parse_rdp_file_integer_ascii(file, name, value, index)) + if (!freerdp_client_parse_rdp_file_integer(file, name, value, index)) goto fail; } else if (*type == 's') { /* string type */ - if (!freerdp_client_parse_rdp_file_string_ascii(file, name, value, index)) + if (!freerdp_client_parse_rdp_file_string(file, name, value, index)) goto fail; } else if (*type == 'b') @@ -599,118 +513,21 @@ fail: return rc; } -static BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BYTE* buffer, - size_t size) -{ - BOOL rc = FALSE; - int index; - int length; - const WCHAR* line; - WCHAR* type; - WCHAR* context; - WCHAR* d1, *d2; - const WCHAR* name, *value; - WCHAR* copy = (WCHAR*)calloc(1, size + sizeof(WCHAR)); - - if (!copy) - return FALSE; - - memcpy(copy, buffer, size); - index = 0; - line = wcstok_s(copy, CR_LF_STR_W, &context); - - while (line != NULL) - { - length = (int) _wcslen(line); - - if (length > 1) - { - const WCHAR* beg = line; - - if (!freerdp_client_parse_rdp_file_add_line_unicode(file, line, index)) - goto fail; - - if (beg[0] == '/') - { - /* FreeRDP option */ - freerdp_client_parse_rdp_file_option_unicode(file, line, index); - goto next_line; - } - - d1 = _wcschr(line, ':'); - - if (!d1) - goto next_line; /* not first delimiter */ - - type = &d1[1]; - d2 = _wcschr(type, ':'); - - if (!d2) - goto next_line; /* no second delimiter */ - - if ((d2 - d1) != 2) - goto next_line; /* improper type length */ - - *d1 = 0; - *d2 = 0; - name = beg; - value = &d2[1]; - - if (*type == 'i') - { - /* integer type */ - if (!freerdp_client_parse_rdp_file_integer_unicode(file, name, value, index)) - goto fail; - } - else if (*type == 's') - { - /* string type */ - if (!freerdp_client_parse_rdp_file_string_unicode(file, name, value, index)) - goto fail; - } - else if (*type == 'b') - { - /* binary type */ - } - } - - next_line: - line = wcstok_s(NULL, CR_LF_STR_W, &context); - index++; - } - - rc = TRUE; -fail: - free(copy); - return rc; -} - -BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, const BYTE* buffer, size_t size) -{ - if (size < 2) - return FALSE; - - if ((buffer[0] == BOM_UTF16_LE[0]) && (buffer[1] == BOM_UTF16_LE[1])) - return freerdp_client_parse_rdp_file_buffer_unicode(file, &buffer[2], size - 2); - - return freerdp_client_parse_rdp_file_buffer_ascii(file, buffer, size); -} - BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name) { BOOL status; BYTE* buffer; FILE* fp = NULL; size_t read_size; - long int file_size; + INT64 file_size; fp = fopen(name, "r"); if (!fp) return FALSE; - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); - fseek(fp, 0, SEEK_SET); + _fseeki64(fp, 0, SEEK_END); + file_size = _ftelli64(fp); + _fseeki64(fp, 0, SEEK_SET); if (file_size < 1) { @@ -785,6 +602,7 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSett } SETTING_MODIFIED_SET_STRING(file->GatewayHostname, settings, GatewayHostname); + SETTING_MODIFIED_SET_STRING(file->GatewayAccessToken, settings, GatewayAccessToken); SETTING_MODIFIED_SET(file->GatewayUsageMethod, settings, GatewayUsageMethod); SETTING_MODIFIED_SET(file->PromptCredentialOnce, settings, GatewayUseSameCredentials); SETTING_MODIFIED_SET(file->RemoteApplicationMode, settings, RemoteApplicationMode); @@ -796,6 +614,7 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSett SETTING_MODIFIED_SET_STRING(file->RemoteApplicationCmdLine, settings, RemoteApplicationCmdLine); SETTING_MODIFIED_SET(file->SpanMonitors, settings, SpanMonitors); SETTING_MODIFIED_SET(file->UseMultiMon, settings, UseMultimon); + SETTING_MODIFIED_SET_STRING(file->PreconnectionBlob, settings, PreconnectionBlob); return TRUE; } @@ -1080,6 +899,12 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* free(host); } + if (~((size_t) file->GatewayAccessToken)) + { + if (freerdp_set_param_string(settings, FreeRDP_GatewayAccessToken, file->GatewayAccessToken) != 0) + return FALSE; + } + if (~file->GatewayUsageMethod) freerdp_set_gateway_usage_method(settings, file->GatewayUsageMethod); @@ -1227,7 +1052,8 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* * Very similar to DevicesToRedirect, but can contain a * comma-separated list of drive letters to redirect. */ - freerdp_set_param_bool(settings, FreeRDP_RedirectDrives, TRUE); + const BOOL empty = !file->DrivesToRedirect || (strlen(file->DrivesToRedirect) == 0); + freerdp_set_param_bool(settings, FreeRDP_RedirectDrives, !empty); } if (~file->KeyboardHook) @@ -1235,6 +1061,13 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* freerdp_set_param_uint32(settings, FreeRDP_KeyboardHook, file->KeyboardHook); } + if (~((size_t) file->PreconnectionBlob)) + { + freerdp_set_param_string(settings, FreeRDP_PreconnectionBlob, file->PreconnectionBlob); + freerdp_set_param_bool(settings, FreeRDP_SendPreconnectionPdu, TRUE); + freerdp_set_param_bool(settings, FreeRDP_VmConnectMode, TRUE); + } + if (file->argc > 1) { char* ConnectionFile = settings->ConnectionFile; @@ -1500,6 +1333,7 @@ void freerdp_client_rdp_file_free(rdpFile* file) freerdp_client_file_string_check_free(file->AlternateShell); freerdp_client_file_string_check_free(file->ShellWorkingDirectory); freerdp_client_file_string_check_free(file->GatewayHostname); + freerdp_client_file_string_check_free(file->GatewayAccessToken); freerdp_client_file_string_check_free(file->KdcProxyName); freerdp_client_file_string_check_free(file->DrivesToRedirect); freerdp_client_file_string_check_free(file->DevicesToRedirect); diff --git a/client/common/test/TestClientCmdLine.c b/client/common/test/TestClientCmdLine.c index df8588a..5b1114f 100644 --- a/client/common/test/TestClientCmdLine.c +++ b/client/common/test/TestClientCmdLine.c @@ -4,31 +4,41 @@ #include <winpr/cmdline.h> #include <winpr/spec.h> -#define TESTCASE(cmd, expected_return) \ -{ \ - rdpSettings* settings = freerdp_settings_new(0); \ - status = freerdp_client_settings_parse_command_line(settings, ARRAYSIZE(cmd), cmd, FALSE); \ - freerdp_settings_free(settings); \ - if (status != expected_return) { \ - printf("Test argument %s failed\n", #cmd); \ - return -1; \ - } \ -} - -#define TESTCASE_SUCCESS(cmd) \ -{ \ - rdpSettings* settings = freerdp_settings_new(0); \ - status = freerdp_client_settings_parse_command_line(settings, ARRAYSIZE(cmd), cmd, FALSE); \ - freerdp_settings_free(settings); \ - if (status < 0) { \ - printf("Test argument %s failed\n", #cmd); \ - return -1; \ - } \ -} - -int TestClientCmdLine(int argc, char* argv[]) +#define TESTCASE(argv, ret_val) TESTCASE_impl(#argv, argv, ARRAYSIZE(argv), ret_val) +#define TESTCASE_SUCCESS(argv) TESTCASE_impl(#argv, argv, ARRAYSIZE(argv), 0) +static INLINE BOOL TESTCASE_impl(const char* name, char** argv, size_t argc, + int expected_return) { int status; + rdpSettings* settings = freerdp_settings_new(0); + printf("Running test %s\n", name); + + if (!settings) + { + fprintf(stderr, "Test %s could not allocate settings!\n", name); + return FALSE; + } + + status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE); + freerdp_settings_free(settings); + + if (status != expected_return) + { + fprintf(stderr, "Test %s failed!\n", name); + return FALSE; + } + + return TRUE; +} + +#if defined(_WIN32) +#define DRIVE_REDIRECT_PATH "c:\\Windows" +#else +#define DRIVE_REDIRECT_PATH "/tmp" +#endif +int TestClientCmdLine(int argc, char* argv[]) +{ + int rc = -1; char* cmd1[] = {"xfreerdp", "--help"}; char* cmd2[] = {"xfreerdp", "/help"}; char* cmd3[] = {"xfreerdp", "-help"}; @@ -39,8 +49,8 @@ int TestClientCmdLine(int argc, char* argv[]) char* cmd8[] = {"xfreerdp", "-v", "test.freerdp.com"}; char* cmd9[] = {"xfreerdp", "--v", "test.freerdp.com"}; char* cmd10[] = {"xfreerdp", "/v:test.freerdp.com"}; - char* cmd11[] = {"xfreerdp", "--plugin", "rdpsnd", "--plugin", "rdpdr", "--data", "disk:media:/tmp", "--", "test.freerdp.com" }; - char* cmd12[] = {"xfreerdp", "/sound", "/drive:media:/tmp", "/v:test.freerdp.com" }; + char* cmd11[] = {"xfreerdp", "--plugin", "rdpsnd", "--plugin", "rdpdr", "--data", "disk:media:"DRIVE_REDIRECT_PATH, "--", "test.freerdp.com" }; + char* cmd12[] = {"xfreerdp", "/sound", "/drive:media,"DRIVE_REDIRECT_PATH, "/v:test.freerdp.com" }; char* cmd13[] = {"xfreerdp", "-u", "test", "-p", "test", "test.freerdp.com"}; char* cmd14[] = {"xfreerdp", "-u", "test", "-p", "test", "-v", "test.freerdp.com"}; char* cmd15[] = {"xfreerdp", "/u:test", "/p:test", "/v:test.freerdp.com"}; @@ -48,60 +58,99 @@ int TestClientCmdLine(int argc, char* argv[]) char* cmd17[] = {"xfreerdp", "--invalid"}; char* cmd18[] = {"xfreerdp", "/kbd-list"}; char* cmd19[] = {"xfreerdp", "/monitor-list"}; + char* cmd20[] = {"xfreerdp", "/sound", "/drive:media:"DRIVE_REDIRECT_PATH, "/v:test.freerdp.com" }; + char* cmd21[] = {"xfreerdp", "/sound", "/drive:media,/foo/bar/blabla", "/v:test.freerdp.com" }; - TESTCASE(cmd1, COMMAND_LINE_STATUS_PRINT_HELP); + if (!TESTCASE(cmd1, COMMAND_LINE_STATUS_PRINT_HELP)) + goto fail; - TESTCASE(cmd2, COMMAND_LINE_STATUS_PRINT_HELP); + if (!TESTCASE(cmd2, COMMAND_LINE_STATUS_PRINT_HELP)) + goto fail; - TESTCASE(cmd3, COMMAND_LINE_STATUS_PRINT_HELP); + if (!TESTCASE(cmd3, COMMAND_LINE_STATUS_PRINT_HELP)) + goto fail; - TESTCASE(cmd4, COMMAND_LINE_STATUS_PRINT_VERSION); + if (!TESTCASE(cmd4, COMMAND_LINE_STATUS_PRINT_VERSION)) + goto fail; - TESTCASE(cmd5, COMMAND_LINE_STATUS_PRINT_VERSION); + if (!TESTCASE(cmd5, COMMAND_LINE_STATUS_PRINT_VERSION)) + goto fail; - TESTCASE(cmd6, COMMAND_LINE_STATUS_PRINT_VERSION); + if (!TESTCASE(cmd6, COMMAND_LINE_STATUS_PRINT_VERSION)) + goto fail; - TESTCASE_SUCCESS(cmd7); + if (!TESTCASE_SUCCESS(cmd7)) + goto fail; - TESTCASE_SUCCESS(cmd8); + if (!TESTCASE_SUCCESS(cmd8)) + goto fail; - TESTCASE_SUCCESS(cmd9); + if (!TESTCASE_SUCCESS(cmd9)) + goto fail; - TESTCASE_SUCCESS(cmd10); + if (!TESTCASE_SUCCESS(cmd10)) + goto fail; - TESTCASE_SUCCESS(cmd11); + if (!TESTCASE_SUCCESS(cmd11)) + goto fail; - TESTCASE_SUCCESS(cmd12); + if (!TESTCASE_SUCCESS(cmd12)) + goto fail; // password gets overwritten therefore it need to be writeable - cmd13[4] = calloc(5, sizeof(char)); - strncpy(cmd13[4], "test", 4); - TESTCASE_SUCCESS(cmd13); + cmd13[4] = _strdup("test"); + cmd14[4] = _strdup("test"); + cmd15[2] = _strdup("/p:test"); + + if (!cmd13[4] || !cmd14[4] || !cmd15[2]) + goto free_arg; + + if (!TESTCASE_SUCCESS(cmd13)) + goto free_arg; + + if (memcmp(cmd13[4], "****", 4) != 0) + goto free_arg; + + if (!TESTCASE_SUCCESS(cmd14)) + goto free_arg; + + if (memcmp(cmd14[4], "****", 4) != 0) + goto free_arg; + + if (!TESTCASE_SUCCESS(cmd15)) + goto free_arg; + + if (memcmp(cmd15[2], "/p:****", 7) != 0) + goto free_arg; + + if (!TESTCASE(cmd16, COMMAND_LINE_ERROR_NO_KEYWORD)) + goto free_arg; + + if (!TESTCASE(cmd17, COMMAND_LINE_ERROR_NO_KEYWORD)) + goto free_arg; + + if (!TESTCASE(cmd18, COMMAND_LINE_STATUS_PRINT)) + goto free_arg; + + if (!TESTCASE(cmd19, COMMAND_LINE_STATUS_PRINT)) + goto free_arg; + + if (!TESTCASE(cmd20, COMMAND_LINE_ERROR)) + goto free_arg; + + if (!TESTCASE(cmd21, COMMAND_LINE_ERROR)) + goto free_arg; + + rc = 0; +free_arg: free(cmd13[4]); - - cmd14[4] = calloc(5, sizeof(char)); - strncpy(cmd14[4], "test", 4); - TESTCASE_SUCCESS(cmd14); free(cmd14[4]); - - cmd15[2] = calloc(7, sizeof(char)); - strncpy(cmd15[2], "/p:test", 6); - TESTCASE_SUCCESS(cmd15); free(cmd15[2]); - - TESTCASE(cmd16, COMMAND_LINE_ERROR_NO_KEYWORD); - - TESTCASE(cmd17, COMMAND_LINE_ERROR_NO_KEYWORD); - - TESTCASE(cmd18, COMMAND_LINE_STATUS_PRINT); - - TESTCASE(cmd19, COMMAND_LINE_STATUS_PRINT); - #if 0 char* cmd20[] = {"-z --plugin cliprdr --plugin rdpsnd --data alsa latency:100 -- --plugin rdpdr --data disk:w7share:/home/w7share -- --plugin drdynvc --data tsmf:decoder:gstreamer -- -u test host.example.com"}; TESTCASE(cmd20, COMMAND_LINE_STATUS_PRINT); #endif - - return 0; +fail: + return rc; } diff --git a/cmake/AutoVersioning.cmake b/cmake/AutoVersioning.cmake deleted file mode 100644 index fe6e339..0000000 --- a/cmake/AutoVersioning.cmake +++ /dev/null @@ -1,55 +0,0 @@ -# - AutoVersioning -# Gather version from tarball or SCM -# -# This module defines the following variables: -# PRODUCT_VERSION - Version of product -# - -#============================================================================= -# Copyright 2011 O.S. Systems Software Ltda. -# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br> -# -# 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. -#============================================================================= - -if(EXISTS "${CMAKE_SOURCE_DIR}/.version" ) - file(READ ${CMAKE_SOURCE_DIR}/.version PRODUCT_VERSION) - - string(STRIP ${PRODUCT_VERSION} PRODUCT_VERSION) -else() - execute_process(COMMAND git describe --match "v[0-9]*" --abbrev=4 - OUTPUT_VARIABLE PRODUCT_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET) - - if(PRODUCT_VERSION) - string(REGEX REPLACE "^v(.*)" "\\1" PRODUCT_VERSION ${PRODUCT_VERSION}) - else() - # GIT is the default version - set(PRODUCT_VERSION GIT) - endif() - - # Check if has not commited changes - execute_process(COMMAND git update-index -q --refresh - ERROR_QUIET) - execute_process(COMMAND git diff-index --name-only HEAD -- - OUTPUT_VARIABLE CHANGED_SOURCE - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET) - - if(CHANGED_SOURCE) - set(PRODUCT_VERSION ${PRODUCT_VERSION}-dirty) - endif() -endif() - -message(STATUS "${CMAKE_PROJECT_NAME} ${PRODUCT_VERSION}") diff --git a/cmake/CheckCmakeCompat.cmake b/cmake/CheckCmakeCompat.cmake index 6b9f9cc..d616ad7 100644 --- a/cmake/CheckCmakeCompat.cmake +++ b/cmake/CheckCmakeCompat.cmake @@ -23,6 +23,7 @@ macro(enable_cmake_compat CMVERSION) endmacro() # Compatibility includes - order does matter! +enable_cmake_compat(3.7.0) enable_cmake_compat(2.8.11) enable_cmake_compat(2.8.6) enable_cmake_compat(2.8.3) diff --git a/cmake/ClangToolchain.cmake b/cmake/ClangToolchain.cmake new file mode 100644 index 0000000..d781bab --- /dev/null +++ b/cmake/ClangToolchain.cmake @@ -0,0 +1,16 @@ +if ($ENV{CLANG_VERSION}) + SET (CLANG_VERSION "-$ENV{CLANG_VERSION}") +endif() + +SET (CMAKE_C_COMPILER "/usr/bin/clang${CLANG_VERSION}" CACHE PATH "") +SET (CMAKE_C_FLAGS "-pedantic -Wall -std=gnu99" CACHE STRING "") +SET (CMAKE_C_FLAGS_DEBUG "-g" CACHE STRING "") +SET (CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING "") +SET (CMAKE_C_FLAGS_RELEASE "-O4 -DNDEBUG" CACHE STRING "") +SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "") + +SET (CMAKE_AR "/usr/bin/llvm-ar${CLANG_VERSION}" CACHE PATH "") +SET (CMAKE_LINKER "/usr/bin/llvm-link${CLANG_VERSION}" CACHE PATH "") +SET (CMAKE_NM "/usr/bin/llvm-nm${CLANG_VERSION}" CACHE PATH "") +SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump${CLANG_VERSION}" CACHE PATH "") +SET (CMAKE_RANLIB "/usr/bin/llvm-ranlib${CLANG_VERSION}" CACHE PATH "") diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake index 523ba3b..ce5b61c 100644 --- a/cmake/ConfigOptions.cmake +++ b/cmake/ConfigOptions.cmake @@ -42,9 +42,14 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif() if(NOT WIN32) - CMAKE_DEPENDENT_OPTION(WITH_VALGRIND_MEMCHECK "Compile with valgrind helpers." OFF "NOT WITH_SANITIZE_ADDRESS; NOT WITH_SANITIZE_LEAK" OFF) - CMAKE_DEPENDENT_OPTION(WITH_SANITIZE_ADDRESS "Compile with gcc/clang address sanitizer." OFF "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_LEAK" OFF) - CMAKE_DEPENDENT_OPTION(WITH_SANITIZE_LEAK "Compile with gcc/clang leak sanitizer." OFF "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_ADDRESS" OFF) + CMAKE_DEPENDENT_OPTION(WITH_VALGRIND_MEMCHECK "Compile with valgrind helpers." OFF + "NOT WITH_SANITIZE_ADDRESS; NOT WITH_SANITIZE_MEMORY; NOT WITH_SANITIZE_THREAD" OFF) + CMAKE_DEPENDENT_OPTION(WITH_SANITIZE_ADDRESS "Compile with gcc/clang address sanitizer." OFF + "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_MEMORY; NOT WITH_SANITIZE_THREAD" OFF) + CMAKE_DEPENDENT_OPTION(WITH_SANITIZE_MEMORY "Compile with gcc/clang memory sanitizer." OFF + "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_ADDRESS; NOT WITH_SANITIZE_THREAD" OFF) + CMAKE_DEPENDENT_OPTION(WITH_SANITIZE_THREAD "Compile with gcc/clang thread sanitizer." OFF + "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_ADDRESS; NOT WITH_SANITIZE_MEMORY" OFF) else() if(NOT UWP) option(WITH_MEDIA_FOUNDATION "Enable H264 media foundation decoder." ON) @@ -130,6 +135,9 @@ option(WITH_DEBUG_RINGBUFFER "Enable Ringbuffer debug messages" ${DEFAULT_DEBUG_ option(WITH_DEBUG_SYMBOLS "Pack debug symbols to installer" OFF) option(WITH_CCACHE "Use ccache support if available" ON) +option(WITH_ICU "Use ICU for unicode conversion" OFF) + +option(USE_VERSION_FROM_GIT_TAG "Extract FreeRDP version from git tag." OFF) if(ANDROID) include(ConfigOptionsAndroid) diff --git a/cmake/FindGSSAPI.cmake b/cmake/FindGSSAPI.cmake new file mode 100644 index 0000000..621238f --- /dev/null +++ b/cmake/FindGSSAPI.cmake @@ -0,0 +1,448 @@ +# - Try to find the GSS Kerberos libraries +# Once done this will define +# +# GSS_ROOT_DIR - Set this variable to the root installation of GSS +# GSS_ROOT_FLAVOUR - Set this variable to the flavour of Kerberos installation (MIT or Heimdal) +# +# Read-Only variables: +# GSS_FOUND - system has the Heimdal library +# GSS_FLAVOUR - "MIT" or "Heimdal" if anything found. +# GSS_INCLUDE_DIR - the Heimdal include directory +# GSS_LIBRARIES - The libraries needed to use GSS +# GSS_LINK_DIRECTORIES - Directories to add to linker search path +# GSS_LINKER_FLAGS - Additional linker flags +# GSS_COMPILER_FLAGS - Additional compiler flags +# GSS_VERSION - This is set to version advertised by pkg-config or read from manifest. +# In case the library is found but no version info availabe it'll be set to "unknown" + +set(_MIT_MODNAME mit-krb5-gssapi) +set(_HEIMDAL_MODNAME heimdal-gssapi) + +include(CheckIncludeFile) +include(CheckIncludeFiles) +include(CheckTypeSize) + +# export GSS_ROOT_FLAVOUR to use pkg-config system under UNIX +if(UNIX) + if(NOT "$ENV{GSS_ROOT_FLAVOUR} " STREQUAL " ") + string(REGEX MATCH "^[M|m]it$" MIT_FLAVOUR "$ENV{GSS_ROOT_FLAVOUR}") + if(NOT MIT_FLAVOUR) + string(REGEX MATCH "^MIT$" MIT_FLAVOUR "$ENV{GSS_ROOT_FLAVOUR}") + endif() + string(REGEX MATCH "^[H|h]eimdal$" HEIMDAL_FLAVOUR "$ENV{GSS_ROOT_FLAVOUR}") + if(NOT HEIMDAL_FLAVOUR) + string(REGEX MATCH "^HEIMDAL$" HEIMDAL_FLAVOUR "$ENV{GSS_ROOT_FLAVOUR}") + endif() + if(MIT_FLAVOUR) + set(GSS_FLAVOUR "MIT") + elseif(HEIMDAL_FLAVOUR) + set(GSS_FLAVOUR "Heimdal") + else() + message(SEND_ERROR "Kerberos flavour unknown ($ENV{GSS_ROOT_FLAVOUR}). Choose MIT or Heimdal.") + endif() + endif() +endif() + +set(_GSS_ROOT_HINTS + "${GSS_ROOT_DIR}" + "$ENV{GSS_ROOT_DIR}" +) + +# try to find library using system pkg-config if user did not specify root dir +if(UNIX) + if("$ENV{GSS_ROOT_DIR} " STREQUAL " ") + if(GSS_FLAVOUR) + find_package(PkgConfig QUIET) + if(GSS_FLAVOUR STREQUAL "MIT") + pkg_search_module(_GSS_PKG ${_MIT_MODNAME}) + else() + pkg_search_module(_GSS_PKG ${_HEIMDAL_MODNAME}) + endif() + + if("${_GSS_PKG_PREFIX} " STREQUAL " ") + if(NOT "$ENV{PKG_CONFIG_PATH} " STREQUAL " ") + list(APPEND _GSS_ROOT_HINTS "$ENV{PKG_CONFIG_PATH}") + else() + message(SEND_ERROR "pkg_search_module failed : try to set PKG_CONFIG_PATH to PREFIX_OF_KERBEROS/lib/pkgconfig") + endif() + else() + if($ENV{GSS_ROOT_FLAVOUR} STREQUAL "Heimdal") + string(FIND "${_GSS_PKG_PREFIX}" "heimdal" PKG_HEIMDAL_PREFIX_POSITION) + if(PKG_HEIMDAL_PREFIX_POSITION STREQUAL "-1") + message(WARNING "Try to set PKG_CONFIG_PATH to \"PREFIX_OF_KERBEROS/lib/pkgconfig\"") + else() + list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}") + endif() + else() + list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}") + endif() + endif() + else() + message(WARNING "export GSS_ROOT_FLAVOUR to use pkg-config") + endif() + endif() +elseif(WIN32) + list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]") +endif() + +if(NOT GSS_FOUND) # not found by pkg-config. Let's take more traditional approach. + find_file(_GSS_CONFIGURE_SCRIPT + NAMES + "krb5-config" + HINTS + ${_GSS_ROOT_HINTS} + PATH_SUFFIXES + bin + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + ) + + # if not found in user-supplied directories, maybe system knows better + find_file(_GSS_CONFIGURE_SCRIPT + NAMES + "krb5-config" + PATH_SUFFIXES + bin + ) + + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor" + OUTPUT_VARIABLE _GSS_VENDOR + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + + if(NOT _GSS_CONFIGURE_FAILED) + string(STRIP "${_GSS_VENDOR}" _GSS_VENDOR) + if((GSS_FLAVOUR STREQUAL "Heimdal" AND NOT _GSS_VENDOR STREQUAL "Heimdal") + OR (GSS_FLAVOUR STREQUAL "MIT" AND NOT _GSS_VENDOR STREQUAL "Massachusetts Institute of Technology")) + message(SEND_ERROR "GSS vendor and GSS flavour are not matching : _GSS_VENDOR=${_GSS_VENDOR} ; GSS_FLAVOUR=${GSS_FLAVOUR}") + message(STATUS "Try to set the path to GSS root folder in the system variable GSS_ROOT_DIR") + endif() + else() + message(SEND_ERROR "GSS configure script failed to get vendor") + endif() + + # NOTE: fail to link Heimdal libraries using configure script due to limitations + # during Heimdal linking process. Then, we do it "manually". + if(NOT "${_GSS_CONFIGURE_SCRIPT} " STREQUAL " " AND GSS_FLAVOUR AND NOT _GSS_VENDOR STREQUAL "Heimdal") + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi" + OUTPUT_VARIABLE _GSS_CFLAGS + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + + if(NOT _GSS_CONFIGURE_FAILED) # 0 means success + # should also work in an odd case when multiple directories are given + string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS) + string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}") + string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}") + + foreach(_flag ${_GSS_CFLAGS}) + if(_flag MATCHES "^-I.*") + string(REGEX REPLACE "^-I" "" _val "${_flag}") + list(APPEND _GSS_INCLUDE_DIR "${_val}") + else() + list(APPEND _GSS_COMPILER_FLAGS "${_flag}") + endif() + endforeach() + endif() + + if(_GSS_VENDOR STREQUAL "Massachusetts Institute of Technology") + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi" + OUTPUT_VARIABLE _GSS_LIB_FLAGS + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + elseif(_GSS_VENDOR STREQUAL "Heimdal") + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--deps --libs" "gssapi kafs" + OUTPUT_VARIABLE _GSS_LIB_FLAGS + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + else() + message(SEND_ERROR "Unknown vendor") + endif() + + if(NOT _GSS_CONFIGURE_FAILED) # 0 means success + # this script gives us libraries and link directories. We have to deal with it. + string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS) + string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}") + string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}") + + foreach(_flag ${_GSS_LIB_FLAGS}) + if(_flag MATCHES "^-l.*") + string(REGEX REPLACE "^-l" "" _val "${_flag}") + list(APPEND _GSS_LIBRARIES "${_val}") + elseif(_flag MATCHES "^-L.*") + string(REGEX REPLACE "^-L" "" _val "${_flag}") + list(APPEND _GSS_LINK_DIRECTORIES "${_val}") + else() + list(APPEND _GSS_LINKER_FLAGS "${_flag}") + endif() + endforeach() + + endif() + + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version" + OUTPUT_VARIABLE _GSS_VERSION + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + + # older versions may not have the "--version" parameter. In this case we just don't care. + if(_GSS_CONFIGURE_FAILED) + set(_GSS_VERSION 0) + endif() + + else() # either there is no config script or we are on platform that doesn't provide one (Windows?) + if(_GSS_VENDOR STREQUAL "Massachusetts Institute of Technology") + find_path(_GSS_INCLUDE_DIR + NAMES + "gssapi/gssapi_generic.h" + HINTS + ${_GSS_ROOT_HINTS} + PATH_SUFFIXES + include + inc + ) + + if(_GSS_INCLUDE_DIR) # we've found something + set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}") + check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_ext.h" _GSS_HAVE_MIT_HEADERS) + if(_GSS_HAVE_MIT_HEADERS) + set(GSS_FLAVOUR "MIT") + else() + message(SEND_ERROR "Try to set the Kerberos flavour (GSS_ROOT_FLAVOUR)") + endif() + elseif("$ENV{PKG_CONFIG_PATH} " STREQUAL " ") + message(WARNING "Try to set PKG_CONFIG_PATH to PREFIX_OF_KERBEROS/lib/pkgconfig") + endif() + elseif(_GSS_VENDOR STREQUAL "Heimdal") + find_path(_GSS_INCLUDE_DIR + NAMES + "gssapi/gssapi_spnego.h" + HINTS + ${_GSS_ROOT_HINTS} + PATHS + /usr/heimdal + /usr/local/heimdal + PATH_SUFFIXES + include + inc + ) + + if(_GSS_INCLUDE_DIR) # we've found something + set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}") + # prevent compiling the header - just check if we can include it + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__") + check_include_file( "roken.h" _GSS_HAVE_ROKEN_H) + check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H) + if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H) + set(GSS_FLAVOUR "Heimdal") + endif() + set(CMAKE_REQUIRED_DEFINITIONS "") + elseif("$ENV{PKG_CONFIG_PATH} " STREQUAL " ") + message(WARNING "Try to set PKG_CONFIG_PATH to PREFIX_OF_KERBEROS/lib/pkgconfig") + endif() + else() + message(SEND_ERROR "Kerberos vendor unknown (${_GSS_VENDOR})") + endif() + + # if we have headers, check if we can link libraries + if(GSS_FLAVOUR) + set(_GSS_LIBDIR_SUFFIXES "") + set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS}) + get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH) + list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT}) + + if(WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64") + if(GSS_FLAVOUR STREQUAL "MIT") + set(_GSS_LIBNAME "gssapi64") + else() + set(_GSS_LIBNAME "libgssapi") + endif() + else() + list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386") + if(GSS_FLAVOUR STREQUAL "MIT") + set(_GSS_LIBNAME "gssapi32") + else() + set(_GSS_LIBNAME "libgssapi") + endif() + endif() + else() + list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64;x86_64-linux-gnu") # those suffixes are not checked for HINTS + if(GSS_FLAVOUR STREQUAL "MIT") + set(_GSS_LIBNAME "gssapi_krb5") + set(_KRB5_LIBNAME "krb5") + set(_COMERR_LIBNAME "com_err") + set(_KRB5SUPPORT_LIBNAME "krb5support") + else() + set(_GSS_LIBNAME "gssapi") + set(_KRB5_LIBNAME "krb5") + set(_KAFS_LIBNAME "kafs") + set(_ROKEN_LIBNAME "roken") + endif() + endif() + + find_library(_GSS_LIBRARIES + NAMES + ${_GSS_LIBNAME} + HINTS + ${_GSS_LIBDIR_HINTS} + PATH_SUFFIXES + ${_GSS_LIBDIR_SUFFIXES} + ) + + if(GSS_FLAVOUR STREQUAL "MIT") + find_library(_KRB5_LIBRARY + NAMES + ${_KRB5_LIBNAME} + HINTS + ${_GSS_LIBDIR_HINTS} + PATH_SUFFIXES + ${_GSS_LIBDIR_SUFFIXES} + ) + find_library(_COMERR_LIBRARY + NAMES + ${_COMERR_LIBNAME} + HINTS + ${_GSS_LIBDIR_HINTS} + PATH_SUFFIXES + ${_GSS_LIBDIR_SUFFIXES} + ) + find_library(_KRB5SUPPORT_LIBRARY + NAMES + ${_KRB5SUPPORT_LIBNAME} + HINTS + ${_GSS_LIBDIR_HINTS} + PATH_SUFFIXES + ${_GSS_LIBDIR_SUFFIXES} + ) + list(APPEND _GSS_LIBRARIES ${_KRB5_LIBRARY} ${_KRB5SUPPORT_LIBRARY} ${_COMERR_LIBRARY}) + endif() + + if(GSS_FLAVOUR STREQUAL "Heimdal") + find_library(_KRB5_LIBRARY + NAMES + ${_KRB5_LIBNAME} + HINTS + ${_GSS_LIBDIR_HINTS} + PATH_SUFFIXES + ${_GSS_LIBDIR_SUFFIXES} + ) + find_library(_KAFS_LIBRARY + NAMES + ${_KAFS_LIBNAME} + HINTS + ${_GSS_LIBDIR_HINTS} + PATH_SUFFIXES + ${_GSS_LIBDIR_SUFFIXES} + ) + find_library(_ROKEN_LIBRARY + NAMES + ${_ROKEN_LIBNAME} + HINTS + ${_GSS_LIBDIR_HINTS} + PATH_SUFFIXES + ${_GSS_LIBDIR_SUFFIXES} + ) + list(APPEND _GSS_LIBRARIES ${_KRB5_LIBRARY} ${_KAFS_LIBRARY} ${_ROKEN_LIBRARY}) + endif() + endif() + + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version" + OUTPUT_VARIABLE _GSS_VERSION + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + + # older versions may not have the "--version" parameter. In this case we just don't care. + if(_GSS_CONFIGURE_FAILED) + set(_GSS_VERSION 0) + endif() + + endif() +else() + if(_GSS_PKG_${_MIT_MODNAME}_VERSION) + set(GSS_FLAVOUR "MIT") + set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION) + else() + set(GSS_FLAVOUR "Heimdal") + set(_GSS_VERSION _GSS_PKG_${_HEIMDAL_MODNAME}_VERSION) + endif() +endif() + +set(GSS_INCLUDE_DIR ${_GSS_INCLUDE_DIR}) +set(GSS_LIBRARIES ${_GSS_LIBRARIES}) +set(GSS_LINK_DIRECTORIES ${_GSS_LINK_DIRECTORIES}) +set(GSS_LINKER_FLAGS ${_GSS_LINKER_FLAGS}) +set(GSS_COMPILER_FLAGS ${_GSS_COMPILER_FLAGS}) +set(GSS_VERSION ${_GSS_VERSION}) + +if(GSS_FLAVOUR) + if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest") + else() + set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest") + endif() + if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}") + file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str + REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$") + + string(REGEX MATCH "[0-9]\\.[^\"]+" + GSS_VERSION "${heimdal_version_str}") + endif() + if(NOT GSS_VERSION) + set(GSS_VERSION "Heimdal Unknown") + endif() + elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT") + get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE) + if(WIN32 AND _MIT_VERSION) + set(GSS_VERSION "${_MIT_VERSION}") + else() + set(GSS_VERSION "MIT Unknown") + endif() + endif() +endif() + +include(FindPackageHandleStandardArgs) + +set(_GSS_REQUIRED_VARS GSS_LIBRARIES GSS_FLAVOUR) + +find_package_handle_standard_args(GSS + REQUIRED_VARS + ${_GSS_REQUIRED_VARS} + VERSION_VAR + GSS_VERSION + FAIL_MESSAGE + "Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR" +) + +if(GSS_FLAVOUR STREQUAL "MIT") + string(STRIP "${GSS_VERSION}" GSS_VERSION) + string(SUBSTRING ${GSS_VERSION} 19 -1 GSS_RELEASE_NUMBER) + string(REGEX MATCH "([0-9]+)\\." GSS_VERSION_MAJOR ${GSS_RELEASE_NUMBER}) + string(REGEX REPLACE "\\." "" GSS_VERSION_MAJOR "${GSS_VERSION_MAJOR}") + string(REGEX MATCH "\\.([0-9]+)$" GSS_VERSION_MINOR ${GSS_RELEASE_NUMBER}) + if(NOT GSS_VERSION_MINOR) + string(REGEX MATCH "\\.([0-9]+)\\." GSS_VERSION_MINOR ${GSS_RELEASE_NUMBER}) + string(REGEX REPLACE "\\." "" GSS_VERSION_MINOR "${GSS_VERSION_MINOR}") + string(REGEX REPLACE "\\." "" GSS_VERSION_MINOR "${GSS_VERSION_MINOR}") + string(REGEX MATCH "([0-9]+)$" GSS_VERSION_PATCH ${GSS_RELEASE_NUMBER}) + string(REGEX REPLACE "\\." "" GSS_VERSION_PATCH "${GSS_VERSION_PATCH}") + else() + string(REGEX REPLACE "\\." "" GSS_VERSION_MINOR "${GSS_VERSION_MINOR}") + set(GSS_VERSION_PATCH "0") + endif() + if(GSS_VERSION_MAJOR AND GSS_VERSION_MINOR) + string(COMPARE GREATER ${GSS_VERSION_MAJOR} 0 GSS_VERSION_1) + string(COMPARE GREATER ${GSS_VERSION_MINOR} 12 GSS_VERSION_1_13) + else() + message(SEND_ERROR "Failed to retrieved Kerberos version number") + endif() +endif() + +mark_as_advanced(GSS_INCLUDE_DIR GSS_LIBRARIES) diff --git a/cmake/FindGStreamer_1_0.cmake b/cmake/FindGStreamer_1_0.cmake index 3aa8fc6..6fbc0ec 100644 --- a/cmake/FindGStreamer_1_0.cmake +++ b/cmake/FindGStreamer_1_0.cmake @@ -59,7 +59,7 @@ macro(FIND_GSTREAMER_COMPONENT _component_prefix _pkgconfig_name _library) string(REGEX MATCH "(.*)>=(.*)" _dummy "${_pkgconfig_name}") if ("${CMAKE_MATCH_2}" STREQUAL "") - pkg_check_modules(PC_${_component_prefix} "${_pkgconfig_name} >= ${GStreamer_FIND_VERSION}") + pkg_check_modules(PC_${_component_prefix} "${_pkgconfig_name} >= ${GSTREAMER_1_0_MINIMUM_VERSION}") else () pkg_check_modules(PC_${_component_prefix} ${_pkgconfig_name}) endif () diff --git a/cmake/FindKRB5.cmake b/cmake/FindKRB5.cmake deleted file mode 100644 index 477f50e..0000000 --- a/cmake/FindKRB5.cmake +++ /dev/null @@ -1,28 +0,0 @@ -# - Try to find krb5 -# Once done this will define -# KRB5_FOUND - pcsc was found -# KRB5_INCLUDE_DIRS - pcsc include directories -# KRB5_LIBRARIES - libraries needed for linking - -include(FindPkgConfig) - -if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_KRB5 QUIET libkrb5) -endif() - -find_path(KRB5_INCLUDE_DIR krb5.h - HINTS ${PC_KRB5_INCLUDEDIR} ${PC_KRB5_INCLUDE_DIRS} - PATH_SUFFIXES KRB5) - -find_library(KRB5_LIBRARY NAMES krb5 - HINTS ${PC_KRB5_LIBDIR} ${PC_KRB5_LIBRARY_DIRS}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(KRB5 DEFAULT_MSG KRB5_LIBRARY KRB5_INCLUDE_DIR) - -set(KRB5_LIBRARIES ${KRB5_LIBRARY}) -set(KRB5_INCLUDE_DIRS ${KRB5_INCLUDE_DIR}) - -mark_as_advanced(KRB5_INCLUDE_DIR KRB5_LIBRARY) - - diff --git a/cmake/FindOpenSSL.cmake b/cmake/FindOpenSSL.cmake index d45657b..ec07605 100644 --- a/cmake/FindOpenSSL.cmake +++ b/cmake/FindOpenSSL.cmake @@ -107,6 +107,7 @@ ELSEIF(WIN32 AND NOT CYGWIN) NAMES "libeay32${MSVC_RUNTIME_SUFFIX}d" libeay32 + libcrypto ${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES ${MSVC_RUNTIME_PATH_SUFFIX} @@ -119,6 +120,7 @@ ELSEIF(WIN32 AND NOT CYGWIN) NAMES "libeay32${MSVC_RUNTIME_SUFFIX}" libeay32 + libcrypto ${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES ${MSVC_RUNTIME_PATH_SUFFIX} @@ -132,6 +134,7 @@ ELSEIF(WIN32 AND NOT CYGWIN) "ssleay32${MSVC_RUNTIME_SUFFIX}d" ssleay32 ssl + libssl ${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES ${MSVC_RUNTIME_PATH_SUFFIX} @@ -145,6 +148,7 @@ ELSEIF(WIN32 AND NOT CYGWIN) "ssleay32${MSVC_RUNTIME_SUFFIX}" ssleay32 ssl + libssl ${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES ${MSVC_RUNTIME_PATH_SUFFIX} @@ -164,6 +168,7 @@ ELSEIF(WIN32 AND NOT CYGWIN) FIND_LIBRARY(LIB_EAY NAMES libeay32 + libcrypto ${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" @@ -173,6 +178,7 @@ ELSEIF(WIN32 AND NOT CYGWIN) FIND_LIBRARY(SSL_EAY NAMES ssleay32 + libssl ${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" @@ -186,6 +192,7 @@ ELSEIF(WIN32 AND NOT CYGWIN) FIND_LIBRARY(LIB_EAY NAMES libeay32 + libcrypto HINTS ${_OPENSSL_LIBDIR} ${_OPENSSL_ROOT_HINTS_AND_PATHS} @@ -196,6 +203,7 @@ ELSEIF(WIN32 AND NOT CYGWIN) FIND_LIBRARY(SSL_EAY NAMES ssleay32 + libssl HINTS ${_OPENSSL_LIBDIR} ${_OPENSSL_ROOT_HINTS_AND_PATHS} diff --git a/cmake/compat_3.7.0/FindICU.cmake b/cmake/compat_3.7.0/FindICU.cmake new file mode 100644 index 0000000..82b557b --- /dev/null +++ b/cmake/compat_3.7.0/FindICU.cmake @@ -0,0 +1,349 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindICU +# ------- +# +# Find the International Components for Unicode (ICU) libraries and +# programs. +# +# This module supports multiple components. +# Components can include any of: ``data``, ``i18n``, ``io``, ``le``, +# ``lx``, ``test``, ``tu`` and ``uc``. +# +# Note that on Windows ``data`` is named ``dt`` and ``i18n`` is named +# ``in``; any of the names may be used, and the appropriate +# platform-specific library name will be automatically selected. +# +# This module reports information about the ICU installation in +# several variables. General variables:: +# +# ICU_VERSION - ICU release version +# ICU_FOUND - true if the main programs and libraries were found +# ICU_LIBRARIES - component libraries to be linked +# ICU_INCLUDE_DIRS - the directories containing the ICU headers +# +# Imported targets:: +# +# ICU::<C> +# +# Where ``<C>`` is the name of an ICU component, for example +# ``ICU::i18n``. +# +# ICU programs are reported in:: +# +# ICU_GENCNVAL_EXECUTABLE - path to gencnval executable +# ICU_ICUINFO_EXECUTABLE - path to icuinfo executable +# ICU_GENBRK_EXECUTABLE - path to genbrk executable +# ICU_ICU-CONFIG_EXECUTABLE - path to icu-config executable +# ICU_GENRB_EXECUTABLE - path to genrb executable +# ICU_GENDICT_EXECUTABLE - path to gendict executable +# ICU_DERB_EXECUTABLE - path to derb executable +# ICU_PKGDATA_EXECUTABLE - path to pkgdata executable +# ICU_UCONV_EXECUTABLE - path to uconv executable +# ICU_GENCFU_EXECUTABLE - path to gencfu executable +# ICU_MAKECONV_EXECUTABLE - path to makeconv executable +# ICU_GENNORM2_EXECUTABLE - path to gennorm2 executable +# ICU_GENCCODE_EXECUTABLE - path to genccode executable +# ICU_GENSPREP_EXECUTABLE - path to gensprep executable +# ICU_ICUPKG_EXECUTABLE - path to icupkg executable +# ICU_GENCMN_EXECUTABLE - path to gencmn executable +# +# ICU component libraries are reported in:: +# +# ICU_<C>_FOUND - ON if component was found +# ICU_<C>_LIBRARIES - libraries for component +# +# Note that ``<C>`` is the uppercased name of the component. +# +# This module reads hints about search results from:: +# +# ICU_ROOT - the root of the ICU installation +# +# The environment variable ``ICU_ROOT`` may also be used; the +# ICU_ROOT variable takes precedence. +# +# The following cache variables may also be set:: +# +# ICU_<P>_EXECUTABLE - the path to executable <P> +# ICU_INCLUDE_DIR - the directory containing the ICU headers +# ICU_<C>_LIBRARY - the library for component <C> +# +# .. note:: +# +# In most cases none of the above variables will require setting, +# unless multiple ICU versions are available and a specific version +# is required. +# +# Other variables one may set to control this module are:: +# +# ICU_DEBUG - Set to ON to enable debug output from FindICU. + +# Written by Roger Leigh <rleigh@codelibre.net> + +set(icu_programs + gencnval + icuinfo + genbrk + icu-config + genrb + gendict + derb + pkgdata + uconv + gencfu + makeconv + gennorm2 + genccode + gensprep + icupkg + gencmn) + +# The ICU checks are contained in a function due to the large number +# of temporary variables needed. +function(_ICU_FIND) + # Set up search paths, taking compiler into account. Search ICU_ROOT, + # with ICU_ROOT in the environment as a fallback if unset. + if(ICU_ROOT) + list(APPEND icu_roots "${ICU_ROOT}") + else() + if(NOT "$ENV{ICU_ROOT}" STREQUAL "") + file(TO_CMAKE_PATH "$ENV{ICU_ROOT}" NATIVE_PATH) + list(APPEND icu_roots "${NATIVE_PATH}") + set(ICU_ROOT "${NATIVE_PATH}" + CACHE PATH "Location of the ICU installation" FORCE) + endif() + endif() + + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + # 64-bit binary directory + set(_bin64 "bin64") + # 64-bit library directory + set(_lib64 "lib64") + endif() + + # Generic 64-bit and 32-bit directories + list(APPEND icu_binary_suffixes "${_bin64}" "bin") + list(APPEND icu_library_suffixes "${_lib64}" "lib") + + # Find all ICU programs + foreach(program ${icu_programs}) + string(TOUPPER "${program}" program_upcase) + set(cache_var "ICU_${program_upcase}_EXECUTABLE") + set(program_var "ICU_${program_upcase}_EXECUTABLE") + find_program("${cache_var}" "${program}" + HINTS ${icu_roots} + PATH_SUFFIXES ${icu_binary_suffixes} + DOC "ICU ${program} executable") + mark_as_advanced(cache_var) + set("${program_var}" "${${cache_var}}" PARENT_SCOPE) + endforeach() + + # Find include directory + find_path(ICU_INCLUDE_DIR + NAMES "unicode/utypes.h" + HINTS ${icu_roots} + PATH_SUFFIXES ${icu_include_suffixes} + DOC "ICU include directory") + set(ICU_INCLUDE_DIR "${ICU_INCLUDE_DIR}" PARENT_SCOPE) + + # Get version + if(ICU_INCLUDE_DIR AND EXISTS "${ICU_INCLUDE_DIR}/unicode/uvernum.h") + file(STRINGS "${ICU_INCLUDE_DIR}/unicode/uvernum.h" icu_header_str + REGEX "^#define[\t ]+U_ICU_VERSION[\t ]+\".*\".*") + + string(REGEX REPLACE "^#define[\t ]+U_ICU_VERSION[\t ]+\"([^ \\n]*)\".*" + "\\1" icu_version_string "${icu_header_str}") + set(ICU_VERSION "${icu_version_string}" PARENT_SCOPE) + unset(icu_header_str) + unset(icu_version_string) + endif() + + # Find all ICU libraries + set(ICU_REQUIRED_LIBS_FOUND ON) + foreach(component ${ICU_FIND_COMPONENTS}) + string(TOUPPER "${component}" component_upcase) + set(component_cache "ICU_${component_upcase}_LIBRARY") + set(component_cache_release "${component_cache}_RELEASE") + set(component_cache_debug "${component_cache}_DEBUG") + set(component_found "${component_upcase}_FOUND") + set(component_libnames "icu${component}") + set(component_debug_libnames "icu${component}d") + + # Special case deliberate library naming mismatches between Unix + # and Windows builds + unset(component_libnames) + unset(component_debug_libnames) + list(APPEND component_libnames "icu${component}") + list(APPEND component_debug_libnames "icu${component}d") + if(component STREQUAL "data") + list(APPEND component_libnames "icudt") + # Note there is no debug variant at present + list(APPEND component_debug_libnames "icudtd") + endif() + if(component STREQUAL "dt") + list(APPEND component_libnames "icudata") + # Note there is no debug variant at present + list(APPEND component_debug_libnames "icudatad") + endif() + if(component STREQUAL "i18n") + list(APPEND component_libnames "icuin") + list(APPEND component_debug_libnames "icuind") + endif() + if(component STREQUAL "in") + list(APPEND component_libnames "icui18n") + list(APPEND component_debug_libnames "icui18nd") + endif() + + find_library("${component_cache_release}" ${component_libnames} + HINTS ${icu_roots} + PATH_SUFFIXES ${icu_library_suffixes} + DOC "ICU ${component} library (release)") + find_library("${component_cache_debug}" ${component_debug_libnames} + HINTS ${icu_roots} + PATH_SUFFIXES ${icu_library_suffixes} + DOC "ICU ${component} library (debug)") + include(SelectLibraryConfigurations) + select_library_configurations(ICU_${component_upcase}) + mark_as_advanced("${component_cache_release}" "${component_cache_debug}") + if(${component_cache}) + set("${component_found}" ON) + list(APPEND ICU_LIBRARY "${${component_cache}}") + endif() + mark_as_advanced("${component_found}") + set("${component_cache}" "${${component_cache}}" PARENT_SCOPE) + set("${component_found}" "${${component_found}}" PARENT_SCOPE) + if(${component_found}) + if (ICU_FIND_REQUIRED_${component}) + list(APPEND ICU_LIBS_FOUND "${component} (required)") + else() + list(APPEND ICU_LIBS_FOUND "${component} (optional)") + endif() + else() + if (ICU_FIND_REQUIRED_${component}) + set(ICU_REQUIRED_LIBS_FOUND OFF) + list(APPEND ICU_LIBS_NOTFOUND "${component} (required)") + else() + list(APPEND ICU_LIBS_NOTFOUND "${component} (optional)") + endif() + endif() + endforeach() + set(_ICU_REQUIRED_LIBS_FOUND "${ICU_REQUIRED_LIBS_FOUND}" PARENT_SCOPE) + set(ICU_LIBRARY "${ICU_LIBRARY}" PARENT_SCOPE) + + if(NOT ICU_FIND_QUIETLY) + if(ICU_LIBS_FOUND) + message(STATUS "Found the following ICU libraries:") + foreach(found ${ICU_LIBS_FOUND}) + message(STATUS " ${found}") + endforeach() + endif() + if(ICU_LIBS_NOTFOUND) + message(STATUS "The following ICU libraries were not found:") + foreach(notfound ${ICU_LIBS_NOTFOUND}) + message(STATUS " ${notfound}") + endforeach() + endif() + endif() + + if(ICU_DEBUG) + message(STATUS "--------FindICU.cmake search debug--------") + message(STATUS "ICU binary path search order: ${icu_roots}") + message(STATUS "ICU include path search order: ${icu_roots}") + message(STATUS "ICU library path search order: ${icu_roots}") + message(STATUS "----------------") + endif() +endfunction() + +_ICU_FIND() + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(ICU + FOUND_VAR ICU_FOUND + REQUIRED_VARS ICU_INCLUDE_DIR + ICU_LIBRARY + _ICU_REQUIRED_LIBS_FOUND + VERSION_VAR ICU_VERSION + FAIL_MESSAGE "Failed to find all ICU components") + +unset(_ICU_REQUIRED_LIBS_FOUND) + +if(ICU_FOUND) + set(ICU_INCLUDE_DIRS "${ICU_INCLUDE_DIR}") + set(ICU_LIBRARIES "${ICU_LIBRARY}") + foreach(_ICU_component ${ICU_FIND_COMPONENTS}) + string(TOUPPER "${_ICU_component}" _ICU_component_upcase) + set(_ICU_component_cache "ICU_${_ICU_component_upcase}_LIBRARY") + set(_ICU_component_cache_release "ICU_${_ICU_component_upcase}_LIBRARY_RELEASE") + set(_ICU_component_cache_debug "ICU_${_ICU_component_upcase}_LIBRARY_DEBUG") + set(_ICU_component_lib "ICU_${_ICU_component_upcase}_LIBRARIES") + set(_ICU_component_found "${_ICU_component_upcase}_FOUND") + set(_ICU_imported_target "ICU::${_ICU_component}") + if(${_ICU_component_found}) + set("${_ICU_component_lib}" "${${_ICU_component_cache}}") + if(NOT TARGET ${_ICU_imported_target}) + add_library(${_ICU_imported_target} UNKNOWN IMPORTED) + if(ICU_INCLUDE_DIR) + set_target_properties(${_ICU_imported_target} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${ICU_INCLUDE_DIR}") + endif() + if(EXISTS "${${_ICU_component_cache}}") + set_target_properties(${_ICU_imported_target} PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" + IMPORTED_LOCATION "${${_ICU_component_cache}}") + endif() + if(EXISTS "${${_ICU_component_cache_release}}") + set_property(TARGET ${_ICU_imported_target} APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(${_ICU_imported_target} PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX" + IMPORTED_LOCATION_RELEASE "${${_ICU_component_cache_release}}") + endif() + if(EXISTS "${${_ICU_component_cache_debug}}") + set_property(TARGET ${_ICU_imported_target} APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(${_ICU_imported_target} PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX" + IMPORTED_LOCATION_DEBUG "${${_ICU_component_cache_debug}}") + endif() + endif() + endif() + unset(_ICU_component_upcase) + unset(_ICU_component_cache) + unset(_ICU_component_lib) + unset(_ICU_component_found) + unset(_ICU_imported_target) + endforeach() +endif() + +if(ICU_DEBUG) + message(STATUS "--------FindICU.cmake results debug--------") + message(STATUS "ICU found: ${ICU_FOUND}") + message(STATUS "ICU_VERSION number: ${ICU_VERSION}") + message(STATUS "ICU_ROOT directory: ${ICU_ROOT}") + message(STATUS "ICU_INCLUDE_DIR directory: ${ICU_INCLUDE_DIR}") + message(STATUS "ICU_LIBRARIES: ${ICU_LIBRARIES}") + + foreach(program IN LISTS icu_programs) + string(TOUPPER "${program}" program_upcase) + set(program_lib "ICU_${program_upcase}_EXECUTABLE") + message(STATUS "${program} program: ${${program_lib}}") + unset(program_upcase) + unset(program_lib) + endforeach() + + foreach(component IN LISTS ICU_FIND_COMPONENTS) + string(TOUPPER "${component}" component_upcase) + set(component_lib "ICU_${component_upcase}_LIBRARIES") + set(component_found "${component_upcase}_FOUND") + message(STATUS "${component} library found: ${${component_found}}") + message(STATUS "${component} library: ${${component_lib}}") + unset(component_upcase) + unset(component_lib) + unset(component_found) + endforeach() + message(STATUS "----------------") +endif() + +unset(icu_programs) diff --git a/config.h.in b/config.h.in index b634b53..96e6e9b 100644 --- a/config.h.in +++ b/config.h.in @@ -3,15 +3,19 @@ /* Include files */ #cmakedefine HAVE_FCNTL_H +#if defined(__APPLE__) && !defined(__IOS__) +#cmakedefine01 HAVE_UNISTD_H +#else #cmakedefine HAVE_UNISTD_H +#endif #cmakedefine HAVE_INTTYPES_H #cmakedefine HAVE_SYS_MODEM_H #cmakedefine HAVE_SYS_FILIO_H #cmakedefine HAVE_SYS_SELECT_H #cmakedefine HAVE_SYS_SOCKIO_H #cmakedefine HAVE_SYS_STRTIO_H -#cmakedefine HAVE_EVENTFD_H -#cmakedefine HAVE_TIMERFD_H +#cmakedefine HAVE_SYS_EVENTFD_H +#cmakedefine HAVE_SYS_TIMERFD_H #cmakedefine HAVE_TM_GMTOFF #cmakedefine HAVE_AIO_H #cmakedefine HAVE_POLL_H @@ -33,6 +37,7 @@ #cmakedefine WITH_NATIVE_SSPI #cmakedefine WITH_JPEG #cmakedefine WITH_WIN8 +#cmakedefine WITH_ICU #cmakedefine WITH_RDPSND_DSOUND #cmakedefine WITH_EVENTFD_READ_WRITE #cmakedefine HAVE_MATH_C99_LONG_DOUBLE @@ -53,10 +58,73 @@ #cmakedefine WITH_X264 #cmakedefine WITH_MEDIA_FOUNDATION +#cmakedefine WITH_VAAPI + /* Plugins */ #cmakedefine BUILTIN_CHANNELS #cmakedefine WITH_RDPDR -#cmakedefine WITH_KRB5 + +/* Channels */ +#cmakedefine CHANNEL_AUDIN +#cmakedefine CHANNEL_AUDIN_CLIENT +#cmakedefine CHANNEL_AUDIN_SERVER +#cmakedefine CHANNEL_CLIPRDR +#cmakedefine CHANNEL_CLIPRDR_CLIENT +#cmakedefine CHANNEL_CLIPRDR_SERVER +#cmakedefine CHANNEL_DISP +#cmakedefine CHANNEL_DISP_CLIENT +#cmakedefine CHANNEL_DISP_SERVER +#cmakedefine CHANNEL_DRDYNVC +#cmakedefine CHANNEL_DRDYNVC_CLIENT +#cmakedefine CHANNEL_DRDYNVC_SERVER +#cmakedefine CHANNEL_DRIVE +#cmakedefine CHANNEL_DRIVE_CLIENT +#cmakedefine CHANNEL_DRIVE_SERVER +#cmakedefine CHANNEL_ECHO +#cmakedefine CHANNEL_ECHO_CLIENT +#cmakedefine CHANNEL_ECHO_SERVER +#cmakedefine CHANNEL_ENCOMSP +#cmakedefine CHANNEL_ENCOMSP_CLIENT +#cmakedefine CHANNEL_ENCOMSP_SERVER +#cmakedefine CHANNEL_PARALLEL +#cmakedefine CHANNEL_PARALLEL_CLIENT +#cmakedefine CHANNEL_PARALLEL_SERVER +#cmakedefine CHANNEL_PRINTER +#cmakedefine CHANNEL_PRINTER_CLIENT +#cmakedefine CHANNEL_PRINTER_SERVER +#cmakedefine CHANNEL_RAIL +#cmakedefine CHANNEL_RAIL_CLIENT +#cmakedefine CHANNEL_RAIL_SERVER +#cmakedefine CHANNEL_RDPDR +#cmakedefine CHANNEL_RDPDR_CLIENT +#cmakedefine CHANNEL_RDPDR_SERVER +#cmakedefine CHANNEL_RDPEI +#cmakedefine CHANNEL_RDPEI_CLIENT +#cmakedefine CHANNEL_RDPEI_SERVER +#cmakedefine CHANNEL_RDPGFX +#cmakedefine CHANNEL_RDPGFX_CLIENT +#cmakedefine CHANNEL_RDPGFX_SERVER +#cmakedefine CHANNEL_RDPSND +#cmakedefine CHANNEL_RDPSND_CLIENT +#cmakedefine CHANNEL_RDPSND_SERVER +#cmakedefine CHANNEL_REMDESK +#cmakedefine CHANNEL_REMDESK_CLIENT +#cmakedefine CHANNEL_REMDESK_SERVER +#cmakedefine CHANNEL_SERIAL +#cmakedefine CHANNEL_SERIAL_CLIENT +#cmakedefine CHANNEL_SERIAL_SERVER +#cmakedefine CHANNEL_SMARTCARD +#cmakedefine CHANNEL_SMARTCARD_CLIENT +#cmakedefine CHANNEL_SMARTCARD_SERVER +#cmakedefine CHANNEL_SSHAGENT +#cmakedefine CHANNEL_SSHAGENT_CLIENT +#cmakedefine CHANNEL_SSHAGENT_SERVER +#cmakedefine CHANNEL_TSMF +#cmakedefine CHANNEL_TSMF_CLIENT +#cmakedefine CHANNEL_TSMF_SERVER +#cmakedefine CHANNEL_URBDRC +#cmakedefine CHANNEL_URBDRC_CLIENT +#cmakedefine CHANNEL_URBDRC_SERVER /* Debug */ #cmakedefine WITH_DEBUG_CERTIFICATE diff --git a/docs/README.android b/docs/README.android index 1e4ff67..f2da658 100644 --- a/docs/README.android +++ b/docs/README.android @@ -52,7 +52,7 @@ They are limited to API level 21 and above. If release binaries (and old android API support) are required, build 32 bit architectures with ./scripts/android-build-freerdp.sh --ndk <ANDROID_NDK> --sdk <ANDROID_SDK> --conf ./scripts/android-build-32.conf and 64 bit architectures with -./scripts/android-build-freerdp.sh --ndk <ANDROID_NDK> --sdk <ANDROID_SDK> --conf ./scripts/android-build-32.conf +./scripts/android-build-freerdp.sh --ndk <ANDROID_NDK> --sdk <ANDROID_SDK> --conf ./scripts/android-build-64.conf Building the APK (Android Studio) ================ diff --git a/docs/README.macOS b/docs/README.macOS new file mode 100644 index 0000000..d9fbb6b --- /dev/null +++ b/docs/README.macOS @@ -0,0 +1,7 @@ +Starting with "El Capitan" Apple removed the openssl headers. Therefore it's +required to build openssl manually upfront. For example by using MacPorts or Homebrew. +To build FreeRDP against this library it's required to set the PKG_CONFIG_PATH +pointing to the openssl root directory befor building. +For example with brew it would look like this: + +export PKG_CONFIG_PATH=$(brew --prefix)/opt/openssl/lib/pkgconfig diff --git a/include/freerdp/channels/geometry.h b/include/freerdp/channels/geometry.h new file mode 100644 index 0000000..af098b0 --- /dev/null +++ b/include/freerdp/channels/geometry.h @@ -0,0 +1,64 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Geometry tracking Virtual Channel Extension + * + * Copyright 2017 David Fort <contact@hardening-consulting.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_GEOMETRY_H +#define FREERDP_CHANNEL_GEOMETRY_H + +#include <winpr/wtypes.h> +#include <freerdp/types.h> + +#define GEOMETRY_DVC_CHANNEL_NAME "Microsoft::Windows::RDS::Geometry::v08.01" + +enum +{ + GEOMETRY_UPDATE = 1, + GEOMETRY_CLEAR = 2 +}; + +enum +{ + RDH_RECTANGLE = 1 +}; + +struct _FREERDP_RGNDATA +{ + RDP_RECT boundingRect; + UINT32 nRectCount; + RDP_RECT *rects; +}; + +typedef struct _FREERDP_RGNDATA FREERDP_RGNDATA; + + +struct _MAPPED_GEOMETRY_PACKET +{ + UINT32 version; + UINT64 mappingId; + UINT32 updateType; + UINT64 topLevelId; + INT32 left, top, right, bottom; + INT32 topLevelLeft, topLevelTop, topLevelRight, topLevelBottom; + UINT32 geometryType; + + FREERDP_RGNDATA geometry; +}; + +typedef struct _MAPPED_GEOMETRY_PACKET MAPPED_GEOMETRY_PACKET; + +#endif /* FREERDP_CHANNEL_GEOMETRY_H */ diff --git a/include/freerdp/channels/video.h b/include/freerdp/channels/video.h new file mode 100644 index 0000000..2367512 --- /dev/null +++ b/include/freerdp/channels/video.h @@ -0,0 +1,118 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Video Optimized Remoting Virtual Channel Extension + * + * Copyright 2018 David Fort <contact@hardening-consulting.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_VIDEO_H +#define FREERDP_CHANNEL_VIDEO_H + +#include <winpr/wtypes.h> +#include <freerdp/types.h> + +#define VIDEO_CONTROL_DVC_CHANNEL_NAME "Microsoft::Windows::RDS::Video::Control::v08.01" +#define VIDEO_DATA_DVC_CHANNEL_NAME "Microsoft::Windows::RDS::Video::Data::v08.01" + +/** @brief TSNM packet type */ +enum +{ + TSMM_PACKET_TYPE_PRESENTATION_REQUEST = 1, + TSMM_PACKET_TYPE_PRESENTATION_RESPONSE = 2, + TSMM_PACKET_TYPE_CLIENT_NOTIFICATION = 3, + TSMM_PACKET_TYPE_VIDEO_DATA = 4 +}; + +/** @brief TSMM_PRESENTATION_REQUEST commands */ +enum +{ + TSMM_START_PRESENTATION = 1, + TSMM_STOP_PRESENTATION = 2 +}; + +/** @brief presentation request struct */ +struct _TSMM_PRESENTATION_REQUEST +{ + BYTE PresentationId; + BYTE Version; + BYTE Command; + BYTE FrameRate; + UINT32 SourceWidth, SourceHeight; + UINT32 ScaledWidth, ScaledHeight; + UINT64 hnsTimestampOffset; + UINT64 GeometryMappingId; + BYTE VideoSubtypeId[16]; + UINT32 cbExtra; + BYTE *pExtraData; +}; +typedef struct _TSMM_PRESENTATION_REQUEST TSMM_PRESENTATION_REQUEST; + +/** @brief response to a TSMM_PRESENTATION_REQUEST */ +struct _TSMM_PRESENTATION_RESPONSE +{ + BYTE PresentationId; +}; +typedef struct _TSMM_PRESENTATION_RESPONSE TSMM_PRESENTATION_RESPONSE; + +/** @brief TSMM_VIDEO_DATA flags */ +enum +{ + TSMM_VIDEO_DATA_FLAG_HAS_TIMESTAMPS = 0x01, + TSMM_VIDEO_DATA_FLAG_KEYFRAME = 0x02, + TSMM_VIDEO_DATA_FLAG_NEW_FRAMERATE = 0x04 +}; + +/** @brief a video data packet */ +struct _TSMM_VIDEO_DATA +{ + BYTE PresentationId; + BYTE Version; + BYTE Flags; + UINT64 hnsTimestamp; + UINT64 hnsDuration; + UINT16 CurrentPacketIndex; + UINT16 PacketsInSample; + UINT32 SampleNumber; + UINT32 cbSample; + BYTE *pSample; +}; +typedef struct _TSMM_VIDEO_DATA TSMM_VIDEO_DATA; + +/** @brief values for NotificationType in TSMM_CLIENT_NOTIFICATION */ +enum +{ + TSMM_CLIENT_NOTIFICATION_TYPE_NETWORK_ERROR = 1, + TSMM_CLIENT_NOTIFICATION_TYPE_FRAMERATE_OVERRIDE = 2 +}; + +/** @brief struct used when NotificationType is FRAMERATE_OVERRIDE */ +struct _TSMM_CLIENT_NOTIFICATION_FRAMERATE_OVERRIDE +{ + UINT32 Flags; + UINT32 DesiredFrameRate; +}; +typedef struct _TSMM_CLIENT_NOTIFICATION_FRAMERATE_OVERRIDE TSMM_CLIENT_NOTIFICATION_FRAMERATE_OVERRIDE; + +/** @brief a client to server notification struct */ +struct _TSMM_CLIENT_NOTIFICATION +{ + BYTE PresentationId; + BYTE NotificationType; + TSMM_CLIENT_NOTIFICATION_FRAMERATE_OVERRIDE FramerateOverride; +}; +typedef struct _TSMM_CLIENT_NOTIFICATION TSMM_CLIENT_NOTIFICATION; + + +#endif /* FREERDP_CHANNEL_VIDEO_H */ diff --git a/include/freerdp/client/cmdline.h b/include/freerdp/client/cmdline.h index 621a997..065d973 100644 --- a/include/freerdp/client/cmdline.h +++ b/include/freerdp/client/cmdline.h @@ -20,6 +20,8 @@ #ifndef FREERDP_CLIENT_CMDLINE_H #define FREERDP_CLIENT_CMDLINE_H +#include <winpr/cmdline.h> + #include <freerdp/api.h> #include <freerdp/freerdp.h> @@ -28,21 +30,28 @@ extern "C" { #endif 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); + 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_settings_command_line_status_print_ex( + rdpSettings* settings, int status, int argc, char** argv, + COMMAND_LINE_ARGUMENT_A* custom); FREERDP_API BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings); 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 BOOL freerdp_client_print_command_line_help_ex( + int argc, char** argv, COMMAND_LINE_ARGUMENT_A* custom); -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_parse_username(const char* username, char** user, char** domain); +FREERDP_API BOOL freerdp_parse_hostname(const char* hostname, char** host, int* port); FREERDP_API BOOL freerdp_set_connection_type(rdpSettings* settings, int type); 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); +FREERDP_API BOOL freerdp_client_add_dynamic_channel(rdpSettings* settings, int count, + char** params); #ifdef __cplusplus } diff --git a/include/freerdp/client/disp.h b/include/freerdp/client/disp.h index d61644c..0b39d33 100644 --- a/include/freerdp/client/disp.h +++ b/include/freerdp/client/disp.h @@ -52,6 +52,8 @@ typedef struct _DISPLAY_CONTROL_MONITOR_LAYOUT DISPLAY_CONTROL_MONITOR_LAYOUT; typedef struct _disp_client_context DispClientContext; +typedef UINT (*pcDispCaps)(DispClientContext* context, UINT32 MaxNumMonitors, UINT32 MaxMonitorAreaFactorA, + UINT32 MaxMonitorAreaFactorB); typedef UINT (*pcDispSendMonitorLayout)(DispClientContext* context, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors); struct _disp_client_context @@ -59,6 +61,7 @@ struct _disp_client_context void* handle; void* custom; + pcDispCaps DisplayControlCaps; pcDispSendMonitorLayout SendMonitorLayout; }; diff --git a/include/freerdp/client/file.h b/include/freerdp/client/file.h index 307eba5..8f12a29 100644 --- a/include/freerdp/client/file.h +++ b/include/freerdp/client/file.h @@ -140,6 +140,7 @@ struct rdp_file DWORD GatewayUsageMethod; /* gatewayusagemethod */ DWORD GatewayProfileUsageMethod; /* gatewayprofileusagemethod */ DWORD GatewayCredentialsSource; /* gatewaycredentialssource */ + LPSTR GatewayAccessToken; /* gatewayaccesstoken */ DWORD UseRedirectionServerName; /* use redirection server name */ @@ -150,6 +151,8 @@ struct rdp_file LPSTR DevicesToRedirect; /* devicestoredirect */ LPSTR WinPosStr; /* winposstr */ + LPSTR PreconnectionBlob; /* pcb */ + int lineCount; int lineSize; rdpFileLine* lines; diff --git a/include/freerdp/client/geometry.h b/include/freerdp/client/geometry.h new file mode 100644 index 0000000..1beee8c --- /dev/null +++ b/include/freerdp/client/geometry.h @@ -0,0 +1,76 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Geometry tracking Virtual Channel Extension + * + * Copyright 2017 David Fort <contact@hardening-consulting.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNELS_CLIENT_GEOMETRY_H +#define FREERDP_CHANNELS_CLIENT_GEOMETRY_H + +#include <winpr/collections.h> +#include <freerdp/api.h> +#include <freerdp/channels/geometry.h> + +/** + * Client Interface + */ +typedef struct _geometry_client_context GeometryClientContext; + +typedef struct _MAPPED_GEOMETRY MAPPED_GEOMETRY; +typedef BOOL (*pcMappedGeometryAdded)(GeometryClientContext* context, MAPPED_GEOMETRY *geometry); +typedef BOOL (*pcMappedGeometryUpdate)(MAPPED_GEOMETRY *geometry); +typedef BOOL (*pcMappedGeometryClear)(MAPPED_GEOMETRY *geometry); + +/** @brief a geometry record tracked by the geometry channel */ +struct _MAPPED_GEOMETRY +{ + volatile LONG refCounter; + UINT64 mappingId; + UINT64 topLevelId; + INT32 left, top, right, bottom; + INT32 topLevelLeft, topLevelTop, topLevelRight, topLevelBottom; + FREERDP_RGNDATA geometry; + + void *custom; + pcMappedGeometryUpdate MappedGeometryUpdate; + pcMappedGeometryClear MappedGeometryClear; +}; + + +/** @brief the geometry context for client channel */ +struct _geometry_client_context +{ + wHashTable *geometries; + void* handle; + void* custom; + + pcMappedGeometryAdded MappedGeometryAdded; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +FREERDP_API void mappedGeometryRef(MAPPED_GEOMETRY *g); +FREERDP_API void mappedGeometryUnref(MAPPED_GEOMETRY *g); + +#ifdef __cplusplus +} +#endif + + +#endif /* FREERDP_CHANNELS_CLIENT_GEOMETRY_H */ + diff --git a/include/freerdp/client/rdpgfx.h b/include/freerdp/client/rdpgfx.h index 50b1914..161a2fa 100644 --- a/include/freerdp/client/rdpgfx.h +++ b/include/freerdp/client/rdpgfx.h @@ -111,7 +111,7 @@ struct _rdpgfx_client_context pcRdpgfxUpdateSurfaces UpdateSurfaces; pcRdpgfxUpdateSurfaceArea UpdateSurfaceArea; - PROFILER_DEFINE(SurfaceProfiler); + PROFILER_DEFINE(SurfaceProfiler) }; #endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_RDPGFX_H */ diff --git a/include/freerdp/client/sshagent.h b/include/freerdp/client/sshagent.h new file mode 100644 index 0000000..64ada33 --- /dev/null +++ b/include/freerdp/client/sshagent.h @@ -0,0 +1,87 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * SSH Agent Virtual Channel Extension + * + * Copyright 2017 Ben Cohen + * + * 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_CHANNEL_CLIENT_SSHAGENT_H +#define FREERDP_CHANNEL_CLIENT_SSHAGENT_H + +#include <freerdp/types.h> + +#include <freerdp/message.h> +#include <freerdp/channels/cliprdr.h> +#include <freerdp/freerdp.h> + +typedef struct _sshagent_client_context +{ + int ProtocolVersion; + int MaxConnections; +} SSHAgentClientContext; + + +/* + * The channel is defined by the sshagent channel in xrdp as follows. + * + * Server to client commands + * ------------------------- + * + * Capabilities (at start of channel stream): + * + * INT32 SA_TAG_CAPABILITY + * INT32 SSHAGENT_CHAN_PROT_VERSION := 1 + * INT32 SSHAGENT_MAX_CONNECTIONS + * + * Open connection: + * + * INT32 SA_TAG_OPEN + * INT32 Connection id (0, ..., SSHAGENT_MAX_CONNECTIONS - 1) + * + * Send data: + * + * INT32 SA_TAG_WRITE + * INT32 Connection id (0, ..., SSHAGENT_MAX_CONNECTIONS - 1) + * INT32 Data length + * DATA ... + * + * Close connection: + * + * INT32 SA_TAG_CLOSE + * INT32 Connection id (0, ..., SSHAGENT_MAX_CONNECTIONS - 1) + * + * Client to server commands + * ------------------------- + * + * Capabilities (in reply to server capabilities): + * + * INT32 SA_TAG_CAPABILITY + * INT32 SSHAGENT_CHAN_PROT_VERSION := 1 + * INT32 SSHAGENT_MAX_CONNECTIONS + * + * Send data: + * + * INT32 SA_TAG_WRITE + * INT32 Connection id (0, ..., SSHAGENT_MAX_CONNECTIONS - 1) + * INT32 Data length + * DATA ... + * + * Close connection (abnormal): + * + * INT32 SA_TAG_CLOSE + * INT32 Connection id (0, ..., SSHAGENT_MAX_CONNECTIONS - 1) + */ + +#endif /* FREERDP_CHANNEL_CLIENT_SSHAGENT_H */ diff --git a/include/freerdp/client/video.h b/include/freerdp/client/video.h new file mode 100644 index 0000000..7ddaa5c --- /dev/null +++ b/include/freerdp/client/video.h @@ -0,0 +1,61 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Video Optimized Remoting Virtual Channel Extension + * + * Copyright 2017 David Fort <contact@hardening-consulting.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNELS_CLIENT_VIDEO_H +#define FREERDP_CHANNELS_CLIENT_VIDEO_H + +#include <freerdp/client/geometry.h> +#include <freerdp/channels/video.h> + +typedef struct _VideoClientContext VideoClientContext; +typedef struct _VideoClientContextPriv VideoClientContextPriv; +typedef struct _VideoSurface VideoSurface; + + +/** @brief an implementation of surface used by the video channel */ +struct _VideoSurface +{ + UINT32 x, y, w, h; + BYTE *data; +}; + +typedef void (*pcVideoTimer)(VideoClientContext *video, UINT64 now); +typedef void (*pcVideoSetGeometry)(VideoClientContext *video, GeometryClientContext *geometry); +typedef VideoSurface *(*pcVideoCreateSurface)(VideoClientContext *video, BYTE *data, UINT32 x, UINT32 y, + UINT32 width, UINT32 height); +typedef BOOL (*pcVideoShowSurface)(VideoClientContext *video, VideoSurface *surface); +typedef BOOL (*pcVideoDeleteSurface)(VideoClientContext *video, VideoSurface *surface); + +/** @brief context for the video (MS-RDPEVOR) channel */ +struct _VideoClientContext +{ + void* handle; + void* custom; + VideoClientContextPriv *priv; + + pcVideoSetGeometry setGeometry; + pcVideoTimer timer; + pcVideoCreateSurface createSurface; + pcVideoShowSurface showSurface; + pcVideoDeleteSurface deleteSurface; +}; + + +#endif /* FREERDP_CHANNELS_CLIENT_VIDEO_H */ + diff --git a/include/freerdp/codec/color.h b/include/freerdp/codec/color.h index d61790c..7e43952 100644 --- a/include/freerdp/codec/color.h +++ b/include/freerdp/codec/color.h @@ -118,7 +118,7 @@ static INLINE DWORD AreColorFormatsEqualNoAlpha(DWORD first, DWORD second) * * @return A string representation of format */ -static const char* GetColorFormatName(UINT32 format) +static const char* FreeRDPGetColorFormatName(UINT32 format) { switch (format) { @@ -509,7 +509,7 @@ static INLINE void SplitColor(UINT32 color, UINT32 format, BYTE* _r, BYTE* _g, if (_a) *_a = 0x00; - WLog_ERR(CTAG, "Unsupported format %s", GetColorFormatName(format)); + WLog_ERR(CTAG, "Unsupported format %s", FreeRDPGetColorFormatName(format)); break; } } @@ -527,7 +527,7 @@ static INLINE void SplitColor(UINT32 color, UINT32 format, BYTE* _r, BYTE* _g, * @return The pixel color in the desired format. Value is in internal * representation. */ -static INLINE UINT32 GetColor(UINT32 format, BYTE r, BYTE g, BYTE b, BYTE a) +static INLINE UINT32 FreeRDPGetColor(UINT32 format, BYTE r, BYTE g, BYTE b, BYTE a) { UINT32 _r = r; UINT32 _g = g; @@ -603,7 +603,7 @@ static INLINE UINT32 GetColor(UINT32 format, BYTE r, BYTE g, BYTE b, BYTE a) /* 1bpp formats */ case PIXEL_FORMAT_MONO: default: - WLog_ERR(CTAG, "Unsupported format %s", GetColorFormatName(format)); + WLog_ERR(CTAG, "Unsupported format %s", FreeRDPGetColorFormatName(format)); return 0; } } @@ -679,7 +679,7 @@ static INLINE UINT32 ReadColor(const BYTE* src, UINT32 format) break; default: - WLog_ERR(CTAG, "Unsupported format %s", GetColorFormatName(format)); + WLog_ERR(CTAG, "Unsupported format %s", FreeRDPGetColorFormatName(format)); color = 0; break; } @@ -732,7 +732,7 @@ static INLINE BOOL WriteColor(BYTE* dst, UINT32 format, UINT32 color) break; default: - WLog_ERR(CTAG, "Unsupported format %s", GetColorFormatName(format)); + WLog_ERR(CTAG, "Unsupported format %s", FreeRDPGetColorFormatName(format)); return FALSE; } @@ -751,7 +751,7 @@ static INLINE BOOL WriteColor(BYTE* dst, UINT32 format, UINT32 color) * * @return The converted pixel color in dstFormat representation */ -static INLINE UINT32 ConvertColor(UINT32 color, UINT32 srcFormat, +static INLINE UINT32 FreeRDPConvertColor(UINT32 color, UINT32 srcFormat, UINT32 dstFormat, const gdiPalette* palette) { BYTE r = 0; @@ -759,7 +759,7 @@ static INLINE UINT32 ConvertColor(UINT32 color, UINT32 srcFormat, BYTE b = 0; BYTE a = 0; SplitColor(color, srcFormat, &r, &g, &b, &a, palette); - return GetColor(dstFormat, r, g, b, a); + return FreeRDPGetColor(dstFormat, r, g, b, a); } /*** @@ -872,7 +872,7 @@ FREERDP_API BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, * @param nWidth width to copy in pixels * @param nHeight height to copy in pixels * @param color Pixel color in DstFormat (internal representation format, - * use GetColor to create) + * use FreeRDPGetColor to create) * * @return TRUE if success, FALSE otherwise */ @@ -880,6 +880,12 @@ FREERDP_API BOOL freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color); +#if !defined(__APPLE__) +#define GetColorFormatName FreeRDPGetColorFormatName +#define GetColor FreeRDPGetColor +#define ConvertColor FreeRDPConvertColor +#endif + #ifdef __cplusplus } #endif diff --git a/include/freerdp/codec/h264.h b/include/freerdp/codec/h264.h index e805092..77e9dd5 100644 --- a/include/freerdp/codec/h264.h +++ b/include/freerdp/codec/h264.h @@ -20,6 +20,8 @@ #ifndef FREERDP_CODEC_H264_H #define FREERDP_CODEC_H264_H +#include <winpr/wlog.h> + #include <freerdp/api.h> #include <freerdp/types.h> #include <freerdp/channels/rdpgfx.h> @@ -31,8 +33,9 @@ typedef void (*pfnH264SubsystemUninit)(H264_CONTEXT* h264); typedef int (*pfnH264SubsystemDecompress)(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize); -typedef int (*pfnH264SubsystemCompress)(H264_CONTEXT* h264, BYTE** ppDstData, - UINT32* pDstSize); +typedef int (*pfnH264SubsystemCompress)(H264_CONTEXT* h264, const BYTE** pSrcYuv, + const UINT32* pStride, + BYTE** ppDstData, UINT32* pDstSize); struct _H264_CONTEXT_SUBSYSTEM { @@ -74,8 +77,10 @@ struct _H264_CONTEXT UINT32 numSystemData; void* pSystemData; H264_CONTEXT_SUBSYSTEM* subsystem; -}; + void* lumaData; + wLog* log; +}; #ifdef __cplusplus extern "C" { #endif @@ -93,7 +98,7 @@ FREERDP_API INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, FREERDP_API INT32 avc444_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, UINT32 nSrcStep, UINT32 nSrcWidth, UINT32 nSrcHeight, - BYTE* op, + BYTE version, BYTE* op, BYTE** pDstData, UINT32* pDstSize, BYTE** pAuxDstData, UINT32* pAuxDstSize); diff --git a/include/freerdp/codec/yuv.h b/include/freerdp/codec/yuv.h new file mode 100644 index 0000000..1497db2 --- /dev/null +++ b/include/freerdp/codec/yuv.h @@ -0,0 +1,48 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * YUV decoder + * + * Copyright 2017 David Fort <contact@hardening-consulting.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CODEC_YUV_H +#define FREERDP_CODEC_YUV_H + +typedef struct _YUV_CONTEXT YUV_CONTEXT; + +#include <freerdp/api.h> +#include <freerdp/types.h> +#include <freerdp/freerdp.h> +#include <freerdp/constants.h> + + +#ifdef __cplusplus +extern "C" { +#endif + + +FREERDP_API BOOL yuv_context_decode(YUV_CONTEXT* context, const BYTE* pYUVData[3], UINT32 iStride[3], + DWORD DstFormat, BYTE *dest, UINT32 nDstStep); + +FREERDP_API void yuv_context_reset(YUV_CONTEXT* context, UINT32 width, UINT32 height); + +FREERDP_API YUV_CONTEXT* yuv_context_new(BOOL encoder); +FREERDP_API void yuv_context_free(YUV_CONTEXT* context); + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_CODEC_YUV_H */ diff --git a/include/freerdp/crypto/ber.h b/include/freerdp/crypto/ber.h index 2834448..1d0a9f7 100644 --- a/include/freerdp/crypto/ber.h +++ b/include/freerdp/crypto/ber.h @@ -53,39 +53,39 @@ #define BER_PC(_pc) (_pc ? BER_CONSTRUCT : BER_PRIMITIVE) #ifdef __cplusplus - extern "C" { +extern "C" { #endif -FREERDP_API BOOL ber_read_length(wStream* s, int* length); -FREERDP_API int ber_write_length(wStream* s, int length); -FREERDP_API int _ber_sizeof_length(int length); +FREERDP_API BOOL ber_read_length(wStream* s, size_t* length); +FREERDP_API size_t ber_write_length(wStream* s, size_t length); +FREERDP_API size_t _ber_sizeof_length(size_t length); FREERDP_API BOOL ber_read_universal_tag(wStream* s, BYTE tag, BOOL pc); -FREERDP_API int ber_write_universal_tag(wStream* s, BYTE tag, BOOL pc); -FREERDP_API BOOL ber_read_application_tag(wStream* s, BYTE tag, int* length); -FREERDP_API void ber_write_application_tag(wStream* s, BYTE tag, int length); +FREERDP_API size_t ber_write_universal_tag(wStream* s, BYTE tag, BOOL pc); +FREERDP_API BOOL ber_read_application_tag(wStream* s, BYTE tag, size_t* length); +FREERDP_API void ber_write_application_tag(wStream* s, BYTE tag, size_t length); FREERDP_API BOOL ber_read_enumerated(wStream* s, BYTE* enumerated, BYTE count); FREERDP_API void ber_write_enumerated(wStream* s, BYTE enumerated, BYTE count); -FREERDP_API BOOL ber_read_contextual_tag(wStream* s, BYTE tag, int* length, BOOL pc); -FREERDP_API int ber_write_contextual_tag(wStream* s, BYTE tag, int length, BOOL pc); -FREERDP_API int ber_sizeof_contextual_tag(int length); -FREERDP_API BOOL ber_read_sequence_tag(wStream* s, int* length); -FREERDP_API int ber_write_sequence_tag(wStream* s, int length); -FREERDP_API int ber_sizeof_sequence(int length); -FREERDP_API int ber_sizeof_sequence_tag(int length); -FREERDP_API BOOL ber_read_bit_string(wStream* s, int* length, BYTE* padding); -FREERDP_API int ber_write_octet_string(wStream* s, const BYTE* oct_str, int length); -FREERDP_API BOOL ber_read_octet_string_tag(wStream* s, int* length); -FREERDP_API int ber_write_octet_string_tag(wStream* s, int length); -FREERDP_API int ber_sizeof_octet_string(int length); +FREERDP_API BOOL ber_read_contextual_tag(wStream* s, BYTE tag, size_t* length, BOOL pc); +FREERDP_API size_t ber_write_contextual_tag(wStream* s, BYTE tag, size_t length, BOOL pc); +FREERDP_API size_t ber_sizeof_contextual_tag(size_t length); +FREERDP_API BOOL ber_read_sequence_tag(wStream* s, size_t* length); +FREERDP_API size_t ber_write_sequence_tag(wStream* s, size_t length); +FREERDP_API size_t ber_sizeof_sequence(size_t length); +FREERDP_API size_t ber_sizeof_sequence_tag(size_t length); +FREERDP_API BOOL ber_read_bit_string(wStream* s, size_t* length, BYTE* padding); +FREERDP_API size_t ber_write_octet_string(wStream* s, const BYTE* oct_str, size_t length); +FREERDP_API BOOL ber_read_octet_string_tag(wStream* s, size_t* length); +FREERDP_API size_t ber_write_octet_string_tag(wStream* s, size_t length); +FREERDP_API size_t ber_sizeof_octet_string(size_t length); FREERDP_API BOOL ber_read_BOOL(wStream* s, BOOL* value); FREERDP_API void ber_write_BOOL(wStream* s, BOOL value); FREERDP_API BOOL ber_read_integer(wStream* s, UINT32* value); -FREERDP_API int ber_write_integer(wStream* s, UINT32 value); -FREERDP_API BOOL ber_read_integer_length(wStream* s, int* length); -FREERDP_API int ber_sizeof_integer(UINT32 value); +FREERDP_API size_t ber_write_integer(wStream* s, UINT32 value); +FREERDP_API BOOL ber_read_integer_length(wStream* s, size_t* length); +FREERDP_API size_t ber_sizeof_integer(UINT32 value); #ifdef __cplusplus - } +} #endif #endif /* FREERDP_CRYPTO_BER_H */ diff --git a/include/freerdp/error.h b/include/freerdp/error.h index 5debf3a..b971b10 100644 --- a/include/freerdp/error.h +++ b/include/freerdp/error.h @@ -244,6 +244,17 @@ FREERDP_API const char* freerdp_get_error_base_name(UINT32 code); #define ERRCONNECT_CLIENT_REVOKED 0x00000010 #define ERRCONNECT_KDC_UNREACHABLE 0x00000011 +#define ERRCONNECT_ACCOUNT_DISABLED 0x00000012 +#define ERRCONNECT_PASSWORD_MUST_CHANGE 0x00000013 +#define ERRCONNECT_LOGON_FAILURE 0x00000014 +#define ERRCONNECT_WRONG_PASSWORD 0x00000015 +#define ERRCONNECT_ACCESS_DENIED 0x00000016 +#define ERRCONNECT_ACCOUNT_RESTRICTION 0x00000017 +#define ERRCONNECT_ACCOUNT_LOCKED_OUT 0x00000018 +#define ERRCONNECT_ACCOUNT_EXPIRED 0x00000019 +#define ERRCONNECT_LOGON_TYPE_NOT_GRANTED 0x0000001A + + #define ERRCONNECT_SUCCESS ERRINFO_SUCCESS #define ERRCONNECT_NONE ERRINFO_NONE @@ -294,14 +305,41 @@ FREERDP_API const char* freerdp_get_error_connect_name(UINT32 code); #define FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED \ MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_PASSWORD_EXPIRED) +#define FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE \ + MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_PASSWORD_MUST_CHANGE) + +#define FREERDP_ERROR_CONNECT_KDC_UNREACHABLE \ + MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_KDC_UNREACHABLE) + +#define FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED \ + MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_ACCOUNT_DISABLED) + #define FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED \ MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_PASSWORD_CERTAINLY_EXPIRED) #define FREERDP_ERROR_CONNECT_CLIENT_REVOKED \ MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_CLIENT_REVOKED) -#define FREERDP_ERROR_CONNECT_KDC_UNREACHABLE \ - MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_KDC_UNREACHABLE) +#define FREERDP_ERROR_CONNECT_LOGON_FAILURE \ + MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_LOGON_FAILURE) + +#define FREERDP_ERROR_CONNECT_WRONG_PASSWORD \ + MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_WRONG_PASSWORD) + +#define FREERDP_ERROR_CONNECT_ACCESS_DENIED \ + MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_ACCESS_DENIED) + +#define FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION \ + MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_ACCOUNT_RESTRICTION) + +#define FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT \ + MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_ACCOUNT_LOCKED_OUT) + +#define FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED \ + MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_ACCOUNT_EXPIRED) + +#define FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED \ + MAKE_FREERDP_ERROR(CONNECT, ERRCONNECT_LOGON_TYPE_NOT_GRANTED) #ifdef __cplusplus } diff --git a/include/freerdp/event.h b/include/freerdp/event.h index 30f5c03..6844484 100644 --- a/include/freerdp/event.h +++ b/include/freerdp/event.h @@ -66,6 +66,10 @@ DEFINE_EVENT_BEGIN(ErrorInfo) UINT32 code; DEFINE_EVENT_END(ErrorInfo) +DEFINE_EVENT_BEGIN(Activated) +BOOL firstActivation; +DEFINE_EVENT_END(Activated) + DEFINE_EVENT_BEGIN(Terminate) int code; DEFINE_EVENT_END(Terminate) @@ -100,6 +104,21 @@ UINT16 x; UINT16 y; DEFINE_EVENT_END(MouseEvent) +DEFINE_EVENT_BEGIN(MouseEventEx) +UINT16 flags; +UINT16 x; +UINT16 y; +DEFINE_EVENT_END(MouseEventEx) + +DEFINE_EVENT_BEGIN(Timer) +UINT64 now; +DEFINE_EVENT_END(Timer) + +DEFINE_EVENT_BEGIN(GraphicsReset) +UINT32 width; +UINT32 height; +DEFINE_EVENT_END(GraphicsReset) + #ifdef __cplusplus } #endif diff --git a/include/freerdp/gdi/gdi.h b/include/freerdp/gdi/gdi.h index 2a893ce..976a8e9 100644 --- a/include/freerdp/gdi/gdi.h +++ b/include/freerdp/gdi/gdi.h @@ -32,6 +32,8 @@ #include <freerdp/codec/region.h> #include <freerdp/client/rdpgfx.h> +#include <freerdp/client/geometry.h> +#include <freerdp/client/video.h> /* For more information, see [MS-RDPEGDI] */ @@ -517,9 +519,11 @@ struct rdp_gdi BOOL inGfxFrame; BOOL graphicsReset; + BOOL suppressOutput; UINT16 outputSurfaceId; - REGION16 invalidRegion; RdpgfxClientContext* gfx; + VideoClientContext* video; + GeometryClientContext* geometry; wLog* log; }; @@ -529,6 +533,9 @@ extern "C" { #endif FREERDP_API DWORD gdi_rop3_code(BYTE code); +FREERDP_API const char* gdi_rop3_code_string(BYTE code); +FREERDP_API const char* gdi_rop3_string(DWORD rop); + FREERDP_API UINT32 gdi_get_pixel_format(UINT32 bitsPerPixel); FREERDP_API BOOL gdi_decode_color(rdpGdi* gdi, const UINT32 srcColor, UINT32* color, UINT32* format); @@ -542,6 +549,8 @@ FREERDP_API BOOL gdi_init_ex(freerdp* instance, UINT32 format, void (*pfree)(void*)); FREERDP_API void gdi_free(freerdp* instance); +FREERDP_API BOOL gdi_send_suppress_output(rdpGdi* gdi, BOOL suppress); + #ifdef __cplusplus } #endif diff --git a/include/freerdp/gdi/region.h b/include/freerdp/gdi/region.h index 26381ef..ad76203 100644 --- a/include/freerdp/gdi/region.h +++ b/include/freerdp/gdi/region.h @@ -26,43 +26,43 @@ #include <freerdp/gdi/gdi.h> #ifdef __cplusplus - extern "C" { +extern "C" { #endif FREERDP_API HGDI_RGN gdi_CreateRectRgn(UINT32 nLeftRect, UINT32 nTopRect, - UINT32 nRightRect, UINT32 nBottomRect); + UINT32 nRightRect, UINT32 nBottomRect); FREERDP_API HGDI_RECT gdi_CreateRect(UINT32 xLeft, UINT32 yTop, - UINT32 xRight, UINT32 yBottom); + UINT32 xRight, UINT32 yBottom); FREERDP_API void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn); FREERDP_API void gdi_CRectToRgn(UINT32 left, UINT32 top, - UINT32 right, UINT32 bottom, HGDI_RGN rgn); -FREERDP_API void gdi_RectToCRgn(const HGDI_RECT rect, UINT32 *x, UINT32 *y, - UINT32 *w, UINT32 *h); + UINT32 right, UINT32 bottom, HGDI_RGN rgn); +FREERDP_API void gdi_RectToCRgn(const HGDI_RECT rect, UINT32* x, UINT32* y, + UINT32* w, UINT32* h); FREERDP_API void gdi_CRectToCRgn(UINT32 left, UINT32 top, - UINT32 right, UINT32 bottom, - UINT32 *x, UINT32 *y, UINT32 *w, UINT32 *h); + UINT32 right, UINT32 bottom, + UINT32* x, UINT32* y, UINT32* w, UINT32* h); FREERDP_API void gdi_RgnToRect(HGDI_RGN rgn, HGDI_RECT rect); -FREERDP_API void gdi_CRgnToRect(UINT32 x, UINT32 y, UINT32 w, UINT32 h, HGDI_RECT rect); -FREERDP_API void gdi_RgnToCRect(HGDI_RGN rgn, UINT32 *left, - UINT32 *top, UINT32 *right, UINT32 *bottom); +FREERDP_API void gdi_CRgnToRect(INT64 x, INT64 y, UINT32 w, UINT32 h, HGDI_RECT rect); +FREERDP_API void gdi_RgnToCRect(HGDI_RGN rgn, UINT32* left, + UINT32* top, UINT32* right, UINT32* bottom); FREERDP_API void gdi_CRgnToCRect(UINT32 x, UINT32 y, UINT32 w, UINT32 h, - UINT32 *left, UINT32 *top, UINT32 *right, UINT32 *bottom); + UINT32* left, UINT32* top, UINT32* right, UINT32* bottom); FREERDP_API BOOL gdi_CopyOverlap(UINT32 x, UINT32 y, UINT32 width, UINT32 height, - UINT32 srcx, UINT32 srcy); + UINT32 srcx, UINT32 srcy); FREERDP_API BOOL gdi_SetRect(HGDI_RECT rc, UINT32 xLeft, UINT32 yTop, - UINT32 xRight, UINT32 yBottom); + UINT32 xRight, UINT32 yBottom); FREERDP_API BOOL gdi_SetRgn(HGDI_RGN hRgn, UINT32 nXLeft, UINT32 nYLeft, - UINT32 nWidth, UINT32 nHeight); + UINT32 nWidth, UINT32 nHeight); FREERDP_API BOOL gdi_SetRectRgn(HGDI_RGN hRgn, UINT32 nLeftRect, UINT32 nTopRect, - UINT32 nRightRect, UINT32 nBottomRect); + UINT32 nRightRect, UINT32 nBottomRect); FREERDP_API BOOL gdi_EqualRgn(HGDI_RGN hSrcRgn1, HGDI_RGN hSrcRgn2); FREERDP_API BOOL gdi_CopyRect(HGDI_RECT dst, HGDI_RECT src); FREERDP_API BOOL gdi_PtInRect(HGDI_RECT rc, UINT32 x, UINT32 y); FREERDP_API BOOL gdi_InvalidateRegion(HGDI_DC hdc, UINT32 x, UINT32 y, - UINT32 w, UINT32 h); + UINT32 w, UINT32 h); #ifdef __cplusplus - } +} #endif #endif /* FREERDP_GDI_REGION_H */ diff --git a/include/freerdp/gdi/video.h b/include/freerdp/gdi/video.h new file mode 100644 index 0000000..3f13013 --- /dev/null +++ b/include/freerdp/gdi/video.h @@ -0,0 +1,43 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Video Optimized Remoting Virtual Channel Extension for X11 + * + * Copyright 2017 David Fort <contact@hardening-consulting.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FREERDP_GDI_VIDEO_H_ +#define FREERDP_GDI_VIDEO_H_ + +#include <freerdp/api.h> +#include <freerdp/freerdp.h> +#include <freerdp/client/geometry.h> +#include <freerdp/client/video.h> + +struct _gdiVideoContext; +typedef struct _gdiVideoContext gdiVideoContext; + +FREERDP_API void gdi_video_geometry_init(rdpGdi* gdi, GeometryClientContext* geom); +FREERDP_API void gdi_video_geometry_uninit(rdpGdi* gdi, GeometryClientContext* geom); + +FREERDP_API void gdi_video_control_init(rdpGdi* gdi, VideoClientContext* video); +FREERDP_API void gdi_video_control_uninit(rdpGdi* gdi, VideoClientContext* video); + +FREERDP_API void gdi_video_data_init(rdpGdi* gdi, VideoClientContext* video); +FREERDP_API void gdi_video_data_uninit(rdpGdi* gdi, VideoClientContext* context); + +FREERDP_API gdiVideoContext* gdi_video_new(rdpGdi* gdi); +FREERDP_API void gdi_video_free(gdiVideoContext* context); + + +#endif /* FREERDP_GDI_VIDEO_H_ */ diff --git a/include/freerdp/primitives.h b/include/freerdp/primitives.h index 022da27..ee29e7f 100644 --- a/include/freerdp/primitives.h +++ b/include/freerdp/primitives.h @@ -254,6 +254,7 @@ typedef struct __YUV444SplitToYUV420_t YUV444SplitToYUV420; __YUV444ToRGB_8u_P3AC4R_t YUV444ToRGB_8u_P3AC4R; __RGBToAVC444YUV_t RGBToAVC444YUV; + __RGBToAVC444YUV_t RGBToAVC444YUVv2; } primitives_t; #ifdef __cplusplus diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 2925851..e35364b 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -446,7 +446,6 @@ struct _RDPDR_SMARTCARD UINT32 Id; UINT32 Type; char* Name; - char* Path; }; typedef struct _RDPDR_SMARTCARD RDPDR_SMARTCARD; @@ -606,6 +605,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_AllowedTlsCiphers 1101 #define FreeRDP_VmConnectMode 1102 #define FreeRDP_NtlmSamFile 1103 +#define FreeRDP_FIPSMode 1104 #define FreeRDP_MstscCookieMode 1152 #define FreeRDP_CookieMaxLength 1153 #define FreeRDP_PreconnectionId 1154 @@ -662,6 +662,8 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_YPan 1553 #define FreeRDP_SmartSizingWidth 1554 #define FreeRDP_SmartSizingHeight 1555 +#define FreeRDP_PercentScreenUseWidth 1556 +#define FreeRDP_PercentScreenUseHeight 1557 #define FreeRDP_SoftwareGdi 1601 #define FreeRDP_LocalConnection 1602 #define FreeRDP_AuthenticationOnly 1603 @@ -689,6 +691,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_GatewayRpcTransport 1994 #define FreeRDP_GatewayHttpTransport 1995 #define FreeRDP_GatewayUdpTransport 1996 +#define FreeRDP_GatewayAccessToken 1997 #define FreeRDP_ProxyType 2015 #define FreeRDP_ProxyHostname 2016 #define FreeRDP_ProxyPort 2017 @@ -807,6 +810,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_SupportEchoChannel 5184 #define FreeRDP_SupportDisplayControl 5185 #define FreeRDP_SupportGeometryTracking 5186 +#define FreeRDP_SupportSSHAgentChannel 5187 /** * FreeRDP Settings Data Structure @@ -1015,7 +1019,8 @@ struct rdp_settings ALIGN64 char* AllowedTlsCiphers; /* 1101 */ ALIGN64 BOOL VmConnectMode; /* 1102 */ ALIGN64 char* NtlmSamFile; /* 1103 */ - UINT64 padding1152[1152 - 1104]; /* 1104 */ + ALIGN64 BOOL FIPSMode; /* 1104 */ + UINT64 padding1152[1152 - 1105]; /* 1105 */ /* Connection Cookie */ ALIGN64 BOOL MstscCookieMode; /* 1152 */ @@ -1098,7 +1103,10 @@ struct rdp_settings ALIGN64 int YPan; /* 1553 */ ALIGN64 UINT32 SmartSizingWidth; /* 1554 */ ALIGN64 UINT32 SmartSizingHeight; /* 1555 */ - UINT64 padding1601[1601 - 1556]; /* 1556 */ + ALIGN64 BOOL PercentScreenUseWidth; /* 1556 */ + ALIGN64 BOOL PercentScreenUseHeight; /* 1557 */ + ALIGN64 BOOL DynamicResolutionUpdate; /* 1558 */ + UINT64 padding1601[1601 - 1559]; /* 1559 */ /* Miscellaneous */ ALIGN64 BOOL SoftwareGdi; /* 1601 */ @@ -1149,7 +1157,8 @@ struct rdp_settings ALIGN64 BOOL GatewayRpcTransport; /* 1994 */ ALIGN64 BOOL GatewayHttpTransport; /* 1995 */ ALIGN64 BOOL GatewayUdpTransport; /* 1996 */ - UINT64 padding2048[2015 - 1997]; /* 1997 */ + ALIGN64 char* GatewayAccessToken; /* 1997 */ + UINT64 padding2015[2015 - 1998]; /* 1998 */ /* Proxy */ ALIGN64 UINT32 ProxyType; /* 2015 */ @@ -1238,7 +1247,8 @@ struct rdp_settings ALIGN64 BOOL MultiTouchGestures; /* 2632 */ ALIGN64 UINT32 KeyboardHook; /* 2633 */ ALIGN64 BOOL HasHorizontalWheel; /* 2634 */ - UINT64 padding2688[2688 - 2635]; /* 2635 */ + ALIGN64 BOOL HasExtendedMouseEvent; /* 2635 */ + UINT64 padding2688[2688 - 2636]; /* 2636 */ /* Brush Capabilities */ ALIGN64 UINT32 BrushSupportLevel; /* 2688 */ @@ -1336,7 +1346,8 @@ struct rdp_settings ALIGN64 BOOL GfxH264; /* 3844 */ ALIGN64 BOOL GfxAVC444; /* 3845 */ ALIGN64 BOOL GfxSendQoeAck; /* 3846 */ - UINT64 padding3904[3904 - 3847]; /* 3847 */ + ALIGN64 BOOL GfxAVC444v2; /* 3847 */ + UINT64 padding3904[3904 - 3848]; /* 3848 */ /** * Caches @@ -1386,7 +1397,8 @@ struct rdp_settings /* Serial and Parallel Port Redirection */ ALIGN64 BOOL RedirectSerialPorts; /* 4672 */ ALIGN64 BOOL RedirectParallelPorts; /* 4673 */ - UINT64 padding4800[4800 - 4674]; /* 4674 */ + ALIGN64 BOOL PreferIPv6OverIPv4; /* 4674 */ + UINT64 padding4800[4800 - 4675]; /* 4675 */ /** * Other Redirection @@ -1417,7 +1429,9 @@ struct rdp_settings ALIGN64 BOOL SupportEchoChannel; /* 5184 */ ALIGN64 BOOL SupportDisplayControl; /* 5185 */ ALIGN64 BOOL SupportGeometryTracking; /* 5186 */ - UINT64 padding5312[5312 - 5187]; /* 5187 */ + ALIGN64 BOOL SupportSSHAgentChannel; /* 5187 */ + ALIGN64 BOOL SupportVideoOptimized; /* 5188 */ + UINT64 padding5312[5312 - 5189]; /* 5189 */ /** * WARNING: End of ABI stable zone! @@ -1437,6 +1451,7 @@ struct rdp_settings ALIGN64 BYTE* SettingsModified; /* byte array marking fields that have been modified from their default value */ ALIGN64 char* ActionScript; + }; typedef struct rdp_settings rdpSettings; diff --git a/include/freerdp/update.h b/include/freerdp/update.h index 04cfd06..35fd7c1 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -42,6 +42,7 @@ typedef struct rdp_update rdpUpdate; #include <freerdp/pointer.h> /* Bitmap Updates */ +#define EX_COMPRESSED_BITMAP_HEADER_PRESENT 0x01 struct _BITMAP_DATA { @@ -91,6 +92,27 @@ struct _PLAY_SOUND_UPDATE typedef struct _PLAY_SOUND_UPDATE PLAY_SOUND_UPDATE; /* Surface Command Updates */ +struct _TS_COMPRESSED_BITMAP_HEADER_EX +{ + UINT32 highUniqueId; + UINT32 lowUniqueId; + UINT64 tmMilliseconds; + UINT64 tmSeconds; +}; +typedef struct _TS_COMPRESSED_BITMAP_HEADER_EX TS_COMPRESSED_BITMAP_HEADER_EX; + +struct _TS_BITMAP_DATA_EX +{ + BYTE bpp; + BYTE flags; + UINT16 codecID; + UINT16 width; + UINT16 height; + UINT32 bitmapDataLength; + TS_COMPRESSED_BITMAP_HEADER_EX exBitmapDataHeader; + BYTE* bitmapData; +}; +typedef struct _TS_BITMAP_DATA_EX TS_BITMAP_DATA_EX; struct _SURFACE_BITS_COMMAND { @@ -99,12 +121,7 @@ struct _SURFACE_BITS_COMMAND UINT32 destTop; UINT32 destRight; UINT32 destBottom; - UINT32 bpp; - UINT32 codecID; - UINT32 width; - UINT32 height; - UINT32 bitmapDataLength; - BYTE* bitmapData; + TS_BITMAP_DATA_EX bmp; BOOL skipCompression; }; typedef struct _SURFACE_BITS_COMMAND SURFACE_BITS_COMMAND; @@ -148,20 +165,21 @@ typedef BOOL (*pSetKeyboardIndicators)(rdpContext* context, UINT16 led_flags); typedef BOOL (*pRefreshRect)(rdpContext* context, BYTE count, const RECTANGLE_16* areas); typedef BOOL (*pSuppressOutput)(rdpContext* context, BYTE allow, const RECTANGLE_16* area); -typedef BOOL (*pRemoteMonitors)(rdpContext* context, UINT32 count, const MONITOR_DEF *monitors); +typedef BOOL (*pRemoteMonitors)(rdpContext* context, UINT32 count, const MONITOR_DEF* monitors); typedef BOOL (*pSurfaceCommand)(rdpContext* context, wStream* s); typedef BOOL (*pSurfaceBits)(rdpContext* context, - const SURFACE_BITS_COMMAND* surfaceBitsCommand); + const SURFACE_BITS_COMMAND* surfaceBitsCommand); typedef BOOL (*pSurfaceFrameMarker)(rdpContext* context, - const SURFACE_FRAME_MARKER* surfaceFrameMarker); + const SURFACE_FRAME_MARKER* surfaceFrameMarker); typedef BOOL (*pSurfaceFrameBits)(rdpContext* context, - const SURFACE_BITS_COMMAND* cmd, BOOL first, - BOOL last, UINT32 frameId); + const 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); -typedef BOOL (*pSetKeyboardImeStatus)(rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode); +typedef BOOL (*pSaveSessionInfo)(rdpContext* context, UINT32 type, void* data); +typedef BOOL (*pSetKeyboardImeStatus)(rdpContext* context, UINT16 imeId, UINT32 imeState, + UINT32 imeConvMode); struct rdp_update { diff --git a/include/freerdp/utils/pcap.h b/include/freerdp/utils/pcap.h index 5276de1..360278a 100644 --- a/include/freerdp/utils/pcap.h +++ b/include/freerdp/utils/pcap.h @@ -59,7 +59,7 @@ struct rdp_pcap FILE* fp; char* name; BOOL write; - int file_size; + INT64 file_size; int record_count; pcap_header header; pcap_record* head; diff --git a/include/freerdp/utils/profiler.h b/include/freerdp/utils/profiler.h index fd61cf1..e80ca1c 100644 --- a/include/freerdp/utils/profiler.h +++ b/include/freerdp/utils/profiler.h @@ -50,24 +50,25 @@ FREERDP_API void profiler_print_footer(void); #ifdef WITH_PROFILER #define IF_PROFILER(then) then -#define PROFILER_DEFINE(prof) PROFILER* prof -#define PROFILER_CREATE(prof,name) prof = profiler_create(name) -#define PROFILER_FREE(prof) profiler_free(prof) -#define PROFILER_ENTER(prof) profiler_enter(prof) -#define PROFILER_EXIT(prof) profiler_exit(prof) -#define PROFILER_PRINT_HEADER profiler_print_header() -#define PROFILER_PRINT(prof) profiler_print(prof) -#define PROFILER_PRINT_FOOTER profiler_print_footer() +#define PROFILER_DEFINE(prof) PROFILER* prof; +#define PROFILER_CREATE(prof,name) prof = profiler_create(name); +#define PROFILER_FREE(prof) profiler_free(prof); +#define PROFILER_ENTER(prof) profiler_enter(prof); +#define PROFILER_EXIT(prof) profiler_exit(prof); +#define PROFILER_PRINT_HEADER profiler_print_header(); +#define PROFILER_PRINT(prof) profiler_print(prof); +#define PROFILER_PRINT_FOOTER profiler_print_footer(); #else #define IF_PROFILER(then) do { } while (0) -#define PROFILER_DEFINE(prof) void* prof -#define PROFILER_CREATE(prof,name) do { } while (0) -#define PROFILER_FREE(prof) do { } while (0) -#define PROFILER_ENTER(prof) do { } while (0) -#define PROFILER_EXIT(prof) do { } while (0) -#define PROFILER_PRINT_HEADER do { } while (0) -#define PROFILER_PRINT(prof) do { } while (0) -#define PROFILER_PRINT_FOOTER do { } while (0) + +#define PROFILER_DEFINE(prof) +#define PROFILER_CREATE(prof,name) do { } while (0); +#define PROFILER_FREE(prof) do { } while (0); +#define PROFILER_ENTER(prof) do { } while (0); +#define PROFILER_EXIT(prof) do { } while (0); +#define PROFILER_PRINT_HEADER do { } while (0); +#define PROFILER_PRINT(prof) do { } while (0); +#define PROFILER_PRINT_FOOTER do { } while (0); #endif #endif /* FREERDP_UTILS_PROFILER_H */ diff --git a/libfreerdp/CMakeLists.txt b/libfreerdp/CMakeLists.txt index 605b5f2..e6095f6 100644 --- a/libfreerdp/CMakeLists.txt +++ b/libfreerdp/CMakeLists.txt @@ -130,7 +130,8 @@ set(CODEC_SRCS codec/zgfx.c codec/clear.c codec/jpeg.c - codec/h264.c) + codec/h264.c + codec/yuv.c) set(CODEC_SSE2_SRCS codec/rfx_sse2.c @@ -145,7 +146,7 @@ set(CODEC_NEON_SRCS if(WITH_SSE2) set(CODEC_SRCS ${CODEC_SRCS} ${CODEC_SSE2_SRCS}) - if(CMAKE_COMPILER_IS_GNUCC) + if(CMAKE_COMPILER_IS_GNUCC OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang") set_source_files_properties(${CODEC_SSE2_SRCS} PROPERTIES COMPILE_FLAGS "-msse2" ) endif() @@ -210,17 +211,35 @@ set(PRIMITIVES_SRCS primitives/primitives.c primitives/prim_internal.h) -set(PRIMITIVES_OPT_SRCS - primitives/prim_add_opt.c - primitives/prim_andor_opt.c - primitives/prim_alphaComp_opt.c +set(PRIMITIVES_SSE2_SRCS primitives/prim_colors_opt.c - primitives/prim_set_opt.c - primitives/prim_shift_opt.c + primitives/prim_set_opt.c) + +set(PRIMITIVES_SSE3_SRCS + primitives/prim_add_opt.c + primitives/prim_alphaComp_opt.c + primitives/prim_andor_opt.c + primitives/prim_shift_opt.c) + +set(PRIMITIVES_SSSE3_SRCS primitives/prim_sign_opt.c - primitives/prim_YUV_opt.c primitives/prim_YCoCg_opt.c) +if (WITH_SSE2) + set(PRIMITIVES_SSSE3_SRCS ${PRIMITIVES_SSSE3_SRCS} + primitives/prim_YUV_ssse3.c) +endif() + +if (WITH_NEON) + set(PRIMITIVES_SSSE3_SRCS ${PRIMITIVES_SSSE3_SRCS} + primitives/prim_YUV_neon.c) +endif() + +set(PRIMITIVES_OPT_SRCS + ${PRIMITIVES_SSE2_SRCS} + ${PRIMITIVES_SSE3_SRCS} + ${PRIMITIVES_SSSE3_SRCS}) + freerdp_definition_add(-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}) ### IPP Variable debugging @@ -233,24 +252,27 @@ if(WITH_IPP) endif() if(WITH_SSE2) - if(CMAKE_COMPILER_IS_GNUCC) - set(OPTIMIZATION "${OPTIMIZATION} -msse2 -mssse3 -Wdeclaration-after-statement") + if(CMAKE_COMPILER_IS_GNUCC OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang") + set_source_files_properties(${PRIMITIVES_SSE2_SRCS} + PROPERTIES COMPILE_FLAGS "${OPTIMIZATION} -msse2") + set_source_files_properties(${PRIMITIVES_SSE3_SRCS} + PROPERTIES COMPILE_FLAGS "${OPTIMIZATION} -msse3") + set_source_files_properties(${PRIMITIVES_SSSE3_SRCS} + PROPERTIES COMPILE_FLAGS "${OPTIMIZATION} -mssse3") endif() if(MSVC) - set(OPTIMIZATION "${OPTIMIZATION} /arch:SSE2") + set_source_files_properties(${PRIMITIVES_OPT_SRCS} + PROPERTIES COMPILE_FLAGS "${OPTIMIZATION} /arch:SSE2") endif() elseif(WITH_NEON) if(CMAKE_COMPILER_IS_GNUCC) - set(OPTIMIZATION "${OPTIMIZATION} -mfpu=neon") + set_source_files_properties(${PRIMITIVES_OPT_SRCS} + PROPERTIES COMPILE_FLAGS "${OPTIMIZATION} -mfpu=neon") endif() # TODO: Add MSVC equivalent endif() -if(DEFINED OPTIMIZATION) - set_source_files_properties(${PRIMITIVES_OPT_SRCS} PROPERTIES COMPILE_FLAGS ${OPTIMIZATION}) -endif() - set(PRIMITIVES_SRCS ${PRIMITIVES_SRCS} ${PRIMITIVES_OPT_SRCS}) freerdp_module_add(${PRIMITIVES_SRCS}) diff --git a/libfreerdp/cache/glyph.c b/libfreerdp/cache/glyph.c index 0292e0e..80cfa6b 100644 --- a/libfreerdp/cache/glyph.c +++ b/libfreerdp/cache/glyph.c @@ -688,7 +688,6 @@ rdpGlyphCache* glyph_cache_new(rdpSettings* settings) if (!glyphCache) return NULL; - WLog_Init(); glyphCache->log = WLog_Get("com.freerdp.cache.glyph"); glyphCache->settings = settings; glyphCache->context = ((freerdp*) settings->instance)->update->context; diff --git a/libfreerdp/cache/offscreen.c b/libfreerdp/cache/offscreen.c index df79fc8..a07012d 100644 --- a/libfreerdp/cache/offscreen.c +++ b/libfreerdp/cache/offscreen.c @@ -60,7 +60,7 @@ static BOOL update_gdi_create_offscreen_bitmap(rdpContext* context, if (!bitmap->New(context, bitmap)) { - free(bitmap); + Bitmap_Free(context, bitmap); return FALSE; } @@ -101,6 +101,9 @@ static BOOL update_gdi_switch_surface(rdpContext* context, { rdpBitmap* bmp; bmp = offscreen_cache_get(cache->offscreen, switchSurface->bitmapId); + if (bmp == NULL) + return FALSE; + bitmap->SetSurface(context, bmp, FALSE); } diff --git a/libfreerdp/codec/bitmap.c b/libfreerdp/codec/bitmap.c index aeb8e93..c260309 100644 --- a/libfreerdp/codec/bitmap.c +++ b/libfreerdp/codec/bitmap.c @@ -435,8 +435,8 @@ #define TEST_MIX \ ((last_line == 0 && pixel == mix) || \ (last_line != 0 && pixel == (ypixel ^ mix))) -#define TEST_FOM (TEST_FILL || TEST_MIX) -#define TEST_COLOR (pixel == last_pixel) +#define TEST_FOM TEST_FILL || TEST_MIX +#define TEST_COLOR pixel == last_pixel #define TEST_BICOLOR \ ( \ (pixel != last_pixel) && \ @@ -470,7 +470,7 @@ int freerdp_bitmap_compress(const char* srcData, int width, int height, int bicolor2; int bicolor_spin; int end; - int i; + size_t i; int out_count; int ypixel; int last_ypixel; @@ -559,7 +559,7 @@ int freerdp_bitmap_compress(const char* srcData, int width, int height, mix_count = 0; } - if (!TEST_COLOR) + if (!(TEST_COLOR)) { if (color_count > 3 && color_count >= fill_count && @@ -607,7 +607,7 @@ int freerdp_bitmap_compress(const char* srcData, int width, int height, bicolor_spin = 0; } - if (!TEST_FOM) + if (!(TEST_FOM)) { if (fom_count > 3 && fom_count >= fill_count && @@ -852,7 +852,7 @@ int freerdp_bitmap_compress(const char* srcData, int width, int height, mix_count = 0; } - if (!TEST_COLOR) + if (!(TEST_COLOR)) { if (color_count > 3 && color_count >= fill_count && @@ -900,7 +900,7 @@ int freerdp_bitmap_compress(const char* srcData, int width, int height, bicolor_spin = 0; } - if (!TEST_FOM) + if (!(TEST_FOM)) { if (fom_count > 3 && fom_count >= fill_count && diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c index 6121428..876e8dd 100644 --- a/libfreerdp/codec/clear.c +++ b/libfreerdp/codec/clear.c @@ -176,7 +176,7 @@ static BOOL clear_decompress_subcode_rlex(wStream* s, Stream_Read_UINT8(s, b); Stream_Read_UINT8(s, g); Stream_Read_UINT8(s, r); - palette[i] = GetColor(DstFormat, r, g, b, 0xFF); + palette[i] = FreeRDPGetColor(DstFormat, r, g, b, 0xFF); } pixelIndex = 0; @@ -393,7 +393,7 @@ static BOOL clear_decompress_residual_data(CLEAR_CONTEXT* clear, Stream_Read_UINT8(s, r); Stream_Read_UINT8(s, runLengthFactor); suboffset += 4; - color = GetColor(clear->format, r, g, b, 0xFF); + color = FreeRDPGetColor(clear->format, r, g, b, 0xFF); if (runLengthFactor >= 0xFF) { @@ -655,7 +655,7 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, Stream_Read_UINT8(s, g); Stream_Read_UINT8(s, r); suboffset += 11; - colorBkg = GetColor(clear->format, r, g, b, 0xFF); + colorBkg = FreeRDPGetColor(clear->format, r, g, b, 0xFF); if (xEnd < xStart) { @@ -766,7 +766,7 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, Stream_Read_UINT8(s, b); Stream_Read_UINT8(s, g); Stream_Read_UINT8(s, r); - color = GetColor(clear->format, r, g, b, 0xFF); + color = FreeRDPGetColor(clear->format, r, g, b, 0xFF); if (!WriteColor(dstBuffer, clear->format, color)) return FALSE; @@ -888,7 +888,7 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, BYTE* pDstPixel8 = &pDstData[((nYDstRel + y) * nDstStep) + ((nXDstRel + i) * GetBytesPerPixel(DstFormat))]; UINT32 color = ReadColor(pSrcPixel, clear->format); - color = ConvertColor(color, clear->format, + color = FreeRDPConvertColor(color, clear->format, DstFormat, NULL); if (!WriteColor(pDstPixel8, DstFormat, color)) diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 851071c..15d8d2f 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -142,7 +142,7 @@ static INLINE UINT32 freerdp_image_inverted_pointer_color(UINT32 x, UINT32 y, #else BYTE fill = 0x00; #endif - return GetColor(format, fill, fill, fill, 0xFF); + return FreeRDPGetColor(format, fill, fill, fill, 0xFF); } /** @@ -237,11 +237,11 @@ BOOL freerdp_image_copy_from_pointer_data( } if (!andPixel && !xorPixel) - color = GetColor(DstFormat, 0, 0, 0, 0xFF); /* black */ + color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0xFF); /* black */ else if (!andPixel && xorPixel) - color = GetColor(DstFormat, 0xFF, 0xFF, 0xFF, 0xFF); /* white */ + color = FreeRDPGetColor(DstFormat, 0xFF, 0xFF, 0xFF, 0xFF); /* white */ else if (andPixel && !xorPixel) - color = GetColor(DstFormat, 0, 0, 0, 0); /* transparent */ + color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0); /* transparent */ else if (andPixel && xorPixel) color = freerdp_image_inverted_pointer_color(x, y, DstFormat); /* inverted */ @@ -325,7 +325,7 @@ BOOL freerdp_image_copy_from_pointer_data( xorPixel = ReadColor(xorBits, pixelFormat); } - xorPixel = ConvertColor(xorPixel, + xorPixel = FreeRDPConvertColor(xorPixel, pixelFormat, PIXEL_FORMAT_ARGB32, palette); @@ -351,7 +351,7 @@ BOOL freerdp_image_copy_from_pointer_data( xorPixel = freerdp_image_inverted_pointer_color(x, y, PIXEL_FORMAT_ARGB32); } - color = ConvertColor(xorPixel, PIXEL_FORMAT_ARGB32, + color = FreeRDPConvertColor(xorPixel, PIXEL_FORMAT_ARGB32, DstFormat, palette); WriteColor(pDstPixel, DstFormat, color); pDstPixel += GetBytesPerPixel(DstFormat); @@ -526,7 +526,7 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 dstColor; UINT32 color = ReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); - dstColor = ConvertColor(color, SrcFormat, DstFormat, palette); + dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); WriteColor(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor); } } diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index 7777310..322c640 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -32,8 +32,12 @@ #include <freerdp/codec/h264.h> #include <freerdp/log.h> +#include "h264.h" + #define TAG FREERDP_TAG("codec") +static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, DWORD nDstHeight); + BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT32 height) { if (!h264) @@ -42,15 +46,20 @@ BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT3 if (stride == 0) stride = width; + if (stride % 16 != 0) + stride += 16 - stride % 16; + + if (height % 16 != 0) + height += 16 - height % 16; + if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2] || - (width != h264->width) || (height != h264->height) || (stride != h264->iStride[0])) + (width != h264->width) || (height != h264->height) || (stride != h264->iStride[0])) { h264->iStride[0] = stride; h264->iStride[1] = (stride + 1) / 2; h264->iStride[2] = (stride + 1) / 2; h264->width = width; h264->height = height; - _aligned_free(h264->pYUVData[0]); _aligned_free(h264->pYUVData[1]); _aligned_free(h264->pYUVData[2]); @@ -171,7 +180,6 @@ INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize return -1001; status = h264->subsystem->Decompress(h264, pSrcData, SrcSize); - if (status == 0) return 1; @@ -203,19 +211,73 @@ INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, roi.width = nSrcWidth; roi.height = nSrcHeight; + if (prims->RGBToYUV420_8u_P3AC4R(pSrcData, SrcFormat, nSrcStep, h264->pYUVData, h264->iStride, - &roi) != PRIMITIVES_SUCCESS) + &roi) != PRIMITIVES_SUCCESS) return -1; - return h264->subsystem->Compress(h264, ppDstData, pDstSize); + return h264->subsystem->Compress(h264, h264->pYUVData, h264->iStride, ppDstData, pDstSize); } INT32 avc444_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, UINT32 nSrcStep, UINT32 nSrcWidth, UINT32 nSrcHeight, - BYTE* op, BYTE** ppDstData, UINT32* pDstSize, + BYTE version, BYTE* op, BYTE** ppDstData, UINT32* pDstSize, BYTE** ppAuxDstData, UINT32* pAuxDstSize) { - return -1; + prim_size_t roi; + primitives_t* prims = primitives_get(); + BYTE* coded; + UINT32 codedSize; + + if (!h264) + return -1; + + if (!h264->subsystem->Compress) + return -1; + + if (!avc420_ensure_buffer(h264, nSrcStep, nSrcWidth, nSrcHeight)) + return -1; + + if (!avc444_ensure_buffer(h264, nSrcHeight)) + return -1; + + roi.width = nSrcWidth; + roi.height = nSrcHeight; + + switch (version) + { + case 1: + if (prims->RGBToAVC444YUV(pSrcData, SrcFormat, nSrcStep, h264->pYUV444Data, h264->iStride, + h264->pYUVData, h264->iStride, &roi) != PRIMITIVES_SUCCESS) + return -1; + + break; + + case 2: + if (prims->RGBToAVC444YUVv2(pSrcData, SrcFormat, nSrcStep, h264->pYUV444Data, h264->iStride, + h264->pYUVData, h264->iStride, &roi) != PRIMITIVES_SUCCESS) + return -1; + + break; + + default: + return -1; + } + + if (h264->subsystem->Compress(h264, h264->pYUV444Data, h264->iStride, &coded, &codedSize) < 0) + return -1; + + memcpy(h264->lumaData, coded, codedSize); + *ppDstData = h264->lumaData; + *pDstSize = codedSize; + + if (h264->subsystem->Compress(h264, h264->pYUVData, h264->iStride, &coded, &codedSize) < 0) + return -1; + + *ppAuxDstData = coded; + *pAuxDstSize = codedSize; + *op = 0; + return 0; } static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, @@ -243,25 +305,33 @@ static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, memset(ppYUVDstData[x], 0, piDstSize[x]); } + + _aligned_free(h264->lumaData); + h264->lumaData = _aligned_malloc(piDstSize[0] * 4, 16); } for (x = 0; x < 3; x++) { if (!ppYUVDstData[x] || (piDstSize[x] == 0) || (piDstStride[x] == 0)) { - WLog_ERR(TAG, "YUV buffer not initialized! check your decoder settings"); + WLog_Print(h264->log, WLOG_ERROR, "YUV buffer not initialized! check your decoder settings"); goto fail; } } + if (!h264->lumaData) + goto fail; + return TRUE; fail: _aligned_free(ppYUVDstData[0]); _aligned_free(ppYUVDstData[1]); _aligned_free(ppYUVDstData[2]); + _aligned_free(h264->lumaData); ppYUVDstData[0] = NULL; ppYUVDstData[1] = NULL; ppYUVDstData[2] = NULL; + h264->lumaData = NULL; return FALSE; } @@ -400,32 +470,31 @@ INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op, break; } - WLog_INFO(TAG, - "luma=%"PRIu64" [avg=%lf] chroma=%"PRIu64" [avg=%lf] combined=%"PRIu64" [avg=%lf]", - op1, op1sum, op2, op2sum, op3, op3sum); + WLog_Print(h264->log, WLOG_INFO, + "luma=%"PRIu64" [avg=%lf] chroma=%"PRIu64" [avg=%lf] combined=%"PRIu64" [avg=%lf]", + op1, op1sum, op2, op2sum, op3, op3sum); #endif return status; } #define MAX_SUBSYSTEMS 10 static INIT_ONCE subsystems_once = INIT_ONCE_STATIC_INIT; -static H264_CONTEXT_SUBSYSTEM *subSystems[MAX_SUBSYSTEMS]; +static H264_CONTEXT_SUBSYSTEM* subSystems[MAX_SUBSYSTEMS]; #if defined(_WIN32) && defined(WITH_MEDIA_FOUNDATION) extern H264_CONTEXT_SUBSYSTEM g_Subsystem_MF; #endif -static BOOL CALLBACK h264_register_subsystems(PINIT_ONCE once, PVOID param, PVOID *context) { +static BOOL CALLBACK h264_register_subsystems(PINIT_ONCE once, PVOID param, PVOID* context) +{ int i = 0; ZeroMemory(subSystems, sizeof(subSystems)); - #if defined(_WIN32) && defined(WITH_MEDIA_FOUNDATION) { subSystems[i] = &g_Subsystem_MF; i++; } #endif - #ifdef WITH_OPENH264 { extern H264_CONTEXT_SUBSYSTEM g_Subsystem_OpenH264; @@ -433,7 +502,6 @@ static BOOL CALLBACK h264_register_subsystems(PINIT_ONCE once, PVOID param, PVOI i++; } #endif - #ifdef WITH_FFMPEG { extern H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec; @@ -441,7 +509,6 @@ static BOOL CALLBACK h264_register_subsystems(PINIT_ONCE once, PVOID param, PVOI i++; } #endif - #ifdef WITH_X264 { extern H264_CONTEXT_SUBSYSTEM g_Subsystem_x264; @@ -449,7 +516,6 @@ static BOOL CALLBACK h264_register_subsystems(PINIT_ONCE once, PVOID param, PVOI i++; } #endif - return i > 0; } @@ -461,14 +527,19 @@ BOOL h264_context_init(H264_CONTEXT* h264) if (!h264) return FALSE; - h264->subsystem = NULL; + h264->log = WLog_Get(TAG); + if (!h264->log) + return FALSE; + + h264->subsystem = NULL; InitOnceExecuteOnce(&subsystems_once, h264_register_subsystems, NULL, NULL); for (i = 0; i < MAX_SUBSYSTEMS; i++) { H264_CONTEXT_SUBSYSTEM* subsystem = subSystems[i]; - if (!subsystem->Init) + + if (!subsystem || !subsystem->Init) break; if (subsystem->Init(h264)) @@ -525,6 +596,7 @@ void h264_context_free(H264_CONTEXT* h264) _aligned_free(h264->pYUV444Data[0]); _aligned_free(h264->pYUV444Data[1]); _aligned_free(h264->pYUV444Data[2]); + _aligned_free(h264->lumaData); free(h264); } } diff --git a/libfreerdp/codec/h264.h b/libfreerdp/codec/h264.h new file mode 100644 index 0000000..f87d17a --- /dev/null +++ b/libfreerdp/codec/h264.h @@ -0,0 +1,31 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * RemoteFX Codec Library - Decode + * + * Copyright 2018 Armin Novak <anovak@thincast.com> + * Copyright 2018 Thincast Technologies GmbH + * + * 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_LIB_CODEC_H264_H +#define FREERDP_LIB_CODEC_H264_H + +#include <freerdp/api.h> +#include <freerdp/codec/h264.h> + +FREERDP_LOCAL BOOL avc420_ensure_buffer(H264_CONTEXT* h264, + UINT32 stride, UINT32 width, UINT32 height); + +#endif /* FREERDP_LIB_CODEC_H264_H */ + diff --git a/libfreerdp/codec/h264_ffmpeg.c b/libfreerdp/codec/h264_ffmpeg.c index 847f359..8d75398 100644 --- a/libfreerdp/codec/h264_ffmpeg.c +++ b/libfreerdp/codec/h264_ffmpeg.c @@ -18,77 +18,258 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <winpr/wlog.h> #include <freerdp/log.h> #include <freerdp/codec/h264.h> #include <libavcodec/avcodec.h> -#include <libavutil/avutil.h> +#include <libavutil/opt.h> -#define TAG FREERDP_TAG("codec") - -#warning "FFMPEG does not support H264 encoding (GFX H264 server mode). Please review your configuration!" +#ifdef WITH_VAAPI +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 9, 0) +#include <libavutil/hwcontext.h> +#else +#pragma warning You have asked for VA-API decoding, but your version of libavutil is too old! Disabling. +#undef WITH_VAAPI +#endif +#endif /* Fallback support for older libavcodec versions */ #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100) #define AV_CODEC_ID_H264 CODEC_ID_H264 #endif +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 34, 2) +#define AV_CODEC_FLAG_LOOP_FILTER CODEC_FLAG_LOOP_FILTER +#define AV_CODEC_CAP_TRUNCATED CODEC_CAP_TRUNCATED +#define AV_CODEC_FLAG_TRUNCATED CODEC_FLAG_TRUNCATED +#endif + +#if LIBAVUTIL_VERSION_MAJOR < 52 +#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P +#endif + +/* Ubuntu 14.04 ships without the functions provided by avutil, + * so define error to string methods here. */ +#if !defined(av_err2str) +static inline char* error_string(char* errbuf, size_t errbuf_size, int errnum) +{ + av_strerror(errnum, errbuf, errbuf_size); + return errbuf; +} + +#define av_err2str(errnum) \ + error_string((char[64]){0}, 64, errnum) +#endif + +#ifdef WITH_VAAPI +#define VAAPI_DEVICE "/dev/dri/renderD128" +#endif + struct _H264_CONTEXT_LIBAVCODEC { - AVCodec* codec; - AVCodecContext* codecContext; + AVCodec* codecDecoder; + AVCodecContext* codecDecoderContext; + AVCodec* codecEncoder; + AVCodecContext* codecEncoderContext; AVCodecParserContext* codecParser; AVFrame* videoFrame; + AVPacket packet; +#ifdef WITH_VAAPI + AVBufferRef* hwctx; + AVFrame* hwVideoFrame; + enum AVPixelFormat hw_pix_fmt; +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100) + AVBufferRef* hw_frames_ctx; +#endif +#endif }; typedef struct _H264_CONTEXT_LIBAVCODEC H264_CONTEXT_LIBAVCODEC; +static void libavcodec_destroy_encoder(H264_CONTEXT* h264) +{ + H264_CONTEXT_LIBAVCODEC* sys; + + if (!h264 || !h264->subsystem) + return; + + sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData; + + if (sys->codecEncoderContext) + { + avcodec_close(sys->codecEncoderContext); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100) + avcodec_free_context(&sys->codecEncoderContext); +#else + av_free(sys->codecEncoderContext); +#endif + } + + sys->codecEncoder = NULL; + sys->codecEncoderContext = NULL; +} + +static BOOL libavcodec_create_encoder(H264_CONTEXT* h264) +{ + BOOL recreate = FALSE; + H264_CONTEXT_LIBAVCODEC* sys; + + if (!h264 || !h264->subsystem) + return FALSE; + + sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData; + recreate = !sys->codecEncoder || !sys->codecEncoderContext; + + if (sys->codecEncoderContext) + { + if ((sys->codecEncoderContext->width != h264->width) || + (sys->codecEncoderContext->height != h264->height)) + recreate = TRUE; + } + + if (!recreate) + return TRUE; + + libavcodec_destroy_encoder(h264); + sys->codecEncoder = avcodec_find_encoder(AV_CODEC_ID_H264); + + if (!sys->codecEncoder) + goto EXCEPTION; + + sys->codecEncoderContext = avcodec_alloc_context3(sys->codecEncoder); + + if (!sys->codecEncoderContext) + goto EXCEPTION; + + switch (h264->RateControlMode) + { + case H264_RATECONTROL_VBR: + sys->codecEncoderContext->bit_rate = h264->BitRate; + break; + + case H264_RATECONTROL_CQP: + /* TODO: sys->codecEncoderContext-> = h264->QP; */ + break; + + default: + break; + } + + sys->codecEncoderContext->width = h264->width; + sys->codecEncoderContext->height = h264->height; + sys->codecEncoderContext->delay = 0; +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 13, 100) + sys->codecEncoderContext->framerate = (AVRational) + { + h264->FrameRate, 1 + }; +#endif + sys->codecEncoderContext->time_base = (AVRational) + { + 1, h264->FrameRate + }; + av_opt_set(sys->codecEncoderContext, "preset", "medium", AV_OPT_SEARCH_CHILDREN); + av_opt_set(sys->codecEncoderContext, "tune", "zerolatency", AV_OPT_SEARCH_CHILDREN); + sys->codecEncoderContext->flags |= AV_CODEC_FLAG_LOOP_FILTER; + sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_YUV420P; + + if (avcodec_open2(sys->codecEncoderContext, sys->codecEncoder, NULL) < 0) + goto EXCEPTION; + + return TRUE; +EXCEPTION: + libavcodec_destroy_encoder(h264); + return FALSE; +} + static int libavcodec_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize) { int status; int gotFrame = 0; - AVPacket packet; H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*) h264->pSystemData; BYTE** pYUVData = h264->pYUVData; UINT32* iStride = h264->iStride; - av_init_packet(&packet); - packet.data = (BYTE*)pSrcData; - packet.size = SrcSize; + av_init_packet(&sys->packet); + sys->packet.data = (BYTE*)pSrcData; + sys->packet.size = SrcSize; /* avcodec_decode_video2 is deprecated with libavcodec 57.48.101 */ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101) - status = avcodec_send_packet(sys->codecContext, &packet); + status = avcodec_send_packet(sys->codecDecoderContext, &sys->packet); if (status < 0) { - WLog_ERR(TAG, "Failed to decode video frame (status=%d)", status); + WLog_Print(h264->log, WLOG_ERROR, "Failed to decode video frame (status=%d)", status); return -1; } + sys->videoFrame->format = AV_PIX_FMT_YUV420P; + do { - status = avcodec_receive_frame(sys->codecContext, sys->videoFrame); +#ifdef WITH_VAAPI + status = avcodec_receive_frame(sys->codecDecoderContext, + sys->hwctx ? sys->hwVideoFrame : sys->videoFrame); +#else + status = avcodec_receive_frame(sys->codecDecoderContext, sys->videoFrame); +#endif } while (status == AVERROR(EAGAIN)); gotFrame = (status == 0); #else - status = avcodec_decode_video2(sys->codecContext, sys->videoFrame, &gotFrame, - &packet); +#ifdef WITH_VAAPI + status = avcodec_decode_video2(sys->codecDecoderContext, + sys->hwctx ? sys->hwVideoFrame : sys->videoFrame, &gotFrame, + &sys->packet); +#else + status = avcodec_decode_video2(sys->codecDecoderContext, sys->videoFrame, &gotFrame, + &sys->packet); +#endif #endif if (status < 0) { - WLog_ERR(TAG, "Failed to decode video frame (status=%d)", status); + WLog_Print(h264->log, WLOG_ERROR, "Failed to decode video frame (status=%d)", status); return -1; } +#ifdef WITH_VAAPI + + if (sys->hwctx) + { + if (sys->hwVideoFrame->format == sys->hw_pix_fmt) + { + sys->videoFrame->width = sys->hwVideoFrame->width; + sys->videoFrame->height = sys->hwVideoFrame->height; + status = av_hwframe_transfer_data(sys->videoFrame, sys->hwVideoFrame, 0); + } + else + { + status = av_frame_copy(sys->videoFrame, sys->hwVideoFrame); + } + } + + gotFrame = (status == 0); + + if (status < 0) + { + WLog_Print(h264->log, WLOG_ERROR, "Failed to transfer video frame (status=%d) (%s)", status, + av_err2str(status)); + return -1; + } + +#endif #if 0 - WLog_INFO(TAG, - "libavcodec_decompress: frame decoded (status=%d, gotFrame=%d, width=%d, height=%d, Y=[%p,%d], U=[%p,%d], V=[%p,%d])", - status, gotFrame, sys->videoFrame->width, sys->videoFrame->height, - (void*) sys->videoFrame->data[0], sys->videoFrame->linesize[0], - (void*) sys->videoFrame->data[1], sys->videoFrame->linesize[1], - (void*) sys->videoFrame->data[2], sys->videoFrame->linesize[2]); + WLog_Print(h264->log, WLOG_INFO, + "libavcodec_decompress: frame decoded (status=%d, gotFrame=%d, width=%d, height=%d, Y=[%p,%d], U=[%p,%d], V=[%p,%d])", + status, gotFrame, sys->videoFrame->width, sys->videoFrame->height, + (void*) sys->videoFrame->data[0], sys->videoFrame->linesize[0], + (void*) sys->videoFrame->data[1], sys->videoFrame->linesize[1], + (void*) sys->videoFrame->data[2], sys->videoFrame->linesize[2]); #endif if (gotFrame) @@ -108,9 +289,105 @@ static int libavcodec_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, return 1; } -static int libavcodec_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize) +static int libavcodec_compress(H264_CONTEXT* h264, const BYTE** pSrcYuv, const UINT32* pStride, + BYTE** ppDstData, UINT32* pDstSize) { - return -1; + int status; + int gotFrame = 0; + H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*) h264->pSystemData; + + if (!libavcodec_create_encoder(h264)) + return -1; + +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 39, 100) + av_packet_unref(&sys->packet); +#else + av_free(sys->packet.data); +#endif + av_init_packet(&sys->packet); + sys->packet.data = NULL; + sys->packet.size = 0; + sys->videoFrame->format = sys->codecEncoderContext->pix_fmt; + sys->videoFrame->width = sys->codecEncoderContext->width; + sys->videoFrame->height = sys->codecEncoderContext->height; +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 48, 100) + sys->videoFrame->colorspace = AVCOL_SPC_BT709; +#endif +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 92, 100) + sys->videoFrame->chroma_location = AVCHROMA_LOC_LEFT; +#endif + sys->videoFrame->data[0] = (uint8_t*)pSrcYuv[0]; + sys->videoFrame->data[1] = (uint8_t*)pSrcYuv[1]; + sys->videoFrame->data[2] = (uint8_t*)pSrcYuv[2]; + sys->videoFrame->linesize[0] = (int)pStride[0]; + sys->videoFrame->linesize[1] = (int)pStride[1]; + sys->videoFrame->linesize[2] = (int)pStride[2]; + sys->videoFrame->pts++; + /* avcodec_encode_video2 is deprecated with libavcodec 57.48.101 */ +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101) + status = avcodec_send_frame(sys->codecEncoderContext, sys->videoFrame); + + if (status < 0) + { + WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])", + av_err2str(status), status); + return -1; + } + + status = avcodec_receive_packet(sys->codecEncoderContext, + &sys->packet); + + if (status < 0) + { + WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])", + av_err2str(status), status); + return -1; + } + + gotFrame = (status == 0); +#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100) + + do + { + status = avcodec_encode_video2(sys->codecEncoderContext, + &sys->packet, + sys->videoFrame, &gotFrame); + } + while ((status >= 0) && (gotFrame == 0)); + +#else + sys->packet.size = avpicture_get_size(sys->codecDecoderContext->pix_fmt, + sys->codecDecoderContext->width, + sys->codecDecoderContext->height); + sys->packet.data = av_malloc(sys->packet.size); + + if (!sys->packet.data) + status = -1; + else + { + status = avcodec_encode_video(sys->codecDecoderContext, sys->packet.data, + sys->packet.size, sys->videoFrame); + } + +#endif + + if (status < 0) + { + WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])", + av_err2str(status), status); + return -1; + } + + *ppDstData = sys->packet.data; + *pDstSize = sys->packet.size; + + if (!gotFrame) + { + WLog_Print(h264->log, WLOG_ERROR, "Did not get frame! (%s [%d])", av_err2str(status), status); + return -2; + } + + return 1; } static void libavcodec_uninit(H264_CONTEXT* h264) @@ -129,25 +406,100 @@ static void libavcodec_uninit(H264_CONTEXT* h264) #endif } - if (sys->codecParser) - { - av_parser_close(sys->codecParser); - } +#ifdef WITH_VAAPI - if (sys->codecContext) + if (sys->hwVideoFrame) { - avcodec_close(sys->codecContext); -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100) - avcodec_free_context(&sys->codecContext); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102) + av_frame_free(&sys->hwVideoFrame); #else - av_free(sys->codecContext); + av_free(sys->hwVideoFrame); #endif } + if (sys->hwctx) + { + av_buffer_unref(&sys->hwctx); + } + +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100) + + if (sys->hw_frames_ctx) + { + av_buffer_unref(&sys->hw_frames_ctx); + } + +#endif +#endif + + if (sys->codecParser) + av_parser_close(sys->codecParser); + + if (sys->codecDecoderContext) + { + avcodec_close(sys->codecDecoderContext); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100) + avcodec_free_context(&sys->codecDecoderContext); +#else + av_free(sys->codecDecoderContext); +#endif + } + + libavcodec_destroy_encoder(h264); free(sys); h264->pSystemData = NULL; } +#ifdef WITH_VAAPI +static enum AVPixelFormat libavcodec_get_format(struct AVCodecContext* ctx, + const enum AVPixelFormat* fmts) +{ + H264_CONTEXT* h264 = (H264_CONTEXT*) ctx->opaque; + H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*) h264->subsystem; + const enum AVPixelFormat* p; + + for (p = fmts; *p != AV_PIX_FMT_NONE; p++) + { + if (*p == sys->hw_pix_fmt) + { +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100) + sys->hw_frames_ctx = av_hwframe_ctx_alloc(sys->hwctx); + + if (!sys->hw_frames_ctx) + { + return AV_PIX_FMT_NONE; + } + + sys->codecDecoderContext->pix_fmt = *p; + AVHWFramesContext* frames = (AVHWFramesContext*) sys->hw_frames_ctx->data; + frames->format = *p; + frames->height = sys->codecDecoderContext->coded_height; + frames->width = sys->codecDecoderContext->coded_width; + frames->sw_format = (sys->codecDecoderContext->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? + AV_PIX_FMT_P010 : AV_PIX_FMT_NV12); + frames->initial_pool_size = 20; + + if (sys->codecDecoderContext->active_thread_type & FF_THREAD_FRAME) + frames->initial_pool_size += sys->codecDecoderContext->thread_count; + + int err = av_hwframe_ctx_init(sys->hw_frames_ctx); + + if (err < 0) + { + WLog_Print(h264->log, WLOG_ERROR, "Could not init hwframes context: %s", av_err2str(err)); + return AV_PIX_FMT_NONE; + } + + sys->codecDecoderContext->hw_frames_ctx = av_buffer_ref(sys->hw_frames_ctx); +#endif + return *p; + } + } + + return AV_PIX_FMT_NONE; +} +#endif + static BOOL libavcodec_init(H264_CONTEXT* h264) { H264_CONTEXT_LIBAVCODEC* sys; @@ -160,53 +512,95 @@ static BOOL libavcodec_init(H264_CONTEXT* h264) h264->pSystemData = (void*) sys; avcodec_register_all(); - sys->codec = avcodec_find_decoder(AV_CODEC_ID_H264); - if (!sys->codec) + if (!h264->Compressor) { - WLog_ERR(TAG, "Failed to find libav H.264 codec"); - goto EXCEPTION; - } + sys->codecDecoder = avcodec_find_decoder(AV_CODEC_ID_H264); - sys->codecContext = avcodec_alloc_context3(sys->codec); + if (!sys->codecDecoder) + { + WLog_Print(h264->log, WLOG_ERROR, "Failed to find libav H.264 codec"); + goto EXCEPTION; + } - if (!sys->codecContext) - { - WLog_ERR(TAG, "Failed to allocate libav codec context"); - goto EXCEPTION; - } + sys->codecDecoderContext = avcodec_alloc_context3(sys->codecDecoder); - if (sys->codec->capabilities & CODEC_CAP_TRUNCATED) - { - sys->codecContext->flags |= CODEC_FLAG_TRUNCATED; - } + if (!sys->codecDecoderContext) + { + WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav codec context"); + goto EXCEPTION; + } - if (avcodec_open2(sys->codecContext, sys->codec, NULL) < 0) - { - WLog_ERR(TAG, "Failed to open libav codec"); - goto EXCEPTION; - } + if (sys->codecDecoder->capabilities & AV_CODEC_CAP_TRUNCATED) + { + sys->codecDecoderContext->flags |= AV_CODEC_FLAG_TRUNCATED; + } - sys->codecParser = av_parser_init(AV_CODEC_ID_H264); +#ifdef WITH_VAAPI - if (!sys->codecParser) - { - WLog_ERR(TAG, "Failed to initialize libav parser"); - goto EXCEPTION; + if (!sys->hwctx) + { + int ret = av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VAAPI, VAAPI_DEVICE, NULL, 0); + + if (ret < 0) + { + WLog_Print(h264->log, WLOG_ERROR, + "Could not initialize hardware decoder, falling back to software: %s", + av_err2str(ret)); + sys->hwctx = NULL; + goto fail_hwdevice_create; + } + } + + sys->codecDecoderContext->get_format = libavcodec_get_format; + sys->hw_pix_fmt = AV_PIX_FMT_VAAPI; +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 80, 100) + sys->codecDecoderContext->hw_device_ctx = av_buffer_ref(sys->hwctx); +#endif + sys->codecDecoderContext->opaque = (void*) h264; + fail_hwdevice_create: +#endif + + if (avcodec_open2(sys->codecDecoderContext, sys->codecDecoder, NULL) < 0) + { + WLog_Print(h264->log, WLOG_ERROR, "Failed to open libav codec"); + goto EXCEPTION; + } + + sys->codecParser = av_parser_init(AV_CODEC_ID_H264); + + if (!sys->codecParser) + { + WLog_Print(h264->log, WLOG_ERROR, "Failed to initialize libav parser"); + goto EXCEPTION; + } } #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102) sys->videoFrame = av_frame_alloc(); +#ifdef WITH_VAAPI + sys->hwVideoFrame = av_frame_alloc(); +#endif #else sys->videoFrame = avcodec_alloc_frame(); #endif if (!sys->videoFrame) { - WLog_ERR(TAG, "Failed to allocate libav frame"); + WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav frame"); goto EXCEPTION; } +#ifdef WITH_VAAPI + + if (!sys->hwVideoFrame) + { + WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav hw frame"); + goto EXCEPTION; + } + +#endif + sys->videoFrame->pts = 0; return TRUE; EXCEPTION: libavcodec_uninit(h264); diff --git a/libfreerdp/codec/h264_mf.c b/libfreerdp/codec/h264_mf.c index 7037ca7..dc9c432 100644 --- a/libfreerdp/codec/h264_mf.c +++ b/libfreerdp/codec/h264_mf.c @@ -28,48 +28,44 @@ #include <wmcodecdsp.h> #include <mftransform.h> -#undef DEFINE_GUID -#define INITGUID -#include <initguid.h> +#include "h264.h" #define TAG FREERDP_TAG("codec") -BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT32 height); - -DEFINE_GUID(CLSID_CMSH264DecoderMFT, 0x62CE7E72, 0x4C71, 0x4d20, 0xB1, 0x5D, - 0x45, 0x28, 0x31, 0xA8, 0x7D, 0x9D); -DEFINE_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, - 0x0c, 0x44, 0x5c, 0x78, 0xc9, 0x82); -DEFINE_GUID(IID_IMFTransform, 0xbf94c121, 0x5b05, 0x4e6f, 0x80, 0x00, 0xba, - 0x59, 0x89, 0x61, 0x41, 0x4d); -DEFINE_GUID(MF_MT_MAJOR_TYPE, 0x48eba18e, 0xf8c9, 0x4687, 0xbf, 0x11, 0x0a, - 0x74, 0xc9, 0xf9, 0x6a, 0x8f); -DEFINE_GUID(MF_MT_FRAME_SIZE, 0x1652c33d, 0xd6b2, 0x4012, 0xb8, 0x34, 0x72, - 0x03, 0x08, 0x49, 0xa3, 0x7d); -DEFINE_GUID(MF_MT_DEFAULT_STRIDE, 0x644b4e48, 0x1e02, 0x4516, 0xb0, 0xeb, 0xc0, - 0x1c, 0xa9, 0xd4, 0x9a, 0xc6); -DEFINE_GUID(MF_MT_SUBTYPE, 0xf7e34c9a, 0x42e8, 0x4714, 0xb7, 0x4b, 0xcb, 0x29, - 0xd7, 0x2c, 0x35, 0xe5); -DEFINE_GUID(MF_XVP_DISABLE_FRC, 0x2c0afa19, 0x7a97, 0x4d5a, 0x9e, 0xe8, 0x16, - 0xd4, 0xfc, 0x51, 0x8d, 0x8c); -DEFINE_GUID(MFMediaType_Video, 0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0x00, - 0xAA, 0x00, 0x38, 0x9B, 0x71); -DEFINE_GUID(MFVideoFormat_RGB32, 22, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, - 0x00, 0x38, 0x9B, 0x71); -DEFINE_GUID(MFVideoFormat_ARGB32, 21, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, - 0x00, 0x38, 0x9B, 0x71); -DEFINE_GUID(MFVideoFormat_H264, 0x34363248, 0x0000, 0x0010, 0x80, 0x00, 0x00, - 0xaa, 0x00, 0x38, 0x9b, 0x71); -DEFINE_GUID(MFVideoFormat_IYUV, 0x56555949, 0x0000, 0x0010, 0x80, 0x00, 0x00, - 0xaa, 0x00, 0x38, 0x9b, 0x71); -DEFINE_GUID(IID_ICodecAPI, 0x901db4c7, 0x31ce, 0x41a2, 0x85, 0xdc, 0x8f, 0xa0, - 0xbf, 0x41, 0xb8, 0xda); -DEFINE_GUID(CODECAPI_AVLowLatencyMode, 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, - 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee); -DEFINE_GUID(CODECAPI_AVDecVideoMaxCodedWidth, 0x5ae557b8, 0x77af, 0x41f5, 0x9f, - 0xa6, 0x4d, 0xb2, 0xfe, 0x1d, 0x4b, 0xca); -DEFINE_GUID(CODECAPI_AVDecVideoMaxCodedHeight, 0x7262a16a, 0xd2dc, 0x4e75, 0x9b, - 0xa8, 0x65, 0xc0, 0xc6, 0xd3, 0x2b, 0x13); +static const GUID sCLSID_CMSH264DecoderMFT = { 0x62CE7E72, 0x4C71, 0x4d20, { 0xB1, 0x5D, + 0x45, 0x28, 0x31, 0xA8, 0x7D, 0x9D } }; +static const GUID sCLSID_VideoProcessorMFT = { 0x88753b26, 0x5b24, 0x49bd, { 0xb2, 0xe7, + 0x0c, 0x44, 0x5c, 0x78, 0xc9, 0x82 } }; +static const GUID sIID_IMFTransform = { 0xbf94c121, 0x5b05, 0x4e6f, { 0x80, 0x00, 0xba, + 0x59, 0x89, 0x61, 0x41, 0x4d } }; +static const GUID sMF_MT_MAJOR_TYPE = { 0x48eba18e, 0xf8c9, 0x4687, { 0xbf, 0x11, 0x0a, + 0x74, 0xc9, 0xf9, 0x6a, 0x8f } }; +static const GUID sMF_MT_FRAME_SIZE = { 0x1652c33d, 0xd6b2, 0x4012, { 0xb8, 0x34, 0x72, + 0x03, 0x08, 0x49, 0xa3, 0x7d } }; +static const GUID sMF_MT_DEFAULT_STRIDE = { 0x644b4e48, 0x1e02, 0x4516, { 0xb0, 0xeb, 0xc0, + 0x1c, 0xa9, 0xd4, 0x9a, 0xc6 } }; +static const GUID sMF_MT_SUBTYPE = { 0xf7e34c9a, 0x42e8, 0x4714, { 0xb7, 0x4b, 0xcb, 0x29, + 0xd7, 0x2c, 0x35, 0xe5 } }; +static const GUID sMF_XVP_DISABLE_FRC = { 0x2c0afa19, 0x7a97, 0x4d5a, { 0x9e, 0xe8, 0x16, + 0xd4, 0xfc, 0x51, 0x8d, 0x8c } }; +static const GUID sMFMediaType_Video = { 0x73646976, 0x0000, 0x0010, { 0x80, 0x00, 0x00, + 0xAA, 0x00, 0x38, 0x9B, 0x71 } }; +static const GUID sMFVideoFormat_RGB32 = { 22, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xAA, + 0x00, 0x38, 0x9B, 0x71 } }; +static const GUID sMFVideoFormat_ARGB32 = { 21, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xAA, + 0x00, 0x38, 0x9B, 0x71 } }; +static const GUID sMFVideoFormat_H264 = { 0x34363248, 0x0000, 0x0010, { 0x80, 0x00, 0x00, + 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; +static const GUID sMFVideoFormat_IYUV = { 0x56555949, 0x0000, 0x0010, { 0x80, 0x00, 0x00, + 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; +static const GUID sIID_ICodecAPI = { 0x901db4c7, 0x31ce, 0x41a2, { 0x85, 0xdc, 0x8f, 0xa0, + 0xbf, 0x41, 0xb8, 0xda } }; +static const GUID sCODECAPI_AVLowLatencyMode = { 0x9c27891a, 0xed7a, 0x40e1, { 0x88, 0xe8, + 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee } }; +static const GUID sCODECAPI_AVDecVideoMaxCodedWidth = { 0x5ae557b8, 0x77af, 0x41f5, { 0x9f, + 0xa6, 0x4d, 0xb2, 0xfe, 0x1d, 0x4b, 0xca } }; +static const GUID sCODECAPI_AVDecVideoMaxCodedHeight = { 0x7262a16a, 0xd2dc, 0x4e75, { 0x9b, + 0xa8, 0x65, 0xc0, 0xc6, 0xd3, 0x2b, 0x13 } }; #ifndef __IMFDXGIDeviceManager_FWD_DEFINED__ #define __IMFDXGIDeviceManager_FWD_DEFINED__ @@ -115,8 +111,6 @@ typedef HRESULT(__stdcall* pfnMFCreateSample)(IMFSample** ppIMFSample); typedef HRESULT(__stdcall* pfnMFCreateMemoryBuffer)(DWORD cbMaxLength, IMFMediaBuffer** ppBuffer); typedef HRESULT(__stdcall* pfnMFCreateMediaType)(IMFMediaType** ppMFType); -typedef HRESULT(__stdcall* pfnMFCreateDXGIDeviceManager)(UINT* pResetToken, - IMFDXGIDeviceManager** ppDXVAManager); struct _H264_CONTEXT_MF { @@ -135,7 +129,6 @@ struct _H264_CONTEXT_MF pfnMFCreateSample MFCreateSample; pfnMFCreateMemoryBuffer MFCreateMemoryBuffer; pfnMFCreateMediaType MFCreateMediaType; - pfnMFCreateDXGIDeviceManager MFCreateDXGIDeviceManager; }; typedef struct _H264_CONTEXT_MF H264_CONTEXT_MF; @@ -155,7 +148,7 @@ static HRESULT mf_find_output_type(H264_CONTEXT_MF* sys, const GUID* guid, if (FAILED(hr)) break; - pMediaType->lpVtbl->GetGUID(pMediaType, &MF_MT_SUBTYPE, &mediaGuid); + pMediaType->lpVtbl->GetGUID(pMediaType, &sMF_MT_SUBTYPE, &mediaGuid); if (IsEqualGUID(&mediaGuid, guid)) { @@ -170,7 +163,7 @@ static HRESULT mf_find_output_type(H264_CONTEXT_MF* sys, const GUID* guid, return hr; } -static HRESULT mf_create_output_sample(H264_CONTEXT_MF* sys) +static HRESULT mf_create_output_sample(H264_CONTEXT* h264, H264_CONTEXT_MF* sys) { HRESULT hr = S_OK; MFT_OUTPUT_STREAM_INFO streamInfo; @@ -185,7 +178,7 @@ static HRESULT mf_create_output_sample(H264_CONTEXT_MF* sys) if (FAILED(hr)) { - WLog_ERR(TAG, "MFCreateSample failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "MFCreateSample failure: 0x%08"PRIX32"", hr); goto error; } @@ -194,7 +187,7 @@ static HRESULT mf_create_output_sample(H264_CONTEXT_MF* sys) if (FAILED(hr)) { - WLog_ERR(TAG, "GetOutputStreamInfo failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "GetOutputStreamInfo failure: 0x%08"PRIX32"", hr); goto error; } @@ -202,7 +195,7 @@ static HRESULT mf_create_output_sample(H264_CONTEXT_MF* sys) if (FAILED(hr)) { - WLog_ERR(TAG, "MFCreateMemoryBuffer failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "MFCreateMemoryBuffer failure: 0x%08"PRIX32"", hr); goto error; } @@ -210,7 +203,7 @@ static HRESULT mf_create_output_sample(H264_CONTEXT_MF* sys) if (FAILED(hr)) { - WLog_ERR(TAG, "AddBuffer failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "AddBuffer failure: 0x%08"PRIX32"", hr); goto error; } @@ -237,7 +230,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "MFCreateMemoryBuffer failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "MFCreateMemoryBuffer failure: 0x%08"PRIX32"", hr); goto error; } @@ -246,7 +239,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "Lock failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "Lock failure: 0x%08"PRIX32"", hr); goto error; } @@ -255,7 +248,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "SetCurrentLength failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "SetCurrentLength failure: 0x%08"PRIX32"", hr); goto error; } @@ -263,7 +256,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "Unlock failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "Unlock failure: 0x%08"PRIX32"", hr); goto error; } @@ -271,7 +264,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "MFCreateSample failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "MFCreateSample failure: 0x%08"PRIX32"", hr); goto error; } @@ -279,7 +272,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "AddBuffer failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "AddBuffer failure: 0x%08"PRIX32"", hr); goto error; } @@ -288,15 +281,15 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "ProcessInput failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "ProcessInput failure: 0x%08"PRIX32"", hr); goto error; } - hr = mf_create_output_sample(sys); + hr = mf_create_output_sample(h264, sys); if (FAILED(hr)) { - WLog_ERR(TAG, "mf_create_output_sample failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "mf_create_output_sample failure: 0x%08"PRIX32"", hr); goto error; } @@ -318,11 +311,11 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz sys->outputType = NULL; } - hr = mf_find_output_type(sys, &MFVideoFormat_IYUV, &sys->outputType); + hr = mf_find_output_type(sys, &sMFVideoFormat_IYUV, &sys->outputType); if (FAILED(hr)) { - WLog_ERR(TAG, "mf_find_output_type failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "mf_find_output_type failure: 0x%08"PRIX32"", hr); goto error; } @@ -331,35 +324,35 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "SetOutputType failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "SetOutputType failure: 0x%08"PRIX32"", hr); goto error; } - hr = mf_create_output_sample(sys); + hr = mf_create_output_sample(h264, sys); if (FAILED(hr)) { - WLog_ERR(TAG, "mf_create_output_sample failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "mf_create_output_sample failure: 0x%08"PRIX32"", hr); goto error; } - hr = sys->outputType->lpVtbl->GetUINT64(sys->outputType, &MF_MT_FRAME_SIZE, + hr = sys->outputType->lpVtbl->GetUINT64(sys->outputType, &sMF_MT_FRAME_SIZE, &frameSize); if (FAILED(hr)) { - WLog_ERR(TAG, "GetUINT64(MF_MT_FRAME_SIZE) failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "GetUINT64(MF_MT_FRAME_SIZE) failure: 0x%08"PRIX32"", hr); goto error; } sys->frameWidth = (UINT32)(frameSize >> 32); sys->frameHeight = (UINT32) frameSize; - hr = sys->outputType->lpVtbl->GetUINT32(sys->outputType, &MF_MT_DEFAULT_STRIDE, + hr = sys->outputType->lpVtbl->GetUINT32(sys->outputType, &sMF_MT_DEFAULT_STRIDE, &stride); if (FAILED(hr)) { - WLog_ERR(TAG, "GetUINT32(MF_MT_DEFAULT_STRIDE) failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "GetUINT32(MF_MT_DEFAULT_STRIDE) failure: 0x%08"PRIX32"", hr); goto error; } @@ -371,7 +364,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz } else if (FAILED(hr)) { - WLog_ERR(TAG, "ProcessOutput failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "ProcessOutput failure: 0x%08"PRIX32"", hr); goto error; } else @@ -385,7 +378,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "GetBufferCount failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "GetBufferCount failure: 0x%08"PRIX32"", hr); goto error; } @@ -394,7 +387,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "GetBufferByIndex failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "GetBufferByIndex failure: 0x%08"PRIX32"", hr); goto error; } @@ -403,7 +396,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "Lock failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "Lock failure: 0x%08"PRIX32"", hr); goto error; } @@ -417,7 +410,7 @@ static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSiz if (FAILED(hr)) { - WLog_ERR(TAG, "Unlock failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "Unlock failure: 0x%08"PRIX32"", hr); goto error; } @@ -431,12 +424,19 @@ error: return -1; } -static int mf_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize) +static int mf_compress(H264_CONTEXT* h264, const BYTE** ppSrcYuv, const UINT32* pStride, + BYTE** ppDstData, UINT32* pDstSize) { H264_CONTEXT_MF* sys = (H264_CONTEXT_MF*) h264->pSystemData; return 1; } +static BOOL mf_plat_loaded(H264_CONTEXT_MF* sys) +{ + return sys->MFStartup && sys->MFShutdown && sys->MFCreateSample + && sys->MFCreateMemoryBuffer && sys->MFCreateMediaType; +} + static void mf_uninit(H264_CONTEXT* h264) { UINT32 x; @@ -476,8 +476,14 @@ static void mf_uninit(H264_CONTEXT* h264) if (sys->mfplat) { + if (mf_plat_loaded(sys)) + sys->MFShutdown(); + FreeLibrary(sys->mfplat); sys->mfplat = NULL; + + if (mf_plat_loaded(sys)) + CoUninitialize(); } for (x = 0; x < sizeof(h264->pYUVData) / sizeof(h264->pYUVData[0]); x++) @@ -485,8 +491,7 @@ static void mf_uninit(H264_CONTEXT* h264) memset(h264->pYUVData, 0, sizeof(h264->pYUVData)); memset(h264->iStride, 0, sizeof(h264->iStride)); - sys->MFShutdown(); - CoUninitialize(); + free(sys); h264->pSystemData = NULL; } @@ -515,12 +520,8 @@ static BOOL mf_init(H264_CONTEXT* h264) sys->mfplat, "MFCreateMemoryBuffer"); sys->MFCreateMediaType = (pfnMFCreateMediaType) GetProcAddress(sys->mfplat, "MFCreateMediaType"); - sys->MFCreateDXGIDeviceManager = (pfnMFCreateDXGIDeviceManager) GetProcAddress( - sys->mfplat, "MFCreateDXGIDeviceManager"); - if (!sys->MFStartup || !sys->MFShutdown || !sys->MFCreateSample - || !sys->MFCreateMemoryBuffer || - !sys->MFCreateMediaType || !sys->MFCreateDXGIDeviceManager) + if (!mf_plat_loaded(sys)) goto error; CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); @@ -535,36 +536,37 @@ static BOOL mf_init(H264_CONTEXT* h264) if (FAILED(hr)) { - WLog_ERR(TAG, "MFStartup failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "MFStartup failure: 0x%08"PRIX32"", hr); goto error; } - hr = CoCreateInstance(&CLSID_CMSH264DecoderMFT, NULL, CLSCTX_INPROC_SERVER, - &IID_IMFTransform, (void**) &sys->transform); + hr = CoCreateInstance(&sCLSID_CMSH264DecoderMFT, NULL, CLSCTX_INPROC_SERVER, + &sIID_IMFTransform, (void**) &sys->transform); if (FAILED(hr)) { - WLog_ERR(TAG, "CoCreateInstance(CLSID_CMSH264DecoderMFT) failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, + "CoCreateInstance(CLSID_CMSH264DecoderMFT) failure: 0x%08"PRIX32"", hr); goto error; } - hr = sys->transform->lpVtbl->QueryInterface(sys->transform, &IID_ICodecAPI, + hr = sys->transform->lpVtbl->QueryInterface(sys->transform, &sIID_ICodecAPI, (void**) &sys->codecApi); if (FAILED(hr)) { - WLog_ERR(TAG, "QueryInterface(IID_ICodecAPI) failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "QueryInterface(IID_ICodecAPI) failure: 0x%08"PRIX32"", hr); goto error; } var.vt = VT_UI4; var.ulVal = 1; - hr = sys->codecApi->lpVtbl->SetValue(sys->codecApi, &CODECAPI_AVLowLatencyMode, + hr = sys->codecApi->lpVtbl->SetValue(sys->codecApi, &sCODECAPI_AVLowLatencyMode, &var); if (FAILED(hr)) { - WLog_ERR(TAG, "SetValue(CODECAPI_AVLowLatencyMode) failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "SetValue(CODECAPI_AVLowLatencyMode) failure: 0x%08"PRIX32"", hr); goto error; } @@ -572,25 +574,25 @@ static BOOL mf_init(H264_CONTEXT* h264) if (FAILED(hr)) { - WLog_ERR(TAG, "MFCreateMediaType failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "MFCreateMediaType failure: 0x%08"PRIX32"", hr); goto error; } - hr = sys->inputType->lpVtbl->SetGUID(sys->inputType, &MF_MT_MAJOR_TYPE, - &MFMediaType_Video); + hr = sys->inputType->lpVtbl->SetGUID(sys->inputType, &sMF_MT_MAJOR_TYPE, + &sMFMediaType_Video); if (FAILED(hr)) { - WLog_ERR(TAG, "SetGUID(MF_MT_MAJOR_TYPE) failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "SetGUID(MF_MT_MAJOR_TYPE) failure: 0x%08"PRIX32"", hr); goto error; } - hr = sys->inputType->lpVtbl->SetGUID(sys->inputType, &MF_MT_SUBTYPE, - &MFVideoFormat_H264); + hr = sys->inputType->lpVtbl->SetGUID(sys->inputType, &sMF_MT_SUBTYPE, + &sMFVideoFormat_H264); if (FAILED(hr)) { - WLog_ERR(TAG, "SetGUID(MF_MT_SUBTYPE) failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "SetGUID(MF_MT_SUBTYPE) failure: 0x%08"PRIX32"", hr); goto error; } @@ -598,15 +600,15 @@ static BOOL mf_init(H264_CONTEXT* h264) if (FAILED(hr)) { - WLog_ERR(TAG, "SetInputType failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "SetInputType failure: 0x%08"PRIX32"", hr); goto error; } - hr = mf_find_output_type(sys, &MFVideoFormat_IYUV, &sys->outputType); + hr = mf_find_output_type(sys, &sMFVideoFormat_IYUV, &sys->outputType); if (FAILED(hr)) { - WLog_ERR(TAG, "mf_find_output_type failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "mf_find_output_type failure: 0x%08"PRIX32"", hr); goto error; } @@ -615,22 +617,22 @@ static BOOL mf_init(H264_CONTEXT* h264) if (FAILED(hr)) { - WLog_ERR(TAG, "SetOutputType failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "SetOutputType failure: 0x%08"PRIX32"", hr); goto error; } - hr = mf_create_output_sample(sys); + hr = mf_create_output_sample(h264, sys); if (FAILED(hr)) { - WLog_ERR(TAG, "mf_create_output_sample failure: 0x%08"PRIX32"", hr); + WLog_Print(h264->log, WLOG_ERROR, "mf_create_output_sample failure: 0x%08"PRIX32"", hr); goto error; } } return TRUE; error: - WLog_ERR(TAG, "mf_init failure"); + WLog_Print(h264->log, WLOG_ERROR, "mf_init failure"); mf_uninit(h264); return FALSE; } diff --git a/libfreerdp/codec/h264_openh264.c b/libfreerdp/codec/h264_openh264.c index 451a5bf..7f22c7d 100644 --- a/libfreerdp/codec/h264_openh264.c +++ b/libfreerdp/codec/h264_openh264.c @@ -25,11 +25,9 @@ #include "wels/codec_api.h" #include "wels/codec_ver.h" -#define TAG FREERDP_TAG("codec") - #if (OPENH264_MAJOR == 1) && (OPENH264_MINOR < 3) || (OPENH264_MAJOR < 1) #error "Unsupported OpenH264 version "OPENH264_MAJOR"."OPENH264_MINOR"."OPENH264_REVISION" detected!" -#elif (OPENH264_MAJOR > 1) || (OPENH264_MINOR > 6) +#elif (OPENH264_MAJOR > 1) || (OPENH264_MINOR > 7) #warning "Untested OpenH264 version "OPENH264_MAJOR"."OPENH264_MINOR"."OPENH264_REVISION" detected!" #endif @@ -41,12 +39,11 @@ struct _H264_CONTEXT_OPENH264 }; typedef struct _H264_CONTEXT_OPENH264 H264_CONTEXT_OPENH264; -static BOOL g_openh264_trace_enabled = FALSE; - static void openh264_trace_callback(H264_CONTEXT* h264, int level, const char* message) { - WLog_INFO(TAG, "%d - %s", level, message); + if (h264) + WLog_Print(h264->log, WLOG_TRACE, "%d - %s", level, message); } static int openh264_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, @@ -88,8 +85,8 @@ static int openh264_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, } else { - WLog_WARN(TAG, "DecodeFrame2 state: 0x%04X iBufferStatus: %d", state, - sBufferInfo.iBufferStatus); + WLog_Print(h264->log, WLOG_WARN, "DecodeFrame2 state: 0x%04X iBufferStatus: %d", state, + sBufferInfo.iBufferStatus); return -2002; } } @@ -101,22 +98,22 @@ static int openh264_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, if (sBufferInfo.iBufferStatus != 1) { - WLog_WARN(TAG, "DecodeFrame2 iBufferStatus: %d", sBufferInfo.iBufferStatus); + WLog_Print(h264->log, WLOG_WARN, "DecodeFrame2 iBufferStatus: %d", sBufferInfo.iBufferStatus); return 0; } if (state != dsErrorFree) { - WLog_WARN(TAG, "DecodeFrame2 state: 0x%02X", state); + WLog_Print(h264->log, WLOG_WARN, "DecodeFrame2 state: 0x%02X", state); return -2003; } #if 0 - WLog_INFO(TAG, - "h264_decompress: state=%u, pYUVData=[%p,%p,%p], bufferStatus=%d, width=%d, height=%d, format=%d, stride=[%d,%d]", - state, (void*) pYUVData[0], (void*) pYUVData[1], (void*) pYUVData[2], sBufferInfo.iBufferStatus, - pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iFormat, - pSystemBuffer->iStride[0], pSystemBuffer->iStride[1]); + WLog_Print(h264->log, WLOG_INFO, + "h264_decompress: state=%u, pYUVData=[%p,%p,%p], bufferStatus=%d, width=%d, height=%d, format=%d, stride=[%d,%d]", + state, (void*) pYUVData[0], (void*) pYUVData[1], (void*) pYUVData[2], sBufferInfo.iBufferStatus, + pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iFormat, + pSystemBuffer->iStride[0], pSystemBuffer->iStride[1]); #endif if (pSystemBuffer->iFormat != videoFormatI420) @@ -128,8 +125,8 @@ static int openh264_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, return 1; } -static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, - UINT32* pDstSize) +static int openh264_compress(H264_CONTEXT* h264, const BYTE** pYUVData, const UINT32* iStride, + BYTE** ppDstData, UINT32* pDstSize) { int i, j; int status; @@ -137,8 +134,6 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, SSourcePicture pic; SBitrateInfo bitrate; H264_CONTEXT_OPENH264* sys; - BYTE** pYUVData = h264->pYUVData; - UINT32* iStride = h264->iStride; sys = &((H264_CONTEXT_OPENH264*) h264->pSystemData)[0]; if (!sys->pEncoder) @@ -154,7 +149,7 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, if (status < 0) { - WLog_ERR(TAG, "Failed to get OpenH264 default parameters (status=%d)", status); + WLog_Print(h264->log, WLOG_ERROR, "Failed to get OpenH264 default parameters (status=%d)", status); return status; } @@ -202,7 +197,7 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, if (status < 0) { - WLog_ERR(TAG, "Failed to initialize OpenH264 encoder (status=%d)", status); + WLog_Print(h264->log, WLOG_ERROR, "Failed to initialize OpenH264 encoder (status=%d)", status); return status; } @@ -212,8 +207,8 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, if (status < 0) { - WLog_ERR(TAG, "Failed to get initial OpenH264 encoder parameters (status=%d)", - status); + WLog_Print(h264->log, WLOG_ERROR, "Failed to get initial OpenH264 encoder parameters (status=%d)", + status); return status; } } @@ -232,7 +227,7 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, if (status < 0) { - WLog_ERR(TAG, "Failed to set encoder bitrate (status=%d)", status); + WLog_Print(h264->log, WLOG_ERROR, "Failed to set encoder bitrate (status=%d)", status); return status; } } @@ -245,7 +240,7 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, if (status < 0) { - WLog_ERR(TAG, "Failed to set encoder framerate (status=%d)", status); + WLog_Print(h264->log, WLOG_ERROR, "Failed to set encoder framerate (status=%d)", status); return status; } } @@ -262,7 +257,7 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, if (status < 0) { - WLog_ERR(TAG, "Failed to set encoder parameters (status=%d)", status); + WLog_Print(h264->log, WLOG_ERROR, "Failed to set encoder parameters (status=%d)", status); return status; } } @@ -273,20 +268,20 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, memset(&info, 0, sizeof(SFrameBSInfo)); memset(&pic, 0, sizeof(SSourcePicture)); - pic.iPicWidth = h264->width; - pic.iPicHeight = h264->height; + pic.iPicWidth = (int)h264->width; + pic.iPicHeight = (int)h264->height; pic.iColorFormat = videoFormatI420; - pic.iStride[0] = iStride[0]; - pic.iStride[1] = iStride[1]; - pic.iStride[2] = iStride[2]; - pic.pData[0] = pYUVData[0]; - pic.pData[1] = pYUVData[1]; - pic.pData[2] = pYUVData[2]; + pic.iStride[0] = (int)iStride[0]; + pic.iStride[1] = (int)iStride[1]; + pic.iStride[2] = (int)iStride[2]; + pic.pData[0] = (unsigned char*)pYUVData[0]; + pic.pData[1] = (unsigned char*)pYUVData[1]; + pic.pData[2] = (unsigned char*)pYUVData[2]; status = (*sys->pEncoder)->EncodeFrame(sys->pEncoder, &pic, &info); if (status < 0) { - WLog_ERR(TAG, "Failed to encode frame (status=%d)", status); + WLog_Print(h264->log, WLOG_ERROR, "Failed to encode frame (status=%d)", status); return status; } @@ -366,7 +361,7 @@ static BOOL openh264_init(H264_CONTEXT* h264) if (!sys->pEncoder) { - WLog_ERR(TAG, "Failed to create OpenH264 encoder"); + WLog_Print(h264->log, WLOG_ERROR, "Failed to create OpenH264 encoder"); goto EXCEPTION; } } @@ -376,7 +371,7 @@ static BOOL openh264_init(H264_CONTEXT* h264) if (!sys->pDecoder) { - WLog_ERR(TAG, "Failed to create OpenH264 decoder"); + WLog_Print(h264->log, WLOG_ERROR, "Failed to create OpenH264 decoder"); goto EXCEPTION; } @@ -390,8 +385,8 @@ static BOOL openh264_init(H264_CONTEXT* h264) if (status != 0) { - WLog_ERR(TAG, "Failed to initialize OpenH264 decoder (status=%ld)", - status); + WLog_Print(h264->log, WLOG_ERROR, "Failed to initialize OpenH264 decoder (status=%ld)", + status); goto EXCEPTION; } @@ -403,13 +398,13 @@ static BOOL openh264_init(H264_CONTEXT* h264) if (status != 0) { - WLog_ERR(TAG, - "Failed to set data format option on OpenH264 decoder (status=%ld)", - status); + WLog_Print(h264->log, WLOG_ERROR, + "Failed to set data format option on OpenH264 decoder (status=%ld)", + status); goto EXCEPTION; } - if (g_openh264_trace_enabled) + if (WLog_GetLogLevel(h264->log) == WLOG_TRACE) { status = (*sys->pDecoder)->SetOption( sys->pDecoder, DECODER_OPTION_TRACE_LEVEL, @@ -417,21 +412,9 @@ static BOOL openh264_init(H264_CONTEXT* h264) if (status != 0) { - WLog_ERR(TAG, - "Failed to set trace level option on OpenH264 decoder (status=%ld)", - status); - goto EXCEPTION; - } - - status = (*sys->pDecoder)->SetOption( - sys->pDecoder, DECODER_OPTION_TRACE_CALLBACK, - &traceCallback); - - if (status != 0) - { - WLog_ERR(TAG, - "Failed to set trace callback option on OpenH264 decoder (status=%ld)", - status); + WLog_Print(h264->log, WLOG_ERROR, + "Failed to set trace level option on OpenH264 decoder (status=%ld)", + status); goto EXCEPTION; } @@ -442,9 +425,21 @@ static BOOL openh264_init(H264_CONTEXT* h264) if (status != 0) { - WLog_ERR(TAG, - "Failed to set trace callback context option on OpenH264 decoder (status=%ld)", - status); + WLog_Print(h264->log, WLOG_ERROR, + "Failed to set trace callback context option on OpenH264 decoder (status=%ld)", + status); + goto EXCEPTION; + } + + status = (*sys->pDecoder)->SetOption( + sys->pDecoder, DECODER_OPTION_TRACE_CALLBACK, + &traceCallback); + + if (status != 0) + { + WLog_Print(h264->log, WLOG_ERROR, + "Failed to set trace callback option on OpenH264 decoder (status=%ld)", + status); goto EXCEPTION; } } diff --git a/libfreerdp/codec/h264_x264.c b/libfreerdp/codec/h264_x264.c index 11e7f0e..5252e3f 100644 --- a/libfreerdp/codec/h264_x264.c +++ b/libfreerdp/codec/h264_x264.c @@ -52,7 +52,7 @@ static int x264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize) return -1; } -static int x264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize) +static int x264_compress(H264_CONTEXT* h264, const BYTE** ppSrcYuv, const UINT32* pStride, BYTE** ppDstData, UINT32* pDstSize) { //H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*) h264->pSystemData; return -1; diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index 3be3b9e..943ca00 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -384,9 +384,11 @@ BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, if (!DstFormat) return FALSE; - status = freerdp_image_copy(interleaved->TempBuffer, DstFormat, 0, 0, 0, nWidth, - nHeight, - pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE); + if (!freerdp_image_copy(interleaved->TempBuffer, DstFormat, 0, 0, 0, nWidth, + nHeight, + pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE)) + return FALSE; + s = Stream_New(pDstData, maxSize); if (!s) diff --git a/libfreerdp/codec/ncrush.c b/libfreerdp/codec/ncrush.c index d841c27..9e79d71 100644 --- a/libfreerdp/codec/ncrush.c +++ b/libfreerdp/codec/ncrush.c @@ -3,6 +3,8 @@ * NCrush (RDP6) Bulk Data Compression * * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * Copyright 2017 Armin Novak <armin.novak@thincast.com> + * Copyright 2017 Thincast Technologies GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +32,7 @@ #define TAG FREERDP_TAG("codec") -UINT16 HuffTableLEC[8192] = +static const UINT16 HuffTableLEC[8192] = { 0x510B, 0x611F, 0x610D, 0x9027, 0x6000, 0x7105, 0x6117, 0xA068, 0x5111, 0x7007, 0x6113, 0x90C0, 0x6108, 0x8018, 0x611B, 0xA0B3, 0x510F, 0x7003, 0x6110, 0x9042, 0x6002, 0x800B, 0x6119, 0xA091, 0x5121, 0x7080, 0x6115, 0xA03A, 0x610A, 0x9012, 0x611D, 0xA0D7, @@ -546,7 +548,7 @@ UINT16 HuffTableLEC[8192] = 0x510F, 0x7006, 0x6112, 0x9090, 0x6107, 0x8013, 0x611A, 0xA0B1, 0x5121, 0x7103, 0x6116, 0xA067, 0x610C, 0x9026, 0x611E, 0xD125 }; -UINT16 HuffTableLOM[512] = +static const UINT16 HuffTableLOM[512] = { 0x2001, 0x4000, 0x3002, 0x4008, 0x2001, 0x4005, 0x3004, 0x500A, 0x2001, 0x4003, 0x3002, 0x5007, 0x2001, 0x4006, 0x3004, 0x700D, 0x2001, 0x4000, 0x3002, 0x4008, 0x2001, 0x4005, 0x3004, 0x600B, 0x2001, 0x4003, 0x3002, 0x5009, 0x2001, 0x4006, 0x3004, 0x8012, @@ -582,7 +584,7 @@ UINT16 HuffTableLOM[512] = 0x2001, 0x4000, 0x3002, 0x4008, 0x2001, 0x4005, 0x3004, 0x600C, 0x2001, 0x4003, 0x3002, 0x5009, 0x2001, 0x4006, 0x3004, 0x901F }; -const BYTE HuffTableMask[39] = +static const BYTE HuffTableMask[39] = { 0x11, /* 0 */ 0x9E, /* 1 */ @@ -625,7 +627,7 @@ const BYTE HuffTableMask[39] = 0x00 /* 38 */ }; -const BYTE HuffLengthLEC[294] = +static const BYTE HuffLengthLEC[294] = { 6, /* 0 */ 6, /* 1 */ @@ -923,7 +925,7 @@ const BYTE HuffLengthLEC[294] = 13 /* 293 */ }; -const BYTE HuffCodeLEC[588] = +static const BYTE HuffCodeLEC[588] = { 0x04, /* 0 */ 0x00, /* 1 */ @@ -1515,7 +1517,7 @@ const BYTE HuffCodeLEC[588] = 0x1F /* 587 */ }; -const BYTE HuffLengthLOM[32] = +static const BYTE HuffLengthLOM[32] = { 4, /* 0 */ 2, /* 1 */ @@ -1551,7 +1553,7 @@ const BYTE HuffLengthLOM[32] = 9 /* 31 */ }; -const UINT16 HuffCodeLOM[32] = +static const UINT16 HuffCodeLOM[32] = { 0x0001, /* 0 */ 0x0000, /* 1 */ @@ -1587,7 +1589,7 @@ const UINT16 HuffCodeLOM[32] = 0x01FF /* 31 */ }; -UINT32 CopyOffsetBitsLUT[32] = +static const UINT32 CopyOffsetBitsLUT[32] = { 0x0, /* 0 */ 0x0, /* 1 */ @@ -1623,7 +1625,7 @@ UINT32 CopyOffsetBitsLUT[32] = 0xE /* 31 */ }; -UINT32 CopyOffsetBaseLUT[32] = +static const UINT32 CopyOffsetBaseLUT[32] = { 0x1, /* 0 */ 0x2, /* 1 */ @@ -1659,7 +1661,7 @@ UINT32 CopyOffsetBaseLUT[32] = 0xC001 /* 31 */ }; -UINT32 LOMBitsLUT[30] = +static const UINT32 LOMBitsLUT[30] = { 0x0, /* 0 */ 0x0, /* 1 */ @@ -1693,7 +1695,7 @@ UINT32 LOMBitsLUT[30] = 0xE /* 29 */ }; -UINT32 LOMBaseLUT[30] = +static const UINT32 LOMBaseLUT[30] = { 0x2, /* 0 */ 0x3, /* 1 */ @@ -1727,51 +1729,89 @@ UINT32 LOMBaseLUT[30] = 0x2 /* 29 */ }; -#define NCrushFetchBits() \ - if (nbits < 16) { \ - if ((SrcPtr + 1) >= SrcEnd) { \ - if (SrcPtr >= SrcEnd) { \ - if (nbits < 0) \ - return -1; \ - } else { \ - bits += *SrcPtr++ << nbits; \ - nbits += 8; \ - } \ - } else { \ - bits += *((UINT16*) SrcPtr) << nbits; \ - SrcPtr += 2; \ - nbits += 16; \ - } \ - } \ +static INLINE UINT16 get_word(const BYTE* data) +{ + UINT16 tmp = *data++; + tmp |= *data << 8; + return tmp; +} -#define NCrushWriteStart() \ - bits = 0; \ - offset = 0; \ - accumulator = 0 +static INLINE UINT32 get_dword(const BYTE* data) +{ + UINT32 tmp = *data++; + tmp |= *data++ << 8U; + tmp |= *data++ << 16U; + tmp |= *data++ << 24U; + return tmp; +} -#define NCrushWriteBits(_bits, _nbits) \ - accumulator |= _bits << offset; \ - offset += _nbits; \ - if (offset >= 16) { \ - *DstPtr++ = accumulator & 0xFF; \ - *DstPtr++ = (accumulator >> 8) & 0xFF; \ - accumulator >>= 16; \ - offset -= 16; \ +static INLINE BOOL NCrushFetchBits(const BYTE** SrcPtr, const BYTE** SrcEnd, INT32* nbits, + UINT32* bits) +{ + if (*nbits < 16) + { + if ((*SrcPtr + 1) >= *SrcEnd) + { + if (*SrcPtr >= *SrcEnd) + { + if (*nbits < 0) + return FALSE; + } + else + { + *bits += *(*SrcPtr)++ << *nbits; + *nbits += 8; + } + } + else + { + UINT16 tmp = *(*SrcPtr)++; + tmp |= (*(*SrcPtr)++) << 8; + *bits += tmp << *nbits; + *nbits += 16; + } } -#define NCrushWriteFinish() \ - *DstPtr++ = accumulator & 0xFF; \ - *DstPtr++ = (accumulator >> 8) & 0xFF + return TRUE; +} -int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) +static INLINE void NCrushWriteStart(UINT32* bits, UINT32* offset, UINT32* accumulator) +{ + *bits = 0; + *offset = 0; + *accumulator = 0; +} + +static INLINE void NCrushWriteBits(BYTE** DstPtr, UINT32* accumulator, UINT32* offset, + UINT32 _bits, UINT32 _nbits) +{ + *accumulator |= _bits << *offset; + *offset += _nbits; + + if (*offset >= 16) + { + *(*DstPtr)++ = (*accumulator & 0xFF); + *(*DstPtr)++ = ((*accumulator >> 8) & 0xFF); + *accumulator >>= 16; + *offset -= 16; + } +} + +static INLINE void NCrushWriteFinish(BYTE** DstPtr, UINT32 accumulator) +{ + *(*DstPtr)++ = accumulator & 0xFF; + *(*DstPtr)++ = (accumulator >> 8) & 0xFF; +} + +int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, + UINT32* pDstSize, UINT32 flags) { UINT32 index; UINT32 bits; - UINT32 nbits; - BYTE* SrcPtr; - BYTE* SrcEnd; + INT32 nbits; + const BYTE* SrcPtr; + const BYTE* SrcEnd; UINT16 Mask; - UINT16* pMask; BYTE Literal; UINT32 IndexLEC; UINT32 BitLength; @@ -1824,26 +1864,23 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY } SrcEnd = &pSrcData[SrcSize]; - nbits = 32; - bits = *((UINT32*) pSrcData); + bits = get_dword(pSrcData); SrcPtr = pSrcData + 4; while (1) { while (1) { - pMask = (UINT16*) &HuffTableMask[29]; - Mask = *pMask; + Mask = get_word(&HuffTableMask[29]); MaskedBits = bits & Mask; - IndexLEC = HuffTableLEC[MaskedBits] & 0xFFF; BitLength = HuffTableLEC[MaskedBits] >> 12; - bits >>= BitLength; nbits -= BitLength; - NCrushFetchBits(); + if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits)) + return -1; if (IndexLEC >= 256) break; @@ -1851,12 +1888,11 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY if (HistoryPtr >= HistoryBufferEnd) { WLog_ERR(TAG, "ncrush_decompress error: HistoryPtr (%p) >= HistoryBufferEnd (%p)", - (void*) HistoryPtr, (void*) HistoryBufferEnd); + (void*) HistoryPtr, (void*) HistoryBufferEnd); return -1003; } Literal = (HuffTableLEC[MaskedBits] & 0xFF); - *HistoryPtr++ = Literal; } @@ -1873,34 +1909,29 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY return -1004; CopyOffset = ncrush->OffsetCache[OffsetCacheIndex]; - - pMask = (UINT16*) &HuffTableMask[21]; - Mask = *pMask; + Mask = get_word(&HuffTableMask[21]); MaskedBits = bits & Mask; - LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF; BitLength = HuffTableLOM[MaskedBits] >> 12; - bits >>= BitLength; nbits -= BitLength; - NCrushFetchBits(); + if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits)) + return -1; LengthOfMatchBits = LOMBitsLUT[LengthOfMatch]; LengthOfMatchBase = LOMBaseLUT[LengthOfMatch]; if (LengthOfMatchBits) { - pMask = (UINT16*) &HuffTableMask[(2 * LengthOfMatchBits) + 3]; - Mask = *pMask; + Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]); MaskedBits = bits & Mask; - bits >>= LengthOfMatchBits; nbits -= LengthOfMatchBits; - LengthOfMatchBase += MaskedBits; - NCrushFetchBits(); + if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits)) + return -1; } OldCopyOffset = ncrush->OffsetCache[OffsetCacheIndex]; @@ -1915,45 +1946,39 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY if (CopyOffsetBits) { - pMask = (UINT16*) &HuffTableMask[(2 * CopyOffsetBits) + 3]; - Mask = *pMask; + Mask = get_word(&HuffTableMask[(2 * CopyOffsetBits) + 3]); MaskedBits = bits & Mask; - CopyOffset = CopyOffsetBase + MaskedBits - 1; - bits >>= CopyOffsetBits; nbits -= CopyOffsetBits; - NCrushFetchBits(); + if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits)) + return -1; } - pMask = (UINT16*) &HuffTableMask[21]; - Mask = *pMask; + Mask = get_word(&HuffTableMask[21]); MaskedBits = bits & Mask; - LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF; BitLength = HuffTableLOM[MaskedBits] >> 12; - bits >>= BitLength; nbits -= BitLength; - NCrushFetchBits(); + if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits)) + return -1; LengthOfMatchBits = LOMBitsLUT[LengthOfMatch]; LengthOfMatchBase = LOMBaseLUT[LengthOfMatch]; if (LengthOfMatchBits) { - pMask = (UINT16*) &HuffTableMask[(2 * LengthOfMatchBits) + 3]; - Mask = *pMask; + Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]); MaskedBits = bits & Mask; - bits >>= LengthOfMatchBits; nbits -= LengthOfMatchBits; - LengthOfMatchBase += MaskedBits; - NCrushFetchBits(); + if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits)) + return -1; } ncrush->OffsetCache[3] = ncrush->OffsetCache[2]; @@ -1969,11 +1994,10 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY return -1005; if ((CopyOffsetPtr >= (HistoryBufferEnd - LengthOfMatch)) || - (HistoryPtr >= (HistoryBufferEnd - LengthOfMatch))) + (HistoryPtr >= (HistoryBufferEnd - LengthOfMatch))) return -1006; CopyOffsetPtr = HistoryPtr - CopyOffset; - index = 0; CopyLength = (LengthOfMatch > CopyOffset) ? CopyOffset : LengthOfMatch; @@ -2024,32 +2048,32 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY if (ncrush->HistoryBufferFence != 0xABABABAB) { - WLog_ERR(TAG, "NCrushDecompress: history buffer fence was overwritten, potential buffer overflow detected!"); + WLog_ERR(TAG, + "NCrushDecompress: history buffer fence was overwritten, potential buffer overflow detected!"); return -1007; } *pDstSize = HistoryPtr - ncrush->HistoryPtr; *ppDstData = ncrush->HistoryPtr; ncrush->HistoryPtr = HistoryPtr; - return 1; } -int ncrush_hash_table_add(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, UINT32 HistoryOffset) +static int ncrush_hash_table_add(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSize, + UINT32 HistoryOffset) { - BYTE* SrcPtr; + const BYTE* SrcPtr; UINT32 Hash; UINT32 Offset; UINT32 EndOffset; - SrcPtr = pSrcData; Offset = HistoryOffset; EndOffset = Offset + SrcSize - 8; while (Offset < EndOffset) - { - Hash = ncrush->HashTable[*((UINT16*) SrcPtr)]; - ncrush->HashTable[*((UINT16*) SrcPtr)] = Offset; + { + Hash = ncrush->HashTable[get_word(SrcPtr)]; + ncrush->HashTable[get_word(SrcPtr)] = Offset; ncrush->MatchTable[Offset] = Hash; SrcPtr++; Offset++; @@ -2058,10 +2082,10 @@ int ncrush_hash_table_add(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize return 1; } -int ncrush_find_match_length(BYTE* Ptr1, BYTE* Ptr2, BYTE* HistoryPtr) +static int ncrush_find_match_length(const BYTE* Ptr1, const BYTE* Ptr2, BYTE* HistoryPtr) { BYTE val1, val2; - BYTE* Ptr = Ptr1; + const BYTE* Ptr = Ptr1; do { @@ -2076,7 +2100,8 @@ int ncrush_find_match_length(BYTE* Ptr1, BYTE* Ptr2, BYTE* HistoryPtr) return Ptr1 - (Ptr + 1); } -int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32* pMatchOffset) +static int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, + UINT32* pMatchOffset) { int i, j; int Length; @@ -2093,10 +2118,8 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32* MatchLength = 2; Offset = HistoryOffset; HistoryBuffer = (BYTE*) ncrush->HistoryBuffer; - ncrush->MatchTable[0] = HistoryOffset; MatchOffset = ncrush->MatchTable[HistoryOffset]; - NextOffset = ncrush->MatchTable[Offset]; MatchPtr = &HistoryBuffer[MatchLength]; @@ -2107,6 +2130,7 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32* if (j < 0) { Offset = ncrush->MatchTable[NextOffset]; + if (MatchPtr[NextOffset] == HistoryBuffer[HistoryOffset + MatchLength]) j = 0; } @@ -2114,27 +2138,31 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32* if (j < 0) { NextOffset = ncrush->MatchTable[Offset]; + if (MatchPtr[Offset] == HistoryBuffer[HistoryOffset + MatchLength]) j = 1; } - + if (j < 0) { Offset = ncrush->MatchTable[NextOffset]; + if (MatchPtr[NextOffset] == HistoryBuffer[HistoryOffset + MatchLength]) j = 2; } - + if (j < 0) { NextOffset = ncrush->MatchTable[Offset]; + if (MatchPtr[Offset] == HistoryBuffer[HistoryOffset + MatchLength]) j = 3; } - + if (j < 0) { Offset = ncrush->MatchTable[NextOffset]; + if (MatchPtr[NextOffset] == HistoryBuffer[HistoryOffset + MatchLength]) j = 4; } @@ -2142,6 +2170,7 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32* if (j < 0) { NextOffset = ncrush->MatchTable[Offset]; + if (MatchPtr[Offset] == HistoryBuffer[HistoryOffset + MatchLength]) j = 5; } @@ -2154,14 +2183,14 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32* if ((Offset != HistoryOffset) && Offset) { Length = ncrush_find_match_length(&HistoryBuffer[HistoryOffset + 2], - &HistoryBuffer[Offset + 2], ncrush->HistoryPtr) + 2; - + &HistoryBuffer[Offset + 2], ncrush->HistoryPtr) + 2; + if (Length < 2) return -1; if (Length > 16) break; - + if (Length > MatchLength) { MatchLength = Length; @@ -2175,17 +2204,17 @@ int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset, UINT32* continue; } } + break; } } ncrush->MatchTable[0] = 0; *pMatchOffset = MatchOffset; - return MatchLength; } -int ncrush_move_encoder_windows(NCRUSH_CONTEXT* ncrush, BYTE* HistoryPtr) +static int ncrush_move_encoder_windows(NCRUSH_CONTEXT* ncrush, BYTE* HistoryPtr) { int i, j; int NewHash; @@ -2197,7 +2226,7 @@ int ncrush_move_encoder_windows(NCRUSH_CONTEXT* ncrush, BYTE* HistoryPtr) if (HistoryPtr > &ncrush->HistoryBuffer[65536]) return -1; - + MoveMemory(ncrush->HistoryBuffer, HistoryPtr - 32768, 32768); HistoryOffset = HistoryPtr - 32768 - ncrush->HistoryBuffer; @@ -2205,13 +2234,10 @@ int ncrush_move_encoder_windows(NCRUSH_CONTEXT* ncrush, BYTE* HistoryPtr) { NewHash = ncrush->HashTable[i + 0] - HistoryOffset; ncrush->HashTable[i + 0] = (NewHash <= 0) ? 0 : NewHash; - NewHash = ncrush->HashTable[i + 1] - HistoryOffset; ncrush->HashTable[i + 1] = (NewHash <= 0) ? 0 : NewHash; - NewHash = ncrush->HashTable[i + 2] - HistoryOffset; ncrush->HashTable[i + 2] = (NewHash <= 0) ? 0 : NewHash; - NewHash = ncrush->HashTable[i + 3] - HistoryOffset; ncrush->HashTable[i + 3] = (NewHash <= 0) ? 0 : NewHash; } @@ -2220,33 +2246,30 @@ int ncrush_move_encoder_windows(NCRUSH_CONTEXT* ncrush, BYTE* HistoryPtr) { NewMatch = ncrush->MatchTable[HistoryOffset + j + 0] - HistoryOffset; ncrush->MatchTable[j + 0] = (NewMatch <= 0) ? 0 : NewMatch; - NewMatch = ncrush->MatchTable[HistoryOffset + j + 1] - HistoryOffset; ncrush->MatchTable[j + 1] = (NewMatch <= 0) ? 0 : NewMatch; - NewMatch = ncrush->MatchTable[HistoryOffset + j + 2] - HistoryOffset; ncrush->MatchTable[j + 2] = (NewMatch <= 0) ? 0 : NewMatch; - NewMatch = ncrush->MatchTable[HistoryOffset + j + 3] - HistoryOffset; ncrush->MatchTable[j + 3] = (NewMatch <= 0) ? 0 : NewMatch; } - - ZeroMemory(&ncrush->MatchTable[32768], 65536); + ZeroMemory(&ncrush->MatchTable[32768], 65536); return 1; } -int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags) +int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, + UINT32* pDstSize, UINT32* pFlags) { BYTE Literal; - BYTE* SrcPtr; + const BYTE* SrcPtr; BYTE* DstPtr; UINT32 bits; UINT32 offset; UINT16 Mask; UINT32 MaskedBits; UINT32 accumulator; - BYTE* SrcEndPtr; + const BYTE* SrcEndPtr; BYTE* DstEndPtr; BYTE* HistoryPtr; BYTE* pDstData; @@ -2258,7 +2281,6 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE UINT32 IndexLOM; UINT32 IndexCO; UINT32 CodeLEC; - UINT16* pCodeLEC; UINT32 BitLength; UINT32 CopyOffset; UINT32 MatchOffset; @@ -2272,10 +2294,8 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE UINT32 CopyOffsetIndex; UINT32 CopyOffsetBits; UINT32 CompressionLevel; - CompressionLevel = 2; HistoryBuffer = ncrush->HistoryBuffer; - *pFlags = 0; PacketFlushed = FALSE; PacketAtFront = FALSE; @@ -2293,7 +2313,6 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE if (ncrush_move_encoder_windows(ncrush, &(HistoryBuffer[ncrush->HistoryOffset])) < 0) return -1001; - HistoryPtr = &HistoryBuffer[32768]; ncrush->HistoryPtr = &HistoryBuffer[32768]; ncrush->HistoryOffset = 32768; PacketAtFront = TRUE; @@ -2315,9 +2334,7 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE return -1003; DstSize = SrcSize; - - NCrushWriteStart(); - + NCrushWriteStart(&bits, &offset, &accumulator); DstPtr = pDstData; SrcPtr = pSrcData; SrcEndPtr = &pSrcData[SrcSize]; @@ -2326,7 +2343,6 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE HistoryPtr = &HistoryBuffer[ncrush->HistoryOffset]; HistoryBufferEndPtr = &HistoryBuffer[65536]; HistoryBufferSize = ncrush->HistoryBufferSize; - CopyOffset = 0; MatchOffset = 0; ncrush_hash_table_add(ncrush, pSrcData, SrcSize, HistoryPtr - HistoryBuffer); @@ -2355,14 +2371,13 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE if (MatchLength) CopyOffset = (HistoryBufferSize - 1) & (HistoryPtr - &HistoryBuffer[MatchOffset]); - + if ((MatchLength == 2) && (CopyOffset >= 64)) MatchLength = 0; if (!MatchLength) { /* Literal */ - Literal = *SrcPtr++; HistoryPtr++; @@ -2378,13 +2393,12 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE IndexLEC = Literal; BitLength = HuffLengthLEC[IndexLEC]; - pCodeLEC = (UINT16*) &HuffCodeLEC[IndexLEC * 2]; - CodeLEC = (UINT32) *pCodeLEC; + CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); if (BitLength > 15) return -1006; - NCrushWriteBits(CodeLEC, BitLength); + NCrushWriteBits(&DstPtr, &accumulator, &offset, CodeLEC, BitLength); } else { @@ -2407,7 +2421,7 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE OffsetCacheIndex = 5; if ((CopyOffset == OffsetCache[0]) || (CopyOffset == OffsetCache[1]) || - (CopyOffset == OffsetCache[2]) || (CopyOffset == OffsetCache[3])) + (CopyOffset == OffsetCache[2]) || (CopyOffset == OffsetCache[3])) { if (CopyOffset == OffsetCache[3]) { @@ -2455,7 +2469,6 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE if (OffsetCacheIndex >= 4) { /* CopyOffset not in OffsetCache */ - if (CopyOffset >= 256) bits = (CopyOffset >> 7) + 256; else @@ -2463,24 +2476,20 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE CopyOffsetIndex = ncrush->HuffTableCopyOffset[bits + 2]; CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex]; - IndexLEC = 257 + CopyOffsetIndex; BitLength = HuffLengthLEC[IndexLEC]; - pCodeLEC = (UINT16*) &HuffCodeLEC[IndexLEC * 2]; - CodeLEC = (UINT32) *pCodeLEC; + CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); if (BitLength > 15) return -1008; - + if (CopyOffsetBits > 18) return -1009; - NCrushWriteBits(CodeLEC, BitLength); - + NCrushWriteBits(&DstPtr, &accumulator, &offset, CodeLEC, BitLength); Mask = ((1 << CopyOffsetBits) - 1); MaskedBits = CopyOffset & Mask; - - NCrushWriteBits(MaskedBits, CopyOffsetBits); + NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, CopyOffsetBits); if ((MatchLength - 2) >= 768) IndexCO = 28; @@ -2489,13 +2498,10 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE BitLength = HuffLengthLOM[IndexCO]; IndexLOM = LOMBitsLUT[IndexCO]; - - NCrushWriteBits(HuffCodeLOM[IndexCO], BitLength); - + NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength); Mask = ((1 << IndexLOM) - 1); MaskedBits = (MatchLength - 2) & Mask; - - NCrushWriteBits(MaskedBits, IndexLOM); + NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM); if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength) return -1010; @@ -2503,16 +2509,14 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE else { /* CopyOffset in OffsetCache */ - IndexLEC = 289 + OffsetCacheIndex; BitLength = HuffLengthLEC[IndexLEC]; - pCodeLEC = (UINT16*) &HuffCodeLEC[IndexLEC * 2]; - CodeLEC = (UINT32) *pCodeLEC; + CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); if (BitLength >= 15) return -1011; - NCrushWriteBits(CodeLEC, BitLength); + NCrushWriteBits(&DstPtr, &accumulator, &offset, CodeLEC, BitLength); if ((MatchLength - 2) >= 768) IndexCO = 28; @@ -2521,13 +2525,10 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE BitLength = HuffLengthLOM[IndexCO]; IndexLOM = LOMBitsLUT[IndexCO]; - - NCrushWriteBits(HuffCodeLOM[IndexCO], BitLength); - + NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength); Mask = ((1 << IndexLOM) - 1); MaskedBits = (MatchLength - 2) & Mask; - - NCrushWriteBits(MaskedBits, IndexLOM); + NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM); if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength) return -1012; @@ -2552,16 +2553,14 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE Literal = *SrcPtr++; HistoryPtr++; - IndexLEC = Literal; BitLength = HuffLengthLEC[IndexLEC]; - pCodeLEC = (UINT16*) &HuffCodeLEC[IndexLEC * 2]; - CodeLEC = (UINT32) *pCodeLEC; + CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); if (BitLength > 15) return -1014; - NCrushWriteBits(CodeLEC, BitLength); + NCrushWriteBits(&DstPtr, &accumulator, &offset, CodeLEC, BitLength); } if ((DstPtr + 4) >= DstEndPtr) /* PACKET_FLUSH #4 */ @@ -2580,13 +2579,9 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE if (BitLength > 15) return -1015; - pCodeLEC = (UINT16*) &HuffCodeLEC[IndexLEC * 2]; - bits = (UINT32) *pCodeLEC; - - NCrushWriteBits(bits, BitLength); - - NCrushWriteFinish(); - + bits = get_word(&HuffCodeLEC[IndexLEC * 2]); + NCrushWriteBits(&DstPtr, &accumulator, &offset, bits, BitLength); + NCrushWriteFinish(&DstPtr, accumulator); *pDstSize = DstPtr - pDstData; if (*pDstSize > SrcSize) @@ -2609,11 +2604,11 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE return 1; } -int ncrush_generate_tables(NCRUSH_CONTEXT *context) +static int ncrush_generate_tables(NCRUSH_CONTEXT* context) { int i, j, k, l; - k = 0; + for (i = 0; i < 28; i++) { for (j = 0; j < 1 << LOMBitsLUT[i]; j++) @@ -2635,6 +2630,7 @@ int ncrush_generate_tables(NCRUSH_CONTEXT *context) } k = 0; + for (i = 0; i < 16; i++) { for (j = 0; j < 1 << CopyOffsetBitsLUT[i]; j++) @@ -2645,6 +2641,7 @@ int ncrush_generate_tables(NCRUSH_CONTEXT *context) } k /= 128; + for (i = 16; i < 32; i++) { for (j = 0; j < 1 << (CopyOffsetBitsLUT[i] - 7); j++) @@ -2664,7 +2661,6 @@ void ncrush_context_reset(NCRUSH_CONTEXT* ncrush, BOOL flush) { ZeroMemory(&(ncrush->HistoryBuffer), sizeof(ncrush->HistoryBuffer)); ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache)); - ZeroMemory(&(ncrush->MatchTable), sizeof(ncrush->MatchTable)); ZeroMemory(&(ncrush->HashTable), sizeof(ncrush->HashTable)); @@ -2679,21 +2675,16 @@ void ncrush_context_reset(NCRUSH_CONTEXT* ncrush, BOOL flush) NCRUSH_CONTEXT* ncrush_context_new(BOOL Compressor) { NCRUSH_CONTEXT* ncrush; - ncrush = (NCRUSH_CONTEXT*) calloc(1, sizeof(NCRUSH_CONTEXT)); if (ncrush) { ncrush->Compressor = Compressor; - ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache)); - ncrush->HistoryBufferSize = 65536; ncrush->HistoryEndOffset = ncrush->HistoryBufferSize - 1; - ZeroMemory(&(ncrush->HistoryBuffer), sizeof(ncrush->HistoryBuffer)); ncrush->HistoryBufferFence = 0xABABABAB; - ncrush->HistoryOffset = 0; ncrush->HistoryPtr = &(ncrush->HistoryBuffer[ncrush->HistoryOffset]); diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c index d0ec420..567b72c 100644 --- a/libfreerdp/codec/nsc.c +++ b/libfreerdp/codec/nsc.c @@ -250,12 +250,12 @@ static BOOL nsc_context_initialize(NSC_CONTEXT* context, wStream* s) static void nsc_profiler_print(NSC_CONTEXT* context) { - PROFILER_PRINT_HEADER; - PROFILER_PRINT(context->priv->prof_nsc_rle_decompress_data); - PROFILER_PRINT(context->priv->prof_nsc_decode); - PROFILER_PRINT(context->priv->prof_nsc_rle_compress_data); - PROFILER_PRINT(context->priv->prof_nsc_encode); - PROFILER_PRINT_FOOTER; + PROFILER_PRINT_HEADER + PROFILER_PRINT(context->priv->prof_nsc_rle_decompress_data) + PROFILER_PRINT(context->priv->prof_nsc_decode) + PROFILER_PRINT(context->priv->prof_nsc_rle_compress_data) + PROFILER_PRINT(context->priv->prof_nsc_encode) + PROFILER_PRINT_FOOTER } BOOL nsc_context_reset(NSC_CONTEXT* context, UINT32 width, UINT32 height) @@ -281,7 +281,6 @@ NSC_CONTEXT* nsc_context_new(void) if (!context->priv) goto error_priv; - WLog_Init(); context->priv->log = WLog_Get("com.freerdp.codec.nsc"); WLog_OpenAppender(context->priv->log); context->BitmapData = NULL; @@ -293,11 +292,11 @@ NSC_CONTEXT* nsc_context_new(void) goto error_PlanePool; PROFILER_CREATE(context->priv->prof_nsc_rle_decompress_data, - "nsc_rle_decompress_data"); - PROFILER_CREATE(context->priv->prof_nsc_decode, "nsc_decode"); + "nsc_rle_decompress_data") + PROFILER_CREATE(context->priv->prof_nsc_decode, "nsc_decode") PROFILER_CREATE(context->priv->prof_nsc_rle_compress_data, - "nsc_rle_compress_data"); - PROFILER_CREATE(context->priv->prof_nsc_encode, "nsc_encode"); + "nsc_rle_compress_data") + PROFILER_CREATE(context->priv->prof_nsc_encode, "nsc_encode") /* Default encoding parameters */ context->ColorLossLevel = 3; context->ChromaSubsamplingLevel = 1; @@ -327,10 +326,10 @@ void nsc_context_free(NSC_CONTEXT* context) free(context->BitmapData); BufferPool_Free(context->priv->PlanePool); nsc_profiler_print(context); - PROFILER_FREE(context->priv->prof_nsc_rle_decompress_data); - PROFILER_FREE(context->priv->prof_nsc_decode); - PROFILER_FREE(context->priv->prof_nsc_rle_compress_data); - PROFILER_FREE(context->priv->prof_nsc_encode); + PROFILER_FREE(context->priv->prof_nsc_rle_decompress_data) + PROFILER_FREE(context->priv->prof_nsc_decode) + PROFILER_FREE(context->priv->prof_nsc_rle_compress_data) + PROFILER_FREE(context->priv->prof_nsc_encode) free(context->priv); free(context); } @@ -397,13 +396,13 @@ BOOL nsc_process_message(NSC_CONTEXT* context, UINT16 bpp, return FALSE; /* RLE decode */ - PROFILER_ENTER(context->priv->prof_nsc_rle_decompress_data); + PROFILER_ENTER(context->priv->prof_nsc_rle_decompress_data) nsc_rle_decompress_data(context); - PROFILER_EXIT(context->priv->prof_nsc_rle_decompress_data); + PROFILER_EXIT(context->priv->prof_nsc_rle_decompress_data) /* Colorloss recover, Chroma supersample and AYCoCg to ARGB Conversion in one step */ - PROFILER_ENTER(context->priv->prof_nsc_decode); + PROFILER_ENTER(context->priv->prof_nsc_decode) context->decode(context); - PROFILER_EXIT(context->priv->prof_nsc_decode); + PROFILER_EXIT(context->priv->prof_nsc_decode) if (!freerdp_image_copy(pDstData, DstFormat, nDstStride, nXDst, nYDst, width, height, context->BitmapData, diff --git a/libfreerdp/codec/nsc_encode.c b/libfreerdp/codec/nsc_encode.c index 716cfe8..492f170 100644 --- a/libfreerdp/codec/nsc_encode.c +++ b/libfreerdp/codec/nsc_encode.c @@ -50,11 +50,11 @@ static BOOL nsc_context_initialize_encode(NSC_CONTEXT* context) { for (i = 0; i < 5; i++) { - context->priv->PlaneBuffers[i] = (BYTE*) realloc(context->priv->PlaneBuffers[i], - length); - - if (!context->priv->PlaneBuffers[i]) + BYTE* tmp = (BYTE*) realloc(context->priv->PlaneBuffers[i], length); + if (!tmp) goto fail; + + context->priv->PlaneBuffers[i] = tmp; } context->priv->PlaneBuffersLength = length; @@ -104,9 +104,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data, INT16 b_val; BYTE a_val; UINT32 tempWidth; - UINT32 tempHeight; tempWidth = ROUND_UP_TO(context->width, 8); - tempHeight = ROUND_UP_TO(context->height, 2); rw = (context->ChromaSubsamplingLevel ? tempWidth : context->width); ccl = context->ColorLossLevel; @@ -237,9 +235,12 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data, if (context->ChromaSubsamplingLevel && (y % 2) == 1) { - CopyMemory(yplane + rw, yplane, rw); - CopyMemory(coplane + rw, coplane, rw); - CopyMemory(cgplane + rw, cgplane, rw); + yplane = context->priv->PlaneBuffers[0] + y * rw; + coplane = context->priv->PlaneBuffers[1] + y * rw; + cgplane = context->priv->PlaneBuffers[2] + y * rw; + CopyMemory(yplane, yplane - rw, rw); + CopyMemory(coplane, coplane - rw, rw); + CopyMemory(cgplane, cgplane - rw, rw); } } @@ -493,12 +494,12 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, const BYTE* data, context->priv->PlaneBuffers[4] = messages[i].PlaneBuffers[4]; dataOffset = (messages[i].y * messages[i].scanline) + (messages[i].x * BytesPerPixel); - PROFILER_ENTER(context->priv->prof_nsc_encode); + PROFILER_ENTER(context->priv->prof_nsc_encode) context->encode(context, &data[dataOffset], scanline); - PROFILER_EXIT(context->priv->prof_nsc_encode); - PROFILER_ENTER(context->priv->prof_nsc_rle_compress_data); + PROFILER_EXIT(context->priv->prof_nsc_encode) + PROFILER_ENTER(context->priv->prof_nsc_rle_compress_data) nsc_rle_compress_data(context); - PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data); + PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data) messages[i].LumaPlaneByteCount = context->PlaneByteCount[0]; messages[i].OrangeChromaPlaneByteCount = context->PlaneByteCount[1]; messages[i].GreenChromaPlaneByteCount = context->PlaneByteCount[2]; @@ -581,13 +582,13 @@ BOOL nsc_compose_message(NSC_CONTEXT* context, wStream* s, const BYTE* data, return FALSE; /* ARGB to AYCoCg conversion, chroma subsampling and colorloss reduction */ - PROFILER_ENTER(context->priv->prof_nsc_encode); + PROFILER_ENTER(context->priv->prof_nsc_encode) context->encode(context, data, scanline); - PROFILER_EXIT(context->priv->prof_nsc_encode); + PROFILER_EXIT(context->priv->prof_nsc_encode) /* RLE encode */ - PROFILER_ENTER(context->priv->prof_nsc_rle_compress_data); + PROFILER_ENTER(context->priv->prof_nsc_rle_compress_data) nsc_rle_compress_data(context); - PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data); + PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data) message->PlaneBuffers[0] = context->priv->PlaneBuffers[0]; message->PlaneBuffers[1] = context->priv->PlaneBuffers[1]; message->PlaneBuffers[2] = context->priv->PlaneBuffers[2]; diff --git a/libfreerdp/codec/nsc_sse2.c b/libfreerdp/codec/nsc_sse2.c index 940aad0..6bd7147 100644 --- a/libfreerdp/codec/nsc_sse2.c +++ b/libfreerdp/codec/nsc_sse2.c @@ -30,6 +30,7 @@ #include <freerdp/codec/color.h> #include <winpr/crt.h> +#include <winpr/sysinfo.h> #include "nsc_types.h" #include "nsc_sse2.h" @@ -54,9 +55,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, __m128i co_val; __m128i cg_val; UINT32 tempWidth; - UINT32 tempHeight; tempWidth = ROUND_UP_TO(context->width, 8); - tempHeight = ROUND_UP_TO(context->height, 2); rw = (context->ChromaSubsamplingLevel > 0 ? tempWidth : context->width); ccl = context->ColorLossLevel; @@ -326,9 +325,12 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, if (context->ChromaSubsamplingLevel > 0 && (y % 2) == 1) { - CopyMemory(yplane + rw, yplane, rw); - CopyMemory(coplane + rw, coplane, rw); - CopyMemory(cgplane + rw, cgplane, rw); + yplane = context->priv->PlaneBuffers[0] + y * rw; + coplane = context->priv->PlaneBuffers[1] + y * rw; + cgplane = context->priv->PlaneBuffers[2] + y * rw; + CopyMemory(yplane, yplane - rw, rw); + CopyMemory(coplane, coplane - rw, rw); + CopyMemory(cgplane, cgplane - rw, rw); } } @@ -396,6 +398,9 @@ static void nsc_encode_sse2(NSC_CONTEXT* context, const BYTE* data, void nsc_init_sse2(NSC_CONTEXT* context) { + if (!IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) + return; + IF_PROFILER(context->priv->prof_nsc_encode->name = "nsc_encode_sse2"); context->encode = nsc_encode_sse2; } diff --git a/libfreerdp/codec/nsc_types.h b/libfreerdp/codec/nsc_types.h index 9045008..37c0e2f 100644 --- a/libfreerdp/codec/nsc_types.h +++ b/libfreerdp/codec/nsc_types.h @@ -45,10 +45,10 @@ struct _NSC_CONTEXT_PRIV UINT32 PlaneBuffersLength; /* Lengths of each plane buffer */ /* profilers */ - PROFILER_DEFINE(prof_nsc_rle_decompress_data); - PROFILER_DEFINE(prof_nsc_decode); - PROFILER_DEFINE(prof_nsc_rle_compress_data); - PROFILER_DEFINE(prof_nsc_encode); + PROFILER_DEFINE(prof_nsc_rle_decompress_data) + PROFILER_DEFINE(prof_nsc_decode) + PROFILER_DEFINE(prof_nsc_rle_compress_data) + PROFILER_DEFINE(prof_nsc_encode) }; #endif /* FREERDP_LIB_CODEC_NSC_TYPES_H */ diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index bf62e58..deb2763 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -258,7 +258,7 @@ static INLINE BOOL writeLine(BYTE** ppRgba, UINT32 DstFormat, UINT32 width, cons for (x = 0; x < width; x++) { BYTE alpha = *(*ppA)++; - UINT32 color = GetColor(DstFormat, *(*ppR)++, *(*ppG)++, *(*ppB)++, alpha); + UINT32 color = FreeRDPGetColor(DstFormat, *(*ppR)++, *(*ppG)++, *(*ppB)++, alpha); WriteColor(*ppRgba, DstFormat, color); *ppRgba += GetBytesPerPixel(DstFormat); } @@ -269,7 +269,7 @@ static INLINE BOOL writeLine(BYTE** ppRgba, UINT32 DstFormat, UINT32 width, cons for (x = 0; x < width; x++) { - UINT32 color = GetColor(DstFormat, *(*ppR)++, *(*ppG)++, *(*ppB)++, alpha); + UINT32 color = FreeRDPGetColor(DstFormat, *(*ppR)++, *(*ppG)++, *(*ppB)++, alpha); WriteColor(*ppRgba, DstFormat, color); *ppRgba += GetBytesPerPixel(DstFormat); } @@ -309,7 +309,7 @@ static INLINE BOOL planar_decompress_planes_raw(const BYTE* pSrcData[4], for (y = beg; y != end; y += inc) { BYTE* pRGB = &pDstData[((nYDst + y) * nDstStep) + (nXDst * GetBytesPerPixel( - DstFormat))]; + DstFormat))]; if (!writeLine(&pRGB, DstFormat, nWidth, &pR, &pG, &pB, &pA)) return FALSE; @@ -320,7 +320,7 @@ static INLINE BOOL planar_decompress_planes_raw(const BYTE* pSrcData[4], for (y = beg; y != end; y += inc) { BYTE* pRGB = &pDstData[((nYDst + y) * nDstStep) + (nXDst * GetBytesPerPixel( - DstFormat))]; + DstFormat))]; if (!writeLine(&pRGB, DstFormat, nWidth, &pR, &pG, &pB, &pA)) return FALSE; @@ -573,7 +573,7 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, } else /* NoAlpha */ { - const UINT32 color = GetColor(TempFormat, 0, 0, 0, 0xFF); + const UINT32 color = FreeRDPGetColor(TempFormat, 0, 0, 0, 0xFF); if (!freerdp_image_fill(pTempData, TempFormat, nTempStep, nXDst, nYDst, nSrcWidth, nSrcHeight, color)) @@ -614,9 +614,14 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, } else /* YCoCg */ { + UINT32 TempFormat; BYTE* pTempData = planar->pTempData; UINT32 nTempStep = planar->nTempStep; - UINT32 TempFormat = PIXEL_FORMAT_BGRA32; + + if (alpha) + TempFormat = PIXEL_FORMAT_BGRA32; + else + TempFormat = PIXEL_FORMAT_BGRX32; if (!pTempData) return FALSE; @@ -998,7 +1003,7 @@ BYTE* freerdp_bitmap_planar_compress_plane_rle(const BYTE* inPlane, return outPlane; } -static INLINE UINT32 freerdp_bitmap_planar_compress_planes_rle( +static INLINE BOOL freerdp_bitmap_planar_compress_planes_rle( BYTE* inPlanes[4], UINT32 width, UINT32 height, BYTE* outPlanes, UINT32* dstSizes, BOOL skipAlpha) { @@ -1015,7 +1020,7 @@ static INLINE UINT32 freerdp_bitmap_planar_compress_planes_rle( if (!freerdp_bitmap_planar_compress_plane_rle( inPlanes[0], width, height, outPlanes, &dstSizes[0])) - return 0; + return FALSE; outPlanes += dstSizes[0]; outPlanesSize -= dstSizes[0]; @@ -1026,7 +1031,7 @@ static INLINE UINT32 freerdp_bitmap_planar_compress_planes_rle( if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[1], width, height, outPlanes, &dstSizes[1])) - return 0; + return FALSE; outPlanes += dstSizes[1]; outPlanesSize -= dstSizes[1]; @@ -1035,7 +1040,7 @@ static INLINE UINT32 freerdp_bitmap_planar_compress_planes_rle( if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[2], width, height, outPlanes, &dstSizes[2])) - return 0; + return FALSE; outPlanes += dstSizes[2]; outPlanesSize -= dstSizes[2]; @@ -1044,9 +1049,9 @@ static INLINE UINT32 freerdp_bitmap_planar_compress_planes_rle( if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[3], width, height, outPlanes, &dstSizes[3])) - return 0; + return FALSE; - return 1; + return TRUE; } BYTE* freerdp_bitmap_planar_delta_encode_plane(const BYTE* inPlane, @@ -1136,10 +1141,12 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, context->deltaPlanes)) return NULL; - if (freerdp_bitmap_planar_compress_planes_rle( + if (!freerdp_bitmap_planar_compress_planes_rle( context->deltaPlanes, width, height, context->rlePlanesBuffer, dstSizes, - context->AllowSkipAlpha) > 0) + context->AllowSkipAlpha)) + return NULL; + { int offset = 0; FormatHeader |= PLANAR_FORMAT_HEADER_RLE; @@ -1155,6 +1162,24 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, } } + if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) + { + if (!context->AllowRunLengthEncoding) + return NULL; + + if (context->rlePlanes[0] == NULL) + return NULL; + + if (context->rlePlanes[1] == NULL) + return NULL; + + if (context->rlePlanes[2] == NULL) + return NULL; + + if (context->rlePlanes[3] == NULL) + return NULL; + } + if (!dstData) { size = 1; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index def5384..d3dc5c3 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -1684,15 +1684,19 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, if (region->numRects > progressive->cRects) { - progressive->rects = (RFX_RECT*) realloc(progressive->rects, - region->numRects * sizeof(RFX_RECT)); + RFX_RECT* tmpBuf = (RFX_RECT*) realloc(progressive->rects, + region->numRects * sizeof(RFX_RECT)); + if (!tmpBuf) + return -1016; + + progressive->rects = tmpBuf; progressive->cRects = region->numRects; } region->rects = progressive->rects; if (!region->rects) - return -1016; + return -1017; for (index = 0; index < region->numRects; index++) { @@ -1705,20 +1709,24 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, } if ((blockLen - boffset) < (region->numQuant * 5)) - return -1017; + return -1018; if (region->numQuant > progressive->cQuant) { - progressive->quantVals = (RFX_COMPONENT_CODEC_QUANT*) realloc( + RFX_COMPONENT_CODEC_QUANT* tmpBuf = (RFX_COMPONENT_CODEC_QUANT*) realloc( progressive->quantVals, region->numQuant * sizeof(RFX_COMPONENT_CODEC_QUANT)); + if (!tmpBuf) + return -1019; + + progressive->quantVals = tmpBuf; progressive->cQuant = region->numQuant; } region->quantVals = progressive->quantVals; if (!region->quantVals) - return -1018; + return -1020; for (index = 0; index < region->numQuant; index++) { @@ -1734,20 +1742,24 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, } if ((blockLen - boffset) < (region->numProgQuant * 16)) - return -1019; + return -1021; if (region->numProgQuant > progressive->cProgQuant) { - progressive->quantProgVals = (RFX_PROGRESSIVE_CODEC_QUANT*) realloc( + RFX_PROGRESSIVE_CODEC_QUANT* tmpBuf = (RFX_PROGRESSIVE_CODEC_QUANT*) realloc( progressive->quantProgVals, region->numProgQuant * sizeof(RFX_PROGRESSIVE_CODEC_QUANT)); + if (!tmpBuf) + return -1022; + + progressive->quantProgVals = tmpBuf; progressive->cProgQuant = region->numProgQuant; } region->quantProgVals = progressive->quantProgVals; if (!region->quantProgVals) - return -1020; + return -1023; for (index = 0; index < region->numProgQuant; index++) { @@ -1763,12 +1775,16 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, } if ((blockLen - boffset) < region->tileDataSize) - return -1021; + return -1024; if (progressive->cTiles < surface->gridSize) { - progressive->tiles = (RFX_PROGRESSIVE_TILE**) realloc(progressive->tiles, + RFX_PROGRESSIVE_TILE** tmpBuf = (RFX_PROGRESSIVE_TILE**) realloc(progressive->tiles, surface->gridSize * sizeof(RFX_PROGRESSIVE_TILE*)); + if (!tmpBuf) + return -1025; + + progressive->tiles = tmpBuf; progressive->cTiles = surface->gridSize; } diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index ce03a74..b7b0873 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -81,68 +81,68 @@ static const UINT32 rfx_default_quantization_values[] = static void rfx_profiler_create(RFX_CONTEXT* context) { - PROFILER_CREATE(context->priv->prof_rfx_decode_rgb, "rfx_decode_rgb"); + PROFILER_CREATE(context->priv->prof_rfx_decode_rgb, "rfx_decode_rgb") PROFILER_CREATE(context->priv->prof_rfx_decode_component, - "rfx_decode_component"); - PROFILER_CREATE(context->priv->prof_rfx_rlgr_decode, "rfx_rlgr_decode"); + "rfx_decode_component") + PROFILER_CREATE(context->priv->prof_rfx_rlgr_decode, "rfx_rlgr_decode") PROFILER_CREATE(context->priv->prof_rfx_differential_decode, - "rfx_differential_decode"); + "rfx_differential_decode") PROFILER_CREATE(context->priv->prof_rfx_quantization_decode, - "rfx_quantization_decode"); - PROFILER_CREATE(context->priv->prof_rfx_dwt_2d_decode, "rfx_dwt_2d_decode"); - PROFILER_CREATE(context->priv->prof_rfx_ycbcr_to_rgb, "prims->yCbCrToRGB"); - PROFILER_CREATE(context->priv->prof_rfx_encode_rgb, "rfx_encode_rgb"); + "rfx_quantization_decode") + PROFILER_CREATE(context->priv->prof_rfx_dwt_2d_decode, "rfx_dwt_2d_decode") + PROFILER_CREATE(context->priv->prof_rfx_ycbcr_to_rgb, "prims->yCbCrToRGB") + PROFILER_CREATE(context->priv->prof_rfx_encode_rgb, "rfx_encode_rgb") PROFILER_CREATE(context->priv->prof_rfx_encode_component, - "rfx_encode_component"); - PROFILER_CREATE(context->priv->prof_rfx_rlgr_encode, "rfx_rlgr_encode"); + "rfx_encode_component") + PROFILER_CREATE(context->priv->prof_rfx_rlgr_encode, "rfx_rlgr_encode") PROFILER_CREATE(context->priv->prof_rfx_differential_encode, - "rfx_differential_encode"); + "rfx_differential_encode") PROFILER_CREATE(context->priv->prof_rfx_quantization_encode, - "rfx_quantization_encode"); - PROFILER_CREATE(context->priv->prof_rfx_dwt_2d_encode, "rfx_dwt_2d_encode"); - PROFILER_CREATE(context->priv->prof_rfx_rgb_to_ycbcr, "prims->RGBToYCbCr"); + "rfx_quantization_encode") + PROFILER_CREATE(context->priv->prof_rfx_dwt_2d_encode, "rfx_dwt_2d_encode") + PROFILER_CREATE(context->priv->prof_rfx_rgb_to_ycbcr, "prims->RGBToYCbCr") PROFILER_CREATE(context->priv->prof_rfx_encode_format_rgb, - "rfx_encode_format_rgb"); + "rfx_encode_format_rgb") } static void rfx_profiler_free(RFX_CONTEXT* context) { - PROFILER_FREE(context->priv->prof_rfx_decode_rgb); - PROFILER_FREE(context->priv->prof_rfx_decode_component); - PROFILER_FREE(context->priv->prof_rfx_rlgr_decode); - PROFILER_FREE(context->priv->prof_rfx_differential_decode); - PROFILER_FREE(context->priv->prof_rfx_quantization_decode); - PROFILER_FREE(context->priv->prof_rfx_dwt_2d_decode); - PROFILER_FREE(context->priv->prof_rfx_ycbcr_to_rgb); - PROFILER_FREE(context->priv->prof_rfx_encode_rgb); - PROFILER_FREE(context->priv->prof_rfx_encode_component); - PROFILER_FREE(context->priv->prof_rfx_rlgr_encode); - PROFILER_FREE(context->priv->prof_rfx_differential_encode); - PROFILER_FREE(context->priv->prof_rfx_quantization_encode); - PROFILER_FREE(context->priv->prof_rfx_dwt_2d_encode); - PROFILER_FREE(context->priv->prof_rfx_rgb_to_ycbcr); - PROFILER_FREE(context->priv->prof_rfx_encode_format_rgb); + PROFILER_FREE(context->priv->prof_rfx_decode_rgb) + PROFILER_FREE(context->priv->prof_rfx_decode_component) + PROFILER_FREE(context->priv->prof_rfx_rlgr_decode) + PROFILER_FREE(context->priv->prof_rfx_differential_decode) + PROFILER_FREE(context->priv->prof_rfx_quantization_decode) + PROFILER_FREE(context->priv->prof_rfx_dwt_2d_decode) + PROFILER_FREE(context->priv->prof_rfx_ycbcr_to_rgb) + PROFILER_FREE(context->priv->prof_rfx_encode_rgb) + PROFILER_FREE(context->priv->prof_rfx_encode_component) + PROFILER_FREE(context->priv->prof_rfx_rlgr_encode) + PROFILER_FREE(context->priv->prof_rfx_differential_encode) + PROFILER_FREE(context->priv->prof_rfx_quantization_encode) + PROFILER_FREE(context->priv->prof_rfx_dwt_2d_encode) + PROFILER_FREE(context->priv->prof_rfx_rgb_to_ycbcr) + PROFILER_FREE(context->priv->prof_rfx_encode_format_rgb) } static void rfx_profiler_print(RFX_CONTEXT* context) { - PROFILER_PRINT_HEADER; - PROFILER_PRINT(context->priv->prof_rfx_decode_rgb); - PROFILER_PRINT(context->priv->prof_rfx_decode_component); - PROFILER_PRINT(context->priv->prof_rfx_rlgr_decode); - PROFILER_PRINT(context->priv->prof_rfx_differential_decode); - PROFILER_PRINT(context->priv->prof_rfx_quantization_decode); - PROFILER_PRINT(context->priv->prof_rfx_dwt_2d_decode); - PROFILER_PRINT(context->priv->prof_rfx_ycbcr_to_rgb); - PROFILER_PRINT(context->priv->prof_rfx_encode_rgb); - PROFILER_PRINT(context->priv->prof_rfx_encode_component); - PROFILER_PRINT(context->priv->prof_rfx_rlgr_encode); - PROFILER_PRINT(context->priv->prof_rfx_differential_encode); - PROFILER_PRINT(context->priv->prof_rfx_quantization_encode); - PROFILER_PRINT(context->priv->prof_rfx_dwt_2d_encode); - PROFILER_PRINT(context->priv->prof_rfx_rgb_to_ycbcr); - PROFILER_PRINT(context->priv->prof_rfx_encode_format_rgb); - PROFILER_PRINT_FOOTER; + PROFILER_PRINT_HEADER + PROFILER_PRINT(context->priv->prof_rfx_decode_rgb) + PROFILER_PRINT(context->priv->prof_rfx_decode_component) + PROFILER_PRINT(context->priv->prof_rfx_rlgr_decode) + PROFILER_PRINT(context->priv->prof_rfx_differential_decode) + PROFILER_PRINT(context->priv->prof_rfx_quantization_decode) + PROFILER_PRINT(context->priv->prof_rfx_dwt_2d_decode) + PROFILER_PRINT(context->priv->prof_rfx_ycbcr_to_rgb) + PROFILER_PRINT(context->priv->prof_rfx_encode_rgb) + PROFILER_PRINT(context->priv->prof_rfx_encode_component) + PROFILER_PRINT(context->priv->prof_rfx_rlgr_encode) + PROFILER_PRINT(context->priv->prof_rfx_differential_encode) + PROFILER_PRINT(context->priv->prof_rfx_quantization_encode) + PROFILER_PRINT(context->priv->prof_rfx_dwt_2d_encode) + PROFILER_PRINT(context->priv->prof_rfx_rgb_to_ycbcr) + PROFILER_PRINT(context->priv->prof_rfx_encode_format_rgb) + PROFILER_PRINT_FOOTER } static void rfx_tile_init(RFX_TILE* tile) @@ -220,7 +220,6 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder) if (!priv) goto error_priv; - WLog_Init(); priv->log = WLog_Get("com.freerdp.codec.rfx"); WLog_OpenAppender(priv->log); #ifdef WITH_DEBUG_RFX @@ -756,7 +755,7 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, { BOOL rc; int i, close_cnt; - int pos; + size_t pos; BYTE quant; RFX_TILE* tile; UINT32* quants; @@ -949,7 +948,7 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, params[i].context = context; params[i].tile = message->tiles[i]; - if (!(work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) + if (!(work_objects[i] = CreateThreadpoolWork( rfx_process_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv))) { @@ -999,7 +998,7 @@ BOOL rfx_process_message(RFX_CONTEXT* context, const BYTE* data, UINT32 length, UINT32 dstStride, UINT32 dstHeight, REGION16* invalidRegion) { - int pos; + size_t pos; REGION16 updateRegion; UINT32 blockLen; UINT32 blockType; @@ -1150,7 +1149,7 @@ BOOL rfx_process_message(RFX_CONTEXT* context, const BYTE* data, UINT32 length, REGION16 clippingRects; const RECTANGLE_16* updateRects; const DWORD formatSize = GetBytesPerPixel(context->pixel_format); - const UINT32 dstWidth = dstStride / formatSize; + const UINT32 dstWidth = dstStride / GetBytesPerPixel(dstFormat); region16_init(&clippingRects); for (i = 0; i < message->numRects; i++) @@ -1367,7 +1366,7 @@ struct _RFX_TILE_COMPOSE_WORK_PARAM RFX_CONTEXT* context; }; -void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE +static void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) { RFX_TILE_COMPOSE_WORK_PARAM* param = (RFX_TILE_COMPOSE_WORK_PARAM*) context; @@ -1580,7 +1579,7 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, workParam->tile = tile; if (!(*workObject = CreateThreadpoolWork( - (PTP_WORK_CALLBACK)rfx_compose_message_tile_work_callback, + rfx_compose_message_tile_work_callback, (void*) workParam, &context->priv->ThreadPoolEnv))) { @@ -1622,32 +1621,34 @@ skip_encoding_loop: } /* when using threads ensure all computations are done */ - message->tilesDataSize = 0; - workObject = context->priv->workObjects; - - for (i = 0; i < message->numTiles; i++) + if (success) { - tile = message->tiles[i]; + message->tilesDataSize = 0; + workObject = context->priv->workObjects; - if (context->priv->UseThreads) + for (i = 0; i < message->numTiles; i++) { - if (*workObject) + tile = message->tiles[i]; + + if (context->priv->UseThreads) { - WaitForThreadpoolWorkCallbacks(*workObject, FALSE); - CloseThreadpoolWork(*workObject); + if (*workObject) + { + WaitForThreadpoolWorkCallbacks(*workObject, FALSE); + CloseThreadpoolWork(*workObject); + } + + workObject++; } - workObject++; + message->tilesDataSize += rfx_tile_length(tile); } - message->tilesDataSize += rfx_tile_length(tile); - } + region16_uninit(&tilesRegion); + region16_uninit(&rectsRegion); - region16_uninit(&tilesRegion); - region16_uninit(&rectsRegion); - - if (success) return message; + } WLog_ERR(TAG, "%s: failed", __FUNCTION__); message->freeRects = TRUE; diff --git a/libfreerdp/codec/rfx_decode.c b/libfreerdp/codec/rfx_decode.c index 11d7629..58e316d 100644 --- a/libfreerdp/codec/rfx_decode.c +++ b/libfreerdp/codec/rfx_decode.c @@ -43,20 +43,20 @@ static void rfx_decode_component(RFX_CONTEXT* context, { INT16* dwt_buffer; dwt_buffer = BufferPool_Take(context->priv->BufferPool, -1); /* dwt_buffer */ - PROFILER_ENTER(context->priv->prof_rfx_decode_component); - PROFILER_ENTER(context->priv->prof_rfx_rlgr_decode); + PROFILER_ENTER(context->priv->prof_rfx_decode_component) + PROFILER_ENTER(context->priv->prof_rfx_rlgr_decode) context->rlgr_decode(context->mode, data, size, buffer, 4096); - PROFILER_EXIT(context->priv->prof_rfx_rlgr_decode); - PROFILER_ENTER(context->priv->prof_rfx_differential_decode); + PROFILER_EXIT(context->priv->prof_rfx_rlgr_decode) + PROFILER_ENTER(context->priv->prof_rfx_differential_decode) rfx_differential_decode(buffer + 4032, 64); - PROFILER_EXIT(context->priv->prof_rfx_differential_decode); - PROFILER_ENTER(context->priv->prof_rfx_quantization_decode); + PROFILER_EXIT(context->priv->prof_rfx_differential_decode) + PROFILER_ENTER(context->priv->prof_rfx_quantization_decode) context->quantization_decode(buffer, quantization_values); - PROFILER_EXIT(context->priv->prof_rfx_quantization_decode); - PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_decode); + PROFILER_EXIT(context->priv->prof_rfx_quantization_decode) + PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_decode) context->dwt_2d_decode(buffer, dwt_buffer); - PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_decode); - PROFILER_EXIT(context->priv->prof_rfx_decode_component); + PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_decode) + PROFILER_EXIT(context->priv->prof_rfx_decode_component) BufferPool_Return(context->priv->BufferPool, dwt_buffer); } @@ -72,7 +72,7 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, UINT32* y_quants, *cb_quants, *cr_quants; static const prim_size_t roi_64x64 = { 64, 64 }; const primitives_t* prims = primitives_get(); - PROFILER_ENTER(context->priv->prof_rfx_decode_rgb); + PROFILER_ENTER(context->priv->prof_rfx_decode_rgb) y_quants = context->quants + (tile->quantIdxY * 10); cb_quants = context->quants + (tile->quantIdxCb * 10); cr_quants = context->quants + (tile->quantIdxCr * 10); @@ -89,14 +89,14 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, pSrcDst[1]); /* CbData */ rfx_decode_component(context, cr_quants, tile->CrData, tile->CrLen, pSrcDst[2]); /* CrData */ - PROFILER_ENTER(context->priv->prof_rfx_ycbcr_to_rgb); + PROFILER_ENTER(context->priv->prof_rfx_ycbcr_to_rgb) if (prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**)pSrcDst, 64 * sizeof(INT16), rgb_buffer, stride, context->pixel_format, &roi_64x64) != PRIMITIVES_SUCCESS) rc = FALSE; - PROFILER_EXIT(context->priv->prof_rfx_ycbcr_to_rgb); - PROFILER_EXIT(context->priv->prof_rfx_decode_rgb); + PROFILER_EXIT(context->priv->prof_rfx_ycbcr_to_rgb) + PROFILER_EXIT(context->priv->prof_rfx_decode_rgb) BufferPool_Return(context->priv->BufferPool, pBuffer); return rc; } diff --git a/libfreerdp/codec/rfx_encode.c b/libfreerdp/codec/rfx_encode.c index cdd69e5..1ee102a 100644 --- a/libfreerdp/codec/rfx_encode.c +++ b/libfreerdp/codec/rfx_encode.c @@ -238,20 +238,20 @@ static void rfx_encode_component(RFX_CONTEXT* context, { INT16* dwt_buffer; dwt_buffer = BufferPool_Take(context->priv->BufferPool, -1); /* dwt_buffer */ - PROFILER_ENTER(context->priv->prof_rfx_encode_component); - PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_encode); + PROFILER_ENTER(context->priv->prof_rfx_encode_component) + PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_encode) context->dwt_2d_encode(data, dwt_buffer); - PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_encode); - PROFILER_ENTER(context->priv->prof_rfx_quantization_encode); + PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_encode) + PROFILER_ENTER(context->priv->prof_rfx_quantization_encode) context->quantization_encode(data, quantization_values); - PROFILER_EXIT(context->priv->prof_rfx_quantization_encode); - PROFILER_ENTER(context->priv->prof_rfx_differential_encode); + PROFILER_EXIT(context->priv->prof_rfx_quantization_encode) + PROFILER_ENTER(context->priv->prof_rfx_differential_encode) rfx_differential_encode(data + 4032, 64); - PROFILER_EXIT(context->priv->prof_rfx_differential_encode); - PROFILER_ENTER(context->priv->prof_rfx_rlgr_encode); + PROFILER_EXIT(context->priv->prof_rfx_differential_encode) + PROFILER_ENTER(context->priv->prof_rfx_rlgr_encode) *size = context->rlgr_encode(context->mode, data, 4096, buffer, buffer_size); - PROFILER_EXIT(context->priv->prof_rfx_rlgr_encode); - PROFILER_EXIT(context->priv->prof_rfx_encode_component); + PROFILER_EXIT(context->priv->prof_rfx_rlgr_encode) + PROFILER_EXIT(context->priv->prof_rfx_encode_component) BufferPool_Return(context->priv->BufferPool, dwt_buffer); } @@ -277,15 +277,15 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile) 16])); /* cb_g_buffer */ pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* cr_b_buffer */ - PROFILER_ENTER(context->priv->prof_rfx_encode_rgb); - PROFILER_ENTER(context->priv->prof_rfx_encode_format_rgb); + PROFILER_ENTER(context->priv->prof_rfx_encode_rgb) + PROFILER_ENTER(context->priv->prof_rfx_encode_format_rgb) rfx_encode_format_rgb(tile->data, tile->width, tile->height, tile->scanline, context->pixel_format, context->palette, pSrcDst[0], pSrcDst[1], pSrcDst[2]); - PROFILER_EXIT(context->priv->prof_rfx_encode_format_rgb); - PROFILER_ENTER(context->priv->prof_rfx_rgb_to_ycbcr); + PROFILER_EXIT(context->priv->prof_rfx_encode_format_rgb) + PROFILER_ENTER(context->priv->prof_rfx_rgb_to_ycbcr) prims->RGBToYCbCr_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), pSrcDst, 64 * sizeof(INT16), &roi_64x64); - PROFILER_EXIT(context->priv->prof_rfx_rgb_to_ycbcr); + PROFILER_EXIT(context->priv->prof_rfx_rgb_to_ycbcr) /** * We need to clear the buffers as the RLGR encoder expects it to be initialized to zero. * This allows simplifying and improving the performance of the encoding process. @@ -299,6 +299,6 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile) tile->YLen = (UINT16) YLen; tile->CbLen = (UINT16) CbLen; tile->CrLen = (UINT16) CrLen; - PROFILER_EXIT(context->priv->prof_rfx_encode_rgb); + PROFILER_EXIT(context->priv->prof_rfx_encode_rgb) BufferPool_Return(context->priv->BufferPool, pBuffer); } diff --git a/libfreerdp/codec/rfx_types.h b/libfreerdp/codec/rfx_types.h index e42591f..0552b15 100644 --- a/libfreerdp/codec/rfx_types.h +++ b/libfreerdp/codec/rfx_types.h @@ -59,22 +59,22 @@ struct _RFX_CONTEXT_PRIV wBufferPool* BufferPool; /* profilers */ - PROFILER_DEFINE(prof_rfx_decode_rgb); - PROFILER_DEFINE(prof_rfx_decode_component); - PROFILER_DEFINE(prof_rfx_rlgr_decode); - PROFILER_DEFINE(prof_rfx_differential_decode); - PROFILER_DEFINE(prof_rfx_quantization_decode); - PROFILER_DEFINE(prof_rfx_dwt_2d_decode); - PROFILER_DEFINE(prof_rfx_ycbcr_to_rgb); + PROFILER_DEFINE(prof_rfx_decode_rgb) + PROFILER_DEFINE(prof_rfx_decode_component) + PROFILER_DEFINE(prof_rfx_rlgr_decode) + PROFILER_DEFINE(prof_rfx_differential_decode) + PROFILER_DEFINE(prof_rfx_quantization_decode) + PROFILER_DEFINE(prof_rfx_dwt_2d_decode) + PROFILER_DEFINE(prof_rfx_ycbcr_to_rgb) - PROFILER_DEFINE(prof_rfx_encode_rgb); - PROFILER_DEFINE(prof_rfx_encode_component); - PROFILER_DEFINE(prof_rfx_rlgr_encode); - PROFILER_DEFINE(prof_rfx_differential_encode); - PROFILER_DEFINE(prof_rfx_quantization_encode); - PROFILER_DEFINE(prof_rfx_dwt_2d_encode); - PROFILER_DEFINE(prof_rfx_rgb_to_ycbcr); - PROFILER_DEFINE(prof_rfx_encode_format_rgb); + PROFILER_DEFINE(prof_rfx_encode_rgb) + PROFILER_DEFINE(prof_rfx_encode_component) + PROFILER_DEFINE(prof_rfx_rlgr_encode) + PROFILER_DEFINE(prof_rfx_differential_encode) + PROFILER_DEFINE(prof_rfx_quantization_encode) + PROFILER_DEFINE(prof_rfx_dwt_2d_encode) + PROFILER_DEFINE(prof_rfx_rgb_to_ycbcr) + PROFILER_DEFINE(prof_rfx_encode_format_rgb) }; #endif /* FREERDP_LIB_CODEC_RFX_TYPES_H */ diff --git a/libfreerdp/codec/test/TestFreeRDPCodecNCrush.c b/libfreerdp/codec/test/TestFreeRDPCodecNCrush.c index c82ead2..ec29593 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecNCrush.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecNCrush.c @@ -6,13 +6,13 @@ static const BYTE TEST_BELLS_DATA[] = "for.whom.the.bell.tolls,.the.bell.tolls.for.thee!"; static const BYTE TEST_BELLS_NCRUSH[] = - "\xfb\x1d\x7e\xe4\xda\xc7\x1d\x70\xf8\xa1\x6b\x1f\x7d\xc0\xbe\x6b" - "\xef\xb5\xef\x21\x87\xd0\xc5\xe1\x85\x71\xd4\x10\x16\xe7\xda\xfb" - "\x1d\x7e\xe4\xda\x47\x1f\xb0\xef\xbe\xbd\xff\x2f"; + "\xfb\x1d\x7e\xe4\xda\xc7\x1d\x70\xf8\xa1\x6b\x1f\x7d\xc0\xbe\x6b" + "\xef\xb5\xef\x21\x87\xd0\xc5\xe1\x85\x71\xd4\x10\x16\xe7\xda\xfb" + "\x1d\x7e\xe4\xda\x47\x1f\xb0\xef\xbe\xbd\xff\x2f"; -static int test_NCrushCompressBells(void) +static BOOL test_NCrushCompressBells(void) { - int rc = -1; + BOOL rc = FALSE; int status; UINT32 Flags; UINT32 SrcSize; @@ -22,8 +22,9 @@ static int test_NCrushCompressBells(void) UINT32 expectedSize; BYTE OutputBuffer[65536]; NCRUSH_CONTEXT* ncrush = ncrush_context_new(TRUE); + if (!ncrush) - return -1; + return rc; SrcSize = sizeof(TEST_BELLS_DATA) - 1; pSrcData = (BYTE*) TEST_BELLS_DATA; @@ -32,13 +33,16 @@ static int test_NCrushCompressBells(void) DstSize = sizeof(OutputBuffer); ZeroMemory(OutputBuffer, sizeof(OutputBuffer)); status = ncrush_compress(ncrush, pSrcData, SrcSize, &pDstData, &DstSize, &Flags); + if (status < 0) goto fail; + printf("status: %d Flags: 0x%08"PRIX32" DstSize: %"PRIu32"\n", status, Flags, DstSize); if (DstSize != expectedSize) { - printf("NCrushCompressBells: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", DstSize, expectedSize); + printf("NCrushCompressBells: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", + DstSize, expectedSize); printf("Actual\n"); BitDump(__FUNCTION__, WLOG_INFO, pDstData, DstSize * 8, 0); printf("Expected\n"); @@ -56,16 +60,15 @@ static int test_NCrushCompressBells(void) goto fail; } - rc = 1; - + rc = TRUE; fail: ncrush_context_free(ncrush); return rc; } -static int test_NCrushDecompressBells(void) +static BOOL test_NCrushDecompressBells(void) { - int rc = -1; + BOOL rc = FALSE; int status; UINT32 Flags; BYTE* pSrcData; @@ -76,13 +79,14 @@ static int test_NCrushDecompressBells(void) NCRUSH_CONTEXT* ncrush = ncrush_context_new(FALSE); if (!ncrush) - return -1; + return rc; SrcSize = sizeof(TEST_BELLS_NCRUSH) - 1; pSrcData = (BYTE*) TEST_BELLS_NCRUSH; Flags = PACKET_COMPRESSED | 2; expectedSize = sizeof(TEST_BELLS_DATA) - 1; status = ncrush_decompress(ncrush, pSrcData, SrcSize, &pDstData, &DstSize, Flags); + if (status < 0) goto fail; @@ -90,7 +94,8 @@ static int test_NCrushDecompressBells(void) if (DstSize != expectedSize) { - printf("NCrushDecompressBells: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", DstSize, expectedSize); + printf("NCrushDecompressBells: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", + DstSize, expectedSize); goto fail; } @@ -100,8 +105,7 @@ static int test_NCrushDecompressBells(void) goto fail; } - rc = 1; - + rc = TRUE; fail: ncrush_context_free(ncrush); return rc; @@ -109,10 +113,10 @@ fail: int TestFreeRDPCodecNCrush(int argc, char* argv[]) { - if (test_NCrushCompressBells() < 0) + if (!test_NCrushCompressBells()) return -1; - if (test_NCrushDecompressBells() < 0) + if (!test_NCrushDecompressBells()) return -1; return 0; diff --git a/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c b/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c index 7370eb6..1bea9f0 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c @@ -2964,13 +2964,12 @@ static BOOL RunTestPlanar(BITMAP_PLANAR_CONTEXT* planar, const BYTE* srcBitmap, const UINT32 width, const UINT32 height) { BOOL rc = FALSE; - const UINT32 size = width * height * GetBytesPerPixel(dstFormat); UINT32 dstSize; BYTE* compressedBitmap = freerdp_bitmap_compress_planar(planar, srcBitmap, srcFormat, width, height, 0, NULL, &dstSize); BYTE* decompressedBitmap = (BYTE*) calloc(height, width * GetBytesPerPixel(dstFormat)); printf("%s [%s] --> [%s]: ", __FUNCTION__, - GetColorFormatName(srcFormat), GetColorFormatName(dstFormat)); + FreeRDPGetColorFormatName(srcFormat), FreeRDPGetColorFormatName(dstFormat)); fflush(stdout); printf("TODO: Skipping unfinished test!"); rc = TRUE; @@ -3010,8 +3009,8 @@ static BOOL RunTestPlanarSingleColor(BITMAP_PLANAR_CONTEXT* planar, { UINT32 i, j, x, y; BOOL rc = FALSE; - printf("%s: [%s] --> [%s]: ", __FUNCTION__, GetColorFormatName(srcFormat), - GetColorFormatName(dstFormat)); + printf("%s: [%s] --> [%s]: ", __FUNCTION__, FreeRDPGetColorFormatName(srcFormat), + FreeRDPGetColorFormatName(dstFormat)); fflush(stdout); for (j = 0; j < 100; j += 8) @@ -3020,7 +3019,7 @@ static BOOL RunTestPlanarSingleColor(BITMAP_PLANAR_CONTEXT* planar, { UINT32 compressedSize; const UINT32 fill = j; - const UINT32 color = GetColor(srcFormat, (fill >> 8) & 0xF, (fill >> 4) & 0xF, + const UINT32 color = FreeRDPGetColor(srcFormat, (fill >> 8) & 0xF, (fill >> 4) & 0xF, (fill) & 0xF, 0xFF); const UINT32 width = i; const UINT32 height = i; diff --git a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c index 4ea50da..e99c55a 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c @@ -1,3 +1,4 @@ +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <winpr/path.h> #include <winpr/image.h> @@ -127,7 +128,7 @@ struct _EGFX_SAMPLE_FILE { BYTE* buffer; - UINT32 size; + size_t size; }; typedef struct _EGFX_SAMPLE_FILE EGFX_SAMPLE_FILE; @@ -265,7 +266,7 @@ static int test_image_fill_unused_quarters(BYTE* pDstData, int nDstStep, int nWi return 1; } -static BYTE* test_progressive_load_file(char* path, char* file, UINT32* size) +static BYTE* test_progressive_load_file(char* path, char* file, size_t* size) { FILE* fp; BYTE* buffer; @@ -281,9 +282,9 @@ static BYTE* test_progressive_load_file(char* path, char* file, UINT32* size) if (!fp) return NULL; - fseek(fp, 0, SEEK_END); - *size = ftell(fp); - fseek(fp, 0, SEEK_SET); + _fseeki64(fp, 0, SEEK_END); + *size = _ftelli64(fp); + _fseeki64(fp, 0, SEEK_SET); buffer = (BYTE*) malloc(*size); if (!buffer) @@ -483,7 +484,7 @@ static int test_progressive_load_files(char* ms_sample_path, EGFX_SAMPLE_FILE fi return 1; } -static BYTE* test_progressive_load_bitmap(char* path, char* file, UINT32* size, int quarter) +static BYTE* test_progressive_load_bitmap(char* path, char* file, size_t* size, int quarter) { int status; BYTE* buffer; diff --git a/libfreerdp/codec/test/TestFreeRDPCodecZGfx.c b/libfreerdp/codec/test/TestFreeRDPCodecZGfx.c index 8d0de92..e1f2170 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecZGfx.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecZGfx.c @@ -8,35 +8,35 @@ /* Sample from [MS-RDPEGFX] */ static const BYTE TEST_FOX_DATA[] = - "The quick brown " - "fox jumps over t" - "he lazy dog"; + "The quick brown " + "fox jumps over t" + "he lazy dog"; static const BYTE TEST_FOX_DATA_SINGLE[] = - "\xE0\x04\x54\x68\x65\x20\x71\x75\x69\x63\x6B\x20\x62\x72\x6F\x77" - "\x6E\x20\x66\x6F\x78\x20\x6A\x75\x6D\x70\x73\x20\x6F\x76\x65\x72" - "\x20\x74\x68\x65\x20\x6C\x61\x7A\x79\x20\x64\x6F\x67"; + "\xE0\x04\x54\x68\x65\x20\x71\x75\x69\x63\x6B\x20\x62\x72\x6F\x77" + "\x6E\x20\x66\x6F\x78\x20\x6A\x75\x6D\x70\x73\x20\x6F\x76\x65\x72" + "\x20\x74\x68\x65\x20\x6C\x61\x7A\x79\x20\x64\x6F\x67"; static const BYTE TEST_FOX_DATA_MULTIPART[] = - "\xE1\x03\x00\x2B\x00\x00\x00\x11\x00\x00\x00\x04\x54\x68\x65\x20" - "\x71\x75\x69\x63\x6B\x20\x62\x72\x6F\x77\x6E\x20\x0E\x00\x00\x00" - "\x04\x66\x6F\x78\x20\x6A\x75\x6D\x70\x73\x20\x6F\x76\x65\x10\x00" - "\x00\x00\x24\x39\x08\x0E\x91\xF8\xD8\x61\x3D\x1E\x44\x06\x43\x79" - "\x9C\x02"; + "\xE1\x03\x00\x2B\x00\x00\x00\x11\x00\x00\x00\x04\x54\x68\x65\x20" + "\x71\x75\x69\x63\x6B\x20\x62\x72\x6F\x77\x6E\x20\x0E\x00\x00\x00" + "\x04\x66\x6F\x78\x20\x6A\x75\x6D\x70\x73\x20\x6F\x76\x65\x10\x00" + "\x00\x00\x24\x39\x08\x0E\x91\xF8\xD8\x61\x3D\x1E\x44\x06\x43\x79" + "\x9C\x02"; static int test_ZGfxCompressFox(void) { int rc = -1; int status; UINT32 Flags; - BYTE* pSrcData; + BYTE* pSrcData = NULL; UINT32 SrcSize; UINT32 DstSize; - BYTE* pDstData; + BYTE* pDstData = NULL; ZGFX_CONTEXT* zgfx; UINT32 expectedSize; - zgfx = zgfx_context_new(TRUE); + if (!zgfx) return -1; @@ -45,6 +45,7 @@ static int test_ZGfxCompressFox(void) Flags = 0; expectedSize = sizeof(TEST_FOX_DATA_SINGLE) - 1; status = zgfx_compress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, &Flags); + if (status < 0) goto fail; @@ -52,7 +53,8 @@ static int test_ZGfxCompressFox(void) if (DstSize != expectedSize) { - printf("test_ZGfxCompressFox: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", DstSize, expectedSize); + printf("test_ZGfxCompressFox: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", + DstSize, expectedSize); goto fail; } @@ -67,8 +69,8 @@ static int test_ZGfxCompressFox(void) } rc = 0; - fail: + free(pDstData); zgfx_context_free(zgfx); return rc; } @@ -81,11 +83,11 @@ static int test_ZGfxDecompressFoxSingle(void) BYTE* pSrcData; UINT32 SrcSize; UINT32 DstSize; - BYTE* pDstData; + BYTE* pDstData = NULL; ZGFX_CONTEXT* zgfx; UINT32 expectedSize; - zgfx = zgfx_context_new(TRUE); + if (!zgfx) return -1; @@ -94,6 +96,7 @@ static int test_ZGfxDecompressFoxSingle(void) Flags = 0; expectedSize = sizeof(TEST_FOX_DATA) - 1; status = zgfx_decompress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, Flags); + if (status < 0) goto fail; @@ -101,7 +104,8 @@ static int test_ZGfxDecompressFoxSingle(void) if (DstSize != expectedSize) { - printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", DstSize, expectedSize); + printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", + DstSize, expectedSize); goto fail; } @@ -116,8 +120,8 @@ static int test_ZGfxDecompressFoxSingle(void) } rc = 0; - fail: + free(pDstData); zgfx_context_free(zgfx); return rc; } @@ -130,11 +134,11 @@ static int test_ZGfxDecompressFoxMultipart(void) BYTE* pSrcData; UINT32 SrcSize; UINT32 DstSize; - BYTE* pDstData; + BYTE* pDstData = NULL; ZGFX_CONTEXT* zgfx; UINT32 expectedSize; - zgfx = zgfx_context_new(TRUE); + if (!zgfx) return -1; @@ -143,6 +147,7 @@ static int test_ZGfxDecompressFoxMultipart(void) Flags = 0; expectedSize = sizeof(TEST_FOX_DATA) - 1; status = zgfx_decompress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, Flags); + if (status < 0) goto fail; @@ -150,7 +155,8 @@ static int test_ZGfxDecompressFoxMultipart(void) if (DstSize != expectedSize) { - printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", DstSize, expectedSize); + printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", + DstSize, expectedSize); goto fail; } @@ -165,10 +171,10 @@ static int test_ZGfxDecompressFoxMultipart(void) } rc = 0; - fail: + free(pDstData); zgfx_context_free(zgfx); - return 0; + return rc; } static int test_ZGfxCompressConsistent(void) @@ -179,16 +185,16 @@ static int test_ZGfxCompressConsistent(void) BYTE* pSrcData; UINT32 SrcSize; UINT32 DstSize; - BYTE* pDstData; + BYTE* pDstData = NULL; UINT32 DstSize2; - BYTE* pDstData2; + BYTE* pDstData2 = NULL; ZGFX_CONTEXT* zgfx; UINT32 expectedSize; BYTE BigBuffer[65536]; - memset(BigBuffer, 0xaa, sizeof(BigBuffer)); memcpy(BigBuffer, TEST_FOX_DATA, sizeof(TEST_FOX_DATA) - 1); zgfx = zgfx_context_new(TRUE); + if (!zgfx) return -1; @@ -197,13 +203,14 @@ static int test_ZGfxCompressConsistent(void) pSrcData = (BYTE*) BigBuffer; Flags = 0; status = zgfx_compress(zgfx, pSrcData, SrcSize, &pDstData2, &DstSize2, &Flags); + if (status < 0) goto fail; printf("Compress: flags: 0x%08"PRIX32" size: %"PRIu32"\n", Flags, DstSize2); - /* Decompress */ status = zgfx_decompress(zgfx, pDstData2, DstSize2, &pDstData, &DstSize, Flags); + if (status < 0) goto fail; @@ -211,7 +218,8 @@ static int test_ZGfxCompressConsistent(void) if (DstSize != expectedSize) { - printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", DstSize, expectedSize); + printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %"PRIu32", Expected: %"PRIu32"\n", + DstSize, expectedSize); goto fail; } @@ -235,6 +243,8 @@ static int test_ZGfxCompressConsistent(void) rc = 0; fail: + free(pDstData); + free(pDstData2); zgfx_context_free(zgfx); return rc; } diff --git a/libfreerdp/codec/test/TestFreeRDPRegion.c b/libfreerdp/codec/test/TestFreeRDPRegion.c index 8dfa389..36f944a 100644 --- a/libfreerdp/codec/test/TestFreeRDPRegion.c +++ b/libfreerdp/codec/test/TestFreeRDPRegion.c @@ -609,6 +609,7 @@ static int test_r1_inter_r3(void) retCode = 0; out: region16_uninit(®ion); + region16_uninit(&intersection); return retCode; } diff --git a/libfreerdp/codec/yuv.c b/libfreerdp/codec/yuv.c new file mode 100644 index 0000000..357781c --- /dev/null +++ b/libfreerdp/codec/yuv.c @@ -0,0 +1,182 @@ +#include <winpr/sysinfo.h> +#include <winpr/pool.h> + +#include <freerdp/primitives.h> +#include <freerdp/log.h> +#include <freerdp/codec/yuv.h> + +#define TAG FREERDP_TAG("codec") + +struct _YUV_CONTEXT +{ + UINT32 width, height; + BOOL useThreads; + UINT32 nthreads; + UINT32 heightStep; + + PTP_POOL threadPool; + TP_CALLBACK_ENVIRON ThreadPoolEnv; +}; + + +struct _YUV_PROCESS_WORK_PARAM +{ + YUV_CONTEXT* context; + const BYTE* pYUVData[3]; + UINT32 iStride[3]; + DWORD DstFormat; + BYTE *dest; + UINT32 nDstStep; + UINT32 y; + UINT32 height; +}; +typedef struct _YUV_PROCESS_WORK_PARAM YUV_PROCESS_WORK_PARAM; + +static void CALLBACK yuv_process_work_callback(PTP_CALLBACK_INSTANCE instance, void* context, + PTP_WORK work) +{ + prim_size_t roi; + YUV_PROCESS_WORK_PARAM* param = (YUV_PROCESS_WORK_PARAM*)context; + primitives_t* prims = primitives_get(); + + roi.width = param->context->width; + roi.height = param->height; + if( prims->YUV420ToRGB_8u_P3AC4R(param->pYUVData, param->iStride, param->dest, param->nDstStep, + param->DstFormat, &roi) != PRIMITIVES_SUCCESS) + { + WLog_ERR(TAG, "error when decoding lines"); + } +} + + +void yuv_context_reset(YUV_CONTEXT* context, UINT32 width, UINT32 height) +{ + context->width = width; + context->height = height; + context->heightStep = (height / context->nthreads); +} + + +YUV_CONTEXT* yuv_context_new(BOOL encoder) +{ + SYSTEM_INFO sysInfos; + YUV_CONTEXT* ret = calloc(1, sizeof(*ret)); + if (!ret) + return NULL; + + /** do it here to avoid a race condition between threads */ + primitives_get(); + + GetNativeSystemInfo(&sysInfos); + ret->useThreads = (sysInfos.dwNumberOfProcessors > 1); + if (ret->useThreads) + { + ret->nthreads = sysInfos.dwNumberOfProcessors; + ret->threadPool = CreateThreadpool(NULL); + if (!ret->threadPool) + { + goto error_threadpool; + } + + InitializeThreadpoolEnvironment(&ret->ThreadPoolEnv); + SetThreadpoolCallbackPool(&ret->ThreadPoolEnv, ret->threadPool); + } + else + { + ret->nthreads = 1; + } + + return ret; + +error_threadpool: + free(ret); + return NULL; +} + + +void yuv_context_free(YUV_CONTEXT* context) +{ + if (context->useThreads) + { + CloseThreadpool(context->threadPool); + DestroyThreadpoolEnvironment(&context->ThreadPoolEnv); + } + free(context); +} + + +BOOL yuv_context_decode(YUV_CONTEXT* context, const BYTE* pYUVData[3], UINT32 iStride[3], + DWORD DstFormat, BYTE *dest, UINT32 nDstStep) +{ + UINT32 y, nobjects, i; + PTP_WORK *work_objects = NULL; + YUV_PROCESS_WORK_PARAM *params; + int waitCount = 0; + BOOL ret = TRUE; + + if (!context->useThreads) + { + primitives_t* prims = primitives_get(); + prim_size_t roi; + roi.width = context->width; + roi.height = context->height; + return prims->YUV420ToRGB_8u_P3AC4R(pYUVData, iStride, dest, nDstStep, + DstFormat, &roi) == PRIMITIVES_SUCCESS; + } + + /* case where we use threads */ + nobjects = (context->height + context->heightStep - 1) / context->heightStep; + work_objects = (PTP_WORK *)calloc(nobjects, sizeof(PTP_WORK)); + if (!work_objects) + { + return FALSE; + } + + params = (YUV_PROCESS_WORK_PARAM *)calloc(nobjects, sizeof(*params)); + if (!params) + { + free(work_objects); + return FALSE; + } + + for (i = 0, y = 0; i < nobjects; i++, y += context->heightStep, waitCount++) + { + params[i].context = context; + params[i].DstFormat = DstFormat; + params[i].pYUVData[0] = pYUVData[0] + (y * iStride[0]); + params[i].pYUVData[1] = pYUVData[1] + ((y / 2) * iStride[1]); + params[i].pYUVData[2] = pYUVData[2] + ((y / 2) * iStride[2]); + + params[i].iStride[0] = iStride[0]; + params[i].iStride[1] = iStride[1]; + params[i].iStride[2] = iStride[2]; + + params[i].nDstStep = nDstStep; + params[i].dest = dest + (nDstStep * y); + params[i].y = y; + if (y + context->heightStep <= context->height) + params[i].height = context->heightStep; + else + params[i].height = context->height % context->heightStep; + + work_objects[i] = CreateThreadpoolWork(yuv_process_work_callback, + (void*) ¶ms[i], &context->ThreadPoolEnv); + if (!work_objects[i]) + { + ret = FALSE; + break; + } + SubmitThreadpoolWork(work_objects[i]); + } + + for (i = 0; i < waitCount; i++) + { + WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); + CloseThreadpoolWork(work_objects[i]); + } + + free(work_objects); + free(params); + + return ret; +} diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c index d9e0a1b..41bcb84 100644 --- a/libfreerdp/codec/zgfx.c +++ b/libfreerdp/codec/zgfx.c @@ -110,17 +110,16 @@ static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] = _zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \ _zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1); -static void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, const BYTE* src, UINT32 count) +static void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, const BYTE* src, size_t count) { UINT32 front; - UINT32 residue; if (count <= 0) return; if (count > zgfx->HistoryBufferSize) { - residue = count - zgfx->HistoryBufferSize; + const size_t residue = count - zgfx->HistoryBufferSize; count = zgfx->HistoryBufferSize; src += residue; zgfx->HistoryIndex = (zgfx->HistoryIndex + residue) % zgfx->HistoryBufferSize; @@ -190,7 +189,7 @@ static void zgfx_history_buffer_ring_read(ZGFX_CONTEXT* zgfx, int offset, BYTE* while ((bytesLeft -= bytes) > 0); } -static int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, const BYTE* pbSegment, UINT32 cbSegment) +static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t segmentSize) { BYTE c; BYTE flags; @@ -200,21 +199,23 @@ static int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, const BYTE* pbSegment, UI int inPrefix; UINT32 count; UINT32 distance; + BYTE* pbSegment; + size_t cbSegment = segmentSize - 1; - if (cbSegment < 1) - return -1; + if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize < 1)) + return FALSE; - flags = pbSegment[0]; /* header (1 byte) */ - pbSegment++; - cbSegment--; + Stream_Read_UINT8(stream, flags); /* header (1 byte) */ zgfx->OutputCount = 0; + pbSegment = Stream_Pointer(stream); + Stream_Seek(stream, cbSegment); if (!(flags & PACKET_COMPRESSED)) { zgfx_history_buffer_ring_write(zgfx, pbSegment, cbSegment); CopyMemory(zgfx->OutputBuffer, pbSegment, cbSegment); zgfx->OutputCount = cbSegment; - return 1; + return TRUE; } zgfx->pbInputCurrent = pbSegment; @@ -308,31 +309,35 @@ static int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, const BYTE* pbSegment, UI } } - return 1; + return TRUE; } int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) { - int status; + int status = -1; BYTE descriptor; - if (SrcSize < 1) + wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize); + if (!stream) return -1; - descriptor = pSrcData[0]; /* descriptor (1 byte) */ + if (Stream_GetRemainingLength(stream) < 1) + goto fail; + + Stream_Read_UINT8(stream, descriptor); /* descriptor (1 byte) */ if (descriptor == ZGFX_SEGMENTED_SINGLE) { - status = zgfx_decompress_segment(zgfx, &pSrcData[1], SrcSize - 1); + if (!zgfx_decompress_segment(zgfx, stream, Stream_GetRemainingLength(stream))) + goto fail; - if (status < 0) - return status; - - *ppDstData = (BYTE*) malloc(zgfx->OutputCount); + *ppDstData = NULL; + if (zgfx->OutputCount > 0) + *ppDstData = (BYTE*) malloc(zgfx->OutputCount); if (!*ppDstData) - return -1; + goto fail; *pDstSize = zgfx->OutputCount; CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount); @@ -342,56 +347,65 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY UINT32 segmentSize; UINT16 segmentNumber; UINT16 segmentCount; - UINT32 segmentOffset; UINT32 uncompressedSize; BYTE* pConcatenated; - segmentOffset = 7; - segmentCount = *((UINT16*) &pSrcData[1]); /* segmentCount (2 bytes) */ - uncompressedSize = *((UINT32*) &pSrcData[3]); /* uncompressedSize (4 bytes) */ + + if (Stream_GetRemainingLength(stream) < 6) + goto fail; + + Stream_Read_UINT16(stream, segmentCount); /* segmentCount (2 bytes) */ + Stream_Read_UINT32(stream, uncompressedSize); /* uncompressedSize (4 bytes) */ + + if (Stream_GetRemainingLength(stream) < segmentCount * sizeof(UINT32)) + goto fail; + pConcatenated = (BYTE*) malloc(uncompressedSize); if (!pConcatenated) - return -1; + goto fail; *ppDstData = pConcatenated; *pDstSize = uncompressedSize; for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++) { - segmentSize = *((UINT32*) &pSrcData[segmentOffset]); /* segmentSize (4 bytes) */ - segmentOffset += 4; - status = zgfx_decompress_segment(zgfx, &pSrcData[segmentOffset], segmentSize); + if (Stream_GetRemainingLength(stream) < sizeof(UINT32)) + goto fail; - if (status < 0) - return status; + Stream_Read_UINT32(stream, segmentSize); /* segmentSize (4 bytes) */ + + if (!zgfx_decompress_segment(zgfx, stream, segmentSize)) + goto fail; - segmentOffset += segmentSize; CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount); pConcatenated += zgfx->OutputCount; } } else { - return -1; + goto fail; } - return 1; + status = 1; +fail: + Stream_Free(stream, FALSE); + return status; } -static int zgfx_compress_segment(ZGFX_CONTEXT* zgfx, wStream* s, const BYTE* pSrcData, - UINT32 SrcSize, UINT32* pFlags) +static BOOL zgfx_compress_segment(ZGFX_CONTEXT* zgfx, wStream* s, const BYTE* pSrcData, + UINT32 SrcSize, UINT32* pFlags) { /* FIXME: Currently compression not implemented. Just copy the raw source */ if (!Stream_EnsureRemainingCapacity(s, SrcSize + 1)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); - return -1; + return FALSE; } (*pFlags) |= ZGFX_PACKET_COMPR_TYPE_RDP8; /* RDP 8.0 compression format */ Stream_Write_UINT8(s, (*pFlags)); /* header (1 byte) */ Stream_Write(s, pSrcData, SrcSize); - return 1; + return TRUE; } int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUncompressed, @@ -448,10 +462,8 @@ int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUnco posDataStart = Stream_GetPosition(sDst); - if ((status = zgfx_compress_segment(zgfx, sDst, pSrcData, SrcSize, pFlags)) < 0) - { - return status; - } + if (!zgfx_compress_segment(zgfx, sDst, pSrcData, SrcSize, pFlags)) + return -1; if (posDstSize) { diff --git a/libfreerdp/common/addin.c b/libfreerdp/common/addin.c index 916099c..15df05f 100644 --- a/libfreerdp/common/addin.c +++ b/libfreerdp/common/addin.c @@ -237,15 +237,15 @@ PVIRTUALCHANNELENTRY freerdp_load_dynamic_channel_addin_entry(LPCSTR pszName, { PVIRTUALCHANNELENTRY entry; LPSTR pszFileName; - size_t cchFileName = sizeof(FREERDP_SHARED_LIBRARY_PREFIX) + 32; + const size_t cchBaseFileName = sizeof(FREERDP_SHARED_LIBRARY_PREFIX) + 32; LPCSTR pszExtension; LPCSTR pszPrefix = FREERDP_SHARED_LIBRARY_PREFIX; pszExtension = PathGetSharedLibraryExtensionA(0); if (pszName && pszSubsystem && pszType) { - cchFileName += strlen(pszName) + strlen(pszSubsystem) + strlen( - pszType) + strlen(pszExtension); + const size_t cchFileName = cchBaseFileName + strlen(pszName) + strlen(pszSubsystem) + strlen( + pszType) + strlen(pszExtension); pszFileName = (LPSTR) malloc(cchFileName); if (!pszFileName) @@ -253,11 +253,10 @@ PVIRTUALCHANNELENTRY freerdp_load_dynamic_channel_addin_entry(LPCSTR pszName, sprintf_s(pszFileName, cchFileName, "%s%s-client-%s-%s.%s", pszPrefix, pszName, pszSubsystem, pszType, pszExtension); - cchFileName = strlen(pszFileName); } else if (pszName && pszSubsystem) { - cchFileName += strlen(pszName) + strlen(pszSubsystem) + strlen(pszExtension); + const size_t cchFileName = cchBaseFileName + strlen(pszName) + strlen(pszSubsystem) + strlen(pszExtension); pszFileName = (LPSTR) malloc(cchFileName); if (!pszFileName) @@ -265,11 +264,10 @@ PVIRTUALCHANNELENTRY freerdp_load_dynamic_channel_addin_entry(LPCSTR pszName, sprintf_s(pszFileName, cchFileName, "%s%s-client-%s.%s", pszPrefix, pszName, pszSubsystem, pszExtension); - cchFileName = strlen(pszFileName); } else if (pszName) { - cchFileName += strlen(pszName) + strlen(pszExtension); + const size_t cchFileName = cchBaseFileName + strlen(pszName) + strlen(pszExtension); pszFileName = (LPSTR) malloc(cchFileName); if (!pszFileName) @@ -277,7 +275,6 @@ PVIRTUALCHANNELENTRY freerdp_load_dynamic_channel_addin_entry(LPCSTR pszName, sprintf_s(pszFileName, cchFileName, "%s%s-client.%s", pszPrefix, pszName, pszExtension); - cchFileName = strlen(pszFileName); } else { diff --git a/libfreerdp/common/assistance.c b/libfreerdp/common/assistance.c index b0fa9ac..a852b69 100644 --- a/libfreerdp/common/assistance.c +++ b/libfreerdp/common/assistance.c @@ -21,6 +21,9 @@ #include "config.h" #endif +#include <errno.h> + +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <winpr/crypto.h> #include <winpr/print.h> @@ -77,7 +80,6 @@ int freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* k BYTE* buffer; BYTE pad1[64]; BYTE pad2[64]; - memset(pad1, 0x36, 64); memset(pad2, 0x5C, 64); @@ -99,11 +101,9 @@ int freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* k goto fail; CopyMemory(key, buffer, keyLength); - rc = 1; fail: free(buffer); - return rc; } @@ -116,7 +116,6 @@ int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list) int count; int length; char** tokens; - count = 1; str = _strdup(list); @@ -132,6 +131,7 @@ int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list) } tokens = (char**) calloc(count, sizeof(char*)); + if (!tokens) { free(str); @@ -160,7 +160,6 @@ int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list) for (i = 0; i < count; i++) { p = tokens[i]; - q = strchr(p, ':'); if (!q) @@ -168,9 +167,16 @@ int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list) q[0] = '\0'; q++; - file->MachineAddresses[i] = _strdup(p); - file->MachinePorts[i] = (UINT32) atoi(q); + errno = 0; + { + unsigned long val = strtoul(q, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + goto out; + + file->MachinePorts[i] = val; + } if (!file->MachineAddresses[i]) goto out; @@ -189,7 +195,6 @@ int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list) } p = tokens[i]; - q = strchr(p, ':'); if (!q) @@ -200,10 +205,21 @@ int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list) if (file->MachineAddress) free(file->MachineAddress); + file->MachineAddress = _strdup(p); + if (!file->MachineAddress) goto out; - file->MachinePort = (UINT32) atoi(q); + + errno = 0; + { + unsigned long val = strtoul(q, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + goto out; + + file->MachinePort = val; + } if (!file->MachineAddress) goto out; @@ -215,18 +231,18 @@ int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list) free(str); return 1; out: + if (file->MachineAddresses) { - for (i=0; i<count; i++) - free (file->MachineAddresses[i]); + for (i = 0; i < count; i++) + free(file->MachineAddresses[i]); } - free (file->MachineAddresses); - free (file->MachinePorts); + free(file->MachineAddresses); + free(file->MachinePorts); file->MachineCount = 0; file->MachinePorts = NULL; file->MachineAddresses = NULL; - free(tokens); free(str); return -1; @@ -240,12 +256,10 @@ int freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file) int length; char* tokens[8]; int ret = -1; - /** * <ProtocolVersion>,<protocolType>,<machineAddressList>,<assistantAccountPwd>, * <RASessionID>,<RASessionName>,<RASessionPwd>,<protocolSpecificParms> */ - count = 1; str = _strdup(file->RCTicket); @@ -301,7 +315,6 @@ int freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file) goto error; ret = freerdp_assistance_parse_address_list(file, tokens[2]); - error: free(str); @@ -334,8 +347,6 @@ int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) char* end; char* p; int ret = -1; - - str = file->ConnectionString2; if (!strstr(str, "<E>")) @@ -345,6 +356,7 @@ int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) return -1; str = _strdup(file->ConnectionString2); + if (!str) return -1; @@ -353,15 +365,16 @@ int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) /* Parse Auth String Node (<A>) */ end = strstr(tag, "/>"); + if (!end) goto out_fail; *end = '\0'; - p = strstr(tag, "KH=\""); + if (p) { - char *q; + char* q; size_t length; p += sizeof("KH=\"") - 1; q = strchr(p, '"'); @@ -372,6 +385,7 @@ int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) length = q - p; free(file->RASpecificParams); file->RASpecificParams = (char*) malloc(length + 1); + if (!file->RASpecificParams) goto out_fail; @@ -380,9 +394,10 @@ int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) } p = strstr(tag, "ID=\""); + if (p) { - char *q; + char* q; size_t length; p += sizeof("ID=\"") - 1; q = strchr(p, '"'); @@ -393,24 +408,24 @@ int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) length = q - p; free(file->RASessionId); file->RASessionId = (char*) malloc(length + 1); + if (!file->RASessionId) goto out_fail; CopyMemory(file->RASessionId, p, length); file->RASessionId[length] = '\0'; } + *end = '/'; - /* Parse <L last address is used */ - p = strstr(str, "<L P=\""); + while (p) { - char *q; + char* q; int port; size_t length; p += sizeof("<L P=\"") - 1; - q = strchr(p, '"'); if (!q) @@ -418,16 +433,21 @@ int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) q[0] = '\0'; q++; + errno = 0; + { + unsigned long val = strtoul(p, NULL, 0); - port = atoi(p); + if ((errno != 0) || (val == 0) || (val > UINT16_MAX)) + goto out_fail; + port = val; + } p = strstr(q, " N=\""); if (!p) goto out_fail; p += sizeof(" N=\"") - 1; - q = strchr(p, '"'); if (!q) @@ -435,7 +455,6 @@ int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) q[0] = '\0'; q++; - length = strlen(p); if (length > 8) @@ -444,9 +463,12 @@ int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) { if (file->MachineAddress) free(file->MachineAddress); + file->MachineAddress = _strdup(p); + if (!file->MachineAddress) goto out_fail; + file->MachinePort = (UINT32) port; break; } @@ -459,7 +481,6 @@ int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) out_fail: free(str); return ret; - } char* freerdp_assistance_construct_expert_blob(const char* name, const char* pass) @@ -474,7 +495,6 @@ char* freerdp_assistance_construct_expert_blob(const char* name, const char* pas nameLength = strlen(name) + strlen("NAME="); passLength = strlen(pass) + strlen("PASS="); - size = nameLength + passLength + 64; ExpertBlob = (char*) calloc(1, size); @@ -482,8 +502,7 @@ char* freerdp_assistance_construct_expert_blob(const char* name, const char* pas return NULL; sprintf_s(ExpertBlob, size, "%d;NAME=%s%d;PASS=%s", - nameLength, name, passLength, pass); - + nameLength, name, passLength, pass); return ExpertBlob; } @@ -496,7 +515,6 @@ char* freerdp_assistance_generate_pass_stub(DWORD flags) char set3[10] = "0123456789"; char set4[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char set5[26] = "abcdefghijklmnopqrstuvwxyz"; - passStub = (char*) malloc(15); if (!passStub) @@ -513,9 +531,7 @@ char* freerdp_assistance_generate_pass_stub(DWORD flags) * * Example: WB^6HsrIaFmEpi */ - winpr_RAND((BYTE*) nums, sizeof(nums)); - passStub[0] = set1[nums[0] % sizeof(set1)]; /* character 0 */ passStub[1] = set2[nums[1] % sizeof(set2)]; /* character 1 */ passStub[2] = set3[nums[2] % sizeof(set3)]; /* character 2 */ @@ -531,11 +547,11 @@ char* freerdp_assistance_generate_pass_stub(DWORD flags) passStub[12] = set1[nums[12] % sizeof(set1)]; /* character 12 */ passStub[13] = set1[nums[13] % sizeof(set1)]; /* character 13 */ passStub[14] = '\0'; - return passStub; } -BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub, int* pEncryptedSize) +BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub, + int* pEncryptedSize) { BOOL rc; int status; @@ -548,7 +564,6 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas size_t cbOut, cbIn, cbFinal; WCHAR* PasswordW = NULL; WCHAR* PassStubW = NULL; - status = ConvertToUnicode(CP_UTF8, 0, password, -1, &PasswordW, 0); if (status <= 0) @@ -556,9 +571,10 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas cbPasswordW = (status - 1) * 2; - if (!winpr_Digest(WINPR_MD_MD5, (BYTE*)PasswordW, cbPasswordW, (BYTE*) PasswordHash, sizeof(PasswordHash))) + if (!winpr_Digest(WINPR_MD_MD5, (BYTE*)PasswordW, cbPasswordW, (BYTE*) PasswordHash, + sizeof(PasswordHash))) { - free (PasswordW); + free(PasswordW); return NULL; } @@ -566,14 +582,12 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas if (status <= 0) { - free (PasswordW); + free(PasswordW); return NULL; } cbPassStubW = (status - 1) * 2; - EncryptedSize = cbPassStubW + 4; - pbIn = (BYTE*) calloc(1, EncryptedSize); pbOut = (BYTE*) calloc(1, EncryptedSize); @@ -597,23 +611,21 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas *((UINT32*) pbIn) = cbPassStubW; CopyMemory(&pbIn[4], PassStubW, cbPassStubW); - free(PasswordW); free(PassStubW); - rc4Ctx = winpr_Cipher_New(WINPR_CIPHER_ARC4_128, WINPR_ENCRYPT, - PasswordHash, NULL); + PasswordHash, NULL); + if (!rc4Ctx) { WLog_ERR(TAG, "EVP_CipherInit_ex failure"); - free (pbOut); - free (pbIn); + free(pbOut); + free(pbIn); return NULL; } cbOut = cbFinal = 0; cbIn = EncryptedSize; - rc = winpr_Cipher_Update(rc4Ctx, pbIn, cbIn, pbOut, &cbOut); free(pbIn); @@ -621,7 +633,7 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas { WLog_ERR(TAG, "EVP_CipherUpdate failure"); winpr_Cipher_Free(rc4Ctx); - free (pbOut); + free(pbOut); return NULL; } @@ -629,14 +641,12 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas { WLog_ERR(TAG, "EVP_CipherFinal_ex failure"); winpr_Cipher_Free(rc4Ctx); - free (pbOut); + free(pbOut); return NULL; } winpr_Cipher_Free(rc4Ctx); - *pEncryptedSize = EncryptedSize; - return pbOut; } @@ -653,7 +663,6 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password) BYTE DerivedKey[WINPR_AES_BLOCK_SIZE]; BYTE InitializationVector[WINPR_AES_BLOCK_SIZE]; BYTE PasswordHash[WINPR_SHA1_DIGEST_LENGTH]; - status = ConvertToUnicode(CP_UTF8, 0, password, -1, &PasswordW, 0); if (status <= 0) @@ -663,12 +672,12 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password) if (!winpr_Digest(WINPR_MD_SHA1, (BYTE*)PasswordW, cbPasswordW, PasswordHash, sizeof(PasswordHash))) { - free (PasswordW); + free(PasswordW); return -1; } status = freerdp_assistance_crypt_derive_key_sha1(PasswordHash, sizeof(PasswordHash), - DerivedKey, sizeof(DerivedKey)); + DerivedKey, sizeof(DerivedKey)); if (status < 0) { @@ -677,9 +686,9 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password) } ZeroMemory(InitializationVector, sizeof(InitializationVector)); - aesDec = winpr_Cipher_New(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, - DerivedKey, InitializationVector); + DerivedKey, InitializationVector); + if (!aesDec) { free(PasswordW); @@ -716,16 +725,12 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password) } winpr_Cipher_Free(aesDec); - cbOut += cbFinal; cbFinal = 0; - pbOutW = (WCHAR*) pbOut; cchOutW = cbOut / 2; - file->ConnectionString2 = NULL; status = ConvertFromUnicode(CP_UTF8, 0, pbOutW, cchOutW, &file->ConnectionString2, 0, NULL, NULL); - free(PasswordW); free(pbOut); @@ -742,9 +747,8 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password) int freerdp_assistance_decrypt(rdpAssistanceFile* file, const char* password) { int status = 1; - file->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(password, - file->PassStub, &file->EncryptedPassStubLength); + file->PassStub, &file->EncryptedPassStubLength); if (!file->EncryptedPassStub) return -1; @@ -763,7 +767,6 @@ BYTE* freerdp_assistance_hex_string_to_bin(const char* str, int* size) int length; BYTE* buffer; int i, ln, hn; - length = strlen(str); if ((length % 2) != 0) @@ -771,7 +774,6 @@ BYTE* freerdp_assistance_hex_string_to_bin(const char* str, int* size) length /= 2; *size = length; - buffer = (BYTE*) malloc(length); if (!buffer) @@ -780,7 +782,6 @@ BYTE* freerdp_assistance_hex_string_to_bin(const char* str, int* size) for (i = 0; i < length; i++) { hn = ln = 0; - c = str[(i * 2) + 0]; if ((c >= '0') && (c <= '9')) @@ -811,8 +812,8 @@ char* freerdp_assistance_bin_to_hex_string(const BYTE* data, int size) char* p; int ln, hn; char bin2hex[] = "0123456789ABCDEF"; - p = (char*) calloc((size + 1), 2); + if (!p) return NULL; @@ -820,13 +821,11 @@ char* freerdp_assistance_bin_to_hex_string(const BYTE* data, int size) { ln = data[i] & 0xF; hn = (data[i] >> 4) & 0xF; - p[i * 2] = bin2hex[hn]; p[(i * 2) + 1] = bin2hex[ln]; } p[size * 2] = '\0'; - return p; } @@ -835,10 +834,8 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu char* p; char* q; char* r; - int value; int status; size_t length; - p = strstr(buffer, "UPLOADINFO"); if (!p) @@ -855,7 +852,6 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; /* Parse USERNAME */ - p = strstr(buffer, "USERNAME=\""); if (p) @@ -877,7 +873,6 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu } /* Parse LHTICKET */ - p = strstr(buffer, "LHTICKET=\""); if (p) @@ -899,7 +894,6 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu } /* Parse RCTICKET */ - p = strstr(buffer, "RCTICKET=\""); if (p) @@ -921,7 +915,6 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu } /* Parse RCTICKETENCRYPTED */ - p = strstr(buffer, "RCTICKETENCRYPTED=\""); if (p) @@ -939,7 +932,6 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu } /* Parse PassStub */ - p = strstr(buffer, "PassStub=\""); if (p) @@ -961,7 +953,6 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu } /* Parse DtStart */ - p = strstr(buffer, "DtStart=\""); if (p) @@ -973,7 +964,6 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; length = q - p; - r = (char*) malloc(length + 1); if (!r) @@ -981,18 +971,19 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu CopyMemory(r, p, length); r[length] = '\0'; + errno = 0; + { + unsigned long val = strtoul(r, NULL, 0); + free(r); - value = atoi(r); - free(r); + if ((errno != 0) || (val > UINT32_MAX)) + return -1; - if (value < 0) - return -1; - - file->DtStart = (UINT32) value; + file->DtStart = val; + } } /* Parse DtLength */ - p = strstr(buffer, "DtLength=\""); if (p) @@ -1004,7 +995,6 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; length = q - p; - r = (char*) malloc(length + 1); if (!r) @@ -1012,18 +1002,19 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu CopyMemory(r, p, length); r[length] = '\0'; + errno = 0; + { + unsigned long val = strtoul(r, NULL, 0); + free(r); - value = atoi(r); - free(r); + if ((errno != 0) || (val > UINT32_MAX)) + return -1; - if (value < 0) - return -1; - - file->DtLength = (UINT32) value; + file->DtLength = val; + } } /* Parse L (LowSpeed) */ - p = strstr(buffer, " L=\""); if (p) @@ -1045,7 +1036,7 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu if (file->LHTicket) { file->EncryptedLHTicket = freerdp_assistance_hex_string_to_bin(file->LHTicket, - &file->EncryptedLHTicketLength); + &file->EncryptedLHTicketLength); } status = freerdp_assistance_parse_connection_string1(file); @@ -1065,16 +1056,19 @@ int freerdp_assistance_parse_file(rdpAssistanceFile* file, const char* name) BYTE* buffer; FILE* fp = NULL; size_t readSize; - long int fileSize; + INT64 fileSize; + + if (!name) + return -1; fp = fopen(name, "r"); if (!fp) return -1; - fseek(fp, 0, SEEK_END); - fileSize = ftell(fp); - fseek(fp, 0, SEEK_SET); + _fseeki64(fp, 0, SEEK_END); + fileSize = _ftelli64(fp); + _fseeki64(fp, 0, SEEK_SET); if (fileSize < 1) { @@ -1097,6 +1091,7 @@ int freerdp_assistance_parse_file(rdpAssistanceFile* file, const char* name) if (!ferror(fp)) readSize = fileSize; } + fclose(fp); if (readSize < 1) @@ -1108,18 +1103,15 @@ int freerdp_assistance_parse_file(rdpAssistanceFile* file, const char* name) buffer[fileSize] = '\0'; buffer[fileSize + 1] = '\0'; - status = freerdp_assistance_parse_file_buffer(file, (char*) buffer, fileSize); - free(buffer); - return status; } -int freerdp_client_populate_settings_from_assistance_file(rdpAssistanceFile* file, rdpSettings* settings) +int freerdp_client_populate_settings_from_assistance_file(rdpAssistanceFile* file, + rdpSettings* settings) { UINT32 i; - freerdp_set_param_bool(settings, FreeRDP_RemoteAssistanceMode, TRUE); if (!file->RASessionId || !file->MachineAddress) @@ -1128,19 +1120,19 @@ int freerdp_client_populate_settings_from_assistance_file(rdpAssistanceFile* fil if (freerdp_set_param_string(settings, FreeRDP_RemoteAssistanceSessionId, file->RASessionId) != 0) return -1; - if (file->RCTicket && (freerdp_set_param_string(settings, FreeRDP_RemoteAssistanceRCTicket, file->RCTicket) != 0)) + if (file->RCTicket && + (freerdp_set_param_string(settings, FreeRDP_RemoteAssistanceRCTicket, file->RCTicket) != 0)) return -1; - if (file->PassStub && (freerdp_set_param_string(settings, FreeRDP_RemoteAssistancePassStub, file->PassStub) != 0)) + if (file->PassStub && + (freerdp_set_param_string(settings, FreeRDP_RemoteAssistancePassStub, file->PassStub) != 0)) return -1; if (freerdp_set_param_string(settings, FreeRDP_ServerHostname, file->MachineAddress) != 0) return -1; freerdp_set_param_uint32(settings, FreeRDP_ServerPort, file->MachinePort); - freerdp_target_net_addresses_free(settings); - settings->TargetNetAddressCount = file->MachineCount; if (settings->TargetNetAddressCount) @@ -1195,6 +1187,5 @@ void freerdp_assistance_file_free(rdpAssistanceFile* file) free(file->MachineAddresses); free(file->MachinePorts); - free(file); } diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index 6415903..f79a282 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -307,17 +307,8 @@ out_print_name_error: goto out_smartc_name_error; } - if (smartcard->Path) - { - _smartcard->Path = _strdup(smartcard->Path); - if (!_smartcard->Path) - goto out_smartc_path_error; - } - return (RDPDR_DEVICE*) _smartcard; -out_smartc_path_error: - free(_smartcard->Name); out_smartc_name_error: free(_smartcard); return NULL; @@ -428,7 +419,7 @@ void freerdp_device_collection_free(rdpSettings* settings) } else if (settings->DeviceArray[index]->Type == RDPDR_DTYP_SMARTCARD) { - free(((RDPDR_SMARTCARD*) device)->Path); + } else if (settings->DeviceArray[index]->Type == RDPDR_DTYP_SERIAL) { @@ -921,6 +912,9 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id) case FreeRDP_ExternalCertificateManagement: return settings->ExternalCertificateManagement; + case FreeRDP_FIPSMode: + return settings->FIPSMode; + case FreeRDP_Workarea: return settings->Workarea; @@ -1381,6 +1375,10 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param) settings->ExternalCertificateManagement = param; break; + case FreeRDP_FIPSMode: + settings->FIPSMode = param; + break; + case FreeRDP_Workarea: settings->Workarea = param; break; @@ -1845,6 +1843,12 @@ UINT32 freerdp_get_param_uint32(rdpSettings* settings, int id) case FreeRDP_PercentScreen: return settings->PercentScreen; + case FreeRDP_PercentScreenUseWidth: + return settings->PercentScreenUseWidth; + + case FreeRDP_PercentScreenUseHeight: + return settings->PercentScreenUseHeight; + case FreeRDP_GatewayUsageMethod: return settings->GatewayUsageMethod; @@ -2142,6 +2146,14 @@ int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param) settings->PercentScreen = param; break; + case FreeRDP_PercentScreenUseWidth: + settings->PercentScreenUseWidth = param; + break; + + case FreeRDP_PercentScreenUseHeight: + settings->PercentScreenUseHeight = param; + break; + case FreeRDP_GatewayUsageMethod: settings->GatewayUsageMethod = param; break; @@ -2491,6 +2503,9 @@ char* freerdp_get_param_string(rdpSettings* settings, int id) case FreeRDP_GatewayDomain: return settings->GatewayDomain; + case FreeRDP_GatewayAccessToken: + return settings->GatewayAccessToken; + case FreeRDP_ProxyHostname: return settings->ProxyHostname; @@ -2701,6 +2716,10 @@ int freerdp_set_param_string(rdpSettings* settings, int id, const char* param) tmp = &settings->GatewayDomain; break; + case FreeRDP_GatewayAccessToken: + tmp = &settings->GatewayAccessToken; + break; + case FreeRDP_ProxyHostname: tmp = &settings->ProxyHostname; break; diff --git a/libfreerdp/core/CMakeLists.txt b/libfreerdp/core/CMakeLists.txt index e73946e..2c8a14c 100644 --- a/libfreerdp/core/CMakeLists.txt +++ b/libfreerdp/core/CMakeLists.txt @@ -21,7 +21,7 @@ set(MODULE_PREFIX "FREERDP_CORE") freerdp_definition_add(-DEXT_PATH="${FREERDP_EXTENSION_PATH}") freerdp_include_directory_add(${OPENSSL_INCLUDE_DIR}) -freerdp_include_directory_add(${KRB5_INCLUDE_DIRS}) +freerdp_include_directory_add(${GSS_INCLUDE_DIR}) set(${MODULE_PREFIX}_GATEWAY_DIR "gateway") @@ -141,9 +141,9 @@ endif() freerdp_library_add(${OPENSSL_LIBRARIES}) -if (WITH_KRB5) - freerdp_library_add(${KRB5_LIBRARIES}) -endif(WITH_KRB5) +if(WITH_GSSAPI) + freerdp_library_add(${GSS_LIBRARIES}) +endif() if(BUILD_TESTING) add_subdirectory(test) diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index e026c00..32e04cc 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -114,6 +114,7 @@ static const GUID CODEC_GUID_IMAGE_REMOTEFX = { 0x80, 0x3C, 0x0E, 0xCB, 0xEE, 0xA1, 0x9C, 0x54 } }; +#if defined(WITH_JPEG) /* CODEC_GUID_JPEG 0x430C9EED1BAF4CE6869ACB8B37B66237 */ static const GUID CODEC_GUID_JPEG = @@ -122,6 +123,7 @@ static const GUID CODEC_GUID_JPEG = 0x1BAF, 0x4CE6, { 0x86, 0x9A, 0xCB, 0x8B, 0x37, 0xB6, 0x62, 0x37 } }; +#endif static void rdp_read_capability_set_header(wStream* s, UINT16* length, UINT16* type) @@ -139,7 +141,7 @@ static void rdp_write_capability_set_header(wStream* s, UINT16 length, static int rdp_capability_set_start(wStream* s) { - int header; + size_t header; header = Stream_GetPosition(s); Stream_Zero(s, CAPSET_HEADER_LENGTH); return header; @@ -147,7 +149,7 @@ static int rdp_capability_set_start(wStream* s) static void rdp_capability_set_finish(wStream* s, int header, UINT16 type) { - int footer; + size_t footer; UINT16 length; footer = Stream_GetPosition(s); length = footer - header; @@ -194,7 +196,6 @@ static BOOL rdp_read_general_capability_set(wStream* s, UINT16 length, Stream_Seek_UINT16(s); /* generalCompressionLevel (2 bytes) */ Stream_Read_UINT8(s, refreshRectSupport); /* refreshRectSupport (1 byte) */ Stream_Read_UINT8(s, suppressOutputSupport); /* suppressOutputSupport (1 byte) */ - settings->NoBitmapCompressionHeader = (extraFlags & NO_BITMAP_COMPRESSION_HDR) ? TRUE : FALSE; settings->LongCredentialsSupported = (extraFlags & LONG_CREDENTIALS_SUPPORTED) ? TRUE : FALSE; @@ -369,7 +370,8 @@ static BOOL rdp_read_bitmap_capability_set(wStream* s, UINT16 length, settings->DrawAllowSkipAlpha = (drawingFlags & DRAW_ALLOW_SKIP_ALPHA) ? TRUE : FALSE; if (settings->DrawAllowDynamicColorFidelity) - settings->DrawAllowDynamicColorFidelity = (drawingFlags & DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY) ? TRUE : FALSE; + settings->DrawAllowDynamicColorFidelity = (drawingFlags & DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY) ? + TRUE : FALSE; if (settings->DrawAllowColorSubsampling) settings->DrawAllowColorSubsampling = (drawingFlags & DRAW_ALLOW_COLOR_SUBSAMPLING) ? TRUE : FALSE; @@ -691,7 +693,8 @@ static BOOL rdp_print_order_capability_set(wStream* s, UINT16 length) WLog_INFO(TAG, "\t\tGLYPH_INDEX: %"PRIu8"", orderSupport[NEG_GLYPH_INDEX_INDEX]); WLog_INFO(TAG, "\t\tGLYPH_WEXTTEXTOUT: %"PRIu8"", orderSupport[NEG_GLYPH_WEXTTEXTOUT_INDEX]); WLog_INFO(TAG, "\t\tGLYPH_WLONGTEXTOUT: %"PRIu8"", orderSupport[NEG_GLYPH_WLONGTEXTOUT_INDEX]); - WLog_INFO(TAG, "\t\tGLYPH_WLONGEXTTEXTOUT: %"PRIu8"", orderSupport[NEG_GLYPH_WLONGEXTTEXTOUT_INDEX]); + WLog_INFO(TAG, "\t\tGLYPH_WLONGEXTTEXTOUT: %"PRIu8"", + orderSupport[NEG_GLYPH_WLONGEXTTEXTOUT_INDEX]); WLog_INFO(TAG, "\t\tUNUSED31: %"PRIu8"", orderSupport[NEG_UNUSED31_INDEX]); WLog_INFO(TAG, "\ttextFlags: 0x%04"PRIX16"", textFlags); WLog_INFO(TAG, "\torderSupportExFlags: 0x%04"PRIX16"", orderSupportExFlags); @@ -1278,9 +1281,13 @@ static BOOL rdp_read_input_capability_set(wStream* s, UINT16 length, } if (inputFlags & TS_INPUT_FLAG_MOUSE_HWHEEL) - { settings->HasHorizontalWheel = TRUE; - } + + if (inputFlags & INPUT_FLAG_UNICODE) + settings->UnicodeInput = TRUE; + + if (inputFlags & INPUT_FLAG_MOUSEX) + settings->HasExtendedMouseEvent = TRUE; } return TRUE; @@ -1832,11 +1839,16 @@ static BOOL rdp_write_bitmap_cache_v2_capability_set(wStream* s, Stream_Write_UINT8(s, 0); /* pad2 (1 byte) */ Stream_Write_UINT8(s, settings->BitmapCacheV2NumCells); /* numCellCaches (1 byte) */ - rdp_write_bitmap_cache_cell_info(s, &settings->BitmapCacheV2CellInfo[0]); /* bitmapCache0CellInfo (4 bytes) */ - rdp_write_bitmap_cache_cell_info(s, &settings->BitmapCacheV2CellInfo[1]); /* bitmapCache1CellInfo (4 bytes) */ - rdp_write_bitmap_cache_cell_info(s, &settings->BitmapCacheV2CellInfo[2]); /* bitmapCache2CellInfo (4 bytes) */ - rdp_write_bitmap_cache_cell_info(s, &settings->BitmapCacheV2CellInfo[3]); /* bitmapCache3CellInfo (4 bytes) */ - rdp_write_bitmap_cache_cell_info(s, &settings->BitmapCacheV2CellInfo[4]); /* bitmapCache4CellInfo (4 bytes) */ + rdp_write_bitmap_cache_cell_info(s, + &settings->BitmapCacheV2CellInfo[0]); /* bitmapCache0CellInfo (4 bytes) */ + rdp_write_bitmap_cache_cell_info(s, + &settings->BitmapCacheV2CellInfo[1]); /* bitmapCache1CellInfo (4 bytes) */ + rdp_write_bitmap_cache_cell_info(s, + &settings->BitmapCacheV2CellInfo[2]); /* bitmapCache2CellInfo (4 bytes) */ + rdp_write_bitmap_cache_cell_info(s, + &settings->BitmapCacheV2CellInfo[3]); /* bitmapCache3CellInfo (4 bytes) */ + rdp_write_bitmap_cache_cell_info(s, + &settings->BitmapCacheV2CellInfo[4]); /* bitmapCache4CellInfo (4 bytes) */ Stream_Zero(s, 12); /* pad3 (12 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_V2); return TRUE; @@ -2118,7 +2130,8 @@ static BOOL rdp_write_draw_gdiplus_cache_capability_set(wStream* s, rdpSettings* Stream_Write_UINT32(s, drawGdiplusCacheLevel); /* drawGdiplusCacheLevel (4 bytes) */ rdp_write_gdiplus_cache_entries(s, 10, 5, 5, 10, 2); /* GdipCacheEntries (10 bytes) */ rdp_write_gdiplus_cache_chunk_size(s, 512, 2048, 1024, 64); /* GdipCacheChunkSize (8 bytes) */ - rdp_write_gdiplus_image_cache_properties(s, 4096, 256, 128); /* GdipImageCacheProperties (6 bytes) */ + 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; } @@ -2599,7 +2612,8 @@ static BOOL rdp_print_surface_commands_capability_set(wStream* s, UINT16 length) static void rdp_print_bitmap_codec_guid(const GUID* guid) { - WLog_INFO(TAG, "%08"PRIX32"%04"PRIX16"%04"PRIX16"%02"PRIX8"%02"PRIX8"%02"PRIX8"%02"PRIX8"%02"PRIX8"%02"PRIX8"%02"PRIX8"%02"PRIX8"", + WLog_INFO(TAG, + "%08"PRIX32"%04"PRIX16"%04"PRIX16"%02"PRIX8"%02"PRIX8"%02"PRIX8"%02"PRIX8"%02"PRIX8"%02"PRIX8"%02"PRIX8"%02"PRIX8"", guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); @@ -2618,9 +2632,12 @@ static char* rdp_get_bitmap_codec_guid_name(const GUID* guid) return "CODEC_GUID_IGNORE"; else if (UuidEqual(guid, &CODEC_GUID_IMAGE_REMOTEFX, &rpc_status)) return "CODEC_GUID_IMAGE_REMOTEFX"; + +#if defined(WITH_JPEG) else if (UuidEqual(guid, &CODEC_GUID_JPEG, &rpc_status)) return "CODEC_GUID_JPEG"; +#endif return "CODEC_GUID_UNKNOWN"; } #endif @@ -2953,6 +2970,7 @@ static BOOL rdp_write_nsc_client_capability_container(wStream* s, return TRUE; } +#if defined(WITH_JPEG) static BOOL rdp_write_jpeg_client_capability_container(wStream* s, rdpSettings* settings) { @@ -2963,6 +2981,7 @@ static BOOL rdp_write_jpeg_client_capability_container(wStream* s, Stream_Write_UINT8(s, settings->JpegQuality); return TRUE; } +#endif /** * Write RemoteFX Server Capability Container.\n @@ -3032,9 +3051,13 @@ static BOOL rdp_write_bitmap_codecs_capability_set(wStream* s, if (settings->NSCodec) bitmapCodecCount++; +#if defined(WITH_JPEG) + if (settings->JpegCodec) bitmapCodecCount++; +#endif + if (settings->RemoteFxImageCodec) bitmapCodecCount++; @@ -3080,6 +3103,8 @@ static BOOL rdp_write_bitmap_codecs_capability_set(wStream* s, } } +#if defined(WITH_JPEG) + if (settings->JpegCodec) { rdp_write_bitmap_codec_guid(s, &CODEC_GUID_JPEG); /* codecGUID */ @@ -3100,6 +3125,8 @@ static BOOL rdp_write_bitmap_codecs_capability_set(wStream* s, } } +#endif + if (settings->RemoteFxImageCodec) { rdp_write_bitmap_codec_guid(s, &CODEC_GUID_IMAGE_REMOTEFX); /* codecGUID */ @@ -3858,18 +3885,17 @@ BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s) /* capabilitySets */ if (!rdp_read_capability_sets(s, rdp->settings, numberCapabilities)) { - WLog_ERR(TAG, "rdp_read_capability_sets failed"); + WLog_ERR(TAG, "rdp_read_capability_sets failed"); return FALSE; } - rdp->update->secondary->glyph_v2 = (rdp->settings->GlyphSupportLevel > - GLYPH_SUPPORT_FULL) ? TRUE : FALSE; + rdp->update->secondary->glyph_v2 = (rdp->settings->GlyphSupportLevel > GLYPH_SUPPORT_FULL); return TRUE; } BOOL rdp_write_demand_active(wStream* s, rdpSettings* settings) { - int bm, em, lm; + size_t bm, em, lm; UINT16 numberCapabilities; UINT16 lengthCombinedCapabilities; @@ -3917,7 +3943,7 @@ BOOL rdp_write_demand_active(wStream* s, rdpSettings* settings) numberCapabilities += 2; if (!rdp_write_remote_programs_capability_set(s, settings) || - !rdp_write_window_list_capability_set(s, settings)) + !rdp_write_window_list_capability_set(s, settings)) return FALSE; } @@ -4023,7 +4049,7 @@ BOOL rdp_recv_confirm_active(rdpRdp* rdp, wStream* s) BOOL rdp_write_confirm_active(wStream* s, rdpSettings* settings) { - int bm, em, lm; + size_t bm, em, lm; UINT16 numberCapabilities; UINT16 lengthSourceDescriptor; UINT16 lengthCombinedCapabilities; diff --git a/libfreerdp/core/certificate.c b/libfreerdp/core/certificate.c index f8f7ed4..0f3b6f0 100644 --- a/libfreerdp/core/certificate.c +++ b/libfreerdp/core/certificate.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <string.h> +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <winpr/crypto.h> @@ -157,21 +158,20 @@ static const char* certificate_read_errors[] = * @param cert X.509 certificate */ -BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) +static BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) { wStream* s; - int length; + size_t length; BYTE padding; UINT32 version; - int modulus_length; - int exponent_length; + size_t modulus_length; + size_t exponent_length; int error = 0; if (!cert || !info) return FALSE; memset(info, 0, sizeof(rdpCertInfo)); - s = Stream_New(cert->data, cert->length); if (!s) @@ -207,7 +207,8 @@ BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) error++; /* signature */ - if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ + if (!ber_read_sequence_tag(s, &length) || + !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; @@ -237,7 +238,8 @@ BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) error++; /* subjectPublicKeyInfo::AlgorithmIdentifier */ - if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ + if (!ber_read_sequence_tag(s, &length) || + !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; @@ -308,7 +310,8 @@ error2: free(info->Modulus); info->Modulus = 0; error1: - WLog_ERR(TAG, "error reading when reading certificate: part=%s error=%d", certificate_read_errors[error], error); + WLog_ERR(TAG, "error reading when reading certificate: part=%s error=%d", + certificate_read_errors[error], error); Stream_Free(s, FALSE); return FALSE; } @@ -319,10 +322,9 @@ error1: * @return new X.509 certificate chain */ -rdpX509CertChain* certificate_new_x509_certificate_chain(UINT32 count) +static rdpX509CertChain* certificate_new_x509_certificate_chain(UINT32 count) { rdpX509CertChain* x509_cert_chain; - x509_cert_chain = (rdpX509CertChain*) malloc(sizeof(rdpX509CertChain)); if (!x509_cert_chain) @@ -345,7 +347,7 @@ rdpX509CertChain* certificate_new_x509_certificate_chain(UINT32 count) * @param x509_cert_chain X.509 certificate chain to be freed */ -void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain) +static void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain) { int i; @@ -361,7 +363,8 @@ void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain) free(x509_cert_chain); } -static BOOL certificate_process_server_public_key(rdpCertificate* certificate, wStream* s, UINT32 length) +static BOOL certificate_process_server_public_key(rdpCertificate* certificate, wStream* s, + UINT32 length) { BYTE magic[4]; UINT32 keylen; @@ -395,23 +398,44 @@ static BOOL certificate_process_server_public_key(rdpCertificate* certificate, w Stream_Read(s, certificate->cert_info.Modulus, certificate->cert_info.ModulusLength); Stream_Seek(s, 8); /* 8 bytes of zero padding */ - return TRUE; } static BOOL certificate_process_server_public_signature(rdpCertificate* certificate, - const BYTE* sigdata, int sigdatalen, wStream* s, UINT32 siglen) + const BYTE* sigdata, size_t sigdatalen, wStream* s, UINT32 siglen) { - int i, sum; +#if defined(CERT_VALIDATE_PADDING) || defined(CERT_VALIDATE_RSA) + size_t i, sum; +#endif +#if defined(CERT_VALIDATE_RSA) BYTE sig[TSSK_KEY_LENGTH]; +#endif BYTE encsig[TSSK_KEY_LENGTH + 8]; +#if defined(CERT_VALIDATE_MD5) && defined(CERT_VALIDATE_RSA) BYTE md5hash[WINPR_MD5_DIGEST_LENGTH]; +#endif +#if !defined(CERT_VALIDATE_MD5) || !defined(CERT_VALIDATE_RSA) + (void)sigdata; + (void)sigdatalen; +#endif + (void)certificate; + /* Do not bother with validation of server proprietary certificate. The use of MD5 here is not allowed under FIPS. + * Since the validation is not protecting against anything since the private/public keys are well known and documented in + * MS-RDPBCGR section 5.3.3.1, we are not gaining any security by using MD5 for signature comparison. Rather then use MD5 + * here we just dont do the validation to avoid its use. Historically, freerdp has been ignoring a failed validation anyways. */ +#if defined(CERT_VALIDATE_MD5) if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash, sizeof(md5hash))) return FALSE; + +#endif Stream_Read(s, encsig, siglen); + if (siglen < 8) + return FALSE; + /* Last 8 bytes shall be all zero. */ +#if defined(CERT_VALIDATE_PADDING) for (sum = 0, i = sizeof(encsig) - 8; i < sizeof(encsig); i++) sum += encsig[i]; @@ -419,20 +443,30 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific if (sum != 0) { WLog_ERR(TAG, "invalid signature"); - //return FALSE; + return FALSE; } - siglen -= 8; - // TODO: check the result of decrypt - crypto_rsa_public_decrypt(encsig, siglen, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig); +#endif +#if defined(CERT_VALIDATE_RSA) + + if (crypto_rsa_public_decrypt(encsig, siglen - 8, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, + sig) <= 0) + { + WLog_ERR(TAG, "invalid RSA decrypt"); + return FALSE; + } /* Verify signature. */ + /* Do not bother with validation of server proprietary certificate as described above. */ +#if defined(CERT_VALIDATE_MD5) + if (memcmp(md5hash, sig, sizeof(md5hash)) != 0) { WLog_ERR(TAG, "invalid signature"); - //return FALSE; + return FALSE; } +#endif /* * Verify rest of decrypted data: * The 17th byte is 0x00. @@ -446,9 +480,10 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01) { WLog_ERR(TAG, "invalid signature"); - //return FALSE; + return FALSE; } +#endif return TRUE; } @@ -458,7 +493,7 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific * @param s stream */ -BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate, wStream* s) +static BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate, wStream* s) { UINT32 dwSigAlgId; UINT32 dwKeyAlgId; @@ -467,7 +502,7 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate UINT16 wSignatureBlobType; UINT16 wSignatureBlobLen; BYTE* sigdata; - int sigdatalen; + size_t sigdatalen; if (Stream_GetRemainingLength(s) < 12) return FALSE; @@ -480,7 +515,7 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA))) { WLog_ERR(TAG, "unsupported signature or key algorithm, dwSigAlgId=%"PRIu32" dwKeyAlgId=%"PRIu32"", - dwSigAlgId, dwKeyAlgId); + dwSigAlgId, dwKeyAlgId); return FALSE; } @@ -532,7 +567,8 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate return FALSE; } - if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s, wSignatureBlobLen)) + if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s, + wSignatureBlobLen)) { WLog_ERR(TAG, "unable to parse server public signature"); return FALSE; @@ -547,13 +583,12 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate * @param s stream */ -BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, wStream* s) +static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, wStream* s) { UINT32 i; BOOL ret; UINT32 certLength; UINT32 numCertBlobs; - DEBUG_CERTIFICATE("Server X.509 Certificate Chain"); if (Stream_GetRemainingLength(s) < 4) @@ -586,20 +621,17 @@ BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, if ((numCertBlobs - i) == 2) { - rdpCertInfo cert_info; - + rdpCertInfo cert_info = { 0 }; DEBUG_CERTIFICATE("License Server Certificate"); - ret = certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &cert_info); - DEBUG_LICENSE("modulus length:%"PRIu32"", cert_info.ModulusLength); - free(cert_info.Modulus); if (!ret) { WLog_ERR(TAG, "failed to read License Server, content follows:"); - winpr_HexDump(TAG, WLOG_ERROR, certificate->x509_cert_chain->array[i].data, certificate->x509_cert_chain->array[i].length); + winpr_HexDump(TAG, WLOG_ERROR, certificate->x509_cert_chain->array[i].data, + certificate->x509_cert_chain->array[i].length); return FALSE; } } @@ -607,7 +639,8 @@ BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, { DEBUG_CERTIFICATE("Terminal Server Certificate"); - if (!certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &certificate->cert_info)) + if (!certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], + &certificate->cert_info)) return FALSE; DEBUG_CERTIFICATE("modulus length:%"PRIu32"", certificate->cert_info.ModulusLength); @@ -624,7 +657,8 @@ BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, * @param length certificate length */ -BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert, size_t length) +BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert, + size_t length) { BOOL ret; wStream* s; @@ -660,24 +694,24 @@ BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* serv } Stream_Free(s, FALSE); - return ret; } -rdpRsaKey* key_new_from_content(const char *keycontent, const char *keyfile) +rdpRsaKey* key_new_from_content(const char* keycontent, const char* keyfile) { BIO* bio = NULL; RSA* rsa = NULL; rdpRsaKey* key = NULL; - const BIGNUM *rsa_e = NULL; - const BIGNUM *rsa_n = NULL; - const BIGNUM *rsa_d = NULL; - + const BIGNUM* rsa_e = NULL; + const BIGNUM* rsa_n = NULL; + const BIGNUM* rsa_d = NULL; key = (rdpRsaKey*) calloc(1, sizeof(rdpRsaKey)); + if (!key) return NULL; - bio = BIO_new_mem_buf((void *)keycontent, strlen(keycontent)); + bio = BIO_new_mem_buf((void*)keycontent, strlen(keycontent)); + if (!bio) goto out_free; @@ -734,7 +768,6 @@ rdpRsaKey* key_new_from_content(const char *keycontent, const char *keyfile) crypto_reverse(key->exponent, sizeof(key->exponent)); RSA_free(rsa); return key; - out_free_modulus: free(key->Modulus); out_free_rsa: @@ -748,40 +781,44 @@ out_free: rdpRsaKey* key_new(const char* keyfile) { FILE* fp = NULL; - int length; + INT64 length; char* buffer = NULL; rdpRsaKey* key = NULL; + fp = fopen(keyfile, "rb"); - 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) + if (_fseeki64(fp, 0, SEEK_END) < 0) goto out_free; - buffer = (char *)malloc(length + 1); + if ((length = _ftelli64(fp)) < 0) + goto out_free; + + if (_fseeki64(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); return NULL; } @@ -809,32 +846,42 @@ rdpCertificate* certificate_clone(rdpCertificate* certificate) if (certificate->cert_info.ModulusLength) { _certificate->cert_info.Modulus = (BYTE*) malloc(certificate->cert_info.ModulusLength); + if (!_certificate->cert_info.Modulus) goto out_fail; - CopyMemory(_certificate->cert_info.Modulus, certificate->cert_info.Modulus, certificate->cert_info.ModulusLength); + + CopyMemory(_certificate->cert_info.Modulus, certificate->cert_info.Modulus, + certificate->cert_info.ModulusLength); _certificate->cert_info.ModulusLength = certificate->cert_info.ModulusLength; } if (certificate->x509_cert_chain) { _certificate->x509_cert_chain = (rdpX509CertChain*) malloc(sizeof(rdpX509CertChain)); + if (!_certificate->x509_cert_chain) goto out_fail; + CopyMemory(_certificate->x509_cert_chain, certificate->x509_cert_chain, sizeof(rdpX509CertChain)); if (certificate->x509_cert_chain->count) { - _certificate->x509_cert_chain->array = (rdpCertBlob*) calloc(certificate->x509_cert_chain->count, sizeof(rdpCertBlob)); + _certificate->x509_cert_chain->array = (rdpCertBlob*) calloc(certificate->x509_cert_chain->count, + sizeof(rdpCertBlob)); + if (!_certificate->x509_cert_chain->array) goto out_fail; for (index = 0; index < certificate->x509_cert_chain->count; index++) { - _certificate->x509_cert_chain->array[index].length = certificate->x509_cert_chain->array[index].length; + _certificate->x509_cert_chain->array[index].length = + certificate->x509_cert_chain->array[index].length; if (certificate->x509_cert_chain->array[index].length) { - _certificate->x509_cert_chain->array[index].data = (BYTE*) malloc(certificate->x509_cert_chain->array[index].length); + _certificate->x509_cert_chain->array[index].data = (BYTE*) malloc( + certificate->x509_cert_chain->array[index].length); + if (!_certificate->x509_cert_chain->array[index].data) { for (--index; index >= 0; --index) @@ -842,23 +889,27 @@ rdpCertificate* certificate_clone(rdpCertificate* certificate) if (certificate->x509_cert_chain->array[index].length) free(_certificate->x509_cert_chain->array[index].data); } + goto out_fail; } - CopyMemory(_certificate->x509_cert_chain->array[index].data, certificate->x509_cert_chain->array[index].data, - _certificate->x509_cert_chain->array[index].length); + + CopyMemory(_certificate->x509_cert_chain->array[index].data, + certificate->x509_cert_chain->array[index].data, + _certificate->x509_cert_chain->array[index].length); } } } } return _certificate; - out_fail: + if (_certificate->x509_cert_chain) { free(_certificate->x509_cert_chain->array); free(_certificate->x509_cert_chain); } + free(_certificate->cert_info.Modulus); free(_certificate); return NULL; @@ -870,7 +921,7 @@ out_fail: * @return new certificate module */ -rdpCertificate* certificate_new() +rdpCertificate* certificate_new(void) { return (rdpCertificate*) calloc(1, sizeof(rdpCertificate)); } @@ -886,8 +937,6 @@ void certificate_free(rdpCertificate* certificate) return; certificate_free_x509_certificate_chain(certificate->x509_cert_chain); - free(certificate->cert_info.Modulus); - free(certificate); } diff --git a/libfreerdp/core/certificate.h b/libfreerdp/core/certificate.h index cfabda8..c5dd4ee 100644 --- a/libfreerdp/core/certificate.h +++ b/libfreerdp/core/certificate.h @@ -45,18 +45,6 @@ #define BB_RSA_KEY_BLOB 6 #define BB_RSA_SIGNATURE_BLOB 8 -FREERDP_LOCAL BOOL certificate_read_x509_certificate(rdpCertBlob* cert, - rdpCertInfo* info); - -FREERDP_LOCAL rdpX509CertChain* certificate_new_x509_certificate_chain( - UINT32 count); -FREERDP_LOCAL void certificate_free_x509_certificate_chain( - rdpX509CertChain* x509_cert_chain); - -FREERDP_LOCAL BOOL certificate_read_server_proprietary_certificate( - rdpCertificate* certificate, wStream* s); -FREERDP_LOCAL BOOL certificate_read_server_x509_certificate_chain( - rdpCertificate* certificate, wStream* s); FREERDP_LOCAL BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert, size_t length); diff --git a/libfreerdp/core/channels.c b/libfreerdp/core/channels.c index 63e720d..74fb37c 100644 --- a/libfreerdp/core/channels.c +++ b/libfreerdp/core/channels.c @@ -110,6 +110,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size) Stream_Write(s, data, chunkSize); + /* WLog_DBG(TAG, "%s: sending data (flags=0x%x size=%d)", __FUNCTION__, flags, size); */ if (!rdp_send(rdp, s, channelId)) { Stream_Release(s); diff --git a/libfreerdp/core/client.c b/libfreerdp/core/client.c index 0683855..64e71b6 100644 --- a/libfreerdp/core/client.c +++ b/libfreerdp/core/client.c @@ -76,6 +76,32 @@ static rdpMcsChannel* freerdp_channels_find_channel_by_name(rdpRdp* rdp, return NULL; } +static void channel_queue_free(void* obj) +{ + CHANNEL_OPEN_EVENT* ev; + wMessage* msg = (wMessage*)obj; + + if (!msg || (msg->id != 0)) + return; + + ev = (CHANNEL_OPEN_EVENT*)msg->wParam; + + if (ev) + { + /* Added by FreeRDP_VirtualChannelWriteEx */ + if (ev->UserData) + { + wStream* s = (wStream*)ev->UserData; + Stream_Free(s, TRUE); + } + /* Either has no data or added by FreeRDP_VirtualChannelWrite */ + else + free(ev->Data); + + free(ev); + } +} + rdpChannels* freerdp_channels_new(freerdp* instance) { rdpChannels* channels; @@ -93,6 +119,7 @@ rdpChannels* freerdp_channels_new(freerdp* instance) if (!channels->queue) goto error; + channels->queue->object.fnObjectFree = channel_queue_free; channels->openHandles = HashTable_New(TRUE); if (!channels->openHandles) @@ -662,18 +689,11 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance) for (index = 0; index < channels->openDataCount; index++) { pChannelOpenData = &channels->openDataList[index]; - - if (pChannelOpenData->pInterface) - { - free(pChannelOpenData->pInterface); - pChannelOpenData->pInterface = NULL; - } - freerdp_channel_remove_open_handle_data(&g_ChannelHandles, pChannelOpenData->OpenHandle); if (channels->openHandles) HashTable_Remove(channels->openHandles, - (void*)(UINT_PTR)pChannelOpenData->OpenHandle); + (void*)(UINT_PTR)pChannelOpenData->OpenHandle); } channels->openDataCount = 0; @@ -708,7 +728,7 @@ static UINT VCAPITYPE FreeRDP_VirtualChannelInitEx(LPVOID lpUserParam, LPVOID cl if (!channels->can_call_init) return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY; - if ((channels->openDataCount + channelCount) >= CHANNEL_MAX_COUNT) + if ((channels->openDataCount + channelCount) > CHANNEL_MAX_COUNT) return CHANNEL_RC_TOO_MANY_CHANNELS; if (!pChannel) @@ -796,7 +816,7 @@ static UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle, if (!channels->can_call_init) return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY; - if (channels->openDataCount + channelCount >= CHANNEL_MAX_COUNT) + if (channels->openDataCount + channelCount > CHANNEL_MAX_COUNT) return CHANNEL_RC_TOO_MANY_CHANNELS; if (!pChannel) @@ -1109,7 +1129,7 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, CHANNEL_ENTRY_POINTS_FREERDP EntryPoints; CHANNEL_CLIENT_DATA* pChannelClientData; - if (channels->clientDataCount + 1 >= CHANNEL_MAX_COUNT) + if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT) { WLog_ERR(TAG, "error: too many channels"); return 1; @@ -1162,7 +1182,7 @@ int freerdp_channels_client_load_ex(rdpChannels* channels, rdpSettings* settings CHANNEL_INIT_DATA* pChannelInitData = NULL; CHANNEL_CLIENT_DATA* pChannelClientData = NULL; - if (channels->clientDataCount + 1 >= CHANNEL_MAX_COUNT) + if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT) { WLog_ERR(TAG, "error: too many channels"); return 1; diff --git a/libfreerdp/core/client.h b/libfreerdp/core/client.h index 3f1e1f4..e985314 100644 --- a/libfreerdp/core/client.h +++ b/libfreerdp/core/client.h @@ -35,7 +35,7 @@ #include <freerdp/client/drdynvc.h> #include <freerdp/channels/channels.h> -#define CHANNEL_MAX_COUNT 30 +#define CHANNEL_MAX_COUNT 31 struct rdp_channel_client_data { diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 8499cc7..0bf1bc1 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -32,6 +32,7 @@ #include <winpr/crt.h> #include <winpr/crypto.h> +#include <winpr/ssl.h> #include <freerdp/log.h> #include <freerdp/error.h> @@ -178,6 +179,24 @@ BOOL rdp_client_connect(rdpRdp* rdp) BOOL status; rdpSettings* settings = rdp->settings; + /* make sure SSL is initialize for earlier enough for crypto, by taking advantage of winpr SSL FIPS flag for openssl initialization */ + DWORD flags = WINPR_SSL_INIT_DEFAULT; + + if (settings->FIPSMode) + flags |= WINPR_SSL_INIT_ENABLE_FIPS; + winpr_InitializeSSL(flags); + + /* FIPS Mode forces the following and overrides the following(by happening later */ + /* in the command line processing): */ + /* 1. Disables NLA Security since NLA in freerdp uses NTLM(no Kerberos support yet) which uses algorithms */ + /* not allowed in FIPS for sensitive data. So, we disallow NLA when FIPS is required. */ + /* 2. Forces the only supported RDP encryption method to be FIPS. */ + if (settings->FIPSMode || winpr_FIPSMode()) + { + settings->NlaSecurity = FALSE; + settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS; + } + nego_init(rdp->nego); nego_set_target(rdp->nego, settings->ServerHostname, settings->ServerPort); diff --git a/libfreerdp/core/errconnect.c b/libfreerdp/core/errconnect.c index 3faabe1..b171448 100644 --- a/libfreerdp/core/errconnect.c +++ b/libfreerdp/core/errconnect.c @@ -85,6 +85,33 @@ #define ERRCONNECT_KDC_UNREACHABLE_STRING \ "The KDC is unreachable." +#define ERRCONNECT_ACCOUNT_DISABLED_STRING \ + "The account is disabled." + +#define ERRCONNECT_PASSWORD_MUST_CHANGE_STRING \ + "The password must be changed." + +#define ERRCONNECT_LOGON_FAILURE_STRING \ + "Logon failed." + +#define ERRCONNECT_WRONG_PASSWORD_STRING \ + "Wrong password supplied." + +#define ERRCONNECT_ACCESS_DENIED_STRING \ + "Access denied." + +#define ERRCONNECT_ACCOUNT_RESTRICTION_STRING \ + "Account restriction." + +#define ERRCONNECT_ACCOUNT_LOCKED_OUT_STRING \ + "Account locked out." + +#define ERRCONNECT_ACCOUNT_EXPIRED_STRING \ + "Account expired." + +#define ERRCONNECT_LOGON_TYPE_NOT_GRANTED_STRING \ + "Logon type not granted." + /* Special codes */ #define ERRCONNECT_SUCCESS_STRING "Success." #define ERRCONNECT_NONE_STRING "" @@ -110,6 +137,15 @@ static const ERRINFO ERRCONNECT_CODES[] = ERRCONNECT_DEFINE(PASSWORD_CERTAINLY_EXPIRED), ERRCONNECT_DEFINE(CLIENT_REVOKED), ERRCONNECT_DEFINE(KDC_UNREACHABLE), + ERRCONNECT_DEFINE(ACCOUNT_DISABLED), + ERRCONNECT_DEFINE(PASSWORD_MUST_CHANGE), + ERRCONNECT_DEFINE(LOGON_FAILURE), + ERRCONNECT_DEFINE(WRONG_PASSWORD), + ERRCONNECT_DEFINE(ACCESS_DENIED), + ERRCONNECT_DEFINE(ACCOUNT_RESTRICTION), + ERRCONNECT_DEFINE(ACCOUNT_LOCKED_OUT), + ERRCONNECT_DEFINE(ACCOUNT_EXPIRED), + ERRCONNECT_DEFINE(LOGON_TYPE_NOT_GRANTED), ERRCONNECT_DEFINE(NONE) }; diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 04c3fc4..353e018 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -328,7 +328,7 @@ static BOOL fastpath_recv_update_synchronize(rdpFastPath* fastpath, wStream* s) return TRUE; } -static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 size, wStream* s) +static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, wStream* s) { int status = 0; rdpUpdate* update; @@ -346,9 +346,9 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s context = update->context; pointer = update->pointer; #ifdef WITH_DEBUG_RDP - DEBUG_RDP("recv Fast-Path %s Update (0x%02"PRIX8"), length:%"PRIu32"", + DEBUG_RDP("recv Fast-Path %s Update (0x%02"PRIX8"), length:%"PRIuz"", updateCode < ARRAYSIZE(FASTPATH_UPDATETYPE_STRINGS) ? FASTPATH_UPDATETYPE_STRINGS[updateCode] : - "???", updateCode, size); + "???", updateCode, Stream_Length(s)); #endif switch (updateCode) @@ -381,7 +381,7 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s break; case FASTPATH_UPDATETYPE_SURFCMDS: - status = update_recv_surfcmds(update, size, s); + status = update_recv_surfcmds(update, s); if (status < 0) WLog_ERR(TAG, "FASTPATH_UPDATETYPE_SURFCMDS - update_recv_surfcmds() - %i", status); @@ -451,10 +451,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) int status; UINT16 size; rdpRdp* rdp; - int next_pos; - wStream* cs; int bulkStatus; - UINT32 totalSize; BYTE updateCode; BYTE fragmentation; BYTE compression; @@ -501,10 +498,9 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) return -1; } - cs = s; - next_pos = Stream_GetPosition(s) + size; bulkStatus = bulk_decompress(rdp->bulk, Stream_Pointer(s), size, &pDstData, &DstSize, compressionFlags); + Stream_Seek(s, size); if (bulkStatus < 0) { @@ -512,19 +508,10 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) return -1; } - if (bulkStatus > 0) - { - /* data was compressed, copy from decompression buffer */ - size = DstSize; + if (!Stream_EnsureRemainingCapacity(fastpath->updateData, DstSize)) + return -1; - if (!(cs = StreamPool_Take(transport->ReceivePool, DstSize))) - return -1; - - Stream_SetPosition(cs, 0); - Stream_Write(cs, pDstData, DstSize); - Stream_SealLength(cs); - Stream_SetPosition(cs, 0); - } + Stream_Write(fastpath->updateData, pDstData, DstSize); if (fragmentation == FASTPATH_FRAGMENT_SINGLE) { @@ -534,8 +521,10 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) goto out_fail; } - totalSize = size; - status = fastpath_recv_update(fastpath, updateCode, totalSize, cs); + Stream_SealLength(fastpath->updateData); + Stream_SetPosition(fastpath->updateData, 0); + status = fastpath_recv_update(fastpath, updateCode, fastpath->updateData); + Stream_SetPosition(fastpath->updateData, 0); if (status < 0) { @@ -545,6 +534,14 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) } else { + const size_t totalSize = Stream_GetPosition(fastpath->updateData); + if (totalSize > transport->settings->MultifragMaxRequestSize) + { + WLog_ERR(TAG, "Total size (%"PRIuz") exceeds MultifragMaxRequestSize (%"PRIu32")", + totalSize, transport->settings->MultifragMaxRequestSize); + goto out_fail; + } + if (fragmentation == FASTPATH_FRAGMENT_FIRST) { if (fastpath->fragmentation != -1) @@ -554,20 +551,8 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) } fastpath->fragmentation = FASTPATH_FRAGMENT_FIRST; - totalSize = size; - if (totalSize > transport->settings->MultifragMaxRequestSize) - { - WLog_ERR(TAG, "Total size (%"PRIu32") exceeds MultifragMaxRequestSize (%"PRIu32")", - totalSize, transport->settings->MultifragMaxRequestSize); - goto out_fail; - } - - if (!(fastpath->updateData = StreamPool_Take(transport->ReceivePool, size))) - goto out_fail; - - Stream_SetPosition(fastpath->updateData, 0); - Stream_Copy(cs, fastpath->updateData, size); + } else if (fragmentation == FASTPATH_FRAGMENT_NEXT) { @@ -579,22 +564,6 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) } fastpath->fragmentation = FASTPATH_FRAGMENT_NEXT; - totalSize = Stream_GetPosition(fastpath->updateData) + size; - - if (totalSize > transport->settings->MultifragMaxRequestSize) - { - WLog_ERR(TAG, "Total size (%"PRIu32") exceeds MultifragMaxRequestSize (%"PRIu32")", - totalSize, transport->settings->MultifragMaxRequestSize); - goto out_fail; - } - - if (!Stream_EnsureCapacity(fastpath->updateData, totalSize)) - { - WLog_ERR(TAG, "Couldn't re-allocate memory for stream"); - goto out_fail; - } - - Stream_Copy(cs, fastpath->updateData, size); } else if (fragmentation == FASTPATH_FRAGMENT_LAST) { @@ -606,26 +575,11 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) } fastpath->fragmentation = -1; - totalSize = Stream_GetPosition(fastpath->updateData) + size; - if (totalSize > transport->settings->MultifragMaxRequestSize) - { - WLog_ERR(TAG, "Total size (%"PRIu32") exceeds MultifragMaxRequestSize (%"PRIu32")", - totalSize, transport->settings->MultifragMaxRequestSize); - goto out_fail; - } - - if (!Stream_EnsureCapacity(fastpath->updateData, totalSize)) - { - WLog_ERR(TAG, "Couldn't re-allocate memory for stream"); - goto out_fail; - } - - Stream_Copy(cs, fastpath->updateData, size); Stream_SealLength(fastpath->updateData); Stream_SetPosition(fastpath->updateData, 0); - status = fastpath_recv_update(fastpath, updateCode, totalSize, fastpath->updateData); - Stream_Release(fastpath->updateData); + status = fastpath_recv_update(fastpath, updateCode, fastpath->updateData); + Stream_SetPosition(fastpath->updateData, 0); if (status < 0) { @@ -635,19 +589,9 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) } } - Stream_SetPosition(s, next_pos); - - if (cs != s) - Stream_Release(cs); - return status; out_fail: - if (cs != s) - { - Stream_Release(cs); - } - return -1; } @@ -1244,13 +1188,14 @@ rdpFastPath* fastpath_new(rdpRdp* rdp) fastpath->rdp = rdp; fastpath->fragmentation = -1; fastpath->fs = Stream_New(NULL, FASTPATH_MAX_PACKET_SIZE); + fastpath->updateData = Stream_New(NULL, FASTPATH_MAX_PACKET_SIZE); - if (!fastpath->fs) + if (!fastpath->fs || !fastpath->updateData) goto out_free; return fastpath; out_free: - free(fastpath); + fastpath_free(fastpath); return NULL; } @@ -1258,6 +1203,7 @@ void fastpath_free(rdpFastPath* fastpath) { if (fastpath) { + Stream_Free(fastpath->updateData, TRUE); Stream_Free(fastpath->fs, TRUE); free(fastpath); } diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index b57499e..a1733ea 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -236,17 +236,14 @@ BOOL freerdp_connect(freerdp* instance) update = instance->update; update->pcap_rfx = pcap_open(settings->PlayRemoteFxFile, FALSE); + status = FALSE; if (!update->pcap_rfx) - { - status = FALSE; goto freerdp_connect_finally; - } else - { update->play_rfx = TRUE; - } - while (pcap_has_next_record(update->pcap_rfx)) + status = TRUE; + while (pcap_has_next_record(update->pcap_rfx) && status) { pcap_get_next_record_header(update->pcap_rfx, &record); @@ -257,15 +254,19 @@ BOOL freerdp_connect(freerdp* instance) pcap_get_next_record_content(update->pcap_rfx, &record); Stream_SetLength(s, record.length); Stream_SetPosition(s, 0); - update->BeginPaint(update->context); - update_recv_surfcmds(update, Stream_Length(s) , s); - update->EndPaint(update->context); + + if (!update->BeginPaint(update->context)) + status = FALSE; + else if (update_recv_surfcmds(update, s) < 0) + status = FALSE; + else if (!update->EndPaint(update->context)) + status = FALSE; + Stream_Release(s); } pcap_close(update->pcap_rfx); update->pcap_rfx = NULL; - status = TRUE; goto freerdp_connect_finally; } } @@ -279,6 +280,10 @@ freerdp_connect_finally: EventArgsInit(&e, "freerdp"); e.result = status ? 0 : -1; PubSub_OnConnectionResult(instance->context->pubSub, instance->context, &e); + + if (!status) + freerdp_disconnect(instance); + return status; } @@ -366,7 +371,9 @@ BOOL freerdp_check_event_handles(rdpContext* context) if (!status) { - WLog_ERR(TAG, "freerdp_check_fds() failed - %"PRIi32"", status); + if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) + WLog_ERR(TAG, "freerdp_check_fds() failed - %"PRIi32"", status); + return FALSE; } @@ -374,7 +381,9 @@ BOOL freerdp_check_event_handles(rdpContext* context) if (!status) { - WLog_ERR(TAG, "freerdp_channels_check_fds() failed - %"PRIi32"", status); + if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) + WLog_ERR(TAG, "freerdp_channels_check_fds() failed - %"PRIi32"", status); + return FALSE; } @@ -596,6 +605,9 @@ static wEventType FreeRDP_Events[] = DEFINE_EVENT_ENTRY(ChannelConnected) DEFINE_EVENT_ENTRY(ChannelDisconnected) DEFINE_EVENT_ENTRY(MouseEvent) + DEFINE_EVENT_ENTRY(Activated) + DEFINE_EVENT_ENTRY(Timer) + DEFINE_EVENT_ENTRY(GraphicsReset) }; /** Allocator function for a rdp context. @@ -626,7 +638,7 @@ BOOL freerdp_context_new(freerdp* instance) goto fail; PubSub_AddEventTypes(context->pubSub, FreeRDP_Events, - sizeof(FreeRDP_Events) / sizeof(wEventType)); + ARRAYSIZE(FreeRDP_Events)); context->metrics = metrics_new(context); if (!context->metrics) @@ -926,7 +938,6 @@ freerdp* freerdp_new() if (!instance) return NULL; - winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT); instance->ContextSize = sizeof(rdpContext); instance->SendChannelData = freerdp_send_channel_data; instance->ReceiveChannelData = freerdp_channels_data; diff --git a/libfreerdp/core/gateway/http.c b/libfreerdp/core/gateway/http.c index 4fd190d..a249a6d 100644 --- a/libfreerdp/core/gateway/http.c +++ b/libfreerdp/core/gateway/http.c @@ -21,6 +21,8 @@ #include "config.h" #endif +#include <errno.h> + #include <winpr/crt.h> #include <winpr/print.h> #include <winpr/stream.h> @@ -36,6 +38,8 @@ #define TAG FREERDP_TAG("core.gateway.http") +#define RESPONSE_SIZE_LIMIT 64 * 1024 * 1024 + static char* string_strnstr(const char* str1, const char* str2, size_t slen) { char c, sc; @@ -52,12 +56,12 @@ static char* string_strnstr(const char* str1, const char* str2, size_t slen) if (slen-- < 1 || (sc = *str1++) == '\0') return NULL; } - while(sc != c); + while (sc != c); if (len > slen) return NULL; } - while(strncmp(str1, str2, len) != 0); + while (strncmp(str1, str2, len) != 0); str1--; } @@ -73,12 +77,7 @@ static BOOL strings_equals_nocase(void* obj1, void* obj2) return _stricmp(obj1, obj2) == 0; } -static void string_free(void* obj1) -{ - free(obj1); -} - -HttpContext* http_context_new() +HttpContext* http_context_new(void) { return (HttpContext*) calloc(1, sizeof(HttpContext)); } @@ -182,6 +181,13 @@ BOOL http_context_set_rdg_connection_id(HttpContext* context, const char* RdgCon return TRUE; } +BOOL http_context_set_rdg_auth_scheme(HttpContext* context, const char* RdgAuthScheme) +{ + free(context->RdgAuthScheme); + context->RdgAuthScheme = _strdup(RdgAuthScheme); + return context->RdgAuthScheme != NULL; +} + void http_context_free(HttpContext* context) { if (context) @@ -195,6 +201,7 @@ void http_context_free(HttpContext* context) free(context->Connection); free(context->Pragma); free(context->RdgConnectionId); + free(context->RdgAuthScheme); free(context); } } @@ -254,11 +261,10 @@ BOOL http_request_set_transfer_encoding(HttpRequest* request, const char* Transf return TRUE; } -char* http_encode_body_line(char* param, char* value) +static char* http_encode_body_line(const char* param, const char* value) { char* line; int length; - length = strlen(param) + strlen(value) + 2; line = (char*) malloc(length + 1); @@ -269,50 +275,50 @@ char* http_encode_body_line(char* param, char* value) return line; } -char* http_encode_content_length_line(int ContentLength) +static char* http_encode_content_length_line(int ContentLength) { + const char* key = "Content-Length:"; char* line; int length; char str[32]; - _itoa_s(ContentLength, str, sizeof(str), 10); - length = strlen("Content-Length") + strlen(str) + 2; + length = strlen(key) + strlen(str) + 2; line = (char*) malloc(length + 1); if (!line) return NULL; - sprintf_s(line, length + 1, "Content-Length: %s", str); + sprintf_s(line, length + 1, "%s %s", key, str); return line; } -char* http_encode_header_line(char* Method, char* URI) +static char* http_encode_header_line(const char* Method, const char* URI) { + const char* key = "HTTP/1.1"; char* line; int length; - - length = strlen("HTTP/1.1") + strlen(Method) + strlen(URI) + 2; + length = strlen(key) + strlen(Method) + strlen(URI) + 2; line = (char*)malloc(length + 1); if (!line) return NULL; - sprintf_s(line, length + 1, "%s %s HTTP/1.1", Method, URI); + sprintf_s(line, length + 1, "%s %s %s", Method, URI, key); return line; } -char* http_encode_authorization_line(char* AuthScheme, char* AuthParam) +static char* http_encode_authorization_line(const char* AuthScheme, const char* AuthParam) { + const char* key = "Authorization:"; char* line; int length; - - length = strlen("Authorization") + strlen(AuthScheme) + strlen(AuthParam) + 3; + length = strlen(key) + strlen(AuthScheme) + strlen(AuthParam) + 3; line = (char*) malloc(length + 1); if (!line) return NULL; - sprintf_s(line, length + 1, "Authorization: %s %s", AuthScheme, AuthParam); + sprintf_s(line, length + 1, "%s %s %s", key, AuthScheme, AuthParam); return line; } @@ -322,7 +328,6 @@ wStream* http_request_write(HttpContext* context, HttpRequest* request) int i, count; char** lines; int length = 0; - count = 0; lines = (char**) calloc(32, sizeof(char*)); @@ -335,9 +340,29 @@ wStream* http_request_write(HttpContext* context, HttpRequest* request) lines[count++] = http_encode_body_line("Pragma", context->Pragma); lines[count++] = http_encode_body_line("Accept", context->Accept); lines[count++] = http_encode_body_line("User-Agent", context->UserAgent); - lines[count++] = http_encode_content_length_line(request->ContentLength); lines[count++] = http_encode_body_line("Host", context->Host); + if (!context->RdgAuthScheme) + lines[count++] = http_encode_content_length_line(request->ContentLength); + + if (context->RdgConnectionId) + lines[count++] = http_encode_body_line("RDG-Connection-Id", context->RdgConnectionId); + + if (context->RdgAuthScheme) + lines[count++] = http_encode_body_line("RDG-Auth-Scheme", context->RdgAuthScheme); + + if (request->TransferEncoding) + lines[count++] = http_encode_body_line("Transfer-Encoding", request->TransferEncoding); + + if (request->Authorization) + { + lines[count++] = http_encode_body_line("Authorization", request->Authorization); + } + else if (request->AuthScheme && request->AuthParam) + { + lines[count++] = http_encode_authorization_line(request->AuthScheme, request->AuthParam); + } + /* check that everything went well */ for (i = 0; i < count; i++) { @@ -345,45 +370,6 @@ wStream* http_request_write(HttpContext* context, HttpRequest* request) goto out_free; } - if (context->RdgConnectionId) - { - lines[count] = http_encode_body_line("RDG-Connection-Id", context->RdgConnectionId); - - if (!lines[count]) - goto out_free; - - count++; - } - - if (request->TransferEncoding) - { - lines[count] = http_encode_body_line("Transfer-Encoding", request->TransferEncoding); - - if (!lines[count]) - goto out_free; - - count++; - } - - if (request->Authorization) - { - lines[count] = http_encode_body_line("Authorization", request->Authorization); - - if (!lines[count]) - goto out_free; - - count++; - } - else if (request->AuthScheme && request->AuthParam) - { - lines[count] = http_encode_authorization_line(request->AuthScheme, request->AuthParam); - - if (!lines[count]) - goto out_free; - - count++; - } - for (i = 0; i < count; i++) { length += (strlen(lines[i]) + 2); /* add +2 for each '\r\n' character */ @@ -409,8 +395,8 @@ wStream* http_request_write(HttpContext* context, HttpRequest* request) Stream_Rewind(s, 1); /* don't include null terminator in length */ Stream_SetLength(s, Stream_GetPosition(s)); return s; - out_free: + for (i = 0; i < count; i++) free(lines[i]); @@ -418,7 +404,7 @@ out_free: return NULL; } -HttpRequest* http_request_new() +HttpRequest* http_request_new(void) { return (HttpRequest*) calloc(1, sizeof(HttpRequest)); } @@ -438,7 +424,7 @@ void http_request_free(HttpRequest* request) free(request); } -BOOL http_response_parse_header_status_line(HttpResponse* response, char* status_line) +static BOOL http_response_parse_header_status_line(HttpResponse* response, char* status_line) { char* separator = NULL; char* status_code; @@ -458,8 +444,16 @@ BOOL http_response_parse_header_status_line(HttpResponse* response, char* status reason_phrase = separator + 1; *separator = '\0'; - response->StatusCode = atoi(status_code); - response->ReasonPhrase = _strdup(reason_phrase); + errno = 0; + { + long val = strtol(status_code, NULL, 0); + + if ((errno != 0) || (val < 0) || (val > INT16_MAX)) + return FALSE; + + response->StatusCode = strtol(status_code, NULL, 0); + } + response->ReasonPhrase = reason_phrase; if (!response->ReasonPhrase) return FALSE; @@ -468,17 +462,25 @@ BOOL http_response_parse_header_status_line(HttpResponse* response, char* status return TRUE; } -BOOL http_response_parse_header_field(HttpResponse* response, char* name, char* value) +static BOOL http_response_parse_header_field(HttpResponse* response, const char* name, + const char* value) { BOOL status = TRUE; if (_stricmp(name, "Content-Length") == 0) { - response->ContentLength = atoi(value); + unsigned long long val; + errno = 0; + val = _strtoui64(value, NULL, 0); + + if ((errno != 0) || (val > INT32_MAX)) + return FALSE; + + response->ContentLength = val; } else if (_stricmp(name, "Content-Type") == 0) { - response->ContentType = _strdup(value); + response->ContentType = value; if (!response->ContentType) return FALSE; @@ -486,9 +488,8 @@ BOOL http_response_parse_header_field(HttpResponse* response, char* name, char* else if (_stricmp(name, "WWW-Authenticate") == 0) { char* separator = NULL; - char* authScheme = NULL; - char* authValue = NULL; - + const char* authScheme = NULL; + const char* authValue = NULL; separator = strchr(value, ' '); if (separator) @@ -500,21 +501,15 @@ BOOL http_response_parse_header_field(HttpResponse* response, char* name, char* * opaque="5ccc069c403ebaf9f0171e9517f40e41" */ *separator = '\0'; - authScheme = _strdup(value); - authValue = _strdup(separator + 1); + authScheme = value; + authValue = separator + 1; if (!authScheme || !authValue) - { - free(authScheme); - free(authValue); return FALSE; - } - - *separator = ' '; } else { - authScheme = _strdup(value); + authScheme = value; if (!authScheme) return FALSE; @@ -522,16 +517,16 @@ BOOL http_response_parse_header_field(HttpResponse* response, char* name, char* authValue = NULL; } - status = ListDictionary_Add(response->Authenticates, authScheme, authValue); + status = ListDictionary_Add(response->Authenticates, (void*)authScheme, (void*)authValue); } return status; } -BOOL http_response_parse_header(HttpResponse* response) +static BOOL http_response_parse_header(HttpResponse* response) { char c; - int count; + size_t count; char* line; char* name; char* value; @@ -551,6 +546,7 @@ BOOL http_response_parse_header(HttpResponse* response) for (count = 1; count < response->count; count++) { line = response->lines[count]; + /** * name end_of_header * | | @@ -612,42 +608,134 @@ void http_response_print(HttpResponse* response) HttpResponse* http_response_recv(rdpTls* tls) { - wStream* s; - int size; - int count; - int status; - int position; - char* line; - char* buffer; - char* header = NULL; - char* payload; - int bodyLength; - int payloadOffset; + size_t size; + size_t position; + size_t bodyLength = 0; + size_t payloadOffset; HttpResponse* response; - size = 2048; - payload = NULL; payloadOffset = 0; - - s = Stream_New(NULL, size); - - if (!s) - goto out_free; - - buffer = (char*) Stream_Buffer(s); - response = http_response_new(); if (!response) - goto out_free; + return NULL; response->ContentLength = 0; - while (TRUE) + while (!payloadOffset) { - while (!payloadOffset) + int status = BIO_read(tls->bio, Stream_Pointer(response->data), + Stream_Capacity(response->data) - Stream_GetPosition(response->data)); + + if (status <= 0) { - status = BIO_read(tls->bio, Stream_Pointer(s), Stream_Capacity(s) - Stream_GetPosition(s)); + if (!BIO_should_retry(tls->bio)) + goto out_error; + + USleep(100); + continue; + } + +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_DEFINED(Stream_Pointer(response->data), status); +#endif + Stream_Seek(response->data, status); + + if (Stream_GetRemainingLength(response->data) < 1024) + { + if (!Stream_EnsureRemainingCapacity(response->data, 1024)) + goto out_error; + } + + position = Stream_GetPosition(response->data); + + if (position > RESPONSE_SIZE_LIMIT) + { + WLog_ERR(TAG, "Request header too large! (%"PRIdz" bytes) Aborting!", bodyLength); + goto out_error; + } + + if (position >= 4) + { + char* buffer = Stream_Buffer(response->data); + const char* line = string_strnstr(buffer, "\r\n\r\n", position); + + if (line) + payloadOffset = (line - buffer) + 4; + } + } + + if (payloadOffset) + { + size_t count = 0; + char* buffer = Stream_Buffer(response->data); + char* line = Stream_Buffer(response->data); + + while ((line = string_strnstr(line, "\r\n", payloadOffset - (line - buffer) - 2))) + { + line += 2; + count++; + } + + response->count = count; + + if (count) + { + response->lines = (char**) calloc(response->count, sizeof(char*)); + + if (!response->lines) + goto out_error; + } + + buffer[payloadOffset - 1] = '\0'; + buffer[payloadOffset - 2] = '\0'; + count = 0; + line = strtok(buffer, "\r\n"); + + while (line && response->lines) + { + response->lines[count] = line; + + if (!response->lines[count]) + goto out_error; + + line = strtok(NULL, "\r\n"); + count++; + } + + if (!http_response_parse_header(response)) + goto out_error; + + response->BodyLength = Stream_GetPosition(response->data) - payloadOffset; + bodyLength = 0; /* expected body length */ + + if (response->ContentType) + { + if (_stricmp(response->ContentType, "application/rpc") != 0) + bodyLength = response->ContentLength; + else if (_stricmp(response->ContentType, "text/plain") == 0) + bodyLength = response->ContentLength; + else if (_stricmp(response->ContentType, "text/html") == 0) + bodyLength = response->ContentLength; + } + else + bodyLength = response->BodyLength; + + if (bodyLength > RESPONSE_SIZE_LIMIT) + { + WLog_ERR(TAG, "Expected request body too large! (%"PRIdz" bytes) Aborting!", bodyLength); + goto out_error; + } + + /* Fetch remaining body! */ + while (response->BodyLength < bodyLength) + { + int status; + + if (!Stream_EnsureRemainingCapacity(response->data, bodyLength - response->BodyLength)) + goto out_error; + + status = BIO_read(tls->bio, Stream_Pointer(response->data), bodyLength - response->BodyLength); if (status <= 0) { @@ -658,164 +746,36 @@ HttpResponse* http_response_recv(rdpTls* tls) continue; } -#ifdef HAVE_VALGRIND_MEMCHECK_H - VALGRIND_MAKE_MEM_DEFINED(Stream_Pointer(s), status); -#endif + Stream_Seek(response->data, status); + response->BodyLength += status; - Stream_Seek(s, status); - - if (Stream_GetRemainingLength(s) < 1024) + if (response->BodyLength > RESPONSE_SIZE_LIMIT) { - if (!Stream_EnsureRemainingCapacity(s, 1024)) - goto out_error; - buffer = (char*) Stream_Buffer(s); - payload = &buffer[payloadOffset]; - } - - position = Stream_GetPosition(s); - - if (position >= 4) - { - line = string_strnstr(buffer, "\r\n\r\n", position); - - if (line) - { - payloadOffset = (line - buffer) + 4; - payload = &buffer[payloadOffset]; - } + WLog_ERR(TAG, "Request body too large! (%"PRIdz" bytes) Aborting!", response->BodyLength); + goto out_error; } } - if (payloadOffset) + if (response->BodyLength > 0) { - count = 0; - line = buffer; - - position = Stream_GetPosition(s); - - while ((line = string_strnstr(line, "\r\n", payloadOffset - (line - buffer) - 2))) - { - line += 2; - count++; - } - - response->count = count; - - if (count) - { - response->lines = (char**) calloc(response->count, sizeof(char*)); - - if (!response->lines) - goto out_error; - } - - header = (char*) malloc(payloadOffset); - - if (!header) - goto out_error; - - CopyMemory(header, buffer, payloadOffset); - header[payloadOffset - 1] = '\0'; - header[payloadOffset - 2] = '\0'; - - count = 0; - line = strtok(header, "\r\n"); - - while (line && response->lines) - { - response->lines[count] = _strdup(line); - - if (!response->lines[count]) - goto out_error; - - line = strtok(NULL, "\r\n"); - count++; - } - - if (!http_response_parse_header(response)) - goto out_error; - - response->BodyLength = Stream_GetPosition(s) - payloadOffset; - - bodyLength = 0; /* expected body length */ - - if (response->ContentType) - { - if (_stricmp(response->ContentType, "application/rpc") != 0) - bodyLength = response->ContentLength; - else if (_stricmp(response->ContentType, "text/plain") == 0) - bodyLength = response->ContentLength; - else if (_stricmp(response->ContentType, "text/html") == 0) - bodyLength = response->ContentLength; - } - else - { - bodyLength = response->BodyLength; - } - - // Fetch remaining body! - while (response->BodyLength < bodyLength) - { - if (!Stream_EnsureRemainingCapacity(s, bodyLength - response->BodyLength)) - goto out_error; - - status = BIO_read(tls->bio, Stream_Pointer(s), bodyLength - response->BodyLength); - - if (status <= 0) - { - if (!BIO_should_retry(tls->bio)) - goto out_error; - - USleep(100); - continue; - } - - Stream_Seek(s, status); - response->BodyLength += status; - - } - - if (response->BodyLength > 0) - { - response->BodyContent = (BYTE*) malloc(response->BodyLength); - - if (!response->BodyContent) - goto out_error; - - CopyMemory(response->BodyContent, payload, response->BodyLength); - response->BodyLength = bodyLength; - } - - if (bodyLength != response->BodyLength) - { - WLog_WARN(TAG, "http_response_recv: %s unexpected body length: actual: %d, expected: %d", - response->ContentType, bodyLength, response->BodyLength); - } - - break; + response->BodyContent = &(Stream_Buffer(response->data))[payloadOffset]; + response->BodyLength = bodyLength; } - if (Stream_GetRemainingLength(s) < 1024) + if (bodyLength != response->BodyLength) { - if (!Stream_EnsureRemainingCapacity(s, 1024)) - goto out_error; - buffer = (char*) Stream_Buffer(s); - payload = &buffer[payloadOffset]; + WLog_WARN(TAG, "http_response_recv: %s unexpected body length: actual: %d, expected: %d", + response->ContentType, bodyLength, response->BodyLength); } } - free(header); - Stream_Free(s, TRUE); return response; out_error: http_response_free(response); - free(header); -out_free: - Stream_Free(s, TRUE); return NULL; } -HttpResponse* http_response_new() +HttpResponse* http_response_new(void) { HttpResponse* response = (HttpResponse*) calloc(1, sizeof(HttpResponse)); @@ -823,44 +783,30 @@ HttpResponse* http_response_new() return NULL; response->Authenticates = ListDictionary_New(FALSE); + if (!response->Authenticates) - { - free(response); - return NULL; - } + goto fail; + + response->data = Stream_New(NULL, 2048); + + if (!response->data) + goto fail; ListDictionary_KeyObject(response->Authenticates)->fnObjectEquals = strings_equals_nocase; - ListDictionary_KeyObject(response->Authenticates)->fnObjectFree = string_free; - ListDictionary_ValueObject(response->Authenticates)->fnObjectEquals = strings_equals_nocase; - ListDictionary_ValueObject(response->Authenticates)->fnObjectFree = string_free; - return response; +fail: + http_response_free(response); + return NULL; } void http_response_free(HttpResponse* response) { - int i; - if (!response) return; - if (response->lines) - for (i = 0; i < response->count; i++) - free(response->lines[i]); - free(response->lines); - free(response->ReasonPhrase); - - free(response->ContentType); - ListDictionary_Free(response->Authenticates); - - if (response->BodyContent) - { - free(response->BodyContent); - response->BodyContent = NULL; - } - + Stream_Free(response->data, TRUE); free(response); } diff --git a/libfreerdp/core/gateway/http.h b/libfreerdp/core/gateway/http.h index 543be72..3e25818 100644 --- a/libfreerdp/core/gateway/http.h +++ b/libfreerdp/core/gateway/http.h @@ -42,6 +42,7 @@ struct _http_context char* Connection; char* Pragma; char* RdgConnectionId; + char* RdgAuthScheme; }; FREERDP_LOCAL BOOL http_context_set_method(HttpContext* context, @@ -61,6 +62,8 @@ FREERDP_LOCAL BOOL http_context_set_pragma(HttpContext* context, const char* Pragma); FREERDP_LOCAL BOOL http_context_set_rdg_connection_id(HttpContext* context, const char* RdgConnectionId); +FREERDP_LOCAL BOOL http_context_set_rdg_auth_scheme(HttpContext* context, + const char* RdgAuthScheme); HttpContext* http_context_new(void); void http_context_free(HttpContext* context); @@ -95,19 +98,20 @@ FREERDP_LOCAL void http_request_free(HttpRequest* request); struct _http_response { - int count; + size_t count; char** lines; - int StatusCode; - char* ReasonPhrase; + long StatusCode; + const char* ReasonPhrase; - int ContentLength; - char* ContentType; + size_t ContentLength; + const char* ContentType; - int BodyLength; + size_t BodyLength; BYTE* BodyContent; wListDictionary* Authenticates; + wStream* data; }; FREERDP_LOCAL void http_response_print(HttpResponse* response); diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c index f6f6801..d8fb8df 100644 --- a/libfreerdp/core/gateway/ncacn_http.c +++ b/libfreerdp/core/gateway/ncacn_http.c @@ -31,19 +31,18 @@ #define TAG FREERDP_TAG("core.gateway.ntlm") -wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, const char* method, int contentLength, SecBuffer* ntlmToken) +static wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, const char* method, + int contentLength, SecBuffer* ntlmToken) { wStream* s; HttpRequest* request; char* base64NtlmToken = NULL; - request = http_request_new(); if (ntlmToken) base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer); http_request_set_method(request, method); - request->ContentLength = contentLength; http_request_set_uri(request, http->URI); @@ -55,9 +54,7 @@ wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, const char* metho s = http_request_write(http, request); http_request_free(request); - free(base64NtlmToken); - return s; } @@ -69,24 +66,20 @@ int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc, RpcInChannel* inChannel) BOOL continueNeeded; rdpNtlm* ntlm = inChannel->ntlm; HttpContext* http = inChannel->http; - continueNeeded = ntlm_authenticate(ntlm); - contentLength = (continueNeeded) ? 0 : 0x40000000; - s = rpc_ntlm_http_request(rpc, http, "RPC_IN_DATA", contentLength, &ntlm->outputBuffer[0]); if (!s) return -1; status = rpc_in_channel_write(inChannel, Stream_Buffer(s), Stream_Length(s)); - Stream_Free(s, TRUE); - return (status > 0) ? 1 : -1; } -int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, RpcInChannel* inChannel, HttpResponse* response) +int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, RpcInChannel* inChannel, + HttpResponse* response) { char* token64 = NULL; int ntlmTokenLength = 0; @@ -121,12 +114,12 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel) freerdp* instance = context->instance; if (!settings->GatewayPassword || !settings->GatewayUsername || - !strlen(settings->GatewayPassword) || !strlen(settings->GatewayUsername)) + !strlen(settings->GatewayPassword) || !strlen(settings->GatewayUsername)) { if (instance->GatewayAuthenticate) { BOOL proceed = instance->GatewayAuthenticate(instance, &settings->GatewayUsername, - &settings->GatewayPassword, &settings->GatewayDomain); + &settings->GatewayPassword, &settings->GatewayDomain); if (!proceed) { @@ -139,18 +132,23 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel) if (settings->GatewayUsername) { free(settings->Username); + if (!(settings->Username = _strdup(settings->GatewayUsername))) return -1; } + if (settings->GatewayDomain) { free(settings->Domain); + if (!(settings->Domain = _strdup(settings->GatewayDomain))) return -1; } + if (settings->GatewayPassword) { free(settings->Password); + if (!(settings->Password = _strdup(settings->GatewayPassword))) return -1; } @@ -159,7 +157,7 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel) } if (!ntlm_client_init(ntlm, TRUE, settings->GatewayUsername, - settings->GatewayDomain, settings->GatewayPassword, tls->Bindings)) + settings->GatewayDomain, settings->GatewayPassword, tls->Bindings)) { return 0; } @@ -179,7 +177,8 @@ void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, RpcChannel* channel) channel->ntlm = NULL; } -int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChannel, BOOL replacement) +int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChannel, + BOOL replacement) { wStream* s; int status; @@ -187,7 +186,6 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChann BOOL continueNeeded; rdpNtlm* ntlm = outChannel->ntlm; HttpContext* http = outChannel->http; - continueNeeded = ntlm_authenticate(ntlm); if (!replacement) @@ -201,13 +199,12 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChann return -1; status = rpc_out_channel_write(outChannel, Stream_Buffer(s), Stream_Length(s)); - Stream_Free(s, TRUE); - return (status > 0) ? 1 : -1; } -int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, RpcOutChannel* outChannel, HttpResponse* response) +int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, RpcOutChannel* outChannel, + HttpResponse* response) { char* token64 = NULL; int ntlmTokenLength = 0; diff --git a/libfreerdp/core/gateway/ntlm.c b/libfreerdp/core/gateway/ntlm.c index 18dfc10..6def662 100644 --- a/libfreerdp/core/gateway/ntlm.c +++ b/libfreerdp/core/gateway/ntlm.c @@ -35,39 +35,36 @@ #define TAG FREERDP_TAG("core.gateway.ntlm") -BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* password, SecPkgContext_Bindings* Bindings) +BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* password, + SecPkgContext_Bindings* Bindings) { SECURITY_STATUS status; - ntlm->http = http; ntlm->Bindings = Bindings; - ntlm->table = InitSecurityInterfaceEx(0); if (!ntlm->table) return FALSE; sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password); - - status = ntlm->table->QuerySecurityPackageInfo(NTLMSP_NAME, &ntlm->pPackageInfo); + status = ntlm->table->QuerySecurityPackageInfo(NTLM_SSP_NAME, &ntlm->pPackageInfo); if (status != SEC_E_OK) { WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); return FALSE; } ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken; - - status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, - SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, - &ntlm->credentials, &ntlm->expiration); + status = ntlm->table->AcquireCredentialsHandle(NULL, NTLM_SSP_NAME, + SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, + &ntlm->credentials, &ntlm->expiration); if (status != SEC_E_OK) { WLog_ERR(TAG, "AcquireCredentialsHandle status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); return FALSE; } @@ -76,7 +73,6 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* ZeroMemory(&ntlm->inputBuffer, sizeof(SecBuffer)); ZeroMemory(&ntlm->outputBuffer, sizeof(SecBuffer)); ZeroMemory(&ntlm->ContextSizes, sizeof(SecPkgContext_Sizes)); - ntlm->fContextReq = 0; if (ntlm->http) @@ -87,12 +83,11 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* else { /** - * flags for RPC authentication: - * RPC_C_AUTHN_LEVEL_PKT_INTEGRITY: - * ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH | - * ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT - */ - + * flags for RPC authentication: + * RPC_C_AUTHN_LEVEL_PKT_INTEGRITY: + * ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH | + * ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT + */ ntlm->fContextReq |= ISC_REQ_USE_DCE_STYLE; ntlm->fContextReq |= ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH; ntlm->fContextReq |= ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT; @@ -106,7 +101,6 @@ BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, char* hostname) BOOL status = FALSE; DWORD SpnLength = 0; LPTSTR hostnameX = NULL; - #ifdef UNICODE ConvertToUnicode(CP_UTF8, 0, hostname, -1, (LPWSTR*) &hostnameX, 0); #else @@ -119,7 +113,6 @@ BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, char* hostname) if (!ServiceClass) { ntlm->ServicePrincipalName = (LPTSTR) _tcsdup(hostnameX); - free(hostnameX); if (!ntlm->ServicePrincipalName) @@ -136,14 +129,13 @@ BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, char* hostname) if (!ntlm->ServicePrincipalName) goto error; - if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName) != ERROR_SUCCESS) + if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, + ntlm->ServicePrincipalName) != ERROR_SUCCESS) goto error; status = TRUE; - error: free(hostnameX); - return status; } @@ -228,38 +220,38 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm) } status = ntlm->table->InitializeSecurityContext(&ntlm->credentials, - (ntlm->haveContext) ? &ntlm->context : NULL, - (ntlm->ServicePrincipalName) ? ntlm->ServicePrincipalName : NULL, - ntlm->fContextReq, 0, SECURITY_NATIVE_DREP, - (ntlm->haveInputBuffer) ? &ntlm->inputBufferDesc : NULL, - 0, &ntlm->context, &ntlm->outputBufferDesc, - &ntlm->pfContextAttr, &ntlm->expiration); - + (ntlm->haveContext) ? &ntlm->context : NULL, + (ntlm->ServicePrincipalName) ? ntlm->ServicePrincipalName : NULL, + ntlm->fContextReq, 0, SECURITY_NATIVE_DREP, + (ntlm->haveInputBuffer) ? &ntlm->inputBufferDesc : NULL, + 0, &ntlm->context, &ntlm->outputBufferDesc, + &ntlm->pfContextAttr, &ntlm->expiration); WLog_VRB(TAG, "InitializeSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); - if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK)) + if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || + (status == SEC_E_OK)) { if ((status != SEC_E_OK) && ntlm->table->CompleteAuthToken) { SECURITY_STATUS cStatus; - cStatus = ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc); if (cStatus != SEC_E_OK) { WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08"PRIX32"]", - GetSecurityStatusString(cStatus), cStatus); + GetSecurityStatusString(cStatus), cStatus); return FALSE; } } - status = ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes); + status = ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, + &ntlm->ContextSizes); if (status != SEC_E_OK) { WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); return FALSE; } @@ -277,7 +269,6 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm) ntlm->haveInputBuffer = TRUE; ntlm->haveContext = TRUE; - return (status == SEC_I_CONTINUE_NEEDED) ? TRUE : FALSE; } @@ -285,48 +276,48 @@ void ntlm_client_uninit(rdpNtlm* ntlm) { free(ntlm->identity.User); ntlm->identity.User = NULL; - free(ntlm->identity.Domain); ntlm->identity.Domain = NULL; - free(ntlm->identity.Password); ntlm->identity.Password = NULL; - free(ntlm->ServicePrincipalName); ntlm->ServicePrincipalName = NULL; if (ntlm->table) { SECURITY_STATUS status; - status = ntlm->table->FreeCredentialsHandle(&ntlm->credentials); + if (status != SEC_E_OK) { WLog_WARN(TAG, "FreeCredentialsHandle status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } + status = ntlm->table->FreeContextBuffer(ntlm->pPackageInfo); + if (status != SEC_E_OK) { WLog_WARN(TAG, "FreeContextBuffer status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } + status = ntlm->table->DeleteSecurityContext(&ntlm->context); + if (status != SEC_E_OK) { WLog_WARN(TAG, "DeleteSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } + ntlm->table = NULL; } } -rdpNtlm* ntlm_new() +rdpNtlm* ntlm_new(void) { rdpNtlm* ntlm; - ntlm = (rdpNtlm*) calloc(1, sizeof(rdpNtlm)); - return ntlm; } @@ -342,6 +333,5 @@ void ntlm_free(rdpNtlm* ntlm) } ntlm_client_uninit(ntlm); - free(ntlm); } diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c index 65e0bc2..ba71339 100644 --- a/libfreerdp/core/gateway/rdg.c +++ b/libfreerdp/core/gateway/rdg.c @@ -51,12 +51,11 @@ typedef struct rdg_packet_header #pragma pack(pop) -BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket) +static BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket) { int status; wStream* sChunk; char chunkSize[11]; - sprintf_s(chunkSize, sizeof(chunkSize), "%"PRIXz"\r\n", Stream_Length(sPacket)); sChunk = Stream_New(NULL, strlen(chunkSize) + Stream_Length(sPacket) + 2); @@ -67,7 +66,6 @@ BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket) Stream_Write(sChunk, Stream_Buffer(sPacket), Stream_Length(sPacket)); Stream_Write(sChunk, "\r\n", 2); Stream_SealLength(sChunk); - status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk)); Stream_Free(sChunk, TRUE); @@ -77,13 +75,12 @@ BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket) return TRUE; } -wStream* rdg_receive_packet(rdpRdg* rdg) +static wStream* rdg_receive_packet(rdpRdg* rdg) { int status; wStream* s; RdgPacketHeader* packet; UINT32 readCount = 0; - s = Stream_New(NULL, 1024); if (!s) @@ -111,6 +108,7 @@ wStream* rdg_receive_packet(rdpRdg* rdg) Stream_Free(s, TRUE); return NULL; } + packet = (RdgPacketHeader*) Stream_Buffer(s); } @@ -128,15 +126,13 @@ wStream* rdg_receive_packet(rdpRdg* rdg) } Stream_SealLength(s); - return s; } -BOOL rdg_send_handshake(rdpRdg* rdg) +static BOOL rdg_send_handshake(rdpRdg* rdg) { wStream* s; BOOL status; - s = Stream_New(NULL, 14); if (!s) @@ -145,14 +141,11 @@ BOOL rdg_send_handshake(rdpRdg* rdg) Stream_Write_UINT16(s, PKT_TYPE_HANDSHAKE_REQUEST); /* Type (2 bytes) */ Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */ Stream_Write_UINT32(s, 14); /* PacketLength (4 bytes) */ - Stream_Write_UINT8(s, 1); /* VersionMajor (1 byte) */ Stream_Write_UINT8(s, 0); /* VersionMinor (1 byte) */ Stream_Write_UINT16(s, 0); /* ClientVersion (2 bytes), must be 0 */ - Stream_Write_UINT16(s, 0); /* ExtendedAuthentication (2 bytes) */ - + Stream_Write_UINT16(s, rdg->extAuth); /* ExtendedAuthentication (2 bytes) */ Stream_SealLength(s); - status = rdg_write_packet(rdg, s); Stream_Free(s, TRUE); @@ -164,28 +157,58 @@ BOOL rdg_send_handshake(rdpRdg* rdg) return status; } -BOOL rdg_send_tunnel_request(rdpRdg* rdg) +static BOOL rdg_send_tunnel_request(rdpRdg* rdg) { wStream* s; BOOL status; + WCHAR* PAACookie = NULL; + UINT16 PAACookieLen = 0; - s = Stream_New(NULL, 16); + if (rdg->extAuth == HTTP_EXTENDED_AUTH_PAA) + { + PAACookieLen = ConvertToUnicode(CP_UTF8, 0, rdg->settings->GatewayAccessToken, -1, &PAACookie, 0); - if (!s) - return FALSE; + if (!PAACookie) + return FALSE; + + s = Stream_New(NULL, 16 + 2 + 2 * PAACookieLen); + + if (!s) + { + free(PAACookie); + return FALSE; + } + } + else + { + s = Stream_New(NULL, 16); + + if (!s) + return FALSE; + } Stream_Write_UINT16(s, PKT_TYPE_TUNNEL_CREATE); /* Type (2 bytes) */ Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */ Stream_Write_UINT32(s, 16); /* PacketLength (4 bytes) */ - Stream_Write_UINT32(s, HTTP_CAPABILITY_TYPE_QUAR_SOH); /* CapabilityFlags (4 bytes) */ - Stream_Write_UINT16(s, 0); /* FieldsPresent (2 bytes) */ - Stream_Write_UINT16(s, 0); /* Reserved (2 bytes), must be 0 */ + + if (rdg->extAuth == HTTP_EXTENDED_AUTH_PAA) + { + Stream_Write_UINT16(s, 1); /* FieldsPresent (2 bytes) */ + Stream_Write_UINT16(s, 0); /* Reserved (2 bytes), must be 0 */ + Stream_Write_UINT16(s, PAACookieLen * 2); /* PAA cookie string length */ + Stream_Write_UTF16_String(s, PAACookie, PAACookieLen); + } + else + { + Stream_Write_UINT16(s, 0); /* FieldsPresent (2 bytes) */ + Stream_Write_UINT16(s, 0); /* Reserved (2 bytes), must be 0 */ + } Stream_SealLength(s); - status = rdg_write_packet(rdg, s); Stream_Free(s, TRUE); + free(PAACookie); if (status) { @@ -195,7 +218,7 @@ BOOL rdg_send_tunnel_request(rdpRdg* rdg) return status; } -BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) +static BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) { int i; wStream* s; @@ -203,8 +226,8 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) WCHAR* clientName = NULL; UINT16 clientNameLen; UINT32 packetSize; - clientNameLen = ConvertToUnicode(CP_UTF8, 0, rdg->settings->ClientHostname, -1, &clientName, 0); + if (!clientName) return FALSE; @@ -220,7 +243,6 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) Stream_Write_UINT16(s, PKT_TYPE_TUNNEL_AUTH); /* Type (2 bytes) */ Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */ Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */ - Stream_Write_UINT16(s, 0); /* FieldsPresent (2 bytes) */ Stream_Write_UINT16(s, clientNameLen * 2); /* Client name string length */ @@ -228,9 +250,7 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) Stream_Write_UINT16(s, clientName[i]); Stream_SealLength(s); - status = rdg_write_packet(rdg, s); - Stream_Free(s, TRUE); free(clientName); @@ -242,7 +262,7 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) return status; } -BOOL rdg_send_channel_create(rdpRdg* rdg) +static BOOL rdg_send_channel_create(rdpRdg* rdg) { int i; wStream* s; @@ -250,7 +270,6 @@ BOOL rdg_send_channel_create(rdpRdg* rdg) char* serverName = rdg->settings->ServerHostname; UINT16 serverNameLen = strlen(serverName) + 1; UINT32 packetSize = 16 + serverNameLen * 2; - s = Stream_New(NULL, packetSize); if (!s) @@ -259,7 +278,6 @@ BOOL rdg_send_channel_create(rdpRdg* rdg) Stream_Write_UINT16(s, PKT_TYPE_CHANNEL_CREATE); /* Type (2 bytes) */ Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */ Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */ - Stream_Write_UINT8(s, 1); /* Number of resources. (1 byte) */ Stream_Write_UINT8(s, 0); /* Number of alternative resources (1 byte) */ Stream_Write_UINT16(s, rdg->settings->ServerPort); /* Resource port (2 bytes) */ @@ -272,9 +290,7 @@ BOOL rdg_send_channel_create(rdpRdg* rdg) } Stream_SealLength(s); - status = rdg_write_packet(rdg, s); - Stream_Free(s, TRUE); if (status) @@ -285,15 +301,13 @@ BOOL rdg_send_channel_create(rdpRdg* rdg) return status; } -wStream* rdg_build_http_request(rdpRdg* rdg, char* method) +static wStream* rdg_build_http_request(rdpRdg* rdg, char* method) { wStream* s; HttpRequest* request = NULL; SecBuffer* ntlmToken = NULL; char* base64NtlmToken = NULL; - assert(method != NULL); - request = http_request_new(); if (!request) @@ -316,7 +330,6 @@ wStream* rdg_build_http_request(rdpRdg* rdg, char* method) { http_request_set_auth_scheme(request, "NTLM"); http_request_set_auth_param(request, base64NtlmToken); - free(base64NtlmToken); if (!request->AuthScheme || !request->AuthParam) @@ -338,7 +351,7 @@ wStream* rdg_build_http_request(rdpRdg* rdg, char* method) return s; } -BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response) +static BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response) { int status; wStream* s; @@ -347,6 +360,36 @@ BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response) BYTE* ntlmTokenData = NULL; rdpNtlm* ntlm = rdg->ntlm; + if (rdg->extAuth == HTTP_EXTENDED_AUTH_PAA) + { + if (response->StatusCode == HTTP_STATUS_OK) + { + rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZED; + /* + packet trace shows additional 10 bytes with value 0xabcdabcdabcdabcdabcd + which is not a normal header + data format + can't find any documentation on how to handle, chose to just read an extra 10 bytes + */ + s = Stream_New(NULL, 10); + + if (!s) + return FALSE; + + status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), 10); + Stream_Free(s, TRUE); + + if (status <= 0) + return FALSE; + + return TRUE; + } + else + { + /* fallback to regular authentication scheme */ + rdg->extAuth = HTTP_EXTENDED_AUTH_NONE; + } + } + if (response->StatusCode != HTTP_STATUS_DENIED) { WLog_DBG(TAG, "RDG not supported"); @@ -375,16 +418,13 @@ BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response) } ntlm_authenticate(ntlm); - s = rdg_build_http_request(rdg, "RDG_OUT_DATA"); if (!s) return FALSE; status = tls_write_all(rdg->tlsOut, Stream_Buffer(s), Stream_Length(s)); - Stream_Free(s, TRUE); - ntlm_free(rdg->ntlm); rdg->ntlm = NULL; @@ -392,11 +432,10 @@ BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response) return FALSE; rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE; - return TRUE; } -BOOL rdg_process_out_channel_authorization(rdpRdg* rdg, HttpResponse* response) +static BOOL rdg_process_out_channel_authorization(rdpRdg* rdg, HttpResponse* response) { if (response->StatusCode != HTTP_STATUS_OK) { @@ -406,11 +445,10 @@ BOOL rdg_process_out_channel_authorization(rdpRdg* rdg, HttpResponse* response) WLog_DBG(TAG, "Out Channel authorization complete"); rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZED; - return TRUE; } -BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response) +static BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response) { int status; wStream* s; @@ -419,6 +457,31 @@ BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response) BYTE* ntlmTokenData = NULL; rdpNtlm* ntlm = rdg->ntlm; + if (rdg->extAuth == HTTP_EXTENDED_AUTH_PAA) + { + if (response->StatusCode == HTTP_STATUS_OK) + { + rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED; + /* send http headers again */ + s = rdg_build_http_request(rdg, "RDG_IN_DATA"); + + if (!s) + return FALSE; + + status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s)); + Stream_Free(s, TRUE); + + if (status < 0) + return FALSE; + + return TRUE; + } + else + { + rdg->extAuth = HTTP_EXTENDED_AUTH_NONE; + } + } + WLog_DBG(TAG, "In Channel authorization required"); if (ListDictionary_Contains(response->Authenticates, "NTLM")) @@ -440,16 +503,13 @@ BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response) } ntlm_authenticate(ntlm); - s = rdg_build_http_request(rdg, "RDG_IN_DATA"); if (!s) return FALSE; status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s)); - Stream_Free(s, TRUE); - ntlm_free(rdg->ntlm); rdg->ntlm = NULL; @@ -457,11 +517,10 @@ BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response) return FALSE; rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE; - return TRUE; } -BOOL rdg_process_in_channel_authorization(rdpRdg* rdg, HttpResponse* response) +static BOOL rdg_process_in_channel_authorization(rdpRdg* rdg, HttpResponse* response) { wStream* s; int status; @@ -474,14 +533,12 @@ BOOL rdg_process_in_channel_authorization(rdpRdg* rdg, HttpResponse* response) WLog_DBG(TAG, "In Channel authorization complete"); rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED; - s = rdg_build_http_request(rdg, "RDG_IN_DATA"); if (!s) return FALSE; status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s)); - Stream_Free(s, TRUE); if (status <= 0) @@ -490,10 +547,9 @@ BOOL rdg_process_in_channel_authorization(rdpRdg* rdg, HttpResponse* response) return TRUE; } -BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s) +static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s) { HRESULT errorCode; - WLog_DBG(TAG, "Handshake response received"); if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE) @@ -516,10 +572,9 @@ BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s) return rdg_send_tunnel_request(rdg); } -BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s) +static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s) { HRESULT errorCode; - WLog_DBG(TAG, "Tunnel response received"); if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE) @@ -542,10 +597,9 @@ BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s) return rdg_send_tunnel_authorization(rdg); } -BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s) +static BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s) { HRESULT errorCode; - WLog_DBG(TAG, "Tunnel authorization received"); if (rdg->state != RDG_CLIENT_STATE_TUNNEL_AUTHORIZE) @@ -568,10 +622,9 @@ BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s) return rdg_send_channel_create(rdg); } -BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s) +static BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s) { HRESULT errorCode; - WLog_DBG(TAG, "Channel response received"); if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE) @@ -592,15 +645,13 @@ BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s) } rdg->state = RDG_CLIENT_STATE_OPENED; - return TRUE; } -BOOL rdg_process_packet(rdpRdg* rdg, wStream* s) +static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s) { BOOL status = TRUE; UINT16 type; - Stream_SetPosition(s, 0); if (Stream_GetRemainingLength(s) < 2) @@ -634,8 +685,7 @@ BOOL rdg_process_packet(rdpRdg* rdg, wStream* s) return status; } - -BOOL rdg_out_channel_recv(rdpRdg* rdg) +static BOOL rdg_out_channel_recv(rdpRdg* rdg) { wStream* s; BOOL status = TRUE; @@ -645,26 +695,27 @@ BOOL rdg_out_channel_recv(rdpRdg* rdg) { case RDG_CLIENT_STATE_OUT_CHANNEL_REQUEST: response = http_response_recv(rdg->tlsOut); + if (!response) - { return FALSE; - } + status = rdg_process_out_channel_response(rdg, response); http_response_free(response); break; case RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE: response = http_response_recv(rdg->tlsOut); + if (!response) - { return FALSE; - } + status = rdg_process_out_channel_authorization(rdg, response); http_response_free(response); break; default: s = rdg_receive_packet(rdg); + if (s) { status = rdg_process_packet(rdg, s); @@ -675,7 +726,7 @@ BOOL rdg_out_channel_recv(rdpRdg* rdg) return status; } -BOOL rdg_in_channel_recv(rdpRdg* rdg) +static BOOL rdg_in_channel_recv(rdpRdg* rdg) { BOOL status = TRUE; HttpResponse* response = NULL; @@ -709,7 +760,6 @@ BOOL rdg_in_channel_recv(rdpRdg* rdg) DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count) { DWORD nCount = 0; - assert(rdg != NULL); if (events && (nCount < count)) @@ -742,12 +792,10 @@ DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count) return nCount; } -BOOL rdg_check_event_handles(rdpRdg* rdg) +static BOOL rdg_check_event_handles(rdpRdg* rdg) { HANDLE event = NULL; - assert(rdg != NULL); - BIO_get_event(rdg->tlsOut->bio, &event); if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0) @@ -765,18 +813,20 @@ BOOL rdg_check_event_handles(rdpRdg* rdg) return TRUE; } -BOOL rdg_ncacn_http_ntlm_init(rdpRdg* rdg, rdpTls* tls) +static BOOL rdg_ncacn_http_ntlm_init(rdpRdg* rdg, rdpTls* tls) { rdpNtlm* ntlm = rdg->ntlm; rdpContext* context = rdg->context; rdpSettings* settings = context->settings; freerdp* instance = context->instance; - if (!settings->GatewayPassword || !settings->GatewayUsername || !strlen(settings->GatewayPassword) || !strlen(settings->GatewayUsername)) + if (!settings->GatewayPassword || !settings->GatewayUsername || + !strlen(settings->GatewayPassword) || !strlen(settings->GatewayUsername)) { if (instance->GatewayAuthenticate) { - BOOL proceed = instance->GatewayAuthenticate(instance, &settings->GatewayUsername, &settings->GatewayPassword, &settings->GatewayDomain); + BOOL proceed = instance->GatewayAuthenticate(instance, &settings->GatewayUsername, + &settings->GatewayPassword, &settings->GatewayDomain); if (!proceed) { @@ -789,18 +839,23 @@ BOOL rdg_ncacn_http_ntlm_init(rdpRdg* rdg, rdpTls* tls) if (settings->GatewayUsername) { free(settings->Username); + if (!(settings->Username = _strdup(settings->GatewayUsername))) return FALSE; } + if (settings->GatewayDomain) { free(settings->Domain); + if (!(settings->Domain = _strdup(settings->GatewayDomain))) return FALSE; } + if (settings->GatewayPassword) { free(settings->Password); + if (!(settings->Password = _strdup(settings->GatewayPassword))) return FALSE; } @@ -808,7 +863,8 @@ BOOL rdg_ncacn_http_ntlm_init(rdpRdg* rdg, rdpTls* tls) } } - if (!ntlm_client_init(ntlm, TRUE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword, tls->Bindings)) + if (!ntlm_client_init(ntlm, TRUE, settings->GatewayUsername, settings->GatewayDomain, + settings->GatewayPassword, tls->Bindings)) { return FALSE; } @@ -821,25 +877,29 @@ BOOL rdg_ncacn_http_ntlm_init(rdpRdg* rdg, rdpTls* tls) return TRUE; } -BOOL rdg_send_out_channel_request(rdpRdg*rdg) +static BOOL rdg_send_out_channel_request(rdpRdg* rdg) { wStream* s = NULL; int status; + rdg->ntlm = NULL; - rdg->ntlm = ntlm_new(); + if (rdg->extAuth == HTTP_EXTENDED_AUTH_NONE) + { + rdg->ntlm = ntlm_new(); - if (!rdg->ntlm) - return FALSE; + if (!rdg->ntlm) + return FALSE; - status = rdg_ncacn_http_ntlm_init(rdg, rdg->tlsOut); + status = rdg_ncacn_http_ntlm_init(rdg, rdg->tlsOut); - if (!status) - return FALSE; + if (!status) + return FALSE; - status = ntlm_authenticate(rdg->ntlm); + status = ntlm_authenticate(rdg->ntlm); - if (!status) - return FALSE; + if (!status) + return FALSE; + } s = rdg_build_http_request(rdg, "RDG_OUT_DATA"); @@ -847,36 +907,38 @@ BOOL rdg_send_out_channel_request(rdpRdg*rdg) return FALSE; status = tls_write_all(rdg->tlsOut, Stream_Buffer(s), Stream_Length(s)); - Stream_Free(s, TRUE); if (status < 0) return FALSE; rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_REQUEST; - return TRUE; } -BOOL rdg_send_in_channel_request(rdpRdg*rdg) +static BOOL rdg_send_in_channel_request(rdpRdg* rdg) { int status; wStream* s = NULL; + rdg->ntlm = NULL; - rdg->ntlm = ntlm_new(); + if (rdg->extAuth == HTTP_EXTENDED_AUTH_NONE) + { + rdg->ntlm = ntlm_new(); - if (!rdg->ntlm) - return FALSE; + if (!rdg->ntlm) + return FALSE; - status = rdg_ncacn_http_ntlm_init(rdg, rdg->tlsIn); + status = rdg_ncacn_http_ntlm_init(rdg, rdg->tlsIn); - if (!status) - return FALSE; + if (!status) + return FALSE; - status = ntlm_authenticate(rdg->ntlm); + status = ntlm_authenticate(rdg->ntlm); - if (!status) - return FALSE; + if (!status) + return FALSE; + } s = rdg_build_http_request(rdg, "RDG_IN_DATA"); @@ -884,32 +946,28 @@ BOOL rdg_send_in_channel_request(rdpRdg*rdg) return FALSE; status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s)); - Stream_Free(s, TRUE); if (status < 0) return FALSE; rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_REQUEST; - return TRUE; } -BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) +static BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) { int sockfd = 0; int status = 0; BIO* socketBio = NULL; BIO* bufferedBio = NULL; rdpSettings* settings = rdg->settings; - const char *peerHostname = settings->GatewayHostname; + const char* peerHostname = settings->GatewayHostname; UINT16 peerPort = settings->GatewayPort; BOOL isProxyConnection = proxy_prepare(settings, &peerHostname, &peerPort, TRUE); - assert(hostname != NULL); - sockfd = freerdp_tcp_connect(rdg->context, settings, peerHostname, - peerPort, timeout); + peerPort, timeout); if (sockfd < 1) { @@ -936,7 +994,8 @@ BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int tim bufferedBio = BIO_push(bufferedBio, socketBio); status = BIO_set_nonblock(bufferedBio, TRUE); - if (isProxyConnection) { + if (isProxyConnection) + { if (!proxy_connect(settings, bufferedBio, settings->GatewayHostname, settings->GatewayPort)) return FALSE; } @@ -960,27 +1019,27 @@ BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int tim return TRUE; } -BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) +static BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) { int sockfd = 0; int status = 0; BIO* socketBio = NULL; BIO* bufferedBio = NULL; rdpSettings* settings = rdg->settings; - const char *peerHostname = settings->GatewayHostname; + const char* peerHostname = settings->GatewayHostname; int peerPort = settings->GatewayPort; BOOL isProxyConnection = FALSE; - assert(hostname != NULL); - if (settings->ProxyType) { + if (settings->ProxyType) + { peerHostname = settings->ProxyHostname; peerPort = settings->ProxyPort; isProxyConnection = TRUE; } sockfd = freerdp_tcp_connect(rdg->context, settings, peerHostname, - peerPort, timeout); + peerPort, timeout); if (sockfd < 1) return FALSE; @@ -1024,14 +1083,12 @@ BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int time return TRUE; } -BOOL rdg_out_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) +static BOOL rdg_out_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) { BOOL status; DWORD nCount; HANDLE events[8]; - assert(hostname != NULL); - status = rdg_tls_out_connect(rdg, hostname, port, timeout); if (!status) @@ -1062,14 +1119,12 @@ BOOL rdg_out_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int return TRUE; } -BOOL rdg_in_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) +static BOOL rdg_in_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) { BOOL status; DWORD nCount; HANDLE events[8]; - assert(hostname != NULL); - status = rdg_tls_in_connect(rdg, hostname, port, timeout); if (!status) @@ -1100,14 +1155,12 @@ BOOL rdg_in_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int return TRUE; } -BOOL rdg_tunnel_connect(rdpRdg* rdg) +static BOOL rdg_tunnel_connect(rdpRdg* rdg) { BOOL status; DWORD nCount; HANDLE events[8]; - rdg_send_handshake(rdg); - nCount = rdg_get_event_handles(rdg, events, 8); if (nCount == 0) @@ -1131,9 +1184,7 @@ BOOL rdg_tunnel_connect(rdpRdg* rdg) BOOL rdg_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) { BOOL status; - assert(rdg != NULL); - status = rdg_out_channel_connect(rdg, hostname, port, timeout); if (!status) @@ -1152,7 +1203,7 @@ BOOL rdg_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) return TRUE; } -int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size) +static int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size) { int status; wStream* sChunk; @@ -1163,24 +1214,19 @@ int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size) return 0; sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize); - sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2); if (!sChunk) return -1; Stream_Write(sChunk, chunkSize, strlen(chunkSize)); - Stream_Write_UINT16(sChunk, PKT_TYPE_DATA); /* Type */ Stream_Write_UINT16(sChunk, 0); /* Reserved */ Stream_Write_UINT32(sChunk, packetSize); /* Packet length */ - Stream_Write_UINT16(sChunk, size); /* Data size */ Stream_Write(sChunk, buf, size); /* Data */ - Stream_Write(sChunk, "\r\n", 2); Stream_SealLength(sChunk); - status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk)); Stream_Free(sChunk, TRUE); @@ -1190,79 +1236,65 @@ int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size) return size; } -BOOL rdg_process_close_packet(rdpRdg* rdg) +static BOOL rdg_process_close_packet(rdpRdg* rdg) { int status; wStream* sChunk; int packetSize = 12; char chunkSize[11]; - sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize); - sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2); - + if (!sChunk) return FALSE; - + Stream_Write(sChunk, chunkSize, strlen(chunkSize)); - Stream_Write_UINT16(sChunk, PKT_TYPE_CLOSE_CHANNEL_RESPONSE); /* Type */ Stream_Write_UINT16(sChunk, 0); /* Reserved */ Stream_Write_UINT32(sChunk, packetSize); /* Packet length */ - Stream_Write_UINT32(sChunk, 0); /* Status code */ - Stream_Write(sChunk, "\r\n", 2); Stream_SealLength(sChunk); - status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk)); Stream_Free(sChunk, TRUE); - return (status < 0 ? FALSE : TRUE); } -BOOL rdg_process_keep_alive_packet(rdpRdg* rdg) +static BOOL rdg_process_keep_alive_packet(rdpRdg* rdg) { int status; wStream* sChunk; int packetSize = 8; char chunkSize[11]; - sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize); - sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2); - + if (!sChunk) return FALSE; - + Stream_Write(sChunk, chunkSize, strlen(chunkSize)); - Stream_Write_UINT16(sChunk, PKT_TYPE_KEEPALIVE); /* Type */ Stream_Write_UINT16(sChunk, 0); /* Reserved */ Stream_Write_UINT32(sChunk, packetSize); /* Packet length */ - Stream_Write(sChunk, "\r\n", 2); Stream_SealLength(sChunk); - status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk)); Stream_Free(sChunk, TRUE); - return (status < 0 ? FALSE : TRUE); } -BOOL rdg_process_unknown_packet(rdpRdg* rdg, int type) +static BOOL rdg_process_unknown_packet(rdpRdg* rdg, int type) { WLog_WARN(TAG, "Unknown Control Packet received: %X", type); - return TRUE; } -BOOL rdg_process_control_packet(rdpRdg* rdg, int type, int packetLength) +static BOOL rdg_process_control_packet(rdpRdg* rdg, int type, size_t packetLength) { wStream* s = NULL; - int readCount = 0; + size_t readCount = 0; int status; - int payloadSize = packetLength - sizeof(RdgPacketHeader); + size_t payloadSize = packetLength - sizeof(RdgPacketHeader); if (payloadSize) { @@ -1282,6 +1314,7 @@ BOOL rdg_process_control_packet(rdpRdg* rdg, int type, int packetLength) Stream_Free(s, TRUE); return FALSE; } + continue; } @@ -1303,21 +1336,20 @@ BOOL rdg_process_control_packet(rdpRdg* rdg, int type, int packetLength) status = rdg_process_keep_alive_packet(rdg); LeaveCriticalSection(&rdg->writeSection); break; - + default: status = rdg_process_unknown_packet(rdg, type); break; } Stream_Free(s, TRUE); - return status; } -int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) +static int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) { RdgPacketHeader header; - int readCount = 0; + size_t readCount = 0; int readSize; int status; int pending; @@ -1326,18 +1358,17 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) { while (readCount < sizeof(RdgPacketHeader)) { - status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount, sizeof(RdgPacketHeader) - readCount); + status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount, + sizeof(RdgPacketHeader) - readCount); if (status <= 0) { if (!BIO_should_retry(rdg->tlsOut->bio)) - { return -1; - } + if (!readCount) - { return 0; - } + BIO_wait_read(rdg->tlsOut->bio, 50); continue; } @@ -1348,10 +1379,10 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) if (header.type != PKT_TYPE_DATA) { status = rdg_process_control_packet(rdg, header.type, header.packetLength); + if (!status) - { return -1; - } + return 0; } @@ -1364,9 +1395,8 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) if (status < 0) { if (!BIO_should_retry(rdg->tlsOut->bio)) - { return -1; - } + BIO_wait_read(rdg->tlsOut->bio, 50); continue; } @@ -1376,7 +1406,6 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) } readSize = (rdg->packetRemainingCount < size ? rdg->packetRemainingCount : size); - status = BIO_read(rdg->tlsOut->bio, buffer, readSize); if (status <= 0) @@ -1385,11 +1414,11 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) { return -1; } + return 0; } rdg->packetRemainingCount -= status; - pending = BIO_pending(rdg->tlsOut->bio); if (pending > 0) @@ -1400,18 +1429,11 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) return status; } -long rdg_bio_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret) -{ - return 1; -} - static int rdg_bio_write(BIO* bio, const char* buf, int num) { int status; rdpRdg* rdg = (rdpRdg*) BIO_get_data(bio); - BIO_clear_flags(bio, BIO_FLAGS_WRITE); - EnterCriticalSection(&rdg->writeSection); status = rdg_write_data_packet(rdg, (BYTE*) buf, num); LeaveCriticalSection(&rdg->writeSection); @@ -1438,7 +1460,6 @@ static int rdg_bio_read(BIO* bio, char* buf, int size) { int status; rdpRdg* rdg = (rdpRdg*) BIO_get_data(bio); - status = rdg_read_data_packet(rdg, (BYTE*) buf, size); if (status < 0) @@ -1545,7 +1566,7 @@ static int rdg_bio_free(BIO* bio) return 1; } -BIO_METHOD* BIO_s_rdg(void) +static BIO_METHOD* BIO_s_rdg(void) { static BIO_METHOD* bio_methods = NULL; @@ -1572,9 +1593,7 @@ rdpRdg* rdg_new(rdpTransport* transport) RPC_CSTR stringUuid; char bracedUuid[40]; RPC_STATUS rpcStatus; - assert(transport != NULL); - rdg = (rdpRdg*) calloc(1, sizeof(rdpRdg)); if (rdg) @@ -1582,9 +1601,12 @@ rdpRdg* rdg_new(rdpTransport* transport) rdg->state = RDG_CLIENT_STATE_INITIAL; rdg->context = transport->context; rdg->settings = rdg->context->settings; + rdg->extAuth = HTTP_EXTENDED_AUTH_NONE; + + if (rdg->settings->GatewayAccessToken) + rdg->extAuth = HTTP_EXTENDED_AUTH_PAA; UuidCreate(&rdg->guid); - rpcStatus = UuidToStringA(&rdg->guid, &stringUuid); if (rpcStatus == RPC_S_OUT_OF_MEMORY) @@ -1592,7 +1614,6 @@ rdpRdg* rdg_new(rdpTransport* transport) sprintf_s(bracedUuid, sizeof(bracedUuid), "{%s}", stringUuid); RpcStringFreeA(&stringUuid); - rdg->tlsOut = tls_new(rdg->settings); if (!rdg->tlsOut) @@ -1618,29 +1639,44 @@ rdpRdg* rdg_new(rdpTransport* transport) http_context_set_rdg_connection_id(rdg->http, bracedUuid); if (!rdg->http->URI || !rdg->http->Accept || !rdg->http->CacheControl || - !rdg->http->Pragma || !rdg->http->Connection || !rdg->http->UserAgent - || !rdg->http->Host || !rdg->http->RdgConnectionId) + !rdg->http->Pragma || !rdg->http->Connection || !rdg->http->UserAgent + || !rdg->http->Host || !rdg->http->RdgConnectionId) { goto rdg_alloc_error; } + if (rdg->extAuth != HTTP_EXTENDED_AUTH_NONE) + { + switch (rdg->extAuth) + { + case HTTP_EXTENDED_AUTH_PAA: + http_context_set_rdg_auth_scheme(rdg->http, "PAA"); + + if (!rdg->http->RdgAuthScheme) + goto rdg_alloc_error; + + break; + + default: + WLog_DBG(TAG, "RDG extended authentication method %d not supported", rdg->extAuth); + } + } + rdg->frontBio = BIO_new(BIO_s_rdg()); if (!rdg->frontBio) goto rdg_alloc_error; BIO_set_data(rdg->frontBio, rdg); - rdg->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!rdg->readEvent) goto rdg_alloc_error; - + InitializeCriticalSection(&rdg->writeSection); } return rdg; - rdg_alloc_error: rdg_free(rdg); return NULL; @@ -1680,8 +1716,7 @@ void rdg_free(rdpRdg* rdg) CloseHandle(rdg->readEvent); rdg->readEvent = NULL; } - - DeleteCriticalSection(&rdg->writeSection); + DeleteCriticalSection(&rdg->writeSection); free(rdg); } diff --git a/libfreerdp/core/gateway/rdg.h b/libfreerdp/core/gateway/rdg.h index 8eca518..9a52012 100644 --- a/libfreerdp/core/gateway/rdg.h +++ b/libfreerdp/core/gateway/rdg.h @@ -50,6 +50,7 @@ typedef struct rdp_rdg rdpRdg; #define HTTP_EXTENDED_AUTH_NONE 0x0 #define HTTP_EXTENDED_AUTH_SC 0x1 /* Smart card authentication. */ #define HTTP_EXTENDED_AUTH_PAA 0x02 /* Pluggable authentication. */ +#define HTTP_EXTENDED_AUTH_SSPI_NTLM 0x04 /* NTLM extended authentication. */ /* HTTP packet types. */ #define PKT_TYPE_HANDSHAKE_REQUEST 0x1 @@ -140,6 +141,7 @@ struct rdp_rdg int state; UINT16 packetRemainingCount; int timeout; + UINT16 extAuth; }; @@ -150,7 +152,6 @@ FREERDP_LOCAL BOOL rdg_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout); FREERDP_LOCAL DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count); -FREERDP_LOCAL BOOL rdg_check_event_handles(rdpRdg* rdg); #endif /* FREERDP_LIB_CORE_GATEWAY_RDG_H */ diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c index 22b865b..5c06d42 100644 --- a/libfreerdp/core/gateway/rpc.c +++ b/libfreerdp/core/gateway/rpc.c @@ -51,10 +51,10 @@ /* Security Verification Trailer Signature */ -rpc_sec_verification_trailer RPC_SEC_VERIFICATION_TRAILER = +static const rpc_sec_verification_trailer RPC_SEC_VERIFICATION_TRAILER = { { 0x8a, 0xe3, 0x13, 0x71, 0x02, 0xf4, 0x36, 0x71 } }; -static char* PTYPE_STRINGS[] = +static const char* PTYPE_STRINGS[] = { "PTYPE_REQUEST", "PTYPE_PING", @@ -80,7 +80,7 @@ static char* PTYPE_STRINGS[] = "" }; -const RPC_SECURITY_PROVIDER_INFO RPC_SECURITY_PROVIDER_INFO_TABLE[] = +static const RPC_SECURITY_PROVIDER_INFO RPC_SECURITY_PROVIDER_INFO_TABLE[] = { { RPC_C_AUTHN_NONE, TRUE, -1 }, { RPC_C_AUTHN_GSS_NEGOTIATE, TRUE, -1 }, @@ -153,8 +153,8 @@ void rpc_pdu_header_print(rpcconn_hdr_t* header) WLog_INFO(TAG, " }"); WLog_INFO(TAG, "packed_drep[4]: %02"PRIX8" %02"PRIX8" %02"PRIX8" %02"PRIX8"", - header->common.packed_drep[0], header->common.packed_drep[1], - header->common.packed_drep[2], header->common.packed_drep[3]); + header->common.packed_drep[0], header->common.packed_drep[1], + header->common.packed_drep[2], header->common.packed_drep[3]); WLog_INFO(TAG, "frag_length: %"PRIu16"", header->common.frag_length); WLog_INFO(TAG, "auth_length: %"PRIu16"", header->common.auth_length); WLog_INFO(TAG, "call_id: %"PRIu32"", header->common.call_id); @@ -277,7 +277,6 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l UINT32 auth_pad_length; UINT32 sec_trailer_offset; rpc_sec_trailer* sec_trailer; - *offset = RPC_COMMON_FIELDS_LENGTH; header = ((rpcconn_hdr_t*) buffer); @@ -320,12 +319,12 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l sec_trailer_offset = frag_length - auth_length - 8; sec_trailer = (rpc_sec_trailer*) &buffer[sec_trailer_offset]; auth_pad_length = sec_trailer->auth_pad_length; - #if 0 - WLog_DBG(TAG, "sec_trailer: type: %"PRIu8" level: %"PRIu8" pad_length: %"PRIu8" reserved: %"PRIu8" context_id: %"PRIu32"", - sec_trailer->auth_type, sec_trailer->auth_level, - sec_trailer->auth_pad_length, sec_trailer->auth_reserved, - sec_trailer->auth_context_id); + WLog_DBG(TAG, + "sec_trailer: type: %"PRIu8" level: %"PRIu8" pad_length: %"PRIu8" reserved: %"PRIu8" context_id: %"PRIu32"", + sec_trailer->auth_type, sec_trailer->auth_level, + sec_trailer->auth_pad_length, sec_trailer->auth_reserved, + sec_trailer->auth_context_id); #endif /** @@ -337,7 +336,7 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l if ((frag_length - (sec_trailer_offset + 8)) != auth_length) { WLog_ERR(TAG, "invalid auth_length: actual: %"PRIu32", expected: %"PRIu32"", auth_length, - (frag_length - (sec_trailer_offset + 8))); + (frag_length - (sec_trailer_offset + 8))); } *length = frag_length - auth_length - 24 - 8 - auth_pad_length; @@ -347,7 +346,6 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l int rpc_out_channel_read(RpcOutChannel* outChannel, BYTE* data, int length) { int status; - status = BIO_read(outChannel->tls->bio, data, length); if (status > 0) @@ -367,18 +365,14 @@ int rpc_out_channel_read(RpcOutChannel* outChannel, BYTE* data, int length) int rpc_in_channel_write(RpcInChannel* inChannel, const BYTE* data, int length) { int status; - status = tls_write_all(inChannel->tls, data, length); - return status; } int rpc_out_channel_write(RpcOutChannel* outChannel, const BYTE* data, int length) { int status; - status = tls_write_all(outChannel->tls, data, length); - return status; } @@ -420,14 +414,12 @@ int rpc_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNE inChannel->State = state; WLog_DBG(TAG, "%s", str); - return status; } -int rpc_in_channel_rpch_init(rdpRpc* rpc, RpcInChannel* inChannel) +static int rpc_in_channel_rpch_init(rdpRpc* rpc, RpcInChannel* inChannel) { HttpContext* http; - inChannel->ntlm = ntlm_new(); if (!inChannel->ntlm) @@ -439,25 +431,20 @@ int rpc_in_channel_rpch_init(rdpRpc* rpc, RpcInChannel* inChannel) return -1; http = inChannel->http; - http_context_set_method(http, "RPC_IN_DATA"); - http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388"); http_context_set_accept(http, "application/rpc"); http_context_set_cache_control(http, "no-cache"); http_context_set_connection(http, "Keep-Alive"); http_context_set_user_agent(http, "MSRPC"); http_context_set_host(http, rpc->settings->GatewayHostname); - http_context_set_pragma(http, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"); - return 1; } -int rpc_in_channel_init(rdpRpc* rpc, RpcInChannel* inChannel) +static int rpc_in_channel_init(rdpRpc* rpc, RpcInChannel* inChannel) { rts_generate_cookie((BYTE*) &inChannel->Cookie); - inChannel->rpc = rpc; inChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL; inChannel->BytesSent = 0; @@ -471,7 +458,7 @@ int rpc_in_channel_init(rdpRpc* rpc, RpcInChannel* inChannel) return 1; } -void rpc_in_channel_rpch_uninit(RpcInChannel* inChannel) +static void rpc_in_channel_rpch_uninit(RpcInChannel* inChannel) { if (inChannel->ntlm) { @@ -486,10 +473,9 @@ void rpc_in_channel_rpch_uninit(RpcInChannel* inChannel) } } -RpcInChannel* rpc_in_channel_new(rdpRpc* rpc) +static RpcInChannel* rpc_in_channel_new(rdpRpc* rpc) { RpcInChannel* inChannel = NULL; - inChannel = (RpcInChannel*) calloc(1, sizeof(RpcInChannel)); if (inChannel) @@ -500,7 +486,7 @@ RpcInChannel* rpc_in_channel_new(rdpRpc* rpc) return inChannel; } -void rpc_in_channel_free(RpcInChannel* inChannel) +static void rpc_in_channel_free(RpcInChannel* inChannel) { if (!inChannel) return; @@ -566,14 +552,12 @@ int rpc_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CH outChannel->State = state; WLog_DBG(TAG, "%s", str); - return status; } -int rpc_out_channel_rpch_init(rdpRpc* rpc, RpcOutChannel* outChannel) +static int rpc_out_channel_rpch_init(rdpRpc* rpc, RpcOutChannel* outChannel) { HttpContext* http; - outChannel->ntlm = ntlm_new(); if (!outChannel->ntlm) @@ -585,27 +569,22 @@ int rpc_out_channel_rpch_init(rdpRpc* rpc, RpcOutChannel* outChannel) return -1; http = outChannel->http; - http_context_set_method(http, "RPC_OUT_DATA"); - http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388"); http_context_set_accept(http, "application/rpc"); http_context_set_cache_control(http, "no-cache"); http_context_set_connection(http, "Keep-Alive"); http_context_set_user_agent(http, "MSRPC"); http_context_set_host(http, rpc->settings->GatewayHostname); - http_context_set_pragma(http, - "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, " - "SessionId=fbd9c34f-397d-471d-a109-1b08cc554624"); - + "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, " + "SessionId=fbd9c34f-397d-471d-a109-1b08cc554624"); return 1; } -int rpc_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel) +static int rpc_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel) { rts_generate_cookie((BYTE*) &outChannel->Cookie); - outChannel->rpc = rpc; outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL; outChannel->BytesReceived = 0; @@ -620,7 +599,7 @@ int rpc_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel) return 1; } -void rpc_out_channel_rpch_uninit(RpcOutChannel* outChannel) +static void rpc_out_channel_rpch_uninit(RpcOutChannel* outChannel) { if (outChannel->ntlm) { @@ -638,7 +617,6 @@ void rpc_out_channel_rpch_uninit(RpcOutChannel* outChannel) RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc) { RpcOutChannel* outChannel = NULL; - outChannel = (RpcOutChannel*) calloc(1, sizeof(RpcOutChannel)); if (outChannel) @@ -666,7 +644,7 @@ void rpc_out_channel_free(RpcOutChannel* outChannel) } int rpc_virtual_connection_transition_to_state(rdpRpc* rpc, - RpcVirtualConnection* connection, VIRTUAL_CONNECTION_STATE state) + RpcVirtualConnection* connection, VIRTUAL_CONNECTION_STATE state) { int status = 1; const char* str = "VIRTUAL_CONNECTION_STATE_UNKNOWN"; @@ -700,24 +678,20 @@ int rpc_virtual_connection_transition_to_state(rdpRpc* rpc, connection->State = state; WLog_DBG(TAG, "%s", str); - return status; } -RpcVirtualConnection* rpc_virtual_connection_new(rdpRpc* rpc) +static RpcVirtualConnection* rpc_virtual_connection_new(rdpRpc* rpc) { RpcVirtualConnection* connection; - connection = (RpcVirtualConnection*) calloc(1, sizeof(RpcVirtualConnection)); if (!connection) return NULL; - rts_generate_cookie((BYTE*) &(connection->Cookie)); - rts_generate_cookie((BYTE*) &(connection->AssociationGroupId)); - + rts_generate_cookie((BYTE*) & (connection->Cookie)); + rts_generate_cookie((BYTE*) & (connection->AssociationGroupId)); connection->State = VIRTUAL_CONNECTION_STATE_INITIAL; - connection->DefaultInChannel = rpc_in_channel_new(rpc); if (!connection->DefaultInChannel) @@ -736,21 +710,19 @@ out_free: return NULL; } -void rpc_virtual_connection_free(RpcVirtualConnection* connection) +static void rpc_virtual_connection_free(RpcVirtualConnection* connection) { if (!connection) return; rpc_in_channel_free(connection->DefaultInChannel); rpc_in_channel_free(connection->NonDefaultInChannel); - rpc_out_channel_free(connection->DefaultOutChannel); rpc_out_channel_free(connection->NonDefaultOutChannel); - free(connection); } -int rpc_channel_tls_connect(RpcChannel* channel, int timeout) +static int rpc_channel_tls_connect(RpcChannel* channel, int timeout) { int sockfd; rdpTls* tls; @@ -760,12 +732,11 @@ int rpc_channel_tls_connect(RpcChannel* channel, int timeout) rdpRpc* rpc = channel->rpc; rdpContext* context = rpc->context; rdpSettings* settings = context->settings; - const char *peerHostname = settings->GatewayHostname; + const char* peerHostname = settings->GatewayHostname; UINT16 peerPort = settings->GatewayPort; BOOL isProxyConnection = proxy_prepare(settings, &peerHostname, &peerPort, TRUE); - sockfd = freerdp_tcp_connect(context, settings, peerHostname, - peerPort, timeout); + peerPort, timeout); if (sockfd < 1) return -1; @@ -776,7 +747,6 @@ int rpc_channel_tls_connect(RpcChannel* channel, int timeout) return FALSE; BIO_set_fd(socketBio, sockfd, BIO_CLOSE); - bufferedBio = BIO_new(BIO_s_buffered_socket()); if (!bufferedBio) @@ -787,13 +757,13 @@ int rpc_channel_tls_connect(RpcChannel* channel, int timeout) if (!BIO_set_nonblock(bufferedBio, TRUE)) return -1; - if (isProxyConnection) { + if (isProxyConnection) + { if (!proxy_connect(settings, bufferedBio, settings->GatewayHostname, settings->GatewayPort)) return -1; } channel->bio = bufferedBio; - tls = channel->tls = tls_new(settings); if (!tls) @@ -802,7 +772,6 @@ int rpc_channel_tls_connect(RpcChannel* channel, int timeout) tls->hostname = settings->GatewayHostname; tls->port = settings->GatewayPort; tls->isGatewayTransport = TRUE; - tlsStatus = tls_connect(tls, bufferedBio); if (tlsStatus < 1) @@ -824,7 +793,7 @@ int rpc_channel_tls_connect(RpcChannel* channel, int timeout) return 1; } -int rpc_in_channel_connect(RpcInChannel* inChannel, int timeout) +static int rpc_in_channel_connect(RpcInChannel* inChannel, int timeout) { rdpRpc* rpc = inChannel->rpc; @@ -847,11 +816,10 @@ int rpc_in_channel_connect(RpcInChannel* inChannel, int timeout) } rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY); - return 1; } -int rpc_out_channel_connect(RpcOutChannel* outChannel, int timeout) +static int rpc_out_channel_connect(RpcOutChannel* outChannel, int timeout) { rdpRpc* rpc = outChannel->rpc; @@ -874,7 +842,6 @@ int rpc_out_channel_connect(RpcOutChannel* outChannel, int timeout) } rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY); - return 1; } @@ -901,7 +868,6 @@ int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, int timeout) } rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY); - return 1; } @@ -910,7 +876,6 @@ BOOL rpc_connect(rdpRpc* rpc, int timeout) RpcInChannel* inChannel; RpcOutChannel* outChannel; RpcVirtualConnection* connection; - rpc->VirtualConnection = rpc_virtual_connection_new(rpc); if (!rpc->VirtualConnection) @@ -919,7 +884,6 @@ BOOL rpc_connect(rdpRpc* rpc, int timeout) connection = rpc->VirtualConnection; inChannel = connection->DefaultInChannel; outChannel = connection->DefaultOutChannel; - rpc_virtual_connection_transition_to_state(rpc, connection, VIRTUAL_CONNECTION_STATE_INITIAL); if (rpc_in_channel_connect(inChannel, timeout) < 0) @@ -939,13 +903,10 @@ rdpRpc* rpc_new(rdpTransport* transport) return NULL; rpc->State = RPC_CLIENT_STATE_INITIAL; - rpc->transport = transport; rpc->settings = transport->settings; rpc->context = transport->context; - rpc->SendSeqNum = 0; - rpc->ntlm = ntlm_new(); if (!rpc->ntlm) @@ -956,7 +917,6 @@ rdpRpc* rpc_new(rdpTransport* transport) rpc->StubFragCount = 0; rpc->rpc_vers = 5; rpc->rpc_vers_minor = 0; - /* little-endian data representation */ rpc->packed_drep[0] = 0x10; rpc->packed_drep[1] = 0x00; @@ -964,13 +924,11 @@ rdpRpc* rpc_new(rdpTransport* transport) rpc->packed_drep[3] = 0x00; rpc->max_xmit_frag = 0x0FF8; rpc->max_recv_frag = 0x0FF8; - rpc->ReceiveWindow = 0x00010000; rpc->ChannelLifetime = 0x40000000; rpc->KeepAliveInterval = 300000; rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval; rpc->CurrentKeepAliveTime = 0; - rpc->CallId = 2; if (rpc_client_new(rpc) < 0) diff --git a/libfreerdp/core/gateway/rpc.h b/libfreerdp/core/gateway/rpc.h index 006b629..1d2b4c5 100644 --- a/libfreerdp/core/gateway/rpc.h +++ b/libfreerdp/core/gateway/rpc.h @@ -715,7 +715,7 @@ struct rpc_virtual_connection_cookie_entry RpcVirtualConnection* Reference; }; typedef struct rpc_virtual_connection_cookie_entry - RpcVirtualConnectionCookieEntry; + RpcVirtualConnectionCookieEntry; struct rpc_client { @@ -782,9 +782,6 @@ FREERDP_LOCAL int rpc_out_channel_read(RpcOutChannel* outChannel, BYTE* data, FREERDP_LOCAL int rpc_out_channel_write(RpcOutChannel* outChannel, const BYTE* data, int length); -FREERDP_LOCAL RpcInChannel* rpc_client_in_channel_new(rdpRpc* rpc); -FREERDP_LOCAL void rpc_in_channel_free(RpcInChannel* inChannel); - FREERDP_LOCAL RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc); FREERDP_LOCAL int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, int timeout); diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index 5a4136b..9bd1bcf 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -47,7 +47,7 @@ static void rpc_pdu_reset(RPC_PDU* pdu) Stream_SetPosition(pdu->s, 0); } -RPC_PDU* rpc_pdu_new() +static RPC_PDU* rpc_pdu_new(void) { RPC_PDU* pdu; pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU)); @@ -76,7 +76,7 @@ static void rpc_pdu_free(RPC_PDU* pdu) free(pdu); } -int rpc_client_receive_pipe_write(rdpRpc* rpc, const BYTE* buffer, size_t length) +static int rpc_client_receive_pipe_write(rdpRpc* rpc, const BYTE* buffer, size_t length) { int status = 0; RpcClient* client = rpc->client; @@ -118,7 +118,7 @@ int rpc_client_receive_pipe_read(rdpRpc* rpc, BYTE* buffer, size_t length) return status; } -int rpc_client_transition_to_state(rdpRpc* rpc, RPC_CLIENT_STATE state) +static int rpc_client_transition_to_state(rdpRpc* rpc, RPC_CLIENT_STATE state) { int status = 1; const char* str = "RPC_CLIENT_STATE_UNKNOWN"; @@ -163,7 +163,7 @@ int rpc_client_transition_to_state(rdpRpc* rpc, RPC_CLIENT_STATE state) return status; } -int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu) +static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu) { int status = -1; rpcconn_rts_hdr_t* rts; @@ -287,7 +287,7 @@ int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu) return status; } -int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment) +static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment) { BYTE* buffer; RPC_PDU* pdu; @@ -448,7 +448,7 @@ int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment) return 1; } -int rpc_client_default_out_channel_recv(rdpRpc* rpc) +static int rpc_client_default_out_channel_recv(rdpRpc* rpc) { int status = -1; UINT32 statusCode; @@ -531,7 +531,6 @@ int rpc_client_default_out_channel_recv(rdpRpc* rpc) { WLog_ERR(TAG, "error! Status Code: %"PRIu32"", statusCode); http_response_print(response); - http_response_free(response); if (statusCode == HTTP_STATUS_DENIED) { @@ -539,6 +538,7 @@ int rpc_client_default_out_channel_recv(rdpRpc* rpc) freerdp_set_last_error(rpc->context, FREERDP_ERROR_AUTHENTICATION_FAILED); } + http_response_free(response); return -1; } @@ -632,7 +632,7 @@ int rpc_client_default_out_channel_recv(rdpRpc* rpc) return status; } -int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc) +static int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc) { int status = -1; HttpResponse* response; @@ -738,6 +738,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc) if (rpc_ncacn_http_recv_in_channel_response(rpc, inChannel, response) < 0) { WLog_ERR(TAG, "rpc_ncacn_http_recv_in_channel_response failure"); + http_response_free(response); return -1; } @@ -746,6 +747,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc) if (rpc_ncacn_http_send_in_channel_request(rpc, inChannel) < 0) { WLog_ERR(TAG, "rpc_ncacn_http_send_in_channel_request failure"); + http_response_free(response); return -1; } @@ -758,6 +760,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc) if (rts_send_CONN_B1_pdu(rpc) < 0) { WLog_ERR(TAG, "rpc_send_CONN_B1_pdu error!"); + http_response_free(response); return -1; } diff --git a/libfreerdp/core/gateway/rpc_fault.c b/libfreerdp/core/gateway/rpc_fault.c index 3dd7072..1e55e2b 100644 --- a/libfreerdp/core/gateway/rpc_fault.c +++ b/libfreerdp/core/gateway/rpc_fault.c @@ -27,9 +27,7 @@ #define TAG FREERDP_TAG("core.gateway.rpc") -extern const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[]; - -const RPC_FAULT_CODE RPC_FAULT_CODES[] = +static const RPC_FAULT_CODE RPC_FAULT_CODES[] = { DEFINE_RPC_FAULT_CODE(nca_s_fault_object_not_found) DEFINE_RPC_FAULT_CODE(nca_s_fault_cancel) @@ -156,10 +154,12 @@ const RPC_FAULT_CODE RPC_FAULT_CODES[] = DEFINE_RPC_FAULT_CODE(RPC_S_GROUP_MEMBER_NOT_FOUND) DEFINE_RPC_FAULT_CODE(EPT_S_CANT_CREATE) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_OBJECT) - { 0, NULL } + { + 0, NULL + } }; -const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] = +static const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] = { DEFINE_RPC_FAULT_CODE(RPC_S_OK) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_ARG) @@ -209,7 +209,9 @@ const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] = DEFINE_RPC_FAULT_CODE(HRESULT_CODE(E_PROXY_CONNECTIONABORTED)) DEFINE_RPC_FAULT_CODE(HRESULT_CODE(E_PROXY_NOCERTAVAILABLE)) DEFINE_RPC_FAULT_CODE(__HRESULT_FROM_WIN32(RPC_S_CALL_CANCELLED)) - { 0, NULL } + { + 0, NULL + } }; /** @@ -217,96 +219,139 @@ const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] = * http://msdn.microsoft.com/en-us/library/ee442005/ */ -UINT32 rpc_map_status_code_to_win32_error_code(UINT32 code) +static UINT32 rpc_map_status_code_to_win32_error_code(UINT32 code) { switch (code) { case nca_s_comm_failure: return RPC_S_COMM_FAILURE; + case nca_s_op_rng_error: return RPC_S_PROCNUM_OUT_OF_RANGE; + case nca_s_unk_if: return RPC_S_UNKNOWN_IF; + case nca_s_wrong_boot_time: return nca_s_wrong_boot_time; + case nca_s_you_crashed: return RPC_S_CALL_FAILED; + case nca_s_proto_error: return RPC_S_PROTOCOL_ERROR; + case nca_s_out_args_too_big: return RPC_S_SERVER_OUT_OF_MEMORY; + case nca_s_server_too_busy: return RPC_S_SERVER_TOO_BUSY; + case nca_s_unsupported_type: return RPC_S_UNSUPPORTED_TYPE; + case nca_s_fault_int_div_by_zero: return RPC_S_ZERO_DIVIDE; + case nca_s_fault_addr_error: return RPC_S_ADDRESS_ERROR; + case nca_s_fault_fp_div_zero: return RPC_S_FP_DIV_ZERO; + case nca_s_fault_fp_underflow: return RPC_S_FP_UNDERFLOW; + case nca_s_fault_fp_overflow: return RPC_S_FP_OVERFLOW; + case nca_s_fault_invalid_tag: return RPC_S_INVALID_TAG; + case nca_s_fault_invalid_bound: return RPC_S_INVALID_BOUND; + case nca_s_rpc_version_mismatch: return RPC_S_PROTOCOL_ERROR; + case nca_s_unspec_reject: return RPC_S_CALL_FAILED; + case nca_s_bad_actid: return RPC_S_CALL_FAILED_DNE; + case nca_s_who_are_you_failed: return RPC_S_CALL_FAILED; + case nca_s_manager_not_entered: return RPC_S_CALL_FAILED_DNE; + case nca_s_fault_cancel: return RPC_S_CALL_CANCELLED; + case nca_s_fault_ill_inst: return RPC_S_ADDRESS_ERROR; + case nca_s_fault_fp_error: return RPC_S_FP_OVERFLOW; + case nca_s_fault_int_overflow: return RPC_S_ADDRESS_ERROR; + case nca_s_fault_unspec: return RPC_S_CALL_FAILED; + case nca_s_fault_remote_comm_failure: return nca_s_fault_remote_comm_failure; + case nca_s_fault_pipe_empty: return RPC_X_PIPE_EMPTY; + case nca_s_fault_pipe_closed: return RPC_X_PIPE_CLOSED; + case nca_s_fault_pipe_order: return RPC_X_WRONG_PIPE_ORDER; + case nca_s_fault_pipe_discipline: return RPC_X_PIPE_DISCIPLINE_ERROR; + case nca_s_fault_pipe_comm_error: return RPC_S_COMM_FAILURE; + case nca_s_fault_pipe_memory: return RPC_S_OUT_OF_MEMORY; + case nca_s_fault_context_mismatch: return RPC_X_SS_CONTEXT_MISMATCH; + case nca_s_fault_remote_no_memory: return RPC_S_SERVER_OUT_OF_MEMORY; + case nca_s_invalid_pres_context_id: return RPC_S_PROTOCOL_ERROR; + case nca_s_unsupported_authn_level: return RPC_S_UNSUPPORTED_AUTHN_LEVEL; + case nca_s_invalid_checksum: return RPC_S_CALL_FAILED_DNE; + case nca_s_invalid_crc: return RPC_S_CALL_FAILED_DNE; + case nca_s_fault_user_defined: return nca_s_fault_user_defined; + case nca_s_fault_tx_open_failed: return nca_s_fault_tx_open_failed; + case nca_s_fault_codeset_conv_error: return nca_s_fault_codeset_conv_error; + case nca_s_fault_object_not_found: return nca_s_fault_object_not_found; + case nca_s_fault_no_client_stub: return nca_s_fault_no_client_stub; } diff --git a/libfreerdp/core/gateway/rpc_fault.h b/libfreerdp/core/gateway/rpc_fault.h index aa55088..a93359e 100644 --- a/libfreerdp/core/gateway/rpc_fault.h +++ b/libfreerdp/core/gateway/rpc_fault.h @@ -26,6 +26,5 @@ #include <freerdp/api.h> FREERDP_LOCAL int rpc_recv_fault_pdu(rpcconn_hdr_t* header); -FREERDP_LOCAL UINT32 rpc_map_status_code_to_win32_error_code(UINT32 code); #endif /* FREERDP_LIB_CORE_GATEWAY_RPC_FAULT_H */ diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c index 05de370..07d2324 100644 --- a/libfreerdp/core/gateway/rts.c +++ b/libfreerdp/core/gateway/rts.c @@ -99,7 +99,7 @@ static void rts_pdu_header_init(rpcconn_rts_hdr_t* header) header->call_id = 0; } -int rts_receive_window_size_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, +static int rts_receive_window_size_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, UINT32* ReceiveWindowSize) { if (ReceiveWindowSize) @@ -108,7 +108,7 @@ int rts_receive_window_size_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 lengt return 4; } -int rts_receive_window_size_command_write(BYTE* buffer, UINT32 ReceiveWindowSize) +static int rts_receive_window_size_command_write(BYTE* buffer, UINT32 ReceiveWindowSize) { if (buffer) { @@ -119,8 +119,8 @@ int rts_receive_window_size_command_write(BYTE* buffer, UINT32 ReceiveWindowSize return 8; } -int rts_flow_control_ack_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, - UINT32* BytesReceived, UINT32* AvailableWindow, BYTE* ChannelCookie) +static int rts_flow_control_ack_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, + UINT32* BytesReceived, UINT32* AvailableWindow, BYTE* ChannelCookie) { /* Ack (24 bytes) */ if (BytesReceived) @@ -135,8 +135,9 @@ int rts_flow_control_ack_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, return 24; } -int rts_flow_control_ack_command_write(BYTE* buffer, UINT32 BytesReceived, UINT32 AvailableWindow, - BYTE* ChannelCookie) +static int rts_flow_control_ack_command_write(BYTE* buffer, UINT32 BytesReceived, + UINT32 AvailableWindow, + BYTE* ChannelCookie) { if (buffer) { @@ -150,8 +151,8 @@ int rts_flow_control_ack_command_write(BYTE* buffer, UINT32 BytesReceived, UINT3 return 28; } -int rts_connection_timeout_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, - UINT32* ConnectionTimeout) +static int rts_connection_timeout_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, + UINT32* ConnectionTimeout) { if (ConnectionTimeout) *ConnectionTimeout = *((UINT32*) &buffer[0]); /* ConnectionTimeout (4 bytes) */ @@ -159,7 +160,7 @@ int rts_connection_timeout_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length return 4; } -int rts_connection_timeout_command_write(BYTE* buffer, UINT32 ConnectionTimeout) +static int rts_connection_timeout_command_write(BYTE* buffer, UINT32 ConnectionTimeout) { if (buffer) { @@ -170,13 +171,13 @@ int rts_connection_timeout_command_write(BYTE* buffer, UINT32 ConnectionTimeout) return 8; } -int rts_cookie_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_cookie_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { /* Cookie (16 bytes) */ return 16; } -int rts_cookie_command_write(BYTE* buffer, BYTE* Cookie) +static int rts_cookie_command_write(BYTE* buffer, BYTE* Cookie) { if (buffer) { @@ -187,13 +188,13 @@ int rts_cookie_command_write(BYTE* buffer, BYTE* Cookie) return 20; } -int rts_channel_lifetime_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_channel_lifetime_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { /* ChannelLifetime (4 bytes) */ return 4; } -int rts_channel_lifetime_command_write(BYTE* buffer, UINT32 ChannelLifetime) +static int rts_channel_lifetime_command_write(BYTE* buffer, UINT32 ChannelLifetime) { if (buffer) { @@ -204,13 +205,13 @@ int rts_channel_lifetime_command_write(BYTE* buffer, UINT32 ChannelLifetime) return 8; } -int rts_client_keepalive_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_client_keepalive_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { /* ClientKeepalive (4 bytes) */ return 4; } -int rts_client_keepalive_command_write(BYTE* buffer, UINT32 ClientKeepalive) +static int rts_client_keepalive_command_write(BYTE* buffer, UINT32 ClientKeepalive) { /** * An unsigned integer that specifies the keep-alive interval, in milliseconds, @@ -226,13 +227,13 @@ int rts_client_keepalive_command_write(BYTE* buffer, UINT32 ClientKeepalive) return 8; } -int rts_version_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_version_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { /* Version (4 bytes) */ return 4; } -int rts_version_command_write(BYTE* buffer) +static int rts_version_command_write(BYTE* buffer) { if (buffer) { @@ -243,12 +244,12 @@ int rts_version_command_write(BYTE* buffer) return 8; } -int rts_empty_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_empty_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { return 0; } -int rts_empty_command_write(BYTE* buffer) +static int rts_empty_command_write(BYTE* buffer) { if (buffer) { @@ -258,7 +259,7 @@ int rts_empty_command_write(BYTE* buffer) return 4; } -int rts_padding_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_padding_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { UINT32 ConformanceCount; ConformanceCount = *((UINT32*) &buffer[0]); /* ConformanceCount (4 bytes) */ @@ -266,7 +267,7 @@ int rts_padding_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) return ConformanceCount + 4; } -int rts_padding_command_write(BYTE* buffer, UINT32 ConformanceCount) +static int rts_padding_command_write(BYTE* buffer, UINT32 ConformanceCount) { if (buffer) { @@ -278,12 +279,12 @@ int rts_padding_command_write(BYTE* buffer, UINT32 ConformanceCount) return 8 + ConformanceCount; } -int rts_negative_ance_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_negative_ance_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { return 0; } -int rts_negative_ance_command_write(BYTE* buffer) +static int rts_negative_ance_command_write(BYTE* buffer) { if (buffer) { @@ -293,12 +294,12 @@ int rts_negative_ance_command_write(BYTE* buffer) return 4; } -int rts_ance_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_ance_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { return 0; } -int rts_ance_command_write(BYTE* buffer) +static int rts_ance_command_write(BYTE* buffer) { if (buffer) { @@ -308,7 +309,7 @@ int rts_ance_command_write(BYTE* buffer) return 4; } -int rts_client_address_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_client_address_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { UINT32 AddressType; AddressType = *((UINT32*) &buffer[0]); /* AddressType (4 bytes) */ @@ -327,7 +328,7 @@ int rts_client_address_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) } } -int rts_client_address_command_write(BYTE* buffer, UINT32 AddressType, BYTE* ClientAddress) +static int rts_client_address_command_write(BYTE* buffer, UINT32 AddressType, BYTE* ClientAddress) { if (buffer) { @@ -357,13 +358,13 @@ int rts_client_address_command_write(BYTE* buffer, UINT32 AddressType, BYTE* Cli } } -int rts_association_group_id_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_association_group_id_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { /* AssociationGroupId (16 bytes) */ return 16; } -int rts_association_group_id_command_write(BYTE* buffer, BYTE* AssociationGroupId) +static int rts_association_group_id_command_write(BYTE* buffer, BYTE* AssociationGroupId) { if (buffer) { @@ -374,7 +375,8 @@ int rts_association_group_id_command_write(BYTE* buffer, BYTE* AssociationGroupI return 20; } -int rts_destination_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, UINT32* Destination) +static int rts_destination_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, + UINT32* Destination) { if (Destination) *Destination = *((UINT32*) &buffer[0]); /* Destination (4 bytes) */ @@ -382,7 +384,7 @@ int rts_destination_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, UINT3 return 4; } -int rts_destination_command_write(BYTE* buffer, UINT32 Destination) +static int rts_destination_command_write(BYTE* buffer, UINT32 Destination) { if (buffer) { @@ -393,13 +395,13 @@ int rts_destination_command_write(BYTE* buffer, UINT32 Destination) return 8; } -int rts_ping_traffic_sent_notify_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) +static int rts_ping_traffic_sent_notify_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) { /* PingTrafficSent (4 bytes) */ return 4; } -int rts_ping_traffic_sent_notify_command_write(BYTE* buffer, UINT32 PingTrafficSent) +static int rts_ping_traffic_sent_notify_command_write(BYTE* buffer, UINT32 PingTrafficSent) { if (buffer) { @@ -432,8 +434,8 @@ int rts_send_CONN_A1_pdu(rdpRpc* rpc) header.Flags = RTS_FLAG_NONE; header.NumberOfCommands = 4; WLog_DBG(TAG, "Sending CONN/A1 RTS PDU"); - VirtualConnectionCookie = (BYTE*) &(connection->Cookie); - OUTChannelCookie = (BYTE*) &(outChannel->Cookie); + VirtualConnectionCookie = (BYTE*) & (connection->Cookie); + OUTChannelCookie = (BYTE*) & (outChannel->Cookie); ReceiveWindowSize = outChannel->ReceiveWindow; buffer = (BYTE*) malloc(header.frag_length); @@ -479,9 +481,9 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc) header.Flags = RTS_FLAG_NONE; header.NumberOfCommands = 6; WLog_DBG(TAG, "Sending CONN/B1 RTS PDU"); - VirtualConnectionCookie = (BYTE*) &(connection->Cookie); - INChannelCookie = (BYTE*) &(inChannel->Cookie); - AssociationGroupId = (BYTE*) &(connection->AssociationGroupId); + VirtualConnectionCookie = (BYTE*) & (connection->Cookie); + INChannelCookie = (BYTE*) & (inChannel->Cookie); + AssociationGroupId = (BYTE*) & (connection->AssociationGroupId); buffer = (BYTE*) malloc(header.frag_length); if (!buffer) @@ -527,7 +529,7 @@ int rts_recv_CONN_C2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) /* Out-of-Sequence PDUs */ -int rts_send_keep_alive_pdu(rdpRpc* rpc) +static int rts_send_keep_alive_pdu(rdpRpc* rpc) { int status; BYTE* buffer; @@ -572,7 +574,7 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc) WLog_DBG(TAG, "Sending FlowControlAck RTS PDU"); BytesReceived = outChannel->BytesReceived; AvailableWindow = outChannel->AvailableWindowAdvertised; - ChannelCookie = (BYTE*) &(outChannel->Cookie); + ChannelCookie = (BYTE*) & (outChannel->Cookie); outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised; buffer = (BYTE*) malloc(header.frag_length); @@ -640,7 +642,7 @@ static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, BYTE* buf return 1; } -int rts_send_ping_pdu(rdpRpc* rpc) +static int rts_send_ping_pdu(rdpRpc* rpc) { int status; BYTE* buffer; @@ -752,7 +754,7 @@ static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc) header.Flags = RTS_FLAG_OUT_CHANNEL; header.NumberOfCommands = 3; WLog_DBG(TAG, "Sending OUT_R2/A7 RTS PDU"); - SuccessorChannelCookie = (BYTE*) &(nextOutChannel->Cookie); + SuccessorChannelCookie = (BYTE*) & (nextOutChannel->Cookie); buffer = (BYTE*) malloc(header.frag_length); if (!buffer) @@ -808,9 +810,9 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc) header.Flags = RTS_FLAG_RECYCLE_CHANNEL; header.NumberOfCommands = 5; WLog_DBG(TAG, "Sending OUT_R1/A3 RTS PDU"); - VirtualConnectionCookie = (BYTE*) &(connection->Cookie); - PredecessorChannelCookie = (BYTE*) &(outChannel->Cookie); - SuccessorChannelCookie = (BYTE*) &(nextOutChannel->Cookie); + VirtualConnectionCookie = (BYTE*) & (connection->Cookie); + PredecessorChannelCookie = (BYTE*) & (outChannel->Cookie); + SuccessorChannelCookie = (BYTE*) & (nextOutChannel->Cookie); ReceiveWindowSize = outChannel->ReceiveWindow; buffer = (BYTE*) malloc(header.frag_length); diff --git a/libfreerdp/core/gateway/rts.h b/libfreerdp/core/gateway/rts.h index 2f1898b..c40a5c4 100644 --- a/libfreerdp/core/gateway/rts.h +++ b/libfreerdp/core/gateway/rts.h @@ -81,78 +81,6 @@ FREERDP_LOCAL void rts_generate_cookie(BYTE* cookie); FREERDP_LOCAL int rts_command_length(rdpRpc* rpc, UINT32 CommandType, BYTE* buffer, UINT32 length); -FREERDP_LOCAL int rts_recv_pdu_commands(rdpRpc* rpc, rpcconn_rts_hdr_t* rts); - -FREERDP_LOCAL int rts_receive_window_size_command_read(rdpRpc* rpc, - BYTE* buffer, UINT32 length, UINT32* ReceiveWindowSize); -FREERDP_LOCAL int rts_receive_window_size_command_write(BYTE* buffer, - UINT32 ReceiveWindowSize); - -FREERDP_LOCAL int rts_flow_control_ack_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length, - UINT32* BytesReceived, UINT32* AvailableWindow, BYTE* ChannelCookie); -FREERDP_LOCAL int rts_flow_control_ack_command_write(BYTE* buffer, - UINT32 BytesReceived, UINT32 AvailableWindow, BYTE* ChannelCookie); - -FREERDP_LOCAL int rts_connection_timeout_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length, UINT32* ConnectionTimeout); -FREERDP_LOCAL int rts_connection_timeout_command_write(BYTE* buffer, - UINT32 ConnectionTimeout); - -FREERDP_LOCAL int rts_cookie_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length); -FREERDP_LOCAL int rts_cookie_command_write(BYTE* buffer, BYTE* Cookie); - -FREERDP_LOCAL int rts_channel_lifetime_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length); -FREERDP_LOCAL int rts_channel_lifetime_command_write(BYTE* buffer, - UINT32 ChannelLifetime); - -FREERDP_LOCAL int rts_client_keepalive_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length); -FREERDP_LOCAL int rts_client_keepalive_command_write(BYTE* buffer, - UINT32 ClientKeepalive); - -FREERDP_LOCAL int rts_version_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length); -FREERDP_LOCAL int rts_version_command_write(BYTE* buffer); - -FREERDP_LOCAL int rts_empty_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length); -FREERDP_LOCAL int rts_empty_command_write(BYTE* buffer); - -FREERDP_LOCAL int rts_padding_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length); -FREERDP_LOCAL int rts_padding_command_write(BYTE* buffer, - UINT32 ConformanceCount); - -FREERDP_LOCAL int rts_negative_ance_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length); -FREERDP_LOCAL int rts_negative_ance_command_write(BYTE* buffer); - -FREERDP_LOCAL int rts_ance_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length); -FREERDP_LOCAL int rts_ance_command_write(BYTE* buffer); - -FREERDP_LOCAL int rts_client_address_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length); -FREERDP_LOCAL int rts_client_address_command_write(BYTE* buffer, - UINT32 AddressType, BYTE* ClientAddress); - -FREERDP_LOCAL int rts_association_group_id_command_read(rdpRpc* rpc, - BYTE* buffer, UINT32 length); -FREERDP_LOCAL int rts_association_group_id_command_write(BYTE* buffer, - BYTE* AssociationGroupId); - -FREERDP_LOCAL int rts_destination_command_read(rdpRpc* rpc, BYTE* buffer, - UINT32 length, UINT32* Destination); -FREERDP_LOCAL int rts_destination_command_write(BYTE* buffer, - UINT32 Destination); - -FREERDP_LOCAL int rts_ping_traffic_sent_notify_command_read(rdpRpc* rpc, - BYTE* buffer, UINT32 length); -FREERDP_LOCAL int rts_ping_traffic_sent_notify_command_write(BYTE* buffer, - UINT32 PingTrafficSent); FREERDP_LOCAL int rts_send_CONN_A1_pdu(rdpRpc* rpc); FREERDP_LOCAL int rts_recv_CONN_A3_pdu(rdpRpc* rpc, BYTE* buffer, @@ -165,9 +93,7 @@ FREERDP_LOCAL int rts_recv_CONN_C2_pdu(rdpRpc* rpc, BYTE* buffer, FREERDP_LOCAL int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc); -FREERDP_LOCAL int rts_send_keep_alive_pdu(rdpRpc* rpc); FREERDP_LOCAL int rts_send_flow_control_ack_pdu(rdpRpc* rpc); -FREERDP_LOCAL int rts_send_ping_pdu(rdpRpc* rpc); FREERDP_LOCAL int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length); diff --git a/libfreerdp/core/gateway/rts_signature.c b/libfreerdp/core/gateway/rts_signature.c index 930e8df..a549fc2 100644 --- a/libfreerdp/core/gateway/rts_signature.c +++ b/libfreerdp/core/gateway/rts_signature.c @@ -24,126 +24,194 @@ #define TAG FREERDP_TAG("core.gateway.rts") RtsPduSignature RTS_PDU_CONN_A1_SIGNATURE = { RTS_FLAG_NONE, 4, - { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0, 0 } }; + { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_CONN_A2_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 5, - { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME, - RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 } }; + { + RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME, + RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 + } +}; RtsPduSignature RTS_PDU_CONN_A3_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_CONN_B1_SIGNATURE = { RTS_FLAG_NONE, 6, - { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME, - RTS_CMD_CLIENT_KEEPALIVE, RTS_CMD_ASSOCIATION_GROUP_ID, 0, 0 } }; + { + RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME, + RTS_CMD_CLIENT_KEEPALIVE, RTS_CMD_ASSOCIATION_GROUP_ID, 0, 0 + } +}; RtsPduSignature RTS_PDU_CONN_B2_SIGNATURE = { RTS_FLAG_IN_CHANNEL, 7, - { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE, - RTS_CMD_CONNECTION_TIMEOUT, RTS_CMD_ASSOCIATION_GROUP_ID, RTS_CMD_CLIENT_ADDRESS, 0 } }; + { + RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE, + RTS_CMD_CONNECTION_TIMEOUT, RTS_CMD_ASSOCIATION_GROUP_ID, RTS_CMD_CLIENT_ADDRESS, 0 + } +}; RtsPduSignature RTS_PDU_CONN_B3_SIGNATURE = { RTS_FLAG_NONE, 2, - { RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_VERSION, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_VERSION, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_CONN_C1_SIGNATURE = { RTS_FLAG_NONE, 3, - { RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } }; + { RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_CONN_C2_SIGNATURE = { RTS_FLAG_NONE, 3, - { RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } }; + { RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_IN_R1_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 4, - { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, 0, 0, 0, 0 } }; + { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_IN_R1_A2_SIGNATURE = { RTS_FLAG_NONE, 4, - { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, - RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0, 0 } }; + { + RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, + RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0, 0 + } +}; RtsPduSignature RTS_PDU_IN_R1_A3_SIGNATURE = { RTS_FLAG_NONE, 4, - { RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE, - RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0 } }; + { + RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE, + RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0 + } +}; RtsPduSignature RTS_PDU_IN_R1_A4_SIGNATURE = { RTS_FLAG_NONE, 4, - { RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE, - RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0 } }; + { + RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE, + RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0 + } +}; RtsPduSignature RTS_PDU_IN_R1_A5_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_IN_R1_A6_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_IN_R1_B1_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_EMPTY, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_EMPTY, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_IN_R1_B2_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_IN_R2_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 4, - { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, 0, 0, 0, 0 } }; + { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_IN_R2_A2_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_IN_R2_A3_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_IN_R2_A4_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_IN_R2_A5_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R1_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1, - { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R1_A2_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1, - { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R1_A3_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 5, - { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, - RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 } }; + { + RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, + RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 + } +}; RtsPduSignature RTS_PDU_OUT_R1_A4_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL | RTS_FLAG_OUT_CHANNEL, 7, - { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME, - RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0 } }; + { + RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME, + RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0 + } +}; RtsPduSignature RTS_PDU_OUT_R1_A5_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 3, - { RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R1_A6_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 3, - { RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R1_A7_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 2, - { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R1_A8_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 2, - { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R1_A9_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R1_A10_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R1_A11_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_A1_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1, - { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_A2_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 1, - { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_A3_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL, 5, - { RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, - RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 } }; + { + RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, + RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 + } +}; RtsPduSignature RTS_PDU_OUT_R2_A4_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_A5_SIGNATURE = { RTS_FLAG_NONE, 2, - { RTS_CMD_DESTINATION, RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_A6_SIGNATURE = { RTS_FLAG_NONE, 2, - { RTS_CMD_DESTINATION, RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_A7_SIGNATURE = { RTS_FLAG_NONE, 3, - { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, RTS_CMD_VERSION, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, RTS_CMD_VERSION, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_A8_SIGNATURE = { RTS_FLAG_OUT_CHANNEL, 2, - { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_B1_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_B2_SIGNATURE = { RTS_FLAG_NONE, 1, - { RTS_CMD_NEGATIVE_ANCE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_NEGATIVE_ANCE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_B3_SIGNATURE = { RTS_FLAG_EOF, 1, - { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_OUT_R2_C1_SIGNATURE = { RTS_FLAG_PING, 1, - { 0, 0, 0, 0, 0, 0, 0, 0 } }; + { 0, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_KEEP_ALIVE_SIGNATURE = { RTS_FLAG_OTHER_CMD, 1, - { RTS_CMD_CLIENT_KEEPALIVE, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_CLIENT_KEEPALIVE, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_PING_TRAFFIC_SENT_NOTIFY_SIGNATURE = { RTS_FLAG_OTHER_CMD, 1, - { RTS_CMD_PING_TRAFFIC_SENT_NOTIFY, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_PING_TRAFFIC_SENT_NOTIFY, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_ECHO_SIGNATURE = { RTS_FLAG_ECHO, 0, - { 0, 0, 0, 0, 0, 0, 0, 0 } }; + { 0, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_PING_SIGNATURE = { RTS_FLAG_PING, 0, - { 0, 0, 0, 0, 0, 0, 0, 0 } }; + { 0, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE = { RTS_FLAG_OTHER_CMD, 1, - { RTS_CMD_FLOW_CONTROL_ACK, 0, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_FLOW_CONTROL_ACK, 0, 0, 0, 0, 0, 0, 0 } +}; RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE = { RTS_FLAG_OTHER_CMD, 2, - { RTS_CMD_DESTINATION, RTS_CMD_FLOW_CONTROL_ACK, 0, 0, 0, 0, 0, 0 } }; + { RTS_CMD_DESTINATION, RTS_CMD_FLOW_CONTROL_ACK, 0, 0, 0, 0, 0, 0 } +}; -RTS_PDU_SIGNATURE_ENTRY RTS_PDU_SIGNATURE_TABLE[] = +static const RTS_PDU_SIGNATURE_ENTRY RTS_PDU_SIGNATURE_TABLE[] = { { RTS_PDU_CONN_A1, FALSE, &RTS_PDU_CONN_A1_SIGNATURE, "CONN/A1" }, { RTS_PDU_CONN_A2, FALSE, &RTS_PDU_CONN_A2_SIGNATURE, "CONN/A2" }, @@ -238,12 +306,12 @@ BOOL rts_match_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_rt return FALSE; status = rts_command_length(rpc, CommandType, &buffer[offset], length); + if (status < 0) return FALSE; CommandLength = (UINT32) status; offset += CommandLength; - length = rts->frag_length - offset; } @@ -259,10 +327,8 @@ int rts_extract_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_r UINT32 offset; UINT32 CommandType; UINT32 CommandLength; - signature->Flags = rts->Flags; signature->NumberOfCommands = rts->NumberOfCommands; - buffer = (BYTE*) rts; offset = RTS_PDU_HEADER_LENGTH; length = rts->frag_length - offset; @@ -271,23 +337,22 @@ int rts_extract_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_r { CommandType = *((UINT32*) &buffer[offset]); /* CommandType (4 bytes) */ offset += 4; - signature->CommandTypes[i] = CommandType; - status = rts_command_length(rpc, CommandType, &buffer[offset], length); + if (status < 0) return FALSE; CommandLength = (UINT32) status; offset += CommandLength; - length = rts->frag_length - offset; } return 0; } -UINT32 rts_identify_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, RTS_PDU_SIGNATURE_ENTRY** entry) +UINT32 rts_identify_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, + RTS_PDU_SIGNATURE_ENTRY** entry) { int i, j; RtsPduSignature* pSignature; @@ -325,7 +390,7 @@ int rts_print_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature) UINT32 SignatureId; RTS_PDU_SIGNATURE_ENTRY* entry; WLog_INFO(TAG, "RTS PDU Signature: Flags: 0x%04"PRIX16" NumberOfCommands: %"PRIu16"", - signature->Flags, signature->NumberOfCommands); + signature->Flags, signature->NumberOfCommands); SignatureId = rts_identify_pdu_signature(rpc, signature, &entry); if (SignatureId) diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c index 589482f..ca6f7f3 100644 --- a/libfreerdp/core/gateway/tsg.c +++ b/libfreerdp/core/gateway/tsg.c @@ -39,6 +39,7 @@ #define TAG FREERDP_TAG("core.gateway.tsg") +static BIO_METHOD* BIO_s_tsg(void); /** * RPC Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378623/ * Remote Procedure Call: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378651/ @@ -75,7 +76,8 @@ * TsProxySendToServerRequest(ChannelContext) */ -DWORD TsProxySendToServer(handle_t IDL_handle, byte pRpcMessage[], UINT32 count, UINT32* lengths) +static DWORD TsProxySendToServer(handle_t IDL_handle, byte pRpcMessage[], UINT32 count, + UINT32* lengths) { wStream* s; int status; @@ -353,9 +355,9 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, packet->tsgPacket.packetCapsResponse = packetCapsResponse; /* PacketQuarResponsePtr (4 bytes) */ packetCapsResponse->pktQuarEncResponse.flags = *((UINT32*) &buffer[offset + - 12]); /* Flags (4 bytes) */ + 12]); /* Flags (4 bytes) */ packetCapsResponse->pktQuarEncResponse.certChainLen = *((UINT32*) &buffer[offset + - 16]); /* CertChainLength (4 bytes) */ + 16]); /* CertChainLength (4 bytes) */ /* CertChainDataPtr (4 bytes) */ CopyMemory(&packetCapsResponse->pktQuarEncResponse.nonce, &buffer[offset + 24], 16); /* Nonce (16 bytes) */ @@ -425,7 +427,7 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, versionCaps->majorVersion = *((UINT16*) &buffer[offset + 8]); /* MajorVersion (2 bytes) */ versionCaps->minorVersion = *((UINT16*) &buffer[offset + 10]); /* MinorVersion (2 bytes) */ versionCaps->quarantineCapabilities = *((UINT16*) &buffer[offset + - 12]); /* QuarantineCapabilities (2 bytes) */ + 12]); /* QuarantineCapabilities (2 bytes) */ offset += 14; /* 4-byte alignment */ rpc_offset_align(&offset, 4); @@ -533,7 +535,7 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, /* PacketQuarResponsePtr (4 bytes) */ packetQuarEncResponse->flags = *((UINT32*) &buffer[offset + 12]); /* Flags (4 bytes) */ packetQuarEncResponse->certChainLen = *((UINT32*) &buffer[offset + - 16]); /* CertChainLength (4 bytes) */ + 16]); /* CertChainLength (4 bytes) */ /* CertChainDataPtr (4 bytes) */ CopyMemory(&packetQuarEncResponse->nonce, &buffer[offset + 24], 16); /* Nonce (16 bytes) */ offset += 40; @@ -590,7 +592,7 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, versionCaps->majorVersion = *((UINT16*) &buffer[offset + 8]); /* MajorVersion (2 bytes) */ versionCaps->majorVersion = *((UINT16*) &buffer[offset + 10]); /* MinorVersion (2 bytes) */ versionCaps->quarantineCapabilities = *((UINT16*) &buffer[offset + - 12]); /* QuarantineCapabilities (2 bytes) */ + 12]); /* QuarantineCapabilities (2 bytes) */ offset += 14; /* 4-byte alignment */ rpc_offset_align(&offset, 4); @@ -753,23 +755,23 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu) /* Reserved (4 bytes) */ Pointer = *((UINT32*) &buffer[offset + 20]); /* ResponseDataPtr (4 bytes) */ packetResponse->responseDataLen = *((UINT32*) &buffer[offset + - 24]); /* ResponseDataLength (4 bytes) */ + 24]); /* ResponseDataLength (4 bytes) */ packetResponse->redirectionFlags.enableAllRedirections = *((UINT32*) &buffer[offset + - 28]); /* EnableAllRedirections (4 bytes) */ + 28]); /* EnableAllRedirections (4 bytes) */ packetResponse->redirectionFlags.disableAllRedirections = *((UINT32*) &buffer[offset + - 32]); /* DisableAllRedirections (4 bytes) */ + 32]); /* DisableAllRedirections (4 bytes) */ packetResponse->redirectionFlags.driveRedirectionDisabled = *((UINT32*) &buffer[offset + - 36]); /* DriveRedirectionDisabled (4 bytes) */ + 36]); /* DriveRedirectionDisabled (4 bytes) */ packetResponse->redirectionFlags.printerRedirectionDisabled = *((UINT32*) &buffer[offset + - 40]); /* PrinterRedirectionDisabled (4 bytes) */ + 40]); /* PrinterRedirectionDisabled (4 bytes) */ packetResponse->redirectionFlags.portRedirectionDisabled = *((UINT32*) &buffer[offset + - 44]); /* PortRedirectionDisabled (4 bytes) */ + 44]); /* PortRedirectionDisabled (4 bytes) */ packetResponse->redirectionFlags.reserved = *((UINT32*) &buffer[offset + - 48]); /* Reserved (4 bytes) */ + 48]); /* Reserved (4 bytes) */ packetResponse->redirectionFlags.clipboardRedirectionDisabled = *((UINT32*) &buffer[offset + - 52]); /* ClipboardRedirectionDisabled (4 bytes) */ + 52]); /* ClipboardRedirectionDisabled (4 bytes) */ packetResponse->redirectionFlags.pnpRedirectionDisabled = *((UINT32*) &buffer[offset + - 56]); /* PnpRedirectionDisabled (4 bytes) */ + 56]); /* PnpRedirectionDisabled (4 bytes) */ offset += 60; SizeValue = *((UINT32*) &buffer[offset]); /* (4 bytes) */ offset += 4; @@ -916,9 +918,9 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu) packetMsgResponse->messagePacket.consentMessage = packetStringMessage; Pointer = *((UINT32*) &buffer[offset + 28]); /* ConsentMessagePtr (4 bytes) */ packetStringMessage->isDisplayMandatory = *((INT32*) &buffer[offset + - 32]); /* IsDisplayMandatory (4 bytes) */ + 32]); /* IsDisplayMandatory (4 bytes) */ packetStringMessage->isConsentMandatory = *((INT32*) &buffer[offset + - 36]); /* IsConsentMandatory (4 bytes) */ + 36]); /* IsConsentMandatory (4 bytes) */ packetStringMessage->msgBytes = *((UINT32*) &buffer[offset + 40]); /* MsgBytes (4 bytes) */ Pointer = *((UINT32*) &buffer[offset + 44]); /* MsgPtr (4 bytes) */ MaxCount = *((UINT32*) &buffer[offset + 48]); /* MaxCount (4 bytes) */ @@ -942,9 +944,9 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu) packetMsgResponse->messagePacket.serviceMessage = packetStringMessage; Pointer = *((UINT32*) &buffer[offset + 28]); /* ServiceMessagePtr (4 bytes) */ packetStringMessage->isDisplayMandatory = *((INT32*) &buffer[offset + - 32]); /* IsDisplayMandatory (4 bytes) */ + 32]); /* IsDisplayMandatory (4 bytes) */ packetStringMessage->isConsentMandatory = *((INT32*) &buffer[offset + - 36]); /* IsConsentMandatory (4 bytes) */ + 36]); /* IsConsentMandatory (4 bytes) */ packetStringMessage->msgBytes = *((UINT32*) &buffer[offset + 40]); /* MsgBytes (4 bytes) */ Pointer = *((UINT32*) &buffer[offset + 44]); /* MsgPtr (4 bytes) */ MaxCount = *((UINT32*) &buffer[offset + 48]); /* MaxCount (4 bytes) */ @@ -969,7 +971,7 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu) Pointer = *((UINT32*) &buffer[offset + 28]); /* ReauthMessagePtr (4 bytes) */ /* alignment pad (4 bytes) */ packetReauthMessage->tunnelContext = *((UINT64*) &buffer[offset + - 36]); /* TunnelContext (8 bytes) */ + 36]); /* TunnelContext (8 bytes) */ /* ReturnValue (4 bytes) */ tsg->ReauthTunnelContext = packetReauthMessage->tunnelContext; break; @@ -1215,7 +1217,7 @@ static BOOL TsProxySetupReceivePipeWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* cha } -int tsg_transition_to_state(rdpTsg* tsg, TSG_STATE state) +static int tsg_transition_to_state(rdpTsg* tsg, TSG_STATE state) { const char* str = "TSG_STATE_UNKNOWN"; @@ -1301,7 +1303,7 @@ int tsg_proxy_begin(rdpTsg* tsg) return 1; } -int tsg_proxy_reauth(rdpTsg* tsg) +static int tsg_proxy_reauth(rdpTsg* tsg) { TSG_PACKET tsgPacket; PTSG_PACKET_REAUTH packetReauth; diff --git a/libfreerdp/core/gateway/tsg.h b/libfreerdp/core/gateway/tsg.h index f1d6144..ac0fb28 100644 --- a/libfreerdp/core/gateway/tsg.h +++ b/libfreerdp/core/gateway/tsg.h @@ -310,12 +310,6 @@ struct rdp_tsg }; FREERDP_LOCAL int tsg_proxy_begin(rdpTsg* tsg); -FREERDP_LOCAL int tsg_proxy_reauth(rdpTsg* tsg); - -FREERDP_LOCAL DWORD TsProxySendToServer(handle_t IDL_handle, BYTE pRpcMessage[], - UINT32 count, UINT32* lengths); - -FREERDP_LOCAL int tsg_transition_to_state(rdpTsg* tsg, TSG_STATE state); FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout); @@ -330,6 +324,4 @@ FREERDP_LOCAL DWORD tsg_get_event_handles(rdpTsg* tsg, HANDLE* events, FREERDP_LOCAL rdpTsg* tsg_new(rdpTransport* transport); FREERDP_LOCAL void tsg_free(rdpTsg* tsg); -FREERDP_LOCAL BIO_METHOD* BIO_s_tsg(void); - #endif /* FREERDP_LIB_CORE_GATEWAY_TSG_H */ diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index ae26115..759468c 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -333,7 +333,7 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, int length) { UINT16 type; UINT16 blockLength; - int begPos, endPos; + size_t begPos, endPos; while (length > 0) { @@ -837,13 +837,13 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) ? TRUE : FALSE; if (settings->SupportStatusInfoPdu) - settings->SupportStatusInfoPdu = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_STATUSINFO_PDU) ? TRUE : FALSE; + settings->SupportStatusInfoPdu = (earlyCapabilityFlags & + RNS_UD_CS_SUPPORT_STATUSINFO_PDU) ? TRUE : FALSE; if (!(earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE)) connectionType = 0; - settings->SupportErrorInfoPdu = earlyCapabilityFlags & - RNS_UD_CS_SUPPORT_ERRINFO_PDU; + settings->SupportErrorInfoPdu = earlyCapabilityFlags & RNS_UD_CS_SUPPORT_ERRINFO_PDU; settings->ConnectionType = connectionType; return TRUE; } @@ -1221,15 +1221,15 @@ BOOL gcc_read_server_security_data(wStream* s, rdpMcs* mcs) data = settings->ServerCertificate; length = settings->ServerCertificateLength; + if (!certificate_read_server_certificate(settings->RdpServerCertificate, data, length)) goto fail; return TRUE; - fail: - free (settings->ServerRandom); - free (settings->ServerCertificate); + free(settings->ServerRandom); + free(settings->ServerCertificate); settings->ServerRandom = NULL; settings->ServerCertificate = NULL; return FALSE; @@ -1471,6 +1471,12 @@ BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs) Stream_Write_UINT32(s, serverCertLen); /* serverCertLen */ settings->ServerRandomLength = serverRandomLen; settings->ServerRandom = (BYTE*) malloc(serverRandomLen); + + if (!settings->ServerRandom) + { + return FALSE; + } + winpr_RAND(settings->ServerRandom, serverRandomLen); Stream_Write(s, settings->ServerRandom, serverRandomLen); sigData = Stream_Pointer(s); @@ -1520,7 +1526,7 @@ BOOL gcc_read_client_network_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) if (blockLength < 4 + mcs->channelCount * 12) return FALSE; - if (mcs->channelCount > 16) + if (mcs->channelCount > CHANNEL_MAX_COUNT) return FALSE; /* channelDefArray */ @@ -1768,6 +1774,7 @@ void gcc_write_client_monitor_data(wStream* s, rdpMcs* mcs) int i; UINT16 length; UINT32 left, top, right, bottom, flags; + INT32 baseX = 0, baseY = 0; rdpSettings* settings = mcs->settings; if (settings->MonitorCount > 1) @@ -1777,13 +1784,23 @@ void gcc_write_client_monitor_data(wStream* s, rdpMcs* mcs) Stream_Write_UINT32(s, 0); /* flags */ Stream_Write_UINT32(s, settings->MonitorCount); /* monitorCount */ + /* first pass to get the primary monitor coordinates (it is supposed to be + * in (0,0) */ for (i = 0; i < settings->MonitorCount; i++) { - left = settings->MonitorDefArray[i].x; - top = settings->MonitorDefArray[i].y; - right = settings->MonitorDefArray[i].x + settings->MonitorDefArray[i].width - 1; - bottom = settings->MonitorDefArray[i].y + settings->MonitorDefArray[i].height - - 1; + if (settings->MonitorDefArray[i].is_primary) + { + baseX = settings->MonitorDefArray[i].x; + baseY = settings->MonitorDefArray[i].y; + } + } + + for (i = 0; i < settings->MonitorCount; i++) + { + left = settings->MonitorDefArray[i].x - baseX; + top = settings->MonitorDefArray[i].y - baseY; + right = left + settings->MonitorDefArray[i].width - 1; + bottom = top + settings->MonitorDefArray[i].height - 1; flags = settings->MonitorDefArray[i].is_primary ? MONITOR_PRIMARY : 0; Stream_Write_UINT32(s, left); /* left */ Stream_Write_UINT32(s, top); /* top */ diff --git a/libfreerdp/core/graphics.c b/libfreerdp/core/graphics.c index fffe2ee..423416b 100644 --- a/libfreerdp/core/graphics.c +++ b/libfreerdp/core/graphics.c @@ -57,14 +57,7 @@ static BOOL Bitmap_New(rdpContext* context, rdpBitmap* bitmap) void Bitmap_Free(rdpContext* context, rdpBitmap* bitmap) { if (bitmap) - { bitmap->Free(context, bitmap); - - if (bitmap->data) - _aligned_free(bitmap->data); - - free(bitmap); - } } BOOL Bitmap_SetRectangle(rdpBitmap* bitmap, diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index 1a0beee..66d32ed 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -675,6 +675,9 @@ static void rdp_write_info_packet(rdpRdp* rdp, wStream* s) if (settings->LogonNotify) flags |= INFO_LOGONNOTIFY; + if (settings->PasswordIsSmartcardPin) + flags |= INFO_PASSWORD_IS_SC_PIN; + if (settings->Domain) { cbDomain = ConvertToUnicode(CP_UTF8, 0, settings->Domain, -1, &domainW, 0) * 2; diff --git a/libfreerdp/core/input.c b/libfreerdp/core/input.c index af45e26..e199ae9 100644 --- a/libfreerdp/core/input.c +++ b/libfreerdp/core/input.c @@ -32,6 +32,15 @@ #define TAG FREERDP_TAG("core") +/* Input Events */ +#define INPUT_EVENT_SYNC 0x0000 +#define INPUT_EVENT_SCANCODE 0x0004 +#define INPUT_EVENT_UNICODE 0x0005 +#define INPUT_EVENT_MOUSE 0x8001 +#define INPUT_EVENT_MOUSEX 0x8002 + +#define RDP_CLIENT_INPUT_PDU_HEADER_LENGTH 4 + static void rdp_write_client_input_pdu_header(wStream* s, UINT16 number) { Stream_Write_UINT16(s, 1); /* numberEvents (2 bytes) */ @@ -44,7 +53,7 @@ static void rdp_write_input_event_header(wStream* s, UINT32 time, UINT16 type) Stream_Write_UINT16(s, type); /* messageType (2 bytes) */ } -wStream* rdp_client_input_pdu_init(rdpRdp* rdp, UINT16 type) +static wStream* rdp_client_input_pdu_init(rdpRdp* rdp, UINT16 type) { wStream* s; s = rdp_data_pdu_init(rdp); @@ -57,7 +66,7 @@ wStream* rdp_client_input_pdu_init(rdpRdp* rdp, UINT16 type) return s; } -BOOL rdp_send_client_input_pdu(rdpRdp* rdp, wStream* s) +static BOOL rdp_send_client_input_pdu(rdpRdp* rdp, wStream* s) { return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_INPUT, rdp->mcs->userId); } @@ -68,7 +77,7 @@ static void input_write_synchronize_event(wStream* s, UINT32 flags) Stream_Write_UINT32(s, flags); /* toggleFlags (4 bytes) */ } -BOOL input_send_synchronize_event(rdpInput* input, UINT32 flags) +static BOOL input_send_synchronize_event(rdpInput* input, UINT32 flags) { wStream* s; rdpRdp* rdp; @@ -93,7 +102,7 @@ static void input_write_keyboard_event(wStream* s, UINT16 flags, UINT16 code) Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ } -BOOL input_send_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) +static BOOL input_send_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { wStream* s; rdpRdp* rdp; @@ -118,7 +127,7 @@ static void input_write_unicode_keyboard_event(wStream* s, UINT16 flags, UINT16 Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ } -BOOL input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) +static BOOL input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { wStream* s; UINT16 keyboardFlags = 0; @@ -127,6 +136,12 @@ BOOL input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 cod if (!input || !input->context) return FALSE; + if (!input->context->settings->UnicodeInput) + { + WLog_WARN(TAG, "Unicode input not supported by server."); + return FALSE; + } + rdp = input->context->rdp; /* * According to the specification, the slow path Unicode Keyboard Event @@ -147,14 +162,14 @@ BOOL input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 cod return rdp_send_client_input_pdu(rdp, s); } -void input_write_mouse_event(wStream* s, UINT16 flags, UINT16 x, UINT16 y) +static void input_write_mouse_event(wStream* s, UINT16 flags, UINT16 x, UINT16 y) { Stream_Write_UINT16(s, flags); /* pointerFlags (2 bytes) */ Stream_Write_UINT16(s, x); /* xPos (2 bytes) */ Stream_Write_UINT16(s, y); /* yPos (2 bytes) */ } -BOOL input_send_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +static BOOL input_send_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { wStream* s; rdpRdp* rdp; @@ -190,7 +205,8 @@ static void input_write_extended_mouse_event(wStream* s, UINT16 flags, UINT16 x, Stream_Write_UINT16(s, y); /* yPos (2 bytes) */ } -BOOL input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +static BOOL input_send_extended_mouse_event(rdpInput* input, UINT16 flags, + UINT16 x, UINT16 y) { wStream* s; rdpRdp* rdp; @@ -198,6 +214,13 @@ BOOL input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UI if (!input || !input->context) return FALSE; + if (!input->context->settings->HasExtendedMouseEvent) + { + WLog_WARN(TAG, "skip extended mouse event %"PRIu16"x%"PRIu16" flags=0x%04"PRIX16", no extended mouse events supported", + x, y, flags); + return TRUE; + } + rdp = input->context->rdp; s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_MOUSEX); @@ -208,7 +231,7 @@ BOOL input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UI return rdp_send_client_input_pdu(rdp, s); } -BOOL input_send_focus_in_event(rdpInput* input, UINT16 toggleStates) +static BOOL input_send_focus_in_event(rdpInput* input, UINT16 toggleStates) { /* send a tab up like mstsc.exe */ if (!input_send_keyboard_event(input, KBD_FLAGS_RELEASE, 0x0f)) @@ -222,7 +245,7 @@ BOOL input_send_focus_in_event(rdpInput* input, UINT16 toggleStates) return input_send_keyboard_event(input, KBD_FLAGS_RELEASE, 0x0f); } -BOOL input_send_keyboard_pause_event(rdpInput* input) +static BOOL input_send_keyboard_pause_event(rdpInput* input) { /* In ancient days, pause-down without control sent E1 1D 45 E1 9D C5, * and pause-up sent nothing. However, reverse engineering mstsc shows @@ -249,7 +272,7 @@ BOOL input_send_keyboard_pause_event(rdpInput* input) RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK)); } -BOOL input_send_fastpath_synchronize_event(rdpInput* input, UINT32 flags) +static BOOL input_send_fastpath_synchronize_event(rdpInput* input, UINT32 flags) { wStream* s; rdpRdp* rdp; @@ -267,7 +290,7 @@ BOOL input_send_fastpath_synchronize_event(rdpInput* input, UINT32 flags) return fastpath_send_input_pdu(rdp->fastpath, s); } -BOOL input_send_fastpath_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) +static BOOL input_send_fastpath_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { wStream* s; BYTE eventFlags = 0; @@ -288,7 +311,7 @@ BOOL input_send_fastpath_keyboard_event(rdpInput* input, UINT16 flags, UINT16 co return fastpath_send_input_pdu(rdp->fastpath, s); } -BOOL input_send_fastpath_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) +static BOOL input_send_fastpath_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { wStream* s; BYTE eventFlags = 0; @@ -297,6 +320,12 @@ BOOL input_send_fastpath_unicode_keyboard_event(rdpInput* input, UINT16 flags, U if (!input || !input->context) return FALSE; + if (!input->context->settings->UnicodeInput) + { + WLog_WARN(TAG, "Unicode input not supported by server."); + return FALSE; + } + rdp = input->context->rdp; eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0; s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_UNICODE); @@ -308,7 +337,8 @@ BOOL input_send_fastpath_unicode_keyboard_event(rdpInput* input, UINT16 flags, U return fastpath_send_input_pdu(rdp->fastpath, s); } -BOOL input_send_fastpath_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +static BOOL input_send_fastpath_mouse_event(rdpInput* input, UINT16 flags, + UINT16 x, UINT16 y) { wStream* s; rdpRdp* rdp; @@ -337,7 +367,8 @@ BOOL input_send_fastpath_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UI return fastpath_send_input_pdu(rdp->fastpath, s); } -BOOL input_send_fastpath_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +static BOOL input_send_fastpath_extended_mouse_event(rdpInput* input, UINT16 flags, + UINT16 x, UINT16 y) { wStream* s; rdpRdp* rdp; @@ -345,6 +376,13 @@ BOOL input_send_fastpath_extended_mouse_event(rdpInput* input, UINT16 flags, UIN if (!input || !input->context) return FALSE; + if (!input->context->settings->HasExtendedMouseEvent) + { + WLog_WARN(TAG, "skip extended mouse event %"PRIu16"x%"PRIu16" flags=0x%04"PRIX16", no extended mouse events supported", + x, y, flags); + return TRUE; + } + rdp = input->context->rdp; s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSEX); @@ -355,7 +393,7 @@ BOOL input_send_fastpath_extended_mouse_event(rdpInput* input, UINT16 flags, UIN return fastpath_send_input_pdu(rdp->fastpath, s); } -BOOL input_send_fastpath_focus_in_event(rdpInput* input, UINT16 toggleStates) +static BOOL input_send_fastpath_focus_in_event(rdpInput* input, UINT16 toggleStates) { wStream* s; BYTE eventFlags = 0; @@ -384,7 +422,7 @@ BOOL input_send_fastpath_focus_in_event(rdpInput* input, UINT16 toggleStates) return fastpath_send_multiple_input_pdu(rdp->fastpath, s, 3); } -BOOL input_send_fastpath_keyboard_pause_event(rdpInput* input) +static BOOL input_send_fastpath_keyboard_pause_event(rdpInput* input) { /* In ancient days, pause-down without control sent E1 1D 45 E1 9D C5, * and pause-up sent nothing. However, reverse engineering mstsc shows diff --git a/libfreerdp/core/input.h b/libfreerdp/core/input.h index a3bb6d5..bf5598c 100644 --- a/libfreerdp/core/input.h +++ b/libfreerdp/core/input.h @@ -30,36 +30,6 @@ #include <winpr/stream.h> -/* Input Events */ -#define INPUT_EVENT_SYNC 0x0000 -#define INPUT_EVENT_SCANCODE 0x0004 -#define INPUT_EVENT_UNICODE 0x0005 -#define INPUT_EVENT_MOUSE 0x8001 -#define INPUT_EVENT_MOUSEX 0x8002 - -#define RDP_CLIENT_INPUT_PDU_HEADER_LENGTH 4 - -FREERDP_LOCAL BOOL input_send_synchronize_event(rdpInput* input, UINT32 flags); -FREERDP_LOCAL BOOL input_send_keyboard_event(rdpInput* input, UINT16 flags, - UINT16 code); -FREERDP_LOCAL BOOL input_send_unicode_keyboard_event(rdpInput* input, - UINT16 flags, UINT16 code); -FREERDP_LOCAL BOOL input_send_mouse_event(rdpInput* input, UINT16 flags, - UINT16 x, UINT16 y); -FREERDP_LOCAL BOOL input_send_extended_mouse_event(rdpInput* input, - UINT16 flags, UINT16 x, UINT16 y); - -FREERDP_LOCAL BOOL input_send_fastpath_synchronize_event(rdpInput* input, - UINT32 flags); -FREERDP_LOCAL BOOL input_send_fastpath_keyboard_event(rdpInput* input, - UINT16 flags, UINT16 code); -FREERDP_LOCAL BOOL input_send_fastpath_unicode_keyboard_event(rdpInput* input, - UINT16 flags, UINT16 code); -FREERDP_LOCAL BOOL input_send_fastpath_mouse_event(rdpInput* input, - UINT16 flags, UINT16 x, UINT16 y); -FREERDP_LOCAL BOOL input_send_fastpath_extended_mouse_event(rdpInput* input, - UINT16 flags, UINT16 x, UINT16 y); - FREERDP_LOCAL BOOL input_recv(rdpInput* input, wStream* s); FREERDP_LOCAL int input_process_events(rdpInput* input); diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index 407e769..ed8b68a 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -233,7 +233,7 @@ wStream* license_send_stream_init(rdpLicense* license) BOOL license_send(rdpLicense* license, wStream* s, BYTE type) { - int length; + size_t length; BYTE flags; UINT16 wMsgSize; rdpRdp* rdp = license->rdp; @@ -424,7 +424,10 @@ BOOL license_generate_hwid(rdpLicense* license) ZeroMemory(macAddress, sizeof(macAddress)); ZeroMemory(license->HardwareId, HWID_LENGTH); - if (!winpr_Digest(WINPR_MD_MD5, macAddress, sizeof(macAddress), &license->HardwareId[HWID_PLATFORM_ID_LENGTH], WINPR_MD5_DIGEST_LENGTH)) + /* Allow FIPS override for use of MD5 here, really this does not have to be MD5 as we are just taking a MD5 hash of the 6 bytes of 0's(macAddress) */ + /* and filling in the Data1-Data4 fields of the CLIENT_HARDWARE_ID structure(from MS-RDPELE section 2.2.2.3.1). This is for RDP licensing packets */ + /* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data protection. */ + if (!winpr_Digest_Allow_FIPS(WINPR_MD_MD5, macAddress, sizeof(macAddress), &license->HardwareId[HWID_PLATFORM_ID_LENGTH], WINPR_MD5_DIGEST_LENGTH)) return FALSE; return TRUE; @@ -495,7 +498,10 @@ BOOL license_decrypt_platform_challenge(rdpLicense* license) return FALSE; license->PlatformChallenge->length = license->EncryptedPlatformChallenge->length; - if ((rc4 = winpr_RC4_New(license->LicensingEncryptionKey, + /* Allow FIPS override for use of RC4 here, this is only used for decrypting the MACData field of the */ + /* Server Platform Challenge packet (from MS-RDPELE section 2.2.2.4). This is for RDP licensing packets */ + /* which will already be encrypted under FIPS, so the use of RC4 here is not for sensitive data protection. */ + if ((rc4 = winpr_RC4_New_Allow_FIPS(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH)) == NULL) { free(license->PlatformChallenge->data); @@ -1089,7 +1095,10 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license) if (!status) return FALSE; - rc4 = winpr_RC4_New(license->LicensingEncryptionKey, + /* Allow FIPS override for use of RC4 here, this is only used for encrypting the EncryptedHWID field of the */ + /* Client Platform Challenge Response packet (from MS-RDPELE section 2.2.2.5). This is for RDP licensing packets */ + /* which will already be encrypted under FIPS, so the use of RC4 here is not for sensitive data protection. */ + rc4 = winpr_RC4_New_Allow_FIPS(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH); if (!rc4) return FALSE; diff --git a/libfreerdp/core/listener.c b/libfreerdp/core/listener.c index 6fb48c8..6598d9e 100644 --- a/libfreerdp/core/listener.c +++ b/libfreerdp/core/listener.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> #include <fcntl.h> +#include <errno.h> #include <winpr/crt.h> #include <winpr/windows.h> @@ -63,7 +64,6 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a #ifdef _WIN32 u_long arg; #endif - hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; @@ -108,7 +108,6 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr); inet_ntop(ai->ai_family, sin_addr, addr, sizeof(addr)); - option_value = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &option_value, sizeof(option_value)) == -1) @@ -120,7 +119,6 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a arg = 1; ioctlsocket(sockfd, FIONBIO, &arg); #endif - status = _bind((SOCKET) sockfd, ai->ai_addr, ai->ai_addrlen); if (status != 0) @@ -139,22 +137,21 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a } /* FIXME: these file descriptors do not work on Windows */ - listener->sockfds[listener->num_sockfds] = sockfd; listener->events[listener->num_sockfds] = WSACreateEvent(); + if (!listener->events[listener->num_sockfds]) { listener->num_sockfds = 0; break; } + WSAEventSelect(sockfd, listener->events[listener->num_sockfds], FD_READ | FD_ACCEPT | FD_CLOSE); listener->num_sockfds++; - WLog_INFO(TAG, "Listening on %s:%s", addr, servname); } freeaddrinfo(res); - return (listener->num_sockfds > 0 ? TRUE : FALSE); } @@ -182,11 +179,9 @@ static BOOL freerdp_listener_open_local(freerdp_listener* instance, const char* } fcntl(sockfd, F_SETFL, O_NONBLOCK); - addr.sun_family = AF_UNIX; strncpy(addr.sun_path, path, sizeof(addr.sun_path)); unlink(path); - status = _bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)); if (status != 0) @@ -206,6 +201,7 @@ static BOOL freerdp_listener_open_local(freerdp_listener* instance, const char* } hevent = CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd, WINPR_FD_READ); + if (!hevent) { WLog_ERR(TAG, "failed to create sockfd event"); @@ -239,25 +235,22 @@ static BOOL freerdp_listener_open_from_socket(freerdp_listener* instance, int fd listener->sockfds[listener->num_sockfds] = fd; listener->events[listener->num_sockfds] = - CreateFileDescriptorEvent(NULL, FALSE, FALSE, fd, WINPR_FD_READ); + CreateFileDescriptorEvent(NULL, FALSE, FALSE, fd, WINPR_FD_READ); + if (!listener->events[listener->num_sockfds]) return FALSE; listener->num_sockfds++; - WLog_INFO(TAG, "Listening on socket %d.", fd); return TRUE; #else return FALSE; #endif - - } static void freerdp_listener_close(freerdp_listener* instance) { int i; - rdpListener* listener = (rdpListener*) instance->listener; for (i = 0; i < listener->num_sockfds; i++) @@ -323,7 +316,6 @@ static BOOL freerdp_listener_check_fds(freerdp_listener* instance) for (i = 0; i < listener->num_sockfds; i++) { WSAResetEvent(listener->events[i]); - peer_addr_size = sizeof(peer_addr); peer_sockfd = _accept(listener->sockfds[i], (struct sockaddr*) &peer_addr, &peer_addr_size); peer_accepted = FALSE; @@ -336,17 +328,20 @@ static BOOL freerdp_listener_check_fds(freerdp_listener* instance) /* No data available */ if (wsa_error == WSAEWOULDBLOCK) continue; + #else + if (errno == EAGAIN || errno == EWOULDBLOCK) continue; + #endif WLog_DBG(TAG, "accept"); - free(client); return FALSE; } client = freerdp_peer_new(peer_sockfd); + if (!client) { closesocket((SOCKET) peer_sockfd); @@ -354,21 +349,26 @@ static BOOL freerdp_listener_check_fds(freerdp_listener* instance) } sin_addr = NULL; + if (peer_addr.ss_family == AF_INET) { sin_addr = &(((struct sockaddr_in*) &peer_addr)->sin_addr); + if ((*(UINT32*) sin_addr) == 0x0100007f) client->local = TRUE; } else if (peer_addr.ss_family == AF_INET6) { sin_addr = &(((struct sockaddr_in6*) &peer_addr)->sin6_addr); + if (memcmp(sin_addr, localhost6_bytes, 16) == 0) client->local = TRUE; } + #ifndef _WIN32 else if (peer_addr.ss_family == AF_UNIX) client->local = TRUE; + #endif if (sin_addr) @@ -391,7 +391,6 @@ freerdp_listener* freerdp_listener_new(void) { freerdp_listener* instance; rdpListener* listener; - instance = (freerdp_listener*) calloc(1, sizeof(freerdp_listener)); if (!instance) @@ -404,25 +403,21 @@ freerdp_listener* freerdp_listener_new(void) instance->GetEventHandles = freerdp_listener_get_event_handles; instance->CheckFileDescriptor = freerdp_listener_check_fds; instance->Close = freerdp_listener_close; - listener = (rdpListener*) calloc(1, sizeof(rdpListener)); if (!listener) { - free (instance); + free(instance); return NULL; } listener->instance = instance; - instance->listener = (void*) listener; - return instance; } void freerdp_listener_free(freerdp_listener* instance) { - if (instance) { free(instance->listener); diff --git a/libfreerdp/core/mcs.c b/libfreerdp/core/mcs.c index cadaa9f..523ff74 100644 --- a/libfreerdp/core/mcs.c +++ b/libfreerdp/core/mcs.c @@ -300,7 +300,7 @@ static BOOL mcs_init_domain_parameters(DomainParameters* domainParameters, static BOOL mcs_read_domain_parameters(wStream* s, DomainParameters* domainParameters) { - int length; + size_t length; if (!s || !domainParameters) return FALSE; @@ -325,7 +325,7 @@ static BOOL mcs_read_domain_parameters(wStream* s, DomainParameters* domainParam static BOOL mcs_write_domain_parameters(wStream* s, DomainParameters* domainParameters) { - int length; + size_t length; wStream* tmps; if (!s || !domainParameters) @@ -508,7 +508,7 @@ BOOL mcs_merge_domain_parameters(DomainParameters* targetParameters, BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s) { UINT16 li; - int length; + size_t length; BOOL upwardFlag; UINT16 tlength; @@ -575,7 +575,7 @@ BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s) BOOL mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData) { - int length; + size_t length; wStream* tmps; BOOL ret = FALSE; @@ -631,7 +631,7 @@ out: BOOL mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData) { - int length; + size_t length; wStream* tmps; BOOL ret = FALSE; @@ -672,9 +672,9 @@ out: BOOL mcs_send_connect_initial(rdpMcs* mcs) { int status = -1; - int length; + size_t length; wStream* s = NULL; - int bm, em; + size_t bm, em; wStream* gcc_CCrq = NULL; wStream* client_data = NULL; @@ -741,7 +741,7 @@ out: BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s) { - int length; + size_t length; UINT16 tlength; BYTE result; UINT16 li; @@ -782,10 +782,10 @@ BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s) BOOL mcs_send_connect_response(rdpMcs* mcs) { - int length; + size_t length; int status; wStream* s; - int bm, em; + size_t bm, em; wStream* gcc_CCrsp; wStream* server_data; diff --git a/libfreerdp/core/message.c b/libfreerdp/core/message.c index ef4c736..bb5edbf 100644 --- a/libfreerdp/core/message.c +++ b/libfreerdp/core/message.c @@ -196,13 +196,15 @@ static BOOL update_message_SetKeyboardIndicators(rdpContext* context, UINT16 led MakeMessageId(Update, SetKeyboardIndicators), (void*)(size_t)led_flags, NULL); } -static BOOL update_message_SetKeyboardImeStatus(rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode) +static BOOL update_message_SetKeyboardImeStatus(rdpContext* context, UINT16 imeId, UINT32 imeState, + UINT32 imeConvMode) { if (!context || !context->update) return FALSE; return MessageQueue_Post(context->update->queue, (void*) context, - MakeMessageId(Update, SetKeyboardImeStatus), (void*)(size_t)((imeId << 16UL) | imeState), (void*)(size_t) imeConvMode); + MakeMessageId(Update, SetKeyboardImeStatus), (void*)(size_t)((imeId << 16UL) | imeState), + (void*)(size_t) imeConvMode); } static BOOL update_message_RefreshRect(rdpContext* context, BYTE count, @@ -278,17 +280,17 @@ static BOOL update_message_SurfaceBits(rdpContext* context, CopyMemory(wParam, surfaceBitsCommand, sizeof(SURFACE_BITS_COMMAND)); #ifdef WITH_STREAM_POOL - StreamPool_AddRef(context->rdp->transport->ReceivePool, surfaceBitsCommand->bitmapData); + StreamPool_AddRef(context->rdp->transport->ReceivePool, surfaceBitsCommand->bmp.bitmapData); #else - wParam->bitmapData = (BYTE*) malloc(wParam->bitmapDataLength); + wParam->bmp.bitmapData = (BYTE*) malloc(wParam->bmp.bitmapDataLength); - if (!wParam->bitmapData) + if (!wParam->bmp.bitmapData) { free(wParam); return FALSE; } - CopyMemory(wParam->bitmapData, surfaceBitsCommand->bitmapData, wParam->bitmapDataLength); + CopyMemory(wParam->bmp.bitmapData, surfaceBitsCommand->bmp.bitmapData, wParam->bmp.bitmapDataLength); #endif return MessageQueue_Post(context->update->queue, (void*) context, MakeMessageId(Update, SurfaceBits), (void*) wParam, NULL); @@ -1700,10 +1702,10 @@ static int update_message_free_update_class(wMessage* msg, int type) #ifdef WITH_STREAM_POOL rdpContext* context = (rdpContext*) msg->context; SURFACE_BITS_COMMAND* wParam = (SURFACE_BITS_COMMAND*) msg->wParam; - StreamPool_Release(context->rdp->transport->ReceivePool, wParam->bitmapData); + StreamPool_Release(context->rdp->transport->ReceivePool, wParam->bmp.bitmapData); #else SURFACE_BITS_COMMAND* wParam = (SURFACE_BITS_COMMAND*) msg->wParam; - free(wParam->bitmapData); + free(wParam->bmp.bitmapData); free(wParam); #endif } @@ -2632,7 +2634,7 @@ int update_message_queue_process_message(rdpUpdate* update, wMessage* message) update_message_free_class(message, msgClass, msgType); if (status < 0) - status = -1; + return -1; return 1; } @@ -2849,7 +2851,7 @@ static BOOL update_message_register_interface(rdpUpdateProxy* message, rdpUpdate return TRUE; } -static void* update_message_proxy_thread(void* arg) +static DWORD WINAPI update_message_proxy_thread(LPVOID arg) { rdpUpdate* update = (rdpUpdate*)arg; wMessage message; @@ -2858,8 +2860,8 @@ static void* update_message_proxy_thread(void* arg) { WLog_ERR(TAG, "update=%p, update->queue=%p", (void*) update, (void*)(update ? update->queue : NULL)); - ExitThread(-1); - return NULL; + ExitThread(1); + return 1; } while (MessageQueue_Wait(update->queue)) @@ -2874,7 +2876,7 @@ static void* update_message_proxy_thread(void* arg) } ExitThread(0); - return NULL; + return 0; } rdpUpdateProxy* update_message_proxy_new(rdpUpdate* update) @@ -2890,7 +2892,7 @@ rdpUpdateProxy* update_message_proxy_new(rdpUpdate* update) message->update = update; update_message_register_interface(message, update); - if (!(message->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) update_message_proxy_thread, + if (!(message->thread = CreateThread(NULL, 0, update_message_proxy_thread, update, 0, NULL))) { WLog_ERR(TAG, "Failed to create proxy thread"); diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c index 068a603..ab4db4e 100644 --- a/libfreerdp/core/nego.c +++ b/libfreerdp/core/nego.c @@ -665,7 +665,7 @@ static BOOL nego_read_request_token_or_cookie(rdpNego* nego, wStream* s) BYTE *str = NULL; UINT16 crlf = 0; - int pos, len; + size_t pos, len; BOOL result = FALSE; BOOL isToken = FALSE; @@ -808,7 +808,7 @@ BOOL nego_send_negotiation_request(rdpNego* nego) { wStream* s; int length; - int bm, em; + size_t bm, em; BYTE flags = 0; int cookie_length; @@ -834,7 +834,7 @@ BOOL nego_send_negotiation_request(rdpNego* nego) (nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A)) { WLog_DBG(TAG, "Routing token looks correctly terminated - use verbatim"); - length +=nego->RoutingTokenLength; + length += nego->RoutingTokenLength; } else { @@ -997,7 +997,7 @@ void nego_process_negotiation_failure(rdpNego* nego, wStream* s) BOOL nego_send_negotiation_response(rdpNego* nego) { int length; - int bm, em; + size_t bm, em; BOOL status; wStream* s; BYTE flags; diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c index 63966f5..0f1eb1f 100644 --- a/libfreerdp/core/nla.c +++ b/libfreerdp/core/nla.c @@ -1,11 +1,12 @@ /** - * WinPR: Windows Portable Runtime + * FreeRDP: A Remote Desktop Protocol Implementation * Network Level Authentication (NLA) * * Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com> * Copyright 2016 Martin Fleisz <martin.fleisz@thincast.com> + * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -94,7 +95,7 @@ * */ -#define NLA_PKG_NAME NEGOSSP_NAME +#define NLA_PKG_NAME NEGO_SSP_NAME #define TERMSRV_SPN_PREFIX "TERMSRV/" @@ -103,7 +104,9 @@ static int nla_recv(rdpNla* nla); static void nla_buffer_print(rdpNla* nla); static void nla_buffer_free(rdpNla* nla); static SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla); +static SECURITY_STATUS nla_encrypt_public_key_hash(rdpNla* nla); static SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla); +static SECURITY_STATUS nla_decrypt_public_key_hash(rdpNla* nla); static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla); static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla); static BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s); @@ -112,10 +115,33 @@ static void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity); #define ber_sizeof_sequence_octet_string(length) ber_sizeof_contextual_tag(ber_sizeof_octet_string(length)) + ber_sizeof_octet_string(length) #define ber_write_sequence_octet_string(stream, context, value, length) ber_write_contextual_tag(stream, context, ber_sizeof_octet_string(length), TRUE) + ber_write_octet_string(stream, value, length) +/* CredSSP Client-To-Server Binding Hash\0 */ +static const BYTE ClientServerHashMagic[] = +{ + 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20, + 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x54, + 0x6F, 0x2D, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67, + 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 +}; + +/* CredSSP Server-To-Client Binding Hash\0 */ +static const BYTE ServerClientHashMagic[] = +{ + 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2D, 0x54, + 0x6F, 0x2D, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, + 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67, + 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 +}; + +static const UINT32 NonceLength = 32; + void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity) { if (identity) { + /* Password authentication */ if (identity->User) { memset(identity->User, 0, identity->UserLength * 2); @@ -139,14 +165,14 @@ void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity) } /** - * Initialize NTLMSSP authentication module (client). + * Initialize NTLM/Kerberos SSP authentication module (client). * @param credssp */ -int nla_client_init(rdpNla* nla) +static int nla_client_init(rdpNla* nla) { char* spn; - int length; + size_t length; rdpTls* tls = NULL; BOOL PromptPassword = FALSE; freerdp* instance = nla->instance; @@ -158,8 +184,9 @@ int nla_client_init(rdpNla* nla) if (settings->RestrictedAdminModeRequired) settings->DisableCredentialsDelegation = TRUE; - if ((!settings->Password) || (!settings->Username) - || (!strlen(settings->Username))) + if ((!settings->Username) || (!strlen(settings->Username)) + || (((!settings->Password) || (!strlen(settings->Password))) + && (!settings->RedirectionPassword))) { PromptPassword = TRUE; } @@ -220,8 +247,21 @@ int nla_client_init(rdpNla* nla) nla->identity = NULL; } else - sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain, - settings->Password); + { + if (settings->RedirectionPassword && settings->RedirectionPasswordLength > 0) + { + if (sspi_SetAuthIdentityWithUnicodePassword(nla->identity, settings->Username, settings->Domain, + (UINT16*) settings->RedirectionPassword, + settings->RedirectionPasswordLength / sizeof(WCHAR) - 1) < 0) + return -1; + } + else + { + if (sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain, + settings->Password) < 0) + return -1; + } + } #ifndef _WIN32 { @@ -262,7 +302,7 @@ int nla_client_init(rdpNla* nla) if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength)) { - WLog_ERR(TAG, "Failed to allocate sspic secBuffer"); + WLog_ERR(TAG, "Failed to allocate sspi secBuffer"); return -1; } @@ -282,6 +322,17 @@ int nla_client_init(rdpNla* nla) nla->ServicePrincipalName = spn; #endif nla->table = InitSecurityInterfaceEx(0); +#ifdef WITH_GSSAPI /* KERBEROS SSP */ + nla->status = nla->table->QuerySecurityPackageInfo(KERBEROS_SSP_NAME, &nla->pPackageInfo); + + if (nla->status != SEC_E_OK) + { + WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08"PRIX32"]", + GetSecurityStatusString(nla->status), nla->status); + return -1; + } + +#else /* NTLM SSP */ nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo); if (nla->status != SEC_E_OK) @@ -291,7 +342,11 @@ int nla_client_init(rdpNla* nla) return -1; } +#endif nla->cbMaxToken = nla->pPackageInfo->cbMaxToken; + nla->packageName = nla->pPackageInfo->Name; + WLog_DBG(TAG, "%s %"PRIu32" : packageName=%ls ; cbMaxToken=%d", __FUNCTION__, __LINE__, + nla->packageName, nla->cbMaxToken); nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME, SECPKG_CRED_OUTBOUND, NULL, nla->identity, NULL, NULL, &nla->credentials, &nla->expiration); @@ -345,6 +400,33 @@ int nla_client_begin(rdpNla* nla) WLog_VRB(TAG, " InitializeSecurityContext status %s [0x%08"PRIX32"]", GetSecurityStatusString(nla->status), nla->status); + /* Handle kerberos context initialization failure. + * After kerberos failed initialize NTLM context */ + if (nla->status == SEC_E_NO_CREDENTIALS) + { + nla->status = nla->table->InitializeSecurityContext(&nla->credentials, + NULL, nla->ServicePrincipalName, nla->fContextReq, 0, + SECURITY_NATIVE_DREP, NULL, 0, &nla->context, + &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration); + WLog_VRB(TAG, " InitializeSecurityContext status %s [0x%08"PRIX32"]", + GetSecurityStatusString(nla->status), nla->status); + + if (nla->status) + { + SECURITY_STATUS status = nla->table->QuerySecurityPackageInfo(NTLM_SSP_NAME, &nla->pPackageInfo); + + if (status != SEC_E_OK) + { + WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08"PRIX32"]", + GetSecurityStatusString(nla->status), status); + return -1; + } + + nla->cbMaxToken = nla->pPackageInfo->cbMaxToken; + nla->packageName = nla->pPackageInfo->Name; + } + } + if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED)) { if (nla->table->CompleteAuthToken) @@ -388,7 +470,7 @@ int nla_client_begin(rdpNla* nla) return 1; } -int nla_client_recv(rdpNla* nla) +static int nla_client_recv(rdpNla* nla) { int status = -1; @@ -453,7 +535,10 @@ int nla_client_recv(rdpNla* nla) return -1; } - nla->status = nla_encrypt_public_key_echo(nla); + if (nla->peerVersion < 5) + nla->status = nla_encrypt_public_key_echo(nla); + else + nla->status = nla_encrypt_public_key_hash(nla); if (nla->status != SEC_E_OK) return -1; @@ -480,7 +565,11 @@ int nla_client_recv(rdpNla* nla) else if (nla->state == NLA_STATE_PUB_KEY_AUTH) { /* Verify Server Public Key Echo */ - nla->status = nla_decrypt_public_key_echo(nla); + if (nla->peerVersion < 5) + nla->status = nla_decrypt_public_key_echo(nla); + else + nla->status = nla_decrypt_public_key_hash(nla); + nla_buffer_free(nla); if (nla->status != SEC_E_OK) @@ -507,7 +596,12 @@ int nla_client_recv(rdpNla* nla) } nla_buffer_free(nla); - nla->table->FreeCredentialsHandle(&nla->credentials); + + if (SecIsValidHandle(&nla->credentials)) + { + nla->table->FreeCredentialsHandle(&nla->credentials); + SecInvalidateHandle(&nla->credentials); + } if (nla->status != SEC_E_OK) { @@ -533,7 +627,7 @@ int nla_client_recv(rdpNla* nla) return status; } -int nla_client_authenticate(rdpNla* nla) +static int nla_client_authenticate(rdpNla* nla) { wStream* s; int status; @@ -581,7 +675,7 @@ int nla_client_authenticate(rdpNla* nla) * @param credssp */ -int nla_server_init(rdpNla* nla) +static int nla_server_init(rdpNla* nla) { rdpTls* tls = nla->transport->tls; @@ -627,6 +721,7 @@ int nla_server_init(rdpNla* nla) } nla->cbMaxToken = nla->pPackageInfo->cbMaxToken; + nla->packageName = nla->pPackageInfo->Name; nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME, SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &nla->credentials, &nla->expiration); @@ -668,7 +763,7 @@ int nla_server_init(rdpNla* nla) * @return 1 if authentication is successful */ -int nla_server_authenticate(rdpNla* nla) +static int nla_server_authenticate(rdpNla* nla) { if (nla_server_init(nla) < 1) return -1; @@ -716,28 +811,33 @@ int nla_server_authenticate(rdpNla* nla) if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED)) { - freerdp_peer *peer = nla->instance->context->peer; + freerdp_peer* peer = nla->instance->context->peer; if (peer->ComputeNtlmHash) { SECURITY_STATUS status; + status = nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_HASH_CB, + peer->ComputeNtlmHash, 0); - status = nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_HASH_CB, peer->ComputeNtlmHash, 0); if (status != SEC_E_OK) { - WLog_ERR(TAG, "SetContextAttributesA(hash cb) status %s [0x%08"PRIX32"]", GetSecurityStatusString(status), status); + WLog_ERR(TAG, "SetContextAttributesA(hash cb) status %s [0x%08"PRIX32"]", + GetSecurityStatusString(status), status); } - status = nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_HASH_CB_DATA, peer, 0); + status = nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_HASH_CB_DATA, peer, + 0); + if (status != SEC_E_OK) { - WLog_ERR(TAG, "SetContextAttributesA(hash cb data) status %s [0x%08"PRIX32"]", GetSecurityStatusString(status), status); + WLog_ERR(TAG, "SetContextAttributesA(hash cb data) status %s [0x%08"PRIX32"]", + GetSecurityStatusString(status), status); } } else if (nla->SamFile) { nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_SAM_FILE, nla->SamFile, - strlen(nla->SamFile) + 1); + strlen(nla->SamFile) + 1); } if (nla->table->CompleteAuthToken) @@ -778,7 +878,7 @@ int nla_server_authenticate(rdpNla* nla) nla->havePubKeyAuth = TRUE; nla->status = nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES, - &nla->ContextSizes); + &nla->ContextSizes); if (nla->status != SEC_E_OK) { @@ -787,7 +887,10 @@ int nla_server_authenticate(rdpNla* nla) return -1; } - nla->status = nla_decrypt_public_key_echo(nla); + if (nla->peerVersion < 5) + nla->status = nla_decrypt_public_key_echo(nla); + else + nla->status = nla_decrypt_public_key_hash(nla); if (nla->status != SEC_E_OK) { @@ -799,7 +902,11 @@ int nla_server_authenticate(rdpNla* nla) sspi_SecBufferFree(&nla->negoToken); nla->negoToken.pvBuffer = NULL; nla->negoToken.cbBuffer = 0; - nla->status = nla_encrypt_public_key_echo(nla); + + if (nla->peerVersion < 5) + nla->status = nla_encrypt_public_key_echo(nla); + else + nla->status = nla_encrypt_public_key_hash(nla); if (nla->status != SEC_E_OK) return -1; @@ -913,7 +1020,7 @@ int nla_authenticate(rdpNla* nla) return nla_client_authenticate(nla); } -void ap_integer_increment_le(BYTE* number, int size) +static void ap_integer_increment_le(BYTE* number, int size) { int index; @@ -932,7 +1039,7 @@ void ap_integer_increment_le(BYTE* number, int size) } } -void ap_integer_decrement_le(BYTE* number, int size) +static void ap_integer_decrement_le(BYTE* number, int size) { int index; @@ -953,24 +1060,37 @@ void ap_integer_decrement_le(BYTE* number, int size) SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla) { - SecBuffer Buffers[2]; + SecBuffer Buffers[2] = { { 0 } }; SecBufferDesc Message; SECURITY_STATUS status; - int public_key_length; + ULONG public_key_length; + const BOOL krb = (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0); + const BOOL nego = (_tcsncmp(nla->packageName, NEGO_SSP_NAME, ARRAYSIZE(NEGO_SSP_NAME)) == 0); + const BOOL ntlm = (_tcsncmp(nla->packageName, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0); public_key_length = nla->PublicKey.cbBuffer; - if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, nla->ContextSizes.cbSecurityTrailer + public_key_length)) + if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, public_key_length + nla->ContextSizes.cbSecurityTrailer)) return SEC_E_INSUFFICIENT_MEMORY; - Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ - Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; - Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer; - Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */ - Buffers[1].cbBuffer = public_key_length; - Buffers[1].pvBuffer = ((BYTE*) nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer; - CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer); + if (krb) + { + Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */ + Buffers[0].cbBuffer = public_key_length; + Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer; + CopyMemory(Buffers[0].pvBuffer, nla->PublicKey.pvBuffer, Buffers[0].cbBuffer); + } + else if (ntlm || nego) + { + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; + Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer; + Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */ + Buffers[1].cbBuffer = public_key_length; + Buffers[1].pvBuffer = ((BYTE*) nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer; + CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer); + } - if (nla->server) + if (!krb && nla->server) { /* server echos the public key +1 */ ap_integer_increment_le((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer); @@ -988,65 +1108,174 @@ SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla) return status; } - if (Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer) + return status; +} + +SECURITY_STATUS nla_encrypt_public_key_hash(rdpNla* nla) +{ + SecBuffer Buffers[2] = { { 0 } }; + SecBufferDesc Message; + SECURITY_STATUS status = SEC_E_INTERNAL_ERROR; + WINPR_DIGEST_CTX* sha256 = NULL; + const BOOL krb = (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0); + const ULONG auth_data_length = krb ? WINPR_SHA256_DIGEST_LENGTH : + (nla->ContextSizes.cbSecurityTrailer + + WINPR_SHA256_DIGEST_LENGTH); + const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic; + const size_t hashSize = nla->server ? sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic); + + if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, auth_data_length)) { - /* EncryptMessage may not use all the signature space, so we need to shrink the excess */ - MoveMemory(((BYTE*)nla->pubKeyAuth.pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer, - Buffers[1].cbBuffer); - nla->pubKeyAuth.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer; + status = SEC_E_INSUFFICIENT_MEMORY; + goto out; } + /* generate SHA256 of following data: ClientServerHashMagic, Nonce, SubjectPublicKey */ + if (!(sha256 = winpr_Digest_New())) + goto out; + + if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256)) + goto out; + + /* include trailing \0 from hashMagic */ + if (!winpr_Digest_Update(sha256, hashMagic, hashSize)) + goto out; + + if (!winpr_Digest_Update(sha256, nla->ClientNonce.pvBuffer, nla->ClientNonce.cbBuffer)) + goto out; + + /* SubjectPublicKey */ + if (!winpr_Digest_Update(sha256, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer)) + goto out; + + Message.pBuffers = (PSecBuffer)&Buffers; + Message.ulVersion = SECBUFFER_VERSION; + + if (krb) + { + Message.cBuffers = 1; + Buffers[0].BufferType = SECBUFFER_DATA; /* SHA256 hash */ + Buffers[0].cbBuffer = WINPR_SHA256_DIGEST_LENGTH; + Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer; + + if (!winpr_Digest_Final(sha256, Buffers[0].pvBuffer, Buffers[0].cbBuffer)) + goto out; + } + else + { + Message.cBuffers = 2; + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; + Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer; + Buffers[1].BufferType = SECBUFFER_DATA; /* SHA256 hash */ + Buffers[1].cbBuffer = WINPR_SHA256_DIGEST_LENGTH; + Buffers[1].pvBuffer = ((BYTE*)nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer; + + if (!winpr_Digest_Final(sha256, Buffers[1].pvBuffer, Buffers[1].cbBuffer)) + goto out; + } + + /* encrypt message */ + status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++); + + if (status != SEC_E_OK) + { + WLog_ERR(TAG, "EncryptMessage status %s [0x%08"PRIX32"]", + GetSecurityStatusString(status), status); + } + +out: + winpr_Digest_Free(sha256); return status; } SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla) { - int length; - BYTE* buffer; + ULONG length; + BYTE* buffer = NULL; ULONG pfQOP = 0; - BYTE* public_key1; - BYTE* public_key2; - int public_key_length; + BYTE* public_key1 = NULL; + BYTE* public_key2 = NULL; + ULONG public_key_length = 0; int signature_length; - SecBuffer Buffers[2]; + SecBuffer Buffers[2] = { { 0 } }; SecBufferDesc Message; - SECURITY_STATUS status; + BOOL krb, ntlm, nego; + SECURITY_STATUS status = SEC_E_INVALID_TOKEN; + + if (!nla) + goto fail; + + krb = (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0); + nego = (_tcsncmp(nla->packageName, NEGO_SSP_NAME, ARRAYSIZE(NEGO_SSP_NAME)) == 0); + ntlm = (_tcsncmp(nla->packageName, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0); signature_length = nla->pubKeyAuth.cbBuffer - nla->PublicKey.cbBuffer; - if (signature_length < 0 || signature_length > nla->ContextSizes.cbSecurityTrailer) + if ((signature_length < 0) || (signature_length > nla->ContextSizes.cbSecurityTrailer)) { WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %"PRIu32"", nla->pubKeyAuth.cbBuffer); - return SEC_E_INVALID_TOKEN; + goto fail; + } + + if ((nla->PublicKey.cbBuffer + nla->ContextSizes.cbSecurityTrailer) != nla->pubKeyAuth.cbBuffer) + { + WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %"PRIu32"", nla->pubKeyAuth.cbBuffer); + goto fail; } length = nla->pubKeyAuth.cbBuffer; buffer = (BYTE*) malloc(length); if (!buffer) - return SEC_E_INSUFFICIENT_MEMORY; + { + status = SEC_E_INSUFFICIENT_MEMORY; + goto fail; + } + + if (krb) + { + CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length); + Buffers[0].BufferType = SECBUFFER_DATA; /* Wrapped and encrypted TLS Public Key */ + Buffers[0].cbBuffer = length; + Buffers[0].pvBuffer = buffer; + Message.cBuffers = 1; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } + else if (ntlm || nego) + { + CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length); + public_key_length = nla->PublicKey.cbBuffer; + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[0].cbBuffer = signature_length; + Buffers[0].pvBuffer = buffer; + Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */ + Buffers[1].cbBuffer = length - signature_length; + Buffers[1].pvBuffer = buffer + signature_length; + Message.cBuffers = 2; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } - CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length); - public_key_length = nla->PublicKey.cbBuffer; - Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ - Buffers[0].cbBuffer = signature_length; - Buffers[0].pvBuffer = buffer; - Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */ - Buffers[1].cbBuffer = length - signature_length; - Buffers[1].pvBuffer = buffer + signature_length; - Message.cBuffers = 2; - Message.ulVersion = SECBUFFER_VERSION; - Message.pBuffers = (PSecBuffer) &Buffers; status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP); if (status != SEC_E_OK) { WLog_ERR(TAG, "DecryptMessage failure %s [%08"PRIX32"]", GetSecurityStatusString(status), status); - return status; + goto fail; } - public_key1 = (BYTE*) nla->PublicKey.pvBuffer; - public_key2 = (BYTE*) Buffers[1].pvBuffer; + if (krb) + { + public_key1 = public_key2 = (BYTE*) nla->pubKeyAuth.pvBuffer ; + public_key_length = length; + } + else if (ntlm || nego) + { + public_key1 = (BYTE*) nla->PublicKey.pvBuffer; + public_key2 = (BYTE*) Buffers[1].pvBuffer; + } if (!nla->server) { @@ -1054,23 +1283,132 @@ SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla) ap_integer_decrement_le(public_key2, public_key_length); } - if (memcmp(public_key1, public_key2, public_key_length) != 0) + if (!public_key1 || !public_key2 || memcmp(public_key1, public_key2, public_key_length) != 0) { WLog_ERR(TAG, "Could not verify server's public key echo"); WLog_ERR(TAG, "Expected (length = %d):", public_key_length); winpr_HexDump(TAG, WLOG_ERROR, public_key1, public_key_length); WLog_ERR(TAG, "Actual (length = %d):", public_key_length); winpr_HexDump(TAG, WLOG_ERROR, public_key2, public_key_length); - return SEC_E_MESSAGE_ALTERED; /* DO NOT SEND CREDENTIALS! */ + status = SEC_E_MESSAGE_ALTERED; /* DO NOT SEND CREDENTIALS! */ + goto fail; } + status = SEC_E_OK; +fail: free(buffer); - return SEC_E_OK; + return status; } -int nla_sizeof_ts_password_creds(rdpNla* nla) +SECURITY_STATUS nla_decrypt_public_key_hash(rdpNla* nla) { - int length = 0; + unsigned long length; + BYTE* buffer = NULL; + ULONG pfQOP = 0; + int signature_length; + SecBuffer Buffers[2] = { { 0 } }; + SecBufferDesc Message; + WINPR_DIGEST_CTX* sha256 = NULL; + BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH]; + SECURITY_STATUS status = SEC_E_INVALID_TOKEN; + const BOOL krb = (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0); + const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic; + const size_t hashSize = nla->server ? sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic); + signature_length = nla->pubKeyAuth.cbBuffer - WINPR_SHA256_DIGEST_LENGTH; + + if ((signature_length < 0) || (signature_length > (int)nla->ContextSizes.cbSecurityTrailer)) + { + WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %"PRIu32"", nla->pubKeyAuth.cbBuffer); + goto fail; + } + + if ((nla->ContextSizes.cbSecurityTrailer + WINPR_SHA256_DIGEST_LENGTH) != nla->pubKeyAuth.cbBuffer) + { + WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %"PRIu32"", (int)nla->pubKeyAuth.cbBuffer); + goto fail; + } + + length = nla->pubKeyAuth.cbBuffer; + buffer = (BYTE*)malloc(length); + + if (!buffer) + { + status = SEC_E_INSUFFICIENT_MEMORY; + goto fail; + } + + if (krb) + { + CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length); + Buffers[0].BufferType = SECBUFFER_DATA; /* Encrypted Hash */ + Buffers[0].cbBuffer = length; + Buffers[0].pvBuffer = buffer; + Message.cBuffers = 1; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer)&Buffers; + } + else + { + CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length); + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[0].cbBuffer = signature_length; + Buffers[0].pvBuffer = buffer; + Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted Hash */ + Buffers[1].cbBuffer = WINPR_SHA256_DIGEST_LENGTH; + Buffers[1].pvBuffer = buffer + signature_length; + Message.cBuffers = 2; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer)&Buffers; + } + + status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP); + + if (status != SEC_E_OK) + { + WLog_ERR(TAG, "DecryptMessage failure %s [%08"PRIX32"]", + GetSecurityStatusString(status), status); + goto fail; + } + + /* generate SHA256 of following data: ServerClientHashMagic, Nonce, SubjectPublicKey */ + if (!(sha256 = winpr_Digest_New())) + goto fail; + + if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256)) + goto fail; + + /* include trailing \0 from hashMagic */ + if (!winpr_Digest_Update(sha256, hashMagic, hashSize)) + goto fail; + + if (!winpr_Digest_Update(sha256, nla->ClientNonce.pvBuffer, nla->ClientNonce.cbBuffer)) + goto fail; + + /* SubjectPublicKey */ + if (!winpr_Digest_Update(sha256, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer)) + goto fail; + + if (!winpr_Digest_Final(sha256, serverClientHash, sizeof(serverClientHash))) + goto fail; + + /* verify hash */ + if (memcmp(serverClientHash, Buffers[krb ? 0 : 1].pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0) + { + WLog_ERR(TAG, "Could not verify server's hash"); + status = SEC_E_MESSAGE_ALTERED; /* DO NOT SEND CREDENTIALS! */ + goto fail; + } + + status = SEC_E_OK; +fail: + free(buffer); + winpr_Digest_Free(sha256); + return status; +} + +static size_t nla_sizeof_ts_password_creds(rdpNla* nla) +{ + size_t length = 0; if (nla->identity) { @@ -1082,9 +1420,18 @@ int nla_sizeof_ts_password_creds(rdpNla* nla) return length; } +static size_t nla_sizeof_ts_credentials(rdpNla* nla) +{ + size_t size = 0; + size += ber_sizeof_integer(1); + size += ber_sizeof_contextual_tag(ber_sizeof_integer(1)); + size += ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla))); + return size; +} + BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s) { - int length; + size_t length; if (!nla->identity) { @@ -1176,10 +1523,10 @@ BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s) return TRUE; } -int nla_write_ts_password_creds(rdpNla* nla, wStream* s) +static size_t nla_write_ts_password_creds(rdpNla* nla, wStream* s) { - int size = 0; - int innerSize = nla_sizeof_ts_password_creds(nla); + size_t size = 0; + size_t innerSize = nla_sizeof_ts_password_creds(nla); /* TSPasswordCreds (SEQUENCE) */ size += ber_write_sequence_tag(s, innerSize); @@ -1202,21 +1549,16 @@ int nla_write_ts_password_creds(rdpNla* nla, wStream* s) return size; } -int nla_sizeof_ts_credentials(rdpNla* nla) -{ - int size = 0; - size += ber_sizeof_integer(1); - size += ber_sizeof_contextual_tag(ber_sizeof_integer(1)); - size += ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla))); - return size; -} - static BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials) { wStream* s; - int length; - int ts_password_creds_length; + size_t length; + size_t ts_password_creds_length = 0; BOOL ret; + + if (!ts_credentials || !ts_credentials->pvBuffer) + return FALSE; + s = Stream_New(ts_credentials->pvBuffer, ts_credentials->cbBuffer); if (!s) @@ -1238,11 +1580,11 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials) return ret; } -int nla_write_ts_credentials(rdpNla* nla, wStream* s) +static size_t nla_write_ts_credentials(rdpNla* nla, wStream* s) { - int size = 0; - int passwordSize; - int innerSize = nla_sizeof_ts_credentials(nla); + size_t size = 0; + size_t passwordSize; + size_t innerSize = nla_sizeof_ts_credentials(nla); /* TSCredentials (SEQUENCE) */ size += ber_write_sequence_tag(s, innerSize); /* [0] credType (INTEGER) */ @@ -1261,16 +1603,17 @@ int nla_write_ts_credentials(rdpNla* nla, wStream* s) * @param credssp */ -BOOL nla_encode_ts_credentials(rdpNla* nla) +static BOOL nla_encode_ts_credentials(rdpNla* nla) { wStream* s; - int length; + size_t length; int DomainLength = 0; int UserLength = 0; int PasswordLength = 0; if (nla->identity) { + /* TSPasswordCreds */ DomainLength = nla->identity->DomainLength; UserLength = nla->identity->UserLength; PasswordLength = nla->identity->PasswordLength; @@ -1278,6 +1621,7 @@ BOOL nla_encode_ts_credentials(rdpNla* nla) if (nla->settings->DisableCredentialsDelegation && nla->identity) { + /* TSPasswordCreds */ nla->identity->DomainLength = 0; nla->identity->UserLength = 0; nla->identity->PasswordLength = 0; @@ -1302,8 +1646,9 @@ BOOL nla_encode_ts_credentials(rdpNla* nla) nla_write_ts_credentials(nla, s); - if (nla->settings->DisableCredentialsDelegation) + if (nla->settings->DisableCredentialsDelegation && nla->identity) { + /* TSPasswordCreds */ nla->identity->DomainLength = DomainLength; nla->identity->UserLength = UserLength; nla->identity->PasswordLength = PasswordLength; @@ -1313,30 +1658,47 @@ BOOL nla_encode_ts_credentials(rdpNla* nla) return TRUE; } -SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla) +static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla) { - SecBuffer Buffers[2]; + SecBuffer Buffers[2] = { { 0 } }; SecBufferDesc Message; SECURITY_STATUS status; + const BOOL krb = (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0); + const BOOL nego = (_tcsncmp(nla->packageName, NEGO_SSP_NAME, ARRAYSIZE(NEGO_SSP_NAME)) == 0); + const BOOL ntlm = (_tcsncmp(nla->packageName, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0); if (!nla_encode_ts_credentials(nla)) return SEC_E_INSUFFICIENT_MEMORY; if (!sspi_SecBufferAlloc(&nla->authInfo, - nla->ContextSizes.cbSecurityTrailer + nla->tsCredentials.cbBuffer)) + nla->tsCredentials.cbBuffer + nla->ContextSizes.cbSecurityTrailer)) return SEC_E_INSUFFICIENT_MEMORY; - Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ - Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; - Buffers[0].pvBuffer = nla->authInfo.pvBuffer; - ZeroMemory(Buffers[0].pvBuffer, Buffers[0].cbBuffer); - Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ - Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer; - Buffers[1].pvBuffer = &((BYTE*) nla->authInfo.pvBuffer)[Buffers[0].cbBuffer]; - CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer); - Message.cBuffers = 2; - Message.ulVersion = SECBUFFER_VERSION; - Message.pBuffers = (PSecBuffer) &Buffers; + if (krb) + { + Buffers[0].BufferType = SECBUFFER_DATA; /* TSCredentials */ + Buffers[0].cbBuffer = nla->tsCredentials.cbBuffer; + Buffers[0].pvBuffer = nla->authInfo.pvBuffer; + CopyMemory(Buffers[0].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[0].cbBuffer); + Message.cBuffers = 1; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } + else if (ntlm || nego) + { + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; + Buffers[0].pvBuffer = nla->authInfo.pvBuffer; + MoveMemory(Buffers[0].pvBuffer, nla->authInfo.pvBuffer, Buffers[0].cbBuffer); + Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ + Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer; + Buffers[1].pvBuffer = &((BYTE*) nla->authInfo.pvBuffer)[Buffers[0].cbBuffer]; + CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer); + Message.cBuffers = 2; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } + status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++); if (status != SEC_E_OK) @@ -1346,27 +1708,20 @@ SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla) return status; } - if (Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer) - { - /* EncryptMessage may not use all the signature space, so we need to shrink the excess */ - MoveMemory(((BYTE*)nla->authInfo.pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer, - Buffers[1].cbBuffer); - nla->authInfo.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer; - } - return SEC_E_OK; } -SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla) +static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla) { int length; BYTE* buffer; ULONG pfQOP; - SecBuffer Buffers[2]; + SecBuffer Buffers[2] = { { 0 } }; SecBufferDesc Message; SECURITY_STATUS status; - Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ - Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ + const BOOL krb = (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0); + const BOOL nego = (_tcsncmp(nla->packageName, NEGO_SSP_NAME, ARRAYSIZE(NEGO_SSP_NAME)) == 0); + const BOOL ntlm = (_tcsncmp(nla->packageName, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0); if (nla->authInfo.cbBuffer < 1) { @@ -1380,20 +1735,37 @@ SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla) if (!buffer) return SEC_E_INSUFFICIENT_MEMORY; - CopyMemory(buffer, nla->authInfo.pvBuffer, length); - Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; - Buffers[0].pvBuffer = buffer; - Buffers[1].cbBuffer = length - nla->ContextSizes.cbSecurityTrailer; - Buffers[1].pvBuffer = &buffer[nla->ContextSizes.cbSecurityTrailer]; - Message.cBuffers = 2; - Message.ulVersion = SECBUFFER_VERSION; - Message.pBuffers = (PSecBuffer) &Buffers; + if (krb) + { + CopyMemory(buffer, nla->authInfo.pvBuffer, length); + Buffers[0].BufferType = SECBUFFER_DATA; /* Wrapped and encrypted TSCredentials */ + Buffers[0].cbBuffer = length; + Buffers[0].pvBuffer = buffer; + Message.cBuffers = 1; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } + else if (ntlm || nego) + { + CopyMemory(buffer, nla->authInfo.pvBuffer, length); + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; + Buffers[0].pvBuffer = buffer; + Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ + Buffers[1].cbBuffer = length - nla->ContextSizes.cbSecurityTrailer; + Buffers[1].pvBuffer = &buffer[ Buffers[0].cbBuffer ]; + Message.cBuffers = 2; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } + status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP); if (status != SEC_E_OK) { WLog_ERR(TAG, "DecryptMessage failure %s [0x%08"PRIX32"]", GetSecurityStatusString(status), status); + free(buffer); return status; } @@ -1407,14 +1779,14 @@ SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla) return SEC_E_OK; } -int nla_sizeof_nego_token(int length) +static size_t nla_sizeof_nego_token(size_t length) { length = ber_sizeof_octet_string(length); length += ber_sizeof_contextual_tag(length); return length; } -int nla_sizeof_nego_tokens(int length) +static size_t nla_sizeof_nego_tokens(size_t length) { length = nla_sizeof_nego_token(length); length += ber_sizeof_sequence_tag(length); @@ -1423,21 +1795,28 @@ int nla_sizeof_nego_tokens(int length) return length; } -int nla_sizeof_pub_key_auth(int length) +static size_t nla_sizeof_pub_key_auth(size_t length) { length = ber_sizeof_octet_string(length); length += ber_sizeof_contextual_tag(length); return length; } -int nla_sizeof_auth_info(int length) +static size_t nla_sizeof_auth_info(size_t length) { length = ber_sizeof_octet_string(length); length += ber_sizeof_contextual_tag(length); return length; } -int nla_sizeof_ts_request(int length) +static size_t nla_sizeof_client_nonce(size_t length) +{ + length = ber_sizeof_octet_string(length); + length += ber_sizeof_contextual_tag(length); + return length; +} + +static size_t nla_sizeof_ts_request(size_t length) { length += ber_sizeof_integer(2); length += ber_sizeof_contextual_tag(3); @@ -1452,30 +1831,30 @@ int nla_sizeof_ts_request(int length) BOOL nla_send(rdpNla* nla) { wStream* s; - int length; - int ts_request_length; - int nego_tokens_length = 0; - int pub_key_auth_length = 0; - int auth_info_length = 0; - int error_code_context_length = 0; - int error_code_length = 0; + size_t length; + size_t ts_request_length; + size_t nego_tokens_length = 0; + size_t pub_key_auth_length = 0; + size_t auth_info_length = 0; + size_t error_code_context_length = 0; + size_t error_code_length = 0; + size_t client_nonce_length = 0; + nego_tokens_length = (nla->negoToken.cbBuffer > 0) ? nla_sizeof_nego_tokens( + nla->negoToken.cbBuffer) : 0; + pub_key_auth_length = (nla->pubKeyAuth.cbBuffer > 0) ? nla_sizeof_pub_key_auth( + nla->pubKeyAuth.cbBuffer) : 0; + auth_info_length = (nla->authInfo.cbBuffer > 0) ? nla_sizeof_auth_info(nla->authInfo.cbBuffer) : 0; + client_nonce_length = (nla->ClientNonce.cbBuffer > 0) ? nla_sizeof_client_nonce( + nla->ClientNonce.cbBuffer) : 0; - if (nla->version < 3 || nla->errorCode == 0) - { - nego_tokens_length = (nla->negoToken.cbBuffer > 0) ? nla_sizeof_nego_tokens( - nla->negoToken.cbBuffer) : 0; - pub_key_auth_length = (nla->pubKeyAuth.cbBuffer > 0) ? nla_sizeof_pub_key_auth( - nla->pubKeyAuth.cbBuffer) : 0; - auth_info_length = (nla->authInfo.cbBuffer > 0) ? nla_sizeof_auth_info(nla->authInfo.cbBuffer) : 0; - } - else + if (nla->peerVersion >= 3 && nla->peerVersion != 5 && nla->errorCode != 0) { error_code_length = ber_sizeof_integer(nla->errorCode); error_code_context_length = ber_sizeof_contextual_tag(error_code_length); } length = nego_tokens_length + pub_key_auth_length + auth_info_length + error_code_context_length + - error_code_length; + error_code_length + client_nonce_length; ts_request_length = nla_sizeof_ts_request(length); s = Stream_New(NULL, ber_sizeof_sequence(ts_request_length)); @@ -1494,9 +1873,9 @@ BOOL nla_send(rdpNla* nla) /* [1] negoTokens (NegoData) */ if (nego_tokens_length > 0) { - int length = ber_write_contextual_tag(s, 1, - ber_sizeof_sequence(ber_sizeof_sequence(ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer))), - TRUE); /* NegoData */ + length = ber_write_contextual_tag(s, 1, + ber_sizeof_sequence(ber_sizeof_sequence(ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer))), + TRUE); /* NegoData */ length += ber_write_sequence_tag(s, ber_sizeof_sequence(ber_sizeof_sequence_octet_string( nla->negoToken.cbBuffer))); /* SEQUENCE OF NegoDataItem */ @@ -1532,24 +1911,48 @@ BOOL nla_send(rdpNla* nla) ber_write_integer(s, nla->errorCode); } + /* [5] clientNonce (OCTET STRING) */ + if (client_nonce_length > 0) + { + if (ber_write_sequence_octet_string(s, 5, nla->ClientNonce.pvBuffer, + nla->ClientNonce.cbBuffer) != client_nonce_length) + return FALSE; + } + Stream_SealLength(s); transport_write(nla->transport, s); Stream_Free(s, TRUE); return TRUE; } -int nla_decode_ts_request(rdpNla* nla, wStream* s) +static int nla_decode_ts_request(rdpNla* nla, wStream* s) { - int length; + size_t length; + UINT32 version = 0; /* TSRequest */ if (!ber_read_sequence_tag(s, &length) || !ber_read_contextual_tag(s, 0, &length, TRUE) || - !ber_read_integer(s, &nla->version)) + !ber_read_integer(s, &version)) { return -1; } + if (nla->peerVersion == 0) + { + WLog_DBG(TAG, "CredSSP protocol support %"PRIu32", peer supports %"PRIu32, + nla->version, version); + nla->peerVersion = version; + } + + /* if the peer suddenly changed its version - kick it */ + if (nla->peerVersion != version) + { + WLog_ERR(TAG, "CredSSP peer changed protocol version from %"PRIu32" to %"PRIu32, + nla->peerVersion, version); + return -1; + } + /* [1] negoTokens (NegoData) */ if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE) { @@ -1557,7 +1960,7 @@ int nla_decode_ts_request(rdpNla* nla, wStream* s) !ber_read_sequence_tag(s, &length) || /* NegoDataItem */ !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */ !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ - ((int) Stream_GetRemainingLength(s)) < length) + Stream_GetRemainingLength(s) < length) { return -1; } @@ -1573,7 +1976,7 @@ int nla_decode_ts_request(rdpNla* nla, wStream* s) if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE) { if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ - ((int) Stream_GetRemainingLength(s)) < length) + Stream_GetRemainingLength(s) < length) return -1; if (!sspi_SecBufferAlloc(&nla->authInfo, length)) @@ -1587,7 +1990,7 @@ int nla_decode_ts_request(rdpNla* nla, wStream* s) if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE) { if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ - ((int) Stream_GetRemainingLength(s)) < length) + Stream_GetRemainingLength(s) < length) return -1; if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length)) @@ -1598,13 +2001,29 @@ int nla_decode_ts_request(rdpNla* nla, wStream* s) } /* [4] errorCode (INTEGER) */ - if (nla->version >= 3) + if (nla->peerVersion >= 3) { if (ber_read_contextual_tag(s, 4, &length, TRUE) != FALSE) { if (!ber_read_integer(s, &nla->errorCode)) return -1; } + + if (nla->peerVersion >= 5) + { + if (ber_read_contextual_tag(s, 5, &length, TRUE) != FALSE) + { + if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ + Stream_GetRemainingLength(s) < length) + return -1; + + if (!sspi_SecBufferAlloc(&nla->ClientNonce, length)) + return -1; + + Stream_Read(s, nla->ClientNonce.pvBuffer, length); + nla->ClientNonce.cbBuffer = length; + } + } } return 1; @@ -1617,8 +2036,57 @@ int nla_recv_pdu(rdpNla* nla, wStream* s) if (nla->errorCode) { - WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: 0x%08"PRIX32"", nla->errorCode); - freerdp_set_last_error(nla->instance->context, nla->errorCode); + UINT32 code; + + switch (nla->errorCode) + { + case STATUS_PASSWORD_MUST_CHANGE: + code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE; + break; + + case STATUS_PASSWORD_EXPIRED: + code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED; + break; + + case STATUS_ACCOUNT_DISABLED: + code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED; + break; + + case STATUS_LOGON_FAILURE: + code = FREERDP_ERROR_CONNECT_LOGON_FAILURE; + break; + + case STATUS_WRONG_PASSWORD: + code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD; + break; + + case STATUS_ACCESS_DENIED: + code = FREERDP_ERROR_CONNECT_ACCESS_DENIED; + break; + + case STATUS_ACCOUNT_RESTRICTION: + code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION; + break; + + case STATUS_ACCOUNT_LOCKED_OUT: + code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT; + break; + + case STATUS_ACCOUNT_EXPIRED: + code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED; + break; + + case STATUS_LOGON_TYPE_NOT_GRANTED: + code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED; + break; + + default: + WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: 0x%08"PRIX32"", nla->errorCode); + code = FREERDP_ERROR_AUTHENTICATION_FAILED; + break; + } + + freerdp_set_last_error(nla->instance->context, code); return -1; } @@ -1765,6 +2233,7 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting return NULL; nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY)); + if (!nla->identity) { free(nla); @@ -1777,24 +2246,29 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting nla->transport = transport; nla->sendSeqNum = 0; nla->recvSeqNum = 0; - nla->version = 3; + nla->version = 6; + + ZeroMemory(&nla->ClientNonce, sizeof(SecBuffer)); + ZeroMemory(&nla->negoToken, sizeof(SecBuffer)); + ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer)); + ZeroMemory(&nla->authInfo, sizeof(SecBuffer)); + SecInvalidateHandle(&nla->context); if (settings->NtlmSamFile) { nla->SamFile = _strdup(settings->NtlmSamFile); if (!nla->SamFile) - { - free(nla->identity); - free(nla); - return NULL; - } + goto cleanup; } - ZeroMemory(&nla->negoToken, sizeof(SecBuffer)); - ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer)); - ZeroMemory(&nla->authInfo, sizeof(SecBuffer)); - SecInvalidateHandle(&nla->context); + /* init to 0 or we end up freeing a bad pointer if the alloc fails */ + if (!sspi_SecBufferAlloc(&nla->ClientNonce, NonceLength)) + goto cleanup; + + /* generate random 32-byte nonce */ + if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0) + goto cleanup; if (nla->server) { @@ -1821,8 +2295,7 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting if (!nla->SspiModule) { RegCloseKey(hKey); - free(nla); - return NULL; + goto cleanup; } status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType, @@ -1835,6 +2308,10 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting } return nla; + +cleanup: + nla_free(nla); + return NULL; } /** @@ -1850,6 +2327,20 @@ void nla_free(rdpNla* nla) if (nla->table) { SECURITY_STATUS status; + + if (SecIsValidHandle(&nla->credentials)) + { + status = nla->table->FreeCredentialsHandle(&nla->credentials); + + if (status != SEC_E_OK) + { + WLog_WARN(TAG, "FreeCredentialsHandle status %s [0x%08"PRIX32"]", + GetSecurityStatusString(status), status); + } + + SecInvalidateHandle(&nla->credentials); + } + status = nla->table->DeleteSecurityContext(&nla->context); if (status != SEC_E_OK) @@ -1861,6 +2352,7 @@ void nla_free(rdpNla* nla) free(nla->SamFile); nla->SamFile = NULL; + sspi_SecBufferFree(&nla->ClientNonce); sspi_SecBufferFree(&nla->PublicKey); sspi_SecBufferFree(&nla->tsCredentials); free(nla->ServicePrincipalName); diff --git a/libfreerdp/core/nla.h b/libfreerdp/core/nla.h index 5039fb4..fcd2ece 100644 --- a/libfreerdp/core/nla.h +++ b/libfreerdp/core/nla.h @@ -1,6 +1,6 @@ /** * FreeRDP: A Remote Desktop Protocol Implementation - * Credential Security Support Provider (CredSSP) + * Network Level Authentication (NLA) * * Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * @@ -60,7 +60,13 @@ struct rdp_nla rdpSettings* settings; rdpTransport* transport; UINT32 cbMaxToken; +#if defined(UNICODE) + SEC_WCHAR* packageName; +#else + SEC_CHAR* packageName; +#endif UINT32 version; + UINT32 peerVersion; UINT32 errorCode; ULONG fContextReq; ULONG pfContextAttr; @@ -78,6 +84,7 @@ struct rdp_nla SecBuffer negoToken; SecBuffer pubKeyAuth; SecBuffer authInfo; + SecBuffer ClientNonce; SecBuffer PublicKey; SecBuffer tsCredentials; LPTSTR ServicePrincipalName; diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 2ee97e6..b68ac91 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -31,6 +31,7 @@ #include <freerdp/log.h> #include <freerdp/graphics.h> #include <freerdp/codec/bitmap.h> +#include <freerdp/gdi/gdi.h> #include "orders.h" @@ -161,7 +162,7 @@ static const BYTE BPP_CBR23[] = static const BYTE BMF_BPP[] = { - 0, 1, 0, 8, 16, 24, 32 + 0, 1, 0, 8, 16, 24, 32, 0 }; static const BYTE BPP_BMF[] = @@ -565,7 +566,7 @@ static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, if (brush->style & CACHED_BRUSH) { brush->index = brush->hatch; - brush->bpp = BMF_BPP[brush->style & 0x0F]; + brush->bpp = BMF_BPP[brush->style & 0x07]; if (brush->bpp == 0) brush->bpp = 1; @@ -611,7 +612,7 @@ static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, if (brush->style & CACHED_BRUSH) { brush->hatch = brush->index; - brush->bpp = BMF_BPP[brush->style & 0x0F]; + brush->bpp = BMF_BPP[brush->style & 0x07]; if (brush->bpp == 0) brush->bpp = 1; @@ -2460,7 +2461,7 @@ static BOOL update_read_create_offscreen_bitmap_order(wStream* s, if (deleteList->cIndices > deleteList->sIndices) { UINT16* new_indices; - new_indices = (UINT16*)realloc(deleteList->indices, deleteList->sIndices * 2); + new_indices = (UINT16*)realloc(deleteList->indices, deleteList->cIndices * 2); if (!new_indices) return FALSE; @@ -2943,8 +2944,6 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) } orderInfo->deltaCoordinates = (flags & ORDER_DELTA_COORDINATES) ? TRUE : FALSE; - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); switch (orderInfo->orderType) { @@ -2955,6 +2954,10 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, + "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, + gdi_rop3_code_string(primary->dstblt.bRop), gdi_rop3_code(primary->dstblt.bRop)); IFCALL(primary->DstBlt, context, &primary->dstblt); break; @@ -2965,6 +2968,10 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, + "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, + gdi_rop3_code_string(primary->patblt.bRop), gdi_rop3_code(primary->patblt.bRop)); IFCALL(primary->PatBlt, context, &primary->patblt); break; @@ -2975,6 +2982,10 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, + "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, + gdi_rop3_code_string(primary->scrblt.bRop), gdi_rop3_code(primary->scrblt.bRop)); IFCALL(primary->ScrBlt, context, &primary->scrblt); break; @@ -2986,6 +2997,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->OpaqueRect, context, &primary->opaque_rect); break; @@ -2997,6 +3010,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->DrawNineGrid, context, &primary->draw_nine_grid); break; @@ -3008,6 +3023,10 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, + "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, + gdi_rop3_code_string(primary->multi_dstblt.bRop), gdi_rop3_code(primary->multi_dstblt.bRop)); IFCALL(primary->MultiDstBlt, context, &primary->multi_dstblt); break; @@ -3019,6 +3038,10 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, + "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, + gdi_rop3_code_string(primary->multi_patblt.bRop), gdi_rop3_code(primary->multi_patblt.bRop)); IFCALL(primary->MultiPatBlt, context, &primary->multi_patblt); break; @@ -3030,6 +3053,10 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, + "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, + gdi_rop3_code_string(primary->multi_scrblt.bRop), gdi_rop3_code(primary->multi_scrblt.bRop)); IFCALL(primary->MultiScrBlt, context, &primary->multi_scrblt); break; @@ -3042,6 +3069,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->MultiOpaqueRect, context, &primary->multi_opaque_rect); break; @@ -3054,6 +3083,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->MultiDrawNineGrid, context, &primary->multi_draw_nine_grid); break; @@ -3064,6 +3095,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->LineTo, context, &primary->line_to); break; @@ -3074,6 +3107,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->Polyline, context, &primary->polyline); break; @@ -3084,6 +3119,10 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, + "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, + gdi_rop3_code_string(primary->memblt.bRop), gdi_rop3_code(primary->memblt.bRop)); IFCALL(primary->MemBlt, context, &primary->memblt); break; @@ -3094,6 +3133,10 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, + "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, + gdi_rop3_code_string(primary->mem3blt.bRop), gdi_rop3_code(primary->mem3blt.bRop)); IFCALL(primary->Mem3Blt, context, &primary->mem3blt); break; @@ -3105,6 +3148,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->SaveBitmap, context, &primary->save_bitmap); break; @@ -3116,6 +3161,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->GlyphIndex, context, &primary->glyph_index); break; @@ -3126,6 +3173,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->FastIndex, context, &primary->fast_index); break; @@ -3136,6 +3185,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->FastGlyph, context, &primary->fast_glyph); break; @@ -3146,6 +3197,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->PolygonSC, context, &primary->polygon_sc); break; @@ -3156,6 +3209,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->PolygonCB, context, &primary->polygon_cb); break; @@ -3166,6 +3221,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->EllipseSC, context, &primary->ellipse_sc); break; @@ -3176,6 +3233,8 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) return FALSE; } + WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", + PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); IFCALL(primary->EllipseCB, context, &primary->ellipse_cb); break; @@ -3451,7 +3510,7 @@ static BOOL update_recv_altsec_order(rdpUpdate* update, wStream* s, break; case ORDER_TYPE_GDIPLUS_END: - if (update_read_draw_gdiplus_end_order(s, &(altsec->draw_gdiplus_end))) + if (!update_read_draw_gdiplus_end_order(s, &(altsec->draw_gdiplus_end))) { WLog_ERR(TAG, "ORDER_TYPE_GDIPLUS_END - update_read_draw_gdiplus_end_order() failed"); diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 2d978da..f6d9746 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -481,7 +481,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra) client->settings->NlaSecurity = (rdp->nego->SelectedProtocol & PROTOCOL_NLA) ? TRUE : FALSE; client->settings->TlsSecurity = (rdp->nego->SelectedProtocol & PROTOCOL_TLS) ? TRUE : FALSE; - client->settings->RdpSecurity = (rdp->nego->SelectedProtocol & PROTOCOL_RDP) ? TRUE : FALSE; + client->settings->RdpSecurity = (rdp->nego->SelectedProtocol == PROTOCOL_RDP) ? TRUE : FALSE; if (rdp->nego->SelectedProtocol & PROTOCOL_NLA) { diff --git a/libfreerdp/core/proxy.c b/libfreerdp/core/proxy.c index 4835477..6c98471 100644 --- a/libfreerdp/core/proxy.c +++ b/libfreerdp/core/proxy.c @@ -18,6 +18,7 @@ */ #include <ctype.h> +#include <errno.h> #include "proxy.h" #include "freerdp/settings.h" @@ -109,13 +110,14 @@ BOOL proxy_parse_uri(rdpSettings* settings, const char* uri) if (pport) { - if (!isdigit(*(pport + 1))) - { - WLog_ERR(TAG, "Could not parse proxy port"); - return FALSE; - } + long val; + errno = 0; + val = strtol(pport + 1, NULL, 0); - port = atoi(pport + 1); + if ((errno != 0) || (val <= 0) || (val > UINT16_MAX)) + return FALSE; + + port = val; } else { diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index a76b2c4..f562584 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -557,7 +557,7 @@ BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id) { UINT16 length; UINT32 sec_bytes; - int sec_hold; + size_t sec_hold; UINT32 pad; length = Stream_GetPosition(s); @@ -584,9 +584,9 @@ BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id) BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id) { - UINT16 length; + size_t length; UINT32 sec_bytes; - int sec_hold; + size_t sec_hold; UINT32 pad; length = Stream_GetPosition(s); @@ -604,6 +604,8 @@ BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id) Stream_SetPosition(s, length); Stream_SealLength(s); + WLog_DBG(TAG, "%s: sending data (type=0x%x size=%"PRIuz" channelId=%"PRIu16")", __FUNCTION__, + type, Stream_Length(s), channel_id); if (transport_write(rdp->transport, s) < 0) return FALSE; @@ -613,17 +615,11 @@ BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id) BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags) { UINT16 length; - UINT32 sec_bytes; - int sec_hold; UINT32 pad; length = Stream_GetPosition(s); Stream_SetPosition(s, 0); rdp_write_header(rdp, s, length, rdp->mcs->messageChannelId); - sec_bytes = rdp_get_sec_bytes(rdp, sec_flags); - sec_hold = Stream_GetPosition(s); - Stream_Seek(s, sec_bytes); - Stream_SetPosition(s, sec_hold); if (!rdp_security_stream_out(rdp, s, length, sec_flags, &pad)) return FALSE; @@ -1138,7 +1134,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s) UINT16 pduSource; UINT16 channelId = 0; UINT16 securityFlags = 0; - int nextPosition; + size_t nextPosition; if (!rdp_read_header(rdp, s, &length, &channelId)) { @@ -1224,6 +1220,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s) case PDU_TYPE_FLOW_RESPONSE: case PDU_TYPE_FLOW_STOP: case PDU_TYPE_FLOW_TEST: + WLog_DBG(TAG, "flow message 0x%04"PRIX16"", pduType); break; default: @@ -1435,7 +1432,15 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra) if ((status >= 0) && (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE)) { + ActivatedEventArgs activatedEvent; + rdpContext *context = rdp->context; + rdp_client_transition_to_state(rdp, CONNECTION_STATE_ACTIVE); + + EventArgsInit(&activatedEvent, "xfreerdp"); + activatedEvent.firstActivation = !rdp->deactivation_reactivation; + PubSub_OnActivated(context->pubSub, context, &activatedEvent); + return 2; } if (status < 0) diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index 807f58f..a6d8bd3 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -137,28 +137,41 @@ static BOOL security_salted_hash(const BYTE* salt, const BYTE* input, int length /* SHA1_Digest = SHA1(Input + Salt + Salt1 + Salt2) */ if (!(sha1 = winpr_Digest_New())) goto out; + if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1)) goto out; + if (!winpr_Digest_Update(sha1, input, length)) /* Input */ goto out; + if (!winpr_Digest_Update(sha1, salt, 48)) /* Salt (48 bytes) */ goto out; + if (!winpr_Digest_Update(sha1, salt1, 32)) /* Salt1 (32 bytes) */ goto out; + if (!winpr_Digest_Update(sha1, salt2, 32)) /* Salt2 (32 bytes) */ goto out; + if (!winpr_Digest_Final(sha1, sha1_digest, sizeof(sha1_digest))) goto out; /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */ if (!(md5 = winpr_Digest_New())) goto out; - if (!winpr_Digest_Init(md5, WINPR_MD_MD5)) + + /* Allow FIPS override for use of MD5 here, this is used for creating hashes of the premaster_secret and master_secret */ + /* used for RDP licensing as described in MS-RDPELE. This is for RDP licensing packets */ + /* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data protection. */ + if (!winpr_Digest_Init_Allow_FIPS(md5, WINPR_MD_MD5)) goto out; + if (!winpr_Digest_Update(md5, salt, 48)) /* Salt (48 bytes) */ goto out; + if (!winpr_Digest_Update(md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ goto out; + if (!winpr_Digest_Final(md5, output, WINPR_MD5_DIGEST_LENGTH)) goto out; @@ -215,8 +228,37 @@ BOOL security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE* in2, BY if (!(md5 = winpr_Digest_New())) return FALSE; + if (!winpr_Digest_Init(md5, WINPR_MD_MD5)) goto out; + + if (!winpr_Digest_Update(md5, in0, 16)) + goto out; + + if (!winpr_Digest_Update(md5, in1, 32)) + goto out; + + if (!winpr_Digest_Update(md5, in2, 32)) + goto out; + + if (!winpr_Digest_Final(md5, output, WINPR_MD5_DIGEST_LENGTH)) + goto out; + + result = TRUE; +out: + winpr_Digest_Free(md5); + return result; +} + +BOOL security_md5_16_32_32_Allow_FIPS(const BYTE* in0, const BYTE* in1, const BYTE* in2, BYTE* output) +{ + WINPR_DIGEST_CTX* md5 = NULL; + BOOL result = FALSE; + + if (!(md5 = winpr_Digest_New())) + return FALSE; + if (!winpr_Digest_Init_Allow_FIPS(md5, WINPR_MD_MD5)) + goto out; if (!winpr_Digest_Update(md5, in0, 16)) goto out; if (!winpr_Digest_Update(md5, in1, 32)) @@ -233,10 +275,14 @@ out: } BOOL security_licensing_encryption_key(const BYTE* session_key_blob, const BYTE* client_random, - const BYTE* server_random, BYTE* output) + const BYTE* server_random, BYTE* output) { - /* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom)) */ - return security_md5_16_32_32(&session_key_blob[16], client_random, server_random, output); + /* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom)) + * Allow FIPS use of MD5 here, this is just used for creating the licensing encryption key as described in MS-RDPELE. + * This is for RDP licensing packets which will already be encrypted under FIPS, so the use of MD5 here is not for + * sensitive data protection. */ + return security_md5_16_32_32_Allow_FIPS(&session_key_blob[16], client_random, server_random, + output); } void security_UINT32_le(BYTE* output, UINT32 value) @@ -255,38 +301,50 @@ BOOL security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length BYTE length_le[4]; BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; BOOL result = FALSE; - /* 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) */ if (!(sha1 = winpr_Digest_New())) goto out; + if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1)) goto out; + if (!winpr_Digest_Update(sha1, mac_salt_key, 16)) /* MacSaltKey */ goto out; + if (!winpr_Digest_Update(sha1, pad1, sizeof(pad1))) /* pad1 */ goto out; + if (!winpr_Digest_Update(sha1, length_le, sizeof(length_le))) /* length */ goto out; + if (!winpr_Digest_Update(sha1, data, length)) /* data */ goto out; + if (!winpr_Digest_Final(sha1, sha1_digest, sizeof(sha1_digest))) goto out; /* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */ if (!(md5 = winpr_Digest_New())) goto out; - if (!winpr_Digest_Init(md5, WINPR_MD_MD5)) + + /* Allow FIPS override for use of MD5 here, this is only used for creating the MACData field of the */ + /* Client Platform Challenge Response packet (from MS-RDPELE section 2.2.2.5). This is for RDP licensing packets */ + /* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data protection. */ + if (!winpr_Digest_Init_Allow_FIPS(md5, WINPR_MD_MD5)) goto out; + if (!winpr_Digest_Update(md5, mac_salt_key, 16)) /* MacSaltKey */ goto out; + if (!winpr_Digest_Update(md5, pad2, sizeof(pad2))) /* pad2 */ goto out; + if (!winpr_Digest_Update(md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ goto out; + if (!winpr_Digest_Final(md5, output, WINPR_MD5_DIGEST_LENGTH)) goto out; @@ -305,36 +363,46 @@ BOOL security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* BYTE md5_digest[WINPR_MD5_DIGEST_LENGTH]; BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; BOOL result = FALSE; - security_UINT32_le(length_le, length); /* length must be little-endian */ /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ if (!(sha1 = winpr_Digest_New())) goto out; + if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1)) goto out; + if (!winpr_Digest_Update(sha1, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ goto out; + if (!winpr_Digest_Update(sha1, pad1, sizeof(pad1))) /* pad1 */ goto out; + if (!winpr_Digest_Update(sha1, length_le, sizeof(length_le))) /* length */ goto out; + if (!winpr_Digest_Update(sha1, data, length)) /* data */ goto out; + if (!winpr_Digest_Final(sha1, sha1_digest, sizeof(sha1_digest))) goto out; /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ if (!(md5 = winpr_Digest_New())) goto out; + if (!winpr_Digest_Init(md5, WINPR_MD_MD5)) goto out; + if (!winpr_Digest_Update(md5, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ goto out; + if (!winpr_Digest_Update(md5, pad2, sizeof(pad2))) /* pad2 */ goto out; + if (!winpr_Digest_Update(md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ goto out; + if (!winpr_Digest_Final(md5, md5_digest, sizeof(md5_digest))) goto out; @@ -356,7 +424,6 @@ BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE md5_digest[WINPR_MD5_DIGEST_LENGTH]; BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; BOOL result = FALSE; - security_UINT32_le(length_le, length); /* length must be little-endian */ if (encryption) @@ -375,32 +442,44 @@ BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ if (!(sha1 = winpr_Digest_New())) goto out; + if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1)) goto out; + if (!winpr_Digest_Update(sha1, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ goto out; + if (!winpr_Digest_Update(sha1, pad1, sizeof(pad1))) /* pad1 */ goto out; + if (!winpr_Digest_Update(sha1, length_le, sizeof(length_le))) /* length */ goto out; + if (!winpr_Digest_Update(sha1, data, length)) /* data */ goto out; + if (!winpr_Digest_Update(sha1, use_count_le, sizeof(use_count_le))) /* encryptionCount */ goto out; + if (!winpr_Digest_Final(sha1, sha1_digest, sizeof(sha1_digest))) goto out; /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ if (!(md5 = winpr_Digest_New())) goto out; + if (!winpr_Digest_Init(md5, WINPR_MD_MD5)) goto out; + if (!winpr_Digest_Update(md5, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ goto out; + if (!winpr_Digest_Update(md5, pad2, sizeof(pad2))) /* pad2 */ goto out; + if (!winpr_Digest_Update(md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ goto out; + if (!winpr_Digest_Final(md5, md5_digest, sizeof(md5_digest))) goto out; @@ -444,9 +523,10 @@ static void fips_expand_key_bits(BYTE* in, BYTE* out) { p = b / 8; r = b % 8; - if (r == 0) + + if (r <= 1) { - out[i] = buf[p] & 0xfe; + out[i] = (buf[p] << r) & 0xfe; } else { @@ -472,7 +552,6 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */ rdpSettings* settings; BOOL status; - settings = rdp->settings; server_random = settings->ServerRandom; @@ -493,6 +572,7 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) winpr_Digest_Free(sha1); return FALSE; } + client_encrypt_key_t[20] = client_encrypt_key_t[0]; if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1) || @@ -503,6 +583,7 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) winpr_Digest_Free(sha1); return FALSE; } + client_decrypt_key_t[20] = client_decrypt_key_t[0]; if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1) || @@ -546,14 +627,16 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) } else { - status = security_md5_16_32_32(&session_key_blob[16], client_random, server_random, rdp->decrypt_key); - status &= security_md5_16_32_32(&session_key_blob[32], client_random, server_random, rdp->encrypt_key); + /* Allow FIPS use of MD5 here, this is just used for generation of the SessionKeyBlob as described in MS-RDPELE. */ + /* This is for RDP licensing packets which will already be encrypted under FIPS, so the use of MD5 here is not */ + /* for sensitive data protection. */ + status = security_md5_16_32_32_Allow_FIPS(&session_key_blob[16], client_random, server_random, rdp->decrypt_key); + status &= security_md5_16_32_32_Allow_FIPS(&session_key_blob[32], client_random, server_random, rdp->encrypt_key); } if (!status) return FALSE; - if (settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT) { memcpy(rdp->sign_key, salt, 3); @@ -579,7 +662,6 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) rdp->decrypt_checksum_use_count = 0; rdp->encrypt_use_count =0; rdp->encrypt_checksum_use_count =0; - return TRUE; } @@ -591,35 +673,47 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) WINPR_RC4_CTX* rc4 = NULL; BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */ BOOL result = FALSE; + WLog_DBG(TAG, "updating RDP key"); if (!(sha1 = winpr_Digest_New())) goto out; + if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1)) goto out; + if (!winpr_Digest_Update(sha1, update_key, key_len)) goto out; + if (!winpr_Digest_Update(sha1, pad1, sizeof(pad1))) goto out; + if (!winpr_Digest_Update(sha1, key, key_len)) goto out; + if (!winpr_Digest_Final(sha1, sha1h, sizeof(sha1h))) goto out; if (!(md5 = winpr_Digest_New())) goto out; + if (!winpr_Digest_Init(md5, WINPR_MD_MD5)) goto out; + if (!winpr_Digest_Update(md5, update_key, key_len)) goto out; + if (!winpr_Digest_Update(md5, pad2, sizeof(pad2))) goto out; + if (!winpr_Digest_Update(md5, sha1h, sizeof(sha1h))) goto out; + if (!winpr_Digest_Final(md5, key, WINPR_MD5_DIGEST_LENGTH)) goto out; if (!(rc4 = winpr_RC4_New(key, key_len))) goto out; + if (!winpr_RC4_Update(rc4, key_len, key, key)) goto out; @@ -633,7 +727,6 @@ out: winpr_Digest_Free(sha1); winpr_Digest_Free(md5); winpr_RC4_Free(rc4); - return result; } @@ -646,6 +739,7 @@ BOOL security_encrypt(BYTE* data, size_t length, rdpRdp* rdp) 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) return FALSE; @@ -654,6 +748,7 @@ BOOL security_encrypt(BYTE* data, size_t length, rdpRdp* rdp) if (!winpr_RC4_Update(rdp->rc4_encrypt_key, length, data, data)) return FALSE; + rdp->encrypt_use_count++; rdp->encrypt_checksum_use_count++; return TRUE; @@ -668,16 +763,20 @@ BOOL security_decrypt(BYTE* data, size_t length, rdpRdp* rdp) { if (!security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len, rdp)) return FALSE; + 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) return FALSE; rdp->decrypt_use_count = 0; } + 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; @@ -689,17 +788,20 @@ BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output, rdpR BYTE use_count_le[4]; WINPR_HMAC_CTX* hmac; BOOL result = FALSE; - security_UINT32_le(use_count_le, rdp->encrypt_use_count); if (!(hmac = winpr_HMAC_New())) return FALSE; + if (!winpr_HMAC_Init(hmac, WINPR_MD_SHA1, rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH)) goto out; + if (!winpr_HMAC_Update(hmac, data, length)) goto out; + if (!winpr_HMAC_Update(hmac, use_count_le, 4)) goto out; + if (!winpr_HMAC_Final(hmac, buf, WINPR_SHA1_DIGEST_LENGTH)) goto out; @@ -716,6 +818,7 @@ BOOL security_fips_encrypt(BYTE* data, size_t length, rdpRdp* rdp) if (!winpr_Cipher_Update(rdp->fips_encrypt, data, length, data, &olen)) return FALSE; + rdp->encrypt_use_count++; return TRUE; } @@ -726,6 +829,7 @@ BOOL security_fips_decrypt(BYTE* data, size_t length, rdpRdp* rdp) if (!winpr_Cipher_Update(rdp->fips_decrypt, data, length, data, &olen)) return FALSE; + return TRUE; } @@ -735,17 +839,20 @@ BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE* BYTE use_count_le[4]; WINPR_HMAC_CTX* hmac; BOOL result = FALSE; - security_UINT32_le(use_count_le, rdp->decrypt_use_count); if (!(hmac = winpr_HMAC_New())) return FALSE; + if (!winpr_HMAC_Init(hmac, WINPR_MD_SHA1, rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH)) goto out; + if (!winpr_HMAC_Update(hmac, data, length)) goto out; + if (!winpr_HMAC_Update(hmac, use_count_le, 4)) goto out; + if (!winpr_HMAC_Final(hmac, buf, WINPR_SHA1_DIGEST_LENGTH)) goto out; @@ -753,6 +860,7 @@ BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE* if (!memcmp(sig, buf, 8)) result = TRUE; + out: winpr_HMAC_Free(hmac); return result; diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index ef4dd8e..4d249eb 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -333,6 +333,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) settings->ConnectionType = CONNECTION_TYPE_LAN; settings->EncryptionMethods = ENCRYPTION_METHOD_NONE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; + settings->FIPSMode = FALSE; settings->CompressionEnabled = TRUE; settings->LogonNotify = TRUE; @@ -562,6 +563,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) if (!settings->ServerMode) { + settings->RedirectClipboard = TRUE; /* these values are used only by the client part */ settings->HomePath = GetKnownPath(KNOWN_PATH_HOME); @@ -690,6 +692,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings) CHECKED_STRDUP(GatewayUsername); /* 1987 */ CHECKED_STRDUP(GatewayPassword); /* 1988 */ CHECKED_STRDUP(GatewayDomain); /* 1989 */ + CHECKED_STRDUP(GatewayAccessToken); /* 1997 */ CHECKED_STRDUP(ProxyHostname); /* 2016 */ CHECKED_STRDUP(RemoteApplicationName); /* 2113 */ CHECKED_STRDUP(RemoteApplicationIcon); /* 2114 */ @@ -1083,6 +1086,7 @@ void freerdp_settings_free(rdpSettings* settings) free(settings->GatewayUsername); free(settings->GatewayPassword); free(settings->GatewayDomain); + free(settings->GatewayAccessToken); free(settings->CertificateName); free(settings->DynamicDSTTimeZoneKeyName); free(settings->PreconnectionBlob); diff --git a/libfreerdp/core/surface.c b/libfreerdp/core/surface.c index dc290dc..b0f5620 100644 --- a/libfreerdp/core/surface.c +++ b/libfreerdp/core/surface.c @@ -28,90 +28,130 @@ #define TAG FREERDP_TAG("core.surface") -static int update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT32* length) +static BOOL update_recv_surfcmd_bitmap_header_ex(wStream* s, TS_COMPRESSED_BITMAP_HEADER_EX* header) +{ + if (!s || !header) + return FALSE; + + if (Stream_GetRemainingLength(s) < 24) + return FALSE; + + Stream_Read_UINT32(s, header->highUniqueId); + Stream_Read_UINT32(s, header->lowUniqueId); + Stream_Read_UINT64(s, header->tmMilliseconds); + Stream_Read_UINT64(s, header->tmSeconds); + return TRUE; +} + +static BOOL update_recv_surfcmd_bitmap_ex(wStream* s, TS_BITMAP_DATA_EX* bmp) +{ + size_t pos; + if (!s || !bmp) + return FALSE; + + if (Stream_GetRemainingLength(s) < 12) + return FALSE; + + Stream_Read_UINT8(s, bmp->bpp); + Stream_Read_UINT8(s, bmp->flags); + Stream_Seek(s, 1); /* reserved */ + Stream_Read_UINT8(s, bmp->codecID); + Stream_Read_UINT16(s, bmp->width); + Stream_Read_UINT16(s, bmp->height); + Stream_Read_UINT32(s, bmp->bitmapDataLength); + + if ((bmp->bpp < 1) || (bmp->bpp > 32)) + { + WLog_ERR(TAG, "invalid bpp value %"PRIu32"", bmp->bpp); + return FALSE; + } + + memset(&bmp->exBitmapDataHeader, 0, sizeof(TS_COMPRESSED_BITMAP_HEADER_EX)); + if (bmp->flags & EX_COMPRESSED_BITMAP_HEADER_PRESENT) + { + if (!update_recv_surfcmd_bitmap_header_ex(s, &bmp->exBitmapDataHeader)) + return FALSE; + } + + if (Stream_GetRemainingLength(s) < bmp->bitmapDataLength) + return FALSE; + + pos = Stream_GetPosition(s) + bmp->bitmapDataLength; + bmp->bitmapData = Stream_Pointer(s); + Stream_SetPosition(s, pos); + + return TRUE; +} + +static BOOL update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s) { - int pos; SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command; - if (Stream_GetRemainingLength(s) < 20) - return -1; + if (Stream_GetRemainingLength(s) < 8) + return FALSE; Stream_Read_UINT16(s, cmd->destLeft); Stream_Read_UINT16(s, cmd->destTop); Stream_Read_UINT16(s, cmd->destRight); Stream_Read_UINT16(s, cmd->destBottom); - Stream_Read_UINT8(s, cmd->bpp); - if ((cmd->bpp < 1) || (cmd->bpp > 32)) + if (!update_recv_surfcmd_bitmap_ex(s, &cmd->bmp)) + return FALSE; + + if (!update->SurfaceBits) { - WLog_ERR(TAG, "invalid bpp value %"PRIu32"", cmd->bpp); + WLog_ERR(TAG, "Missing callback update->SurfaceBits"); return FALSE; } - Stream_Seek(s, 2); /* reserved1, reserved2 */ - Stream_Read_UINT8(s, cmd->codecID); - Stream_Read_UINT16(s, cmd->width); - Stream_Read_UINT16(s, cmd->height); - Stream_Read_UINT32(s, cmd->bitmapDataLength); - - if (Stream_GetRemainingLength(s) < cmd->bitmapDataLength) - return -1; - - pos = Stream_GetPosition(s) + cmd->bitmapDataLength; - cmd->bitmapData = Stream_Pointer(s); - - Stream_SetPosition(s, pos); - *length = 20 + cmd->bitmapDataLength; - - IFCALL(update->SurfaceBits, update->context, cmd); - - return 0; + return update->SurfaceBits(update->context, cmd); } -static int update_recv_surfcmd_frame_marker(rdpUpdate* update, wStream* s, UINT32 *length) +static BOOL update_recv_surfcmd_frame_marker(rdpUpdate* update, wStream* s) { SURFACE_FRAME_MARKER* marker = &update->surface_frame_marker; if (Stream_GetRemainingLength(s) < 6) - return -1; + return FALSE; Stream_Read_UINT16(s, marker->frameAction); Stream_Read_UINT32(s, marker->frameId); - WLog_Print(update->log, WLOG_DEBUG, "SurfaceFrameMarker: action: %s (%"PRIu32") id: %"PRIu32"", - (!marker->frameAction) ? "Begin" : "End", - marker->frameAction, marker->frameId); + (!marker->frameAction) ? "Begin" : "End", + marker->frameAction, marker->frameId); - IFCALL(update->SurfaceFrameMarker, update->context, marker); + if (!update->SurfaceFrameMarker) + { + WLog_ERR(TAG, "Missing callback update->SurfaceFrameMarker"); + return FALSE; + } - *length = 6; - - return 0; + return update->SurfaceFrameMarker(update->context, marker); } -int update_recv_surfcmds(rdpUpdate* update, UINT32 size, wStream* s) +int update_recv_surfcmds(rdpUpdate* update, wStream* s) { BYTE* mark; UINT16 cmdType; - UINT32 cmdLength = 0; - while (size > 2) + while (Stream_GetRemainingLength(s) >= 2) { + const size_t start = Stream_GetPosition(s); Stream_GetPointer(s, mark); - Stream_Read_UINT16(s, cmdType); - size -= 2; switch (cmdType) { case CMDTYPE_SET_SURFACE_BITS: case CMDTYPE_STREAM_SURFACE_BITS: - if (update_recv_surfcmd_surface_bits(update, s, &cmdLength) < 0) + if (!update_recv_surfcmd_surface_bits(update, s)) return -1; + break; case CMDTYPE_FRAME_MARKER: - if (update_recv_surfcmd_frame_marker(update, s, &cmdLength) < 0) + if (!update_recv_surfcmd_frame_marker(update, s)) return -1; + break; default: @@ -119,12 +159,11 @@ int update_recv_surfcmds(rdpUpdate* update, UINT32 size, wStream* s) return -1; } - size -= cmdLength; - if (update->dump_rfx) { + const size_t size = Stream_GetPosition(s) - start; /* TODO: treat return values */ - pcap_add_record(update->pcap_rfx, mark, cmdLength + 2); + pcap_add_record(update->pcap_rfx, mark, size); pcap_flush(update->pcap_rfx); } } @@ -132,26 +171,63 @@ int update_recv_surfcmds(rdpUpdate* update, UINT32 size, wStream* s) return 0; } -BOOL update_write_surfcmd_surface_bits_header(wStream* s, - const SURFACE_BITS_COMMAND* cmd) +static BOOL update_write_surfcmd_bitmap_header_ex(wStream* s, const TS_COMPRESSED_BITMAP_HEADER_EX* header) +{ + if (!s || !header) + return FALSE; + + if (!Stream_EnsureRemainingCapacity(s, 24)) + return FALSE; + + Stream_Write_UINT32(s, header->highUniqueId); + Stream_Write_UINT32(s, header->lowUniqueId); + Stream_Write_UINT64(s, header->tmMilliseconds); + Stream_Write_UINT64(s, header->tmSeconds); + + return TRUE; +} + +static BOOL update_write_surfcmd_bitmap_ex(wStream* s, const TS_BITMAP_DATA_EX* bmp) +{ + if (!s || !bmp) + return FALSE; + + if (!Stream_EnsureRemainingCapacity(s, 12)) + return FALSE; + + Stream_Write_UINT8(s, bmp->bpp); + Stream_Write_UINT8(s, bmp->flags); + Stream_Write_UINT8(s, 0); /* reserved1, reserved2 */ + Stream_Write_UINT8(s, bmp->codecID); + Stream_Write_UINT16(s, bmp->width); + Stream_Write_UINT16(s, bmp->height); + Stream_Write_UINT32(s, bmp->bitmapDataLength); + + if (bmp->flags & EX_COMPRESSED_BITMAP_HEADER_PRESENT) + { + if (!update_write_surfcmd_bitmap_header_ex(s, &bmp->exBitmapDataHeader)) + return FALSE; + } + + if (!Stream_EnsureRemainingCapacity(s, bmp->bitmapDataLength)) + return FALSE; + + Stream_Write(s, bmp->bitmapData, bmp->bitmapDataLength); + return TRUE; +} + +BOOL update_write_surfcmd_surface_bits(wStream* s, const SURFACE_BITS_COMMAND* cmd) { if (!Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH)) return FALSE; Stream_Write_UINT16(s, CMDTYPE_STREAM_SURFACE_BITS); - Stream_Write_UINT16(s, cmd->destLeft); Stream_Write_UINT16(s, cmd->destTop); Stream_Write_UINT16(s, cmd->destRight); Stream_Write_UINT16(s, cmd->destBottom); - Stream_Write_UINT8(s, cmd->bpp); - Stream_Write_UINT16(s, 0); /* reserved1, reserved2 */ - Stream_Write_UINT8(s, cmd->codecID); - Stream_Write_UINT16(s, cmd->width); - Stream_Write_UINT16(s, cmd->height); - Stream_Write_UINT32(s, cmd->bitmapDataLength); - return TRUE; + return update_write_surfcmd_bitmap_ex(s, &cmd->bmp); } BOOL update_write_surfcmd_frame_marker(wStream* s, UINT16 frameAction, UINT32 frameId) @@ -160,7 +236,6 @@ BOOL update_write_surfcmd_frame_marker(wStream* s, UINT16 frameAction, UINT32 fr return FALSE; Stream_Write_UINT16(s, CMDTYPE_FRAME_MARKER); - Stream_Write_UINT16(s, frameAction); Stream_Write_UINT32(s, frameId); return TRUE; diff --git a/libfreerdp/core/surface.h b/libfreerdp/core/surface.h index 2176714..65bf018 100644 --- a/libfreerdp/core/surface.h +++ b/libfreerdp/core/surface.h @@ -35,10 +35,9 @@ enum SURFCMD_CMDTYPE CMDTYPE_STREAM_SURFACE_BITS = 0x0006 }; -FREERDP_LOCAL int update_recv_surfcmds(rdpUpdate* update, UINT32 size, - wStream* s); +FREERDP_LOCAL int update_recv_surfcmds(rdpUpdate* update, wStream* s); -FREERDP_LOCAL BOOL update_write_surfcmd_surface_bits_header(wStream* s, +FREERDP_LOCAL BOOL update_write_surfcmd_surface_bits(wStream* s, const SURFACE_BITS_COMMAND* cmd); FREERDP_LOCAL BOOL update_write_surfcmd_frame_marker(wStream* s, UINT16 frameAction, UINT32 frameId); diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index f5aa3d7..03f848c 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -664,26 +664,43 @@ BIO_METHOD* BIO_s_buffered_socket(void) return bio_methods; } -char* freerdp_tcp_get_ip_address(int sockfd) +static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6) { - BYTE* ip; socklen_t length; - char ipAddress[32]; - struct sockaddr_in sockaddr; - length = sizeof(sockaddr); - ZeroMemory(&sockaddr, length); + char ipAddress[INET6_ADDRSTRLEN + 1] = { 0 }; + struct sockaddr_storage saddr = { 0 }; + struct sockaddr_in6* sockaddr_ipv6 = (struct sockaddr_in6*)&saddr; + struct sockaddr_in* sockaddr_ipv4 = (struct sockaddr_in*)&saddr; + length = sizeof(struct sockaddr_storage); - if (getsockname(sockfd, (struct sockaddr*) &sockaddr, &length) == 0) + if (getsockname(sockfd, (struct sockaddr*)&saddr, &length) != 0) + return NULL; + + switch (sockaddr_ipv4->sin_family) { - ip = (BYTE*)(&sockaddr.sin_addr); - sprintf_s(ipAddress, sizeof(ipAddress), "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8"", ip[0], ip[1], ip[2], - ip[3]); - } - else - { - strcpy(ipAddress, "127.0.0.1"); + case AF_INET: + if (!inet_ntop(sockaddr_ipv4->sin_family, &sockaddr_ipv4->sin_addr, ipAddress, sizeof(ipAddress))) + return NULL; + + break; + + case AF_INET6: + if (!inet_ntop(sockaddr_ipv6->sin6_family, &sockaddr_ipv6->sin6_addr, ipAddress, sizeof(ipAddress))) + return NULL; + + break; + + case AF_UNIX: + strcpy(ipAddress, "127.0.0.1"); + break; + + default: + return NULL; } + if (pIPv6) + *pIPv6 = (sockaddr_ipv4->sin_family == AF_INET6); + return _strdup(ipAddress); } @@ -743,6 +760,7 @@ static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, struct sockaddr* addr, socklen_t addrlen, int timeout) { + BOOL rc = FALSE; HANDLE handles[2]; int status = 0; int count = 0; @@ -758,7 +776,7 @@ static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, if (status < 0) { WLog_ERR(TAG, "WSAEventSelect failed with %d", WSAGetLastError()); - return FALSE; + goto fail; } handles[count++] = context->abortEvent; @@ -775,7 +793,7 @@ static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, break; default: - return FALSE; + goto fail; } } @@ -786,7 +804,7 @@ static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, if (status == WAIT_OBJECT_0 + 1) freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED); - return FALSE; + goto fail; } status = recv(sockfd, NULL, 0, 0); @@ -794,26 +812,28 @@ static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, if (status == SOCKET_ERROR) { if (WSAGetLastError() == WSAECONNRESET) - return FALSE; + goto fail; } status = WSAEventSelect(sockfd, handles[0], 0); - CloseHandle(handles[0]); if (status < 0) { WLog_ERR(TAG, "WSAEventSelect failed with %d", WSAGetLastError()); - return FALSE; + goto fail; } if (_ioctlsocket(sockfd, FIONBIO, &arg) != 0) - return FALSE; + goto fail; - return TRUE; + rc = TRUE; +fail: + CloseHandle(handles[0]); + return rc; } static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames, - UINT32* ports, int count, int port, + UINT32* ports, UINT32 count, int port, int timeout) { int index; @@ -990,6 +1010,10 @@ BOOL freerdp_tcp_set_keep_alive_mode(int sockfd) WLog_WARN(TAG, "setsockopt() IPPROTO_TCP, TCP_KEEPIDLE"); } +#endif +#ifndef SOL_TCP + /* "tcp" from /etc/protocols as getprotobyname(3C) */ +#define SOL_TCP 6 #endif #ifdef TCP_KEEPCNT optval = 3; @@ -1106,7 +1130,7 @@ int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings, addr = result; - if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0)) + if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0) && !settings->PreferIPv6OverIPv4) { while ((addr = addr->ai_next)) { @@ -1139,9 +1163,8 @@ int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings, } } - settings->IPv6Enabled = FALSE; free(settings->ClientAddress); - settings->ClientAddress = freerdp_tcp_get_ip_address(sockfd); + settings->ClientAddress = freerdp_tcp_get_ip_address(sockfd, &settings->IPv6Enabled); if (!settings->ClientAddress) { diff --git a/libfreerdp/core/test/TestConnect.c b/libfreerdp/core/test/TestConnect.c index cab56f7..83762c6 100644 --- a/libfreerdp/core/test/TestConnect.c +++ b/libfreerdp/core/test/TestConnect.c @@ -9,21 +9,23 @@ static HANDLE s_sync = NULL; static int runInstance(int argc, char* argv[], freerdp** inst) { int rc = -1; - freerdp* instance = freerdp_new(); + RDP_CLIENT_ENTRY_POINTS clientEntryPoints; + ZeroMemory(&clientEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS)); + clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS); + clientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION; + clientEntryPoints.ContextSize = sizeof(rdpContext); + rdpContext* context = freerdp_client_context_new(&clientEntryPoints); - if (!instance) + if (!context) goto finish; if (inst) - *inst = instance; + *inst = context->instance; - if (!freerdp_context_new(instance)) + if (freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE) < 0) goto finish; - 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)) + if (!freerdp_client_load_addins(context->channels, context->settings)) goto finish; if (s_sync) @@ -34,18 +36,17 @@ static int runInstance(int argc, char* argv[], freerdp** inst) rc = 1; - if (!freerdp_connect(instance)) + if (!freerdp_connect(context->instance)) goto finish; rc = 2; - if (!freerdp_disconnect(instance)) + if (!freerdp_disconnect(context->instance)) goto finish; rc = 0; finish: - freerdp_context_free(instance); - freerdp_free(instance); + freerdp_client_context_free(context); return rc; } @@ -87,7 +88,7 @@ struct testThreadArgs freerdp** arg; }; -static void* testThread(void* arg) +static DWORD WINAPI testThread(LPVOID arg) { char arg1[] = "/v:192.0.2.1:XXXXX"; char* argv[] = @@ -106,7 +107,7 @@ static void* testThread(void* arg) ExitThread(-1); ExitThread(0); - return NULL; + return 0; } static int testAbort(int port) @@ -124,7 +125,7 @@ static int testAbort(int port) args.port = port; args.arg = &instance; start = GetTickCount(); - thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)testThread, + thread = CreateThread(NULL, 0, testThread, &args, 0, NULL); if (!thread) @@ -135,6 +136,7 @@ static int testAbort(int port) } WaitForSingleObject(s_sync, INFINITE); + Sleep(1000); /* Wait until freerdp_connect has been called */ freerdp_abort_connect(instance); status = WaitForSingleObject(instance->context->abortEvent, 0); @@ -153,8 +155,11 @@ static int testAbort(int port) s_sync = NULL; diff = end - start; - if (diff > 1000) + if (diff > 5000) + { + printf("%s required %"PRIu32"ms for the test\n", __FUNCTION__, diff); return -1; + } if (WAIT_OBJECT_0 != status) return -1; @@ -227,7 +232,7 @@ static int testSuccess(int port) } // Start sample server locally. - commandLineLen = strlen(exe) + strlen(" --port=XXXXX") + 1; + commandLineLen = strlen(exe) + strlen("--local-only --port=XXXXX") + 1; commandLine = malloc(commandLineLen); if (!commandLine) @@ -238,7 +243,7 @@ static int testSuccess(int port) return -2; } - _snprintf(commandLine, commandLineLen, "%s --port=%d", exe, port); + _snprintf(commandLine, commandLineLen, "%s --local-only --port=%d", exe, port); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); diff --git a/libfreerdp/core/tpdu.c b/libfreerdp/core/tpdu.c index 441b090..9c94d89 100644 --- a/libfreerdp/core/tpdu.c +++ b/libfreerdp/core/tpdu.c @@ -161,8 +161,8 @@ void tpdu_write_connection_request(wStream* s, UINT16 length) BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li) { BYTE code; - int position; - int bytes_read = 0; + size_t position; + size_t bytes_read = 0; /* save the position to determine the number of bytes read */ position = Stream_GetPosition(s); diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index cb97cf3..ad44e0a 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -57,9 +57,9 @@ #define BUFFER_SIZE 16384 -static void* transport_client_thread(void* arg); +static DWORD WINAPI transport_client_thread(LPVOID arg); -#ifdef WITH_KRB5 +#ifdef WITH_GSSAPI #include <krb5.h> #include <winpr/library.h> @@ -150,7 +150,7 @@ out: krb5_free_context(context); return ret; } -#endif /* WITH_KRB5 */ +#endif /* WITH_GSSAPI */ static void transport_ssl_cb(SSL* ssl, int where, int ret) { @@ -174,7 +174,7 @@ static void transport_ssl_cb(SSL* ssl, int where, int ret) if (transport->NlaMode) { UINT32 kret = 0; -#ifdef WITH_KRB5 +#ifdef WITH_GSSAPI if ((strlen(transport->settings->Domain) != 0) && (strncmp(transport->settings->Domain, ".", 1) != 0)) @@ -184,7 +184,7 @@ static void transport_ssl_cb(SSL* ssl, int where, int ret) transport->settings->Password); } else -#endif /* WITH_KRB5 */ +#endif /* WITH_GSSAPI */ kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED; if (!freerdp_get_last_error(transport->context)) @@ -425,8 +425,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, return FALSE; } - if (!(transport->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL))) + if (!(transport->thread = CreateThread(NULL, 0, transport_client_thread, transport, 0, NULL))) { WLog_Print(transport->log, WLOG_ERROR, "Failed to create transport client thread"); CloseHandle(transport->stopEvent); @@ -642,7 +641,7 @@ static int transport_read_layer_bytes(rdpTransport* transport, wStream* s, int transport_read_pdu(rdpTransport* transport, wStream* s) { int status; - int position; + size_t position; int pduLength; BYTE* header; pduLength = 0; @@ -767,8 +766,7 @@ int transport_read_pdu(rdpTransport* transport, wStream* s) if (!Stream_EnsureCapacity(s, Stream_GetPosition(s) + pduLength)) return -1; - status = transport_read_layer_bytes(transport, s, - pduLength - Stream_GetPosition(s)); + status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s)); if (status != 1) return status; @@ -784,7 +782,7 @@ int transport_read_pdu(rdpTransport* transport, wStream* s) int transport_write(rdpTransport* transport, wStream* s) { - int length; + size_t length; int status = -1; int writtenlength = 0; @@ -955,7 +953,7 @@ void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount) rfds[index] = GetEventWaitObject(events[index]); } - rfds[nCount + 1] = GetEventWaitObject(transport->rereadEvent); + rfds[nCount] = GetEventWaitObject(transport->rereadEvent); } BOOL transport_is_write_blocked(rdpTransport* transport) @@ -997,8 +995,13 @@ int transport_check_fds(rdpTransport* transport) ResetEvent(transport->rereadEvent); } - while (!freerdp_shall_disconnect(transport->context->instance) && (now < dueDate)) + while (now < dueDate) { + if (freerdp_shall_disconnect(transport->context->instance)) + { + return -1; + } + /** * Note: transport_read_pdu tries to read one PDU from * the transport layer. @@ -1027,8 +1030,7 @@ int transport_check_fds(rdpTransport* transport) * 0: success * 1: redirection */ - recv_status = transport->ReceiveCallback(transport, received, - transport->ReceiveExtra); + recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra); Stream_Release(received); /* session redirection or activation */ @@ -1129,7 +1131,7 @@ BOOL transport_disconnect(rdpTransport* transport) return status; } -static void* transport_client_thread(void* arg) +DWORD WINAPI transport_client_thread(LPVOID arg) { DWORD dwExitCode = 0; DWORD status; @@ -1192,7 +1194,9 @@ static void* transport_client_thread(void* arg) { if (!freerdp_check_event_handles(context)) { - WLog_Print(transport->log, WLOG_ERROR, "freerdp_check_event_handles()"); + if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) + WLog_Print(transport->log, WLOG_ERROR, "freerdp_check_event_handles()"); + rdp_set_error_info(rdp, ERRINFO_PEER_DISCONNECTED); break; } @@ -1212,7 +1216,7 @@ static void* transport_client_thread(void* arg) out: WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread"); ExitThread(dwExitCode); - return NULL; + return dwExitCode; } rdpTransport* transport_new(rdpContext* context) diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index d2d9112..8088794 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -42,7 +42,7 @@ #define TAG FREERDP_TAG("core.update") -const char* const UPDATE_TYPE_STRINGS[] = +static const char* const UPDATE_TYPE_STRINGS[] = { "Orders", "Bitmap", @@ -50,7 +50,7 @@ const char* const UPDATE_TYPE_STRINGS[] = "Synchronize" }; -BOOL update_recv_orders(rdpUpdate* update, wStream* s) +static BOOL update_recv_orders(rdpUpdate* update, wStream* s) { UINT16 numberOrders; @@ -121,8 +121,8 @@ static BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, return TRUE; } -BOOL update_write_bitmap_data(rdpUpdate* update, wStream* s, - BITMAP_DATA* bitmapData) +static BOOL update_write_bitmap_data(rdpUpdate* update, wStream* s, + BITMAP_DATA* bitmapData) { if (!Stream_EnsureRemainingCapacity(s, 64 + bitmapData->bitmapLength)) return FALSE; @@ -262,7 +262,7 @@ BOOL update_read_palette(rdpUpdate* update, wStream* s, return TRUE; } -void update_read_synchronize(rdpUpdate* update, wStream* s) +static void update_read_synchronize(rdpUpdate* update, wStream* s) { Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */ /** @@ -271,7 +271,7 @@ void update_read_synchronize(rdpUpdate* update, wStream* s) */ } -BOOL update_read_play_sound(wStream* s, PLAY_SOUND_UPDATE* play_sound) +static BOOL update_read_play_sound(wStream* s, PLAY_SOUND_UPDATE* play_sound) { if (Stream_GetRemainingLength(s) < 8) return FALSE; @@ -301,8 +301,8 @@ BOOL update_read_pointer_position(wStream* s, return TRUE; } -BOOL update_read_pointer_system(wStream* s, - POINTER_SYSTEM_UPDATE* pointer_system) +static BOOL update_read_pointer_system(wStream* s, + POINTER_SYSTEM_UPDATE* pointer_system) { if (Stream_GetRemainingLength(s) < 4) return FALSE; @@ -376,7 +376,8 @@ BOOL update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color, if (scanlineSize * pointer_color->height != pointer_color->lengthXorMask) { - WLog_ERR(TAG, "invalid lengthXorMask: width=%"PRIu32" height=%"PRIu32", %"PRIu32" instead of %"PRIu32"", + WLog_ERR(TAG, + "invalid lengthXorMask: width=%"PRIu32" height=%"PRIu32", %"PRIu32" instead of %"PRIu32"", pointer_color->width, pointer_color->height, pointer_color->lengthXorMask, scanlineSize * pointer_color->height); return FALSE; @@ -562,6 +563,10 @@ BOOL update_recv(rdpUpdate* update, wStream* s) update_read_synchronize(update, s); IFCALL(update->Synchronize, context); break; + + default: + WLog_ERR(TAG, "unknown update type %"PRIu16"", updateType); + break; } IFCALL(update->EndPaint, context); @@ -831,7 +836,7 @@ static int update_prepare_order_info(rdpContext* context, int update_write_order_info(rdpContext* context, wStream* s, ORDER_INFO* orderInfo, int offset) { - int position; + size_t position; position = Stream_GetPosition(s); Stream_SetPosition(s, offset); Stream_Write_UINT8(s, orderInfo->controlFlags); /* controlFlags (1 byte) */ @@ -961,15 +966,9 @@ static BOOL update_send_surface_bits(rdpContext* context, if (!s) return FALSE; - if (!Stream_EnsureRemainingCapacity(s, - SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surfaceBitsCommand->bitmapDataLength) - || - !update_write_surfcmd_surface_bits_header(s, surfaceBitsCommand)) + if (!update_write_surfcmd_surface_bits(s, surfaceBitsCommand)) goto out_fail; - Stream_Write(s, surfaceBitsCommand->bitmapData, - surfaceBitsCommand->bitmapDataLength); - if (!fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s, surfaceBitsCommand->skipCompression)) goto out_fail; @@ -1019,10 +1018,6 @@ static BOOL update_send_surface_frame_bits(rdpContext* context, if (!s) return FALSE; - if (!Stream_EnsureRemainingCapacity(s, - SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) cmd->bitmapDataLength + 16)) - goto out_fail; - if (first) { if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, @@ -1030,11 +1025,9 @@ static BOOL update_send_surface_frame_bits(rdpContext* context, goto out_fail; } - if (!update_write_surfcmd_surface_bits_header(s, cmd)) + if (!update_write_surfcmd_surface_bits(s, cmd)) goto out_fail; - Stream_Write(s, cmd->bitmapData, cmd->bitmapDataLength); - if (last) { if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId)) @@ -1184,7 +1177,7 @@ static BOOL update_send_dstblt(rdpContext* context, static BOOL update_send_patblt(rdpContext* context, PATBLT_ORDER* patblt) { wStream* s; - int offset; + size_t offset; int headerLength; ORDER_INFO orderInfo; rdpUpdate* update = context->update; @@ -1242,7 +1235,7 @@ static BOOL update_send_opaque_rect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect) { wStream* s; - int offset; + size_t offset; int headerLength; ORDER_INFO orderInfo; rdpUpdate* update = context->update; @@ -1300,7 +1293,7 @@ static BOOL update_send_line_to(rdpContext* context, static BOOL update_send_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { wStream* s; - int offset; + size_t offset; int headerLength; ORDER_INFO orderInfo; rdpUpdate* update = context->update; @@ -1329,7 +1322,7 @@ static BOOL update_send_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index) { wStream* s; - int offset; + size_t offset; int headerLength; int inf; ORDER_INFO orderInfo; @@ -1363,7 +1356,7 @@ static BOOL update_send_cache_bitmap(rdpContext* context, const CACHE_BITMAP_ORDER* cache_bitmap) { wStream* s; - int bm, em; + size_t bm, em; BYTE orderType; int headerLength; int inf; @@ -1411,7 +1404,7 @@ static BOOL update_send_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2) { wStream* s; - int bm, em; + size_t bm, em; BYTE orderType; int headerLength; UINT16 extraFlags; @@ -1461,7 +1454,7 @@ static BOOL update_send_cache_bitmap_v3(rdpContext* context, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3) { wStream* s; - int bm, em; + size_t bm, em; BYTE orderType; int headerLength; UINT16 extraFlags; @@ -1506,7 +1499,7 @@ static BOOL update_send_cache_color_table(rdpContext* context, { wStream* s; UINT16 flags; - int bm, em, inf; + size_t bm, em, inf; int headerLength; INT16 orderLength; rdpUpdate* update = context->update; @@ -1547,7 +1540,7 @@ static BOOL update_send_cache_glyph(rdpContext* context, { wStream* s; UINT16 flags; - int bm, em, inf; + size_t bm, em, inf; int headerLength; INT16 orderLength; rdpUpdate* update = context->update; @@ -1588,7 +1581,7 @@ static BOOL update_send_cache_glyph_v2(rdpContext* context, { wStream* s; UINT16 flags; - int bm, em, inf; + size_t bm, em, inf; int headerLength; INT16 orderLength; rdpUpdate* update = context->update; @@ -1614,8 +1607,7 @@ static BOOL update_send_cache_glyph_v2(rdpContext* context, em = Stream_GetPosition(s); orderLength = (em - bm) - 13; Stream_SetPosition(s, bm); - Stream_Write_UINT8(s, ORDER_STANDARD | - ORDER_SECONDARY); /* controlFlags (1 byte) */ + Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */ Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */ Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */ Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH); /* orderType (1 byte) */ @@ -1629,7 +1621,7 @@ static BOOL update_send_cache_brush(rdpContext* context, { wStream* s; UINT16 flags; - int bm, em, inf; + size_t bm, em, inf; int headerLength; INT16 orderLength; rdpUpdate* update = context->update; @@ -1674,7 +1666,7 @@ static BOOL update_send_create_offscreen_bitmap_order( const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap) { wStream* s; - int bm, em, inf; + size_t bm, em, inf; BYTE orderType; BYTE controlFlags; int headerLength; @@ -1713,7 +1705,7 @@ static BOOL update_send_switch_surface_order( const SWITCH_SURFACE_ORDER* switch_surface) { wStream* s; - int bm, em, inf; + size_t bm, em, inf; BYTE orderType; BYTE controlFlags; int headerLength; @@ -2044,17 +2036,15 @@ static void update_free_queued_message(void* obj) static void update_free_window_state(WINDOW_STATE_ORDER* window_state) { - if (!window_state) - return; + if (!window_state) + return; - free(window_state->titleInfo.string); - window_state->titleInfo.string = NULL; - - free(window_state->windowRects); - window_state->windowRects = NULL; - - free(window_state->visibilityRects); - window_state->visibilityRects = NULL; + free(window_state->titleInfo.string); + window_state->titleInfo.string = NULL; + free(window_state->windowRects); + window_state->windowRects = NULL; + free(window_state->visibilityRects); + window_state->visibilityRects = NULL; } rdpUpdate* update_new(rdpRdp* rdp) @@ -2067,7 +2057,6 @@ rdpUpdate* update_new(rdpRdp* rdp) if (!update) return NULL; - WLog_Init(); update->log = WLog_Get("com.freerdp.core.update"); update->bitmap_update.count = 64; update->bitmap_update.rectangles = (BITMAP_DATA*) calloc( diff --git a/libfreerdp/core/update.h b/libfreerdp/core/update.h index d9b43d0..df0990c 100644 --- a/libfreerdp/core/update.h +++ b/libfreerdp/core/update.h @@ -40,7 +40,6 @@ FREERDP_LOCAL rdpUpdate* update_new(rdpRdp* rdp); FREERDP_LOCAL void update_free(rdpUpdate* update); -FREERDP_LOCAL void update_free_bitmap(BITMAP_UPDATE* bitmap_update); FREERDP_LOCAL void update_reset_state(rdpUpdate* update); FREERDP_LOCAL BOOL update_post_connect(rdpUpdate* update); FREERDP_LOCAL void update_post_disconnect(rdpUpdate* update); @@ -53,8 +52,6 @@ FREERDP_LOCAL BOOL update_recv_pointer(rdpUpdate* update, wStream* s); FREERDP_LOCAL BOOL update_recv(rdpUpdate* update, wStream* s); FREERDP_LOCAL BOOL update_read_pointer_position(wStream* s, POINTER_POSITION_UPDATE* pointer_position); -FREERDP_LOCAL BOOL update_read_pointer_system(wStream* s, - POINTER_SYSTEM_UPDATE* pointer_system); FREERDP_LOCAL BOOL update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color, int xorBpp); FREERDP_LOCAL BOOL update_read_pointer_new(wStream* s, diff --git a/libfreerdp/crypto/ber.c b/libfreerdp/crypto/ber.c index 86b965f..e7bce2e 100644 --- a/libfreerdp/crypto/ber.c +++ b/libfreerdp/crypto/ber.c @@ -29,12 +29,13 @@ #define TAG FREERDP_TAG("crypto") -BOOL ber_read_length(wStream* s, int* length) +BOOL ber_read_length(wStream* s, size_t* length) { BYTE byte; if (Stream_GetRemainingLength(s) < 1) return FALSE; + Stream_Read_UINT8(s, byte); if (byte & 0x80) @@ -55,6 +56,7 @@ BOOL ber_read_length(wStream* s, int* length) { *length = byte; } + return TRUE; } @@ -64,7 +66,7 @@ BOOL ber_read_length(wStream* s, int* length) * @param length length */ -int ber_write_length(wStream* s, int length) +size_t ber_write_length(wStream* s, size_t length) { if (length > 0xFF) { @@ -72,22 +74,26 @@ int ber_write_length(wStream* s, int length) Stream_Write_UINT16_BE(s, length); return 3; } + if (length > 0x7F) { Stream_Write_UINT8(s, 0x80 ^ 1); Stream_Write_UINT8(s, length); return 2; } + Stream_Write_UINT8(s, length); return 1; } -int _ber_sizeof_length(int length) +size_t _ber_sizeof_length(size_t length) { if (length > 0xFF) return 3; + if (length > 0x7F) return 2; + return 1; } @@ -104,6 +110,7 @@ BOOL ber_read_universal_tag(wStream* s, BYTE tag, BOOL pc) if (Stream_GetRemainingLength(s) < 1) return FALSE; + Stream_Read_UINT8(s, byte); if (byte != (BER_CLASS_UNIV | BER_PC(pc) | (BER_TAG_MASK & tag))) @@ -119,7 +126,7 @@ BOOL ber_read_universal_tag(wStream* s, BYTE tag, BOOL pc) * @param pc primitive (FALSE) or constructed (TRUE) */ -int ber_write_universal_tag(wStream* s, BYTE tag, BOOL pc) +size_t ber_write_universal_tag(wStream* s, BYTE tag, BOOL pc) { Stream_Write_UINT8(s, (BER_CLASS_UNIV | BER_PC(pc)) | (BER_TAG_MASK & tag)); return 1; @@ -132,7 +139,7 @@ int ber_write_universal_tag(wStream* s, BYTE tag, BOOL pc) * @param length length */ -BOOL ber_read_application_tag(wStream* s, BYTE tag, int* length) +BOOL ber_read_application_tag(wStream* s, BYTE tag, size_t* length) { BYTE byte; @@ -140,6 +147,7 @@ BOOL ber_read_application_tag(wStream* s, BYTE tag, int* length) { if (Stream_GetRemainingLength(s) < 1) return FALSE; + Stream_Read_UINT8(s, byte); if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK)) @@ -147,6 +155,7 @@ BOOL ber_read_application_tag(wStream* s, BYTE tag, int* length) if (Stream_GetRemainingLength(s) < 1) return FALSE; + Stream_Read_UINT8(s, byte); if (byte != tag) @@ -158,6 +167,7 @@ BOOL ber_read_application_tag(wStream* s, BYTE tag, int* length) { if (Stream_GetRemainingLength(s) < 1) return FALSE; + Stream_Read_UINT8(s, byte); if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag))) @@ -176,7 +186,7 @@ BOOL ber_read_application_tag(wStream* s, BYTE tag, int* length) * @param length length */ -void ber_write_application_tag(wStream* s, BYTE tag, int length) +void ber_write_application_tag(wStream* s, BYTE tag, size_t length) { if (tag > 30) { @@ -191,12 +201,13 @@ void ber_write_application_tag(wStream* s, BYTE tag, int length) } } -BOOL ber_read_contextual_tag(wStream* s, BYTE tag, int* length, BOOL pc) +BOOL ber_read_contextual_tag(wStream* s, BYTE tag, size_t* length, BOOL pc) { BYTE byte; if (Stream_GetRemainingLength(s) < 1) return FALSE; + Stream_Read_UINT8(s, byte); if (byte != ((BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag))) @@ -208,23 +219,24 @@ BOOL ber_read_contextual_tag(wStream* s, BYTE tag, int* length, BOOL pc) return ber_read_length(s, length); } -int ber_write_contextual_tag(wStream* s, BYTE tag, int length, BOOL pc) +size_t ber_write_contextual_tag(wStream* s, BYTE tag, size_t length, BOOL pc) { Stream_Write_UINT8(s, (BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag)); return 1 + ber_write_length(s, length); } -int ber_sizeof_contextual_tag(int length) +size_t ber_sizeof_contextual_tag(size_t length) { return 1 + _ber_sizeof_length(length); } -BOOL ber_read_sequence_tag(wStream* s, int* length) +BOOL ber_read_sequence_tag(wStream* s, size_t* length) { BYTE byte; if (Stream_GetRemainingLength(s) < 1) return FALSE; + Stream_Read_UINT8(s, byte); if (byte != ((BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_SEQUENCE_OF))) @@ -239,28 +251,28 @@ BOOL ber_read_sequence_tag(wStream* s, int* length) * @param length length */ -int ber_write_sequence_tag(wStream* s, int length) +size_t ber_write_sequence_tag(wStream* s, size_t length) { Stream_Write_UINT8(s, (BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_MASK & BER_TAG_SEQUENCE)); return 1 + ber_write_length(s, length); } -int ber_sizeof_sequence(int length) +size_t ber_sizeof_sequence(size_t length) { return 1 + _ber_sizeof_length(length) + length; } -int ber_sizeof_sequence_tag(int length) +size_t ber_sizeof_sequence_tag(size_t length) { return 1 + _ber_sizeof_length(length); } BOOL ber_read_enumerated(wStream* s, BYTE* enumerated, BYTE count) { - int length; + size_t length; if (!ber_read_universal_tag(s, BER_TAG_ENUMERATED, FALSE) || - !ber_read_length(s, &length)) + !ber_read_length(s, &length)) return FALSE; if (length != 1 || Stream_GetRemainingLength(s) < 1) @@ -282,14 +294,15 @@ void ber_write_enumerated(wStream* s, BYTE enumerated, BYTE count) Stream_Write_UINT8(s, enumerated); } -BOOL ber_read_bit_string(wStream* s, int* length, BYTE* padding) +BOOL ber_read_bit_string(wStream* s, size_t* length, BYTE* padding) { if (!ber_read_universal_tag(s, BER_TAG_BIT_STRING, FALSE) || - !ber_read_length(s, length)) + !ber_read_length(s, length)) return FALSE; if (Stream_GetRemainingLength(s) < 1) return FALSE; + Stream_Read_UINT8(s, *padding); return TRUE; } @@ -301,9 +314,9 @@ BOOL ber_read_bit_string(wStream* s, int* length, BYTE* padding) * @param length string length */ -int ber_write_octet_string(wStream* s, const BYTE* oct_str, int length) +size_t ber_write_octet_string(wStream* s, const BYTE* oct_str, size_t length) { - int size = 0; + size_t size = 0; size += ber_write_universal_tag(s, BER_TAG_OCTET_STRING, FALSE); size += ber_write_length(s, length); Stream_Write(s, oct_str, length); @@ -311,21 +324,21 @@ int ber_write_octet_string(wStream* s, const BYTE* oct_str, int length) return size; } -BOOL ber_read_octet_string_tag(wStream* s, int* length) +BOOL ber_read_octet_string_tag(wStream* s, size_t* length) { return - ber_read_universal_tag(s, BER_TAG_OCTET_STRING, FALSE) && - ber_read_length(s, length); + ber_read_universal_tag(s, BER_TAG_OCTET_STRING, FALSE) && + ber_read_length(s, length); } -int ber_write_octet_string_tag(wStream* s, int length) +size_t ber_write_octet_string_tag(wStream* s, size_t length) { ber_write_universal_tag(s, BER_TAG_OCTET_STRING, FALSE); ber_write_length(s, length); return 1 + _ber_sizeof_length(length); } -int ber_sizeof_octet_string(int length) +size_t ber_sizeof_octet_string(size_t length) { return 1 + _ber_sizeof_length(length) + length; } @@ -338,11 +351,11 @@ int ber_sizeof_octet_string(int length) BOOL ber_read_BOOL(wStream* s, BOOL* value) { - int length; + size_t length; BYTE v; if (!ber_read_universal_tag(s, BER_TAG_BOOLEAN, FALSE) || - !ber_read_length(s, &length)) + !ber_read_length(s, &length)) return FALSE; if (length != 1 || Stream_GetRemainingLength(s) < 1) @@ -368,11 +381,11 @@ void ber_write_BOOL(wStream* s, BOOL value) BOOL ber_read_integer(wStream* s, UINT32* value) { - int length; + size_t length; if (!ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE) || - !ber_read_length(s, &length) || - ((int) Stream_GetRemainingLength(s)) < length) + !ber_read_length(s, &length) || + (Stream_GetRemainingLength(s) < length)) return FALSE; if (value == NULL) @@ -420,7 +433,7 @@ BOOL ber_read_integer(wStream* s, UINT32* value) * @param value */ -int ber_write_integer(wStream* s, UINT32 value) +size_t ber_write_integer(wStream* s, UINT32 value) { if (value < 0x80) { @@ -463,7 +476,7 @@ int ber_write_integer(wStream* s, UINT32 value) return 0; } -int ber_sizeof_integer(UINT32 value) +size_t ber_sizeof_integer(UINT32 value) { if (value < 0x80) { @@ -490,9 +503,9 @@ int ber_sizeof_integer(UINT32 value) return 0; } -BOOL ber_read_integer_length(wStream* s, int* length) +BOOL ber_read_integer_length(wStream* s, size_t* length) { return - ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE) && - ber_read_length(s, length); + ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE) && + ber_read_length(s, length); } diff --git a/libfreerdp/crypto/certificate.c b/libfreerdp/crypto/certificate.c index 4a6d5a7..91c7796 100644 --- a/libfreerdp/crypto/certificate.c +++ b/libfreerdp/crypto/certificate.c @@ -184,7 +184,9 @@ static int certificate_data_match_legacy(rdpCertificateStore* certificate_store, hostname, pline); else if (strcmp(hostname, certificate_data->hostname) == 0) { - match = strcmp(pline, certificate_data->fingerprint); + const int diff = strcmp(pline, certificate_data->fingerprint); + + match = (diff == 0) ? 0 : -1; break; } } diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 15e65d5..8564c57 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -388,7 +388,7 @@ BOOL x509_verify_certificate(CryptoCert cert, char* certificate_store_path) if (cert_ctx == NULL) goto end; -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) OpenSSL_add_all_algorithms(); #else OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ @@ -477,7 +477,7 @@ void crypto_cert_print_info(X509* xcert) WLog_INFO(TAG, "\tThumbprint: %s", fp); 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."); + "Please look at the OpenSSL documentation on how to add a private CA to the store."); free(fp); out_free_issuer: free(issuer); diff --git a/libfreerdp/crypto/per.c b/libfreerdp/crypto/per.c index 6a7bbf8..41f0ea8 100644 --- a/libfreerdp/crypto/per.c +++ b/libfreerdp/crypto/per.c @@ -309,6 +309,7 @@ void per_write_enumerated(wStream* s, BYTE enumerated, BYTE count) * Read PER OBJECT_IDENTIFIER (OID). * @param s stream * @param oid object identifier (OID) + * @warning It works correctly only for limited set of OIDs. * @return */ @@ -328,8 +329,8 @@ BOOL per_read_object_identifier(wStream* s, BYTE oid[6]) return FALSE; Stream_Read_UINT8(s, t12); /* first two tuples */ - a_oid[0] = (t12 >> 4); - a_oid[1] = (t12 & 0x0F); + a_oid[0] = t12 / 40; + a_oid[1] = t12 % 40; Stream_Read_UINT8(s, a_oid[2]); /* tuple 3 */ Stream_Read_UINT8(s, a_oid[3]); /* tuple 4 */ @@ -352,11 +353,12 @@ BOOL per_read_object_identifier(wStream* s, BYTE oid[6]) * Write PER OBJECT_IDENTIFIER (OID) * @param s stream * @param oid object identifier (oid) + * @warning It works correctly only for limited set of OIDs. */ void per_write_object_identifier(wStream* s, BYTE oid[6]) { - BYTE t12 = (oid[0] << 4) & (oid[1] & 0x0F); + BYTE t12 = oid[0] * 40 + oid[1]; Stream_Write_UINT8(s, 5); /* length */ Stream_Write_UINT8(s, t12); /* first two tuples */ Stream_Write_UINT8(s, oid[2]); /* tuple 3 */ diff --git a/libfreerdp/crypto/test/TestKnownHosts.c b/libfreerdp/crypto/test/TestKnownHosts.c index 1c76233..45dd8c2 100644 --- a/libfreerdp/crypto/test/TestKnownHosts.c +++ b/libfreerdp/crypto/test/TestKnownHosts.c @@ -24,13 +24,13 @@ static int prepare(const char* currentFileV2, const char* legacyFileV2, const char* legacyFile) { char* legacy[] = { - "someurl ff:11:22:dd\r\n", - "otherurl aa:bb:cc:dd\r", - "legacyurl aa:bb:cc:dd\n" + "someurl ff:11:22:dd\r\n", + "otherurl aa:bb:cc:dd\r", + "legacyurl aa:bb:cc:dd\n" }; char* hosts[] = { - "someurl 3389 ff:11:22:dd subject issuer\r\n", - "otherurl\t3389\taa:bb:cc:dd\tsubject2\tissuer2\r", + "someurl 3389 ff:11:22:dd subject issuer\r\n", + "otherurl\t3389\taa:bb:cc:dd\tsubject2\tissuer2\r", }; FILE* fl = NULL; FILE* fc = NULL; @@ -47,7 +47,7 @@ static int prepare(const char* currentFileV2, const char* legacyFileV2, const ch for (i=0; i<sizeof(hosts)/sizeof(hosts[0]); i++) { if (fwrite(hosts[i], strlen(hosts[i]), 1, fl) != 1 || - fwrite(hosts[i], strlen(hosts[i]), 1, fc) != 1) + fwrite(hosts[i], strlen(hosts[i]), 1, fc) != 1) goto finish; } @@ -135,7 +135,7 @@ int TestKnownHosts(int argc, char* argv[]) goto finish; } - store = certificate_store_new(¤t); + store = certificate_store_new(¤t); if (!store) { fprintf(stderr, "Could not create certificate store!\n"); @@ -306,6 +306,8 @@ int TestKnownHosts(int argc, char* argv[]) rc = 0; finish: + free(current.ConfigPath); + free(legacy.ConfigPath); if (store) certificate_store_free(store); if (data) diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index c415763..c9ae8c8 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -23,6 +23,7 @@ #include <assert.h> #include <string.h> +#include <errno.h> #include <winpr/crt.h> #include <winpr/sspi.h> @@ -77,8 +78,8 @@ struct _BIO_RDP_TLS }; typedef struct _BIO_RDP_TLS BIO_RDP_TLS; -long bio_rdp_tls_callback(BIO* bio, int mode, const char* argp, int argi, - long argl, long ret) +static long bio_rdp_tls_callback(BIO* bio, int mode, const char* argp, int argi, + long argl, long ret) { return 1; } @@ -234,7 +235,6 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr) int status = -1; BIO_RDP_TLS* tls = (BIO_RDP_TLS*) BIO_get_data(bio); - if (!tls) return 0; @@ -340,6 +340,7 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr) break; case BIO_CTRL_POP: + /* Only detach if we are the BIO explicitly being popped */ if (bio == ptr) { @@ -347,8 +348,10 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr) BIO_free_all(ssl_wbio); #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + if (next_bio) CRYPTO_add(&(bio->next_bio->references), -1, CRYPTO_LOCK_BIO); + tls->ssl->wbio = tls->ssl->rbio = NULL; #else /* OpenSSL 1.1: This will also clear the reference we obtained during push */ @@ -392,7 +395,6 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr) } BIO_set_init(bio, 1); - status = 1; break; @@ -437,16 +439,13 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr) static int bio_rdp_tls_new(BIO* bio) { BIO_RDP_TLS* tls; - BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY); if (!(tls = calloc(1, sizeof(BIO_RDP_TLS)))) return 0; InitializeCriticalSectionAndSpinCount(&tls->lock, 4000); - BIO_set_data(bio, (void*) tls); - return 1; } @@ -469,6 +468,7 @@ static int bio_rdp_tls_free(BIO* bio) SSL_shutdown(tls->ssl); SSL_free(tls->ssl); } + BIO_set_init(bio, 0); BIO_set_flags(bio, 0); } @@ -508,7 +508,7 @@ static long bio_rdp_tls_callback_ctrl(BIO* bio, int cmd, bio_info_cb* fp) #define BIO_TYPE_RDP_TLS 68 -BIO_METHOD* BIO_s_rdp_tls(void) +static BIO_METHOD* BIO_s_rdp_tls(void) { static BIO_METHOD* bio_methods = NULL; @@ -530,7 +530,7 @@ BIO_METHOD* BIO_s_rdp_tls(void) return bio_methods; } -BIO* BIO_new_rdp_tls(SSL_CTX* ctx, int client) +static BIO* BIO_new_rdp_tls(SSL_CTX* ctx, int client) { BIO* bio; SSL* ssl; @@ -596,7 +596,7 @@ static void tls_free_certificate(CryptoCert cert) #define TLS_SERVER_END_POINT "tls-server-end-point:" -SecPkgContext_Bindings* tls_get_channel_bindings(X509* cert) +static SecPkgContext_Bindings* tls_get_channel_bindings(X509* cert) { int PrefixLength; BYTE CertificateHash[32]; @@ -681,7 +681,7 @@ static BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method, return TRUE; } -int tls_do_handshake(rdpTls* tls, BOOL clientMode) +static int tls_do_handshake(rdpTls* tls, BOOL clientMode) { CryptoCert cert; int verify_status; @@ -1016,12 +1016,12 @@ BOOL tls_send_alert(rdpTls* tls) if (!tls->ssl) return TRUE; -/** - * FIXME: The following code does not work on OpenSSL > 1.1.0 because the - * SSL struct is opaqe now - */ - + /** + * FIXME: The following code does not work on OpenSSL > 1.1.0 because the + * SSL struct is opaqe now + */ #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + if (tls->alertDescription != TLS_ALERT_DESCRIPTION_CLOSE_NOTIFY) { /** @@ -1035,7 +1035,6 @@ BOOL tls_send_alert(rdpTls* tls) */ SSL_SESSION* ssl_session = SSL_get_session(tls->ssl); SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(tls->ssl); - SSL_set_quiet_shutdown(tls->ssl, 1); if ((tls->alertLevel == TLS_ALERT_LEVEL_FATAL) && (ssl_session)) @@ -1048,12 +1047,12 @@ BOOL tls_send_alert(rdpTls* tls) if (tls->ssl->s3->wbuf.left == 0) tls->ssl->method->ssl_dispatch_alert(tls->ssl); } -#endif +#endif return TRUE; } -BIO* findBufferedBio(BIO* front) +static BIO* findBufferedBio(BIO* front) { BIO* ret = front; @@ -1467,7 +1466,6 @@ rdpTls* tls_new(rdpSettings* settings) if (!tls) return NULL; - winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT); tls->settings = settings; if (!settings->ServerMode) diff --git a/libfreerdp/gdi/CMakeLists.txt b/libfreerdp/gdi/CMakeLists.txt index d3f91a1..891e743 100644 --- a/libfreerdp/gdi/CMakeLists.txt +++ b/libfreerdp/gdi/CMakeLists.txt @@ -33,6 +33,7 @@ set(${MODULE_PREFIX}_SRCS graphics.c graphics.h gfx.c + video.c gdi.c gdi.h) diff --git a/libfreerdp/gdi/bitmap.c b/libfreerdp/gdi/bitmap.c index 49f8da6..0c87753 100644 --- a/libfreerdp/gdi/bitmap.c +++ b/libfreerdp/gdi/bitmap.c @@ -230,11 +230,11 @@ static UINT32 process_rop(UINT32 src, UINT32 dst, UINT32 pat, const char* rop, switch (op) { case '0': - stack[stackp++] = GetColor(format, 0, 0, 0, 0xFF); + stack[stackp++] = FreeRDPGetColor(format, 0, 0, 0, 0xFF); break; case '1': - stack[stackp++] = GetColor(format, 0xFF, 0xFF, 0xFF, 0xFF); + stack[stackp++] = FreeRDPGetColor(format, 0xFF, 0xFF, 0xFF, 0xFF); break; case 'D': @@ -303,7 +303,7 @@ static INLINE BOOL BitBlt_write(HGDI_DC hdcDest, HGDI_DC hdcSrc, UINT32 nXDest, } colorC = ReadColor(srcp, hdcSrc->format); - colorC = ConvertColor(colorC, hdcSrc->format, hdcDest->format, palette); + colorC = FreeRDPConvertColor(colorC, hdcSrc->format, hdcDest->format, palette); } if (usePat) diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 39fe62c..1bbac20 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -32,6 +32,7 @@ #include <freerdp/log.h> #include <freerdp/freerdp.h> +#include <freerdp/gdi/gdi.h> #include <freerdp/gdi/dc.h> #include <freerdp/gdi/pen.h> #include <freerdp/gdi/shape.h> @@ -48,264 +49,270 @@ #define TAG FREERDP_TAG("gdi") /* Ternary Raster Operation Table */ -static const DWORD rop3_code_table[] = +typedef struct { - 0x00000042, /* 0 */ - 0x00010289, /* DPSoon */ - 0x00020C89, /* DPSona */ - 0x000300AA, /* PSon */ - 0x00040C88, /* SDPona */ - 0x000500A9, /* DPon */ - 0x00060865, /* PDSxnon */ - 0x000702C5, /* PDSaon */ - 0x00080F08, /* SDPnaa */ - 0x00090245, /* PDSxon */ - 0x000A0329, /* DPna */ - 0x000B0B2A, /* PSDnaon */ - 0x000C0324, /* SPna */ - 0x000D0B25, /* PDSnaon */ - 0x000E08A5, /* PDSonon */ - 0x000F0001, /* Pn */ - 0x00100C85, /* PDSona */ - 0x001100A6, /* DSon */ - 0x00120868, /* SDPxnon */ - 0x001302C8, /* SDPaon */ - 0x00140869, /* DPSxnon */ - 0x001502C9, /* DPSaon */ - 0x00165CCA, /* PSDPSanaxx */ - 0x00171D54, /* SSPxDSxaxn */ - 0x00180D59, /* SPxPDxa */ - 0x00191CC8, /* SDPSanaxn */ - 0x001A06C5, /* PDSPaox */ - 0x001B0768, /* SDPSxaxn */ - 0x001C06CA, /* PSDPaox */ - 0x001D0766, /* DSPDxaxn */ - 0x001E01A5, /* PDSox */ - 0x001F0385, /* PDSoan */ - 0x00200F09, /* DPSnaa */ - 0x00210248, /* SDPxon */ - 0x00220326, /* DSna */ - 0x00230B24, /* SPDnaon */ - 0x00240D55, /* SPxDSxa */ - 0x00251CC5, /* PDSPanaxn */ - 0x002606C8, /* SDPSaox */ - 0x00271868, /* SDPSxnox */ - 0x00280369, /* DPSxa */ - 0x002916CA, /* PSDPSaoxxn */ - 0x002A0CC9, /* DPSana */ - 0x002B1D58, /* SSPxPDxaxn */ - 0x002C0784, /* SPDSoax */ - 0x002D060A, /* PSDnox */ - 0x002E064A, /* PSDPxox */ - 0x002F0E2A, /* PSDnoan */ - 0x0030032A, /* PSna */ - 0x00310B28, /* SDPnaon */ - 0x00320688, /* SDPSoox */ - 0x00330008, /* Sn */ - 0x003406C4, /* SPDSaox */ - 0x00351864, /* SPDSxnox */ - 0x003601A8, /* SDPox */ - 0x00370388, /* SDPoan */ - 0x0038078A, /* PSDPoax */ - 0x00390604, /* SPDnox */ - 0x003A0644, /* SPDSxox */ - 0x003B0E24, /* SPDnoan */ - 0x003C004A, /* PSx */ - 0x003D18A4, /* SPDSonox */ - 0x003E1B24, /* SPDSnaox */ - 0x003F00EA, /* PSan */ - 0x00400F0A, /* PSDnaa */ - 0x00410249, /* DPSxon */ - 0x00420D5D, /* SDxPDxa */ - 0x00431CC4, /* SPDSanaxn */ - 0x00440328, /* SDna */ - 0x00450B29, /* DPSnaon */ - 0x004606C6, /* DSPDaox */ - 0x0047076A, /* PSDPxaxn */ - 0x00480368, /* SDPxa */ - 0x004916C5, /* PDSPDaoxxn */ - 0x004A0789, /* DPSDoax */ - 0x004B0605, /* PDSnox */ - 0x004C0CC8, /* SDPana */ - 0x004D1954, /* SSPxDSxoxn */ - 0x004E0645, /* PDSPxox */ - 0x004F0E25, /* PDSnoan */ - 0x00500325, /* PDna */ - 0x00510B26, /* DSPnaon */ - 0x005206C9, /* DPSDaox */ - 0x00530764, /* SPDSxaxn */ - 0x005408A9, /* DPSonon */ - 0x00550009, /* Dn */ - 0x005601A9, /* DPSox */ - 0x00570389, /* DPSoan */ - 0x00580785, /* PDSPoax */ - 0x00590609, /* DPSnox */ - 0x005A0049, /* DPx */ - 0x005B18A9, /* DPSDonox */ - 0x005C0649, /* DPSDxox */ - 0x005D0E29, /* DPSnoan */ - 0x005E1B29, /* DPSDnaox */ - 0x005F00E9, /* DPan */ - 0x00600365, /* PDSxa */ - 0x006116C6, /* DSPDSaoxxn */ - 0x00620786, /* DSPDoax */ - 0x00630608, /* SDPnox */ - 0x00640788, /* SDPSoax */ - 0x00650606, /* DSPnox */ - 0x00660046, /* DSx */ - 0x006718A8, /* SDPSonox */ - 0x006858A6, /* DSPDSonoxxn */ - 0x00690145, /* PDSxxn */ - 0x006A01E9, /* DPSax */ - 0x006B178A, /* PSDPSoaxxn */ - 0x006C01E8, /* SDPax */ - 0x006D1785, /* PDSPDoaxxn */ - 0x006E1E28, /* SDPSnoax */ - 0x006F0C65, /* PDSxnan */ - 0x00700CC5, /* PDSana */ - 0x00711D5C, /* SSDxPDxaxn */ - 0x00720648, /* SDPSxox */ - 0x00730E28, /* SDPnoan */ - 0x00740646, /* DSPDxox */ - 0x00750E26, /* DSPnoan */ - 0x00761B28, /* SDPSnaox */ - 0x007700E6, /* DSan */ - 0x007801E5, /* PDSax */ - 0x00791786, /* DSPDSoaxxn */ - 0x007A1E29, /* DPSDnoax */ - 0x007B0C68, /* SDPxnan */ - 0x007C1E24, /* SPDSnoax */ - 0x007D0C69, /* DPSxnan */ - 0x007E0955, /* SPxDSxo */ - 0x007F03C9, /* DPSaan */ - 0x008003E9, /* DPSaa */ - 0x00810975, /* SPxDSxon */ - 0x00820C49, /* DPSxna */ - 0x00831E04, /* SPDSnoaxn */ - 0x00840C48, /* SDPxna */ - 0x00851E05, /* PDSPnoaxn */ - 0x008617A6, /* DSPDSoaxx */ - 0x008701C5, /* PDSaxn */ - 0x008800C6, /* DSa */ - 0x00891B08, /* SDPSnaoxn */ - 0x008A0E06, /* DSPnoa */ - 0x008B0666, /* DSPDxoxn */ - 0x008C0E08, /* SDPnoa */ - 0x008D0668, /* SDPSxoxn */ - 0x008E1D7C, /* SSDxPDxax */ - 0x008F0CE5, /* PDSanan */ - 0x00900C45, /* PDSxna */ - 0x00911E08, /* SDPSnoaxn */ - 0x009217A9, /* DPSDPoaxx */ - 0x009301C4, /* SPDaxn */ - 0x009417AA, /* PSDPSoaxx */ - 0x009501C9, /* DPSaxn */ - 0x00960169, /* DPSxx */ - 0x0097588A, /* PSDPSonoxx */ - 0x00981888, /* SDPSonoxn */ - 0x00990066, /* DSxn */ - 0x009A0709, /* DPSnax */ - 0x009B07A8, /* SDPSoaxn */ - 0x009C0704, /* SPDnax */ - 0x009D07A6, /* DSPDoaxn */ - 0x009E16E6, /* DSPDSaoxx */ - 0x009F0345, /* PDSxan */ - 0x00A000C9, /* DPa */ - 0x00A11B05, /* PDSPnaoxn */ - 0x00A20E09, /* DPSnoa */ - 0x00A30669, /* DPSDxoxn */ - 0x00A41885, /* PDSPonoxn */ - 0x00A50065, /* PDxn */ - 0x00A60706, /* DSPnax */ - 0x00A707A5, /* PDSPoaxn */ - 0x00A803A9, /* DPSoa */ - 0x00A90189, /* DPSoxn */ - 0x00AA0029, /* D */ - 0x00AB0889, /* DPSono */ - 0x00AC0744, /* SPDSxax */ - 0x00AD06E9, /* DPSDaoxn */ - 0x00AE0B06, /* DSPnao */ - 0x00AF0229, /* DPno */ - 0x00B00E05, /* PDSnoa */ - 0x00B10665, /* PDSPxoxn */ - 0x00B21974, /* SSPxDSxox */ - 0x00B30CE8, /* SDPanan */ - 0x00B4070A, /* PSDnax */ - 0x00B507A9, /* DPSDoaxn */ - 0x00B616E9, /* DPSDPaoxx */ - 0x00B70348, /* SDPxan */ - 0x00B8074A, /* PSDPxax */ - 0x00B906E6, /* DSPDaoxn */ - 0x00BA0B09, /* DPSnao */ - 0x00BB0226, /* DSno */ - 0x00BC1CE4, /* SPDSanax */ - 0x00BD0D7D, /* SDxPDxan */ - 0x00BE0269, /* DPSxo */ - 0x00BF08C9, /* DPSano */ - 0x00C000CA, /* PSa */ - 0x00C11B04, /* SPDSnaoxn */ - 0x00C21884, /* SPDSonoxn */ - 0x00C3006A, /* PSxn */ - 0x00C40E04, /* SPDnoa */ - 0x00C50664, /* SPDSxoxn */ - 0x00C60708, /* SDPnax */ - 0x00C707AA, /* PSDPoaxn */ - 0x00C803A8, /* SDPoa */ - 0x00C90184, /* SPDoxn */ - 0x00CA0749, /* DPSDxax */ - 0x00CB06E4, /* SPDSaoxn */ - 0x00CC0020, /* S */ - 0x00CD0888, /* SDPono */ - 0x00CE0B08, /* SDPnao */ - 0x00CF0224, /* SPno */ - 0x00D00E0A, /* PSDnoa */ - 0x00D1066A, /* PSDPxoxn */ - 0x00D20705, /* PDSnax */ - 0x00D307A4, /* SPDSoaxn */ - 0x00D41D78, /* SSPxPDxax */ - 0x00D50CE9, /* DPSanan */ - 0x00D616EA, /* PSDPSaoxx */ - 0x00D70349, /* DPSxan */ - 0x00D80745, /* PDSPxax */ - 0x00D906E8, /* SDPSaoxn */ - 0x00DA1CE9, /* DPSDanax */ - 0x00DB0D75, /* SPxDSxan */ - 0x00DC0B04, /* SPDnao */ - 0x00DD0228, /* SDno */ - 0x00DE0268, /* SDPxo */ - 0x00DF08C8, /* SDPano */ - 0x00E003A5, /* PDSoa */ - 0x00E10185, /* PDSoxn */ - 0x00E20746, /* DSPDxax */ - 0x00E306EA, /* PSDPaoxn */ - 0x00E40748, /* SDPSxax */ - 0x00E506E5, /* PDSPaoxn */ - 0x00E61CE8, /* SDPSanax */ - 0x00E70D79, /* SPxPDxan */ - 0x00E81D74, /* SSPxDSxax */ - 0x00E95CE6, /* DSPDSanaxxn */ - 0x00EA02E9, /* DPSao */ - 0x00EB0849, /* DPSxno */ - 0x00EC02E8, /* SDPao */ - 0x00ED0848, /* SDPxno */ - 0x00EE0086, /* DSo */ - 0x00EF0A08, /* SDPnoo */ - 0x00F00021, /* P */ - 0x00F10885, /* PDSono */ - 0x00F20B05, /* PDSnao */ - 0x00F3022A, /* PSno */ - 0x00F40B0A, /* PSDnao */ - 0x00F50225, /* PDno */ - 0x00F60265, /* PDSxo */ - 0x00F708C5, /* PDSano */ - 0x00F802E5, /* PDSao */ - 0x00F90845, /* PDSxno */ - 0x00FA0089, /* DPo */ - 0x00FB0A09, /* DPSnoo */ - 0x00FC008A, /* PSo */ - 0x00FD0A0A, /* PSDnoo */ - 0x00FE02A9, /* DPSoo */ - 0x00FF0062 /* 1 */ + DWORD code; + const char* name; +} rop_table_entry; + +static const rop_table_entry rop3_code_table[] = +{ + { GDI_BLACKNESS, "0" }, + { GDI_DPSoon, "DPSoon" }, + { GDI_DPSona, "DPSona" }, + { GDI_PSon, "PSon" }, + { GDI_SDPona, "SDPona" }, + { GDI_DPon, "DPon" }, + { GDI_PDSxnon, "PDSxnon" }, + { GDI_PDSaon, "PDSaon" }, + { GDI_SDPnaa, "SDPnaa" }, + { GDI_PDSxon, "PDSxon" }, + { GDI_DPna, "DPna" }, + { GDI_PSDnaon, "PSDnaon" }, + { GDI_SPna, "SPna" }, + { GDI_PDSnaon, "PDSnaon" }, + { GDI_PDSonon, "PDSonon" }, + { GDI_Pn , "Pn" }, + { GDI_PDSona, "PDSona" }, + { GDI_NOTSRCERASE, "DSon" }, + { GDI_SDPxnon, "SDPxnon" }, + { GDI_SDPaon, "SDPaon" }, + { GDI_DPSxnon, "DPSxnon" }, + { GDI_DPSaon, "DPSaon" }, + { GDI_PSDPSanaxx, "PSDPSanaxx" }, + { GDI_SSPxDSxaxn, "SSPxDSxaxn" }, + { GDI_SPxPDxa, "SPxPDxa" }, + { GDI_SDPSanaxn, "SDPSanaxn" }, + { GDI_PDSPaox, "PDSPaox" }, + { GDI_SDPSxaxn, "SDPSxaxn" }, + { GDI_PSDPaox, "PSDPaox" }, + { GDI_DSPDxaxn, "DSPDxaxn" }, + { GDI_PDSox, "PDSox" }, + { GDI_PDSoan, "PDSoan" }, + { GDI_DPSnaa, "DPSnaa" }, + { GDI_SDPxon, "SDPxon" }, + { GDI_DSna, "DSna" }, + { GDI_SPDnaon, "SPDnaon" }, + { GDI_SPxDSxa, "SPxDSxa" }, + { GDI_PDSPanaxn, "PDSPanaxn" }, + { GDI_SDPSaox, "SDPSaox" }, + { GDI_SDPSxnox, "SDPSxnox" }, + { GDI_DPSxa, "DPSxa" }, + { GDI_PSDPSaoxxn, "PSDPSaoxxn" }, + { GDI_DPSana, "DPSana" }, + { GDI_SSPxPDxaxn, "SSPxPDxaxn" }, + { GDI_SPDSoax, "SPDSoax" }, + { GDI_PSDnox, "PSDnox" }, + { GDI_PSDPxox, "PSDPxox" }, + { GDI_PSDnoan, "PSDnoan" }, + { GDI_PSna, "PSna" }, + { GDI_SDPnaon, "SDPnaon" }, + { GDI_SDPSoox, "SDPSoox" }, + { GDI_NOTSRCCOPY, "Sn" }, + { GDI_SPDSaox, "SPDSaox" }, + { GDI_SPDSxnox, "SPDSxnox" }, + { GDI_SDPox, "SDPox" }, + { GDI_SDPoan, "SDPoan" }, + { GDI_PSDPoax, "PSDPoax" }, + { GDI_SPDnox, "SPDnox" }, + { GDI_SPDSxox, "SPDSxox" }, + { GDI_SPDnoan, "SPDnoan" }, + { GDI_PSx , "PSx" }, + { GDI_SPDSonox, "SPDSonox" }, + { GDI_SPDSnaox, "SPDSnaox" }, + { GDI_PSan, "PSan" }, + { GDI_PSDnaa, "PSDnaa" }, + { GDI_DPSxon, "DPSxon" }, + { GDI_SDxPDxa, "SDxPDxa" }, + { GDI_SPDSanaxn, "SPDSanaxn" }, + { GDI_SRCERASE, "SDna" }, + { GDI_DPSnaon, "DPSnaon" }, + { GDI_DSPDaox, "DSPDaox" }, + { GDI_PSDPxaxn, "PSDPxaxn" }, + { GDI_SDPxa, "SDPxa" }, + { GDI_PDSPDaoxxn, "PDSPDaoxxn" }, + { GDI_DPSDoax, "DPSDoax" }, + { GDI_PDSnox, "PDSnox" }, + { GDI_SDPana, "SDPana" }, + { GDI_SSPxDSxoxn, "SSPxDSxoxn" }, + { GDI_PDSPxox, "PDSPxox" }, + { GDI_PDSnoan, "PDSnoan" }, + { GDI_PDna, "PDna" }, + { GDI_DSPnaon, "DSPnaon" }, + { GDI_DPSDaox, "DPSDaox" }, + { GDI_SPDSxaxn, "SPDSxaxn" }, + { GDI_DPSonon, "DPSonon" }, + { GDI_DSTINVERT, "Dn" }, + { GDI_DPSox, "DPSox" }, + { GDI_DPSoan, "DPSoan" }, + { GDI_PDSPoax, "PDSPoax" }, + { GDI_DPSnox, "DPSnox" }, + { GDI_PATINVERT, "DPx" }, + { GDI_DPSDonox, "DPSDonox" }, + { GDI_DPSDxox, "DPSDxox" }, + { GDI_DPSnoan, "DPSnoan" }, + { GDI_DPSDnaox, "DPSDnaox" }, + { GDI_DPan, "DPan" }, + { GDI_PDSxa, "PDSxa" }, + { GDI_DSPDSaoxxn, "DSPDSaoxxn" }, + { GDI_DSPDoax, "DSPDoax" }, + { GDI_SDPnox, "SDPnox" }, + { GDI_SDPSoax, "SDPSoax" }, + { GDI_DSPnox, "DSPnox" }, + { GDI_SRCINVERT, "DSx" }, + { GDI_SDPSonox, "SDPSonox" }, + { GDI_DSPDSonoxxn, "DSPDSonoxxn" }, + { GDI_PDSxxn, "PDSxxn" }, + { GDI_DPSax, "DPSax" }, + { GDI_PSDPSoaxxn, "PSDPSoaxxn" }, + { GDI_SDPax, "SDPax" }, + { GDI_PDSPDoaxxn, "PDSPDoaxxn" }, + { GDI_SDPSnoax, "SDPSnoax" }, + { GDI_PDSxnan, "PDSxnan" }, + { GDI_PDSana, "PDSana" }, + { GDI_SSDxPDxaxn, "SSDxPDxaxn" }, + { GDI_SDPSxox, "SDPSxox" }, + { GDI_SDPnoan, "SDPnoan" }, + { GDI_DSPDxox, "DSPDxox" }, + { GDI_DSPnoan, "DSPnoan" }, + { GDI_SDPSnaox, "SDPSnaox" }, + { GDI_DSan, "DSan" }, + { GDI_PDSax, "PDSax" }, + { GDI_DSPDSoaxxn, "DSPDSoaxxn" }, + { GDI_DPSDnoax, "DPSDnoax" }, + { GDI_SDPxnan, "SDPxnan" }, + { GDI_SPDSnoax, "SPDSnoax" }, + { GDI_DPSxnan, "DPSxnan" }, + { GDI_SPxDSxo, "SPxDSxo" }, + { GDI_DPSaan, "DPSaan" }, + { GDI_DPSaa, "DPSaa" }, + { GDI_SPxDSxon, "SPxDSxon" }, + { GDI_DPSxna, "DPSxna" }, + { GDI_SPDSnoaxn, "SPDSnoaxn" }, + { GDI_SDPxna, "SDPxna" }, + { GDI_PDSPnoaxn, "PDSPnoaxn" }, + { GDI_DSPDSoaxx, "DSPDSoaxx" }, + { GDI_PDSaxn, "PDSaxn" }, + { GDI_SRCAND, "DSa" }, + { GDI_SDPSnaoxn, "SDPSnaoxn" }, + { GDI_DSPnoa, "DSPnoa" }, + { GDI_DSPDxoxn, "DSPDxoxn" }, + { GDI_SDPnoa, "SDPnoa" }, + { GDI_SDPSxoxn, "SDPSxoxn" }, + { GDI_SSDxPDxax, "SSDxPDxax" }, + { GDI_PDSanan, "PDSanan" }, + { GDI_PDSxna, "PDSxna" }, + { GDI_SDPSnoaxn, "SDPSnoaxn" }, + { GDI_DPSDPoaxx, "DPSDPoaxx" }, + { GDI_SPDaxn, "SPDaxn" }, + { GDI_PSDPSoaxx, "PSDPSoaxx" }, + { GDI_DPSaxn, "DPSaxn" }, + { GDI_DPSxx, "DPSxx" }, + { GDI_PSDPSonoxx, "PSDPSonoxx" }, + { GDI_SDPSonoxn, "SDPSonoxn" }, + { GDI_DSxn, "DSxn" }, + { GDI_DPSnax, "DPSnax" }, + { GDI_SDPSoaxn, "SDPSoaxn" }, + { GDI_SPDnax, "SPDnax" }, + { GDI_DSPDoaxn, "DSPDoaxn" }, + { GDI_DSPDSaoxx, "DSPDSaoxx" }, + { GDI_PDSxan, "PDSxan" }, + { GDI_DPa , "DPa" }, + { GDI_PDSPnaoxn, "PDSPnaoxn" }, + { GDI_DPSnoa, "DPSnoa" }, + { GDI_DPSDxoxn, "DPSDxoxn" }, + { GDI_PDSPonoxn, "PDSPonoxn" }, + { GDI_PDxn, "PDxn" }, + { GDI_DSPnax, "DSPnax" }, + { GDI_PDSPoaxn, "PDSPoaxn" }, + { GDI_DPSoa, "DPSoa" }, + { GDI_DPSoxn, "DPSoxn" }, + { GDI_DSTCOPY, "D" }, + { GDI_DPSono, "DPSono" }, + { GDI_SPDSxax, "SPDSxax" }, + { GDI_DPSDaoxn, "DPSDaoxn" }, + { GDI_DSPnao, "DSPnao" }, + { GDI_DPno, "DPno" }, + { GDI_PDSnoa, "PDSnoa" }, + { GDI_PDSPxoxn, "PDSPxoxn" }, + { GDI_SSPxDSxox, "SSPxDSxox" }, + { GDI_SDPanan, "SDPanan" }, + { GDI_PSDnax, "PSDnax" }, + { GDI_DPSDoaxn, "DPSDoaxn" }, + { GDI_DPSDPaoxx, "DPSDPaoxx" }, + { GDI_SDPxan, "SDPxan" }, + { GDI_PSDPxax, "PSDPxax" }, + { GDI_DSPDaoxn, "DSPDaoxn" }, + { GDI_DPSnao, "DPSnao" }, + { GDI_MERGEPAINT, "DSno" }, + { GDI_SPDSanax, "SPDSanax" }, + { GDI_SDxPDxan, "SDxPDxan" }, + { GDI_DPSxo, "DPSxo" }, + { GDI_DPSano, "DPSano" }, + { GDI_MERGECOPY, "PSa" }, + { GDI_SPDSnaoxn, "SPDSnaoxn" }, + { GDI_SPDSonoxn, "SPDSonoxn" }, + { GDI_PSxn, "PSxn" }, + { GDI_SPDnoa, "SPDnoa" }, + { GDI_SPDSxoxn, "SPDSxoxn" }, + { GDI_SDPnax, "SDPnax" }, + { GDI_PSDPoaxn, "PSDPoaxn" }, + { GDI_SDPoa, "SDPoa" }, + { GDI_SPDoxn, "SPDoxn" }, + { GDI_DPSDxax, "DPSDxax" }, + { GDI_SPDSaoxn, "SPDSaoxn" }, + { GDI_SRCCOPY, "S" }, + { GDI_SDPono, "SDPono" }, + { GDI_SDPnao, "SDPnao" }, + { GDI_SPno, "SPno" }, + { GDI_PSDnoa, "PSDnoa" }, + { GDI_PSDPxoxn, "PSDPxoxn" }, + { GDI_PDSnax, "PDSnax" }, + { GDI_SPDSoaxn, "SPDSoaxn" }, + { GDI_SSPxPDxax, "SSPxPDxax" }, + { GDI_DPSanan, "DPSanan" }, + { GDI_PSDPSaoxx, "PSDPSaoxx" }, + { GDI_DPSxan, "DPSxan" }, + { GDI_PDSPxax, "PDSPxax" }, + { GDI_SDPSaoxn, "SDPSaoxn" }, + { GDI_DPSDanax, "DPSDanax" }, + { GDI_SPxDSxan, "SPxDSxan" }, + { GDI_SPDnao, "SPDnao" }, + { GDI_SDno, "SDno" }, + { GDI_SDPxo, "SDPxo" }, + { GDI_SDPano, "SDPano" }, + { GDI_PDSoa, "PDSoa" }, + { GDI_PDSoxn, "PDSoxn" }, + { GDI_DSPDxax, "DSPDxax" }, + { GDI_PSDPaoxn, "PSDPaoxn" }, + { GDI_SDPSxax, "SDPSxax" }, + { GDI_PDSPaoxn, "PDSPaoxn" }, + { GDI_SDPSanax, "SDPSanax" }, + { GDI_SPxPDxan, "SPxPDxan" }, + { GDI_SSPxDSxax, "SSPxDSxax" }, + { GDI_DSPDSanaxxn, "DSPDSanaxxn" }, + { GDI_DPSao, "DPSao" }, + { GDI_DPSxno, "DPSxno" }, + { GDI_SDPao, "SDPao" }, + { GDI_SDPxno, "SDPxno" }, + { GDI_SRCPAINT, "DSo" }, + { GDI_SDPnoo, "SDPnoo" }, + { GDI_PATCOPY, "P" }, + { GDI_PDSono, "PDSono" }, + { GDI_PDSnao, "PDSnao" }, + { GDI_PSno, "PSno" }, + { GDI_PSDnao, "PSDnao" }, + { GDI_PDno, "PDno" }, + { GDI_PDSxo, "PDSxo" }, + { GDI_PDSano, "PDSano" }, + { GDI_PDSao, "PDSao" }, + { GDI_PDSxno, "PDSxno" }, + { GDI_DPo , "DPo" }, + { GDI_PATPAINT, "DPSnoo" }, + { GDI_PSo , "PSo" }, + { GDI_PSDnoo, "PSDnoo" }, + { GDI_DPSoo, "DPSoo" }, + { GDI_WHITENESS, "1" } }; /* Hatch Patterns as monochrome data */ @@ -356,14 +363,33 @@ INLINE BOOL gdi_decode_color(rdpGdi* gdi, const UINT32 srcColor, if (format) *format = gdi->dstFormat; - *color = ConvertColor(srcColor, SrcFormat, gdi->dstFormat, &gdi->palette); + *color = FreeRDPConvertColor(srcColor, SrcFormat, gdi->dstFormat, &gdi->palette); return TRUE; } /* GDI Helper Functions */ -INLINE DWORD gdi_rop3_code(BYTE code) +DWORD gdi_rop3_code(BYTE code) { - return rop3_code_table[code]; + return rop3_code_table[code].code; +} + +const char* gdi_rop3_code_string(BYTE code) +{ + return rop3_code_table[code].name; +} + +const char* gdi_rop3_string(DWORD rop) +{ + const size_t count = sizeof(rop3_code_table) / sizeof(rop3_code_table[0]); + size_t x; + + for (x = 0; x < count; x++) + { + if (rop3_code_table[x].code == rop) + return rop3_code_table[x].name; + } + + return "UNKNOWN"; } UINT32 gdi_get_pixel_format(UINT32 bitsPerPixel) @@ -509,7 +535,7 @@ static BOOL gdi_palette_update(rdpContext* context, { const PALETTE_ENTRY* pe = &(palette->entries[index]); gdi->palette.palette[index] = - GetColor(gdi->dstFormat, pe->red, pe->green, pe->blue, 0xFF); + FreeRDPGetColor(gdi->dstFormat, pe->red, pe->green, pe->blue, 0xFF); } return TRUE; @@ -603,7 +629,12 @@ static BOOL gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) if (brush->bpp > 1) { - brushFormat = gdi_get_pixel_format(brush->bpp); + UINT32 bpp = brush->bpp; + + if ((bpp == 16) && (context->settings->ColorDepth == 15)) + bpp = 15; + + brushFormat = gdi_get_pixel_format(bpp); if (!freerdp_image_copy(data, gdi->drawing->hdc->format, 0, 0, 0, 8, 8, brush->data, brushFormat, 0, 0, 0, @@ -848,7 +879,12 @@ static BOOL gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) if (brush->bpp > 1) { - brushFormat = gdi_get_pixel_format(brush->bpp); + UINT32 bpp = brush->bpp; + + if ((bpp == 16) && (context->settings->ColorDepth == 15)) + bpp = 15; + + brushFormat = gdi_get_pixel_format(bpp); if (!freerdp_image_copy(data, gdi->drawing->hdc->format, 0, 0, 0, 8, 8, brush->data, brushFormat, @@ -986,22 +1022,20 @@ static BOOL gdi_surface_bits(rdpContext* context, gdi = context->gdi; WLog_Print(gdi->log, WLOG_DEBUG, "destLeft %"PRIu32" destTop %"PRIu32" destRight %"PRIu32" destBottom %"PRIu32" " - "bpp %"PRIu32" codecID %"PRIu32" width %"PRIu32" height %"PRIu32" length %"PRIu32"", + "bpp %"PRIu8" flags %"PRIx8" codecID %"PRIu16" width %"PRIu16" height %"PRIu16" length %"PRIu32"", cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom, - cmd->bpp, cmd->codecID, cmd->width, cmd->height, cmd->bitmapDataLength); - + cmd->bmp.bpp, cmd->bmp.flags, cmd->bmp.codecID, cmd->bmp.width, cmd->bmp.height, cmd->bmp.bitmapDataLength); region16_init(®ion); cmdRect.left = cmd->destLeft; cmdRect.top = cmd->destTop; - cmdRect.right = cmdRect.left + cmd->width; - cmdRect.bottom = cmdRect.top + cmd->height; + cmdRect.right = cmdRect.left + cmd->bmp.width; + cmdRect.bottom = cmdRect.top + cmd->bmp.height; - - switch (cmd->codecID) + switch (cmd->bmp.codecID) { case RDP_CODEC_ID_REMOTEFX: - if (!rfx_process_message(context->codecs->rfx, cmd->bitmapData, - cmd->bitmapDataLength, + if (!rfx_process_message(context->codecs->rfx, cmd->bmp.bitmapData, + cmd->bmp.bitmapDataLength, cmd->destLeft, cmd->destTop, gdi->primary_buffer, gdi->dstFormat, gdi->stride, gdi->height, ®ion)) @@ -1009,39 +1043,42 @@ static BOOL gdi_surface_bits(rdpContext* context, WLog_ERR(TAG, "Failed to process RemoteFX message"); goto out; } + break; case RDP_CODEC_ID_NSCODEC: format = gdi->dstFormat; - if (!nsc_process_message(context->codecs->nsc, cmd->bpp, cmd->width, - cmd->height, cmd->bitmapData, - cmd->bitmapDataLength, gdi->primary_buffer, + if (!nsc_process_message(context->codecs->nsc, cmd->bmp.bpp, cmd->bmp.width, + cmd->bmp.height, cmd->bmp.bitmapData, + cmd->bmp.bitmapDataLength, gdi->primary_buffer, format, gdi->stride, cmd->destLeft, cmd->destTop, - cmd->width, cmd->height, FREERDP_FLIP_VERTICAL)) + cmd->bmp.width, cmd->bmp.height, FREERDP_FLIP_VERTICAL)) { WLog_ERR(TAG, "Failed to process NSCodec message"); goto out; } + region16_union_rect(®ion, ®ion, &cmdRect); break; case RDP_CODEC_ID_NONE: - format = gdi_get_pixel_format(cmd->bpp); + format = gdi_get_pixel_format(cmd->bmp.bpp); if (!freerdp_image_copy(gdi->primary_buffer, gdi->dstFormat, gdi->stride, - cmd->destLeft, cmd->destTop, cmd->width, cmd->height, - cmd->bitmapData, format, 0, 0, 0, + cmd->destLeft, cmd->destTop, cmd->bmp.width, cmd->bmp.height, + cmd->bmp.bitmapData, format, 0, 0, 0, &gdi->palette, FREERDP_FLIP_VERTICAL)) { WLog_ERR(TAG, "Failed to process nocodec message"); goto out; } + region16_union_rect(®ion, ®ion, &cmdRect); break; default: - WLog_ERR(TAG, "Unsupported codecID %"PRIu32"", cmd->codecID); + WLog_ERR(TAG, "Unsupported codecID %"PRIu32"", cmd->bmp.codecID); break; } @@ -1138,11 +1175,10 @@ static BOOL gdi_init_primary(rdpGdi* gdi, UINT32 stride, UINT32 format, buffer, pfree); } - gdi->stride = gdi->primary->bitmap->scanline; - if (!gdi->primary->bitmap) goto fail_bitmap; + gdi->stride = gdi->primary->bitmap->scanline; gdi_SelectObject(gdi->primary->hdc, (HGDIOBJECT) gdi->primary->bitmap); gdi->primary->org_bitmap = NULL; gdi->primary_buffer = gdi->primary->bitmap->data; @@ -1236,9 +1272,9 @@ BOOL gdi_init_ex(freerdp* instance, UINT32 format, UINT32 stride, BYTE* buffer, gdi->dstFormat = format; /* default internal buffer format */ WLog_Print(gdi->log, WLOG_INFO, "Local framebuffer format %s", - GetColorFormatName(gdi->dstFormat)); + FreeRDPGetColorFormatName(gdi->dstFormat)); WLog_Print(gdi->log, WLOG_INFO, "Remote framebuffer format %s", - GetColorFormatName(SrcFormat)); + FreeRDPGetColorFormatName(SrcFormat)); if (!(gdi->hdc = gdi_GetDC())) goto fail; @@ -1295,3 +1331,25 @@ void gdi_free(freerdp* instance) instance->context->gdi = (rdpGdi*) NULL; } +BOOL gdi_send_suppress_output(rdpGdi* gdi, BOOL suppress) +{ + RECTANGLE_16 rect; + rdpSettings* settings; + rdpUpdate* update; + + if (!gdi || !gdi->context->settings || !gdi->context->update) + return FALSE; + + if (gdi->suppressOutput == suppress) + return TRUE; + + gdi->suppressOutput = suppress; + settings = gdi->context->settings; + update = gdi->context->update; + rect.left = 0; + rect.top = 0; + rect.right = settings->DesktopWidth; + rect.bottom = settings->DesktopHeight; + return update->SuppressOutput(gdi->context, !suppress, &rect); +} + diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index d6d0030..a5e427f 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -61,8 +61,7 @@ static UINT gdi_ResetGraphics(RdpgfxClientContext* context, DesktopWidth = resetGraphics->width; DesktopHeight = resetGraphics->height; - if ((DesktopWidth != settings->DesktopWidth) - || (DesktopHeight != settings->DesktopHeight)) + if ((DesktopWidth != settings->DesktopWidth) || (DesktopHeight != settings->DesktopHeight)) { settings->DesktopWidth = DesktopWidth; settings->DesktopHeight = DesktopHeight; @@ -103,6 +102,10 @@ static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) const RECTANGLE_16* rects; UINT32 i, nbRects; rdpUpdate* update = gdi->context->update; + + if (gdi->suppressOutput) + return CHANNEL_RC_OK; + surfaceX = surface->outputOriginX; surfaceY = surface->outputOriginY; surfaceRect.left = 0; @@ -113,7 +116,7 @@ static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) &(surface->invalidRegion), &surfaceRect); if (!(rects = region16_rects(&surface->invalidRegion, &nbRects)) || !nbRects) - return CHANNEL_RC_OK; + return CHANNEL_RC_OK; update->BeginPaint(gdi->context); @@ -137,7 +140,6 @@ static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) } update->EndPaint(gdi->context); - region16_clear(&(surface->invalidRegion)); return CHANNEL_RC_OK; } @@ -213,11 +215,12 @@ static UINT gdi_SurfaceCommand_Uncompressed(rdpGdi* gdi, UINT status = CHANNEL_RC_OK; gdiGfxSurface* surface; RECTANGLE_16 invalidRect; - surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + if (!surface) { - WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId); + WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, + cmd->surfaceId); return ERROR_NOT_FOUND; } @@ -232,7 +235,6 @@ static UINT gdi_SurfaceCommand_Uncompressed(rdpGdi* gdi, invalidRect.bottom = cmd->bottom; region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); - IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect); if (!gdi->inGfxFrame) @@ -258,17 +260,18 @@ static UINT gdi_SurfaceCommand_RemoteFX(rdpGdi* gdi, REGION16 invalidRegion; const RECTANGLE_16* rects; UINT32 nrRects, x; - surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + if (!surface) { - WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId); + WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, + cmd->surfaceId); return ERROR_NOT_FOUND; } rfx_context_set_pixel_format(surface->codecs->rfx, cmd->format); - region16_init(&invalidRegion); + if (!rfx_process_message(surface->codecs->rfx, cmd->data, cmd->length, cmd->left, cmd->top, surface->data, surface->format, surface->scanline, @@ -282,10 +285,11 @@ static UINT gdi_SurfaceCommand_RemoteFX(rdpGdi* gdi, rects = region16_rects(&invalidRegion, &nrRects); IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, nrRects, rects); - for (x=0; x<nrRects; x++) + for (x = 0; x < nrRects; x++) region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &rects[x]); region16_uninit(&invalidRegion); + if (!gdi->inGfxFrame) { status = CHANNEL_RC_NOT_INITIALIZED; @@ -308,11 +312,12 @@ static UINT gdi_SurfaceCommand_ClearCodec(rdpGdi* gdi, UINT status = CHANNEL_RC_OK; gdiGfxSurface* surface; RECTANGLE_16 invalidRect; - surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + if (!surface) { - WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId); + WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, + cmd->surfaceId); return ERROR_NOT_FOUND; } @@ -334,7 +339,6 @@ static UINT gdi_SurfaceCommand_ClearCodec(rdpGdi* gdi, invalidRect.bottom = cmd->bottom; region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); - IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect); if (!gdi->inGfxFrame) @@ -358,11 +362,12 @@ static UINT gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context, BYTE* DstData = NULL; gdiGfxSurface* surface; RECTANGLE_16 invalidRect; - surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + if (!surface) { - WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId); + WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, + cmd->surfaceId); return ERROR_NOT_FOUND; } @@ -381,7 +386,6 @@ static UINT gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context, invalidRect.bottom = cmd->bottom; region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); - IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect); if (!gdi->inGfxFrame) @@ -409,17 +413,19 @@ static UINT gdi_SurfaceCommand_AVC420(rdpGdi* gdi, gdiGfxSurface* surface; RDPGFX_H264_METABLOCK* meta; RDPGFX_AVC420_BITMAP_STREAM* bs; - surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + if (!surface) { - WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId); + WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, + cmd->surfaceId); return ERROR_NOT_FOUND; } if (!surface->h264) { surface->h264 = h264_context_new(FALSE); + if (!surface->h264) { WLog_ERR(TAG, "%s: unable to create h264 context", __FUNCTION__); @@ -431,6 +437,7 @@ static UINT gdi_SurfaceCommand_AVC420(rdpGdi* gdi, } bs = (RDPGFX_AVC420_BITMAP_STREAM*) cmd->extra; + if (!bs) return ERROR_INTERNAL_ERROR; @@ -451,6 +458,7 @@ static UINT gdi_SurfaceCommand_AVC420(rdpGdi* gdi, region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), (RECTANGLE_16*) & (meta->regionRects[i])); } + IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, meta->numRegionRects, meta->regionRects); @@ -485,17 +493,19 @@ static UINT gdi_SurfaceCommand_AVC444(rdpGdi* gdi, RdpgfxClientContext* context, RDPGFX_AVC420_BITMAP_STREAM* avc2; RDPGFX_H264_METABLOCK* meta2; RECTANGLE_16* regionRects = NULL; - surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + if (!surface) { - WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId); + WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, + cmd->surfaceId); return ERROR_NOT_FOUND; } if (!surface->h264) { surface->h264 = h264_context_new(FALSE); + if (!surface->h264) { WLog_ERR(TAG, "%s: unable to create h264 context", __FUNCTION__); @@ -534,6 +544,7 @@ static UINT gdi_SurfaceCommand_AVC444(rdpGdi* gdi, RdpgfxClientContext* context, { region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &(meta1->regionRects[i])); } + IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, meta1->numRegionRects, meta1->regionRects); @@ -541,6 +552,7 @@ static UINT gdi_SurfaceCommand_AVC444(rdpGdi* gdi, RdpgfxClientContext* context, { region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &(meta2->regionRects[i])); } + IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, meta2->numRegionRects, meta2->regionRects); @@ -569,17 +581,18 @@ static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context, UINT32 color; gdiGfxSurface* surface; RECTANGLE_16 invalidRect; - surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + if (!surface) { - WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId); + WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, + cmd->surfaceId); return ERROR_NOT_FOUND; } WLog_WARN(TAG, "TODO gdi_SurfaceCommand_Alpha: status: %"PRIu32"", status); /* fill with green for now to distinguish from the rest */ - color = GetColor(surface->format, 0x00, 0xFF, 0x00, 0xFF); + color = FreeRDPGetColor(surface->format, 0x00, 0xFF, 0x00, 0xFF); if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, color)) @@ -591,7 +604,6 @@ static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context, invalidRect.bottom = cmd->bottom; region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); - IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect); if (!gdi->inGfxFrame) @@ -618,17 +630,17 @@ static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi, REGION16 invalidRegion; const RECTANGLE_16* rects; UINT32 nrRects, x; - /** * Note: Since this comes via a Wire-To-Surface-2 PDU the * cmd's top/left/right/bottom/width/height members are always zero! * The update region is determined during decompression. */ - surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + if (!surface) { - WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId); + WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, + cmd->surfaceId); return ERROR_NOT_FOUND; } @@ -658,8 +670,9 @@ static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi, rects = region16_rects(&invalidRegion, &nrRects); IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, nrRects, rects); - for (x=0; x<nrRects; x++) + for (x = 0; x < nrRects; x++) region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &rects[x]); + region16_uninit(&invalidRegion); if (!gdi->inGfxFrame) @@ -690,7 +703,7 @@ static UINT gdi_SurfaceCommand(RdpgfxClientContext* context, "left=%"PRIu32", top=%"PRIu32", right=%"PRIu32", bottom=%"PRIu32", width=%"PRIu32", height=%"PRIu32" " "length=%"PRIu32", data=%p, extra=%p", cmd->surfaceId, cmd->codecId, cmd->contextId, - GetColorFormatName(cmd->format), cmd->left, cmd->top, cmd->right, + FreeRDPGetColorFormatName(cmd->format), cmd->left, cmd->top, cmd->right, cmd->bottom, cmd->width, cmd->height, cmd->length, (void*) cmd->data, (void*) cmd->extra); switch (cmd->codecId) @@ -760,7 +773,7 @@ static UINT gdi_CreateSurface(RdpgfxClientContext* context, const RDPGFX_CREATE_SURFACE_PDU* createSurface) { gdiGfxSurface* surface; - rdpGdi* gdi = (rdpGdi*) context->custom; + rdpGdi* gdi = (rdpGdi*) context->custom; surface = (gdiGfxSurface*) calloc(1, sizeof(gdiGfxSurface)); if (!surface) @@ -868,7 +881,7 @@ static UINT gdi_SolidFill(RdpgfxClientContext* context, /* a = solidFill->fillPixel.XA; * Ignore alpha channel, this is a solid fill. */ a = 0xFF; - color = GetColor(surface->format, r, g, b, a); + color = FreeRDPGetColor(surface->format, r, g, b, a); for (index = 0; index < solidFill->fillRectCount; index++) { @@ -887,6 +900,7 @@ static UINT gdi_SolidFill(RdpgfxClientContext* context, region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); } + IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, solidFill->fillRectCount, solidFill->fillRects); @@ -977,8 +991,7 @@ static UINT gdi_SurfaceToCache(RdpgfxClientContext* context, gdiGfxSurface* surface; gdiGfxCacheEntry* cacheEntry; rect = &(surfaceToCache->rectSrc); - surface = (gdiGfxSurface*) context->GetSurfaceData(context, - surfaceToCache->surfaceId); + surface = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; @@ -986,7 +999,7 @@ static UINT gdi_SurfaceToCache(RdpgfxClientContext* context, cacheEntry = (gdiGfxCacheEntry*) calloc(1, sizeof(gdiGfxCacheEntry)); if (!cacheEntry) - return ERROR_INTERNAL_ERROR; + return ERROR_NOT_ENOUGH_MEMORY; cacheEntry->width = (UINT32)(rect->right - rect->left); cacheEntry->height = (UINT32)(rect->bottom - rect->top); @@ -997,7 +1010,7 @@ static UINT gdi_SurfaceToCache(RdpgfxClientContext* context, if (!cacheEntry->data) { free(cacheEntry); - return ERROR_INTERNAL_ERROR; + return ERROR_NOT_ENOUGH_MEMORY; } if (!freerdp_image_copy(cacheEntry->data, cacheEntry->format, cacheEntry->scanline, @@ -1008,9 +1021,7 @@ static UINT gdi_SurfaceToCache(RdpgfxClientContext* context, return ERROR_INTERNAL_ERROR; } - context->SetCacheSlotData(context, surfaceToCache->cacheSlot, - (void*) cacheEntry); - return CHANNEL_RC_OK; + return context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry); } /** @@ -1028,10 +1039,8 @@ static UINT gdi_CacheToSurface(RdpgfxClientContext* context, gdiGfxCacheEntry* cacheEntry; RECTANGLE_16 invalidRect; rdpGdi* gdi = (rdpGdi*) context->custom; - surface = (gdiGfxSurface*) context->GetSurfaceData(context, - cacheToSurface->surfaceId); - cacheEntry = (gdiGfxCacheEntry*) context->GetCacheSlotData(context, - cacheToSurface->cacheSlot); + surface = (gdiGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId); + cacheEntry = (gdiGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot); if (!surface || !cacheEntry) return ERROR_INTERNAL_ERROR; @@ -1150,17 +1159,16 @@ void gdi_graphics_pipeline_init(rdpGdi* gdi, RdpgfxClientContext* gfx) gfx->MapSurfaceToOutput = gdi_MapSurfaceToOutput; gfx->MapSurfaceToWindow = gdi_MapSurfaceToWindow; gfx->UpdateSurfaces = gdi_UpdateSurfaces; - PROFILER_CREATE(gfx->SurfaceProfiler, "GFX-PROFILER"); + PROFILER_CREATE(gfx->SurfaceProfiler, "GFX-PROFILER") } void gdi_graphics_pipeline_uninit(rdpGdi* gdi, RdpgfxClientContext* gfx) { - region16_uninit(&(gdi->invalidRegion)); gdi->gfx = NULL; gfx->custom = NULL; - PROFILER_PRINT_HEADER; - PROFILER_PRINT(gfx->SurfaceProfiler); - PROFILER_PRINT_FOOTER; - PROFILER_FREE(gfx->SurfaceProfiler); + PROFILER_PRINT_HEADER + PROFILER_PRINT(gfx->SurfaceProfiler) + PROFILER_PRINT_FOOTER + PROFILER_FREE(gfx->SurfaceProfiler) } diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c index 0424a8a..fbb3f02 100644 --- a/libfreerdp/gdi/graphics.c +++ b/libfreerdp/gdi/graphics.c @@ -115,7 +115,11 @@ static void gdi_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap) gdi_SelectObject(gdi_bitmap->hdc, (HGDIOBJECT) gdi_bitmap->org_bitmap); gdi_DeleteObject((HGDIOBJECT) gdi_bitmap->bitmap); gdi_DeleteDC(gdi_bitmap->hdc); + + _aligned_free(bitmap->data); } + + free(bitmap); } static BOOL gdi_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap) diff --git a/libfreerdp/gdi/line.c b/libfreerdp/gdi/line.c index fdec8ab..8564dc4 100644 --- a/libfreerdp/gdi/line.c +++ b/libfreerdp/gdi/line.c @@ -53,7 +53,7 @@ static BOOL gdi_rop_color(UINT32 rop, BYTE* pixelPtr, UINT32 pen, UINT32 format) switch (rop) { case GDI_R2_BLACK: /* LineTo_BLACK */ - dstPixel = GetColor(format, 0, 0, 0, 0xFF); + dstPixel = FreeRDPGetColor(format, 0, 0, 0, 0xFF); break; case GDI_R2_NOTMERGEPEN: /* LineTo_NOTMERGEPEN */ @@ -113,7 +113,7 @@ static BOOL gdi_rop_color(UINT32 rop, BYTE* pixelPtr, UINT32 pen, UINT32 format) break; case GDI_R2_WHITE: /* LineTo_WHITE */ - dstPixel = GetColor(format, 0xFF, 0xFF, 0xFF, 0xFF); + dstPixel = FreeRDPGetColor(format, 0xFF, 0xFF, 0xFF, 0xFF); break; default: diff --git a/libfreerdp/gdi/pen.c b/libfreerdp/gdi/pen.c index 4d191d4..872127e 100644 --- a/libfreerdp/gdi/pen.c +++ b/libfreerdp/gdi/pen.c @@ -58,5 +58,5 @@ HGDI_PEN gdi_CreatePen(UINT32 fnPenStyle, UINT32 nWidth, UINT32 crColor, INLINE UINT32 gdi_GetPenColor(HGDI_PEN pen, UINT32 format) { - return ConvertColor(pen->color, pen->format, format, pen->palette); + return FreeRDPConvertColor(pen->color, pen->format, format, pen->palette); } diff --git a/libfreerdp/gdi/region.c b/libfreerdp/gdi/region.c index 4b9a757..24dc259 100644 --- a/libfreerdp/gdi/region.c +++ b/libfreerdp/gdi/region.c @@ -184,22 +184,32 @@ INLINE void gdi_RgnToRect(HGDI_RGN rgn, HGDI_RECT rect) * @param rect destination rectangle */ -INLINE void gdi_CRgnToRect(UINT32 x, UINT32 y, UINT32 w, UINT32 h, +INLINE void gdi_CRgnToRect(INT64 x, INT64 y, UINT32 w, UINT32 h, HGDI_RECT rect) { - memset(rect, 0, sizeof(GDI_RECT)); - rect->left = x; - rect->top = y; + BOOL invalid = FALSE; + const INT64 r = x + w - 1; + const INT64 b = y + h - 1; + rect->left = (x > 0) ? x : 0; + rect->top = (y > 0) ? y : 0; + rect->right = rect->left; + rect->bottom = rect->top; - if (w > 0) - rect->right = x + w - 1; + if (r > 0) + rect->right = r; else - WLog_ERR(TAG, "Invalid width"); + invalid = TRUE; - if (h > 0) - rect->bottom = y + h - 1; + if (b > 0) + rect->bottom = b; else - WLog_ERR(TAG, "Invalid height"); + invalid = TRUE; + + if (invalid) + { + WLog_DBG(TAG, "Invisible rectangle %"PRId64"x%"PRId64"-%"PRId64"x%"PRId64, + x, y, r, b); + } } /** diff --git a/libfreerdp/gdi/shape.c b/libfreerdp/gdi/shape.c index 14a5367..8f0ff8c 100644 --- a/libfreerdp/gdi/shape.c +++ b/libfreerdp/gdi/shape.c @@ -195,7 +195,7 @@ BOOL gdi_FillRect(HGDI_DC hdc, const HGDI_RECT rect, HGDI_BRUSH hbr) else { dstColor = ReadColor(patp, hbr->pattern->format); - dstColor = ConvertColor(dstColor, hbr->pattern->format, hdc->format, NULL); + dstColor = FreeRDPConvertColor(dstColor, hbr->pattern->format, hdc->format, NULL); } if (dstp) @@ -256,7 +256,6 @@ BOOL gdi_Rectangle(HGDI_DC hdc, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, return TRUE; color = hdc->textColor; - color = GetColor(hdc->format, 0, 0xFF, 0, 0xFF); for (y = 0; y < nHeight; y++) { diff --git a/libfreerdp/gdi/test/TestGdiBitBlt.c b/libfreerdp/gdi/test/TestGdiBitBlt.c index 64367e9..dc0530a 100644 --- a/libfreerdp/gdi/test/TestGdiBitBlt.c +++ b/libfreerdp/gdi/test/TestGdiBitBlt.c @@ -500,7 +500,7 @@ static BOOL test_gdi_BitBlt(UINT32 SrcFormat, UINT32 DstFormat) g.format = DstFormat; for (x = 0; x < 256; x++) - g.palette[x] = GetColor(DstFormat, x, x, x, 0xFF); + g.palette[x] = FreeRDPGetColor(DstFormat, x, x, x, 0xFF); if (!(hdcSrc = gdi_GetDC())) { @@ -530,7 +530,7 @@ static BOOL test_gdi_BitBlt(UINT32 SrcFormat, UINT32 DstFormat) goto fail; hBmpDstOriginal = test_convert_to_bitmap(bmp_DST, RawFormat, 0, 0, 0, - DstFormat, 0, 0, 0, 16, 16, hPalette); + SrcFormat, 0, 0, 0, 16, 16, hPalette); if (!hBmpDstOriginal) goto fail; @@ -605,8 +605,8 @@ int TestGdiBitBlt(int argc, char* argv[]) if (!test_gdi_BitBlt(formatList[x], formatList[y])) { fprintf(stderr, "test_gdi_BitBlt(SrcFormat=%s, DstFormat=%s) failed!\n", - GetColorFormatName(formatList[x]), - GetColorFormatName(formatList[y])); + FreeRDPGetColorFormatName(formatList[x]), + FreeRDPGetColorFormatName(formatList[y])); rc = -y; } } diff --git a/libfreerdp/gdi/test/TestGdiClip.c b/libfreerdp/gdi/test/TestGdiClip.c index 2c64b49..b78ada2 100644 --- a/libfreerdp/gdi/test/TestGdiClip.c +++ b/libfreerdp/gdi/test/TestGdiClip.c @@ -14,11 +14,12 @@ static int test_gdi_ClipCoords(void) { + int rc = -1; BOOL draw; HGDI_DC hdc; - HGDI_RGN rgn1; - HGDI_RGN rgn2; - HGDI_BITMAP bmp; + HGDI_RGN rgn1 = NULL; + HGDI_RGN rgn2 = NULL; + HGDI_BITMAP bmp = NULL; const UINT32 format = PIXEL_FORMAT_ARGB32; if (!(hdc = gdi_GetDC())) @@ -42,7 +43,7 @@ static int test_gdi_ClipCoords(void) gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); if (!gdi_EqualRgn(rgn1, rgn2)) - return -1; + goto fail; /* region all inside clipping region */ gdi_SetClipRgn(hdc, 0, 0, 1024, 768); @@ -51,7 +52,7 @@ static int test_gdi_ClipCoords(void) gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); if (!gdi_EqualRgn(rgn1, rgn2)) - return -1; + goto fail; /* region all outside clipping region, on the left */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -61,7 +62,7 @@ static int test_gdi_ClipCoords(void) NULL); if (draw) - return -1; + goto fail; /* region all outside clipping region, on the right */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -71,7 +72,7 @@ static int test_gdi_ClipCoords(void) NULL); if (draw) - return -1; + goto fail; /* region all outside clipping region, on top */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -81,7 +82,7 @@ static int test_gdi_ClipCoords(void) NULL); if (draw) - return -1; + goto fail; /* region all outside clipping region, at the bottom */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -91,7 +92,7 @@ static int test_gdi_ClipCoords(void) NULL); if (draw) - return -1; + goto fail; /* left outside, right = clip, top = clip, bottom = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -100,7 +101,7 @@ static int test_gdi_ClipCoords(void) gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); if (!gdi_EqualRgn(rgn1, rgn2)) - return -1; + goto fail; /* left outside, right inside, top = clip, bottom = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -109,7 +110,7 @@ static int test_gdi_ClipCoords(void) gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); if (!gdi_EqualRgn(rgn1, rgn2)) - return -1; + goto fail; /* left = clip, right outside, top = clip, bottom = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -118,7 +119,7 @@ static int test_gdi_ClipCoords(void) gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); if (!gdi_EqualRgn(rgn1, rgn2)) - return -1; + goto fail; /* left inside, right outside, top = clip, bottom = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -127,7 +128,7 @@ static int test_gdi_ClipCoords(void) gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); if (!gdi_EqualRgn(rgn1, rgn2)) - return -1; + goto fail; /* top outside, bottom = clip, left = clip, right = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -136,7 +137,7 @@ static int test_gdi_ClipCoords(void) gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); if (!gdi_EqualRgn(rgn1, rgn2)) - return -1; + goto fail; /* top = clip, bottom outside, left = clip, right = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -145,7 +146,7 @@ static int test_gdi_ClipCoords(void) gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); if (!gdi_EqualRgn(rgn1, rgn2)) - return -1; + goto fail; /* top = clip, bottom = clip, top = clip, bottom = clip */ gdi_SetClipRgn(hdc, 300, 300, 100, 100); @@ -154,18 +155,27 @@ static int test_gdi_ClipCoords(void) gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); if (!gdi_EqualRgn(rgn1, rgn2)) - return -1; + goto fail; - return 0; + rc = 0; +fail: + + gdi_DeleteObject((HGDIOBJECT)rgn1); + gdi_DeleteObject((HGDIOBJECT)rgn2); + gdi_DeleteObject((HGDIOBJECT)bmp); + + gdi_DeleteDC(hdc); + return rc; } static int test_gdi_InvalidateRegion(void) { + int rc = -1; HGDI_DC hdc; - HGDI_RGN rgn1; - HGDI_RGN rgn2; - HGDI_RGN invalid; - HGDI_BITMAP bmp; + HGDI_RGN rgn1 = NULL; + HGDI_RGN rgn2 = NULL; + HGDI_RGN invalid = NULL; + HGDI_BITMAP bmp = NULL; const UINT32 format = PIXEL_FORMAT_XRGB32; if (!(hdc = gdi_GetDC())) @@ -195,7 +205,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* region same as invalid region */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -204,7 +214,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* left outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -213,7 +223,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* right outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -222,7 +232,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* top outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -231,7 +241,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* bottom outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -240,7 +250,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* left outside, right outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -249,7 +259,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* top outside, bottom outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -258,7 +268,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* all outside, left */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -267,7 +277,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* all outside, right */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -276,7 +286,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* all outside, top */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -285,7 +295,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* all outside, bottom */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -294,7 +304,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* all outside */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -303,7 +313,7 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; /* everything */ gdi_SetRgn(invalid, 300, 300, 100, 100); @@ -312,8 +322,16 @@ static int test_gdi_InvalidateRegion(void) gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h); if (!gdi_EqualRgn(invalid, rgn2)) - return -1; + goto fail; + rc = 0; +fail: + + gdi_DeleteObject((HGDIOBJECT)rgn1); + gdi_DeleteObject((HGDIOBJECT)rgn2); + gdi_DeleteObject((HGDIOBJECT)bmp); + + gdi_DeleteDC(hdc); return 0; } diff --git a/libfreerdp/gdi/test/TestGdiCreate.c b/libfreerdp/gdi/test/TestGdiCreate.c index 0f92774..e7390ad 100644 --- a/libfreerdp/gdi/test/TestGdiCreate.c +++ b/libfreerdp/gdi/test/TestGdiCreate.c @@ -34,6 +34,7 @@ static const UINT32 colorFormatCount = sizeof(colorFormatList) / sizeof( static int test_gdi_GetDC(void) { + int rc = -1; HGDI_DC hdc; if (!(hdc = gdi_GetDC())) @@ -43,18 +44,22 @@ static int test_gdi_GetDC(void) } if (hdc->format != PIXEL_FORMAT_XRGB32) - return -1; + goto fail; if (hdc->drawMode != GDI_R2_BLACK) - return -1; + goto fail; - return 0; + rc = 0; +fail: + gdi_DeleteDC(hdc); + return rc; } static int test_gdi_CreateCompatibleDC(void) { - HGDI_DC hdc; - HGDI_DC chdc; + int rc = -1; + HGDI_DC hdc = NULL; + HGDI_DC chdc = NULL; if (!(hdc = gdi_GetDC())) { @@ -68,25 +73,33 @@ static int test_gdi_CreateCompatibleDC(void) if (!(chdc = gdi_CreateCompatibleDC(hdc))) { printf("gdi_CreateCompatibleDC failed\n"); - return -1; + goto fail; } if (chdc->format != hdc->format) - return -1; + goto fail; if (chdc->drawMode != hdc->drawMode) - return -1; + goto fail; - return 0; + rc = 0; +fail: + + if (chdc) + gdi_DeleteDC(chdc); + + gdi_DeleteDC(hdc); + return rc; } static int test_gdi_CreateBitmap(void) { + int rc = -1; UINT32 format = PIXEL_FORMAT_ARGB32; UINT32 width; UINT32 height; BYTE* data; - HGDI_BITMAP hBitmap; + HGDI_BITMAP hBitmap = NULL; width = 32; height = 16; @@ -99,34 +112,42 @@ static int test_gdi_CreateBitmap(void) if (!(hBitmap = gdi_CreateBitmap(width, height, format, data))) { printf("gdi_CreateBitmap failed\n"); - return -1; + goto fail; } if (hBitmap->objectType != GDIOBJECT_BITMAP) - return -1; + goto fail; if (hBitmap->format != format) - return -1; + goto fail; if (hBitmap->width != width) - return -1; + goto fail; if (hBitmap->height != height) - return -1; + goto fail; if (hBitmap->data != data) - return -1; + goto fail; - gdi_DeleteObject((HGDIOBJECT) hBitmap); - return 0; + rc = 0; +fail: + + if (hBitmap) + gdi_DeleteObject((HGDIOBJECT) hBitmap); + else + free(data); + + return rc; } static int test_gdi_CreateCompatibleBitmap(void) { + int rc = -1; HGDI_DC hdc; UINT32 width; UINT32 height; - HGDI_BITMAP hBitmap; + HGDI_BITMAP hBitmap = NULL; if (!(hdc = gdi_GetDC())) { @@ -140,26 +161,33 @@ static int test_gdi_CreateCompatibleBitmap(void) hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height); if (hBitmap->objectType != GDIOBJECT_BITMAP) - return -1; + goto fail; if (hBitmap->format != hdc->format) - return -1; + goto fail; if (hBitmap->width != width) - return -1; + goto fail; if (hBitmap->height != height) - return -1; + goto fail; if (!hBitmap->data) - return -1; + goto fail; - gdi_DeleteObject((HGDIOBJECT) hBitmap); - return 0; + rc = 0; +fail: + + if (hBitmap) + gdi_DeleteObject((HGDIOBJECT) hBitmap); + + gdi_DeleteDC(hdc); + return rc; } static int test_gdi_CreatePen(void) { + int rc = -1; const UINT32 format = PIXEL_FORMAT_RGBA32; HGDI_PEN hPen = gdi_CreatePen(GDI_PS_SOLID, 8, 0xAABBCCDD, format, NULL); @@ -171,92 +199,116 @@ static int test_gdi_CreatePen(void) } if (hPen->style != GDI_PS_SOLID) - return -1; + goto fail; if (hPen->width != 8) - return -1; + goto fail; if (hPen->color != 0xAABBCCDD) - return -1; + goto fail; + rc = 0; +fail: gdi_DeleteObject((HGDIOBJECT) hPen); - return 0; + return rc; } static int test_gdi_CreateSolidBrush(void) { + int rc = -1; HGDI_BRUSH hBrush = gdi_CreateSolidBrush(0xAABBCCDD); if (hBrush->objectType != GDIOBJECT_BRUSH) - return -1; + goto fail; if (hBrush->style != GDI_BS_SOLID) - return -1; + goto fail; if (hBrush->color != 0xAABBCCDD) - return -1; + goto fail; + rc = 0; +fail: gdi_DeleteObject((HGDIOBJECT) hBrush); - return 0; + return rc; } static int test_gdi_CreatePatternBrush(void) { + int rc = -1; HGDI_BRUSH hBrush; HGDI_BITMAP hBitmap; hBitmap = gdi_CreateBitmap(64, 64, 32, NULL); hBrush = gdi_CreatePatternBrush(hBitmap); + if (!hBitmap || !hBrush) + goto fail; + if (hBrush->objectType != GDIOBJECT_BRUSH) - return -1; + goto fail; if (hBrush->style != GDI_BS_PATTERN) - return -1; + goto fail; if (hBrush->pattern != hBitmap) - return -1; + goto fail; - gdi_DeleteObject((HGDIOBJECT) hBitmap); - return 0; + rc = 0; +fail: + + if (hBitmap) + gdi_DeleteObject((HGDIOBJECT) hBitmap); + + if (hBrush) + gdi_DeleteObject((HGDIOBJECT) hBrush); + + return rc; } static int test_gdi_CreateRectRgn(void) { - int x1 = 32; - int y1 = 64; - int x2 = 128; - int y2 = 256; + int rc = -1; + UINT32 x1 = 32; + UINT32 y1 = 64; + UINT32 x2 = 128; + UINT32 y2 = 256; HGDI_RGN hRegion = gdi_CreateRectRgn(x1, y1, x2, y2); + if (!hRegion) + return rc; + if (hRegion->objectType != GDIOBJECT_REGION) - return -1; + goto fail; if (hRegion->x != x1) - return -1; + goto fail; if (hRegion->y != y1) - return -1; + goto fail; if (hRegion->w != x2 - x1 + 1) - return -1; + goto fail; if (hRegion->h != y2 - y1 + 1) - return -1; + goto fail; if (hRegion->null) - return -1; + goto fail; + rc = 0; +fail: gdi_DeleteObject((HGDIOBJECT) hRegion); - return 0; + return rc; } static int test_gdi_CreateRect(void) { + int rc = -1; HGDI_RECT hRect; - int x1 = 32; - int y1 = 64; - int x2 = 128; - int y2 = 256; + UINT32 x1 = 32; + UINT32 y1 = 64; + UINT32 x2 = 128; + UINT32 y2 = 256; if (!(hRect = gdi_CreateRect(x1, y1, x2, y2))) { @@ -265,22 +317,24 @@ static int test_gdi_CreateRect(void) } if (hRect->objectType != GDIOBJECT_RECT) - return -1; + goto fail; if (hRect->left != x1) - return -1; + goto fail; if (hRect->top != y1) - return -1; + goto fail; if (hRect->right != x2) - return -1; + goto fail; if (hRect->bottom != y2) - return -1; + goto fail; + rc = 0; +fail: gdi_DeleteObject((HGDIOBJECT) hRect); - return 0; + return rc; } static BOOL test_gdi_GetPixel(void) @@ -305,6 +359,13 @@ static BOOL test_gdi_GetPixel(void) hdc->format = colorFormatList[x]; hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height); + + if (!hBitmap) + { + gdi_DeleteDC(hdc); + return -1; + } + gdi_SelectObject(hdc, (HGDIOBJECT) hBitmap); bpp = GetBytesPerPixel(hBitmap->format); @@ -313,7 +374,7 @@ static BOOL test_gdi_GetPixel(void) for (j = 0; j < width; j++) { UINT32 pixel; - const UINT32 color = GetColor(hBitmap->format, rand(), rand(), rand(), rand()); + const UINT32 color = FreeRDPGetColor(hBitmap->format, rand(), rand(), rand(), rand()); WriteColor(&hBitmap->data[i * hBitmap->scanline + j * bpp], hBitmap->format, color); pixel = gdi_GetPixel(hdc, j, i); @@ -365,7 +426,7 @@ static BOOL test_gdi_SetPixel(void) for (j = 0; j < width; j++) { UINT32 pixel; - const UINT32 color = GetColor(hBitmap->format, rand(), rand(), rand(), rand()); + const UINT32 color = FreeRDPGetColor(hBitmap->format, rand(), rand(), rand(), rand()); gdi_SetPixel(hdc, j, i, color); pixel = ReadColor(&hBitmap->data[i * hBitmap->scanline + j * bpp], hBitmap->format); @@ -390,6 +451,7 @@ static BOOL test_gdi_SetPixel(void) static int test_gdi_SetROP2(void) { + int rc = -1; HGDI_DC hdc; if (!(hdc = gdi_GetDC())) @@ -401,16 +463,20 @@ static int test_gdi_SetROP2(void) gdi_SetROP2(hdc, GDI_R2_BLACK); if (hdc->drawMode != GDI_R2_BLACK) - return -1; + goto fail; - return 0; + rc = 0; +fail: + gdi_DeleteDC(hdc); + return rc; } static int test_gdi_MoveToEx(void) { + int rc = -1; HGDI_DC hdc; - HGDI_PEN hPen; - HGDI_POINT prevPoint; + HGDI_PEN hPen = NULL; + HGDI_POINT prevPoint = NULL; const UINT32 format = PIXEL_FORMAT_RGBA32; gdiPalette* palette = NULL; @@ -423,35 +489,43 @@ static int test_gdi_MoveToEx(void) if (!(hPen = gdi_CreatePen(GDI_PS_SOLID, 8, 0xAABBCCDD, format, palette))) { printf("gdi_CreatePen failed\n"); - return -1; + goto fail; } gdi_SelectObject(hdc, (HGDIOBJECT) hPen); gdi_MoveToEx(hdc, 128, 256, NULL); if (hdc->pen->posX != 128) - return -1; + goto fail; if (hdc->pen->posY != 256) - return -1; + goto fail; prevPoint = (HGDI_POINT) malloc(sizeof(GDI_POINT)); ZeroMemory(prevPoint, sizeof(GDI_POINT)); gdi_MoveToEx(hdc, 64, 128, prevPoint); if (prevPoint->x != 128) - return -1; + goto fail; if (prevPoint->y != 256) - return -1; + goto fail; if (hdc->pen->posX != 64) - return -1; + goto fail; if (hdc->pen->posY != 128) - return -1; + goto fail; - return 0; + rc = 0; +fail: + + if (hPen) + gdi_DeleteObject((HGDIOBJECT)hPen); + + free(prevPoint); + gdi_DeleteDC(hdc); + return rc; } int TestGdiCreate(int argc, char* argv[]) diff --git a/libfreerdp/gdi/test/TestGdiEllipse.c b/libfreerdp/gdi/test/TestGdiEllipse.c index 83fb3b0..b195be1 100644 --- a/libfreerdp/gdi/test/TestGdiEllipse.c +++ b/libfreerdp/gdi/test/TestGdiEllipse.c @@ -117,7 +117,7 @@ int TestGdiEllipse(int argc, char* argv[]) g.format = format; for (j = 0; j < 256; j++) - g.palette[i] = GetColor(format, j, j, j, 0xFF); + g.palette[i] = FreeRDPGetColor(format, j, j, j, 0xFF); rc = -1; diff --git a/libfreerdp/gdi/test/TestGdiLine.c b/libfreerdp/gdi/test/TestGdiLine.c index f85154a..f5d1f3d 100644 --- a/libfreerdp/gdi/test/TestGdiLine.c +++ b/libfreerdp/gdi/test/TestGdiLine.c @@ -700,7 +700,7 @@ int TestGdiLine(int argc, char* argv[]) g.format = format; for (i = 0; i < 256; i++) - g.palette[i] = GetColor(format, i, i, i, 0xFF); + g.palette[i] = FreeRDPGetColor(format, i, i, i, 0xFF); rc = -1; @@ -712,7 +712,7 @@ int TestGdiLine(int argc, char* argv[]) hdc->format = format; gdi_SetNullClipRgn(hdc); - penColor = GetColor(format, 0xFF, 0xFF, 0xFF, 0xFF); + penColor = FreeRDPGetColor(format, 0xFF, 0xFF, 0xFF, 0xFF); if (!(pen = gdi_CreatePen(1, 1, penColor, format, hPalette))) { @@ -780,7 +780,7 @@ int TestGdiLine(int argc, char* argv[]) { char name[1024]; _snprintf(name, sizeof(name), "%s [%s]", gdi_rop_to_string(rop_map[x].rop), - GetColorFormatName(hdc->format)); + FreeRDPGetColorFormatName(hdc->format)); /* Test Case 13: (0,0) -> (16,16), R2_NOTMERGEPEN */ if (!gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS, hPalette)) @@ -809,6 +809,7 @@ int TestGdiLine(int argc, char* argv[]) for (x = 0; x < map_size; x++) gdi_DeleteObject((HGDIOBJECT) rop_map[x].bmp); + gdi_DeleteObject((HGDIOBJECT)hBmp); gdi_DeleteObject((HGDIOBJECT) pen); gdi_DeleteDC(hdc); diff --git a/libfreerdp/gdi/test/TestGdiRect.c b/libfreerdp/gdi/test/TestGdiRect.c index cff092b..e850f9e 100644 --- a/libfreerdp/gdi/test/TestGdiRect.c +++ b/libfreerdp/gdi/test/TestGdiRect.c @@ -16,67 +16,71 @@ static int test_gdi_PtInRect(void) { + int rc = -1; HGDI_RECT hRect; - int left = 20; - int top = 40; - int right = 60; - int bottom = 80; + UINT32 left = 20; + UINT32 top = 40; + UINT32 right = 60; + UINT32 bottom = 80; if (!(hRect = gdi_CreateRect(left, top, right, bottom))) { printf("gdi_CreateRect failed\n"); - return -1; + return rc; } if (gdi_PtInRect(hRect, 0, 0)) - return -1; + goto fail; if (gdi_PtInRect(hRect, 500, 500)) - return -1; + goto fail; if (gdi_PtInRect(hRect, 40, 100)) - return -1; + goto fail; if (gdi_PtInRect(hRect, 10, 40)) - return -1; + goto fail; if (!gdi_PtInRect(hRect, 30, 50)) - return -1; + goto fail; if (!gdi_PtInRect(hRect, left, top)) - return -1; + goto fail; if (!gdi_PtInRect(hRect, right, bottom)) - return -1; + goto fail; if (!gdi_PtInRect(hRect, right, 60)) - return -1; + goto fail; if (!gdi_PtInRect(hRect, 40, bottom)) - return -1; + goto fail; - return 0; + rc = 0; +fail: + gdi_DeleteObject((HGDIOBJECT)hRect); + return rc; } int test_gdi_FillRect(void) { int rc = -1; - HGDI_DC hdc; - HGDI_RECT hRect; + HGDI_DC hdc = NULL; + HGDI_RECT hRect = NULL; HGDI_BRUSH hBrush = NULL; HGDI_BITMAP hBitmap = NULL; UINT32 color; UINT32 pixel; UINT32 rawPixel; - int x, y; - int badPixels; - int goodPixels; - int width = 200; - int height = 300; - int left = 20; - int top = 40; - int right = 60; - int bottom = 80; + UINT32 x, y; + UINT32 badPixels; + UINT32 goodPixels; + UINT32 width = 200; + UINT32 height = 300; + UINT32 left = 20; + UINT32 top = 40; + UINT32 right = 60; + UINT32 bottom = 80; if (!(hdc = gdi_GetDC())) { @@ -95,7 +99,7 @@ int test_gdi_FillRect(void) hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height); ZeroMemory(hBitmap->data, width * height * GetBytesPerPixel(hdc->format)); gdi_SelectObject(hdc, (HGDIOBJECT) hBitmap); - color = GetColor(PIXEL_FORMAT_ARGB32, 0xAA, 0xBB, 0xCC, 0xFF); + color = FreeRDPGetColor(PIXEL_FORMAT_ARGB32, 0xAA, 0xBB, 0xCC, 0xFF); hBrush = gdi_CreateSolidBrush(color); gdi_FillRect(hdc, hRect, hBrush); badPixels = 0; @@ -106,7 +110,7 @@ int test_gdi_FillRect(void) for (y = 0; y < height; y++) { rawPixel = gdi_GetPixel(hdc, x, y); - pixel = ConvertColor(rawPixel, hdc->format, PIXEL_FORMAT_ARGB32, NULL); + pixel = FreeRDPConvertColor(rawPixel, hdc->format, PIXEL_FORMAT_ARGB32, NULL); if (gdi_PtInRect(hRect, x, y)) { @@ -144,6 +148,8 @@ int test_gdi_FillRect(void) fail: gdi_DeleteObject((HGDIOBJECT) hBrush); gdi_DeleteObject((HGDIOBJECT) hBitmap); + gdi_DeleteObject((HGDIOBJECT)hRect); + gdi_DeleteDC(hdc); return rc; } diff --git a/libfreerdp/gdi/test/TestGdiRop3.c b/libfreerdp/gdi/test/TestGdiRop3.c index d80fd5b..9e9c414 100644 --- a/libfreerdp/gdi/test/TestGdiRop3.c +++ b/libfreerdp/gdi/test/TestGdiRop3.c @@ -93,10 +93,6 @@ * */ -static const BYTE rop_P = 0xF0; /* 11110000 */ -static const BYTE rop_S = 0xCC; /* 11001100 */ -static const BYTE rop_D = 0xAA; /* 10101010 */ - static char* gdi_convert_postfix_to_infix(const char* postfix) { int i; diff --git a/libfreerdp/gdi/test/helpers.c b/libfreerdp/gdi/test/helpers.c index caa3261..6fe2ca0 100644 --- a/libfreerdp/gdi/test/helpers.c +++ b/libfreerdp/gdi/test/helpers.c @@ -111,7 +111,7 @@ static BOOL CompareBitmaps(HGDI_BITMAP hBmp1, HGDI_BITMAP hBmp2, p2 += GetBytesPerPixel(hBmp2->format); if (hBmp1->format != hBmp2->format) - colorB = ConvertColor(colorB, hBmp2->format, hBmp1->format, palette); + colorB = FreeRDPConvertColor(colorB, hBmp2->format, hBmp1->format, palette); if (colorA != colorB) return FALSE; @@ -130,7 +130,9 @@ BOOL test_assert_bitmaps_equal(HGDI_BITMAP hBmpActual, if (!bitmapsEqual) { - printf("\n%s\n", name); + printf("Testing ROP %s [%s|%s]\n", name, + FreeRDPGetColorFormatName(hBmpActual->format), + FreeRDPGetColorFormatName(hBmpExpected->format)); test_dump_bitmap(hBmpActual, "Actual"); test_dump_bitmap(hBmpExpected, "Expected"); fflush(stdout); diff --git a/libfreerdp/gdi/video.c b/libfreerdp/gdi/video.c new file mode 100644 index 0000000..0813df4 --- /dev/null +++ b/libfreerdp/gdi/video.c @@ -0,0 +1,159 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Video Optimized Remoting Virtual Channel Extension for X11 + * + * Copyright 2017 David Fort <contact@hardening-consulting.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <freerdp/client/geometry.h> +#include <freerdp/client/video.h> +#include <freerdp/gdi/gdi.h> +#include <freerdp/gdi/video.h> +#include <freerdp/gdi/region.h> + +#define TAG FREERDP_TAG("video") + +typedef struct +{ + VideoSurface base; + UINT32 scanline; + BYTE* image; +} gdiVideoSurface; + + +void gdi_video_geometry_init(rdpGdi* gdi, GeometryClientContext* geom) +{ + gdi->geometry = geom; + + if (gdi->video) + { + VideoClientContext* video = gdi->video; + video->setGeometry(video, gdi->geometry); + } +} + +void gdi_video_geometry_uninit(rdpGdi* gdi, GeometryClientContext* geom) +{ +} + +static VideoSurface* gdiVideoCreateSurface(VideoClientContext* video, BYTE* data, UINT32 x, + UINT32 y, + UINT32 width, UINT32 height) +{ + rdpGdi* gdi = (rdpGdi*)video->custom; + gdiVideoSurface* ret = calloc(1, sizeof(*ret)); + UINT32 bpp; + + if (!ret) + return NULL; + + bpp = GetBytesPerPixel(gdi->dstFormat); + ret->base.data = data; + ret->base.x = x; + ret->base.y = y; + ret->base.w = width; + ret->base.h = height; + ret->scanline = width * bpp; + ret->image = _aligned_malloc(ret->scanline * height, 16); + + if (!ret->image) + { + WLog_ERR(TAG, "unable to create surface image"); + free(ret); + return NULL; + } + + return &ret->base; +} + + +static BOOL gdiVideoShowSurface(VideoClientContext* video, VideoSurface* surface) +{ + rdpGdi* gdi = (rdpGdi*)video->custom; + gdiVideoSurface* gdiSurface = (gdiVideoSurface*)surface; + RECTANGLE_16 surfaceRect; + rdpUpdate* update = gdi->context->update; + surfaceRect.left = surface->x; + surfaceRect.top = surface->y; + surfaceRect.right = surface->x + surface->w; + surfaceRect.bottom = surface->y + surface->h; + update->BeginPaint(gdi->context); + { + const UINT32 nXSrc = surface->x; + const UINT32 nYSrc = surface->y; + const UINT32 nXDst = nXSrc; + const UINT32 nYDst = nYSrc; + const UINT32 width = (surface->w + surface->x < gdi->width) ? surface->w : gdi->width - surface->x; + const UINT32 height = (surface->h + surface->y < gdi->height) ? surface->h : gdi->height - + surface->y; + + if (!freerdp_image_copy(gdi->primary_buffer, gdi->primary->hdc->format, + gdi->stride, + nXDst, nYDst, width, height, + surface->data, gdi->primary->hdc->format, + gdiSurface->scanline, 0, 0, NULL, FREERDP_FLIP_NONE)) + return CHANNEL_RC_NULL_DATA; + + gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, width, height); + } + update->EndPaint(gdi->context); + return TRUE; +} + +static BOOL gdiVideoDeleteSurface(VideoClientContext* video, VideoSurface* surface) +{ + gdiVideoSurface* gdiSurface = (gdiVideoSurface*)surface; + + if (gdiSurface) + _aligned_free(gdiSurface->image); + + free(gdiSurface); + return TRUE; +} +void gdi_video_control_init(rdpGdi* gdi, VideoClientContext* video) +{ + gdi->video = video; + video->custom = gdi; + video->createSurface = gdiVideoCreateSurface; + video->showSurface = gdiVideoShowSurface; + video->deleteSurface = gdiVideoDeleteSurface; + video->setGeometry(video, gdi->geometry); +} + + +void gdi_video_control_uninit(rdpGdi* gdi, VideoClientContext* video) +{ + gdi->video = NULL; +} + +static void gdi_video_timer(void* context, TimerEventArgs* timer) +{ + rdpContext* ctx = (rdpContext*)context; + rdpGdi* gdi = ctx->gdi; + + if (gdi && gdi->video) + gdi->video->timer(gdi->video, timer->now); +} + +void gdi_video_data_init(rdpGdi* gdi, VideoClientContext* video) +{ + PubSub_SubscribeTimer(gdi->context->pubSub, gdi_video_timer); +} + +void gdi_video_data_uninit(rdpGdi* gdi, VideoClientContext* context) +{ + PubSub_UnsubscribeTimer(gdi->context->pubSub, gdi_video_timer); +} diff --git a/libfreerdp/locale/CMakeLists.txt b/libfreerdp/locale/CMakeLists.txt index e418e0c..1a300f2 100644 --- a/libfreerdp/locale/CMakeLists.txt +++ b/libfreerdp/locale/CMakeLists.txt @@ -69,4 +69,8 @@ if(WITH_X11) endif() endif() +if(WITH_WAYLAND) + freerdp_definition_add(-DWITH_WAYLAND) +endif() + freerdp_module_add(${${MODULE_PREFIX}_SRCS}) diff --git a/libfreerdp/locale/keyboard.c b/libfreerdp/locale/keyboard.c index dbbf1dd..bd467e6 100644 --- a/libfreerdp/locale/keyboard.c +++ b/libfreerdp/locale/keyboard.c @@ -98,7 +98,7 @@ int freerdp_keyboard_init_x11_evdev(DWORD* keyboardLayoutId, DWORD x11_keycode_t DWORD freerdp_keyboard_init(DWORD keyboardLayoutId) { DWORD keycode; -#if defined(__APPLE__) || defined(WITH_X11) +#if defined(__APPLE__) || defined(WITH_X11) || defined(WITH_WAYLAND) int status = -1; #endif @@ -107,7 +107,7 @@ DWORD freerdp_keyboard_init(DWORD keyboardLayoutId) status = freerdp_keyboard_init_apple(&keyboardLayoutId, X11_KEYCODE_TO_VIRTUAL_SCANCODE); #endif -#ifdef WITH_X11 +#if defined(WITH_X11) || defined(WITH_WAYLAND) #ifdef WITH_XKBFILE if (status < 0) diff --git a/libfreerdp/locale/keyboard_sun.c b/libfreerdp/locale/keyboard_sun.c index 111abf7..57fa9dc 100644 --- a/libfreerdp/locale/keyboard_sun.c +++ b/libfreerdp/locale/keyboard_sun.c @@ -24,6 +24,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> #include <winpr/crt.h> @@ -210,8 +211,8 @@ int freerdp_get_solaris_keyboard_layout_and_type(int* type, int* layout) char* pch; char* beg; char* end; + int rc = -1; char buffer[1024]; - /* Sample output for "kbd -t -l" : @@ -221,10 +222,8 @@ int freerdp_get_solaris_keyboard_layout_and_type(int* type, int* layout) delay(ms)=500 rate(ms)=40 */ - *type = 0; *layout = 0; - kbd = popen("kbd -t -l", "r"); if (!kbd) @@ -232,25 +231,40 @@ int freerdp_get_solaris_keyboard_layout_and_type(int* type, int* layout) while (fgets(buffer, sizeof(buffer), kbd) != NULL) { + long val; + if ((pch = strstr(buffer, "type=")) != NULL) { beg = pch + sizeof("type=") - 1; end = strchr(beg, '\n'); end[0] = '\0'; - *type = atoi(beg); + errno = 0; + val = strtol(beg, NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + goto fail; + + *type = val; } else if ((pch = strstr(buffer, "layout=")) != NULL) { beg = pch + sizeof("layout=") - 1; end = strchr(beg, ' '); end[0] = '\0'; - *layout = atoi(beg); + errno = 0; + val = strtol(beg, NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + goto fail; + + *layout = val; } } + rc = 0; +fail: pclose(kbd); - - return 0; + return rc; } DWORD freerdp_detect_solaris_keyboard_layout() diff --git a/libfreerdp/primitives/prim_YUV.c b/libfreerdp/primitives/prim_YUV.c index 0e2b4b0..b86365b 100644 --- a/libfreerdp/primitives/prim_YUV.c +++ b/libfreerdp/primitives/prim_YUV.c @@ -726,6 +726,73 @@ static INLINE pstatus_t general_RGBToYUV420_BGRX( return PRIMITIVES_SUCCESS; } +static INLINE pstatus_t general_RGBToYUV420_RGBX( + const BYTE* pSrc, UINT32 srcStep, + BYTE* pDst[3], UINT32 dstStep[3], const prim_size_t* roi) +{ + UINT32 x, y, i; + size_t x1 = 0, x2 = 4, x3 = srcStep, x4 = srcStep + 4; + size_t y1 = 0, y2 = 1, y3 = dstStep[0], y4 = dstStep[0] + 1; + UINT32 max_x = roi->width - 1; + UINT32 max_y = roi->height - 1; + + for (y = i = 0; y < roi->height; y += 2, i++) + { + const BYTE* src = pSrc + y * srcStep; + BYTE* ydst = pDst[0] + y * dstStep[0]; + BYTE* udst = pDst[1] + i * dstStep[1]; + BYTE* vdst = pDst[2] + i * dstStep[2]; + + for (x = 0; x < roi->width; x += 2) + { + BYTE R, G, B; + INT32 Ra, Ga, Ba; + /* row 1, pixel 1 */ + Ra = R = *(src + x1 + 0); + Ga = G = *(src + x1 + 1); + Ba = B = *(src + x1 + 2); + ydst[y1] = RGB2Y(R, G, B); + + if (x < max_x) + { + /* row 1, pixel 2 */ + Ra += R = *(src + x2 + 0); + Ga += G = *(src + x2 + 1); + Ba += B = *(src + x2 + 2); + ydst[y2] = RGB2Y(R, G, B); + } + + if (y < max_y) + { + /* row 2, pixel 1 */ + Ra += R = *(src + x3 + 0); + Ga += G = *(src + x3 + 1); + Ba += B = *(src + x3 + 2); + ydst[y3] = RGB2Y(R, G, B); + + if (x < max_x) + { + /* row 2, pixel 2 */ + Ra += R = *(src + x4 + 0); + Ga += G = *(src + x4 + 1); + Ba += B = *(src + x4 + 2); + ydst[y4] = RGB2Y(R, G, B); + } + } + + Ba >>= 2; + Ga >>= 2; + Ra >>= 2; + *udst++ = RGB2U(Ra, Ga, Ba); + *vdst++ = RGB2V(Ra, Ga, Ba); + ydst += 2; + src += 8; + } + } + + return PRIMITIVES_SUCCESS; +} + static INLINE pstatus_t general_RGBToYUV420_ANY( const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep, BYTE* pDst[3], UINT32 dstStep[3], const prim_size_t* roi) @@ -813,13 +880,113 @@ static pstatus_t general_RGBToYUV420_8u_P3AC4R( case PIXEL_FORMAT_BGRX32: return general_RGBToYUV420_BGRX(pSrc, srcStep, pDst, dstStep, roi); + case PIXEL_FORMAT_RGBA32: + case PIXEL_FORMAT_RGBX32: + return general_RGBToYUV420_RGBX(pSrc, srcStep, pDst, dstStep, roi); + default: return general_RGBToYUV420_ANY(pSrc, srcFormat, srcStep, pDst, dstStep, roi); } } +static INLINE void general_RGBToAVC444YUV_BGRX_DOUBLE_ROW( + const BYTE* srcEven, const BYTE* srcOdd, BYTE* b1Even, BYTE* b1Odd, BYTE* b2, + BYTE* b3, BYTE* b4, BYTE* b5, BYTE* b6, BYTE* b7, UINT32 width) +{ + UINT32 x; + + for (x = 0; x < width; x += 2) + { + const BOOL lastX = (x + 1) >= width; + BYTE Y1e, Y2e, U1e, V1e, U2e, V2e; + BYTE Y1o, Y2o, U1o, V1o, U2o, V2o; + /* Read 4 pixels, 2 from even, 2 from odd lines */ + { + const BYTE b = *srcEven++; + const BYTE g = *srcEven++; + const BYTE r = *srcEven++; + srcEven++; + Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b); + U1e = U2e = U1o = U2o = RGB2U(r, g, b); + V1e = V2e = V1o = V2o = RGB2V(r, g, b); + } + + if (!lastX) + { + const BYTE b = *srcEven++; + const BYTE g = *srcEven++; + const BYTE r = *srcEven++; + srcEven++; + Y2e = RGB2Y(r, g, b); + U2e = RGB2U(r, g, b); + V2e = RGB2V(r, g, b); + } + + if (b1Odd) + { + const BYTE b = *srcOdd++; + const BYTE g = *srcOdd++; + const BYTE r = *srcOdd++; + srcOdd++; + Y1o = Y2o = RGB2Y(r, g, b); + U1o = U2o = RGB2U(r, g, b); + V1o = V2o = RGB2V(r, g, b); + } + + if (b1Odd && !lastX) + { + const BYTE b = *srcOdd++; + const BYTE g = *srcOdd++; + const BYTE r = *srcOdd++; + srcOdd++; + Y2o = RGB2Y(r, g, b); + U2o = RGB2U(r, g, b); + V2o = RGB2V(r, g, b); + } + + /* We have 4 Y pixels, so store them. */ + *b1Even++ = Y1e; + *b1Even++ = Y2e; + + if (b1Odd) + { + *b1Odd++ = Y1o; + *b1Odd++ = Y2o; + } + + /* 2x 2y pixel in luma UV plane use averaging + */ + { + const BYTE Uavg = ((UINT16)U1e + (UINT16)U2e + (UINT16)U1o + (UINT16)U2o) / 4; + const BYTE Vavg = ((UINT16)V1e + (UINT16)V2e + (UINT16)V1o + (UINT16)V2o) / 4; + *b2++ = Uavg; + *b3++ = Vavg; + } + + /* UV from 2x, 2y+1 */ + if (b1Odd) + { + *b4++ = U1o; + *b5++ = V1o; + + if (!lastX) + { + *b4++ = U2o; + *b5++ = V2o; + } + } + + /* UV from 2x+1, 2y */ + if (!lastX) + { + *b6++ = U2e; + *b7++ = V2e; + } + } +} + static INLINE pstatus_t general_RGBToAVC444YUV_BGRX( - const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep, + const BYTE* pSrc, UINT32 srcStep, BYTE* pDst1[3], const UINT32 dst1Step[3], BYTE* pDst2[3], const UINT32 dst2Step[3], const prim_size_t* roi) @@ -828,78 +995,260 @@ static INLINE pstatus_t general_RGBToAVC444YUV_BGRX( * Note: * Read information in function general_RGBToAVC444YUV_ANY below ! */ - UINT32 x, y, n, numRows, numCols; - BOOL evenRow = TRUE; - BYTE* b1, *b2, *b3, *b4, *b5, *b6, *b7; + UINT32 y; const BYTE* pMaxSrc = pSrc + (roi->height - 1) * srcStep; - numRows = (roi->height + 1) & ~1; - numCols = (roi->width + 1) & ~1; - for (y = 0; y < numRows; y++, evenRow = !evenRow) + for (y = 0; y < roi->height; y += 2) { - const BYTE* src = y < roi->height ? pSrc + y * srcStep : pMaxSrc; - UINT32 i = y >> 1; - b1 = pDst1[0] + y * dst1Step[0]; - - if (evenRow) - { - b2 = pDst1[1] + i * dst1Step[1]; - b3 = pDst1[2] + i * dst1Step[2]; - b6 = pDst2[1] + i * dst2Step[1]; - b7 = pDst2[2] + i * dst2Step[2]; - } - else - { - n = (i & ~7) + i; - b4 = pDst2[0] + dst2Step[0] * n; - b5 = b4 + 8 * dst2Step[0]; - } - - for (x = 0; x < numCols; x += 2) - { - BYTE R, G, B, Y1, Y2, U1, U2, V1, V2; - B = src[0]; - G = src[1]; - R = src[2]; - Y1 = Y2 = RGB2Y(R, G, B); - U1 = U2 = RGB2U(R, G, B); - V1 = V2 = RGB2V(R, G, B); - - if (x + 1 < roi->width) - { - B = src[4]; - G = src[5]; - R = src[6]; - Y2 = RGB2Y(R, G, B); - U2 = RGB2U(R, G, B); - V2 = RGB2V(R, G, B); - } - - *b1++ = Y1; - *b1++ = Y2; - - if (evenRow) - { - *b2++ = U1; - *b3++ = V1; - *b6++ = U2; - *b7++ = V2; - } - else - { - *b4++ = U1; - *b4++ = U2; - *b5++ = V1; - *b5++ = V2; - } - - src += 8; - } + const BOOL last = (y >= (roi->height - 1)); + const BYTE* srcEven = y < roi->height ? pSrc + y * srcStep : pMaxSrc; + const BYTE* srcOdd = !last ? pSrc + (y + 1) * srcStep : pMaxSrc; + const UINT32 i = y >> 1; + const UINT32 n = (i & ~7) + i; + BYTE* b1Even = pDst1[0] + y * dst1Step[0]; + BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : NULL; + BYTE* b2 = pDst1[1] + (y / 2) * dst1Step[1]; + BYTE* b3 = pDst1[2] + (y / 2) * dst1Step[2]; + BYTE* b4 = pDst2[0] + dst2Step[0] * n; + BYTE* b5 = b4 + 8 * dst2Step[0]; + BYTE* b6 = pDst2[1] + (y / 2) * dst2Step[1]; + BYTE* b7 = pDst2[2] + (y / 2) * dst2Step[2]; + general_RGBToAVC444YUV_BGRX_DOUBLE_ROW(srcEven, srcOdd, b1Even, b1Odd, b2, b3, b4, b5, b6, b7, + roi->width); } return PRIMITIVES_SUCCESS; } +static INLINE void general_RGBToAVC444YUV_RGBX_DOUBLE_ROW( + const BYTE* srcEven, const BYTE* srcOdd, BYTE* b1Even, BYTE* b1Odd, BYTE* b2, + BYTE* b3, BYTE* b4, BYTE* b5, BYTE* b6, BYTE* b7, UINT32 width) +{ + UINT32 x; + + for (x = 0; x < width; x += 2) + { + const BOOL lastX = (x + 1) >= width; + BYTE Y1e, Y2e, U1e, V1e, U2e, V2e; + BYTE Y1o, Y2o, U1o, V1o, U2o, V2o; + /* Read 4 pixels, 2 from even, 2 from odd lines */ + { + const BYTE r = *srcEven++; + const BYTE g = *srcEven++; + const BYTE b = *srcEven++; + srcEven++; + Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b); + U1e = U2e = U1o = U2o = RGB2U(r, g, b); + V1e = V2e = V1o = V2o = RGB2V(r, g, b); + } + + if (!lastX) + { + const BYTE r = *srcEven++; + const BYTE g = *srcEven++; + const BYTE b = *srcEven++; + srcEven++; + Y2e = RGB2Y(r, g, b); + U2e = RGB2U(r, g, b); + V2e = RGB2V(r, g, b); + } + + if (b1Odd) + { + const BYTE r = *srcOdd++; + const BYTE g = *srcOdd++; + const BYTE b = *srcOdd++; + srcOdd++; + Y1o = Y2o = RGB2Y(r, g, b); + U1o = U2o = RGB2U(r, g, b); + V1o = V2o = RGB2V(r, g, b); + } + + if (b1Odd && !lastX) + { + const BYTE r = *srcOdd++; + const BYTE g = *srcOdd++; + const BYTE b = *srcOdd++; + srcOdd++; + Y2o = RGB2Y(r, g, b); + U2o = RGB2U(r, g, b); + V2o = RGB2V(r, g, b); + } + + /* We have 4 Y pixels, so store them. */ + *b1Even++ = Y1e; + *b1Even++ = Y2e; + + if (b1Odd) + { + *b1Odd++ = Y1o; + *b1Odd++ = Y2o; + } + + /* 2x 2y pixel in luma UV plane use averaging + */ + { + const BYTE Uavg = ((UINT16)U1e + (UINT16)U2e + (UINT16)U1o + (UINT16)U2o) / 4; + const BYTE Vavg = ((UINT16)V1e + (UINT16)V2e + (UINT16)V1o + (UINT16)V2o) / 4; + *b2++ = Uavg; + *b3++ = Vavg; + } + + /* UV from 2x, 2y+1 */ + if (b1Odd) + { + *b4++ = U1o; + *b5++ = V1o; + + if (!lastX) + { + *b4++ = U2o; + *b5++ = V2o; + } + } + + /* UV from 2x+1, 2y */ + if (!lastX) + { + *b6++ = U2e; + *b7++ = V2e; + } + } +} + +static INLINE pstatus_t general_RGBToAVC444YUV_RGBX( + const BYTE* pSrc, UINT32 srcStep, + BYTE* pDst1[3], const UINT32 dst1Step[3], + BYTE* pDst2[3], const UINT32 dst2Step[3], + const prim_size_t* roi) +{ + /** + * Note: + * Read information in function general_RGBToAVC444YUV_ANY below ! + */ + UINT32 y; + const BYTE* pMaxSrc = pSrc + (roi->height - 1) * srcStep; + + for (y = 0; y < roi->height; y += 2) + { + const BOOL last = (y >= (roi->height - 1)); + const BYTE* srcEven = y < roi->height ? pSrc + y * srcStep : pMaxSrc; + const BYTE* srcOdd = !last ? pSrc + (y + 1) * srcStep : pMaxSrc; + const UINT32 i = y >> 1; + const UINT32 n = (i & ~7) + i; + BYTE* b1Even = pDst1[0] + y * dst1Step[0]; + BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : NULL; + BYTE* b2 = pDst1[1] + (y / 2) * dst1Step[1]; + BYTE* b3 = pDst1[2] + (y / 2) * dst1Step[2]; + BYTE* b4 = pDst2[0] + dst2Step[0] * n; + BYTE* b5 = b4 + 8 * dst2Step[0]; + BYTE* b6 = pDst2[1] + (y / 2) * dst2Step[1]; + BYTE* b7 = pDst2[2] + (y / 2) * dst2Step[2]; + general_RGBToAVC444YUV_RGBX_DOUBLE_ROW(srcEven, srcOdd, b1Even, b1Odd, b2, b3, b4, b5, b6, b7, + roi->width); + } + + return PRIMITIVES_SUCCESS; +} + +static INLINE void general_RGBToAVC444YUV_ANY_DOUBLE_ROW( + const BYTE* srcEven, const BYTE* srcOdd, UINT32 srcFormat, + BYTE* b1Even, BYTE* b1Odd, BYTE* b2, + BYTE* b3, BYTE* b4, BYTE* b5, BYTE* b6, BYTE* b7, UINT32 width) +{ + const UINT32 bpp = GetBytesPerPixel(srcFormat); + UINT32 x; + + for (x = 0; x < width; x += 2) + { + const BOOL lastX = (x + 1) >= width; + BYTE Y1e, Y2e, U1e, V1e, U2e, V2e; + BYTE Y1o, Y2o, U1o, V1o, U2o, V2o; + /* Read 4 pixels, 2 from even, 2 from odd lines */ + { + BYTE r, g, b; + const UINT32 color = ReadColor(srcEven, srcFormat); + srcEven += bpp; + SplitColor(color, srcFormat, &r, &g, &b, NULL, NULL); + Y1e = Y2e = Y1o = Y2o = RGB2Y(r, g, b); + U1e = U2e = U1o = U2o = RGB2U(r, g, b); + V1e = V2e = V1o = V2o = RGB2V(r, g, b); + } + + if (!lastX) + { + BYTE r, g, b; + const UINT32 color = ReadColor(srcEven, srcFormat); + srcEven += bpp; + SplitColor(color, srcFormat, &r, &g, &b, NULL, NULL); + Y2e = RGB2Y(r, g, b); + U2e = RGB2U(r, g, b); + V2e = RGB2V(r, g, b); + } + + if (b1Odd) + { + BYTE r, g, b; + const UINT32 color = ReadColor(srcOdd, srcFormat); + srcOdd += bpp; + SplitColor(color, srcFormat, &r, &g, &b, NULL, NULL); + Y1o = Y2o = RGB2Y(r, g, b); + U1o = U2o = RGB2U(r, g, b); + V1o = V2o = RGB2V(r, g, b); + } + + if (b1Odd && !lastX) + { + BYTE r, g, b; + const UINT32 color = ReadColor(srcOdd, srcFormat); + srcOdd += bpp; + SplitColor(color, srcFormat, &r, &g, &b, NULL, NULL); + Y2o = RGB2Y(r, g, b); + U2o = RGB2U(r, g, b); + V2o = RGB2V(r, g, b); + } + + /* We have 4 Y pixels, so store them. */ + *b1Even++ = Y1e; + *b1Even++ = Y2e; + + if (b1Odd) + { + *b1Odd++ = Y1o; + *b1Odd++ = Y2o; + } + + /* 2x 2y pixel in luma UV plane use averaging + */ + { + const BYTE Uavg = ((UINT16)U1e + (UINT16)U2e + (UINT16)U1o + (UINT16)U2o) / 4; + const BYTE Vavg = ((UINT16)V1e + (UINT16)V2e + (UINT16)V1o + (UINT16)V2o) / 4; + *b2++ = Uavg; + *b3++ = Vavg; + } + + /* UV from 2x, 2y+1 */ + if (b1Odd) + { + *b4++ = U1o; + *b5++ = V1o; + + if (!lastX) + { + *b4++ = U2o; + *b5++ = V2o; + } + } + + /* UV from 2x+1, 2y */ + if (!lastX) + { + *b6++ = U2e; + *b7++ = V2e; + } + } +} + static INLINE pstatus_t general_RGBToAVC444YUV_ANY( const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep, BYTE* pDst1[3], const UINT32 dst1Step[3], @@ -962,73 +1311,27 @@ static INLINE pstatus_t general_RGBToAVC444YUV_ANY( * } * */ - const UINT32 bpp = GetBytesPerPixel(srcFormat); - UINT32 x, y, n, numRows, numCols; - BOOL evenRow = TRUE; - BYTE* b1, *b2, *b3, *b4, *b5, *b6, *b7; + UINT32 y; const BYTE* pMaxSrc = pSrc + (roi->height - 1) * srcStep; - numRows = (roi->height + 1) & ~1; - numCols = (roi->width + 1) & ~1; - for (y = 0; y < numRows; y++, evenRow = !evenRow) + for (y = 0; y < roi->height; y += 2) { - const BYTE* src = y < roi->height ? pSrc + y * srcStep : pMaxSrc; - UINT32 i = y >> 1; - b1 = pDst1[0] + y * dst1Step[0]; - - if (evenRow) - { - b2 = pDst1[1] + i * dst1Step[1]; - b3 = pDst1[2] + i * dst1Step[2]; - b6 = pDst2[1] + i * dst2Step[1]; - b7 = pDst2[2] + i * dst2Step[2]; - } - else - { - n = (i & ~7) + i; - b4 = pDst2[0] + dst2Step[0] * n; - b5 = b4 + 8 * dst2Step[0]; - } - - for (x = 0; x < numCols; x += 2) - { - BYTE R, G, B, Y1, Y2, U1, U2, V1, V2; - UINT32 color; - color = ReadColor(src, srcFormat); - SplitColor(color, srcFormat, &R, &G, &B, NULL, NULL); - Y1 = Y2 = RGB2Y(R, G, B); - U1 = U2 = RGB2U(R, G, B); - V1 = V2 = RGB2V(R, G, B); - - if (x + 1 < roi->width) - { - color = ReadColor(src + bpp, srcFormat); - SplitColor(color, srcFormat, &R, &G, &B, NULL, NULL); - Y2 = RGB2Y(R, G, B); - U2 = RGB2U(R, G, B); - V2 = RGB2V(R, G, B); - } - - *b1++ = Y1; - *b1++ = Y2; - - if (evenRow) - { - *b2++ = U1; - *b3++ = V1; - *b6++ = U2; - *b7++ = V2; - } - else - { - *b4++ = U1; - *b4++ = U2; - *b5++ = V1; - *b5++ = V2; - } - - src += 2 * bpp; - } + const BOOL last = (y >= (roi->height - 1)); + const BYTE* srcEven = y < roi->height ? pSrc + y * srcStep : pMaxSrc; + const BYTE* srcOdd = !last ? pSrc + (y + 1) * srcStep : pMaxSrc; + const UINT32 i = y >> 1; + const UINT32 n = (i & ~7) + i; + BYTE* b1Even = pDst1[0] + y * dst1Step[0]; + BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : NULL; + BYTE* b2 = pDst1[1] + (y / 2) * dst1Step[1]; + BYTE* b3 = pDst1[2] + (y / 2) * dst1Step[2]; + BYTE* b4 = pDst2[0] + dst2Step[0] * n; + BYTE* b5 = b4 + 8 * dst2Step[0]; + BYTE* b6 = pDst2[1] + (y / 2) * dst2Step[1]; + BYTE* b7 = pDst2[2] + (y / 2) * dst2Step[2]; + general_RGBToAVC444YUV_ANY_DOUBLE_ROW(srcEven, srcOdd, srcFormat, + b1Even, b1Odd, b2, b3, b4, b5, b6, b7, + roi->width); } return PRIMITIVES_SUCCESS; @@ -1044,7 +1347,11 @@ static INLINE pstatus_t general_RGBToAVC444YUV( { case PIXEL_FORMAT_BGRA32: case PIXEL_FORMAT_BGRX32: - return general_RGBToAVC444YUV_BGRX(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi); + return general_RGBToAVC444YUV_BGRX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi); + + case PIXEL_FORMAT_RGBA32: + case PIXEL_FORMAT_RGBX32: + return general_RGBToAVC444YUV_RGBX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi); default: return general_RGBToAVC444YUV_ANY(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi); @@ -1053,6 +1360,408 @@ static INLINE pstatus_t general_RGBToAVC444YUV( return !PRIMITIVES_SUCCESS; } +static INLINE void general_RGBToAVC444YUVv2_ANY_DOUBLE_ROW( + const BYTE* srcEven, const BYTE* srcOdd, UINT32 srcFormat, + BYTE* yLumaDstEven, BYTE* yLumaDstOdd, + BYTE* uLumaDst, BYTE* vLumaDst, + BYTE* yEvenChromaDst1, BYTE* yEvenChromaDst2, + BYTE* yOddChromaDst1, BYTE* yOddChromaDst2, + BYTE* uChromaDst1, BYTE* uChromaDst2, + BYTE* vChromaDst1, BYTE* vChromaDst2, + UINT32 width) +{ + UINT32 x; + const UINT32 bpp = GetBytesPerPixel(srcFormat); + + for (x = 0; x < width; x += 2) + { + BYTE Ya, Ua, Va; + BYTE Yb, Ub, Vb; + BYTE Yc, Uc, Vc; + BYTE Yd, Ud, Vd; + { + BYTE b, g, r; + const UINT32 color = ReadColor(srcEven, srcFormat); + srcEven += bpp; + SplitColor(color, srcFormat, &r, &g, &b, NULL, NULL); + Ya = RGB2Y(r, g, b); + Ua = RGB2U(r, g, b); + Va = RGB2V(r, g, b); + } + + if (x < width - 1) + { + BYTE b, g, r; + const UINT32 color = ReadColor(srcEven, srcFormat); + srcEven += bpp; + SplitColor(color, srcFormat, &r, &g, &b, NULL, NULL); + Yb = RGB2Y(r, g, b); + Ub = RGB2U(r, g, b); + Vb = RGB2V(r, g, b); + } + else + { + Yb = Ya; + Ub = Ua; + Vb = Va; + } + + if (srcOdd) + { + BYTE b, g, r; + const UINT32 color = ReadColor(srcOdd, srcFormat); + srcOdd += bpp; + SplitColor(color, srcFormat, &r, &g, &b, NULL, NULL); + Yc = RGB2Y(r, g, b); + Uc = RGB2U(r, g, b); + Vc = RGB2V(r, g, b); + } + else + { + Yc = Ya; + Uc = Ua; + Vc = Va; + } + + if (srcOdd && (x < width - 1)) + { + BYTE b, g, r; + const UINT32 color = ReadColor(srcOdd, srcFormat); + srcOdd += bpp; + SplitColor(color, srcFormat, &r, &g, &b, NULL, NULL); + Yd = RGB2Y(r, g, b); + Ud = RGB2U(r, g, b); + Vd = RGB2V(r, g, b); + } + else + { + Yd = Ya; + Ud = Ua; + Vd = Va; + } + + /* Y [b1] */ + *yLumaDstEven++ = Ya; + + if (x < width - 1) + *yLumaDstEven++ = Yb; + + if (srcOdd) + *yLumaDstOdd++ = Yc; + + if (srcOdd && (x < width - 1)) + *yLumaDstOdd++ = Yd; + + /* 2x 2y [b2,b3] */ + *uLumaDst++ = (Ua + Ub + Uc + Ud) / 4; + *vLumaDst++ = (Va + Vb + Vc + Vd) / 4; + + /* 2x+1, y [b4,b5] even */ + if (x < width - 1) + { + *yEvenChromaDst1++ = Ub; + *yEvenChromaDst2++ = Vb; + } + + if (srcOdd) + { + /* 2x+1, y [b4,b5] odd */ + if (x < width - 1) + { + *yOddChromaDst1++ = Ud; + *yOddChromaDst2++ = Vd; + } + + /* 4x 2y+1 [b6, b7] */ + if (x % 4 == 0) + { + *uChromaDst1++ = Uc; + *uChromaDst2++ = Vc; + } + /* 4x+2 2y+1 [b8, b9] */ + else + { + *vChromaDst1++ = Uc; + *vChromaDst2++ = Vc; + } + } + } +} + +static INLINE pstatus_t general_RGBToAVC444YUVv2_ANY( + const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep, + BYTE* pDst1[3], const UINT32 dst1Step[3], + BYTE* pDst2[3], const UINT32 dst2Step[3], + const prim_size_t* roi) +{ + /** + * Note: According to [MS-RDPEGFX 2.2.4.4 RFX_AVC420_BITMAP_STREAM] the + * width and height of the MPEG-4 AVC/H.264 codec bitstream MUST be aligned + * to a multiple of 16. + * Hence the passed destination YUV420/CHROMA420 buffers must have been + * allocated accordingly !! + */ + /** + * [MS-RDPEGFX 3.3.8.3.3 YUV420p Stream Combination for YUV444v2 mode] defines the following "Bx areas": + * + * YUV420 frame (main view): + * B1: From Y444 all pixels + * B2: From U444 all pixels in even rows with even rows and columns + * B3: From V444 all pixels in even rows with even rows and columns + * + * Chroma420 frame (auxillary view): + * B45: From U444 and V444 all pixels from all odd columns + * B67: From U444 and V444 every 4th pixel in odd rows + * B89: From U444 and V444 every 4th pixel (initial offset of 2) in odd rows + * + * Chroma Bxy areas correspond to the left and right half of the YUV420 plane. + * for (y = 0; y < fullHeight; y++) + * { + * for (x = 0; x < fullWidth; x++) + * { + * B1[x,y] = Y444[x,y]; + * } + * + * for (x = 0; x < halfWidth; x++) + * { + * B4[x,y] = U444[2 * x, 2 * y]; + * B5[x,y] = V444[2 * x, 2 * y]; + * } + * } + * + * for (y = 0; y < halfHeight; y++) + * { + * for (x = 0; x < halfWidth; x++) + * { + * B2[x,y] = U444[2 * x, 2 * y]; + * B3[x,y] = V444[2 * x, 2 * y]; + * B6[x,y] = U444[4 * x, 2 * y + 1]; + * B7[x,y] = V444[4 * x, 2 * y + 1]; + * B8[x,y] = V444[4 * x + 2, 2 * y + 1]; + * B9[x,y] = V444[4 * x + 2, 2 * y] + 1; + * } + * } + * + */ + UINT32 y; + + if (roi->height < 1 || roi->width < 1) + return !PRIMITIVES_SUCCESS; + + for (y = 0; y < roi->height; y += 2) + { + const BYTE* srcEven = (pSrc + y * srcStep); + const BYTE* srcOdd = (y < roi->height - 1) ? (srcEven + srcStep) : NULL; + BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]); + BYTE* dstLumaYOdd = (dstLumaYEven + dst1Step[0]); + BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]); + BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]); + BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]); + BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2; + BYTE* dstOddChromaY1 = dstEvenChromaY1 + dst2Step[0]; + BYTE* dstOddChromaY2 = dstEvenChromaY2 + dst2Step[0]; + BYTE* dstChromaU1 = (pDst2[1] + (y / 2) * dst2Step[1]); + BYTE* dstChromaV1 = (pDst2[2] + (y / 2) * dst2Step[2]); + BYTE* dstChromaU2 = dstChromaU1 + roi->width / 4; + BYTE* dstChromaV2 = dstChromaV1 + roi->width / 4; + general_RGBToAVC444YUVv2_ANY_DOUBLE_ROW(srcEven, srcOdd, srcFormat, dstLumaYEven, + dstLumaYOdd, dstLumaU, dstLumaV, + dstEvenChromaY1, dstEvenChromaY2, + dstOddChromaY1, dstOddChromaY2, + dstChromaU1, dstChromaU2, + dstChromaV1, dstChromaV2, + roi->width); + } + + return PRIMITIVES_SUCCESS; +} + +static INLINE void general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW( + const BYTE* srcEven, const BYTE* srcOdd, + BYTE* yLumaDstEven, BYTE* yLumaDstOdd, + BYTE* uLumaDst, BYTE* vLumaDst, + BYTE* yEvenChromaDst1, BYTE* yEvenChromaDst2, + BYTE* yOddChromaDst1, BYTE* yOddChromaDst2, + BYTE* uChromaDst1, BYTE* uChromaDst2, + BYTE* vChromaDst1, BYTE* vChromaDst2, + UINT32 width) +{ + UINT32 x; + + for (x = 0; x < width; x += 2) + { + BYTE Ya, Ua, Va; + BYTE Yb, Ub, Vb; + BYTE Yc, Uc, Vc; + BYTE Yd, Ud, Vd; + { + const BYTE b = *srcEven++; + const BYTE g = *srcEven++; + const BYTE r = *srcEven++; + srcEven++; + Ya = RGB2Y(r, g, b); + Ua = RGB2U(r, g, b); + Va = RGB2V(r, g, b); + } + + if (x < width - 1) + { + const BYTE b = *srcEven++; + const BYTE g = *srcEven++; + const BYTE r = *srcEven++; + srcEven++; + Yb = RGB2Y(r, g, b); + Ub = RGB2U(r, g, b); + Vb = RGB2V(r, g, b); + } + else + { + Yb = Ya; + Ub = Ua; + Vb = Va; + } + + if (srcOdd) + { + const BYTE b = *srcOdd++; + const BYTE g = *srcOdd++; + const BYTE r = *srcOdd++; + srcOdd++; + Yc = RGB2Y(r, g, b); + Uc = RGB2U(r, g, b); + Vc = RGB2V(r, g, b); + } + else + { + Yc = Ya; + Uc = Ua; + Vc = Va; + } + + if (srcOdd && (x < width - 1)) + { + const BYTE b = *srcOdd++; + const BYTE g = *srcOdd++; + const BYTE r = *srcOdd++; + srcOdd++; + Yd = RGB2Y(r, g, b); + Ud = RGB2U(r, g, b); + Vd = RGB2V(r, g, b); + } + else + { + Yd = Ya; + Ud = Ua; + Vd = Va; + } + + /* Y [b1] */ + *yLumaDstEven++ = Ya; + + if (x < width - 1) + *yLumaDstEven++ = Yb; + + if (srcOdd) + *yLumaDstOdd++ = Yc; + + if (srcOdd && (x < width - 1)) + *yLumaDstOdd++ = Yd; + + /* 2x 2y [b2,b3] */ + *uLumaDst++ = (Ua + Ub + Uc + Ud) / 4; + *vLumaDst++ = (Va + Vb + Vc + Vd) / 4; + + /* 2x+1, y [b4,b5] even */ + if (x < width - 1) + { + *yEvenChromaDst1++ = Ub; + *yEvenChromaDst2++ = Vb; + } + + if (srcOdd) + { + /* 2x+1, y [b4,b5] odd */ + if (x < width - 1) + { + *yOddChromaDst1++ = Ud; + *yOddChromaDst2++ = Vd; + } + + /* 4x 2y+1 [b6, b7] */ + if (x % 4 == 0) + { + *uChromaDst1++ = Uc; + *uChromaDst2++ = Vc; + } + /* 4x+2 2y+1 [b8, b9] */ + else + { + *vChromaDst1++ = Uc; + *vChromaDst2++ = Vc; + } + } + } +} + +static INLINE pstatus_t general_RGBToAVC444YUVv2_BGRX( + const BYTE* pSrc, UINT32 srcStep, + BYTE* pDst1[3], const UINT32 dst1Step[3], + BYTE* pDst2[3], const UINT32 dst2Step[3], + const prim_size_t* roi) +{ + UINT32 y; + + if (roi->height < 1 || roi->width < 1) + return !PRIMITIVES_SUCCESS; + + for (y = 0; y < roi->height; y += 2) + { + const BYTE* srcEven = (pSrc + y * srcStep); + const BYTE* srcOdd = (y < roi->height - 1) ? (srcEven + srcStep) : NULL; + BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]); + BYTE* dstLumaYOdd = (dstLumaYEven + dst1Step[0]); + BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]); + BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]); + BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]); + BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2; + BYTE* dstOddChromaY1 = dstEvenChromaY1 + dst2Step[0]; + BYTE* dstOddChromaY2 = dstEvenChromaY2 + dst2Step[0]; + BYTE* dstChromaU1 = (pDst2[1] + (y / 2) * dst2Step[1]); + BYTE* dstChromaV1 = (pDst2[2] + (y / 2) * dst2Step[2]); + BYTE* dstChromaU2 = dstChromaU1 + roi->width / 4; + BYTE* dstChromaV2 = dstChromaV1 + roi->width / 4; + general_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(srcEven, srcOdd, dstLumaYEven, + dstLumaYOdd, dstLumaU, dstLumaV, + dstEvenChromaY1, dstEvenChromaY2, + dstOddChromaY1, dstOddChromaY2, + dstChromaU1, dstChromaU2, + dstChromaV1, dstChromaV2, + roi->width); + } + + return PRIMITIVES_SUCCESS; +} + +static INLINE pstatus_t general_RGBToAVC444YUVv2( + const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep, + BYTE* pDst1[3], const UINT32 dst1Step[3], + BYTE* pDst2[3], const UINT32 dst2Step[3], + const prim_size_t* roi) +{ + switch (srcFormat) + { + case PIXEL_FORMAT_BGRA32: + case PIXEL_FORMAT_BGRX32: + return general_RGBToAVC444YUVv2_BGRX(pSrc, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi); + + default: + return general_RGBToAVC444YUVv2_ANY(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2, dst2Step, + roi); + } + + return !PRIMITIVES_SUCCESS; +} + void primitives_init_YUV(primitives_t* prims) { prims->YUV420ToRGB_8u_P3AC4R = general_YUV420ToRGB_8u_P3AC4R; @@ -1062,5 +1771,6 @@ void primitives_init_YUV(primitives_t* prims) prims->YUV420CombineToYUV444 = general_YUV420CombineToYUV444; prims->YUV444SplitToYUV420 = general_YUV444SplitToYUV420; prims->RGBToAVC444YUV = general_RGBToAVC444YUV; + prims->RGBToAVC444YUVv2 = general_RGBToAVC444YUVv2; } diff --git a/libfreerdp/primitives/prim_YUV_neon.c b/libfreerdp/primitives/prim_YUV_neon.c new file mode 100644 index 0000000..885b856 --- /dev/null +++ b/libfreerdp/primitives/prim_YUV_neon.c @@ -0,0 +1,771 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Optimized YUV/RGB conversion operations + * + * Copyright 2014 Thomas Erbesdobler + * Copyright 2016-2017 Armin Novak <armin.novak@thincast.com> + * Copyright 2016-2017 Norbert Federa <norbert.federa@thincast.com> + * Copyright 2016-2017 Thincast Technologies GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <winpr/sysinfo.h> +#include <winpr/crt.h> +#include <freerdp/types.h> +#include <freerdp/primitives.h> + +#include "prim_internal.h" + +#if !defined(WITH_NEON) +#error "This file must only be included if WITH_NEON is active!" +#endif + +#include <arm_neon.h> + +static primitives_t* generic = NULL; + +static INLINE uint8x8_t neon_YUV2R(int32x4_t Ch, int32x4_t Cl, + int16x4_t Dh, int16x4_t Dl, + int16x4_t Eh, int16x4_t El) +{ + /* R = (256 * Y + 403 * (V - 128)) >> 8 */ + const int16x4_t c403 = vdup_n_s16(403); + const int32x4_t CEh = vmlal_s16(Ch, Eh, c403); + const int32x4_t CEl = vmlal_s16(Cl, El, c403); + const int32x4_t Rh = vrshrq_n_s32(CEh, 8); + const int32x4_t Rl = vrshrq_n_s32(CEl, 8); + const int16x8_t R = vcombine_s16(vqmovn_s32(Rl), vqmovn_s32(Rh)); + return vqmovun_s16(R); +} + +static INLINE uint8x8_t neon_YUV2G(int32x4_t Ch, int32x4_t Cl, + int16x4_t Dh, int16x4_t Dl, + int16x4_t Eh, int16x4_t El) +{ + /* G = (256L * Y - 48 * (U - 128) - 120 * (V - 128)) >> 8 */ + const int16x4_t c48 = vdup_n_s16(48); + const int16x4_t c120 = vdup_n_s16(120); + const int32x4_t CDh = vmlsl_s16(Ch, Dh, c48); + const int32x4_t CDl = vmlsl_s16(Cl, Dl, c48); + const int32x4_t CDEh = vmlsl_s16(CDh, Eh, c120); + const int32x4_t CDEl = vmlsl_s16(CDl, El, c120); + const int32x4_t Gh = vrshrq_n_s32(CDEh, 8); + const int32x4_t Gl = vrshrq_n_s32(CDEl, 8); + const int16x8_t G = vcombine_s16(vqmovn_s32(Gl), vqmovn_s32(Gh)); + return vqmovun_s16(G); +} + +static INLINE uint8x8_t neon_YUV2B(int32x4_t Ch, int32x4_t Cl, + int16x4_t Dh, int16x4_t Dl, + int16x4_t Eh, int16x4_t El) +{ + /* B = (256L * Y + 475 * (U - 128)) >> 8*/ + const int16x4_t c475 = vdup_n_s16(475); + const int32x4_t CDh = vmlal_s16(Ch, Dh, c475); + const int32x4_t CDl = vmlal_s16(Ch, Dl, c475); + const int32x4_t Bh = vrshrq_n_s32(CDh, 8); + const int32x4_t Bl = vrshrq_n_s32(CDl, 8); + const int16x8_t B = vcombine_s16(vqmovn_s32(Bl), vqmovn_s32(Bh)); + return vqmovun_s16(B); +} + +static INLINE BYTE* neon_YuvToRgbPixel(BYTE* pRGB, int16x8_t Y, int16x8_t D, int16x8_t E, + const uint8_t rPos, const uint8_t gPos, const uint8_t bPos, const uint8_t aPos) +{ + uint8x8x4_t bgrx; + const int32x4_t Ch = vmulq_n_s32(vmovl_s16(vget_high_s16(Y)), 256); /* Y * 256 */ + const int32x4_t Cl = vmulq_n_s32(vmovl_s16(vget_low_s16(Y)), 256); /* Y * 256 */ + const int16x4_t Dh = vget_high_s16(D); + const int16x4_t Dl = vget_low_s16(D); + const int16x4_t Eh = vget_high_s16(E); + const int16x4_t El = vget_low_s16(E); + { + /* B = (256L * Y + 475 * (U - 128)) >> 8*/ + const int16x4_t c475 = vdup_n_s16(475); + const int32x4_t CDh = vmlal_s16(Ch, Dh, c475); + const int32x4_t CDl = vmlal_s16(Cl, Dl, c475); + const int32x4_t Bh = vrshrq_n_s32(CDh, 8); + const int32x4_t Bl = vrshrq_n_s32(CDl, 8); + const int16x8_t B = vcombine_s16(vqmovn_s32(Bl), vqmovn_s32(Bh)); + bgrx.val[bPos] = vqmovun_s16(B); + } + { + /* G = (256L * Y - 48 * (U - 128) - 120 * (V - 128)) >> 8 */ + const int16x4_t c48 = vdup_n_s16(48); + const int16x4_t c120 = vdup_n_s16(120); + const int32x4_t CDh = vmlsl_s16(Ch, Dh, c48); + const int32x4_t CDl = vmlsl_s16(Cl, Dl, c48); + const int32x4_t CDEh = vmlsl_s16(CDh, Eh, c120); + const int32x4_t CDEl = vmlsl_s16(CDl, El, c120); + const int32x4_t Gh = vrshrq_n_s32(CDEh, 8); + const int32x4_t Gl = vrshrq_n_s32(CDEl, 8); + const int16x8_t G = vcombine_s16(vqmovn_s32(Gl), vqmovn_s32(Gh)); + bgrx.val[gPos] = vqmovun_s16(G); + } + { + /* R = (256 * Y + 403 * (V - 128)) >> 8 */ + const int16x4_t c403 = vdup_n_s16(403); + const int32x4_t CEh = vmlal_s16(Ch, Eh, c403); + const int32x4_t CEl = vmlal_s16(Cl, El, c403); + const int32x4_t Rh = vrshrq_n_s32(CEh, 8); + const int32x4_t Rl = vrshrq_n_s32(CEl, 8); + const int16x8_t R = vcombine_s16(vqmovn_s32(Rl), vqmovn_s32(Rh)); + bgrx.val[rPos] = vqmovun_s16(R); + } + { + /* A */ + bgrx.val[aPos] = vdup_n_u8(0xFF); + } + vst4_u8(pRGB, bgrx); + pRGB += 32; + return pRGB; +} + +static INLINE pstatus_t neon_YUV420ToX( + const BYTE* pSrc[3], const UINT32 srcStep[3], + BYTE* pDst, UINT32 dstStep, + const prim_size_t* roi, const uint8_t rPos, const uint8_t gPos, + const uint8_t bPos, const uint8_t aPos) +{ + UINT32 y; + const UINT32 nWidth = roi->width; + const UINT32 nHeight = roi->height; + const DWORD pad = nWidth % 16; + const UINT32 yPad = srcStep[0] - roi->width; + const UINT32 uPad = srcStep[1] - roi->width / 2; + const UINT32 vPad = srcStep[2] - roi->width / 2; + const UINT32 dPad = dstStep - roi->width * 4; + const int16x8_t c128 = vdupq_n_s16(128); + + for (y = 0; y < nHeight; y += 2) + { + const uint8_t* pY1 = pSrc[0] + y * srcStep[0]; + const uint8_t* pY2 = pY1 + srcStep[0]; + const uint8_t* pU = pSrc[1] + (y / 2) * srcStep[1]; + const uint8_t* pV = pSrc[2] + (y / 2) * srcStep[2]; + uint8_t* pRGB1 = pDst + y * dstStep; + uint8_t* pRGB2 = pRGB1 + dstStep; + UINT32 x; + const BOOL lastY = y >= nHeight - 1; + + for (x = 0; x < nWidth - pad;) + { + const uint8x8_t Uraw = vld1_u8(pU); + const uint8x8x2_t Uu = vzip_u8(Uraw, Uraw); + const int16x8_t U1 = vreinterpretq_s16_u16(vmovl_u8(Uu.val[0])); + const int16x8_t U2 = vreinterpretq_s16_u16(vmovl_u8(Uu.val[1])); + const uint8x8_t Vraw = vld1_u8(pV); + const uint8x8x2_t Vu = vzip_u8(Vraw, Vraw); + const int16x8_t V1 = vreinterpretq_s16_u16(vmovl_u8(Vu.val[0])); + const int16x8_t V2 = vreinterpretq_s16_u16(vmovl_u8(Vu.val[1])); + const int16x8_t D1 = vsubq_s16(U1, c128); + const int16x8_t E1 = vsubq_s16(V1, c128); + const int16x8_t D2 = vsubq_s16(U2, c128); + const int16x8_t E2 = vsubq_s16(V2, c128); + { + const uint8x8_t Y1u = vld1_u8(pY1); + const int16x8_t Y1 = vreinterpretq_s16_u16(vmovl_u8(Y1u)); + pRGB1 = neon_YuvToRgbPixel(pRGB1, Y1, D1, E1, rPos, gPos, bPos, aPos); + pY1 += 8; + x += 8; + } + { + const uint8x8_t Y1u = vld1_u8(pY1); + const int16x8_t Y1 = vreinterpretq_s16_u16(vmovl_u8(Y1u)); + pRGB1 = neon_YuvToRgbPixel(pRGB1, Y1, D2, E2, rPos, gPos, bPos, aPos); + pY1 += 8; + x += 8; + } + + if (!lastY) + { + { + const uint8x8_t Y2u = vld1_u8(pY2); + const int16x8_t Y2 = vreinterpretq_s16_u16(vmovl_u8(Y2u)); + pRGB2 = neon_YuvToRgbPixel(pRGB2, Y2, D1, E1, rPos, gPos, bPos, aPos); + pY2 += 8; + } + { + const uint8x8_t Y2u = vld1_u8(pY2); + const int16x8_t Y2 = vreinterpretq_s16_u16(vmovl_u8(Y2u)); + pRGB2 = neon_YuvToRgbPixel(pRGB2, Y2, D2, E2, rPos, gPos, bPos, aPos); + pY2 += 8; + } + } + + pU += 8; + pV += 8; + } + + for (; x < nWidth; x++) + { + const BYTE U = *pU; + const BYTE V = *pV; + { + const BYTE Y = *pY1++; + const BYTE r = YUV2R(Y, U, V); + const BYTE g = YUV2G(Y, U, V); + const BYTE b = YUV2B(Y, U, V); + pRGB1[aPos] = 0xFF; + pRGB1[rPos] = r; + pRGB1[gPos] = g; + pRGB1[bPos] = b; + pRGB1 += 4; + } + + if (!lastY) + { + const BYTE Y = *pY2++; + const BYTE r = YUV2R(Y, U, V); + const BYTE g = YUV2G(Y, U, V); + const BYTE b = YUV2B(Y, U, V); + pRGB2[aPos] = 0xFF; + pRGB2[rPos] = r; + pRGB2[gPos] = g; + pRGB2[bPos] = b; + pRGB2 += 4; + } + + if (x % 2) + { + pU++; + pV++; + } + } + + pRGB1 += dPad; + pRGB2 += dPad; + pY1 += yPad; + pY2 += yPad; + pU += uPad; + pV += vPad; + } + + return PRIMITIVES_SUCCESS; +} + +static pstatus_t neon_YUV420ToRGB_8u_P3AC4R( + const BYTE* pSrc[3], const UINT32 srcStep[3], + BYTE* pDst, UINT32 dstStep, UINT32 DstFormat, + const prim_size_t* roi) +{ + switch (DstFormat) + { + case PIXEL_FORMAT_BGRA32: + case PIXEL_FORMAT_BGRX32: + return neon_YUV420ToX(pSrc, srcStep, pDst, dstStep, roi, 2, 1, 0, 3); + + case PIXEL_FORMAT_RGBA32: + case PIXEL_FORMAT_RGBX32: + return neon_YUV420ToX(pSrc, srcStep, pDst, dstStep, roi, 0, 1, 2, 3); + + case PIXEL_FORMAT_ARGB32: + case PIXEL_FORMAT_XRGB32: + return neon_YUV420ToX(pSrc, srcStep, pDst, dstStep, roi, 1, 2, 3, 0); + + case PIXEL_FORMAT_ABGR32: + case PIXEL_FORMAT_XBGR32: + return neon_YUV420ToX(pSrc, srcStep, pDst, dstStep, roi, 3, 2, 1, 0); + + default: + return generic->YUV420ToRGB_8u_P3AC4R(pSrc, srcStep, pDst, dstStep, DstFormat, roi); + } +} + +static INLINE pstatus_t neon_YUV444ToX( + const BYTE* pSrc[3], const UINT32 srcStep[3], + BYTE* pDst, UINT32 dstStep, + const prim_size_t* roi, const uint8_t rPos, const uint8_t gPos, + const uint8_t bPos, const uint8_t aPos) +{ + UINT32 y; + const UINT32 nWidth = roi->width; + const UINT32 nHeight = roi->height; + const UINT32 yPad = srcStep[0] - roi->width; + const UINT32 uPad = srcStep[1] - roi->width; + const UINT32 vPad = srcStep[2] - roi->width; + const UINT32 dPad = dstStep - roi->width * 4; + const uint8_t* pY = pSrc[0]; + const uint8_t* pU = pSrc[1]; + const uint8_t* pV = pSrc[2]; + uint8_t* pRGB = pDst; + const int16x8_t c128 = vdupq_n_s16(128); + const DWORD pad = nWidth % 8; + + for (y = 0; y < nHeight; y++) + { + UINT32 x; + + for (x = 0; x < nWidth - pad; x += 8) + { + const uint8x8_t Yu = vld1_u8(pY); + const int16x8_t Y = vreinterpretq_s16_u16(vmovl_u8(Yu)); + const uint8x8_t Uu = vld1_u8(pU); + const int16x8_t U = vreinterpretq_s16_u16(vmovl_u8(Uu)); + const uint8x8_t Vu = vld1_u8(pV); + const int16x8_t V = vreinterpretq_s16_u16(vmovl_u8(Vu)); + /* Do the calculations on Y in 32bit width, the result of 255 * 256 does not fit + * a signed 16 bit value. */ + const int16x8_t D = vsubq_s16(U, c128); + const int16x8_t E = vsubq_s16(V, c128); + pRGB = neon_YuvToRgbPixel(pRGB, Y, D, E, rPos, gPos, bPos, aPos); + pY += 8; + pU += 8; + pV += 8; + } + + for (x = 0; x < pad; x++) + { + const BYTE Y = *pY++; + const BYTE U = *pU++; + const BYTE V = *pV++; + const BYTE r = YUV2R(Y, U, V); + const BYTE g = YUV2G(Y, U, V); + const BYTE b = YUV2B(Y, U, V); + pRGB[aPos] = 0xFF; + pRGB[rPos] = r; + pRGB[gPos] = g; + pRGB[bPos] = b; + pRGB += 4; + } + + pRGB += dPad; + pY += yPad; + pU += uPad; + pV += vPad; + } + + return PRIMITIVES_SUCCESS; +} + +static pstatus_t neon_YUV444ToRGB_8u_P3AC4R( + const BYTE* pSrc[3], const UINT32 srcStep[3], + BYTE* pDst, UINT32 dstStep, UINT32 DstFormat, + const prim_size_t* roi) +{ + switch (DstFormat) + { + case PIXEL_FORMAT_BGRA32: + case PIXEL_FORMAT_BGRX32: + return neon_YUV444ToX(pSrc, srcStep, pDst, dstStep, roi, 2, 1, 0, 3); + + case PIXEL_FORMAT_RGBA32: + case PIXEL_FORMAT_RGBX32: + return neon_YUV444ToX(pSrc, srcStep, pDst, dstStep, roi, 0, 1, 2, 3); + + case PIXEL_FORMAT_ARGB32: + case PIXEL_FORMAT_XRGB32: + return neon_YUV444ToX(pSrc, srcStep, pDst, dstStep, roi, 1, 2, 3, 0); + + case PIXEL_FORMAT_ABGR32: + case PIXEL_FORMAT_XBGR32: + return neon_YUV444ToX(pSrc, srcStep, pDst, dstStep, roi, 3, 2, 1, 0); + + default: + return generic->YUV444ToRGB_8u_P3AC4R(pSrc, srcStep, pDst, dstStep, DstFormat, roi); + } +} + +static pstatus_t neon_LumaToYUV444(const BYTE* pSrcRaw[3], const UINT32 srcStep[3], + BYTE* pDstRaw[3], const UINT32 dstStep[3], + const RECTANGLE_16* roi) +{ + UINT32 x, y; + const UINT32 nWidth = roi->right - roi->left; + const UINT32 nHeight = roi->bottom - roi->top; + const UINT32 halfWidth = (nWidth + 1) / 2; + const UINT32 halfHeight = (nHeight + 1) / 2; + const UINT32 evenY = 0; + const BYTE* pSrc[3] = + { + pSrcRaw[0] + roi->top* srcStep[0] + roi->left, + pSrcRaw[1] + roi->top / 2 * srcStep[1] + roi->left / 2, + pSrcRaw[2] + roi->top / 2 * srcStep[2] + roi->left / 2 + }; + BYTE* pDst[3] = + { + pDstRaw[0] + roi->top* dstStep[0] + roi->left, + pDstRaw[1] + roi->top* dstStep[1] + roi->left, + pDstRaw[2] + roi->top* dstStep[2] + roi->left + }; + + /* Y data is already here... */ + /* B1 */ + for (y = 0; y < nHeight; y++) + { + const BYTE* Ym = pSrc[0] + srcStep[0] * y; + BYTE* pY = pDst[0] + dstStep[0] * y; + memcpy(pY, Ym, nWidth); + } + + /* The first half of U, V are already here part of this frame. */ + /* B2 and B3 */ + for (y = 0; y < halfHeight; y++) + { + const UINT32 val2y = (2 * y + evenY); + const BYTE* Um = pSrc[1] + srcStep[1] * y; + const BYTE* Vm = pSrc[2] + srcStep[2] * y; + BYTE* pU = pDst[1] + dstStep[1] * val2y; + BYTE* pV = pDst[2] + dstStep[2] * val2y; + BYTE* pU1 = pU + dstStep[1]; + BYTE* pV1 = pV + dstStep[2]; + + for (x = 0; x + 16 < halfWidth; x += 16) + { + { + const uint8x16_t u = vld1q_u8(Um); + uint8x16x2_t u2x; + u2x.val[0] = u; + u2x.val[1] = u; + vst2q_u8(pU, u2x); + vst2q_u8(pU1, u2x); + Um += 16; + pU += 32; + pU1 += 32; + } + { + const uint8x16_t v = vld1q_u8(Vm); + uint8x16x2_t v2x; + v2x.val[0] = v; + v2x.val[1] = v; + vst2q_u8(pV, v2x); + vst2q_u8(pV1, v2x); + Vm += 16; + pV += 32; + pV1 += 32; + } + } + + for (; x < halfWidth; x++) + { + const BYTE u = *Um++; + const BYTE v = *Vm++; + *pU++ = u; + *pU++ = u; + *pU1++ = u; + *pU1++ = u; + *pV++ = v; + *pV++ = v; + *pV1++ = v; + *pV1++ = v; + } + } + + return PRIMITIVES_SUCCESS; +} + +static pstatus_t neon_ChromaFilter(BYTE* pDst[3], const UINT32 dstStep[3], + const RECTANGLE_16* roi) +{ + const UINT32 oddY = 1; + const UINT32 evenY = 0; + const UINT32 nWidth = roi->right - roi->left; + const UINT32 nHeight = roi->bottom - roi->top; + const UINT32 halfHeight = (nHeight + 1) / 2; + const UINT32 halfWidth = (nWidth + 1) / 2; + const UINT32 halfPad = halfWidth % 16; + UINT32 x, y; + + /* Filter */ + for (y = roi->top; y < halfHeight + roi->top; y++) + { + const UINT32 val2y = (y * 2 + evenY); + const UINT32 val2y1 = val2y + oddY; + BYTE* pU1 = pDst[1] + dstStep[1] * val2y1; + BYTE* pV1 = pDst[2] + dstStep[2] * val2y1; + BYTE* pU = pDst[1] + dstStep[1] * val2y; + BYTE* pV = pDst[2] + dstStep[2] * val2y; + + if (val2y1 > nHeight) + continue; + + for (x = roi->left / 2; x < halfWidth + roi->left / 2 - halfPad; x += 16) + { + { + /* U = (U2x,2y << 2) - U2x1,2y - U2x,2y1 - U2x1,2y1 */ + uint8x8x2_t u = vld2_u8(&pU[2 * x]); + const int16x8_t up = vreinterpretq_s16_u16(vshll_n_u8(u.val[0], 2)); /* Ux2,2y << 2 */ + const uint8x8x2_t u1 = vld2_u8(&pU1[2 * x]); + const uint16x8_t usub = vaddl_u8(u1.val[1], u1.val[0]); /* U2x,2y1 + U2x1,2y1 */ + const int16x8_t us = vreinterpretq_s16_u16(vaddw_u8(usub, + u.val[1])); /* U2x1,2y + U2x,2y1 + U2x1,2y1 */ + const int16x8_t un = vsubq_s16(up, us); + const uint8x8_t u8 = vqmovun_s16(un); /* CLIP(un) */ + u.val[0] = u8; + vst2_u8(&pU[2 * x], u); + } + { + /* V = (V2x,2y << 2) - V2x1,2y - V2x,2y1 - V2x1,2y1 */ + uint8x8x2_t v = vld2_u8(&pV[2 * x]); + const int16x8_t vp = vreinterpretq_s16_u16(vshll_n_u8(v.val[0], 2)); /* Vx2,2y << 2 */ + const uint8x8x2_t v1 = vld2_u8(&pV1[2 * x]); + const uint16x8_t vsub = vaddl_u8(v1.val[1], v1.val[0]); /* V2x,2y1 + V2x1,2y1 */ + const int16x8_t vs = vreinterpretq_s16_u16(vaddw_u8(vsub, + v.val[1])); /* V2x1,2y + V2x,2y1 + V2x1,2y1 */ + const int16x8_t vn = vsubq_s16(vp, vs); + const uint8x8_t v8 = vqmovun_s16(vn); /* CLIP(vn) */ + v.val[0] = v8; + vst2_u8(&pV[2 * x], v); + } + } + + for (; x < halfWidth + roi->left / 2; x++) + { + const UINT32 val2x = (x * 2); + const UINT32 val2x1 = val2x + 1; + const INT32 up = pU[val2x] * 4; + const INT32 vp = pV[val2x] * 4; + INT32 u2020; + INT32 v2020; + + if (val2x1 > nWidth) + continue; + + u2020 = up - pU[val2x1] - pU1[val2x] - pU1[val2x1]; + v2020 = vp - pV[val2x1] - pV1[val2x] - pV1[val2x1]; + pU[val2x] = CLIP(u2020); + pV[val2x] = CLIP(v2020); + } + } + + return PRIMITIVES_SUCCESS; +} + +static pstatus_t neon_ChromaV1ToYUV444(const BYTE* pSrcRaw[3], const UINT32 srcStep[3], + BYTE* pDstRaw[3], const UINT32 dstStep[3], + const RECTANGLE_16* roi) +{ + const UINT32 mod = 16; + UINT32 uY = 0; + UINT32 vY = 0; + UINT32 x, y; + const UINT32 nWidth = roi->right - roi->left; + const UINT32 nHeight = roi->bottom - roi->top; + const UINT32 halfWidth = (nWidth) / 2; + const UINT32 halfHeight = (nHeight) / 2; + const UINT32 oddY = 1; + const UINT32 evenY = 0; + const UINT32 oddX = 1; + /* The auxilary frame is aligned to multiples of 16x16. + * We need the padded height for B4 and B5 conversion. */ + const UINT32 padHeigth = nHeight + 16 - nHeight % 16; + const UINT32 halfPad = halfWidth % 16; + const BYTE* pSrc[3] = + { + pSrcRaw[0] + roi->top* srcStep[0] + roi->left, + pSrcRaw[1] + roi->top / 2 * srcStep[1] + roi->left / 2, + pSrcRaw[2] + roi->top / 2 * srcStep[2] + roi->left / 2 + }; + BYTE* pDst[3] = + { + pDstRaw[0] + roi->top* dstStep[0] + roi->left, + pDstRaw[1] + roi->top* dstStep[1] + roi->left, + pDstRaw[2] + roi->top* dstStep[2] + roi->left + }; + + /* The second half of U and V is a bit more tricky... */ + /* B4 and B5 */ + for (y = 0; y < padHeigth; y++) + { + const BYTE* Ya = pSrc[0] + srcStep[0] * y; + BYTE* pX; + + if ((y) % mod < (mod + 1) / 2) + { + const UINT32 pos = (2 * uY++ + oddY); + + if (pos >= nHeight) + continue; + + pX = pDst[1] + dstStep[1] * pos; + } + else + { + const UINT32 pos = (2 * vY++ + oddY); + + if (pos >= nHeight) + continue; + + pX = pDst[2] + dstStep[2] * pos; + } + + memcpy(pX, Ya, nWidth); + } + + /* B6 and B7 */ + for (y = 0; y < halfHeight; y++) + { + const UINT32 val2y = (y * 2 + evenY); + const BYTE* Ua = pSrc[1] + srcStep[1] * y; + const BYTE* Va = pSrc[2] + srcStep[2] * y; + BYTE* pU = pDst[1] + dstStep[1] * val2y; + BYTE* pV = pDst[2] + dstStep[2] * val2y; + + for (x = 0; x < halfWidth - halfPad; x += 16) + { + { + uint8x16x2_t u = vld2q_u8(&pU[2 * x]); + u.val[1] = vld1q_u8(&Ua[x]); + vst2q_u8(&pU[2 * x], u); + } + { + uint8x16x2_t v = vld2q_u8(&pV[2 * x]); + v.val[1] = vld1q_u8(&Va[x]); + vst2q_u8(&pV[2 * x], v); + } + } + + for (; x < halfWidth; x++) + { + const UINT32 val2x1 = (x * 2 + oddX); + pU[val2x1] = Ua[x]; + pV[val2x1] = Va[x]; + } + } + + /* Filter */ + return neon_ChromaFilter(pDst, dstStep, roi); +} + +static pstatus_t neon_ChromaV2ToYUV444(const BYTE* pSrc[3], const UINT32 srcStep[3], + UINT32 nTotalWidth, UINT32 nTotalHeight, + BYTE* pDst[3], const UINT32 dstStep[3], + const RECTANGLE_16* roi) +{ + UINT32 x, y; + const UINT32 nWidth = roi->right - roi->left; + const UINT32 nHeight = roi->bottom - roi->top; + const UINT32 halfWidth = (nWidth + 1) / 2; + const UINT32 halfPad = halfWidth % 16; + const UINT32 halfHeight = (nHeight + 1) / 2; + const UINT32 quaterWidth = (nWidth + 3) / 4; + const UINT32 quaterPad = quaterWidth % 16; + + /* B4 and B5: odd UV values for width/2, height */ + for (y = 0; y < nHeight; y++) + { + const UINT32 yTop = y + roi->top; + const BYTE* pYaU = pSrc[0] + srcStep[0] * yTop + roi->left / 2; + const BYTE* pYaV = pYaU + nTotalWidth / 2; + BYTE* pU = pDst[1] + dstStep[1] * yTop + roi->left; + BYTE* pV = pDst[2] + dstStep[2] * yTop + roi->left; + + for (x = 0; x < halfWidth - halfPad; x += 16) + { + { + uint8x16x2_t u = vld2q_u8(&pU[2 * x]); + u.val[1] = vld1q_u8(&pYaU[x]); + vst2q_u8(&pU[2 * x], u); + } + { + uint8x16x2_t v = vld2q_u8(&pV[2 * x]); + v.val[1] = vld1q_u8(&pYaV[x]); + vst2q_u8(&pV[2 * x], v); + } + } + + for (; x < halfWidth; x++) + { + const UINT32 odd = 2 * x + 1; + pU[odd] = pYaU[x]; + pV[odd] = pYaV[x]; + } + } + + /* B6 - B9 */ + for (y = 0; y < halfHeight; y++) + { + const BYTE* pUaU = pSrc[1] + srcStep[1] * (y + roi->top / 2) + roi->left / 4; + const BYTE* pUaV = pUaU + nTotalWidth / 4; + const BYTE* pVaU = pSrc[2] + srcStep[2] * (y + roi->top / 2) + roi->left / 4; + const BYTE* pVaV = pVaU + nTotalWidth / 4; + BYTE* pU = pDst[1] + dstStep[1] * (2 * y + 1 + roi->top) + roi->left; + BYTE* pV = pDst[2] + dstStep[2] * (2 * y + 1 + roi->top) + roi->left; + + for (x = 0; x < quaterWidth - quaterPad; x += 16) + { + { + uint8x16x4_t u = vld4q_u8(&pU[4 * x]); + u.val[0] = vld1q_u8(&pUaU[x]); + u.val[2] = vld1q_u8(&pVaU[x]); + vst4q_u8(&pU[4 * x], u); + } + { + uint8x16x4_t v = vld4q_u8(&pV[4 * x]); + v.val[0] = vld1q_u8(&pUaV[x]); + v.val[2] = vld1q_u8(&pVaV[x]); + vst4q_u8(&pV[4 * x], v); + } + } + + for (; x < quaterWidth; x++) + { + pU[4 * x + 0] = pUaU[x]; + pV[4 * x + 0] = pUaV[x]; + pU[4 * x + 2] = pVaU[x]; + pV[4 * x + 2] = pVaV[x]; + } + } + + return neon_ChromaFilter(pDst, dstStep, roi); +} + +static pstatus_t neon_YUV420CombineToYUV444( + avc444_frame_type type, + const BYTE* pSrc[3], const UINT32 srcStep[3], + UINT32 nWidth, UINT32 nHeight, + BYTE* pDst[3], const UINT32 dstStep[3], + const RECTANGLE_16* roi) +{ + if (!pSrc || !pSrc[0] || !pSrc[1] || !pSrc[2]) + return -1; + + if (!pDst || !pDst[0] || !pDst[1] || !pDst[2]) + return -1; + + if (!roi) + return -1; + + switch (type) + { + case AVC444_LUMA: + return neon_LumaToYUV444(pSrc, srcStep, pDst, dstStep, roi); + + case AVC444_CHROMAv1: + return neon_ChromaV1ToYUV444(pSrc, srcStep, pDst, dstStep, roi); + + case AVC444_CHROMAv2: + return neon_ChromaV2ToYUV444(pSrc, srcStep, nWidth, nHeight, pDst, dstStep, roi); + + default: + return -1; + } +} + +void primitives_init_YUV_opt(primitives_t* prims) +{ + generic = primitives_get_generic(); + primitives_init_YUV(prims); + + if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE)) + { + prims->YUV420ToRGB_8u_P3AC4R = neon_YUV420ToRGB_8u_P3AC4R; + prims->YUV444ToRGB_8u_P3AC4R = neon_YUV444ToRGB_8u_P3AC4R; + prims->YUV420CombineToYUV444 = neon_YUV420CombineToYUV444; + } +} diff --git a/libfreerdp/primitives/prim_YUV_opt.c b/libfreerdp/primitives/prim_YUV_ssse3.c similarity index 53% rename from libfreerdp/primitives/prim_YUV_opt.c rename to libfreerdp/primitives/prim_YUV_ssse3.c index 022b4b4..5049545 100644 --- a/libfreerdp/primitives/prim_YUV_opt.c +++ b/libfreerdp/primitives/prim_YUV_ssse3.c @@ -31,23 +31,22 @@ #include "prim_internal.h" -#ifdef WITH_SSE2 - #include <emmintrin.h> #include <tmmintrin.h> -#elif defined(WITH_NEON) -#include <arm_neon.h> -#endif /* WITH_SSE2 else WITH_NEON */ + +#if !defined(WITH_SSE2) +#error "This file needs WITH_SSE2 enabled!" +#endif static primitives_t* generic = NULL; -#ifdef WITH_SSE2 /****************************************************************************/ /* SSSE3 YUV420 -> RGB conversion */ /****************************************************************************/ static __m128i* ssse3_YUV444Pixel(__m128i* dst, __m128i Yraw, __m128i Uraw, __m128i Vraw, UINT8 pos) { /* Visual Studio 2010 doesn't like _mm_set_epi32 in array initializer list */ + /* Note: This also applies to Visual Studio 2013 before Update 4 */ #if !defined(_MSC_VER) || (_MSC_VER > 1600) const __m128i mapY[] = { @@ -70,25 +69,27 @@ static __m128i* ssse3_YUV444Pixel(__m128i* dst, __m128i Yraw, __m128i Uraw, __m1 _mm_set_epi32(0x80808003, 0x80808002, 0x80808001, 0x80808000) }; #else + /* Note: must be in little-endian format ! */ const __m128i mapY[] = { - { 0x80, 0x80, 0x03, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x00, 0x80}, - { 0x80, 0x80, 0x07, 0x80, 0x80, 0x80, 0x06, 0x80, 0x80, 0x80, 0x05, 0x80, 0x80, 0x80, 0x04, 0x80}, - { 0x80, 0x80, 0x0B, 0x80, 0x80, 0x80, 0x0A, 0x80, 0x80, 0x80, 0x09, 0x80, 0x80, 0x80, 0x08, 0x80}, - { 0x80, 0x80, 0x0F, 0x80, 0x80, 0x80, 0x0E, 0x80, 0x80, 0x80, 0x0D, 0x80, 0x80, 0x80, 0x0C, 0x80} + { 0x80, 0x00, 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x03, 0x80, 0x80 }, + { 0x80, 0x04, 0x80, 0x80, 0x80, 0x05, 0x80, 0x80, 0x80, 0x06, 0x80, 0x80, 0x80, 0x07, 0x80, 0x80 }, + { 0x80, 0x08, 0x80, 0x80, 0x80, 0x09, 0x80, 0x80, 0x80, 0x0a, 0x80, 0x80, 0x80, 0x0b, 0x80, 0x80 }, + { 0x80, 0x0c, 0x80, 0x80, 0x80, 0x0d, 0x80, 0x80, 0x80, 0x0e, 0x80, 0x80, 0x80, 0x0f, 0x80, 0x80 } + }; const __m128i mapUV[] = { - { 0x80, 0x03, 0x80, 0x02, 0x80, 0x01, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, - { 0x80, 0x07, 0x80, 0x06, 0x80, 0x05, 0x80, 0x04, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, - { 0x80, 0x0B, 0x80, 0x0A, 0x80, 0x09, 0x80, 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, - { 0x80, 0x0F, 0x80, 0x0E, 0x80, 0x0D, 0x80, 0x0C, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80} + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x01, 0x80, 0x02, 0x80, 0x03, 0x80 }, + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x04, 0x80, 0x05, 0x80, 0x06, 0x80, 0x07, 0x80 }, + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x08, 0x80, 0x09, 0x80, 0x0a, 0x80, 0x0b, 0x80 }, + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0c, 0x80, 0x0d, 0x80, 0x0e, 0x80, 0x0f, 0x80 } }; const __m128i mask[] = { - { 0x80, 0x03, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80}, - { 0x80, 0x80, 0x03, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x00, 0x80}, - { 0x80, 0x80, 0x80, 0x03, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x00} + { 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x03, 0x80 }, + { 0x80, 0x00, 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x03, 0x80, 0x80 }, + { 0x00, 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x03, 0x80, 0x80, 0x80 } }; #endif const __m128i c128 = _mm_set1_epi16(128); @@ -307,28 +308,21 @@ static pstatus_t ssse3_YUV444ToRGB_8u_P3AC4R(const BYTE** pSrc, const UINT32* sr * integer factors with 16-bit signed integer intermediate results is: * * Y = ( ( 27 * R + 92 * G + 9 * B) >> 7 ); - * U = ( (-15 * R - 49 * G + 64 * B) >> 7 ) + 128; - * V = ( ( 64 * R - 58 * G - 6 * B) >> 7 ) + 128; + * U = ( (-29 * R - 99 * G + 128 * B) >> 8 ) + 128; + * V = ( ( 128 * R - 116 * G - 12 * B) >> 8 ) + 128; * + * Due to signed 8bit range being [-128,127] the U and V constants of 128 are + * rounded to 127 */ -PRIM_ALIGN_128 static const BYTE bgrx_y_factors[] = -{ - 9, 92, 27, 0, 9, 92, 27, 0, 9, 92, 27, 0, 9, 92, 27, 0 -}; -PRIM_ALIGN_128 static const BYTE bgrx_u_factors[] = -{ - 64, -49, -15, 0, 64, -49, -15, 0, 64, -49, -15, 0, 64, -49, -15, 0 -}; -PRIM_ALIGN_128 static const BYTE bgrx_v_factors[] = -{ - -6, -58, 64, 0, -6, -58, 64, 0, -6, -58, 64, 0, -6, -58, 64, 0 -}; +#define BGRX_Y_FACTORS _mm_set_epi8(0, 27, 92, 9, 0, 27, 92, 9, 0, 27, 92, 9, 0, 27, 92, 9) +#define BGRX_U_FACTORS _mm_set_epi8(0, -29, -99, 127, 0, -29, -99, 127, 0, -29, -99, 127, 0, -29, -99, 127) +#define BGRX_V_FACTORS _mm_set_epi8(0, 127, -116, -12, 0, 127, -116, -12, 0, 127, -116, -12, 0, 127, -116, -12) +#define CONST128_FACTORS _mm_set1_epi8(-128) -PRIM_ALIGN_128 static const BYTE const_buf_128b[] = -{ - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 -}; +#define Y_SHIFT 7 +#define U_SHIFT 8 +#define V_SHIFT 8 /* TODO: @@ -337,13 +331,13 @@ globals directly the functions below could be passed pointers to the correct vec depending on the source picture format. PRIM_ALIGN_128 static const BYTE rgbx_y_factors[] = { - 27, 92, 9, 0, 27, 92, 9, 0, 27, 92, 9, 0, 27, 92, 9, 0 + 27, 92, 9, 0, 27, 92, 9, 0, 27, 92, 9, 0, 27, 92, 9, 0 }; PRIM_ALIGN_128 static const BYTE rgbx_u_factors[] = { - -15, -49, 64, 0, -15, -49, 64, 0, -15, -49, 64, 0, -15, -49, 64, 0 + -15, -49, 64, 0, -15, -49, 64, 0, -15, -49, 64, 0, -15, -49, 64, 0 }; PRIM_ALIGN_128 static const BYTE rgbx_v_factors[] = { - 64, -58, -6, 0, 64, -58, -6, 0, 64, -58, -6, 0, 64, -58, -6, 0 + 64, -58, -6, 0, 64, -58, -6, 0, 64, -58, -6, 0, 64, -58, -6, 0 }; */ @@ -354,10 +348,10 @@ static INLINE void ssse3_RGBToYUV420_BGRX_Y( const BYTE* src, BYTE* dst, UINT32 width) { UINT32 x; - __m128i y_factors, x0, x1, x2, x3; + __m128i x0, x1, x2, x3; + const __m128i y_factors = BGRX_Y_FACTORS; const __m128i* argb = (const __m128i*) src; __m128i* ydst = (__m128i*) dst; - y_factors = _mm_load_si128((__m128i*)bgrx_y_factors); for (x = 0; x < width; x += 16) { @@ -375,8 +369,8 @@ static INLINE void ssse3_RGBToYUV420_BGRX_Y( x0 = _mm_hadd_epi16(x0, x1); x2 = _mm_hadd_epi16(x2, x3); /* shift the results */ - x0 = _mm_srli_epi16(x0, 7); - x2 = _mm_srli_epi16(x2, 7); + x0 = _mm_srli_epi16(x0, Y_SHIFT); + x2 = _mm_srli_epi16(x2, Y_SHIFT); /* pack the 16 words into bytes */ x0 = _mm_packus_epi16(x0, x2); /* save to y plane */ @@ -391,14 +385,14 @@ static INLINE void ssse3_RGBToYUV420_BGRX_UV( BYTE* dst1, BYTE* dst2, UINT32 width) { UINT32 x; - __m128i vector128, u_factors, v_factors, x0, x1, x2, x3, x4, x5; + const __m128i u_factors = BGRX_U_FACTORS; + const __m128i v_factors = BGRX_V_FACTORS; + const __m128i vector128 = CONST128_FACTORS; + __m128i x0, x1, x2, x3, x4, x5; const __m128i* rgb1 = (const __m128i*)src1; const __m128i* rgb2 = (const __m128i*)src2; __m64* udst = (__m64*)dst1; __m64* vdst = (__m64*)dst2; - vector128 = _mm_load_si128((__m128i*)const_buf_128b); - u_factors = _mm_load_si128((__m128i*)bgrx_u_factors); - v_factors = _mm_load_si128((__m128i*)bgrx_v_factors); for (x = 0; x < width; x += 16) { @@ -436,12 +430,12 @@ static INLINE void ssse3_RGBToYUV420_BGRX_UV( x0 = _mm_hadd_epi16(x2, x3); x1 = _mm_hadd_epi16(x4, x5); /* shift the results */ - x0 = _mm_srai_epi16(x0, 7); - x1 = _mm_srai_epi16(x1, 7); + x0 = _mm_srai_epi16(x0, U_SHIFT); + x1 = _mm_srai_epi16(x1, V_SHIFT); /* pack the 16 words into bytes */ x0 = _mm_packs_epi16(x0, x1); /* add 128 */ - x0 = _mm_add_epi8(x0, vector128); + x0 = _mm_sub_epi8(x0, vector128); /* the lower 8 bytes go to the u plane */ _mm_storel_pi(udst++, _mm_castsi128_ps(x0)); /* the upper 8 bytes go to the v plane */ @@ -514,83 +508,184 @@ static pstatus_t ssse3_RGBToYUV420( /* SSSE3 RGB -> AVC444-YUV conversion **/ /****************************************************************************/ -static INLINE void ssse3_RGBToAVC444YUV_BGRX_ROW( - const BYTE* src, BYTE* ydst, BYTE* udst1, BYTE* udst2, BYTE* vdst1, BYTE* vdst2, BOOL isEvenRow, - UINT32 width) +static INLINE void ssse3_RGBToAVC444YUV_BGRX_DOUBLE_ROW( + const BYTE* srcEven, const BYTE* srcOdd, BYTE* b1Even, BYTE* b1Odd, BYTE* b2, + BYTE* b3, BYTE* b4, BYTE* b5, BYTE* b6, BYTE* b7, UINT32 width) { UINT32 x; - __m128i vector128, y_factors, u_factors, v_factors, smask; - __m128i x1, x2, x3, x4, y, y1, y2, u, u1, u2, v, v1, v2; - const __m128i* argb = (const __m128i*) src; - __m128i* py = (__m128i*) ydst; - __m64* pu1 = (__m64*) udst1; - __m64* pu2 = (__m64*) udst2; - __m64* pv1 = (__m64*) vdst1; - __m64* pv2 = (__m64*) vdst2; - y_factors = _mm_load_si128((__m128i*)bgrx_y_factors); - u_factors = _mm_load_si128((__m128i*)bgrx_u_factors); - v_factors = _mm_load_si128((__m128i*)bgrx_v_factors); - vector128 = _mm_load_si128((__m128i*)const_buf_128b); - smask = _mm_set_epi8(15, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 0); + const __m128i* argbEven = (const __m128i*) srcEven; + const __m128i* argbOdd = (const __m128i*) srcOdd; + const __m128i y_factors = BGRX_Y_FACTORS; + const __m128i u_factors = BGRX_U_FACTORS; + const __m128i v_factors = BGRX_V_FACTORS; + const __m128i vector128 = CONST128_FACTORS; for (x = 0; x < width; x += 16) { /* store 16 rgba pixels in 4 128 bit registers */ - x1 = _mm_load_si128(argb++); // 1st 4 pixels - x2 = _mm_load_si128(argb++); // 2nd 4 pixels - x3 = _mm_load_si128(argb++); // 3rd 4 pixels - x4 = _mm_load_si128(argb++); // 4th 4 pixels - /* Y: multiplications with subtotals and horizontal sums */ - y1 = _mm_hadd_epi16(_mm_maddubs_epi16(x1, y_factors), _mm_maddubs_epi16(x2, y_factors)); - y2 = _mm_hadd_epi16(_mm_maddubs_epi16(x3, y_factors), _mm_maddubs_epi16(x4, y_factors)); - /* Y: shift the results (logical) */ - y1 = _mm_srli_epi16(y1, 7); - y2 = _mm_srli_epi16(y2, 7); - /* Y: pack (unsigned) 16 words into bytes */ - y = _mm_packus_epi16(y1, y2); - /* U: multiplications with subtotals and horizontal sums */ - u1 = _mm_hadd_epi16(_mm_maddubs_epi16(x1, u_factors), _mm_maddubs_epi16(x2, u_factors)); - u2 = _mm_hadd_epi16(_mm_maddubs_epi16(x3, u_factors), _mm_maddubs_epi16(x4, u_factors)); - /* U: shift the results (arithmetic) */ - u1 = _mm_srai_epi16(u1, 7); - u2 = _mm_srai_epi16(u2, 7); - /* U: pack (signed) 16 words into bytes */ - u = _mm_packs_epi16(u1, u2); - /* U: add 128 */ - u = _mm_add_epi8(u, vector128); - /* V: multiplications with subtotals and horizontal sums */ - v1 = _mm_hadd_epi16(_mm_maddubs_epi16(x1, v_factors), _mm_maddubs_epi16(x2, v_factors)); - v2 = _mm_hadd_epi16(_mm_maddubs_epi16(x3, v_factors), _mm_maddubs_epi16(x4, v_factors)); - /* V: shift the results (arithmetic) */ - v1 = _mm_srai_epi16(v1, 7); - v2 = _mm_srai_epi16(v2, 7); - /* V: pack (signed) 16 words into bytes */ - v = _mm_packs_epi16(v1, v2); - /* V: add 128 */ - v = _mm_add_epi8(v, vector128); - /* store y */ - _mm_storeu_si128(py++, y); + const __m128i xe1 = _mm_load_si128(argbEven++); // 1st 4 pixels + const __m128i xe2 = _mm_load_si128(argbEven++); // 2nd 4 pixels + const __m128i xe3 = _mm_load_si128(argbEven++); // 3rd 4 pixels + const __m128i xe4 = _mm_load_si128(argbEven++); // 4th 4 pixels + const __m128i xo1 = _mm_load_si128(argbOdd++); // 1st 4 pixels + const __m128i xo2 = _mm_load_si128(argbOdd++); // 2nd 4 pixels + const __m128i xo3 = _mm_load_si128(argbOdd++); // 3rd 4 pixels + const __m128i xo4 = _mm_load_si128(argbOdd++); // 4th 4 pixels + { + /* Y: multiplications with subtotals and horizontal sums */ + const __m128i ye1 = _mm_srli_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe1, y_factors), + _mm_maddubs_epi16(xe2, y_factors)), Y_SHIFT); + const __m128i ye2 = _mm_srli_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe3, y_factors), + _mm_maddubs_epi16(xe4, y_factors)), Y_SHIFT); + const __m128i ye = _mm_packus_epi16(ye1, ye2); + const __m128i yo1 = _mm_srli_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo1, y_factors), + _mm_maddubs_epi16(xo2, y_factors)), Y_SHIFT); + const __m128i yo2 = _mm_srli_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo3, y_factors), + _mm_maddubs_epi16(xo4, y_factors)), Y_SHIFT); + const __m128i yo = _mm_packus_epi16(yo1, yo2); + /* store y [b1] */ + _mm_storeu_si128((__m128i*)b1Even, ye); + b1Even += 16; - /* store u and v */ - if (isEvenRow) - { - u = _mm_shuffle_epi8(u, smask); - v = _mm_shuffle_epi8(v, smask); - _mm_storel_pi(pu1++, _mm_castsi128_ps(u)); - _mm_storeh_pi(pu2++, _mm_castsi128_ps(u)); - _mm_storel_pi(pv1++, _mm_castsi128_ps(v)); - _mm_storeh_pi(pv2++, _mm_castsi128_ps(v)); + if (b1Odd) + { + _mm_storeu_si128((__m128i*)b1Odd, yo); + b1Odd += 16; + } } - else { - _mm_storel_pi(pu1, _mm_castsi128_ps(u)); - _mm_storeh_pi(pu2, _mm_castsi128_ps(u)); - _mm_storel_pi(pv1, _mm_castsi128_ps(v)); - _mm_storeh_pi(pv2, _mm_castsi128_ps(v)); - pu1 += 2; - pu2 += 2; - pv1 += 2; - pv2 += 2; + /* We have now + * 16 even U values in ue + * 16 odd U values in uo + * + * We need to split these according to + * 3.3.8.3.2 YUV420p Stream Combination for YUV444 mode */ + __m128i ue, uo; + { + const __m128i ue1 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe1, u_factors), + _mm_maddubs_epi16(xe2, u_factors)), U_SHIFT); + const __m128i ue2 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe3, u_factors), + _mm_maddubs_epi16(xe4, u_factors)), U_SHIFT); + ue = _mm_sub_epi8(_mm_packs_epi16(ue1, ue2), vector128); + } + + if (b1Odd) + { + const __m128i uo1 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo1, u_factors), + _mm_maddubs_epi16(xo2, u_factors)), U_SHIFT); + const __m128i uo2 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo3, u_factors), + _mm_maddubs_epi16(xo4, u_factors)), U_SHIFT); + uo = _mm_sub_epi8(_mm_packs_epi16(uo1, uo2), vector128); + } + + /* Now we need the following storage distribution: + * 2x 2y -> b2 + * x 2y+1 -> b4 + * 2x+1 2y -> b6 */ + if (b1Odd) /* b2 */ + { + const __m128i ueh = _mm_unpackhi_epi8(ue, _mm_setzero_si128()); + const __m128i uoh = _mm_unpackhi_epi8(uo, _mm_setzero_si128()); + const __m128i hi = _mm_add_epi16(ueh, uoh); + const __m128i uel = _mm_unpacklo_epi8(ue, _mm_setzero_si128()); + const __m128i uol = _mm_unpacklo_epi8(uo, _mm_setzero_si128()); + const __m128i lo = _mm_add_epi16(uel, uol); + const __m128i added = _mm_hadd_epi16(lo, hi); + const __m128i avg16 = _mm_srai_epi16(added, 2); + const __m128i avg = _mm_packus_epi16(avg16, avg16); + _mm_storel_epi64((__m128i*)b2, avg); + } + else + { + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 14, 12, 10, 8, 6, 4, 2, 0); + const __m128i ud = _mm_shuffle_epi8(ue, mask); + _mm_storel_epi64((__m128i*)b2, ud); + } + + b2 += 8; + + if (b1Odd) /* b4 */ + { + _mm_store_si128((__m128i*)b4, uo); + b4 += 16; + } + + { + /* b6 */ + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 15, 13, 11, 9, 7, 5, 3, 1); + const __m128i ude = _mm_shuffle_epi8(ue, mask); + _mm_storel_epi64((__m128i*)b6, ude); + b6 += 8; + } + } + { + /* We have now + * 16 even V values in ue + * 16 odd V values in uo + * + * We need to split these according to + * 3.3.8.3.2 YUV420p Stream Combination for YUV444 mode */ + __m128i ve, vo; + { + const __m128i ve1 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe1, v_factors), + _mm_maddubs_epi16(xe2, v_factors)), V_SHIFT); + const __m128i ve2 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe3, v_factors), + _mm_maddubs_epi16(xe4, v_factors)), V_SHIFT); + ve = _mm_sub_epi8(_mm_packs_epi16(ve1, ve2), vector128); + } + + if (b1Odd) + { + const __m128i vo1 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo1, v_factors), + _mm_maddubs_epi16(xo2, v_factors)), V_SHIFT); + const __m128i vo2 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo3, v_factors), + _mm_maddubs_epi16(xo4, v_factors)), V_SHIFT); + vo = _mm_sub_epi8(_mm_packs_epi16(vo1, vo2), vector128); + } + + /* Now we need the following storage distribution: + * 2x 2y -> b3 + * x 2y+1 -> b5 + * 2x+1 2y -> b7 */ + if (b1Odd) /* b3 */ + { + const __m128i veh = _mm_unpackhi_epi8(ve, _mm_setzero_si128()); + const __m128i voh = _mm_unpackhi_epi8(vo, _mm_setzero_si128()); + const __m128i hi = _mm_add_epi16(veh, voh); + const __m128i vel = _mm_unpacklo_epi8(ve, _mm_setzero_si128()); + const __m128i vol = _mm_unpacklo_epi8(vo, _mm_setzero_si128()); + const __m128i lo = _mm_add_epi16(vel, vol); + const __m128i added = _mm_hadd_epi16(lo, hi); + const __m128i avg16 = _mm_srai_epi16(added, 2); + const __m128i avg = _mm_packus_epi16(avg16, avg16); + _mm_storel_epi64((__m128i*)b3, avg); + } + else + { + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 14, 12, 10, 8, 6, 4, 2, 0); + const __m128i vd = _mm_shuffle_epi8(ve, mask); + _mm_storel_epi64((__m128i*)b3, vd); + } + + b3 += 8; + + if (b1Odd) /* b5 */ + { + _mm_store_si128((__m128i*)b5, vo); + b5 += 16; + } + + { + /* b7 */ + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 15, 13, 11, 9, 7, 5, 3, 1); + const __m128i vde = _mm_shuffle_epi8(ve, mask); + _mm_storel_epi64((__m128i*)b7, vde); + b7 += 8; + } } } } @@ -602,49 +697,37 @@ static pstatus_t ssse3_RGBToAVC444YUV_BGRX( BYTE* pDst2[3], const UINT32 dst2Step[3], const prim_size_t* roi) { - UINT32 y, numRows; - BOOL evenRow = TRUE; - BYTE* b1, *b2, *b3, *b4, *b5, *b6, *b7; + UINT32 y; const BYTE* pMaxSrc = pSrc + (roi->height - 1) * srcStep; if (roi->height < 1 || roi->width < 1) - { return !PRIMITIVES_SUCCESS; - } if (roi->width % 16 || (unsigned long)pSrc % 16 || srcStep % 16) - { return generic->RGBToAVC444YUV(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi); - } - numRows = (roi->height + 1) & ~1; - - for (y = 0; y < numRows; y++, evenRow = !evenRow) + for (y = 0; y < roi->height; y += 2) { - const BYTE* src = y < roi->height ? pSrc + y * srcStep : pMaxSrc; - UINT32 i = y >> 1; - b1 = pDst1[0] + y * dst1Step[0]; - - if (evenRow) - { - b2 = pDst1[1] + i * dst1Step[1]; - b3 = pDst1[2] + i * dst1Step[2]; - b6 = pDst2[1] + i * dst2Step[1]; - b7 = pDst2[2] + i * dst2Step[2]; - ssse3_RGBToAVC444YUV_BGRX_ROW(src, b1, b2, b6, b3, b7, TRUE, roi->width); - } - else - { - b4 = pDst2[0] + dst2Step[0] * ((i & ~7) + i); - b5 = b4 + 8 * dst2Step[0]; - ssse3_RGBToAVC444YUV_BGRX_ROW(src, b1, b4, b4 + 8, b5, b5 + 8, FALSE, roi->width); - } + const BOOL last = (y >= (roi->height - 1)); + const BYTE* srcEven = y < roi->height ? pSrc + y * srcStep : pMaxSrc; + const BYTE* srcOdd = !last ? pSrc + (y + 1) * srcStep : pMaxSrc; + const UINT32 i = y >> 1; + const UINT32 n = (i & ~7) + i; + BYTE* b1Even = pDst1[0] + y * dst1Step[0]; + BYTE* b1Odd = !last ? (b1Even + dst1Step[0]) : NULL; + BYTE* b2 = pDst1[1] + (y / 2) * dst1Step[1]; + BYTE* b3 = pDst1[2] + (y / 2) * dst1Step[2]; + BYTE* b4 = pDst2[0] + dst2Step[0] * n; + BYTE* b5 = b4 + 8 * dst2Step[0]; + BYTE* b6 = pDst2[1] + (y / 2) * dst2Step[1]; + BYTE* b7 = pDst2[2] + (y / 2) * dst2Step[2]; + ssse3_RGBToAVC444YUV_BGRX_DOUBLE_ROW(srcEven, srcOdd, b1Even, b1Odd, b2, b3, b4, b5, b6, b7, + roi->width); } return PRIMITIVES_SUCCESS; } - static pstatus_t ssse3_RGBToAVC444YUV( const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep, BYTE* pDst1[3], const UINT32 dst1Step[3], @@ -662,6 +745,293 @@ static pstatus_t ssse3_RGBToAVC444YUV( } } +/* Mapping of arguments: + * + * b1 [even lines] -> yLumaDstEven + * b1 [odd lines] -> yLumaDstOdd + * b2 -> uLumaDst + * b3 -> vLumaDst + * b4 -> yChromaDst1 + * b5 -> yChromaDst2 + * b6 -> uChromaDst1 + * b7 -> uChromaDst2 + * b8 -> vChromaDst1 + * b9 -> vChromaDst2 + */ +static INLINE void ssse3_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW( + const BYTE* srcEven, const BYTE* srcOdd, + BYTE* yLumaDstEven, BYTE* yLumaDstOdd, + BYTE* uLumaDst, BYTE* vLumaDst, + BYTE* yEvenChromaDst1, BYTE* yEvenChromaDst2, + BYTE* yOddChromaDst1, BYTE* yOddChromaDst2, + BYTE* uChromaDst1, BYTE* uChromaDst2, + BYTE* vChromaDst1, BYTE* vChromaDst2, + UINT32 width) +{ + UINT32 x; + const __m128i vector128 = CONST128_FACTORS; + const __m128i* argbEven = (const __m128i*) srcEven; + const __m128i* argbOdd = (const __m128i*) srcOdd; + + for (x = 0; x < width; x += 16) + { + /* store 16 rgba pixels in 4 128 bit registers + * for even and odd rows. + */ + const __m128i xe1 = _mm_load_si128(argbEven++); /* 1st 4 pixels */ + const __m128i xe2 = _mm_load_si128(argbEven++); /* 2nd 4 pixels */ + const __m128i xe3 = _mm_load_si128(argbEven++); /* 3rd 4 pixels */ + const __m128i xe4 = _mm_load_si128(argbEven++); /* 4th 4 pixels */ + const __m128i xo1 = _mm_load_si128(argbOdd++); /* 1st 4 pixels */ + const __m128i xo2 = _mm_load_si128(argbOdd++); /* 2nd 4 pixels */ + const __m128i xo3 = _mm_load_si128(argbOdd++); /* 3rd 4 pixels */ + const __m128i xo4 = _mm_load_si128(argbOdd++); /* 4th 4 pixels */ + { + /* Y: multiplications with subtotals and horizontal sums */ + const __m128i y_factors = BGRX_Y_FACTORS; + const __m128i ye1 = _mm_srli_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe1, y_factors), + _mm_maddubs_epi16(xe2, y_factors)), Y_SHIFT); + const __m128i ye2 = _mm_srli_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe3, y_factors), + _mm_maddubs_epi16(xe4, y_factors)), Y_SHIFT); + const __m128i ye = _mm_packus_epi16(ye1, ye2); + /* store y [b1] */ + _mm_storeu_si128((__m128i*)yLumaDstEven, ye); + yLumaDstEven += 16; + } + + if (yLumaDstOdd) + { + const __m128i y_factors = BGRX_Y_FACTORS; + const __m128i yo1 = _mm_srli_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo1, y_factors), + _mm_maddubs_epi16(xo2, y_factors)), Y_SHIFT); + const __m128i yo2 = _mm_srli_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo3, y_factors), + _mm_maddubs_epi16(xo4, y_factors)), Y_SHIFT); + const __m128i yo = _mm_packus_epi16(yo1, yo2); + _mm_storeu_si128((__m128i*)yLumaDstOdd, yo); + yLumaDstOdd += 16; + } + + { + /* We have now + * 16 even U values in ue + * 16 odd U values in uo + * + * We need to split these according to + * 3.3.8.3.3 YUV420p Stream Combination for YUV444v2 mode */ + /* U: multiplications with subtotals and horizontal sums */ + __m128i ue, uo, uavg; + { + const __m128i u_factors = BGRX_U_FACTORS; + const __m128i ue1 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe1, u_factors), + _mm_maddubs_epi16(xe2, u_factors)), U_SHIFT); + const __m128i ue2 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe3, u_factors), + _mm_maddubs_epi16(xe4, u_factors)), U_SHIFT); + const __m128i ueavg = _mm_hadd_epi16(ue1, ue2); + ue = _mm_sub_epi8(_mm_packs_epi16(ue1, ue2), vector128); + uavg = ueavg; + } + { + const __m128i u_factors = BGRX_U_FACTORS; + const __m128i uo1 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo1, u_factors), + _mm_maddubs_epi16(xo2, u_factors)), U_SHIFT); + const __m128i uo2 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo3, u_factors), + _mm_maddubs_epi16(xo4, u_factors)), U_SHIFT); + const __m128i uoavg = _mm_hadd_epi16(uo1, uo2); + uo = _mm_sub_epi8(_mm_packs_epi16(uo1, uo2), vector128); + uavg = _mm_add_epi16(uavg, uoavg); + uavg = _mm_srai_epi16(uavg, 2); + uavg = _mm_packs_epi16(uavg, uoavg); + uavg = _mm_sub_epi8(uavg, vector128); + } + /* Now we need the following storage distribution: + * 2x 2y -> uLumaDst + * 2x+1 y -> yChromaDst1 + * 4x 2y+1 -> uChromaDst1 + * 4x+2 2y+1 -> vChromaDst1 */ + { + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 15, 13, 11, 9, 7, 5, 3, 1); + const __m128i ude = _mm_shuffle_epi8(ue, mask); + _mm_storel_epi64((__m128i*)yEvenChromaDst1, ude); + yEvenChromaDst1 += 8; + } + + if (yLumaDstOdd) + { + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 15, 13, 11, 9, 7, 5, 3, 1); + const __m128i udo = _mm_shuffle_epi8(uo, mask); + _mm_storel_epi64((__m128i*)yOddChromaDst1, udo); + yOddChromaDst1 += 8; + } + + if (yLumaDstOdd) + { + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 14, 10, 6, 2, 12, 8, 4, 0); + const __m128i ud = _mm_shuffle_epi8(uo, mask); + int* uDst1 = (int*)uChromaDst1; + int* vDst1 = (int*)vChromaDst1; + const int* src = (const int*)&ud; + _mm_stream_si32(uDst1, src[0]); + _mm_stream_si32(vDst1, src[1]); + uChromaDst1 += 4; + vChromaDst1 += 4; + } + + if (yLumaDstOdd) + { + _mm_storel_epi64((__m128i*)uLumaDst, uavg); + uLumaDst += 8; + } + else + { + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 14, 12, 10, 8, 6, 4, 2, 0); + const __m128i ud = _mm_shuffle_epi8(ue, mask); + _mm_storel_epi64((__m128i*)uLumaDst, ud); + uLumaDst += 8; + } + } + + { + /* V: multiplications with subtotals and horizontal sums */ + __m128i ve, vo, vavg; + { + const __m128i v_factors = BGRX_V_FACTORS; + const __m128i ve1 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe1, v_factors), + _mm_maddubs_epi16(xe2, v_factors)), V_SHIFT); + const __m128i ve2 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xe3, v_factors), + _mm_maddubs_epi16(xe4, v_factors)), V_SHIFT); + const __m128i veavg = _mm_hadd_epi16(ve1, ve2); + ve = _mm_sub_epi8(_mm_packs_epi16(ve1, ve2), vector128); + vavg = veavg; + } + { + const __m128i v_factors = BGRX_V_FACTORS; + const __m128i vo1 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo1, v_factors), + _mm_maddubs_epi16(xo2, v_factors)), V_SHIFT); + const __m128i vo2 = _mm_srai_epi16(_mm_hadd_epi16(_mm_maddubs_epi16(xo3, v_factors), + _mm_maddubs_epi16(xo4, v_factors)), V_SHIFT); + const __m128i voavg = _mm_hadd_epi16(vo1, vo2); + vo = _mm_sub_epi8(_mm_packs_epi16(vo1, vo2), vector128); + vavg = _mm_add_epi16(vavg, voavg); + vavg = _mm_srai_epi16(vavg, 2); + vavg = _mm_packs_epi16(vavg, voavg); + vavg = _mm_sub_epi8(vavg, vector128); + } + /* Now we need the following storage distribution: + * 2x 2y -> vLumaDst + * 2x+1 y -> yChromaDst2 + * 4x 2y+1 -> uChromaDst2 + * 4x+2 2y+1 -> vChromaDst2 */ + { + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 15, 13, 11, 9, 7, 5, 3, 1); + __m128i vde = _mm_shuffle_epi8(ve, mask); + _mm_storel_epi64((__m128i*)yEvenChromaDst2, vde); + yEvenChromaDst2 += 8; + } + + if (yLumaDstOdd) + { + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 15, 13, 11, 9, 7, 5, 3, 1); + __m128i vdo = _mm_shuffle_epi8(vo, mask); + _mm_storel_epi64((__m128i*)yOddChromaDst2, vdo); + yOddChromaDst2 += 8; + } + + if (yLumaDstOdd) + { + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 14, 10, 6, 2, 12, 8, 4, 0); + const __m128i vd = _mm_shuffle_epi8(vo, mask); + int* uDst2 = (int*)uChromaDst2; + int* vDst2 = (int*)vChromaDst2; + const int* src = (const int*)&vd; + _mm_stream_si32(uDst2, src[0]); + _mm_stream_si32(vDst2, src[1]); + uChromaDst2 += 4; + vChromaDst2 += 4; + } + + if (yLumaDstOdd) + { + _mm_storel_epi64((__m128i*)vLumaDst, vavg); + vLumaDst += 8; + } + else + { + const __m128i mask = _mm_set_epi8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 14, 12, 10, 8, 6, 4, 2, 0); + __m128i vd = _mm_shuffle_epi8(ve, mask); + _mm_storel_epi64((__m128i*)vLumaDst, vd); + vLumaDst += 8; + } + } + } +} + +static pstatus_t ssse3_RGBToAVC444YUVv2_BGRX( + const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep, + BYTE* pDst1[3], const UINT32 dst1Step[3], + BYTE* pDst2[3], const UINT32 dst2Step[3], + const prim_size_t* roi) +{ + UINT32 y; + + if (roi->height < 1 || roi->width < 1) + return !PRIMITIVES_SUCCESS; + + if (roi->width % 16 || (unsigned long)pSrc % 16 || srcStep % 16) + return generic->RGBToAVC444YUVv2(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi); + + for (y = 0; y < roi->height; y += 2) + { + const BYTE* srcEven = (pSrc + y * srcStep); + const BYTE* srcOdd = (srcEven + srcStep); + BYTE* dstLumaYEven = (pDst1[0] + y * dst1Step[0]); + BYTE* dstLumaYOdd = (y < roi->height - 1) ? (dstLumaYEven + dst1Step[0]) : NULL; + BYTE* dstLumaU = (pDst1[1] + (y / 2) * dst1Step[1]); + BYTE* dstLumaV = (pDst1[2] + (y / 2) * dst1Step[2]); + BYTE* dstEvenChromaY1 = (pDst2[0] + y * dst2Step[0]); + BYTE* dstEvenChromaY2 = dstEvenChromaY1 + roi->width / 2; + BYTE* dstOddChromaY1 = dstEvenChromaY1 + dst2Step[0]; + BYTE* dstOddChromaY2 = dstEvenChromaY2 + dst2Step[0]; + BYTE* dstChromaU1 = (pDst2[1] + (y / 2) * dst2Step[1]); + BYTE* dstChromaV1 = (pDst2[2] + (y / 2) * dst2Step[2]); + BYTE* dstChromaU2 = dstChromaU1 + roi->width / 4; + BYTE* dstChromaV2 = dstChromaV1 + roi->width / 4; + ssse3_RGBToAVC444YUVv2_BGRX_DOUBLE_ROW(srcEven, srcOdd, dstLumaYEven, + dstLumaYOdd, dstLumaU, dstLumaV, + dstEvenChromaY1, dstEvenChromaY2, + dstOddChromaY1, dstOddChromaY2, + dstChromaU1, dstChromaU2, + dstChromaV1, dstChromaV2, + roi->width); + } + + return PRIMITIVES_SUCCESS; +} + +static pstatus_t ssse3_RGBToAVC444YUVv2( + const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep, + BYTE* pDst1[3], const UINT32 dst1Step[3], + BYTE* pDst2[3], const UINT32 dst2Step[3], + const prim_size_t* roi) +{ + switch (srcFormat) + { + case PIXEL_FORMAT_BGRX32: + case PIXEL_FORMAT_BGRA32: + return ssse3_RGBToAVC444YUVv2_BGRX(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi); + + default: + return generic->RGBToAVC444YUVv2(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi); + } +} + static pstatus_t ssse3_LumaToYUV444(const BYTE* pSrcRaw[3], const UINT32 srcStep[3], BYTE* pDstRaw[3], const UINT32 dstStep[3], const RECTANGLE_16* roi) @@ -1075,751 +1445,19 @@ static pstatus_t ssse3_YUV420CombineToYUV444( } } -#elif defined(WITH_NEON) - -static INLINE uint8x8_t neon_YUV2R(int32x4_t Ch, int32x4_t Cl, - int16x4_t Dh, int16x4_t Dl, - int16x4_t Eh, int16x4_t El) -{ - /* R = (256 * Y + 403 * (V - 128)) >> 8 */ - const int16x4_t c403 = vdup_n_s16(403); - const int32x4_t CEh = vmlal_s16(Ch, Eh, c403); - const int32x4_t CEl = vmlal_s16(Cl, El, c403); - const int32x4_t Rh = vrshrq_n_s32(CEh, 8); - const int32x4_t Rl = vrshrq_n_s32(CEl, 8); - const int16x8_t R = vcombine_s16(vqmovn_s32(Rl), vqmovn_s32(Rh)); - return vqmovun_s16(R); -} - -static INLINE uint8x8_t neon_YUV2G(int32x4_t Ch, int32x4_t Cl, - int16x4_t Dh, int16x4_t Dl, - int16x4_t Eh, int16x4_t El) -{ - /* G = (256L * Y - 48 * (U - 128) - 120 * (V - 128)) >> 8 */ - const int16x4_t c48 = vdup_n_s16(48); - const int16x4_t c120 = vdup_n_s16(120); - const int32x4_t CDh = vmlsl_s16(Ch, Dh, c48); - const int32x4_t CDl = vmlsl_s16(Cl, Dl, c48); - const int32x4_t CDEh = vmlsl_s16(CDh, Eh, c120); - const int32x4_t CDEl = vmlsl_s16(CDl, El, c120); - const int32x4_t Gh = vrshrq_n_s32(CDEh, 8); - const int32x4_t Gl = vrshrq_n_s32(CDEl, 8); - const int16x8_t G = vcombine_s16(vqmovn_s32(Gl), vqmovn_s32(Gh)); - return vqmovun_s16(G); -} - -static INLINE uint8x8_t neon_YUV2B(int32x4_t Ch, int32x4_t Cl, - int16x4_t Dh, int16x4_t Dl, - int16x4_t Eh, int16x4_t El) -{ - /* B = (256L * Y + 475 * (U - 128)) >> 8*/ - const int16x4_t c475 = vdup_n_s16(475); - const int32x4_t CDh = vmlal_s16(Ch, Dh, c475); - const int32x4_t CDl = vmlal_s16(Ch, Dl, c475); - const int32x4_t Bh = vrshrq_n_s32(CDh, 8); - const int32x4_t Bl = vrshrq_n_s32(CDl, 8); - const int16x8_t B = vcombine_s16(vqmovn_s32(Bl), vqmovn_s32(Bh)); - return vqmovun_s16(B); -} - -static INLINE BYTE* neon_YuvToRgbPixel(BYTE* pRGB, int16x8_t Y, int16x8_t D, int16x8_t E, - const uint8_t rPos, const uint8_t gPos, const uint8_t bPos, const uint8_t aPos) -{ - uint8x8x4_t bgrx; - const int32x4_t Ch = vmulq_n_s32(vmovl_s16(vget_high_s16(Y)), 256); /* Y * 256 */ - const int32x4_t Cl = vmulq_n_s32(vmovl_s16(vget_low_s16(Y)), 256); /* Y * 256 */ - const int16x4_t Dh = vget_high_s16(D); - const int16x4_t Dl = vget_low_s16(D); - const int16x4_t Eh = vget_high_s16(E); - const int16x4_t El = vget_low_s16(E); - { - /* B = (256L * Y + 475 * (U - 128)) >> 8*/ - const int16x4_t c475 = vdup_n_s16(475); - const int32x4_t CDh = vmlal_s16(Ch, Dh, c475); - const int32x4_t CDl = vmlal_s16(Cl, Dl, c475); - const int32x4_t Bh = vrshrq_n_s32(CDh, 8); - const int32x4_t Bl = vrshrq_n_s32(CDl, 8); - const int16x8_t B = vcombine_s16(vqmovn_s32(Bl), vqmovn_s32(Bh)); - bgrx.val[bPos] = vqmovun_s16(B); - } - { - /* G = (256L * Y - 48 * (U - 128) - 120 * (V - 128)) >> 8 */ - const int16x4_t c48 = vdup_n_s16(48); - const int16x4_t c120 = vdup_n_s16(120); - const int32x4_t CDh = vmlsl_s16(Ch, Dh, c48); - const int32x4_t CDl = vmlsl_s16(Cl, Dl, c48); - const int32x4_t CDEh = vmlsl_s16(CDh, Eh, c120); - const int32x4_t CDEl = vmlsl_s16(CDl, El, c120); - const int32x4_t Gh = vrshrq_n_s32(CDEh, 8); - const int32x4_t Gl = vrshrq_n_s32(CDEl, 8); - const int16x8_t G = vcombine_s16(vqmovn_s32(Gl), vqmovn_s32(Gh)); - bgrx.val[gPos] = vqmovun_s16(G); - } - { - /* R = (256 * Y + 403 * (V - 128)) >> 8 */ - const int16x4_t c403 = vdup_n_s16(403); - const int32x4_t CEh = vmlal_s16(Ch, Eh, c403); - const int32x4_t CEl = vmlal_s16(Cl, El, c403); - const int32x4_t Rh = vrshrq_n_s32(CEh, 8); - const int32x4_t Rl = vrshrq_n_s32(CEl, 8); - const int16x8_t R = vcombine_s16(vqmovn_s32(Rl), vqmovn_s32(Rh)); - bgrx.val[rPos] = vqmovun_s16(R); - } - { - /* A */ - bgrx.val[aPos] = vdup_n_u8(0xFF); - } - vst4_u8(pRGB, bgrx); - pRGB += 32; - return pRGB; -} - -static INLINE pstatus_t neon_YUV420ToX( - const BYTE* pSrc[3], const UINT32 srcStep[3], - BYTE* pDst, UINT32 dstStep, - const prim_size_t* roi, const uint8_t rPos, const uint8_t gPos, - const uint8_t bPos, const uint8_t aPos) -{ - UINT32 y; - const UINT32 nWidth = roi->width; - const UINT32 nHeight = roi->height; - const DWORD pad = nWidth % 16; - const UINT32 yPad = srcStep[0] - roi->width; - const UINT32 uPad = srcStep[1] - roi->width / 2; - const UINT32 vPad = srcStep[2] - roi->width / 2; - const UINT32 dPad = dstStep - roi->width * 4; - const int16x8_t c128 = vdupq_n_s16(128); - - for (y = 0; y < nHeight; y += 2) - { - const uint8_t* pY1 = pSrc[0] + y * srcStep[0]; - const uint8_t* pY2 = pY1 + srcStep[0]; - const uint8_t* pU = pSrc[1] + (y / 2) * srcStep[1]; - const uint8_t* pV = pSrc[2] + (y / 2) * srcStep[2]; - uint8_t* pRGB1 = pDst + y * dstStep; - uint8_t* pRGB2 = pRGB1 + dstStep; - UINT32 x; - const BOOL lastY = y >= nHeight - 1; - - for (x = 0; x < nWidth - pad;) - { - const uint8x8_t Uraw = vld1_u8(pU); - const uint8x8x2_t Uu = vzip_u8(Uraw, Uraw); - const int16x8_t U1 = vreinterpretq_s16_u16(vmovl_u8(Uu.val[0])); - const int16x8_t U2 = vreinterpretq_s16_u16(vmovl_u8(Uu.val[1])); - const uint8x8_t Vraw = vld1_u8(pV); - const uint8x8x2_t Vu = vzip_u8(Vraw, Vraw); - const int16x8_t V1 = vreinterpretq_s16_u16(vmovl_u8(Vu.val[0])); - const int16x8_t V2 = vreinterpretq_s16_u16(vmovl_u8(Vu.val[1])); - const int16x8_t D1 = vsubq_s16(U1, c128); - const int16x8_t E1 = vsubq_s16(V1, c128); - const int16x8_t D2 = vsubq_s16(U2, c128); - const int16x8_t E2 = vsubq_s16(V2, c128); - { - const uint8x8_t Y1u = vld1_u8(pY1); - const int16x8_t Y1 = vreinterpretq_s16_u16(vmovl_u8(Y1u)); - pRGB1 = neon_YuvToRgbPixel(pRGB1, Y1, D1, E1, rPos, gPos, bPos, aPos); - pY1 += 8; - x += 8; - } - { - const uint8x8_t Y1u = vld1_u8(pY1); - const int16x8_t Y1 = vreinterpretq_s16_u16(vmovl_u8(Y1u)); - pRGB1 = neon_YuvToRgbPixel(pRGB1, Y1, D2, E2, rPos, gPos, bPos, aPos); - pY1 += 8; - x += 8; - } - - if (!lastY) - { - { - const uint8x8_t Y2u = vld1_u8(pY2); - const int16x8_t Y2 = vreinterpretq_s16_u16(vmovl_u8(Y2u)); - pRGB2 = neon_YuvToRgbPixel(pRGB2, Y2, D1, E1, rPos, gPos, bPos, aPos); - pY2 += 8; - } - { - const uint8x8_t Y2u = vld1_u8(pY2); - const int16x8_t Y2 = vreinterpretq_s16_u16(vmovl_u8(Y2u)); - pRGB2 = neon_YuvToRgbPixel(pRGB2, Y2, D2, E2, rPos, gPos, bPos, aPos); - pY2 += 8; - } - } - - pU += 8; - pV += 8; - } - - for (; x < nWidth; x++) - { - const BYTE U = *pU; - const BYTE V = *pV; - { - const BYTE Y = *pY1++; - const BYTE r = YUV2R(Y, U, V); - const BYTE g = YUV2G(Y, U, V); - const BYTE b = YUV2B(Y, U, V); - pRGB1[aPos] = 0xFF; - pRGB1[rPos] = r; - pRGB1[gPos] = g; - pRGB1[bPos] = b; - pRGB1 += 4; - } - - if (!lastY) - { - const BYTE Y = *pY2++; - const BYTE r = YUV2R(Y, U, V); - const BYTE g = YUV2G(Y, U, V); - const BYTE b = YUV2B(Y, U, V); - pRGB2[aPos] = 0xFF; - pRGB2[rPos] = r; - pRGB2[gPos] = g; - pRGB2[bPos] = b; - pRGB2 += 4; - } - - if (x % 2) - { - pU++; - pV++; - } - } - - pRGB1 += dPad; - pRGB2 += dPad; - pY1 += yPad; - pY2 += yPad; - pU += uPad; - pV += vPad; - } - - return PRIMITIVES_SUCCESS; -} - -static pstatus_t neon_YUV420ToRGB_8u_P3AC4R( - const BYTE* pSrc[3], const UINT32 srcStep[3], - BYTE* pDst, UINT32 dstStep, UINT32 DstFormat, - const prim_size_t* roi) -{ - switch (DstFormat) - { - case PIXEL_FORMAT_BGRA32: - case PIXEL_FORMAT_BGRX32: - return neon_YUV420ToX(pSrc, srcStep, pDst, dstStep, roi, 2, 1, 0, 3); - - case PIXEL_FORMAT_RGBA32: - case PIXEL_FORMAT_RGBX32: - return neon_YUV420ToX(pSrc, srcStep, pDst, dstStep, roi, 0, 1, 2, 3); - - case PIXEL_FORMAT_ARGB32: - case PIXEL_FORMAT_XRGB32: - return neon_YUV420ToX(pSrc, srcStep, pDst, dstStep, roi, 1, 2, 3, 0); - - case PIXEL_FORMAT_ABGR32: - case PIXEL_FORMAT_XBGR32: - return neon_YUV420ToX(pSrc, srcStep, pDst, dstStep, roi, 3, 2, 1, 0); - - default: - return generic->YUV420ToRGB_8u_P3AC4R(pSrc, srcStep, pDst, dstStep, DstFormat, roi); - } -} - -static INLINE pstatus_t neon_YUV444ToX( - const BYTE* pSrc[3], const UINT32 srcStep[3], - BYTE* pDst, UINT32 dstStep, - const prim_size_t* roi, const uint8_t rPos, const uint8_t gPos, - const uint8_t bPos, const uint8_t aPos) -{ - UINT32 y; - const UINT32 nWidth = roi->width; - const UINT32 nHeight = roi->height; - const UINT32 yPad = srcStep[0] - roi->width; - const UINT32 uPad = srcStep[1] - roi->width; - const UINT32 vPad = srcStep[2] - roi->width; - const UINT32 dPad = dstStep - roi->width * 4; - const uint8_t* pY = pSrc[0]; - const uint8_t* pU = pSrc[1]; - const uint8_t* pV = pSrc[2]; - uint8_t* pRGB = pDst; - const int16x8_t c128 = vdupq_n_s16(128); - const DWORD pad = nWidth % 8; - - for (y = 0; y < nHeight; y++) - { - UINT32 x; - - for (x = 0; x < nWidth - pad; x += 8) - { - const uint8x8_t Yu = vld1_u8(pY); - const int16x8_t Y = vreinterpretq_s16_u16(vmovl_u8(Yu)); - const uint8x8_t Uu = vld1_u8(pU); - const int16x8_t U = vreinterpretq_s16_u16(vmovl_u8(Uu)); - const uint8x8_t Vu = vld1_u8(pV); - const int16x8_t V = vreinterpretq_s16_u16(vmovl_u8(Vu)); - /* Do the calculations on Y in 32bit width, the result of 255 * 256 does not fit - * a signed 16 bit value. */ - const int16x8_t D = vsubq_s16(U, c128); - const int16x8_t E = vsubq_s16(V, c128); - pRGB = neon_YuvToRgbPixel(pRGB, Y, D, E, rPos, gPos, bPos, aPos); - pY += 8; - pU += 8; - pV += 8; - } - - for (x = 0; x < pad; x++) - { - const BYTE Y = *pY++; - const BYTE U = *pU++; - const BYTE V = *pV++; - const BYTE r = YUV2R(Y, U, V); - const BYTE g = YUV2G(Y, U, V); - const BYTE b = YUV2B(Y, U, V); - pRGB[aPos] = 0xFF; - pRGB[rPos] = r; - pRGB[gPos] = g; - pRGB[bPos] = b; - pRGB += 4; - } - - pRGB += dPad; - pY += yPad; - pU += uPad; - pV += vPad; - } - - return PRIMITIVES_SUCCESS; -} - -static pstatus_t neon_YUV444ToRGB_8u_P3AC4R( - const BYTE* pSrc[3], const UINT32 srcStep[3], - BYTE* pDst, UINT32 dstStep, UINT32 DstFormat, - const prim_size_t* roi) -{ - switch (DstFormat) - { - case PIXEL_FORMAT_BGRA32: - case PIXEL_FORMAT_BGRX32: - return neon_YUV444ToX(pSrc, srcStep, pDst, dstStep, roi, 2, 1, 0, 3); - - case PIXEL_FORMAT_RGBA32: - case PIXEL_FORMAT_RGBX32: - return neon_YUV444ToX(pSrc, srcStep, pDst, dstStep, roi, 0, 1, 2, 3); - - case PIXEL_FORMAT_ARGB32: - case PIXEL_FORMAT_XRGB32: - return neon_YUV444ToX(pSrc, srcStep, pDst, dstStep, roi, 1, 2, 3, 0); - - case PIXEL_FORMAT_ABGR32: - case PIXEL_FORMAT_XBGR32: - return neon_YUV444ToX(pSrc, srcStep, pDst, dstStep, roi, 3, 2, 1, 0); - - default: - return generic->YUV444ToRGB_8u_P3AC4R(pSrc, srcStep, pDst, dstStep, DstFormat, roi); - } -} - -static pstatus_t neon_LumaToYUV444(const BYTE* pSrcRaw[3], const UINT32 srcStep[3], - BYTE* pDstRaw[3], const UINT32 dstStep[3], - const RECTANGLE_16* roi) -{ - UINT32 x, y; - const UINT32 nWidth = roi->right - roi->left; - const UINT32 nHeight = roi->bottom - roi->top; - const UINT32 halfWidth = (nWidth + 1) / 2; - const UINT32 halfHeight = (nHeight + 1) / 2; - const UINT32 evenY = 0; - const BYTE* pSrc[3] = - { - pSrcRaw[0] + roi->top* srcStep[0] + roi->left, - pSrcRaw[1] + roi->top / 2 * srcStep[1] + roi->left / 2, - pSrcRaw[2] + roi->top / 2 * srcStep[2] + roi->left / 2 - }; - BYTE* pDst[3] = - { - pDstRaw[0] + roi->top* dstStep[0] + roi->left, - pDstRaw[1] + roi->top* dstStep[1] + roi->left, - pDstRaw[2] + roi->top* dstStep[2] + roi->left - }; - - /* Y data is already here... */ - /* B1 */ - for (y = 0; y < nHeight; y++) - { - const BYTE* Ym = pSrc[0] + srcStep[0] * y; - BYTE* pY = pDst[0] + dstStep[0] * y; - memcpy(pY, Ym, nWidth); - } - - /* The first half of U, V are already here part of this frame. */ - /* B2 and B3 */ - for (y = 0; y < halfHeight; y++) - { - const UINT32 val2y = (2 * y + evenY); - const BYTE* Um = pSrc[1] + srcStep[1] * y; - const BYTE* Vm = pSrc[2] + srcStep[2] * y; - BYTE* pU = pDst[1] + dstStep[1] * val2y; - BYTE* pV = pDst[2] + dstStep[2] * val2y; - BYTE* pU1 = pU + dstStep[1]; - BYTE* pV1 = pV + dstStep[2]; - - for (x = 0; x + 16 < halfWidth; x += 16) - { - { - const uint8x16_t u = vld1q_u8(Um); - uint8x16x2_t u2x; - u2x.val[0] = u; - u2x.val[1] = u; - vst2q_u8(pU, u2x); - vst2q_u8(pU1, u2x); - Um += 16; - pU += 32; - pU1 += 32; - } - { - const uint8x16_t v = vld1q_u8(Vm); - uint8x16x2_t v2x; - v2x.val[0] = v; - v2x.val[1] = v; - vst2q_u8(pV, v2x); - vst2q_u8(pV1, v2x); - Vm += 16; - pV += 32; - pV1 += 32; - } - } - - for (; x < halfWidth; x++) - { - const BYTE u = *Um++; - const BYTE v = *Vm++; - *pU++ = u; - *pU++ = u; - *pU1++ = u; - *pU1++ = u; - *pV++ = v; - *pV++ = v; - *pV1++ = v; - *pV1++ = v; - } - } - - return PRIMITIVES_SUCCESS; -} - -static pstatus_t neon_ChromaFilter(BYTE* pDst[3], const UINT32 dstStep[3], - const RECTANGLE_16* roi) -{ - const UINT32 oddY = 1; - const UINT32 evenY = 0; - const UINT32 nWidth = roi->right - roi->left; - const UINT32 nHeight = roi->bottom - roi->top; - const UINT32 halfHeight = (nHeight + 1) / 2; - const UINT32 halfWidth = (nWidth + 1) / 2; - const UINT32 halfPad = halfWidth % 16; - UINT32 x, y; - - /* Filter */ - for (y = roi->top; y < halfHeight + roi->top; y++) - { - const UINT32 val2y = (y * 2 + evenY); - const UINT32 val2y1 = val2y + oddY; - BYTE* pU1 = pDst[1] + dstStep[1] * val2y1; - BYTE* pV1 = pDst[2] + dstStep[2] * val2y1; - BYTE* pU = pDst[1] + dstStep[1] * val2y; - BYTE* pV = pDst[2] + dstStep[2] * val2y; - - if (val2y1 > nHeight) - continue; - - for (x = roi->left / 2; x < halfWidth + roi->left / 2 - halfPad; x += 16) - { - { - /* U = (U2x,2y << 2) - U2x1,2y - U2x,2y1 - U2x1,2y1 */ - uint8x8x2_t u = vld2_u8(&pU[2 * x]); - const int16x8_t up = vreinterpretq_s16_u16(vshll_n_u8(u.val[0], 2)); /* Ux2,2y << 2 */ - const uint8x8x2_t u1 = vld2_u8(&pU1[2 * x]); - const uint16x8_t usub = vaddl_u8(u1.val[1], u1.val[0]); /* U2x,2y1 + U2x1,2y1 */ - const int16x8_t us = vreinterpretq_s16_u16(vaddw_u8(usub, - u.val[1])); /* U2x1,2y + U2x,2y1 + U2x1,2y1 */ - const int16x8_t un = vsubq_s16(up, us); - const uint8x8_t u8 = vqmovun_s16(un); /* CLIP(un) */ - u.val[0] = u8; - vst2_u8(&pU[2 * x], u); - } - { - /* V = (V2x,2y << 2) - V2x1,2y - V2x,2y1 - V2x1,2y1 */ - uint8x8x2_t v = vld2_u8(&pV[2 * x]); - const int16x8_t vp = vreinterpretq_s16_u16(vshll_n_u8(v.val[0], 2)); /* Vx2,2y << 2 */ - const uint8x8x2_t v1 = vld2_u8(&pV1[2 * x]); - const uint16x8_t vsub = vaddl_u8(v1.val[1], v1.val[0]); /* V2x,2y1 + V2x1,2y1 */ - const int16x8_t vs = vreinterpretq_s16_u16(vaddw_u8(vsub, - v.val[1])); /* V2x1,2y + V2x,2y1 + V2x1,2y1 */ - const int16x8_t vn = vsubq_s16(vp, vs); - const uint8x8_t v8 = vqmovun_s16(vn); /* CLIP(vn) */ - v.val[0] = v8; - vst2_u8(&pV[2 * x], v); - } - } - - for (; x < halfWidth + roi->left / 2; x++) - { - const UINT32 val2x = (x * 2); - const UINT32 val2x1 = val2x + 1; - const INT32 up = pU[val2x] * 4; - const INT32 vp = pV[val2x] * 4; - INT32 u2020; - INT32 v2020; - - if (val2x1 > nWidth) - continue; - - u2020 = up - pU[val2x1] - pU1[val2x] - pU1[val2x1]; - v2020 = vp - pV[val2x1] - pV1[val2x] - pV1[val2x1]; - pU[val2x] = CLIP(u2020); - pV[val2x] = CLIP(v2020); - } - } - - return PRIMITIVES_SUCCESS; -} - -static pstatus_t neon_ChromaV1ToYUV444(const BYTE* pSrcRaw[3], const UINT32 srcStep[3], - BYTE* pDstRaw[3], const UINT32 dstStep[3], - const RECTANGLE_16* roi) -{ - const UINT32 mod = 16; - UINT32 uY = 0; - UINT32 vY = 0; - UINT32 x, y; - const UINT32 nWidth = roi->right - roi->left; - const UINT32 nHeight = roi->bottom - roi->top; - const UINT32 halfWidth = (nWidth) / 2; - const UINT32 halfHeight = (nHeight) / 2; - const UINT32 oddY = 1; - const UINT32 evenY = 0; - const UINT32 oddX = 1; - /* The auxilary frame is aligned to multiples of 16x16. - * We need the padded height for B4 and B5 conversion. */ - const UINT32 padHeigth = nHeight + 16 - nHeight % 16; - const UINT32 halfPad = halfWidth % 16; - const BYTE* pSrc[3] = - { - pSrcRaw[0] + roi->top* srcStep[0] + roi->left, - pSrcRaw[1] + roi->top / 2 * srcStep[1] + roi->left / 2, - pSrcRaw[2] + roi->top / 2 * srcStep[2] + roi->left / 2 - }; - BYTE* pDst[3] = - { - pDstRaw[0] + roi->top* dstStep[0] + roi->left, - pDstRaw[1] + roi->top* dstStep[1] + roi->left, - pDstRaw[2] + roi->top* dstStep[2] + roi->left - }; - - /* The second half of U and V is a bit more tricky... */ - /* B4 and B5 */ - for (y = 0; y < padHeigth; y++) - { - const BYTE* Ya = pSrc[0] + srcStep[0] * y; - BYTE* pX; - - if ((y) % mod < (mod + 1) / 2) - { - const UINT32 pos = (2 * uY++ + oddY); - - if (pos >= nHeight) - continue; - - pX = pDst[1] + dstStep[1] * pos; - } - else - { - const UINT32 pos = (2 * vY++ + oddY); - - if (pos >= nHeight) - continue; - - pX = pDst[2] + dstStep[2] * pos; - } - - memcpy(pX, Ya, nWidth); - } - - /* B6 and B7 */ - for (y = 0; y < halfHeight; y++) - { - const UINT32 val2y = (y * 2 + evenY); - const BYTE* Ua = pSrc[1] + srcStep[1] * y; - const BYTE* Va = pSrc[2] + srcStep[2] * y; - BYTE* pU = pDst[1] + dstStep[1] * val2y; - BYTE* pV = pDst[2] + dstStep[2] * val2y; - - for (x = 0; x < halfWidth - halfPad; x += 16) - { - { - uint8x16x2_t u = vld2q_u8(&pU[2 * x]); - u.val[1] = vld1q_u8(&Ua[x]); - vst2q_u8(&pU[2 * x], u); - } - { - uint8x16x2_t v = vld2q_u8(&pV[2 * x]); - v.val[1] = vld1q_u8(&Va[x]); - vst2q_u8(&pV[2 * x], v); - } - } - - for (; x < halfWidth; x++) - { - const UINT32 val2x1 = (x * 2 + oddX); - pU[val2x1] = Ua[x]; - pV[val2x1] = Va[x]; - } - } - - /* Filter */ - return neon_ChromaFilter(pDst, dstStep, roi); -} - -static pstatus_t neon_ChromaV2ToYUV444(const BYTE* pSrc[3], const UINT32 srcStep[3], - UINT32 nTotalWidth, UINT32 nTotalHeight, - BYTE* pDst[3], const UINT32 dstStep[3], - const RECTANGLE_16* roi) -{ - UINT32 x, y; - const UINT32 nWidth = roi->right - roi->left; - const UINT32 nHeight = roi->bottom - roi->top; - const UINT32 halfWidth = (nWidth + 1) / 2; - const UINT32 halfPad = halfWidth % 16; - const UINT32 halfHeight = (nHeight + 1) / 2; - const UINT32 quaterWidth = (nWidth + 3) / 4; - const UINT32 quaterPad = quaterWidth % 16; - - /* B4 and B5: odd UV values for width/2, height */ - for (y = 0; y < nHeight; y++) - { - const UINT32 yTop = y + roi->top; - const BYTE* pYaU = pSrc[0] + srcStep[0] * yTop + roi->left / 2; - const BYTE* pYaV = pYaU + nTotalWidth / 2; - BYTE* pU = pDst[1] + dstStep[1] * yTop + roi->left; - BYTE* pV = pDst[2] + dstStep[2] * yTop + roi->left; - - for (x = 0; x < halfWidth - halfPad; x += 16) - { - { - uint8x16x2_t u = vld2q_u8(&pU[2 * x]); - u.val[1] = vld1q_u8(&pYaU[x]); - vst2q_u8(&pU[2 * x], u); - } - { - uint8x16x2_t v = vld2q_u8(&pV[2 * x]); - v.val[1] = vld1q_u8(&pYaV[x]); - vst2q_u8(&pV[2 * x], v); - } - } - - for (; x < halfWidth; x++) - { - const UINT32 odd = 2 * x + 1; - pU[odd] = pYaU[x]; - pV[odd] = pYaV[x]; - } - } - - /* B6 - B9 */ - for (y = 0; y < halfHeight; y++) - { - const BYTE* pUaU = pSrc[1] + srcStep[1] * (y + roi->top / 2) + roi->left / 4; - const BYTE* pUaV = pUaU + nTotalWidth / 4; - const BYTE* pVaU = pSrc[2] + srcStep[2] * (y + roi->top / 2) + roi->left / 4; - const BYTE* pVaV = pVaU + nTotalWidth / 4; - BYTE* pU = pDst[1] + dstStep[1] * (2 * y + 1 + roi->top) + roi->left; - BYTE* pV = pDst[2] + dstStep[2] * (2 * y + 1 + roi->top) + roi->left; - - for (x = 0; x < quaterWidth - quaterPad; x += 16) - { - { - uint8x16x4_t u = vld4q_u8(&pU[4 * x]); - u.val[0] = vld1q_u8(&pUaU[x]); - u.val[2] = vld1q_u8(&pVaU[x]); - vst4q_u8(&pU[4 * x], u); - } - { - uint8x16x4_t v = vld4q_u8(&pV[4 * x]); - v.val[0] = vld1q_u8(&pUaV[x]); - v.val[2] = vld1q_u8(&pVaV[x]); - vst4q_u8(&pV[4 * x], v); - } - } - - for (; x < quaterWidth; x++) - { - pU[4 * x + 0] = pUaU[x]; - pV[4 * x + 0] = pUaV[x]; - pU[4 * x + 2] = pVaU[x]; - pV[4 * x + 2] = pVaV[x]; - } - } - - return neon_ChromaFilter(pDst, dstStep, roi); -} - -static pstatus_t neon_YUV420CombineToYUV444( - avc444_frame_type type, - const BYTE* pSrc[3], const UINT32 srcStep[3], - UINT32 nWidth, UINT32 nHeight, - BYTE* pDst[3], const UINT32 dstStep[3], - const RECTANGLE_16* roi) -{ - if (!pSrc || !pSrc[0] || !pSrc[1] || !pSrc[2]) - return -1; - - if (!pDst || !pDst[0] || !pDst[1] || !pDst[2]) - return -1; - - if (!roi) - return -1; - - switch (type) - { - case AVC444_LUMA: - return neon_LumaToYUV444(pSrc, srcStep, pDst, dstStep, roi); - - case AVC444_CHROMAv1: - return neon_ChromaV1ToYUV444(pSrc, srcStep, pDst, dstStep, roi); - - case AVC444_CHROMAv2: - return neon_ChromaV2ToYUV444(pSrc, srcStep, nWidth, nHeight, pDst, dstStep, roi); - - default: - return -1; - } -} -#endif - void primitives_init_YUV_opt(primitives_t* prims) { generic = primitives_get_generic(); primitives_init_YUV(prims); -#ifdef WITH_SSE2 if (IsProcessorFeaturePresentEx(PF_EX_SSSE3) && IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE)) { prims->RGBToYUV420_8u_P3AC4R = ssse3_RGBToYUV420; prims->RGBToAVC444YUV = ssse3_RGBToAVC444YUV; + prims->RGBToAVC444YUVv2 = ssse3_RGBToAVC444YUVv2; prims->YUV420ToRGB_8u_P3AC4R = ssse3_YUV420ToRGB; prims->YUV444ToRGB_8u_P3AC4R = ssse3_YUV444ToRGB_8u_P3AC4R; prims->YUV420CombineToYUV444 = ssse3_YUV420CombineToYUV444; } - -#elif defined(WITH_NEON) - - if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE)) - { - prims->YUV420ToRGB_8u_P3AC4R = neon_YUV420ToRGB_8u_P3AC4R; - prims->YUV444ToRGB_8u_P3AC4R = neon_YUV444ToRGB_8u_P3AC4R; - prims->YUV420CombineToYUV444 = neon_YUV420CombineToYUV444; - } - -#endif } diff --git a/libfreerdp/primitives/prim_internal.h b/libfreerdp/primitives/prim_internal.h index 3cd7b1d..14bea91 100644 --- a/libfreerdp/primitives/prim_internal.h +++ b/libfreerdp/primitives/prim_internal.h @@ -17,8 +17,8 @@ #ifndef FREERDP_LIB_PRIM_INTERNAL_H #define FREERDP_LIB_PRIM_INTERNAL_H -#ifndef CMAKE_BUILD_TYPE -#define CMAKE_BUILD_TYPE Release +#ifdef HAVE_CONFIG_H +#include "config.h" #endif #include <freerdp/primitives.h> @@ -33,11 +33,17 @@ #endif #endif +#if defined(WITH_SSE2) || defined(WITH_NEON) +#define HAVE_OPTIMIZED_PRIMITIVES 1 +#endif + +#if defined(WITH_SSE2) /* Use lddqu for unaligned; load for 16-byte aligned. */ #define LOAD_SI128(_ptr_) \ (((ULONG_PTR) (_ptr_) & 0x0f) \ ? _mm_lddqu_si128((__m128i *) (_ptr_)) \ : _mm_load_si128((__m128i *) (_ptr_))) +#endif static INLINE BYTE* writePixelBGRX(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, BYTE B, BYTE A) @@ -82,7 +88,7 @@ static INLINE BYTE* writePixelXRGB(BYTE* dst, DWORD formatSize, UINT32 format, static INLINE BYTE* writePixelGeneric(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, BYTE B, BYTE A) { - UINT32 color = GetColor(format, R, G, B, A); + UINT32 color = FreeRDPGetColor(format, R, G, B, A); WriteColor(dst, format, color); return dst + formatSize; } @@ -178,6 +184,7 @@ FREERDP_LOCAL void primitives_init_colors(primitives_t* prims); FREERDP_LOCAL void primitives_init_YCoCg(primitives_t* prims); FREERDP_LOCAL void primitives_init_YUV(primitives_t* prims); +#if defined(WITH_SSE2) || defined(WITH_NEON) FREERDP_LOCAL void primitives_init_copy_opt(primitives_t* prims); FREERDP_LOCAL void primitives_init_set_opt(primitives_t* prims); FREERDP_LOCAL void primitives_init_add_opt(primitives_t* prims); @@ -188,5 +195,6 @@ FREERDP_LOCAL void primitives_init_alphaComp_opt(primitives_t* prims); FREERDP_LOCAL void primitives_init_colors_opt(primitives_t* prims); FREERDP_LOCAL void primitives_init_YCoCg_opt(primitives_t* prims); FREERDP_LOCAL void primitives_init_YUV_opt(primitives_t* prims); +#endif #endif /* FREERDP_LIB_PRIM_INTERNAL_H */ diff --git a/libfreerdp/primitives/primitives.c b/libfreerdp/primitives/primitives.c index 987342a..fd236df 100644 --- a/libfreerdp/primitives/primitives.c +++ b/libfreerdp/primitives/primitives.c @@ -22,6 +22,7 @@ #include <string.h> #include <stdlib.h> +#include <winpr/synch.h> #include <freerdp/primitives.h> #include "prim_internal.h" @@ -29,11 +30,12 @@ /* Singleton pointer used throughout the program when requested. */ static primitives_t pPrimitives = { 0 }; static primitives_t pPrimitivesGeneric = { 0 }; -static BOOL pPrimitivesInitialized = FALSE; -static BOOL pPrimitivesGenericInitialized = FALSE; +static INIT_ONCE generic_primitives_InitOnce = INIT_ONCE_STATIC_INIT; +static INIT_ONCE primitives_InitOnce = INIT_ONCE_STATIC_INIT; + /* ------------------------------------------------------------------------- */ -static void primitives_init_generic(void) +static BOOL CALLBACK primitives_init_generic(PINIT_ONCE once, PVOID param, PVOID* context) { primitives_init_add(&pPrimitivesGeneric); primitives_init_andor(&pPrimitivesGeneric); @@ -45,10 +47,11 @@ static void primitives_init_generic(void) primitives_init_colors(&pPrimitivesGeneric); primitives_init_YCoCg(&pPrimitivesGeneric); primitives_init_YUV(&pPrimitivesGeneric); - pPrimitivesGenericInitialized = TRUE; + return TRUE; } -static void primitives_init(void) +#if defined(HAVE_OPTIMIZED_PRIMITIVES) +static BOOL CALLBACK primitives_init(PINIT_ONCE once, PVOID param, PVOID* context) { /* Now call each section's initialization routine. */ primitives_init_add_opt(&pPrimitives); @@ -61,26 +64,23 @@ static void primitives_init(void) primitives_init_colors_opt(&pPrimitives); primitives_init_YCoCg_opt(&pPrimitives); primitives_init_YUV_opt(&pPrimitives); - pPrimitivesInitialized = TRUE; + return TRUE; } +#endif /* ------------------------------------------------------------------------- */ primitives_t* primitives_get(void) { - if (!pPrimitivesGenericInitialized) - primitives_init_generic(); - - if (!pPrimitivesInitialized) - primitives_init(); - + InitOnceExecuteOnce(&generic_primitives_InitOnce, primitives_init_generic, NULL, NULL); +#if defined(HAVE_OPTIMIZED_PRIMITIVES) + InitOnceExecuteOnce(&primitives_InitOnce, primitives_init, NULL, NULL); +#endif return &pPrimitives; } primitives_t* primitives_get_generic(void) { - if (!pPrimitivesGenericInitialized) - primitives_init_generic(); - + InitOnceExecuteOnce(&generic_primitives_InitOnce, primitives_init_generic, NULL, NULL); return &pPrimitivesGeneric; } diff --git a/libfreerdp/primitives/test/TestPrimitivesAlphaComp.c b/libfreerdp/primitives/test/TestPrimitivesAlphaComp.c index 4073197..92fe2c9 100644 --- a/libfreerdp/primitives/test/TestPrimitivesAlphaComp.c +++ b/libfreerdp/primitives/test/TestPrimitivesAlphaComp.c @@ -75,19 +75,19 @@ static UINT32 colordist( UINT32 c2) { int d, maxd = 0; - d = ABS(ALF(c1) - ALF(c2)); + d = ABS((INT32)(ALF(c1) - ALF(c2))); if (d > maxd) maxd = d; - d = ABS(RED(c1) - RED(c2)); + d = ABS((INT32)(RED(c1) - RED(c2))); if (d > maxd) maxd = d; - d = ABS(GRN(c1) - GRN(c2)); + d = ABS((INT32)(GRN(c1) - GRN(c2))); if (d > maxd) maxd = d; - d = ABS(BLU(c1) - BLU(c2)); + d = ABS((INT32)(BLU(c1) - BLU(c2))); if (d > maxd) maxd = d; diff --git a/libfreerdp/primitives/test/TestPrimitivesColors.c b/libfreerdp/primitives/test/TestPrimitivesColors.c index 1b9b6b1..94efee8 100644 --- a/libfreerdp/primitives/test/TestPrimitivesColors.c +++ b/libfreerdp/primitives/test/TestPrimitivesColors.c @@ -34,10 +34,10 @@ static BOOL test_RGBToRGB_16s8u_P3AC4R_func(prim_size_t roi, DWORD DstFormat) const INT16* ptrs[3]; const UINT32 rgbStride = roi.width * 2; const UINT32 dstStride = roi.width * 4; - PROFILER_DEFINE(genericProf); - PROFILER_DEFINE(optProf); - PROFILER_CREATE(genericProf, "RGBToRGB_16s8u_P3AC4R-GENERIC"); - PROFILER_CREATE(optProf, "RGBToRGB_16s8u_P3AC4R-OPTIMIZED"); + PROFILER_DEFINE(genericProf) + PROFILER_DEFINE(optProf) + PROFILER_CREATE(genericProf, "RGBToRGB_16s8u_P3AC4R-GENERIC") + PROFILER_CREATE(optProf, "RGBToRGB_16s8u_P3AC4R-OPTIMIZED") r = _aligned_malloc(rgbStride * roi.height, 16); g = _aligned_malloc(rgbStride * roi.height, 16); b = _aligned_malloc(rgbStride * roi.height, 16); @@ -69,22 +69,22 @@ static BOOL test_RGBToRGB_16s8u_P3AC4R_func(prim_size_t roi, DWORD DstFormat) ptrs[0] = r; ptrs[1] = g; ptrs[2] = b; - PROFILER_ENTER(genericProf); + PROFILER_ENTER(genericProf) if (generic->RGBToRGB_16s8u_P3AC4R(ptrs, rgbStride, out1, dstStride, DstFormat, &roi) != PRIMITIVES_SUCCESS) goto fail; - PROFILER_EXIT(genericProf); - PROFILER_ENTER(optProf); + PROFILER_EXIT(genericProf) + PROFILER_ENTER(optProf) if (optimized->RGBToRGB_16s8u_P3AC4R(ptrs, rgbStride, out2, dstStride, DstFormat, &roi) != PRIMITIVES_SUCCESS) goto fail; - PROFILER_EXIT(optProf); + PROFILER_EXIT(optProf) if (memcmp(out1, out2, dstStride * roi.height) != 0) { @@ -102,14 +102,14 @@ static BOOL test_RGBToRGB_16s8u_P3AC4R_func(prim_size_t roi, DWORD DstFormat) } } - printf("Results for %"PRIu32"x%"PRIu32" [%s]", roi.width, roi.height, GetColorFormatName(DstFormat)); - PROFILER_PRINT_HEADER; - PROFILER_PRINT(genericProf); - PROFILER_PRINT(optProf); - PROFILER_PRINT_FOOTER; + printf("Results for %"PRIu32"x%"PRIu32" [%s]", roi.width, roi.height, FreeRDPGetColorFormatName(DstFormat)); + PROFILER_PRINT_HEADER + PROFILER_PRINT(genericProf) + PROFILER_PRINT(optProf) + PROFILER_PRINT_FOOTER fail: - PROFILER_FREE(genericProf); - PROFILER_FREE(optProf); + PROFILER_FREE(genericProf) + PROFILER_FREE(optProf) _aligned_free(r); _aligned_free(g); _aligned_free(b); diff --git a/libfreerdp/primitives/test/TestPrimitivesYCbCr.c b/libfreerdp/primitives/test/TestPrimitivesYCbCr.c index 7c28d8a..bbd7758 100644 --- a/libfreerdp/primitives/test/TestPrimitivesYCbCr.c +++ b/libfreerdp/primitives/test/TestPrimitivesYCbCr.c @@ -2167,16 +2167,16 @@ static int test_PrimitivesYCbCr(const primitives_t* prims, UINT32 format, prim_s const UINT32 dstStride = roi.width * GetBytesPerPixel(format); const UINT32 srcSize = srcStride * roi.height; const UINT32 dstSize = dstStride * roi.height; - PROFILER_DEFINE(prof); - PROFILER_DEFINE(prof1); - PROFILER_DEFINE(prof2); + PROFILER_DEFINE(prof) + PROFILER_DEFINE(prof1) + PROFILER_DEFINE(prof2) //return test_YCbCr_pixels(); expected = (BYTE*) TEST_XRGB_IMAGE; actual = _aligned_malloc(dstSize, 16); actual1 = _aligned_malloc(dstSize, 16); - PROFILER_CREATE(prof, "yCbCrToRGB_16s8u"); - PROFILER_CREATE(prof1, "yCbCrToRGB16s16s"); - PROFILER_CREATE(prof2, "RGBToRGB_16s8u"); + PROFILER_CREATE(prof, "yCbCrToRGB_16s8u") + PROFILER_CREATE(prof1, "yCbCrToRGB16s16s") + PROFILER_CREATE(prof2, "RGBToRGB_16s8u") if (!actual || !actual1) goto fail; @@ -2202,14 +2202,14 @@ static int test_PrimitivesYCbCr(const primitives_t* prims, UINT32 format, prim_s } { - PROFILER_ENTER(prof); + PROFILER_ENTER(prof) status = prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**) pYCbCr, srcStride, actual, dstStride, format, &roi); if (status != PRIMITIVES_SUCCESS) goto fail; - PROFILER_EXIT(prof); + PROFILER_EXIT(prof) } { @@ -2220,18 +2220,18 @@ static int test_PrimitivesYCbCr(const primitives_t* prims, UINT32 format, prim_s CopyMemory(pSrcDst[0], pYCbCr[0], srcSize); CopyMemory(pSrcDst[1], pYCbCr[1], srcSize); CopyMemory(pSrcDst[2], pYCbCr[2], srcSize); - PROFILER_ENTER(prof1); + PROFILER_ENTER(prof1) status = prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, srcStride, pSrcDst, srcStride, &roi); - PROFILER_EXIT(prof1); + PROFILER_EXIT(prof1) if (status != PRIMITIVES_SUCCESS) goto fail2; - PROFILER_ENTER(prof2); + PROFILER_ENTER(prof2) status = prims->RGBToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, srcStride, actual1, dstStride, format, &roi); - PROFILER_EXIT(prof2); + PROFILER_EXIT(prof2) fail2: _aligned_free(pSrcDst[0]); _aligned_free(pSrcDst[1]); @@ -2286,20 +2286,20 @@ static int test_PrimitivesYCbCr(const primitives_t* prims, UINT32 format, prim_s } } - PROFILER_PRINT_HEADER; - PROFILER_PRINT(prof); - PROFILER_PRINT(prof1); - PROFILER_PRINT(prof2); - PROFILER_PRINT_FOOTER; + PROFILER_PRINT_HEADER + PROFILER_PRINT(prof) + PROFILER_PRINT(prof1) + PROFILER_PRINT(prof2) + PROFILER_PRINT_FOOTER fail: _aligned_free((BYTE*)pYCbCr[0]); _aligned_free((BYTE*)pYCbCr[1]); _aligned_free((BYTE*)pYCbCr[2]); _aligned_free(actual); _aligned_free(actual1); - PROFILER_FREE(prof); - PROFILER_FREE(prof1); - PROFILER_FREE(prof2); + PROFILER_FREE(prof) + PROFILER_FREE(prof1) + PROFILER_FREE(prof2) return status; } @@ -2329,23 +2329,23 @@ int TestPrimitivesYCbCr(int argc, char* argv[]) prim_size_t roi = { 64, 64 }; int rc; printf("----------------------- GENERIC %s [%"PRIu32"x%"PRIu32"] COMPARE CONTENT ----\n", - GetColorFormatName(formats[x]), roi.width, roi.height); + FreeRDPGetColorFormatName(formats[x]), roi.width, roi.height); rc = test_PrimitivesYCbCr(generics, formats[x], roi, TRUE); if (rc != PRIMITIVES_SUCCESS) return rc; printf("------------------------- END %s ----------------------\n", - GetColorFormatName(formats[x])); + FreeRDPGetColorFormatName(formats[x])); printf("---------------------- OPTIMIZED %s [%"PRIu32"x%"PRIu32"] COMPARE CONTENT ----\n", - GetColorFormatName(formats[x]), roi.width, roi.height); + FreeRDPGetColorFormatName(formats[x]), roi.width, roi.height); rc = test_PrimitivesYCbCr(prims, formats[x], roi, TRUE); if (rc != PRIMITIVES_SUCCESS) return rc; printf("------------------------- END %s ----------------------\n", - GetColorFormatName(formats[x])); + FreeRDPGetColorFormatName(formats[x])); } } /* Do random data conversion with random sizes */ @@ -2370,23 +2370,23 @@ int TestPrimitivesYCbCr(int argc, char* argv[]) { int rc; printf("----------------------- GENERIC %s [%"PRIu32"x%"PRIu32"] COMPARE CONTENT ----\n", - GetColorFormatName(formats[x]), roi.width, roi.height); + FreeRDPGetColorFormatName(formats[x]), roi.width, roi.height); rc = test_PrimitivesYCbCr(generics, formats[x], roi, FALSE); if (rc != PRIMITIVES_SUCCESS) return rc; printf("------------------------- END %s ----------------------\n", - GetColorFormatName(formats[x])); + FreeRDPGetColorFormatName(formats[x])); printf("---------------------- OPTIMIZED %s [%"PRIu32"x%"PRIu32"] COMPARE CONTENT ----\n", - GetColorFormatName(formats[x]), roi.width, roi.height); + FreeRDPGetColorFormatName(formats[x]), roi.width, roi.height); rc = test_PrimitivesYCbCr(prims, formats[x], roi, FALSE); if (rc != PRIMITIVES_SUCCESS) return rc; printf("------------------------- END %s ----------------------\n", - GetColorFormatName(formats[x])); + FreeRDPGetColorFormatName(formats[x])); } } } @@ -2399,23 +2399,23 @@ int TestPrimitivesYCbCr(int argc, char* argv[]) { int rc; printf("----------------------- GENERIC %s [%"PRIu32"x%"PRIu32"] COMPARE CONTENT ----\n", - GetColorFormatName(formats[x]), roi.width, roi.height); + FreeRDPGetColorFormatName(formats[x]), roi.width, roi.height); rc = test_PrimitivesYCbCr(generics, formats[x], roi, FALSE); if (rc != PRIMITIVES_SUCCESS) return rc; printf("------------------------- END %s ----------------------\n", - GetColorFormatName(formats[x])); + FreeRDPGetColorFormatName(formats[x])); printf("---------------------- OPTIMIZED %s [%"PRIu32"x%"PRIu32"] COMPARE CONTENT ----\n", - GetColorFormatName(formats[x]), roi.width, roi.height); + FreeRDPGetColorFormatName(formats[x]), roi.width, roi.height); rc = test_PrimitivesYCbCr(prims, formats[x], roi, FALSE); if (rc != PRIMITIVES_SUCCESS) return rc; printf("------------------------- END %s ----------------------\n", - GetColorFormatName(formats[x])); + FreeRDPGetColorFormatName(formats[x])); } } diff --git a/libfreerdp/primitives/test/TestPrimitivesYCoCg.c b/libfreerdp/primitives/test/TestPrimitivesYCoCg.c index c115336..465319e 100644 --- a/libfreerdp/primitives/test/TestPrimitivesYCoCg.c +++ b/libfreerdp/primitives/test/TestPrimitivesYCoCg.c @@ -43,8 +43,8 @@ static BOOL test_YCoCgRToRGB_8u_AC4R_func(UINT32 width, UINT32 height) PIXEL_FORMAT_BGRA32, PIXEL_FORMAT_BGRX32 }; - PROFILER_DEFINE(genericProf); - PROFILER_DEFINE(optProf); + PROFILER_DEFINE(genericProf) + PROFILER_DEFINE(optProf) in = _aligned_malloc(size, 16); out_c = _aligned_malloc(size, 16); out_sse = _aligned_malloc(size, 16); @@ -58,23 +58,23 @@ static BOOL test_YCoCgRToRGB_8u_AC4R_func(UINT32 width, UINT32 height) { const UINT32 format = formats[x]; const UINT32 dstStride = width * GetBytesPerPixel(format); - const char* formatName = GetColorFormatName(format); - PROFILER_CREATE(genericProf, "YCoCgRToRGB_8u_AC4R-GENERIC"); - PROFILER_CREATE(optProf, "YCoCgRToRGB_8u_AC4R-OPT"); - PROFILER_ENTER(genericProf); + const char* formatName = FreeRDPGetColorFormatName(format); + PROFILER_CREATE(genericProf, "YCoCgRToRGB_8u_AC4R-GENERIC") + PROFILER_CREATE(optProf, "YCoCgRToRGB_8u_AC4R-OPT") + PROFILER_ENTER(genericProf) status = generic->YCoCgToRGB_8u_AC4R( in, srcStride, out_c, format, dstStride, width, height, 2, TRUE); - PROFILER_EXIT(genericProf); + PROFILER_EXIT(genericProf) if (status != PRIMITIVES_SUCCESS) goto loop_fail; - PROFILER_ENTER(optProf); + PROFILER_ENTER(optProf) status = optimized->YCoCgToRGB_8u_AC4R( in, srcStride, out_sse, format, dstStride, width, height, 2, TRUE); - PROFILER_EXIT(optProf); + PROFILER_EXIT(optProf) if (status != PRIMITIVES_SUCCESS) goto loop_fail; @@ -97,13 +97,13 @@ static BOOL test_YCoCgRToRGB_8u_AC4R_func(UINT32 width, UINT32 height) printf("--------------------------- [%s] [%"PRIu32"x%"PRIu32"] ---------------------------\n", formatName, width, height); - PROFILER_PRINT_HEADER; - PROFILER_PRINT(genericProf); - PROFILER_PRINT(optProf); - PROFILER_PRINT_FOOTER; + PROFILER_PRINT_HEADER + PROFILER_PRINT(genericProf) + PROFILER_PRINT(optProf) + PROFILER_PRINT_FOOTER loop_fail: - PROFILER_FREE(genericProf); - PROFILER_FREE(optProf); + PROFILER_FREE(genericProf) + PROFILER_FREE(optProf) if (status != PRIMITIVES_SUCCESS) goto fail; diff --git a/libfreerdp/primitives/test/TestPrimitivesYUV.c b/libfreerdp/primitives/test/TestPrimitivesYUV.c index 1832ba3..8abe04e 100644 --- a/libfreerdp/primitives/test/TestPrimitivesYUV.c +++ b/libfreerdp/primitives/test/TestPrimitivesYUV.c @@ -3,6 +3,8 @@ #include "config.h" #endif +#include <math.h> + #include "prim_test.h" #include <winpr/wlog.h> @@ -174,16 +176,16 @@ static BOOL TestPrimitiveYUVCombine(primitives_t* prims, prim_size_t roi) UINT32 lumaStride[3]; UINT32 chromaStride[3]; UINT32 yuvStride[3]; - size_t padding = 10000; + const size_t padding = 10000; RECTANGLE_16 rect; - PROFILER_DEFINE(yuvCombine); - PROFILER_DEFINE(yuvSplit); + PROFILER_DEFINE(yuvCombine) + PROFILER_DEFINE(yuvSplit) awidth = roi.width + 16 - roi.width % 16; aheight = roi.height + 16 - roi.height % 16; fprintf(stderr, "Running YUVCombine on frame size %"PRIu32"x%"PRIu32" [%"PRIu32"x%"PRIu32"]\n", roi.width, roi.height, awidth, aheight); - PROFILER_CREATE(yuvCombine, "YUV420CombineToYUV444"); - PROFILER_CREATE(yuvSplit, "YUV444SplitToYUV420"); + PROFILER_CREATE(yuvCombine, "YUV420CombineToYUV444") + PROFILER_CREATE(yuvSplit, "YUV444SplitToYUV420") rect.left = 0; rect.top = 0; rect.right = roi.width; @@ -237,14 +239,14 @@ static BOOL TestPrimitiveYUVCombine(primitives_t* prims, prim_size_t roi) goto fail; } - PROFILER_ENTER(yuvCombine); + PROFILER_ENTER(yuvCombine) if (prims->YUV420CombineToYUV444(AVC444_LUMA, (const BYTE**)luma, lumaStride, roi.width, roi.height, yuv, yuvStride, &rect) != PRIMITIVES_SUCCESS) { - PROFILER_EXIT(yuvCombine); + PROFILER_EXIT(yuvCombine) goto fail; } @@ -253,11 +255,11 @@ static BOOL TestPrimitiveYUVCombine(primitives_t* prims, prim_size_t roi) roi.width, roi.height, yuv, yuvStride, &rect) != PRIMITIVES_SUCCESS) { - PROFILER_EXIT(yuvCombine); + PROFILER_EXIT(yuvCombine) goto fail; } - PROFILER_EXIT(yuvCombine); + PROFILER_EXIT(yuvCombine) for (x = 0; x < 3; x++) { @@ -275,16 +277,16 @@ static BOOL TestPrimitiveYUVCombine(primitives_t* prims, prim_size_t roi) goto fail; } - PROFILER_ENTER(yuvSplit); + PROFILER_ENTER(yuvSplit) if (prims->YUV444SplitToYUV420((const BYTE**)yuv, yuvStride, pmain, lumaStride, paux, chromaStride, &roi) != PRIMITIVES_SUCCESS) { - PROFILER_EXIT(yuvSplit); + PROFILER_EXIT(yuvSplit) goto fail; } - PROFILER_EXIT(yuvSplit); + PROFILER_EXIT(yuvSplit) for (x = 0; x < 3; x++) { @@ -344,14 +346,14 @@ static BOOL TestPrimitiveYUVCombine(primitives_t* prims, prim_size_t roi) } } - PROFILER_PRINT_HEADER; - PROFILER_PRINT(yuvSplit); - PROFILER_PRINT(yuvCombine); - PROFILER_PRINT_FOOTER; + PROFILER_PRINT_HEADER + PROFILER_PRINT(yuvSplit) + PROFILER_PRINT(yuvCombine) + PROFILER_PRINT_FOOTER rc = TRUE; fail: - PROFILER_FREE(yuvCombine); - PROFILER_FREE(yuvSplit); + PROFILER_FREE(yuvCombine) + PROFILER_FREE(yuvSplit) for (x = 0; x < 3; x++) { @@ -389,10 +391,10 @@ static BOOL TestPrimitiveYUV(primitives_t* prims, prim_size_t roi, BOOL use444) PIXEL_FORMAT_BGRA32, PIXEL_FORMAT_BGRX32 }; - PROFILER_DEFINE(rgbToYUV420); - PROFILER_DEFINE(rgbToYUV444); - PROFILER_DEFINE(yuv420ToRGB); - PROFILER_DEFINE(yuv444ToRGB); + PROFILER_DEFINE(rgbToYUV420) + PROFILER_DEFINE(rgbToYUV444) + PROFILER_DEFINE(yuv420ToRGB) + PROFILER_DEFINE(yuv444ToRGB) /* Buffers need to be 16x16 aligned. */ awidth = roi.width + 16 - roi.width % 16; aheight = roi.height + 16 - roi.height % 16; @@ -456,41 +458,41 @@ static BOOL TestPrimitiveYUV(primitives_t* prims, prim_size_t roi, BOOL use444) { pstatus_t rc; const UINT32 DstFormat = formats[x]; - printf("Testing destination color format %s\n", GetColorFormatName(DstFormat)); - PROFILER_CREATE(rgbToYUV420, "RGBToYUV420"); - PROFILER_CREATE(rgbToYUV444, "RGBToYUV444"); - PROFILER_CREATE(yuv420ToRGB, "YUV420ToRGB"); - PROFILER_CREATE(yuv444ToRGB, "YUV444ToRGB"); + printf("Testing destination color format %s\n", FreeRDPGetColorFormatName(DstFormat)); + PROFILER_CREATE(rgbToYUV420, "RGBToYUV420") + PROFILER_CREATE(rgbToYUV444, "RGBToYUV444") + PROFILER_CREATE(yuv420ToRGB, "YUV420ToRGB") + PROFILER_CREATE(yuv444ToRGB, "YUV444ToRGB") if (use444) { - PROFILER_ENTER(rgbToYUV444); + PROFILER_ENTER(rgbToYUV444) rc = prims->RGBToYUV444_8u_P3AC4R(rgb, DstFormat, stride, yuv, yuv_step, &roi); - PROFILER_EXIT(rgbToYUV444); + PROFILER_EXIT(rgbToYUV444) if (rc != PRIMITIVES_SUCCESS) goto loop_fail; - PROFILER_PRINT_HEADER; - PROFILER_PRINT(rgbToYUV444); - PROFILER_PRINT_FOOTER; + PROFILER_PRINT_HEADER + PROFILER_PRINT(rgbToYUV444) + PROFILER_PRINT_FOOTER } else { - PROFILER_ENTER(rgbToYUV420); + PROFILER_ENTER(rgbToYUV420) rc = prims->RGBToYUV420_8u_P3AC4R(rgb, DstFormat, stride, yuv, yuv_step, &roi); - PROFILER_EXIT(rgbToYUV420); + PROFILER_EXIT(rgbToYUV420) if (rc != PRIMITIVES_SUCCESS) goto loop_fail; - PROFILER_PRINT_HEADER; - PROFILER_PRINT(rgbToYUV420); - PROFILER_PRINT_FOOTER; + PROFILER_PRINT_HEADER + PROFILER_PRINT(rgbToYUV420) + PROFILER_PRINT_FOOTER } if (!check_padding(rgb, size * sizeof(UINT32), padding, "rgb")) @@ -509,39 +511,39 @@ static BOOL TestPrimitiveYUV(primitives_t* prims, prim_size_t roi, BOOL use444) if (use444) { - PROFILER_ENTER(yuv444ToRGB); + PROFILER_ENTER(yuv444ToRGB) rc = prims->YUV444ToRGB_8u_P3AC4R((const BYTE**)yuv, yuv_step, rgb_dst, stride, DstFormat, &roi); - PROFILER_EXIT(yuv444ToRGB); + PROFILER_EXIT(yuv444ToRGB) if (rc != PRIMITIVES_SUCCESS) goto loop_fail; loop_fail: - PROFILER_EXIT(yuv444ToRGB); - PROFILER_PRINT_HEADER; - PROFILER_PRINT(yuv444ToRGB); - PROFILER_PRINT_FOOTER; + PROFILER_EXIT(yuv444ToRGB) + PROFILER_PRINT_HEADER + PROFILER_PRINT(yuv444ToRGB) + PROFILER_PRINT_FOOTER if (rc != PRIMITIVES_SUCCESS) goto fail; } else { - PROFILER_ENTER(yuv420ToRGB); + PROFILER_ENTER(yuv420ToRGB) if (prims->YUV420ToRGB_8u_P3AC4R((const BYTE**)yuv, yuv_step, rgb_dst, stride, DstFormat, &roi) != PRIMITIVES_SUCCESS) { - PROFILER_EXIT(yuv420ToRGB); + PROFILER_EXIT(yuv420ToRGB) goto fail; } - PROFILER_EXIT(yuv420ToRGB); - PROFILER_PRINT_HEADER; - PROFILER_PRINT(yuv420ToRGB); - PROFILER_PRINT_FOOTER; + PROFILER_EXIT(yuv420ToRGB) + PROFILER_PRINT_HEADER + PROFILER_PRINT(yuv420ToRGB) + PROFILER_PRINT_FOOTER } if (!check_padding(rgb_dst, size * sizeof(UINT32), padding, "rgb dst")) @@ -561,10 +563,10 @@ static BOOL TestPrimitiveYUV(primitives_t* prims, prim_size_t roi, BOOL use444) goto fail; } - PROFILER_FREE(rgbToYUV420); - PROFILER_FREE(rgbToYUV444); - PROFILER_FREE(yuv420ToRGB); - PROFILER_FREE(yuv444ToRGB); + PROFILER_FREE(rgbToYUV420) + PROFILER_FREE(rgbToYUV444) + PROFILER_FREE(yuv420ToRGB) + PROFILER_FREE(yuv444ToRGB) } rc = TRUE; @@ -577,6 +579,299 @@ fail: return rc; } +static BOOL allocate_yuv420(BYTE** planes, UINT32 width, UINT32 height, UINT32 padding) +{ + const size_t size = width * height; + const size_t uvwidth = (width + 1) / 2; + const size_t uvsize = (height + 1) / 2 * uvwidth; + + if (!(planes[0] = set_padding(size, padding))) + goto fail; + + if (!(planes[1] = set_padding(uvsize, padding))) + goto fail; + + if (!(planes[2] = set_padding(uvsize, padding))) + goto fail; + + return TRUE; +fail: + free_padding(planes[0], padding); + free_padding(planes[1], padding); + free_padding(planes[2], padding); + return FALSE; +} + +static void free_yuv420(BYTE** planes, UINT32 padding) +{ + if (!planes) + return; + + free_padding(planes[0], padding); + free_padding(planes[1], padding); + free_padding(planes[2], padding); + planes[0] = NULL; + planes[1] = NULL; + planes[2] = NULL; +} +static BOOL check_yuv420(BYTE** planes, UINT32 width, UINT32 height, UINT32 padding) +{ + const size_t size = width * height; + const size_t uvwidth = (width + 1) / 2; + const size_t uvsize = (height + 1) / 2 * uvwidth; + const BOOL yOk = check_padding(planes[0], size, padding, "Y"); + const BOOL uOk = check_padding(planes[1], uvsize, padding, "U"); + const BOOL vOk = check_padding(planes[2], uvsize, padding, "V"); + return (yOk && uOk && vOk); +} + +static BOOL check_for_mismatches(const BYTE* planeA, const BYTE* planeB, UINT32 size) +{ + BOOL rc = FALSE; + UINT32 x; + + for (x = 0; x < size; x++) + { + const BYTE a = planeA[x]; + const BYTE b = planeB[x]; + + if (fabsf((float)a - (float)b) > 2.0f) + { + rc = TRUE; + fprintf(stderr, "[%08x] %02x != %02x\n", + x, a, b); + } + } + + return rc; +} + +static BOOL compare_yuv420(BYTE** planesA, BYTE** planesB, UINT32 width, UINT32 height, + UINT32 padding) +{ + BOOL rc = TRUE; + const size_t size = width * height; + const size_t uvwidth = (width + 1) / 2; + const size_t uvsize = (height + 1) / 2 * uvwidth; + + if (check_for_mismatches(planesA[0], planesB[0], size)) + { + fprintf(stderr, "Mismatch in Y planes!"); + rc = FALSE; + } + + if (check_for_mismatches(planesA[1], planesB[1], uvsize)) + { + fprintf(stderr, "Mismatch in U planes!"); + rc = FALSE; + } + + if (check_for_mismatches(planesA[2], planesB[2], uvsize)) + { + fprintf(stderr, "Mismatch in V planes!"); + rc = FALSE; + } + + return rc; +} + +static BOOL TestPrimitiveRgbToLumaChroma(primitives_t* prims, prim_size_t roi, UINT32 version) +{ + BOOL rc = FALSE; + UINT32 x, y, cnt; + UINT32 awidth, aheight; + BYTE* luma[3] = {0}; + BYTE* chroma[3] = {0}; + BYTE* lumaGeneric[3] = {0}; + BYTE* chromaGeneric[3] = {0}; + UINT32 yuv_step[3]; + BYTE* rgb = NULL; + size_t size; + size_t uvsize, uvwidth; + const size_t padding = 0x1000; + UINT32 stride; + __RGBToAVC444YUV_t fkt, gen; + const UINT32 formats[] = + { + PIXEL_FORMAT_XRGB32, + PIXEL_FORMAT_XBGR32, + PIXEL_FORMAT_ARGB32, + PIXEL_FORMAT_ABGR32, + PIXEL_FORMAT_RGBA32, + PIXEL_FORMAT_RGBX32, + PIXEL_FORMAT_BGRA32, + PIXEL_FORMAT_BGRX32 + }; + PROFILER_DEFINE(rgbToYUV444) + PROFILER_DEFINE(rgbToYUV444opt) + /* Buffers need to be 16x16 aligned. */ + awidth = roi.width; + + if (awidth % 16 != 0) + awidth += 16 - roi.width % 16; + + aheight = roi.height; + + if (aheight % 16 != 0) + aheight += 16 - roi.height % 16; + + stride = awidth * sizeof(UINT32); + size = awidth * aheight; + uvwidth = (awidth + 1) / 2; + uvsize = (aheight + 1) / 2 * uvwidth; + + if (!prims || !generic) + return FALSE; + + switch (version) + { + case 1: + fkt = prims->RGBToAVC444YUV; + gen = generic->RGBToAVC444YUV; + break; + + case 2: + fkt = prims->RGBToAVC444YUVv2; + gen = generic->RGBToAVC444YUVv2; + break; + + default: + return FALSE; + } + + if (!fkt || !gen) + return FALSE; + + fprintf(stderr, "Running AVC444 on frame size %"PRIu32"x%"PRIu32"\n", + roi.width, roi.height); + + /* Test RGB to YUV444 conversion and vice versa */ + if (!(rgb = set_padding(size * sizeof(UINT32), padding))) + goto fail; + + if (!allocate_yuv420(luma, awidth, aheight, padding)) + goto fail; + + if (!allocate_yuv420(chroma, awidth, aheight, padding)) + goto fail; + + if (!allocate_yuv420(lumaGeneric, awidth, aheight, padding)) + goto fail; + + if (!allocate_yuv420(chromaGeneric, awidth, aheight, padding)) + goto fail; + + for (y = 0; y < roi.height; y++) + { + BYTE* line = &rgb[y * stride]; + + for (x = 0; x < roi.width; x++) + { +#if 1 + line[x * 4 + 0] = rand(); + line[x * 4 + 1] = rand(); + line[x * 4 + 2] = rand(); + line[x * 4 + 3] = rand(); +#else + line[x * 4 + 0] = (y * roi.width + x) * 16 + 5; + line[x * 4 + 1] = (y * roi.width + x) * 16 + 7; + line[x * 4 + 2] = (y * roi.width + x) * 16 + 11; + line[x * 4 + 3] = (y * roi.width + x) * 16 + 0; +#endif + } + } + + yuv_step[0] = awidth; + yuv_step[1] = uvwidth; + yuv_step[2] = uvwidth; + + for (x = 0; x < sizeof(formats) / sizeof(formats[0]); x++) + { + pstatus_t rc; + const UINT32 DstFormat = formats[x]; + printf("Testing destination color format %s\n", FreeRDPGetColorFormatName(DstFormat)); + PROFILER_CREATE(rgbToYUV444, "RGBToYUV444-generic") + PROFILER_CREATE(rgbToYUV444opt, "RGBToYUV444-optimized") + + for (cnt = 0; cnt < 10; cnt++) + { + PROFILER_ENTER(rgbToYUV444opt) + rc = fkt(rgb, DstFormat, stride, luma, yuv_step, chroma, yuv_step, &roi); + PROFILER_EXIT(rgbToYUV444opt) + + if (rc != PRIMITIVES_SUCCESS) + goto loop_fail; + } + + PROFILER_PRINT_HEADER + PROFILER_PRINT(rgbToYUV444opt) + PROFILER_PRINT_FOOTER + + if (!check_padding(rgb, size * sizeof(UINT32), padding, "rgb")) + { + rc = -1; + goto loop_fail; + } + + if (!check_yuv420(luma, awidth, aheight, padding) || + !check_yuv420(chroma, awidth, aheight, padding)) + { + rc = -1; + goto loop_fail; + } + + for (cnt = 0; cnt < 10; cnt++) + { + PROFILER_ENTER(rgbToYUV444) + rc = gen(rgb, DstFormat, stride, lumaGeneric, yuv_step, chromaGeneric, yuv_step, &roi); + PROFILER_EXIT(rgbToYUV444) + + if (rc != PRIMITIVES_SUCCESS) + goto loop_fail; + } + + PROFILER_PRINT_HEADER + PROFILER_PRINT(rgbToYUV444) + PROFILER_PRINT_FOOTER + + if (!check_padding(rgb, size * sizeof(UINT32), padding, "rgb")) + { + rc = -1; + goto loop_fail; + } + + if (!check_yuv420(lumaGeneric, awidth, aheight, padding) || + !check_yuv420(chromaGeneric, awidth, aheight, padding)) + { + rc = -1; + goto loop_fail; + } + + if (!compare_yuv420(luma, lumaGeneric, awidth, aheight, padding) || + !compare_yuv420(chroma, chromaGeneric, awidth, aheight, padding)) + { + rc = -1; + goto loop_fail; + } + + loop_fail: + PROFILER_FREE(rgbToYUV444) + PROFILER_FREE(rgbToYUV444opt) + + if (rc != PRIMITIVES_SUCCESS) + goto fail; + } + + rc = TRUE; +fail: + free_padding(rgb, padding); + free_yuv420(luma, padding); + free_yuv420(chroma, padding); + free_yuv420(lumaGeneric, padding); + free_yuv420(chromaGeneric, padding); + return rc; +} + int TestPrimitivesYUV(int argc, char* argv[]) { BOOL large = (argc > 1); @@ -584,7 +879,6 @@ int TestPrimitivesYUV(int argc, char* argv[]) int rc = -1; prim_test_setup(FALSE); primitives_t* prims = primitives_get(); - primitives_t* generic = primitives_get_generic(); for (x = 0; x < 10; x++) { @@ -592,8 +886,13 @@ int TestPrimitivesYUV(int argc, char* argv[]) if (argc > 1) { - roi.width = 1920; - roi.height = 1080; + int rc = sscanf(argv[1], "%"PRIu32"x%"PRIu32, &roi.width, &roi.height); + + if (rc != 2) + { + roi.width = 1920; + roi.height = 1080; + } } else get_size(large, &roi.width, &roi.height); @@ -607,7 +906,6 @@ int TestPrimitivesYUV(int argc, char* argv[]) } printf("---------------------- END --------------------------\n"); -#if 1 printf("------------------- OPTIMIZED -----------------------\n"); if (!TestPrimitiveYUV(prims, roi, TRUE)) @@ -617,7 +915,6 @@ int TestPrimitivesYUV(int argc, char* argv[]) } printf("---------------------- END --------------------------\n"); -#endif printf("-------------------- GENERIC ------------------------\n"); if (!TestPrimitiveYUV(generic, roi, FALSE)) @@ -653,6 +950,24 @@ int TestPrimitivesYUV(int argc, char* argv[]) goto end; } + printf("---------------------- END --------------------------\n"); + printf("------------------- OPTIMIZED -----------------------\n"); + + if (!TestPrimitiveRgbToLumaChroma(prims, roi, 1)) + { + printf("TestPrimitiveRgbToLumaChroma failed.\n"); + goto end; + } + + printf("---------------------- END --------------------------\n"); + printf("-------------------- GENERIC ------------------------\n"); + + if (!TestPrimitiveRgbToLumaChroma(prims, roi, 2)) + { + printf("TestPrimitiveYUVCombine failed.\n"); + goto end; + } + printf("---------------------- END --------------------------\n"); } diff --git a/libfreerdp/utils/pcap.c b/libfreerdp/utils/pcap.c index e6224ce..11a277b 100644 --- a/libfreerdp/utils/pcap.c +++ b/libfreerdp/utils/pcap.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <freerdp/log.h> @@ -138,7 +139,7 @@ BOOL pcap_add_record(rdpPcap* pcap, void* data, UINT32 length) BOOL pcap_has_next_record(rdpPcap* pcap) { - if (pcap->file_size - (ftell(pcap->fp)) <= 16) + if (pcap->file_size - (_ftelli64(pcap->fp)) <= 16) return FALSE; return TRUE; @@ -201,9 +202,9 @@ rdpPcap* pcap_open(char* name, BOOL write) } else { - fseek(pcap->fp, 0, SEEK_END); - pcap->file_size = (int) ftell(pcap->fp); - fseek(pcap->fp, 0, SEEK_SET); + _fseeki64(pcap->fp, 0, SEEK_END); + pcap->file_size = _ftelli64(pcap->fp); + _fseeki64(pcap->fp, 0, SEEK_SET); if (!pcap_read_header(pcap, &pcap->header)) goto fail; } diff --git a/packaging/deb/freerdp-nightly/control b/packaging/deb/freerdp-nightly/control index aafadd5..b491b58 100644 --- a/packaging/deb/freerdp-nightly/control +++ b/packaging/deb/freerdp-nightly/control @@ -5,6 +5,7 @@ Maintainer: FreeRDP <team@freerdp.com> Build-Depends: debhelper (>= 9), cdbs, + dpkg-dev, autotools-dev, cmake, pkg-config, diff --git a/packaging/deb/freerdp-nightly/freerdp-nightly.install b/packaging/deb/freerdp-nightly/freerdp-nightly.install index e50b5a6..1b576fe 100644 --- a/packaging/deb/freerdp-nightly/freerdp-nightly.install +++ b/packaging/deb/freerdp-nightly/freerdp-nightly.install @@ -1,7 +1,4 @@ opt/freerdp-nightly/lib/*.so.* opt/freerdp-nightly/bin -opt/freerdp-nightly/share/man/man1/freerdp-shadow-cli.1* -opt/freerdp-nightly/share/man/man1/winpr-makecert.1* -opt/freerdp-nightly/share/man/man1/winpr-hash.1* -opt/freerdp-nightly/share/man/man1/xfreerdp.1* +opt/freerdp-nightly/share/man/man1/*.1* opt/freerdp-nightly/share/man/man7/wlog.7* diff --git a/packaging/deb/freerdp-nightly/rules b/packaging/deb/freerdp-nightly/rules index 5cf2d9e..97ba26a 100755 --- a/packaging/deb/freerdp-nightly/rules +++ b/packaging/deb/freerdp-nightly/rules @@ -2,6 +2,10 @@ NULL = +DEB_HOST_ARCH=$(shell dpkg-architecture -qDEB_HOST_ARCH) + +SANATIZE_ADDRESS = -DWITH_SANITIZE_ADDRESS=ON + DEB_CMAKE_EXTRA_FLAGS := -DCMAKE_SKIP_RPATH=FALSE \ -DCMAKE_SKIP_INSTALL_RPATH=FALSE \ -DWITH_PULSE=ON \ @@ -16,10 +20,11 @@ DEB_CMAKE_EXTRA_FLAGS := -DCMAKE_SKIP_RPATH=FALSE \ -DCHANNEL_URBDRC_CLIENT=ON \ -DWITH_SERVER=ON \ -DBUILD_TESTING=OFF \ - -DCMAKE_BUILD_TYPE=RELWITHDEBINFO \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_INSTALL_PREFIX=/opt/freerdp-nightly/ \ -DCMAKE_INSTALL_INCLUDEDIR=include \ -DCMAKE_INSTALL_LIBDIR=lib \ + $(SANATIZE_ADDRESS) \ $(NULL) %: diff --git a/packaging/rpm/freerdp-nightly.spec b/packaging/rpm/freerdp-nightly.spec index a53206a..602c620 100644 --- a/packaging/rpm/freerdp-nightly.spec +++ b/packaging/rpm/freerdp-nightly.spec @@ -7,6 +7,15 @@ %define INSTALL_PREFIX /opt/freerdp-nightly/ + +# do not add provides for libs provided by this package +# or it could possibly mess with system provided packages +# which depend on freerdp libs +%global __provides_exclude_from ^%{INSTALL_PREFIX}.*$ + +# do not require our own libs +%global __requires_exclude ^(libfreerdp.*|libwinpr).*$ + Name: freerdp-nightly Version: 2.0 Release: 0 @@ -16,6 +25,7 @@ Url: http://www.freerdp.com Group: Productivity/Networking/Other Source0: %{name}-%{version}.tar.bz2 #Source1: %{name}-rpmlintrc +Source1: source_version BuildRequires: gcc-c++ BuildRequires: cmake >= 2.8.12 BuildRequires: libxkbfile-devel @@ -35,6 +45,7 @@ BuildRequires: pcsc-lite-devel BuildRequires: uuid-devel BuildRequires: libxml2-devel BuildRequires: zlib-devel +BuildRequires: krb5-devel # (Open)Suse %if %{defined suse_version} @@ -55,7 +66,7 @@ BuildRequires: libjpeg-devel BuildRequires: libavutil-devel %endif # fedora 21+ -%if 0%{?fedora} >= 21 +%if 0%{?fedora} >= 21 || 0%{?rhel} >= 7 BuildRequires: docbook-style-xsl BuildRequires: libxslt BuildRequires: pkgconfig @@ -68,10 +79,13 @@ BuildRequires: systemd-devel BuildRequires: dbus-glib-devel BuildRequires: gstreamer1-devel BuildRequires: gstreamer1-plugins-base-devel -BuildRequires: libwayland-client-devel BuildRequires: libjpeg-turbo-devel %endif +%if 0%{?fedora} >= 21 || 0%{?rhel} >= 8 +BuildRequires: libwayland-client-devel +%endif + BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -89,8 +103,11 @@ based on freerdp and winpr. %prep %setup -q +cd %{_topdir}/BUILD +cp %{_topdir}/SOURCES/source_version freerdp-nightly-%{version}/.source_version %build + %cmake -DCMAKE_SKIP_RPATH=FALSE \ -DCMAKE_SKIP_INSTALL_RPATH=FALSE \ -DWITH_PULSE=ON \ @@ -101,14 +118,20 @@ based on freerdp and winpr. -DWITH_JPEG=ON \ -DWITH_GSTREAMER_0_10=ON \ -DWITH_GSM=ON \ +%if %{defined rhel} && 0%{?rhel} <= 7 + -DWITH_WAYLAND=OFF \ +%endif + -DWITH_GSSAPI=ON \ -DCHANNEL_URBDRC=ON \ -DCHANNEL_URBDRC_CLIENT=ON \ -DWITH_SERVER=ON \ -DBUILD_TESTING=OFF \ - -DCMAKE_BUILD_TYPE=RELWITHDEBINFO \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_INSTALL_PREFIX=%{INSTALL_PREFIX} \ %if %{defined suse_version} - -DCMAKE_NO_BUILTIN_CHRPATH=ON \ + -DCMAKE_NO_BUILTIN_CHRPATH=ON \ +%else + -DWITH_SANITIZE_ADDRESS=ON \ %endif -DCMAKE_INSTALL_LIBDIR=%{_lib} @@ -119,7 +142,7 @@ make %{?_smp_mflags} %cmake_install %endif -%if %{defined fedora} +%if %{defined fedora} || %{defined rhel} rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %endif @@ -158,7 +181,7 @@ export NO_BRP_CHECK_RPATH true %changelog -* Tue Nov 16 2015 FreeRDP Team <team@freerdp.com> - 2.0.0-0 +* Wed Feb 7 2018 FreeRDP Team <team@freerdp.com> - 2.0.0-0 - Update version information and support for OpenSuse 42.1 * Tue Feb 03 2015 FreeRDP Team <team@freerdp.com> - 1.2.1-0 - Update version information diff --git a/packaging/scripts/prepare_deb_freerdp-nightly.sh b/packaging/scripts/prepare_deb_freerdp-nightly.sh index 318e112..a465491 100755 --- a/packaging/scripts/prepare_deb_freerdp-nightly.sh +++ b/packaging/scripts/prepare_deb_freerdp-nightly.sh @@ -1,3 +1,4 @@ #!/bin/sh ln -s packaging/deb/freerdp-nightly debian +git rev-parse --short HEAD > .source_version diff --git a/packaging/scripts/prepare_rpm_freerdp-nightly.sh b/packaging/scripts/prepare_rpm_freerdp-nightly.sh new file mode 100755 index 0000000..5401a81 --- /dev/null +++ b/packaging/scripts/prepare_rpm_freerdp-nightly.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +git rev-parse --short HEAD > source_version diff --git a/rdtk/CMakeLists.txt b/rdtk/CMakeLists.txt index 9028678..764a545 100644 --- a/rdtk/CMakeLists.txt +++ b/rdtk/CMakeLists.txt @@ -34,7 +34,6 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/) # Check for cmake compatibility (enable/disable features) include(CheckCmakeCompat) include(FindFeature) -include(AutoVersioning) include(ConfigOptions) include(CheckCCompilerFlag) include(GNUInstallDirsWrapper) diff --git a/rdtk/librdtk/rdtk_font.c b/rdtk/librdtk/rdtk_font.c index 7d341df..97a13f1 100644 --- a/rdtk/librdtk/rdtk_font.c +++ b/rdtk/librdtk/rdtk_font.c @@ -20,6 +20,9 @@ #include "config.h" #endif +#include <errno.h> + +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <winpr/path.h> #include <winpr/print.h> @@ -156,9 +159,9 @@ static char* rdtk_font_load_descriptor_file(const char* filename, int* pSize) if (!fp) return NULL; - fseek(fp, 0, SEEK_END); - fileSize = ftell(fp); - fseek(fp, 0, SEEK_SET); + _fseeki64(fp, 0, SEEK_END); + fileSize = _ftelli64(fp); + _fseeki64(fp, 0, SEEK_SET); if (fileSize < 1) { @@ -273,7 +276,15 @@ static int rdtk_font_parse_descriptor_buffer(rdtkFont* font, BYTE* buffer, int s return -1; *q = '\0'; - font->size = atoi(p); + errno = 0; + { + long val = strtol(p, NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + return -1; + + font->size = val; + } *q = '"'; if (font->size <= 0) @@ -313,7 +324,15 @@ static int rdtk_font_parse_descriptor_buffer(rdtkFont* font, BYTE* buffer, int s return -1; *q = '\0'; - font->height = atoi(p); + errno = 0; + { + long val = strtol(p, NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + return -1; + + font->height = val; + } *q = '"'; if (font->height <= 0) @@ -405,7 +424,15 @@ static int rdtk_font_parse_descriptor_buffer(rdtkFont* font, BYTE* buffer, int s return -1; *q = '\0'; - glyph->width = atoi(p); + errno = 0; + { + long val = strtoul(p, NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + return -1; + + glyph->width = val; + } *q = '"'; if (glyph->width < 0) @@ -433,8 +460,23 @@ static int rdtk_font_parse_descriptor_buffer(rdtkFont* font, BYTE* buffer, int s *p = 0; tok[1] = p + 1; - glyph->offsetX = atoi(tok[0]); - glyph->offsetY = atoi(tok[1]); + errno = 0; + { + long val = strtol(tok[0], NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + return -1; + + glyph->offsetX = val; + } + { + long val = strtol(tok[1], NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + return -1; + + glyph->offsetY = val; + } *q = '"'; p = q + 1; /* parse glyph rect x,y,w,h */ @@ -472,10 +514,39 @@ static int rdtk_font_parse_descriptor_buffer(rdtkFont* font, BYTE* buffer, int s *p = 0; tok[3] = p + 1; - glyph->rectX = atoi(tok[0]); - glyph->rectY = atoi(tok[1]); - glyph->rectWidth = atoi(tok[2]); - glyph->rectHeight = atoi(tok[3]); + errno = 0; + { + long val = strtol(tok[0], NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + return -1; + + glyph->rectX = val; + } + { + long val = strtol(tok[1], NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + return -1; + + glyph->rectY = val; + } + { + long val = strtol(tok[2], NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + return -1; + + glyph->rectWidth = val; + } + { + long val = strtol(tok[3], NULL, 0); + + if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX)) + return -1; + + glyph->rectHeight = val; + } *q = '"'; p = q + 1; /* parse code */ @@ -513,7 +584,6 @@ static int rdtk_font_load_descriptor(rdtkFont* font, const char* filename) return rdtk_font_parse_descriptor_buffer(font, (BYTE*) buffer, size); } - rdtkFont* rdtk_font_new(rdtkEngine* engine, const char* path, const char* file) { int status; @@ -588,7 +658,6 @@ cleanup: return NULL; } - static rdtkFont* rdtk_embedded_font_new(rdtkEngine* engine, BYTE* imageData, int imageSize, BYTE* descriptorData, int descriptorSize) { @@ -642,7 +711,6 @@ static rdtkFont* rdtk_embedded_font_new(rdtkEngine* engine, BYTE* imageData, int return font; } - void rdtk_font_free(rdtkFont* font) { if (font) @@ -654,7 +722,6 @@ void rdtk_font_free(rdtkFont* font) free(font); } } - int rdtk_font_engine_init(rdtkEngine* engine) { if (!engine->font) @@ -675,7 +742,6 @@ int rdtk_font_engine_init(rdtkEngine* engine) return 1; } - int rdtk_font_engine_uninit(rdtkEngine* engine) { if (engine->font) diff --git a/rdtk/librdtk/rdtk_nine_patch.c b/rdtk/librdtk/rdtk_nine_patch.c index ccac2c2..818332f 100644 --- a/rdtk/librdtk/rdtk_nine_patch.c +++ b/rdtk/librdtk/rdtk_nine_patch.c @@ -30,11 +30,7 @@ int rdtk_image_copy_alpha_blend(BYTE* pDstData, int nDstStep, int nXDst, int nYD int nWidth, int nHeight, BYTE* pSrcData, int nSrcStep, int nXSrc, int nYSrc) { int x, y; - int nSrcPad; - int nDstPad; BYTE A, R, G, B; - nSrcPad = (nSrcStep - (nWidth * 4)); - nDstPad = (nDstStep - (nWidth * 4)); for (y = 0; y < nHeight; y++) { @@ -268,7 +264,7 @@ int rdtk_nine_patch_set_image(rdtkNinePatch* ninePatch, wImage* image) } } - pixel = (UINT32*) &((BYTE*) pixel)[scanline]; + pixel = (UINT32*) & ((BYTE*) pixel)[scanline]; } ninePatch->scaleTop = beg - 1; @@ -323,7 +319,7 @@ int rdtk_nine_patch_set_image(rdtkNinePatch* ninePatch, wImage* image) } } - pixel = (UINT32*) &((BYTE*) pixel)[scanline]; + pixel = (UINT32*) & ((BYTE*) pixel)[scanline]; } ninePatch->fillTop = beg - 1; diff --git a/rdtk/sample/rdtk_x11.c b/rdtk/sample/rdtk_x11.c index dbe8c27..9e1a7a2 100644 --- a/rdtk/sample/rdtk_x11.c +++ b/rdtk/sample/rdtk_x11.c @@ -24,6 +24,7 @@ #include <rdtk/rdtk.h> #include <X11/Xlib.h> +#include <X11/Xutil.h> #define TAG "rdtk.sample" @@ -60,7 +61,7 @@ int main(int argc, char** argv) if (!display) { WLog_ERR(TAG, "Cannot open display"); - exit(1); + return 1; } x = 10; @@ -142,7 +143,8 @@ int main(int argc, char** argv) } XFlush(display); - + + XDestroyImage(image); XCloseDisplay(display); rdtk_surface_free(surface); diff --git a/scripts/.gitignore b/scripts/.gitignore index 840af4a..9fc9024 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -1,2 +1,4 @@ !*.sh regenerate_jni_headers.sh +WindowsZones.txt +TimeZones.txt diff --git a/scripts/TimeZones.cs b/scripts/TimeZones.cs deleted file mode 100644 index 33459ba..0000000 --- a/scripts/TimeZones.cs +++ /dev/null @@ -1,230 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Time Zone Redirection Table Generator - * - * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.IO; -using System.Globalization; -using System.Collections.ObjectModel; - -namespace TimeZones -{ - struct SYSTEM_TIME_ENTRY - { - public UInt16 wYear; - public UInt16 wMonth; - public UInt16 wDayOfWeek; - public UInt16 wDay; - public UInt16 wHour; - public UInt16 wMinute; - public UInt16 wSecond; - public UInt16 wMilliseconds; - }; - - struct TIME_ZONE_RULE_ENTRY - { - public long TicksStart; - public long TicksEnd; - public Int32 DaylightDelta; - public SYSTEM_TIME_ENTRY StandardDate; - public SYSTEM_TIME_ENTRY DaylightDate; - }; - - struct TIME_ZONE_ENTRY - { - public string Id; - public Int32 Bias; - public bool SupportsDST; - public string DisplayName; - public string StandardName; - public string DaylightName; - public string RuleTable; - public UInt32 RuleTableCount; - }; - - class TimeZones - { - static void Main(string[] args) - { - int i; - UInt32 index; - const string file = @"TimeZones.txt"; - TimeZoneInfo.AdjustmentRule[] rules; - StreamWriter stream = new StreamWriter(file, false); - ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones(); - - stream.WriteLine(); - - stream.WriteLine("struct _TIME_ZONE_RULE_ENTRY"); - stream.WriteLine("{"); - stream.WriteLine("\tUINT64 TicksStart;"); - stream.WriteLine("\tUINT64 TicksEnd;"); - stream.WriteLine("\tINT32 DaylightDelta;"); - stream.WriteLine("\tSYSTEMTIME StandardDate;"); - stream.WriteLine("\tSYSTEMTIME DaylightDate;"); - stream.WriteLine("};"); - stream.WriteLine("typedef struct _TIME_ZONE_RULE_ENTRY TIME_ZONE_RULE_ENTRY;"); - stream.WriteLine(); - - stream.WriteLine("struct _TIME_ZONE_ENTRY"); - stream.WriteLine("{"); - stream.WriteLine("\tconst char* Id;"); - stream.WriteLine("\tINT32 Bias;"); - stream.WriteLine("\tBOOL SupportsDST;"); - stream.WriteLine("\tconst char* DisplayName;"); - stream.WriteLine("\tconst char* StandardName;"); - stream.WriteLine("\tconst char* DaylightName;"); - stream.WriteLine("\tTIME_ZONE_RULE_ENTRY* RuleTable;"); - stream.WriteLine("\tUINT32 RuleTableCount;"); - stream.WriteLine("};"); - stream.WriteLine("typedef struct _TIME_ZONE_ENTRY TIME_ZONE_ENTRY;"); - stream.WriteLine(); - - index = 0; - - foreach (TimeZoneInfo timeZone in timeZones) - { - rules = timeZone.GetAdjustmentRules(); - - if ((!timeZone.SupportsDaylightSavingTime) || (rules.Length < 1)) - { - index++; - continue; - } - - stream.WriteLine("static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_{0}[] =", index); - stream.WriteLine("{"); - - i = 0; - foreach (TimeZoneInfo.AdjustmentRule rule in rules) - { - DateTime time; - TIME_ZONE_RULE_ENTRY tzr; - TimeZoneInfo.TransitionTime transition; - - tzr.TicksStart = rule.DateEnd.ToUniversalTime().Ticks; - tzr.TicksEnd = rule.DateStart.ToUniversalTime().Ticks; - tzr.DaylightDelta = (Int32)rule.DaylightDelta.TotalMinutes; - - transition = rule.DaylightTransitionEnd; - time = transition.TimeOfDay; - - tzr.StandardDate.wYear = (UInt16)0; - tzr.StandardDate.wMonth = (UInt16)transition.Month; - tzr.StandardDate.wDayOfWeek = (UInt16)transition.DayOfWeek; - tzr.StandardDate.wDay = (UInt16)transition.Week; - tzr.StandardDate.wHour = (UInt16)time.Hour; - tzr.StandardDate.wMinute = (UInt16)time.Minute; - tzr.StandardDate.wSecond = (UInt16)time.Second; - tzr.StandardDate.wMilliseconds = (UInt16)time.Millisecond; - - transition = rule.DaylightTransitionStart; - time = transition.TimeOfDay; - - tzr.DaylightDate.wYear = (UInt16)0; - tzr.DaylightDate.wMonth = (UInt16)transition.Month; - tzr.DaylightDate.wDayOfWeek = (UInt16)transition.DayOfWeek; - tzr.DaylightDate.wDay = (UInt16)transition.Week; - tzr.DaylightDate.wHour = (UInt16)time.Hour; - tzr.DaylightDate.wMinute = (UInt16)time.Minute; - tzr.DaylightDate.wSecond = (UInt16)time.Second; - tzr.DaylightDate.wMilliseconds = (UInt16)time.Millisecond; - - stream.Write("\t{"); - stream.Write(" {0}ULL, {1}ULL, {2},", tzr.TicksStart, tzr.TicksEnd, tzr.DaylightDelta); - - stream.Write(" { "); - stream.Write("{0}, {1}, {2}, {3}, {4}, {5}", - tzr.StandardDate.wYear, tzr.StandardDate.wMonth, tzr.StandardDate.wDayOfWeek, - tzr.StandardDate.wDay, tzr.StandardDate.wHour, tzr.StandardDate.wMinute, - tzr.StandardDate.wSecond, tzr.StandardDate.wMilliseconds); - stream.Write(" }, "); - - stream.Write("{ "); - stream.Write("{0}, {1}, {2}, {3}, {4}, {5}", - tzr.DaylightDate.wYear, tzr.DaylightDate.wMonth, tzr.DaylightDate.wDayOfWeek, - tzr.DaylightDate.wDay, tzr.DaylightDate.wHour, tzr.DaylightDate.wMinute, - tzr.DaylightDate.wSecond, tzr.DaylightDate.wMilliseconds); - stream.Write(" },"); - - if (++i < rules.Length) - stream.WriteLine(" },"); - else - stream.WriteLine(" }"); - } - - stream.WriteLine("};"); - stream.WriteLine(); - index++; - } - - index = 0; - stream.WriteLine("static const TIME_ZONE_ENTRY TimeZoneTable[] ="); - stream.WriteLine("{"); - - foreach (TimeZoneInfo timeZone in timeZones) - { - TIME_ZONE_ENTRY tz; - TimeSpan offset = timeZone.BaseUtcOffset; - - rules = timeZone.GetAdjustmentRules(); - - tz.Id = timeZone.Id; - tz.Bias = -(Int32)offset.TotalMinutes; - - tz.SupportsDST = timeZone.SupportsDaylightSavingTime; - - tz.DisplayName = timeZone.DisplayName; - tz.StandardName = timeZone.StandardName; - tz.DaylightName = timeZone.DaylightName; - - if ((!tz.SupportsDST) || (rules.Length < 1)) - { - tz.RuleTableCount = 0; - tz.RuleTable = "NULL"; - } - else - { - tz.RuleTableCount = (UInt32)rules.Length; - tz.RuleTable = "&TimeZoneRuleTable_" + index; - tz.RuleTable = "(TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_" + index; - } - - stream.WriteLine("\t{"); - - stream.WriteLine("\t\t\"{0}\", {1}, {2}, \"{3}\",", - tz.Id, tz.Bias, tz.SupportsDST ? "TRUE" : "FALSE", tz.DisplayName); - - stream.WriteLine("\t\t\"{0}\", \"{1}\",", tz.StandardName, tz.DaylightName); - stream.WriteLine("\t\t{0}, {1}", tz.RuleTable, tz.RuleTableCount); - - index++; - - if ((int)index < timeZones.Count) - stream.WriteLine("\t},"); - else - stream.WriteLine("\t}"); - } - stream.WriteLine("};"); - stream.WriteLine(); - - stream.Close(); - } - } -} - diff --git a/scripts/TimeZones.csx b/scripts/TimeZones.csx new file mode 100644 index 0000000..c0dbfd9 --- /dev/null +++ b/scripts/TimeZones.csx @@ -0,0 +1,221 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Time Zone Redirection Table Generator + * + * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.IO; +using System.Globalization; +using System.Collections.ObjectModel; + +struct SYSTEM_TIME_ENTRY +{ + public UInt16 wYear; + public UInt16 wMonth; + public UInt16 wDayOfWeek; + public UInt16 wDay; + public UInt16 wHour; + public UInt16 wMinute; + public UInt16 wSecond; + public UInt16 wMilliseconds; +}; + +struct TIME_ZONE_RULE_ENTRY +{ + public long TicksStart; + public long TicksEnd; + public Int32 DaylightDelta; + public SYSTEM_TIME_ENTRY StandardDate; + public SYSTEM_TIME_ENTRY DaylightDate; +}; + +struct TIME_ZONE_ENTRY +{ + public string Id; + public Int32 Bias; + public bool SupportsDST; + public string DisplayName; + public string StandardName; + public string DaylightName; + public string RuleTable; + public UInt32 RuleTableCount; +}; + +int i; +UInt32 index; +const string file = @"TimeZones.txt"; +TimeZoneInfo.AdjustmentRule[] rules; +StreamWriter stream = new StreamWriter(file, false); +ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones(); + +stream.WriteLine(); + +stream.WriteLine("struct _TIME_ZONE_RULE_ENTRY"); +stream.WriteLine("{"); +stream.WriteLine("\tUINT64 TicksStart;"); +stream.WriteLine("\tUINT64 TicksEnd;"); +stream.WriteLine("\tINT32 DaylightDelta;"); +stream.WriteLine("\tSYSTEMTIME StandardDate;"); +stream.WriteLine("\tSYSTEMTIME DaylightDate;"); +stream.WriteLine("};"); +stream.WriteLine("typedef struct _TIME_ZONE_RULE_ENTRY TIME_ZONE_RULE_ENTRY;"); +stream.WriteLine(); + +stream.WriteLine("struct _TIME_ZONE_ENTRY"); +stream.WriteLine("{"); +stream.WriteLine("\tconst char* Id;"); +stream.WriteLine("\tINT32 Bias;"); +stream.WriteLine("\tBOOL SupportsDST;"); +stream.WriteLine("\tconst char* DisplayName;"); +stream.WriteLine("\tconst char* StandardName;"); +stream.WriteLine("\tconst char* DaylightName;"); +stream.WriteLine("\tTIME_ZONE_RULE_ENTRY* RuleTable;"); +stream.WriteLine("\tUINT32 RuleTableCount;"); +stream.WriteLine("};"); +stream.WriteLine("typedef struct _TIME_ZONE_ENTRY TIME_ZONE_ENTRY;"); +stream.WriteLine(); + +index = 0; + +foreach (TimeZoneInfo timeZone in timeZones) +{ + rules = timeZone.GetAdjustmentRules(); + + if ((!timeZone.SupportsDaylightSavingTime) || (rules.Length < 1)) + { + index++; + continue; + } + + stream.WriteLine("static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_{0}[] =", index); + stream.WriteLine("{"); + + i = 0; + foreach (TimeZoneInfo.AdjustmentRule rule in rules) + { + DateTime time; + TIME_ZONE_RULE_ENTRY tzr; + TimeZoneInfo.TransitionTime transition; + + tzr.TicksStart = rule.DateEnd.ToUniversalTime().Ticks; + tzr.TicksEnd = rule.DateStart.ToUniversalTime().Ticks; + tzr.DaylightDelta = (Int32)rule.DaylightDelta.TotalMinutes; + + transition = rule.DaylightTransitionEnd; + time = transition.TimeOfDay; + + tzr.StandardDate.wYear = (UInt16)0; + tzr.StandardDate.wMonth = (UInt16)transition.Month; + tzr.StandardDate.wDayOfWeek = (UInt16)transition.DayOfWeek; + tzr.StandardDate.wDay = (UInt16)transition.Week; + tzr.StandardDate.wHour = (UInt16)time.Hour; + tzr.StandardDate.wMinute = (UInt16)time.Minute; + tzr.StandardDate.wSecond = (UInt16)time.Second; + tzr.StandardDate.wMilliseconds = (UInt16)time.Millisecond; + + transition = rule.DaylightTransitionStart; + time = transition.TimeOfDay; + + tzr.DaylightDate.wYear = (UInt16)0; + tzr.DaylightDate.wMonth = (UInt16)transition.Month; + tzr.DaylightDate.wDayOfWeek = (UInt16)transition.DayOfWeek; + tzr.DaylightDate.wDay = (UInt16)transition.Week; + tzr.DaylightDate.wHour = (UInt16)time.Hour; + tzr.DaylightDate.wMinute = (UInt16)time.Minute; + tzr.DaylightDate.wSecond = (UInt16)time.Second; + tzr.DaylightDate.wMilliseconds = (UInt16)time.Millisecond; + + stream.Write("\t{"); + stream.Write(" {0}ULL, {1}ULL, {2},", tzr.TicksStart, tzr.TicksEnd, tzr.DaylightDelta); + + stream.Write(" { "); + stream.Write("{0}, {1}, {2}, {3}, {4}, {5}", + tzr.StandardDate.wYear, tzr.StandardDate.wMonth, tzr.StandardDate.wDayOfWeek, + tzr.StandardDate.wDay, tzr.StandardDate.wHour, tzr.StandardDate.wMinute, + tzr.StandardDate.wSecond, tzr.StandardDate.wMilliseconds); + stream.Write(" }, "); + + stream.Write("{ "); + stream.Write("{0}, {1}, {2}, {3}, {4}, {5}", + tzr.DaylightDate.wYear, tzr.DaylightDate.wMonth, tzr.DaylightDate.wDayOfWeek, + tzr.DaylightDate.wDay, tzr.DaylightDate.wHour, tzr.DaylightDate.wMinute, + tzr.DaylightDate.wSecond, tzr.DaylightDate.wMilliseconds); + stream.Write(" },"); + + if (++i < rules.Length) + stream.WriteLine(" },"); + else + stream.WriteLine(" }"); + } + + stream.WriteLine("};"); + stream.WriteLine(); + index++; +} + +index = 0; +stream.WriteLine("static const TIME_ZONE_ENTRY TimeZoneTable[] ="); +stream.WriteLine("{"); + +foreach (TimeZoneInfo timeZone in timeZones) +{ + TIME_ZONE_ENTRY tz; + TimeSpan offset = timeZone.BaseUtcOffset; + + rules = timeZone.GetAdjustmentRules(); + + tz.Id = timeZone.Id; + tz.Bias = -(Int32)offset.TotalMinutes; + + tz.SupportsDST = timeZone.SupportsDaylightSavingTime; + + tz.DisplayName = timeZone.DisplayName; + tz.StandardName = timeZone.StandardName; + tz.DaylightName = timeZone.DaylightName; + + if ((!tz.SupportsDST) || (rules.Length < 1)) + { + tz.RuleTableCount = 0; + tz.RuleTable = "NULL"; + } + else + { + tz.RuleTableCount = (UInt32)rules.Length; + tz.RuleTable = "&TimeZoneRuleTable_" + index; + tz.RuleTable = "(TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_" + index; + } + + stream.WriteLine("\t{"); + + stream.WriteLine("\t\t\"{0}\", {1}, {2}, \"{3}\",", + tz.Id, tz.Bias, tz.SupportsDST ? "TRUE" : "FALSE", tz.DisplayName); + + stream.WriteLine("\t\t\"{0}\", \"{1}\",", tz.StandardName, tz.DaylightName); + stream.WriteLine("\t\t{0}, {1}", tz.RuleTable, tz.RuleTableCount); + + index++; + + if ((int)index < timeZones.Count) + stream.WriteLine("\t},"); + else + stream.WriteLine("\t}"); +} +stream.WriteLine("};"); +stream.WriteLine(); + +stream.Close(); + diff --git a/scripts/WindowsZones.cs b/scripts/WindowsZones.cs deleted file mode 100644 index 878dade..0000000 --- a/scripts/WindowsZones.cs +++ /dev/null @@ -1,90 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * TZID to Windows TimeZone Identifier Table Generator - * - * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.IO; -using System.Xml; -using System.Text; -using System.Collections; -using System.Collections.Generic; - -/* - * this script uses windowsZones.xml which can be obtained at: - * http://www.unicode.org/repos/cldr/tags/latest/common/supplemental/windowsZones.xml - */ - -namespace WindowsZones -{ - class MainClass - { - public static void Main(string[] args) - { - string tzid, windows; - const string file = @"WindowsZones.txt"; - List<string> list = new List<string>(); - StreamWriter stream = new StreamWriter(file, false); - XmlTextReader reader = new XmlTextReader(@"windowsZones.xml"); - - stream.WriteLine("struct _WINDOWS_TZID_ENTRY"); - stream.WriteLine("{"); - stream.WriteLine("\tconst char* windows;"); - stream.WriteLine("\tconst char* tzid;"); - stream.WriteLine("};"); - stream.WriteLine("typedef struct _WINDOWS_TZID_ENTRY WINDOWS_TZID_ENTRY;"); - stream.WriteLine(); - - while (reader.Read()) - { - switch (reader.NodeType) - { - case XmlNodeType.Element: - - if (reader.Name.Equals("mapZone")) - { - tzid = reader.GetAttribute("type"); - windows = reader.GetAttribute("other"); - - string entry = String.Format("\"{0}\", \"{1}\"", windows, tzid); - - if (!list.Contains(entry)) - list.Add(entry); - } - - break; - } - } - - list.Sort(); - - stream.WriteLine("const WINDOWS_TZID_ENTRY WindowsTimeZoneIdTable[] ="); - stream.WriteLine("{"); - - foreach (string entry in list) - { - stream.Write("\t{ "); - stream.Write(entry); - stream.WriteLine(" },"); - } - - stream.WriteLine("};"); - - stream.Close(); - } - } -} diff --git a/scripts/WindowsZones.csx b/scripts/WindowsZones.csx new file mode 100644 index 0000000..ccd8bf4 --- /dev/null +++ b/scripts/WindowsZones.csx @@ -0,0 +1,84 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * TZID to Windows TimeZone Identifier Table Generator + * + * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#r "System.Xml" + +using System; +using System.IO; +using System.Xml; +using System.Text; +using System.Collections; +using System.Collections.Generic; + +/* + * this script uses windowsZones.xml which can be obtained at: + * http://www.unicode.org/repos/cldr/tags/latest/common/supplemental/windowsZones.xml + */ + +string tzid, windows; +const string file = @"WindowsZones.txt"; +const string zonesUrl = @"http://www.unicode.org/repos/cldr/tags/latest/common/supplemental/windowsZones.xml"; +List<string> list = new List<string>(); +StreamWriter stream = new StreamWriter(file, false); +XmlTextReader reader = new XmlTextReader(zonesUrl); + +stream.WriteLine("struct _WINDOWS_TZID_ENTRY"); +stream.WriteLine("{"); +stream.WriteLine("\tconst char* windows;"); +stream.WriteLine("\tconst char* tzid;"); +stream.WriteLine("};"); +stream.WriteLine("typedef struct _WINDOWS_TZID_ENTRY WINDOWS_TZID_ENTRY;"); +stream.WriteLine(); + +while (reader.Read()) +{ + switch (reader.NodeType) + { + case XmlNodeType.Element: + + if (reader.Name.Equals("mapZone")) + { + tzid = reader.GetAttribute("type"); + windows = reader.GetAttribute("other"); + + string entry = String.Format("\"{0}\", \"{1}\"", windows, tzid); + + if (!list.Contains(entry)) + list.Add(entry); + } + + break; + } +} + +list.Sort(); + +stream.WriteLine("const WINDOWS_TZID_ENTRY WindowsTimeZoneIdTable[] ="); +stream.WriteLine("{"); + +foreach (string entry in list) +{ + stream.Write("\t{ "); + stream.Write(entry); + stream.WriteLine(" },"); +} + +stream.WriteLine("};"); + +stream.Close(); diff --git a/scripts/android-build-32.conf b/scripts/android-build-32.conf index c2c43d5..af5e339 100644 --- a/scripts/android-build-32.conf +++ b/scripts/android-build-32.conf @@ -17,8 +17,8 @@ DEPS_ONLY=0 NDK_TARGET=14 JPEG_TAG=master -OPENH264_TAG=v1.6.0 -OPENSSL_TAG=OpenSSL_1_1_0c +OPENH264_TAG=v1.7.0 +OPENSSL_TAG=OpenSSL_1_1_0g SRC_DIR=$SCRIPT_PATH/.. BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs diff --git a/scripts/android-build-64.conf b/scripts/android-build-64.conf index c7f6e81..fe3b727 100644 --- a/scripts/android-build-64.conf +++ b/scripts/android-build-64.conf @@ -17,8 +17,8 @@ DEPS_ONLY=0 NDK_TARGET=21 JPEG_TAG=master -OPENH264_TAG=v1.6.0 -OPENSSL_TAG=OpenSSL_1_1_0c +OPENH264_TAG=v1.7.0 +OPENSSL_TAG=OpenSSL_1_1_0g SRC_DIR=$SCRIPT_PATH/.. BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs diff --git a/scripts/android-build-openh264.sh b/scripts/android-build-openh264.sh index 76afe5f..f90d9e3 100755 --- a/scripts/android-build-openh264.sh +++ b/scripts/android-build-openh264.sh @@ -9,7 +9,7 @@ function build { 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" + MAKE="make PATH=$PATH ENABLEPIC=Yes OS=android NDKROOT=$ANDROID_NDK TARGET=android-$2 NDKLEVEL=$2 ARCH=$1 -j libraries" common_run git clean -xdf common_run export QUIET_AR="$CCACHE " common_run export QUIET_ASM="$CCACHE " diff --git a/scripts/android-build.conf b/scripts/android-build.conf index 04ad66a..3439aa1 100644 --- a/scripts/android-build.conf +++ b/scripts/android-build.conf @@ -17,8 +17,8 @@ DEPS_ONLY=0 NDK_TARGET=21 JPEG_TAG=master -OPENH264_TAG=v1.6.0 -OPENSSL_TAG=OpenSSL_1_1_0e +OPENH264_TAG=v1.7.0 +OPENSSL_TAG=OpenSSL_1_1_0g SRC_DIR=$SCRIPT_PATH/.. BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs diff --git a/scripts/blacklist-address-sanitizer.txt b/scripts/blacklist-address-sanitizer.txt new file mode 100644 index 0000000..e69de29 diff --git a/scripts/blacklist-memory-sanitizer.txt b/scripts/blacklist-memory-sanitizer.txt new file mode 100644 index 0000000..9a05abb --- /dev/null +++ b/scripts/blacklist-memory-sanitizer.txt @@ -0,0 +1 @@ +fun:RAND* diff --git a/scripts/blacklist-thread-sanitizer.txt b/scripts/blacklist-thread-sanitizer.txt new file mode 100644 index 0000000..e69de29 diff --git a/scripts/format_code.sh b/scripts/format_code.sh index 92ed9b9..3ad769b 100755 --- a/scripts/format_code.sh +++ b/scripts/format_code.sh @@ -14,14 +14,17 @@ VERSION=$(echo $STR_VERSION | cut -d ' ' -f4) MAJOR_VERSION=$(echo $VERSION | cut -d'.' -f1) MINOR_VERSION=$(echo $VERSION | cut -d'.' -f2) -if [ "$MAJOR_VERSION" -lt "2" ]; then - echo "Your version of astyle($VERSION) is too old, need at least 2.03" - exit 1 -fi - -if [ "$MINOR_VERSION" -lt "3" ]; then +if [ "$MAJOR_VERSION" -lt "2" ]; +then echo "Your version of astyle($VERSION) is too old, need at least 2.03" exit 1 +elif [ "$MAJOR_VERSION" -eq "2" ]; +then + if [ "$MINOR_VERSION" -lt "3" ]; + then + echo "Your version of astyle($VERSION) is too old, need at least 2.03" + exit 1 + fi fi if [ $# -le 0 ]; then @@ -31,9 +34,9 @@ if [ $# -le 0 ]; then fi $ASTYLE --lineend=linux --mode=c --indent=tab=4 --pad-header --pad-oper --style=allman --min-conditional-indent=0 \ - --indent-switches --indent-cases --indent-preprocessor -k1 --max-code-length=100 \ - --indent-col1-comments --delete-empty-lines --break-closing-brackets \ - --align-pointer=type --indent-labels -xe --break-after-logical \ - --unpad-paren --break-blocks $@ + --indent-switches --indent-cases --indent-preprocessor -k1 --max-code-length=100 \ + --indent-col1-comments --delete-empty-lines --break-closing-brackets \ + --align-pointer=type --indent-labels -xe --break-after-logical \ + --unpad-paren --break-blocks $@ exit $? diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 24f7bb1..65e5c51 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -27,7 +27,7 @@ if(FREERDP_VENDOR) if(NOT WIN32) if(APPLE AND (NOT IOS)) - #add_subdirectory(Mac) + add_subdirectory(Mac) endif() else() #add_subdirectory(Windows) diff --git a/server/Mac/mf_info.c b/server/Mac/mf_info.c index 1325444..da7b44d 100644 --- a/server/Mac/mf_info.c +++ b/server/Mac/mf_info.c @@ -28,6 +28,9 @@ #include "mf_info.h" #include "mf_mountain_lion.h" +#define MF_INFO_DEFAULT_FPS 30 +#define MF_INFO_MAXPEERS 32 + static mfInfo* mfInfoInstance = NULL; int mf_info_lock(mfInfo* mfi) @@ -142,7 +145,7 @@ void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context) mf_mlion_start_getting_screen_updates(); } - peerId = NULL; + peerId = 0; for(i=0; i<MF_INFO_MAXPEERS; ++i) { diff --git a/server/Mac/mf_input.c b/server/Mac/mf_input.c index 0b02daf..bd1c2a0 100644 --- a/server/Mac/mf_input.c +++ b/server/Mac/mf_input.c @@ -291,59 +291,59 @@ static const CGKeyCode keymap[256] = 0xFF, //0xfe }; -void mf_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) +BOOL mf_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { - CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateHIDSystemState); - + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); BOOL keyDown = TRUE; CGEventRef kbEvent; CGKeyCode kCode = 0xFF; - + if (flags & KBD_FLAGS_RELEASE) { keyDown = FALSE; } - + if (flags & KBD_FLAGS_EXTENDED) { - switch (code) { + switch (code) + { //case 0x52: //insert case 0x53: kCode = kVK_ForwardDelete; break; - + case 0x4B: kCode = kVK_LeftArrow; break; - + case 0x47: kCode = kVK_Home; break; - + case 0x4F: kCode = kVK_End; break; - + case 0x48: kCode = kVK_UpArrow; break; - + case 0x50: kCode = kVK_DownArrow; break; - + case 0x49: kCode = kVK_PageUp; break; - + case 0x51: kCode = kVK_PageDown; break; - + case 0x4D: kCode = kVK_RightArrow; break; - + default: break; } @@ -352,22 +352,22 @@ void mf_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { kCode = keymap[code]; } - + kbEvent = CGEventCreateKeyboardEvent(source, kCode, keyDown); CGEventPost(kCGHIDEventTap, kbEvent); CFRelease(kbEvent); CFRelease(source); + return TRUE; } -void mf_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) +BOOL mf_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { - + return FALSE; } -void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +BOOL mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { float width, height; - CGWheelCount wheelCount = 2; INT32 scroll_x = 0; INT32 scroll_y = 0; @@ -386,35 +386,29 @@ void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) else scroll_x = scroll; - CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateHIDSystemState); - CGEventRef scroll = CGEventCreateScrollWheelEvent(source, - kCGScrollEventUnitLine, - wheelCount, - scroll_y, - scroll_x); - CGEventPost(kCGHIDEventTap, scroll); - - CFRelease(scroll); + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventRef scrollEvent = CGEventCreateScrollWheelEvent(source, + kCGScrollEventUnitLine, + wheelCount, + scroll_y, + scroll_x); + CGEventPost(kCGHIDEventTap, scrollEvent); + CFRelease(scrollEvent); CFRelease(source); } else { - - mfInfo * mfi; - CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateHIDSystemState); + mfInfo* mfi; + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); CGEventType mouseType = kCGEventNull; CGMouseButton mouseButton = kCGMouseButtonLeft; - - mfi = mf_info_get_instance(); - //width and height of primary screen (even in multimon setups width = (float) mfi->servscreen_width; height = (float) mfi->servscreen_height; - x += mfi->servscreen_xoffset; y += mfi->servscreen_yoffset; - + if (flags & PTR_FLAGS_MOVE) { if (mfi->mouse_down_left == TRUE) @@ -433,21 +427,20 @@ void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { mouseType = kCGEventMouseMoved; } - + CGEventRef move = CGEventCreateMouseEvent(source, - mouseType, - CGPointMake(x, y), - mouseButton // ignored for just movement - ); - + mouseType, + CGPointMake(x, y), + mouseButton // ignored for just movement + ); CGEventPost(kCGHIDEventTap, move); - CFRelease(move); } - + if (flags & PTR_FLAGS_BUTTON1) { mouseButton = kCGMouseButtonLeft; + if (flags & PTR_FLAGS_DOWN) { mouseType = kCGEventLeftMouseDown; @@ -462,6 +455,7 @@ void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) else if (flags & PTR_FLAGS_BUTTON2) { mouseButton = kCGMouseButtonRight; + if (flags & PTR_FLAGS_DOWN) { mouseType = kCGEventRightMouseDown; @@ -472,11 +466,11 @@ void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) mouseType = kCGEventRightMouseUp; mfi->mouse_down_right = FALSE; } - } else if (flags & PTR_FLAGS_BUTTON3) { mouseButton = kCGMouseButtonCenter; + if (flags & PTR_FLAGS_DOWN) { mouseType = kCGEventOtherMouseDown; @@ -487,40 +481,43 @@ void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) mouseType = kCGEventOtherMouseUp; mfi->mouse_down_other = FALSE; } - } - - + CGEventRef mouseEvent = CGEventCreateMouseEvent(source, - mouseType, - CGPointMake(x, y), - mouseButton - ); + mouseType, + CGPointMake(x, y), + mouseButton + ); CGEventPost(kCGHIDEventTap, mouseEvent); - CFRelease(mouseEvent); CFRelease(source); } + + return TRUE; } -void mf_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +BOOL mf_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { - + return FALSE; } -void mf_input_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code) +BOOL mf_input_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code) { + return FALSE; } -void mf_input_unicode_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code) +BOOL mf_input_unicode_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code) { + return FALSE; } -void mf_input_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +BOOL mf_input_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { + return FALSE; } -void mf_input_extended_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +BOOL mf_input_extended_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { + return FALSE; } diff --git a/server/Mac/mf_input.h b/server/Mac/mf_input.h index 8e8903c..336ac24 100644 --- a/server/Mac/mf_input.h +++ b/server/Mac/mf_input.h @@ -22,15 +22,15 @@ #include "mf_interface.h" -void mf_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code); -void mf_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code); -void mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); -void mf_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); +BOOL mf_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code); +BOOL mf_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code); +BOOL mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); +BOOL mf_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); //dummy versions -void mf_input_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code); -void mf_input_unicode_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code); -void mf_input_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); -void mf_input_extended_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); +BOOL mf_input_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code); +BOOL mf_input_unicode_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code); +BOOL mf_input_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); +BOOL mf_input_extended_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); -#endif /* FREERDP_SERVER_MAC_INPUT_H */ \ No newline at end of file +#endif /* FREERDP_SERVER_MAC_INPUT_H */ diff --git a/server/Mac/mf_peer.c b/server/Mac/mf_peer.c index bcc0914..2a1b8f3 100644 --- a/server/Mac/mf_peer.c +++ b/server/Mac/mf_peer.c @@ -25,6 +25,7 @@ #include <freerdp/codec/rfx.h> #include <winpr/stream.h> #include <freerdp/peer.h> +#include <freerdp/codec/color.h> #include <winpr/crt.h> @@ -33,6 +34,7 @@ #include "mf_input.h" #include "mf_event.h" #include "mf_rdpsnd.h" +#include "mf_audin.h" #include <mach/clock.h> #include <mach/mach.h> @@ -44,22 +46,19 @@ #include "CoreVideo/CoreVideo.h" //refactor these -int info_last_sec = 0; -int info_last_nsec = 0; +static int info_last_sec = 0; +static int info_last_nsec = 0; -dispatch_source_t info_timer; -dispatch_queue_t info_queue; +static dispatch_source_t info_timer; +static dispatch_queue_t info_queue; -mfEventQueue* info_event_queue; +static mfEventQueue* info_event_queue; +static CGLContextObj glContext; +static CGContextRef bmp; +static CGImageRef img; -CGLContextObj glContext; -CGContextRef bmp; -CGImageRef img; - - - -BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount) +static BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount) { if (info_event_queue->pipe_fd[0] == -1) return TRUE; @@ -69,33 +68,8 @@ BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount) return TRUE; } -BOOL mf_peer_check_fds(freerdp_peer* client) -{ - mfPeerContext* context = (mfPeerContext*) client->context; - mfEvent* event; - if (context->activated == FALSE) - return TRUE; - - event = mf_event_peek(info_event_queue); - - if (event != NULL) - { - if (event->type == MF_EVENT_TYPE_REGION) - { - } - else if (event->type == MF_EVENT_TYPE_FRAME_TICK) - { - event = mf_event_pop(info_event_queue); - mf_peer_rfx_update(client); - mf_event_free(event); - } - } - - return TRUE; -} - -void mf_peer_rfx_update(freerdp_peer* client) +static void mf_peer_rfx_update(freerdp_peer* client) { //check mfInfo* mfi = mf_info_get_instance(); @@ -139,23 +113,50 @@ void mf_peer_rfx_update(freerdp_peer* client) return; } + memset(cmd, 0, sizeof(SURFACE_BITS_COMMAND)); cmd->destLeft = x; cmd->destTop = y; cmd->destRight = x + rect.width; cmd->destBottom = y + rect.height; - cmd->bpp = 32; - cmd->codecID = 3; - cmd->width = rect.width; - cmd->height = rect.height; - cmd->bitmapDataLength = Stream_GetPosition(s); - cmd->bitmapData = Stream_Buffer(s); + cmd->bmp.bpp = 32; + cmd->bmp.codecID = 3; + cmd->bmp.width = rect.width; + cmd->bmp.height = rect.height; + cmd->bmp.bitmapDataLength = Stream_GetPosition(s); + cmd->bmp.bitmapData = Stream_Buffer(s); //send update->SurfaceBits(update->context, cmd); //clean up... maybe? } +static BOOL mf_peer_check_fds(freerdp_peer* client) +{ + mfPeerContext* context = (mfPeerContext*) client->context; + mfEvent* event; + + if (context->activated == FALSE) + return TRUE; + + event = mf_event_peek(info_event_queue); + + if (event != NULL) + { + if (event->type == FREERDP_SERVER_MAC_EVENT_TYPE_REGION) + { + } + else if (event->type == FREERDP_SERVER_MAC_EVENT_TYPE_FRAME_TICK) + { + event = mf_event_pop(info_event_queue); + mf_peer_rfx_update(client); + mf_event_free(event); + } + } + + return TRUE; +} + /* Called when we have a new peer connecting */ -BOOL mf_peer_context_new(freerdp_peer* client, mfPeerContext* context) +static BOOL mf_peer_context_new(freerdp_peer* client, mfPeerContext* context) { if (!(context->info = mf_info_get_instance())) return FALSE; @@ -166,7 +167,7 @@ BOOL mf_peer_context_new(freerdp_peer* client, mfPeerContext* context) context->rfx_context->mode = RLGR3; context->rfx_context->width = client->settings->DesktopWidth; context->rfx_context->height = client->settings->DesktopHeight; - rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_BGRA32); + rfx_context_set_pixel_format(context->rfx_context, PIXEL_FORMAT_BGRA32); if (!(context->s = Stream_New(NULL, 0xFFFF))) goto fail_stream_new; @@ -189,7 +190,7 @@ fail_rfx_context: } /* Called after a peer disconnects */ -void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context) +static void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context) { if (context) { @@ -204,19 +205,19 @@ void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context) audin_server_context_free(context->audin); #endif - //#ifdef CHANNEL_RDPSND_SERVER +#ifdef CHANNEL_RDPSND_SERVER mf_peer_rdpsnd_stop(); if (context->rdpsnd) rdpsnd_server_context_free(context->rdpsnd); - //#endif +#endif WTSCloseServer(context->vcm); } } /* Called when a new client connects */ -BOOL mf_peer_init(freerdp_peer* client) +static BOOL mf_peer_init(freerdp_peer* client) { client->ContextSize = sizeof(mfPeerContext); client->ContextNew = (psPeerContextNew) mf_peer_context_new; @@ -239,7 +240,7 @@ BOOL mf_peer_init(freerdp_peer* client) dispatch_source_set_event_handler(info_timer, ^ { //DEBUG_WARN( "dispatch\n"); - mfEvent* event = mf_event_new(MF_EVENT_TYPE_FRAME_TICK); + mfEvent* event = mf_event_new(FREERDP_SERVER_MAC_EVENT_TYPE_FRAME_TICK); mf_event_push(info_event_queue, (mfEvent*) event); } ); @@ -249,7 +250,7 @@ BOOL mf_peer_init(freerdp_peer* client) return TRUE; } -BOOL mf_peer_post_connect(freerdp_peer* client) +static BOOL mf_peer_post_connect(freerdp_peer* client) { mfPeerContext* context = (mfPeerContext*) client->context; rdpSettings* settings = client->settings; @@ -271,12 +272,14 @@ BOOL mf_peer_post_connect(freerdp_peer* client) mfi->mouse_down_left = FALSE; mfi->mouse_down_right = FALSE; mfi->mouse_down_other = FALSE; +#ifdef CHANNEL_RDPSND_SERVER if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpsnd")) { mf_peer_rdpsnd_init(context); /* Audio Output */ } +#endif /* Dynamic Virtual Channels */ #ifdef CHANNEL_AUDIN_SERVER mf_peer_audin_init(context); /* Audio Input */ @@ -284,16 +287,18 @@ BOOL mf_peer_post_connect(freerdp_peer* client) return TRUE; } -BOOL mf_peer_activate(freerdp_peer* client) +static BOOL mf_peer_activate(freerdp_peer* client) { mfPeerContext* context = (mfPeerContext*) client->context; - rfx_context_reset(context->rfx_context); + rfx_context_reset(context->rfx_context, client->settings->DesktopWidth, + client->settings->DesktopHeight); context->activated = TRUE; return TRUE; } -void mf_peer_synchronize_event(rdpInput* input, UINT32 flags) +static BOOL mf_peer_synchronize_event(rdpInput* input, UINT32 flags) { + return TRUE; } void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) @@ -308,29 +313,19 @@ void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) } } -void mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) +static BOOL mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { -} - -static void mf_peer_suppress_output(rdpContext* context, BYTE allow, - RECTANGLE_16* area) -{ -} - -BOOL mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client) -{ - pthread_t th; - - if (pthread_create(&th, 0, mf_peer_main_loop, client) == 0) - { - pthread_detach(th); - return TRUE; - } - return FALSE; } -void* mf_peer_main_loop(void* arg) +static BOOL mf_peer_suppress_output(rdpContext* context, BYTE allow, + const RECTANGLE_16* area) +{ + return FALSE; +} + + +static void* mf_peer_main_loop(void* arg) { int i; int fds; @@ -439,3 +434,16 @@ void* mf_peer_main_loop(void* arg) freerdp_peer_free(client); return NULL; } + +BOOL mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client) +{ + pthread_t th; + + if (pthread_create(&th, 0, mf_peer_main_loop, client) == 0) + { + pthread_detach(th); + return TRUE; + } + + return FALSE; +} diff --git a/server/Mac/mf_peer.h b/server/Mac/mf_peer.h index 9b137db..3e14ccd 100644 --- a/server/Mac/mf_peer.h +++ b/server/Mac/mf_peer.h @@ -22,23 +22,6 @@ #include "mf_interface.h" -BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount); -BOOL mf_peer_check_fds(freerdp_peer* client); - -void mf_peer_rfx_update(freerdp_peer* client); - -BOOL mf_peer_context_new(freerdp_peer* client, mfPeerContext* context); -void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context); - -BOOL mf_peer_init(freerdp_peer* client); - -BOOL mf_peer_post_connect(freerdp_peer* client); -BOOL mf_peer_activate(freerdp_peer* client); - -void mf_peer_synchronize_event(rdpInput* input, UINT32 flags); - BOOL mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client); -void* mf_peer_main_loop(void* arg); - #endif /* FREERDP_SERVER_MAC_PEER_H */ diff --git a/server/Mac/mf_rdpsnd.c b/server/Mac/mf_rdpsnd.c index 6ae987a..55900db 100644 --- a/server/Mac/mf_rdpsnd.c +++ b/server/Mac/mf_rdpsnd.c @@ -28,6 +28,7 @@ #include "mf_info.h" #include "mf_rdpsnd.h" +#include <winpr/sysinfo.h> #include <freerdp/log.h> #define TAG SERVER_TAG("mac") @@ -45,7 +46,6 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) int i, j; BOOL formatAgreed = FALSE; AUDIO_FORMAT* agreedFormat = NULL; - //we should actually loop through the list of client formats here //and see if we can send the client something that it supports... WLog_DBG(TAG, "Client supports the following %d formats: ", context->num_client_formats); @@ -65,11 +65,11 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) break; } } + if (formatAgreed == TRUE) break; - } - + if (formatAgreed == FALSE) { WLog_DBG(TAG, "Could not agree on a audio format with the server"); @@ -78,75 +78,66 @@ static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) context->SelectFormat(context, i); context->SetVolume(context, 0x7FFF, 0x7FFF); - + switch (agreedFormat->wFormatTag) { case WAVE_FORMAT_ALAW: recorderState.dataFormat.mFormatID = kAudioFormatDVIIntelIMA; break; - + case WAVE_FORMAT_PCM: recorderState.dataFormat.mFormatID = kAudioFormatLinearPCM; break; - + default: recorderState.dataFormat.mFormatID = kAudioFormatLinearPCM; break; } - + recorderState.dataFormat.mSampleRate = agreedFormat->nSamplesPerSec; - recorderState.dataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;; + recorderState.dataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | + kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;; recorderState.dataFormat.mBytesPerPacket = 4; recorderState.dataFormat.mFramesPerPacket = 1; recorderState.dataFormat.mBytesPerFrame = 4; recorderState.dataFormat.mChannelsPerFrame = agreedFormat->nChannels; recorderState.dataFormat.mBitsPerChannel = agreedFormat->wBitsPerSample; - - recorderState.snd_context = context; - status = AudioQueueNewInput(&recorderState.dataFormat, - mf_peer_rdpsnd_input_callback, - &recorderState, - NULL, - kCFRunLoopCommonModes, - 0, - &recorderState.queue); - + mf_peer_rdpsnd_input_callback, + &recorderState, + NULL, + kCFRunLoopCommonModes, + 0, + &recorderState.queue); + if (status != noErr) { WLog_DBG(TAG, "Failed to create a new Audio Queue. Status code: %"PRId32"", status); } - - UInt32 dataFormatSize = sizeof (recorderState.dataFormat); - + + UInt32 dataFormatSize = sizeof(recorderState.dataFormat); AudioQueueGetProperty(recorderState.queue, - kAudioConverterCurrentInputStreamDescription, - &recorderState.dataFormat, - &dataFormatSize); - - - mf_rdpsnd_derive_buffer_size(recorderState.queue, &recorderState.dataFormat, 0.05, &recorderState.bufferByteSize); - - + kAudioConverterCurrentInputStreamDescription, + &recorderState.dataFormat, + &dataFormatSize); + mf_rdpsnd_derive_buffer_size(recorderState.queue, &recorderState.dataFormat, 0.05, + &recorderState.bufferByteSize); + for (i = 0; i < SND_NUMBUFFERS; ++i) { AudioQueueAllocateBuffer(recorderState.queue, - recorderState.bufferByteSize, - &recorderState.buffers[i]); - + recorderState.bufferByteSize, + &recorderState.buffers[i]); AudioQueueEnqueueBuffer(recorderState.queue, - recorderState.buffers[i], - 0, - NULL); + recorderState.buffers[i], + 0, + NULL); } - - + recorderState.currentPacket = 0; recorderState.isRunning = true; - - AudioQueueStart (recorderState.queue, NULL); - + AudioQueueStart(recorderState.queue, NULL); } BOOL mf_peer_rdpsnd_init(mfPeerContext* context) @@ -154,19 +145,15 @@ BOOL mf_peer_rdpsnd_init(mfPeerContext* context) context->rdpsnd = rdpsnd_server_context_new(context->vcm); context->rdpsnd->rdpcontext = &context->_p; context->rdpsnd->data = context; - context->rdpsnd->server_formats = supported_audio_formats; - context->rdpsnd->num_server_formats = sizeof(supported_audio_formats) / sizeof(supported_audio_formats[0]); - + context->rdpsnd->num_server_formats = sizeof(supported_audio_formats) / sizeof( + supported_audio_formats[0]); context->rdpsnd->src_format.wFormatTag = 1; context->rdpsnd->src_format.nChannels = 2; context->rdpsnd->src_format.nSamplesPerSec = 44100; context->rdpsnd->src_format.wBitsPerSample = 16; - context->rdpsnd->Activated = mf_peer_rdpsnd_activated; - context->rdpsnd->Initialize(context->rdpsnd, TRUE); - return TRUE; } @@ -174,71 +161,66 @@ BOOL mf_peer_rdpsnd_stop() { recorderState.isRunning = false; AudioQueueStop(recorderState.queue, true); - return TRUE; } -void mf_peer_rdpsnd_input_callback (void *inUserData, - AudioQueueRef inAQ, - AudioQueueBufferRef inBuffer, - const AudioTimeStamp *inStartTime, - UInt32 inNumberPacketDescriptions, - const AudioStreamPacketDescription *inPacketDescs) +void mf_peer_rdpsnd_input_callback(void* inUserData, + AudioQueueRef inAQ, + AudioQueueBufferRef inBuffer, + const AudioTimeStamp* inStartTime, + UInt32 inNumberPacketDescriptions, + const AudioStreamPacketDescription* inPacketDescs) { OSStatus status; - AQRecorderState * rState; + AQRecorderState* rState; rState = inUserData; - - + if (inNumberPacketDescriptions == 0 && rState->dataFormat.mBytesPerPacket != 0) { inNumberPacketDescriptions = inBuffer->mAudioDataByteSize / rState->dataFormat.mBytesPerPacket; } - - + if (rState->isRunning == 0) { return ; } - + rState->snd_context->SendSamples(rState->snd_context, inBuffer->mAudioData, - inBuffer->mAudioDataByteSize/4, (UINT16)(GetTickCount() & 0xffff)); - + inBuffer->mAudioDataByteSize / 4, (UINT16)(GetTickCount() & 0xffff)); status = AudioQueueEnqueueBuffer( - rState->queue, - inBuffer, - 0, - NULL); - + rState->queue, + inBuffer, + 0, + NULL); + if (status != noErr) { WLog_DBG(TAG, "AudioQueueEnqueueBuffer() returned status = %"PRId32"", status); } - } -void mf_rdpsnd_derive_buffer_size (AudioQueueRef audioQueue, - AudioStreamBasicDescription *ASBDescription, - Float64 seconds, - UInt32 *outBufferSize) +void mf_rdpsnd_derive_buffer_size(AudioQueueRef audioQueue, + AudioStreamBasicDescription* ASBDescription, + Float64 seconds, + UInt32* outBufferSize) { static const int maxBufferSize = 0x50000; - int maxPacketSize = ASBDescription->mBytesPerPacket; + if (maxPacketSize == 0) { UInt32 maxVBRPacketSize = sizeof(maxPacketSize); - AudioQueueGetProperty (audioQueue, - kAudioQueueProperty_MaximumOutputPacketSize, - // in Mac OS X v10.5, instead use - // kAudioConverterPropertyMaximumOutputPacketSize - &maxPacketSize, - &maxVBRPacketSize - ); + AudioQueueGetProperty(audioQueue, + kAudioQueueProperty_MaximumOutputPacketSize, + // in Mac OS X v10.5, instead use + // kAudioConverterPropertyMaximumOutputPacketSize + &maxPacketSize, + &maxVBRPacketSize + ); } - + Float64 numBytesForTime = - ASBDescription->mSampleRate * maxPacketSize * seconds; - *outBufferSize = (UInt32) (numBytesForTime < maxBufferSize ? numBytesForTime : maxBufferSize); + ASBDescription->mSampleRate * maxPacketSize * seconds; + *outBufferSize = (UInt32)(numBytesForTime < maxBufferSize ? numBytesForTime : maxBufferSize); } diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c index c60a229..3384068 100644 --- a/server/Sample/sfreerdp.c +++ b/server/Sample/sfreerdp.c @@ -27,6 +27,7 @@ #include <signal.h> #include <winpr/crt.h> +#include <winpr/ssl.h> #include <winpr/synch.h> #include <winpr/string.h> #include <winpr/path.h> @@ -193,6 +194,7 @@ static BOOL test_peer_draw_background(freerdp_peer* client) } memset(rgb_data, 0xA0, size); + memset(cmd, 0, sizeof(SURFACE_BITS_COMMAND)); if (client->settings->RemoteFxCodec) { @@ -202,24 +204,25 @@ static BOOL test_peer_draw_background(freerdp_peer* client) goto out; } - cmd->codecID = client->settings->RemoteFxCodecId; + cmd->bmp.codecID = client->settings->RemoteFxCodecId; } else { nsc_compose_message(context->nsc_context, s, rgb_data, rect.width, rect.height, rect.width * 3); - cmd->codecID = client->settings->NSCodecId; + cmd->bmp.codecID = client->settings->NSCodecId; } cmd->destLeft = 0; cmd->destTop = 0; cmd->destRight = rect.width; cmd->destBottom = rect.height; - cmd->bpp = 32; - cmd->width = rect.width; - cmd->height = rect.height; - cmd->bitmapDataLength = Stream_GetPosition(s); - cmd->bitmapData = Stream_Buffer(s); + cmd->bmp.bpp = 32; + cmd->bmp.flags = 0; + cmd->bmp.width = rect.width; + cmd->bmp.height = rect.height; + cmd->bmp.bitmapDataLength = Stream_GetPosition(s); + cmd->bmp.bitmapData = Stream_Buffer(s); test_peer_begin_frame(client); update->SurfaceBits(update->context, cmd); test_peer_end_frame(client); @@ -314,6 +317,7 @@ static void test_peer_draw_icon(freerdp_peer* client, int x, int y) rect.y = 0; rect.width = context->icon_width; rect.height = context->icon_height; + memset(cmd, 0, sizeof(SURFACE_BITS_COMMAND)); if (context->icon_x >= 0) { @@ -323,24 +327,25 @@ static void test_peer_draw_icon(freerdp_peer* client, int x, int y) { rfx_compose_message(context->rfx_context, s, &rect, 1, context->bg_data, rect.width, rect.height, rect.width * 3); - cmd->codecID = client->settings->RemoteFxCodecId; + cmd->bmp.codecID = client->settings->RemoteFxCodecId; } else { nsc_compose_message(context->nsc_context, s, context->bg_data, rect.width, rect.height, rect.width * 3); - cmd->codecID = client->settings->NSCodecId; + cmd->bmp.codecID = client->settings->NSCodecId; } cmd->destLeft = context->icon_x; cmd->destTop = context->icon_y; cmd->destRight = context->icon_x + context->icon_width; cmd->destBottom = context->icon_y + context->icon_height; - cmd->bpp = 32; - cmd->width = context->icon_width; - cmd->height = context->icon_height; - cmd->bitmapDataLength = Stream_GetPosition(s); - cmd->bitmapData = Stream_Buffer(s); + cmd->bmp.bpp = 32; + cmd->bmp.flags = 0; + cmd->bmp.width = context->icon_width; + cmd->bmp.height = context->icon_height; + cmd->bmp.bitmapDataLength = Stream_GetPosition(s); + cmd->bmp.bitmapData = Stream_Buffer(s); update->SurfaceBits(update->context, cmd); } @@ -350,24 +355,24 @@ static void test_peer_draw_icon(freerdp_peer* client, int x, int y) { rfx_compose_message(context->rfx_context, s, &rect, 1, context->icon_data, rect.width, rect.height, rect.width * 3); - cmd->codecID = client->settings->RemoteFxCodecId; + cmd->bmp.codecID = client->settings->RemoteFxCodecId; } else { nsc_compose_message(context->nsc_context, s, context->icon_data, rect.width, rect.height, rect.width * 3); - cmd->codecID = client->settings->NSCodecId; + cmd->bmp.codecID = client->settings->NSCodecId; } cmd->destLeft = x; cmd->destTop = y; cmd->destRight = x + context->icon_width; cmd->destBottom = y + context->icon_height; - cmd->bpp = 32; - cmd->width = context->icon_width; - cmd->height = context->icon_height; - cmd->bitmapDataLength = Stream_GetPosition(s); - cmd->bitmapData = Stream_Buffer(s); + cmd->bmp.bpp = 32; + cmd->bmp.width = context->icon_width; + cmd->bmp.height = context->icon_height; + cmd->bmp.bitmapDataLength = Stream_GetPosition(s); + cmd->bmp.bitmapData = Stream_Buffer(s); update->SurfaceBits(update->context, cmd); context->icon_x = x; context->icon_y = y; @@ -461,7 +466,7 @@ BOOL tf_peer_dump_rfx(freerdp_peer* client) return TRUE; } -static void* tf_debug_channel_thread_func(void* arg) +static DWORD WINAPI tf_debug_channel_thread_func(LPVOID arg) { void* fd; wStream* s; @@ -477,7 +482,7 @@ static void* tf_debug_channel_thread_func(void* arg) WTSFreeMemory(buffer); if (!(context->event = CreateWaitObjectEvent(NULL, TRUE, FALSE, fd))) - return NULL; + return 0; } s = Stream_New(NULL, 4096); @@ -579,8 +584,7 @@ BOOL tf_peer_post_connect(freerdp_peer* client) } if (!(context->debug_channel_thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) tf_debug_channel_thread_func, (void*) context, 0, - NULL))) + tf_debug_channel_thread_func, (void*) context, 0, NULL))) { WLog_ERR(TAG, "Failed to create debug channel thread"); CloseHandle(context->stopEvent); @@ -735,7 +739,8 @@ static BOOL tf_peer_suppress_output(rdpContext* context, BYTE allow, { if (allow > 0) { - WLog_DBG(TAG, "Client restore output (%"PRIu16", %"PRIu16") (%"PRIu16", %"PRIu16").", area->left, area->top, + WLog_DBG(TAG, "Client restore output (%"PRIu16", %"PRIu16") (%"PRIu16", %"PRIu16").", area->left, + area->top, area->right, area->bottom); } else @@ -746,7 +751,7 @@ static BOOL tf_peer_suppress_output(rdpContext* context, BYTE allow, return TRUE; } -static void* test_peer_mainloop(void* arg) +static DWORD WINAPI test_peer_mainloop(LPVOID arg) { HANDLE handles[32]; DWORD count; @@ -757,7 +762,7 @@ static void* test_peer_mainloop(void* arg) if (!test_peer_init(client)) { freerdp_peer_free(client); - return NULL; + return 0; } /* Initialize the real server settings here */ @@ -770,7 +775,7 @@ static void* test_peer_mainloop(void* arg) { WLog_ERR(TAG, "Memory allocation failed (strdup)"); freerdp_peer_free(client); - return NULL; + return 0; } client->settings->RdpSecurity = TRUE; @@ -834,15 +839,14 @@ static void* test_peer_mainloop(void* arg) client->Disconnect(client); freerdp_peer_context_free(client); freerdp_peer_free(client); - return NULL; + return 0; } static BOOL test_peer_accepted(freerdp_listener* instance, freerdp_peer* client) { HANDLE hThread; - if (!(hThread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) test_peer_mainloop, (void*) client, 0, NULL))) + if (!(hThread = CreateThread(NULL, 0, test_peer_mainloop, (void*) client, 0, NULL))) return FALSE; CloseHandle(hThread); @@ -889,8 +893,9 @@ int main(int argc, char* argv[]) freerdp_listener* instance; char* file; char name[MAX_PATH]; - int port = 3389, i; + long port = 3389, i; BOOL localOnly = FALSE; + errno = 0; for (i = 1; i < argc; i++) { @@ -907,7 +912,7 @@ int main(int argc, char* argv[]) port = strtol(arg, NULL, 10); - if ((port < 1) || (port > 0xFFFF)) + if ((port < 1) || (port > 0xFFFF) || (errno != 0)) return -1; } else if (strcmp(arg, "--local-only")) @@ -917,6 +922,7 @@ int main(int argc, char* argv[]) } WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi()); + winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT); instance = freerdp_listener_new(); if (!instance) @@ -931,7 +937,7 @@ int main(int argc, char* argv[]) } /* Open the server socket and start listening. */ - sprintf_s(name, sizeof(name), "tfreerdp-server.%d", port); + sprintf_s(name, sizeof(name), "tfreerdp-server.%ld", port); file = GetKnownSubPath(KNOWN_PATH_TEMP, name); if (!file) diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index 0b7c2f7..edcd23a 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -24,6 +24,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> #include <winpr/tchar.h> #include <winpr/windows.h> @@ -40,10 +41,9 @@ int IDcount = 0; BOOL CALLBACK moncb(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { WLog_DBG(TAG, "%d\t(%ld, %ld), (%ld, %ld)", - IDcount, lprcMonitor->left, lprcMonitor->top, - lprcMonitor->right, lprcMonitor->bottom); + IDcount, lprcMonitor->left, lprcMonitor->top, + lprcMonitor->right, lprcMonitor->bottom); IDcount++; - return TRUE; } @@ -52,13 +52,12 @@ int main(int argc, char* argv[]) BOOL screen_selected = FALSE; int index; wfServer* server; - server = wfreerdp_server_new(); - set_screen_id(0); - //handle args index = 1; + errno = 0; + while (index < argc) { //first the args that will cause the program to terminate @@ -72,11 +71,11 @@ int main(int argc, char* argv[]) WLog_INFO(TAG, "Detecting screens..."); WLog_INFO(TAG, "ID\tResolution\t\tName (Interface)"); - for (i=0; ; i++) + for (i = 0; ; i++) { if (get_screen_info(i, name, &width, &height, &bpp) != 0) { - if ( (width * height * bpp) == 0 ) + if ((width * height * bpp) == 0) continue; WLog_INFO(TAG, "%d\t%dx%dx%d\t", i, width, height, bpp); @@ -101,24 +100,36 @@ int main(int argc, char* argv[]) return 0; } - + if (strcmp("--screen", argv[index]) == 0) { + UINT32 val; screen_selected = TRUE; index++; + if (index == argc) { WLog_INFO(TAG, "missing screen id parameter"); return 0; } - set_screen_id(atoi(argv[index])); + val = strtoul(argv[index], NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return -1; + + set_screen_id(val); index++; } if (index == argc - 1) { - server->port = (DWORD) atoi(argv[index]); + UINT32 val = strtoul(argv[index], NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return -1; + + server->port = val; break; } } @@ -134,11 +145,11 @@ int main(int argc, char* argv[]) WLog_INFO(TAG, "Detecting screens..."); WLog_INFO(TAG, "ID\tResolution\t\tName (Interface)"); - for (i=0; ; i++) + for (i = 0; ; i++) { if (get_screen_info(i, name, &width, &height, &bpp) != 0) { - if ( (width * height * bpp) == 0 ) + if ((width * height * bpp) == 0) continue; WLog_INFO(TAG, "%d\t%dx%dx%d\t", i, width, height, bpp); @@ -155,11 +166,9 @@ int main(int argc, char* argv[]) WLog_INFO(TAG, "Starting server"); wfreerdp_server_start(server); - WaitForSingleObject(server->thread, INFINITE); WLog_INFO(TAG, "Stopping server"); wfreerdp_server_stop(server); wfreerdp_server_free(server); - return 0; } diff --git a/server/Windows/wf_directsound.c b/server/Windows/wf_directsound.c index 1ba1e23..ff69b21 100644 --- a/server/Windows/wf_directsound.c +++ b/server/Windows/wf_directsound.c @@ -88,7 +88,7 @@ int wf_directsound_activate(RdpsndServerContext* context) return 0; } -DWORD WINAPI wf_rdpsnd_directsound_thread(LPVOID lpParam) +static DWORD WINAPI wf_rdpsnd_directsound_thread(LPVOID lpParam) { HRESULT hr; DWORD beg = 0; diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index da596b3..2e688b9 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -88,7 +88,7 @@ void set_screen_id(int id) return; } -DWORD WINAPI wf_server_main_loop(LPVOID lpParam) +static DWORD WINAPI wf_server_main_loop(LPVOID lpParam) { int i, fds; int rcount; diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index ce4d876..686461e 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -167,7 +167,7 @@ BOOL wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client) return TRUE; } -DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam) +static DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam) { int i, fds; int rcount; @@ -239,7 +239,7 @@ BOOL wf_peer_read_settings(freerdp_peer* client) return TRUE; } -DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) +static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) { wfInfo* wfi; DWORD nCount; diff --git a/server/Windows/wf_wasapi.c b/server/Windows/wf_wasapi.c index 1855e4c..60c3df7 100644 --- a/server/Windows/wf_wasapi.c +++ b/server/Windows/wf_wasapi.c @@ -160,7 +160,7 @@ int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr) return 0; } -DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam) +static DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam) { IMMDeviceEnumerator *pEnumerator = NULL; IMMDevice *pDevice = NULL; diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index a29574a..a8b74a9 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -333,7 +333,7 @@ static int freerdp_image_copy_from_retina(BYTE* pDstData, DWORD DstFormat, R = pSrcPixel[2] + pSrcPixel[6] + pSrcPixel[nSrcStep + 2] + pSrcPixel[nSrcStep + 6]; pSrcPixel += 8; - color = GetColor(DstFormat, R >> 2, G >> 2, B >> 2, 0xFF); + color = FreeRDPGetColor(DstFormat, R >> 2, G >> 2, B >> 2, 0xFF); WriteColor(pDstPixel, DstFormat, color); pDstPixel += dstBytesPerPixel; } @@ -457,7 +457,6 @@ static int mac_shadow_capture_init(macShadowSubsystem* subsystem) CFDictionaryRef opts; CGDirectDisplayID displayId; displayId = CGMainDisplayID(); - subsystem->captureQueue = dispatch_queue_create("mac.shadow.capture", NULL); keys[0] = (void*) kCGDisplayStreamShowCursor; values[0] = (void*) kCFBooleanFalse; @@ -500,8 +499,9 @@ static int mac_shadow_subsystem_process_message(macShadowSubsystem* subsystem, return 1; } -static void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) +static DWORD WINAPI mac_shadow_subsystem_thread(LPVOID arg) { + macShadowSubsystem* subsystem = (macShadowSubsystem*)arg; DWORD status; DWORD nCount; UINT64 cTime; @@ -544,7 +544,7 @@ static void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) } ExitThread(0); - return NULL; + return 0; } static int mac_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors) @@ -601,8 +601,7 @@ static int mac_shadow_subsystem_start(macShadowSubsystem* subsystem) mac_shadow_capture_start(subsystem); - if (!(thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) mac_shadow_subsystem_thread, + if (!(thread = CreateThread(NULL, 0, mac_shadow_subsystem_thread, (void*) subsystem, 0, NULL))) { WLog_ERR(TAG, "Failed to create thread"); diff --git a/server/shadow/Win/win_rdp.c b/server/shadow/Win/win_rdp.c index fbcd3c2..50467b4 100644 --- a/server/shadow/Win/win_rdp.c +++ b/server/shadow/Win/win_rdp.c @@ -28,21 +28,21 @@ #define TAG SERVER_TAG("shadow.win") -void shw_OnChannelConnectedEventHandler(rdpContext* context, - ChannelConnectedEventArgs* e) +static void shw_OnChannelConnectedEventHandler(void* context, + ChannelConnectedEventArgs* e) { shwContext* shw = (shwContext*) context; WLog_INFO(TAG, "OnChannelConnected: %s", e->name); } -void shw_OnChannelDisconnectedEventHandler(rdpContext* context, +static void shw_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEventArgs* e) { shwContext* shw = (shwContext*) context; WLog_INFO(TAG, "OnChannelDisconnected: %s", e->name); } -BOOL shw_begin_paint(rdpContext* context) +static BOOL shw_begin_paint(rdpContext* context) { shwContext* shw; rdpGdi* gdi = context->gdi; @@ -52,7 +52,7 @@ BOOL shw_begin_paint(rdpContext* context) return TRUE; } -BOOL shw_end_paint(rdpContext* context) +static BOOL shw_end_paint(rdpContext* context) { int index; int ninvalid; @@ -61,7 +61,7 @@ BOOL shw_end_paint(rdpContext* context) rdpGdi* gdi = context->gdi; shwContext* shw = (shwContext*) context; winShadowSubsystem* subsystem = shw->subsystem; - rdpShadowSurface* surface = subsystem->server->surface; + rdpShadowSurface* surface = subsystem->base.server->surface; ninvalid = gdi->primary->hdc->hwnd->ninvalid; cinvalid = gdi->primary->hdc->hwnd->cinvalid; @@ -86,15 +86,15 @@ BOOL shw_desktop_resize(rdpContext* context) return TRUE; } -BOOL shw_surface_frame_marker(rdpContext* context, - const SURFACE_FRAME_MARKER* surfaceFrameMarker) +static BOOL shw_surface_frame_marker(rdpContext* context, + const SURFACE_FRAME_MARKER* surfaceFrameMarker) { shwContext* shw = (shwContext*) context; return TRUE; } -BOOL shw_authenticate(freerdp* instance, char** username, char** password, - char** domain) +static BOOL shw_authenticate(freerdp* instance, char** username, char** password, + char** domain) { return TRUE; } @@ -106,30 +106,30 @@ static DWORD shw_verify_certificate(freerdp* instance, const char* common_name, return 1; } -int shw_verify_x509_certificate(freerdp* instance, BYTE* data, int length, - const char* hostname, int port, DWORD flags) +static int shw_verify_x509_certificate(freerdp* instance, BYTE* data, int length, + const char* hostname, int port, DWORD flags) { return 1; } -void shw_OnConnectionResultEventHandler(rdpContext* context, - ConnectionResultEventArgs* e) +static void shw_OnConnectionResultEventHandler(void* context, + ConnectionResultEventArgs* e) { shwContext* shw = (shwContext*) context; WLog_INFO(TAG, "OnConnectionResult: %d", e->result); } -BOOL shw_pre_connect(freerdp* instance) +static BOOL shw_pre_connect(freerdp* instance) { shwContext* shw; rdpContext* context = instance->context; shw = (shwContext*) context; PubSub_SubscribeConnectionResult(context->pubSub, - (pConnectionResultEventHandler) shw_OnConnectionResultEventHandler); + shw_OnConnectionResultEventHandler); PubSub_SubscribeChannelConnected(context->pubSub, - (pChannelConnectedEventHandler) shw_OnChannelConnectedEventHandler); + shw_OnChannelConnectedEventHandler); PubSub_SubscribeChannelDisconnected(context->pubSub, - (pChannelDisconnectedEventHandler) shw_OnChannelDisconnectedEventHandler); + shw_OnChannelDisconnectedEventHandler); if (!freerdp_client_load_addins(context->channels, instance->settings)) return FALSE; @@ -137,7 +137,7 @@ BOOL shw_pre_connect(freerdp* instance) return TRUE; } -BOOL shw_post_connect(freerdp* instance) +static BOOL shw_post_connect(freerdp* instance) { rdpGdi* gdi; shwContext* shw; @@ -156,7 +156,7 @@ BOOL shw_post_connect(freerdp* instance) return TRUE; } -void* shw_client_thread(void* arg) +static DWORD WINAPI shw_client_thread(LPVOID arg) { int index; int rcount; @@ -180,7 +180,7 @@ void* shw_client_thread(void* arg) if (!bSuccess) { ExitThread(0); - return NULL; + return 0; } channels = instance->context->channels; @@ -237,30 +237,29 @@ void* shw_client_thread(void* arg) freerdp_free(instance); ExitThread(0); - return NULL; + return 0; } /** * Client Interface */ -BOOL shw_freerdp_client_global_init(void) +static BOOL shw_freerdp_client_global_init(void) { return TRUE; } -void shw_freerdp_client_global_uninit(void) +static void shw_freerdp_client_global_uninit(void) { } -int shw_freerdp_client_start(rdpContext* context) +static int shw_freerdp_client_start(rdpContext* context) { shwContext* shw; freerdp* instance = context->instance; shw = (shwContext*) context; - if (!(shw->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) shw_client_thread, + if (!(shw->thread = CreateThread(NULL, 0, shw_client_thread, instance, 0, NULL))) { WLog_ERR(TAG, "Failed to create thread"); @@ -270,14 +269,14 @@ int shw_freerdp_client_start(rdpContext* context) return 0; } -int shw_freerdp_client_stop(rdpContext* context) +static int shw_freerdp_client_stop(rdpContext* context) { shwContext* shw = (shwContext*) context; SetEvent(shw->StopEvent); return 0; } -BOOL shw_freerdp_client_new(freerdp* instance, rdpContext* context) +static BOOL shw_freerdp_client_new(freerdp* instance, rdpContext* context) { shwContext* shw; rdpSettings* settings; @@ -335,7 +334,7 @@ BOOL shw_freerdp_client_new(freerdp* instance, rdpContext* context) return TRUE; } -void shw_freerdp_client_free(freerdp* instance, rdpContext* context) +static void shw_freerdp_client_free(freerdp* instance, rdpContext* context) { shwContext* shw = (shwContext*) instance->context; } diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c index dc603dc..04de71c 100644 --- a/server/shadow/Win/win_shadow.c +++ b/server/shadow/Win/win_shadow.c @@ -28,13 +28,14 @@ #define TAG SERVER_TAG("shadow.win") -void win_shadow_input_synchronize_event(winShadowSubsystem* subsystem, - rdpShadowClient* client, UINT32 flags) +static int win_shadow_input_synchronize_event(rdpShadowSubsystem* subsystem, + rdpShadowClient* client, UINT32 flags) { + return 0; } -void win_shadow_input_keyboard_event(winShadowSubsystem* subsystem, - rdpShadowClient* client, UINT16 flags, UINT16 code) +static int win_shadow_input_keyboard_event(rdpShadowSubsystem* subsystem, + rdpShadowClient* client, UINT16 flags, UINT16 code) { INPUT event; event.type = INPUT_KEYBOARD; @@ -50,10 +51,10 @@ void win_shadow_input_keyboard_event(winShadowSubsystem* subsystem, if (flags & KBD_FLAGS_EXTENDED) event.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; - SendInput(1, &event, sizeof(INPUT)); + return SendInput(1, &event, sizeof(INPUT)); } -void win_shadow_input_unicode_keyboard_event(winShadowSubsystem* subsystem, +static int win_shadow_input_unicode_keyboard_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 code) { INPUT event; @@ -67,11 +68,11 @@ void win_shadow_input_unicode_keyboard_event(winShadowSubsystem* subsystem, if (flags & KBD_FLAGS_RELEASE) event.ki.dwFlags |= KEYEVENTF_KEYUP; - SendInput(1, &event, sizeof(INPUT)); + return SendInput(1, &event, sizeof(INPUT)); } -void win_shadow_input_mouse_event(winShadowSubsystem* subsystem, - rdpShadowClient* client, UINT16 flags, UINT16 x, UINT16 y) +static int win_shadow_input_mouse_event(rdpShadowSubsystem* subsystem, + rdpShadowClient* client, UINT16 flags, UINT16 x, UINT16 y) { INPUT event; float width; @@ -133,9 +134,11 @@ void win_shadow_input_mouse_event(winShadowSubsystem* subsystem, SendInput(1, &event, sizeof(INPUT)); } } + + return 0; } -void win_shadow_input_extended_mouse_event(winShadowSubsystem* subsystem, +static int win_shadow_input_extended_mouse_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client, UINT16 flags, UINT16 x, UINT16 y) { INPUT event; @@ -171,16 +174,18 @@ void win_shadow_input_extended_mouse_event(winShadowSubsystem* subsystem, SendInput(1, &event, sizeof(INPUT)); } + + return 0; } -int win_shadow_invalidate_region(winShadowSubsystem* subsystem, int x, int y, - int width, int height) +static int win_shadow_invalidate_region(winShadowSubsystem* subsystem, int x, int y, + int width, int height) { rdpShadowServer* server; rdpShadowSurface* surface; RECTANGLE_16 invalidRect; - server = subsystem->server; + server = subsystem->base.server; surface = server->surface; invalidRect.left = x; invalidRect.top = y; @@ -193,7 +198,7 @@ int win_shadow_invalidate_region(winShadowSubsystem* subsystem, int x, int y, return 1; } -int win_shadow_surface_copy(winShadowSubsystem* subsystem) +static int win_shadow_surface_copy(winShadowSubsystem* subsystem) { int x, y; int width; @@ -208,14 +213,11 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem) RECTANGLE_16 surfaceRect; RECTANGLE_16 invalidRect; const RECTANGLE_16* extents; - server = subsystem->server; + server = subsystem->base.server; surface = server->surface; if (ArrayList_Count(server->clients) < 1) - { - region16_clear(&(surface->invalidRegion)); return 1; - } surfaceRect.left = surface->x; surfaceRect.top = surface->y; @@ -252,7 +254,7 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem) shwContext* shw; rdpContext* context; shw = subsystem->shw; - context = (rdpContext*) shw; + context = &shw->context; gdi = context->gdi; pDstData = gdi->primary_buffer; nDstStep = gdi->width * 4; @@ -267,12 +269,14 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem) if (status <= 0) return status; - freerdp_image_copy(surface->data, surface->format, - surface->scanline, x - surface->x, y - surface->y, width, height, - pDstData, DstFormat, nDstStep, 0, 0, NULL, FREERDP_FLIP_NONE); + if (!freerdp_image_copy(surface->data, surface->format, + surface->scanline, x, y, width, height, + pDstData, DstFormat, nDstStep, x, y, NULL, FREERDP_FLIP_NONE)) + return ERROR_INTERNAL_ERROR; + ArrayList_Lock(server->clients); count = ArrayList_Count(server->clients); - shadow_subsystem_frame_update((rdpShadowSubsystem*)subsystem); + shadow_subsystem_frame_update(&subsystem->base); ArrayList_Unlock(server->clients); region16_clear(&(surface->invalidRegion)); return 1; @@ -280,13 +284,14 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem) #if defined(WITH_WDS_API) -void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem) +static DWORD WINAPI win_shadow_subsystem_thread(LPVOID arg) { + winShadowSubsystem* subsystem = (winShadowSubsystem*)arg; DWORD status; DWORD nCount; HANDLE events[32]; HANDLE StopEvent; - StopEvent = subsystem->server->StopEvent; + StopEvent = subsystem->base.server->StopEvent; nCount = 0; events[nCount++] = StopEvent; events[nCount++] = subsystem->RdpUpdateEnterEvent; @@ -309,13 +314,14 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem) } ExitThread(0); - return NULL; + return 0; } #elif defined(WITH_DXGI_1_2) -void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem) +static DWORD WINAPI win_shadow_subsystem_thread(LPVOID arg) { + winShadowSubsystem* subsystem = (winShadowSubsystem*)arg; int fps; DWORD status; DWORD nCount; @@ -361,12 +367,12 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem) } ExitThread(0); - return NULL; + return 0; } #endif -int win_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors) +static UINT32 win_shadow_enum_monitors(MONITOR_DEF* monitors, UINT32 maxMonitors) { HDC hdc; int index; @@ -398,17 +404,18 @@ int win_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors) return numMonitors; } -int win_shadow_subsystem_init(winShadowSubsystem* subsystem) +static int win_shadow_subsystem_init(rdpShadowSubsystem* arg) { + winShadowSubsystem* subsystem = (winShadowSubsystem*)arg; int status; MONITOR_DEF* virtualScreen; - subsystem->numMonitors = win_shadow_enum_monitors(subsystem->monitors, 16); + subsystem->base.numMonitors = win_shadow_enum_monitors(subsystem->base.monitors, 16); #if defined(WITH_WDS_API) status = win_shadow_wds_init(subsystem); #elif defined(WITH_DXGI_1_2) status = win_shadow_dxgi_init(subsystem); #endif - virtualScreen = &(subsystem->virtualScreen); + virtualScreen = &(subsystem->base.virtualScreen); virtualScreen->left = 0; virtualScreen->top = 0; virtualScreen->right = subsystem->width; @@ -418,8 +425,10 @@ int win_shadow_subsystem_init(winShadowSubsystem* subsystem) return 1; } -int win_shadow_subsystem_uninit(winShadowSubsystem* subsystem) +static int win_shadow_subsystem_uninit(rdpShadowSubsystem* arg) { + winShadowSubsystem* subsystem = (winShadowSubsystem*)arg; + if (!subsystem) return -1; @@ -431,15 +440,16 @@ int win_shadow_subsystem_uninit(winShadowSubsystem* subsystem) return 1; } -int win_shadow_subsystem_start(winShadowSubsystem* subsystem) +static int win_shadow_subsystem_start(rdpShadowSubsystem* arg) { + winShadowSubsystem* subsystem = (winShadowSubsystem*)arg; HANDLE thread; if (!subsystem) return -1; if (!(thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) win_shadow_subsystem_thread, + win_shadow_subsystem_thread, (void*) subsystem, 0, NULL))) { WLog_ERR(TAG, "Failed to create thread"); @@ -449,24 +459,28 @@ int win_shadow_subsystem_start(winShadowSubsystem* subsystem) return 1; } -int win_shadow_subsystem_stop(winShadowSubsystem* subsystem) +static int win_shadow_subsystem_stop(rdpShadowSubsystem* arg) { + winShadowSubsystem* subsystem = (winShadowSubsystem*)arg; + if (!subsystem) return -1; return 1; } -void win_shadow_subsystem_free(winShadowSubsystem* subsystem) +static void win_shadow_subsystem_free(rdpShadowSubsystem* arg) { + winShadowSubsystem* subsystem = (winShadowSubsystem*)arg; + if (!subsystem) return; - win_shadow_subsystem_uninit(subsystem); + win_shadow_subsystem_uninit(arg); free(subsystem); } -winShadowSubsystem* win_shadow_subsystem_new() +static rdpShadowSubsystem* win_shadow_subsystem_new(void) { winShadowSubsystem* subsystem; subsystem = (winShadowSubsystem*) calloc(1, sizeof(winShadowSubsystem)); @@ -474,26 +488,22 @@ winShadowSubsystem* win_shadow_subsystem_new() if (!subsystem) return NULL; - subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) - win_shadow_input_synchronize_event; - subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) - win_shadow_input_keyboard_event; - subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) - win_shadow_input_unicode_keyboard_event; - subsystem->MouseEvent = (pfnShadowMouseEvent) win_shadow_input_mouse_event; - subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) - win_shadow_input_extended_mouse_event; - return subsystem; + subsystem->base.SynchronizeEvent = win_shadow_input_synchronize_event; + subsystem->base.KeyboardEvent = win_shadow_input_keyboard_event; + subsystem->base.UnicodeKeyboardEvent = win_shadow_input_unicode_keyboard_event; + subsystem->base.MouseEvent = win_shadow_input_mouse_event; + subsystem->base.ExtendedMouseEvent = win_shadow_input_extended_mouse_event; + return &subsystem->base; } FREERDP_API int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { - pEntryPoints->New = (pfnShadowSubsystemNew) win_shadow_subsystem_new; - pEntryPoints->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free; - pEntryPoints->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init; - pEntryPoints->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit; - pEntryPoints->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start; - pEntryPoints->Stop = (pfnShadowSubsystemStop) win_shadow_subsystem_stop; - pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) win_shadow_enum_monitors; + pEntryPoints->New = win_shadow_subsystem_new; + pEntryPoints->Free = win_shadow_subsystem_free; + pEntryPoints->Init = win_shadow_subsystem_init; + pEntryPoints->Uninit = win_shadow_subsystem_uninit; + pEntryPoints->Start = win_shadow_subsystem_start; + pEntryPoints->Stop = win_shadow_subsystem_stop; + pEntryPoints->EnumMonitors = win_shadow_enum_monitors; return 1; } diff --git a/server/shadow/Win/win_shadow.h b/server/shadow/Win/win_shadow.h index 2ce22f1..f42006c 100644 --- a/server/shadow/Win/win_shadow.h +++ b/server/shadow/Win/win_shadow.h @@ -37,7 +37,7 @@ typedef struct win_shadow_subsystem winShadowSubsystem; struct win_shadow_subsystem { - RDP_SHADOW_SUBSYSTEM_COMMON(); + rdpShadowSubsystem base; int bpp; int width; diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 2a3f890..d3a07f9 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -384,13 +384,12 @@ static int x11_shadow_pointer_position_update(x11ShadowSubsystem* subsystem) int count = 0; int index = 0; - if (!subsystem || !subsystem->server || !subsystem->server->clients) - return -1; + if (!subsystem || !subsystem->server || !subsystem->server->clients) + return -1; templateMsg.xPos = subsystem->pointerX; templateMsg.yPos = subsystem->pointerY; templateMsg.Free = x11_shadow_message_free; - server = subsystem->server; ArrayList_Lock(server->clients); @@ -858,8 +857,9 @@ static int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, return 1; } -static void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) +static DWORD WINAPI x11_shadow_subsystem_thread(LPVOID arg) { + x11ShadowSubsystem* subsystem = (x11ShadowSubsystem*)arg; XEvent xevent; DWORD status; DWORD nCount; @@ -919,7 +919,7 @@ static void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) } ExitThread(0); - return NULL; + return 0; } static int x11_shadow_subsystem_base_init(x11ShadowSubsystem* subsystem) @@ -1176,6 +1176,7 @@ UINT32 x11_shadow_enum_monitors(MONITOR_DEF* monitors, UINT32 maxMonitors) monitor->flags = 1; } + errno = 0; return numMonitors; } @@ -1209,7 +1210,7 @@ static int x11_shadow_subsystem_init(rdpShadowSubsystem* sub) extensions = XListExtensions(subsystem->display, &nextensions); if (!extensions || (nextensions < 0)) - return -1; + return -1; for (i = 0; i < nextensions; i++) { @@ -1272,7 +1273,7 @@ static int x11_shadow_subsystem_init(rdpShadowSubsystem* sub) subsystem->cursorMaxWidth = 256; subsystem->cursorMaxHeight = 256; subsystem->cursorPixels = _aligned_malloc(subsystem->cursorMaxWidth * - subsystem->cursorMaxHeight * 4, 16); + subsystem->cursorMaxHeight * 4, 16); if (!subsystem->cursorPixels) return -1; @@ -1282,29 +1283,29 @@ static int x11_shadow_subsystem_init(rdpShadowSubsystem* sub) if (subsystem->use_xfixes) { if (x11_shadow_xfixes_init(subsystem) < 0) - subsystem->use_xfixes = FALSE; + subsystem->use_xfixes = FALSE; } if (subsystem->use_xinerama) { if (x11_shadow_xinerama_init(subsystem) < 0) - subsystem->use_xinerama = FALSE; + subsystem->use_xinerama = FALSE; } if (subsystem->use_xshm) { if (x11_shadow_xshm_init(subsystem) < 0) - subsystem->use_xshm = FALSE; + subsystem->use_xshm = FALSE; } if (subsystem->use_xdamage) { if (x11_shadow_xdamage_init(subsystem) < 0) - subsystem->use_xdamage = FALSE; + subsystem->use_xdamage = FALSE; } if (!(subsystem->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, - subsystem->xfds, WINPR_FD_READ))) + subsystem->xfds, WINPR_FD_READ))) return -1; virtualScreen = &(subsystem->virtualScreen); @@ -1322,7 +1323,7 @@ static int x11_shadow_subsystem_init(rdpShadowSubsystem* sub) static int x11_shadow_subsystem_uninit(rdpShadowSubsystem* sub) { - x11ShadowSubsystem* subsystem = (x11ShadowSubsystem*)sub; + x11ShadowSubsystem* subsystem = (x11ShadowSubsystem*)sub; if (!subsystem) return -1; @@ -1350,13 +1351,12 @@ static int x11_shadow_subsystem_uninit(rdpShadowSubsystem* sub) static int x11_shadow_subsystem_start(rdpShadowSubsystem* sub) { - x11ShadowSubsystem* subsystem = (x11ShadowSubsystem*)sub; + x11ShadowSubsystem* subsystem = (x11ShadowSubsystem*)sub; - if (!subsystem) - return -1; + if (!subsystem) + return -1; - if (!(subsystem->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) x11_shadow_subsystem_thread, + if (!(subsystem->thread = CreateThread(NULL, 0, x11_shadow_subsystem_thread, (void*) subsystem, 0, NULL))) { WLog_ERR(TAG, "Failed to create thread"); @@ -1368,10 +1368,10 @@ static int x11_shadow_subsystem_start(rdpShadowSubsystem* sub) static int x11_shadow_subsystem_stop(rdpShadowSubsystem* sub) { - x11ShadowSubsystem* subsystem = (x11ShadowSubsystem*)sub; + x11ShadowSubsystem* subsystem = (x11ShadowSubsystem*)sub; - if (!subsystem) - return -1; + if (!subsystem) + return -1; if (subsystem->thread) { @@ -1397,14 +1397,14 @@ static rdpShadowSubsystem* x11_shadow_subsystem_new(void) subsystem->Authenticate = (pfnShadowAuthenticate) x11_shadow_pam_authenticate; #endif subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) - x11_shadow_input_synchronize_event; + x11_shadow_input_synchronize_event; subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) - x11_shadow_input_keyboard_event; + x11_shadow_input_keyboard_event; subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) - x11_shadow_input_unicode_keyboard_event; + x11_shadow_input_unicode_keyboard_event; subsystem->MouseEvent = (pfnShadowMouseEvent) x11_shadow_input_mouse_event; subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) - x11_shadow_input_extended_mouse_event; + x11_shadow_input_extended_mouse_event; subsystem->composite = FALSE; subsystem->use_xshm = FALSE; /* temporarily disabled */ subsystem->use_xfixes = TRUE; @@ -1424,8 +1424,8 @@ static void x11_shadow_subsystem_free(rdpShadowSubsystem* subsystem) FREERDP_API int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { - if (!pEntryPoints) - return -1; + if (!pEntryPoints) + return -1; pEntryPoints->New = x11_shadow_subsystem_new; pEntryPoints->Free = x11_shadow_subsystem_free; diff --git a/server/shadow/freerdp-shadow-cli.1.in b/server/shadow/freerdp-shadow-cli.1.in index 97cef81..46f376d 100644 --- a/server/shadow/freerdp-shadow-cli.1.in +++ b/server/shadow/freerdp-shadow-cli.1.in @@ -1,7 +1,7 @@ .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. -.if \n[.g] .mso www.tmac)) +.if \n[.g] .mso www.tmac .TH freerdp\-shadow\-cli 1 2017-01-12 "@FREERDP_VERSION_FULL@" "FreeRDP" .SH NAME freerdp\-shadow\-cli \- A utility for sharing a X display via RDP. @@ -49,14 +49,14 @@ Clients may view without prompt. Clients may interact without prompt. .IP /sec:<rdp|tls|nla|ext> Force a specific protocol security -.IP -sec-rdp (default:on) -Disable RDP security -.IP -sec-tls (default:on) -Disable TLS protocol security -.IP -sec-nla (default:on) -Disable NLA protocol security -.IP +sec-ext (default:off) -Use NLA extended protocol security +.IP -sec-rdp +Disable RDP security (default:on) +.IP -sec-tls +Disable TLS protocol security (default:on) +.IP -sec-nla +Disable NLA protocol security (default:on) +.IP +sec-ext +Use NLA extended protocol security (default:off) .IP /sam-file:<file> NTLM SAM file for NLA authentication .IP /version diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 08a1331..94337c9 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -641,10 +641,11 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, flags = pdu.capsSet->flags; settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); #ifndef WITH_GFX_H264 - settings->GfxH264 = FALSE; + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = FALSE; pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; #else - settings->GfxH264 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED); + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = !(flags & + RDPGFX_CAPS_FLAG_AVC_DISABLED); #endif } @@ -667,10 +668,11 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, flags = pdu.capsSet->flags; settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); #ifndef WITH_GFX_H264 - settings->GfxH264 = FALSE; + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = FALSE; pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; #else - settings->GfxH264 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED); + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = !(flags & + RDPGFX_CAPS_FLAG_AVC_DISABLED); #endif } @@ -693,10 +695,10 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, flags = pdu.capsSet->flags; settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); #ifndef WITH_GFX_H264 - settings->GfxH264 = FALSE; + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = FALSE; pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; #else - settings->GfxH264 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED); + settings->GfxAVC444 = settings->GfxH264 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED); #endif } @@ -709,7 +711,7 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index]; if (currentCaps->version == RDPGFX_CAPVERSION_81) - { + { RDPGFX_CAPSET caps = *currentCaps; RDPGFX_CAPS_CONFIRM_PDU pdu; pdu.capsSet = ∩︀ @@ -717,8 +719,9 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, if (settings) { flags = pdu.capsSet->flags; + settings->GfxAVC444v2 = settings->GfxAVC444 = FALSE; settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT); - settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); + settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); #ifndef WITH_GFX_H264 settings->GfxH264 = FALSE; pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED; @@ -755,6 +758,15 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, return CHANNEL_RC_UNSUPPORTED_VERSION; } +static INLINE UINT32 rdpgfx_estimate_h264_avc420( + RDPGFX_AVC420_BITMAP_STREAM* havc420) +{ + /* H264 metadata + H264 stream. See rdpgfx_write_h264_avc420 */ + return sizeof(UINT32) /* numRegionRects */ + + 10 /* regionRects + quantQualityVals */ + * havc420->meta.numRegionRects + + havc420->length; +} /** * Function description @@ -801,7 +813,55 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, cmd.data = NULL; cmd.extra = NULL; - if (settings->GfxH264) + if (settings->GfxAVC444 || settings->GfxAVC444v2) + { + RDPGFX_AVC444_BITMAP_STREAM avc444; + RECTANGLE_16 regionRect; + RDPGFX_H264_QUANT_QUALITY quantQualityVal; + BYTE version = settings->GfxAVC444v2 ? 2 : 1; + + if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC444) < 0) + { + WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_AVC444"); + return FALSE; + } + + if (avc444_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, + nWidth, nHeight, version, &avc444.LC, &avc444.bitstream[0].data, + &avc444.bitstream[0].length, &avc444.bitstream[1].data, + &avc444.bitstream[1].length) < 0) + { + WLog_ERR(TAG, "avc420_compress failed for avc444"); + return FALSE; + } + + regionRect.left = cmd.left; + regionRect.top = cmd.top; + regionRect.right = cmd.right; + regionRect.bottom = cmd.bottom; + quantQualityVal.qp = encoder->h264->QP; + quantQualityVal.r = 0; + quantQualityVal.p = 0; + quantQualityVal.qualityVal = 100 - quantQualityVal.qp; + avc444.bitstream[0].meta.numRegionRects = 1; + avc444.bitstream[0].meta.regionRects = ®ionRect; + avc444.bitstream[0].meta.quantQualityVals = &quantQualityVal; + avc444.bitstream[1].meta.numRegionRects = 1; + avc444.bitstream[1].meta.regionRects = ®ionRect; + avc444.bitstream[1].meta.quantQualityVals = &quantQualityVal; + avc444.cbAvc420EncodedBitstream1 = rdpgfx_estimate_h264_avc420(&avc444.bitstream[0]); + cmd.codecId = settings->GfxAVC444v2 ? RDPGFX_CODECID_AVC444v2 : RDPGFX_CODECID_AVC444; + cmd.extra = (void*)&avc444; + IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, + &cmdstart, &cmdend); + + if (error) + { + WLog_ERR(TAG, "SurfaceFrameCommand failed with error %"PRIu32"", error); + return FALSE; + } + } + else if (settings->GfxH264) { RDPGFX_AVC420_BITMAP_STREAM avc420; RECTANGLE_16 regionRect; @@ -813,8 +873,13 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, return FALSE; } - avc420_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, - nWidth, nHeight, &avc420.data, &avc420.length); + if (avc420_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, + nWidth, nHeight, &avc420.data, &avc420.length) < 0) + { + WLog_ERR(TAG, "avc420_compress failed"); + return FALSE; + } + cmd.codecId = RDPGFX_CODECID_AVC420; cmd.extra = (void*)&avc420; regionRect.left = cmd.left; @@ -860,7 +925,7 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, rdpContext* context = (rdpContext*) client; rdpSettings* settings; rdpShadowEncoder* encoder; - SURFACE_BITS_COMMAND cmd; + SURFACE_BITS_COMMAND cmd = { 0 }; if (!context || !pSrcData) return FALSE; @@ -901,14 +966,15 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, return FALSE; } - cmd.codecID = settings->RemoteFxCodecId; + cmd.bmp.codecID = settings->RemoteFxCodecId; cmd.destLeft = 0; cmd.destTop = 0; cmd.destRight = settings->DesktopWidth; cmd.destBottom = settings->DesktopHeight; - cmd.bpp = 32; - cmd.width = settings->DesktopWidth; - cmd.height = settings->DesktopHeight; + cmd.bmp.bpp = 32; + cmd.bmp.flags = 0; + cmd.bmp.width = settings->DesktopWidth; + cmd.bmp.height = settings->DesktopHeight; cmd.skipCompression = TRUE; if (numMessages > 0) @@ -931,8 +997,8 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, } rfx_message_free(encoder->rfx, &messages[i]); - cmd.bitmapDataLength = Stream_GetPosition(s); - cmd.bitmapData = Stream_Buffer(s); + cmd.bmp.bitmapDataLength = Stream_GetPosition(s); + cmd.bmp.bitmapData = Stream_Buffer(s); first = (i == 0) ? TRUE : FALSE; last = ((i + 1) == numMessages) ? TRUE : FALSE; @@ -964,16 +1030,16 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, Stream_SetPosition(s, 0); pSrcData = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)]; nsc_compose_message(encoder->nsc, s, pSrcData, nWidth, nHeight, nSrcStep); - cmd.bpp = 32; - cmd.codecID = settings->NSCodecId; + cmd.bmp.bpp = 32; + cmd.bmp.codecID = settings->NSCodecId; cmd.destLeft = nXSrc; cmd.destTop = nYSrc; cmd.destRight = cmd.destLeft + nWidth; cmd.destBottom = cmd.destTop + nHeight; - cmd.width = nWidth; - cmd.height = nHeight; - cmd.bitmapDataLength = Stream_GetPosition(s); - cmd.bitmapData = Stream_Buffer(s); + cmd.bmp.width = nWidth; + cmd.bmp.height = nHeight; + cmd.bmp.bitmapDataLength = Stream_GetPosition(s); + cmd.bmp.bitmapData = Stream_Buffer(s); first = TRUE; last = TRUE; @@ -1529,8 +1595,9 @@ static int shadow_client_subsystem_process_message(rdpShadowClient* client, return 1; } -static void* shadow_client_thread(rdpShadowClient* client) +static DWORD WINAPI shadow_client_thread(LPVOID arg) { + rdpShadowClient* client = (rdpShadowClient*)arg; DWORD status; DWORD nCount; wMessage message; @@ -1803,7 +1870,7 @@ out: freerdp_peer_context_free(peer); freerdp_peer_free(peer); ExitThread(0); - return NULL; + return 0; } BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer) @@ -1826,8 +1893,7 @@ BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer) client = (rdpShadowClient*) peer->context; - if (!(client->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) - shadow_client_thread, client, 0, NULL))) + if (!(client->thread = CreateThread(NULL, 0, shadow_client_thread, client, 0, NULL))) { freerdp_peer_context_free(peer); return FALSE; diff --git a/server/shadow/shadow_encoder.c b/server/shadow/shadow_encoder.c index 5d92184..b7e422e 100644 --- a/server/shadow/shadow_encoder.c +++ b/server/shadow/shadow_encoder.c @@ -238,7 +238,7 @@ static int shadow_encoder_init_h264(rdpShadowEncoder* encoder) encoder->h264->BitRate = encoder->server->h264BitRate; encoder->h264->FrameRate = encoder->server->h264FrameRate; encoder->h264->QP = encoder->server->h264QP; - encoder->codecs |= FREERDP_CODEC_AVC420; + encoder->codecs |= FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444; return 1; fail: h264_context_free(encoder->h264); @@ -319,7 +319,7 @@ static int shadow_encoder_uninit_h264(rdpShadowEncoder* encoder) encoder->h264 = NULL; } - encoder->codecs &= ~FREERDP_CODEC_AVC420; + encoder->codecs &= ~(FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444); return 1; } @@ -353,7 +353,7 @@ static int shadow_encoder_uninit(rdpShadowEncoder* encoder) shadow_encoder_uninit_interleaved(encoder); } - if (encoder->codecs & FREERDP_CODEC_AVC420) + if (encoder->codecs & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444)) { shadow_encoder_uninit_h264(encoder); } @@ -430,8 +430,8 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs) return -1; } - if ((codecs & FREERDP_CODEC_AVC420) - && !(encoder->codecs & FREERDP_CODEC_AVC420)) + if ((codecs & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444)) + && !(encoder->codecs & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444))) { status = shadow_encoder_init_h264(encoder); diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index 2c0e0bf..fa7213e 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -22,6 +22,8 @@ #include "config.h" #endif +#include <errno.h> + #include <winpr/crt.h> #include <winpr/ssl.h> #include <winpr/wnd.h> @@ -172,6 +174,7 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a return status; arg = shadow_args; + errno = 0; do { @@ -181,7 +184,12 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "port") { - server->port = (DWORD) atoi(arg->Value); + long val = strtol(arg->Value, NULL, 0); + + if ((errno != 0) || (val <= 0) || (val > UINT16_MAX)) + return -1; + + server->port = (DWORD) val; } CommandLineSwitchCase(arg, "ipc-socket") { @@ -202,7 +210,7 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a { char* p; char* tok[4]; - int x, y, w, h; + long x = -1, y = -1, w = -1, h = -1; char* str = _strdup(arg->Value); if (!str) @@ -239,13 +247,30 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a *p++ = '\0'; tok[3] = p; - x = atoi(tok[0]); - y = atoi(tok[1]); - w = atoi(tok[2]); - h = atoi(tok[3]); + x = strtol(tok[0], NULL, 0); + + if (errno != 0) + goto fail; + + y = strtol(tok[1], NULL, 0); + + if (errno != 0) + goto fail; + + w = strtol(tok[2], NULL, 0); + + if (errno != 0) + goto fail; + + h = strtol(tok[3], NULL, 0); + + if (errno != 0) + goto fail; + + fail: free(str); - if ((x < 0) || (y < 0) || (w < 1) || (h < 1)) + if ((x < 0) || (y < 0) || (w < 1) || (h < 1) || (errno != 0)) return -1; server->subRect.left = x; @@ -333,15 +358,12 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) { /* Select monitors */ - index = atoi(arg->Value); + long val = strtol(arg->Value, NULL, 0); - if (index < 0) - index = 0; + if ((val < 0) || (errno != 0) || (val >= numMonitors)) + status = COMMAND_LINE_STATUS_PRINT; - if (index >= numMonitors) - index = 0; - - server->selectedMonitor = index; + server->selectedMonitor = val; } else { @@ -367,8 +389,9 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a return status; } -static void* shadow_server_thread(rdpShadowServer* server) +static DWORD WINAPI shadow_server_thread(LPVOID arg) { + rdpShadowServer* server = (rdpShadowServer*)arg; BOOL running = TRUE; DWORD status; freerdp_listener* listener = server->listener; @@ -428,7 +451,7 @@ static void* shadow_server_thread(rdpShadowServer* server) } ExitThread(0); - return NULL; + return 0; } int shadow_server_start(rdpShadowServer* server) @@ -472,8 +495,7 @@ int shadow_server_start(rdpShadowServer* server) return -1; } - if (!(server->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) - shadow_server_thread, (void*) server, 0, NULL))) + if (!(server->thread = CreateThread(NULL, 0, shadow_server_thread, (void*) server, 0, NULL))) { return -1; } @@ -766,7 +788,7 @@ rdpShadowServer* shadow_server_new(void) server->mayInteract = TRUE; server->rfxMode = RLGR3; server->h264RateControlMode = H264_RATECONTROL_VBR; - server->h264BitRate = 1000000; + server->h264BitRate = 10000000; server->h264FrameRate = 30; server->h264QP = 0; server->authentication = FALSE; diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index 89c5e27..8daf717 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -683,7 +683,12 @@ static void pointer_axis_source(void *data, struct wl_pointer *wl_pointer, uint3 /*UwacSeat *seat = data;*/ } -void pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) +static void pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) +{ + /*UwacSeat *seat = data;*/ +} + +static void pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete) { /*UwacSeat *seat = data;*/ } @@ -697,6 +702,7 @@ static const struct wl_pointer_listener pointer_listener = { pointer_frame, pointer_axis_source, pointer_axis_stop, + pointer_axis_discrete, }; diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index 9c2e792..e56b3ad 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -39,7 +39,6 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/) # Check for cmake compatibility (enable/disable features) include(CheckCmakeCompat) include(FindFeature) -include(AutoVersioning) include(ConfigOptions) include(ComplexLibrary) include(FeatureSummary) diff --git a/winpr/include/winpr/cmdline.h b/winpr/include/winpr/cmdline.h index b843ee7..2452ad4 100644 --- a/winpr/include/winpr/cmdline.h +++ b/winpr/include/winpr/cmdline.h @@ -137,13 +137,17 @@ extern "C" { WINPR_API int CommandLineClearArgumentsA(COMMAND_LINE_ARGUMENT_A* options); WINPR_API int CommandLineClearArgumentsW(COMMAND_LINE_ARGUMENT_W* options); -WINPR_API int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* options, DWORD flags, - void* context, COMMAND_LINE_PRE_FILTER_FN_A preFilter, COMMAND_LINE_POST_FILTER_FN_A postFilter); -WINPR_API int CommandLineParseArgumentsW(int argc, LPCWSTR* argv, COMMAND_LINE_ARGUMENT_W* options, DWORD flags, - void* context, COMMAND_LINE_PRE_FILTER_FN_W preFilter, COMMAND_LINE_POST_FILTER_FN_W postFilter); +WINPR_API int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* options, + DWORD flags, + void* context, COMMAND_LINE_PRE_FILTER_FN_A preFilter, COMMAND_LINE_POST_FILTER_FN_A postFilter); +WINPR_API int CommandLineParseArgumentsW(int argc, LPCWSTR* argv, COMMAND_LINE_ARGUMENT_W* options, + DWORD flags, + void* context, COMMAND_LINE_PRE_FILTER_FN_W preFilter, COMMAND_LINE_POST_FILTER_FN_W postFilter); -WINPR_API COMMAND_LINE_ARGUMENT_A* CommandLineFindArgumentA(COMMAND_LINE_ARGUMENT_A* options, LPCSTR Name); -WINPR_API COMMAND_LINE_ARGUMENT_W* CommandLineFindArgumentW(COMMAND_LINE_ARGUMENT_W* options, LPCWSTR Name); +WINPR_API COMMAND_LINE_ARGUMENT_A* CommandLineFindArgumentA(COMMAND_LINE_ARGUMENT_A* options, + LPCSTR Name); +WINPR_API COMMAND_LINE_ARGUMENT_W* CommandLineFindArgumentW(COMMAND_LINE_ARGUMENT_W* options, + LPCWSTR Name); WINPR_API COMMAND_LINE_ARGUMENT_A* CommandLineFindNextArgumentA(COMMAND_LINE_ARGUMENT_A* argument); diff --git a/winpr/include/winpr/crt.h b/winpr/include/winpr/crt.h index 25e9b79..397f7e4 100644 --- a/winpr/include/winpr/crt.h +++ b/winpr/include/winpr/crt.h @@ -32,26 +32,38 @@ #ifndef _WIN32 +#ifndef _strtoui64 +#define _strtoui64 strtoull +#endif + +#ifndef _strtoi64 +#define _strtoi64 strtoll +#endif + #ifndef _rotl -static INLINE UINT32 _rotl(UINT32 value, int shift) { +static INLINE UINT32 _rotl(UINT32 value, int shift) +{ return (value << shift) | (value >> (32 - shift)); } #endif #ifndef _rotl64 -static INLINE UINT64 _rotl64(UINT64 value, int shift) { +static INLINE UINT64 _rotl64(UINT64 value, int shift) +{ return (value << shift) | (value >> (64 - shift)); } #endif #ifndef _rotr -static INLINE UINT32 _rotr(UINT32 value, int shift) { +static INLINE UINT32 _rotr(UINT32 value, int shift) +{ return (value >> shift) | (value << (32 - shift)); } #endif #ifndef _rotr64 -static INLINE UINT64 _rotr64(UINT64 value, int shift) { +static INLINE UINT64 _rotr64(UINT64 value, int shift) +{ return (value >> shift) | (value << (64 - shift)); } #endif @@ -63,22 +75,24 @@ static INLINE UINT64 _rotr64(UINT64 value, int shift) { #else -static INLINE UINT32 _byteswap_ulong(UINT32 _val) { - return (((_val) >> 24) | \ - (((_val) & 0x00FF0000) >> 8) | \ - (((_val) & 0x0000FF00) << 8) | \ - ((_val) << 24)); +static INLINE UINT32 _byteswap_ulong(UINT32 _val) +{ + return (((_val) >> 24) | \ + (((_val) & 0x00FF0000) >> 8) | \ + (((_val) & 0x0000FF00) << 8) | \ + ((_val) << 24)); } -static INLINE UINT64 _byteswap_uint64(UINT64 _val) { - return (((_val) << 56) | \ - (((_val) << 40) & 0xFF000000000000) | \ - (((_val) << 24) & 0xFF0000000000) | \ - (((_val) << 8) & 0xFF00000000) | \ - (((_val) >> 8) & 0xFF000000) | \ - (((_val) >> 24) & 0xFF0000) | \ - (((_val) >> 40) & 0xFF00) | \ - ((_val) >> 56)); +static INLINE UINT64 _byteswap_uint64(UINT64 _val) +{ + return (((_val) << 56) | \ + (((_val) << 40) & 0xFF000000000000) | \ + (((_val) << 24) & 0xFF0000000000) | \ + (((_val) << 8) & 0xFF00000000) | \ + (((_val) >> 8) & 0xFF000000) | \ + (((_val) >> 24) & 0xFF0000) | \ + (((_val) >> 40) & 0xFF00) | \ + ((_val) >> 56)); } #endif @@ -89,7 +103,8 @@ static INLINE UINT64 _byteswap_uint64(UINT64 _val) { #else -static INLINE UINT16 _byteswap_ushort(UINT16 _val) { +static INLINE UINT16 _byteswap_ushort(UINT16 _val) +{ return (((_val) >> 8) | ((_val) << 8)); } @@ -128,8 +143,10 @@ WINPR_API void* _aligned_realloc(void* memblock, size_t size, size_t alignment); WINPR_API void* _aligned_recalloc(void* memblock, size_t num, size_t size, size_t alignment); WINPR_API void* _aligned_offset_malloc(size_t size, size_t alignment, size_t offset); -WINPR_API void* _aligned_offset_realloc(void* memblock, size_t size, size_t alignment, size_t offset); -WINPR_API void* _aligned_offset_recalloc(void* memblock, size_t num, size_t size, size_t alignment, size_t offset); +WINPR_API void* _aligned_offset_realloc(void* memblock, size_t size, size_t alignment, + size_t offset); +WINPR_API void* _aligned_offset_recalloc(void* memblock, size_t num, size_t size, size_t alignment, + size_t offset); WINPR_API size_t _aligned_msize(void* memblock, size_t alignment, size_t offset); diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 3ee989e..b674960 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -617,6 +617,7 @@ BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, L #define WINPR_MD4_DIGEST_LENGTH 16 #define WINPR_MD5_DIGEST_LENGTH 16 #define WINPR_SHA1_DIGEST_LENGTH 20 +#define WINPR_SHA256_DIGEST_LENGTH 32 /** @@ -665,11 +666,13 @@ extern "C" { #endif WINPR_API WINPR_DIGEST_CTX* winpr_Digest_New(void); +WINPR_API BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md); 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 void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx); -WINPR_API BOOL winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen); +WINPR_API BOOL winpr_Digest_Allow_FIPS(WINPR_MD_TYPE md, const BYTE* input, size_t ilen, BYTE* output, size_t olen); +WINPR_API BOOL winpr_Digest(WINPR_MD_TYPE md, const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -700,6 +703,7 @@ typedef struct _winpr_rc4_ctx_private_st WINPR_RC4_CTX; extern "C" { #endif +WINPR_API WINPR_RC4_CTX* winpr_RC4_New_Allow_FIPS(const BYTE* key, size_t keylen); 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); diff --git a/winpr/include/winpr/pool.h b/winpr/include/winpr/pool.h index b49350a..1d52c96 100644 --- a/winpr/include/winpr/pool.h +++ b/winpr/include/winpr/pool.h @@ -61,9 +61,9 @@ typedef struct _TP_CALLBACK_ENVIRON_V1 DWORD Flags; struct { - DWORD LongFunction:1; - DWORD Persistent:1; - DWORD Private:30; + DWORD LongFunction: 1; + DWORD Persistent: 1; + DWORD Private: 30; } s; } u; } TP_CALLBACK_ENVIRON_V1; @@ -85,14 +85,15 @@ typedef struct _TP_IO TP_IO, *PTP_IO; typedef VOID (*PTP_WORK_CALLBACK)(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work); typedef VOID (*PTP_TIMER_CALLBACK)(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_TIMER Timer); -typedef VOID (*PTP_WAIT_CALLBACK)(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WAIT Wait, TP_WAIT_RESULT WaitResult); +typedef VOID (*PTP_WAIT_CALLBACK)(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WAIT Wait, + TP_WAIT_RESULT WaitResult); #endif -/* -There is a bug in the Win8 header that defines the IO +/* +There is a bug in the Win8 header that defines the IO callback unconditionally. Versions of Windows greater -than XP will conditionally define it. The following +than XP will conditionally define it. The following logic tries to fix that. */ #ifdef _THREADPOOLAPISET_H_ @@ -105,8 +106,9 @@ logic tries to fix that. #ifndef PTP_WIN32_IO_CALLBACK_DEFINED -typedef VOID (*PTP_WIN32_IO_CALLBACK)(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PVOID Overlapped, - ULONG IoResult, ULONG_PTR NumberOfBytesTransferred, PTP_IO Io); +typedef VOID (*PTP_WIN32_IO_CALLBACK)(PTP_CALLBACK_INSTANCE Instance, PVOID Context, + PVOID Overlapped, + ULONG IoResult, ULONG_PTR NumberOfBytesTransferred, PTP_IO Io); #endif @@ -122,7 +124,8 @@ extern "C" { #ifdef WINPR_THREAD_POOL -WINPR_API PTP_WAIT winpr_CreateThreadpoolWait(PTP_WAIT_CALLBACK pfnwa, PVOID pv, PTP_CALLBACK_ENVIRON pcbe); +WINPR_API PTP_WAIT winpr_CreateThreadpoolWait(PTP_WAIT_CALLBACK pfnwa, PVOID pv, + PTP_CALLBACK_ENVIRON pcbe); WINPR_API VOID winpr_CloseThreadpoolWait(PTP_WAIT pwa); WINPR_API VOID winpr_SetThreadpoolWait(PTP_WAIT pwa, HANDLE h, PFILETIME pftTimeout); WINPR_API VOID winpr_WaitForThreadpoolWaitCallbacks(PTP_WAIT pwa, BOOL fCancelPendingCallbacks); @@ -134,10 +137,12 @@ WINPR_API VOID winpr_WaitForThreadpoolWaitCallbacks(PTP_WAIT pwa, BOOL fCancelPe /* Work */ -WINPR_API PTP_WORK winpr_CreateThreadpoolWork(PTP_WORK_CALLBACK pfnwk, PVOID pv, PTP_CALLBACK_ENVIRON pcbe); +WINPR_API PTP_WORK winpr_CreateThreadpoolWork(PTP_WORK_CALLBACK pfnwk, PVOID pv, + PTP_CALLBACK_ENVIRON pcbe); WINPR_API VOID winpr_CloseThreadpoolWork(PTP_WORK pwk); WINPR_API VOID winpr_SubmitThreadpoolWork(PTP_WORK pwk); -WINPR_API BOOL winpr_TrySubmitThreadpoolCallback(PTP_SIMPLE_CALLBACK pfns, PVOID pv, PTP_CALLBACK_ENVIRON pcbe); +WINPR_API BOOL winpr_TrySubmitThreadpoolCallback(PTP_SIMPLE_CALLBACK pfns, PVOID pv, + PTP_CALLBACK_ENVIRON pcbe); WINPR_API VOID winpr_WaitForThreadpoolWorkCallbacks(PTP_WORK pwk, BOOL fCancelPendingCallbacks); #define CreateThreadpoolWork winpr_CreateThreadpoolWork @@ -148,10 +153,12 @@ WINPR_API VOID winpr_WaitForThreadpoolWorkCallbacks(PTP_WORK pwk, BOOL fCancelPe /* Timer */ -WINPR_API PTP_TIMER winpr_CreateThreadpoolTimer(PTP_TIMER_CALLBACK pfnti, PVOID pv, PTP_CALLBACK_ENVIRON pcbe); +WINPR_API PTP_TIMER winpr_CreateThreadpoolTimer(PTP_TIMER_CALLBACK pfnti, PVOID pv, + PTP_CALLBACK_ENVIRON pcbe); WINPR_API VOID winpr_CloseThreadpoolTimer(PTP_TIMER pti); WINPR_API BOOL winpr_IsThreadpoolTimerSet(PTP_TIMER pti); -WINPR_API VOID winpr_SetThreadpoolTimer(PTP_TIMER pti, PFILETIME pftDueTime, DWORD msPeriod, DWORD msWindowLength); +WINPR_API VOID winpr_SetThreadpoolTimer(PTP_TIMER pti, PFILETIME pftDueTime, DWORD msPeriod, + DWORD msWindowLength); WINPR_API VOID winpr_WaitForThreadpoolTimerCallbacks(PTP_TIMER pti, BOOL fCancelPendingCallbacks); #define CreateThreadpoolTimer winpr_CreateThreadpoolTimer @@ -162,7 +169,8 @@ WINPR_API VOID winpr_WaitForThreadpoolTimerCallbacks(PTP_TIMER pti, BOOL fCancel /* I/O */ -WINPR_API PTP_IO winpr_CreateThreadpoolIo(HANDLE fl, PTP_WIN32_IO_CALLBACK pfnio, PVOID pv, PTP_CALLBACK_ENVIRON pcbe); +WINPR_API PTP_IO winpr_CreateThreadpoolIo(HANDLE fl, PTP_WIN32_IO_CALLBACK pfnio, PVOID pv, + PTP_CALLBACK_ENVIRON pcbe); WINPR_API VOID winpr_CloseThreadpoolIo(PTP_IO pio); WINPR_API VOID winpr_StartThreadpoolIo(PTP_IO pio); WINPR_API VOID winpr_CancelThreadpoolIo(PTP_IO pio); @@ -176,10 +184,14 @@ WINPR_API VOID winpr_WaitForThreadpoolIoCallbacks(PTP_IO pio, BOOL fCancelPendin /* Clean-up Group */ +WINPR_API VOID winpr_SetThreadpoolCallbackCleanupGroup(PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, + PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng); WINPR_API PTP_CLEANUP_GROUP winpr_CreateThreadpoolCleanupGroup(void); -WINPR_API VOID winpr_CloseThreadpoolCleanupGroupMembers(PTP_CLEANUP_GROUP ptpcg, BOOL fCancelPendingCallbacks, PVOID pvCleanupContext); +WINPR_API VOID winpr_CloseThreadpoolCleanupGroupMembers(PTP_CLEANUP_GROUP ptpcg, + BOOL fCancelPendingCallbacks, PVOID pvCleanupContext); WINPR_API VOID winpr_CloseThreadpoolCleanupGroup(PTP_CLEANUP_GROUP ptpcg); +#define SetThreadpoolCallbackCleanupGroup winpr_SetThreadpoolCallbackCleanupGroup #define CreateThreadpoolCleanupGroup winpr_CreateThreadpoolCleanupGroup #define CloseThreadpoolCleanupGroupMembers winpr_CloseThreadpoolCleanupGroupMembers #define CloseThreadpoolCleanupGroup winpr_CloseThreadpoolCleanupGroup @@ -220,12 +232,6 @@ static INLINE VOID SetThreadpoolCallbackPool(PTP_CALLBACK_ENVIRON pcbe, PTP_POOL pcbe->Pool = ptpp; } -static INLINE VOID SetThreadpoolCallbackCleanupGroup(PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng) -{ - pcbe->CleanupGroup = ptpcg; - pcbe->CleanupGroupCancelCallback = pfng; -} - static INLINE VOID SetThreadpoolCallbackRunsLong(PTP_CALLBACK_ENVIRON pcbe) { pcbe->u.s.LongFunction = 1; @@ -244,9 +250,11 @@ WINPR_API BOOL winpr_CallbackMayRunLong(PTP_CALLBACK_INSTANCE pci); /* Callback Clean-up */ WINPR_API VOID winpr_SetEventWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HANDLE evt); -WINPR_API VOID winpr_ReleaseSemaphoreWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HANDLE sem, DWORD crel); +WINPR_API VOID winpr_ReleaseSemaphoreWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HANDLE sem, + DWORD crel); WINPR_API VOID winpr_ReleaseMutexWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HANDLE mut); -WINPR_API VOID winpr_LeaveCriticalSectionWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, PCRITICAL_SECTION pcs); +WINPR_API VOID winpr_LeaveCriticalSectionWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, + PCRITICAL_SECTION pcs); WINPR_API VOID winpr_FreeLibraryWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HMODULE mod); WINPR_API VOID winpr_DisassociateCurrentThreadFromCallback(PTP_CALLBACK_INSTANCE pci); diff --git a/winpr/include/winpr/smartcard.h b/winpr/include/winpr/smartcard.h index 8b52beb..d168f2d 100644 --- a/winpr/include/winpr/smartcard.h +++ b/winpr/include/winpr/smartcard.h @@ -789,8 +789,6 @@ WINSCARDAPI LONG WINAPI SCardListReadersWithDeviceInstanceIdW(SCARDCONTEXT hCont WINSCARDAPI LONG WINAPI SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent); -WINSCARDAPI LONG WINAPI SCardAddReaderName(HANDLE* key, LPSTR readerName); - #ifdef UNICODE #define SCardListReaderGroups SCardListReaderGroupsW #define SCardListReaders SCardListReadersW @@ -1045,8 +1043,6 @@ typedef LONG(WINAPI* fnSCardListReadersWithDeviceInstanceIdW)(SCARDCONTEXT hCont typedef LONG(WINAPI* fnSCardAudit)(SCARDCONTEXT hContext, DWORD dwEvent); -typedef LONG(WINAPI* fnSCardAddReaderName)(HANDLE* key, LPSTR readerName); - struct _SCardApiFunctionTable { DWORD dwVersion; @@ -1128,7 +1124,6 @@ struct _SCardApiFunctionTable fnSCardListReadersWithDeviceInstanceIdA pfnSCardListReadersWithDeviceInstanceIdA; fnSCardListReadersWithDeviceInstanceIdW pfnSCardListReadersWithDeviceInstanceIdW; fnSCardAudit pfnSCardAudit; - fnSCardAddReaderName pfnSCardAddReaderName; }; typedef struct _SCardApiFunctionTable SCardApiFunctionTable; diff --git a/winpr/include/winpr/ssl.h b/winpr/include/winpr/ssl.h index 647c0e4..0ff6b74 100644 --- a/winpr/include/winpr/ssl.h +++ b/winpr/include/winpr/ssl.h @@ -26,6 +26,7 @@ #define WINPR_SSL_INIT_DEFAULT 0x00 #define WINPR_SSL_INIT_ALREADY_INITIALIZED 0x01 #define WINPR_SSL_INIT_ENABLE_LOCKING 0x2 +#define WINPR_SSL_INIT_ENABLE_FIPS 0x4 #define WINPR_SSL_CLEANUP_GLOBAL 0x01 #define WINPR_SSL_CLEANUP_THREAD 0x02 @@ -37,6 +38,8 @@ extern "C" { WINPR_API BOOL winpr_InitializeSSL(DWORD flags); WINPR_API BOOL winpr_CleanupSSL(DWORD flags); +WINPR_API BOOL winpr_FIPSMode(void); + #ifdef __cplusplus } #endif diff --git a/winpr/include/winpr/sspi.h b/winpr/include/winpr/sspi.h index 53a033a..7667f0b 100644 --- a/winpr/include/winpr/sspi.h +++ b/winpr/include/winpr/sspi.h @@ -92,11 +92,12 @@ typedef SecPkgInfoW* PSecPkgInfoW; #define PSecPkgInfo PSecPkgInfoA #endif -#define NTLMSP_NAME _T("NTLM") -#define NEGOSSP_NAME _T("Negotiate") - #endif +#define NTLM_SSP_NAME _T("NTLM") +#define KERBEROS_SSP_NAME _T("Kerberos") +#define NEGO_SSP_NAME _T("Negotiate") + #define SECPKG_ID_NONE 0xFFFF #define SECPKG_FLAG_INTEGRITY 0x00000001 @@ -589,6 +590,7 @@ typedef SecPkgCredentials_NamesW* PSecPkgCredentials_NamesW; typedef struct _SEC_WINNT_AUTH_IDENTITY_W { + /* TSPasswordCreds */ UINT16* User; UINT32 UserLength; UINT16* Domain; @@ -596,10 +598,11 @@ typedef struct _SEC_WINNT_AUTH_IDENTITY_W UINT16* Password; UINT32 PasswordLength; UINT32 Flags; -} SEC_WINNT_AUTH_IDENTITY_W,*PSEC_WINNT_AUTH_IDENTITY_W; +} SEC_WINNT_AUTH_IDENTITY_W, *PSEC_WINNT_AUTH_IDENTITY_W; typedef struct _SEC_WINNT_AUTH_IDENTITY_A { + /* TSPasswordCreds */ BYTE* User; UINT32 UserLength; BYTE* Domain; @@ -607,10 +610,11 @@ typedef struct _SEC_WINNT_AUTH_IDENTITY_A BYTE* Password; UINT32 PasswordLength; UINT32 Flags; -} SEC_WINNT_AUTH_IDENTITY_A,*PSEC_WINNT_AUTH_IDENTITY_A; +} SEC_WINNT_AUTH_IDENTITY_A, *PSEC_WINNT_AUTH_IDENTITY_A; struct _SEC_WINNT_AUTH_IDENTITY { + /* TSPasswordCreds */ UINT16* User; UINT32 UserLength; UINT16* Domain; @@ -641,7 +645,7 @@ typedef CtxtHandle* PCtxtHandle; #define SecIsValidHandle(x) \ ((((PSecHandle)(x))->dwLower != ((ULONG_PTR)((INT_PTR) - 1))) && \ - (((PSecHandle) (x))->dwUpper != ((ULONG_PTR)((INT_PTR) - 1)))) + (((PSecHandle) (x))->dwUpper != ((ULONG_PTR)((INT_PTR) - 1)))) #endif @@ -693,10 +697,13 @@ struct _SecBufferDesc typedef struct _SecBufferDesc SecBufferDesc; typedef SecBufferDesc* PSecBufferDesc; -typedef void (SEC_ENTRY * SEC_GET_KEY_FN)(void* Arg, void* Principal, UINT32 KeyVer, void** Key, SECURITY_STATUS* pStatus); +typedef void (SEC_ENTRY* SEC_GET_KEY_FN)(void* Arg, void* Principal, UINT32 KeyVer, void** Key, + SECURITY_STATUS* pStatus); -typedef SECURITY_STATUS (SEC_ENTRY * ENUMERATE_SECURITY_PACKAGES_FN_A)(ULONG* pcPackages, PSecPkgInfoA* ppPackageInfo); -typedef SECURITY_STATUS (SEC_ENTRY * ENUMERATE_SECURITY_PACKAGES_FN_W)(ULONG* pcPackages, PSecPkgInfoW* ppPackageInfo); +typedef SECURITY_STATUS(SEC_ENTRY* ENUMERATE_SECURITY_PACKAGES_FN_A)(ULONG* pcPackages, + PSecPkgInfoA* ppPackageInfo); +typedef SECURITY_STATUS(SEC_ENTRY* ENUMERATE_SECURITY_PACKAGES_FN_W)(ULONG* pcPackages, + PSecPkgInfoW* ppPackageInfo); #ifdef UNICODE #define EnumerateSecurityPackages EnumerateSecurityPackagesW @@ -706,8 +713,10 @@ typedef SECURITY_STATUS (SEC_ENTRY * ENUMERATE_SECURITY_PACKAGES_FN_W)(ULONG* pc #define ENUMERATE_SECURITY_PACKAGES_FN ENUMERATE_SECURITY_PACKAGES_FN_A #endif -typedef SECURITY_STATUS (SEC_ENTRY * QUERY_CREDENTIALS_ATTRIBUTES_FN_A)(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer); -typedef SECURITY_STATUS (SEC_ENTRY * QUERY_CREDENTIALS_ATTRIBUTES_FN_W)(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer); +typedef SECURITY_STATUS(SEC_ENTRY* QUERY_CREDENTIALS_ATTRIBUTES_FN_A)(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer); +typedef SECURITY_STATUS(SEC_ENTRY* QUERY_CREDENTIALS_ATTRIBUTES_FN_W)(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer); #ifdef UNICODE #define QueryCredentialsAttributes QueryCredentialsAttributesW @@ -717,12 +726,14 @@ typedef SECURITY_STATUS (SEC_ENTRY * QUERY_CREDENTIALS_ATTRIBUTES_FN_W)(PCredHan #define QUERY_CREDENTIALS_ATTRIBUTES_FN QUERY_CREDENTIALS_ATTRIBUTES_FN_A #endif -typedef SECURITY_STATUS (SEC_ENTRY * ACQUIRE_CREDENTIALS_HANDLE_FN_A)(LPSTR pszPrincipal, LPSTR pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry); -typedef SECURITY_STATUS (SEC_ENTRY * ACQUIRE_CREDENTIALS_HANDLE_FN_W)(LPWSTR pszPrincipal, LPWSTR pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry); +typedef SECURITY_STATUS(SEC_ENTRY* ACQUIRE_CREDENTIALS_HANDLE_FN_A)(LPSTR pszPrincipal, + LPSTR pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry); +typedef SECURITY_STATUS(SEC_ENTRY* ACQUIRE_CREDENTIALS_HANDLE_FN_W)(LPWSTR pszPrincipal, + LPWSTR pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry); #ifdef UNICODE #define AcquireCredentialsHandle AcquireCredentialsHandleW @@ -732,16 +743,18 @@ typedef SECURITY_STATUS (SEC_ENTRY * ACQUIRE_CREDENTIALS_HANDLE_FN_W)(LPWSTR psz #define ACQUIRE_CREDENTIALS_HANDLE_FN ACQUIRE_CREDENTIALS_HANDLE_FN_A #endif -typedef SECURITY_STATUS (SEC_ENTRY * FREE_CREDENTIALS_HANDLE_FN)(PCredHandle phCredential); +typedef SECURITY_STATUS(SEC_ENTRY* FREE_CREDENTIALS_HANDLE_FN)(PCredHandle phCredential); -typedef SECURITY_STATUS (SEC_ENTRY * INITIALIZE_SECURITY_CONTEXT_FN_A)(PCredHandle phCredential, PCtxtHandle phContext, - SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry); -typedef SECURITY_STATUS (SEC_ENTRY * INITIALIZE_SECURITY_CONTEXT_FN_W)(PCredHandle phCredential, PCtxtHandle phContext, - SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry); +typedef SECURITY_STATUS(SEC_ENTRY* INITIALIZE_SECURITY_CONTEXT_FN_A)(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry); +typedef SECURITY_STATUS(SEC_ENTRY* INITIALIZE_SECURITY_CONTEXT_FN_W)(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry); #ifdef UNICODE #define InitializeSecurityContext InitializeSecurityContextW @@ -751,18 +764,23 @@ typedef SECURITY_STATUS (SEC_ENTRY * INITIALIZE_SECURITY_CONTEXT_FN_W)(PCredHand #define INITIALIZE_SECURITY_CONTEXT_FN INITIALIZE_SECURITY_CONTEXT_FN_A #endif -typedef SECURITY_STATUS (SEC_ENTRY * ACCEPT_SECURITY_CONTEXT_FN)(PCredHandle phCredential, PCtxtHandle phContext, - PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp); +typedef SECURITY_STATUS(SEC_ENTRY* ACCEPT_SECURITY_CONTEXT_FN)(PCredHandle phCredential, + PCtxtHandle phContext, + PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp); -typedef SECURITY_STATUS (SEC_ENTRY * COMPLETE_AUTH_TOKEN_FN)(PCtxtHandle phContext, PSecBufferDesc pToken); +typedef SECURITY_STATUS(SEC_ENTRY* COMPLETE_AUTH_TOKEN_FN)(PCtxtHandle phContext, + PSecBufferDesc pToken); -typedef SECURITY_STATUS (SEC_ENTRY * DELETE_SECURITY_CONTEXT_FN)(PCtxtHandle phContext); +typedef SECURITY_STATUS(SEC_ENTRY* DELETE_SECURITY_CONTEXT_FN)(PCtxtHandle phContext); -typedef SECURITY_STATUS (SEC_ENTRY * APPLY_CONTROL_TOKEN_FN)(PCtxtHandle phContext, PSecBufferDesc pInput); +typedef SECURITY_STATUS(SEC_ENTRY* APPLY_CONTROL_TOKEN_FN)(PCtxtHandle phContext, + PSecBufferDesc pInput); -typedef SECURITY_STATUS (SEC_ENTRY * QUERY_CONTEXT_ATTRIBUTES_FN_A)(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer); -typedef SECURITY_STATUS (SEC_ENTRY * QUERY_CONTEXT_ATTRIBUTES_FN_W)(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer); +typedef SECURITY_STATUS(SEC_ENTRY* QUERY_CONTEXT_ATTRIBUTES_FN_A)(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer); +typedef SECURITY_STATUS(SEC_ENTRY* QUERY_CONTEXT_ATTRIBUTES_FN_W)(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer); #ifdef UNICODE #define QueryContextAttributes QueryContextAttributesW @@ -772,18 +790,22 @@ typedef SECURITY_STATUS (SEC_ENTRY * QUERY_CONTEXT_ATTRIBUTES_FN_W)(PCtxtHandle #define QUERY_CONTEXT_ATTRIBUTES_FN QUERY_CONTEXT_ATTRIBUTES_FN_A #endif -typedef SECURITY_STATUS (SEC_ENTRY * IMPERSONATE_SECURITY_CONTEXT_FN)(PCtxtHandle phContext); +typedef SECURITY_STATUS(SEC_ENTRY* IMPERSONATE_SECURITY_CONTEXT_FN)(PCtxtHandle phContext); -typedef SECURITY_STATUS (SEC_ENTRY * REVERT_SECURITY_CONTEXT_FN)(PCtxtHandle phContext); +typedef SECURITY_STATUS(SEC_ENTRY* REVERT_SECURITY_CONTEXT_FN)(PCtxtHandle phContext); -typedef SECURITY_STATUS (SEC_ENTRY * MAKE_SIGNATURE_FN)(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo); +typedef SECURITY_STATUS(SEC_ENTRY* MAKE_SIGNATURE_FN)(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo); -typedef SECURITY_STATUS (SEC_ENTRY * VERIFY_SIGNATURE_FN)(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP); +typedef SECURITY_STATUS(SEC_ENTRY* VERIFY_SIGNATURE_FN)(PCtxtHandle phContext, + PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP); -typedef SECURITY_STATUS (SEC_ENTRY * FREE_CONTEXT_BUFFER_FN)(void* pvContextBuffer); +typedef SECURITY_STATUS(SEC_ENTRY* FREE_CONTEXT_BUFFER_FN)(void* pvContextBuffer); -typedef SECURITY_STATUS (SEC_ENTRY * QUERY_SECURITY_PACKAGE_INFO_FN_A)(SEC_CHAR* pszPackageName, PSecPkgInfoA* ppPackageInfo); -typedef SECURITY_STATUS (SEC_ENTRY * QUERY_SECURITY_PACKAGE_INFO_FN_W)(SEC_WCHAR* pszPackageName, PSecPkgInfoW* ppPackageInfo); +typedef SECURITY_STATUS(SEC_ENTRY* QUERY_SECURITY_PACKAGE_INFO_FN_A)(SEC_CHAR* pszPackageName, + PSecPkgInfoA* ppPackageInfo); +typedef SECURITY_STATUS(SEC_ENTRY* QUERY_SECURITY_PACKAGE_INFO_FN_W)(SEC_WCHAR* pszPackageName, + PSecPkgInfoW* ppPackageInfo); #ifdef UNICODE #define QuerySecurityPackageInfo QuerySecurityPackageInfoW @@ -793,10 +815,13 @@ typedef SECURITY_STATUS (SEC_ENTRY * QUERY_SECURITY_PACKAGE_INFO_FN_W)(SEC_WCHAR #define QUERY_SECURITY_PACKAGE_INFO_FN QUERY_SECURITY_PACKAGE_INFO_FN_A #endif -typedef SECURITY_STATUS (SEC_ENTRY * EXPORT_SECURITY_CONTEXT_FN)(PCtxtHandle phContext, ULONG fFlags, PSecBuffer pPackedContext, HANDLE* pToken); +typedef SECURITY_STATUS(SEC_ENTRY* EXPORT_SECURITY_CONTEXT_FN)(PCtxtHandle phContext, ULONG fFlags, + PSecBuffer pPackedContext, HANDLE* pToken); -typedef SECURITY_STATUS (SEC_ENTRY * IMPORT_SECURITY_CONTEXT_FN_A)(SEC_CHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext); -typedef SECURITY_STATUS (SEC_ENTRY * IMPORT_SECURITY_CONTEXT_FN_W)(SEC_WCHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext); +typedef SECURITY_STATUS(SEC_ENTRY* IMPORT_SECURITY_CONTEXT_FN_A)(SEC_CHAR* pszPackage, + PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext); +typedef SECURITY_STATUS(SEC_ENTRY* IMPORT_SECURITY_CONTEXT_FN_W)(SEC_WCHAR* pszPackage, + PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext); #ifdef UNICODE #define ImportSecurityContext ImportSecurityContextW @@ -806,10 +831,14 @@ typedef SECURITY_STATUS (SEC_ENTRY * IMPORT_SECURITY_CONTEXT_FN_W)(SEC_WCHAR* ps #define IMPORT_SECURITY_CONTEXT_FN IMPORT_SECURITY_CONTEXT_FN_A #endif -typedef SECURITY_STATUS (SEC_ENTRY * ADD_CREDENTIALS_FN_A)(PCredHandle hCredentials, SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, - UINT32 fCredentialUse, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PTimeStamp ptsExpiry); -typedef SECURITY_STATUS (SEC_ENTRY * ADD_CREDENTIALS_FN_W)(PCredHandle hCredentials, SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, - UINT32 fCredentialUse, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PTimeStamp ptsExpiry); +typedef SECURITY_STATUS(SEC_ENTRY* ADD_CREDENTIALS_FN_A)(PCredHandle hCredentials, + SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, + UINT32 fCredentialUse, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, + PTimeStamp ptsExpiry); +typedef SECURITY_STATUS(SEC_ENTRY* ADD_CREDENTIALS_FN_W)(PCredHandle hCredentials, + SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, + UINT32 fCredentialUse, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, + PTimeStamp ptsExpiry); #ifdef UNICODE #define AddCredentials AddCredentialsW @@ -819,14 +848,19 @@ typedef SECURITY_STATUS (SEC_ENTRY * ADD_CREDENTIALS_FN_W)(PCredHandle hCredenti #define ADD_CREDENTIALS_FN ADD_CREDENTIALS_FN_A #endif -typedef SECURITY_STATUS (SEC_ENTRY * QUERY_SECURITY_CONTEXT_TOKEN_FN)(PCtxtHandle phContext, HANDLE* phToken); +typedef SECURITY_STATUS(SEC_ENTRY* QUERY_SECURITY_CONTEXT_TOKEN_FN)(PCtxtHandle phContext, + HANDLE* phToken); -typedef SECURITY_STATUS (SEC_ENTRY * ENCRYPT_MESSAGE_FN)(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo); +typedef SECURITY_STATUS(SEC_ENTRY* ENCRYPT_MESSAGE_FN)(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo); -typedef SECURITY_STATUS (SEC_ENTRY * DECRYPT_MESSAGE_FN)(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP); +typedef SECURITY_STATUS(SEC_ENTRY* DECRYPT_MESSAGE_FN)(PCtxtHandle phContext, + PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP); -typedef SECURITY_STATUS (SEC_ENTRY * SET_CONTEXT_ATTRIBUTES_FN_A)(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer); -typedef SECURITY_STATUS (SEC_ENTRY * SET_CONTEXT_ATTRIBUTES_FN_W)(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer); +typedef SECURITY_STATUS(SEC_ENTRY* SET_CONTEXT_ATTRIBUTES_FN_A)(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer, ULONG cbBuffer); +typedef SECURITY_STATUS(SEC_ENTRY* SET_CONTEXT_ATTRIBUTES_FN_W)(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer, ULONG cbBuffer); #ifdef UNICODE #define SetContextAttributes SetContextAttributesW @@ -909,8 +943,8 @@ struct _SecurityFunctionTableW typedef struct _SecurityFunctionTableW SecurityFunctionTableW; typedef SecurityFunctionTableW* PSecurityFunctionTableW; -typedef PSecurityFunctionTableA (SEC_ENTRY * INIT_SECURITY_INTERFACE_A)(void); -typedef PSecurityFunctionTableW (SEC_ENTRY * INIT_SECURITY_INTERFACE_W)(void); +typedef PSecurityFunctionTableA(SEC_ENTRY* INIT_SECURITY_INTERFACE_A)(void); +typedef PSecurityFunctionTableW(SEC_ENTRY* INIT_SECURITY_INTERFACE_W)(void); #ifdef UNICODE #define InitSecurityInterface InitSecurityInterfaceW @@ -930,38 +964,50 @@ extern "C" { /* Package Management */ -WINPR_API SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesA(ULONG* pcPackages, PSecPkgInfoA* ppPackageInfo); -WINPR_API SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesW(ULONG* pcPackages, PSecPkgInfoW* ppPackageInfo); +WINPR_API SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesA(ULONG* pcPackages, + PSecPkgInfoA* ppPackageInfo); +WINPR_API SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesW(ULONG* pcPackages, + PSecPkgInfoW* ppPackageInfo); WINPR_API PSecurityFunctionTableA SEC_ENTRY InitSecurityInterfaceA(void); WINPR_API PSecurityFunctionTableW SEC_ENTRY InitSecurityInterfaceW(void); -WINPR_API SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName, PSecPkgInfoA* ppPackageInfo); -WINPR_API SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, PSecPkgInfoW* ppPackageInfo); +WINPR_API SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName, + PSecPkgInfoA* ppPackageInfo); +WINPR_API SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, + PSecPkgInfoW* ppPackageInfo); /* Credential Management */ -WINPR_API SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry); -WINPR_API SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry); +WINPR_API SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, + SEC_CHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry); +WINPR_API SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, + SEC_WCHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry); -WINPR_API SECURITY_STATUS SEC_ENTRY ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags, PSecBuffer pPackedContext, HANDLE* pToken); +WINPR_API SECURITY_STATUS SEC_ENTRY ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags, + PSecBuffer pPackedContext, HANDLE* pToken); WINPR_API SECURITY_STATUS SEC_ENTRY FreeCredentialsHandle(PCredHandle phCredential); -WINPR_API SECURITY_STATUS SEC_ENTRY ImportSecurityContextA(SEC_CHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext); -WINPR_API SECURITY_STATUS SEC_ENTRY ImportSecurityContextW(SEC_WCHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext); +WINPR_API SECURITY_STATUS SEC_ENTRY ImportSecurityContextA(SEC_CHAR* pszPackage, + PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext); +WINPR_API SECURITY_STATUS SEC_ENTRY ImportSecurityContextW(SEC_WCHAR* pszPackage, + PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext); -WINPR_API SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer); -WINPR_API SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer); +WINPR_API SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesA(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer); +WINPR_API SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesW(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer); /* Context Management */ -WINPR_API SECURITY_STATUS SEC_ENTRY AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, - PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp); +WINPR_API SECURITY_STATUS SEC_ENTRY AcceptSecurityContext(PCredHandle phCredential, + PCtxtHandle phContext, + PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp); WINPR_API SECURITY_STATUS SEC_ENTRY ApplyControlToken(PCtxtHandle phContext, PSecBufferDesc pInput); WINPR_API SECURITY_STATUS SEC_ENTRY CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken); @@ -969,26 +1015,35 @@ WINPR_API SECURITY_STATUS SEC_ENTRY DeleteSecurityContext(PCtxtHandle phContext) WINPR_API SECURITY_STATUS SEC_ENTRY FreeContextBuffer(void* pvContextBuffer); WINPR_API SECURITY_STATUS SEC_ENTRY ImpersonateSecurityContext(PCtxtHandle phContext); -WINPR_API SECURITY_STATUS SEC_ENTRY InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, - SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry); -WINPR_API SECURITY_STATUS SEC_ENTRY InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, - SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry); +WINPR_API SECURITY_STATUS SEC_ENTRY InitializeSecurityContextA(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry); +WINPR_API SECURITY_STATUS SEC_ENTRY InitializeSecurityContextW(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry); -WINPR_API SECURITY_STATUS SEC_ENTRY QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer); -WINPR_API SECURITY_STATUS SEC_ENTRY QuerySecurityContextToken(PCtxtHandle phContext, HANDLE* phToken); -WINPR_API SECURITY_STATUS SEC_ENTRY SetContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer); +WINPR_API SECURITY_STATUS SEC_ENTRY QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer); +WINPR_API SECURITY_STATUS SEC_ENTRY QuerySecurityContextToken(PCtxtHandle phContext, + HANDLE* phToken); +WINPR_API SECURITY_STATUS SEC_ENTRY SetContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer, ULONG cbBuffer); WINPR_API SECURITY_STATUS SEC_ENTRY RevertSecurityContext(PCtxtHandle phContext); /* Message Support */ -WINPR_API SECURITY_STATUS SEC_ENTRY DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP); -WINPR_API SECURITY_STATUS SEC_ENTRY EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo); -WINPR_API SECURITY_STATUS SEC_ENTRY MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo); -WINPR_API SECURITY_STATUS SEC_ENTRY VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP); +WINPR_API SECURITY_STATUS SEC_ENTRY DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, + ULONG MessageSeqNo, PULONG pfQOP); +WINPR_API SECURITY_STATUS SEC_ENTRY EncryptMessage(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo); +WINPR_API SECURITY_STATUS SEC_ENTRY MakeSignature(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo); +WINPR_API SECURITY_STATUS SEC_ENTRY VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, + ULONG MessageSeqNo, PULONG pfQOP); #ifdef __cplusplus } @@ -1068,8 +1123,8 @@ typedef struct _SecPkgContext_AuthNtlmMessage SecPkgContext_AuthNtlmMessage; #define SSPI_INTERFACE_WINPR 0x00000001 #define SSPI_INTERFACE_NATIVE 0x00000002 -typedef PSecurityFunctionTableA (SEC_ENTRY * INIT_SECURITY_INTERFACE_EX_A)(DWORD flags); -typedef PSecurityFunctionTableW (SEC_ENTRY * INIT_SECURITY_INTERFACE_EX_W)(DWORD flags); +typedef PSecurityFunctionTableA(SEC_ENTRY* INIT_SECURITY_INTERFACE_EX_A)(DWORD flags); +typedef PSecurityFunctionTableW(SEC_ENTRY* INIT_SECURITY_INTERFACE_EX_W)(DWORD flags); WINPR_API void sspi_GlobalInit(void); WINPR_API void sspi_GlobalFinish(void); @@ -1077,8 +1132,13 @@ WINPR_API void sspi_GlobalFinish(void); WINPR_API void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size); WINPR_API void sspi_SecBufferFree(PSecBuffer SecBuffer); -WINPR_API int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain, const char* password); -WINPR_API int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDENTITY* srcIdentity); +WINPR_API int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, + const char* domain, const char* password); +WINPR_API int sspi_SetAuthIdentityWithUnicodePassword(SEC_WINNT_AUTH_IDENTITY* identity, + const char* user, const char* domain, + LPWSTR password, ULONG passwordLength); +WINPR_API int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, + SEC_WINNT_AUTH_IDENTITY* srcIdentity); WINPR_API const char* GetSecurityStatusString(SECURITY_STATUS status); diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h index 730540e..4a00059 100644 --- a/winpr/include/winpr/stream.h +++ b/winpr/include/winpr/stream.h @@ -332,6 +332,38 @@ static INLINE BOOL Stream_SafeSeek(wStream* s, size_t size) return TRUE; } +static INLINE BOOL Stream_Read_UTF16_String(wStream* s, WCHAR* dst, size_t length) +{ + size_t x; + + if (!s || !dst) + return FALSE; + + if (Stream_GetRemainingLength(s) / sizeof(WCHAR) < length) + return FALSE; + + for (x=0; x<length; x++) + Stream_Read_UINT16(s, dst[x]); + + return TRUE; +} + +static INLINE BOOL Stream_Write_UTF16_String(wStream* s, const WCHAR* src, size_t length) +{ + size_t x; + + if (!s || !src) + return FALSE; + + if (Stream_GetRemainingCapacity(s) / sizeof(WCHAR) < length) + return FALSE; + + for (x=0; x<length; x++) + Stream_Write_UINT16(s, src[x]); + + return TRUE; +} + /* StreamPool */ struct _wStreamPool diff --git a/winpr/include/winpr/tchar.h b/winpr/include/winpr/tchar.h index f3525bc..2129c71 100644 --- a/winpr/include/winpr/tchar.h +++ b/winpr/include/winpr/tchar.h @@ -47,6 +47,7 @@ typedef CHAR TCHAR; #define _tcsrchr wcsrchr #define _tcsstr wcsstr #define _stprintf_s swprintf_s +#define _tcsnccmp wcsncmp #else #define _tprintf printf #define _tcslen strlen @@ -59,6 +60,7 @@ typedef CHAR TCHAR; #define _tcsrchr strrchr #define _tcsstr strstr #define _stprintf_s sprintf_s +#define _tcsnccmp strncmp #endif #endif diff --git a/winpr/include/winpr/winpr.h b/winpr/include/winpr/winpr.h index cafd692..9961e98 100644 --- a/winpr/include/winpr/winpr.h +++ b/winpr/include/winpr/winpr.h @@ -71,4 +71,6 @@ 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); +#define WINPR_UNUSED(x) (void)(x) + #endif /* WINPR_H */ diff --git a/winpr/include/winpr/wlog.h b/winpr/include/winpr/wlog.h index c8ad36e..242f1df 100644 --- a/winpr/include/winpr/wlog.h +++ b/winpr/include/winpr/wlog.h @@ -182,7 +182,9 @@ WINPR_API BOOL WLog_Layout_SetPrefixFormat(wLog* log, wLogLayout* layout, WINPR_API wLog* WLog_GetRoot(void); WINPR_API wLog* WLog_Get(LPCSTR name); +/** Deprecated */ WINPR_API BOOL WLog_Init(void); +/** Deprecated */ WINPR_API BOOL WLog_Uninit(void); typedef BOOL (*wLogCallbackMessage_t)(const wLogMessage* msg); diff --git a/winpr/include/winpr/wtsapi.h b/winpr/include/winpr/wtsapi.h index eb546be..dcdf8d3 100644 --- a/winpr/include/winpr/wtsapi.h +++ b/winpr/include/winpr/wtsapi.h @@ -66,7 +66,7 @@ #define CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000 #define CHANNEL_OPTION_REMOTE_CONTROL_PERSISTENT 0x00100000 -#define CHANNEL_MAX_COUNT 30 +#define CHANNEL_MAX_COUNT 31 #define CHANNEL_NAME_LEN 7 typedef struct tagCHANNEL_DEF diff --git a/winpr/include/winpr/wtypes.h.in b/winpr/include/winpr/wtypes.h.in index 0549f97..cee7fdd 100644 --- a/winpr/include/winpr/wtypes.h.in +++ b/winpr/include/winpr/wtypes.h.in @@ -53,6 +53,15 @@ #ifdef _WIN32 #include <wtypes.h> + +/* Handle missing ssize_t on Windows */ +#ifdef _WIN64 +typedef long long LONG_PTR; +#else +typedef long LONG_PTR; +#endif +typedef LONG_PTR SSIZE_T; + #endif #if defined(__OBJC__) && defined(__APPLE__) @@ -115,7 +124,7 @@ typedef unsigned long __uint32; #else #error "32-bit type not configured" #endif - #if ULONG_MAX == 0xFFFFFFFFFFFFFFFF +#if ULONG_MAX == 0xFFFFFFFFFFFFFFFF typedef long __int64; typedef unsigned long __uint64; #elif ULLONG_MAX == 0xFFFFFFFFFFFFFFFF @@ -145,7 +154,7 @@ typedef unsigned long long __uint64; #endif /* WINPR_HAVE_STDINT_H */ -typedef void *PVOID, *LPVOID, *PVOID64, *LPVOID64; +typedef void* PVOID, *LPVOID, *PVOID64, *LPVOID64; #ifndef XMD_H /* X11/Xmd.h typedef collision with BOOL */ #ifndef __OBJC__ /* objc.h typedef collision with BOOL */ @@ -162,7 +171,7 @@ typedef signed char BOOL; #endif /* __OBJC__ */ #endif /* XMD_H */ -typedef BOOL *PBOOL, *LPBOOL; +typedef BOOL* PBOOL, *LPBOOL; #ifndef FALSE #define FALSE 0 @@ -186,12 +195,12 @@ typedef __int8 CHAR; typedef __uint8 UCHAR; #endif typedef CHAR CCHAR, *PCHAR, *LPCH, *PCH, *PSTR, *LPSTR; -typedef const CHAR *LPCCH, *PCCH, *LPCSTR, *PCSTR; -typedef UCHAR *PUCHAR; +typedef const CHAR* LPCCH, *PCCH, *LPCSTR, *PCSTR; +typedef UCHAR* PUCHAR; typedef __uint16 WCHAR; typedef WCHAR UNICODE, *PWCHAR, *LPWCH, *PWCH, *BSTR, *LMSTR, *LPWSTR, *PWSTR; -typedef const WCHAR *LPCWCH, *PCWCH, *LMCSTR, *LPCWSTR, *PCWSTR; +typedef const WCHAR* LPCWCH, *PCWCH, *LMCSTR, *LPCWSTR, *PCWSTR; typedef __int16 SHORT, *PSHORT; typedef __int32 INT, *PINT, *LPINT; @@ -209,10 +218,10 @@ typedef __int16 INT16; typedef __int32 INT32; typedef __int64 INT64; #endif -typedef INT8 *PINT8; -typedef INT16 *PINT16; -typedef INT32 *PINT32; -typedef INT64 *PINT64; +typedef INT8* PINT8; +typedef INT16* PINT16; +typedef INT32* PINT32; +typedef INT64* PINT64; typedef __int32 LONG32, *PLONG32; #ifndef LONG64 /* X11/Xmd.h uses/defines LONG64 */ @@ -257,7 +266,7 @@ typedef DWORD HCALL; typedef ULONG error_status_t; typedef LONG HRESULT; typedef LONG SCODE; -typedef SCODE *PSCODE; +typedef SCODE* PSCODE; typedef struct _GUID { @@ -344,7 +353,7 @@ typedef struct _SYSTEMTIME WORD wMinute; WORD wSecond; WORD wMilliseconds; -} SYSTEMTIME,*PSYSTEMTIME,*LPSYSTEMTIME; +} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; typedef struct _RPC_SID_IDENTIFIER_AUTHORITY { @@ -406,16 +415,20 @@ typedef void* FARPROC; typedef struct tagDEC { USHORT wReserved; - union { - struct { + union + { + struct + { BYTE scale; BYTE sign; } DUMMYSTRUCTNAME; USHORT signscale; } DUMMYUNIONNAME; ULONG Hi32; - union { - struct { + union + { + struct + { ULONG Lo32; ULONG Mid32; } DUMMYSTRUCTNAME2; @@ -423,7 +436,7 @@ typedef struct tagDEC } DUMMYUNIONNAME2; } DECIMAL; -typedef DECIMAL *LPDECIMAL; +typedef DECIMAL* LPDECIMAL; #define DECIMAL_NEG ((BYTE) 0x80) #define DECIMAL_SETZERO(dec) { (dec).Lo64 = 0; (dec).Hi32 = 0; (dec).signscale = 0; } @@ -439,17 +452,17 @@ typedef PCONTEXT_HANDLE* PPCONTEXT_HANDLE; #ifndef _NTDEF typedef LONG NTSTATUS; -typedef NTSTATUS *PNTSTATUS; +typedef NTSTATUS* PNTSTATUS; #endif #ifndef _LPCVOID_DEFINED #define _LPCVOID_DEFINED -typedef const VOID *LPCVOID; +typedef const VOID* LPCVOID; #endif #ifndef _LPCBYTE_DEFINED #define _LPCBYTE_DEFINED -typedef const BYTE *LPCBYTE; +typedef const BYTE* LPCBYTE; #endif /* integer format specifiers */ @@ -525,4 +538,9 @@ typedef const BYTE *LPCBYTE; #include <winpr/user.h> +#ifndef _WIN32 +#define _fseeki64(fp, offset, origin) fseeko(fp, offset, origin) +#define _ftelli64(fp) ftello(fp) +#endif + #endif /* WINPR_WTYPES_H */ diff --git a/winpr/libwinpr/CMakeLists.txt b/winpr/libwinpr/CMakeLists.txt index 1be1ed9..17efaf2 100644 --- a/winpr/libwinpr/CMakeLists.txt +++ b/winpr/libwinpr/CMakeLists.txt @@ -15,12 +15,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -if (APPLE) - # flat_namespace should be avoided, but is required for -undefined warning. Since WinPR currently has - # a lot of undefined symbols in use, use this hack until they're filled out. - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-flat_namespace,-undefined,warning") -endif() - set(WINPR_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(WINPR_SRCS "") set(WINPR_LIBS "") @@ -127,9 +121,9 @@ endif() add_definitions(${WINPR_DEFINITIONS}) if (WIN32) -target_link_libraries(${MODULE_NAME} ${PUBLIC_KEYWORD} ${WINPR_LIBS}) + target_link_libraries(${MODULE_NAME} ${PUBLIC_KEYWORD} ${WINPR_LIBS}) else() -target_link_libraries(${MODULE_NAME} ${PRIVATE_KEYWORD} ${WINPR_LIBS}) + target_link_libraries(${MODULE_NAME} ${PRIVATE_KEYWORD} ${WINPR_LIBS}) endif(WIN32) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT WinPRTargets) if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS) diff --git a/winpr/libwinpr/clipboard/posix.c b/winpr/libwinpr/clipboard/posix.c index c8305fc..76d8cb5 100644 --- a/winpr/libwinpr/clipboard/posix.c +++ b/winpr/libwinpr/clipboard/posix.c @@ -53,22 +53,21 @@ struct posix_file BOOL is_directory; int fd; - off_t offset; - off_t size; + INT64 offset; + INT64 size; }; static struct posix_file* make_posix_file(const char* local_name, const WCHAR* remote_name) { struct posix_file* file = NULL; struct stat statbuf; - file = calloc(1, sizeof(*file)); + if (!file) return NULL; file->fd = -1; file->offset = 0; - file->local_name = _strdup(local_name); file->remote_name = _wcsdup(remote_name); @@ -84,14 +83,11 @@ static struct posix_file* make_posix_file(const char* local_name, const WCHAR* r file->is_directory = S_ISDIR(statbuf.st_mode); file->size = statbuf.st_size; - return file; - error: free(file->local_name); free(file->remote_name); free(file); - return NULL; } @@ -142,7 +138,6 @@ static BOOL decode_percent_encoded_byte(const char* str, const char* end, char* *value |= hex_to_dec(str[1], &valid); *value <<= 4; *value |= hex_to_dec(str[2], &valid); - return valid; } @@ -152,9 +147,9 @@ static char* decode_percent_encoded_string(const char* str, size_t len) char* next = NULL; const char* cur = str; const char* lim = str + len; - /* Percent decoding shrinks data length, so len bytes will be enough. */ buffer = calloc(len + 1, sizeof(char)); + if (!buffer) return NULL; @@ -180,10 +175,8 @@ static char* decode_percent_encoded_string(const char* str, size_t len) } return buffer; - error: free(buffer); - return NULL; } @@ -220,7 +213,6 @@ static WCHAR* convert_local_name_component_to_remote(const char* local_name) } return remote_name; - error: free(remote_name); return NULL; @@ -231,18 +223,16 @@ static char* concat_local_name(const char* dir, const char* file) size_t len_dir = 0; size_t len_file = 0; char* buffer = NULL; - len_dir = strlen(dir); len_file = strlen(file); - buffer = calloc(len_dir + 1 + len_file + 1, sizeof(char)); + if (!buffer) return NULL; memcpy(buffer, dir, len_dir * sizeof(char)); buffer[len_dir] = '/'; memcpy(buffer + len_dir + 1, file, len_file * sizeof(char)); - return buffer; } @@ -251,25 +241,23 @@ static WCHAR* concat_remote_name(const WCHAR* dir, const WCHAR* file) size_t len_dir = 0; size_t len_file = 0; WCHAR* buffer = NULL; - len_dir = _wcslen(dir); len_file = _wcslen(file); - buffer = calloc(len_dir + 1 + len_file + 1, sizeof(WCHAR)); + if (!buffer) return NULL; memcpy(buffer, dir, len_dir * sizeof(WCHAR)); buffer[len_dir] = L'\\'; memcpy(buffer + len_dir + 1, file, len_file * sizeof(WCHAR)); - return buffer; } static BOOL add_file_to_list(const char* local_name, const WCHAR* remote_name, wArrayList* files); static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR* remote_dir_name, - const struct dirent* entry, wArrayList* files) + const struct dirent* entry, wArrayList* files) { BOOL result = FALSE; char* local_name = NULL; @@ -281,6 +269,7 @@ static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR* return TRUE; remote_base_name = convert_local_name_component_to_remote(entry->d_name); + if (!remote_base_name) return FALSE; @@ -293,12 +282,11 @@ static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR* free(remote_base_name); free(remote_name); free(local_name); - return result; } static BOOL do_add_directory_contents_to_list(const char* local_name, const WCHAR* remote_name, - DIR* dirp, wArrayList* files) + DIR* dirp, wArrayList* files) { /* * For some reason POSIX does not require readdir() to be thread-safe. @@ -313,16 +301,16 @@ static BOOL do_add_directory_contents_to_list(const char* local_name, const WCHA * musl). We should not be breaking people's builds because of that, * so we do nothing and proceed with fingers crossed. */ - for (;;) { struct dirent* entry = NULL; - errno = 0; entry = readdir(dirp); + if (!entry) { int err = errno; + if (!err) break; @@ -338,14 +326,13 @@ static BOOL do_add_directory_contents_to_list(const char* local_name, const WCHA } static BOOL add_directory_contents_to_list(const char* local_name, const WCHAR* remote_name, - wArrayList* files) + wArrayList* files) { BOOL result = FALSE; DIR* dirp = NULL; - WLog_VRB(TAG, "adding directory: %s", local_name); - dirp = opendir(local_name); + if (!dirp) { int err = errno; @@ -360,6 +347,7 @@ static BOOL add_directory_contents_to_list(const char* local_name, const WCHAR* int err = errno; WLog_WARN(TAG, "failed to close directory: %s", strerror(err)); } + out: return result; } @@ -367,17 +355,15 @@ out: static BOOL add_file_to_list(const char* local_name, const WCHAR* remote_name, wArrayList* files) { struct posix_file* file = NULL; - WLog_VRB(TAG, "adding file: %s", local_name); - file = make_posix_file(local_name, remote_name); + if (!file) return FALSE; if (ArrayList_Add(files, file) < 0) { free_posix_file(file); - return FALSE; } @@ -413,22 +399,19 @@ static BOOL process_file_name(const char* local_name, wArrayList* files) BOOL result = FALSE; const char* base_name = NULL; WCHAR* remote_name = NULL; - /* * Start with the base name of the file. text/uri-list contains the * exact files selected by the user, and we want the remote files * to have names relative to that selection. */ base_name = get_basename(local_name); - remote_name = convert_local_name_component_to_remote(base_name); + if (!remote_name) return FALSE; result = add_file_to_list(local_name, remote_name, files); - free(remote_name); - return result; } @@ -436,7 +419,6 @@ static BOOL process_uri(const char* uri, size_t uri_len, wArrayList* files) { BOOL result = FALSE; char* name = NULL; - WLog_VRB(TAG, "processing URI: %.*s", uri_len, uri); if ((uri_len < strlen("file://")) || strncmp(uri, "file://", strlen("file://"))) @@ -446,13 +428,13 @@ static BOOL process_uri(const char* uri, size_t uri_len, wArrayList* files) } name = decode_percent_encoded_string(uri + strlen("file://"), uri_len - strlen("file://")); + if (!name) goto out; result = process_file_name(name, files); out: free(name); - return result; } @@ -462,9 +444,7 @@ static BOOL process_uri_list(const char* data, size_t length, wArrayList* files) const char* lim = data + length; const char* start = NULL; const char* stop = NULL; - WLog_VRB(TAG, "processing URI list:\n%.*s", length, data); - ArrayList_Clear(files); /* @@ -478,9 +458,7 @@ static BOOL process_uri_list(const char* data, size_t length, wArrayList* files) while (cur < lim) { BOOL comment = (*cur == '#'); - start = cur; - stop = cur; for (stop = cur; stop < lim; stop++) { @@ -490,14 +468,17 @@ static BOOL process_uri_list(const char* data, size_t length, wArrayList* files) cur = stop + 2; else cur = stop + 1; + break; } + if (*stop == '\n') { cur = stop + 1; break; } } + if (stop == lim) cur = lim; @@ -512,10 +493,9 @@ static BOOL process_uri_list(const char* data, size_t length, wArrayList* files) } static BOOL convert_local_file_to_filedescriptor(const struct posix_file* file, - FILEDESCRIPTOR* descriptor) + FILEDESCRIPTOR* descriptor) { size_t remote_len = 0; - descriptor->dwFlags = FD_ATTRIBUTES | FD_FILESIZE | FD_SHOWPROGRESSUI; if (file->is_directory) @@ -532,6 +512,7 @@ static BOOL convert_local_file_to_filedescriptor(const struct posix_file* file, } remote_len = _wcslen(file->remote_name); + if (remote_len + 1 > ARRAYSIZE(descriptor->cFileName)) { WLog_ERR(TAG, "file name too long (%"PRIuz" characters)", remote_len); @@ -539,7 +520,6 @@ static BOOL convert_local_file_to_filedescriptor(const struct posix_file* file, } memcpy(descriptor->cFileName, file->remote_name, remote_len * sizeof(WCHAR)); - return TRUE; } @@ -548,10 +528,9 @@ static FILEDESCRIPTOR* convert_local_file_list_to_filedescriptors(wArrayList* fi int i; int count = 0; FILEDESCRIPTOR* descriptors = NULL; - count = ArrayList_Count(files); - descriptors = calloc(count, sizeof(descriptors[0])); + if (!descriptors) goto error; @@ -564,15 +543,13 @@ static FILEDESCRIPTOR* convert_local_file_list_to_filedescriptors(wArrayList* fi } return descriptors; - error: free(descriptors); - return NULL; } static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 formatId, - const void* data, UINT32* pSize) + const void* data, UINT32* pSize) { FILEDESCRIPTOR* descriptors = NULL; @@ -586,13 +563,12 @@ static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 f return NULL; descriptors = convert_local_file_list_to_filedescriptors(clipboard->localFiles); + if (!descriptors) return NULL; *pSize = ArrayList_Count(clipboard->localFiles) * sizeof(FILEDESCRIPTOR); - clipboard->fileListSequenceNumber = clipboard->sequenceNumber; - return descriptors; } @@ -600,25 +576,25 @@ static BOOL register_file_formats_and_synthesizers(wClipboard* clipboard) { UINT32 file_group_format_id; UINT32 local_file_format_id; - file_group_format_id = ClipboardRegisterFormat(clipboard, "FileGroupDescriptorW"); local_file_format_id = ClipboardRegisterFormat(clipboard, "text/uri-list"); + if (!file_group_format_id || !local_file_format_id) goto error; clipboard->localFiles = ArrayList_New(FALSE); + if (!clipboard->localFiles) goto error; ArrayList_Object(clipboard->localFiles)->fnObjectFree = free_posix_file; if (!ClipboardRegisterSynthesizer(clipboard, - local_file_format_id, file_group_format_id, - convert_uri_list_to_filedescriptors)) + local_file_format_id, file_group_format_id, + convert_uri_list_to_filedescriptors)) goto error_free_local_files; return TRUE; - error_free_local_files: ArrayList_Free(clipboard->localFiles); clipboard->localFiles = NULL; @@ -626,7 +602,7 @@ error: return FALSE; } -static UINT posix_file_get_size(const struct posix_file* file, off_t* size) +static UINT posix_file_get_size(const struct posix_file* file, INT64* size) { struct stat statbuf; @@ -638,15 +614,14 @@ static UINT posix_file_get_size(const struct posix_file* file, off_t* size) } *size = statbuf.st_size; - return NO_ERROR; } static UINT posix_file_request_size(wClipboardDelegate* delegate, - const wClipboardFileSizeRequest* request) + const wClipboardFileSizeRequest* request) { UINT error = NO_ERROR; - off_t size = 0; + INT64 size = 0; struct posix_file* file = NULL; if (!delegate || !delegate->clipboard || !request) @@ -656,6 +631,7 @@ static UINT posix_file_request_size(wClipboardDelegate* delegate, return ERROR_INVALID_STATE; file = ArrayList_GetItem(delegate->clipboard->localFiles, request->listIndex); + if (!file) return ERROR_INDEX_ABSENT; @@ -680,6 +656,7 @@ static UINT posix_file_read_open(struct posix_file* file) return NO_ERROR; file->fd = open(file->local_name, O_RDONLY); + if (file->fd < 0) { int err = errno; @@ -696,10 +673,8 @@ static UINT posix_file_read_open(struct posix_file* file) file->offset = 0; file->size = statbuf.st_size; - WLog_VRB(TAG, "open file %d -> %s", file->fd, file->local_name); WLog_VRB(TAG, "file %d size: %"PRIu64" bytes", file->fd, file->size); - return NO_ERROR; } @@ -715,7 +690,7 @@ static UINT posix_file_read_seek(struct posix_file* file, UINT64 offset) return NO_ERROR; WLog_VRB(TAG, "file %d force seeking to %"PRIu64", current %"PRIu64, file->fd, - offset, file->offset); + offset, file->offset); if (lseek(file->fd, offset, SEEK_SET) < 0) { @@ -728,14 +703,13 @@ static UINT posix_file_read_seek(struct posix_file* file, UINT64 offset) } static UINT posix_file_read_perform(struct posix_file* file, UINT32 size, - BYTE** actual_data, UINT32* actual_size) + BYTE** actual_data, UINT32* actual_size) { BYTE* buffer = NULL; ssize_t amount = 0; - WLog_VRB(TAG, "file %d request read %"PRIu32" bytes", file->fd, size); - buffer = malloc(size); + if (!buffer) { WLog_ERR(TAG, "failed to allocate %"PRIu32" buffer bytes", size); @@ -743,6 +717,7 @@ static UINT posix_file_read_perform(struct posix_file* file, UINT32 size, } amount = read(file->fd, buffer, size); + if (amount < 0) { int err = errno; @@ -753,15 +728,11 @@ static UINT posix_file_read_perform(struct posix_file* file, UINT32 size, *actual_data = buffer; *actual_size = amount; file->offset += amount; - WLog_VRB(TAG, "file %d actual read %"PRIu32" bytes (offset %"PRIu64")", file->fd, - amount, file->offset); - + amount, file->offset); return NO_ERROR; - error: free(buffer); - return ERROR_READ_FAULT; } @@ -779,6 +750,7 @@ static UINT posix_file_read_close(struct posix_file* file) int err = errno; WLog_WARN(TAG, "failed to close fd %d: %s", file->fd, strerror(err)); } + file->fd = -1; } @@ -786,31 +758,35 @@ static UINT posix_file_read_close(struct posix_file* file) } static UINT posix_file_get_range(struct posix_file* file, UINT64 offset, UINT32 size, - BYTE** actual_data, UINT32* actual_size) + BYTE** actual_data, UINT32* actual_size) { UINT error = NO_ERROR; - error = posix_file_read_open(file); + if (error) goto out; error = posix_file_read_seek(file, offset); + if (error) goto out; error = posix_file_read_perform(file, size, actual_data, actual_size); + if (error) goto out; error = posix_file_read_close(file); + if (error) goto out; + out: return error; } static UINT posix_file_request_range(wClipboardDelegate* delegate, - const wClipboardFileRangeRequest* request) + const wClipboardFileRangeRequest* request) { UINT error = 0; BYTE* data = NULL; @@ -825,6 +801,7 @@ static UINT posix_file_request_range(wClipboardDelegate* delegate, return ERROR_INVALID_STATE; file = ArrayList_GetItem(delegate->clipboard->localFiles, request->listIndex); + if (!file) return ERROR_INDEX_ABSENT; @@ -840,26 +817,29 @@ static UINT posix_file_request_range(wClipboardDelegate* delegate, WLog_WARN(TAG, "failed to report file range result: 0x%08X", error); free(data); - return NO_ERROR; } -static UINT dummy_file_size_success(wClipboardDelegate* delegate, const wClipboardFileSizeRequest* request, UINT64 fileSize) +static UINT dummy_file_size_success(wClipboardDelegate* delegate, + const wClipboardFileSizeRequest* request, UINT64 fileSize) { return ERROR_NOT_SUPPORTED; } -static UINT dummy_file_size_failure(wClipboardDelegate* delegate, const wClipboardFileSizeRequest* request, UINT errorCode) +static UINT dummy_file_size_failure(wClipboardDelegate* delegate, + const wClipboardFileSizeRequest* request, UINT errorCode) { return ERROR_NOT_SUPPORTED; } -static UINT dummy_file_range_success(wClipboardDelegate* delegate, const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size) +static UINT dummy_file_range_success(wClipboardDelegate* delegate, + const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size) { return ERROR_NOT_SUPPORTED; } -static UINT dummy_file_range_failure(wClipboardDelegate* delegate, const wClipboardFileRangeRequest* request, UINT errorCode) +static UINT dummy_file_range_failure(wClipboardDelegate* delegate, + const wClipboardFileRangeRequest* request, UINT errorCode) { return ERROR_NOT_SUPPORTED; } @@ -869,7 +849,6 @@ static void setup_delegate(wClipboardDelegate* delegate) delegate->ClientRequestFileSize = posix_file_request_size; delegate->ClipboardFileSizeSuccess = dummy_file_size_success; delegate->ClipboardFileSizeFailure = dummy_file_size_failure; - delegate->ClientRequestFileRange = posix_file_request_range; delegate->ClipboardFileRangeSuccess = dummy_file_range_success; delegate->ClipboardFileRangeFailure = dummy_file_range_failure; @@ -884,6 +863,5 @@ BOOL ClipboardInitPosixFileSubsystem(wClipboard* clipboard) return FALSE; setup_delegate(&clipboard->delegate); - return TRUE; } diff --git a/winpr/libwinpr/clipboard/synthetic.c b/winpr/libwinpr/clipboard/synthetic.c index 156e738..a5d3c60 100644 --- a/winpr/libwinpr/clipboard/synthetic.c +++ b/winpr/libwinpr/clipboard/synthetic.c @@ -21,6 +21,7 @@ #include "config.h" #endif +#include <errno.h> #include <winpr/crt.h> #include <winpr/user.h> @@ -37,7 +38,8 @@ * Null-terminated ANSI text with CR/LF line endings. */ -static void* clipboard_synthesize_cf_text(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +static void* clipboard_synthesize_cf_text(wClipboard* clipboard, UINT32 formatId, const void* data, + UINT32* pSize) { int size; char* pDstData = NULL; @@ -46,34 +48,34 @@ static void* clipboard_synthesize_cf_text(wClipboard* clipboard, UINT32 formatId { char* str = NULL; - size = (int) *pSize; + if (*pSize > INT32_MAX) + return NULL; + + size = (int) * pSize; size = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) data, - size / 2, (CHAR**) &str, 0, NULL, NULL); + size / 2, (CHAR**) &str, 0, NULL, NULL); if (!str) return NULL; pDstData = ConvertLineEndingToCRLF((const char*) str, &size); free(str); - *pSize = size; - return pDstData; } else if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) || - (formatId == ClipboardGetFormatId(clipboard, "UTF8_STRING")) || - (formatId == ClipboardGetFormatId(clipboard, "text/plain")) || - (formatId == ClipboardGetFormatId(clipboard, "TEXT")) || - (formatId == ClipboardGetFormatId(clipboard, "STRING"))) + (formatId == ClipboardGetFormatId(clipboard, "UTF8_STRING")) || + (formatId == ClipboardGetFormatId(clipboard, "text/plain")) || + (formatId == ClipboardGetFormatId(clipboard, "TEXT")) || + (formatId == ClipboardGetFormatId(clipboard, "STRING"))) { - size = (int) *pSize; + size = (INT64) * pSize; pDstData = ConvertLineEndingToCRLF((const char*) data, &size); if (!pDstData) return NULL; *pSize = size; - return pDstData; } @@ -86,7 +88,8 @@ static void* clipboard_synthesize_cf_text(wClipboard* clipboard, UINT32 formatId * Null-terminated OEM text with CR/LF line endings. */ -static void* clipboard_synthesize_cf_oemtext(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +static void* clipboard_synthesize_cf_oemtext(wClipboard* clipboard, UINT32 formatId, + const void* data, UINT32* pSize) { return clipboard_synthesize_cf_text(clipboard, formatId, data, pSize); } @@ -97,15 +100,16 @@ static void* clipboard_synthesize_cf_oemtext(wClipboard* clipboard, UINT32 forma * System locale identifier associated with CF_TEXT */ -static void* clipboard_synthesize_cf_locale(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +static void* clipboard_synthesize_cf_locale(wClipboard* clipboard, UINT32 formatId, + const void* data, UINT32* pSize) { UINT32* pDstData = NULL; - pDstData = (UINT32*) malloc(sizeof(UINT32)); + if (!pDstData) return NULL; - *pDstData = 0x0409; /* English - United States */ + *pDstData = 0x0409; /* English - United States */ return (void*) pDstData; } @@ -115,7 +119,8 @@ static void* clipboard_synthesize_cf_locale(wClipboard* clipboard, UINT32 format * Null-terminated UTF-16 text with CR/LF line endings. */ -static void* clipboard_synthesize_cf_unicodetext(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +static void* clipboard_synthesize_cf_unicodetext(wClipboard* clipboard, UINT32 formatId, + const void* data, UINT32* pSize) { int size; int status; @@ -123,12 +128,15 @@ static void* clipboard_synthesize_cf_unicodetext(wClipboard* clipboard, UINT32 f WCHAR* pDstData = NULL; if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) || - (formatId == ClipboardGetFormatId(clipboard, "UTF8_STRING")) || - (formatId == ClipboardGetFormatId(clipboard, "text/plain")) || - (formatId == ClipboardGetFormatId(clipboard, "TEXT")) || - (formatId == ClipboardGetFormatId(clipboard, "STRING"))) + (formatId == ClipboardGetFormatId(clipboard, "UTF8_STRING")) || + (formatId == ClipboardGetFormatId(clipboard, "text/plain")) || + (formatId == ClipboardGetFormatId(clipboard, "TEXT")) || + (formatId == ClipboardGetFormatId(clipboard, "STRING"))) { - size = (int) *pSize; + if (!pSize || (*pSize > INT32_MAX)) + return NULL; + + size = (int) * pSize; crlfStr = ConvertLineEndingToCRLF((char*) data, &size); if (!crlfStr) @@ -152,43 +160,39 @@ static void* clipboard_synthesize_cf_unicodetext(wClipboard* clipboard, UINT32 f * Null-terminated UTF-8 string with LF line endings. */ -static void* clipboard_synthesize_utf8_string(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +static void* clipboard_synthesize_utf8_string(wClipboard* clipboard, UINT32 formatId, + const void* data, UINT32* pSize) { - int size; + INT64 size; char* pDstData = NULL; if (formatId == CF_UNICODETEXT) { - size = (int) *pSize; + size = (INT64) * pSize; size = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) data, - size / 2, (CHAR**) &pDstData, 0, NULL, NULL); + size / 2, (CHAR**) &pDstData, 0, NULL, NULL); if (!pDstData) return NULL; size = ConvertLineEndingToLF(pDstData, size); - *pSize = size; - return pDstData; } else if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) || - (formatId == ClipboardGetFormatId(clipboard, "text/plain")) || - (formatId == ClipboardGetFormatId(clipboard, "TEXT")) || - (formatId == ClipboardGetFormatId(clipboard, "STRING"))) + (formatId == ClipboardGetFormatId(clipboard, "text/plain")) || + (formatId == ClipboardGetFormatId(clipboard, "TEXT")) || + (formatId == ClipboardGetFormatId(clipboard, "STRING"))) { - size = (int) *pSize; + size = (INT64) * pSize; pDstData = (char*) malloc(size); if (!pDstData) return NULL; CopyMemory(pDstData, data, size); - size = ConvertLineEndingToLF((char*) pDstData, size); - *pSize = size; - return pDstData; } @@ -201,17 +205,16 @@ static void* clipboard_synthesize_utf8_string(wClipboard* clipboard, UINT32 form * BITMAPINFO structure followed by the bitmap bits. */ -static void* clipboard_synthesize_cf_dib(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +static void* clipboard_synthesize_cf_dib(wClipboard* clipboard, UINT32 formatId, const void* data, + UINT32* pSize) { UINT32 SrcSize; UINT32 DstSize; BYTE* pDstData; - SrcSize = *pSize; if (formatId == CF_DIBV5) { - } else if (formatId == ClipboardGetFormatId(clipboard, "image/bmp")) { @@ -231,11 +234,9 @@ static void* clipboard_synthesize_cf_dib(wClipboard* clipboard, UINT32 formatId, if (!pDstData) return NULL; - data = (void*) &((BYTE*) data)[sizeof(BITMAPFILEHEADER)]; - + data = (void*) & ((BYTE*) data)[sizeof(BITMAPFILEHEADER)]; CopyMemory(pDstData, data, DstSize); *pSize = DstSize; - return pDstData; } @@ -248,15 +249,14 @@ static void* clipboard_synthesize_cf_dib(wClipboard* clipboard, UINT32 formatId, * BITMAPV5HEADER structure followed by the bitmap color space information and the bitmap bits. */ -static void* clipboard_synthesize_cf_dibv5(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +static void* clipboard_synthesize_cf_dibv5(wClipboard* clipboard, UINT32 formatId, const void* data, + UINT32* pSize) { if (formatId == CF_DIB) { - } else if (formatId == ClipboardGetFormatId(clipboard, "image/bmp")) { - } return NULL; @@ -268,12 +268,12 @@ static void* clipboard_synthesize_cf_dibv5(wClipboard* clipboard, UINT32 formatI * Bitmap file format. */ -static void* clipboard_synthesize_image_bmp(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +static void* clipboard_synthesize_image_bmp(wClipboard* clipboard, UINT32 formatId, + const void* data, UINT32* pSize) { UINT32 SrcSize; UINT32 DstSize; BYTE* pDstData; - SrcSize = *pSize; if (formatId == CF_DIB) @@ -302,16 +302,13 @@ static void* clipboard_synthesize_image_bmp(wClipboard* clipboard, UINT32 format pFileHeader->bfReserved1 = 0; pFileHeader->bfReserved2 = 0; pFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - pDst = &pDstData[sizeof(BITMAPFILEHEADER)]; CopyMemory(pDst, data, SrcSize); *pSize = DstSize; - return pDstData; } else if (formatId == CF_DIBV5) { - } return NULL; @@ -323,11 +320,12 @@ static void* clipboard_synthesize_image_bmp(wClipboard* clipboard, UINT32 format * HTML clipboard format: msdn.microsoft.com/en-us/library/windows/desktop/ms649015/ */ -static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 formatId, + const void* data, UINT32* pSize) { char* pSrcData = NULL; char* pDstData = NULL; - int SrcSize = (int) *pSize; + INT64 SrcSize = (INT64) * pSize; if (formatId == ClipboardGetFormatId(clipboard, "text/html")) { @@ -347,22 +345,24 @@ static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 form if ((bom[0] == 0xFF) && (bom[1] == 0xFE)) { - wstr = (WCHAR*) &((BYTE*) data)[2]; - + wstr = (WCHAR*) & ((BYTE*) data)[2]; ConvertFromUnicode(CP_UTF8, 0, wstr, - (SrcSize - 2) / 2, &pSrcData, 0, NULL, NULL); + (SrcSize - 2) / 2, &pSrcData, 0, NULL, NULL); } } if (!pSrcData) { pSrcData = (char*) calloc(1, SrcSize + 1); + if (!pSrcData) return NULL; + CopyMemory(pSrcData, data, SrcSize); } pDstData = (char*) calloc(1, SrcSize + 200); + if (!pDstData) { free(pSrcData); @@ -370,12 +370,11 @@ static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 form } strcpy(pDstData, - "Version:0.9\r\n" - "StartHTML:0000000000\r\n" - "EndHTML:0000000000\r\n" - "StartFragment:0000000000\r\n" - "EndFragment:0000000000\r\n"); - + "Version:0.9\r\n" + "StartHTML:0000000000\r\n" + "EndHTML:0000000000\r\n" + "StartFragment:0000000000\r\n" + "EndFragment:0000000000\r\n"); body = strstr(pSrcData, "<body"); if (!body) @@ -389,12 +388,10 @@ static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 form strcat(pDstData, "<HTML><BODY>"); strcat(pDstData, "<!--StartFragment-->"); - /* StartFragment */ sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData)); CopyMemory(&pDstData[69], num, 10); strcat(pDstData, pSrcData); - /* EndFragment */ sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData)); CopyMemory(&pDstData[93], num, 10); @@ -406,7 +403,6 @@ static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 form /* EndHTML */ sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData)); CopyMemory(&pDstData[43], num, 10); - *pSize = (UINT32) strlen(pDstData) + 1; free(pSrcData); } @@ -420,32 +416,37 @@ static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 form * HTML text format. */ -static void* clipboard_synthesize_text_html(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +static void* clipboard_synthesize_text_html(wClipboard* clipboard, UINT32 formatId, + const void* data, UINT32* pSize) { - int beg; - int end; + long beg; + long end; char* str; char* begStr; char* endStr; - int SrcSize; - int DstSize = -1; + INT64 SrcSize; + long DstSize = -1; BYTE* pDstData = NULL; if (formatId == ClipboardGetFormatId(clipboard, "HTML Format")) { str = (char*) data; - SrcSize = (int) *pSize; - + SrcSize = (INT64) * pSize; begStr = strstr(str, "StartHTML:"); endStr = strstr(str, "EndHTML:"); if (!begStr || !endStr) return NULL; - beg = atoi(&begStr[10]); - end = atoi(&endStr[8]); + errno = 0; + beg = strtol(&begStr[10], NULL, 10); - if (beg < 0 || end < 0 || (beg > SrcSize) || (end > SrcSize) || (beg >= end)) + if (errno != 0) + return NULL; + + end = strtol(&endStr[8], NULL, 10); + + if (beg < 0 || end < 0 || (beg > SrcSize) || (end > SrcSize) || (beg >= end) || (errno != 0)) return NULL; DstSize = end - beg; @@ -466,143 +467,108 @@ BOOL ClipboardInitSynthesizers(wClipboard* clipboard) { UINT32 formatId; UINT32 altFormatId; - /** * CF_TEXT */ - ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_OEMTEXT, - clipboard_synthesize_cf_oemtext); - + clipboard_synthesize_cf_oemtext); ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_UNICODETEXT, - clipboard_synthesize_cf_unicodetext); - + clipboard_synthesize_cf_unicodetext); ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_LOCALE, - clipboard_synthesize_cf_locale); - + clipboard_synthesize_cf_locale); altFormatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING"); - ClipboardRegisterSynthesizer(clipboard, CF_TEXT, altFormatId, - clipboard_synthesize_utf8_string); - + clipboard_synthesize_utf8_string); /** * CF_OEMTEXT */ - ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_TEXT, - clipboard_synthesize_cf_text); - + clipboard_synthesize_cf_text); ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_UNICODETEXT, - clipboard_synthesize_cf_unicodetext); - + clipboard_synthesize_cf_unicodetext); ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_LOCALE, - clipboard_synthesize_cf_locale); - + clipboard_synthesize_cf_locale); altFormatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING"); - ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, altFormatId, - clipboard_synthesize_utf8_string); - + clipboard_synthesize_utf8_string); /** * CF_UNICODETEXT */ - ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_TEXT, - clipboard_synthesize_cf_text); - + clipboard_synthesize_cf_text); ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_OEMTEXT, - clipboard_synthesize_cf_oemtext); - + clipboard_synthesize_cf_oemtext); ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_LOCALE, - clipboard_synthesize_cf_locale); - + clipboard_synthesize_cf_locale); altFormatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING"); - ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, altFormatId, - clipboard_synthesize_utf8_string); - + clipboard_synthesize_utf8_string); /** * UTF8_STRING */ - formatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING"); if (formatId) { ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT, - clipboard_synthesize_cf_text); - + clipboard_synthesize_cf_text); ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT, - clipboard_synthesize_cf_oemtext); - + clipboard_synthesize_cf_oemtext); ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT, - clipboard_synthesize_cf_unicodetext); - + clipboard_synthesize_cf_unicodetext); ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE, - clipboard_synthesize_cf_locale); + clipboard_synthesize_cf_locale); } /** * text/plain */ - formatId = ClipboardRegisterFormat(clipboard, "text/plain"); if (formatId) { ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT, - clipboard_synthesize_cf_text); - + clipboard_synthesize_cf_text); ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT, - clipboard_synthesize_cf_oemtext); - + clipboard_synthesize_cf_oemtext); ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT, - clipboard_synthesize_cf_unicodetext); - + clipboard_synthesize_cf_unicodetext); ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE, - clipboard_synthesize_cf_locale); + clipboard_synthesize_cf_locale); } /** * TEXT */ - formatId = ClipboardRegisterFormat(clipboard, "TEXT"); if (formatId) { ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT, - clipboard_synthesize_cf_text); - + clipboard_synthesize_cf_text); ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT, - clipboard_synthesize_cf_oemtext); - + clipboard_synthesize_cf_oemtext); ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT, - clipboard_synthesize_cf_unicodetext); - + clipboard_synthesize_cf_unicodetext); ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE, - clipboard_synthesize_cf_locale); + clipboard_synthesize_cf_locale); } /** * STRING */ - formatId = ClipboardRegisterFormat(clipboard, "STRING"); if (formatId) { ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT, - clipboard_synthesize_cf_text); - + clipboard_synthesize_cf_text); ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT, - clipboard_synthesize_cf_oemtext); - + clipboard_synthesize_cf_oemtext); ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT, - clipboard_synthesize_cf_unicodetext); - + clipboard_synthesize_cf_unicodetext); ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE, - clipboard_synthesize_cf_locale); + clipboard_synthesize_cf_locale); } /** @@ -612,12 +578,10 @@ BOOL ClipboardInitSynthesizers(wClipboard* clipboard) if (formatId) { ClipboardRegisterSynthesizer(clipboard, CF_DIB, CF_DIBV5, - clipboard_synthesize_cf_dibv5); - + clipboard_synthesize_cf_dibv5); altFormatId = ClipboardRegisterFormat(clipboard, "image/bmp"); - ClipboardRegisterSynthesizer(clipboard, CF_DIB, altFormatId, - clipboard_synthesize_image_bmp); + clipboard_synthesize_image_bmp); } /** @@ -627,55 +591,47 @@ BOOL ClipboardInitSynthesizers(wClipboard* clipboard) if (formatId && 0) { ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, CF_DIB, - clipboard_synthesize_cf_dib); - + clipboard_synthesize_cf_dib); altFormatId = ClipboardRegisterFormat(clipboard, "image/bmp"); - ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, altFormatId, - clipboard_synthesize_image_bmp); + clipboard_synthesize_image_bmp); } /** * image/bmp */ - formatId = ClipboardRegisterFormat(clipboard, "image/bmp"); if (formatId) { ClipboardRegisterSynthesizer(clipboard, formatId, CF_DIB, - clipboard_synthesize_cf_dib); - + clipboard_synthesize_cf_dib); ClipboardRegisterSynthesizer(clipboard, formatId, CF_DIBV5, - clipboard_synthesize_cf_dibv5); + clipboard_synthesize_cf_dibv5); } /** * HTML Format */ - formatId = ClipboardRegisterFormat(clipboard, "HTML Format"); if (formatId) { altFormatId = ClipboardRegisterFormat(clipboard, "text/html"); - ClipboardRegisterSynthesizer(clipboard, formatId, altFormatId, - clipboard_synthesize_text_html); + clipboard_synthesize_text_html); } /** * text/html */ - formatId = ClipboardRegisterFormat(clipboard, "text/html"); if (formatId) { altFormatId = ClipboardRegisterFormat(clipboard, "HTML Format"); - ClipboardRegisterSynthesizer(clipboard, formatId, altFormatId, - clipboard_synthesize_html_format); + clipboard_synthesize_html_format); } return TRUE; diff --git a/winpr/libwinpr/comm/comm.c b/winpr/libwinpr/comm/comm.c index 9e4e7f0..0c63fc4 100644 --- a/winpr/libwinpr/comm/comm.c +++ b/winpr/libwinpr/comm/comm.c @@ -425,10 +425,8 @@ BOOL GetCommState(HANDLE hFile, LPDCB lpDCB) lpLocalDcb->fDtrControl = DTR_CONTROL_DISABLE; } - lpLocalDcb->fDsrSensitivity = (handflow.ControlHandShake & - SERIAL_DSR_SENSITIVITY) != 0; - lpLocalDcb->fTXContinueOnXoff = (handflow.FlowReplace & SERIAL_XOFF_CONTINUE) != - 0; + lpLocalDcb->fDsrSensitivity = (handflow.ControlHandShake & SERIAL_DSR_SENSITIVITY) != 0; + lpLocalDcb->fTXContinueOnXoff = (handflow.FlowReplace & SERIAL_XOFF_CONTINUE) != 0; lpLocalDcb->fOutX = (handflow.FlowReplace & SERIAL_AUTO_TRANSMIT) != 0; lpLocalDcb->fInX = (handflow.FlowReplace & SERIAL_AUTO_RECEIVE) != 0; lpLocalDcb->fErrorChar = (handflow.FlowReplace & SERIAL_ERROR_CHAR) != 0; @@ -995,49 +993,6 @@ BOOL WaitCommEvent(HANDLE hFile, PDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) return FALSE; } - -/* Extended API */ - -static BOOL _IsReservedCommDeviceName(LPCTSTR lpName) -{ - int i; - - if (!CommInitialized()) - return FALSE; - - /* Serial ports, COM1-9 */ - for (i = 1; i < 10; i++) - { - TCHAR genericName[5]; - - if (_stprintf_s(genericName, 5, _T("COM%d"), i) < 0) - { - return FALSE; - } - - if (_tcscmp(genericName, lpName) == 0) - return TRUE; - } - - /* Parallel ports, LPT1-9 */ - for (i = 1; i < 10; i++) - { - TCHAR genericName[5]; - - if (_stprintf_s(genericName, 5, _T("LPT%d"), i) < 0) - { - return FALSE; - } - - if (_tcscmp(genericName, lpName) == 0) - return TRUE; - } - - /* FIXME: what about PRN ? */ - return FALSE; -} - - /** * Returns TRUE on success, FALSE otherwise. To get extended error * information, call GetLastError. @@ -1065,15 +1020,6 @@ BOOL DefineCommDevice(/* DWORD dwFlags,*/ LPCTSTR lpDeviceName, goto error_handle; } - if (_tcsncmp(lpDeviceName, _T("\\\\.\\"), 4) != 0) - { - if (!_IsReservedCommDeviceName(lpDeviceName)) - { - SetLastError(ERROR_INVALID_DATA); - goto error_handle; - } - } - storedDeviceName = _tcsdup(lpDeviceName); if (storedDeviceName == NULL) @@ -1472,12 +1418,7 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, return (HANDLE)pComm; error_handle: - - if (pComm != NULL) - { - CloseHandle(pComm); - } - + CloseHandle(pComm); return INVALID_HANDLE_VALUE; } diff --git a/winpr/libwinpr/comm/comm.h b/winpr/libwinpr/comm/comm.h index 8bc5fdd..8dbceae 100644 --- a/winpr/libwinpr/comm/comm.h +++ b/winpr/libwinpr/comm/comm.h @@ -69,6 +69,7 @@ struct winpr_comm ULONG WaitEventMask; ULONG PendingEvents; + char eventChar; /* NB: CloseHandle() has to free resources */ }; diff --git a/winpr/libwinpr/comm/comm_io.c b/winpr/libwinpr/comm/comm_io.c index d3eb2c1..e401ea2 100644 --- a/winpr/libwinpr/comm/comm_io.c +++ b/winpr/libwinpr/comm/comm_io.c @@ -146,7 +146,7 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, * * ReadIntervalTimeout | ReadTotalTimeoutMultiplier | ReadTotalTimeoutConstant | VMIN | VTIME | TMAX | * 0 | 0 | 0 | N | 0 | INDEF | Blocks for N bytes available. - * 0< Ti <MAXULONG | 0 | 0 | N | Ti | INDEF | Blocks on first byte, then use Ti between bytes. + * 0< Ti <MAXULONG | 0 | 0 | N | Ti | INDEF | Blocks on first byte, then use Ti between bytes. * MAXULONG | 0 | 0 | 0 | 0 | 0 | Returns immediately with bytes available (don't block) * MAXULONG | MAXULONG | 0< Tc <MAXULONG | N | 0 | Tc | Blocks on first byte during Tc or returns immediately whith bytes available * MAXULONG | m | MAXULONG | | Invalid @@ -349,6 +349,14 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, } *lpNumberOfBytesRead = nbRead; + + EnterCriticalSection(&pComm->EventsLock); + if (pComm->PendingEvents & SERIAL_EV_FREERDP_WAITING) + { + if (pComm->eventChar != '\0' && memchr(lpBuffer, pComm->eventChar, nbRead)) + pComm->PendingEvents |= SERIAL_EV_RXCHAR; + } + LeaveCriticalSection(&pComm->EventsLock); goto return_true; } @@ -546,13 +554,15 @@ BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, * printer. Its driver was expecting the modem line status * SERIAL_MSR_DSR true after the sending which was never * happenning otherwise. A purge was also done before each - * Write operation. The serial port was oppened with: + * Write operation. The serial port was opened with: * DesiredAccess=0x0012019F. The printer worked fine with * mstsc. */ tcdrain(pComm->fd_write); + return_true: LeaveCriticalSection(&pComm->WriteLock); return TRUE; + return_false: LeaveCriticalSection(&pComm->WriteLock); return FALSE; diff --git a/winpr/libwinpr/comm/comm_serial_sys.c b/winpr/libwinpr/comm/comm_serial_sys.c index 950f36f..1ba0abd 100644 --- a/winpr/libwinpr/comm/comm_serial_sys.c +++ b/winpr/libwinpr/comm/comm_serial_sys.c @@ -316,7 +316,7 @@ static BOOL _set_serial_chars(WINPR_COMM *pComm, const SERIAL_CHARS *pSerialChar if (pSerialChars->XonChar == pSerialChars->XoffChar) { - /* http://msdn.microsoft.com/en-us/library/windows/hardware/ff546688%28v=vs.85%29.aspx */ + /* https://msdn.microsoft.com/en-us/library/windows/hardware/ff546688?v=vs.85.aspx */ SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -360,12 +360,9 @@ static BOOL _set_serial_chars(WINPR_COMM *pComm, const SERIAL_CHARS *pSerialChar result = FALSE; /* but keep on */ } - /* FIXME: could be implemented during read/write I/O. What about ISIG? */ if (pSerialChars->EventChar != '\0') { - CommLog_Print(WLOG_WARN, "EventChar 0x%02"PRIX8" ('%c') cannot be set\n", pSerialChars->EventChar, (char) pSerialChars->EventChar); - SetLastError(ERROR_NOT_SUPPORTED); - result = FALSE; /* but keep on */ + pComm->eventChar = pSerialChars->EventChar; } upcomingTermios.c_cc[VSTART] = pSerialChars->XonChar; @@ -1076,7 +1073,8 @@ static BOOL _set_wait_mask(WINPR_COMM *pComm, const ULONG *pWaitMask) if (possibleMask != *pWaitMask) { - CommLog_Print(WLOG_WARN, "Not all wait events supported (Serial.sys), requested events= 0x%08"PRIX32", possible events= 0x%08"PRIX32"", *pWaitMask, possibleMask); + CommLog_Print(WLOG_WARN, "Not all wait events supported (Serial.sys), requested events= 0x%08"PRIX32", possible events= 0x%08"PRIX32"", + *pWaitMask, possibleMask); /* FIXME: shall we really set the possibleMask and return FALSE? */ pComm->WaitEventMask = possibleMask; @@ -1209,7 +1207,7 @@ static BOOL _get_commstatus(WINPR_COMM *pComm, SERIAL_STATUS *pCommstatus) if (ioctl(pComm->fd, TIOCGICOUNT, ¤tCounters) < 0) { CommLog_Print(WLOG_WARN, "TIOCGICOUNT ioctl failed, errno=[%d] %s.", errno, strerror(errno)); - CommLog_Print(WLOG_WARN, " coult not read counters."); + CommLog_Print(WLOG_WARN, " could not read counters."); if (pComm->permissive) { @@ -1310,7 +1308,7 @@ static BOOL _get_commstatus(WINPR_COMM *pComm, SERIAL_STATUS *pCommstatus) if (currentCounters.rx != pComm->counters.rx) { - pComm->PendingEvents |= SERIAL_EV_RXCHAR; + pComm->PendingEvents |= SERIAL_EV_RXFLAG; } if ((currentCounters.tx != pComm->counters.tx) && /* at least a transmission occurred AND ...*/ @@ -1458,7 +1456,7 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask) * * NOTE: previously used a semaphore but used * sem_timedwait() anyway. Finally preferred a simpler - * solution with Sleep() whithout the burden of the + * solution with Sleep() without the burden of the * semaphore initialization and destroying. */ diff --git a/winpr/libwinpr/crt/CMakeLists.txt b/winpr/libwinpr/crt/CMakeLists.txt index 3fd7e05..678f937 100644 --- a/winpr/libwinpr/crt/CMakeLists.txt +++ b/winpr/libwinpr/crt/CMakeLists.txt @@ -15,15 +15,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -winpr_module_add( - alignment.c +set (CRT_FILES alignment.c conversion.c buffer.c memory.c - string.c unicode.c - utf.c - utf.h) + string.c) + +if (NOT WITH_ICU) + set (CRT_FILES ${CRT_FILES} + utf.c + utf.h) +endif(NOT WITH_ICU) + +if (WITH_ICU) + find_package(ICU REQUIRED i18n uc io) + include_directories(${ICU_INCLUDE_DIRS}) + winpr_library_add(${ICU_LIBRARIES}) +endif (WITH_ICU) + +winpr_module_add(${CRT_FILES}) if(BUILD_TESTING) add_subdirectory(test) diff --git a/winpr/libwinpr/crt/unicode.c b/winpr/libwinpr/crt/unicode.c index 26ced2b..b60cba8 100644 --- a/winpr/libwinpr/crt/unicode.c +++ b/winpr/libwinpr/crt/unicode.c @@ -30,7 +30,15 @@ #ifndef _WIN32 +#if defined(WITH_ICU) +#include <unicode/ucnv.h> +#include <unicode/ustring.h> +#else #include "utf.h" +#endif + +#include "../log.h" +#define TAG WINPR_TAG("unicode") /** * Notes on cross-platform Unicode portability: @@ -144,14 +152,16 @@ int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar) { - int length; LPWSTR targetStart; +#if !defined(WITH_ICU) const BYTE* sourceStart; + int length; ConversionResult result; +#endif /* If cbMultiByte is 0, the function fails */ - if (cbMultiByte == 0) + if ((cbMultiByte == 0) || (cbMultiByte < -1)) return 0; /* If cbMultiByte is -1, the string is null-terminated */ @@ -163,6 +173,44 @@ int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, * if cchWideChar is 0, the function returns the required buffer size * in characters for lpWideCharStr and makes no use of the output parameter itself. */ +#if defined(WITH_ICU) + { + UErrorCode error; + int32_t targetLength; + int32_t targetCapacity; + + switch (CodePage) + { + case CP_ACP: + case CP_UTF8: + break; + + default: + WLog_ERR(TAG, "Unsupported encoding %u", CodePage); + return 0; + } + + if (cbMultiByte > UINT32_MAX) + return 0; + + targetStart = lpWideCharStr; + targetCapacity = cchWideChar; + error = U_ZERO_ERROR; + + if (cchWideChar == 0) + { + u_strFromUTF8(NULL, 0, &targetLength, + lpMultiByteStr, cbMultiByte, &error); + cchWideChar = targetLength; + } + else + { + u_strFromUTF8(targetStart, targetCapacity, &targetLength, + lpMultiByteStr, cbMultiByte, &error); + cchWideChar = U_SUCCESS(error) ? targetLength : 0; + } + } +#else if (cchWideChar == 0) { @@ -182,6 +230,7 @@ int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, } cchWideChar = (result == conversionOK) ? length : 0; +#endif return cchWideChar; } @@ -223,14 +272,18 @@ int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar) { +#if !defined(WITH_ICU) int length; - BYTE* targetStart; const WCHAR* sourceStart; ConversionResult result; + BYTE* targetStart; +#else + char* targetStart; +#endif /* If cchWideChar is 0, the function fails */ - if (cchWideChar == 0) + if ((cchWideChar == 0) || (cchWideChar < -1)) return 0; /* If cchWideChar is -1, the string is null-terminated */ @@ -242,6 +295,44 @@ int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int * if cbMultiByte is 0, the function returns the required buffer size * in bytes for lpMultiByteStr and makes no use of the output parameter itself. */ +#if defined(WITH_ICU) + { + UErrorCode error; + int32_t targetLength; + int32_t targetCapacity; + + switch (CodePage) + { + case CP_ACP: + case CP_UTF8: + break; + + default: + WLog_ERR(TAG, "Unsupported encoding %u", CodePage); + return 0; + } + + if (cchWideChar > UINT32_MAX) + return 0; + + targetStart = lpMultiByteStr; + targetCapacity = cbMultiByte; + error = U_ZERO_ERROR; + + if (cbMultiByte == 0) + { + u_strToUTF8(NULL, 0, &targetLength, + lpWideCharStr, cchWideChar, &error); + cbMultiByte = targetLength; + } + else + { + u_strToUTF8(targetStart, targetCapacity, &targetLength, + lpWideCharStr, cchWideChar, &error); + cbMultiByte = U_SUCCESS(error) ? targetLength : 0; + } + } +#else if (cbMultiByte == 0) { @@ -261,6 +352,7 @@ int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int } cbMultiByte = (result == conversionOK) ? length : 0; +#endif return cbMultiByte; } diff --git a/winpr/libwinpr/crypto/cipher.c b/winpr/libwinpr/crypto/cipher.c index 72e13af..f1e4290 100644 --- a/winpr/libwinpr/crypto/cipher.c +++ b/winpr/libwinpr/crypto/cipher.c @@ -43,36 +43,69 @@ * RC4 */ -WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen) +WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOOL override_fips) { WINPR_RC4_CTX* ctx = NULL; +#if defined(WITH_OPENSSL) + const EVP_CIPHER* evp = NULL; +#endif if (!key || (keylen == 0)) return NULL; #if defined(WITH_OPENSSL) - if (!(ctx = (WINPR_RC4_CTX*) calloc(1, sizeof(RC4_KEY)))) - return NULL; - RC4_set_key((RC4_KEY*) ctx, keylen, key); + if (!(ctx = (WINPR_RC4_CTX*) EVP_CIPHER_CTX_new())) + return NULL; + + evp = EVP_rc4(); + + if (!evp) + return NULL; + + EVP_CIPHER_CTX_init((EVP_CIPHER_CTX*) ctx); + EVP_EncryptInit_ex((EVP_CIPHER_CTX*) ctx, evp, NULL, NULL, NULL); + /* EVP_CIPH_FLAG_NON_FIPS_ALLOW does not exist before openssl 1.0.1 */ +#if !(OPENSSL_VERSION_NUMBER < 0x10001000L) + + if (override_fips == TRUE) + EVP_CIPHER_CTX_set_flags((EVP_CIPHER_CTX*) ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW); + +#endif + EVP_CIPHER_CTX_set_key_length((EVP_CIPHER_CTX*) ctx, keylen); + EVP_EncryptInit_ex((EVP_CIPHER_CTX*) ctx, NULL, NULL, key, NULL); #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) + if (!(ctx = (WINPR_RC4_CTX*) calloc(1, sizeof(mbedtls_arc4_context)))) return NULL; + mbedtls_arc4_init((mbedtls_arc4_context*) ctx); mbedtls_arc4_setup((mbedtls_arc4_context*) ctx, key, (unsigned int) keylen); #endif return ctx; } +WINPR_RC4_CTX* winpr_RC4_New_Allow_FIPS(const BYTE* key, size_t keylen) +{ + return winpr_RC4_New_Internal(key, keylen, TRUE); +} + +WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen) +{ + return winpr_RC4_New_Internal(key, keylen, FALSE); +} + 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); + int outputLength; + EVP_CipherUpdate((EVP_CIPHER_CTX*) ctx, output, &outputLength, input, length); return TRUE; - #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) + if (mbedtls_arc4_crypt((mbedtls_arc4_context*) ctx, length, input, output) == 0) return TRUE; + #endif return FALSE; } @@ -83,9 +116,7 @@ void winpr_RC4_Free(WINPR_RC4_CTX* ctx) return; #if defined(WITH_OPENSSL) - memset(ctx, 0, sizeof(RC4_KEY)); - free(ctx); - + EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*) ctx); #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) mbedtls_arc4_free((mbedtls_arc4_context*) ctx); free(ctx); @@ -518,7 +549,6 @@ mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher) WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BYTE* iv) { WINPR_CIPHER_CTX* ctx = NULL; - #if defined(WITH_OPENSSL) int operation; const EVP_CIPHER* evp; @@ -539,9 +569,7 @@ WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BY } EVP_CIPHER_CTX_set_padding(octx, 0); - ctx = (WINPR_CIPHER_CTX*) octx; - #elif defined(WITH_MBEDTLS) int key_bitlen; mbedtls_operation_t operation; @@ -560,7 +588,7 @@ WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BY if (mbedtls_cipher_setup(mctx, cipher_info) != 0) { - free (mctx); + free(mctx); return NULL; } @@ -569,27 +597,27 @@ WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BY if (mbedtls_cipher_setkey(mctx, key, key_bitlen, operation) != 0) { mbedtls_cipher_free(mctx); - free (mctx); + free(mctx); return NULL; } if (mbedtls_cipher_set_padding_mode(mctx, MBEDTLS_PADDING_NONE) != 0) { mbedtls_cipher_free(mctx); - free (mctx); + free(mctx); return NULL; } ctx = (WINPR_CIPHER_CTX*) mctx; #endif - return ctx; } -BOOL 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; + int outl = (int) * olen; if (EVP_CipherUpdate((EVP_CIPHER_CTX*) ctx, output, &outl, input, ilen) == 1) { @@ -598,17 +626,18 @@ BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, } #elif defined(WITH_MBEDTLS) + if (mbedtls_cipher_update((mbedtls_cipher_context_t*) ctx, input, ilen, output, olen) == 0) return TRUE; -#endif +#endif return FALSE; } BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen) { #if defined(WITH_OPENSSL) - int outl = (int) *olen; + int outl = (int) * olen; if (EVP_CipherFinal_ex((EVP_CIPHER_CTX*) ctx, output, &outl) == 1) { @@ -617,10 +646,11 @@ BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen) } #elif defined(WITH_MBEDTLS) + if (mbedtls_cipher_finish((mbedtls_cipher_context_t*) ctx, output, olen) == 0) return TRUE; -#endif +#endif return FALSE; } @@ -642,13 +672,13 @@ void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx) * Key Generation */ -int winpr_Cipher_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* data, int datal, int count, BYTE* key, BYTE* iv) +int winpr_Cipher_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* data, int datal, + int count, BYTE* key, BYTE* iv) { /** * Key and IV generation compatible with OpenSSL EVP_BytesToKey(): * https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html */ - #if defined(WITH_OPENSSL) const EVP_MD* evp_md; const EVP_CIPHER* evp_cipher; @@ -664,13 +694,10 @@ int winpr_Cipher_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* da const mbedtls_md_info_t* md_info; mbedtls_cipher_type_t cipher_type; const mbedtls_cipher_info_t* cipher_info; - mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md); md_info = mbedtls_md_info_from_type(md_type); - cipher_type = winpr_mbedtls_get_cipher_type(cipher); cipher_info = mbedtls_cipher_info_from_type(cipher_type); - nkey = cipher_info->key_bitlen / 8; niv = cipher_info->iv_size; @@ -714,8 +741,10 @@ int winpr_Cipher_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* da { if (mbedtls_md_starts(&ctx) != 0) goto err; + if (mbedtls_md_update(&ctx, md_buf, mds) != 0) goto err; + if (mbedtls_md_finish(&ctx, md_buf) != 0) goto err; } @@ -728,10 +757,13 @@ int winpr_Cipher_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* da { if (nkey == 0) break; + if (i == mds) break; + if (key) *(key++) = md_buf[i]; + nkey--; i++; } @@ -743,10 +775,13 @@ int winpr_Cipher_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* da { if (niv == 0) break; + if (i == mds) break; + if (iv) *(iv++) = md_buf[i]; + niv--; i++; } @@ -762,6 +797,5 @@ err: SecureZeroMemory(md_buf, 64); return rv; #endif - return 0; } diff --git a/winpr/libwinpr/crypto/hash.c b/winpr/libwinpr/crypto/hash.c index 27eb434..9e731fc 100644 --- a/winpr/libwinpr/crypto/hash.c +++ b/winpr/libwinpr/crypto/hash.c @@ -143,29 +143,30 @@ mbedtls_md_type_t winpr_mbedtls_get_md_type(int md) WINPR_HMAC_CTX* winpr_HMAC_New(void) { WINPR_HMAC_CTX* ctx = NULL; - #if defined(WITH_OPENSSL) HMAC_CTX* hmac = NULL; #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) + if (!(hmac = (HMAC_CTX*) calloc(1, sizeof(HMAC_CTX)))) return NULL; + HMAC_CTX_init(hmac); #else + if (!(hmac = HMAC_CTX_new())) return NULL; + #endif ctx = (WINPR_HMAC_CTX*) hmac; - #elif defined(WITH_MBEDTLS) mbedtls_md_context_t* hmac; + if (!(hmac = (mbedtls_md_context_t*) calloc(1, sizeof(mbedtls_md_context_t)))) return NULL; mbedtls_md_init(hmac); - ctx = (WINPR_HMAC_CTX*) hmac; #endif - return ctx; } @@ -182,10 +183,11 @@ BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, siz HMAC_Init_ex(hmac, key, keylen, evp, NULL); /* no return value on OpenSSL 0.9.x */ return TRUE; #else + if (HMAC_Init_ex(hmac, key, keylen, evp, NULL) == 1) return TRUE; -#endif +#endif #elif defined(WITH_MBEDTLS) mbedtls_md_context_t* hmac = (mbedtls_md_context_t*) ctx; mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md); @@ -204,8 +206,8 @@ BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, siz if (mbedtls_md_hmac_starts(hmac, key, keylen) == 0) return TRUE; -#endif +#endif return FALSE; } @@ -213,21 +215,22 @@ BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) HMAC_CTX* hmac = (HMAC_CTX*) ctx; - #if (OPENSSL_VERSION_NUMBER < 0x10000000L) HMAC_Update(hmac, input, ilen); /* no return value on OpenSSL 0.9.x */ return TRUE; #else + if (HMAC_Update(hmac, input, ilen) == 1) return TRUE; -#endif +#endif #elif defined(WITH_MBEDTLS) mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx; + if (mbedtls_md_hmac_update(mdctx, input, ilen) == 0) return TRUE; -#endif +#endif return FALSE; } @@ -248,16 +251,18 @@ BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t olen) HMAC_Final(hmac, output, NULL); /* no return value on OpenSSL 0.9.x */ return TRUE; #else + if (HMAC_Final(hmac, output, NULL) == 1) return TRUE; -#endif +#endif #elif defined(WITH_MBEDTLS) mdctx = (mbedtls_md_context_t*) ctx; + if (mbedtls_md_hmac_finish(mdctx, output) == 0) return TRUE; -#endif +#endif return FALSE; } @@ -265,6 +270,7 @@ void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx) { #if defined(WITH_OPENSSL) HMAC_CTX* hmac = (HMAC_CTX*) ctx; + if (hmac) { #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) @@ -277,27 +283,31 @@ void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx) #elif defined(WITH_MBEDTLS) mbedtls_md_context_t* hmac = (mbedtls_md_context_t*) ctx; + if (hmac) { mbedtls_md_free(hmac); free(hmac); } + #endif } BOOL winpr_HMAC(WINPR_MD_TYPE md, const BYTE* key, size_t keylen, - const BYTE* input, size_t ilen, BYTE* output, size_t olen) + const BYTE* input, size_t ilen, BYTE* output, size_t olen) { BOOL result = FALSE; - WINPR_HMAC_CTX *ctx = winpr_HMAC_New(); + WINPR_HMAC_CTX* ctx = winpr_HMAC_New(); if (!ctx) return FALSE; if (!winpr_HMAC_Init(ctx, md, key, keylen)) goto out; + if (!winpr_HMAC_Update(ctx, input, ilen)) goto out; + if (!winpr_HMAC_Final(ctx, output, olen)) goto out; @@ -314,7 +324,6 @@ out: WINPR_DIGEST_CTX* winpr_Digest_New(void) { WINPR_DIGEST_CTX* ctx = NULL; - #if defined(WITH_OPENSSL) EVP_MD_CTX* mdctx; #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) @@ -323,23 +332,22 @@ WINPR_DIGEST_CTX* winpr_Digest_New(void) mdctx = EVP_MD_CTX_new(); #endif ctx = (WINPR_DIGEST_CTX*) mdctx; - #elif defined(WITH_MBEDTLS) mbedtls_md_context_t* mdctx; mdctx = (mbedtls_md_context_t*) calloc(1, sizeof(mbedtls_md_context_t)); + if (mdctx) mbedtls_md_init(mdctx); + ctx = (WINPR_DIGEST_CTX*) mdctx; #endif - return ctx; } -BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md) -{ #if defined(WITH_OPENSSL) +static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, const EVP_MD* evp) +{ EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx; - const EVP_MD* evp = winpr_openssl_get_evp_md(md); if (!mdctx || !evp) return FALSE; @@ -347,7 +355,12 @@ BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md) if (EVP_DigestInit_ex(mdctx, evp, NULL) != 1) return FALSE; + return TRUE; +} + #elif defined(WITH_MBEDTLS) +static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md) +{ mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx; mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md); const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type); @@ -365,21 +378,57 @@ BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md) if (mbedtls_md_starts(mdctx) != 0) return FALSE; -#endif return TRUE; } +#endif + +BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md) +{ +#if defined(WITH_OPENSSL) + EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx; + const EVP_MD* evp = winpr_openssl_get_evp_md(md); + + /* Only MD5 is supported for FIPS allow override */ + if (md != WINPR_MD_MD5) + return FALSE; + + EVP_MD_CTX_set_flags(mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + return winpr_Digest_Init_Internal(ctx, evp); +#elif defined(WITH_MBEDTLS) + + /* Only MD5 is supported for FIPS allow override */ + if (md != WINPR_MD_MD5) + return FALSE; + + return winpr_Digest_Init_Internal(ctx, md); +#endif +} + +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); + return winpr_Digest_Init_Internal(ctx, evp); +#else + return winpr_Digest_Init_Internal(ctx, md); +#endif +} BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx; + if (EVP_DigestUpdate(mdctx, input, ilen) != 1) return FALSE; + #elif defined(WITH_MBEDTLS) mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx; + if (mbedtls_md_update(mdctx, input, ilen) != 0) return FALSE; + #endif return TRUE; } @@ -388,15 +437,17 @@ BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t olen) { #if defined(WITH_OPENSSL) EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx; + if (EVP_DigestFinal_ex(mdctx, output, NULL) == 1) return TRUE; #elif defined(WITH_MBEDTLS) mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx; + if (mbedtls_md_finish(mdctx, output) == 0) return TRUE; -#endif +#endif return FALSE; } @@ -404,6 +455,7 @@ void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx) { #if defined(WITH_OPENSSL) EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx; + if (mdctx) { #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) @@ -415,26 +467,53 @@ void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx) #elif defined(WITH_MBEDTLS) mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx; + if (mdctx) { mbedtls_md_free(mdctx); free(mdctx); } + #endif } -BOOL winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen) +BOOL winpr_Digest_Allow_FIPS(WINPR_MD_TYPE md, const BYTE* input, size_t ilen, BYTE* output, size_t olen) { BOOL result = FALSE; - WINPR_DIGEST_CTX *ctx = winpr_Digest_New(); + WINPR_DIGEST_CTX* ctx = winpr_Digest_New(); if (!ctx) return FALSE; - if (!winpr_Digest_Init(ctx, md)) + if (!winpr_Digest_Init_Allow_FIPS(ctx, md)) goto out; + if (!winpr_Digest_Update(ctx, input, ilen)) goto out; + + if (!winpr_Digest_Final(ctx, output, olen)) + goto out; + + result = TRUE; +out: + winpr_Digest_Free(ctx); + return result; +} + +BOOL winpr_Digest(WINPR_MD_TYPE md, const BYTE* input, size_t ilen, BYTE* output, size_t olen) +{ + BOOL result = FALSE; + WINPR_DIGEST_CTX* ctx = winpr_Digest_New(); + + if (!ctx) + return FALSE; + + if (!winpr_Digest_Init(ctx, md)) + goto out; + + if (!winpr_Digest_Update(ctx, input, ilen)) + goto out; + if (!winpr_Digest_Final(ctx, output, olen)) goto out; diff --git a/winpr/libwinpr/dsparse/test/TestDsMakeSpn.c b/winpr/libwinpr/dsparse/test/TestDsMakeSpn.c index 3088de9..07a725b 100644 --- a/winpr/libwinpr/dsparse/test/TestDsMakeSpn.c +++ b/winpr/libwinpr/dsparse/test/TestDsMakeSpn.c @@ -5,23 +5,23 @@ #include <winpr/tchar.h> #include <winpr/dsparse.h> -LPCTSTR testServiceClass = _T("HTTP"); -LPCTSTR testServiceName = _T("LAB1-W2K8R2-GW.lab1.awake.local"); -LPCTSTR testSpn = _T("HTTP/LAB1-W2K8R2-GW.lab1.awake.local"); +static LPCTSTR testServiceClass = _T("HTTP"); +static LPCTSTR testServiceName = _T("LAB1-W2K8R2-GW.lab1.awake.local"); +static LPCTSTR testSpn = _T("HTTP/LAB1-W2K8R2-GW.lab1.awake.local"); int TestDsMakeSpn(int argc, char* argv[]) { - LPTSTR Spn; + int rc = -1; + LPTSTR Spn = NULL; DWORD status; DWORD SpnLength; - SpnLength = -1; status = DsMakeSpn(testServiceClass, testServiceName, NULL, 0, NULL, &SpnLength, NULL); if (status != ERROR_INVALID_PARAMETER) { _tprintf(_T("DsMakeSpn: expected ERROR_INVALID_PARAMETER\n")); - return -1; + goto fail; } SpnLength = 0; @@ -30,40 +30,42 @@ int TestDsMakeSpn(int argc, char* argv[]) if (status != ERROR_BUFFER_OVERFLOW) { _tprintf(_T("DsMakeSpn: expected ERROR_BUFFER_OVERFLOW\n")); - return -1; + goto fail; } if (SpnLength != 37) { _tprintf(_T("DsMakeSpn: SpnLength mismatch: Actual: %")_T(PRIu32)_T(", Expected: 37\n"), SpnLength); - return -1; + goto fail; } /* SpnLength includes null terminator */ Spn = (LPTSTR) calloc(SpnLength, sizeof(TCHAR)); + if (!Spn) { _tprintf(_T("DsMakeSpn: Unable to allocate memroy\n")); - return -1; + goto fail; } - status = DsMakeSpn(testServiceClass, testServiceName, NULL, 0, NULL, &SpnLength, Spn); if (status != ERROR_SUCCESS) { _tprintf(_T("DsMakeSpn: expected ERROR_SUCCESS\n")); - return -1; + goto fail; } if (_tcscmp(Spn, testSpn) != 0) { _tprintf(_T("DsMakeSpn: SPN mismatch: Actual: %s, Expected: %s\n"), Spn, testSpn); - return -1; + goto fail; } _tprintf(_T("DsMakeSpn: %s\n"), Spn); - - return 0; + rc = 0; +fail: + free(Spn); + return rc; } diff --git a/winpr/libwinpr/environment/test/TestEnvironmentMergeEnvironmentStrings.c b/winpr/libwinpr/environment/test/TestEnvironmentMergeEnvironmentStrings.c index dca2011..6a69e5b 100644 --- a/winpr/libwinpr/environment/test/TestEnvironmentMergeEnvironmentStrings.c +++ b/winpr/libwinpr/environment/test/TestEnvironmentMergeEnvironmentStrings.c @@ -12,10 +12,8 @@ int TestEnvironmentMergeEnvironmentStrings(int argc, char* argv[]) LPTCH lpszEnvironmentBlock; LPTCH lpsz2Merge = "SHELL=123\0test=1\0test1=2\0DISPLAY=:77\0\0"; LPTCH lpszMergedEnvironmentBlock; - lpszEnvironmentBlock = GetEnvironmentStrings(); - lpszMergedEnvironmentBlock = MergeEnvironmentStrings(lpszEnvironmentBlock,lpsz2Merge); - + lpszMergedEnvironmentBlock = MergeEnvironmentStrings(lpszEnvironmentBlock, lpsz2Merge); p = (TCHAR*) lpszMergedEnvironmentBlock; while (p[0] && p[1]) @@ -25,9 +23,9 @@ int TestEnvironmentMergeEnvironmentStrings(int argc, char* argv[]) p += (length + 1); } + FreeEnvironmentStrings(lpszMergedEnvironmentBlock); FreeEnvironmentStrings(lpszEnvironmentBlock); #endif - return 0; } diff --git a/winpr/libwinpr/error/test/TestErrorSetLastError.c b/winpr/libwinpr/error/test/TestErrorSetLastError.c index 2d8a699..5ddf5cc 100644 --- a/winpr/libwinpr/error/test/TestErrorSetLastError.c +++ b/winpr/libwinpr/error/test/TestErrorSetLastError.c @@ -31,7 +31,7 @@ static int status = 0; LONG *pLoopCount = NULL; BOOL bStopTest = FALSE; -static void* test_error_thread(void* arg) +static DWORD WINAPI test_error_thread(LPVOID arg) { int id; DWORD dwErrorSet; @@ -53,7 +53,7 @@ static void* test_error_thread(void* arg) InterlockedIncrement(pLoopCount); } while (!status && !bStopTest); - return NULL; + return 0; } int TestErrorSetLastError(int argc, char* argv[]) @@ -88,7 +88,7 @@ int TestErrorSetLastError(int argc, char* argv[]) for (i = 0; i < 4; i++) { - if (!(threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_error_thread, (void*) (size_t) 0, 0, NULL))) + if (!(threads[i] = CreateThread(NULL, 0, test_error_thread, (void*) (size_t) 0, 0, NULL))) { printf("Failed to create thread #%d\n", i); return -1; diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index c8e9597..e27c115 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -23,6 +23,12 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ +#if defined(__FreeBSD_kernel__) && defined(__GLIBC__) +#define _GNU_SOURCE +#define KFREEBSD +#endif + +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <winpr/file.h> @@ -99,12 +105,12 @@ static BOOL FileCloseHandle(HANDLE handle) { static BOOL FileSetEndOfFile(HANDLE hFile) { WINPR_FILE* pFile = (WINPR_FILE*) hFile; - off_t size; + INT64 size; if (!hFile) return FALSE; - size = ftell(pFile->fp); + size = _ftelli64(pFile->fp); if (ftruncate(fileno(pFile->fp), size) < 0) { @@ -122,12 +128,21 @@ static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) { WINPR_FILE* pFile = (WINPR_FILE*) hFile; - long offset = lDistanceToMove; + INT64 offset; int whence; if (!hFile) return INVALID_SET_FILE_POINTER; + /* If there is a high part, the sign is contained in that + * and the low integer must be interpreted as unsigned. */ + if (lpDistanceToMoveHigh) + { + offset = (INT64)(((UINT64)*lpDistanceToMoveHigh << 32U) | (UINT64)lDistanceToMove); + } + else + offset = lDistanceToMove; + switch(dwMoveMethod) { case FILE_BEGIN: @@ -143,14 +158,50 @@ static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, return INVALID_SET_FILE_POINTER; } - if (fseek(pFile->fp, offset, whence)) + if (_fseeki64(pFile->fp, offset, whence)) { - WLog_ERR(TAG, "fseek(%s) failed with %s [0x%08X]", pFile->lpFileName, + WLog_ERR(TAG, "_fseeki64(%s) failed with %s [0x%08X]", pFile->lpFileName, strerror(errno), errno); return INVALID_SET_FILE_POINTER; } - return ftell(pFile->fp); + return _ftelli64(pFile->fp); +} + +static BOOL FileSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) +{ + WINPR_FILE* pFile = (WINPR_FILE*) hFile; + int whence; + + if (!hFile) + return FALSE; + + switch(dwMoveMethod) + { + case FILE_BEGIN: + whence = SEEK_SET; + break; + case FILE_END: + whence = SEEK_END; + break; + case FILE_CURRENT: + whence = SEEK_CUR; + break; + default: + return FALSE; + } + + if (_fseeki64(pFile->fp, liDistanceToMove.QuadPart, whence)) + { + WLog_ERR(TAG, "_fseeki64(%s) failed with %s [0x%08X]", pFile->lpFileName, + strerror(errno), errno); + return FALSE; + } + + if (lpNewFilePointer) + lpNewFilePointer->QuadPart = _ftelli64(pFile->fp); + + return TRUE; } static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, @@ -227,41 +278,41 @@ static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrit static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh) { WINPR_FILE* file; - long cur, size; + INT64 cur, size; if (!Object) return 0; file = (WINPR_FILE *)Object; - cur = ftell(file->fp); + cur = _ftelli64(file->fp); if (cur < 0) { - WLog_ERR(TAG, "ftell(%s) failed with %s [0x%08X]", file->lpFileName, + WLog_ERR(TAG, "_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno), errno); return INVALID_FILE_SIZE; } - if (fseek(file->fp, 0, SEEK_END) != 0) + if (_fseeki64(file->fp, 0, SEEK_END) != 0) { - WLog_ERR(TAG, "fseek(%s) failed with %s [0x%08X]", file->lpFileName, + WLog_ERR(TAG, "_fseeki64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno), errno); return INVALID_FILE_SIZE; } - size = ftell(file->fp); + size = _ftelli64(file->fp); if (size < 0) { - WLog_ERR(TAG, "ftell(%s) failed with %s [0x%08X]", file->lpFileName, + WLog_ERR(TAG, "_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno), errno); return INVALID_FILE_SIZE; } - if (fseek(file->fp, cur, SEEK_SET) != 0) + if (_fseeki64(file->fp, cur, SEEK_SET) != 0) { - WLog_ERR(TAG, "ftell(%s) failed with %s [0x%08X]", file->lpFileName, + WLog_ERR(TAG, "_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno), errno); return INVALID_FILE_SIZE; } @@ -276,7 +327,12 @@ static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped) { +#ifdef __sun + struct flock lock; + int lckcmd; +#else int lock; +#endif WINPR_FILE* pFile = (WINPR_FILE*)hFile; if (lpOverlapped) @@ -295,6 +351,27 @@ static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, return FALSE; } +#ifdef __sun + lock.l_start = 0; + lock.l_len = 0; + lock.l_whence = SEEK_SET; + + if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK) + lock.l_type = F_WRLCK; + else + lock.l_type = F_WRLCK; + + if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY) + lckcmd = F_SETLK; + else + lckcmd = F_SETLKW; + + if(fcntl(fileno(pFile->fp), lckcmd, &lock) == -1) { + WLog_ERR(TAG, "F_SETLK failed with %s [0x%08X]", + strerror(errno), errno); + return FALSE; + } +#else if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK) lock = LOCK_EX; else @@ -309,6 +386,7 @@ static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, strerror(errno), errno); return FALSE; } +#endif pFile->bLocked = TRUE; @@ -319,6 +397,9 @@ static BOOL FileUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffs DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh) { WINPR_FILE* pFile = (WINPR_FILE*)hFile; +#ifdef __sun + struct flock lock; +#endif if (!hFile) return FALSE; @@ -329,12 +410,26 @@ static BOOL FileUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffs return FALSE; } +#ifdef __sun + lock.l_start = 0; + lock.l_len = 0; + lock.l_whence = SEEK_SET; + lock.l_type = F_UNLCK; + if (fcntl(fileno(pFile->fp), F_GETLK, &lock) == -1) + { + WLog_ERR(TAG, "F_UNLCK on %s failed with %s [0x%08X]", + pFile->lpFileName, strerror(errno), errno); + return FALSE; + } + +#else if (flock(fileno(pFile->fp), LOCK_UN) < 0) { WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [0x%08X]", pFile->lpFileName, strerror(errno), errno); return FALSE; } +#endif return TRUE; } @@ -343,6 +438,9 @@ static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfByte DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped) { WINPR_FILE* pFile = (WINPR_FILE*)hFile; +#ifdef __sun + struct flock lock; +#endif if (lpOverlapped) { @@ -360,12 +458,25 @@ static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfByte return FALSE; } +#ifdef __sun + lock.l_start = 0; + lock.l_len = 0; + lock.l_whence = SEEK_SET; + lock.l_type = F_UNLCK; + if (fcntl(fileno(pFile->fp), F_GETLK, &lock) == -1) + { + WLog_ERR(TAG, "F_UNLCK on %s failed with %s [0x%08X]", + pFile->lpFileName, strerror(errno), errno); + return FALSE; + } +#else if (flock(fileno(pFile->fp), LOCK_UN) < 0) { WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [0x%08X]", pFile->lpFileName, strerror(errno), errno); return FALSE; } +#endif return TRUE; } @@ -384,7 +495,7 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime) { int rc; -#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD) struct stat buf; /* OpenBSD, NetBSD and DragonflyBSD support POSIX futimens */ struct timeval timevals[2]; @@ -396,7 +507,7 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, if (!hFile) return FALSE; -#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD) rc = fstat(fileno(pFile->fp), &buf); if (rc < 0) @@ -406,7 +517,7 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, if (!lpLastAccessTime) { -#if defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD) timevals[0].tv_sec = buf.st_atime; #ifdef _POSIX_SOURCE TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atim); @@ -424,7 +535,7 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, else { UINT64 tmp = FileTimeToUS(lpLastAccessTime); -#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD) timevals[0].tv_sec = tmp / 1000000ULL; timevals[0].tv_usec = tmp % 1000000ULL; #else @@ -435,7 +546,7 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, if (!lpLastWriteTime) { -#if defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD) timevals[1].tv_sec = buf.st_mtime; #ifdef _POSIX_SOURCE TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtim); @@ -453,7 +564,7 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, else { UINT64 tmp = FileTimeToUS(lpLastWriteTime); -#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD) timevals[1].tv_sec = tmp / 1000000ULL; timevals[1].tv_usec = tmp % 1000000ULL; #else @@ -463,7 +574,7 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, } // TODO: Creation time can not be handled! -#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) +#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD) rc = utimes(pFile->lpFileName, timevals); #else rc = futimens(fileno(pFile->fp), times); @@ -490,7 +601,7 @@ static HANDLE_OPS fileOps = { NULL, /* FlushFileBuffers */ FileSetEndOfFile, FileSetFilePointer, - NULL, /* SetFilePointerEx */ + FileSetFilePointerEx, NULL, /* FileLockFile */ FileLockFileEx, FileUnlockFile, @@ -524,7 +635,7 @@ static HANDLE_OPS shmOps = { static const char* FileGetMode(DWORD dwDesiredAccess, DWORD dwCreationDisposition, BOOL* create) { - BOOL writeable = (dwDesiredAccess & (GENERIC_WRITE | STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0; + BOOL writeable = (dwDesiredAccess & (GENERIC_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0; switch(dwCreationDisposition) { @@ -561,6 +672,14 @@ UINT32 map_posix_err(int fs_errno) rc = STATUS_SUCCESS; break; + case ENOTCONN: + case ENODEV: + case ENOTDIR: + case ENXIO: + rc = ERROR_FILE_NOT_FOUND; + break; + + case EROFS: case EPERM: case EACCES: rc = ERROR_ACCESS_DENIED; @@ -587,6 +706,8 @@ UINT32 map_posix_err(int fs_errno) break; default: + WLog_ERR(TAG, "Missing ERRNO mapping %s [%d]", + strerror(fs_errno), fs_errno); rc = STATUS_UNSUCCESSFUL; break; } @@ -600,7 +721,11 @@ static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw WINPR_FILE* pFile; BOOL create; const char* mode = FileGetMode(dwDesiredAccess, dwCreationDisposition, &create); +#ifdef __sun + struct flock lock; +#else int lock = 0; +#endif FILE* fp = NULL; struct stat st; @@ -660,6 +785,27 @@ static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw fp = freopen(pFile->lpFileName, mode, fp); } + else + { + if (stat(pFile->lpFileName, &st) != 0) + { + SetLastError(map_posix_err(errno)); + free(pFile->lpFileName); + free(pFile); + return INVALID_HANDLE_VALUE; + } + + /* FIFO (named pipe) would block the following fopen + * call if not connected. This renders the channel unusable, + * therefore abort early. */ + if (S_ISFIFO(st.st_mode)) + { + SetLastError(ERROR_FILE_NOT_FOUND); + free(pFile->lpFileName); + free(pFile); + return INVALID_HANDLE_VALUE; + } + } if (NULL == fp) fp = fopen(pFile->lpFileName, mode); @@ -677,16 +823,35 @@ static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw setvbuf(fp, NULL, _IONBF, 0); +#ifdef __sun + lock.l_start = 0; + lock.l_len = 0; + lock.l_whence = SEEK_SET; + + if (dwShareMode & FILE_SHARE_READ) + lock.l_type = F_RDLCK; + if (dwShareMode & FILE_SHARE_WRITE) + lock.l_type = F_RDLCK; +#else if (dwShareMode & FILE_SHARE_READ) lock = LOCK_SH; if (dwShareMode & FILE_SHARE_WRITE) lock = LOCK_EX; +#endif if (dwShareMode & (FILE_SHARE_READ | FILE_SHARE_WRITE)) { +#ifdef __sun + if (fcntl(fileno(pFile->fp), F_SETLKW, &lock) == -1) +#else if (flock(fileno(pFile->fp), lock) < 0) +#endif { +#ifdef __sun + WLog_ERR(TAG, "F_SETLKW failed with %s [0x%08X]", +#else WLog_ERR(TAG, "flock failed with %s [0x%08X]", +#endif strerror(errno), errno); SetLastError(map_posix_err(errno)); FileCloseHandle(pFile); diff --git a/winpr/libwinpr/file/generic.c b/winpr/libwinpr/file/generic.c index 004656a..32b6cfe 100644 --- a/winpr/libwinpr/file/generic.c +++ b/winpr/libwinpr/file/generic.c @@ -788,8 +788,8 @@ typedef struct _WIN32_FILE_SEARCH WIN32_FILE_SEARCH; HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData) { LPSTR p; - int index; - int length; + size_t index; + size_t length; struct stat fileStat; WIN32_FILE_SEARCH* pFileSearch; ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA)); @@ -867,7 +867,7 @@ HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData) static BOOL ConvertFindDataAToW(LPWIN32_FIND_DATAA lpFindFileDataA, LPWIN32_FIND_DATAW lpFindFileDataW) { - int length; + size_t length; WCHAR* unicodeFileName; if (!lpFindFileDataA || !lpFindFileDataW) @@ -882,7 +882,7 @@ static BOOL ConvertFindDataAToW(LPWIN32_FIND_DATAA lpFindFileDataA, lpFindFileDataW->dwReserved0 = lpFindFileDataA->dwReserved0; lpFindFileDataW->dwReserved1 = lpFindFileDataA->dwReserved1; unicodeFileName = NULL; - length = ConvertToUnicode(CP_UTF8, 0, lpFindFileDataA->cFileName, -1, &unicodeFileName, 0) * 2; + length = ConvertToUnicode(CP_UTF8, 0, lpFindFileDataA->cFileName, -1, &unicodeFileName, 0); if (length == 0) return FALSE; @@ -890,10 +890,10 @@ static BOOL ConvertFindDataAToW(LPWIN32_FIND_DATAA lpFindFileDataA, if (length > MAX_PATH) length = MAX_PATH; - CopyMemory(lpFindFileDataW->cFileName, unicodeFileName, length); + CopyMemory(lpFindFileDataW->cFileName, unicodeFileName, length * sizeof(WCHAR)); free(unicodeFileName); length = ConvertToUnicode(CP_UTF8, 0, lpFindFileDataA->cAlternateFileName, - -1, &unicodeFileName, 0) * 2; + -1, &unicodeFileName, 0); if (length == 0) return TRUE; @@ -901,7 +901,7 @@ static BOOL ConvertFindDataAToW(LPWIN32_FIND_DATAA lpFindFileDataA, if (length > 14) length = 14; - CopyMemory(lpFindFileDataW->cAlternateFileName, unicodeFileName, length); + CopyMemory(lpFindFileDataW->cAlternateFileName, unicodeFileName, length * sizeof(WCHAR)); free(unicodeFileName); return TRUE; } @@ -960,8 +960,8 @@ BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData) WIN32_FILE_SEARCH* pFileSearch; struct stat fileStat; char* fullpath; - int pathlen; - int namelen; + size_t pathlen; + size_t namelen; UINT64 ft; ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA)); @@ -977,8 +977,8 @@ BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData) { if (FilePatternMatchA(pFileSearch->pDirent->d_name, pFileSearch->lpPattern)) { - strcpy(lpFindFileData->cFileName, pFileSearch->pDirent->d_name); - namelen = strlen(lpFindFileData->cFileName); + strncpy(lpFindFileData->cFileName, pFileSearch->pDirent->d_name, MAX_PATH); + namelen = strnlen(lpFindFileData->cFileName, MAX_PATH); pathlen = strlen(pFileSearch->lpPath); fullpath = (char*)malloc(pathlen + namelen + 2); @@ -997,10 +997,14 @@ BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData) { free(fullpath); SetLastError(map_posix_err(errno)); - return FALSE; + continue; } free(fullpath); + + /* Skip FIFO entries. */ + if (S_ISFIFO(fileStat.st_mode)) + continue; lpFindFileData->dwFileAttributes = 0; if (S_ISDIR(fileStat.st_mode)) @@ -1025,7 +1029,7 @@ BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData) lpFindFileData->ftCreationTime.dwLowDateTime = ft & 0xFFFFFFFF; ft = STAT_TIME_TO_FILETIME(fileStat.st_mtime); lpFindFileData->ftLastWriteTime.dwHighDateTime = ((UINT64)ft) >> 32ULL; - lpFindFileData->ftCreationTime.dwLowDateTime = ft & 0xFFFFFFFF; + lpFindFileData->ftLastWriteTime.dwLowDateTime = ft & 0xFFFFFFFF; ft = STAT_TIME_TO_FILETIME(fileStat.st_atime); lpFindFileData->ftLastAccessTime.dwHighDateTime = ((UINT64)ft) >> 32ULL; lpFindFileData->ftLastAccessTime.dwLowDateTime = ft & 0xFFFFFFFF; diff --git a/winpr/libwinpr/file/test/TestFileFindFirstFile.c b/winpr/libwinpr/file/test/TestFileFindFirstFile.c index 7cb5678..30a197f 100644 --- a/winpr/libwinpr/file/test/TestFileFindFirstFile.c +++ b/winpr/libwinpr/file/test/TestFileFindFirstFile.c @@ -16,37 +16,36 @@ int TestFileFindFirstFile(int argc, char* argv[]) LPTSTR BasePath; WIN32_FIND_DATA FindData; TCHAR FilePath[PATHCCH_MAX_CCH]; - str = argv[1]; - #ifdef UNICODE length = MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), NULL, 0); BasePath = (WCHAR*) calloc((length + 1), sizeof(WCHAR)); + if (!BasePath) { _tprintf(_T("Unable to allocate memory\n")); return -1; } + MultiByteToWideChar(CP_UTF8, 0, str, length, (LPWSTR) BasePath, length * sizeof(WCHAR)); BasePath[length] = 0; #else BasePath = _strdup(str); + if (!BasePath) { printf("Unable to allocate memory\n"); return -1; } + length = strlen(BasePath); #endif - CopyMemory(FilePath, BasePath, length * sizeof(TCHAR)); FilePath[length] = 0; - PathCchConvertStyle(BasePath, length, PATH_STYLE_WINDOWS); NativePathCchAppend(FilePath, PATHCCH_MAX_CCH, _T("TestFile1")); - + free(BasePath); _tprintf(_T("Finding file: %s\n"), FilePath); - hFind = FindFirstFile(FilePath, &FindData); if (hFind == INVALID_HANDLE_VALUE) @@ -60,11 +59,10 @@ int TestFileFindFirstFile(int argc, char* argv[]) if (_tcscmp(FindData.cFileName, testFile1) != 0) { _tprintf(_T("FindFirstFile failure: Expected: %s, Actual: %s\n"), - testFile1, FindData.cFileName); + testFile1, FindData.cFileName); return -1; } FindClose(hFind); - return 0; } diff --git a/winpr/libwinpr/file/test/TestFileFindNextFile.c b/winpr/libwinpr/file/test/TestFileFindNextFile.c index 7b154ea..172103a 100644 --- a/winpr/libwinpr/file/test/TestFileFindNextFile.c +++ b/winpr/libwinpr/file/test/TestFileFindNextFile.c @@ -18,40 +18,38 @@ int TestFileFindNextFile(int argc, char* argv[]) LPTSTR BasePath; WIN32_FIND_DATA FindData; TCHAR FilePath[PATHCCH_MAX_CCH]; - str = argv[1]; - #ifdef UNICODE length = MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), NULL, 0); BasePath = (WCHAR*) calloc((length + 1), sizeof(WCHAR)); + if (!BasePath) { _tprintf(_T("Unable to allocate memory")); return -1; } + MultiByteToWideChar(CP_UTF8, 0, str, length, (LPWSTR) BasePath, length * sizeof(WCHAR)); BasePath[length] = 0; #else BasePath = _strdup(str); + if (!BasePath) { printf("Unable to allocate memory"); return -1; } + length = strlen(BasePath); #endif - /* Simple filter matching all files inside current directory */ - CopyMemory(FilePath, BasePath, length * sizeof(TCHAR)); FilePath[length] = 0; - PathCchConvertStyle(BasePath, length, PATH_STYLE_WINDOWS); NativePathCchAppend(FilePath, PATHCCH_MAX_CCH, _T("TestDirectory2")); NativePathCchAppend(FilePath, PATHCCH_MAX_CCH, _T("TestDirectory2File*")); - + free(BasePath); _tprintf(_T("Finding file: %s\n"), FilePath); - hFind = FindFirstFile(FilePath, &FindData); if (hFind == INVALID_HANDLE_VALUE) @@ -66,10 +64,11 @@ int TestFileFindNextFile(int argc, char* argv[]) * The current implementation does not enforce a particular order */ - if ((_tcscmp(FindData.cFileName, testDirectory2File1) != 0) && (_tcscmp(FindData.cFileName, testDirectory2File2) != 0)) + if ((_tcscmp(FindData.cFileName, testDirectory2File1) != 0) && + (_tcscmp(FindData.cFileName, testDirectory2File2) != 0)) { _tprintf(_T("FindFirstFile failure: Expected: %s, Actual: %s\n"), - testDirectory2File1, FindData.cFileName); + testDirectory2File1, FindData.cFileName); return -1; } @@ -81,10 +80,11 @@ int TestFileFindNextFile(int argc, char* argv[]) return -1; } - if ((_tcscmp(FindData.cFileName, testDirectory2File1) != 0) && (_tcscmp(FindData.cFileName, testDirectory2File2) != 0)) + if ((_tcscmp(FindData.cFileName, testDirectory2File1) != 0) && + (_tcscmp(FindData.cFileName, testDirectory2File2) != 0)) { _tprintf(_T("FindNextFile failure: Expected: %s, Actual: %s\n"), - testDirectory2File2, FindData.cFileName); + testDirectory2File2, FindData.cFileName); return -1; } @@ -97,7 +97,6 @@ int TestFileFindNextFile(int argc, char* argv[]) } FindClose(hFind); - return 0; } diff --git a/winpr/libwinpr/input/keycode.c b/winpr/libwinpr/input/keycode.c index 1c628b2..beec519 100644 --- a/winpr/libwinpr/input/keycode.c +++ b/winpr/libwinpr/input/keycode.c @@ -401,6 +401,20 @@ DWORD KEYCODE_TO_VKCODE_EVDEV[256] = VK_OEM_102, /* <LSGT> 94 */ VK_F11, /* <FK11> 95 */ VK_F12, /* <FK12> 96 */ +#ifdef __sun + VK_HOME | KBDEXT, /* <HOME> 97 */ + VK_UP | KBDEXT, /* <UP> 98 */ + VK_PRIOR | KBDEXT, /* <PGUP> 99 */ + VK_LEFT | KBDEXT, /* <LEFT> 100 */ + VK_HKTG, /* <HKTG> 101 */ + VK_RIGHT | KBDEXT, /* <RGHT> 102 */ + VK_END | KBDEXT, /* <END> 103 */ + VK_DOWN | KBDEXT, /* <DOWN> 104 */ + VK_NEXT | KBDEXT, /* <PGDN> 105 */ + VK_INSERT | KBDEXT, /* <INS> 106 */ + VK_DELETE | KBDEXT, /* <DELE> 107 */ + VK_RETURN | KBDEXT, /* <KPEN> 108 */ +#else VK_ABNT_C1, /* <AB11> 97 */ VK_DBE_KATAKANA, /* <KATA> 98 */ VK_DBE_HIRAGANA, /* <HIRA> 99 */ @@ -413,6 +427,7 @@ DWORD KEYCODE_TO_VKCODE_EVDEV[256] = VK_DIVIDE | KBDEXT, /* <KPDV> 106 */ VK_SNAPSHOT | KBDEXT, /* <PRSC> 107 */ VK_RMENU | KBDEXT, /* <RALT> <ALGR> 108 */ +#endif 0, /* <LNFD> KEY_LINEFEED 109 */ VK_HOME | KBDEXT, /* <HOME> 110 */ VK_UP | KBDEXT, /* <UP> 111 */ diff --git a/winpr/libwinpr/io/device.c b/winpr/libwinpr/io/device.c index 0e13092..2a1b7f8 100644 --- a/winpr/libwinpr/io/device.c +++ b/winpr/libwinpr/io/device.c @@ -138,7 +138,7 @@ NTSTATUS _IoCreateDeviceEx(PDRIVER_OBJECT_EX DriverObject, ULONG DeviceExtension if (!PathFileExistsA(DeviceBasePath)) { - if (!mkdir(DeviceBasePath, S_IRUSR | S_IWUSR | S_IXUSR)) + if (mkdir(DeviceBasePath, S_IRUSR | S_IWUSR | S_IXUSR) != 0) { free(DeviceBasePath); return STATUS_ACCESS_DENIED; diff --git a/winpr/libwinpr/nt/nt.c b/winpr/libwinpr/nt/nt.c index 2730ea3..f872a36 100644 --- a/winpr/libwinpr/nt/nt.c +++ b/winpr/libwinpr/nt/nt.c @@ -27,6 +27,7 @@ #include <winpr/library.h> #include <winpr/wlog.h> #include <winpr/nt.h> +#include <winpr/endian.h> #include "../log.h" #define TAG WINPR_TAG("nt") @@ -187,7 +188,7 @@ NTSTATUS _RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, for (index = 0; index < SourceString->MaximumLength; index++) { - DestinationString->Buffer[index] = (WCHAR) SourceString->Buffer[index]; + Data_Write_UINT16(&DestinationString->Buffer[index], SourceString->Buffer[index]); } DestinationString->Length = SourceString->Length * 2; diff --git a/winpr/libwinpr/nt/test/TestNtCreateFile.c b/winpr/libwinpr/nt/test/TestNtCreateFile.c index d7167fd..d5e6dad 100644 --- a/winpr/libwinpr/nt/test/TestNtCreateFile.c +++ b/winpr/libwinpr/nt/test/TestNtCreateFile.c @@ -21,10 +21,9 @@ int TestNtCreateFile(int argc, char* argv[]) OBJECT_ATTRIBUTES attributes; IO_STATUS_BLOCK ioStatusBlock; int result = -1; - _RtlInitAnsiString(&aString, TESTFILE); - ntstatus = _RtlAnsiStringToUnicodeString(&uString, &aString, TRUE); + if (ntstatus != STATUS_SUCCESS) { printf("_RtlAnsiStringToUnicodeString failure: 0x%08"PRIX32"\n", ntstatus); @@ -33,15 +32,12 @@ int TestNtCreateFile(int argc, char* argv[]) handle = NULL; ZeroMemory(&ioStatusBlock, sizeof(IO_STATUS_BLOCK)); - _InitializeObjectAttributes(&attributes, &uString, 0, NULL, NULL); - DesiredAccess = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE; CreateOptions = FILE_DIRECTORY_FILE | FILE_WRITE_THROUGH; CreateDisposition = FILE_OVERWRITE_IF; - ntstatus = _NtCreateFile(&handle, DesiredAccess, &attributes, &ioStatusBlock, - 0, 0, CreateDisposition, CreateOptions, 0, 0, 0); + 0, 0, CreateDisposition, CreateOptions, 0, 0, 0); if (ntstatus != STATUS_SUCCESS) { @@ -49,8 +45,6 @@ int TestNtCreateFile(int argc, char* argv[]) goto out; } - _RtlFreeUnicodeString(&uString); - ntstatus = _NtClose(handle); if (ntstatus != STATUS_SUCCESS) @@ -60,23 +54,23 @@ int TestNtCreateFile(int argc, char* argv[]) } result = 0; - out: - + _RtlFreeUnicodeString(&uString); #ifndef _WIN32 + if (result == 0) { printf("%s: Error, this test is currently expected not to succeed on this platform.\n", - __FUNCTION__); + __FUNCTION__); result = -1; } else { printf("%s: This test is currently expected to fail on this platform.\n", - __FUNCTION__); + __FUNCTION__); result = 0; } -#endif +#endif return result; } diff --git a/winpr/libwinpr/path/test/TestPathShell.c b/winpr/libwinpr/path/test/TestPathShell.c index e311f1b..1e2781d 100644 --- a/winpr/libwinpr/path/test/TestPathShell.c +++ b/winpr/libwinpr/path/test/TestPathShell.c @@ -7,43 +7,61 @@ int TestPathShell(int argc, char* argv[]) { - char* path; + const int paths[] = + { + KNOWN_PATH_HOME, + KNOWN_PATH_TEMP, + KNOWN_PATH_XDG_DATA_HOME, + KNOWN_PATH_XDG_CONFIG_HOME, + KNOWN_PATH_XDG_CACHE_HOME, + KNOWN_PATH_XDG_RUNTIME_DIR, + KNOWN_PATH_XDG_CONFIG_HOME + }; + const char* names[] = + { + "KNOWN_PATH_HOME", + "KNOWN_PATH_TEMP", + "KNOWN_PATH_XDG_DATA_HOME", + "KNOWN_PATH_XDG_CONFIG_HOME", + "KNOWN_PATH_XDG_CACHE_HOME", + "KNOWN_PATH_XDG_RUNTIME_DIR", + "KNOWN_PATH_XDG_CONFIG_HOME" + }; + int rc = 0; + size_t x; - path = GetKnownPath(KNOWN_PATH_HOME); - if (!path) - return -1; - printf("KNOWN_PATH_HOME: %s\n", path); + for (x = 0; x < sizeof(paths) / sizeof(paths[0]); x++) + { + const int id = paths[x]; + const char* name = names[x]; + { + char* path = GetKnownPath(id); - path = GetKnownPath(KNOWN_PATH_TEMP); - if (!path) - return -1; - printf("KNOWN_PATH_TEMP: %s\n", path); + if (!path) + { + rc = -1; + } + else + { + printf("%s Path: %s\n", name, path); + } + free(path); + } + { + char* path = GetKnownSubPath(id, "freerdp"); - path = GetKnownPath(KNOWN_PATH_XDG_DATA_HOME); - if (!path) - return -1; - printf("KNOWN_PATH_DATA: %s\n", path); + if (!path) + { + rc = -1; + } + else + { + printf("%s SubPath: %s\n", name, path); + } + free(path); + } + } - path = GetKnownPath(KNOWN_PATH_XDG_CONFIG_HOME); - if (!path) - return -1; - printf("KNOWN_PATH_CONFIG: %s\n", path); - - path = GetKnownPath(KNOWN_PATH_XDG_CACHE_HOME); - if (!path) - return -1; - printf("KNOWN_PATH_CACHE: %s\n", path); - - path = GetKnownPath(KNOWN_PATH_XDG_RUNTIME_DIR); - if (!path) - return -1; - printf("KNOWN_PATH_RUNTIME: %s\n", path); - - path = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, "freerdp"); - if (!path) - return -1; - printf("KNOWN_PATH_CONFIG SubPath: %s\n", path); - - return 0; + return rc; } diff --git a/winpr/libwinpr/pipe/pipe.c b/winpr/libwinpr/pipe/pipe.c index 054c2a5..d606a27 100644 --- a/winpr/libwinpr/pipe/pipe.c +++ b/winpr/libwinpr/pipe/pipe.c @@ -45,11 +45,11 @@ #include <assert.h> #include <unistd.h> -#ifdef HAVE_AIO_H -#undef HAVE_AIO_H /* disable for now, incomplete */ +#ifdef HAVE_SYS_AIO_H +#undef HAVE_SYS_AIO_H /* disable for now, incomplete */ #endif -#ifdef HAVE_AIO_H +#ifdef HAVE_SYS_AIO_H #include <aio.h> #endif @@ -327,7 +327,7 @@ BOOL NamedPipeRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, return FALSE; pipe->lpOverlapped = lpOverlapped; -#ifdef HAVE_AIO_H +#ifdef HAVE_SYS_AIO_H { int aio_status; struct aiocb cb; @@ -416,7 +416,7 @@ BOOL NamedPipeWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, return FALSE; pipe->lpOverlapped = lpOverlapped; -#ifdef HAVE_AIO_H +#ifdef HAVE_SYS_AIO_H { struct aiocb cb; ZeroMemory(&cb, sizeof(struct aiocb)); diff --git a/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipe.c b/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipe.c index 57519a4..e89e9af 100644 --- a/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipe.c +++ b/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipe.c @@ -21,9 +21,9 @@ static HANDLE ReadyEvent; static LPTSTR lpszPipeNameMt = _T("\\\\.\\pipe\\winpr_test_pipe_mt"); static LPTSTR lpszPipeNameSt = _T("\\\\.\\pipe\\winpr_test_pipe_st"); -BOOL testFailed = FALSE; +static BOOL testFailed = FALSE; -static void* named_pipe_client_thread(void* arg) +static DWORD WINAPI named_pipe_client_thread(LPVOID arg) { HANDLE hNamedPipe = NULL; BYTE* lpReadBuffer = NULL; @@ -87,10 +87,11 @@ out: if (!fSuccess) testFailed = TRUE; - return NULL; + ExitThread(0); + return 0; } -static void* named_pipe_server_thread(void* arg) +static DWORD WINAPI named_pipe_server_thread(LPVOID arg) { HANDLE hNamedPipe = NULL; BYTE* lpReadBuffer = NULL; @@ -179,11 +180,12 @@ out: if (!fSuccess) testFailed = TRUE; - return NULL; + ExitThread(0); + return 0; } #define TESTNUMPIPESST 16 -static void* named_pipe_single_thread(void* arg) +static DWORD WINAPI named_pipe_single_thread(LPVOID arg) { HANDLE servers[TESTNUMPIPESST]; HANDLE clients[TESTNUMPIPESST]; @@ -431,7 +433,7 @@ out: if (!bSuccess) testFailed = TRUE; - return NULL; + return 0; } @@ -459,17 +461,17 @@ int TestPipeCreateNamedPipe(int argc, char* argv[]) printf("CreateEvent failure: (%"PRIu32")\n", GetLastError()); return -1; } - if (!(SingleThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_single_thread, NULL, 0, NULL))) + if (!(SingleThread = CreateThread(NULL, 0, named_pipe_single_thread, NULL, 0, NULL))) { printf("CreateThread (SingleThread) failure: (%"PRIu32")\n", GetLastError()); return -1; } - if (!(ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_client_thread, NULL, 0, NULL))) + if (!(ClientThread = CreateThread(NULL, 0, named_pipe_client_thread, NULL, 0, NULL))) { printf("CreateThread (ClientThread) failure: (%"PRIu32")\n", GetLastError()); return -1; } - if (!(ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_server_thread, NULL, 0, NULL))) + if (!(ServerThread = CreateThread(NULL, 0, named_pipe_server_thread, NULL, 0, NULL))) { printf("CreateThread (ServerThread) failure: (%"PRIu32")\n", GetLastError()); return -1; diff --git a/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipeOverlapped.c b/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipeOverlapped.c index 3bae9d1..8218898 100644 --- a/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipeOverlapped.c +++ b/winpr/libwinpr/pipe/test/TestPipeCreateNamedPipeOverlapped.c @@ -13,17 +13,17 @@ #define PIPE_BUFFER_SIZE 32 #define PIPE_TIMEOUT_MS 20000 // 20 seconds -BYTE SERVER_MESSAGE[PIPE_BUFFER_SIZE]; -BYTE CLIENT_MESSAGE[PIPE_BUFFER_SIZE]; +static BYTE SERVER_MESSAGE[PIPE_BUFFER_SIZE]; +static BYTE CLIENT_MESSAGE[PIPE_BUFFER_SIZE]; -BOOL bClientSuccess = FALSE; -BOOL bServerSuccess = FALSE; +static BOOL bClientSuccess = FALSE; +static BOOL bServerSuccess = FALSE; static HANDLE serverReadyEvent; static LPTSTR lpszPipeName = _T("\\\\.\\pipe\\winpr_test_pipe_overlapped"); -static void* named_pipe_client_thread(void* arg) +static DWORD WINAPI named_pipe_client_thread(LPVOID arg) { DWORD status; HANDLE hEvent = NULL; @@ -153,10 +153,10 @@ finish: if (hEvent) CloseHandle(hEvent); - return NULL; + return 0; } -static void* named_pipe_server_thread(void* arg) +static DWORD WINAPI named_pipe_server_thread(LPVOID arg) { DWORD status; HANDLE hEvent = NULL; @@ -331,7 +331,7 @@ finish: CloseHandle(hNamedPipe); CloseHandle(hEvent); free(lpReadBuffer); - return NULL; + return 0; } int TestPipeCreateNamedPipeOverlapped(int argc, char* argv[]) @@ -348,7 +348,7 @@ int TestPipeCreateNamedPipeOverlapped(int argc, char* argv[]) printf("CreateEvent failed: %"PRIu32"\n", GetLastError()); goto out; } - if (!(ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_client_thread, NULL, 0, NULL))) + if (!(ClientThread = CreateThread(NULL, 0, named_pipe_client_thread, NULL, 0, NULL))) { printf("CreateThread (client) failed: %"PRIu32"\n", GetLastError()); goto out; diff --git a/winpr/libwinpr/pool/cleanup_group.c b/winpr/libwinpr/pool/cleanup_group.c index 5696095..cf8eb2d 100644 --- a/winpr/libwinpr/pool/cleanup_group.c +++ b/winpr/libwinpr/pool/cleanup_group.c @@ -31,59 +31,109 @@ #ifdef _WIN32 static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT; -static PTP_CLEANUP_GROUP (WINAPI * pCreateThreadpoolCleanupGroup)(); -static VOID (WINAPI * pCloseThreadpoolCleanupGroupMembers)(PTP_CLEANUP_GROUP ptpcg, BOOL fCancelPendingCallbacks, PVOID pvCleanupContext); -static VOID (WINAPI * pCloseThreadpoolCleanupGroup)(PTP_CLEANUP_GROUP ptpcg); +static PTP_CLEANUP_GROUP(WINAPI* pCreateThreadpoolCleanupGroup)(); +static VOID (WINAPI* pCloseThreadpoolCleanupGroupMembers)(PTP_CLEANUP_GROUP ptpcg, + BOOL fCancelPendingCallbacks, PVOID pvCleanupContext); +static VOID (WINAPI* pCloseThreadpoolCleanupGroup)(PTP_CLEANUP_GROUP ptpcg); -static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context) +static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID* context) { HMODULE kernel32 = LoadLibraryA("kernel32.dll"); + if (kernel32) { pCreateThreadpoolCleanupGroup = (void*)GetProcAddress(kernel32, "CreateThreadpoolCleanupGroup"); - pCloseThreadpoolCleanupGroupMembers = (void*)GetProcAddress(kernel32, "CloseThreadpoolCleanupGroupMembers"); + pCloseThreadpoolCleanupGroupMembers = (void*)GetProcAddress(kernel32, + "CloseThreadpoolCleanupGroupMembers"); pCloseThreadpoolCleanupGroup = (void*)GetProcAddress(kernel32, "CloseThreadpoolCleanupGroup"); } + return TRUE; } #endif -PTP_CLEANUP_GROUP winpr_CreateThreadpoolCleanupGroup() +PTP_CLEANUP_GROUP winpr_CreateThreadpoolCleanupGroup(void) { PTP_CLEANUP_GROUP cleanupGroup = NULL; #ifdef _WIN32 InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL); + if (pCreateThreadpoolCleanupGroup) return pCreateThreadpoolCleanupGroup(); -#endif - cleanupGroup = (PTP_CLEANUP_GROUP) malloc(sizeof(TP_CLEANUP_GROUP)); + return cleanupGroup; +#else + cleanupGroup = (PTP_CLEANUP_GROUP) calloc(1, sizeof(TP_CLEANUP_GROUP)); + + if (!cleanupGroup) + return NULL; + + cleanupGroup->groups = ArrayList_New(FALSE); + + if (!cleanupGroup->groups) + { + free(cleanupGroup); + return NULL; + } + + return cleanupGroup; +#endif } -VOID winpr_CloseThreadpoolCleanupGroupMembers(PTP_CLEANUP_GROUP ptpcg, BOOL fCancelPendingCallbacks, PVOID pvCleanupContext) +VOID winpr_SetThreadpoolCallbackCleanupGroup(PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, + PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng) +{ + pcbe->CleanupGroup = ptpcg; + pcbe->CleanupGroupCancelCallback = pfng; +#ifndef _WIN32 + pcbe->CleanupGroup->env = pcbe; +#endif +} + +VOID winpr_CloseThreadpoolCleanupGroupMembers(PTP_CLEANUP_GROUP ptpcg, BOOL fCancelPendingCallbacks, + PVOID pvCleanupContext) { #ifdef _WIN32 InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL); + if (pCloseThreadpoolCleanupGroupMembers) { pCloseThreadpoolCleanupGroupMembers(ptpcg, fCancelPendingCallbacks, pvCleanupContext); return; } + +#else + + while (ArrayList_Count(ptpcg->groups) > 0) + { + PTP_WORK work = ArrayList_GetItem(ptpcg->groups, 0); + winpr_CloseThreadpoolWork(work); + } + #endif - /* No default implementation */ } VOID winpr_CloseThreadpoolCleanupGroup(PTP_CLEANUP_GROUP ptpcg) { #ifdef _WIN32 InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL); + if (pCloseThreadpoolCleanupGroup) { pCloseThreadpoolCleanupGroup(ptpcg); return; } -#endif + +#else + + if (ptpcg && ptpcg->groups) + ArrayList_Free(ptpcg->groups); + + if (ptpcg && ptpcg->env) + ptpcg->env->CleanupGroup = NULL; + free(ptpcg); +#endif } #endif /* WINPR_THREAD_POOL defined */ diff --git a/winpr/libwinpr/pool/pool.c b/winpr/libwinpr/pool/pool.c index 9efa781..cb8e15c 100644 --- a/winpr/libwinpr/pool/pool.c +++ b/winpr/libwinpr/pool/pool.c @@ -60,7 +60,7 @@ static TP_POOL DEFAULT_POOL = NULL, /* wCountdownEvent* WorkComplete */ }; -static void* thread_pool_work_func(void* arg) +static DWORD WINAPI thread_pool_work_func(LPVOID arg) { DWORD status; PTP_POOL pool; @@ -95,7 +95,7 @@ static void* thread_pool_work_func(void* arg) } ExitThread(0); - return NULL; + return 0; } static void threads_close(void *thread) @@ -132,7 +132,7 @@ static BOOL InitializeThreadpool(PTP_POOL pool) for (index = 0; index < 4; index++) { if (!(thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) thread_pool_work_func, + thread_pool_work_func, (void*) pool, 0, NULL))) { goto fail_create_threads; @@ -237,7 +237,7 @@ BOOL winpr_SetThreadpoolThreadMinimum(PTP_POOL ptpp, DWORD cthrdMic) while (ArrayList_Count(ptpp->Threads) < ptpp->Minimum) { if (!(thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) thread_pool_work_func, + thread_pool_work_func, (void*) ptpp, 0, NULL))) { return FALSE; diff --git a/winpr/libwinpr/pool/pool.h b/winpr/libwinpr/pool/pool.h index e84635f..6bf7153 100644 --- a/winpr/libwinpr/pool/pool.h +++ b/winpr/libwinpr/pool/pool.h @@ -64,10 +64,15 @@ struct _TP_IO struct _TP_CLEANUP_GROUP { +#ifndef _WIN32 + wArrayList* groups; + PTP_CALLBACK_ENVIRON env; +#else void* dummy; +#endif }; -PTP_POOL GetDefaultThreadpool(); +PTP_POOL GetDefaultThreadpool(void); #endif /* WINPR_POOL_PRIVATE_H */ diff --git a/winpr/libwinpr/pool/test/TestPoolWork.c b/winpr/libwinpr/pool/test/TestPoolWork.c index fee5833..74ef711 100644 --- a/winpr/libwinpr/pool/test/TestPoolWork.c +++ b/winpr/libwinpr/pool/test/TestPoolWork.c @@ -5,15 +5,14 @@ static LONG count = 0; -void CALLBACK test_WorkCallback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) +static void CALLBACK test_WorkCallback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) { int index; BYTE a[1024]; BYTE b[1024]; BYTE c[1024]; - printf("Hello %s: %03"PRId32" (thread: 0x%08"PRIX32")\n", (char*) context, - InterlockedIncrement(&count), GetCurrentThreadId()); + InterlockedIncrement(&count), GetCurrentThreadId()); for (index = 0; index < 100; index++) { @@ -27,22 +26,17 @@ void CALLBACK test_WorkCallback(PTP_CALLBACK_INSTANCE instance, void* context, P } } -int TestPoolWork(int argc, char* argv[]) +static BOOL test1(void) { int index; - PTP_POOL pool; PTP_WORK work; - PTP_CLEANUP_GROUP cleanupGroup; - TP_CALLBACK_ENVIRON environment; - printf("Global Thread Pool\n"); - - work = CreateThreadpoolWork((PTP_WORK_CALLBACK) test_WorkCallback, "world", NULL); + work = CreateThreadpoolWork(test_WorkCallback, "world", NULL); if (!work) { printf("CreateThreadpoolWork failure\n"); - return -1; + return FALSE; } /** @@ -55,66 +49,86 @@ int TestPoolWork(int argc, char* argv[]) WaitForThreadpoolWorkCallbacks(work, FALSE); CloseThreadpoolWork(work); + return TRUE; +} +static BOOL test2(void) +{ + BOOL rc = FALSE; + int index; + PTP_POOL pool; + PTP_WORK work; + PTP_CLEANUP_GROUP cleanupGroup = NULL; + TP_CALLBACK_ENVIRON environment; printf("Private Thread Pool\n"); if (!(pool = CreateThreadpool(NULL))) { printf("CreateThreadpool failure\n"); - return -1; + return FALSE; } if (!SetThreadpoolThreadMinimum(pool, 4)) { printf("SetThreadpoolThreadMinimum failure\n"); - return -1; + goto fail; } SetThreadpoolThreadMaximum(pool, 8); - InitializeThreadpoolEnvironment(&environment); SetThreadpoolCallbackPool(&environment, pool); - cleanupGroup = CreateThreadpoolCleanupGroup(); if (!cleanupGroup) { printf("CreateThreadpoolCleanupGroup failure\n"); - return -1; + goto fail; } SetThreadpoolCallbackCleanupGroup(&environment, cleanupGroup, NULL); - - work = CreateThreadpoolWork((PTP_WORK_CALLBACK) test_WorkCallback, "world", &environment); + work = CreateThreadpoolWork(test_WorkCallback, "world", &environment); if (!work) { printf("CreateThreadpoolWork failure\n"); - return -1; + goto fail; } for (index = 0; index < 10; index++) SubmitThreadpoolWork(work); WaitForThreadpoolWorkCallbacks(work, FALSE); + rc = TRUE; +fail: - CloseThreadpoolCleanupGroupMembers(cleanupGroup, TRUE, NULL); - - CloseThreadpoolCleanupGroup(cleanupGroup); - - DestroyThreadpoolEnvironment(&environment); - - /** - * See Remarks at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682043(v=vs.85).aspx - * If there is a cleanup group associated with the work object, - * it is not necessary to call CloseThreadpoolWork ! - * calling the CloseThreadpoolCleanupGroupMembers function releases the work, wait, - * and timer objects associated with the cleanup group. - */ - - /* CloseThreadpoolWork(work); // this would segfault, see comment above. */ + if (cleanupGroup) + { + CloseThreadpoolCleanupGroupMembers(cleanupGroup, TRUE, NULL); + CloseThreadpoolCleanupGroup(cleanupGroup); + DestroyThreadpoolEnvironment(&environment); + /** + * See Remarks at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682043(v=vs.85).aspx + * If there is a cleanup group associated with the work object, + * it is not necessary to call CloseThreadpoolWork ! + * calling the CloseThreadpoolCleanupGroupMembers function releases the work, wait, + * and timer objects associated with the cleanup group. + */ +#if 0 + CloseThreadpoolWork(work); // this would segfault, see comment above. */ +#endif + } CloseThreadpool(pool); + return rc; +} + +int TestPoolWork(int argc, char* argv[]) +{ + if (!test1()) + return -1; + + if (!test2()) + return -1; return 0; } diff --git a/winpr/libwinpr/pool/work.c b/winpr/libwinpr/pool/work.c index f388f4a..2cf53b4 100644 --- a/winpr/libwinpr/pool/work.c +++ b/winpr/libwinpr/pool/work.c @@ -33,15 +33,18 @@ #ifdef _WIN32 static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT; -static PTP_WORK(WINAPI* pCreateThreadpoolWork)(PTP_WORK_CALLBACK pfnwk, PVOID pv, PTP_CALLBACK_ENVIRON pcbe); +static PTP_WORK(WINAPI* pCreateThreadpoolWork)(PTP_WORK_CALLBACK pfnwk, PVOID pv, + PTP_CALLBACK_ENVIRON pcbe); static VOID (WINAPI* pCloseThreadpoolWork)(PTP_WORK pwk); static VOID (WINAPI* pSubmitThreadpoolWork)(PTP_WORK pwk); -static BOOL (WINAPI* pTrySubmitThreadpoolCallback)(PTP_SIMPLE_CALLBACK pfns, PVOID pv, PTP_CALLBACK_ENVIRON pcbe); +static BOOL (WINAPI* pTrySubmitThreadpoolCallback)(PTP_SIMPLE_CALLBACK pfns, PVOID pv, + PTP_CALLBACK_ENVIRON pcbe); static VOID (WINAPI* pWaitForThreadpoolWorkCallbacks)(PTP_WORK pwk, BOOL fCancelPendingCallbacks); -static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context) +static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID* context) { HMODULE kernel32 = LoadLibraryA("kernel32.dll"); + if (kernel32) { pCreateThreadpoolWork = (void*)GetProcAddress(kernel32, "CreateThreadpoolWork"); @@ -50,6 +53,7 @@ static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context) pTrySubmitThreadpoolCallback = (void*)GetProcAddress(kernel32, "TrySubmitThreadpoolCallback"); pWaitForThreadpoolWorkCallbacks = (void*)GetProcAddress(kernel32, "WaitForThreadpoolWorkCallbacks"); } + return TRUE; } #endif @@ -71,10 +75,12 @@ PTP_WORK winpr_CreateThreadpoolWork(PTP_WORK_CALLBACK pfnwk, PVOID pv, PTP_CALLB PTP_WORK work = NULL; #ifdef _WIN32 InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL); + if (pCreateThreadpoolWork) return pCreateThreadpoolWork(pfnwk, pv, pcbe); + #endif - work = (PTP_WORK) malloc(sizeof(TP_WORK)); + work = (PTP_WORK) calloc(1, sizeof(TP_WORK)); if (work) { @@ -83,9 +89,16 @@ PTP_WORK winpr_CreateThreadpoolWork(PTP_WORK_CALLBACK pfnwk, PVOID pv, PTP_CALLB pcbe = &DEFAULT_CALLBACK_ENVIRONMENT; pcbe->Pool = GetDefaultThreadpool(); } + work->CallbackEnvironment = pcbe; work->WorkCallback = pfnwk; work->CallbackParameter = pv; +#ifndef _WIN32 + + if (pcbe->CleanupGroup) + ArrayList_Add(pcbe->CleanupGroup->groups, work); + +#endif } return work; @@ -95,11 +108,18 @@ VOID winpr_CloseThreadpoolWork(PTP_WORK pwk) { #ifdef _WIN32 InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL); + if (pCloseThreadpoolWork) { pCloseThreadpoolWork(pwk); return; } + +#else + + if (pwk->CallbackEnvironment->CleanupGroup) + ArrayList_Remove(pwk->CallbackEnvironment->CleanupGroup->groups, pwk); + #endif free(pwk); } @@ -110,14 +130,16 @@ VOID winpr_SubmitThreadpoolWork(PTP_WORK pwk) PTP_CALLBACK_INSTANCE callbackInstance; #ifdef _WIN32 InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL); + if (pSubmitThreadpoolWork) { pSubmitThreadpoolWork(pwk); return; } + #endif pool = pwk->CallbackEnvironment->Pool; - callbackInstance = (PTP_CALLBACK_INSTANCE) malloc(sizeof(TP_CALLBACK_INSTANCE)); + callbackInstance = (PTP_CALLBACK_INSTANCE) calloc(1, sizeof(TP_CALLBACK_INSTANCE)); if (callbackInstance) { @@ -127,12 +149,15 @@ VOID winpr_SubmitThreadpoolWork(PTP_WORK pwk) } } -BOOL winpr_TrySubmitThreadpoolCallback(PTP_SIMPLE_CALLBACK pfns, PVOID pv, PTP_CALLBACK_ENVIRON pcbe) +BOOL winpr_TrySubmitThreadpoolCallback(PTP_SIMPLE_CALLBACK pfns, PVOID pv, + PTP_CALLBACK_ENVIRON pcbe) { #ifdef _WIN32 InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL); + if (pTrySubmitThreadpoolCallback) return pTrySubmitThreadpoolCallback(pfns, pv, pcbe); + #endif WLog_ERR(TAG, "TrySubmitThreadpoolCallback is not implemented"); return FALSE; @@ -144,11 +169,13 @@ VOID winpr_WaitForThreadpoolWorkCallbacks(PTP_WORK pwk, BOOL fCancelPendingCallb PTP_POOL pool; #ifdef _WIN32 InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL); + if (pWaitForThreadpoolWorkCallbacks) { pWaitForThreadpoolWorkCallbacks(pwk, fCancelPendingCallbacks); return; } + #endif pool = pwk->CallbackEnvironment->Pool; event = CountdownEvent_WaitHandle(pool->WorkComplete); diff --git a/winpr/libwinpr/registry/registry_reg.c b/winpr/libwinpr/registry/registry_reg.c index afc6739..498a449 100644 --- a/winpr/libwinpr/registry/registry_reg.c +++ b/winpr/libwinpr/registry/registry_reg.c @@ -21,10 +21,12 @@ #include "config.h" #endif +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <winpr/wtypes.h> #include <winpr/crt.h> #include "registry_reg.h" @@ -76,10 +78,10 @@ static char* REG_DATA_TYPE_STRINGS[] = static void reg_load_start(Reg* reg) { - long int file_size; - fseek(reg->fp, 0, SEEK_END); - file_size = ftell(reg->fp); - fseek(reg->fp, 0, SEEK_SET); + INT64 file_size; + _fseeki64(reg->fp, 0, SEEK_END); + file_size = _ftelli64(reg->fp); + _fseeki64(reg->fp, 0, SEEK_SET); reg->line = NULL; reg->next_line = NULL; reg->buffer = NULL; @@ -88,6 +90,7 @@ static void reg_load_start(Reg* reg) return; reg->buffer = (char*) malloc(file_size + 2); + if (!reg->buffer) return ; @@ -137,16 +140,20 @@ static RegVal* reg_load_value(Reg* reg, RegKey* key) data = p[3] + 1; length = p[1] - p[0]; name = (char*) malloc(length + 1); + if (!name) return NULL; + memcpy(name, p[0], length); name[length] = '\0'; value = (RegVal*) malloc(sizeof(RegVal)); + if (!value) { free(name); return NULL; } + value->name = name; value->type = REG_NONE; value->next = value->prev = NULL; @@ -162,13 +169,25 @@ static RegVal* reg_load_value(Reg* reg, RegKey* key) if (value->type == REG_DWORD) { - value->data.dword = strtoul(data, NULL, 16); + unsigned long val; + errno = 0; + val = strtoul(data, NULL, 16); + + if ((errno != 0) || (val > UINT32_MAX)) + { + free(value); + free(name); + return NULL; + } + + value->data.dword = val; } else if (value->type == REG_SZ) { p[4] = strchr(data, '"'); p[4][0] = '\0'; value->data.string = _strdup(data); + if (!value->data.string) { free(value); @@ -232,8 +251,10 @@ static void reg_insert_key(Reg* reg, RegKey* key, RegKey* subkey) char* save; int length; path = _strdup(subkey->name); + if (!path) return; + name = strtok_s(path, "\\", &save); while (name != NULL) @@ -243,6 +264,7 @@ static void reg_insert_key(Reg* reg, RegKey* key, RegKey* subkey) length = strlen(name); name += length + 1; subkey->subname = _strdup(name); + /* TODO: free allocated memory in error case */ if (!subkey->subname) { @@ -266,17 +288,21 @@ static RegKey* reg_load_key(Reg* reg, RegKey* key) p[0] = reg->line + 1; p[1] = strrchr(p[0], ']'); subkey = (RegKey*) malloc(sizeof(RegKey)); + if (!subkey) return NULL; + subkey->values = NULL; subkey->prev = subkey->next = NULL; length = p[1] - p[0]; subkey->name = (char*) malloc(length + 1); + if (!subkey->name) { free(subkey); return NULL; } + memcpy(subkey->name, p[0], length); subkey->name[length] = '\0'; @@ -392,39 +418,40 @@ Reg* reg_open(BOOL read_only) if (!reg) return NULL; - reg->read_only = read_only; - reg->filename = WINPR_HKLM_HIVE; + reg->read_only = read_only; + reg->filename = WINPR_HKLM_HIVE; - if (reg->read_only) - { - reg->fp = fopen(reg->filename, "r"); - } - else - { - reg->fp = fopen(reg->filename, "r+"); + if (reg->read_only) + { + reg->fp = fopen(reg->filename, "r"); + } + else + { + reg->fp = fopen(reg->filename, "r+"); - if (!reg->fp) - reg->fp = fopen(reg->filename, "w+"); - } + if (!reg->fp) + reg->fp = fopen(reg->filename, "w+"); + } - if (!reg->fp) - { - free(reg); - return NULL; - } + if (!reg->fp) + { + free(reg); + return NULL; + } + + reg->root_key = (RegKey*) malloc(sizeof(RegKey)); - reg->root_key = (RegKey*) malloc(sizeof(RegKey)); if (!reg->root_key) { fclose(reg->fp); free(reg); return NULL; } - reg->root_key->values = NULL; - reg->root_key->subkeys = NULL; - reg->root_key->name = "HKEY_LOCAL_MACHINE"; - reg_load(reg); + reg->root_key->values = NULL; + reg->root_key->subkeys = NULL; + reg->root_key->name = "HKEY_LOCAL_MACHINE"; + reg_load(reg); return reg; } diff --git a/winpr/libwinpr/smartcard/smartcard.c b/winpr/libwinpr/smartcard/smartcard.c index 2d2a8e5..6f9acb8 100644 --- a/winpr/libwinpr/smartcard/smartcard.c +++ b/winpr/libwinpr/smartcard/smartcard.c @@ -24,14 +24,33 @@ #include <winpr/crt.h> #include <winpr/library.h> #include <winpr/smartcard.h> +#include <winpr/synch.h> #include "smartcard.h" #include "smartcard_inspect.h" -static BOOL g_Initialized = FALSE; +static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT; static PSCardApiFunctionTable g_SCardApi = NULL; +#define SCARDAPI_STUB_CALL_LONG(_name, ...) \ + InitOnceExecuteOnce(&g_Initialized, InitializeSCardApiStubs, NULL, NULL); \ + if (!g_SCardApi || !g_SCardApi->pfn ## _name) \ + return SCARD_E_NO_SERVICE; \ + return g_SCardApi->pfn ## _name ( __VA_ARGS__ ) + +#define SCARDAPI_STUB_CALL_HANDLE(_name, ...) \ + InitOnceExecuteOnce(&g_Initialized, InitializeSCardApiStubs, NULL, NULL); \ + if (!g_SCardApi || !g_SCardApi->pfn ## _name) \ + return NULL; \ + return g_SCardApi->pfn ## _name ( __VA_ARGS__ ) + +#define SCARDAPI_STUB_CALL_VOID(_name, ...) \ + InitOnceExecuteOnce(&g_Initialized, InitializeSCardApiStubs, NULL, NULL); \ + if (!g_SCardApi || !g_SCardApi->pfn ## _name) \ + return; \ + g_SCardApi->pfn ## _name ( __VA_ARGS__ ) + /** * Standard Windows Smart Card API */ @@ -40,6 +59,25 @@ const SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 }; const SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 }; const SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 }; +static BOOL CALLBACK InitializeSCardApiStubs(PINIT_ONCE once, PVOID param, PVOID* context) +{ +#ifndef _WIN32 + + if (PCSC_InitializeSCardApi() >= 0) + g_SCardApi = PCSC_GetSCardApiFunctionTable(); + +#else + + if (WinSCard_InitializeSCardApi() >= 0) + g_SCardApi = WinSCard_GetSCardApiFunctionTable(); + +#endif +#ifdef WITH_SMARTCARD_INSPECT + g_SCardApi = Inspect_RegisterSCardApi(g_SCardApi); +#endif + return TRUE; +} + WINSCARDAPI LONG WINAPI SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext) { @@ -507,11 +545,6 @@ WINSCARDAPI LONG WINAPI SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent) SCARDAPI_STUB_CALL_LONG(SCardAudit, hContext, dwEvent); } -WINSCARDAPI LONG WINAPI SCardAddReaderName(HANDLE* key, LPSTR readerName) -{ - SCARDAPI_STUB_CALL_LONG(SCardAddReaderName, key, readerName); -} - /** * Extended API */ @@ -1158,26 +1191,3 @@ WINSCARDAPI char* WINAPI SCardGetReaderStateString(DWORD dwReaderState) return szReaderState; } - -void InitializeSCardApiStubs(void) -{ - g_Initialized = TRUE; -#ifndef _WIN32 - - if (PCSC_InitializeSCardApi() >= 0) - { - g_SCardApi = PCSC_GetSCardApiFunctionTable(); - } - -#else - - if (WinSCard_InitializeSCardApi() >= 0) - { - g_SCardApi = WinSCard_GetSCardApiFunctionTable(); - } - -#endif -#ifdef WITH_SMARTCARD_INSPECT - g_SCardApi = Inspect_RegisterSCardApi(g_SCardApi); -#endif -} diff --git a/winpr/libwinpr/smartcard/smartcard.h b/winpr/libwinpr/smartcard/smartcard.h index c0b6d68..a9787de 100644 --- a/winpr/libwinpr/smartcard/smartcard.h +++ b/winpr/libwinpr/smartcard/smartcard.h @@ -22,29 +22,6 @@ #include <winpr/smartcard.h> -#define SCARDAPI_STUB_CALL_LONG(_name, ...) \ - if (!g_Initialized) \ - InitializeSCardApiStubs(); \ - if (!g_SCardApi || !g_SCardApi->pfn ## _name) \ - return SCARD_E_NO_SERVICE; \ - return g_SCardApi->pfn ## _name ( __VA_ARGS__ ) - -#define SCARDAPI_STUB_CALL_HANDLE(_name, ...) \ - if (!g_Initialized) \ - InitializeSCardApiStubs(); \ - if (!g_SCardApi || !g_SCardApi->pfn ## _name) \ - return NULL; \ - return g_SCardApi->pfn ## _name ( __VA_ARGS__ ) - -#define SCARDAPI_STUB_CALL_VOID(_name, ...) \ - if (!g_Initialized) \ - InitializeSCardApiStubs(); \ - if (!g_SCardApi || !g_SCardApi->pfn ## _name) \ - return; \ - g_SCardApi->pfn ## _name ( __VA_ARGS__ ) - -void InitializeSCardApiStubs(void); - #ifndef _WIN32 #include "smartcard_pcsc.h" #else diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index 5a3d7ea..2672e78 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -28,14 +28,14 @@ #include <sys/param.h> #include <sys/sysctl.h> #include <string.h> +#include <ctype.h> +#include <errno.h> #endif #include <stdio.h> #include <stdlib.h> -#include <ctype.h> #include <winpr/crt.h> -#include <winpr/print.h> #include <winpr/synch.h> #include <winpr/library.h> #include <winpr/smartcard.h> @@ -129,13 +129,6 @@ struct _PCSC_SCARDHANDLE SCARDCONTEXT hSharedContext; }; -struct _PCSC_READER -{ - char* namePCSC; - char* nameWinSCard; -}; -typedef struct _PCSC_READER PCSC_READER; - static HMODULE g_PCSCModule = NULL; static PCSCFunctionTable g_PCSC = { 0 }; @@ -151,17 +144,12 @@ static unsigned int OSXVersion = 0; -static wArrayList* g_Readers = NULL; static wListDictionary* g_CardHandles = NULL; static wListDictionary* g_CardContexts = NULL; static wListDictionary* g_MemoryBlocks = NULL; -static wListDictionary* g_ReadersNames = NULL; char SMARTCARD_PNP_NOTIFICATION_A[] = "\\\\?PnP?\\Notification"; -WCHAR SMARTCARD_PNP_NOTIFICATION_W[] = -{ '\\', '\\', '?', 'P', 'n', 'P', '?', '\\', 'N', 'o', 't', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n', '\0' }; - const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT0Pci = { SCARD_PROTOCOL_T0, sizeof(PCSC_SCARD_IO_REQUEST) }; const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(PCSC_SCARD_IO_REQUEST) }; const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardRawPci = { PCSC_SCARD_PROTOCOL_RAW, sizeof(PCSC_SCARD_IO_REQUEST) }; @@ -171,7 +159,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext); WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext); -LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode) +static LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode) { /** * pcsc-lite returns SCARD_E_UNEXPECTED when it @@ -187,7 +175,7 @@ LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode) return errorCode; } -DWORD PCSC_ConvertCardStateToWinSCard(DWORD dwCardState, LONG status) +static DWORD PCSC_ConvertCardStateToWinSCard(DWORD dwCardState, LONG status) { /** * pcsc-lite's SCardStatus returns a bit-field, not an enumerated value. @@ -235,7 +223,7 @@ DWORD PCSC_ConvertCardStateToWinSCard(DWORD dwCardState, LONG status) return SCARD_UNKNOWN; } -DWORD PCSC_ConvertProtocolsToWinSCard(DWORD dwProtocols) +static DWORD PCSC_ConvertProtocolsToWinSCard(DWORD dwProtocols) { /** * pcsc-lite uses a different value for SCARD_PROTOCOL_RAW, @@ -255,7 +243,7 @@ DWORD PCSC_ConvertProtocolsToWinSCard(DWORD dwProtocols) return dwProtocols; } -DWORD PCSC_ConvertProtocolsFromWinSCard(DWORD dwProtocols) +static DWORD PCSC_ConvertProtocolsFromWinSCard(DWORD dwProtocols) { /** * pcsc-lite uses a different value for SCARD_PROTOCOL_RAW, @@ -280,16 +268,7 @@ DWORD PCSC_ConvertProtocolsFromWinSCard(DWORD dwProtocols) return dwProtocols; } -void PCSC_ReaderAliasFree(PCSC_READER* reader) -{ - if (!reader) - return; - - free(reader->namePCSC); - free(reader->nameWinSCard); -} - -PCSC_SCARDCONTEXT* PCSC_GetCardContextData(SCARDCONTEXT hContext) +static PCSC_SCARDCONTEXT* PCSC_GetCardContextData(SCARDCONTEXT hContext) { PCSC_SCARDCONTEXT* pContext; @@ -304,7 +283,7 @@ PCSC_SCARDCONTEXT* PCSC_GetCardContextData(SCARDCONTEXT hContext) return pContext; } -PCSC_SCARDCONTEXT* PCSC_EstablishCardContext(SCARDCONTEXT hContext) +static PCSC_SCARDCONTEXT* PCSC_EstablishCardContext(SCARDCONTEXT hContext) { PCSC_SCARDCONTEXT* pContext; pContext = (PCSC_SCARDCONTEXT*) calloc(1, sizeof(PCSC_SCARDCONTEXT)); @@ -325,16 +304,6 @@ PCSC_SCARDCONTEXT* PCSC_EstablishCardContext(SCARDCONTEXT hContext) goto errors; } - if (!g_Readers) - { - g_Readers = ArrayList_New(TRUE); - - if (!g_Readers) - goto errors; - - ArrayList_Object(g_Readers)->fnObjectFree = (OBJECT_FREE_FN) PCSC_ReaderAliasFree; - } - if (!ListDictionary_Add(g_CardContexts, (void*) hContext, (void*) pContext)) goto errors; @@ -346,7 +315,7 @@ error_spinlock: return NULL; } -void PCSC_ReleaseCardContext(SCARDCONTEXT hContext) +static void PCSC_ReleaseCardContext(SCARDCONTEXT hContext) { PCSC_SCARDCONTEXT* pContext; pContext = PCSC_GetCardContextData(hContext); @@ -366,7 +335,7 @@ void PCSC_ReleaseCardContext(SCARDCONTEXT hContext) ListDictionary_Remove(g_CardContexts, (void*) hContext); } -BOOL PCSC_LockCardContext(SCARDCONTEXT hContext) +static BOOL PCSC_LockCardContext(SCARDCONTEXT hContext) { PCSC_SCARDCONTEXT* pContext; pContext = PCSC_GetCardContextData(hContext); @@ -381,7 +350,7 @@ BOOL PCSC_LockCardContext(SCARDCONTEXT hContext) return TRUE; } -BOOL PCSC_UnlockCardContext(SCARDCONTEXT hContext) +static BOOL PCSC_UnlockCardContext(SCARDCONTEXT hContext) { PCSC_SCARDCONTEXT* pContext; pContext = PCSC_GetCardContextData(hContext); @@ -396,7 +365,7 @@ BOOL PCSC_UnlockCardContext(SCARDCONTEXT hContext) return TRUE; } -PCSC_SCARDHANDLE* PCSC_GetCardHandleData(SCARDHANDLE hCard) +static PCSC_SCARDHANDLE* PCSC_GetCardHandleData(SCARDHANDLE hCard) { PCSC_SCARDHANDLE* pCard; @@ -411,7 +380,7 @@ PCSC_SCARDHANDLE* PCSC_GetCardHandleData(SCARDHANDLE hCard) return pCard; } -SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard) +static SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard) { PCSC_SCARDHANDLE* pCard; pCard = PCSC_GetCardHandleData(hCard); @@ -422,7 +391,7 @@ SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard) return pCard->hSharedContext; } -BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared) +static BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared) { BOOL status = TRUE; PCSC_SCARDHANDLE* pCard = NULL; @@ -476,7 +445,7 @@ BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL share return status; } -BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard) +static BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard) { PCSC_SCARDHANDLE* pCard = NULL; PCSC_SCARDCONTEXT* pContext = NULL; @@ -524,7 +493,7 @@ BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard) return TRUE; } -PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDHANDLE hCard) +static PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDHANDLE hCard) { PCSC_SCARDHANDLE* pCard; PCSC_SCARDCONTEXT* pContext; @@ -561,7 +530,7 @@ error: return NULL; } -void PCSC_DisconnectCardHandle(SCARDHANDLE hCard) +static void PCSC_DisconnectCardHandle(SCARDHANDLE hCard) { PCSC_SCARDHANDLE* pCard; PCSC_SCARDCONTEXT* pContext; @@ -587,314 +556,7 @@ void PCSC_DisconnectCardHandle(SCARDHANDLE hCard) pContext->dwCardHandleCount--; } -char* PCSC_GetReaderNameFromAlias(char* nameWinSCard) -{ - int index; - int count; - PCSC_READER* reader; - char* namePCSC = NULL; - ArrayList_Lock(g_Readers); - count = ArrayList_Count(g_Readers); - - for (index = 0; index < count; index++) - { - reader = ArrayList_GetItem(g_Readers, index); - - if (strcmp(nameWinSCard, reader->nameWinSCard) == 0) - { - namePCSC = reader->namePCSC; - break; - } - } - - ArrayList_Unlock(g_Readers); - return namePCSC; -} - -BOOL PCSC_AddReaderNameAlias(char* namePCSC, char* nameWinSCard) -{ - PCSC_READER* reader; - - if (PCSC_GetReaderNameFromAlias(nameWinSCard)) - return TRUE; - - reader = (PCSC_READER*) calloc(1, sizeof(PCSC_READER)); - - if (!reader) - return FALSE; - - reader->namePCSC = _strdup(namePCSC); - - if (!reader->namePCSC) - goto error_namePSC; - - reader->nameWinSCard = _strdup(nameWinSCard); - - if (!reader->nameWinSCard) - goto error_nameWinSCard; - - if (ArrayList_Add(g_Readers, reader) < 0) - goto error_add; - - return TRUE; -error_add: - free(reader->nameWinSCard); -error_nameWinSCard: - free(reader->namePCSC); -error_namePSC: - free(reader); - return FALSE; -} - -char* PCSC_ConvertReaderNameToWinSCard(const char* name) -{ - int size; - int length; - int ctoken; - int ntokens; - char* p, *q; - char* tokens[64][2]; - char* nameWinSCard; - - /** - * pcsc-lite reader name format: - * name [interface] (serial) index slot - * - * Athena IDProtect Key v2 [Main Interface] 00 00 - * - * name: Athena IDProtect Key v2 - * interface: Main Interface - * serial: N/A - * index: 00 - * slot: 00 - * - * Athena ASE IIIe 00 00 - * - * name: Athena ASE IIIe - * interface: N/A - * serial: N/A - * index: 00 - * slot: 00 - * - * Athena ASE IIIe [CCID Bulk Interface] 00 00 - * - * name: Athena ASE IIIe - * interface: CCID Bulk Interface - * serial: N/A - * index: 00 - * slot: 00 - * - * Gemalto PC Twin Reader (944B4BF1) 00 00 - * - * name: Gemalto PC Twin Reader - * interface: N/A - * serial: 944B4BF1 - * index: 00 - * slot: 00 - * - * the serial component is optional - * the index is a two digit zero-padded integer - * the slot is a two digit zero-padded integer - */ - if (!name) - return NULL; - - memset(tokens, 0, sizeof(tokens)); - length = strlen(name); - - if (length < 10) - return NULL; - - ntokens = 0; - p = q = (char*) name; - - while (*p) - { - if (*p == ' ') - { - tokens[ntokens][0] = q; - tokens[ntokens][1] = p; - q = p + 1; - ntokens++; - } - - p++; - } - - tokens[ntokens][0] = q; - tokens[ntokens][1] = p; - ntokens++; - - if (ntokens < 2) - return NULL; - - ctoken = ntokens - 1; - p = tokens[0][0]; - q = tokens[ctoken][1]; - length = (q - p); - size = length + 16; - nameWinSCard = (char*) malloc(size); - - if (!nameWinSCard) - return NULL; - - sprintf_s(nameWinSCard, size, "%.*s", length, p); - return nameWinSCard; -} - -char* PCSC_GetReaderAliasFromName(char* namePCSC) -{ - char* nameWinSCard = NULL; - nameWinSCard = PCSC_ConvertReaderNameToWinSCard(namePCSC); - - if (nameWinSCard) - PCSC_AddReaderNameAlias(namePCSC, nameWinSCard); - - return nameWinSCard; -} - -int PCSC_RedirectReader(char* readerName) -{ - char* name; - ULONG_PTR* readers; - int i, nbReaders; - nbReaders = ListDictionary_GetKeys(g_ReadersNames, &readers); - - for (i = 0; i < nbReaders; i++) - { - name = ListDictionary_GetItemValue(g_ReadersNames, (void*) readers[i]); - - if (name) - { - if (strcmp(name, "") == 0) - { - return 1; - } - - if (strncmp(readerName, name, strlen(readerName)) == 0) - { - return 1; - } - } - else - { - return 2; - } - } - - return 0; -} - -char* PCSC_ConvertReaderNamesToWinSCard(const char* names, LPDWORD pcchReaders) -{ - int ret = 0; - int length; - char* p, *q; - DWORD cchReaders; - char* nameWinSCard; - char* namesWinSCard; - BOOL endReaderName = FALSE; - BOOL allReaders = FALSE; - p = (char*) names; - cchReaders = *pcchReaders; - namesWinSCard = (char*) calloc(cchReaders, 2); - - if (!namesWinSCard) - return NULL; - - q = namesWinSCard; - p = (char*) names; - - while ((p - names) < cchReaders) - { - nameWinSCard = PCSC_GetReaderAliasFromName(p); - - if (nameWinSCard) - { - length = strlen(nameWinSCard); - ret = PCSC_RedirectReader(nameWinSCard); - - if (ret == 1) - { - CopyMemory(q, nameWinSCard, length); - endReaderName = TRUE; - } - else if (ret == 2) - { - CopyMemory(q, nameWinSCard, length); - allReaders = TRUE; - } - - free(nameWinSCard); - } - else - { - length = strlen(p); - CopyMemory(q, p, length); - } - - if (endReaderName) - { - q += length; - *q = '\0'; - q++; - endReaderName = FALSE; - } - else if (allReaders) - { - q += length; - *q = '\0'; - q++; - } - - p += strlen(p) + 1; - } - - *q = '\0'; - q++; - *pcchReaders = (DWORD)(q - namesWinSCard); - return namesWinSCard; -} - -char* PCSC_ConvertReaderNamesToPCSC(const char* names, LPDWORD pcchReaders) -{ - int length; - char* p, *q; - char* namePCSC; - char* namesPCSC; - DWORD cchReaders; - p = (char*) names; - cchReaders = *pcchReaders; - namesPCSC = (char*) calloc(cchReaders, 2); - - if (!namesPCSC) - return NULL; - - q = namesPCSC; - p = (char*) names; - - while ((p - names) < cchReaders) - { - namePCSC = PCSC_GetReaderNameFromAlias(p); - - if (!namePCSC) - namePCSC = p; - - length = strlen(namePCSC); - CopyMemory(q, namePCSC, length); - q += length; - *q = '\0'; - q++; - p += strlen(p) + 1; - } - - *q = '\0'; - q++; - *pcchReaders = (DWORD)(q - namesPCSC); - return namesPCSC; -} - -BOOL PCSC_AddMemoryBlock(SCARDCONTEXT hContext, void* pvMem) +static BOOL PCSC_AddMemoryBlock(SCARDCONTEXT hContext, void* pvMem) { if (!g_MemoryBlocks) { @@ -907,31 +569,16 @@ BOOL PCSC_AddMemoryBlock(SCARDCONTEXT hContext, void* pvMem) return ListDictionary_Add(g_MemoryBlocks, pvMem, (void*) hContext); } -void* PCSC_RemoveMemoryBlock(SCARDCONTEXT hContext, void* pvMem) +static void* PCSC_RemoveMemoryBlock(SCARDCONTEXT hContext, void* pvMem) { + WINPR_UNUSED(hContext); + if (!g_MemoryBlocks) return NULL; return ListDictionary_Remove(g_MemoryBlocks, pvMem); } -void* PCSC_SCardAllocMemory(SCARDCONTEXT hContext, size_t size) -{ - void* pvMem; - pvMem = malloc(size); - - if (!pvMem) - return NULL; - - if (!PCSC_AddMemoryBlock(hContext, pvMem)) - { - free(pvMem); - return NULL; - } - - return pvMem; -} - /** * Standard Windows Smart Card API (PCSC) */ @@ -939,14 +586,14 @@ void* PCSC_SCardAllocMemory(SCARDCONTEXT hContext, size_t size) WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext) { + WINPR_UNUSED(dwScope); /* SCARD_SCOPE_SYSTEM is the only scope supported by pcsc-lite */ LONG status = SCARD_S_SUCCESS; - PCSC_DWORD pcsc_dwScope = (PCSC_DWORD) dwScope; if (!g_PCSC.pfnSCardEstablishContext) return SCARD_E_NO_SERVICE; - pcsc_dwScope = SCARD_SCOPE_SYSTEM; /* this is the only scope supported by pcsc-lite */ - status = (LONG) g_PCSC.pfnSCardEstablishContext(pcsc_dwScope, pvReserved1, pvReserved2, phContext); + status = (LONG) g_PCSC.pfnSCardEstablishContext(SCARD_SCOPE_SYSTEM, pvReserved1, pvReserved2, + phContext); status = PCSC_MapErrorCodeToWinSCard(status); return status; } @@ -954,7 +601,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope, WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext) { - LONG status = SCARD_S_SUCCESS; + LONG status; status = PCSC_SCardEstablishContext_Internal(dwScope, pvReserved1, pvReserved2, phContext); if (status == SCARD_S_SUCCESS) @@ -1008,7 +655,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroups_Internal(SCARDCONTEXT hContex LPSTR mszGroups, LPDWORD pcchGroups) { LONG status = SCARD_S_SUCCESS; - char* mszGroupsWinSCard = NULL; BOOL pcchGroupsAlloc = FALSE; LPSTR* pMszGroups = (LPSTR*) mszGroups; PCSC_DWORD pcsc_cchGroups = 0; @@ -1051,19 +697,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaderGroups_Internal(SCARDCONTEXT hContex status = PCSC_MapErrorCodeToWinSCard(status); *pcchGroups = (DWORD) pcsc_cchGroups; - - if (status == SCARD_S_SUCCESS) - { - mszGroupsWinSCard = PCSC_ConvertReaderNamesToWinSCard(*pMszGroups, pcchGroups); - - if (mszGroupsWinSCard) - { - PCSC_SCardFreeMemory_Internal(hContext, *pMszGroups); - *pMszGroups = mszGroupsWinSCard; - PCSC_AddMemoryBlock(hContext, *pMszGroups); - } - } - return status; } @@ -1118,7 +751,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders) { LONG status = SCARD_S_SUCCESS; - char* mszReadersWinSCard = NULL; BOOL pcchReadersAlloc = FALSE; LPSTR* pMszReaders = (LPSTR*) mszReaders; PCSC_DWORD pcsc_cchReaders = 0; @@ -1163,19 +795,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext, status = PCSC_MapErrorCodeToWinSCard(status); *pcchReaders = (DWORD) pcsc_cchReaders; - - if (status == SCARD_S_SUCCESS) - { - mszReadersWinSCard = PCSC_ConvertReaderNamesToWinSCard(*pMszReaders, pcchReaders); - - if (mszReadersWinSCard) - { - PCSC_SCardFreeMemory_Internal(hContext, *pMszReaders); - *pMszReaders = mszReadersWinSCard; - PCSC_AddMemoryBlock(hContext, *pMszReaders); - } - } - return status; } @@ -1533,8 +1152,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext { int i, j; int* map; - DWORD dwEventState; - BOOL stateChanged = FALSE; PCSC_DWORD cMappedReaders; PCSC_SCARD_READERSTATE* states; LONG status = SCARD_S_SUCCESS; @@ -1579,7 +1196,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext { if (!g_PnP_Notification) { - if (strcmp(rgReaderStates[i].szReader, SMARTCARD_PNP_NOTIFICATION_A) == 0) + if (0 == _stricmp(rgReaderStates[i].szReader, SMARTCARD_PNP_NOTIFICATION_A)) { map[i] = -1; /* unmapped */ continue; @@ -1587,11 +1204,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext } map[i] = j; - states[j].szReader = PCSC_GetReaderNameFromAlias((char*) rgReaderStates[i].szReader); - - if (!states[j].szReader) - states[j].szReader = rgReaderStates[i].szReader; - + states[j].szReader = rgReaderStates[i].szReader; states[j].dwCurrentState = rgReaderStates[i].dwCurrentState; states[j].pvUserData = rgReaderStates[i].pvUserData; states[j].dwEventState = rgReaderStates[i].dwEventState; @@ -1622,37 +1235,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext rgReaderStates[i].dwCurrentState = states[j].dwCurrentState; rgReaderStates[i].cbAtr = states[j].cbAtr; CopyMemory(&(rgReaderStates[i].rgbAtr), &(states[j].rgbAtr), PCSC_MAX_ATR_SIZE); - dwEventState = states[j].dwEventState & ~SCARD_STATE_CHANGED; - - if (dwEventState != rgReaderStates[i].dwCurrentState) - { - rgReaderStates[i].dwEventState = states[j].dwEventState; - - if (dwEventState & SCARD_STATE_PRESENT) - { - if (!(dwEventState & SCARD_STATE_EXCLUSIVE)) - rgReaderStates[i].dwEventState |= SCARD_STATE_INUSE; - } - - stateChanged = TRUE; - } - else - { - rgReaderStates[i].dwEventState = dwEventState; - } - - if (rgReaderStates[i].dwCurrentState & SCARD_STATE_IGNORE) - rgReaderStates[i].dwEventState = SCARD_STATE_IGNORE; + rgReaderStates[i].dwEventState = states[j].dwEventState; } free(map); free(states); - - if ((status == SCARD_S_SUCCESS) && !stateChanged) - status = SCARD_E_TIMEOUT; - else if ((status == SCARD_E_TIMEOUT) && stateChanged) - return SCARD_S_SUCCESS; - return status; } @@ -1742,7 +1329,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) { BOOL shared; - BOOL access; char* szReaderPCSC; LONG status = SCARD_S_SUCCESS; PCSC_SCARDHANDLE* pCard = NULL; @@ -1754,11 +1340,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext, return SCARD_E_NO_SERVICE; shared = (dwShareMode == SCARD_SHARE_DIRECT) ? TRUE : FALSE; - access = PCSC_WaitForCardAccess(hContext, 0, shared); - szReaderPCSC = PCSC_GetReaderNameFromAlias((char*) szReader); - - if (!szReaderPCSC) - szReaderPCSC = (char*) szReader; + PCSC_WaitForCardAccess(hContext, 0, shared); + szReaderPCSC = (char*) szReader; /** * As stated here : https://pcsclite.alioth.debian.org/api/group__API.html#ga4e515829752e0a8dbc4d630696a8d6a5 @@ -1830,7 +1413,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol) { BOOL shared; - BOOL access; LONG status = SCARD_S_SUCCESS; PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode; PCSC_DWORD pcsc_dwPreferredProtocols = 0; @@ -1841,7 +1423,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard, return SCARD_E_NO_SERVICE; shared = (dwShareMode == SCARD_SHARE_DIRECT) ? TRUE : FALSE; - access = PCSC_WaitForCardAccess(0, hCard, shared); + PCSC_WaitForCardAccess(0, hCard, shared); pcsc_dwPreferredProtocols = (PCSC_DWORD) PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols); status = (LONG) g_PCSC.pfnSCardReconnect(hCard, pcsc_dwShareMode, pcsc_dwPreferredProtocols, pcsc_dwInitialization, &pcsc_dwActiveProtocol); @@ -1974,22 +1556,27 @@ WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard, return status; } +/* + * PCSC returns a string but Windows SCardStatus requires the return to be a multi string. + * Therefore extra length checks and additional buffer allocation is required + */ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard, LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, - LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) + LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen, BOOL unicode) { - SCARDCONTEXT hContext; - char* mszReaderNamesWinSCard = NULL; - BOOL pcbAtrLenAlloc = FALSE; - BOOL pcchReaderLenAlloc = FALSE; - LPBYTE* pPbAtr = (LPBYTE*) pbAtr; - LPSTR* pMszReaderNames = (LPSTR*) mszReaderNames; - LONG status = SCARD_S_SUCCESS; PCSC_SCARDHANDLE* pCard = NULL; + SCARDCONTEXT hContext; + LONG status; PCSC_DWORD pcsc_cchReaderLen = 0; + PCSC_DWORD pcsc_cbAtrLen = 0; PCSC_DWORD pcsc_dwState = 0; PCSC_DWORD pcsc_dwProtocol = 0; - PCSC_DWORD pcsc_cbAtrLen = 0; + BOOL allocateReader = FALSE; + BOOL allocateAtr = FALSE; + LPSTR readerNames = mszReaderNames; + LPBYTE atr = pbAtr; + LPSTR tReader = NULL; + LPBYTE tATR = NULL; if (!g_PCSC.pfnSCardStatus) return SCARD_E_NO_SERVICE; @@ -2002,109 +1589,150 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard, PCSC_WaitForCardAccess(0, hCard, pCard->shared); hContext = PCSC_GetCardContextFromHandle(hCard); - if (!hContext || !pcchReaderLen || !pdwState || !pdwProtocol || !pcbAtrLen) + if (!hContext) return SCARD_E_INVALID_VALUE; - if (*pcchReaderLen == SCARD_AUTOALLOCATE) - pcchReaderLenAlloc = TRUE; + status = (LONG) g_PCSC.pfnSCardStatus(hCard, NULL, &pcsc_cchReaderLen, NULL, NULL, NULL, + &pcsc_cbAtrLen); - pcsc_cchReaderLen = pcchReaderLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD) * pcchReaderLen; + if (status != STATUS_SUCCESS) + return PCSC_MapErrorCodeToWinSCard(status); - if (*pcbAtrLen == SCARD_AUTOALLOCATE) - pcbAtrLenAlloc = TRUE; + pcsc_cchReaderLen++; - pcsc_cbAtrLen = pcbAtrLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD) * pcbAtrLen; + if (unicode) + pcsc_cchReaderLen *= 2; - if ((pcchReaderLenAlloc || pcbAtrLenAlloc) && !g_SCardAutoAllocate) + if (pcchReaderLen) { - if (pcchReaderLenAlloc) - pcsc_cchReaderLen = 0; + if (*pcchReaderLen == SCARD_AUTOALLOCATE) + allocateReader = TRUE; + else if (mszReaderNames && (*pcchReaderLen < pcsc_cchReaderLen)) + return SCARD_E_INSUFFICIENT_BUFFER; + else + pcsc_cchReaderLen = *pcchReaderLen; + } - if (pcbAtrLenAlloc) - pcsc_cbAtrLen = 0; + if (pcbAtrLen) + { + if (*pcbAtrLen == SCARD_AUTOALLOCATE) + allocateAtr = TRUE; + else if (pbAtr && (*pcbAtrLen < pcsc_cbAtrLen)) + return SCARD_E_INSUFFICIENT_BUFFER; + else + pcsc_cbAtrLen = *pcbAtrLen; + } - status = (LONG) g_PCSC.pfnSCardStatus(hCard, - (pcchReaderLenAlloc) ? NULL : mszReaderNames, &pcsc_cchReaderLen, - &pcsc_dwState, &pcsc_dwProtocol, - (pcbAtrLenAlloc) ? NULL : pbAtr, &pcsc_cbAtrLen); - - if (status == SCARD_S_SUCCESS) - { - if (pcchReaderLenAlloc) - { + if (allocateReader && pcsc_cchReaderLen > 0 && mszReaderNames) + { #ifdef __MACOSX__ - /** - * Workaround for SCardStatus Bug in MAC OS X Yosemite - */ - if (OSXVersion == 0x10100000) - pcsc_cchReaderLen++; + /** + * Workaround for SCardStatus Bug in MAC OS X Yosemite + */ + if (OSXVersion == 0x10100000) + pcsc_cchReaderLen++; #endif - *pMszReaderNames = (LPSTR) calloc(1, pcsc_cchReaderLen); + tReader = calloc(1, pcsc_cchReaderLen); - if (!*pMszReaderNames) - return SCARD_E_NO_MEMORY; - } - - if (pcbAtrLenAlloc) - { - *pPbAtr = (BYTE*) calloc(1, pcsc_cbAtrLen); - - if (!*pPbAtr) - return SCARD_E_NO_MEMORY; - } - - status = (LONG) g_PCSC.pfnSCardStatus(hCard, - *pMszReaderNames, &pcsc_cchReaderLen, - &pcsc_dwState, &pcsc_dwProtocol, - pbAtr, &pcsc_cbAtrLen); - - if (status != SCARD_S_SUCCESS) - { - if (pcchReaderLenAlloc) - { - free(*pMszReaderNames); - *pMszReaderNames = NULL; - } - - if (pcbAtrLenAlloc) - { - free(*pPbAtr); - *pPbAtr = NULL; - } - } - else - { - if (pcchReaderLenAlloc) - PCSC_AddMemoryBlock(hContext, *pMszReaderNames); - - if (pcbAtrLenAlloc) - PCSC_AddMemoryBlock(hContext, *pPbAtr); - } + if (!tReader) + { + status = ERROR_NOT_ENOUGH_MEMORY; + goto out_fail; } - } - else - { - status = (LONG) g_PCSC.pfnSCardStatus(hCard, mszReaderNames, &pcsc_cchReaderLen, - &pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen); + + readerNames = tReader; } - status = PCSC_MapErrorCodeToWinSCard(status); - *pcchReaderLen = (DWORD) pcsc_cchReaderLen; - mszReaderNamesWinSCard = PCSC_ConvertReaderNamesToWinSCard(*pMszReaderNames, pcchReaderLen); - - if (mszReaderNamesWinSCard) + if (allocateAtr && pcsc_cbAtrLen > 0 && pbAtr) { - PCSC_SCardFreeMemory_Internal(hContext, *pMszReaderNames); - *pMszReaderNames = mszReaderNamesWinSCard; - PCSC_AddMemoryBlock(hContext, *pMszReaderNames); + tATR = calloc(1, pcsc_cbAtrLen); + + if (!tATR) + { + status = ERROR_NOT_ENOUGH_MEMORY; + goto out_fail; + } + + atr = tATR; + } + + status = (LONG) g_PCSC.pfnSCardStatus(hCard, readerNames, &pcsc_cchReaderLen, &pcsc_dwState, + &pcsc_dwProtocol, atr, + &pcsc_cbAtrLen); + + if (status != STATUS_SUCCESS) + goto out_fail; + + if (tATR) + { + PCSC_AddMemoryBlock(hContext, tATR); + *(LPBYTE*)pbAtr = tATR; + } + + if (tReader) + { + if (unicode) + { + LPSTR mszReaderNamesW = NULL; + int pcsc_cchReaderLenW = 0; + pcsc_cchReaderLenW = ConvertToUnicode(CP_UTF8, 0, tReader, *pcchReaderLen, + (WCHAR**) &mszReaderNamesW, 0); + + if (pcsc_cchReaderLenW <= 0 || mszReaderNamesW == NULL) + { + status = ERROR_NOT_ENOUGH_MEMORY; + goto out_fail; + } + + readerNames = mszReaderNamesW; + free(tReader); + PCSC_AddMemoryBlock(hContext, mszReaderNamesW); + *(LPSTR*) mszReaderNames = mszReaderNamesW; + } + else + { + PCSC_AddMemoryBlock(hContext, tReader); + *(LPSTR*) mszReaderNames = tReader; + } } pcsc_dwState &= 0xFFFF; - *pdwState = PCSC_ConvertCardStateToWinSCard((DWORD) pcsc_dwState, status); - *pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwProtocol); - *pcbAtrLen = (DWORD) pcsc_cbAtrLen; + + if (pdwState) + *pdwState = PCSC_ConvertCardStateToWinSCard((DWORD) pcsc_dwState, status); + + if (pdwProtocol) + *pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwProtocol); + + if (pcbAtrLen) + *pcbAtrLen = (DWORD) pcsc_cbAtrLen; + + if (pcchReaderLen) + { + if (unicode) + *pcchReaderLen = (pcsc_cchReaderLen + 1) * 2; + else + *pcchReaderLen = pcsc_cchReaderLen + 1; + } + + /* Make sure the last byte is set */ + if (readerNames) + { + if (unicode) + { + readerNames[pcsc_cchReaderLen * 2] = '\0'; + readerNames[pcsc_cchReaderLen * 2 + 1] = '\0'; + } + else + readerNames[pcsc_cchReaderLen] = '\0'; + } + + return status; +out_fail: + free(tReader); + free(tATR); return status; } @@ -2112,40 +1740,16 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard, LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) { - LONG status = SCARD_S_SUCCESS; - status = PCSC_SCardStatus_Internal(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, - pbAtr, pcbAtrLen); - return status; + return PCSC_SCardStatus_Internal(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, + pbAtr, pcbAtrLen, FALSE); } WINSCARDAPI LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard, LPWSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) { - SCARDCONTEXT hContext = 0; - LPSTR mszReaderNamesA = NULL; - LONG status = SCARD_S_SUCCESS; - - if (!g_PCSC.pfnSCardStatus) - return SCARD_E_NO_SERVICE; - - hContext = PCSC_GetCardContextFromHandle(hCard); - - if (!hContext) - return SCARD_E_INVALID_VALUE; - - status = PCSC_SCardStatus_Internal(hCard, (LPSTR) &mszReaderNamesA, pcchReaderLen, pdwState, - pdwProtocol, pbAtr, pcbAtrLen); - - if (mszReaderNamesA) - { - *pcchReaderLen = ConvertToUnicode(CP_UTF8, 0, mszReaderNamesA, *pcchReaderLen, - (WCHAR**) mszReaderNames, 0); - PCSC_AddMemoryBlock(hContext, mszReaderNames); - PCSC_SCardFreeMemory_Internal(hContext, mszReaderNamesA); - } - - return status; + return PCSC_SCardStatus_Internal(hCard, (LPSTR) mszReaderNames, pcchReaderLen, pdwState, + pdwProtocol, pbAtr, pcbAtrLen, TRUE); } WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard, @@ -2260,6 +1864,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard, WINSCARDAPI LONG WINAPI PCSC_SCardGetTransmitCount(SCARDHANDLE hCard, LPDWORD pcTransmitCount) { + WINPR_UNUSED(pcTransmitCount); PCSC_SCARDHANDLE* pCard = NULL; pCard = PCSC_GetCardHandleData(hCard); @@ -2415,7 +2020,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWOR { int length = 0; char* namePCSC = NULL; - char* nameWinSCard; DWORD cbAttrLen = 0; char* pbAttrA = NULL; WCHAR* pbAttrW = NULL; @@ -2444,8 +2048,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWOR if (status != SCARD_S_SUCCESS) return status; - length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) pbAttrW, *pcbAttrLen, (char**) &pbAttrA, 0, NULL, - NULL); + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) pbAttrW, *pcbAttrLen, (char**) &pbAttrA, 0, NULL, + NULL); namePCSC = pbAttrA; PCSC_SCardFreeMemory_Internal(hContext, pbAttrW); } @@ -2460,24 +2064,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWOR } length = strlen(namePCSC); - nameWinSCard = PCSC_GetReaderAliasFromName(namePCSC); - - if (nameWinSCard) - { - length = strlen(nameWinSCard); - friendlyNameA = _strdup(nameWinSCard); - - if (!friendlyNameA) - { - free(namePCSC); - return SCARD_E_NO_MEMORY; - } - } - else - { - friendlyNameA = namePCSC; - namePCSC = NULL; - } + friendlyNameA = namePCSC; + namePCSC = NULL; if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W) { @@ -2539,7 +2127,6 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWOR } free(namePCSC); - free(nameWinSCard); return status; } @@ -2833,38 +2420,17 @@ WINSCARDAPI LONG WINAPI PCSC_SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent) return 0; } -WINSCARDAPI LONG WINAPI PCSC_SCardAddReaderName(HANDLE* key, LPSTR readerName) -{ - LONG status = SCARD_S_SUCCESS; - int count = 0; - - if (!g_ReadersNames) - { - g_ReadersNames = ListDictionary_New(TRUE); - - if (!g_ReadersNames) - return SCARD_E_NO_SERVICE; - } - - count = ListDictionary_Count(g_ReadersNames); - - if (!ListDictionary_Add(g_ReadersNames, key, readerName)) - return SCARD_E_NO_SERVICE; - - return status; -} - #ifdef __MACOSX__ -unsigned int determineMacOSXVersion() +unsigned int determineMacOSXVersion(void) { int mib[2]; size_t len = 0; char* kernelVersion = NULL; char* tok = NULL; unsigned int version = 0; - int majorVersion = 0; - int minorVersion = 0; - int patchVersion = 0; + long majorVersion = 0; + long minorVersion = 0; + long patchVersion = 0; int count = 0; mib[0] = CTL_KERN; mib[1] = KERN_OSRELEASE; @@ -2884,21 +2450,34 @@ unsigned int determineMacOSXVersion() } tok = strtok(kernelVersion, "."); + errno = 0; while (tok) { switch (count) { case 0: - majorVersion = atoi(tok); + majorVersion = strtol(tok, NULL, 0); + + if (errno != 0) + goto fail; + break; case 1: - minorVersion = atoi(tok); + minorVersion = strtol(tok, NULL, 0); + + if (errno != 0) + goto fail; + break; case 2: - patchVersion = atoi(tok); + patchVersion = strtol(tok, NULL, 0); + + if (errno != 0) + goto fail; + break; } @@ -2964,6 +2543,7 @@ unsigned int determineMacOSXVersion() version |= (minorVersion << 8) | (patchVersion); } +fail: free(kernelVersion); return version; } @@ -3049,8 +2629,7 @@ SCardApiFunctionTable PCSC_SCardApiFunctionTable = PCSC_SCardGetReaderDeviceInstanceIdW, /* SCardGetReaderDeviceInstanceIdW */ PCSC_SCardListReadersWithDeviceInstanceIdA, /* SCardListReadersWithDeviceInstanceIdA */ PCSC_SCardListReadersWithDeviceInstanceIdW, /* SCardListReadersWithDeviceInstanceIdW */ - PCSC_SCardAudit, /* SCardAudit */ - PCSC_SCardAddReaderName /* SCardAddReaderName */ + PCSC_SCardAudit /* SCardAudit */ }; PSCardApiFunctionTable PCSC_GetSCardApiFunctionTable(void) diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.h b/winpr/libwinpr/smartcard/smartcard_pcsc.h index 85d1c32..1d85d25 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.h +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.h @@ -155,7 +155,6 @@ struct _PCSCFunctionTable PCSC_LPDWORD pcbAttrLen); PCSC_LONG(* pfnSCardSetAttrib)(SCARDHANDLE hCard, PCSC_DWORD dwAttrId, LPCBYTE pbAttr, PCSC_DWORD cbAttrLen); - PCSC_LONG(* pfnSCardAddReaderName)(HANDLE* key, LPSTR readerName); }; typedef struct _PCSCFunctionTable PCSCFunctionTable; diff --git a/winpr/libwinpr/smartcard/smartcard_winscard.c b/winpr/libwinpr/smartcard/smartcard_winscard.c index c4b3b6f..29f1002 100644 --- a/winpr/libwinpr/smartcard/smartcard_winscard.c +++ b/winpr/libwinpr/smartcard/smartcard_winscard.c @@ -111,8 +111,7 @@ SCardApiFunctionTable WinSCard_SCardApiFunctionTable = NULL, /* SCardGetReaderDeviceInstanceIdW */ NULL, /* SCardListReadersWithDeviceInstanceIdA */ NULL, /* SCardListReadersWithDeviceInstanceIdW */ - NULL, /* SCardAudit */ - NULL /* SCardAddReaderName */ + NULL /* SCardAudit */ }; PSCardApiFunctionTable WinSCard_GetSCardApiFunctionTable(void) diff --git a/winpr/libwinpr/smartcard/test/TestSmartCardStatus.c b/winpr/libwinpr/smartcard/test/TestSmartCardStatus.c new file mode 100644 index 0000000..a830685 --- /dev/null +++ b/winpr/libwinpr/smartcard/test/TestSmartCardStatus.c @@ -0,0 +1,166 @@ +// compile against PCSC gcc -o scardtest TestSmartCardStatus.c -DPCSC=1 -I /usr/include/PCSC -lpcsclite +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#if defined(__APPLE__) || defined(PCSC) +#include <PCSC/winscard.h> +#include <PCSC/wintypes.h> +#elif defined (__linux__) +#include <winpr/crt.h> +#include <winpr/smartcard.h> +#include <winpr/synch.h> +#else +#include <winscard.h> +#endif + +#if defined(PCSC) +int main(int argc, char* argv[]) +#else +int TestSmartCardStatus(int argc, char* argv[]) +#endif +{ + SCARDCONTEXT hContext; + LPSTR mszReaders; + DWORD cchReaders = 0; + DWORD err; + SCARDHANDLE hCard; + DWORD dwActiveProtocol; + char name[100]; + char* aname = NULL; + char* aatr = NULL; + DWORD len; + BYTE atr[32]; + DWORD atrlen = 32; + DWORD status = 0; + DWORD protocol = 0; + err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); + + if (err != SCARD_S_SUCCESS) + { + printf("ScardEstablishedContext: 0x%08x\n", err); + return -1; + } + + err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders); + + if (err != 0) + { + printf("ScardListReaders: 0x%08x\n", err); + return -1; + } + + mszReaders = calloc(cchReaders, sizeof(char)); + + if (!mszReaders) + { + printf("calloc\n"); + return -1; + } + + err = SCardListReaders(hContext, "SCard$AllReaders", mszReaders, &cchReaders); + + if (err != SCARD_S_SUCCESS) + { + printf("ScardListReaders: 0x%08x\n", err); + return -1; + } + + printf("Reader: %s\n", mszReaders); + err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, + &hCard, &dwActiveProtocol); + + if (err != SCARD_S_SUCCESS) + { + printf("ScardConnect: 0x%08x\n", err); + return -1; + } + + free(mszReaders); + + + printf("# test 1 - get reader length\n"); + err = SCardStatus(hCard, NULL, &len, NULL, NULL, NULL, NULL); + if (err != SCARD_S_SUCCESS) + { + printf("SCardStatus: 0x%08x\n", err); + return -1; + } + printf("reader name length: %u\n", len); + + + printf("# test 2 - get reader name value\n"); + err = SCardStatus(hCard, name, &len, NULL, NULL, NULL, NULL); + if (err != SCARD_S_SUCCESS) + { + printf("SCardStatus: 0x%08x\n", err); + return -1; + } + printf("Reader name: %s (%ld)\n", name, strlen(name)); + + + printf("# test 3 - get all values - pre allocated\n"); + err = SCardStatus(hCard, name, &len, &status, &protocol, atr, &atrlen); + if (err != SCARD_S_SUCCESS) + { + printf("SCardStatus: 0x%08x\n", err); + return -1; + } + printf("Reader name: %s (%ld/len %u)\n", name, strlen(name), len); + printf("status: 0x%08X\n", status); + printf("proto: 0x%08X\n", protocol); + printf("atrlen: %u\n", atrlen); + + + printf("# test 4 - get all values - auto allocate\n"); + len = atrlen = SCARD_AUTOALLOCATE; + err = SCardStatus(hCard, (LPSTR)&aname, &len, &status, &protocol, (LPBYTE)&aatr, &atrlen); + if (err != SCARD_S_SUCCESS) + { + printf("SCardStatus: 0x%08x\n", err); + return -1; + } + printf("Reader name: %s (%ld/%u)\n", aname, strlen(aname), len); + printf("status: 0x%08X\n", status); + printf("proto: 0x%08X\n", protocol); + printf("atrlen: %u\n", atrlen); + SCardFreeMemory(hContext, aname); + SCardFreeMemory(hContext, aatr); + + + printf("# test 5 - get status and protocol only\n"); + err = SCardStatus(hCard, NULL, NULL, &status, &protocol, NULL, NULL); + if (err != SCARD_S_SUCCESS) + { + printf("SCardStatus: 0x%08x\n", err); + return -1; + } + printf("status: 0x%08X\n", status); + printf("proto: 0x%08X\n", protocol); + + + printf("# test 6 - get atr only auto allocated\n"); + atrlen = SCARD_AUTOALLOCATE; + err = SCardStatus(hCard, NULL, NULL, NULL, NULL, (LPBYTE)&aatr, &atrlen); + if (err != SCARD_S_SUCCESS) + { + printf("SCardStatus: 0x%08x\n", err); + return -1; + } + printf("atrlen: %u\n", atrlen); + SCardFreeMemory(hContext, aatr); + + + printf("# test 7 - get atr only pre allocated\n"); + atrlen = 32; + err = SCardStatus(hCard, NULL, NULL, NULL, NULL, atr, &atrlen); + if (err != SCARD_S_SUCCESS) + { + printf("SCardStatus: 0x%08x\n", err); + return -1; + } + printf("atrlen: %u\n", atrlen); + SCardDisconnect(hCard, SCARD_LEAVE_CARD); + SCardReleaseContext(hContext); + + return 0; +} diff --git a/winpr/libwinpr/sspi/CMakeLists.txt b/winpr/libwinpr/sspi/CMakeLists.txt index efcad47..597e095 100644 --- a/winpr/libwinpr/sspi/CMakeLists.txt +++ b/winpr/libwinpr/sspi/CMakeLists.txt @@ -27,6 +27,10 @@ set(${MODULE_PREFIX}_NTLM_SRCS NTLM/ntlm.c NTLM/ntlm.h) +set(${MODULE_PREFIX}_KERBEROS_SRCS + Kerberos/kerberos.c + Kerberos/kerberos.h) + set(${MODULE_PREFIX}_NEGOTIATE_SRCS Negotiate/negotiate.c Negotiate/negotiate.h) @@ -38,17 +42,20 @@ set(${MODULE_PREFIX}_SCHANNEL_SRCS Schannel/schannel.h) set(${MODULE_PREFIX}_CREDSSP_SRCS - CredSSP/credssp.c) + CredSSP/credssp.c + CredSSP/credssp.h) set(${MODULE_PREFIX}_SRCS - ${${MODULE_PREFIX}_CREDSSP_SRCS} sspi_winpr.c sspi_winpr.h sspi_export.c + sspi_gss.c + sspi_gss.h sspi.c sspi.h) -winpr_module_add(${${MODULE_PREFIX}_NTLM_SRCS} +winpr_module_add(${${MODULE_PREFIX}_CREDSSP_SRCS} + ${${MODULE_PREFIX}_NTLM_SRCS} ${${MODULE_PREFIX}_KERBEROS_SRCS} ${${MODULE_PREFIX}_NEGOTIATE_SRCS} ${${MODULE_PREFIX}_SCHANNEL_SRCS} @@ -64,6 +71,11 @@ if(MBEDTLS_FOUND) winpr_library_add(${MBEDTLS_LIBRARIES}) endif() +if(GSS_FOUND) + winpr_include_directory_add(${GSS_INCLUDE_DIR}) + winpr_library_add(${GSS_LIBRARIES}) +endif() + if(WIN32) winpr_library_add(ws2_32) endif() diff --git a/winpr/libwinpr/sspi/CredSSP/credssp.c b/winpr/libwinpr/sspi/CredSSP/credssp.c index f6d5e25..091f6d9 100644 --- a/winpr/libwinpr/sspi/CredSSP/credssp.c +++ b/winpr/libwinpr/sspi/CredSSP/credssp.c @@ -28,24 +28,25 @@ #include "../sspi.h" -char* CREDSSP_PACKAGE_NAME = "CredSSP"; +static const char* CREDSSP_PACKAGE_NAME = "CredSSP"; -SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, - SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextW(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, - SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { CREDSSP_CONTEXT* context; SSPI_CREDENTIALS* credentials; - context = (CREDSSP_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -57,6 +58,12 @@ SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCrede credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + if (!credentials) + { + credssp_ContextFree(context); + return SEC_E_INVALID_HANDLE; + } + sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) CREDSSP_PACKAGE_NAME); } @@ -64,10 +71,9 @@ SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCrede return SEC_E_OK; } -CREDSSP_CONTEXT* credssp_ContextNew() +CREDSSP_CONTEXT* credssp_ContextNew(void) { CREDSSP_CONTEXT* context; - context = (CREDSSP_CONTEXT*) calloc(1, sizeof(CREDSSP_CONTEXT)); if (!context) @@ -81,7 +87,9 @@ void credssp_ContextFree(CREDSSP_CONTEXT* context) free(context); } -SECURITY_STATUS SEC_ENTRY credssp_QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY credssp_QueryContextAttributes(PCtxtHandle phContext, + ULONG ulAttribute, + void* pBuffer) { if (!phContext) return SEC_E_INVALID_HANDLE; @@ -92,16 +100,18 @@ SECURITY_STATUS SEC_ENTRY credssp_QueryContextAttributes(PCtxtHandle phContext, return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, + SEC_WCHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, + SEC_CHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SSPI_CREDENTIALS* credentials; SEC_WINNT_AUTH_IDENTITY* identity; @@ -114,30 +124,30 @@ SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleA(SEC_CHAR* pszPrincip return SEC_E_INSUFFICIENT_MEMORY; identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; - CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); sspi_SecureHandleSetUpperPointer(phCredential, (void*) CREDSSP_PACKAGE_NAME); - return SEC_E_OK; } return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesW(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { if (ulAttribute == SECPKG_CRED_ATTR_NAMES) { - SSPI_CREDENTIALS* credentials; + SSPI_CREDENTIALS* credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); - credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + if (!credentials) + return SEC_E_INVALID_HANDLE; return SEC_E_OK; } @@ -145,7 +155,7 @@ SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCred return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle phCredential) +static SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle phCredential) { SSPI_CREDENTIALS* credentials; @@ -158,26 +168,31 @@ SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle phCredential return SEC_E_INVALID_HANDLE; sspi_CredentialsFree(credentials); - return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY credssp_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +static SECURITY_STATUS SEC_ENTRY credssp_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY credssp_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +static SECURITY_STATUS SEC_ENTRY credssp_DecryptMessage(PCtxtHandle phContext, + PSecBufferDesc pMessage, + ULONG MessageSeqNo, ULONG* pfQOP) { return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY credssp_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +static SECURITY_STATUS SEC_ENTRY credssp_MakeSignature(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY credssp_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +static SECURITY_STATUS SEC_ENTRY credssp_VerifySignature(PCtxtHandle phContext, + PSecBufferDesc pMessage, + ULONG MessageSeqNo, ULONG* pfQOP) { return SEC_E_UNSUPPORTED_FUNCTION; } @@ -256,14 +271,14 @@ const SecPkgInfoA CREDSSP_SecPkgInfoA = "Microsoft CredSSP Security Provider" /* Comment */ }; -WCHAR CREDSSP_SecPkgInfoW_Name[] = { 'C','R','E','D','S','S','P','\0' }; +static WCHAR CREDSSP_SecPkgInfoW_Name[] = { 'C', 'R', 'E', 'D', 'S', 'S', 'P', '\0' }; -WCHAR CREDSSP_SecPkgInfoW_Comment[] = +static WCHAR CREDSSP_SecPkgInfoW_Comment[] = { - 'M','i','c','r','o','s','o','f','t',' ', - 'C','r','e','d','S','S','P',' ', - 'S','e','c','u','r','i','t','y',' ', - 'P','r','o','v','i','d','e','r','\0' + 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', ' ', + 'C', 'r', 'e', 'd', 'S', 'S', 'P', ' ', + 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', ' ', + 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\0' }; const SecPkgInfoW CREDSSP_SecPkgInfoW = diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.c b/winpr/libwinpr/sspi/Kerberos/kerberos.c new file mode 100644 index 0000000..f955590 --- /dev/null +++ b/winpr/libwinpr/sspi/Kerberos/kerberos.c @@ -0,0 +1,807 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Kerberos Auth Protocol + * + * Copyright 2015 ANSSI, Author Thomas Calderon + * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> + +#include <winpr/crt.h> +#include <winpr/sspi.h> +#include <winpr/print.h> +#include <winpr/sysinfo.h> +#include <winpr/registry.h> + +#include "kerberos.h" + +#ifdef WITH_GSSAPI_HEIMDAL +#include <krb5-protos.h> +#endif + +#include "../sspi.h" +#include "../../log.h" +#define TAG WINPR_TAG("sspi.Kerberos") + +struct _KRB_CONTEXT +{ + CtxtHandle context; + SSPI_CREDENTIALS* credentials; + SEC_WINNT_AUTH_IDENTITY identity; + + /* GSSAPI */ + UINT32 major_status; + UINT32 minor_status; + UINT32 actual_time; + sspi_gss_cred_id_t cred; + sspi_gss_ctx_id_t gss_ctx; + sspi_gss_name_t target_name; +}; + +static const char* KRB_PACKAGE_NAME = "Kerberos"; + +const SecPkgInfoA KERBEROS_SecPkgInfoA = +{ + 0x000F3BBF, /* fCapabilities */ + 1, /* wVersion */ + 0x0010, /* wRPCID */ + 0x0000BB80, /* cbMaxToken : 48k bytes maximum for Windows Server 2012 */ + "Kerberos", /* Name */ + "Kerberos Security Package" /* Comment */ +}; + +static const WCHAR KERBEROS_SecPkgInfoW_Name[] = { 'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', '\0' }; + +static const WCHAR KERBEROS_SecPkgInfoW_Comment[] = +{ + 'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', ' ', + 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', ' ', + 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\0' +}; + +const SecPkgInfoW KERBEROS_SecPkgInfoW = +{ + 0x000F3BBF, /* fCapabilities */ + 1, /* wVersion */ + 0x0010, /* wRPCID */ + 0x0000BB80, /* cbMaxToken : 48k bytes maximum for Windows Server 2012 */ + KERBEROS_SecPkgInfoW_Name, /* Name */ + KERBEROS_SecPkgInfoW_Comment /* Comment */ +}; + +static sspi_gss_OID_desc g_SSPI_GSS_C_SPNEGO_KRB5 = { 9, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }; +static sspi_gss_OID SSPI_GSS_C_SPNEGO_KRB5 = &g_SSPI_GSS_C_SPNEGO_KRB5; + +static KRB_CONTEXT* kerberos_ContextNew(void) +{ + KRB_CONTEXT* context; + context = (KRB_CONTEXT*) calloc(1, sizeof(KRB_CONTEXT)); + + if (!context) + return NULL; + + context->minor_status = 0; + context->major_status = 0; + context->gss_ctx = SSPI_GSS_C_NO_CONTEXT; + context->cred = SSPI_GSS_C_NO_CREDENTIAL; + return context; +} + +static void kerberos_ContextFree(KRB_CONTEXT* context) +{ + UINT32 minor_status; + + if (!context) + return; + + if (context->target_name) + { + sspi_gss_release_name(&minor_status, &context->target_name); + context->target_name = NULL; + } + + if (context->gss_ctx) + { + sspi_gss_delete_sec_context(&minor_status, &context->gss_ctx, SSPI_GSS_C_NO_BUFFER); + context->gss_ctx = SSPI_GSS_C_NO_CONTEXT; + } + + free(context); +} + +static SECURITY_STATUS SEC_ENTRY kerberos_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, + SEC_WCHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, + SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, + PCredHandle phCredential, PTimeStamp ptsExpiry) +{ + return SEC_E_OK; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, + SEC_CHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, + SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, + PCredHandle phCredential, PTimeStamp ptsExpiry) +{ + return SEC_E_OK; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_FreeCredentialsHandle(PCredHandle phCredential) +{ + SSPI_CREDENTIALS* credentials; + + if (!phCredential) + return SEC_E_INVALID_HANDLE; + + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + + if (!credentials) + return SEC_E_INVALID_HANDLE; + + sspi_CredentialsFree(credentials); + return SEC_E_OK; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_QueryCredentialsAttributesW(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) +{ + if (ulAttribute == SECPKG_CRED_ATTR_NAMES) + { + return SEC_E_OK; + } + + return SEC_E_UNSUPPORTED_FUNCTION; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_QueryCredentialsAttributesA(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) +{ + return kerberos_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer); +} + +static SECURITY_STATUS SEC_ENTRY kerberos_InitializeSecurityContextW(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, + ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, + PCtxtHandle phNewContext, PSecBufferDesc pOutput, + ULONG* pfContextAttr, PTimeStamp ptsExpiry) +{ + return SEC_E_UNSUPPORTED_FUNCTION; +} + +static int kerberos_SetContextServicePrincipalNameA(KRB_CONTEXT* context, + SEC_CHAR* ServicePrincipalName) +{ + char* p; + UINT32 major_status; + UINT32 minor_status; + char* gss_name = NULL; + sspi_gss_buffer_desc name_buffer; + + if (!ServicePrincipalName) + { + context->target_name = NULL; + return 1; + } + + /* GSSAPI expects a SPN of type <service>@FQDN, let's construct it */ + gss_name = _strdup(ServicePrincipalName); + + if (!gss_name) + return -1; + + p = strchr(gss_name, '/'); + + if (p) + *p = '@'; + + name_buffer.value = gss_name; + name_buffer.length = strlen(gss_name) + 1; + major_status = sspi_gss_import_name(&minor_status, &name_buffer, + SSPI_GSS_C_NT_HOSTBASED_SERVICE, &(context->target_name)); + free(gss_name); + + if (SSPI_GSS_ERROR(major_status)) + { + WLog_ERR(TAG, "error: gss_import_name failed"); + return -1; + } + + return 1; +} + +#ifdef WITH_GSSAPI +static krb5_error_code KRB5_CALLCONV +acquire_cred(krb5_context ctx, krb5_principal client, const char* password) +{ + krb5_error_code ret; + krb5_creds creds; + krb5_deltat starttime = 0; + krb5_get_init_creds_opt* options = NULL; + krb5_ccache ccache; + krb5_init_creds_context init_ctx = NULL; + + /* Get default ccache */ + if ((ret = krb5_cc_default(ctx, &ccache))) + { + WLog_ERR(TAG, "error while getting default ccache"); + goto cleanup; + } + + if ((ret = krb5_cc_initialize(ctx, ccache, client))) + { + WLog_ERR(TAG, "error: could not initialize ccache"); + goto cleanup; + } + + memset(&creds, 0, sizeof(creds)); + + if ((ret = krb5_get_init_creds_opt_alloc(ctx, &options))) + { + WLog_ERR(TAG, "error while allocating options"); + goto cleanup; + } + + /* Set default options */ + krb5_get_init_creds_opt_set_forwardable(options, 0); + krb5_get_init_creds_opt_set_proxiable(options, 0); +#ifdef WITH_GSSAPI_MIT + + /* for MIT we specify ccache output using an option */ + if ((ret = krb5_get_init_creds_opt_set_out_ccache(ctx, options, ccache))) + { + WLog_ERR(TAG, "error while setting ccache output"); + goto cleanup; + } + +#endif + + if ((ret = krb5_init_creds_init(ctx, client, NULL, NULL, starttime, options, &init_ctx))) + { + WLog_ERR(TAG, "error krb5_init_creds_init failed"); + goto cleanup; + } + + if ((ret = krb5_init_creds_set_password(ctx, init_ctx, password))) + { + WLog_ERR(TAG, "error krb5_init_creds_set_password failed"); + goto cleanup; + } + + /* Get credentials */ + if ((ret = krb5_init_creds_get(ctx, init_ctx))) + { + WLog_ERR(TAG, "error while getting credentials"); + goto cleanup; + } + + /* Retrieve credentials */ + if ((ret = krb5_init_creds_get_creds(ctx, init_ctx, &creds))) + { + WLog_ERR(TAG, "error while retrieving credentials"); + goto cleanup; + } + +#ifdef WITH_GSSAPI_HEIMDAL + + /* For Heimdal, we use this function to store credentials */ + if ((ret = krb5_init_creds_store(ctx, init_ctx, ccache))) + { + WLog_ERR(TAG, "error while storing credentials"); + goto cleanup; + } + +#endif +cleanup: + krb5_free_cred_contents(ctx, &creds); +#ifdef HAVE_AT_LEAST_KRB_V1_13 + + /* MIT Kerberos version 1.13 at minimum. + * For releases 1.12 and previous, krb5_get_init_creds_opt structure + * is freed in krb5_init_creds_free() */ + if (options) + krb5_get_init_creds_opt_free(ctx, options); + +#endif + + if (init_ctx) + krb5_init_creds_free(ctx, init_ctx); + + if (ccache) + krb5_cc_close(ctx, ccache); + + return ret; +} + +static int init_creds(LPCWSTR username, size_t username_len, LPCWSTR password, size_t password_len) +{ + krb5_error_code ret = 0; + krb5_context ctx = NULL; + krb5_principal principal = NULL; + char* krb_name = NULL; + char* lusername = NULL; + char* lrealm = NULL; + char* lpassword = NULL; + int flags = 0; + char* pstr = NULL; + size_t krb_name_len = 0; + size_t lrealm_len = 0; + size_t lusername_len = 0; + int status = 0; + status = ConvertFromUnicode(CP_UTF8, 0, username, + username_len, &lusername, 0, NULL, NULL); + + if (status <= 0) + { + WLog_ERR(TAG, "Failed to convert username"); + goto cleanup; + } + + status = ConvertFromUnicode(CP_UTF8, 0, password, + password_len, &lpassword, 0, NULL, NULL); + + if (status <= 0) + { + WLog_ERR(TAG, "Failed to convert password"); + goto cleanup; + } + + /* Could call krb5_init_secure_context, but it disallows user overrides */ + ret = krb5_init_context(&ctx); + + if (ret) + { + WLog_ERR(TAG, "error: while initializing Kerberos 5 library"); + goto cleanup; + } + + ret = krb5_get_default_realm(ctx, &lrealm); + + if (ret) + { + WLog_WARN(TAG, "could not get Kerberos default realm"); + goto cleanup; + } + + lrealm_len = strlen(lrealm); + lusername_len = strlen(lusername); + krb_name_len = lusername_len + lrealm_len + 1; // +1 for '@' + krb_name = calloc(krb_name_len + 1, sizeof(char)); + + if (!krb_name) + { + WLog_ERR(TAG, "could not allocate memory for string rep of principal\n"); + ret = -1; + goto cleanup; + } + + /* Set buffer */ + _snprintf(krb_name, krb_name_len + 1, "%s@%s", lusername, lrealm); +#ifdef WITH_DEBUG_NLA + WLog_DBG(TAG, "copied string is %s\n", krb_name); +#endif + pstr = strchr(lusername, '@'); + + if (pstr != NULL) + flags = KRB5_PRINCIPAL_PARSE_ENTERPRISE; + + /* Use the specified principal name. */ + ret = krb5_parse_name_flags(ctx, krb_name, flags, + &principal); + + if (ret) + { + WLog_ERR(TAG, "could not convert %s to principal", krb_name); + goto cleanup; + } + + ret = acquire_cred(ctx, principal, lpassword); + + if (ret) + { + WLog_ERR(TAG, "Kerberos credentials not found and could not be acquired"); + goto cleanup; + } + +cleanup: + free(lusername); + free(lpassword); + + if (krb_name) + free(krb_name); + + if (lrealm) + krb5_free_default_realm(ctx, lrealm); + + if (principal) + krb5_free_principal(ctx, principal); + + if (ctx) + krb5_free_context(ctx); + + return ret; +} +#endif + +static SECURITY_STATUS SEC_ENTRY kerberos_InitializeSecurityContextA(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, + ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, + PCtxtHandle phNewContext, PSecBufferDesc pOutput, + ULONG* pfContextAttr, PTimeStamp ptsExpiry) +{ + KRB_CONTEXT* context; + SSPI_CREDENTIALS* credentials; + PSecBuffer input_buffer = NULL; + PSecBuffer output_buffer = NULL; + sspi_gss_buffer_desc input_tok = { 0 }; + sspi_gss_buffer_desc output_tok = { 0 }; + sspi_gss_OID actual_mech; + sspi_gss_OID desired_mech; + UINT32 actual_services; + input_tok.length = 0; + output_tok.length = 0; + desired_mech = SSPI_GSS_C_SPNEGO_KRB5; + context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + { + context = kerberos_ContextNew(); + + if (!context) + return SEC_E_INSUFFICIENT_MEMORY; + + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + context->credentials = credentials; + + if (kerberos_SetContextServicePrincipalNameA(context, pszTargetName) < 0) + { + kerberos_ContextFree(context); + return SEC_E_INTERNAL_ERROR; + } + + sspi_SecureHandleSetLowerPointer(phNewContext, context); + sspi_SecureHandleSetUpperPointer(phNewContext, (void*) KRB_PACKAGE_NAME); + } + + if (!pInput) + { +#if defined(WITH_GSSAPI) + context->major_status = sspi_gss_init_sec_context(&(context->minor_status), + context->cred, &(context->gss_ctx), context->target_name, + desired_mech, SSPI_GSS_C_MUTUAL_FLAG | SSPI_GSS_C_DELEG_FLAG, + SSPI_GSS_C_INDEFINITE, SSPI_GSS_C_NO_CHANNEL_BINDINGS, + &input_tok, &actual_mech, &output_tok, &actual_services, &(context->actual_time)); + + if (SSPI_GSS_ERROR(context->major_status)) + { + /* GSSAPI failed because we do not have credentials */ + if (context->major_status & SSPI_GSS_S_NO_CRED) + { + /* Then let's try to acquire credentials using login and password, + * and only those two, means not with a smartcard. + * If we use smartcard-logon, the credentials have already + * been acquired by pkinit process. If not, returned error previously. + */ + if (init_creds(context->credentials->identity.User, + context->credentials->identity.UserLength, + context->credentials->identity.Password, + context->credentials->identity.PasswordLength)) + return SEC_E_NO_CREDENTIALS; + + WLog_INFO(TAG, "Authenticated to Kerberos v5 via login/password"); + /* retry GSSAPI call */ + context->major_status = sspi_gss_init_sec_context(&(context->minor_status), + context->cred, &(context->gss_ctx), context->target_name, + desired_mech, SSPI_GSS_C_MUTUAL_FLAG | SSPI_GSS_C_DELEG_FLAG, + SSPI_GSS_C_INDEFINITE, SSPI_GSS_C_NO_CHANNEL_BINDINGS, + &input_tok, &actual_mech, &output_tok, &actual_services, &(context->actual_time)); + + if (SSPI_GSS_ERROR(context->major_status)) + { + /* We can't use Kerberos */ + WLog_ERR(TAG, "Init GSS security context failed : can't use Kerberos"); + return SEC_E_INTERNAL_ERROR; + } + } + } + +#endif + + if (context->major_status & SSPI_GSS_S_CONTINUE_NEEDED) + { + if (output_tok.length != 0) + { + if (!pOutput) + return SEC_E_INVALID_TOKEN; + + if (pOutput->cBuffers < 1) + return SEC_E_INVALID_TOKEN; + + output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN); + + if (!output_buffer) + return SEC_E_INVALID_TOKEN; + + if (output_buffer->cbBuffer < 1) + return SEC_E_INVALID_TOKEN; + + CopyMemory(output_buffer->pvBuffer, output_tok.value, output_tok.length); + output_buffer->cbBuffer = output_tok.length; + sspi_gss_release_buffer(&(context->minor_status), &output_tok); + return SEC_I_CONTINUE_NEEDED; + } + } + } + else + { + input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN); + + if (!input_buffer) + return SEC_E_INVALID_TOKEN; + + if (input_buffer->cbBuffer < 1) + return SEC_E_INVALID_TOKEN; + + input_tok.value = input_buffer->pvBuffer; + input_tok.length = input_buffer->cbBuffer; + context->major_status = sspi_gss_init_sec_context(&(context->minor_status), + context->cred, &(context->gss_ctx), context->target_name, + desired_mech, SSPI_GSS_C_MUTUAL_FLAG | SSPI_GSS_C_DELEG_FLAG, + SSPI_GSS_C_INDEFINITE, SSPI_GSS_C_NO_CHANNEL_BINDINGS, + &input_tok, &actual_mech, &output_tok, &actual_services, &(context->actual_time)); + + if (SSPI_GSS_ERROR(context->major_status)) + return SEC_E_INTERNAL_ERROR; + + if (output_tok.length == 0) + { + /* Free output_buffer to detect second call in NLA */ + output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN); + sspi_SecBufferFree(output_buffer); + return SEC_E_OK; + } + else + { + return SEC_E_INTERNAL_ERROR; + } + } + + return SEC_E_INTERNAL_ERROR; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_DeleteSecurityContext(PCtxtHandle phContext) +{ + KRB_CONTEXT* context; + context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + return SEC_E_INVALID_HANDLE; + + kerberos_ContextFree(context); + return SEC_E_OK; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesW(PCtxtHandle phContext, + ULONG ulAttribute, + void* pBuffer) +{ + return SEC_E_OK; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesA(PCtxtHandle phContext, + ULONG ulAttribute, + void* pBuffer) +{ + if (!phContext) + return SEC_E_INVALID_HANDLE; + + if (!pBuffer) + return SEC_E_INSUFFICIENT_MEMORY; + + if (ulAttribute == SECPKG_ATTR_SIZES) + { + SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer; + /* The MaxTokenSize by default is 12,000 bytes. This has been the default value + * since Windows 2000 SP2 and still remains in Windows 7 and Windows 2008 R2. + * For Windows Server 2012, the default value of the MaxTokenSize registry + * entry is 48,000 bytes.*/ + ContextSizes->cbMaxToken = KERBEROS_SecPkgInfoA.cbMaxToken; + ContextSizes->cbMaxSignature = 0; /* means verify not supported */ + ContextSizes->cbBlockSize = 0; /* padding not used */ + ContextSizes->cbSecurityTrailer = 60; /* gss_wrap adds additional 60 bytes for encrypt message */ + return SEC_E_OK; + } + + return SEC_E_UNSUPPORTED_FUNCTION; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) +{ + int index; + int conf_state; + UINT32 major_status; + UINT32 minor_status; + KRB_CONTEXT* context; + sspi_gss_buffer_desc input; + sspi_gss_buffer_desc output; + PSecBuffer data_buffer = NULL; + context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + return SEC_E_INVALID_HANDLE; + + for (index = 0; index < (int) pMessage->cBuffers; index++) + { + if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA) + data_buffer = &pMessage->pBuffers[index]; + } + + if (!data_buffer) + return SEC_E_INVALID_TOKEN; + + input.value = data_buffer->pvBuffer; + input.length = data_buffer->cbBuffer; + major_status = sspi_gss_wrap(&minor_status, context->gss_ctx, TRUE, + SSPI_GSS_C_QOP_DEFAULT, &input, &conf_state, &output); + + if (SSPI_GSS_ERROR(major_status)) + return SEC_E_INTERNAL_ERROR; + + if (conf_state == 0) + { + WLog_ERR(TAG, "error: gss_wrap confidentiality was not applied"); + sspi_gss_release_buffer(&minor_status, &output); + return SEC_E_INTERNAL_ERROR; + } + + CopyMemory(data_buffer->pvBuffer, output.value, output.length); + sspi_gss_release_buffer(&minor_status, &output); + return SEC_E_OK; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_DecryptMessage(PCtxtHandle phContext, + PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +{ + int index; + int conf_state; + UINT32 major_status; + UINT32 minor_status; + KRB_CONTEXT* context; + sspi_gss_buffer_desc input_data; + sspi_gss_buffer_desc output; + PSecBuffer data_buffer_to_unwrap = NULL; + context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + return SEC_E_INVALID_HANDLE; + + for (index = 0; index < (int) pMessage->cBuffers; index++) + { + if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA) + data_buffer_to_unwrap = &pMessage->pBuffers[index]; + } + + if (!data_buffer_to_unwrap) + return SEC_E_INVALID_TOKEN; + + /* unwrap encrypted TLS key AND its signature */ + input_data.value = data_buffer_to_unwrap->pvBuffer; + input_data.length = data_buffer_to_unwrap->cbBuffer; + major_status = sspi_gss_unwrap(&minor_status, context->gss_ctx, &input_data, &output, &conf_state, + NULL); + + if (SSPI_GSS_ERROR(major_status)) + return SEC_E_INTERNAL_ERROR; + + if (conf_state == 0) + { + WLog_ERR(TAG, "error: gss_unwrap confidentiality was not applied"); + sspi_gss_release_buffer(&minor_status, &output); + return SEC_E_INTERNAL_ERROR; + } + + CopyMemory(data_buffer_to_unwrap->pvBuffer, output.value, output.length); + sspi_gss_release_buffer(&minor_status, &output); + return SEC_E_OK; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_MakeSignature(PCtxtHandle phContext, + ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +{ + return SEC_E_OK; +} + +static SECURITY_STATUS SEC_ENTRY kerberos_VerifySignature(PCtxtHandle phContext, + PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +{ + return SEC_E_OK; +} + + +const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA = +{ + 1, /* dwVersion */ + NULL, /* EnumerateSecurityPackages */ + kerberos_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */ + kerberos_AcquireCredentialsHandleA, /* AcquireCredentialsHandle */ + kerberos_FreeCredentialsHandle, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + kerberos_InitializeSecurityContextA, /* InitializeSecurityContext */ + NULL, /* AcceptSecurityContext */ + NULL, /* CompleteAuthToken */ + kerberos_DeleteSecurityContext, /* DeleteSecurityContext */ + NULL, /* ApplyControlToken */ + kerberos_QueryContextAttributesA, /* QueryContextAttributes */ + NULL, /* ImpersonateSecurityContext */ + NULL, /* RevertSecurityContext */ + kerberos_MakeSignature, /* MakeSignature */ + kerberos_VerifySignature, /* VerifySignature */ + NULL, /* FreeContextBuffer */ + NULL, /* QuerySecurityPackageInfo */ + NULL, /* Reserved3 */ + NULL, /* Reserved4 */ + NULL, /* ExportSecurityContext */ + NULL, /* ImportSecurityContext */ + NULL, /* AddCredentials */ + NULL, /* Reserved8 */ + NULL, /* QuerySecurityContextToken */ + kerberos_EncryptMessage, /* EncryptMessage */ + kerberos_DecryptMessage, /* DecryptMessage */ + NULL, /* SetContextAttributes */ +}; + +const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW = +{ + 1, /* dwVersion */ + NULL, /* EnumerateSecurityPackages */ + kerberos_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */ + kerberos_AcquireCredentialsHandleW, /* AcquireCredentialsHandle */ + kerberos_FreeCredentialsHandle, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + kerberos_InitializeSecurityContextW, /* InitializeSecurityContext */ + NULL, /* AcceptSecurityContext */ + NULL, /* CompleteAuthToken */ + kerberos_DeleteSecurityContext, /* DeleteSecurityContext */ + NULL, /* ApplyControlToken */ + kerberos_QueryContextAttributesW, /* QueryContextAttributes */ + NULL, /* ImpersonateSecurityContext */ + NULL, /* RevertSecurityContext */ + kerberos_MakeSignature, /* MakeSignature */ + kerberos_VerifySignature, /* VerifySignature */ + NULL, /* FreeContextBuffer */ + NULL, /* QuerySecurityPackageInfo */ + NULL, /* Reserved3 */ + NULL, /* Reserved4 */ + NULL, /* ExportSecurityContext */ + NULL, /* ImportSecurityContext */ + NULL, /* AddCredentials */ + NULL, /* Reserved8 */ + NULL, /* QuerySecurityContextToken */ + kerberos_EncryptMessage, /* EncryptMessage */ + kerberos_DecryptMessage, /* DecryptMessage */ + NULL, /* SetContextAttributes */ +}; diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.h b/winpr/libwinpr/sspi/Kerberos/kerberos.h new file mode 100644 index 0000000..504c8df --- /dev/null +++ b/winpr/libwinpr/sspi/Kerberos/kerberos.h @@ -0,0 +1,37 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Kerberos Auth Protocol + * + * Copyright 2015 ANSSI, Author Thomas Calderon + * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_SSPI_KERBEROS_PRIVATE_H +#define FREERDP_SSPI_KERBEROS_PRIVATE_H + +#include <winpr/sspi.h> +#include <winpr/windows.h> + +#include "../sspi.h" +#include "../../log.h" + +#ifdef WITH_GSSAPI +#include <krb5.h> +#include <gssapi.h> +#endif + +typedef struct _KRB_CONTEXT KRB_CONTEXT; + +#endif /* FREERDP_SSPI_KERBEROS_PRIVATE_H */ diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c index 376eba8..e6ce48a 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm.c @@ -41,9 +41,9 @@ #define WINPR_KEY "Software\\"FREERDP_VENDOR_STRING \ "\\"FREERDP_PRODUCT_STRING"\\WinPR\\NTLM" -char* NTLM_PACKAGE_NAME = "NTLM"; +static const char* NTLM_PACKAGE_NAME = "NTLM"; -int ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation) +static int ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation) { int status; char* ws = Workstation; @@ -90,7 +90,7 @@ int ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation) return 1; } -int ntlm_SetContextServicePrincipalNameW(NTLM_CONTEXT* context, LPWSTR ServicePrincipalName) +static int ntlm_SetContextServicePrincipalNameW(NTLM_CONTEXT* context, LPWSTR ServicePrincipalName) { if (!ServicePrincipalName) { @@ -110,7 +110,7 @@ int ntlm_SetContextServicePrincipalNameW(NTLM_CONTEXT* context, LPWSTR ServicePr return 1; } -int ntlm_SetContextServicePrincipalNameA(NTLM_CONTEXT* context, char* ServicePrincipalName) +static int ntlm_SetContextServicePrincipalNameA(NTLM_CONTEXT* context, char* ServicePrincipalName) { int status; context->ServicePrincipalName.Buffer = NULL; @@ -124,7 +124,7 @@ int ntlm_SetContextServicePrincipalNameA(NTLM_CONTEXT* context, char* ServicePri return 1; } -int ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName) +static int ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName) { int status; char* name = TargetName; @@ -178,7 +178,7 @@ int ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName) return 1; } -NTLM_CONTEXT* ntlm_ContextNew() +static NTLM_CONTEXT* ntlm_ContextNew(void) { HKEY hKey; LONG status; @@ -274,7 +274,7 @@ NTLM_CONTEXT* ntlm_ContextNew() return context; } -void ntlm_ContextFree(NTLM_CONTEXT* context) +static void ntlm_ContextFree(NTLM_CONTEXT* context) { if (!context) return; @@ -293,7 +293,7 @@ void ntlm_ContextFree(NTLM_CONTEXT* context) free(context); } -SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, +static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) @@ -326,7 +326,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, +static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) @@ -359,7 +359,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential) +static SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential) { SSPI_CREDENTIALS* credentials; @@ -375,7 +375,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential) return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW(PCredHandle phCredential, +static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) { if (ulAttribute == SECPKG_CRED_ATTR_NAMES) @@ -386,7 +386,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW(PCredHandle phCredent return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(PCredHandle phCredential, +static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) { return ntlm_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer); @@ -395,7 +395,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(PCredHandle phCredent /** * @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa374707 */ -SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, +static SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) @@ -502,12 +502,12 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, return SEC_E_OUT_OF_SEQUENCE; } -SECURITY_STATUS SEC_ENTRY ntlm_ImpersonateSecurityContext(PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY ntlm_ImpersonateSecurityContext(PCtxtHandle phContext) { return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredential, +static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, @@ -537,11 +537,17 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti if (context->Workstation.Length < 1) { if (ntlm_SetContextWorkstation(context, NULL) < 0) + { + ntlm_ContextFree(context); return SEC_E_INTERNAL_ERROR; + } } if (ntlm_SetContextServicePrincipalNameW(context, pszTargetName) < 0) + { + ntlm_ContextFree(context); return SEC_E_INTERNAL_ERROR; + } sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NTLM_PACKAGE_NAME); @@ -623,7 +629,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti /** * @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa375512%28v=vs.85%29.aspx */ -SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredential, +static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, @@ -644,7 +650,8 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti return status; } -SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken) +static SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext, + PSecBufferDesc pToken) { NTLM_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; @@ -663,7 +670,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext, PSecBuff /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375354 */ -SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext) { NTLM_CONTEXT* context; context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); @@ -675,7 +682,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext) return SEC_E_OK; } -SECURITY_STATUS ntlm_computeProofValue(NTLM_CONTEXT *ntlm, SecBuffer *ntproof) +SECURITY_STATUS ntlm_computeProofValue(NTLM_CONTEXT* ntlm, SecBuffer* ntproof) { BYTE* blob; SecBuffer* target = &ntlm->ChallengeTargetInfo; @@ -683,33 +690,29 @@ SECURITY_STATUS ntlm_computeProofValue(NTLM_CONTEXT *ntlm, SecBuffer *ntproof) if (!sspi_SecBufferAlloc(ntproof, 36 + target->cbBuffer)) return SEC_E_INSUFFICIENT_MEMORY; - blob = (BYTE *)ntproof->pvBuffer; - + blob = (BYTE*)ntproof->pvBuffer; CopyMemory(blob, ntlm->ServerChallenge, 8); /* Server challenge. */ blob[8] = 1; /* Response version. */ blob[9] = 1; /* Highest response version understood by the client. */ /* Reserved 6B. */ - CopyMemory(&blob[16], ntlm->Timestamp, 8); /* Time. */ CopyMemory(&blob[24], ntlm->ClientChallenge, 8); /* Client challenge. */ /* Reserved 4B. */ /* Server name. */ CopyMemory(&blob[36], target->pvBuffer, target->cbBuffer); - return SEC_E_OK; - } -SECURITY_STATUS ntlm_computeMicValue(NTLM_CONTEXT *ntlm, SecBuffer *micvalue) +SECURITY_STATUS ntlm_computeMicValue(NTLM_CONTEXT* ntlm, SecBuffer* micvalue) { BYTE* blob; ULONG msgSize = ntlm->NegotiateMessage.cbBuffer + ntlm->ChallengeMessage.cbBuffer + - ntlm->AuthenticateMessage.cbBuffer; + ntlm->AuthenticateMessage.cbBuffer; if (!sspi_SecBufferAlloc(micvalue, msgSize)) return SEC_E_INSUFFICIENT_MEMORY; - blob = (BYTE *) micvalue->pvBuffer; + blob = (BYTE*) micvalue->pvBuffer; CopyMemory(blob, ntlm->NegotiateMessage.pvBuffer, ntlm->NegotiateMessage.cbBuffer); blob += ntlm->NegotiateMessage.cbBuffer; CopyMemory(blob, ntlm->ChallengeMessage.pvBuffer, ntlm->ChallengeMessage.cbBuffer); @@ -717,14 +720,14 @@ SECURITY_STATUS ntlm_computeMicValue(NTLM_CONTEXT *ntlm, SecBuffer *micvalue) CopyMemory(blob, ntlm->AuthenticateMessage.pvBuffer, ntlm->AuthenticateMessage.cbBuffer); blob += ntlm->MessageIntegrityCheckOffset; ZeroMemory(blob, 16); - return SEC_E_OK; } /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa379337/ */ -SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, +static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer) { NTLM_CONTEXT* context; @@ -741,9 +744,10 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, UL { SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer; ContextSizes->cbMaxToken = 2010; - ContextSizes->cbMaxSignature = 16; - ContextSizes->cbBlockSize = 0; - ContextSizes->cbSecurityTrailer = 16; + ContextSizes->cbMaxSignature = 16; /* the size of expected signature is 16 bytes */ + ContextSizes->cbBlockSize = 0; /* no padding */ + ContextSizes->cbSecurityTrailer = 16; /* no security trailer appended in NTLM + contrary to Kerberos */ return SEC_E_OK; } else if (ulAttribute == SECPKG_ATTR_AUTH_IDENTITY) @@ -820,13 +824,15 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, UL return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, +static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer) { return ntlm_QueryContextAttributesW(phContext, ulAttribute, pBuffer); } -SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, +static SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesW(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) { NTLM_CONTEXT* context; @@ -956,18 +962,19 @@ SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesW(PCtxtHandle phContext, ULON return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, +static SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesA(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) { return ntlm_SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer); } -SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext) { return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, +static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) { int index; @@ -1055,7 +1062,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, +static SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) { int index; @@ -1151,13 +1158,14 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP, +static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) { return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, +static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, + PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) { return SEC_E_UNSUPPORTED_FUNCTION; @@ -1237,9 +1245,9 @@ const SecPkgInfoA NTLM_SecPkgInfoA = "NTLM Security Package" /* Comment */ }; -WCHAR NTLM_SecPkgInfoW_Name[] = { 'N', 'T', 'L', 'M', '\0' }; +static const WCHAR NTLM_SecPkgInfoW_Name[] = { 'N', 'T', 'L', 'M', '\0' }; -WCHAR NTLM_SecPkgInfoW_Comment[] = +static const WCHAR NTLM_SecPkgInfoW_Comment[] = { 'N', 'T', 'L', 'M', ' ', 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', ' ', diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.h b/winpr/libwinpr/sspi/NTLM/ntlm.h index af0690b..f12d9d5 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.h +++ b/winpr/libwinpr/sspi/NTLM/ntlm.h @@ -275,14 +275,12 @@ struct _NTLM_CONTEXT BYTE MessageIntegrityCheck[16]; UINT32 MessageIntegrityCheckOffset; psPeerComputeNtlmHash HashCallback; - void *HashCallbackArg; + void* HashCallbackArg; }; typedef struct _NTLM_CONTEXT NTLM_CONTEXT; -NTLM_CONTEXT* ntlm_ContextNew(void); -void ntlm_ContextFree(NTLM_CONTEXT* context); -SECURITY_STATUS ntlm_computeProofValue(NTLM_CONTEXT *ntlm, SecBuffer *ntproof); -SECURITY_STATUS ntlm_computeMicValue(NTLM_CONTEXT *ntlm, SecBuffer *micvalue); +SECURITY_STATUS ntlm_computeProofValue(NTLM_CONTEXT* ntlm, SecBuffer* ntproof); +SECURITY_STATUS ntlm_computeMicValue(NTLM_CONTEXT* ntlm, SecBuffer* micvalue); #ifdef WITH_DEBUG_NLA #define WITH_DEBUG_NTLM diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c index bfb3ec4..68ecc1f 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c @@ -340,7 +340,6 @@ int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context) int length; ULONG AvPairsCount; ULONG AvPairsLength; - LONG AvPairListSize; NTLM_AV_PAIR* pAvPairList; UNICODE_STRING NbDomainName; UNICODE_STRING NbComputerName; @@ -375,7 +374,6 @@ int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context) return -1; pAvPairList = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer; - AvPairListSize = (ULONG) context->ChallengeTargetInfo.cbBuffer; ntlm_av_pair_list_init(pAvPairList); ntlm_av_pair_add(pAvPairList, MsvAvNbDomainName, (PBYTE) NbDomainName.Buffer, NbDomainName.Length); ntlm_av_pair_add(pAvPairList, MsvAvNbComputerName, (PBYTE) NbComputerName.Buffer, diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c index a1130c4..9a98eb3 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c @@ -38,10 +38,14 @@ const char LM_MAGIC[] = "KGS!@#$%"; -static const char NTLM_CLIENT_SIGN_MAGIC[] = "session key to client-to-server signing key magic constant"; -static const char NTLM_SERVER_SIGN_MAGIC[] = "session key to server-to-client signing key magic constant"; -static const char NTLM_CLIENT_SEAL_MAGIC[] = "session key to client-to-server sealing key magic constant"; -static const char NTLM_SERVER_SEAL_MAGIC[] = "session key to server-to-client sealing key magic constant"; +static const char NTLM_CLIENT_SIGN_MAGIC[] = + "session key to client-to-server signing key magic constant"; +static const char NTLM_SERVER_SIGN_MAGIC[] = + "session key to server-to-client signing key magic constant"; +static const char NTLM_CLIENT_SEAL_MAGIC[] = + "session key to client-to-server sealing key magic constant"; +static const char NTLM_SERVER_SEAL_MAGIC[] = + "session key to server-to-client sealing key magic constant"; static const BYTE NTLM_NULL_BUFFER[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -111,7 +115,7 @@ void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo) WLog_INFO(TAG, "\tProductMinorVersion: %"PRIu8"", versionInfo->ProductMinorVersion); WLog_INFO(TAG, "\tProductBuild: %"PRIu16"", versionInfo->ProductBuild); WLog_INFO(TAG, "\tReserved: 0x%02"PRIX8"%02"PRIX8"%02"PRIX8"", versionInfo->Reserved[0], - versionInfo->Reserved[1], versionInfo->Reserved[2]); + versionInfo->Reserved[1], versionInfo->Reserved[2]); WLog_INFO(TAG, "\tNTLMRevisionCurrent: 0x%02"PRIX8"", versionInfo->NTLMRevisionCurrent); } @@ -195,14 +199,14 @@ int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) WINPR_SAM* sam; WINPR_SAM_ENTRY* entry; SSPI_CREDENTIALS* credentials = context->credentials; - sam = SamOpen(context->SamFile, TRUE); if (!sam) return -1; - entry = SamLookupUserW(sam, (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, - (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2); + entry = SamLookupUserW(sam, (LPWSTR) credentials->identity.User, + credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2); if (entry) { @@ -211,15 +215,16 @@ int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) winpr_HexDump(TAG, WLOG_DEBUG, entry->NtHash, 16); #endif NTOWFv2FromHashW(entry->NtHash, - (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, - (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, - (BYTE*) hash); + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, + (BYTE*) hash); SamFreeEntry(sam, entry); SamClose(sam); return 1; } - entry = SamLookupUserW(sam, (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, NULL, 0); + entry = SamLookupUserW(sam, (LPWSTR) credentials->identity.User, + credentials->identity.UserLength * 2, NULL, 0); if (entry) { @@ -228,9 +233,9 @@ int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) winpr_HexDump(TAG, WLOG_DEBUG, entry->NtHash, 16); #endif NTOWFv2FromHashW(entry->NtHash, - (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, - (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, - (BYTE*) hash); + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, + (BYTE*) hash); SamFreeEntry(sam, entry); SamClose(sam); return 1; @@ -255,7 +260,7 @@ int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash) /* Password contains a password hash of length (PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR) */ PasswordHashLength = credentials->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR; status = ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR) credentials->identity.Password, - PasswordHashLength, &PasswordHash, 0, NULL, NULL); + PasswordHashLength, &PasswordHash, 0, NULL, NULL); if (status <= 0) return -1; @@ -276,6 +281,28 @@ int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash) int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) { SSPI_CREDENTIALS* credentials = context->credentials; +#ifdef WITH_DEBUG_NTLM + + if (credentials) + { + WLog_DBG(TAG, "Password (length = %"PRIu32")", credentials->identity.PasswordLength * 2); + winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.Password, + credentials->identity.PasswordLength * 2); + WLog_DBG(TAG, "Username (length = %"PRIu32")", credentials->identity.UserLength * 2); + winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.User, + credentials->identity.UserLength * 2); + WLog_DBG(TAG, "Domain (length = %"PRIu32")", credentials->identity.DomainLength * 2); + winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.Domain, + credentials->identity.DomainLength * 2); + } + else + WLog_DBG(TAG, "Strange, NTLM_CONTEXT is missing valid credentials..."); + + WLog_DBG(TAG, "Workstation (length = %"PRIu16")", 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, WINPR_MD5_DIGEST_LENGTH); +#endif if (memcmp(context->NtlmV2Hash, NTLM_NULL_BUFFER, 16) != 0) return 1; @@ -283,9 +310,9 @@ int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) if (memcmp(context->NtlmHash, NTLM_NULL_BUFFER, 16) != 0) { NTOWFv2FromHashW(context->NtlmHash, - (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, - (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, - (BYTE*) hash); + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, + (BYTE*) hash); } else if (credentials->identity.PasswordLength > 256) { @@ -294,15 +321,15 @@ int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) return -1; NTOWFv2FromHashW(context->NtlmHash, - (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, - (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, - (BYTE*) hash); + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, + (BYTE*) hash); } else if (credentials->identity.Password) { NTOWFv2W((LPWSTR) credentials->identity.Password, credentials->identity.PasswordLength * 2, - (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, - (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, (BYTE*) hash); + (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, + (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, (BYTE*) hash); } else if (context->HashCallback) { @@ -319,9 +346,8 @@ int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) } ret = context->HashCallback(context->HashCallbackArg, &credentials->identity, &proofValue, - context->EncryptedRandomSessionKey, context->MessageIntegrityCheck, &micValue, - hash); - + context->EncryptedRandomSessionKey, context->MessageIntegrityCheck, &micValue, + hash); sspi_SecBufferFree(&proofValue); sspi_SecBufferFree(&micValue); return ret ? 1 : -1; @@ -363,8 +389,8 @@ 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, WINPR_MD5_DIGEST_LENGTH, - (BYTE*) value, WINPR_MD5_DIGEST_LENGTH, - (BYTE*) response, 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; @@ -384,8 +410,6 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) SecBuffer ntlm_v2_temp; SecBuffer ntlm_v2_temp_chal; PSecBuffer TargetInfo; - SSPI_CREDENTIALS* credentials; - credentials = context->credentials; TargetInfo = &context->ChallengeTargetInfo; if (!sspi_SecBufferAlloc(&ntlm_v2_temp, TargetInfo->cbBuffer + 28)) @@ -398,18 +422,6 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) if (ntlm_compute_ntlm_v2_hash(context, (BYTE*) context->NtlmV2Hash) < 0) return -1; -#ifdef WITH_DEBUG_NTLM - WLog_DBG(TAG, "Password (length = %"PRIu32")", credentials->identity.PasswordLength * 2); - winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.Password, credentials->identity.PasswordLength * 2); - WLog_DBG(TAG, "Username (length = %"PRIu32")", credentials->identity.UserLength * 2); - winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.User, credentials->identity.UserLength * 2); - WLog_DBG(TAG, "Domain (length = %"PRIu32")", credentials->identity.DomainLength * 2); - winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.Domain, credentials->identity.DomainLength * 2); - WLog_DBG(TAG, "Workstation (length = %"PRIu16")", 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, WINPR_MD5_DIGEST_LENGTH); -#endif /* Construct temp */ blob[0] = 1; /* RespType (1 byte) */ blob[1] = 1; /* HighRespType (1 byte) */ @@ -433,8 +445,8 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); 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); + (BYTE*) ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, + (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH); /* NtChallengeResponse, Concatenate NTProofStr with temp */ @@ -446,8 +458,8 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) 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, WINPR_MD5_DIGEST_LENGTH, - (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH, - (BYTE*) context->SessionBaseKey, 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; @@ -464,6 +476,7 @@ 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_New(key, 16); + if (rc4) { winpr_RC4_Update(rc4, length, plaintext, ciphertext); @@ -534,7 +547,8 @@ void ntlm_generate_exported_session_key(NTLM_CONTEXT* context) void ntlm_encrypt_random_session_key(NTLM_CONTEXT* context) { /* In NTLMv2, EncryptedRandomSessionKey is the ExportedSessionKey RC4-encrypted with the KeyExchangeKey */ - ntlm_rc4k(context->KeyExchangeKey, 16, context->RandomSessionKey, context->EncryptedRandomSessionKey); + ntlm_rc4k(context->KeyExchangeKey, 16, context->RandomSessionKey, + context->EncryptedRandomSessionKey); } /** @@ -553,7 +567,8 @@ void ntlm_decrypt_random_session_key(NTLM_CONTEXT* context) * Set RandomSessionKey to KeyExchangeKey */ if (context->NegotiateKeyExchange) - ntlm_rc4k(context->KeyExchangeKey, 16, context->EncryptedRandomSessionKey, context->RandomSessionKey); + ntlm_rc4k(context->KeyExchangeKey, 16, context->EncryptedRandomSessionKey, + context->RandomSessionKey); else CopyMemory(context->RandomSessionKey, context->KeyExchangeKey, 16); } @@ -570,7 +585,6 @@ int ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic, { int length; BYTE* value; - length = WINPR_MD5_DIGEST_LENGTH + sign_magic->cbBuffer; value = (BYTE*) malloc(length); @@ -586,6 +600,7 @@ int ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic, free(value); return -1; } + free(value); return 1; } @@ -639,7 +654,8 @@ int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, CopyMemory(p, exported_session_key, WINPR_MD5_DIGEST_LENGTH); CopyMemory(&p[WINPR_MD5_DIGEST_LENGTH], seal_magic->pvBuffer, seal_magic->cbBuffer); - if (!winpr_Digest(WINPR_MD_MD5, buffer.pvBuffer, buffer.cbBuffer, sealing_key, WINPR_MD5_DIGEST_LENGTH)) + if (!winpr_Digest(WINPR_MD_MD5, buffer.pvBuffer, buffer.cbBuffer, sealing_key, + WINPR_MD5_DIGEST_LENGTH)) { sspi_SecBufferFree(&buffer); return -1; @@ -710,7 +726,6 @@ void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context) * Compute the HMAC-MD5 hash of ConcatenationOf(NEGOTIATE_MESSAGE, * CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE) using the ExportedSessionKey */ - WINPR_HMAC_CTX* hmac = winpr_HMAC_New(); if (!hmac) @@ -718,10 +733,14 @@ void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context) if (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_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_MD5_DIGEST_LENGTH); } + winpr_HMAC_Free(hmac); } diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_message.c b/winpr/libwinpr/sspi/NTLM/ntlm_message.c index 96e8e96..b5d7fe3 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_message.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_message.c @@ -192,7 +192,7 @@ void ntlm_print_message_fields(NTLM_MESSAGE_FIELDS* fields, const char* name) SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { wStream* s; - int length; + size_t length; NTLM_NEGOTIATE_MESSAGE* message; message = &context->NEGOTIATE_MESSAGE; ZeroMemory(message, sizeof(NTLM_NEGOTIATE_MESSAGE)); @@ -261,7 +261,7 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { wStream* s; - int length; + size_t length; NTLM_NEGOTIATE_MESSAGE* message; message = &context->NEGOTIATE_MESSAGE; ZeroMemory(message, sizeof(NTLM_NEGOTIATE_MESSAGE)); @@ -503,7 +503,7 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { wStream* s; - int length; + size_t length; UINT32 PayloadOffset; NTLM_CHALLENGE_MESSAGE* message; message = &context->CHALLENGE_MESSAGE; @@ -593,7 +593,7 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { wStream* s; - int length; + size_t length; UINT32 flags; NTLM_AV_PAIR* AvFlags; UINT32 PayloadBufferOffset; @@ -784,7 +784,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { wStream* s; - int length; + size_t length; UINT32 PayloadBufferOffset; NTLM_AUTHENTICATE_MESSAGE* message; SSPI_CREDENTIALS* credentials = context->credentials; diff --git a/winpr/libwinpr/sspi/Negotiate/negotiate.c b/winpr/libwinpr/sspi/Negotiate/negotiate.c index 5458208..18e42c8 100644 --- a/winpr/libwinpr/sspi/Negotiate/negotiate.c +++ b/winpr/libwinpr/sspi/Negotiate/negotiate.c @@ -3,6 +3,7 @@ * Negotiate Security Package * * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +24,7 @@ #include <winpr/crt.h> #include <winpr/sspi.h> +#include <winpr/tchar.h> #include "negotiate.h" @@ -33,12 +35,63 @@ extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA; extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW; -char* NEGOTIATE_PACKAGE_NAME = "Negotiate"; +extern const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA; +extern const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW; -NEGOTIATE_CONTEXT* negotiate_ContextNew() +#ifdef WITH_GSSAPI +static BOOL ErrorInitContextKerberos = FALSE; +#else +static BOOL ErrorInitContextKerberos = TRUE; +#endif + +const SecPkgInfoA NEGOTIATE_SecPkgInfoA = +{ + 0x00083BB3, /* fCapabilities */ + 1, /* wVersion */ + 0x0009, /* wRPCID */ + 0x00002FE0, /* cbMaxToken */ + "Negotiate", /* Name */ + "Microsoft Package Negotiator" /* Comment */ +}; + +static const WCHAR NEGOTIATE_SecPkgInfoW_Name[] = { 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'e', '\0' }; + +static const WCHAR NEGOTIATE_SecPkgInfoW_Comment[] = +{ + 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', ' ', + 'P', 'a', 'c', 'k', 'a', 'g', 'e', ' ', + 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'o', 'r', '\0' +}; + +const SecPkgInfoW NEGOTIATE_SecPkgInfoW = +{ + 0x00083BB3, /* fCapabilities */ + 1, /* wVersion */ + 0x0009, /* wRPCID */ + 0x00002FE0, /* cbMaxToken */ + NEGOTIATE_SecPkgInfoW_Name, /* Name */ + NEGOTIATE_SecPkgInfoW_Comment /* Comment */ +}; + +static void negotiate_SetSubPackage(NEGOTIATE_CONTEXT* context, const TCHAR* name) +{ + if (_tcsnccmp(name, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0) + { + context->sspiA = (SecurityFunctionTableA*) &KERBEROS_SecurityFunctionTableA; + context->sspiW = (SecurityFunctionTableW*) &KERBEROS_SecurityFunctionTableW; + context->kerberos = TRUE; + } + else + { + context->sspiA = (SecurityFunctionTableA*) &NTLM_SecurityFunctionTableA; + context->sspiW = (SecurityFunctionTableW*) &NTLM_SecurityFunctionTableW; + context->kerberos = FALSE; + } +} + +static NEGOTIATE_CONTEXT* negotiate_ContextNew(void) { NEGOTIATE_CONTEXT* context; - context = (NEGOTIATE_CONTEXT*) calloc(1, sizeof(NEGOTIATE_CONTEXT)); if (!context) @@ -46,28 +99,24 @@ NEGOTIATE_CONTEXT* negotiate_ContextNew() context->NegotiateFlags = 0; context->state = NEGOTIATE_STATE_INITIAL; - SecInvalidateHandle(&(context->SubContext)); - - context->sspiA = (SecurityFunctionTableA*) &NTLM_SecurityFunctionTableA; - context->sspiW = (SecurityFunctionTableW*) &NTLM_SecurityFunctionTableW; - + negotiate_SetSubPackage(context, KERBEROS_SSP_NAME); return context; } -void negotiate_ContextFree(NEGOTIATE_CONTEXT* context) +static void negotiate_ContextFree(NEGOTIATE_CONTEXT* context) { free(context); } -SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, - SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SECURITY_STATUS status; NEGOTIATE_CONTEXT* context; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -78,24 +127,54 @@ SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCre return SEC_E_INTERNAL_ERROR; sspi_SecureHandleSetLowerPointer(phNewContext, context); - sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME); + sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGO_SSP_NAME); } - status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext), - pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), - pOutput, pfContextAttr, ptsExpiry); + /* if Kerberos has previously failed or WITH_GSSAPI is not defined, we use NTLM directly */ + if (ErrorInitContextKerberos == FALSE) + { + if (!pInput) + { + negotiate_SetSubPackage(context, KERBEROS_SSP_NAME); + } + + status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext), + pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), + pOutput, pfContextAttr, ptsExpiry); + + if (status == SEC_E_NO_CREDENTIALS) + { + WLog_WARN(TAG, "No Kerberos credentials. Retry with NTLM"); + ErrorInitContextKerberos = TRUE; + context->sspiA->DeleteSecurityContext(&(context->SubContext)); + negotiate_ContextFree(context); + return status; + } + } + else + { + if (!pInput) + { + context->sspiA->DeleteSecurityContext(&(context->SubContext)); + negotiate_SetSubPackage(context, NTLM_SSP_NAME); + } + + status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext), + pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), + pOutput, pfContextAttr, ptsExpiry); + } return status; } -SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, - SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SECURITY_STATUS status; NEGOTIATE_CONTEXT* context; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -106,23 +185,53 @@ SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCre return SEC_E_INTERNAL_ERROR; sspi_SecureHandleSetLowerPointer(phNewContext, context); - sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME); + sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGO_SSP_NAME); } - status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext), - pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), - pOutput, pfContextAttr, ptsExpiry); + /* if Kerberos has previously failed or WITH_GSSAPI is not defined, we use NTLM directly */ + if (ErrorInitContextKerberos == FALSE) + { + if (!pInput) + { + negotiate_SetSubPackage(context, KERBEROS_SSP_NAME); + } + + status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext), + pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), + pOutput, pfContextAttr, ptsExpiry); + + if (status == SEC_E_NO_CREDENTIALS) + { + WLog_WARN(TAG, "No Kerberos credentials. Retry with NTLM"); + ErrorInitContextKerberos = TRUE; + context->sspiA->DeleteSecurityContext(&(context->SubContext)); + negotiate_ContextFree(context); + return status; + } + } + else + { + if (!pInput) + { + context->sspiA->DeleteSecurityContext(&(context->SubContext)); + negotiate_SetSubPackage(context, NTLM_SSP_NAME); + } + + status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext), + pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), + pOutput, pfContextAttr, ptsExpiry); + } return status; } -SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, - PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) +static SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredential, + PCtxtHandle phContext, + PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) { SECURITY_STATUS status; NEGOTIATE_CONTEXT* context; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -133,26 +242,28 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredenti return SEC_E_INTERNAL_ERROR; sspi_SecureHandleSetLowerPointer(phNewContext, context); - sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME); + sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGO_SSP_NAME); } + negotiate_SetSubPackage(context, NTLM_SSP_NAME); /* server-side Kerberos not yet implemented */ status = context->sspiA->AcceptSecurityContext(phCredential, &(context->SubContext), - pInput, fContextReq, TargetDataRep, &(context->SubContext), - pOutput, pfContextAttr, ptsTimeStamp); + pInput, fContextReq, TargetDataRep, &(context->SubContext), + pOutput, pfContextAttr, ptsTimeStamp); if (status != SEC_E_OK) { WLog_WARN(TAG, "AcceptSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } + return status; } -SECURITY_STATUS SEC_ENTRY negotiate_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken) +static SECURITY_STATUS SEC_ENTRY negotiate_CompleteAuthToken(PCtxtHandle phContext, + PSecBufferDesc pToken) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -164,11 +275,10 @@ SECURITY_STATUS SEC_ENTRY negotiate_CompleteAuthToken(PCtxtHandle phContext, PSe return status; } -SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle phContext) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -178,15 +288,13 @@ SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle phContext) status = context->sspiW->DeleteSecurityContext(&(context->SubContext)); negotiate_ContextFree(context); - return status; } -SECURITY_STATUS SEC_ENTRY negotiate_ImpersonateSecurityContext(PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY negotiate_ImpersonateSecurityContext(PCtxtHandle phContext) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -198,11 +306,10 @@ SECURITY_STATUS SEC_ENTRY negotiate_ImpersonateSecurityContext(PCtxtHandle phCon return status; } -SECURITY_STATUS SEC_ENTRY negotiate_RevertSecurityContext(PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY negotiate_RevertSecurityContext(PCtxtHandle phContext) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -214,11 +321,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_RevertSecurityContext(PCtxtHandle phContext) return status; } -SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -233,11 +340,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContex return status; } -SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -252,11 +359,12 @@ SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContex return status; } -SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) +static SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, + ULONG ulAttribute, + void* pBuffer, ULONG cbBuffer) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -266,16 +374,18 @@ SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, return SEC_E_INSUFFICIENT_MEMORY; if (context->sspiW->SetContextAttributesW) - status = context->sspiW->SetContextAttributesW(&(context->SubContext), ulAttribute, pBuffer, cbBuffer); + status = context->sspiW->SetContextAttributesW(&(context->SubContext), ulAttribute, pBuffer, + cbBuffer); return status; } -SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) +static SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, + ULONG ulAttribute, + void* pBuffer, ULONG cbBuffer) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -285,21 +395,23 @@ SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, return SEC_E_INSUFFICIENT_MEMORY; if (context->sspiA->SetContextAttributesA) - status = context->sspiA->SetContextAttributesA(&(context->SubContext), ulAttribute, pBuffer, cbBuffer); + status = context->sspiA->SetContextAttributesA(&(context->SubContext), ulAttribute, pBuffer, + cbBuffer); return status; } -SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, + SEC_WCHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SSPI_CREDENTIALS* credentials; SEC_WINNT_AUTH_IDENTITY* identity; if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && - (fCredentialUse != SECPKG_CRED_INBOUND) && - (fCredentialUse != SECPKG_CRED_BOTH)) + (fCredentialUse != SECPKG_CRED_INBOUND) && + (fCredentialUse != SECPKG_CRED_BOTH)) { return SEC_E_INVALID_PARAMETER; } @@ -312,28 +424,27 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrin credentials->fCredentialUse = fCredentialUse; credentials->pGetKeyFn = pGetKeyFn; credentials->pvGetKeyArgument = pvGetKeyArgument; - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; if (identity) sspi_CopyAuthIdentity(&(credentials->identity), identity); sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); - + sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGO_SSP_NAME); return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, + SEC_CHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SSPI_CREDENTIALS* credentials; SEC_WINNT_AUTH_IDENTITY* identity; if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && - (fCredentialUse != SECPKG_CRED_INBOUND) && - (fCredentialUse != SECPKG_CRED_BOTH)) + (fCredentialUse != SECPKG_CRED_INBOUND) && + (fCredentialUse != SECPKG_CRED_BOTH)) { return SEC_E_INVALID_PARAMETER; } @@ -346,29 +457,29 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrinc credentials->fCredentialUse = fCredentialUse; credentials->pGetKeyFn = pGetKeyFn; credentials->pvGetKeyArgument = pvGetKeyArgument; - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; if (identity) sspi_CopyAuthIdentity(&(credentials->identity), identity); sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); - + sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGO_SSP_NAME); return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredential) +static SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredential) { SSPI_CREDENTIALS* credentials; @@ -381,15 +492,15 @@ SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredenti return SEC_E_INVALID_HANDLE; sspi_CredentialsFree(credentials); - + sspi_SecureHandleInvalidate(phCredential); return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +static SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (context->sspiW->EncryptMessage) @@ -398,11 +509,12 @@ SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG return status; } -SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +static SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, + PSecBufferDesc pMessage, + ULONG MessageSeqNo, ULONG* pfQOP) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (context->sspiW->DecryptMessage) @@ -411,11 +523,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBu return status; } -SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +static SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (context->sspiW->MakeSignature) @@ -424,11 +536,12 @@ SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG f return status; } -SECURITY_STATUS SEC_ENTRY negotiate_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +static SECURITY_STATUS SEC_ENTRY negotiate_VerifySignature(PCtxtHandle phContext, + PSecBufferDesc pMessage, + ULONG MessageSeqNo, ULONG* pfQOP) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (context->sspiW->VerifySignature) @@ -501,31 +614,3 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW = negotiate_SetContextAttributesW, /* SetContextAttributes */ }; -const SecPkgInfoA NEGOTIATE_SecPkgInfoA = -{ - 0x00083BB3, /* fCapabilities */ - 1, /* wVersion */ - 0x0009, /* wRPCID */ - 0x00002FE0, /* cbMaxToken */ - "Negotiate", /* Name */ - "Microsoft Package Negotiator" /* Comment */ -}; - -WCHAR NEGOTIATE_SecPkgInfoW_Name[] = { 'N','e','g','o','t','i','a','t','e','\0' }; - -WCHAR NEGOTIATE_SecPkgInfoW_Comment[] = -{ - 'M','i','c','r','o','s','o','f','t',' ', - 'P','a','c','k','a','g','e',' ', - 'N','e','g','o','t','i','a','t','o','r','\0' -}; - -const SecPkgInfoW NEGOTIATE_SecPkgInfoW = -{ - 0x00083BB3, /* fCapabilities */ - 1, /* wVersion */ - 0x0009, /* wRPCID */ - 0x00002FE0, /* cbMaxToken */ - NEGOTIATE_SecPkgInfoW_Name, /* Name */ - NEGOTIATE_SecPkgInfoW_Comment /* Comment */ -}; diff --git a/winpr/libwinpr/sspi/Negotiate/negotiate.h b/winpr/libwinpr/sspi/Negotiate/negotiate.h index fe6375e..b18c0e7 100644 --- a/winpr/libwinpr/sspi/Negotiate/negotiate.h +++ b/winpr/libwinpr/sspi/Negotiate/negotiate.h @@ -44,13 +44,11 @@ struct _NEGOTIATE_CONTEXT CtxtHandle SubContext; + BOOL kerberos; SecurityFunctionTableA* sspiA; SecurityFunctionTableW* sspiW; }; typedef struct _NEGOTIATE_CONTEXT NEGOTIATE_CONTEXT; -NEGOTIATE_CONTEXT* negotiate_ContextNew(void); -void negotiate_ContextFree(NEGOTIATE_CONTEXT* context); - #endif /* WINPR_SSPI_NEGOTIATE_PRIVATE_H */ diff --git a/winpr/libwinpr/sspi/Schannel/schannel.c b/winpr/libwinpr/sspi/Schannel/schannel.c index bff2e4c..a916b69 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.c +++ b/winpr/libwinpr/sspi/Schannel/schannel.c @@ -3,7 +3,7 @@ * Schannel Security Package * * Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com> - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -33,8 +33,8 @@ char* SCHANNEL_PACKAGE_NAME = "Schannel"; SCHANNEL_CONTEXT* schannel_ContextNew() { SCHANNEL_CONTEXT* context; - context = (SCHANNEL_CONTEXT*) calloc(1, sizeof(SCHANNEL_CONTEXT)); + if (!context) return NULL; @@ -55,16 +55,13 @@ void schannel_ContextFree(SCHANNEL_CONTEXT* context) return; schannel_openssl_free(context->openssl); - free(context); } SCHANNEL_CREDENTIALS* schannel_CredentialsNew() { SCHANNEL_CREDENTIALS* credentials; - credentials = (SCHANNEL_CREDENTIALS*) calloc(1, sizeof(SCHANNEL_CREDENTIALS)); - return credentials; } @@ -82,57 +79,52 @@ static ALG_ID schannel_SupportedAlgs[] = CALG_DSS_SIGN, CALG_ECDSA }; -SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { if (ulAttribute == SECPKG_ATTR_SUPPORTED_ALGS) { PSecPkgCred_SupportedAlgs SupportedAlgs = (PSecPkgCred_SupportedAlgs) pBuffer; - SupportedAlgs->cSupportedAlgs = sizeof(schannel_SupportedAlgs) / sizeof(ALG_ID); SupportedAlgs->palgSupportedAlgs = (ALG_ID*) schannel_SupportedAlgs; - return SEC_E_OK; } else if (ulAttribute == SECPKG_ATTR_CIPHER_STRENGTHS) { PSecPkgCred_CipherStrengths CipherStrengths = (PSecPkgCred_CipherStrengths) pBuffer; - CipherStrengths->dwMinimumCipherStrength = 40; CipherStrengths->dwMaximumCipherStrength = 256; - return SEC_E_OK; } else if (ulAttribute == SECPKG_ATTR_SUPPORTED_PROTOCOLS) { PSecPkgCred_SupportedProtocols SupportedProtocols = (PSecPkgCred_SupportedProtocols) pBuffer; - /* Observed SupportedProtocols: 0x208A0 */ SupportedProtocols->grbitProtocol = (SP_PROT_CLIENTS | SP_PROT_SERVERS); - return SEC_E_OK; } return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesA(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { return schannel_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer); } -SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, + SEC_WCHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SCHANNEL_CREDENTIALS* credentials; if (fCredentialUse == SECPKG_CRED_OUTBOUND) { SCHANNEL_CRED* cred; - credentials = schannel_CredentialsNew(); credentials->fCredentialUse = fCredentialUse; - cred = (SCHANNEL_CRED*) pAuthData; if (cred) @@ -142,41 +134,35 @@ SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleW(SEC_WCHAR* pszPrinc sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); sspi_SecureHandleSetUpperPointer(phCredential, (void*) SCHANNEL_PACKAGE_NAME); - return SEC_E_OK; } else if (fCredentialUse == SECPKG_CRED_INBOUND) { credentials = schannel_CredentialsNew(); credentials->fCredentialUse = fCredentialUse; - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); sspi_SecureHandleSetUpperPointer(phCredential, (void*) SCHANNEL_PACKAGE_NAME); - return SEC_E_OK; } return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, + SEC_CHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SECURITY_STATUS status; SEC_WCHAR* pszPrincipalW = NULL; SEC_WCHAR* pszPackageW = NULL; - ConvertToUnicode(CP_UTF8, 0, pszPrincipal, -1, &pszPrincipalW, 0); ConvertToUnicode(CP_UTF8, 0, pszPackage, -1, &pszPackageW, 0); - status = schannel_AcquireCredentialsHandleW(pszPrincipalW, pszPackageW, fCredentialUse, pvLogonID, - pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); - + pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); free(pszPrincipalW); free(pszPackageW); - - return SEC_E_OK; + return status; } SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(PCredHandle phCredential) @@ -192,19 +178,18 @@ SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(PCredHandle phCredentia return SEC_E_INVALID_HANDLE; schannel_CredentialsFree(credentials); - return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, - SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SECURITY_STATUS status; SCHANNEL_CONTEXT* context; SCHANNEL_CREDENTIALS* credentials; - context = sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -215,25 +200,22 @@ SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCred return SEC_E_INSUFFICIENT_MEMORY; credentials = (SCHANNEL_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); - context->server = FALSE; CopyMemory(&context->cred, &credentials->cred, sizeof(SCHANNEL_CRED)); - sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME); - schannel_openssl_client_init(context->openssl); } status = schannel_openssl_client_process_tokens(context->openssl, pInput, pOutput); - return status; } -SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, - SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SECURITY_STATUS status; SEC_WCHAR* pszTargetNameW = NULL; @@ -244,22 +226,18 @@ SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(PCredHandle phCred } status = schannel_InitializeSecurityContextW(phCredential, phContext, pszTargetNameW, fContextReq, - Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); - + Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); free(pszTargetNameW); - return status; } -SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, - PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) +SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(PCredHandle phCredential, + PCtxtHandle phContext, + PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) { SECURITY_STATUS status; SCHANNEL_CONTEXT* context; - SCHANNEL_CREDENTIALS* credentials; - - status = SEC_E_OK; context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -269,36 +247,30 @@ SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(PCredHandle phCredentia if (!context) return SEC_E_INSUFFICIENT_MEMORY; - credentials = (SCHANNEL_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); - context->server = TRUE; - sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME); - schannel_openssl_server_init(context->openssl); } status = schannel_openssl_server_process_tokens(context->openssl, pInput, pOutput); - return status; } SECURITY_STATUS SEC_ENTRY schannel_DeleteSecurityContext(PCtxtHandle phContext) { SCHANNEL_CONTEXT* context; - context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) return SEC_E_INVALID_HANDLE; schannel_ContextFree(context); - return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer) { if (!phContext) return SEC_E_INVALID_HANDLE; @@ -309,67 +281,63 @@ SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(PCtxtHandle phContext, if (ulAttribute == SECPKG_ATTR_SIZES) { SecPkgContext_Sizes* Sizes = (SecPkgContext_Sizes*) pBuffer; - Sizes->cbMaxToken = 0x6000; Sizes->cbMaxSignature = 16; Sizes->cbBlockSize = 0; Sizes->cbSecurityTrailer = 16; - return SEC_E_OK; } else if (ulAttribute == SECPKG_ATTR_STREAM_SIZES) { SecPkgContext_StreamSizes* StreamSizes = (SecPkgContext_StreamSizes*) pBuffer; - StreamSizes->cbHeader = 5; StreamSizes->cbTrailer = 36; StreamSizes->cbMaximumMessage = 0x4000; StreamSizes->cBuffers = 4; StreamSizes->cbBlockSize = 16; - return SEC_E_OK; } return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY schannel_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +SECURITY_STATUS SEC_ENTRY schannel_MakeSignature(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY schannel_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +SECURITY_STATUS SEC_ENTRY schannel_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, + ULONG MessageSeqNo, ULONG* pfQOP) { return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY schannel_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +SECURITY_STATUS SEC_ENTRY schannel_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { SECURITY_STATUS status; SCHANNEL_CONTEXT* context; - context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) return SEC_E_INVALID_HANDLE; status = schannel_openssl_encrypt_message(context->openssl, pMessage); - return status; } -SECURITY_STATUS SEC_ENTRY schannel_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +SECURITY_STATUS SEC_ENTRY schannel_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, + ULONG MessageSeqNo, ULONG* pfQOP) { SECURITY_STATUS status; SCHANNEL_CONTEXT* context; - context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) return SEC_E_INVALID_HANDLE; status = schannel_openssl_decrypt_message(context->openssl, pMessage); - return status; } @@ -447,13 +415,13 @@ const SecPkgInfoA SCHANNEL_SecPkgInfoA = "Schannel Security Package" /* Comment */ }; -WCHAR SCHANNEL_SecPkgInfoW_Name[] = { 'S','c','h','a','n','n','e','l','\0' }; +WCHAR SCHANNEL_SecPkgInfoW_Name[] = { 'S', 'c', 'h', 'a', 'n', 'n', 'e', 'l', '\0' }; WCHAR SCHANNEL_SecPkgInfoW_Comment[] = { - 'S','c','h','a','n','n','e','l',' ', - 'S','e','c','u','r','i','t','y',' ', - 'P','a','c','k','a','g','e','\0' + 'S', 'c', 'h', 'a', 'n', 'n', 'e', 'l', ' ', + 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', ' ', + 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\0' }; const SecPkgInfoW SCHANNEL_SecPkgInfoW = diff --git a/winpr/libwinpr/sspi/sspi.c b/winpr/libwinpr/sspi/sspi.c index ac5e922..e1ac00d 100644 --- a/winpr/libwinpr/sspi/sspi.c +++ b/winpr/libwinpr/sspi/sspi.c @@ -114,11 +114,13 @@ BOOL InitializeSspiModule_Native(void) static BOOL CALLBACK InitializeSspiModuleInt(PINIT_ONCE once, PVOID param, PVOID* context) { BOOL status = FALSE; +#if defined(WITH_NATIVE_SSPI) DWORD flags = 0; if (param) flags = *(DWORD*)param; +#endif sspi_GlobalInit(); g_Log = WLog_Get("com.winpr.sspi"); #if defined(WITH_NATIVE_SSPI) diff --git a/winpr/libwinpr/sspi/sspi.h b/winpr/libwinpr/sspi/sspi.h index 430efd1..0c89343 100644 --- a/winpr/libwinpr/sspi/sspi.h +++ b/winpr/libwinpr/sspi/sspi.h @@ -53,38 +53,39 @@ void sspi_SecureHandleFree(SecHandle* handle); enum SecurityFunctionTableIndex { - EnumerateSecurityPackagesIndex = 1, - Reserved1Index = 2, - QueryCredentialsAttributesIndex = 3, - AcquireCredentialsHandleIndex = 4, - FreeCredentialsHandleIndex = 5, - Reserved2Index = 6, - InitializeSecurityContextIndex = 7, - AcceptSecurityContextIndex = 8, - CompleteAuthTokenIndex = 9, - DeleteSecurityContextIndex = 10, - ApplyControlTokenIndex = 11, - QueryContextAttributesIndex = 12, - ImpersonateSecurityContextIndex = 13, - RevertSecurityContextIndex = 14, - MakeSignatureIndex = 15, - VerifySignatureIndex = 16, - FreeContextBufferIndex = 17, - QuerySecurityPackageInfoIndex = 18, - Reserved3Index = 19, - Reserved4Index = 20, - ExportSecurityContextIndex = 21, - ImportSecurityContextIndex = 22, - AddCredentialsIndex = 23, - Reserved8Index = 24, - QuerySecurityContextTokenIndex = 25, - EncryptMessageIndex = 26, - DecryptMessageIndex = 27, - SetContextAttributesIndex = 28 + EnumerateSecurityPackagesIndex = 1, + Reserved1Index = 2, + QueryCredentialsAttributesIndex = 3, + AcquireCredentialsHandleIndex = 4, + FreeCredentialsHandleIndex = 5, + Reserved2Index = 6, + InitializeSecurityContextIndex = 7, + AcceptSecurityContextIndex = 8, + CompleteAuthTokenIndex = 9, + DeleteSecurityContextIndex = 10, + ApplyControlTokenIndex = 11, + QueryContextAttributesIndex = 12, + ImpersonateSecurityContextIndex = 13, + RevertSecurityContextIndex = 14, + MakeSignatureIndex = 15, + VerifySignatureIndex = 16, + FreeContextBufferIndex = 17, + QuerySecurityPackageInfoIndex = 18, + Reserved3Index = 19, + Reserved4Index = 20, + ExportSecurityContextIndex = 21, + ImportSecurityContextIndex = 22, + AddCredentialsIndex = 23, + Reserved8Index = 24, + QuerySecurityContextTokenIndex = 25, + EncryptMessageIndex = 26, + DecryptMessageIndex = 27, + SetContextAttributesIndex = 28 }; BOOL IsSecurityStatusError(SECURITY_STATUS status); +#include "sspi_gss.h" #include "sspi_winpr.h" #endif /* WINPR_SSPI_PRIVATE_H */ diff --git a/winpr/libwinpr/sspi/sspi_gss.c b/winpr/libwinpr/sspi/sspi_gss.c new file mode 100644 index 0000000..b0794ce --- /dev/null +++ b/winpr/libwinpr/sspi/sspi_gss.c @@ -0,0 +1,1033 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Generic Security Service Application Program Interface (GSSAPI) + * + * Copyright 2015 ANSSI, Author Thomas Calderon + * Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <winpr/crt.h> +#include <winpr/library.h> + +#include "sspi_gss.h" + +#include "../log.h" +#define TAG WINPR_TAG("sspi.gss") + +static GSSAPI_FUNCTION_TABLE* g_GssApi = NULL; +static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT; + +#ifdef WITH_GSSAPI + +#include <gssapi/gssapi.h> + +GSSAPI_FUNCTION_TABLE g_GssApiLink = +{ + (fn_sspi_gss_acquire_cred) gss_acquire_cred, /* gss_acquire_cred */ + (fn_sspi_gss_release_cred) gss_release_cred, /* gss_release_cred */ + (fn_sspi_gss_init_sec_context) gss_init_sec_context, /* gss_init_sec_context */ + (fn_sspi_gss_accept_sec_context) gss_accept_sec_context, /* gss_accept_sec_context */ + (fn_sspi_gss_process_context_token) gss_process_context_token, /* gss_process_context_token */ + (fn_sspi_gss_delete_sec_context) gss_delete_sec_context, /* gss_delete_sec_context */ + (fn_sspi_gss_context_time) gss_context_time, /* gss_context_time */ + (fn_sspi_gss_get_mic) gss_get_mic, /* gss_get_mic */ + (fn_sspi_gss_verify_mic) gss_verify_mic, /* gss_verify_mic */ + (fn_sspi_gss_wrap) gss_wrap, /* gss_wrap */ + (fn_sspi_gss_unwrap) gss_unwrap, /* gss_unwrap */ + (fn_sspi_gss_display_status) gss_display_status, /* gss_display_status */ + (fn_sspi_gss_indicate_mechs) gss_indicate_mechs, /* gss_indicate_mechs */ + (fn_sspi_gss_compare_name) gss_compare_name, /* gss_compare_name */ + (fn_sspi_gss_display_name) gss_display_name, /* gss_display_name */ + (fn_sspi_gss_import_name) gss_import_name, /* gss_import_name */ + (fn_sspi_gss_release_name) gss_release_name, /* gss_release_name */ + (fn_sspi_gss_release_buffer) gss_release_buffer, /* gss_release_buffer */ + (fn_sspi_gss_release_oid_set) gss_release_oid_set, /* gss_release_oid_set */ + (fn_sspi_gss_inquire_cred) gss_inquire_cred, /* gss_inquire_cred */ + (fn_sspi_gss_inquire_context) gss_inquire_context, /* gss_inquire_context */ + (fn_sspi_gss_wrap_size_limit) gss_wrap_size_limit, /* gss_wrap_size_limit */ +#if 0 + (fn_sspi_gss_import_name_object) gss_import_name_object, /* gss_import_name_object */ + (fn_sspi_gss_export_name_object) gss_export_name_object, /* gss_export_name_object */ +#else + (fn_sspi_gss_import_name_object) NULL, /* gss_import_name_object */ + (fn_sspi_gss_export_name_object) NULL, /* gss_export_name_object */ +#endif + (fn_sspi_gss_add_cred) gss_add_cred, /* gss_add_cred */ + (fn_sspi_gss_inquire_cred_by_mech) gss_inquire_cred_by_mech, /* gss_inquire_cred_by_mech */ + (fn_sspi_gss_export_sec_context) gss_export_sec_context, /* gss_export_sec_context */ + (fn_sspi_gss_import_sec_context) gss_import_sec_context, /* gss_import_sec_context */ + (fn_sspi_gss_release_oid) gss_release_oid, /* gss_release_oid */ + (fn_sspi_gss_create_empty_oid_set) gss_create_empty_oid_set, /* gss_create_empty_oid_set */ + (fn_sspi_gss_add_oid_set_member) gss_add_oid_set_member, /* gss_add_oid_set_member */ + (fn_sspi_gss_test_oid_set_member) gss_test_oid_set_member, /* gss_test_oid_set_member */ +#if 0 + (fn_sspi_gss_str_to_oid) gss_str_to_oid, /* gss_str_to_oid */ +#else + (fn_sspi_gss_str_to_oid) NULL, /* gss_str_to_oid */ +#endif + (fn_sspi_gss_oid_to_str) gss_oid_to_str, /* gss_oid_to_str */ + (fn_sspi_gss_inquire_names_for_mech) gss_inquire_names_for_mech, /* gss_inquire_names_for_mech */ + (fn_sspi_gss_inquire_mechs_for_name) gss_inquire_mechs_for_name, /* gss_inquire_mechs_for_name */ + (fn_sspi_gss_sign) gss_sign, /* gss_sign */ + (fn_sspi_gss_verify) gss_verify, /* gss_verify */ + (fn_sspi_gss_seal) gss_seal, /* gss_seal */ + (fn_sspi_gss_unseal) gss_unseal, /* gss_unseal */ + (fn_sspi_gss_export_name) gss_export_name, /* gss_export_name */ + (fn_sspi_gss_duplicate_name) gss_duplicate_name, /* gss_duplicate_name */ + (fn_sspi_gss_canonicalize_name) gss_canonicalize_name, /* gss_canonicalize_name */ + (fn_sspi_gss_pseudo_random) gss_pseudo_random, /* gss_pseudo_random */ + (fn_sspi_gss_store_cred) gss_store_cred, /* gss_store_cred */ +#if 0 + (fn_sspi_gss_set_neg_mechs) gss_set_neg_mechs, /* gss_set_neg_mechs */ +#else + (fn_sspi_gss_set_neg_mechs) NULL, /* gss_set_neg_mechs */ +#endif +}; + +#endif + +GSSAPI_FUNCTION_TABLE* SEC_ENTRY gssApi_InitSecurityInterface(void) +{ +#ifdef WITH_GSSAPI + return &g_GssApiLink; +#else + return NULL; +#endif +} + +static BOOL CALLBACK sspi_GssApiInit(PINIT_ONCE once, PVOID param, PVOID* context) +{ + g_GssApi = gssApi_InitSecurityInterface(); + + if (!g_GssApi) + return FALSE; + + return TRUE; +} + +/** + * SSPI GSSAPI OIDs + */ + +static sspi_gss_OID_desc g_SSPI_GSS_C_NT_USER_NAME = { 10, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01" }; +static sspi_gss_OID_desc g_SSPI_GSS_C_NT_MACHINE_UID_NAME = { 10, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02" }; +static sspi_gss_OID_desc g_SSPI_GSS_C_NT_STRING_UID_NAME = { 10, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03" }; +static sspi_gss_OID_desc g_SSPI_GSS_C_NT_HOSTBASED_SERVICE_X = { 6, (void*) "\x2b\x06\x01\x05\x06\x02" }; +static sspi_gss_OID_desc g_SSPI_GSS_C_NT_HOSTBASED_SERVICE = { 10, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04" }; +static sspi_gss_OID_desc g_SSPI_GSS_C_NT_ANONYMOUS = { 6, (void*) "\x2b\x06\01\x05\x06\x03" }; +static sspi_gss_OID_desc g_SSPI_GSS_C_NT_EXPORT_NAME = { 6, (void*) "\x2b\x06\x01\x05\x06\x04" }; + +sspi_gss_OID SSPI_GSS_C_NT_USER_NAME = &g_SSPI_GSS_C_NT_USER_NAME; +sspi_gss_OID SSPI_GSS_C_NT_MACHINE_UID_NAME = &g_SSPI_GSS_C_NT_MACHINE_UID_NAME; +sspi_gss_OID SSPI_GSS_C_NT_STRING_UID_NAME = &g_SSPI_GSS_C_NT_STRING_UID_NAME; +sspi_gss_OID SSPI_GSS_C_NT_HOSTBASED_SERVICE_X = &g_SSPI_GSS_C_NT_HOSTBASED_SERVICE_X; +sspi_gss_OID SSPI_GSS_C_NT_HOSTBASED_SERVICE = &g_SSPI_GSS_C_NT_HOSTBASED_SERVICE; +sspi_gss_OID SSPI_GSS_C_NT_ANONYMOUS = &g_SSPI_GSS_C_NT_ANONYMOUS; +sspi_gss_OID SSPI_GSS_C_NT_EXPORT_NAME = &g_SSPI_GSS_C_NT_EXPORT_NAME; + + +/** + * SSPI GSSAPI + */ + +UINT32 SSPI_GSSAPI sspi_gss_acquire_cred( + UINT32* minor_status, + sspi_gss_name_t desired_name, + UINT32 time_req, + sspi_gss_OID_set desired_mechs, + sspi_gss_cred_usage_t cred_usage, + sspi_gss_cred_id_t* output_cred_handle, + sspi_gss_OID_set* actual_mechs, + UINT32* time_rec) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_acquire_cred)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_acquire_cred(minor_status, desired_name, time_req, + desired_mechs, cred_usage, output_cred_handle, actual_mechs, time_rec); + WLog_DBG(TAG, "gss_acquire_cred: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_release_cred( + UINT32* minor_status, + sspi_gss_cred_id_t* cred_handle) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_release_cred)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_release_cred(minor_status, cred_handle); + WLog_DBG(TAG, "gss_release_cred: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_init_sec_context( + UINT32* minor_status, + sspi_gss_cred_id_t claimant_cred_handle, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_name_t target_name, + sspi_gss_OID mech_type, + UINT32 req_flags, + UINT32 time_req, + sspi_gss_channel_bindings_t input_chan_bindings, + sspi_gss_buffer_t input_token, + sspi_gss_OID* actual_mech_type, + sspi_gss_buffer_t output_token, + UINT32* ret_flags, + UINT32* time_rec) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_init_sec_context)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_init_sec_context(minor_status, claimant_cred_handle, context_handle, + target_name, mech_type, req_flags, time_req, input_chan_bindings, + input_token, actual_mech_type, output_token, ret_flags, time_rec); + WLog_DBG(TAG, "gss_init_sec_context: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_accept_sec_context( + UINT32* minor_status, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_cred_id_t acceptor_cred_handle, + sspi_gss_buffer_t input_token_buffer, + sspi_gss_channel_bindings_t input_chan_bindings, + sspi_gss_name_t* src_name, + sspi_gss_OID* mech_type, + sspi_gss_buffer_t output_token, + UINT32* ret_flags, + UINT32* time_rec, + sspi_gss_cred_id_t* delegated_cred_handle) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_accept_sec_context)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_accept_sec_context(minor_status, context_handle, acceptor_cred_handle, + input_token_buffer, input_chan_bindings, src_name, mech_type, output_token, + ret_flags, time_rec, delegated_cred_handle); + WLog_DBG(TAG, "gss_accept_sec_context: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_process_context_token( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t token_buffer) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_process_context_token)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_process_context_token(minor_status, context_handle, token_buffer); + WLog_DBG(TAG, "gss_process_context_token: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_delete_sec_context( + UINT32* minor_status, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_buffer_t output_token) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_delete_sec_context)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_delete_sec_context(minor_status, context_handle, output_token); + WLog_DBG(TAG, "gss_delete_sec_context: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_context_time( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + UINT32* time_rec) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_context_time)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_context_time(minor_status, context_handle, time_rec); + WLog_DBG(TAG, "gss_context_time: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_get_mic( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_qop_t qop_req, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t message_token) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_get_mic)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_get_mic(minor_status, context_handle, qop_req, message_buffer, + message_token); + WLog_DBG(TAG, "gss_get_mic: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_verify_mic( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t message_token, + sspi_gss_qop_t* qop_state) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_verify_mic)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_verify_mic(minor_status, context_handle, message_buffer, message_token, + qop_state); + WLog_DBG(TAG, "gss_verify_mic: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_wrap( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int conf_req_flag, + sspi_gss_qop_t qop_req, + sspi_gss_buffer_t input_message_buffer, + int* conf_state, + sspi_gss_buffer_t output_message_buffer) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_wrap)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_wrap(minor_status, context_handle, conf_req_flag, + qop_req, input_message_buffer, conf_state, output_message_buffer); + WLog_DBG(TAG, "gss_acquire_cred: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_unwrap( + UINT32* minor_status, + const sspi_gss_ctx_id_t context_handle, + const sspi_gss_buffer_t input_message_buffer, + sspi_gss_buffer_t output_message_buffer, + int* conf_state, + sspi_gss_qop_t* qop_state) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_unwrap)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_unwrap(minor_status, context_handle, input_message_buffer, + output_message_buffer, conf_state, qop_state); + WLog_DBG(TAG, "gss_unwrap: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_display_status( + UINT32* minor_status, + UINT32 status_value, + int status_type, + sspi_gss_OID mech_type, + UINT32* message_context, + sspi_gss_buffer_t status_string) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_display_status)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_display_status(minor_status, status_value, status_type, + mech_type, message_context, status_string); + WLog_DBG(TAG, "gss_display_status: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_indicate_mechs( + UINT32* minor_status, + sspi_gss_OID_set* mech_set) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_indicate_mechs)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_indicate_mechs(minor_status, mech_set); + WLog_DBG(TAG, "gss_indicate_mechs: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_compare_name( + UINT32* minor_status, + sspi_gss_name_t name1, + sspi_gss_name_t name2, + int* name_equal) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_compare_name)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_compare_name(minor_status, name1, name2, name_equal); + WLog_DBG(TAG, "gss_compare_name: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_display_name( + UINT32* minor_status, + sspi_gss_name_t input_name, + sspi_gss_buffer_t output_name_buffer, + sspi_gss_OID* output_name_type) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_display_name)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_display_name(minor_status, input_name, output_name_buffer, output_name_type); + WLog_DBG(TAG, "gss_display_name: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_import_name( + UINT32* minor_status, + sspi_gss_buffer_t input_name_buffer, + sspi_gss_OID input_name_type, + sspi_gss_name_t* output_name) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_import_name)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_import_name(minor_status, input_name_buffer, input_name_type, output_name); + WLog_DBG(TAG, "gss_import_name: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_release_name( + UINT32* minor_status, + sspi_gss_name_t* input_name) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_release_name)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_release_name(minor_status, input_name); + WLog_DBG(TAG, "gss_release_name: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_release_buffer( + UINT32* minor_status, + sspi_gss_buffer_t buffer) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_release_buffer)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_release_buffer(minor_status, buffer); + WLog_DBG(TAG, "gss_release_buffer: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_release_oid_set( + UINT32* minor_status, + sspi_gss_OID_set* set) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_release_oid_set)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_release_oid_set(minor_status, set); + WLog_DBG(TAG, "gss_release_oid_set: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_inquire_cred( + UINT32* minor_status, + sspi_gss_cred_id_t cred_handle, + sspi_gss_name_t* name, + UINT32* lifetime, + sspi_gss_cred_usage_t* cred_usage, + sspi_gss_OID_set* mechanisms) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_inquire_cred)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_inquire_cred(minor_status, cred_handle, name, lifetime, cred_usage, + mechanisms); + WLog_DBG(TAG, "gss_inquire_cred: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_inquire_context( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_name_t* src_name, + sspi_gss_name_t* targ_name, + UINT32* lifetime_rec, + sspi_gss_OID* mech_type, + UINT32* ctx_flags, + int* locally_initiated, + int* open) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_inquire_context)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_inquire_context(minor_status, context_handle, src_name, targ_name, + lifetime_rec, mech_type, ctx_flags, locally_initiated, open); + WLog_DBG(TAG, "gss_inquire_context: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_wrap_size_limit( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int conf_req_flag, + sspi_gss_qop_t qop_req, + UINT32 req_output_size, + UINT32* max_input_size) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_wrap_size_limit)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_wrap_size_limit(minor_status, context_handle, + conf_req_flag, qop_req, req_output_size, max_input_size); + WLog_DBG(TAG, "gss_wrap_size_limit: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_import_name_object( + UINT32* minor_status, + void* input_name, + sspi_gss_OID input_name_type, + sspi_gss_name_t* output_name) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_import_name_object)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_import_name_object(minor_status, input_name, input_name_type, output_name); + WLog_DBG(TAG, "gss_import_name_object: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_export_name_object( + UINT32* minor_status, + sspi_gss_name_t input_name, + sspi_gss_OID desired_name_type, + void** output_name) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_export_name_object)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_export_name_object(minor_status, input_name, desired_name_type, output_name); + WLog_DBG(TAG, "gss_export_name_object: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_add_cred( + UINT32* minor_status, + sspi_gss_cred_id_t input_cred_handle, + sspi_gss_name_t desired_name, + sspi_gss_OID desired_mech, + sspi_gss_cred_usage_t cred_usage, + UINT32 initiator_time_req, + UINT32 acceptor_time_req, + sspi_gss_cred_id_t* output_cred_handle, + sspi_gss_OID_set* actual_mechs, + UINT32* initiator_time_rec, + UINT32* acceptor_time_rec) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_add_cred)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_add_cred(minor_status, input_cred_handle, desired_name, desired_mech, + cred_usage, + initiator_time_req, acceptor_time_req, output_cred_handle, actual_mechs, initiator_time_rec, + acceptor_time_rec); + WLog_DBG(TAG, "gss_add_cred: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_inquire_cred_by_mech( + UINT32* minor_status, + sspi_gss_cred_id_t cred_handle, + sspi_gss_OID mech_type, + sspi_gss_name_t* name, + UINT32* initiator_lifetime, + UINT32* acceptor_lifetime, + sspi_gss_cred_usage_t* cred_usage) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_inquire_cred_by_mech)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name, + initiator_lifetime, acceptor_lifetime, cred_usage); + WLog_DBG(TAG, "gss_inquire_cred_by_mech: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_export_sec_context( + UINT32* minor_status, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_buffer_t interprocess_token) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_export_sec_context)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_export_sec_context(minor_status, context_handle, interprocess_token); + WLog_DBG(TAG, "gss_export_sec_context: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_import_sec_context( + UINT32* minor_status, + sspi_gss_buffer_t interprocess_token, + sspi_gss_ctx_id_t* context_handle) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_import_sec_context)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_import_sec_context(minor_status, interprocess_token, context_handle); + WLog_DBG(TAG, "gss_import_sec_context: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_release_oid( + UINT32* minor_status, + sspi_gss_OID* oid) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_release_oid)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_release_oid(minor_status, oid); + WLog_DBG(TAG, "gss_release_oid: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_create_empty_oid_set( + UINT32* minor_status, + sspi_gss_OID_set* oid_set) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_create_empty_oid_set)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_create_empty_oid_set(minor_status, oid_set); + WLog_DBG(TAG, "gss_create_empty_oid_set: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_add_oid_set_member( + UINT32* minor_status, + sspi_gss_OID member_oid, + sspi_gss_OID_set* oid_set) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_add_oid_set_member)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_add_oid_set_member(minor_status, member_oid, oid_set); + WLog_DBG(TAG, "gss_add_oid_set_member: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_test_oid_set_member( + UINT32* minor_status, + sspi_gss_OID member, + sspi_gss_OID_set set, + int* present) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_test_oid_set_member)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_test_oid_set_member(minor_status, member, set, present); + WLog_DBG(TAG, "gss_test_oid_set_member: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_str_to_oid( + UINT32* minor_status, + sspi_gss_buffer_t oid_str, + sspi_gss_OID* oid) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_str_to_oid)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_str_to_oid(minor_status, oid_str, oid); + WLog_DBG(TAG, "gss_str_to_oid: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_oid_to_str( + UINT32* minor_status, + sspi_gss_OID oid, + sspi_gss_buffer_t oid_str) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_oid_to_str)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_oid_to_str(minor_status, oid, oid_str); + WLog_DBG(TAG, "gss_oid_to_str: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_inquire_names_for_mech( + UINT32* minor_status, + sspi_gss_OID mechanism, + sspi_gss_OID_set* name_types) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_inquire_names_for_mech)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_inquire_names_for_mech(minor_status, mechanism, name_types); + WLog_DBG(TAG, "gss_inquire_names_for_mech: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_inquire_mechs_for_name( + UINT32* minor_status, + const sspi_gss_name_t input_name, + sspi_gss_OID_set* mech_types) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_inquire_mechs_for_name)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_inquire_mechs_for_name(minor_status, input_name, mech_types); + WLog_DBG(TAG, "gss_inquire_mechs_for_name: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_sign( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int qop_req, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t message_token) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_sign)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_sign(minor_status, context_handle, qop_req, message_buffer, message_token); + WLog_DBG(TAG, "gss_sign: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_verify( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t token_buffer, + int* qop_state) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_verify)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_verify(minor_status, context_handle, message_buffer, token_buffer, + qop_state); + WLog_DBG(TAG, "gss_verify: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_seal( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int conf_req_flag, + int qop_req, + sspi_gss_buffer_t input_message_buffer, + int* conf_state, + sspi_gss_buffer_t output_message_buffer) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_seal)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_seal(minor_status, context_handle, conf_req_flag, qop_req, + input_message_buffer, conf_state, output_message_buffer); + WLog_DBG(TAG, "gss_seal: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_unseal( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t input_message_buffer, + sspi_gss_buffer_t output_message_buffer, + int* conf_state, + int* qop_state) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_unseal)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_unseal(minor_status, context_handle, input_message_buffer, + output_message_buffer, + conf_state, qop_state); + WLog_DBG(TAG, "gss_unseal: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_export_name( + UINT32* minor_status, + const sspi_gss_name_t input_name, + sspi_gss_buffer_t exported_name) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_export_name)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_export_name(minor_status, input_name, exported_name); + WLog_DBG(TAG, "gss_export_name: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_duplicate_name( + UINT32* minor_status, + const sspi_gss_name_t input_name, + sspi_gss_name_t* dest_name) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_duplicate_name)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_duplicate_name(minor_status, input_name, dest_name); + WLog_DBG(TAG, "gss_duplicate_name: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_canonicalize_name( + UINT32* minor_status, + const sspi_gss_name_t input_name, + const sspi_gss_OID mech_type, + sspi_gss_name_t* output_name) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_canonicalize_name)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_canonicalize_name(minor_status, input_name, mech_type, output_name); + WLog_DBG(TAG, "gss_canonicalize_name: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_pseudo_random( + UINT32* minor_status, + sspi_gss_ctx_id_t context, + int prf_key, + const sspi_gss_buffer_t prf_in, + SSIZE_T desired_output_len, + sspi_gss_buffer_t prf_out) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_pseudo_random)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_pseudo_random(minor_status, context, prf_key, prf_in, desired_output_len, + prf_out); + WLog_DBG(TAG, "gss_pseudo_random: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_store_cred( + UINT32* minor_status, + const sspi_gss_cred_id_t input_cred_handle, + sspi_gss_cred_usage_t input_usage, + const sspi_gss_OID desired_mech, + UINT32 overwrite_cred, + UINT32 default_cred, + sspi_gss_OID_set* elements_stored, + sspi_gss_cred_usage_t* cred_usage_stored) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_store_cred)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_store_cred(minor_status, input_cred_handle, input_usage, desired_mech, + overwrite_cred, default_cred, elements_stored, cred_usage_stored); + WLog_DBG(TAG, "gss_store_cred: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} + +UINT32 SSPI_GSSAPI sspi_gss_set_neg_mechs( + UINT32* minor_status, + sspi_gss_cred_id_t cred_handle, + const sspi_gss_OID_set mech_set) +{ + SECURITY_STATUS status; + InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); + + if (!(g_GssApi && g_GssApi->gss_set_neg_mechs)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = g_GssApi->gss_set_neg_mechs(minor_status, cred_handle, mech_set); + WLog_DBG(TAG, "gss_set_neg_mechs: %s (0x%08"PRIX32")", + GetSecurityStatusString(status), status); + return status; +} diff --git a/winpr/libwinpr/sspi/sspi_gss.h b/winpr/libwinpr/sspi/sspi_gss.h new file mode 100644 index 0000000..2ab3988 --- /dev/null +++ b/winpr/libwinpr/sspi/sspi_gss.h @@ -0,0 +1,886 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Generic Security Service Application Program Interface (GSSAPI) + * + * Copyright 2015 ANSSI, Author Thomas Calderon + * Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_SSPI_GSS_PRIVATE_H +#define FREERDP_SSPI_GSS_PRIVATE_H + +#include <winpr/crt.h> +#include <winpr/sspi.h> + +/** + * The following are ABI-compatible, non-conflicting GSSAPI definitions + * + * http://tools.ietf.org/html/rfc2743 + * http://tools.ietf.org/html/rfc2744 + */ + +#define SSPI_GSSAPI +#define SSPI_GSSOID + +struct sspi_gss_name_struct; +typedef struct sspi_gss_name_struct* sspi_gss_name_t; + +struct sspi_gss_cred_id_struct; +typedef struct sspi_gss_cred_id_struct* sspi_gss_cred_id_t; + +struct sspi_gss_ctx_id_struct; +typedef struct sspi_gss_ctx_id_struct* sspi_gss_ctx_id_t; + +typedef struct sspi_gss_OID_desc_struct +{ + UINT32 length; + void* elements; +} sspi_gss_OID_desc, *sspi_gss_OID; + +typedef struct sspi_gss_OID_set_desc_struct +{ + size_t count; + sspi_gss_OID elements; +} sspi_gss_OID_set_desc, *sspi_gss_OID_set; + +typedef struct sspi_gss_buffer_desc_struct +{ + size_t length; + void* value; +} sspi_gss_buffer_desc, *sspi_gss_buffer_t; + +typedef struct sspi_gss_channel_bindings_struct +{ + UINT32 initiator_addrtype; + sspi_gss_buffer_desc initiator_address; + UINT32 acceptor_addrtype; + sspi_gss_buffer_desc acceptor_address; + sspi_gss_buffer_desc application_data; +}* sspi_gss_channel_bindings_t; + +typedef UINT32 sspi_gss_qop_t; +typedef int sspi_gss_cred_usage_t; + +#define SSPI_GSS_C_DELEG_FLAG 1 +#define SSPI_GSS_C_MUTUAL_FLAG 2 +#define SSPI_GSS_C_REPLAY_FLAG 4 +#define SSPI_GSS_C_SEQUENCE_FLAG 8 +#define SSPI_GSS_C_CONF_FLAG 16 +#define SSPI_GSS_C_INTEG_FLAG 32 +#define SSPI_GSS_C_ANON_FLAG 64 +#define SSPI_GSS_C_PROT_READY_FLAG 128 +#define SSPI_GSS_C_TRANS_FLAG 256 +#define SSPI_GSS_C_DELEG_POLICY_FLAG 32768 + +#define SSPI_GSS_C_BOTH 0 +#define SSPI_GSS_C_INITIATE 1 +#define SSPI_GSS_C_ACCEPT 2 + +#define SSPI_GSS_C_GSS_CODE 1 +#define SSPI_GSS_C_MECH_CODE 2 + +#define SSPI_GSS_C_AF_UNSPEC 0 +#define SSPI_GSS_C_AF_LOCAL 1 +#define SSPI_GSS_C_AF_INET 2 +#define SSPI_GSS_C_AF_IMPLINK 3 +#define SSPI_GSS_C_AF_PUP 4 +#define SSPI_GSS_C_AF_CHAOS 5 +#define SSPI_GSS_C_AF_NS 6 +#define SSPI_GSS_C_AF_NBS 7 +#define SSPI_GSS_C_AF_ECMA 8 +#define SSPI_GSS_C_AF_DATAKIT 9 +#define SSPI_GSS_C_AF_CCITT 10 +#define SSPI_GSS_C_AF_SNA 11 +#define SSPI_GSS_C_AF_DECnet 12 +#define SSPI_GSS_C_AF_DLI 13 +#define SSPI_GSS_C_AF_LAT 14 +#define SSPI_GSS_C_AF_HYLINK 15 +#define SSPI_GSS_C_AF_APPLETALK 16 +#define SSPI_GSS_C_AF_BSC 17 +#define SSPI_GSS_C_AF_DSS 18 +#define SSPI_GSS_C_AF_OSI 19 +#define SSPI_GSS_C_AF_NETBIOS 20 +#define SSPI_GSS_C_AF_X25 21 +#define SSPI_GSS_C_AF_NULLADDR 255 + +#define SSPI_GSS_C_NO_NAME ((sspi_gss_name_t) 0) +#define SSPI_GSS_C_NO_BUFFER ((sspi_gss_buffer_t) 0) +#define SSPI_GSS_C_NO_OID ((sspi_gss_OID) 0) +#define SSPI_GSS_C_NO_OID_SET ((sspi_gss_OID_set) 0) +#define SSPI_GSS_C_NO_CONTEXT ((sspi_gss_ctx_id_t) 0) +#define SSPI_GSS_C_NO_CREDENTIAL ((sspi_gss_cred_id_t) 0) +#define SSPI_GSS_C_NO_CHANNEL_BINDINGS ((sspi_gss_channel_bindings_t) 0) +#define SSPI_GSS_C_EMPTY_BUFFER {0, NULL} + +#define SSPI_GSS_C_NULL_OID SSPI_GSS_C_NO_OID +#define SSPI_GSS_C_NULL_OID_SET SSPI_GSS_C_NO_OID_SET + +#define SSPI_GSS_C_QOP_DEFAULT 0 + +#define SSPI_GSS_C_INDEFINITE ((UINT32) 0xFFFFFFFF) + +#define SSPI_GSS_S_COMPLETE 0 + +#define SSPI_GSS_C_CALLING_ERROR_OFFSET 24 +#define SSPI_GSS_C_ROUTINE_ERROR_OFFSET 16 +#define SSPI_GSS_C_SUPPLEMENTARY_OFFSET 0 +#define SSPI_GSS_C_CALLING_ERROR_MASK ((UINT32) 0377) +#define SSPI_GSS_C_ROUTINE_ERROR_MASK ((UINT32) 0377) +#define SSPI_GSS_C_SUPPLEMENTARY_MASK ((UINT32) 0177777) + +#define SSPI_GSS_CALLING_ERROR(_x) \ + ((_x) & (SSPI_GSS_C_CALLING_ERROR_MASK << SSPI_GSS_C_CALLING_ERROR_OFFSET)) +#define SSPI_GSS_ROUTINE_ERROR(_x) \ + ((_x) & (SSPI_GSS_C_ROUTINE_ERROR_MASK << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)) +#define SSPI_GSS_SUPPLEMENTARY_INFO(_x) \ + ((_x) & (SSPI_GSS_C_SUPPLEMENTARY_MASK << SSPI_GSS_C_SUPPLEMENTARY_OFFSET)) +#define SSPI_GSS_ERROR(_x) \ + ((_x) & ((SSPI_GSS_C_CALLING_ERROR_MASK << SSPI_GSS_C_CALLING_ERROR_OFFSET) | \ + (SSPI_GSS_C_ROUTINE_ERROR_MASK << SSPI_GSS_C_ROUTINE_ERROR_OFFSET))) + +#define SSPI_GSS_S_CALL_INACCESSIBLE_READ (((UINT32) 1) << SSPI_GSS_C_CALLING_ERROR_OFFSET) +#define SSPI_GSS_S_CALL_INACCESSIBLE_WRITE (((UINT32) 2) << SSPI_GSS_C_CALLING_ERROR_OFFSET) +#define SSPI_GSS_S_CALL_BAD_STRUCTURE (((UINT32) 3) << SSPI_GSS_C_CALLING_ERROR_OFFSET) + +#define SSPI_GSS_S_BAD_MECH (((UINT32) 1) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_BAD_NAME (((UINT32) 2) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_BAD_NAMETYPE (((UINT32) 3) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_BAD_BINDINGS (((UINT32) 4) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_BAD_STATUS (((UINT32) 5) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_BAD_SIG (((UINT32) 6) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_NO_CRED (((UINT32) 7) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_NO_CONTEXT (((UINT32) 8) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_DEFECTIVE_TOKEN (((UINT32) 9) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_DEFECTIVE_CREDENTIAL (((UINT32) 10) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_CREDENTIALS_EXPIRED (((UINT32) 11) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_CONTEXT_EXPIRED (((UINT32) 12) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_FAILURE (((UINT32) 13) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_BAD_QOP (((UINT32) 14) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_UNAUTHORIZED (((UINT32) 15) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_UNAVAILABLE (((UINT32) 16) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_DUPLICATE_ELEMENT (((UINT32) 17) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_NAME_NOT_MN (((UINT32) 18) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) +#define SSPI_GSS_S_BAD_MECH_ATTR (((UINT32) 19) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET) + +#define SSPI_GSS_S_CONTINUE_NEEDED (1 << (SSPI_GSS_C_SUPPLEMENTARY_OFFSET + 0)) +#define SSPI_GSS_S_DUPLICATE_TOKEN (1 << (SSPI_GSS_C_SUPPLEMENTARY_OFFSET + 1)) +#define SSPI_GSS_S_OLD_TOKEN (1 << (SSPI_GSS_C_SUPPLEMENTARY_OFFSET + 2)) +#define SSPI_GSS_S_UNSEQ_TOKEN (1 << (SSPI_GSS_C_SUPPLEMENTARY_OFFSET + 3)) +#define SSPI_GSS_S_GAP_TOKEN (1 << (SSPI_GSS_C_SUPPLEMENTARY_OFFSET + 4)) + +#define SSPI_GSS_C_PRF_KEY_FULL 0 +#define SSPI_GSS_C_PRF_KEY_PARTIAL 1 + +#ifdef __cplusplus +extern "C" { +#endif + +SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_USER_NAME; +SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_MACHINE_UID_NAME; +SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_STRING_UID_NAME; +SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_HOSTBASED_SERVICE_X; +SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_HOSTBASED_SERVICE; +SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_ANONYMOUS; +SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_EXPORT_NAME; + +UINT32 SSPI_GSSAPI sspi_gss_acquire_cred( + UINT32* minor_status, + sspi_gss_name_t desired_name, + UINT32 time_req, + sspi_gss_OID_set desired_mechs, + sspi_gss_cred_usage_t cred_usage, + sspi_gss_cred_id_t* output_cred_handle, + sspi_gss_OID_set* actual_mechs, + UINT32* time_rec); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_acquire_cred)( + UINT32* minor_status, + sspi_gss_name_t desired_name, + UINT32 time_req, + sspi_gss_OID_set desired_mechs, + sspi_gss_cred_usage_t cred_usage, + sspi_gss_cred_id_t* output_cred_handle, + sspi_gss_OID_set* actual_mechs, + UINT32* time_rec); + +UINT32 SSPI_GSSAPI sspi_gss_release_cred( + UINT32* minor_status, + sspi_gss_cred_id_t* cred_handle); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_release_cred)( + UINT32* minor_status, + sspi_gss_cred_id_t* cred_handle); + +UINT32 SSPI_GSSAPI sspi_gss_init_sec_context( + UINT32* minor_status, + sspi_gss_cred_id_t claimant_cred_handle, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_name_t target_name, + sspi_gss_OID mech_type, + UINT32 req_flags, + UINT32 time_req, + sspi_gss_channel_bindings_t input_chan_bindings, + sspi_gss_buffer_t input_token, + sspi_gss_OID* actual_mech_type, + sspi_gss_buffer_t output_token, + UINT32* ret_flags, + UINT32* time_rec); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_init_sec_context)( + UINT32* minor_status, + sspi_gss_cred_id_t claimant_cred_handle, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_name_t target_name, + sspi_gss_OID mech_type, + UINT32 req_flags, + UINT32 time_req, + sspi_gss_channel_bindings_t input_chan_bindings, + sspi_gss_buffer_t input_token, + sspi_gss_OID* actual_mech_type, + sspi_gss_buffer_t output_token, + UINT32* ret_flags, + UINT32* time_rec); + +UINT32 SSPI_GSSAPI sspi_gss_accept_sec_context( + UINT32* minor_status, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_cred_id_t acceptor_cred_handle, + sspi_gss_buffer_t input_token_buffer, + sspi_gss_channel_bindings_t input_chan_bindings, + sspi_gss_name_t* src_name, + sspi_gss_OID* mech_type, + sspi_gss_buffer_t output_token, + UINT32* ret_flags, + UINT32* time_rec, + sspi_gss_cred_id_t* delegated_cred_handle); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_accept_sec_context)( + UINT32* minor_status, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_cred_id_t acceptor_cred_handle, + sspi_gss_buffer_t input_token_buffer, + sspi_gss_channel_bindings_t input_chan_bindings, + sspi_gss_name_t* src_name, + sspi_gss_OID* mech_type, + sspi_gss_buffer_t output_token, + UINT32* ret_flags, + UINT32* time_rec, + sspi_gss_cred_id_t* delegated_cred_handle); + +UINT32 SSPI_GSSAPI sspi_gss_process_context_token( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t token_buffer); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_process_context_token)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t token_buffer); + +UINT32 SSPI_GSSAPI sspi_gss_delete_sec_context( + UINT32* minor_status, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_buffer_t output_token); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_delete_sec_context)( + UINT32* minor_status, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_buffer_t output_token); + +UINT32 SSPI_GSSAPI sspi_gss_context_time( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + UINT32* time_rec); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_context_time)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + UINT32* time_rec); + +UINT32 SSPI_GSSAPI sspi_gss_get_mic( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_qop_t qop_req, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t message_token); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_get_mic)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_qop_t qop_req, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t message_token); + +UINT32 SSPI_GSSAPI sspi_gss_verify_mic( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t message_token, + sspi_gss_qop_t* qop_state); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_verify_mic)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t message_token, + sspi_gss_qop_t* qop_state); + +UINT32 SSPI_GSSAPI sspi_gss_wrap( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int conf_req_flag, + sspi_gss_qop_t qop_req, + sspi_gss_buffer_t input_message_buffer, + int* conf_state, + sspi_gss_buffer_t output_message_buffer); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_wrap)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int conf_req_flag, + sspi_gss_qop_t qop_req, + sspi_gss_buffer_t input_message_buffer, + int* conf_state, + sspi_gss_buffer_t output_message_buffer); + +UINT32 SSPI_GSSAPI sspi_gss_unwrap( + UINT32* minor_status, + const sspi_gss_ctx_id_t context_handle, + const sspi_gss_buffer_t input_message_buffer, + sspi_gss_buffer_t output_message_buffer, + int* conf_state, + sspi_gss_qop_t* qop_state); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_unwrap)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t input_message_buffer, + sspi_gss_buffer_t output_message_buffer, + int* conf_state, + sspi_gss_qop_t* qop_state); + +UINT32 SSPI_GSSAPI sspi_gss_display_status( + UINT32* minor_status, + UINT32 status_value, + int status_type, + sspi_gss_OID mech_type, + UINT32* message_context, + sspi_gss_buffer_t status_string); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_display_status)( + UINT32* minor_status, + UINT32 status_value, + int status_type, + sspi_gss_OID mech_type, + UINT32* message_context, + sspi_gss_buffer_t status_string); + +UINT32 SSPI_GSSAPI sspi_gss_indicate_mechs( + UINT32* minor_status, + sspi_gss_OID_set* mech_set); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_indicate_mechs)( + UINT32* minor_status, + sspi_gss_OID_set* mech_set); + +UINT32 SSPI_GSSAPI sspi_gss_compare_name( + UINT32* minor_status, + sspi_gss_name_t name1, + sspi_gss_name_t name2, + int* name_equal); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_compare_name)( + UINT32* minor_status, + sspi_gss_name_t name1, + sspi_gss_name_t name2, + int* name_equal); + +UINT32 SSPI_GSSAPI sspi_gss_display_name( + UINT32* minor_status, + sspi_gss_name_t input_name, + sspi_gss_buffer_t output_name_buffer, + sspi_gss_OID* output_name_type); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_display_name)( + UINT32* minor_status, + sspi_gss_name_t input_name, + sspi_gss_buffer_t output_name_buffer, + sspi_gss_OID* output_name_type); + +UINT32 SSPI_GSSAPI sspi_gss_import_name( + UINT32* minor_status, + sspi_gss_buffer_t input_name_buffer, + sspi_gss_OID input_name_type, + sspi_gss_name_t* output_name); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_import_name)( + UINT32* minor_status, + sspi_gss_buffer_t input_name_buffer, + sspi_gss_OID input_name_type, + sspi_gss_name_t* output_name); + +UINT32 SSPI_GSSAPI sspi_gss_release_name( + UINT32* minor_status, + sspi_gss_name_t* input_name); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_release_name)( + UINT32* minor_status, + sspi_gss_name_t* input_name); + +UINT32 SSPI_GSSAPI sspi_gss_release_buffer( + UINT32* minor_status, + sspi_gss_buffer_t buffer); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_release_buffer)( + UINT32* minor_status, + sspi_gss_buffer_t buffer); + +UINT32 SSPI_GSSAPI sspi_gss_release_oid_set( + UINT32* minor_status, + sspi_gss_OID_set* set); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_release_oid_set)( + UINT32* minor_status, + sspi_gss_OID_set* set); + +UINT32 SSPI_GSSAPI sspi_gss_inquire_cred( + UINT32* minor_status, + sspi_gss_cred_id_t cred_handle, + sspi_gss_name_t* name, + UINT32* lifetime, + sspi_gss_cred_usage_t* cred_usage, + sspi_gss_OID_set* mechanisms); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_inquire_cred)( + UINT32* minor_status, + sspi_gss_cred_id_t cred_handle, + sspi_gss_name_t* name, + UINT32* lifetime, + sspi_gss_cred_usage_t* cred_usage, + sspi_gss_OID_set* mechanisms); + +UINT32 SSPI_GSSAPI sspi_gss_inquire_context( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_name_t* src_name, + sspi_gss_name_t* targ_name, + UINT32* lifetime_rec, + sspi_gss_OID* mech_type, + UINT32* ctx_flags, + int* locally_initiated, + int* open); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_inquire_context)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_name_t* src_name, + sspi_gss_name_t* targ_name, + UINT32* lifetime_rec, + sspi_gss_OID* mech_type, + UINT32* ctx_flags, + int* locally_initiated, + int* open); + +UINT32 SSPI_GSSAPI sspi_gss_wrap_size_limit( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int conf_req_flag, + sspi_gss_qop_t qop_req, + UINT32 req_output_size, + UINT32* max_input_size); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_wrap_size_limit)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int conf_req_flag, + sspi_gss_qop_t qop_req, + UINT32 req_output_size, + UINT32* max_input_size); + +UINT32 SSPI_GSSAPI sspi_gss_import_name_object( + UINT32* minor_status, + void* input_name, + sspi_gss_OID input_name_type, + sspi_gss_name_t* output_name); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_import_name_object)( + UINT32* minor_status, + void* input_name, + sspi_gss_OID input_name_type, + sspi_gss_name_t* output_name); + +UINT32 SSPI_GSSAPI sspi_gss_export_name_object( + UINT32* minor_status, + sspi_gss_name_t input_name, + sspi_gss_OID desired_name_type, + void** output_name); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_export_name_object)( + UINT32* minor_status, + sspi_gss_name_t input_name, + sspi_gss_OID desired_name_type, + void** output_name); + +UINT32 SSPI_GSSAPI sspi_gss_add_cred( + UINT32* minor_status, + sspi_gss_cred_id_t input_cred_handle, + sspi_gss_name_t desired_name, + sspi_gss_OID desired_mech, + sspi_gss_cred_usage_t cred_usage, + UINT32 initiator_time_req, + UINT32 acceptor_time_req, + sspi_gss_cred_id_t* output_cred_handle, + sspi_gss_OID_set* actual_mechs, + UINT32* initiator_time_rec, + UINT32* acceptor_time_rec); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_add_cred)( + UINT32* minor_status, + sspi_gss_cred_id_t input_cred_handle, + sspi_gss_name_t desired_name, + sspi_gss_OID desired_mech, + sspi_gss_cred_usage_t cred_usage, + UINT32 initiator_time_req, + UINT32 acceptor_time_req, + sspi_gss_cred_id_t* output_cred_handle, + sspi_gss_OID_set* actual_mechs, + UINT32* initiator_time_rec, + UINT32* acceptor_time_rec); + +UINT32 SSPI_GSSAPI sspi_gss_inquire_cred_by_mech( + UINT32* minor_status, + sspi_gss_cred_id_t cred_handle, + sspi_gss_OID mech_type, + sspi_gss_name_t* name, + UINT32* initiator_lifetime, + UINT32* acceptor_lifetime, + sspi_gss_cred_usage_t* cred_usage); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_inquire_cred_by_mech)( + UINT32* minor_status, + sspi_gss_cred_id_t cred_handle, + sspi_gss_OID mech_type, + sspi_gss_name_t* name, + UINT32* initiator_lifetime, + UINT32* acceptor_lifetime, + sspi_gss_cred_usage_t* cred_usage); + +UINT32 SSPI_GSSAPI sspi_gss_export_sec_context( + UINT32* minor_status, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_buffer_t interprocess_token); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_export_sec_context)( + UINT32* minor_status, + sspi_gss_ctx_id_t* context_handle, + sspi_gss_buffer_t interprocess_token); + +UINT32 SSPI_GSSAPI sspi_gss_import_sec_context( + UINT32* minor_status, + sspi_gss_buffer_t interprocess_token, + sspi_gss_ctx_id_t* context_handle); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_import_sec_context)( + UINT32* minor_status, + sspi_gss_buffer_t interprocess_token, + sspi_gss_ctx_id_t* context_handle); + +UINT32 SSPI_GSSAPI sspi_gss_release_oid( + UINT32* minor_status, + sspi_gss_OID* oid); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_release_oid)( + UINT32* minor_status, + sspi_gss_OID* oid); + +UINT32 SSPI_GSSAPI sspi_gss_create_empty_oid_set( + UINT32* minor_status, + sspi_gss_OID_set* oid_set); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_create_empty_oid_set)( + UINT32* minor_status, + sspi_gss_OID_set* oid_set); + +UINT32 SSPI_GSSAPI sspi_gss_add_oid_set_member( + UINT32* minor_status, + sspi_gss_OID member_oid, + sspi_gss_OID_set* oid_set); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_add_oid_set_member)( + UINT32* minor_status, + sspi_gss_OID member_oid, + sspi_gss_OID_set* oid_set); + +UINT32 SSPI_GSSAPI sspi_gss_test_oid_set_member( + UINT32* minor_status, + sspi_gss_OID member, + sspi_gss_OID_set set, + int* present); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_test_oid_set_member)( + UINT32* minor_status, + sspi_gss_OID member, + sspi_gss_OID_set set, + int* present); + +UINT32 SSPI_GSSAPI sspi_gss_str_to_oid( + UINT32* minor_status, + sspi_gss_buffer_t oid_str, + sspi_gss_OID* oid); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_str_to_oid)( + UINT32* minor_status, + sspi_gss_buffer_t oid_str, + sspi_gss_OID* oid); + +UINT32 SSPI_GSSAPI sspi_gss_oid_to_str( + UINT32* minor_status, + sspi_gss_OID oid, + sspi_gss_buffer_t oid_str); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_oid_to_str)( + UINT32* minor_status, + sspi_gss_OID oid, + sspi_gss_buffer_t oid_str); + +UINT32 SSPI_GSSAPI sspi_gss_inquire_names_for_mech( + UINT32* minor_status, + sspi_gss_OID mechanism, + sspi_gss_OID_set* name_types); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_inquire_names_for_mech)( + UINT32* minor_status, + sspi_gss_OID mechanism, + sspi_gss_OID_set* name_types); + +UINT32 SSPI_GSSAPI sspi_gss_inquire_mechs_for_name( + UINT32* minor_status, + const sspi_gss_name_t input_name, + sspi_gss_OID_set* mech_types); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_inquire_mechs_for_name)( + UINT32* minor_status, + const sspi_gss_name_t input_name, + sspi_gss_OID_set* mech_types); + +UINT32 SSPI_GSSAPI sspi_gss_sign( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int qop_req, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t message_token); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_sign)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int qop_req, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t message_token); + +UINT32 SSPI_GSSAPI sspi_gss_verify( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t token_buffer, + int* qop_state); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_verify)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t message_buffer, + sspi_gss_buffer_t token_buffer, + int* qop_state); + +UINT32 SSPI_GSSAPI sspi_gss_seal( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int conf_req_flag, + int qop_req, + sspi_gss_buffer_t input_message_buffer, + int* conf_state, + sspi_gss_buffer_t output_message_buffer); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_seal)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + int conf_req_flag, + int qop_req, + sspi_gss_buffer_t input_message_buffer, + int* conf_state, + sspi_gss_buffer_t output_message_buffer); + +UINT32 SSPI_GSSAPI sspi_gss_unseal( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t input_message_buffer, + sspi_gss_buffer_t output_message_buffer, + int* conf_state, + int* qop_state); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_unseal)( + UINT32* minor_status, + sspi_gss_ctx_id_t context_handle, + sspi_gss_buffer_t input_message_buffer, + sspi_gss_buffer_t output_message_buffer, + int* conf_state, + int* qop_state); + +UINT32 SSPI_GSSAPI sspi_gss_export_name( + UINT32* minor_status, + const sspi_gss_name_t input_name, + sspi_gss_buffer_t exported_name); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_export_name)( + UINT32* minor_status, + const sspi_gss_name_t input_name, + sspi_gss_buffer_t exported_name); + +UINT32 SSPI_GSSAPI sspi_gss_duplicate_name( + UINT32* minor_status, + const sspi_gss_name_t input_name, + sspi_gss_name_t* dest_name); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_duplicate_name)( + UINT32* minor_status, + const sspi_gss_name_t input_name, + sspi_gss_name_t* dest_name); + +UINT32 SSPI_GSSAPI sspi_gss_canonicalize_name( + UINT32* minor_status, + const sspi_gss_name_t input_name, + const sspi_gss_OID mech_type, + sspi_gss_name_t* output_name); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_canonicalize_name)( + UINT32* minor_status, + const sspi_gss_name_t input_name, + const sspi_gss_OID mech_type, + sspi_gss_name_t* output_name); + +UINT32 SSPI_GSSAPI sspi_gss_pseudo_random( + UINT32* minor_status, + sspi_gss_ctx_id_t context, + int prf_key, + const sspi_gss_buffer_t prf_in, + SSIZE_T desired_output_len, + sspi_gss_buffer_t prf_out); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_pseudo_random)( + UINT32* minor_status, + sspi_gss_ctx_id_t context, + int prf_key, + const sspi_gss_buffer_t prf_in, + SSIZE_T desired_output_len, + sspi_gss_buffer_t prf_out); + +UINT32 SSPI_GSSAPI sspi_gss_store_cred( + UINT32* minor_status, + const sspi_gss_cred_id_t input_cred_handle, + sspi_gss_cred_usage_t input_usage, + const sspi_gss_OID desired_mech, + UINT32 overwrite_cred, + UINT32 default_cred, + sspi_gss_OID_set* elements_stored, + sspi_gss_cred_usage_t* cred_usage_stored); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_store_cred)( + UINT32* minor_status, + const sspi_gss_cred_id_t input_cred_handle, + sspi_gss_cred_usage_t input_usage, + const sspi_gss_OID desired_mech, + UINT32 overwrite_cred, + UINT32 default_cred, + sspi_gss_OID_set* elements_stored, + sspi_gss_cred_usage_t* cred_usage_stored); + +UINT32 SSPI_GSSAPI sspi_gss_set_neg_mechs( + UINT32* minor_status, + sspi_gss_cred_id_t cred_handle, + const sspi_gss_OID_set mech_set); + +typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_set_neg_mechs)( + UINT32* minor_status, + sspi_gss_cred_id_t cred_handle, + const sspi_gss_OID_set mech_set); + +#ifdef __cplusplus +} +#endif + +struct _GSSAPI_FUNCTION_TABLE +{ + fn_sspi_gss_acquire_cred gss_acquire_cred; + fn_sspi_gss_release_cred gss_release_cred; + fn_sspi_gss_init_sec_context gss_init_sec_context; + fn_sspi_gss_accept_sec_context gss_accept_sec_context; + fn_sspi_gss_process_context_token gss_process_context_token; + fn_sspi_gss_delete_sec_context gss_delete_sec_context; + fn_sspi_gss_context_time gss_context_time; + fn_sspi_gss_get_mic gss_get_mic; + fn_sspi_gss_verify_mic gss_verify_mic; + fn_sspi_gss_wrap gss_wrap; + fn_sspi_gss_unwrap gss_unwrap; + fn_sspi_gss_display_status gss_display_status; + fn_sspi_gss_indicate_mechs gss_indicate_mechs; + fn_sspi_gss_compare_name gss_compare_name; + fn_sspi_gss_display_name gss_display_name; + fn_sspi_gss_import_name gss_import_name; + fn_sspi_gss_release_name gss_release_name; + fn_sspi_gss_release_buffer gss_release_buffer; + fn_sspi_gss_release_oid_set gss_release_oid_set; + fn_sspi_gss_inquire_cred gss_inquire_cred; + fn_sspi_gss_inquire_context gss_inquire_context; + fn_sspi_gss_wrap_size_limit gss_wrap_size_limit; + fn_sspi_gss_import_name_object gss_import_name_object; + fn_sspi_gss_export_name_object gss_export_name_object; + fn_sspi_gss_add_cred gss_add_cred; + fn_sspi_gss_inquire_cred_by_mech gss_inquire_cred_by_mech; + fn_sspi_gss_export_sec_context gss_export_sec_context; + fn_sspi_gss_import_sec_context gss_import_sec_context; + fn_sspi_gss_release_oid gss_release_oid; + fn_sspi_gss_create_empty_oid_set gss_create_empty_oid_set; + fn_sspi_gss_add_oid_set_member gss_add_oid_set_member; + fn_sspi_gss_test_oid_set_member gss_test_oid_set_member; + fn_sspi_gss_str_to_oid gss_str_to_oid; + fn_sspi_gss_oid_to_str gss_oid_to_str; + fn_sspi_gss_inquire_names_for_mech gss_inquire_names_for_mech; + fn_sspi_gss_inquire_mechs_for_name gss_inquire_mechs_for_name; + fn_sspi_gss_sign gss_sign; + fn_sspi_gss_verify gss_verify; + fn_sspi_gss_seal gss_seal; + fn_sspi_gss_unseal gss_unseal; + fn_sspi_gss_export_name gss_export_name; + fn_sspi_gss_duplicate_name gss_duplicate_name; + fn_sspi_gss_canonicalize_name gss_canonicalize_name; + fn_sspi_gss_pseudo_random gss_pseudo_random; + fn_sspi_gss_store_cred gss_store_cred; + fn_sspi_gss_set_neg_mechs gss_set_neg_mechs; +}; +typedef struct _GSSAPI_FUNCTION_TABLE GSSAPI_FUNCTION_TABLE; + +GSSAPI_FUNCTION_TABLE* SEC_ENTRY gssApi_InitSecurityInterface(void); + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_SSPI_GSS_PRIVATE_H */ diff --git a/winpr/libwinpr/sspi/sspi_winpr.c b/winpr/libwinpr/sspi/sspi_winpr.c index ec41f56..bad9992 100644 --- a/winpr/libwinpr/sspi/sspi_winpr.c +++ b/winpr/libwinpr/sspi/sspi_winpr.c @@ -3,6 +3,7 @@ * Security Support Provider Interface (SSPI) * * Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com> + * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com> * * 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,11 @@ extern const SecPkgInfoW NTLM_SecPkgInfoW; extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA; extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW; +extern const SecPkgInfoA KERBEROS_SecPkgInfoA; +extern const SecPkgInfoW KERBEROS_SecPkgInfoW; +extern const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA; +extern const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW; + extern const SecPkgInfoA NEGOTIATE_SecPkgInfoA; extern const SecPkgInfoW NEGOTIATE_SecPkgInfoW; extern const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA; @@ -57,55 +63,60 @@ extern const SecPkgInfoW SCHANNEL_SecPkgInfoW; extern const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA; extern const SecurityFunctionTableW SCHANNEL_SecurityFunctionTableW; -const SecPkgInfoA* SecPkgInfoA_LIST[] = +static const SecPkgInfoA* SecPkgInfoA_LIST[] = { &NTLM_SecPkgInfoA, + &KERBEROS_SecPkgInfoA, &NEGOTIATE_SecPkgInfoA, &CREDSSP_SecPkgInfoA, &SCHANNEL_SecPkgInfoA }; -const SecPkgInfoW* SecPkgInfoW_LIST[] = +static const SecPkgInfoW* SecPkgInfoW_LIST[] = { &NTLM_SecPkgInfoW, + &KERBEROS_SecPkgInfoW, &NEGOTIATE_SecPkgInfoW, &CREDSSP_SecPkgInfoW, &SCHANNEL_SecPkgInfoW }; -SecurityFunctionTableA winpr_SecurityFunctionTableA; -SecurityFunctionTableW winpr_SecurityFunctionTableW; +static SecurityFunctionTableA winpr_SecurityFunctionTableA; +static SecurityFunctionTableW winpr_SecurityFunctionTableW; struct _SecurityFunctionTableA_NAME { - SEC_CHAR* Name; + const SEC_CHAR* Name; const SecurityFunctionTableA* SecurityFunctionTable; }; typedef struct _SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME; struct _SecurityFunctionTableW_NAME { - SEC_WCHAR* Name; + const SEC_WCHAR* Name; const SecurityFunctionTableW* SecurityFunctionTable; }; typedef struct _SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME; -const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] = +static const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] = { { "NTLM", &NTLM_SecurityFunctionTableA }, + { "Kerberos", &KERBEROS_SecurityFunctionTableA }, { "Negotiate", &NEGOTIATE_SecurityFunctionTableA }, { "CREDSSP", &CREDSSP_SecurityFunctionTableA }, { "Schannel", &SCHANNEL_SecurityFunctionTableA } }; -WCHAR NTLM_NAME_W[] = { 'N','T','L','M','\0' }; -WCHAR NEGOTIATE_NAME_W[] = { 'N','e','g','o','t','i','a','t','e','\0' }; -WCHAR CREDSSP_NAME_W[] = { 'C','r','e','d','S','S','P','\0' }; -WCHAR SCHANNEL_NAME_W[] = { 'S','c','h','a','n','n','e','l','\0' }; +static const WCHAR NTLM_NAME_W[] = { 'N', 'T', 'L', 'M', '\0' }; +static const WCHAR KERBEROS_NAME_W[] = { 'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', '\0' }; +static const WCHAR NEGOTIATE_NAME_W[] = { 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'e', '\0' }; +static const WCHAR CREDSSP_NAME_W[] = { 'C', 'r', 'e', 'd', 'S', 'S', 'P', '\0' }; +static const WCHAR SCHANNEL_NAME_W[] = { 'S', 'c', 'h', 'a', 'n', 'n', 'e', 'l', '\0' }; -const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] = +static const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] = { { NTLM_NAME_W, &NTLM_SecurityFunctionTableW }, + { KERBEROS_NAME_W, &KERBEROS_SecurityFunctionTableW }, { NEGOTIATE_NAME_W, &NEGOTIATE_SecurityFunctionTableW }, { CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW }, { SCHANNEL_NAME_W, &SCHANNEL_SecurityFunctionTableW } @@ -129,18 +140,15 @@ struct _CONTEXT_BUFFER_ALLOC_TABLE }; typedef struct _CONTEXT_BUFFER_ALLOC_TABLE CONTEXT_BUFFER_ALLOC_TABLE; -CONTEXT_BUFFER_ALLOC_TABLE ContextBufferAllocTable; +static CONTEXT_BUFFER_ALLOC_TABLE ContextBufferAllocTable = { 0 }; -int sspi_ContextBufferAllocTableNew() +static int sspi_ContextBufferAllocTableNew(void) { size_t size; - ContextBufferAllocTable.entries = NULL; ContextBufferAllocTable.cEntries = 0; ContextBufferAllocTable.cMaxEntries = 4; - size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries; - ContextBufferAllocTable.entries = (CONTEXT_BUFFER_ALLOC_ENTRY*) calloc(1, size); if (!ContextBufferAllocTable.entries) @@ -149,13 +157,12 @@ int sspi_ContextBufferAllocTableNew() return 1; } -int sspi_ContextBufferAllocTableGrow() +static int sspi_ContextBufferAllocTableGrow(void) { size_t size; CONTEXT_BUFFER_ALLOC_ENTRY* entries; ContextBufferAllocTable.cEntries = 0; ContextBufferAllocTable.cMaxEntries *= 2; - size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries; if (!size) @@ -170,24 +177,27 @@ int sspi_ContextBufferAllocTableGrow() } ContextBufferAllocTable.entries = entries; - - ZeroMemory((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2], size / 2); - + ZeroMemory((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2], + size / 2); return 1; } -void sspi_ContextBufferAllocTableFree() +static void sspi_ContextBufferAllocTableFree(void) { + if (ContextBufferAllocTable.cEntries != 0) + WLog_ERR(TAG, "ContextBufferAllocTable.entries == %"PRIu32, ContextBufferAllocTable.cEntries); + ContextBufferAllocTable.cEntries = ContextBufferAllocTable.cMaxEntries = 0; free(ContextBufferAllocTable.entries); + ContextBufferAllocTable.entries = NULL; } -void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size) +static void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size) { - int index; + UINT32 index; void* contextBuffer; - for (index = 0; index < (int) ContextBufferAllocTable.cMaxEntries; index++) + for (index = 0; index < ContextBufferAllocTable.cMaxEntries; index++) { if (!ContextBufferAllocTable.entries[index].contextBuffer) { @@ -197,10 +207,8 @@ void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size) return NULL; ContextBufferAllocTable.cEntries++; - ContextBufferAllocTable.entries[index].contextBuffer = contextBuffer; ContextBufferAllocTable.entries[index].allocatorIndex = allocatorIndex; - return ContextBufferAllocTable.entries[index].contextBuffer; } } @@ -211,24 +219,21 @@ void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size) return NULL; /* the next call to sspi_ContextBufferAlloc() should now succeed */ - return sspi_ContextBufferAlloc(allocatorIndex, size); } -SSPI_CREDENTIALS* sspi_CredentialsNew() +SSPI_CREDENTIALS* sspi_CredentialsNew(void) { SSPI_CREDENTIALS* credentials; - credentials = (SSPI_CREDENTIALS*) calloc(1, sizeof(SSPI_CREDENTIALS)); - return credentials; } void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials) { - size_t userLength; - size_t domainLength; - size_t passwordLength; + size_t userLength = 0; + size_t domainLength = 0; + size_t passwordLength = 0; if (!credentials) return; @@ -247,11 +252,9 @@ void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials) memset(credentials->identity.User, 0, userLength); memset(credentials->identity.Domain, 0, domainLength); memset(credentials->identity.Password, 0, passwordLength); - free(credentials->identity.User); free(credentials->identity.Domain); free(credentials->identity.Password); - free(credentials); } @@ -261,6 +264,7 @@ void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size) return NULL; SecBuffer->pvBuffer = calloc(1, size); + if (!SecBuffer->pvBuffer) return NULL; @@ -275,12 +279,13 @@ void sspi_SecBufferFree(PSecBuffer SecBuffer) if (SecBuffer->pvBuffer) memset(SecBuffer->pvBuffer, 0, SecBuffer->cbBuffer); + free(SecBuffer->pvBuffer); SecBuffer->pvBuffer = NULL; SecBuffer->cbBuffer = 0; } -SecHandle* sspi_SecureHandleAlloc() +SecHandle* sspi_SecureHandleAlloc(void) { SecHandle* handle = (SecHandle*) calloc(1, sizeof(SecHandle)); @@ -288,7 +293,6 @@ SecHandle* sspi_SecureHandleAlloc() return NULL; SecInvalidateHandle(handle); - return handle; } @@ -300,16 +304,24 @@ void* sspi_SecureHandleGetLowerPointer(SecHandle* handle) return NULL; pointer = (void*) ~((size_t) handle->dwLower); - return pointer; } +void sspi_SecureHandleInvalidate(SecHandle* handle) +{ + if (!handle) + return; + + handle->dwLower = 0; + handle->dwUpper = 0; +} + void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer) { if (!handle) return; - handle->dwLower = (ULONG_PTR) (~((size_t) pointer)); + handle->dwLower = (ULONG_PTR)(~((size_t) pointer)); } void* sspi_SecureHandleGetUpperPointer(SecHandle* handle) @@ -320,7 +332,6 @@ void* sspi_SecureHandleGetUpperPointer(SecHandle* handle) return NULL; pointer = (void*) ~((size_t) handle->dwUpper); - return pointer; } @@ -329,7 +340,7 @@ void sspi_SecureHandleSetUpperPointer(SecHandle* handle, void* pointer) if (!handle) return; - handle->dwUpper = (ULONG_PTR) (~((size_t) pointer)); + handle->dwUpper = (ULONG_PTR)(~((size_t) pointer)); } void sspi_SecureHandleFree(SecHandle* handle) @@ -337,57 +348,64 @@ void sspi_SecureHandleFree(SecHandle* handle) free(handle); } -int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain, const char* password) +int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain, + const char* password) +{ + int rc; + int unicodePasswordLenW; + LPWSTR unicodePassword = NULL; + unicodePasswordLenW = ConvertToUnicode(CP_UTF8, 0, password, -1, &unicodePassword, 0); + + if (unicodePasswordLenW <= 0) + return -1; + + rc = sspi_SetAuthIdentityWithUnicodePassword(identity, user, domain, unicodePassword, + (ULONG)(unicodePasswordLenW - 1)); + free(unicodePassword); + return rc; +} + +int sspi_SetAuthIdentityWithUnicodePassword(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, + const char* domain, LPWSTR password, ULONG passwordLength) { int status; - identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - free(identity->User); - identity->User = (UINT16*) NULL; identity->UserLength = 0; if (user) { - status = ConvertToUnicode(CP_UTF8, 0, user, -1, (LPWSTR*) &(identity->User), 0); + status = ConvertToUnicode(CP_UTF8, 0, user, -1, (LPWSTR*) & (identity->User), 0); if (status <= 0) return -1; - identity->UserLength = (ULONG) (status - 1); + identity->UserLength = (ULONG)(status - 1); } free(identity->Domain); - identity->Domain = (UINT16*) NULL; identity->DomainLength = 0; if (domain) { - status = ConvertToUnicode(CP_UTF8, 0, domain, -1, (LPWSTR*) &(identity->Domain), 0); + status = ConvertToUnicode(CP_UTF8, 0, domain, -1, (LPWSTR*) & (identity->Domain), 0); if (status <= 0) return -1; - identity->DomainLength = (ULONG) (status - 1); + identity->DomainLength = (ULONG)(status - 1); } free(identity->Password); + identity->Password = (UINT16*) calloc(1, (passwordLength + 1) * sizeof(WCHAR)); - identity->Password = NULL; - identity->PasswordLength = 0; - - if (password) - { - status = ConvertToUnicode(CP_UTF8, 0, password, -1, (LPWSTR*) &(identity->Password), 0); - - if (status <= 0) - return -1; - - identity->PasswordLength = (ULONG) (status - 1); - } + if (!identity->Password) + return -1; + CopyMemory(identity->Password, password, passwordLength * sizeof(WCHAR)); + identity->PasswordLength = passwordLength; return 1; } @@ -398,20 +416,18 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN if (srcIdentity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI) { status = sspi_SetAuthIdentity(identity, (char*) srcIdentity->User, - (char*) srcIdentity->Domain, (char*) srcIdentity->Password); + (char*) srcIdentity->Domain, (char*) srcIdentity->Password); if (status <= 0) return -1; identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - return 1; } identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - + /* login/password authentication */ identity->User = identity->Domain = identity->Password = NULL; - identity->UserLength = srcIdentity->UserLength; if (identity->UserLength > 0) @@ -454,8 +470,7 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN identity->Password[identity->PasswordLength] = 0; } - identity->PasswordLength = srcIdentity->PasswordLength; - + /* End of login/password authentication */ return 1; } @@ -476,34 +491,29 @@ PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType) return pSecBuffer; } -static BOOL sspi_initialized = FALSE; - -void sspi_GlobalInit() +static BOOL CALLBACK sspi_init(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* Context) { - if (!sspi_initialized) - { - winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT); - - sspi_ContextBufferAllocTableNew(); - sspi_initialized = TRUE; - } + winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT); + sspi_ContextBufferAllocTableNew(); + return TRUE; } -void sspi_GlobalFinish() +void sspi_GlobalInit(void) { - if (sspi_initialized) - { - sspi_ContextBufferAllocTableFree(); - } - - sspi_initialized = FALSE; + static INIT_ONCE once = INIT_ONCE_STATIC_INIT; + DWORD flags = 0; + InitOnceExecuteOnce(&once, sspi_init, &flags, NULL); } -SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Name) +void sspi_GlobalFinish(void) +{ + sspi_ContextBufferAllocTableFree(); +} + +static SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Name) { int index; UINT32 cPackages; - cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST)); for (index = 0; index < (int) cPackages; index++) @@ -517,16 +527,10 @@ SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Na return NULL; } -SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameW(const SEC_WCHAR* Name) -{ - return NULL; -} - -SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* Name) +static SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* Name) { int index; UINT32 cPackages; - cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST)); for (index = 0; index < (int) cPackages; index++) @@ -540,12 +544,11 @@ SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* N return NULL; } -SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Name) +static SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Name) { int status; SEC_WCHAR* NameW = NULL; SecurityFunctionTableW* table; - status = ConvertToUnicode(CP_UTF8, 0, Name, -1, &NameW, 0); if (status <= 0) @@ -553,39 +556,36 @@ SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Na table = sspi_GetSecurityFunctionTableWByNameW(NameW); free(NameW); - return table; } -void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer); -void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer); +static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer); +static void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer); -void sspi_ContextBufferFree(void* contextBuffer) +static void sspi_ContextBufferFree(void* contextBuffer) { - int index; + UINT32 index; UINT32 allocatorIndex; - for (index = 0; index < (int) ContextBufferAllocTable.cMaxEntries; index++) + for (index = 0; index < ContextBufferAllocTable.cMaxEntries; index++) { if (contextBuffer == ContextBufferAllocTable.entries[index].contextBuffer) { contextBuffer = ContextBufferAllocTable.entries[index].contextBuffer; allocatorIndex = ContextBufferAllocTable.entries[index].allocatorIndex; - ContextBufferAllocTable.cEntries--; - ContextBufferAllocTable.entries[index].allocatorIndex = 0; ContextBufferAllocTable.entries[index].contextBuffer = NULL; switch (allocatorIndex) { - case EnumerateSecurityPackagesIndex: - FreeContextBuffer_EnumerateSecurityPackages(contextBuffer); - break; + case EnumerateSecurityPackagesIndex: + FreeContextBuffer_EnumerateSecurityPackages(contextBuffer); + break; - case QuerySecurityPackageInfoIndex: - FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer); - break; + case QuerySecurityPackageInfoIndex: + FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer); + break; } } } @@ -597,16 +597,15 @@ void sspi_ContextBufferFree(void* contextBuffer) /* Package Management */ -SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages, PSecPkgInfoW* ppPackageInfo) +static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages, + PSecPkgInfoW* ppPackageInfo) { int index; size_t size; UINT32 cPackages; SecPkgInfoW* pPackageInfo; - cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST)); size = sizeof(SecPkgInfoW) * cPackages; - pPackageInfo = (SecPkgInfoW*) sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size); if (!pPackageInfo) @@ -624,20 +623,18 @@ SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages, PS *(pcPackages) = cPackages; *(ppPackageInfo) = pPackageInfo; - return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, PSecPkgInfoA* ppPackageInfo) +static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, + PSecPkgInfoA* ppPackageInfo) { int index; size_t size; UINT32 cPackages; SecPkgInfoA* pPackageInfo; - cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST)); size = sizeof(SecPkgInfoA) * cPackages; - pPackageInfo = (SecPkgInfoA*) sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size); if (!pPackageInfo) @@ -651,6 +648,7 @@ SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, PS pPackageInfo[index].cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken; pPackageInfo[index].Name = _strdup(SecPkgInfoA_LIST[index]->Name); pPackageInfo[index].Comment = _strdup(SecPkgInfoA_LIST[index]->Comment); + if (!pPackageInfo[index].Name || !pPackageInfo[index].Comment) { sspi_ContextBufferFree(pPackageInfo); @@ -660,16 +658,14 @@ SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, PS *(pcPackages) = cPackages; *(ppPackageInfo) = pPackageInfo; - return SEC_E_OK; } -void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer) +static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer) { int index; UINT32 cPackages; SecPkgInfoA* pPackageInfo = (SecPkgInfoA*) contextBuffer; - cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST)); for (index = 0; index < (int) cPackages; index++) @@ -691,13 +687,13 @@ SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void) return &winpr_SecurityFunctionTableA; } -SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, PSecPkgInfoW* ppPackageInfo) +static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, + PSecPkgInfoW* ppPackageInfo) { int index; size_t size; UINT32 cPackages; SecPkgInfoW* pPackageInfo; - cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST)); for (index = 0; index < (int) cPackages; index++) @@ -716,25 +712,22 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageN pPackageInfo->cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken; pPackageInfo->Name = _wcsdup(SecPkgInfoW_LIST[index]->Name); pPackageInfo->Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment); - *(ppPackageInfo) = pPackageInfo; - return SEC_E_OK; } } *(ppPackageInfo) = NULL; - return SEC_E_SECPKG_NOT_FOUND; } -SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName, PSecPkgInfoA* ppPackageInfo) +static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName, + PSecPkgInfoA* ppPackageInfo) { int index; size_t size; UINT32 cPackages; SecPkgInfoA* pPackageInfo; - cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST)); for (index = 0; index < (int) cPackages; index++) @@ -753,6 +746,7 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageNa pPackageInfo->cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken; pPackageInfo->Name = _strdup(SecPkgInfoA_LIST[index]->Name); pPackageInfo->Comment = _strdup(SecPkgInfoA_LIST[index]->Comment); + if (!pPackageInfo->Name || !pPackageInfo->Comment) { sspi_ContextBufferFree(pPackageInfo); @@ -760,13 +754,11 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageNa } *(ppPackageInfo) = pPackageInfo; - return SEC_E_OK; } } *(ppPackageInfo) = NULL; - return SEC_E_SECPKG_NOT_FOUND; } @@ -784,9 +776,10 @@ void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer) /* Credential Management */ -SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, + SEC_WCHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SECURITY_STATUS status; SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(pszPackage); @@ -798,20 +791,21 @@ SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipa return SEC_E_UNSUPPORTED_FUNCTION; status = table->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, - pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); + pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "AcquireCredentialsHandleW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, + SEC_CHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SECURITY_STATUS status; SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(pszPackage); @@ -823,23 +817,23 @@ SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal return SEC_E_UNSUPPORTED_FUNCTION; status = table->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, - pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); + pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "AcquireCredentialsHandleA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags, PSecBuffer pPackedContext, HANDLE* pToken) +static SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags, + PSecBuffer pPackedContext, HANDLE* pToken) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -858,18 +852,17 @@ SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULO if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "ExportSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential) +static SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -888,18 +881,18 @@ SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential) if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "FreeCredentialsHandle status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage, + PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -918,18 +911,18 @@ SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage, PS if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "ImportSecurityContextW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage, + PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext) { char* Name = NULL; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -948,18 +941,18 @@ SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage, PSe if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "ImportSecurityContextA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { SEC_WCHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_WCHAR*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -978,18 +971,18 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCreden if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "QueryCredentialsAttributesW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -1008,7 +1001,7 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCreden if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "QueryCredentialsAttributesA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -1016,14 +1009,14 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCreden /* Context Management */ -SECURITY_STATUS SEC_ENTRY winpr_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, - PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) +static SECURITY_STATUS SEC_ENTRY winpr_AcceptSecurityContext(PCredHandle phCredential, + PCtxtHandle phContext, + PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -1038,23 +1031,23 @@ SECURITY_STATUS SEC_ENTRY winpr_AcceptSecurityContext(PCredHandle phCredential, return SEC_E_UNSUPPORTED_FUNCTION; status = table->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, - TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsTimeStamp); + TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsTimeStamp); if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "AcceptSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext, PSecBufferDesc pInput) +static SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext, + PSecBufferDesc pInput) { char* Name = NULL; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1073,18 +1066,18 @@ SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext, PSecBuf if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "ApplyControlToken status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken) +static SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext, + PSecBufferDesc pToken) { char* Name = NULL; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1103,18 +1096,17 @@ SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext, PSecBuf if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext) { char* Name = NULL; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1133,28 +1125,26 @@ SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext) if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "DeleteSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_FreeContextBuffer(void* pvContextBuffer) +static SECURITY_STATUS SEC_ENTRY winpr_FreeContextBuffer(void* pvContextBuffer) { if (!pvContextBuffer) return SEC_E_INVALID_HANDLE; sspi_ContextBufferFree(pvContextBuffer); - return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1173,21 +1163,21 @@ SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "ImpersonateSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, - SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -1202,27 +1192,27 @@ SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(PCredHandle phCredent return SEC_E_UNSUPPORTED_FUNCTION; status = table->InitializeSecurityContextW(phCredential, phContext, - pszTargetName, fContextReq, Reserved1, TargetDataRep, - pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); + pszTargetName, fContextReq, Reserved1, TargetDataRep, + pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "InitializeSecurityContextW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, - SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +static SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -1237,24 +1227,25 @@ SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(PCredHandle phCredent return SEC_E_UNSUPPORTED_FUNCTION; status = table->InitializeSecurityContextA(phCredential, phContext, - pszTargetName, fContextReq, Reserved1, TargetDataRep, - pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); + pszTargetName, fContextReq, Reserved1, TargetDataRep, + pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "InitializeSecurityContextA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext, + ULONG ulAttribute, + void* pBuffer) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1273,18 +1264,19 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext, U if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "QueryContextAttributesW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext, + ULONG ulAttribute, + void* pBuffer) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1303,18 +1295,18 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext, U if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "QueryContextAttributesA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext, HANDLE* phToken) +static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext, + HANDLE* phToken) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1333,18 +1325,19 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext, if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "QuerySecurityContextToken status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) +static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext, + ULONG ulAttribute, + void* pBuffer, ULONG cbBuffer) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1363,18 +1356,19 @@ SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext, ULO if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "SetContextAttributesW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) +static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext, + ULONG ulAttribute, + void* pBuffer, ULONG cbBuffer) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1393,18 +1387,17 @@ SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext, ULO if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "SetContextAttributesA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext) +static SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1423,7 +1416,7 @@ SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext) if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "RevertSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -1431,12 +1424,13 @@ SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext) /* Message Support */ -SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) +static SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext, + PSecBufferDesc pMessage, + ULONG MessageSeqNo, PULONG pfQOP) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1455,18 +1449,18 @@ SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext, PSecBuffer if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "DecryptMessage status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +static SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1485,18 +1479,18 @@ SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP if (status != SEC_E_OK) { WLog_ERR(TAG, "EncryptMessage status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +static SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1515,18 +1509,19 @@ SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP, if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "MakeSignature status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) +static SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, + PSecBufferDesc pMessage, + ULONG MessageSeqNo, PULONG pfQOP) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1545,13 +1540,13 @@ SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, PSecBuffe if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "VerifySignature status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SecurityFunctionTableA winpr_SecurityFunctionTableA = +static SecurityFunctionTableA winpr_SecurityFunctionTableA = { 1, /* dwVersion */ winpr_EnumerateSecurityPackagesA, /* EnumerateSecurityPackages */ @@ -1583,7 +1578,7 @@ SecurityFunctionTableA winpr_SecurityFunctionTableA = winpr_SetContextAttributesA, /* SetContextAttributes */ }; -SecurityFunctionTableW winpr_SecurityFunctionTableW = +static SecurityFunctionTableW winpr_SecurityFunctionTableW = { 1, /* dwVersion */ winpr_EnumerateSecurityPackagesW, /* EnumerateSecurityPackages */ diff --git a/winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c b/winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c index 66ebaca..626b6a8 100644 --- a/winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c +++ b/winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c @@ -10,52 +10,47 @@ static const char* test_Password = "Password"; int TestAcquireCredentialsHandle(int argc, char* argv[]) { + int rc = -1; SECURITY_STATUS status; - CredHandle credentials; + CredHandle credentials = { 0 }; TimeStamp expiration; SEC_WINNT_AUTH_IDENTITY identity; SecurityFunctionTable* table; SecPkgCredentials_Names credential_names; - sspi_GlobalInit(); - table = InitSecurityInterface(); - identity.User = (UINT16*) _strdup(test_User); identity.Domain = (UINT16*) _strdup(test_Domain); identity.Password = (UINT16*) _strdup(test_Password); + if (!identity.User || !identity.Domain || !identity.Password) - { - free(identity.User); - free(identity.Domain); - free(identity.Password); - fprintf(stderr, "Memory allocation failed\n"); - return -1; - } + goto fail; + identity.UserLength = strlen(test_User); identity.DomainLength = strlen(test_Domain); identity.PasswordLength = strlen(test_Password); identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; - - status = table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, - SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); + status = table->AcquireCredentialsHandle(NULL, NTLM_SSP_NAME, + SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) - { - sspi_GlobalFinish(); - return -1; - } + goto fail; status = table->QueryCredentialsAttributes(&credentials, SECPKG_CRED_ATTR_NAMES, &credential_names); if (status != SEC_E_OK) - { - sspi_GlobalFinish(); - return -1; - } + goto fail; + rc = 0; +fail: + + if (SecIsValidHandle(&credentials)) + table->FreeCredentialsHandle(&credentials); + + free(identity.User); + free(identity.Domain); + free(identity.Password); sspi_GlobalFinish(); - - return 0; + return rc; } diff --git a/winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c b/winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c index e5e9308..92261f4 100644 --- a/winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c +++ b/winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c @@ -10,102 +10,102 @@ static const char* test_Password = "Password"; int TestInitializeSecurityContext(int argc, char* argv[]) { + int rc = -1; UINT32 cbMaxLen; UINT32 fContextReq; - void* output_buffer; + void* output_buffer = NULL; CtxtHandle context; ULONG pfContextAttr; SECURITY_STATUS status; - CredHandle credentials; + CredHandle credentials = { 0 }; TimeStamp expiration; PSecPkgInfo pPackageInfo; - SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY identity = { 0 }; SecurityFunctionTable* table; PSecBuffer p_SecBuffer; SecBuffer output_SecBuffer; SecBufferDesc output_SecBuffer_desc; - sspi_GlobalInit(); - table = InitSecurityInterface(); - - status = QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo); + status = QuerySecurityPackageInfo(NTLM_SSP_NAME, &pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo status: 0x%08"PRIX32"\n", status); - return -1; + goto fail; } cbMaxLen = pPackageInfo->cbMaxToken; - identity.User = (UINT16*) _strdup(test_User); identity.Domain = (UINT16*) _strdup(test_Domain); identity.Password = (UINT16*) _strdup(test_Password); + if (!identity.User || !identity.Domain || !identity.Password) - { - free(identity.User); - free(identity.Domain); - free(identity.Password); - fprintf(stderr, "Memory allocation failed\n"); - return -1; - } + goto fail; identity.UserLength = strlen(test_User); identity.DomainLength = strlen(test_Domain); identity.PasswordLength = strlen(test_Password); identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; - - status = table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, - SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); + status = table->AcquireCredentialsHandle(NULL, NTLM_SSP_NAME, + SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle status: 0x%08"PRIX32"\n", status); - sspi_GlobalFinish(); - return -1; + goto fail; } - fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE; - + fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | + ISC_REQ_DELEGATE; output_buffer = malloc(cbMaxLen); + if (!output_buffer) { printf("Memory allocation failed\n"); - sspi_GlobalFinish(); - return -1; + goto fail; } output_SecBuffer_desc.ulVersion = 0; output_SecBuffer_desc.cBuffers = 1; output_SecBuffer_desc.pBuffers = &output_SecBuffer; - output_SecBuffer.cbBuffer = cbMaxLen; output_SecBuffer.BufferType = SECBUFFER_TOKEN; output_SecBuffer.pvBuffer = output_buffer; - status = table->InitializeSecurityContext(&credentials, NULL, NULL, fContextReq, 0, 0, NULL, 0, - &context, &output_SecBuffer_desc, &pfContextAttr, &expiration); + &context, &output_SecBuffer_desc, &pfContextAttr, &expiration); if (status != SEC_I_CONTINUE_NEEDED) { printf("InitializeSecurityContext status: 0x%08"PRIX32"\n", status); - sspi_GlobalFinish(); - return -1; + goto fail; } - printf("cBuffers: %"PRIu32" ulVersion: %"PRIu32"\n", output_SecBuffer_desc.cBuffers, output_SecBuffer_desc.ulVersion); - + printf("cBuffers: %"PRIu32" ulVersion: %"PRIu32"\n", output_SecBuffer_desc.cBuffers, + output_SecBuffer_desc.ulVersion); p_SecBuffer = &output_SecBuffer_desc.pBuffers[0]; + printf("BufferType: 0x%08"PRIX32" cbBuffer: %"PRIu32"\n", p_SecBuffer->BufferType, + p_SecBuffer->cbBuffer); + status = table->DeleteSecurityContext(&context); - printf("BufferType: 0x%08"PRIX32" cbBuffer: %"PRIu32"\n", p_SecBuffer->BufferType, p_SecBuffer->cbBuffer); + if (status != SEC_E_OK) + { + printf("DeleteSecurityContext status: 0x%08"PRIX32"\n", status); + goto fail; + } - table->FreeCredentialsHandle(&credentials); + rc = 0; +fail: + free(identity.User); + free(identity.Domain); + free(identity.Password); + free(output_buffer); + + if (SecIsValidHandle(&credentials)) + table->FreeCredentialsHandle(&credentials); FreeContextBuffer(pPackageInfo); - sspi_GlobalFinish(); - - return 0; + return rc; } diff --git a/winpr/libwinpr/sspi/test/TestNTLM.c b/winpr/libwinpr/sspi/test/TestNTLM.c index eb424e6..539d993 100644 --- a/winpr/libwinpr/sspi/test/TestNTLM.c +++ b/winpr/libwinpr/sspi/test/TestNTLM.c @@ -11,50 +11,50 @@ static BYTE TEST_NTLM_CLIENT_CHALLENGE[8] = { 0x20, 0xc0, 0x2b, 0x3d, 0xc0, 0x61 static BYTE TEST_NTLM_SERVER_CHALLENGE[8] = { 0xa4, 0xf1, 0xba, 0xa6, 0x7c, 0xdc, 0x1a, 0x12 }; static BYTE TEST_NTLM_NEGOTIATE[] = - "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x06\x03\x80\x25\x00\x00\x00\x0f"; + "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x06\x03\x80\x25\x00\x00\x00\x0f"; static BYTE TEST_NTLM_CHALLENGE[] = - "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x02\x00\x00\x00\x00\x00\x00\x00" - "\x38\x00\x00\x00\x07\x82\x88\xa2\xa4\xf1\xba\xa6\x7c\xdc\x1a\x12" - "\x00\x00\x00\x00\x00\x00\x00\x00\x66\x00\x66\x00\x38\x00\x00\x00" - "\x06\x03\x80\x25\x00\x00\x00\x0f\x02\x00\x0e\x00\x4e\x00\x45\x00" - "\x57\x00\x59\x00\x45\x00\x41\x00\x52\x00\x01\x00\x0e\x00\x4e\x00" - "\x45\x00\x57\x00\x59\x00\x45\x00\x41\x00\x52\x00\x04\x00\x1c\x00" - "\x6c\x00\x61\x00\x62\x00\x2e\x00\x77\x00\x61\x00\x79\x00\x6b\x00" - "\x2e\x00\x6c\x00\x6f\x00\x63\x00\x61\x00\x6c\x00\x03\x00\x0e\x00" - "\x6e\x00\x65\x00\x77\x00\x79\x00\x65\x00\x61\x00\x72\x00\x07\x00" - "\x08\x00\x33\x57\xbd\xb1\x07\x8b\xcf\x01\x00\x00\x00\x00"; + "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x02\x00\x00\x00\x00\x00\x00\x00" + "\x38\x00\x00\x00\x07\x82\x88\xa2\xa4\xf1\xba\xa6\x7c\xdc\x1a\x12" + "\x00\x00\x00\x00\x00\x00\x00\x00\x66\x00\x66\x00\x38\x00\x00\x00" + "\x06\x03\x80\x25\x00\x00\x00\x0f\x02\x00\x0e\x00\x4e\x00\x45\x00" + "\x57\x00\x59\x00\x45\x00\x41\x00\x52\x00\x01\x00\x0e\x00\x4e\x00" + "\x45\x00\x57\x00\x59\x00\x45\x00\x41\x00\x52\x00\x04\x00\x1c\x00" + "\x6c\x00\x61\x00\x62\x00\x2e\x00\x77\x00\x61\x00\x79\x00\x6b\x00" + "\x2e\x00\x6c\x00\x6f\x00\x63\x00\x61\x00\x6c\x00\x03\x00\x0e\x00" + "\x6e\x00\x65\x00\x77\x00\x79\x00\x65\x00\x61\x00\x72\x00\x07\x00" + "\x08\x00\x33\x57\xbd\xb1\x07\x8b\xcf\x01\x00\x00\x00\x00"; static BYTE TEST_NTLM_AUTHENTICATE[] = - "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x03\x00\x00\x00\x18\x00\x18\x00" - "\x82\x00\x00\x00\x08\x01\x08\x01\x9a\x00\x00\x00\x0c\x00\x0c\x00" - "\x58\x00\x00\x00\x10\x00\x10\x00\x64\x00\x00\x00\x0e\x00\x0e\x00" - "\x74\x00\x00\x00\x00\x00\x00\x00\xa2\x01\x00\x00\x05\x82\x88\xa2" - "\x06\x03\x80\x25\x00\x00\x00\x0f\x12\xe5\x5a\xf5\x80\xee\x3f\x29" - "\xe1\xde\x90\x4d\x73\x77\x06\x25\x44\x00\x6f\x00\x6d\x00\x61\x00" - "\x69\x00\x6e\x00\x55\x00\x73\x00\x65\x00\x72\x00\x6e\x00\x61\x00" - "\x6d\x00\x65\x00\x4e\x00\x45\x00\x57\x00\x59\x00\x45\x00\x41\x00" - "\x52\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x62\x14\x68\xc8\x98\x12" - "\xe7\x39\xd8\x76\x1b\xe9\xf7\x54\xb5\xe3\x01\x01\x00\x00\x00\x00" - "\x00\x00\x33\x57\xbd\xb1\x07\x8b\xcf\x01\x20\xc0\x2b\x3d\xc0\x61" - "\xa7\x73\x00\x00\x00\x00\x02\x00\x0e\x00\x4e\x00\x45\x00\x57\x00" - "\x59\x00\x45\x00\x41\x00\x52\x00\x01\x00\x0e\x00\x4e\x00\x45\x00" - "\x57\x00\x59\x00\x45\x00\x41\x00\x52\x00\x04\x00\x1c\x00\x6c\x00" - "\x61\x00\x62\x00\x2e\x00\x77\x00\x61\x00\x79\x00\x6b\x00\x2e\x00" - "\x6c\x00\x6f\x00\x63\x00\x61\x00\x6c\x00\x03\x00\x0e\x00\x6e\x00" - "\x65\x00\x77\x00\x79\x00\x65\x00\x61\x00\x72\x00\x07\x00\x08\x00" - "\x33\x57\xbd\xb1\x07\x8b\xcf\x01\x06\x00\x04\x00\x02\x00\x00\x00" - "\x08\x00\x30\x00\x30\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" - "\x00\x20\x00\x00\x1e\x10\xf5\x2c\x54\x2f\x2e\x77\x1c\x13\xbf\xc3" - "\x3f\xe1\x7b\x28\x7e\x0b\x93\x5a\x39\xd2\xce\x12\xd7\xbd\x8c\x4e" - "\x2b\xb5\x0b\xf5\x0a\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x1a\x00\x48\x00\x54\x00" - "\x54\x00\x50\x00\x2f\x00\x72\x00\x77\x00\x2e\x00\x6c\x00\x6f\x00" - "\x63\x00\x61\x00\x6c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00"; + "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x03\x00\x00\x00\x18\x00\x18\x00" + "\x82\x00\x00\x00\x08\x01\x08\x01\x9a\x00\x00\x00\x0c\x00\x0c\x00" + "\x58\x00\x00\x00\x10\x00\x10\x00\x64\x00\x00\x00\x0e\x00\x0e\x00" + "\x74\x00\x00\x00\x00\x00\x00\x00\xa2\x01\x00\x00\x05\x82\x88\xa2" + "\x06\x03\x80\x25\x00\x00\x00\x0f\x12\xe5\x5a\xf5\x80\xee\x3f\x29" + "\xe1\xde\x90\x4d\x73\x77\x06\x25\x44\x00\x6f\x00\x6d\x00\x61\x00" + "\x69\x00\x6e\x00\x55\x00\x73\x00\x65\x00\x72\x00\x6e\x00\x61\x00" + "\x6d\x00\x65\x00\x4e\x00\x45\x00\x57\x00\x59\x00\x45\x00\x41\x00" + "\x52\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x62\x14\x68\xc8\x98\x12" + "\xe7\x39\xd8\x76\x1b\xe9\xf7\x54\xb5\xe3\x01\x01\x00\x00\x00\x00" + "\x00\x00\x33\x57\xbd\xb1\x07\x8b\xcf\x01\x20\xc0\x2b\x3d\xc0\x61" + "\xa7\x73\x00\x00\x00\x00\x02\x00\x0e\x00\x4e\x00\x45\x00\x57\x00" + "\x59\x00\x45\x00\x41\x00\x52\x00\x01\x00\x0e\x00\x4e\x00\x45\x00" + "\x57\x00\x59\x00\x45\x00\x41\x00\x52\x00\x04\x00\x1c\x00\x6c\x00" + "\x61\x00\x62\x00\x2e\x00\x77\x00\x61\x00\x79\x00\x6b\x00\x2e\x00" + "\x6c\x00\x6f\x00\x63\x00\x61\x00\x6c\x00\x03\x00\x0e\x00\x6e\x00" + "\x65\x00\x77\x00\x79\x00\x65\x00\x61\x00\x72\x00\x07\x00\x08\x00" + "\x33\x57\xbd\xb1\x07\x8b\xcf\x01\x06\x00\x04\x00\x02\x00\x00\x00" + "\x08\x00\x30\x00\x30\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + "\x00\x20\x00\x00\x1e\x10\xf5\x2c\x54\x2f\x2e\x77\x1c\x13\xbf\xc3" + "\x3f\xe1\x7b\x28\x7e\x0b\x93\x5a\x39\xd2\xce\x12\xd7\xbd\x8c\x4e" + "\x2b\xb5\x0b\xf5\x0a\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x1a\x00\x48\x00\x54\x00" + "\x54\x00\x50\x00\x2f\x00\x72\x00\x77\x00\x2e\x00\x6c\x00\x6f\x00" + "\x63\x00\x61\x00\x6c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00"; #define TEST_SSPI_INTERFACE SSPI_INTERFACE_WINPR @@ -72,8 +72,7 @@ static const BYTE TEST_NTLM_HASH[16] = static const BYTE TEST_NTLM_V2_HASH[16] = { 0x4c, 0x7f, 0x70, 0x6f, 0x7d, 0xde, 0x05, 0xa9, 0xd1, 0xa0, 0xf4, 0xe7, 0xff, 0xe3, 0xbf, 0xb8 }; -//#define NTLM_PACKAGE_NAME NEGOSSP_NAME -#define NTLM_PACKAGE_NAME NTLMSP_NAME +#define NTLM_PACKAGE_NAME NTLM_SSP_NAME struct _TEST_NTLM_CLIENT { @@ -98,7 +97,8 @@ struct _TEST_NTLM_CLIENT }; typedef struct _TEST_NTLM_CLIENT TEST_NTLM_CLIENT; -int test_ntlm_client_init(TEST_NTLM_CLIENT* ntlm, const char* user, const char* domain, const char* password) +int test_ntlm_client_init(TEST_NTLM_CLIENT* ntlm, const char* user, const char* domain, + const char* password) { SECURITY_STATUS status; SecInvalidateHandle(&(ntlm->context)); @@ -109,18 +109,18 @@ int test_ntlm_client_init(TEST_NTLM_CLIENT* ntlm, const char* user, const char* if (status != SEC_E_OK) { fprintf(stderr, "QuerySecurityPackageInfo status: %s (0x%08"PRIX32")\n", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); return -1; } ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken; status = ntlm->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME, - SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration); + SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration); if (status != SEC_E_OK) { fprintf(stderr, "AcquireCredentialsHandle status: %s (0x%08"PRIX32")\n", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); return -1; } @@ -237,12 +237,12 @@ int test_ntlm_client_authenticate(TEST_NTLM_CLIENT* ntlm) } status = ntlm->table->InitializeSecurityContext(&ntlm->credentials, - (ntlm->haveContext) ? &ntlm->context : NULL, - (ntlm->ServicePrincipalName) ? ntlm->ServicePrincipalName : NULL, - ntlm->fContextReq, 0, SECURITY_NATIVE_DREP, - (ntlm->haveInputBuffer) ? &ntlm->inputBufferDesc : NULL, - 0, &ntlm->context, &ntlm->outputBufferDesc, - &ntlm->pfContextAttr, &ntlm->expiration); + (ntlm->haveContext) ? &ntlm->context : NULL, + (ntlm->ServicePrincipalName) ? ntlm->ServicePrincipalName : NULL, + ntlm->fContextReq, 0, SECURITY_NATIVE_DREP, + (ntlm->haveInputBuffer) ? &ntlm->inputBufferDesc : NULL, + 0, &ntlm->context, &ntlm->outputBufferDesc, + &ntlm->pfContextAttr, &ntlm->expiration); if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED)) { @@ -320,19 +320,19 @@ int test_ntlm_server_init(TEST_NTLM_SERVER* ntlm) if (status != SEC_E_OK) { fprintf(stderr, "QuerySecurityPackageInfo status: %s (0x%08"PRIX32")\n", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); return -1; } ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken; status = ntlm->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME, - SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, - &ntlm->credentials, &ntlm->expiration); + SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, + &ntlm->credentials, &ntlm->expiration); if (status != SEC_E_OK) { fprintf(stderr, "AcquireCredentialsHandle status: %s (0x%08"PRIX32")\n", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); return -1; } @@ -389,13 +389,14 @@ int test_ntlm_server_authenticate(TEST_NTLM_SERVER* ntlm) ntlm->outputBuffer[0].BufferType = SECBUFFER_TOKEN; ntlm->outputBuffer[0].cbBuffer = ntlm->cbMaxToken; ntlm->outputBuffer[0].pvBuffer = malloc(ntlm->outputBuffer[0].cbBuffer); + if (!ntlm->outputBuffer[0].pvBuffer) return -1; status = ntlm->table->AcceptSecurityContext(&ntlm->credentials, - ntlm->haveContext? &ntlm->context: NULL, - &ntlm->inputBufferDesc, ntlm->fContextReq, SECURITY_NATIVE_DREP, &ntlm->context, - &ntlm->outputBufferDesc, &ntlm->pfContextAttr, &ntlm->expiration); + ntlm->haveContext ? &ntlm->context : NULL, + &ntlm->inputBufferDesc, ntlm->fContextReq, SECURITY_NATIVE_DREP, &ntlm->context, + &ntlm->outputBufferDesc, &ntlm->pfContextAttr, &ntlm->expiration); if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED)) { @@ -403,7 +404,8 @@ int test_ntlm_server_authenticate(TEST_NTLM_SERVER* ntlm) SecPkgContext_AuthNtlmHash AuthNtlmHash; ZeroMemory(&AuthIdentity, sizeof(SecPkgContext_AuthIdentity)); ZeroMemory(&AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash)); - status = ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_AUTH_IDENTITY, &AuthIdentity); + status = ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_AUTH_IDENTITY, + &AuthIdentity); if (status == SEC_E_OK) { @@ -421,7 +423,7 @@ int test_ntlm_server_authenticate(TEST_NTLM_SERVER* ntlm) } status = ntlm->table->SetContextAttributes(&ntlm->context, - SECPKG_ATTR_AUTH_NTLM_HASH, &AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash)); + SECPKG_ATTR_AUTH_NTLM_HASH, &AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash)); } } @@ -437,7 +439,7 @@ int test_ntlm_server_authenticate(TEST_NTLM_SERVER* ntlm) if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED)) { fprintf(stderr, "AcceptSecurityContext status: %s (0x%08"PRIX32")\n", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); return -1; /* Access Denied */ } @@ -476,11 +478,13 @@ int TestNTLM(int argc, char* argv[]) * Client Initialization */ client = test_ntlm_client_new(); + if (!client) { printf("Memory allocation failed"); return -1; } + status = test_ntlm_client_init(client, TEST_NTLM_USER, TEST_NTLM_DOMAIN, TEST_NTLM_PASSWORD); if (status < 0) @@ -493,11 +497,13 @@ int TestNTLM(int argc, char* argv[]) * Server Initialization */ server = test_ntlm_server_new(); + if (!server) { printf("Memory allocation failed\n"); return -1; } + status = test_ntlm_server_init(server); if (status < 0) @@ -525,24 +531,25 @@ int TestNTLM(int argc, char* argv[]) CopyMemory(AuthNtlmTimestamp.Timestamp, TEST_NTLM_TIMESTAMP, 8); AuthNtlmTimestamp.ChallengeOrResponse = TRUE; client->table->SetContextAttributes(&client->context, SECPKG_ATTR_AUTH_NTLM_TIMESTAMP, - &AuthNtlmTimestamp, sizeof(SecPkgContext_AuthNtlmTimestamp)); + &AuthNtlmTimestamp, sizeof(SecPkgContext_AuthNtlmTimestamp)); AuthNtlmTimestamp.ChallengeOrResponse = FALSE; client->table->SetContextAttributes(&client->context, SECPKG_ATTR_AUTH_NTLM_TIMESTAMP, - &AuthNtlmTimestamp, sizeof(SecPkgContext_AuthNtlmTimestamp)); + &AuthNtlmTimestamp, sizeof(SecPkgContext_AuthNtlmTimestamp)); CopyMemory(AuthNtlmClientChallenge.ClientChallenge, TEST_NTLM_CLIENT_CHALLENGE, 8); CopyMemory(AuthNtlmServerChallenge.ServerChallenge, TEST_NTLM_SERVER_CHALLENGE, 8); client->table->SetContextAttributes(&client->context, SECPKG_ATTR_AUTH_NTLM_CLIENT_CHALLENGE, - &AuthNtlmClientChallenge, sizeof(SecPkgContext_AuthNtlmClientChallenge)); + &AuthNtlmClientChallenge, sizeof(SecPkgContext_AuthNtlmClientChallenge)); client->table->SetContextAttributes(&client->context, SECPKG_ATTR_AUTH_NTLM_SERVER_CHALLENGE, - &AuthNtlmServerChallenge, sizeof(SecPkgContext_AuthNtlmServerChallenge)); + &AuthNtlmServerChallenge, sizeof(SecPkgContext_AuthNtlmServerChallenge)); } pSecBuffer = &(client->outputBuffer[0]); if (!DynamicTest) { - pSecBuffer->cbBuffer = sizeof(TEST_NTLM_NEGOTIATE) -1; + pSecBuffer->cbBuffer = sizeof(TEST_NTLM_NEGOTIATE) - 1; pSecBuffer->pvBuffer = (void*) malloc(pSecBuffer->cbBuffer); + if (!pSecBuffer->pvBuffer) { printf("Memory allocation failed\n"); @@ -578,16 +585,16 @@ int TestNTLM(int argc, char* argv[]) CopyMemory(AuthNtlmTimestamp.Timestamp, TEST_NTLM_TIMESTAMP, 8); AuthNtlmTimestamp.ChallengeOrResponse = TRUE; client->table->SetContextAttributes(&server->context, SECPKG_ATTR_AUTH_NTLM_TIMESTAMP, - &AuthNtlmTimestamp, sizeof(SecPkgContext_AuthNtlmTimestamp)); + &AuthNtlmTimestamp, sizeof(SecPkgContext_AuthNtlmTimestamp)); AuthNtlmTimestamp.ChallengeOrResponse = FALSE; client->table->SetContextAttributes(&server->context, SECPKG_ATTR_AUTH_NTLM_TIMESTAMP, - &AuthNtlmTimestamp, sizeof(SecPkgContext_AuthNtlmTimestamp)); + &AuthNtlmTimestamp, sizeof(SecPkgContext_AuthNtlmTimestamp)); CopyMemory(AuthNtlmClientChallenge.ClientChallenge, TEST_NTLM_CLIENT_CHALLENGE, 8); CopyMemory(AuthNtlmServerChallenge.ServerChallenge, TEST_NTLM_SERVER_CHALLENGE, 8); server->table->SetContextAttributes(&server->context, SECPKG_ATTR_AUTH_NTLM_CLIENT_CHALLENGE, - &AuthNtlmClientChallenge, sizeof(SecPkgContext_AuthNtlmClientChallenge)); + &AuthNtlmClientChallenge, sizeof(SecPkgContext_AuthNtlmClientChallenge)); server->table->SetContextAttributes(&server->context, SECPKG_ATTR_AUTH_NTLM_SERVER_CHALLENGE, - &AuthNtlmServerChallenge, sizeof(SecPkgContext_AuthNtlmServerChallenge)); + &AuthNtlmServerChallenge, sizeof(SecPkgContext_AuthNtlmServerChallenge)); } pSecBuffer = &(server->outputBuffer[0]); @@ -595,19 +602,21 @@ int TestNTLM(int argc, char* argv[]) if (!DynamicTest) { SecPkgContext_AuthNtlmMessage AuthNtlmMessage; - pSecBuffer->cbBuffer = sizeof(TEST_NTLM_CHALLENGE) -1; + pSecBuffer->cbBuffer = sizeof(TEST_NTLM_CHALLENGE) - 1; pSecBuffer->pvBuffer = (void*) malloc(pSecBuffer->cbBuffer); + if (!pSecBuffer->pvBuffer) { printf("Memory allocation failed\n"); return -1; } + CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_CHALLENGE, pSecBuffer->cbBuffer); AuthNtlmMessage.type = 2; AuthNtlmMessage.length = pSecBuffer->cbBuffer; AuthNtlmMessage.buffer = (BYTE*) pSecBuffer->pvBuffer; server->table->SetContextAttributes(&server->context, SECPKG_ATTR_AUTH_NTLM_MESSAGE, - &AuthNtlmMessage, sizeof(SecPkgContext_AuthNtlmMessage)); + &AuthNtlmMessage, sizeof(SecPkgContext_AuthNtlmMessage)); } fprintf(stderr, "NTLM_CHALLENGE (length = %"PRIu32"):\n", pSecBuffer->cbBuffer); @@ -632,13 +641,15 @@ int TestNTLM(int argc, char* argv[]) if (!DynamicTest) { - pSecBuffer->cbBuffer = sizeof(TEST_NTLM_AUTHENTICATE) -1; + pSecBuffer->cbBuffer = sizeof(TEST_NTLM_AUTHENTICATE) - 1; pSecBuffer->pvBuffer = (void*) malloc(pSecBuffer->cbBuffer); + if (!pSecBuffer->pvBuffer) { printf("Memory allocation failed\n"); return -1; } + CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_AUTHENTICATE, pSecBuffer->cbBuffer); } diff --git a/winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c b/winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c index a85797f..8f5b621 100644 --- a/winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c +++ b/winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c @@ -6,24 +6,23 @@ int TestQuerySecurityPackageInfo(int argc, char* argv[]) { + int rc; SECURITY_STATUS status; SecPkgInfo* pPackageInfo; - sspi_GlobalInit(); - - status = QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo); + status = QuerySecurityPackageInfo(NTLM_SSP_NAME, &pPackageInfo); if (status != SEC_E_OK) + rc = -1; + else { - sspi_GlobalFinish(); - return -1; + _tprintf(_T("\nQuerySecurityPackageInfo:\n")); + _tprintf(_T("\"%s\", \"%s\"\n"), pPackageInfo->Name, pPackageInfo->Comment); + rc = 0; } - _tprintf(_T("\nQuerySecurityPackageInfo:\n")); - _tprintf(_T("\"%s\", \"%s\"\n"), pPackageInfo->Name, pPackageInfo->Comment); - + FreeContextBuffer(pPackageInfo); sspi_GlobalFinish(); - - return 0; + return rc; } diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index f22ccfe..18cdde7 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -12,15 +12,15 @@ #include <winpr/wlog.h> #include <winpr/schannel.h> -BOOL g_ClientWait = FALSE; -BOOL g_ServerWait = FALSE; +static BOOL g_ClientWait = FALSE; +static BOOL g_ServerWait = FALSE; -HANDLE g_ClientReadPipe = NULL; -HANDLE g_ClientWritePipe = NULL; -HANDLE g_ServerReadPipe = NULL; -HANDLE g_ServerWritePipe = NULL; +static HANDLE g_ClientReadPipe = NULL; +static HANDLE g_ClientWritePipe = NULL; +static HANDLE g_ServerReadPipe = NULL; +static HANDLE g_ServerWritePipe = NULL; -BYTE test_localhost_crt[1029] = +static const BYTE test_localhost_crt[1029] = { 0x2D,0x2D,0x2D,0x2D,0x2D,0x42,0x45,0x47,0x49,0x4E,0x20,0x43,0x45,0x52,0x54, 0x49,0x46,0x49,0x43,0x41,0x54,0x45,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A,0x4D,0x49, @@ -93,7 +93,7 @@ BYTE test_localhost_crt[1029] = 0x41,0x54,0x45,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A }; -BYTE test_localhost_key[1704] = +static const BYTE test_localhost_key[1704] = { 0x2D,0x2D,0x2D,0x2D,0x2D,0x42,0x45,0x47,0x49,0x4E,0x20,0x50,0x52,0x49,0x56, 0x41,0x54,0x45,0x20,0x4B,0x45,0x59,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A,0x4D,0x49, @@ -211,7 +211,7 @@ BYTE test_localhost_key[1704] = 0x4B,0x45,0x59,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A }; -BYTE test_DummyMessage[64] = +static const BYTE test_DummyMessage[64] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, @@ -219,7 +219,7 @@ BYTE test_DummyMessage[64] = 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD }; -BYTE test_LastDummyMessage[64] = +static const BYTE test_LastDummyMessage[64] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -227,7 +227,7 @@ BYTE test_LastDummyMessage[64] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext, BYTE* buffer, UINT32 length) +static int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext, BYTE* buffer, UINT32 length) { BYTE* ioBuffer; UINT32 ioBufferLength; @@ -284,7 +284,7 @@ int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont return 0; } -int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext) +static int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext) { BYTE* ioBuffer; UINT32 ioBufferLength; @@ -342,7 +342,7 @@ int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont return 0; } -static void* schannel_test_server_thread(void* arg) +static DWORD WINAPI schannel_test_server_thread(LPVOID arg) { BOOL extraData; BYTE* lpTokenIn; @@ -377,7 +377,7 @@ static void* schannel_test_server_thread(void* arg) if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo failure: 0x%08"PRIX32"\n", status); - return NULL; + return 0; } cbMaxToken = pPackageInfo->cbMaxToken; @@ -406,7 +406,7 @@ static void* schannel_test_server_thread(void* arg) if (!pszNameString) { printf("Memory allocation failed\n"); - return NULL; + return 0; } cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, cchNameString); _tprintf(_T("Certificate Name: %s\n"), pszNameString); @@ -424,7 +424,7 @@ static void* schannel_test_server_thread(void* arg) if (status != SEC_E_OK) { printf("AcquireCredentialsHandle failure: 0x%08"PRIX32"\n", status); - return NULL; + return 0; } extraData = FALSE; @@ -432,13 +432,13 @@ static void* schannel_test_server_thread(void* arg) if (!(lpTokenIn = (BYTE*) malloc(cbMaxToken))) { printf("Memory allocation failed\n"); - return NULL; + return 0; } if (!(lpTokenOut = (BYTE*) malloc(cbMaxToken))) { printf("Memory allocation failed\n"); free(lpTokenIn); - return NULL; + return 0; } fContextReq = ASC_REQ_STREAM | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | @@ -544,10 +544,10 @@ static void* schannel_test_server_thread(void* arg) } while (1); - return NULL; + return 0; } -int dump_test_certificate_files() +static int dump_test_certificate_files(void) { FILE* fp; char* fullpath = NULL; @@ -634,7 +634,7 @@ int TestSchannel(int argc, char* argv[]) return -1; } - if (!(thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) schannel_test_server_thread, NULL, 0, NULL))) + if (!(thread = CreateThread(NULL, 0, schannel_test_server_thread, NULL, 0, NULL))) { printf("Failed to create server thread\n"); return -1; diff --git a/winpr/libwinpr/synch/critical.c b/winpr/libwinpr/synch/critical.c index fe2fdfe..610072b 100644 --- a/winpr/libwinpr/synch/critical.c +++ b/winpr/libwinpr/synch/critical.c @@ -34,6 +34,12 @@ #include <unistd.h> #endif +#if defined(__APPLE__) +#include <mach/task.h> +#include <mach/mach.h> +#include <mach/semaphore.h> +#endif + #ifndef _WIN32 #include "../log.h" @@ -44,7 +50,8 @@ VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) InitializeCriticalSectionEx(lpCriticalSection, 0, 0); } -BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags) +BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, + DWORD Flags) { /** * See http://msdn.microsoft.com/en-us/library/ff541979(v=vs.85).aspx @@ -67,18 +74,24 @@ BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwS lpCriticalSection->RecursionCount = 0; lpCriticalSection->OwningThread = NULL; lpCriticalSection->LockSemaphore = (winpr_sem_t*) malloc(sizeof(winpr_sem_t)); + if (!lpCriticalSection->LockSemaphore) return FALSE; + #if defined(__APPLE__) - if (semaphore_create(mach_task_self(), lpCriticalSection->LockSemaphore, SYNC_POLICY_FIFO, 0) != KERN_SUCCESS) + + if (semaphore_create(mach_task_self(), lpCriticalSection->LockSemaphore, SYNC_POLICY_FIFO, + 0) != KERN_SUCCESS) goto out_fail; + #else - if(sem_init(lpCriticalSection->LockSemaphore, 0, 0) != 0) + + if (sem_init(lpCriticalSection->LockSemaphore, 0, 0) != 0) goto out_fail; + #endif SetCriticalSectionSpinCount(lpCriticalSection, dwSpinCount); return TRUE; - out_fail: free(lpCriticalSection->LockSemaphore); return FALSE; @@ -150,7 +163,7 @@ VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) } /* Failed to get the lock. Let the scheduler know that we're spinning. */ - if (sched_yield()!=0) + if (sched_yield() != 0) { /** * On some operating systems sched_yield is a stub. diff --git a/winpr/libwinpr/synch/event.c b/winpr/libwinpr/synch/event.c index 9f7c168..1fbc4a5 100644 --- a/winpr/libwinpr/synch/event.c +++ b/winpr/libwinpr/synch/event.c @@ -37,7 +37,7 @@ #include <unistd.h> #endif -#ifdef HAVE_EVENTFD_H +#ifdef HAVE_SYS_EVENTFD_H #include <sys/eventfd.h> #endif @@ -126,7 +126,7 @@ HANDLE CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, event->pipe_fd[0] = -1; event->pipe_fd[1] = -1; -#ifdef HAVE_EVENTFD_H +#ifdef HAVE_SYS_EVENTFD_H event->pipe_fd[0] = eventfd(0, EFD_NONBLOCK); if (event->pipe_fd[0] < 0) @@ -176,7 +176,7 @@ HANDLE OpenEventA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName) return NULL; } -#ifdef HAVE_EVENTFD_H +#ifdef HAVE_SYS_EVENTFD_H #if !defined(WITH_EVENTFD_READ_WRITE) static int eventfd_read(int fd, eventfd_t* value) { @@ -202,7 +202,7 @@ BOOL SetEvent(HANDLE hEvent) if (winpr_Handle_GetInfo(hEvent, &Type, &Object)) { event = (WINPR_EVENT*) Object; -#ifdef HAVE_EVENTFD_H +#ifdef HAVE_SYS_EVENTFD_H eventfd_t val = 1; do @@ -249,7 +249,7 @@ BOOL ResetEvent(HANDLE hEvent) { do { -#ifdef HAVE_EVENTFD_H +#ifdef HAVE_SYS_EVENTFD_H eventfd_t value; length = eventfd_read(event->pipe_fd[0], &value); #else diff --git a/winpr/libwinpr/synch/semaphore.c b/winpr/libwinpr/synch/semaphore.c index aa8f80a..68040e6 100644 --- a/winpr/libwinpr/synch/semaphore.c +++ b/winpr/libwinpr/synch/semaphore.c @@ -129,7 +129,7 @@ HANDLE CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lIniti return NULL; semaphore->pipe_fd[0] = -1; - semaphore->pipe_fd[0] = -1; + semaphore->pipe_fd[1] = -1; semaphore->sem = (winpr_sem_t*) NULL; semaphore->ops = &ops; diff --git a/winpr/libwinpr/synch/synch.h b/winpr/libwinpr/synch/synch.h index f8ff093..b0f0db2 100644 --- a/winpr/libwinpr/synch/synch.h +++ b/winpr/libwinpr/synch/synch.h @@ -79,13 +79,17 @@ struct winpr_event }; typedef struct winpr_event WINPR_EVENT; -#ifdef HAVE_TIMERFD_H +#ifdef HAVE_SYS_TIMERFD_H #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/timerfd.h> #endif +#if defined(__APPLE__) +#include <dispatch/dispatch.h> +#endif + struct winpr_timer { WINPR_HANDLE_DEF(); @@ -96,11 +100,17 @@ struct winpr_timer BOOL bManualReset; PTIMERAPCROUTINE pfnCompletionRoutine; LPVOID lpArgToCompletionRoutine; - + #ifdef WITH_POSIX_TIMER timer_t tid; struct itimerspec timeout; #endif +#if defined(__APPLE__) + dispatch_queue_t queue; + dispatch_source_t source; + int pipe[2]; + BOOL running; +#endif }; typedef struct winpr_timer WINPR_TIMER; @@ -109,7 +119,7 @@ typedef struct winpr_timer_queue_timer WINPR_TIMER_QUEUE_TIMER; struct winpr_timer_queue { WINPR_HANDLE_DEF(); - + pthread_t thread; pthread_attr_t attr; pthread_mutex_t mutex; @@ -132,7 +142,7 @@ struct winpr_timer_queue_timer DWORD Period; PVOID Parameter; WAITORTIMERCALLBACK Callback; - + int FireCount; struct timespec StartTime; diff --git a/winpr/libwinpr/synch/test/TestSynchBarrier.c b/winpr/libwinpr/synch/test/TestSynchBarrier.c index 8b96c25..bd6d191 100644 --- a/winpr/libwinpr/synch/test/TestSynchBarrier.c +++ b/winpr/libwinpr/synch/test/TestSynchBarrier.c @@ -23,7 +23,7 @@ struct test_params }; -DWORD WINAPI test_synch_barrier_thread(LPVOID lpParam) +static DWORD WINAPI test_synch_barrier_thread(LPVOID lpParam) { BOOL status = FALSE; struct test_params* p = (struct test_params*)lpParam; diff --git a/winpr/libwinpr/synch/test/TestSynchCritical.c b/winpr/libwinpr/synch/test/TestSynchCritical.c index 3575ace..3c1ab0e 100644 --- a/winpr/libwinpr/synch/test/TestSynchCritical.c +++ b/winpr/libwinpr/synch/test/TestSynchCritical.c @@ -10,11 +10,11 @@ #define TEST_SYNC_CRITICAL_TEST1_RUNTIME_MS 500 #define TEST_SYNC_CRITICAL_TEST1_RUNS 4 -CRITICAL_SECTION critical; -LONG gTestValueVulnerable = 0; -LONG gTestValueSerialized = 0; +static CRITICAL_SECTION critical; +static LONG gTestValueVulnerable = 0; +static LONG gTestValueSerialized = 0; -BOOL TestSynchCritical_TriggerAndCheckRaceCondition(HANDLE OwningThread, LONG RecursionCount) +static BOOL TestSynchCritical_TriggerAndCheckRaceCondition(HANDLE OwningThread, LONG RecursionCount) { /* if called unprotected this will hopefully trigger a race condition ... */ gTestValueVulnerable++; @@ -41,7 +41,7 @@ BOOL TestSynchCritical_TriggerAndCheckRaceCondition(HANDLE OwningThread, LONG Re } /* this thread function shall increment the global dwTestValue until the PBOOL passsed in arg is FALSE */ -static PVOID TestSynchCritical_Test1(PVOID arg) +static DWORD WINAPI TestSynchCritical_Test1(LPVOID arg) { int i, j, rc; HANDLE hThread = (HANDLE) (ULONG_PTR) GetCurrentThreadId(); @@ -55,25 +55,25 @@ static PVOID TestSynchCritical_Test1(PVOID arg) rc = 1; if (!TestSynchCritical_TriggerAndCheckRaceCondition(hThread, rc)) - return (PVOID)1; + return 1; /* add some random recursion level */ j = rand()%5; for (i=0; i<j; i++) { if (!TestSynchCritical_TriggerAndCheckRaceCondition(hThread, rc++)) - return (PVOID)2; + return 2; EnterCriticalSection(&critical); } for (i=0; i<j; i++) { if (!TestSynchCritical_TriggerAndCheckRaceCondition(hThread, rc--)) - return (PVOID)2; + return 2; LeaveCriticalSection(&critical); } if (!TestSynchCritical_TriggerAndCheckRaceCondition(hThread, rc)) - return (PVOID)3; + return 3; LeaveCriticalSection(&critical); } @@ -82,18 +82,17 @@ static PVOID TestSynchCritical_Test1(PVOID arg) } /* this thread function tries to call TryEnterCriticalSection while the main thread holds the lock */ -static PVOID TestSynchCritical_Test2(PVOID arg) +static DWORD WINAPI TestSynchCritical_Test2(LPVOID arg) { if (TryEnterCriticalSection(&critical)==TRUE) { LeaveCriticalSection(&critical); - return (PVOID)1; + return 1; } - return (PVOID)0; + return 0; } - -static PVOID TestSynchCritical_Main(PVOID arg) +static DWORD WINAPI TestSynchCritical_Main(LPVOID arg) { int i, j; SYSTEM_INFO sysinfo; @@ -219,7 +218,7 @@ static PVOID TestSynchCritical_Main(PVOID arg) bTest1Running = TRUE; for (i = 0; i < (int) dwThreadCount; i++) { - if (!(hThreads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) TestSynchCritical_Test1, &bTest1Running, 0, NULL))) + if (!(hThreads[i] = CreateThread(NULL, 0, TestSynchCritical_Test1, &bTest1Running, 0, NULL))) { printf("CriticalSection failure: Failed to create test_1 thread #%d\n", i); goto fail; @@ -270,7 +269,7 @@ static PVOID TestSynchCritical_Main(PVOID arg) goto fail; } /* This thread tries to call TryEnterCriticalSection which must fail */ - if (!(hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) TestSynchCritical_Test2, NULL, 0, NULL))) + if (!(hThread = CreateThread(NULL, 0, TestSynchCritical_Test2, NULL, 0, NULL))) { printf("CriticalSection failure: Failed to create test_2 thread\n"); goto fail; @@ -289,11 +288,11 @@ static PVOID TestSynchCritical_Main(PVOID arg) CloseHandle(hThread); *pbThreadTerminated = TRUE; /* requ. for winpr issue, see below */ - return (PVOID)0; + return 0; fail: *pbThreadTerminated = TRUE; /* requ. for winpr issue, see below */ - return (PVOID)1; + return 1; } @@ -309,7 +308,7 @@ int TestSynchCritical(int argc, char* argv[]) printf("Deadlock will be assumed after %"PRIu32" ms.\n", dwDeadLockDetectionTimeMs); - if (!(hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) TestSynchCritical_Main, &bThreadTerminated, 0, NULL))) + if (!(hThread = CreateThread(NULL, 0, TestSynchCritical_Main, &bThreadTerminated, 0, NULL))) { printf("CriticalSection failure: Failed to create main thread\n"); return -1; diff --git a/winpr/libwinpr/synch/test/TestSynchInit.c b/winpr/libwinpr/synch/test/TestSynchInit.c index 44aa6c3..59e17a9 100644 --- a/winpr/libwinpr/synch/test/TestSynchInit.c +++ b/winpr/libwinpr/synch/test/TestSynchInit.c @@ -7,16 +7,16 @@ #define TEST_NUM_THREADS 100 #define TEST_NUM_FAILURES 10 -INIT_ONCE initOnceTest = INIT_ONCE_STATIC_INIT; +static INIT_ONCE initOnceTest = INIT_ONCE_STATIC_INIT; -HANDLE hStartEvent = NULL; -LONG *pErrors = NULL; -LONG *pTestThreadFunctionCalls = NULL; -LONG *pTestOnceFunctionCalls = NULL; -LONG *pInitOnceExecuteOnceCalls = NULL; +static HANDLE hStartEvent = NULL; +static LONG *pErrors = NULL; +static LONG *pTestThreadFunctionCalls = NULL; +static LONG *pTestOnceFunctionCalls = NULL; +static LONG *pInitOnceExecuteOnceCalls = NULL; -BOOL CALLBACK TestOnceFunction(PINIT_ONCE once, PVOID param, PVOID *context) +static BOOL CALLBACK TestOnceFunction(PINIT_ONCE once, PVOID param, PVOID *context) { LONG calls = InterlockedIncrement(pTestOnceFunctionCalls) - 1; @@ -37,7 +37,7 @@ BOOL CALLBACK TestOnceFunction(PINIT_ONCE once, PVOID param, PVOID *context) return FALSE; } -DWORD WINAPI TestThreadFunction(LPVOID lpParam) +static DWORD WINAPI TestThreadFunction(LPVOID lpParam) { LONG calls; BOOL ok; diff --git a/winpr/libwinpr/synch/test/TestSynchMultipleThreads.c b/winpr/libwinpr/synch/test/TestSynchMultipleThreads.c index d752c32..27fe9d9 100644 --- a/winpr/libwinpr/synch/test/TestSynchMultipleThreads.c +++ b/winpr/libwinpr/synch/test/TestSynchMultipleThreads.c @@ -5,14 +5,14 @@ #include <winpr/synch.h> #include <winpr/thread.h> -static void *test_thread(void *arg) +static DWORD WINAPI test_thread(LPVOID arg) { long timeout = rand(); timeout %= 1000; timeout += 100; Sleep(timeout); ExitThread(0); - return NULL; + return 0; } static int start_threads(DWORD count, HANDLE *threads) @@ -21,8 +21,7 @@ static int start_threads(DWORD count, HANDLE *threads) for (i=0; i<count; i++) { - threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)test_thread, - NULL, 0, NULL); + threads[i] = CreateThread(NULL, 0, test_thread, NULL, 0, NULL); if (!threads[i]) { diff --git a/winpr/libwinpr/synch/test/TestSynchMutex.c b/winpr/libwinpr/synch/test/TestSynchMutex.c index 9ee3171..1bab037 100644 --- a/winpr/libwinpr/synch/test/TestSynchMutex.c +++ b/winpr/libwinpr/synch/test/TestSynchMutex.c @@ -4,7 +4,7 @@ #include <winpr/thread.h> -BOOL test_mutex_basic() +static BOOL test_mutex_basic(void) { HANDLE mutex; DWORD rc; @@ -42,7 +42,7 @@ BOOL test_mutex_basic() return TRUE; } -BOOL test_mutex_recursive() +static BOOL test_mutex_recursive(void) { HANDLE mutex; DWORD rc, i, cnt = 50; @@ -94,11 +94,11 @@ BOOL test_mutex_recursive() } -HANDLE thread1_mutex1 = NULL; -HANDLE thread1_mutex2 = NULL; -BOOL thread1_failed = TRUE; +static HANDLE thread1_mutex1 = NULL; +static HANDLE thread1_mutex2 = NULL; +static BOOL thread1_failed = TRUE; -DWORD WINAPI test_mutex_thread1(LPVOID lpParam) +static DWORD WINAPI test_mutex_thread1(LPVOID lpParam) { HANDLE hStartEvent = (HANDLE)lpParam; DWORD rc = 0; @@ -143,7 +143,7 @@ DWORD WINAPI test_mutex_thread1(LPVOID lpParam) return 0; } -BOOL test_mutex_threading() +static BOOL test_mutex_threading(void) { HANDLE hThread = NULL; HANDLE hStartEvent = NULL; diff --git a/winpr/libwinpr/synch/test/TestSynchThread.c b/winpr/libwinpr/synch/test/TestSynchThread.c index 7b019c5..50a0927 100644 --- a/winpr/libwinpr/synch/test/TestSynchThread.c +++ b/winpr/libwinpr/synch/test/TestSynchThread.c @@ -3,19 +3,18 @@ #include <winpr/synch.h> #include <winpr/thread.h> -static void *test_thread(void *arg) +static DWORD WINAPI test_thread(LPVOID arg) { Sleep(1000); ExitThread(0); - return NULL; + return 0; } int TestSynchThread(int argc, char *argv[]) { DWORD rc; HANDLE thread; - thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)test_thread, - NULL, 0, NULL); + thread = CreateThread(NULL, 0, test_thread, NULL, 0, NULL); if (!thread) { @@ -56,8 +55,7 @@ int TestSynchThread(int argc, char *argv[]) return -1; } - thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)test_thread, - NULL, 0, NULL); + thread = CreateThread(NULL, 0, test_thread, NULL, 0, NULL); if (!thread) { @@ -99,8 +97,7 @@ int TestSynchThread(int argc, char *argv[]) } /* Thread detach test */ - thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)test_thread, - NULL, 0, NULL); + thread = CreateThread(NULL, 0, test_thread, NULL, 0, NULL); if (!thread) { diff --git a/winpr/libwinpr/synch/test/TestSynchWaitableTimer.c b/winpr/libwinpr/synch/test/TestSynchWaitableTimer.c index c0efd48..25e8f02 100644 --- a/winpr/libwinpr/synch/test/TestSynchWaitableTimer.c +++ b/winpr/libwinpr/synch/test/TestSynchWaitableTimer.c @@ -9,7 +9,6 @@ int TestSynchWaitableTimer(int argc, char* argv[]) LONG period; LARGE_INTEGER due; int result = -1; - timer = CreateWaitableTimer(NULL, FALSE, NULL); if (!timer) @@ -35,17 +34,16 @@ int TestSynchWaitableTimer(int argc, char* argv[]) } printf("Timer Signaled\n"); - status = WaitForSingleObject(timer, 2000); if (status != WAIT_TIMEOUT) { - printf("WaitForSingleObject(timer, 2000) failure: Actual: 0x%08"PRIX32", Expected: 0x%08X\n", status, WAIT_TIMEOUT); + printf("WaitForSingleObject(timer, 2000) failure: Actual: 0x%08"PRIX32", Expected: 0x%08X\n", + status, WAIT_TIMEOUT); goto out; } due.QuadPart = 0; - period = 1200; /* 1.2 seconds */ if (!SetWaitableTimer(timer, &due, period, NULL, NULL, 0)) @@ -62,6 +60,12 @@ int TestSynchWaitableTimer(int argc, char* argv[]) printf("Timer Signaled\n"); + if (!SetWaitableTimer(timer, &due, period, NULL, NULL, 0)) + { + printf("SetWaitableTimer failure\n"); + goto out; + } + if (WaitForMultipleObjects(1, &timer, FALSE, INFINITE) != WAIT_OBJECT_0) { printf("WaitForMultipleObjects(timer, INFINITE) failure\n"); @@ -69,28 +73,9 @@ int TestSynchWaitableTimer(int argc, char* argv[]) } printf("Timer Signaled\n"); - result = 0; - out: CloseHandle(timer); - - -#ifdef __APPLE__ - if (result == 0) - { - printf("%s: Error, this test is currently expected not to succeed on this platform.\n", - __FUNCTION__); - result = -1; - } - else - { - printf("%s: This test is currently expected to fail on this platform.\n", - __FUNCTION__); - result = 0; - } -#endif - return result; } diff --git a/winpr/libwinpr/synch/test/TestSynchWaitableTimerAPC.c b/winpr/libwinpr/synch/test/TestSynchWaitableTimerAPC.c index 0bfaf9f..97f3e26 100644 --- a/winpr/libwinpr/synch/test/TestSynchWaitableTimerAPC.c +++ b/winpr/libwinpr/synch/test/TestSynchWaitableTimerAPC.c @@ -12,7 +12,7 @@ struct apc_data }; typedef struct apc_data APC_DATA; -VOID CALLBACK TimerAPCProc(LPVOID lpArg, DWORD dwTimerLowValue, DWORD dwTimerHighValue) +static VOID CALLBACK TimerAPCProc(LPVOID lpArg, DWORD dwTimerLowValue, DWORD dwTimerHighValue) { APC_DATA* apcData; UINT32 CurrentTime = GetTickCount(); @@ -108,20 +108,6 @@ cleanup: CloseHandle(g_Event); free(apcData); -#ifdef __APPLE__ - if (status == 0) - { - printf("%s: Error, this test is currently expected not to succeed on this platform.\n", - __FUNCTION__); - status = -1; - } - else - { - printf("%s: This test is currently expected to fail on this platform.\n", - __FUNCTION__); - status = 0; - } -#endif return status; } diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c index 5e527e7..dbd628f 100644 --- a/winpr/libwinpr/synch/timer.c +++ b/winpr/libwinpr/synch/timer.c @@ -60,7 +60,7 @@ static BOOL TimerIsHandled(HANDLE handle) static int TimerGetFd(HANDLE handle) { - WINPR_TIMER *timer = (WINPR_TIMER *)handle; + WINPR_TIMER* timer = (WINPR_TIMER*)handle; if (!TimerIsHandled(handle)) return -1; @@ -72,19 +72,29 @@ static DWORD TimerCleanupHandle(HANDLE handle) { int length; UINT64 expirations; - WINPR_TIMER *timer = (WINPR_TIMER *)handle; + WINPR_TIMER* timer = (WINPR_TIMER*)handle; if (!TimerIsHandled(handle)) return WAIT_FAILED; - length = read(timer->fd, (void *) &expirations, sizeof(UINT64)); + if (timer->bManualReset) + return WAIT_OBJECT_0; + + length = read(timer->fd, (void*) &expirations, sizeof(UINT64)); if (length != 8) { if (length == -1) { - if (errno == ETIMEDOUT) - return WAIT_TIMEOUT; + switch (errno) + { + case ETIMEDOUT: + case EAGAIN: + return WAIT_TIMEOUT; + + default: + break; + } WLog_ERR(TAG, "timer read() failure [%d] %s", errno, strerror(errno)); } @@ -99,33 +109,54 @@ static DWORD TimerCleanupHandle(HANDLE handle) return WAIT_OBJECT_0; } -BOOL TimerCloseHandle(HANDLE handle) { +BOOL TimerCloseHandle(HANDLE handle) +{ WINPR_TIMER* timer; timer = (WINPR_TIMER*) handle; - if (!TimerIsHandled(handle)) - return FALSE; + if (!TimerIsHandled(handle)) + return FALSE; -#ifdef __linux__ + if (!timer->lpArgToCompletionRoutine) + { +#ifdef HAVE_SYS_TIMERFD_H - if (timer->fd != -1) - close(timer->fd); + if (timer->fd != -1) + close(timer->fd); + +#endif + } + else + { +#ifdef WITH_POSIX_TIMER + timer_delete(timer->tid); +#endif + } + +#if defined(__APPLE__) + dispatch_release(timer->queue); + dispatch_release(timer->source); + + if (timer->pipe[0] != -1) + close(timer->pipe[0]); + + if (timer->pipe[1] != -1) + close(timer->pipe[1]); #endif free(timer); - - return TRUE; + return TRUE; } #ifdef WITH_POSIX_TIMER static BOOL g_WaitableTimerSignalHandlerInstalled = FALSE; -static void WaitableTimerSignalHandler(int signum, siginfo_t* siginfo, void* arg) +static void WaitableTimerHandler(void* arg) { - WINPR_TIMER* timer = siginfo->si_value.sival_ptr; + WINPR_TIMER* timer = (WINPR_TIMER*)arg; - if (!timer || (signum != SIGALRM)) + if (!timer) return; if (timer->pfnCompletionRoutine) @@ -139,11 +170,20 @@ static void WaitableTimerSignalHandler(int signum, siginfo_t* siginfo, void* arg if ((timer_settime(timer->tid, 0, &(timer->timeout), NULL)) != 0) { - WLog_ERR(TAG,"timer_settime"); + WLog_ERR(TAG, "timer_settime"); } } } } +static void WaitableTimerSignalHandler(int signum, siginfo_t* siginfo, void* arg) +{ + WINPR_TIMER* timer = siginfo->si_value.sival_ptr; + + if (!timer || (signum != SIGALRM)) + return; + + WaitableTimerHandler(timer); +} static int InstallWaitableTimerSignalHandler(void) { @@ -163,13 +203,37 @@ static int InstallWaitableTimerSignalHandler(void) #endif -int InitializeWaitableTimer(WINPR_TIMER* timer) +#if defined(__APPLE__) +static void WaitableTimerHandler(void* arg) +{ + UINT64 data = 1; + WINPR_TIMER* timer = (WINPR_TIMER*)arg; + + if (!timer) + return; + + if (timer->pfnCompletionRoutine) + timer->pfnCompletionRoutine(timer->lpArgToCompletionRoutine, 0, 0); + + if (write(timer->pipe[1], &data, sizeof(data)) != sizeof(data)) + WLog_ERR(TAG, "failed to write to pipe"); + + if (timer->lPeriod == 0) + { + if (timer->running) + dispatch_suspend(timer->source); + timer->running = FALSE; + } +} +#endif + +static int InitializeWaitableTimer(WINPR_TIMER* timer) { int result = 0; if (!timer->lpArgToCompletionRoutine) { -#ifdef HAVE_TIMERFD_H +#ifdef HAVE_SYS_TIMERFD_H int status; timer->fd = timerfd_create(CLOCK_MONOTONIC, 0); @@ -186,6 +250,8 @@ int InitializeWaitableTimer(WINPR_TIMER* timer) close(timer->fd); return -1; } + +#elif defined(__APPLE__) #else WLog_ERR(TAG, "%s: os specific implementation is missing", __FUNCTION__); result = -1; @@ -203,9 +269,11 @@ int InitializeWaitableTimer(WINPR_TIMER* timer) if ((timer_create(CLOCK_MONOTONIC, &sigev, &(timer->tid))) != 0) { - WLog_ERR(TAG,"timer_create"); + WLog_ERR(TAG, "timer_create"); return -1; } + +#elif defined(__APPLE__) #else WLog_ERR(TAG, "%s: os specific implementation is missing", __FUNCTION__); result = -1; @@ -217,23 +285,25 @@ int InitializeWaitableTimer(WINPR_TIMER* timer) } -static HANDLE_OPS ops = { - TimerIsHandled, - TimerCloseHandle, - TimerGetFd, - TimerCleanupHandle +static HANDLE_OPS ops = +{ + TimerIsHandled, + TimerCloseHandle, + TimerGetFd, + TimerCleanupHandle }; /** * Waitable Timer */ -HANDLE CreateWaitableTimerA(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCSTR lpTimerName) +HANDLE CreateWaitableTimerA(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, + LPCSTR lpTimerName) { HANDLE handle = NULL; WINPR_TIMER* timer; - timer = (WINPR_TIMER*) calloc(1, sizeof(WINPR_TIMER)); + if (timer) { WINPR_HANDLE_SET_TYPE_AND_MODE(timer, HANDLE_TYPE_TIMER, WINPR_FD_READ); @@ -245,40 +315,87 @@ HANDLE CreateWaitableTimerA(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManua timer->lpArgToCompletionRoutine = NULL; timer->bInit = FALSE; timer->ops = &ops; +#if defined(__APPLE__) + + if (pipe(timer->pipe) != 0) + goto fail; + + timer->queue = dispatch_queue_create(TAG, DISPATCH_QUEUE_SERIAL); + + if (!timer->queue) + goto fail; + + timer->source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, timer->queue); + + if (!timer->source) + goto fail; + + dispatch_set_context(timer->source, timer); + dispatch_source_set_event_handler_f(timer->source, WaitableTimerHandler); + timer->fd = timer->pipe[0]; + if (fcntl(timer->fd, F_SETFL, O_NONBLOCK) < 0) + goto fail; +#endif } return handle; -} - -HANDLE CreateWaitableTimerW(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCWSTR lpTimerName) -{ +fail: + TimerCloseHandle(handle); return NULL; } -HANDLE CreateWaitableTimerExA(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCSTR lpTimerName, DWORD dwFlags, DWORD dwDesiredAccess) +HANDLE CreateWaitableTimerW(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, + LPCWSTR lpTimerName) +{ + int rc; + HANDLE handle; + LPSTR name = NULL; + rc = ConvertFromUnicode(CP_UTF8, 0, lpTimerName, -1, &name, 0, NULL, NULL); + + if (rc < 0) + return NULL; + + handle = CreateWaitableTimerA(lpTimerAttributes, bManualReset, name); + free(name); + return handle; +} + +HANDLE CreateWaitableTimerExA(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCSTR lpTimerName, + DWORD dwFlags, DWORD dwDesiredAccess) { BOOL bManualReset; bManualReset = (dwFlags & CREATE_WAITABLE_TIMER_MANUAL_RESET) ? TRUE : FALSE; return CreateWaitableTimerA(lpTimerAttributes, bManualReset, lpTimerName); } -HANDLE CreateWaitableTimerExW(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCWSTR lpTimerName, DWORD dwFlags, DWORD dwDesiredAccess) +HANDLE CreateWaitableTimerExW(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCWSTR lpTimerName, + DWORD dwFlags, DWORD dwDesiredAccess) { - return NULL; + int rc; + HANDLE handle; + LPSTR name = NULL; + rc = ConvertFromUnicode(CP_UTF8, 0, lpTimerName, -1, &name, 0, NULL, NULL); + + if (rc < 0) + return NULL; + + handle = CreateWaitableTimerExA(lpTimerAttributes, name, dwFlags, dwDesiredAccess); + free(name); + return handle; } BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPeriod, - PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, BOOL fResume) + PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, BOOL fResume) { ULONG Type; WINPR_HANDLE* Object; WINPR_TIMER* timer; -#ifdef WITH_POSIX_TIMER +#if defined(WITH_POSIX_TIMER) || defined(__APPLE__) LONGLONG seconds = 0; LONGLONG nanoseconds = 0; -#ifdef HAVE_TIMERFD_H +#ifdef HAVE_SYS_TIMERFD_H int status = 0; -#endif /* HAVE_TIMERFD_H */ +#endif /* HAVE_SYS_TIMERFD_H */ #endif /* WITH_POSIX_TIMER */ if (!winpr_Handle_GetInfo(hTimer, &Type, &Object)) @@ -343,7 +460,7 @@ BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPerio if (!timer->pfnCompletionRoutine) { -#ifdef HAVE_TIMERFD_H +#ifdef HAVE_SYS_TIMERFD_H status = timerfd_settime(timer->fd, 0, &(timer->timeout), NULL); if (status) @@ -358,32 +475,59 @@ BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPerio { if ((timer_settime(timer->tid, 0, &(timer->timeout), NULL)) != 0) { - WLog_ERR(TAG,"timer_settime"); + WLog_ERR(TAG, "timer_settime"); return FALSE; } } +#elif defined(__APPLE__) + + if (lpDueTime->QuadPart < 0) + { + LONGLONG due = lpDueTime->QuadPart * (-1); + /* due time is in 100 nanosecond intervals */ + seconds = (due / 10000000); + nanoseconds = due * 100; + } + else if (lpDueTime->QuadPart == 0) + { + seconds = nanoseconds = 0; + } + else + { + WLog_ERR(TAG, "absolute time not implemented"); + return FALSE; + } + + { /* Clean out old data from FD */ + BYTE buffer[32]; + + while (read(timer->fd, buffer, sizeof(buffer)) > 0); + } + { + if (timer->running) + dispatch_suspend(timer->source); + + dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, nanoseconds); + uint64_t interval = DISPATCH_TIME_FOREVER; + if (lPeriod > 0) + interval = lPeriod * 1000000; + + dispatch_source_set_timer(timer->source, start, interval, 0); + dispatch_resume(timer->source); + timer->running = TRUE; + } + #endif return TRUE; } BOOL SetWaitableTimerEx(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPeriod, - PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, ULONG TolerableDelay) + PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, + ULONG TolerableDelay) { - ULONG Type; - WINPR_HANDLE* Object; - WINPR_TIMER* timer; - - if (!winpr_Handle_GetInfo(hTimer, &Type, &Object)) - return FALSE; - - if (Type == HANDLE_TYPE_TIMER) - { - timer = (WINPR_TIMER*) Object; - return TRUE; - } - - return TRUE; + return SetWaitableTimer(hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine, + FALSE); } HANDLE OpenWaitableTimerA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpTimerName) @@ -398,6 +542,22 @@ HANDLE OpenWaitableTimerW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lp BOOL CancelWaitableTimer(HANDLE hTimer) { + ULONG Type; + WINPR_HANDLE* Object; + WINPR_TIMER* timer; + + if (!winpr_Handle_GetInfo(hTimer, &Type, &Object)) + return FALSE; + + if (Type != HANDLE_TYPE_TIMER) + return FALSE; + + timer = (WINPR_TIMER*)Object; +#if defined(__APPLE__) + if (timer->running) + dispatch_suspend(timer->source); + timer->running = FALSE; +#endif return TRUE; } @@ -410,14 +570,14 @@ BOOL CancelWaitableTimer(HANDLE hTimer) * http://www.cs.wustl.edu/~schmidt/Timer_Queue.html */ -void timespec_add_ms(struct timespec* tspec, UINT32 ms) +static void timespec_add_ms(struct timespec* tspec, UINT32 ms) { UINT64 ns = tspec->tv_nsec + (ms * 1000000); tspec->tv_sec += (ns / 1000000000); tspec->tv_nsec = (ns % 1000000000); } -UINT64 timespec_to_ms(struct timespec* tspec) +static UINT64 timespec_to_ms(struct timespec* tspec) { UINT64 ms; ms = tspec->tv_sec * 1000; @@ -447,7 +607,7 @@ static void timespec_copy(struct timespec* dst, struct timespec* src) dst->tv_nsec = src->tv_nsec; } -void InsertTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer) +static void InsertTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer) { WINPR_TIMER_QUEUE_TIMER* node; @@ -483,7 +643,7 @@ void InsertTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TI } } -void RemoveTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer) +static void RemoveTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer) { BOOL found = FALSE; WINPR_TIMER_QUEUE_TIMER* node; @@ -522,7 +682,7 @@ void RemoveTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TI } } -int FireExpiredTimerQueueTimers(WINPR_TIMER_QUEUE* timerQueue) +static int FireExpiredTimerQueueTimers(WINPR_TIMER_QUEUE* timerQueue) { struct timespec CurrentTime; WINPR_TIMER_QUEUE_TIMER* node; @@ -590,6 +750,9 @@ static void* TimerQueueThread(void* arg) FireExpiredTimerQueueTimers(timerQueue); pthread_mutex_unlock(&(timerQueue->cond_mutex)); + if ((status != ETIMEDOUT) && (status != 0)) + break; + if (timerQueue->bCancelled) break; } @@ -597,7 +760,7 @@ static void* TimerQueueThread(void* arg) return NULL; } -int StartTimerQueueThread(WINPR_TIMER_QUEUE* timerQueue) +static int StartTimerQueueThread(WINPR_TIMER_QUEUE* timerQueue) { pthread_cond_init(&(timerQueue->cond), NULL); pthread_mutex_init(&(timerQueue->cond_mutex), NULL); @@ -646,7 +809,6 @@ BOOL DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) pthread_cond_signal(&(timerQueue->cond)); pthread_mutex_unlock(&(timerQueue->cond_mutex)); pthread_join(timerQueue->thread, &rvalue); - /** * Quote from MSDN regarding CompletionEvent: * If this parameter is INVALID_HANDLE_VALUE, the function waits for @@ -657,7 +819,6 @@ BOOL DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) * Note: The current WinPR implementation implicitly waits for any * callback functions to complete (see pthread_join above) */ - { /* Move all active timers to the inactive timer list */ node = timerQueue->activeHead; @@ -681,7 +842,6 @@ BOOL DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) timerQueue->inactiveHead = NULL; } - /* Delete timer queue */ pthread_cond_destroy(&(timerQueue->cond)); pthread_mutex_destroy(&(timerQueue->cond_mutex)); @@ -701,7 +861,7 @@ BOOL DeleteTimerQueue(HANDLE TimerQueue) } BOOL CreateTimerQueueTimer(PHANDLE phNewTimer, HANDLE TimerQueue, - WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, DWORD Period, ULONG Flags) + WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, DWORD Period, ULONG Flags) { struct timespec CurrentTime; WINPR_TIMER_QUEUE* timerQueue; @@ -775,7 +935,6 @@ BOOL DeleteTimerQueueTimer(HANDLE TimerQueue, HANDLE Timer, HANDLE CompletionEve timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; timer = (WINPR_TIMER_QUEUE_TIMER*) Timer; pthread_mutex_lock(&(timerQueue->cond_mutex)); - /** * Quote from MSDN regarding CompletionEvent: * If this parameter is INVALID_HANDLE_VALUE, the function waits for @@ -786,9 +945,7 @@ BOOL DeleteTimerQueueTimer(HANDLE TimerQueue, HANDLE Timer, HANDLE CompletionEve * Note: The current WinPR implementation implicitly waits for any * callback functions to complete (see cond_mutex usage) */ - RemoveTimerQueueTimer(&(timerQueue->activeHead), timer); - pthread_cond_signal(&(timerQueue->cond)); pthread_mutex_unlock(&(timerQueue->cond_mutex)); free(timer); diff --git a/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c b/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c index adff1d7..acdfa34 100644 --- a/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c +++ b/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c @@ -71,6 +71,7 @@ #include <stdlib.h> #include <sys/system_properties.h> #include <unistd.h> +#include <winpr/wtypes.h> static pthread_once_t g_once; static int g_inited; diff --git a/winpr/libwinpr/thread/argv.c b/winpr/libwinpr/thread/argv.c index 6739150..52905b4 100644 --- a/winpr/libwinpr/thread/argv.c +++ b/winpr/libwinpr/thread/argv.c @@ -96,7 +96,7 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs) char* pEnd; char* buffer; char* pOutput; - int numArgs; + int numArgs = 0; LPSTR* pArgs; int maxNumArgs; int maxBufferSize; @@ -111,7 +111,6 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs) return NULL; pArgs = NULL; - numArgs = 0; lpEscapedCmdLine = NULL; cmdLineLength = (int) strlen(lpCmdLine); lpEscapedChars = (BOOL*) calloc(cmdLineLength + 1, sizeof(BOOL)); @@ -204,7 +203,6 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs) pArgs = (LPSTR*) buffer; pOutput = (char*) &buffer[maxNumArgs * (sizeof(char*))]; - numArgs = 0; p = (char*) lpCmdLine; while (p < lpCmdLine + cmdLineLength) diff --git a/winpr/libwinpr/thread/test/TestThreadExitThread.c b/winpr/libwinpr/thread/test/TestThreadExitThread.c index 2376bd1..c9760cc 100644 --- a/winpr/libwinpr/thread/test/TestThreadExitThread.c +++ b/winpr/libwinpr/thread/test/TestThreadExitThread.c @@ -4,11 +4,11 @@ #include <winpr/synch.h> #include <winpr/thread.h> -static void* thread_func(void* arg) +static DWORD WINAPI thread_func(LPVOID arg) { /* exists of the thread the quickest as possible */ ExitThread(0); - return NULL; + return 0; } int TestThreadExitThread(int argc, char* argv[]) @@ -23,7 +23,7 @@ int TestThreadExitThread(int argc, char* argv[]) { thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE)thread_func, + thread_func, NULL, 0, NULL); diff --git a/winpr/libwinpr/thread/thread.c b/winpr/libwinpr/thread/thread.c index 7e3d724..0c678ae 100644 --- a/winpr/libwinpr/thread/thread.c +++ b/winpr/libwinpr/thread/thread.c @@ -77,7 +77,7 @@ #include <unistd.h> #endif -#ifdef HAVE_EVENTFD_H +#ifdef HAVE_SYS_EVENTFD_H #include <sys/eventfd.h> #endif @@ -215,7 +215,7 @@ static BOOL set_event(WINPR_THREAD* thread) { int length; BOOL status = FALSE; -#ifdef HAVE_EVENTFD_H +#ifdef HAVE_SYS_EVENTFD_H eventfd_t val = 1; do @@ -247,7 +247,7 @@ static BOOL reset_event(WINPR_THREAD* thread) { int length; BOOL status = FALSE; -#ifdef HAVE_EVENTFD_H +#ifdef HAVE_SYS_EVENTFD_H eventfd_t value; do @@ -282,7 +282,6 @@ static BOOL thread_compare(void* a, void* b) * in thread function. */ static void* thread_launcher(void* arg) { - DWORD res = 1; void* rc = NULL; WINPR_THREAD* thread = (WINPR_THREAD*) arg; typedef void* (*fkt_t)(void*); @@ -296,7 +295,7 @@ static void* thread_launcher(void* arg) if (!(fkt = (fkt_t)thread->lpStartAddress)) { - WLog_ERR(TAG, "Thread function argument is %p", (void *)fkt); + WLog_ERR(TAG, "Thread function argument is %p", (void*)fkt); goto exit; } @@ -326,7 +325,6 @@ exit: thread->dwExitCode = (DWORD)(size_t)rc; set_event(thread); - res = thread->dwExitCode; if (thread->detached || !thread->started) cleanup_handle(thread); @@ -401,7 +399,7 @@ HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, #endif thread->pipe_fd[0] = -1; thread->pipe_fd[1] = -1; -#ifdef HAVE_EVENTFD_H +#ifdef HAVE_SYS_EVENTFD_H thread->pipe_fd[0] = eventfd(0, EFD_NONBLOCK); if (thread->pipe_fd[0] < 0) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index 62f33f1..5163154 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -21,6 +21,7 @@ #include "config.h" #endif +#include <winpr/wtypes.h> #include <winpr/timezone.h> #include <winpr/crt.h> #include "../log.h" @@ -1999,13 +2000,13 @@ static UINT64 winpr_windows_gmtime() static char* winpr_read_unix_timezone_identifier_from_file(FILE* fp) { - long length; + INT64 length; char* tzid = NULL; - if (fseek(fp, 0, SEEK_END) != 0) + if (_fseeki64(fp, 0, SEEK_END) != 0) return NULL; - length = ftell(fp); - if (fseek(fp, 0, SEEK_SET) != 0) + length = _ftelli64(fp); + if (_fseeki64(fp, 0, SEEK_SET) != 0) return NULL; if (length < 2) diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index e305d06..abf4dc1 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -141,7 +141,7 @@ if(UNIX) winpr_library_add(m) endif() -if(FREEBSD) +if((FREEBSD) AND (NOT KFREEBSD)) winpr_library_add(execinfo) endif() diff --git a/winpr/libwinpr/utils/cmdline.c b/winpr/libwinpr/utils/cmdline.c index 19e4eab..473286a 100644 --- a/winpr/libwinpr/utils/cmdline.c +++ b/winpr/libwinpr/utils/cmdline.c @@ -45,39 +45,24 @@ * */ -int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* options, DWORD flags, - void* context, COMMAND_LINE_PRE_FILTER_FN_A preFilter, COMMAND_LINE_POST_FILTER_FN_A postFilter) +int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* options, + DWORD flags, + void* context, COMMAND_LINE_PRE_FILTER_FN_A preFilter, COMMAND_LINE_POST_FILTER_FN_A postFilter) { int i, j; int status; int count; - int length; - int index; - BOOL match; - BOOL found; - BOOL argument; - BOOL escaped; + size_t length; BOOL notescaped; - char* sigil; - int sigil_length; - int sigil_index; - char* keyword; - int keyword_length; - int keyword_index; + const char* sigil; + size_t sigil_length; + const char* keyword; + SSIZE_T keyword_length; + SSIZE_T keyword_index; char* separator; - int separator_length; - int separator_index; - char* value; - int value_length; - int value_index; + const char* value; int toggle; - status = 0; - - match = FALSE; - found = FALSE; - argument = FALSE; - escaped = TRUE; notescaped = FALSE; if (!argv) @@ -85,15 +70,18 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* if (argc == 1) { - status = COMMAND_LINE_STATUS_PRINT_HELP; + if (flags & COMMAND_LINE_IGN_UNKNOWN_KEYWORD) + status = 0; + else + status = COMMAND_LINE_STATUS_PRINT_HELP; + return status; } for (i = 1; i < argc; i++) { - index = i; - - escaped = TRUE; + BOOL found = FALSE; + BOOL escaped = TRUE; if (preFilter) { @@ -112,10 +100,8 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* } } - sigil_index = 0; - sigil_length = 0; - sigil = (char*) &argv[i][sigil_index]; - length = (int) strlen(argv[i]); + sigil = argv[i]; + length = strlen(argv[i]); if ((sigil[0] == '/') && (flags & COMMAND_LINE_SIGIL_SLASH)) { @@ -146,7 +132,7 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* else if (flags & COMMAND_LINE_SIGIL_NOT_ESCAPED) { if (notescaped) - return COMMAND_LINE_ERROR; + return COMMAND_LINE_ERROR; sigil_length = 0; escaped = FALSE; @@ -158,17 +144,18 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* } if ((sigil_length > 0) || (flags & COMMAND_LINE_SIGIL_NONE) || - (flags & COMMAND_LINE_SIGIL_NOT_ESCAPED)) + (flags & COMMAND_LINE_SIGIL_NOT_ESCAPED)) { - if (length < (sigil_length + 1)) { + if (length < (sigil_length + 1)) + { if ((flags & COMMAND_LINE_IGN_UNKNOWN_KEYWORD)) continue; + return COMMAND_LINE_ERROR_NO_KEYWORD; } - keyword_index = sigil_index + sigil_length; - keyword = (char*) &argv[i][keyword_index]; - + keyword_index = sigil_length; + keyword = &argv[i][keyword_index]; toggle = -1; if (flags & COMMAND_LINE_SIGIL_ENABLE_DISABLE) @@ -177,13 +164,13 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* { toggle = TRUE; keyword_index += 7; - keyword = (char*) &argv[i][keyword_index]; + keyword = &argv[i][keyword_index]; } else if (strncmp(keyword, "disable-", 8) == 0) { toggle = FALSE; keyword_index += 8; - keyword = (char*) &argv[i][keyword_index]; + keyword = &argv[i][keyword_index]; } } @@ -197,33 +184,23 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* if (separator) { - separator_length = 1; - separator_index = (int) (separator - argv[i]); - - keyword_length = (int) (separator - keyword); - - value_index = separator_index + separator_length; - value = (char*) &argv[i][value_index]; - value_length = (length - value_index); + SSIZE_T separator_index = (separator - argv[i]); + SSIZE_T value_index = separator_index + 1; + keyword_length = (separator - keyword); + value = &argv[i][value_index]; } else { - separator_length = 0; - separator_index = -1; keyword_length = (length - keyword_index); - - value_index = -1; value = NULL; - value_length = 0; } if (!escaped) continue; - found = FALSE; for (j = 0; options[j].Name != NULL; j++) { - match = FALSE; + BOOL match = FALSE; if (strncmp(options[j].Name, keyword, keyword_length) == 0) { @@ -244,10 +221,11 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* continue; found = match; - options[j].Index = index; + options[j].Index = i; if ((flags & COMMAND_LINE_SEPARATOR_SPACE) && ((i + 1) < argc)) { + BOOL argument; int value_present = 1; if (flags & COMMAND_LINE_SIGIL_DASH) @@ -269,25 +247,19 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* } if ((options[j].Flags & COMMAND_LINE_VALUE_REQUIRED) || - (options[j].Flags & COMMAND_LINE_VALUE_OPTIONAL)) + (options[j].Flags & COMMAND_LINE_VALUE_OPTIONAL)) argument = TRUE; else argument = FALSE; - + if (value_present && argument) { i++; - value_index = 0; - length = (int) strlen(argv[i]); - - value = (char*) &argv[i][value_index]; - value_length = (length - value_index); + value = argv[i]; } else if (!value_present && (options[j].Flags & COMMAND_LINE_VALUE_OPTIONAL)) { - value_index = 0; value = NULL; - value_length = 0; } else if (!value_present && argument) return COMMAND_LINE_ERROR; @@ -303,9 +275,7 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* if (value && (options[j].Flags & COMMAND_LINE_VALUE_FLAG)) { i--; - value_index = -1; value = NULL; - value_length = 0; } } @@ -355,18 +325,26 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* } if (postFilter) - postFilter(context, &options[j]); + { + count = postFilter(context, &options[j]); + + if (count < 0) + { + status = COMMAND_LINE_ERROR; + return status; + } + } if (options[j].Flags & COMMAND_LINE_PRINT) - return COMMAND_LINE_STATUS_PRINT; + return COMMAND_LINE_STATUS_PRINT; else if (options[j].Flags & COMMAND_LINE_PRINT_HELP) - return COMMAND_LINE_STATUS_PRINT_HELP; + return COMMAND_LINE_STATUS_PRINT_HELP; else if (options[j].Flags & COMMAND_LINE_PRINT_VERSION) - return COMMAND_LINE_STATUS_PRINT_VERSION; + return COMMAND_LINE_STATUS_PRINT_VERSION; else if (options[j].Flags & COMMAND_LINE_PRINT_BUILDCONFIG) - return COMMAND_LINE_STATUS_PRINT_BUILDCONFIG; + return COMMAND_LINE_STATUS_PRINT_BUILDCONFIG; } - + if (!found && (flags & COMMAND_LINE_IGN_UNKNOWN_KEYWORD) == 0) return COMMAND_LINE_ERROR_NO_KEYWORD; } @@ -375,15 +353,16 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* return status; } -int CommandLineParseArgumentsW(int argc, LPCWSTR* argv, COMMAND_LINE_ARGUMENT_W* options, DWORD flags, - void* context, COMMAND_LINE_PRE_FILTER_FN_W preFilter, COMMAND_LINE_POST_FILTER_FN_W postFilter) +int CommandLineParseArgumentsW(int argc, LPCWSTR* argv, COMMAND_LINE_ARGUMENT_W* options, + DWORD flags, + void* context, COMMAND_LINE_PRE_FILTER_FN_W preFilter, COMMAND_LINE_POST_FILTER_FN_W postFilter) { return 0; } int CommandLineClearArgumentsA(COMMAND_LINE_ARGUMENT_A* options) { - int i; + size_t i; for (i = 0; options[i].Name != NULL; i++) { @@ -448,7 +427,6 @@ COMMAND_LINE_ARGUMENT_W* CommandLineFindArgumentW(COMMAND_LINE_ARGUMENT_W* optio COMMAND_LINE_ARGUMENT_A* CommandLineFindNextArgumentA(COMMAND_LINE_ARGUMENT_A* argument) { COMMAND_LINE_ARGUMENT_A* nextArgument; - nextArgument = &argument[1]; if (nextArgument->Name == NULL) diff --git a/winpr/libwinpr/utils/collections/HashTable.c b/winpr/libwinpr/utils/collections/HashTable.c index 4f98d8c..c09f646 100644 --- a/winpr/libwinpr/utils/collections/HashTable.c +++ b/winpr/libwinpr/utils/collections/HashTable.c @@ -40,7 +40,7 @@ BOOL HashTable_PointerCompare(void* pointer1, void* pointer2) UINT32 HashTable_PointerHash(void* pointer) { - return ((UINT32) (UINT_PTR) pointer) >> 4; + return ((UINT32)(UINT_PTR) pointer) >> 4; } BOOL HashTable_StringCompare(void* string1, void* string2) @@ -149,7 +149,7 @@ void HashTable_Rehash(wHashTable* table, int numOfBuckets) } void HashTable_SetIdealRatio(wHashTable* table, float idealRatio, - float lowerRehashThreshold, float upperRehashThreshold) + float lowerRehashThreshold, float upperRehashThreshold) { table->idealRatio = idealRatio; table->lowerRehashThreshold = lowerRehashThreshold; @@ -160,9 +160,7 @@ wKeyValuePair* HashTable_Get(wHashTable* table, void* key) { UINT32 hashValue; wKeyValuePair* pair; - hashValue = table->hash(key) % table->numOfBuckets; - pair = table->bucketArray[hashValue]; while (pair && !table->keyCompare(key, pair->key)) @@ -238,6 +236,7 @@ int HashTable_Add(wHashTable* table, void* key, void* value) { if (table->keyFree) table->keyFree(pair->key); + pair->key = key; } @@ -245,6 +244,7 @@ int HashTable_Add(wHashTable* table, void* key, void* value) { if (table->valueFree) table->valueFree(pair->value); + pair->value = value; } } @@ -295,7 +295,6 @@ BOOL HashTable_Remove(wHashTable* table, void* key) EnterCriticalSection(&table->lock); hashValue = table->hash(key) % table->numOfBuckets; - pair = table->bucketArray[hashValue]; while (pair && !table->keyCompare(key, pair->key)) @@ -322,7 +321,6 @@ BOOL HashTable_Remove(wHashTable* table, void* key) table->bucketArray[hashValue] = pair->next; free(pair); - table->numOfElements--; if (table->lowerRehashThreshold > 0.0) @@ -388,7 +386,12 @@ BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value) if (!pair) status = FALSE; else + { + if (table->valueClone && table->valueFree) + table->valueFree(pair->value); + pair->value = value; + } if (table->synchronized) LeaveCriticalSection(&table->lock); @@ -424,7 +427,6 @@ void HashTable_Clear(wHashTable* table) table->valueFree(pair->value); free(pair); - pair = nextPair; } @@ -482,9 +484,7 @@ int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys) while (pair) { nextPair = pair->next; - pKeys[iKey++] = (ULONG_PTR) pair->key; - pair = nextPair; } } @@ -493,7 +493,6 @@ int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys) LeaveCriticalSection(&table->lock); *ppKeys = pKeys; - return count; } @@ -580,18 +579,14 @@ BOOL HashTable_ContainsValue(wHashTable* table, void* value) wHashTable* HashTable_New(BOOL synchronized) { wHashTable* table; - table = (wHashTable*) calloc(1, sizeof(wHashTable)); if (table) { table->synchronized = synchronized; - InitializeCriticalSectionAndSpinCount(&(table->lock), 4000); - table->numOfBuckets = 64; table->numOfElements = 0; - table->bucketArray = (wKeyValuePair**) calloc(table->numOfBuckets, sizeof(wKeyValuePair*)); if (!table->bucketArray) @@ -603,7 +598,6 @@ wHashTable* HashTable_New(BOOL synchronized) table->idealRatio = 3.0; table->lowerRehashThreshold = 0.0; table->upperRehashThreshold = 15.0; - table->hash = HashTable_PointerHash; table->keyCompare = HashTable_PointerCompare; table->valueCompare = HashTable_PointerCompare; @@ -639,13 +633,11 @@ void HashTable_Free(wHashTable* table) table->valueFree(pair->value); free(pair); - pair = nextPair; } } DeleteCriticalSection(&(table->lock)); - free(table->bucketArray); free(table); } diff --git a/winpr/libwinpr/utils/collections/MessageQueue.c b/winpr/libwinpr/utils/collections/MessageQueue.c index d49d216..c41c473 100644 --- a/winpr/libwinpr/utils/collections/MessageQueue.c +++ b/winpr/libwinpr/utils/collections/MessageQueue.c @@ -227,6 +227,8 @@ void MessageQueue_Free(wMessageQueue* queue) if (!queue) return; + MessageQueue_Clear(queue); + CloseHandle(queue->event); DeleteCriticalSection(&queue->lock); diff --git a/winpr/libwinpr/utils/collections/PubSub.c b/winpr/libwinpr/utils/collections/PubSub.c index de9d88b..9326284 100644 --- a/winpr/libwinpr/utils/collections/PubSub.c +++ b/winpr/libwinpr/utils/collections/PubSub.c @@ -84,7 +84,7 @@ void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, int count) wEventType *new_event; new_size = pubSub->size * 2; - new_event = (wEventType*) realloc(pubSub->events, new_size); + new_event = (wEventType*) realloc(pubSub->events, new_size * sizeof(wEventType)); if (!new_event) return; pubSub->size = new_size; @@ -151,7 +151,7 @@ int PubSub_Unsubscribe(wPubSub* pubSub, const char* EventName, pEventHandler Eve event->EventHandlers[index] = NULL; event->EventHandlerCount--; MoveMemory(&event->EventHandlers[index], &event->EventHandlers[index + 1], - (MAX_EVENT_HANDLERS - index - 1) * sizeof(pEventHandler)); + (MAX_EVENT_HANDLERS - index - 1) * sizeof(pEventHandler)); status = 1; } } diff --git a/winpr/libwinpr/utils/debug.c b/winpr/libwinpr/utils/debug.c index 4c2d0db..8196d04 100644 --- a/winpr/libwinpr/utils/debug.c +++ b/winpr/libwinpr/utils/debug.c @@ -424,10 +424,10 @@ char** winpr_backtrace_symbols(void* buffer, size_t* used) if (SymGetLineFromAddr64(process, address, &displacement, line)) { - sprintf_s(vlines[i], line_len, "%08lX: %s in %s:%lu", symbol->Address, symbol->Name, line->FileName, line->LineNumber); + sprintf_s(vlines[i], line_len, "%016"PRIx64": %s in %s:%"PRIu32, symbol->Address, symbol->Name, line->FileName, line->LineNumber); } else - sprintf_s(vlines[i], line_len, "%08lX: %s", symbol->Address, symbol->Name); + sprintf_s(vlines[i], line_len, "%016"PRIx64": %s", symbol->Address, symbol->Name); } if (used) diff --git a/winpr/libwinpr/utils/image.c b/winpr/libwinpr/utils/image.c index 8370515..d98243c 100644 --- a/winpr/libwinpr/utils/image.c +++ b/winpr/libwinpr/utils/image.c @@ -23,15 +23,83 @@ #include "config.h" #endif +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <winpr/image.h> #include "lodepng/lodepng.h" +#include <winpr/stream.h> #include "../log.h" #define TAG WINPR_TAG("utils.image") +static BOOL writeBitmapFileHeader(wStream* s, const WINPR_BITMAP_FILE_HEADER* bf) +{ + if (!Stream_EnsureRemainingCapacity(s, sizeof(WINPR_BITMAP_FILE_HEADER))) + return FALSE; + + Stream_Write_UINT8(s, bf->bfType[0]); + Stream_Write_UINT8(s, bf->bfType[1]); + Stream_Write_UINT32(s, bf->bfSize); + Stream_Write_UINT16(s, bf->bfReserved1); + Stream_Write_UINT16(s, bf->bfReserved2); + Stream_Write_UINT32(s, bf->bfOffBits); + return TRUE; +} + +static BOOL readBitmapFileHeader(wStream* s, WINPR_BITMAP_FILE_HEADER* bf) +{ + if (!s || !bf || (Stream_GetRemainingLength(s) < sizeof(WINPR_BITMAP_FILE_HEADER))) + return FALSE; + + Stream_Read_UINT8(s, bf->bfType[0]); + Stream_Read_UINT8(s, bf->bfType[1]); + Stream_Read_UINT32(s, bf->bfSize); + Stream_Read_UINT16(s, bf->bfReserved1); + Stream_Read_UINT16(s, bf->bfReserved2); + Stream_Read_UINT32(s, bf->bfOffBits); + return TRUE; +} + +static BOOL writeBitmapInfoHeader(wStream* s, const WINPR_BITMAP_INFO_HEADER* bi) +{ + if (!Stream_EnsureRemainingCapacity(s, sizeof(WINPR_BITMAP_INFO_HEADER))) + return FALSE; + + Stream_Write_UINT32(s, bi->biSize); + Stream_Write_UINT32(s, bi->biWidth); + Stream_Write_UINT32(s, bi->biHeight); + Stream_Write_UINT16(s, bi->biPlanes); + Stream_Write_UINT16(s, bi->biBitCount); + Stream_Write_UINT32(s, bi->biCompression); + Stream_Write_UINT32(s, bi->biSizeImage); + Stream_Write_UINT32(s, bi->biXPelsPerMeter); + Stream_Write_UINT32(s, bi->biYPelsPerMeter); + Stream_Write_UINT32(s, bi->biClrUsed); + Stream_Write_UINT32(s, bi->biClrImportant); + return TRUE; +} + +static BOOL readBitmapInfoHeader(wStream* s, WINPR_BITMAP_INFO_HEADER* bi) +{ + if (!s || !bi || (Stream_GetRemainingLength(s) < sizeof(WINPR_BITMAP_INFO_HEADER))) + return FALSE; + + Stream_Read_UINT32(s, bi->biSize); + Stream_Read_INT32(s, bi->biWidth); + Stream_Read_INT32(s, bi->biHeight); + Stream_Read_UINT16(s, bi->biPlanes); + Stream_Read_UINT16(s, bi->biBitCount); + Stream_Read_UINT32(s, bi->biCompression); + Stream_Read_UINT32(s, bi->biSizeImage); + Stream_Read_INT32(s, bi->biXPelsPerMeter); + Stream_Read_INT32(s, bi->biYPelsPerMeter); + Stream_Read_UINT32(s, bi->biClrUsed); + Stream_Read_UINT32(s, bi->biClrImportant); + return TRUE; +} + /** * Refer to "Compressed Image File Formats: JPEG, PNG, GIF, XBM, BMP" book */ @@ -41,8 +109,8 @@ int winpr_bitmap_write(const char* filename, BYTE* data, int width, int height, FILE* fp; WINPR_BITMAP_FILE_HEADER bf; WINPR_BITMAP_INFO_HEADER bi; - int ret = 1; - + wStream* s; + int ret = -1; fp = fopen(filename, "w+b"); if (!fp) @@ -58,7 +126,6 @@ int winpr_bitmap_write(const char* filename, BYTE* data, int width, int height, bf.bfOffBits = sizeof(WINPR_BITMAP_FILE_HEADER) + sizeof(WINPR_BITMAP_INFO_HEADER); bi.biSizeImage = width * height * (bpp / 8); bf.bfSize = bf.bfOffBits + bi.biSizeImage; - bi.biWidth = width; bi.biHeight = -1 * height; bi.biPlanes = 1; @@ -69,14 +136,27 @@ int winpr_bitmap_write(const char* filename, BYTE* data, int width, int height, bi.biClrUsed = 0; bi.biClrImportant = 0; bi.biSize = sizeof(WINPR_BITMAP_INFO_HEADER); + s = Stream_New(NULL, sizeof(WINPR_BITMAP_FILE_HEADER) + sizeof(WINPR_BITMAP_INFO_HEADER)); - if (fwrite((void*) &bf, sizeof(WINPR_BITMAP_FILE_HEADER), 1, fp) != 1 || - fwrite((void*) &bi, sizeof(WINPR_BITMAP_INFO_HEADER), 1, fp) != 1 || - fwrite((void*) data, bi.biSizeImage, 1, fp) != 1) - ret = -1; + if (!s) + goto fail; + if (!writeBitmapFileHeader(s, &bf)) + goto fail; + + if (!writeBitmapInfoHeader(s, &bi)) + goto fail; + + Stream_SealLength(s); + + if (fwrite(Stream_Buffer(s), Stream_Length(s), 1, fp) != 1 || + fwrite((void*) data, bi.biSizeImage, 1, fp) != 1) + goto fail; + + ret = 1; +fail: fclose(fp); - + Stream_Free(s, TRUE); return ret; } @@ -86,32 +166,29 @@ int winpr_image_write(wImage* image, const char* filename) if (image->type == WINPR_IMAGE_BITMAP) { - status = winpr_bitmap_write(filename, image->data, image->width, image->height, image->bitsPerPixel); + status = winpr_bitmap_write(filename, image->data, image->width, image->height, + image->bitsPerPixel); } else { int lodepng_status; - lodepng_status = lodepng_encode32_file(filename, image->data, image->width, image->height); - status = (lodepng_status) ? -1 : 1; } return status; } -int winpr_image_png_read_fp(wImage* image, FILE* fp) +static int winpr_image_png_read_fp(wImage* image, FILE* fp) { - int size; + INT64 size; BYTE* data; UINT32 width; UINT32 height; int lodepng_status; - - fseek(fp, 0, SEEK_END); - size = ftell(fp); - fseek(fp, 0, SEEK_SET); - + _fseeki64(fp, 0, SEEK_END); + size = _ftelli64(fp); + _fseeki64(fp, 0, SEEK_SET); data = (BYTE*) malloc(size); if (!data) @@ -124,7 +201,6 @@ int winpr_image_png_read_fp(wImage* image, FILE* fp) } lodepng_status = lodepng_decode32(&(image->data), &width, &height, data, size); - free(data); if (lodepng_status) @@ -132,20 +208,17 @@ int winpr_image_png_read_fp(wImage* image, FILE* fp) image->width = width; image->height = height; - image->bitsPerPixel = 32; image->bytesPerPixel = 4; image->scanline = image->bytesPerPixel * image->width; - return 1; } -int winpr_image_png_read_buffer(wImage* image, BYTE* buffer, int size) +static int winpr_image_png_read_buffer(wImage* image, BYTE* buffer, size_t size) { UINT32 width; UINT32 height; int lodepng_status; - lodepng_status = lodepng_decode32(&(image->data), &width, &height, buffer, size); if (lodepng_status) @@ -153,37 +226,45 @@ int winpr_image_png_read_buffer(wImage* image, BYTE* buffer, int size) image->width = width; image->height = height; - image->bitsPerPixel = 32; image->bytesPerPixel = 4; image->scanline = image->bytesPerPixel * image->width; - return 1; } -int winpr_image_bitmap_read_fp(wImage* image, FILE* fp) +static int winpr_image_bitmap_read_fp(wImage* image, FILE* fp) { + int rc = -1; int index; BOOL vFlip; BYTE* pDstData; + wStream* s; WINPR_BITMAP_FILE_HEADER bf; WINPR_BITMAP_INFO_HEADER bi; - if (fread((void*) &bf, sizeof(WINPR_BITMAP_FILE_HEADER), 1, fp) != 1) + if (!image || !fp) return -1; - if ((bf.bfType[0] != 'B') || (bf.bfType[1] != 'M')) + image->data = NULL; + + s = Stream_New(NULL, sizeof(WINPR_BITMAP_FILE_HEADER) + sizeof(WINPR_BITMAP_INFO_HEADER)); + + if (!s) return -1; + if (fread(Stream_Buffer(s), Stream_Capacity(s), 1, fp) != 1) + goto fail; + + if (!readBitmapFileHeader(s, &bf) || !readBitmapInfoHeader(s, &bi)) + goto fail; + + if ((bf.bfType[0] != 'B') || (bf.bfType[1] != 'M')) + goto fail; + image->type = WINPR_IMAGE_BITMAP; - if (fread((void*) &bi, sizeof(WINPR_BITMAP_INFO_HEADER), 1, fp) != 1) - return -1; - - if (ftell(fp) != bf.bfOffBits) - { - fseek(fp, bf.bfOffBits, SEEK_SET); - } + if (_ftelli64(fp) != bf.bfOffBits) + _fseeki64(fp, bf.bfOffBits, SEEK_SET); image->width = bi.biWidth; @@ -201,20 +282,15 @@ int winpr_image_bitmap_read_fp(wImage* image, FILE* fp) image->bitsPerPixel = bi.biBitCount; image->bytesPerPixel = (image->bitsPerPixel / 8); image->scanline = (bi.biSizeImage / image->height); - image->data = (BYTE*) malloc(bi.biSizeImage); if (!image->data) - return -1; + goto fail; if (!vFlip) { if (fread((void*) image->data, bi.biSizeImage, 1, fp) != 1) - { - free(image->data); - image->data = NULL; - return -1; - } + goto fail; } else { @@ -223,45 +299,50 @@ int winpr_image_bitmap_read_fp(wImage* image, FILE* fp) for (index = 0; index < image->height; index++) { if (fread((void*) pDstData, image->scanline, 1, fp) != 1) - { - free(image->data); - image->data = NULL; - return -1; - } + goto fail; + pDstData -= image->scanline; } } + rc = 1; +fail: + + if (rc < 0) + { + free(image->data); + image->data = NULL; + } + + Stream_Free(s, TRUE); return 1; } -int winpr_image_bitmap_read_buffer(wImage* image, BYTE* buffer, int size) +static int winpr_image_bitmap_read_buffer(wImage* image, BYTE* buffer, size_t size) { + int rc = -1; int index; BOOL vFlip; - BYTE* pSrcData; BYTE* pDstData; WINPR_BITMAP_FILE_HEADER bf; WINPR_BITMAP_INFO_HEADER bi; + wStream* s = Stream_New(buffer, size); - pSrcData = buffer; + if (!s) + return -1; - CopyMemory(&bf, pSrcData, sizeof(WINPR_BITMAP_FILE_HEADER)); - pSrcData += sizeof(WINPR_BITMAP_FILE_HEADER); + if (!readBitmapFileHeader(s, &bf) || !readBitmapInfoHeader(s, &bi)) + goto fail; if ((bf.bfType[0] != 'B') || (bf.bfType[1] != 'M')) - return -1; + goto fail; image->type = WINPR_IMAGE_BITMAP; - CopyMemory(&bi, pSrcData, sizeof(WINPR_BITMAP_INFO_HEADER)); - pSrcData += sizeof(WINPR_BITMAP_INFO_HEADER); - - if ((pSrcData - buffer) != bf.bfOffBits) - { - pSrcData = &buffer[bf.bfOffBits]; - } + if (Stream_Capacity(s) < bf.bfOffBits + bi.biSizeImage) + goto fail; + Stream_SetPosition(s, bf.bfOffBits); image->width = bi.biWidth; if (bi.biHeight < 0) @@ -278,27 +359,35 @@ int winpr_image_bitmap_read_buffer(wImage* image, BYTE* buffer, int size) image->bitsPerPixel = bi.biBitCount; image->bytesPerPixel = (image->bitsPerPixel / 8); image->scanline = (bi.biSizeImage / image->height); - image->data = (BYTE*) malloc(bi.biSizeImage); if (!image->data) - return -1; + goto fail; if (!vFlip) - CopyMemory(image->data, pSrcData, bi.biSizeImage); + Stream_Read(s, image->data, bi.biSizeImage); else { pDstData = &(image->data[(image->height - 1) * image->scanline]); for (index = 0; index < image->height; index++) { - CopyMemory(pDstData, pSrcData, image->scanline); - pSrcData += image->scanline; + Stream_Read(s, pDstData, image->scanline); pDstData -= image->scanline; } } - return 1; + rc = 1; +fail: + + if (rc < 0) + { + free(image->data); + image->data = NULL; + } + + Stream_Free(s, FALSE); + return rc; } int winpr_image_read(wImage* image, const char* filename) @@ -306,7 +395,6 @@ int winpr_image_read(wImage* image, const char* filename) FILE* fp; BYTE sig[8]; int status = -1; - fp = fopen(filename, "rb"); if (!fp) @@ -315,7 +403,7 @@ int winpr_image_read(wImage* image, const char* filename) return -1; } - if (fread((void*) &sig, sizeof(sig), 1, fp) != 1 || fseek(fp, 0, SEEK_SET) < 0) + if (fread((void*) &sig, sizeof(sig), 1, fp) != 1 || _fseeki64(fp, 0, SEEK_SET) < 0) { fclose(fp); return -1; @@ -327,13 +415,13 @@ int winpr_image_read(wImage* image, const char* filename) status = winpr_image_bitmap_read_fp(image, fp); } else if ((sig[0] == 0x89) && (sig[1] == 'P') && (sig[2] == 'N') && (sig[3] == 'G') && - (sig[4] == '\r') && (sig[5] == '\n') && (sig[6] == 0x1A) && (sig[7] == '\n')) + (sig[4] == '\r') && (sig[5] == '\n') && (sig[6] == 0x1A) && (sig[7] == '\n')) { image->type = WINPR_IMAGE_PNG; status = winpr_image_png_read_fp(image, fp); } - fclose(fp); + fclose(fp); return status; } @@ -353,7 +441,7 @@ int winpr_image_read_buffer(wImage* image, BYTE* buffer, int size) status = winpr_image_bitmap_read_buffer(image, buffer, size); } else if ((sig[0] == 0x89) && (sig[1] == 'P') && (sig[2] == 'N') && (sig[3] == 'G') && - (sig[4] == '\r') && (sig[5] == '\n') && (sig[6] == 0x1A) && (sig[7] == '\n')) + (sig[4] == '\r') && (sig[5] == '\n') && (sig[6] == 0x1A) && (sig[7] == '\n')) { image->type = WINPR_IMAGE_PNG; status = winpr_image_png_read_buffer(image, buffer, size); @@ -362,10 +450,9 @@ int winpr_image_read_buffer(wImage* image, BYTE* buffer, int size) return status; } -wImage* winpr_image_new() +wImage* winpr_image_new(void) { wImage* image; - image = (wImage*) calloc(1, sizeof(wImage)); if (!image) diff --git a/winpr/libwinpr/utils/ini.c b/winpr/libwinpr/utils/ini.c index 9bbf45f..5c0798f 100644 --- a/winpr/libwinpr/utils/ini.c +++ b/winpr/libwinpr/utils/ini.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <winpr/ini.h> @@ -32,7 +33,6 @@ BOOL IniFile_Load_NextLine(wIniFile* ini, char* str) { int length = 0; - ini->nextLine = strtok_s(str, "\n", &ini->tokctx); if (ini->nextLine) @@ -56,11 +56,9 @@ BOOL IniFile_Load_NextLine(wIniFile* ini, char* str) int IniFile_Load_String(wIniFile* ini, const char* iniString) { long int fileSize; - ini->line = NULL; ini->nextLine = NULL; ini->buffer = NULL; - fileSize = (long int) strlen(iniString); if (fileSize < 1) @@ -72,12 +70,9 @@ int IniFile_Load_String(wIniFile* ini, const char* iniString) return -1; CopyMemory(ini->buffer, iniString, fileSize); - ini->buffer[fileSize] = '\n'; ini->buffer[fileSize + 1] = '\0'; - IniFile_Load_NextLine(ini, ini->buffer); - return 1; } @@ -96,20 +91,20 @@ int IniFile_Open_File(wIniFile* ini, const char* filename) int IniFile_Load_File(wIniFile* ini, const char* filename) { - int fileSize; + INT64 fileSize; if (IniFile_Open_File(ini, filename) < 0) return -1; - if (fseek(ini->fp, 0, SEEK_END) < 0) + if (_fseeki64(ini->fp, 0, SEEK_END) < 0) goto out_file; - fileSize = ftell(ini->fp); - + fileSize = _ftelli64(ini->fp); + if (fileSize < 0) goto out_file; - - if (fseek(ini->fp, 0, SEEK_SET) < 0) + + if (_fseeki64(ini->fp, 0, SEEK_SET) < 0) goto out_file; ini->line = NULL; @@ -129,14 +124,10 @@ int IniFile_Load_File(wIniFile* ini, const char* filename) fclose(ini->fp); ini->fp = NULL; - ini->buffer[fileSize] = '\n'; ini->buffer[fileSize + 1] = '\0'; - IniFile_Load_NextLine(ini, ini->buffer); - return 1; - out_buffer: free(ini->buffer); ini->buffer = NULL; @@ -173,9 +164,7 @@ char* IniFile_Load_GetNextLine(wIniFile* ini) ini->line = ini->nextLine; ini->lineLength = (int) strlen(ini->line); - IniFile_Load_NextLine(ini, NULL); - return ini->line; } @@ -289,13 +278,12 @@ wIniFileSection* IniFile_AddSection(wIniFile* ini, const char* name) { int new_size; wIniFileSection** new_sect; - new_size = ini->cSections * 2; new_sect = (wIniFileSection**) realloc(ini->sections, sizeof(wIniFileSection*) * new_size); - + if (!new_sect) return NULL; - + ini->cSections = new_size; ini->sections = new_sect; } @@ -325,13 +313,14 @@ wIniFileKey* IniFile_GetKey(wIniFile* ini, wIniFileSection* section, const char* return key; } -wIniFileKey* IniFile_AddKey(wIniFile* ini, wIniFileSection* section, const char* name, const char* value) +wIniFileKey* IniFile_AddKey(wIniFile* ini, wIniFileSection* section, const char* name, + const char* value) { wIniFileKey* key; if (!section || !name) return NULL; - + key = IniFile_GetKey(ini, section, name); if (!key) @@ -340,19 +329,18 @@ wIniFileKey* IniFile_AddKey(wIniFile* ini, wIniFileSection* section, const char* { int new_size; wIniFileKey** new_key; - new_size = section->cKeys * 2; new_key = (wIniFileKey**) realloc(section->keys, sizeof(wIniFileKey*) * new_size); - + if (!new_key) return NULL; - + section->cKeys = new_size; section->keys = new_key; } key = IniFile_Key_New(name, value); - + if (!key) return NULL; @@ -377,8 +365,7 @@ int IniFile_Load(wIniFile* ini) char* name; char* value; char* separator; - char *beg, *end; - wIniFileKey* key = NULL; + char* beg, *end; wIniFileSection* section = NULL; while (IniFile_Load_HasNextLine(ini)) @@ -391,21 +378,18 @@ int IniFile_Load(wIniFile* ini) if (line[0] == '[') { beg = &line[1]; - end = strchr(line, ']'); if (!end) return -1; *end = '\0'; - IniFile_AddSection(ini, beg); section = ini->sections[ini->nSections - 1]; } else { separator = strchr(line, '='); - end = separator; while ((&end[-1] > line) && ((end[-1] == ' ') || (end[-1] == '\t'))) @@ -413,64 +397,51 @@ int IniFile_Load(wIniFile* ini) *end = '\0'; name = line; - beg = separator + 1; while (*beg && ((*beg == ' ') || (*beg == '\t'))) beg++; - + if (*beg == '"') beg++; - + end = &line[ini->lineLength]; - + while ((end > beg) && ((end[-1] == ' ') || (end[-1] == '\t'))) end--; - + if (end[-1] == '"') end[-1] = '\0'; - + value = beg; if (!IniFile_AddKey(ini, section, name, value)) - { return -1; - } - - key = NULL; - if (section && section->keys) - key = section->keys[section->nKeys - 1]; } } IniFile_Load_Finish(ini); - return 1; } int IniFile_ReadBuffer(wIniFile* ini, const char* buffer) { int status; - ini->readOnly = TRUE; ini->filename = NULL; - status = IniFile_Load_String(ini, buffer); - + if (status < 0) return status; - - status = IniFile_Load(ini); + status = IniFile_Load(ini); return status; } int IniFile_ReadFile(wIniFile* ini, const char* filename) { int status; - ini->readOnly = TRUE; - free(ini->filename); ini->filename = _strdup(filename); @@ -478,12 +449,11 @@ int IniFile_ReadFile(wIniFile* ini, const char* filename) return -1; status = IniFile_Load_File(ini, filename); - + if (status < 0) return status; - - status = IniFile_Load(ini); + status = IniFile_Load(ini); return status; } @@ -495,23 +465,22 @@ char** IniFile_GetSectionNames(wIniFile* ini, int* count) int nameLength; char** sectionNames; wIniFileSection* section = NULL; - length = (sizeof(char*) * ini->nSections) + sizeof(char); - + for (index = 0; index < ini->nSections; index++) { section = ini->sections[index]; nameLength = (int) strlen(section->name); length += (nameLength + 1); } - + sectionNames = (char**) malloc(length); if (!sectionNames) return NULL; - p = (char*) &((BYTE*) sectionNames)[sizeof(char*) * ini->nSections]; - + p = (char*) & ((BYTE*) sectionNames)[sizeof(char*) * ini->nSections]; + for (index = 0; index < ini->nSections; index++) { sectionNames[index] = p; @@ -522,9 +491,7 @@ char** IniFile_GetSectionNames(wIniFile* ini, int* count) } *p = '\0'; - *count = ini->nSections; - return sectionNames; } @@ -537,27 +504,27 @@ char** IniFile_GetSectionKeyNames(wIniFile* ini, const char* section, int* count char** keyNames; wIniFileKey* pKey = NULL; wIniFileSection* pSection = NULL; - pSection = IniFile_GetSection(ini, section); - + if (!pSection) return NULL; - + length = (sizeof(char*) * pSection->nKeys) + sizeof(char); - + for (index = 0; index < pSection->nKeys; index++) { pKey = pSection->keys[index]; nameLength = (int) strlen(pKey->name); length += (nameLength + 1); } - + keyNames = (char**) malloc(length); + if (!keyNames) return NULL; - p = (char*) &((BYTE*) keyNames)[sizeof(char*) * pSection->nKeys]; - + p = (char*) & ((BYTE*) keyNames)[sizeof(char*) * pSection->nKeys]; + for (index = 0; index < pSection->nKeys; index++) { keyNames[index] = p; @@ -568,9 +535,7 @@ char** IniFile_GetSectionKeyNames(wIniFile* ini, const char* section, int* count } *p = '\0'; - *count = pSection->nKeys; - return keyNames; } @@ -579,48 +544,44 @@ const char* IniFile_GetKeyValueString(wIniFile* ini, const char* section, const const char* value = NULL; wIniFileKey* pKey = NULL; wIniFileSection* pSection = NULL; - pSection = IniFile_GetSection(ini, section); - + if (!pSection) return NULL; - + pKey = IniFile_GetKey(ini, pSection, key); - + if (!pKey) return NULL; - + value = (const char*) pKey->value; - return value; } int IniFile_GetKeyValueInt(wIniFile* ini, const char* section, const char* key) { - int value = 0; + long value = 0; wIniFileKey* pKey = NULL; wIniFileSection* pSection = NULL; - pSection = IniFile_GetSection(ini, section); - + if (!pSection) return 0; - + pKey = IniFile_GetKey(ini, pSection, key); - + if (!pKey) return 0; - - value = atoi(pKey->value); - + + value = strtol(pKey->value, NULL, 0); return value; } -int IniFile_SetKeyValueString(wIniFile* ini, const char* section, const char* key, const char* value) +int IniFile_SetKeyValueString(wIniFile* ini, const char* section, const char* key, + const char* value) { wIniFileKey* pKey = NULL; wIniFileSection* pSection = NULL; - pSection = IniFile_GetSection(ini, section); if (!pSection) @@ -642,9 +603,7 @@ int IniFile_SetKeyValueInt(wIniFile* ini, const char* section, const char* key, char strVal[128]; wIniFileKey* pKey = NULL; wIniFileSection* pSection = NULL; - sprintf_s(strVal, sizeof(strVal), "%d", value); - pSection = IniFile_GetSection(ini, section); if (!pSection) @@ -664,30 +623,28 @@ int IniFile_SetKeyValueInt(wIniFile* ini, const char* section, const char* key, char* IniFile_WriteBuffer(wIniFile* ini) { int i, j; - int offset; - int size; + size_t offset; + size_t size; char* buffer; wIniFileKey* key; wIniFileSection* section; - size = 0; for (i = 0; i < ini->nSections; i++) { section = ini->sections[i]; - size += (int) (strlen(section->name) + 3); + size += (strlen(section->name) + 3); for (j = 0; j < section->nKeys; j++) { key = section->keys[j]; - size += (int) (strlen(key->name) + strlen(key->value) + 2); + size += (strlen(key->name) + strlen(key->value) + 2); } size += 1; } size += 1; - buffer = malloc(size + 1); if (!buffer) @@ -699,13 +656,13 @@ char* IniFile_WriteBuffer(wIniFile* ini) { section = ini->sections[i]; sprintf_s(&buffer[offset], size - offset, "[%s]\n", section->name); - offset += (int) (strlen(section->name) + 3); + offset += (strlen(section->name) + 3); for (j = 0; j < section->nKeys; j++) { key = section->keys[j]; sprintf_s(&buffer[offset], size - offset, "%s=%s\n", key->name, key->value); - offset += (int) (strlen(key->name) + strlen(key->value) + 2); + offset += (strlen(key->name) + strlen(key->value) + 2); } sprintf_s(&buffer[offset], size - offset, "\n"); @@ -713,7 +670,6 @@ char* IniFile_WriteBuffer(wIniFile* ini) } buffer[offset] = '\0'; - return buffer; } @@ -722,14 +678,12 @@ int IniFile_WriteFile(wIniFile* ini, const char* filename) int length; char* buffer; int ret = 1; - buffer = IniFile_WriteBuffer(ini); if (!buffer) return -1; length = (int) strlen(buffer); - ini->readOnly = FALSE; if (!filename) @@ -745,9 +699,7 @@ int IniFile_WriteFile(wIniFile* ini, const char* filename) ret = -1; fclose(ini->fp); - free(buffer); - return ret; } @@ -786,6 +738,5 @@ void IniFile_Free(wIniFile* ini) } free(ini->sections); - free(ini); } diff --git a/winpr/libwinpr/utils/lodepng/lodepng.c b/winpr/libwinpr/utils/lodepng/lodepng.c index 36902ce..05e2b81 100644 --- a/winpr/libwinpr/utils/lodepng/lodepng.c +++ b/winpr/libwinpr/utils/lodepng/lodepng.c @@ -26,6 +26,7 @@ freely, subject to the following restrictions: * Modifications fixing various errors. */ #include "lodepng.h" +#include <winpr/wtypes.h> #include <stdio.h> #include <stdlib.h> @@ -342,7 +343,7 @@ static int lodepng_add32bitInt(ucvector* buffer, unsigned value) unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) { FILE* file; - long size; + INT64 size; /*provide some proper output values if error will happen*/ *out = 0; @@ -352,8 +353,8 @@ unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* fil if(!file) return 78; /*get filesize:*/ - fseek(file , 0 , SEEK_END); - size = ftell(file); + _fseeki64(file , 0 , SEEK_END); + size = _ftelli64(file); rewind(file); /*read contents of the file into the vector*/ diff --git a/winpr/libwinpr/utils/sam.c b/winpr/libwinpr/utils/sam.c index 0e229b2..04e06f9 100644 --- a/winpr/libwinpr/utils/sam.c +++ b/winpr/libwinpr/utils/sam.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <winpr/sam.h> #include <winpr/print.h> @@ -51,9 +52,7 @@ WINPR_SAM* SamOpen(const char* filename, BOOL readOnly) filename = WINPR_SAM_FILE; if (readOnly) - { fp = fopen(filename, "r"); - } else { fp = fopen(filename, "r+"); @@ -78,6 +77,7 @@ WINPR_SAM* SamOpen(const char* filename, BOOL readOnly) else { WLog_DBG(TAG, "Could not open SAM file!"); + return NULL; } return sam; @@ -86,11 +86,14 @@ WINPR_SAM* SamOpen(const char* filename, BOOL readOnly) static BOOL SamLookupStart(WINPR_SAM* sam) { size_t readSize; - long int fileSize; + INT64 fileSize; - fseek(sam->fp, 0, SEEK_END); - fileSize = ftell(sam->fp); - fseek(sam->fp, 0, SEEK_SET); + if (!sam || !sam->fp) + return FALSE; + + _fseeki64(sam->fp, 0, SEEK_END); + fileSize = _ftelli64(sam->fp); + _fseeki64(sam->fp, 0, SEEK_SET); if (fileSize < 1) return FALSE; @@ -118,7 +121,6 @@ static BOOL SamLookupStart(WINPR_SAM* sam) sam->buffer[fileSize] = '\n'; sam->buffer[fileSize + 1] = '\0'; sam->line = strtok(sam->buffer, "\n"); - return TRUE; } @@ -152,55 +154,74 @@ static void HexStrToBin(char* str, BYTE* bin, int length) } } -BOOL SamReadEntry(WINPR_SAM *sam, WINPR_SAM_ENTRY *entry) +BOOL SamReadEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry) { - char* p[7]; - int LmHashLength; - int NtHashLength; + char* p[5]; + size_t LmHashLength; + size_t NtHashLength; + size_t count = 0; + char* cur; + + if (!sam || !entry || !sam->line) + return FALSE; + + cur = sam->line; + + while ((cur = strchr(cur, ':')) != NULL) + { + count++; + cur++; + } + + if (count < 4) + return FALSE; p[0] = sam->line; p[1] = strchr(p[0], ':') + 1; p[2] = strchr(p[1], ':') + 1; p[3] = strchr(p[2], ':') + 1; p[4] = strchr(p[3], ':') + 1; - p[5] = strchr(p[4], ':') + 1; - p[6] = p[0] + strlen(p[0]); + LmHashLength = (p[3] - p[2] - 1); + NtHashLength = (p[4] - p[3] - 1); + + if ((LmHashLength != 0) && (LmHashLength != 32)) + return FALSE; + + if ((NtHashLength != 0) && (NtHashLength != 32)) + return FALSE; + entry->UserLength = (UINT32)(p[1] - p[0] - 1); entry->User = (LPSTR) malloc(entry->UserLength + 1); + if (!entry->User) return FALSE; + entry->User[entry->UserLength] = '\0'; entry->DomainLength = (UINT32)(p[2] - p[1] - 1); - LmHashLength = (int)(p[3] - p[2] - 1); - NtHashLength = (int)(p[4] - p[3] - 1); memcpy(entry->User, p[0], entry->UserLength); if (entry->DomainLength > 0) { entry->Domain = (LPSTR) malloc(entry->DomainLength + 1); + if (!entry->Domain) { free(entry->User); entry->User = NULL; return FALSE; } + memcpy(entry->Domain, p[1], entry->DomainLength); entry->Domain[entry->DomainLength] = '\0'; } else - { entry->Domain = NULL; - } if (LmHashLength == 32) - { HexStrToBin(p[2], (BYTE*) entry->LmHash, 16); - } if (NtHashLength == 32) - { HexStrToBin(p[3], (BYTE*) entry->NtHash, 16); - } return TRUE; } @@ -240,12 +261,12 @@ void SamResetEntry(WINPR_SAM_ENTRY* entry) ZeroMemory(entry->NtHash, sizeof(entry->NtHash)); } -WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, LPSTR Domain, UINT32 DomainLength) +WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, LPSTR Domain, + UINT32 DomainLength) { - int length; + size_t length; BOOL found = FALSE; WINPR_SAM_ENTRY* entry; - entry = (WINPR_SAM_ENTRY*) calloc(1, sizeof(WINPR_SAM_ENTRY)); if (!entry) @@ -259,7 +280,7 @@ WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, L while (sam->line != NULL) { - length = (int) strlen(sam->line); + length = strlen(sam->line); if (length > 1) { @@ -277,6 +298,7 @@ WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, L } } } + SamResetEntry(entry); sam->line = strtok(NULL, "\n"); } @@ -293,9 +315,10 @@ out_fail: return entry; } -WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength) +WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, LPWSTR Domain, + UINT32 DomainLength) { - int length; + size_t length; BOOL Found = FALSE; BOOL UserMatch; BOOL DomainMatch; @@ -316,7 +339,7 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, while (sam->line != NULL) { - length = (int) strlen(sam->line); + length = strlen(sam->line); if (length > 1) { @@ -324,6 +347,7 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, { DomainMatch = 0; UserMatch = 0; + if (!SamReadEntry(sam, entry)) goto out_fail; @@ -333,10 +357,12 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, { EntryDomainLength = (UINT32) strlen(entry->Domain) * 2; EntryDomain = (LPWSTR) malloc(EntryDomainLength + 2); + if (!EntryDomain) goto out_fail; + MultiByteToWideChar(CP_ACP, 0, entry->Domain, EntryDomainLength / 2, - (LPWSTR) EntryDomain, EntryDomainLength / 2); + (LPWSTR) EntryDomain, EntryDomainLength / 2); if (DomainLength == EntryDomainLength) { @@ -362,10 +388,12 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, { EntryUserLength = (UINT32) strlen(entry->User) * 2; EntryUser = (LPWSTR) malloc(EntryUserLength + 2); + if (!EntryUser) goto out_fail; + MultiByteToWideChar(CP_ACP, 0, entry->User, EntryUserLength / 2, - (LPWSTR) EntryUser, EntryUserLength / 2); + (LPWSTR) EntryUser, EntryUserLength / 2); if (UserLength == EntryUserLength) { diff --git a/winpr/libwinpr/utils/ssl.c b/winpr/libwinpr/utils/ssl.c index b674e21..194f826 100644 --- a/winpr/libwinpr/utils/ssl.c +++ b/winpr/libwinpr/utils/ssl.c @@ -93,7 +93,8 @@ static struct CRYPTO_dynlock_value* _winpr_openssl_dynlock_create(const char* fi return dynlock; } -static void _winpr_openssl_dynlock_lock(int mode, struct CRYPTO_dynlock_value* dynlock, const char* file, int line) +static void _winpr_openssl_dynlock_lock(int mode, struct CRYPTO_dynlock_value* dynlock, + const char* file, int line) { if (mode & CRYPTO_LOCK) { @@ -105,7 +106,8 @@ static void _winpr_openssl_dynlock_lock(int mode, struct CRYPTO_dynlock_value* d } } -static void _winpr_openssl_dynlock_destroy(struct CRYPTO_dynlock_value* dynlock, const char* file, int line) +static void _winpr_openssl_dynlock_destroy(struct CRYPTO_dynlock_value* dynlock, const char* file, + int line) { CloseHandle(dynlock->mutex); free(dynlock); @@ -159,8 +161,8 @@ static BOOL _winpr_openssl_initialize_locking(void) /* OpenSSL dynamic locking */ if (CRYPTO_get_dynlock_create_callback() || - CRYPTO_get_dynlock_lock_callback() || - CRYPTO_get_dynlock_destroy_callback()) + CRYPTO_get_dynlock_lock_callback() || + CRYPTO_get_dynlock_destroy_callback()) { WLog_WARN(TAG, "dynamic locking callbacks are already set"); } @@ -246,6 +248,7 @@ static BOOL CALLBACK _winpr_openssl_initialize(PINIT_ONCE once, PVOID param, PVO } #ifdef WINPR_OPENSSL_LOCKING_REQUIRED + if (flags & WINPR_SSL_INIT_ENABLE_LOCKING) { if (!_winpr_openssl_initialize_locking()) @@ -253,23 +256,45 @@ static BOOL CALLBACK _winpr_openssl_initialize(PINIT_ONCE once, PVOID param, PVO return FALSE; } } + #endif /* SSL_load_error_strings() is void */ -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) SSL_load_error_strings(); /* SSL_library_init() always returns "1" */ SSL_library_init(); OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); #else + if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS | - OPENSSL_INIT_LOAD_CRYPTO_STRINGS | - OPENSSL_INIT_ADD_ALL_CIPHERS | - OPENSSL_INIT_ADD_ALL_DIGESTS | - OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL) != 1) + OPENSSL_INIT_LOAD_CRYPTO_STRINGS | + OPENSSL_INIT_ADD_ALL_CIPHERS | + OPENSSL_INIT_ADD_ALL_DIGESTS | + OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL) != 1) return FALSE; + #endif g_winpr_openssl_initialized_by_winpr = TRUE; + + if (flags & WINPR_SSL_INIT_ENABLE_FIPS) + { +#if (OPENSSL_VERSION_NUMBER < 0x10001000L) || defined(LIBRESSL_VERSION_NUMBER) + WLog_ERR(TAG, "Openssl fips mode ENable not available on openssl versions less than 1.0.1!"); +#else + WLog_DBG(TAG, "Ensuring openssl fips mode is ENabled"); + + if (FIPS_mode() != 1) + { + if (FIPS_mode_set(1)) + WLog_INFO(TAG, "Openssl fips mode ENabled!"); + else + WLog_ERR(TAG, "Openssl fips mode ENable failed!"); + } + +#endif + } + return TRUE; } @@ -296,27 +321,40 @@ BOOL winpr_CleanupSSL(DWORD flags) #ifdef WINPR_OPENSSL_LOCKING_REQUIRED _winpr_openssl_cleanup_locking(); #endif -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); EVP_cleanup(); #endif +#ifdef WINPR_OPENSSL_LOCKING_REQUIRED flags |= WINPR_SSL_CLEANUP_THREAD; +#endif } #ifdef WINPR_OPENSSL_LOCKING_REQUIRED + if (flags & WINPR_SSL_CLEANUP_THREAD) { -#if (OPENSSL_VERSION_NUMBER < 0x10000000L) +#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || defined(LIBRESSL_VERSION_NUMBER) ERR_remove_state(0); #else ERR_remove_thread_state(NULL); #endif } + #endif return TRUE; } +BOOL winpr_FIPSMode(void) +{ +#if (OPENSSL_VERSION_NUMBER < 0x10001000L) || defined(LIBRESSL_VERSION_NUMBER) + return FALSE; +#else + return (FIPS_mode() == 1); +#endif +} + #else BOOL winpr_InitializeSSL(DWORD flags) @@ -329,4 +367,9 @@ BOOL winpr_CleanupSSL(DWORD flags) return TRUE; } +BOOL winpr_FIPSMode(void) +{ + return FALSE; +} + #endif diff --git a/winpr/libwinpr/utils/test/TestBacktrace.c b/winpr/libwinpr/utils/test/TestBacktrace.c index 76ff919..5df0cdd 100644 --- a/winpr/libwinpr/utils/test/TestBacktrace.c +++ b/winpr/libwinpr/utils/test/TestBacktrace.c @@ -5,8 +5,9 @@ int TestBacktrace(int argc, char* argv[]) { int rc = -1; size_t used, x; - char **msg; - void *stack = winpr_backtrace(20); + char** msg; + void* stack = winpr_backtrace(20); + if (!stack) { fprintf(stderr, "winpr_backtrace failed!\n"); @@ -14,15 +15,17 @@ int TestBacktrace(int argc, char* argv[]) } msg = winpr_backtrace_symbols(stack, &used); + if (msg) { - for (x=0; x<used; x++) + for (x = 0; x < used; x++) printf("%"PRIuz": %s\n", x, msg[x]); + rc = 0; } + winpr_backtrace_symbols_fd(stack, fileno(stdout)); - winpr_backtrace_free(stack); - + free(msg); return rc; } diff --git a/winpr/libwinpr/utils/test/TestBipBuffer.c b/winpr/libwinpr/utils/test/TestBipBuffer.c index 0899f40..03bc5da 100644 --- a/winpr/libwinpr/utils/test/TestBipBuffer.c +++ b/winpr/libwinpr/utils/test/TestBipBuffer.c @@ -5,8 +5,8 @@ int TestBipBuffer(int argc, char* argv[]) { BYTE* data; + int rc = -1; wBipBuffer* bb; - bb = BipBuffer_New(1024); if (!bb) @@ -14,9 +14,10 @@ int TestBipBuffer(int argc, char* argv[]) data = BipBuffer_WriteReserve(bb, 1024 * 2); + if (data) + rc = 0; + fprintf(stderr, "BipBuffer_BufferSize: %"PRIuz"\n", BipBuffer_BufferSize(bb)); - BipBuffer_Free(bb); - - return 0; + return rc; } diff --git a/winpr/libwinpr/utils/test/TestCmdLine.c b/winpr/libwinpr/utils/test/TestCmdLine.c index 538e500..a22315a 100644 --- a/winpr/libwinpr/utils/test/TestCmdLine.c +++ b/winpr/libwinpr/utils/test/TestCmdLine.c @@ -1,9 +1,10 @@ +#include <errno.h> #include <winpr/crt.h> #include <winpr/tchar.h> #include <winpr/cmdline.h> -const char* testArgv[] = +static const char* testArgv[] = { "mstsc.exe", "+z", @@ -17,7 +18,7 @@ const char* testArgv[] = "/v:localhost:3389" }; -COMMAND_LINE_ARGUMENT_A args[] = +static COMMAND_LINE_ARGUMENT_A args[] = { { "v", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "destination server" }, { "port", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "server port" }, @@ -60,10 +61,9 @@ int TestCmdLine(int argc, char* argv[]) { int status; DWORD flags; - int width = 0; - int height = 0; + long width = 0; + long height = 0; COMMAND_LINE_ARGUMENT_A* arg; - flags = COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_SIGIL_PLUS_MINUS; status = CommandLineParseArgumentsA(testArgc, testArgv, args, flags, NULL, NULL, NULL); @@ -146,6 +146,7 @@ int TestCmdLine(int argc, char* argv[]) } arg = args; + errno = 0; do { @@ -153,33 +154,34 @@ int TestCmdLine(int argc, char* argv[]) continue; printf("Argument: %s\n", arg->Name); - CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "v") { - } CommandLineSwitchCase(arg, "w") { - width = atoi(arg->Value); + width = strtol(arg->Value, NULL, 0); + + if (errno != 0) + return -1; } CommandLineSwitchCase(arg, "h") { - height = atoi(arg->Value); + height = strtol(arg->Value, NULL, 0); + + if (errno != 0) + return -1; } CommandLineSwitchDefault(arg) { - } - CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); if ((width != 1024) || (height != 768)) { - printf("Unexpected width and height: Actual: (%dx%d), Expected: (1024x768)\n", width, height); + printf("Unexpected width and height: Actual: (%ldx%ld), Expected: (1024x768)\n", width, height); return -1; } diff --git a/winpr/libwinpr/utils/test/TestHashTable.c b/winpr/libwinpr/utils/test/TestHashTable.c index 3371d0f..199b46a 100644 --- a/winpr/libwinpr/utils/test/TestHashTable.c +++ b/winpr/libwinpr/utils/test/TestHashTable.c @@ -11,68 +11,64 @@ static char* val1 = "val1"; static char* val2 = "val2"; static char* val3 = "val3"; -int test_hash_table_pointer() +static int test_hash_table_pointer(void) { + int rc = -1; int count; char* value; wHashTable* table; - table = HashTable_New(TRUE); + if (!table) return -1; HashTable_Add(table, key1, val1); HashTable_Add(table, key2, val2); HashTable_Add(table, key3, val3); - count = HashTable_Count(table); if (count != 3) { printf("HashTable_Count: Expected : 3, Actual: %d\n", count); - return -1; + goto fail; } HashTable_Remove(table, key2); - count = HashTable_Count(table); if (count != 2) { printf("HashTable_Count: Expected : 2, Actual: %d\n", count); - return -1; + goto fail; } HashTable_Remove(table, key3); - count = HashTable_Count(table); if (count != 1) { printf("HashTable_Count: Expected : 1, Actual: %d\n", count); - return -1; + goto fail; } HashTable_Remove(table, key1); - count = HashTable_Count(table); if (count != 0) { printf("HashTable_Count: Expected : 0, Actual: %d\n", count); - return -1; + goto fail; } HashTable_Add(table, key1, val1); HashTable_Add(table, key2, val2); HashTable_Add(table, key3, val3); - count = HashTable_Count(table); if (count != 3) { printf("HashTable_Count: Expected : 3, Actual: %d\n", count); - return -1; + goto fail; } value = (char*) HashTable_GetItemValue(table, key1); @@ -80,7 +76,7 @@ int test_hash_table_pointer() if (strcmp(value, val1) != 0) { printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val1, value); - return -1; + goto fail; } value = (char*) HashTable_GetItemValue(table, key2); @@ -88,7 +84,7 @@ int test_hash_table_pointer() if (strcmp(value, val2) != 0) { printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val2, value); - return -1; + goto fail; } value = (char*) HashTable_GetItemValue(table, key3); @@ -96,59 +92,59 @@ int test_hash_table_pointer() if (strcmp(value, val3) != 0) { printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val3, value); - return -1; + goto fail; } HashTable_SetItemValue(table, key2, "apple"); - value = (char*) HashTable_GetItemValue(table, key2); if (strcmp(value, "apple") != 0) { printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", "apple", value); - return -1; + goto fail; } if (!HashTable_Contains(table, key2)) { printf("HashTable_Contains: Expected : TRUE, Actual: FALSE\n"); - return -1; + goto fail; } if (!HashTable_Remove(table, key2)) { printf("HashTable_Remove: Expected : TRUE, Actual: FALSE\n"); - return -1; + goto fail; } if (HashTable_Remove(table, key2)) { printf("HashTable_Remove: Expected : FALSE, Actual: TRUE\n"); - return -1; + goto fail; } HashTable_Clear(table); - count = HashTable_Count(table); if (count != 0) { printf("HashTable_Count: Expected : 0, Actual: %d\n", count); - return -1; + goto fail; } + rc = 1; +fail: HashTable_Free(table); - - return 1; + return rc; } -int test_hash_table_string() +static int test_hash_table_string(void) { + int rc = -1; int count; char* value; wHashTable* table; - table = HashTable_New(TRUE); + if (!table) return -1; @@ -159,59 +155,53 @@ int test_hash_table_string() table->valueClone = HashTable_StringClone; table->keyFree = HashTable_StringFree; table->valueFree = HashTable_StringFree; - HashTable_Add(table, key1, val1); HashTable_Add(table, key2, val2); HashTable_Add(table, key3, val3); - count = HashTable_Count(table); if (count != 3) { printf("HashTable_Count: Expected : 3, Actual: %d\n", count); - return -1; + goto fail; } HashTable_Remove(table, key2); - count = HashTable_Count(table); if (count != 2) { printf("HashTable_Count: Expected : 3, Actual: %d\n", count); - return -1; + goto fail; } HashTable_Remove(table, key3); - count = HashTable_Count(table); if (count != 1) { printf("HashTable_Count: Expected : 1, Actual: %d\n", count); - return -1; + goto fail; } HashTable_Remove(table, key1); - count = HashTable_Count(table); if (count != 0) { printf("HashTable_Count: Expected : 0, Actual: %d\n", count); - return -1; + goto fail; } HashTable_Add(table, key1, val1); HashTable_Add(table, key2, val2); HashTable_Add(table, key3, val3); - count = HashTable_Count(table); if (count != 3) { printf("HashTable_Count: Expected : 3, Actual: %d\n", count); - return -1; + goto fail; } value = (char*) HashTable_GetItemValue(table, key1); @@ -219,7 +209,7 @@ int test_hash_table_string() if (strcmp(value, val1) != 0) { printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val1, value); - return -1; + goto fail; } value = (char*) HashTable_GetItemValue(table, key2); @@ -227,7 +217,7 @@ int test_hash_table_string() if (strcmp(value, val2) != 0) { printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val2, value); - return -1; + goto fail; } value = (char*) HashTable_GetItemValue(table, key3); @@ -235,50 +225,49 @@ int test_hash_table_string() if (strcmp(value, val3) != 0) { printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", val3, value); - return -1; + goto fail; } HashTable_SetItemValue(table, key2, "apple"); - value = (char*) HashTable_GetItemValue(table, key2); if (strcmp(value, "apple") != 0) { printf("HashTable_GetItemValue: Expected : %s, Actual: %s\n", "apple", value); - return -1; + goto fail; } if (!HashTable_Contains(table, key2)) { printf("HashTable_Contains: Expected : TRUE, Actual: FALSE\n"); - return -1; + goto fail; } if (!HashTable_Remove(table, key2)) { printf("HashTable_Remove: Expected : TRUE, Actual: FALSE\n"); - return -1; + goto fail; } if (HashTable_Remove(table, key2)) { printf("HashTable_Remove: Expected : FALSE, Actual: TRUE\n"); - return -1; + goto fail; } HashTable_Clear(table); - count = HashTable_Count(table); if (count != 0) { printf("HashTable_Count: Expected : 0, Actual: %d\n", count); - return -1; + goto fail; } + rc = 1; +fail: HashTable_Free(table); - - return 1; + return rc; } int TestHashTable(int argc, char* argv[]) diff --git a/winpr/libwinpr/utils/test/TestImage.c b/winpr/libwinpr/utils/test/TestImage.c index 9cd16cd..7b26b82 100644 --- a/winpr/libwinpr/utils/test/TestImage.c +++ b/winpr/libwinpr/utils/test/TestImage.c @@ -1,3 +1,4 @@ +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <winpr/path.h> #include <winpr/print.h> @@ -8,12 +9,12 @@ #define PATH_MAX 4096 #endif -static void *read_image(const char *src, size_t *size) +static void* read_image(const char* src, size_t* size) { int success = 0; - void *a = NULL; - long src_size; - FILE *fsrc = fopen(src, "rb"); + void* a = NULL; + INT64 src_size; + FILE* fsrc = fopen(src, "rb"); if (!fsrc) { @@ -21,15 +22,15 @@ static void *read_image(const char *src, size_t *size) goto cleanup; } - if (fseek(fsrc, 0, SEEK_END)) + if (_fseeki64(fsrc, 0, SEEK_END)) { fprintf(stderr, "Failed to seek to file end\n"); goto cleanup; } - src_size = ftell(fsrc); + src_size = _ftelli64(fsrc); - if (fseek(fsrc, 0, SEEK_SET)) + if (_fseeki64(fsrc, 0, SEEK_SET)) { fprintf(stderr, "Failed to seek to SEEK_SET\n"); goto cleanup; @@ -51,22 +52,24 @@ static void *read_image(const char *src, size_t *size) success = 1; *size = src_size; - cleanup: + if (a && !success) { free(a); a = NULL; } + if (fsrc) fclose(fsrc); return a; } -static int img_compare(wImage *image, wImage *image2, BOOL ignoreType) +static int img_compare(wImage* image, wImage* image2, BOOL ignoreType) { int rc = -1; + if ((image->type != image2->type) && !ignoreType) { fprintf(stderr, "Image type mismatch %d:%d\n", image->type, image2->type); @@ -99,7 +102,8 @@ static int img_compare(wImage *image, wImage *image2, BOOL ignoreType) if (image->bytesPerPixel != image2->bytesPerPixel) { - fprintf(stderr, "Image bytesPerPixel mismatch %d:%d\n", image->bytesPerPixel, image2->bytesPerPixel); + fprintf(stderr, "Image bytesPerPixel mismatch %d:%d\n", image->bytesPerPixel, + image2->bytesPerPixel); goto cleanup; } @@ -112,11 +116,10 @@ cleanup: return rc; } -static wImage *get_image(const char *src) +static wImage* get_image(const char* src) { int status; wImage* image = NULL; - image = winpr_image_new(); if (!image) @@ -135,17 +138,16 @@ static wImage *get_image(const char *src) } cleanup: - return image; } -static int create_test(const char *src, const char *dst_png, const char *dst_bmp) +static int create_test(const char* src, const char* dst_png, const char* dst_bmp) { int rc = -1; int ret = -1; int status; size_t bsize; - void *buffer = NULL; + void* buffer = NULL; wImage* image = NULL, *image2 = NULL, *image3 = NULL, *image4 = NULL; if (!PathFileExistsA(src)) @@ -181,6 +183,7 @@ static int create_test(const char *src, const char *dst_png, const char *dst_bmp /* Read image from buffer, compare. */ buffer = read_image(src, &bsize); + if (!buffer) { fprintf(stderr, "Failed to read image %s!\n", src); @@ -204,57 +207,68 @@ static int create_test(const char *src, const char *dst_png, const char *dst_bmp } rc = img_compare(image, image2, TRUE); + if (rc) goto cleanup; image3 = get_image(dst_png); + if (!image3) goto cleanup; rc = img_compare(image, image3, TRUE); + if (rc) goto cleanup; image4 = get_image(dst_bmp); + if (!image4) goto cleanup; rc = img_compare(image, image4, TRUE); + if (rc) goto cleanup; ret = 0; cleanup: + if (image) winpr_image_free(image, TRUE); + if (image2) winpr_image_free(image2, TRUE); + if (image3) winpr_image_free(image3, TRUE); + if (image4) winpr_image_free(image4, TRUE); free(buffer); - return ret; } -int test_image_png_to_bmp() +static int test_image_png_to_bmp(void) { - char *buffer = TEST_SOURCE_PATH; + char* buffer = TEST_SOURCE_PATH; char src_png[PATH_MAX]; char src_bmp[PATH_MAX]; char dst_png[PATH_MAX]; char dst_bmp[PATH_MAX]; char dst_png2[PATH_MAX]; char dst_bmp2[PATH_MAX]; - char *tmp = GetKnownPath(KNOWN_PATH_TEMP); + char* tmp = GetKnownPath(KNOWN_PATH_TEMP); if (!tmp) return -1; if (!buffer) + { + free(tmp); return -1; + } sprintf_s(src_png, sizeof(src_png), "%s/lodepng_32bit.png", buffer); sprintf_s(src_bmp, sizeof(src_bmp), "%s/lodepng_32bit.bmp", buffer); @@ -262,6 +276,7 @@ int test_image_png_to_bmp() sprintf_s(dst_bmp, sizeof(dst_bmp), "%s/lodepng_32bit.bmp", tmp); sprintf_s(dst_png2, sizeof(dst_png2), "%s/lodepng_32bit-2.png", tmp); sprintf_s(dst_bmp2, sizeof(dst_bmp2), "%s/lodepng_32bit-2.bmp", tmp); + free(tmp); if (create_test(src_png, dst_png, dst_bmp)) return -1; @@ -275,7 +290,6 @@ int test_image_png_to_bmp() int TestImage(int argc, char* argv[]) { int rc = test_image_png_to_bmp(); - return rc; } diff --git a/winpr/libwinpr/utils/test/TestMessagePipe.c b/winpr/libwinpr/utils/test/TestMessagePipe.c index 2163bbf..fc6b5bc 100644 --- a/winpr/libwinpr/utils/test/TestMessagePipe.c +++ b/winpr/libwinpr/utils/test/TestMessagePipe.c @@ -3,7 +3,7 @@ #include <winpr/thread.h> #include <winpr/collections.h> -static void* message_echo_pipe_client_thread(void* arg) +static DWORD WINAPI message_echo_pipe_client_thread(LPVOID arg) { int index = 0; wMessagePipe* pipe = (wMessagePipe*) arg; @@ -35,10 +35,10 @@ static void* message_echo_pipe_client_thread(void* arg) MessageQueue_PostQuit(pipe->In, 0); - return NULL; + return 0; } -static void* message_echo_pipe_server_thread(void* arg) +static DWORD WINAPI message_echo_pipe_server_thread(LPVOID arg) { wMessage message; wMessagePipe* pipe; @@ -57,7 +57,7 @@ static void* message_echo_pipe_server_thread(void* arg) } } - return NULL; + return 0; } int TestMessagePipe(int argc, char* argv[]) @@ -73,13 +73,13 @@ int TestMessagePipe(int argc, char* argv[]) goto out; } - if (!(ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) message_echo_pipe_client_thread, (void*) EchoPipe, 0, NULL))) + if (!(ClientThread = CreateThread(NULL, 0, message_echo_pipe_client_thread, (void*) EchoPipe, 0, NULL))) { printf("failed to create client thread\n"); goto out; } - if (!(ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) message_echo_pipe_server_thread, (void*) EchoPipe, 0, NULL))) + if (!(ServerThread = CreateThread(NULL, 0, message_echo_pipe_server_thread, (void*) EchoPipe, 0, NULL))) { printf("failed to create server thread\n"); goto out; diff --git a/winpr/libwinpr/utils/test/TestMessageQueue.c b/winpr/libwinpr/utils/test/TestMessageQueue.c index 97dcec0..5825bad 100644 --- a/winpr/libwinpr/utils/test/TestMessageQueue.c +++ b/winpr/libwinpr/utils/test/TestMessageQueue.c @@ -3,7 +3,7 @@ #include <winpr/thread.h> #include <winpr/collections.h> -static void* message_queue_consumer_thread(void* arg) +static DWORD WINAPI message_queue_consumer_thread(LPVOID arg) { wMessage message; wMessageQueue* queue; @@ -21,7 +21,7 @@ static void* message_queue_consumer_thread(void* arg) } } - return NULL; + return 0; } int TestMessageQueue(int argc, char* argv[]) @@ -35,7 +35,7 @@ int TestMessageQueue(int argc, char* argv[]) return 1; } - if (!(thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) message_queue_consumer_thread, (void*) queue, 0, NULL))) + if (!(thread = CreateThread(NULL, 0, message_queue_consumer_thread, (void*) queue, 0, NULL))) { printf("failed to create thread\n"); MessageQueue_Free(queue); diff --git a/winpr/libwinpr/utils/test/TestStream.c b/winpr/libwinpr/utils/test/TestStream.c index ded6157..b6ba856 100644 --- a/winpr/libwinpr/utils/test/TestStream.c +++ b/winpr/libwinpr/utils/test/TestStream.c @@ -2,7 +2,7 @@ #include <winpr/print.h> #include <winpr/stream.h> -static BOOL TestStream_Verify(wStream* s, int mincap, int len, int pos) +static BOOL TestStream_Verify(wStream* s, int mincap, int len, size_t pos) { if (Stream_Buffer(s) == NULL) { @@ -32,7 +32,7 @@ static BOOL TestStream_Verify(wStream* s, int mincap, int len, int pos) } if (Stream_GetPosition(s) != pos) { - printf("stream has unexpected position (%"PRIuz" instead of %d)\n", + printf("stream has unexpected position (%"PRIuz" instead of %"PRIuz")\n", Stream_GetPosition(s), pos); return FALSE; } @@ -56,7 +56,7 @@ static BOOL TestStream_Verify(wStream* s, int mincap, int len, int pos) } if (Stream_GetRemainingLength(s) != len - pos) { - printf("stream remaining length (%"PRIuz" instead of %d)\n", + printf("stream remaining length (%"PRIuz" instead of %"PRIuz")\n", Stream_GetRemainingLength(s), len - pos); return FALSE; } diff --git a/winpr/libwinpr/utils/test/TestWLog.c b/winpr/libwinpr/utils/test/TestWLog.c index 1162db4..e3fc86d 100644 --- a/winpr/libwinpr/utils/test/TestWLog.c +++ b/winpr/libwinpr/utils/test/TestWLog.c @@ -21,8 +21,6 @@ int TestWLog(int argc, char* argv[]) goto out; } - WLog_Init(); - root = WLog_GetRoot(); WLog_SetLogAppenderType(root, WLOG_APPENDER_BINARY); @@ -56,8 +54,6 @@ int TestWLog(int argc, char* argv[]) WLog_CloseAppender(root); - WLog_Uninit(); - if ((wlog_file = GetCombinedPath(tmp_path, "test_w.log"))) DeleteFileA(wlog_file); diff --git a/winpr/libwinpr/utils/test/TestWLogCallback.c b/winpr/libwinpr/utils/test/TestWLogCallback.c index e073e94..378f312 100644 --- a/winpr/libwinpr/utils/test/TestWLogCallback.c +++ b/winpr/libwinpr/utils/test/TestWLogCallback.c @@ -92,7 +92,6 @@ int TestWLogCallback(int argc, char* argv[]) wLogCallbacks callbacks; function = __FUNCTION__; - WLog_Init(); root = WLog_GetRoot(); @@ -130,8 +129,6 @@ int TestWLogCallback(int argc, char* argv[]) WLog_CloseAppender(root); - WLog_Uninit(); - return success ? 0 : -1; } diff --git a/winpr/libwinpr/utils/winpr.c b/winpr/libwinpr/utils/winpr.c index 4093689..1e72cf9 100644 --- a/winpr/libwinpr/utils/winpr.c +++ b/winpr/libwinpr/utils/winpr.c @@ -30,6 +30,11 @@ #include <winpr/string.h> #include <winpr/winpr.h> #include <winpr/version.h> +#include <winpr/wlog.h> + +#if !defined(WIN32) +#include <pthread.h> +#endif void winpr_get_version(int* major, int* minor, int* revision) { @@ -69,3 +74,4 @@ const char* winpr_get_build_config(void) return build_config; } + diff --git a/winpr/libwinpr/utils/wlog/PacketMessage.c b/winpr/libwinpr/utils/wlog/PacketMessage.c index 9bcddbb..abd3038 100644 --- a/winpr/libwinpr/utils/wlog/PacketMessage.c +++ b/winpr/libwinpr/utils/wlog/PacketMessage.c @@ -27,6 +27,7 @@ #include "wlog/PacketMessage.h" +#include <winpr/wtypes.h> #include <winpr/crt.h> #include <winpr/stream.h> @@ -125,7 +126,7 @@ static BOOL Pcap_Add_Record(wPcap* pcap, void* data, UINT32 length) static BOOL Pcap_HasNext_Record(wPcap* pcap) { - if (pcap->file_size - (ftell(pcap->fp)) <= 16) + if (pcap->file_size - (_ftelli64(pcap->fp)) <= 16) return FALSE; return TRUE; @@ -220,12 +221,12 @@ wPcap* Pcap_Open(char* name, BOOL write) } else { - if (fseek(pcap->fp, 0, SEEK_END) < 0) + if (_fseeki64(pcap->fp, 0, SEEK_END) < 0) goto out_fail; - pcap->file_size = (int) ftell(pcap->fp); + pcap->file_size = _ftelli64(pcap->fp); if (pcap->file_size < 0) goto out_fail; - if (fseek(pcap->fp, 0, SEEK_SET) < 0) + if (_fseeki64(pcap->fp, 0, SEEK_SET) < 0) goto out_fail; if (!Pcap_Read_Header(pcap, &pcap->header)) goto out_fail; diff --git a/winpr/libwinpr/utils/wlog/wlog.c b/winpr/libwinpr/utils/wlog/wlog.c index 2734e37..285df1c 100644 --- a/winpr/libwinpr/utils/wlog/wlog.c +++ b/winpr/libwinpr/utils/wlog/wlog.c @@ -28,6 +28,7 @@ #include <winpr/print.h> #include <winpr/debug.h> #include <winpr/environment.h> +#include <winpr/wlog.h> #if defined(ANDROID) #include <android/log.h> @@ -36,7 +37,6 @@ #include "wlog.h" - struct _wLogFilter { DWORD Level; @@ -66,12 +66,105 @@ LPCSTR WLOG_LEVELS[7] = "OFF" }; +static INIT_ONCE _WLogInitialized = INIT_ONCE_STATIC_INIT; static DWORD g_FilterCount = 0; static wLogFilter* g_Filters = NULL; +static wLog* g_RootLog = NULL; +static wLog* WLog_New(LPCSTR name, wLog* rootLogger); +static void WLog_Free(wLog* log); static LONG WLog_GetFilterLogLevel(wLog* log); static int WLog_ParseLogLevel(LPCSTR level); static BOOL WLog_ParseFilter(wLogFilter* filter, LPCSTR name); +static BOOL WLog_ParseFilters(void); + +#if !defined(_WIN32) +static void WLog_Uninit_(void) __attribute__((destructor)); +#endif + +static void WLog_Uninit_(void) +{ + DWORD index; + wLog* child = NULL; + wLog* root = g_RootLog; + + if (!root) + return; + + for (index = 0; index < root->ChildrenCount; index++) + { + child = root->Children[index]; + WLog_Free(child); + } + + WLog_Free(root); + g_RootLog = NULL; +} + +static BOOL CALLBACK WLog_InitializeRoot(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* Context) +{ + char* env; + DWORD nSize; + DWORD logAppenderType; + LPCSTR appender = "WLOG_APPENDER"; + + if (!(g_RootLog = WLog_New("", NULL))) + return FALSE; + + g_RootLog->IsRoot = TRUE; + WLog_ParseFilters(); + logAppenderType = WLOG_APPENDER_CONSOLE; + nSize = GetEnvironmentVariableA(appender, NULL, 0); + + if (nSize) + { + env = (LPSTR) malloc(nSize); + + if (!env) + goto fail; + + if (GetEnvironmentVariableA(appender, env, nSize) != nSize - 1) + { + fprintf(stderr, "%s environment variable modified in my back", appender); + free(env); + goto fail; + } + + if (_stricmp(env, "CONSOLE") == 0) + logAppenderType = WLOG_APPENDER_CONSOLE; + else if (_stricmp(env, "FILE") == 0) + logAppenderType = WLOG_APPENDER_FILE; + else if (_stricmp(env, "BINARY") == 0) + logAppenderType = WLOG_APPENDER_BINARY; + +#ifdef HAVE_SYSLOG_H + else if (_stricmp(env, "SYSLOG") == 0) + logAppenderType = WLOG_APPENDER_SYSLOG; + +#endif /* HAVE_SYSLOG_H */ +#ifdef HAVE_JOURNALD_H + else if (_stricmp(env, "JOURNALD") == 0) + logAppenderType = WLOG_APPENDER_JOURNALD; + +#endif + else if (_stricmp(env, "UDP") == 0) + logAppenderType = WLOG_APPENDER_UDP; + + free(env); + } + + if (!WLog_SetLogAppenderType(g_RootLog, logAppenderType)) + goto fail; + +#if defined(_WIN32) + atexit(WLog_Uninit_); +#endif + return TRUE; +fail: + free(g_RootLog); + g_RootLog = NULL; + return FALSE; +} static BOOL log_recursion(LPCSTR file, LPCSTR fkt, int line) { @@ -121,7 +214,7 @@ static BOOL log_recursion(LPCSTR file, LPCSTR fkt, int line) return TRUE; } -BOOL WLog_Write(wLog* log, wLogMessage* message) +static BOOL WLog_Write(wLog* log, wLogMessage* message) { BOOL status; wLogAppender* appender; @@ -153,7 +246,7 @@ BOOL WLog_Write(wLog* log, wLogMessage* message) return status; } -BOOL WLog_WriteData(wLog* log, wLogMessage* message) +static BOOL WLog_WriteData(wLog* log, wLogMessage* message) { BOOL status; wLogAppender* appender; @@ -185,7 +278,7 @@ BOOL WLog_WriteData(wLog* log, wLogMessage* message) return status; } -BOOL WLog_WriteImage(wLog* log, wLogMessage* message) +static BOOL WLog_WriteImage(wLog* log, wLogMessage* message) { BOOL status; wLogAppender* appender; @@ -217,7 +310,7 @@ BOOL WLog_WriteImage(wLog* log, wLogMessage* message) return status; } -BOOL WLog_WritePacket(wLog* log, wLogMessage* message) +static BOOL WLog_WritePacket(wLog* log, wLogMessage* message) { BOOL status; wLogAppender* appender; @@ -556,6 +649,7 @@ BOOL WLog_ParseFilters(void) if (GetEnvironmentVariableA(filter, env, nSize) == nSize - 1) res = WLog_AddStringLogFilters(env); + free(env); return res; } @@ -603,7 +697,7 @@ LONG WLog_GetFilterLogLevel(wLog* log) return log->FilterLevel; } -BOOL WLog_ParseName(wLog* log, LPCSTR name) +static BOOL WLog_ParseName(wLog* log, LPCSTR name) { char* p; int count; @@ -684,7 +778,6 @@ wLog* WLog_New(LPCSTR name, wLog* rootLogger) else { LPCSTR level = "WLOG_LEVEL"; - log->Level = WLOG_INFO; nSize = GetEnvironmentVariableA(level, NULL, 0); @@ -741,75 +834,15 @@ void WLog_Free(wLog* log) } } -static wLog* g_RootLog = NULL; - wLog* WLog_GetRoot(void) { - char* env; - DWORD nSize; - DWORD logAppenderType; - - if (!g_RootLog) - { - LPCSTR appender = "WLOG_APPENDER"; - - if (!(g_RootLog = WLog_New("", NULL))) - return NULL; - - g_RootLog->IsRoot = TRUE; - WLog_ParseFilters(); - logAppenderType = WLOG_APPENDER_CONSOLE; - nSize = GetEnvironmentVariableA(appender, NULL, 0); - - if (nSize) - { - env = (LPSTR) malloc(nSize); - - if (!env) - goto fail; - - if (GetEnvironmentVariableA(appender, env, nSize) != nSize - 1) - { - fprintf(stderr, "%s environment variable modified in my back", appender); - free(env); - goto fail; - } - - if (_stricmp(env, "CONSOLE") == 0) - logAppenderType = WLOG_APPENDER_CONSOLE; - else if (_stricmp(env, "FILE") == 0) - logAppenderType = WLOG_APPENDER_FILE; - else if (_stricmp(env, "BINARY") == 0) - logAppenderType = WLOG_APPENDER_BINARY; - -#ifdef HAVE_SYSLOG_H - else if (_stricmp(env, "SYSLOG") == 0) - logAppenderType = WLOG_APPENDER_SYSLOG; - -#endif /* HAVE_SYSLOG_H */ -#ifdef HAVE_JOURNALD_H - else if (_stricmp(env, "JOURNALD") == 0) - logAppenderType = WLOG_APPENDER_JOURNALD; - -#endif - else if (_stricmp(env, "UDP") == 0) - logAppenderType = WLOG_APPENDER_UDP; - - free(env); - } - - if (!WLog_SetLogAppenderType(g_RootLog, logAppenderType)) - goto fail; - } + if (!InitOnceExecuteOnce(&_WLogInitialized, WLog_InitializeRoot, NULL, NULL)) + return NULL; return g_RootLog; -fail: - free(g_RootLog); - g_RootLog = NULL; - return NULL; } -BOOL WLog_AddChild(wLog* parent, wLog* child) +static BOOL WLog_AddChild(wLog* parent, wLog* child) { if (parent->ChildrenCount >= parent->ChildrenSize) { @@ -848,7 +881,7 @@ BOOL WLog_AddChild(wLog* parent, wLog* child) return TRUE; } -wLog* WLog_FindChild(LPCSTR name) +static wLog* WLog_FindChild(LPCSTR name) { DWORD index; wLog* root; @@ -904,20 +937,6 @@ BOOL WLog_Init(void) BOOL WLog_Uninit(void) { - DWORD index; - wLog* child = NULL; - wLog* root = g_RootLog; - - if (!root) - return FALSE; - - for (index = 0; index < root->ChildrenCount; index++) - { - child = root->Children[index]; - WLog_Free(child); - } - - WLog_Free(root); - g_RootLog = NULL; return TRUE; } + diff --git a/winpr/tools/hash-cli/hash.c b/winpr/tools/hash-cli/hash.c index e295a7c..162696f 100644 --- a/winpr/tools/hash-cli/hash.c +++ b/winpr/tools/hash-cli/hash.c @@ -20,6 +20,7 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <errno.h> #include <winpr/ntlm.h> @@ -46,16 +47,16 @@ void usage_and_exit() { - printf("winpr-hash: NTLM hashing tool\n"); - printf("Usage: winpr-hash -u <username> -p <password> [-d <domain>] [-f <_default_,sam>] [-v <_1_,2>]\n"); - exit(1); + printf("winpr-hash: NTLM hashing tool\n"); + printf("Usage: winpr-hash -u <username> -p <password> [-d <domain>] [-f <_default_,sam>] [-v <_1_,2>]\n"); + exit(1); } int main(int argc, char* argv[]) { int index = 1; int format = 0; - int version = 1; + unsigned long version = 1; BYTE NtHash[16]; char* User = NULL; UINT32 UserLength; @@ -63,6 +64,7 @@ int main(int argc, char* argv[]) UINT32 DomainLength; char* Password = NULL; UINT32 PasswordLength; + errno = 0; while (index < argc) { @@ -112,11 +114,11 @@ int main(int argc, char* argv[]) usage_and_exit(); } - version = atoi(argv[index]); + version = strtoul(argv[index], NULL, 0); - if ((version != 1) && (version != 2)) + if (((version != 1) && (version != 2)) || (errno != 0)) { - printf("unkown version %d \n\n", version); + printf("unknown version %lu \n\n", version); usage_and_exit(); } } @@ -172,6 +174,7 @@ int main(int argc, char* argv[]) { for (index = 0; index < 16; index++) printf("%02"PRIx8"", NtHash[index]); + printf("\n"); } else if (format == 1) diff --git a/winpr/tools/makecert-cli/CMakeLists.txt b/winpr/tools/makecert-cli/CMakeLists.txt index 74afa09..48fda5b 100644 --- a/winpr/tools/makecert-cli/CMakeLists.txt +++ b/winpr/tools/makecert-cli/CMakeLists.txt @@ -42,7 +42,7 @@ add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) set(${MODULE_PREFIX}_LIBS winpr-tools) -target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS} winpr) set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Tools") diff --git a/winpr/tools/makecert-cli/winpr-makecert.1.in b/winpr/tools/makecert-cli/winpr-makecert.1.in index 302bc6a..57be0ff 100644 --- a/winpr/tools/makecert-cli/winpr-makecert.1.in +++ b/winpr/tools/makecert-cli/winpr-makecert.1.in @@ -1,7 +1,7 @@ .de URL \\$2 \(laURL: \\$1 \(ra\\$3 .. -.if \n[.g] .mso www.tmac)) +.if \n[.g] .mso www.tmac .TH winpr\-makecert 1 2017-01-11 "@FREERDP_VERSION_FULL@" "FreeRDP" .SH NAME winpr\-makecert \- A tool to create X.509 certificates. @@ -15,7 +15,7 @@ winpr\-makecert \- A tool to create X.509 certificates. [\fB-n\fP common_name] [\fB-y\fP years] [\fB-m\fP months] -[\fB-len\fP lenth] +[\fB-len\fP length] [\fB-#\fP serial] [\fB-a\fP { \fImd5\fP | \fIsha1\fP | \fIsha256\fP | \fIs384\fP | \fIsha512\fP }] [\fB-path\fP outputpath] diff --git a/winpr/tools/makecert/CMakeLists.txt b/winpr/tools/makecert/CMakeLists.txt index 89f7af9..a41cccd 100644 --- a/winpr/tools/makecert/CMakeLists.txt +++ b/winpr/tools/makecert/CMakeLists.txt @@ -37,7 +37,7 @@ if(OPENSSL_FOUND) else() # if ${OPENSSL_LIBRARIES} libssl and libcrypto is linked # therefor explicitly link against libcrypto - list(APPEND ${MODULE_PREFIX}_LIBS crypto) + list(APPEND ${MODULE_PREFIX}_LIBS ${OPENSSL_CRYPTO_LIBRARIES}) endif() endif() diff --git a/winpr/tools/makecert/makecert.c b/winpr/tools/makecert/makecert.c index a9efb35..48cd5cf 100644 --- a/winpr/tools/makecert/makecert.c +++ b/winpr/tools/makecert/makecert.c @@ -17,6 +17,8 @@ * limitations under the License. */ +#include <errno.h> + #include <winpr/crt.h> #include <winpr/path.h> #include <winpr/cmdline.h> @@ -441,6 +443,7 @@ static int makecert_context_parse_arguments(MAKECERT_CONTEXT* context, int argc, } arg = args; + errno = 0; do { @@ -515,17 +518,31 @@ static int makecert_context_parse_arguments(MAKECERT_CONTEXT* context, int argc, } CommandLineSwitchCase(arg, "y") { + long val; + if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)) continue; - context->duration_years = atoi(arg->Value); + val = strtol(arg->Value, NULL, 0); + + if ((errno != 0) || (val < 0) || (val > INT32_MAX)) + return -1; + + context->duration_years = strtol(arg->Value, NULL, 0); } CommandLineSwitchCase(arg, "m") { + long val; + if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)) continue; - context->duration_months = atoi(arg->Value); + val = strtol(arg->Value, NULL, 0); + + if ((errno != 0) || (val < 1) || (val > 12)) + return -1; + + context->duration_months = val; } CommandLineSwitchDefault(arg) { @@ -620,7 +637,7 @@ int makecert_context_output_certificate_file(MAKECERT_CONTEXT* context, char* pa printf("Using default export password \"password\"\n"); } -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) OpenSSL_add_all_algorithms(); OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); @@ -952,7 +969,7 @@ int makecert_context_process(MAKECERT_CONTEXT* context, int argc, char** argv) #ifdef WITH_OPENSSL int length; char* entry; - int key_length; + unsigned long key_length; long serial = 0; X509_NAME* name = NULL; const EVP_MD* md = NULL; @@ -1005,10 +1022,13 @@ int makecert_context_process(MAKECERT_CONTEXT* context, int argc, char** argv) if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) { - key_length = atoi(arg->Value); + key_length = strtoul(arg->Value, NULL, 0); + + if (errno != 0) + return -1; } -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) context->rsa = RSA_generate_key(key_length, RSA_F4, NULL, NULL); #else { @@ -1018,6 +1038,14 @@ int makecert_context_process(MAKECERT_CONTEXT* context, int argc, char** argv) if (!rsa) return -1; + context->rsa = RSA_new(); + + if (!context->rsa) + { + BN_clear_free(rsa); + return -1; + } + BN_set_word(rsa, RSA_F4); rc = RSA_generate_key_ex(context->rsa, key_length, rsa, NULL); BN_clear_free(rsa); @@ -1035,7 +1063,12 @@ int makecert_context_process(MAKECERT_CONTEXT* context, int argc, char** argv) arg = CommandLineFindArgumentA(args, "#"); if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) - serial = atoi(arg->Value); + { + serial = strtol(arg->Value, NULL, 0); + + if (errno != 0) + return -1; + } else serial = (long) GetTickCount64(); @@ -1043,7 +1076,7 @@ int makecert_context_process(MAKECERT_CONTEXT* context, int argc, char** argv) { ASN1_TIME* before; ASN1_TIME* after; -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) before = X509_get_notBefore(context->x509); after = X509_get_notAfter(context->x509); #else From b3e2df24dd3555e435e88f4f2d0a0840d17fd299 Mon Sep 17 00:00:00 2001 From: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Wed, 9 May 2018 21:59:57 +0200 Subject: [PATCH 02/11] debian/patches: Drop 0001-Fix-gstreamer-1.0-detection.patch and 0002-fix-nla-don-t-use-server-version.patch. Included in this Git snapshot (i.e. 2.0.0~rc2). --- .../0001-Fix-gstreamer-1.0-detection.patch | 25 ------------ ...002-fix-nla-don-t-use-server-version.patch | 38 ------------------- 2 files changed, 63 deletions(-) delete mode 100644 debian/patches/0001-Fix-gstreamer-1.0-detection.patch delete mode 100644 debian/patches/0002-fix-nla-don-t-use-server-version.patch diff --git a/debian/patches/0001-Fix-gstreamer-1.0-detection.patch b/debian/patches/0001-Fix-gstreamer-1.0-detection.patch deleted file mode 100644 index 2015a13..0000000 --- a/debian/patches/0001-Fix-gstreamer-1.0-detection.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 368989526c32cdf9d680a397fede3cb773fa2609 Mon Sep 17 00:00:00 2001 -From: Mike Gilbert <floppym@gentoo.org> -Date: Fri, 28 Jul 2017 16:31:41 -0400 -Subject: [PATCH] Fix gstreamer-1.0 detection - ---- - cmake/FindGStreamer_1_0.cmake | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/cmake/FindGStreamer_1_0.cmake b/cmake/FindGStreamer_1_0.cmake -index 3aa8fc6..6fbc0ec 100644 ---- a/cmake/FindGStreamer_1_0.cmake -+++ b/cmake/FindGStreamer_1_0.cmake -@@ -59,7 +59,7 @@ macro(FIND_GSTREAMER_COMPONENT _component_prefix _pkgconfig_name _library) - - string(REGEX MATCH "(.*)>=(.*)" _dummy "${_pkgconfig_name}") - if ("${CMAKE_MATCH_2}" STREQUAL "") -- pkg_check_modules(PC_${_component_prefix} "${_pkgconfig_name} >= ${GStreamer_FIND_VERSION}") -+ pkg_check_modules(PC_${_component_prefix} "${_pkgconfig_name} >= ${GSTREAMER_1_0_MINIMUM_VERSION}") - else () - pkg_check_modules(PC_${_component_prefix} ${_pkgconfig_name}) - endif () --- -2.1.4 - diff --git a/debian/patches/0002-fix-nla-don-t-use-server-version.patch b/debian/patches/0002-fix-nla-don-t-use-server-version.patch deleted file mode 100644 index 14b0043..0000000 --- a/debian/patches/0002-fix-nla-don-t-use-server-version.patch +++ /dev/null @@ -1,38 +0,0 @@ -From dd415320b78e6f703680aee64f9297909bd34f5e Mon Sep 17 00:00:00 2001 -From: Bernhard Miklautz <bernhard.miklautz@thincast.com> -Date: Wed, 14 Mar 2018 16:58:50 +0100 -Subject: [PATCH] fix nla: don't use server version - -based on upstream commit e7ae3f6babc881d893411a5ada9156abe8525b2f ---- - libfreerdp/core/nla.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c -index 63966f5..ab9bfb3 100644 ---- a/libfreerdp/core/nla.c -+++ b/libfreerdp/core/nla.c -@@ -1541,15 +1541,19 @@ BOOL nla_send(rdpNla* nla) - int nla_decode_ts_request(rdpNla* nla, wStream* s) - { - int length; -+ UINT32 version; - - /* TSRequest */ - if (!ber_read_sequence_tag(s, &length) || - !ber_read_contextual_tag(s, 0, &length, TRUE) || -- !ber_read_integer(s, &nla->version)) -+ !ber_read_integer(s, &version)) - { - return -1; - } - -+ if (version < nla->version) -+ nla->version = version; -+ - /* [1] negoTokens (NegoData) */ - if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE) - { --- -2.11.0 - From 2e22ca3c7f95c42a1ff412f2d47f688a12d79d52 Mon Sep 17 00:00:00 2001 From: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Wed, 9 May 2018 22:01:12 +0200 Subject: [PATCH 03/11] debian/patches: Drop 1001__Typo-Fixes.patch, 1002_macro-fix-in-man-pages.patch, 1003_fix-FTBFS-on-kFreeBSD.patch and 1004_FreeBSD-is-not-kFreeBSD.patch. All issues resolved upstream. --- debian/patches/1001_Typo-Fixes.patch | 58 ------------- .../patches/1002_macro-fix-in-man-pages.patch | 59 -------------- .../patches/1003_fix-FTBFS-on-kFreeBSD.patch | 81 ------------------- .../1004_FreeBSD-is-not-kFreeBSD.patch | 30 ------- debian/patches/series | 6 -- 5 files changed, 234 deletions(-) delete mode 100644 debian/patches/1001_Typo-Fixes.patch delete mode 100644 debian/patches/1002_macro-fix-in-man-pages.patch delete mode 100644 debian/patches/1003_fix-FTBFS-on-kFreeBSD.patch delete mode 100644 debian/patches/1004_FreeBSD-is-not-kFreeBSD.patch delete mode 100644 debian/patches/series diff --git a/debian/patches/1001_Typo-Fixes.patch b/debian/patches/1001_Typo-Fixes.patch deleted file mode 100644 index aead7ab..0000000 --- a/debian/patches/1001_Typo-Fixes.patch +++ /dev/null @@ -1,58 +0,0 @@ -Description: Fix some error msg typos -Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> - ---- a/ChangeLog -+++ b/ChangeLog -@@ -11638,7 +11638,7 @@ - - 2015-03-16 10:25:31 +0100 Armin Novak (b39940e0a) - -- * Added ignore unkown keyword flag to detection. -+ * Added ignore unknown keyword flag to detection. - - 2015-03-16 10:15:37 +0100 Armin Novak (c380fb352) - ---- a/channels/rdpgfx/client/rdpgfx_main.c -+++ b/channels/rdpgfx/client/rdpgfx_main.c -@@ -1684,7 +1684,7 @@ - if (!gfx->log) - { - free(gfx); -- WLog_ERR(TAG, "Failed to aquire reference to WLog %s", TAG); -+ WLog_ERR(TAG, "Failed to acquire reference to WLog %s", TAG); - return ERROR_INTERNAL_ERROR; - } - ---- a/winpr/libwinpr/comm/comm_serial_sys.c -+++ b/winpr/libwinpr/comm/comm_serial_sys.c -@@ -1209,7 +1209,7 @@ - if (ioctl(pComm->fd, TIOCGICOUNT, ¤tCounters) < 0) - { - CommLog_Print(WLOG_WARN, "TIOCGICOUNT ioctl failed, errno=[%d] %s.", errno, strerror(errno)); -- CommLog_Print(WLOG_WARN, " coult not read counters."); -+ CommLog_Print(WLOG_WARN, " could not read counters."); - - if (pComm->permissive) - { ---- a/winpr/tools/hash-cli/hash.c -+++ b/winpr/tools/hash-cli/hash.c -@@ -116,7 +116,7 @@ - - if ((version != 1) && (version != 2)) - { -- printf("unkown version %d \n\n", version); -+ printf("unknown version %d \n\n", version); - usage_and_exit(); - } - } ---- a/winpr/tools/makecert-cli/winpr-makecert.1.in -+++ b/winpr/tools/makecert-cli/winpr-makecert.1.in -@@ -15,7 +15,7 @@ - [\fB-n\fP common_name] - [\fB-y\fP years] - [\fB-m\fP months] --[\fB-len\fP lenth] -+[\fB-len\fP length] - [\fB-#\fP serial] - [\fB-a\fP { \fImd5\fP | \fIsha1\fP | \fIsha256\fP | \fIs384\fP | \fIsha512\fP }] - [\fB-path\fP outputpath] diff --git a/debian/patches/1002_macro-fix-in-man-pages.patch b/debian/patches/1002_macro-fix-in-man-pages.patch deleted file mode 100644 index 9ff6967..0000000 --- a/debian/patches/1002_macro-fix-in-man-pages.patch +++ /dev/null @@ -1,59 +0,0 @@ -Description: Fix "warning: can't find macro file `www.tmac))'" -Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> - ---- a/server/shadow/freerdp-shadow-cli.1.in -+++ b/server/shadow/freerdp-shadow-cli.1.in -@@ -1,7 +1,7 @@ - .de URL - \\$2 \(laURL: \\$1 \(ra\\$3 - .. --.if \n[.g] .mso www.tmac)) -+.if \n[.g] .mso www.tmac - .TH freerdp\-shadow\-cli 1 2017-01-12 "@FREERDP_VERSION_FULL@" "FreeRDP" - .SH NAME - freerdp\-shadow\-cli \- A utility for sharing a X display via RDP. -@@ -49,14 +49,14 @@ - Clients may interact without prompt. - .IP /sec:<rdp|tls|nla|ext> - Force a specific protocol security --.IP -sec-rdp (default:on) --Disable RDP security --.IP -sec-tls (default:on) --Disable TLS protocol security --.IP -sec-nla (default:on) --Disable NLA protocol security --.IP +sec-ext (default:off) --Use NLA extended protocol security -+.IP -sec-rdp -+Disable RDP security (default:on) -+.IP -sec-tls -+Disable TLS protocol security (default:on) -+.IP -sec-nla -+Disable NLA protocol security (default:on) -+.IP +sec-ext -+Use NLA extended protocol security (default:off) - .IP /sam-file:<file> - NTLM SAM file for NLA authentication - .IP /version ---- a/winpr/tools/makecert-cli/winpr-makecert.1.in -+++ b/winpr/tools/makecert-cli/winpr-makecert.1.in -@@ -1,7 +1,7 @@ - .de URL - \\$2 \(laURL: \\$1 \(ra\\$3 - .. --.if \n[.g] .mso www.tmac)) -+.if \n[.g] .mso www.tmac - .TH winpr\-makecert 1 2017-01-11 "@FREERDP_VERSION_FULL@" "FreeRDP" - .SH NAME - winpr\-makecert \- A tool to create X.509 certificates. ---- a/client/Wayland/wlfreerdp.1.in -+++ b/client/Wayland/wlfreerdp.1.in -@@ -1,7 +1,7 @@ - .de URL - \\$2 \(laURL: \\$1 \(ra\\$3 - .. --.if \n[.g] .mso www.tmac)) -+.if \n[.g] .mso www.tmac - .TH wlfreerdp 1 2017-01-12 "@FREERDP_VERSION_FULL@" "FreeRDP" - .SH NAME - wlfreerdp \- FreeRDP wayland client diff --git a/debian/patches/1003_fix-FTBFS-on-kFreeBSD.patch b/debian/patches/1003_fix-FTBFS-on-kFreeBSD.patch deleted file mode 100644 index d06a20f..0000000 --- a/debian/patches/1003_fix-FTBFS-on-kFreeBSD.patch +++ /dev/null @@ -1,81 +0,0 @@ -Description: Handle GNU/kFreeBSD the same way as other BSD variants -Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> - -Index: freerdp2-2.0.0~git20170725.1.1648deb+dfsg1/winpr/libwinpr/file/file.c -=================================================================== ---- freerdp2-2.0.0~git20170725.1.1648deb+dfsg1.orig/winpr/libwinpr/file/file.c -+++ freerdp2-2.0.0~git20170725.1.1648deb+dfsg1/winpr/libwinpr/file/file.c -@@ -23,6 +23,10 @@ - #include "config.h" - #endif /* HAVE_CONFIG_H */ - -+#if defined(__FreeBSD_kernel__) && defined(__GLIBC__) -+#define _GNU_SOURCE -+#endif -+ - #include <winpr/crt.h> - #include <winpr/file.h> - -@@ -384,7 +388,7 @@ static BOOL FileSetFileTime(HANDLE hFile - const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime) - { - int rc; --#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) -+#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) - struct stat buf; - /* OpenBSD, NetBSD and DragonflyBSD support POSIX futimens */ - struct timeval timevals[2]; -@@ -396,7 +400,7 @@ static BOOL FileSetFileTime(HANDLE hFile - if (!hFile) - return FALSE; - --#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) -+#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) - rc = fstat(fileno(pFile->fp), &buf); - - if (rc < 0) -@@ -406,7 +410,7 @@ static BOOL FileSetFileTime(HANDLE hFile - - if (!lpLastAccessTime) - { --#if defined(__FreeBSD__) || defined(__APPLE__) -+#if defined(__FreeBSD__) || defined(__APPLE__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) - timevals[0].tv_sec = buf.st_atime; - #ifdef _POSIX_SOURCE - TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atim); -@@ -424,7 +428,7 @@ static BOOL FileSetFileTime(HANDLE hFile - else - { - UINT64 tmp = FileTimeToUS(lpLastAccessTime); --#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) -+#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) - timevals[0].tv_sec = tmp / 1000000ULL; - timevals[0].tv_usec = tmp % 1000000ULL; - #else -@@ -435,7 +439,7 @@ static BOOL FileSetFileTime(HANDLE hFile - - if (!lpLastWriteTime) - { --#if defined(__FreeBSD__) || defined(__APPLE__) -+#if defined(__FreeBSD__) || defined(__APPLE__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) - timevals[1].tv_sec = buf.st_mtime; - #ifdef _POSIX_SOURCE - TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtim); -@@ -453,7 +457,7 @@ static BOOL FileSetFileTime(HANDLE hFile - else - { - UINT64 tmp = FileTimeToUS(lpLastWriteTime); --#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) -+#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) - timevals[1].tv_sec = tmp / 1000000ULL; - timevals[1].tv_usec = tmp % 1000000ULL; - #else -@@ -463,7 +467,7 @@ static BOOL FileSetFileTime(HANDLE hFile - } - - // TODO: Creation time can not be handled! --#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) -+#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) - rc = utimes(pFile->lpFileName, timevals); - #else - rc = futimens(fileno(pFile->fp), times); diff --git a/debian/patches/1004_FreeBSD-is-not-kFreeBSD.patch b/debian/patches/1004_FreeBSD-is-not-kFreeBSD.patch deleted file mode 100644 index 5918773..0000000 --- a/debian/patches/1004_FreeBSD-is-not-kFreeBSD.patch +++ /dev/null @@ -1,30 +0,0 @@ -Description: GNU/kFreeBSD != FreeBSD -Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> - -Index: freerdp2-2.0.0~git20170725.1.1648deb+dfsg1/CMakeLists.txt -=================================================================== ---- freerdp2-2.0.0~git20170725.1.1648deb+dfsg1.orig/CMakeLists.txt -+++ freerdp2-2.0.0~git20170725.1.1648deb+dfsg1/CMakeLists.txt -@@ -158,6 +158,9 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "BSD") - if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - set(FREEBSD TRUE) - endif() -+ if(${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD") -+ set(KFREEBSD TRUE) -+ endif() - if(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") - set(OPENBSD TRUE) - endif() -Index: freerdp2-2.0.0~git20170725.1.1648deb+dfsg1/winpr/libwinpr/utils/CMakeLists.txt -=================================================================== ---- freerdp2-2.0.0~git20170725.1.1648deb+dfsg1.orig/winpr/libwinpr/utils/CMakeLists.txt -+++ freerdp2-2.0.0~git20170725.1.1648deb+dfsg1/winpr/libwinpr/utils/CMakeLists.txt -@@ -141,7 +141,7 @@ if(UNIX) - winpr_library_add(m) - endif() - --if(FREEBSD) -+if((FREEBSD) AND (NOT KFREEBSD)) - winpr_library_add(execinfo) - endif() - diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index 5b68f07..0000000 --- a/debian/patches/series +++ /dev/null @@ -1,6 +0,0 @@ -0001-Fix-gstreamer-1.0-detection.patch -0002-fix-nla-don-t-use-server-version.patch -1001_Typo-Fixes.patch -1002_macro-fix-in-man-pages.patch -1003_fix-FTBFS-on-kFreeBSD.patch -1004_FreeBSD-is-not-kFreeBSD.patch From c15a3e082b6180a1a45ddd3e3eca062e9accece4 Mon Sep 17 00:00:00 2001 From: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Wed, 9 May 2018 22:03:28 +0200 Subject: [PATCH 04/11] debian/control: Bump Standards-Version: to 4.1.4. No changes needed. --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index cf4b367..1e91ce4 100644 --- a/debian/control +++ b/debian/control @@ -43,7 +43,7 @@ Build-Depends: uuid-dev, xmlto, xsltproc, -Standards-Version: 4.1.3 +Standards-Version: 4.1.4 Homepage: http://www.freerdp.com/ Vcs-Browser: https://salsa.debian.org/debian-remote-team/freerdp2 Vcs-Git: https://salsa.debian.org/debian-remote-team/freerdp2.git From 6853d4636f9a66d64375468743a69ccbfaa2929f Mon Sep 17 00:00:00 2001 From: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Wed, 9 May 2018 22:15:38 +0200 Subject: [PATCH 05/11] debian/*.symbols: Update symbols (libfreerdp-client2-2, libfreerdp2-2 and libwinpr2-2). --- debian/libfreerdp-client2-2.symbols | 4 ++++ debian/libfreerdp2-2.symbols | 13 +++++++++++++ debian/libwinpr2-2.symbols | 10 ++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/debian/libfreerdp-client2-2.symbols b/debian/libfreerdp-client2-2.symbols index b92a65b..6ef7b10 100644 --- a/debian/libfreerdp-client2-2.symbols +++ b/debian/libfreerdp-client2-2.symbols @@ -24,6 +24,7 @@ libfreerdp-client2.so.2 libfreerdp-client2-2 #MINVER# freerdp_client_populate_settings_from_rdp_file@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_client_print_buildconfig@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_client_print_command_line_help@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + freerdp_client_print_command_line_help_ex@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 freerdp_client_print_version@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_client_rdp_file_free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_client_rdp_file_get_integer_option@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 @@ -32,6 +33,7 @@ libfreerdp-client2.so.2 libfreerdp-client2-2 #MINVER# freerdp_client_rdp_file_set_integer_option@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_client_rdp_file_set_string_option@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_client_settings_command_line_status_print@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + freerdp_client_settings_command_line_status_print_ex@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 freerdp_client_settings_parse_assistance_file@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_client_settings_parse_command_line@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_client_settings_parse_command_line_arguments@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 @@ -46,3 +48,5 @@ libfreerdp-client2.so.2 libfreerdp-client2-2 #MINVER# freerdp_parse_hostname@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_parse_username@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_set_connection_type@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + mappedGeometryRef@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + mappedGeometryUnref@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 diff --git a/debian/libfreerdp2-2.symbols b/debian/libfreerdp2-2.symbols index 777d57b..16e7d7d 100644 --- a/debian/libfreerdp2-2.symbols +++ b/debian/libfreerdp2-2.symbols @@ -333,6 +333,15 @@ libfreerdp2.so.2 libfreerdp2-2 #MINVER# gdi_resize@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 gdi_resize_ex@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 gdi_rop3_code@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + gdi_rop3_code_string@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + gdi_rop3_string@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + gdi_send_suppress_output@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + gdi_video_control_init@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + gdi_video_control_uninit@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + gdi_video_data_init@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + gdi_video_data_uninit@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + gdi_video_geometry_init@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + gdi_video_geometry_uninit@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 getChannelError@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 getChannelErrorDescription@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 getChannelErrorEventHandle@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 @@ -514,6 +523,10 @@ libfreerdp2.so.2 libfreerdp2-2 #MINVER# xcrush_context_new@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 xcrush_context_reset@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 xcrush_decompress@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + yuv_context_decode@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + yuv_context_free@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + yuv_context_new@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 + yuv_context_reset@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 zgfx_compress@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 zgfx_compress_to_stream@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 zgfx_context_free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 diff --git a/debian/libwinpr2-2.symbols b/debian/libwinpr2-2.symbols index 43ee5af..df98827 100644 --- a/debian/libwinpr2-2.symbols +++ b/debian/libwinpr2-2.symbols @@ -637,7 +637,7 @@ libwinpr2.so.2 libwinpr2-2 #MINVER# PCSC_GetOpenCardNameA@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 PCSC_GetOpenCardNameW@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 PCSC_SCardAccessStartedEvent@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 - PCSC_SCardAddReaderName@Base 2.0.0~git20170725.1.1648deb+dfsg1 +#MISSING: 2.0.0~git20180411.1.7a7b1802+dfsg1# PCSC_SCardAddReaderName@Base 2.0.0~git20170725.1.1648deb+dfsg1 PCSC_SCardAddReaderToGroupA@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 PCSC_SCardAddReaderToGroupW@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 PCSC_SCardAudit@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 @@ -999,7 +999,7 @@ libwinpr2.so.2 libwinpr2-2 #MINVER# RpcStringFreeW@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 RpcTestCancel@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 SCardAccessStartedEvent@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 - SCardAddReaderName@Base 2.0.0~git20170725.1.1648deb+dfsg1 +#MISSING: 2.0.0~git20180411.1.7a7b1802+dfsg1# SCardAddReaderName@Base 2.0.0~git20170725.1.1648deb+dfsg1 SCardAddReaderToGroupA@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 SCardAddReaderToGroupW@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 SCardAudit@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 @@ -1443,6 +1443,7 @@ libwinpr2.so.2 libwinpr2-2 #MINVER# sspi_SecBufferAlloc@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 sspi_SecBufferFree@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 sspi_SetAuthIdentity@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + sspi_SetAuthIdentityWithUnicodePassword@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 strtok_s@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 wcstok_s@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 winpr_BinToHexString@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 @@ -1469,13 +1470,16 @@ libwinpr2.so.2 libwinpr2-2 #MINVER# winpr_CreateThreadpoolWork@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_DeleteSynchronizationBarrier@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_Digest@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + winpr_Digest_Allow_FIPS@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 winpr_Digest_Final@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 winpr_Digest_Free@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_Digest_Init@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + winpr_Digest_Init_Allow_FIPS@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 winpr_Digest_New@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_Digest_Update@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 winpr_DisassociateCurrentThreadFromCallback@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_EnterSynchronizationBarrier@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 + winpr_FIPSMode@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 winpr_FreeLibraryWhenCallbackReturns@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_GetTickCount64@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_HMAC@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 @@ -1497,10 +1501,12 @@ libwinpr2.so.2 libwinpr2-2 #MINVER# winpr_RAND_pseudo@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 winpr_RC4_Free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 winpr_RC4_New@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + winpr_RC4_New_Allow_FIPS@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 winpr_RC4_Update@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 winpr_ReleaseMutexWhenCallbackReturns@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_ReleaseSemaphoreWhenCallbackReturns@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_SetEventWhenCallbackReturns@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 + winpr_SetThreadpoolCallbackCleanupGroup@Base 2.0.0~git20180411.1.7a7b1802+dfsg1 winpr_SetThreadpoolThreadMaximum@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_SetThreadpoolThreadMinimum@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 winpr_SetThreadpoolTimer@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 From 30573d58e099def8e73709cd52cb01a166e092f7 Mon Sep 17 00:00:00 2001 From: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Wed, 9 May 2018 22:15:58 +0200 Subject: [PATCH 06/11] debian/copyright.in: Update autogenerated copyright.in file. --- debian/copyright.in | 1083 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 924 insertions(+), 159 deletions(-) diff --git a/debian/copyright.in b/debian/copyright.in index dc14735..67627f5 100644 --- a/debian/copyright.in +++ b/debian/copyright.in @@ -4,22 +4,81 @@ Upstream-Contact: FIXME Source: FIXME Disclaimer: Autogenerated by CDBS -Files: channels/client/addin.h +Files: channels/CMakeLists.txt + channels/audin/CMakeLists.txt + channels/audin/client/CMakeLists.txt + channels/audin/client/alsa/CMakeLists.txt + channels/audin/client/pulse/CMakeLists.txt + channels/audin/client/winmm/CMakeLists.txt + channels/audin/server/CMakeLists.txt + channels/client/CMakeLists.txt + channels/client/addin.h channels/client/tables.h + channels/cliprdr/CMakeLists.txt + channels/cliprdr/client/CMakeLists.txt + channels/cliprdr/server/CMakeLists.txt channels/cliprdr/server/cliprdr_main.h + channels/disp/CMakeLists.txt + channels/disp/client/CMakeLists.txt + channels/drdynvc/CMakeLists.txt + channels/drdynvc/client/CMakeLists.txt + channels/drdynvc/server/CMakeLists.txt channels/drdynvc/server/drdynvc_main.h + channels/drive/CMakeLists.txt + channels/drive/client/CMakeLists.txt + channels/echo/CMakeLists.txt + channels/echo/client/CMakeLists.txt + channels/echo/server/CMakeLists.txt + channels/encomsp/CMakeLists.txt + channels/encomsp/client/CMakeLists.txt + channels/encomsp/server/CMakeLists.txt channels/encomsp/server/encomsp_main.h + channels/parallel/CMakeLists.txt + channels/parallel/client/CMakeLists.txt + channels/printer/CMakeLists.txt + channels/printer/client/CMakeLists.txt + channels/rail/CMakeLists.txt + channels/rail/client/CMakeLists.txt + channels/rdpdr/CMakeLists.txt + channels/rdpdr/server/CMakeLists.txt + channels/rdpei/CMakeLists.txt + channels/rdpei/client/CMakeLists.txt channels/rdpei/client/rdpei_main.h + channels/rdpgfx/CMakeLists.txt + channels/rdpgfx/client/CMakeLists.txt channels/rdpgfx/client/rdpgfx_main.h + channels/rdpsnd/CMakeLists.txt + channels/rdpsnd/client/CMakeLists.txt + channels/rdpsnd/client/alsa/CMakeLists.txt + channels/rdpsnd/client/pulse/CMakeLists.txt + channels/rdpsnd/client/winmm/CMakeLists.txt + channels/rdpsnd/server/CMakeLists.txt + channels/remdesk/CMakeLists.txt + channels/remdesk/client/CMakeLists.txt + channels/remdesk/server/CMakeLists.txt channels/remdesk/server/remdesk_main.h + channels/serial/CMakeLists.txt + channels/serial/client/CMakeLists.txt + channels/server/CMakeLists.txt + channels/smartcard/CMakeLists.txt + channels/smartcard/client/CMakeLists.txt + channels/tsmf/CMakeLists.txt + channels/tsmf/client/alsa/CMakeLists.txt + channels/tsmf/client/ffmpeg/CMakeLists.txt + channels/tsmf/client/pulse/CMakeLists.txt + channels/urbdrc/CMakeLists.txt + client/CMakeLists.txt + client/DirectFB/CMakeLists.txt client/DirectFB/df_event.c client/DirectFB/df_event.h client/DirectFB/df_graphics.c client/DirectFB/df_graphics.h client/DirectFB/dfreerdp.c client/DirectFB/dfreerdp.h + client/Sample/CMakeLists.txt client/Wayland/wlf_channels.c client/Wayland/wlf_channels.h + client/X11/cli/CMakeLists.txt client/X11/xf_channels.c client/X11/xf_channels.h client/X11/xf_client.h @@ -28,14 +87,15 @@ Files: channels/client/addin.h client/X11/xf_graphics.h client/X11/xf_keyboard.c client/X11/xf_keyboard.h - client/X11/xf_monitor.c client/X11/xf_monitor.h client/X11/xf_rail.c client/X11/xf_rail.h client/X11/xf_window.h + client/common/CMakeLists.txt client/common/client.c client/common/compatibility.h client/common/file.c + cmake/FindPixman.cmake include/freerdp/addin.h include/freerdp/altsec.h include/freerdp/assistance.h @@ -93,6 +153,8 @@ Files: channels/client/addin.h include/freerdp/update.h include/freerdp/utils/pcap.h include/freerdp/window.h + libfreerdp/CMakeLists.txt + libfreerdp/cache/CMakeLists.txt libfreerdp/cache/bitmap.c libfreerdp/cache/brush.c libfreerdp/cache/cache.c @@ -103,10 +165,11 @@ Files: channels/client/addin.h libfreerdp/cache/pointer.c libfreerdp/codec/audio.c libfreerdp/codec/mppc.c - libfreerdp/codec/ncrush.c libfreerdp/codec/progressive.c + libfreerdp/common/CMakeLists.txt libfreerdp/common/addin.c libfreerdp/common/assistance.c + libfreerdp/core/CMakeLists.txt libfreerdp/core/activation.c libfreerdp/core/activation.h libfreerdp/core/bulk.c @@ -153,14 +216,17 @@ Files: channels/client/addin.h libfreerdp/core/tpkt.c libfreerdp/core/tpkt.h libfreerdp/core/update.h + libfreerdp/crypto/CMakeLists.txt libfreerdp/crypto/base64.c libfreerdp/crypto/ber.c libfreerdp/crypto/crypto.c libfreerdp/crypto/er.c libfreerdp/crypto/per.c libfreerdp/crypto/tls.c + libfreerdp/gdi/CMakeLists.txt libfreerdp/gdi/gdi.h libfreerdp/gdi/pen.c + libfreerdp/locale/CMakeLists.txt libfreerdp/locale/keyboard.c libfreerdp/locale/keyboard_layout.c libfreerdp/locale/keyboard_sun.c @@ -172,9 +238,12 @@ Files: channels/client/addin.h libfreerdp/locale/liblocale.h libfreerdp/locale/locale.c libfreerdp/locale/xkb_layout_ids.h + libfreerdp/utils/CMakeLists.txt libfreerdp/utils/pcap.c + rdtk/CMakeLists.txt rdtk/include/rdtk/api.h rdtk/include/rdtk/rdtk.h + rdtk/librdtk/CMakeLists.txt rdtk/librdtk/rdtk_button.c rdtk/librdtk/rdtk_button.h rdtk/librdtk/rdtk_engine.c @@ -191,15 +260,21 @@ Files: channels/client/addin.h rdtk/librdtk/rdtk_surface.h rdtk/librdtk/rdtk_text_field.c rdtk/librdtk/rdtk_text_field.h + rdtk/sample/CMakeLists.txt rdtk/sample/rdtk_x11.c - scripts/TimeZones.cs - scripts/WindowsZones.cs + scripts/TimeZones.csx + scripts/WindowsZones.csx scripts/xkb.pl + server/CMakeLists.txt + server/Mac/CMakeLists.txt server/Mac/mf_rdpsnd.h + server/Sample/CMakeLists.txt server/Sample/sf_audin.h server/Sample/sf_encomsp.h server/Sample/sf_rdpsnd.h server/Sample/sfreerdp.h + server/Windows/CMakeLists.txt + server/Windows/cli/CMakeLists.txt server/Windows/cli/wfreerdp.c server/Windows/cli/wfreerdp.h server/Windows/wf_input.c @@ -209,7 +284,9 @@ Files: channels/client/addin.h server/Windows/wf_settings.c server/Windows/wf_settings.h server/Windows/wf_update.h + server/common/CMakeLists.txt server/common/server.c + server/shadow/CMakeLists.txt server/shadow/Mac/mac_shadow.c server/shadow/Mac/mac_shadow.h server/shadow/Win/win_dxgi.c @@ -242,6 +319,9 @@ Files: channels/client/addin.h server/shadow/shadow_subsystem.h server/shadow/shadow_surface.c server/shadow/shadow_surface.h + third-party/CMakeLists.txt + winpr/CMakeLists.txt + winpr/include/CMakeLists.txt winpr/include/winpr/asn1.h winpr/include/winpr/bcrypt.h winpr/include/winpr/bitstream.h @@ -292,44 +372,72 @@ Files: channels/client/addin.h winpr/include/winpr/winhttp.h winpr/include/winpr/winpr.h winpr/include/winpr/winsock.h + winpr/include/winpr/wtypes.h.in + winpr/libwinpr/CMakeLists.txt + winpr/libwinpr/asn1/CMakeLists.txt winpr/libwinpr/asn1/asn1.c + winpr/libwinpr/bcrypt/CMakeLists.txt winpr/libwinpr/bcrypt/bcrypt.c + winpr/libwinpr/clipboard/CMakeLists.txt winpr/libwinpr/clipboard/clipboard.c winpr/libwinpr/clipboard/clipboard.h winpr/libwinpr/clipboard/synthetic.c + winpr/libwinpr/com/CMakeLists.txt winpr/libwinpr/com/com.c + winpr/libwinpr/comm/CMakeLists.txt + winpr/libwinpr/credentials/CMakeLists.txt winpr/libwinpr/credentials/credentials.c + winpr/libwinpr/credui/CMakeLists.txt winpr/libwinpr/credui/credui.c + winpr/libwinpr/crt/CMakeLists.txt winpr/libwinpr/crt/alignment.c winpr/libwinpr/crt/buffer.c winpr/libwinpr/crt/conversion.c winpr/libwinpr/crt/memory.c winpr/libwinpr/crt/string.c winpr/libwinpr/crt/unicode.c + winpr/libwinpr/crypto/CMakeLists.txt winpr/libwinpr/crypto/cert.c winpr/libwinpr/crypto/cipher.c winpr/libwinpr/crypto/crypto.c winpr/libwinpr/crypto/crypto.h winpr/libwinpr/crypto/hash.c winpr/libwinpr/crypto/rand.c + winpr/libwinpr/dsparse/CMakeLists.txt winpr/libwinpr/dsparse/dsparse.c + winpr/libwinpr/environment/CMakeLists.txt + winpr/libwinpr/error/CMakeLists.txt winpr/libwinpr/error/error.c + winpr/libwinpr/file/CMakeLists.txt winpr/libwinpr/file/pattern.c winpr/libwinpr/handle/handle.h + winpr/libwinpr/heap/CMakeLists.txt winpr/libwinpr/heap/heap.c + winpr/libwinpr/input/CMakeLists.txt winpr/libwinpr/input/keycode.c winpr/libwinpr/input/scancode.c winpr/libwinpr/input/virtualkey.c + winpr/libwinpr/interlocked/CMakeLists.txt winpr/libwinpr/interlocked/interlocked.c + winpr/libwinpr/io/CMakeLists.txt winpr/libwinpr/io/device.c winpr/libwinpr/io/io.c winpr/libwinpr/io/io.h + winpr/libwinpr/library/CMakeLists.txt winpr/libwinpr/library/library.c + winpr/libwinpr/library/test/TestLibraryA/CMakeLists.txt + winpr/libwinpr/library/test/TestLibraryB/CMakeLists.txt + winpr/libwinpr/locale/CMakeLists.txt winpr/libwinpr/locale/locale.c + winpr/libwinpr/memory/CMakeLists.txt winpr/libwinpr/memory/memory.c winpr/libwinpr/memory/memory.h + winpr/libwinpr/nt/CMakeLists.txt + winpr/libwinpr/path/CMakeLists.txt winpr/libwinpr/path/path.c + winpr/libwinpr/pipe/CMakeLists.txt winpr/libwinpr/pipe/pipe.h + winpr/libwinpr/pool/CMakeLists.txt winpr/libwinpr/pool/callback.c winpr/libwinpr/pool/callback_cleanup.c winpr/libwinpr/pool/cleanup_group.c @@ -339,9 +447,11 @@ Files: channels/client/addin.h winpr/libwinpr/pool/synch.c winpr/libwinpr/pool/timer.c winpr/libwinpr/pool/work.c + winpr/libwinpr/registry/CMakeLists.txt winpr/libwinpr/registry/registry.c winpr/libwinpr/registry/registry_reg.c winpr/libwinpr/registry/registry_reg.h + winpr/libwinpr/rpc/CMakeLists.txt winpr/libwinpr/rpc/midl.c winpr/libwinpr/rpc/ndr.c winpr/libwinpr/rpc/ndr_array.c @@ -363,8 +473,10 @@ Files: channels/client/addin.h winpr/libwinpr/rpc/ndr_union.c winpr/libwinpr/rpc/ndr_union.h winpr/libwinpr/rpc/rpc.c + winpr/libwinpr/security/CMakeLists.txt winpr/libwinpr/security/security.c winpr/libwinpr/security/security.h + winpr/libwinpr/smartcard/CMakeLists.txt winpr/libwinpr/smartcard/smartcard.c winpr/libwinpr/smartcard/smartcard.h winpr/libwinpr/smartcard/smartcard_inspect.c @@ -373,6 +485,7 @@ Files: channels/client/addin.h winpr/libwinpr/smartcard/smartcard_pcsc.h winpr/libwinpr/smartcard/smartcard_winscard.c winpr/libwinpr/smartcard/smartcard_winscard.h + winpr/libwinpr/sspi/CMakeLists.txt winpr/libwinpr/sspi/CredSSP/credssp.c winpr/libwinpr/sspi/CredSSP/credssp.h winpr/libwinpr/sspi/NTLM/ntlm.c @@ -383,7 +496,6 @@ Files: channels/client/addin.h winpr/libwinpr/sspi/NTLM/ntlm_compute.h winpr/libwinpr/sspi/NTLM/ntlm_message.c winpr/libwinpr/sspi/NTLM/ntlm_message.h - winpr/libwinpr/sspi/Negotiate/negotiate.c winpr/libwinpr/sspi/Schannel/schannel.c winpr/libwinpr/sspi/Schannel/schannel.h winpr/libwinpr/sspi/Schannel/schannel_openssl.c @@ -391,9 +503,10 @@ Files: channels/client/addin.h winpr/libwinpr/sspi/sspi.c winpr/libwinpr/sspi/sspi.h winpr/libwinpr/sspi/sspi_export.c - winpr/libwinpr/sspi/sspi_winpr.c winpr/libwinpr/sspi/sspi_winpr.h + winpr/libwinpr/sspicli/CMakeLists.txt winpr/libwinpr/sspicli/sspicli.c + winpr/libwinpr/synch/CMakeLists.txt winpr/libwinpr/synch/address.c winpr/libwinpr/synch/condition.c winpr/libwinpr/synch/mutex.c @@ -402,10 +515,14 @@ Files: channels/client/addin.h winpr/libwinpr/synch/srw.c winpr/libwinpr/synch/synch.h winpr/libwinpr/synch/timer.c + winpr/libwinpr/sysinfo/CMakeLists.txt + winpr/libwinpr/thread/CMakeLists.txt winpr/libwinpr/thread/argv.c winpr/libwinpr/thread/processor.c winpr/libwinpr/thread/tls.c + winpr/libwinpr/timezone/CMakeLists.txt winpr/libwinpr/timezone/timezone.c + winpr/libwinpr/utils/CMakeLists.txt winpr/libwinpr/utils/cmdline.c winpr/libwinpr/utils/collections/ArrayList.c winpr/libwinpr/utils/collections/BipBuffer.c @@ -448,14 +565,20 @@ Files: channels/client/addin.h winpr/libwinpr/utils/wlog/TextMessage.c winpr/libwinpr/utils/wlog/wlog.c winpr/libwinpr/utils/wlog/wlog.h + winpr/libwinpr/winhttp/CMakeLists.txt winpr/libwinpr/winhttp/winhttp.c + winpr/libwinpr/winsock/CMakeLists.txt winpr/libwinpr/winsock/winsock.c + winpr/libwinpr/wnd/CMakeLists.txt winpr/libwinpr/wnd/wnd.c winpr/libwinpr/wnd/wnd.h + winpr/libwinpr/wtsapi/CMakeLists.txt winpr/libwinpr/wtsapi/wtsapi_win32.c winpr/libwinpr/wtsapi/wtsapi_win32.h + winpr/tools/hash-cli/CMakeLists.txt winpr/tools/hash-cli/hash.c winpr/tools/makecert-cli/main.c + winpr/tools/makecert/CMakeLists.txt winpr/tools/makecert/makecert.c Copyright: 2009, Marc-Andre Moreau <marcandre.moreau@gmail.com> 2009-2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> @@ -475,13 +598,137 @@ Copyright: 2009, Marc-Andre Moreau <marcandre.moreau@gmail.com> License: Apache (v2.0) FIXME -Files: client/X11/generate_argument_docbook.c +Files: CMakeCPack.cmake + CMakeCPackOptions.cmake.in + ChangeLog + README + buildflags.h.in + channels/audin/ChannelOptions.cmake + channels/cliprdr/ChannelOptions.cmake + channels/disp/ChannelOptions.cmake + channels/drdynvc/ChannelOptions.cmake + channels/drive/ChannelOptions.cmake + channels/echo/ChannelOptions.cmake + channels/encomsp/ChannelOptions.cmake + channels/geometry/ChannelOptions.cmake + channels/parallel/ChannelOptions.cmake + channels/printer/ChannelOptions.cmake + channels/rail/ChannelOptions.cmake + channels/rdpdr/ChannelOptions.cmake + channels/rdpei/ChannelOptions.cmake + channels/rdpgfx/ChannelOptions.cmake + channels/rdpsnd/ChannelOptions.cmake + channels/remdesk/ChannelOptions.cmake + channels/serial/ChannelOptions.cmake + channels/smartcard/ChannelOptions.cmake + channels/sshagent/ChannelOptions.cmake + channels/tsmf/ChannelOptions.cmake + channels/urbdrc/ChannelOptions.cmake + channels/video/ChannelOptions.cmake + ci/cmake-preloads/config-android.txt + ci/cmake-preloads/config-debian-squeeze.txt + ci/cmake-preloads/config-ios.txt + ci/cmake-preloads/config-linux-all.txt + ci/cmake-preloads/config-macosx.txt + ci/cmake-preloads/config-ubuntu-1204.txt + ci/cmake-preloads/config-windows.txt + client/DirectFB/ModuleOptions.cmake + client/FreeRDP-ClientConfig.cmake.in + client/Sample/ModuleOptions.cmake + client/Wayland/wlfreerdp.1.in + client/X11/ModuleOptions.cmake + client/X11/generate_argument_docbook.c + client/X11/xfreerdp-envvar.1.xml + client/X11/xfreerdp-examples.1.xml + client/X11/xfreerdp.1.xml.in + client/common/test/CMakeLists.txt client/common/test/TestClientChannels.c client/common/test/TestClientCmdLine.c client/common/test/TestClientRdpFile.c + client/freerdp-client.pc.in + cmake/ClangToolchain.cmake + cmake/ComplexLibrary.cmake + cmake/ConfigOptions.cmake + cmake/EchoTarget.cmake + cmake/FindFFmpeg.cmake + cmake/FindFeature.cmake + cmake/FindGSM.cmake + cmake/FindGSSAPI.cmake + cmake/FindGlib.cmake + cmake/FindIPP.cmake + cmake/FindMbedTLS.cmake + cmake/FindOSS.cmake + cmake/FindOpenH264.cmake + cmake/FindOpenSLES.cmake + cmake/FindPAM.cmake + cmake/FindPCSC.cmake + cmake/FindPCSCWinPR.cmake + cmake/FindPulse.cmake + cmake/Findlibsystemd.cmake + cmake/Findx264.cmake + cmake/GNUInstallDirsWrapper.cmake + cmake/InstallFreeRDPMan.cmake + cmake/LibFindMacros.cmake + cmake/MSVCRuntime.cmake + cmake/compat_2.8.11/BasicConfigVersion-AnyNewerVersion.cmake.in + cmake/compat_2.8.11/BasicConfigVersion-ExactVersion.cmake.in + cmake/compat_2.8.11/BasicConfigVersion-SameMajorVersion.cmake.in + cmake/compat_2.8.11/CMakePackageConfigHelpers.cmake + cmake/compat_2.8.2/FindPkgConfig.cmake + cmake/compat_2.8.3/CMakeParseArguments.cmake + cmake/compat_2.8.3/FindPackageHandleStandardArgs.cmake + cmake/compat_2.8.6/FeatureSummary.cmake + cmake/compat_3.7.0/FindICU.cmake + cmake/iOSToolchain.cmake + cmake/today.cmake + config.h.in + debian/changelog + debian/compat + debian/control + debian/files + debian/freerdp2-dev.install + debian/freerdp2-shadow-x11.install + debian/freerdp2-wayland.install + debian/freerdp2-x11.install + debian/gbp.conf + debian/libfreerdp-client2-2.install + debian/libfreerdp-client2-2.symbols + debian/libfreerdp-server2-2.install + debian/libfreerdp-server2-2.symbols + debian/libfreerdp-shadow-subsystem2-2.install + debian/libfreerdp-shadow-subsystem2-2.symbols + debian/libfreerdp-shadow2-2.install + debian/libfreerdp-shadow2-2.symbols + debian/libfreerdp2-2.install + debian/libfreerdp2-2.symbols + debian/libuwac0-0.install + debian/libuwac0-0.symbols + debian/libuwac0-dev.install + debian/libwinpr-tools2-2.install + debian/libwinpr-tools2-2.symbols + debian/libwinpr2-2.docs + debian/libwinpr2-2.install + debian/libwinpr2-2.symbols + debian/libwinpr2-2.symbols.hurd-i386 + debian/libwinpr2-2.symbols.kfreebsd-amd64 + debian/libwinpr2-2.symbols.kfreebsd-i386 + debian/libwinpr2-dev.install + debian/patches/README + debian/rules + debian/source/format + debian/watch + debian/winpr-utils.install docs/PrintFormatSpecifiers.md + docs/README.android + docs/README.directfb + docs/README.ios + docs/README.macOS + docs/valgrind.supp docs/wlog.md external/README + include/freerdp/build-config.h.in + libfreerdp/FreeRDPConfig.cmake.in + libfreerdp/codec/test/CMakeLists.txt libfreerdp/codec/test/TestFreeRDPCodecClear.c libfreerdp/codec/test/TestFreeRDPCodecMppc.c libfreerdp/codec/test/TestFreeRDPCodecNCrush.c @@ -490,11 +737,19 @@ Files: client/X11/generate_argument_docbook.c libfreerdp/codec/test/TestFreeRDPCodecRemoteFX.c libfreerdp/codec/test/TestFreeRDPCodecXCrush.c libfreerdp/codec/test/TestFreeRDPCodecZGfx.c + libfreerdp/codec/test/test01.bmp + libfreerdp/codec/yuv.c + libfreerdp/common/test/CMakeLists.txt libfreerdp/common/test/TestCommonAssistance.c + libfreerdp/core/test/CMakeLists.txt libfreerdp/core/test/TestConnect.c libfreerdp/core/test/TestSettings.c libfreerdp/core/test/TestVersion.c + libfreerdp/crypto/test/CMakeLists.txt libfreerdp/crypto/test/known_hosts/known_hosts + libfreerdp/crypto/test/known_hosts/known_hosts.v2 + libfreerdp/freerdp.pc.in + libfreerdp/gdi/test/CMakeLists.txt libfreerdp/gdi/test/TestGdiBitBlt.c libfreerdp/gdi/test/TestGdiClip.c libfreerdp/gdi/test/TestGdiCreate.c @@ -502,31 +757,71 @@ Files: client/X11/generate_argument_docbook.c libfreerdp/gdi/test/TestGdiLine.c libfreerdp/gdi/test/TestGdiRect.c libfreerdp/gdi/test/TestGdiRop3.c + libfreerdp/primitives/README.txt + libfreerdp/primitives/test/CMakeLists.txt libfreerdp/primitives/test/TestPrimitivesYCbCr.c libfreerdp/primitives/test/TestPrimitivesYUV.c + libfreerdp/utils/test/CMakeLists.txt packaging/deb/freerdp-nightly/changelog packaging/deb/freerdp-nightly/compat packaging/deb/freerdp-nightly/control + packaging/deb/freerdp-nightly/freerdp-nightly-dev.install + packaging/deb/freerdp-nightly/freerdp-nightly.install packaging/deb/freerdp-nightly/lintian-overrides packaging/deb/freerdp-nightly/rules packaging/deb/freerdp-nightly/source/format packaging/rpm/freerdp-nightly-rpmlintrc packaging/scripts/prepare_deb_freerdp-nightly.sh + packaging/scripts/prepare_rpm_freerdp-nightly.sh + rdtk/librdtk/test/CMakeLists.txt rdtk/librdtk/test/TestRdTkNinePatch.c + resources/FreeRDP_Icon.svg resources/FreeRDP_Icon_256px.h + resources/FreeRDP_Icon_256px.xpm + resources/FreeRDP_Logo.svg + resources/FreeRDP_Logo_Icon.ai + resources/FreeRDP_Logo_Icon.svg scripts/LECHash.c scripts/LOMHash.c + scripts/android-build-32.conf + scripts/android-build-64.conf scripts/android-build-common.sh scripts/android-build-freerdp.sh scripts/android-build-jpeg.sh scripts/android-build-openh264.sh scripts/android-build-openssl.sh + scripts/android-build.conf scripts/autoformat.sh + scripts/blacklist-memory-sanitizer.txt scripts/format_code.sh + scripts/openssl-mips64.conf + server/FreeRDP-ServerConfig.cmake.in + server/Mac/ModuleOptions.cmake + server/Mac/server.crt + server/Mac/server.key + server/Sample/ModuleOptions.cmake + server/Sample/rfx_test.pcap + server/Sample/server.crt + server/Sample/server.key + server/Sample/test_icon.ppm + server/Windows/ModuleOptions.cmake + server/Windows/server.crt + server/Windows/server.key server/Windows/wf_directsound.c server/Windows/wf_directsound.h server/Windows/wf_wasapi.c server/Windows/wf_wasapi.h + server/freerdp-server.pc.in + server/shadow/FreeRDP-ShadowConfig.cmake.in + server/shadow/freerdp-shadow-cli.1.in + server/shadow/freerdp-shadow.pc.in + uwac/protocols/fullscreen-shell.xml + uwac/uwac.pc.in + uwac/uwacConfig.cmake.in + uwac/uwacVersion.cmake + winpr/WinPRConfig.cmake.in + winpr/libwinpr/asn1/ModuleOptions.cmake + winpr/libwinpr/asn1/test/CMakeLists.txt winpr/libwinpr/asn1/test/TestAsn1BerDec.c winpr/libwinpr/asn1/test/TestAsn1BerEnc.c winpr/libwinpr/asn1/test/TestAsn1Compare.c @@ -539,31 +834,53 @@ Files: client/X11/generate_argument_docbook.c winpr/libwinpr/asn1/test/TestAsn1Integer.c winpr/libwinpr/asn1/test/TestAsn1Module.c winpr/libwinpr/asn1/test/TestAsn1String.c + winpr/libwinpr/bcrypt/ModuleOptions.cmake + winpr/libwinpr/clipboard/ModuleOptions.cmake + winpr/libwinpr/clipboard/test/CMakeLists.txt winpr/libwinpr/clipboard/test/TestClipboardFormats.c + winpr/libwinpr/com/ModuleOptions.cmake + winpr/libwinpr/com/test/CMakeLists.txt winpr/libwinpr/com/test/TestComReference.c + winpr/libwinpr/comm/ModuleOptions.cmake + winpr/libwinpr/comm/test/CMakeLists.txt winpr/libwinpr/comm/test/TestCommMonitor.c + winpr/libwinpr/credentials/ModuleOptions.cmake + winpr/libwinpr/credui/ModuleOptions.cmake + winpr/libwinpr/credui/test/CMakeLists.txt winpr/libwinpr/credui/test/TestCredUICmdLinePromptForCredentials.c winpr/libwinpr/credui/test/TestCredUIConfirmCredentials.c winpr/libwinpr/credui/test/TestCredUIParseUserName.c winpr/libwinpr/credui/test/TestCredUIPromptForCredentials.c + winpr/libwinpr/crt/ModuleOptions.cmake + winpr/libwinpr/crt/test/CMakeLists.txt winpr/libwinpr/crt/test/TestAlignment.c winpr/libwinpr/crt/test/TestFormatSpecifiers.c winpr/libwinpr/crt/test/TestString.c winpr/libwinpr/crt/test/TestTypes.c winpr/libwinpr/crt/test/TestUnicodeConversion.c + winpr/libwinpr/crypto/ModuleOptions.cmake + winpr/libwinpr/crypto/test/CMakeLists.txt winpr/libwinpr/crypto/test/TestCryptoCertEnumCertificatesInStore.c winpr/libwinpr/crypto/test/TestCryptoCipher.c winpr/libwinpr/crypto/test/TestCryptoHash.c winpr/libwinpr/crypto/test/TestCryptoProtectData.c winpr/libwinpr/crypto/test/TestCryptoProtectMemory.c winpr/libwinpr/crypto/test/TestCryptoRand.c + winpr/libwinpr/dsparse/ModuleOptions.cmake + winpr/libwinpr/dsparse/test/CMakeLists.txt winpr/libwinpr/dsparse/test/TestDsCrackNames.c winpr/libwinpr/dsparse/test/TestDsMakeSpn.c winpr/libwinpr/dummy.c + winpr/libwinpr/environment/ModuleOptions.cmake + winpr/libwinpr/environment/test/CMakeLists.txt winpr/libwinpr/environment/test/TestEnvironmentGetEnvironmentStrings.c winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c winpr/libwinpr/environment/test/TestEnvironmentMergeEnvironmentStrings.c winpr/libwinpr/environment/test/TestEnvironmentSetEnvironmentVariable.c + winpr/libwinpr/error/ModuleOptions.cmake + winpr/libwinpr/error/test/CMakeLists.txt + winpr/libwinpr/file/ModuleOptions.cmake + winpr/libwinpr/file/test/CMakeLists.txt winpr/libwinpr/file/test/TestFileCreateFile.c winpr/libwinpr/file/test/TestFileDeleteFile.c winpr/libwinpr/file/test/TestFileFindFirstFile.c @@ -572,26 +889,44 @@ Files: client/X11/generate_argument_docbook.c winpr/libwinpr/file/test/TestFilePatternMatch.c winpr/libwinpr/file/test/TestFileReadFile.c winpr/libwinpr/file/test/TestFileWriteFile.c + winpr/libwinpr/handle/ModuleOptions.cmake + winpr/libwinpr/heap/ModuleOptions.cmake + winpr/libwinpr/input/ModuleOptions.cmake + winpr/libwinpr/interlocked/ModuleOptions.cmake + winpr/libwinpr/interlocked/module_5.1.def + winpr/libwinpr/interlocked/test/CMakeLists.txt winpr/libwinpr/interlocked/test/TestInterlockedAccess.c winpr/libwinpr/interlocked/test/TestInterlockedDList.c winpr/libwinpr/interlocked/test/TestInterlockedSList.c + winpr/libwinpr/io/ModuleOptions.cmake + winpr/libwinpr/io/test/CMakeLists.txt winpr/libwinpr/io/test/TestIoDevice.c winpr/libwinpr/io/test/TestIoGetOverlappedResult.c + winpr/libwinpr/library/ModuleOptions.cmake + winpr/libwinpr/library/test/CMakeLists.txt winpr/libwinpr/library/test/TestLibraryA/TestLibraryA.c winpr/libwinpr/library/test/TestLibraryB/TestLibraryB.c winpr/libwinpr/library/test/TestLibraryGetModuleFileName.c winpr/libwinpr/library/test/TestLibraryGetProcAddress.c winpr/libwinpr/library/test/TestLibraryLoadLibrary.c + winpr/libwinpr/locale/ModuleOptions.cmake + winpr/libwinpr/locale/test/CMakeLists.txt winpr/libwinpr/locale/test/TestLocaleFormatMessage.c + winpr/libwinpr/memory/ModuleOptions.cmake + winpr/libwinpr/memory/test/CMakeLists.txt winpr/libwinpr/memory/test/TestMemoryCreateFileMapping.c + winpr/libwinpr/nt/ModuleOptions.cmake + winpr/libwinpr/nt/test/CMakeLists.txt winpr/libwinpr/nt/test/TestNtCreateFile.c winpr/libwinpr/nt/test/TestNtCurrentTeb.c + winpr/libwinpr/path/ModuleOptions.cmake winpr/libwinpr/path/include/PathAllocCombine.c winpr/libwinpr/path/include/PathCchAddExtension.c winpr/libwinpr/path/include/PathCchAddSeparator.c winpr/libwinpr/path/include/PathCchAddSeparatorEx.c winpr/libwinpr/path/include/PathCchAppend.c winpr/libwinpr/path/shell_ios.h + winpr/libwinpr/path/test/CMakeLists.txt winpr/libwinpr/path/test/TestPathAllocCanonicalize.c winpr/libwinpr/path/test/TestPathAllocCombine.c winpr/libwinpr/path/test/TestPathCchAddBackslash.c @@ -616,16 +951,30 @@ Files: client/X11/generate_argument_docbook.c winpr/libwinpr/path/test/TestPathIsUNCEx.c winpr/libwinpr/path/test/TestPathMakePath.c winpr/libwinpr/path/test/TestPathShell.c + winpr/libwinpr/pipe/ModuleOptions.cmake + winpr/libwinpr/pipe/test/CMakeLists.txt winpr/libwinpr/pipe/test/TestPipeCreateNamedPipe.c winpr/libwinpr/pipe/test/TestPipeCreateNamedPipeOverlapped.c winpr/libwinpr/pipe/test/TestPipeCreatePipe.c + winpr/libwinpr/pool/ModuleOptions.cmake + winpr/libwinpr/pool/test/CMakeLists.txt winpr/libwinpr/pool/test/TestPoolIO.c winpr/libwinpr/pool/test/TestPoolSynch.c winpr/libwinpr/pool/test/TestPoolThread.c winpr/libwinpr/pool/test/TestPoolTimer.c winpr/libwinpr/pool/test/TestPoolWork.c + winpr/libwinpr/registry/ModuleOptions.cmake + winpr/libwinpr/rpc/ModuleOptions.cmake + winpr/libwinpr/security/ModuleOptions.cmake + winpr/libwinpr/security/test/CMakeLists.txt winpr/libwinpr/security/test/TestSecurityToken.c + winpr/libwinpr/shell/ModuleOptions.cmake + winpr/libwinpr/smartcard/ModuleOptions.cmake + winpr/libwinpr/smartcard/test/CMakeLists.txt winpr/libwinpr/smartcard/test/TestSmartCardListReaders.c + winpr/libwinpr/smartcard/test/TestSmartCardStatus.c + winpr/libwinpr/sspi/ModuleOptions.cmake + winpr/libwinpr/sspi/test/CMakeLists.txt winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c winpr/libwinpr/sspi/test/TestCredSSP.c winpr/libwinpr/sspi/test/TestEnumerateSecurityPackages.c @@ -633,6 +982,9 @@ Files: client/X11/generate_argument_docbook.c winpr/libwinpr/sspi/test/TestNTLM.c winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c winpr/libwinpr/sspi/test/TestSchannel.c + winpr/libwinpr/sspicli/ModuleOptions.cmake + winpr/libwinpr/synch/ModuleOptions.cmake + winpr/libwinpr/synch/test/CMakeLists.txt winpr/libwinpr/synch/test/TestSynchBarrier.c winpr/libwinpr/synch/test/TestSynchCritical.c winpr/libwinpr/synch/test/TestSynchEvent.c @@ -644,14 +996,21 @@ Files: client/X11/generate_argument_docbook.c winpr/libwinpr/synch/test/TestSynchTimerQueue.c winpr/libwinpr/synch/test/TestSynchWaitableTimer.c winpr/libwinpr/synch/test/TestSynchWaitableTimerAPC.c + winpr/libwinpr/sysinfo/ModuleOptions.cmake winpr/libwinpr/sysinfo/cpufeatures/README + winpr/libwinpr/sysinfo/test/CMakeLists.txt winpr/libwinpr/sysinfo/test/TestCPUFeatures.c winpr/libwinpr/sysinfo/test/TestGetComputerName.c winpr/libwinpr/sysinfo/test/TestGetNativeSystemInfo.c winpr/libwinpr/sysinfo/test/TestLocalTime.c winpr/libwinpr/sysinfo/test/TestSystemTime.c + winpr/libwinpr/thread/ModuleOptions.cmake + winpr/libwinpr/thread/test/CMakeLists.txt winpr/libwinpr/thread/test/TestThreadCommandLineToArgv.c winpr/libwinpr/thread/test/TestThreadCreateProcess.c + winpr/libwinpr/timezone/ModuleOptions.cmake + winpr/libwinpr/utils/ModuleOptions.cmake + winpr/libwinpr/utils/test/CMakeLists.txt winpr/libwinpr/utils/test/TestArrayList.c winpr/libwinpr/utils/test/TestBacktrace.c winpr/libwinpr/utils/test/TestBipBuffer.c @@ -673,8 +1032,14 @@ Files: client/X11/generate_argument_docbook.c winpr/libwinpr/utils/test/TestVersion.c winpr/libwinpr/utils/test/TestWLog.c winpr/libwinpr/utils/test/TestWLogCallback.c + winpr/libwinpr/winhttp/ModuleOptions.cmake + winpr/libwinpr/winsock/ModuleOptions.cmake + winpr/libwinpr/wnd/ModuleOptions.cmake + winpr/libwinpr/wnd/test/CMakeLists.txt winpr/libwinpr/wnd/test/TestWndCreateWindowEx.c winpr/libwinpr/wnd/test/TestWndWmCopyData.c + winpr/libwinpr/wtsapi/ModuleOptions.cmake + winpr/libwinpr/wtsapi/test/CMakeLists.txt winpr/libwinpr/wtsapi/test/TestWtsApiEnumerateProcesses.c winpr/libwinpr/wtsapi/test/TestWtsApiEnumerateSessions.c winpr/libwinpr/wtsapi/test/TestWtsApiExtraDisconnectSession.c @@ -687,7 +1052,13 @@ Files: client/X11/generate_argument_docbook.c winpr/libwinpr/wtsapi/test/TestWtsApiSessionNotification.c winpr/libwinpr/wtsapi/test/TestWtsApiShutdownSystem.c winpr/libwinpr/wtsapi/test/TestWtsApiWaitSystemEvent.c + winpr/test/CMakeLists.txt winpr/test/TestIntrinsics.c + winpr/tools/hash-cli/winpr-hash.1.in + winpr/tools/makecert-cli/winpr-makecert.1.in + winpr/tools/winpr-tools.pc.in + winpr/winpr.pc.in + winpr/wlog.7 Copyright: NONE License: UNKNOWN FIXME @@ -708,6 +1079,7 @@ Files: client/Sample/freerdp.c include/freerdp/graphics.h libfreerdp/codec/clear.c libfreerdp/codec/color.c + libfreerdp/codec/ncrush.c libfreerdp/codec/planar.c libfreerdp/codec/xcrush.c libfreerdp/codec/zgfx.c @@ -750,6 +1122,61 @@ Copyright: 2010, Marc-Andre Moreau <marcandre.moreau@gmail.com> License: Apache (v2.0) FIXME +Files: channels/client/addin.c + channels/client/tables.c.in + channels/cliprdr/server/cliprdr_main.c + channels/disp/client/disp_main.h + channels/drdynvc/server/drdynvc_main.c + channels/encomsp/client/encomsp_main.c + channels/encomsp/client/encomsp_main.h + channels/encomsp/server/encomsp_main.c + channels/rdpei/client/rdpei_main.c + channels/rdpgfx/client/rdpgfx_codec.c + channels/rdpgfx/client/rdpgfx_codec.h + channels/rdpgfx/rdpgfx_common.c + channels/rdpgfx/rdpgfx_common.h + channels/remdesk/client/remdesk_main.c + channels/remdesk/client/remdesk_main.h + channels/remdesk/server/remdesk_main.c + channels/smartcard/client/smartcard_pack.c + channels/smartcard/client/smartcard_pack.h + include/freerdp/client/disp.h + include/freerdp/client/drdynvc.h + include/freerdp/client/encomsp.h + include/freerdp/client/rdpei.h + include/freerdp/client/rdpgfx.h + include/freerdp/server/cliprdr.h + include/freerdp/server/drdynvc.h + include/freerdp/server/encomsp.h + include/freerdp/server/remdesk.h + libfreerdp/core/client.c + libfreerdp/core/connection.c + libfreerdp/core/freerdp.c + libfreerdp/core/info.c + libfreerdp/core/mcs.h + libfreerdp/core/server.c + server/Mac/mf_audin.c + server/Mac/mf_rdpsnd.c + server/Sample/sf_audin.c + server/Sample/sf_encomsp.c + server/Sample/sf_rdpsnd.c + server/shadow/shadow_encomsp.c + server/shadow/shadow_remdesk.c + winpr/include/winpr/environment.h + winpr/libwinpr/environment/environment.c + winpr/libwinpr/utils/wlog/BinaryAppender.c + winpr/libwinpr/utils/wlog/PacketMessage.c +Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2013, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> + 2013, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2013, Thincast Technologies GmbH + 2014, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2015, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> + 2015, Thincast Technologies GmbH +License: Apache (v2.0) + FIXME + Files: channels/audin/client/audin_main.h channels/printer/client/printer_cups.h channels/tsmf/client/alsa/tsmf_alsa.c @@ -801,61 +1228,8 @@ Copyright: 2010-2011, Vic Lee License: Apache (v2.0) FIXME -Files: channels/client/addin.c - channels/cliprdr/server/cliprdr_main.c - channels/disp/client/disp_main.h - channels/drdynvc/server/drdynvc_main.c - channels/encomsp/client/encomsp_main.c - channels/encomsp/client/encomsp_main.h - channels/encomsp/server/encomsp_main.c - channels/rdpei/client/rdpei_main.c - channels/rdpgfx/client/rdpgfx_codec.c - channels/rdpgfx/client/rdpgfx_codec.h - channels/rdpgfx/rdpgfx_common.c - channels/rdpgfx/rdpgfx_common.h - channels/remdesk/client/remdesk_main.c - channels/remdesk/client/remdesk_main.h - channels/remdesk/server/remdesk_main.c - channels/smartcard/client/smartcard_pack.c - channels/smartcard/client/smartcard_pack.h - include/freerdp/client/disp.h - include/freerdp/client/drdynvc.h - include/freerdp/client/encomsp.h - include/freerdp/client/rdpei.h - include/freerdp/client/rdpgfx.h - include/freerdp/server/cliprdr.h - include/freerdp/server/drdynvc.h - include/freerdp/server/encomsp.h - include/freerdp/server/remdesk.h - libfreerdp/core/client.c - libfreerdp/core/connection.c - libfreerdp/core/freerdp.c - libfreerdp/core/info.c - libfreerdp/core/mcs.h - libfreerdp/core/server.c - server/Mac/mf_audin.c - server/Mac/mf_rdpsnd.c - server/Sample/sf_audin.c - server/Sample/sf_encomsp.c - server/Sample/sf_rdpsnd.c - server/shadow/shadow_encomsp.c - server/shadow/shadow_remdesk.c - winpr/include/winpr/environment.h - winpr/libwinpr/environment/environment.c - winpr/libwinpr/utils/wlog/BinaryAppender.c - winpr/libwinpr/utils/wlog/PacketMessage.c -Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> - 2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> - 2013, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> - 2013, Marc-Andre Moreau <marcandre.moreau@gmail.com> - 2013, Thincast Technologies GmbH - 2014, Marc-Andre Moreau <marcandre.moreau@gmail.com> - 2015, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> - 2015, Thincast Technologies GmbH -License: Apache (v2.0) - FIXME - -Files: include/freerdp/primitives.h +Files: channels/tsmf/client/gstreamer/CMakeLists.txt + include/freerdp/primitives.h libfreerdp/primitives/prim_YCoCg.c libfreerdp/primitives/prim_YCoCg_opt.c libfreerdp/primitives/prim_add.c @@ -901,6 +1275,57 @@ Copyright: 2012, Hewlett-Packard Development Company, L.P. License: Apache (v2.0) FIXME +Files: channels/geometry/CMakeLists.txt + channels/geometry/client/CMakeLists.txt + channels/geometry/client/geometry_main.c + channels/geometry/client/geometry_main.h + channels/printer/printer.h + channels/video/CMakeLists.txt + channels/video/client/CMakeLists.txt + channels/video/client/video_main.c + channels/video/client/video_main.h + client/X11/xf_disp.c + client/X11/xf_disp.h + client/X11/xf_video.c + client/X11/xf_video.h + cmake/FindWayland.cmake + include/freerdp/channels/geometry.h + include/freerdp/channels/video.h + include/freerdp/client/geometry.h + include/freerdp/client/video.h + include/freerdp/codec/yuv.h + include/freerdp/gdi/video.h + libfreerdp/gdi/video.c +Copyright: 2015, David Fort <contact@hardening-consulting.com> + 2016, David Fort <contact@hardening-consulting.com> + 2017, David Fort <contact@hardening-consulting.com> + 2018, David Fort <contact@hardening-consulting.com> +License: Apache (v2.0) + FIXME + +Files: channels/urbdrc/client/CMakeLists.txt + channels/urbdrc/client/data_transfer.c + channels/urbdrc/client/data_transfer.h + channels/urbdrc/client/isoch_queue.c + channels/urbdrc/client/isoch_queue.h + channels/urbdrc/client/libusb/CMakeLists.txt + channels/urbdrc/client/libusb/libusb_udevice.c + channels/urbdrc/client/libusb/libusb_udevice.h + channels/urbdrc/client/libusb/libusb_udevman.c + channels/urbdrc/client/libusb/request_queue.c + channels/urbdrc/client/libusb/request_queue.h + channels/urbdrc/client/searchman.c + channels/urbdrc/client/searchman.h + channels/urbdrc/client/urbdrc_main.c + channels/urbdrc/client/urbdrc_main.h + channels/urbdrc/client/urbdrc_types.h + include/freerdp/utils/msusb.h + libfreerdp/utils/msusb.c +Copyright: 2012, Alfred Liu <alfred.liu@atruscorp.com> + 2012, Atrust corp. +License: Apache (v2.0) + FIXME + Files: channels/audin/client/alsa/audin_alsa.c channels/audin/client/pulse/audin_pulse.c channels/audin/server/audin.c @@ -928,29 +1353,9 @@ Copyright: 2010-2011, Vic Lee License: Apache (v2.0) FIXME -Files: channels/urbdrc/client/data_transfer.c - channels/urbdrc/client/data_transfer.h - channels/urbdrc/client/isoch_queue.c - channels/urbdrc/client/isoch_queue.h - channels/urbdrc/client/libusb/libusb_udevice.c - channels/urbdrc/client/libusb/libusb_udevice.h - channels/urbdrc/client/libusb/libusb_udevman.c - channels/urbdrc/client/libusb/request_queue.c - channels/urbdrc/client/libusb/request_queue.h - channels/urbdrc/client/searchman.c - channels/urbdrc/client/searchman.h - channels/urbdrc/client/urbdrc_main.c - channels/urbdrc/client/urbdrc_main.h - channels/urbdrc/client/urbdrc_types.h - include/freerdp/utils/msusb.h - libfreerdp/utils/msusb.c -Copyright: 2012, Alfred Liu <alfred.liu@atruscorp.com> - 2012, Atrust corp. -License: Apache (v2.0) - FIXME - Files: client/X11/xf_input.c client/X11/xf_input.h + cmake/FindXrender.cmake server/Mac/mf_event.c server/Mac/mf_event.h server/Mac/mf_info.c @@ -970,9 +1375,11 @@ Copyright: 2012, Corey Clayton <can.of.tuna@gmail.com> License: Apache (v2.0) FIXME -Files: channels/audin/client/mac/audin_mac.c +Files: channels/audin/client/mac/CMakeLists.txt + channels/audin/client/mac/audin_mac.c channels/tsmf/client/gstreamer/tsmf_X11.c channels/tsmf/client/gstreamer/tsmf_platform.h + cmake/FindDbusGlib.cmake include/freerdp/channels/tsmf.h libfreerdp/core/errbase.c libfreerdp/core/errconnect.c @@ -980,18 +1387,24 @@ Files: channels/audin/client/mac/audin_mac.c libfreerdp/gdi/test/helpers.c libfreerdp/gdi/test/helpers.h winpr/include/winpr/debug.h + winpr/libwinpr/sysinfo/cpufeatures/CMakeLists.txt winpr/libwinpr/utils/debug.c winpr/libwinpr/utils/winpr.c -Copyright: 2014, Armin Novak <armin.novak@thincast.com> +Copyright: 2013, Armin Novak <armin.novak@thincast.com> + 2013, Thincast Technologies GmbH + 2014, Armin Novak <armin.novak@thincast.com> 2014, Thincast Technologies GmbH 2015, Armin Novak <armin.novak@thincast.com> 2015, Thincast Technologies GmbH 2016, Armin Novak <armin.novak@thincast.com> 2016, Thincast Technologies GmbH + 2017, Armin Novak <armin.novak@thincast.com> + 2017, Thincast Technologies GmbH License: Apache (v2.0) FIXME -Files: channels/rdpgfx/server/rdpgfx_main.c +Files: channels/rdpgfx/server/CMakeLists.txt + channels/rdpgfx/server/rdpgfx_main.c channels/rdpgfx/server/rdpgfx_main.h include/freerdp/server/rdpgfx.h server/shadow/shadow_audin.c @@ -1008,7 +1421,8 @@ Copyright: 2015, Jiang Zihao <zihao.jiang@yahoo.com> License: Apache (v2.0) FIXME -Files: server/Mac/mf_audin.h +Files: client/X11/CMakeLists.txt + server/Mac/mf_audin.h server/Mac/mf_interface.h server/Mac/mfreerdp.c server/Mac/mfreerdp.h @@ -1026,6 +1440,24 @@ Copyright: 2012, Corey Clayton <can.of.tuna@gmail.com> License: Apache (v2.0) FIXME +Files: cmake/FindDirectFB.cmake + cmake/FindX11.cmake + cmake/FindXKBFile.cmake + cmake/FindXShm.cmake + cmake/FindXTest.cmake + cmake/FindXcursor.cmake + cmake/FindXdamage.cmake + cmake/FindXext.cmake + cmake/FindXfixes.cmake + cmake/FindXinerama.cmake + cmake/FindXv.cmake + include/CMakeLists.txt +Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2011, O.S. Systems Software Ltda. + 2011, Otavio Salvador <otavio@ossystems.com.br> +License: Apache (v2.0) + FIXME + Files: channels/rdpdr/client/irp.h channels/rdpsnd/client/rdpsnd_main.h channels/rdpsnd/server/rdpsnd_main.h @@ -1068,6 +1500,7 @@ Files: libfreerdp/core/autodetect.c libfreerdp/core/heartbeat.h libfreerdp/core/multitransport.c libfreerdp/core/multitransport.h + winpr/libwinpr/shell/CMakeLists.txt winpr/libwinpr/shell/shell.c Copyright: 2014, Dell Software <Mike.McDonald@software.dell.com> 2015, Dell Software <Mike.McDonald@software.dell.com> @@ -1078,6 +1511,7 @@ Files: libfreerdp/core/rdp.c libfreerdp/core/rdp.h winpr/include/winpr/user.h winpr/include/winpr/wnd.h + winpr/libwinpr/handle/CMakeLists.txt winpr/libwinpr/handle/handle.c winpr/libwinpr/thread/process.c Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> @@ -1088,6 +1522,21 @@ Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> License: Apache (v2.0) FIXME +Files: client/common/cmdline.h + cmake/ConfigOptionsAndroid.cmake + include/freerdp/version.h.in + winpr/include/winpr/intrin.h + winpr/include/winpr/version.h.in + winpr/libwinpr/file/test/TestFileGetStdHandle.c +Copyright: 2013, Bernhard Miklautz <bernhard.miklautz@thincast.com> + 2013, Thincast Technologies GmbH + 2015, Bernhard Miklautz <bernhard.miklautz@thincast.com> + 2015, Thincast Technologies GmbH + 2018, Bernhard Miklautz <bernhard.miklautz@thincast.com> + 2018, Thincast Technologies GmbH +License: Apache (v2.0) + FIXME + Files: winpr/include/winpr/comm.h winpr/libwinpr/comm/comm.c winpr/libwinpr/comm/comm_ioctl.c @@ -1125,6 +1574,16 @@ Copyright: 1998, 2009, Bjorn Reese and Daniel Stenberg. License: UNKNOWN FIXME +Files: channels/audin/client/opensles/CMakeLists.txt + channels/rdpsnd/client/opensles/CMakeLists.txt + include/freerdp/channels/log.h + include/freerdp/log.h + winpr/libwinpr/log.h +Copyright: 2013, Armin Novak <armin.novak@gmail.com> + 2014, Armin Novak <armin.novak@gmail.com> +License: Apache (v2.0) + FIXME + Files: libfreerdp/core/gateway/ntlm.c libfreerdp/core/gateway/ntlm.h libfreerdp/core/gateway/rpc.c @@ -1146,6 +1605,19 @@ Copyright: 2014, Hardening <contact@hardening-consulting.com> License: Apache (v2.0) FIXME +Files: channels/tsmf/client/CMakeLists.txt + winpr/libwinpr/comm/comm.h + winpr/libwinpr/comm/test/TestCommConfig.c + winpr/libwinpr/thread/thread.c + winpr/libwinpr/thread/thread.h +Copyright: 2012, Hewlett-Packard Development Company, L.P. + 2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2014, Hewlett-Packard Development Company, L.P. + 2014, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2015, Hewlett-Packard Development Company, L.P. +License: Apache (v2.0) + FIXME + Files: client/X11/xf_gdi.c winpr/include/winpr/synch.h winpr/libwinpr/error/test/TestErrorSetLastError.c @@ -1192,17 +1664,6 @@ Copyright: 2010-2011, Vic Lee License: Apache (v2.0) FIXME -Files: winpr/libwinpr/comm/comm.h - winpr/libwinpr/comm/test/TestCommConfig.c - winpr/libwinpr/thread/thread.c - winpr/libwinpr/thread/thread.h -Copyright: 2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> - 2014, Hewlett-Packard Development Company, L.P. - 2014, Marc-Andre Moreau <marcandre.moreau@gmail.com> - 2015, Hewlett-Packard Development Company, L.P. -License: Apache (v2.0) - FIXME - Files: include/freerdp/codec/bitmap.h include/freerdp/codec/jpeg.h libfreerdp/codec/bitmap.c @@ -1226,6 +1687,14 @@ Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> License: Apache (v2.0) FIXME +Files: channels/audin/client/oss/CMakeLists.txt + channels/rdpsnd/client/oss/CMakeLists.txt + channels/tsmf/client/oss/CMakeLists.txt + channels/tsmf/client/oss/tsmf_oss.c +Copyright: 2015, Rozhuk Ivan <rozhuk.im@gmail.com> +License: Apache (v2.0) + FIXME + Files: include/freerdp/utils/passphrase.h include/freerdp/utils/signal.h libfreerdp/utils/passphrase.c @@ -1242,13 +1711,6 @@ Copyright: 2012, Victor Lazzarini License: BSD (3 clause) FIXME -Files: include/freerdp/channels/log.h - include/freerdp/log.h - winpr/libwinpr/log.h -Copyright: 2014, Armin Novak <armin.novak@gmail.com> -License: Apache (v2.0) - FIXME - Files: channels/rdpgfx/client/rdpgfx_main.c libfreerdp/codec/interleaved.c libfreerdp/core/mcs.c @@ -1274,6 +1736,14 @@ Copyright: 2011, Vic Lee License: Apache (v2.0) FIXME +Files: channels/sshagent/CMakeLists.txt + channels/sshagent/client/CMakeLists.txt + channels/sshagent/server/CMakeLists.txt +Copyright: 2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2017, Ben Cohen +License: Apache (v2.0) + FIXME + Files: channels/rdpdr/server/rdpdr_main.c channels/rdpdr/server/rdpdr_main.h include/freerdp/server/rdpdr.h @@ -1305,6 +1775,14 @@ Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> License: Apache (v2.0) FIXME +Files: include/freerdp/session.h + uwac/CMakeLists.txt + uwac/include/CMakeLists.txt +Copyright: 2015, David FORT <contact@hardening-consulting.com> + 2016, David FORT <contact@hardening-consulting.com> +License: Apache (v2.0) + FIXME + Files: winpr/libwinpr/utils/wlog/JournaldAppender.c winpr/libwinpr/utils/wlog/SyslogAppender.c winpr/libwinpr/utils/wlog/UdpAppender.c @@ -1313,6 +1791,14 @@ Copyright: 2015, David FORT <contact@hardening-consulting.com> License: Apache (v2.0) FIXME +Files: client/Wayland/CMakeLists.txt + client/Wayland/wlf_input.c + client/Wayland/wlf_input.h +Copyright: 2014, Manuel Bachmann <tarnyko@tarnyko.net> + 2015, David Fort <contact@hardening-consulting.com> +License: Apache (v2.0) + FIXME + Files: winpr/include/winpr/file.h winpr/include/winpr/string.h winpr/libwinpr/path/shell.c @@ -1347,6 +1833,13 @@ Copyright: 2014, Norbert Federa <norbert.federa@thincast.com> License: Apache (v2.0) FIXME +Files: docs/Doxyfile + scripts/gprof_generate.sh.cmake + scripts/xcode.sh +Copyright: NONE +License: GENERATED FILE + FIXME + Files: winpr/libwinpr/utils/wlog/JournaldAppender.h winpr/libwinpr/utils/wlog/SyslogAppender.h winpr/libwinpr/utils/wlog/UdpAppender.h @@ -1362,6 +1855,21 @@ Copyright: 2001, Bjorn Reese <breese@users.sourceforge.net> License: UNKNOWN FIXME +Files: winpr/libwinpr/sspi/Kerberos/kerberos.c + winpr/libwinpr/sspi/Kerberos/kerberos.h +Copyright: 2015, ANSSI, Author Thomas Calderon + 2017, Dorian Ducournau <dorian.ducournau@gmail.com> +License: Apache (v2.0) + FIXME + +Files: winpr/libwinpr/sspi/sspi_gss.c + winpr/libwinpr/sspi/sspi_gss.h +Copyright: 2015, ANSSI, Author Thomas Calderon + 2015, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2017, Dorian Ducournau <dorian.ducournau@gmail.com> +License: Apache (v2.0) + FIXME + Files: winpr/libwinpr/clipboard/posix.c winpr/libwinpr/clipboard/posix.h Copyright: 2017, Alexei Lozovsky <a.lozovsky@gmail.com> @@ -1391,6 +1899,15 @@ Copyright: 2014, Armin Novak <armin.novak@thincast.com> License: Apache (v2.0) FIXME +Files: libfreerdp/primitives/prim_YUV_neon.c + libfreerdp/primitives/prim_YUV_ssse3.c +Copyright: 2014, Thomas Erbesdobler + 2016-2017, Armin Novak <armin.novak@thincast.com> + 2016-2017, Norbert Federa <norbert.federa@thincast.com> + 2016-2017, Thincast Technologies GmbH +License: Apache (v2.0) + FIXME + Files: include/freerdp/codec/nsc.h libfreerdp/codec/nsc.c Copyright: 2011, Samsung, Author Jiten Pathy @@ -1400,13 +1917,6 @@ Copyright: 2011, Samsung, Author Jiten Pathy License: Apache (v2.0) FIXME -Files: winpr/include/winpr/intrin.h - winpr/libwinpr/file/test/TestFileGetStdHandle.c -Copyright: 2015, Bernhard Miklautz <bernhard.miklautz@thincast.com> - 2015, Thincast Technologies GmbH -License: Apache (v2.0) - FIXME - Files: libfreerdp/core/proxy.c libfreerdp/core/proxy.h Copyright: 2014, Christian Plattner <ccpp@gmx.at> @@ -1422,6 +1932,14 @@ Copyright: 2013, Marc-Andre Moreau <marcandre.moreau@gmail.com> License: Apache (v2.0) FIXME +Files: channels/rdpsnd/client/ios/CMakeLists.txt + channels/rdpsnd/client/mac/CMakeLists.txt +Copyright: 2012, Laxmikant Rashinkar <LK.Rashinkar@gmail.com> + 2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2013, Corey Clayton <can.of.tuna@gmail.com> +License: Apache (v2.0) + FIXME + Files: winpr/libwinpr/handle/nonehandle.c winpr/libwinpr/handle/nonehandle.h Copyright: 2014, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> @@ -1464,13 +1982,6 @@ Copyright: 2015, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> License: Apache (v2.0) FIXME -Files: client/Wayland/wlf_input.c - client/Wayland/wlf_input.h -Copyright: 2014, Manuel Bachmann <tarnyko@tarnyko.net> - 2015, David Fort <contact@hardening-consulting.com> -License: Apache (v2.0) - FIXME - Files: channels/rdpei/rdpei_common.c channels/rdpei/rdpei_common.h Copyright: 2013, Marc-Andre Moreau <marcandre.moreau@gmail.com> @@ -1478,12 +1989,29 @@ Copyright: 2013, Marc-Andre Moreau <marcandre.moreau@gmail.com> License: Apache (v2.0) FIXME +Files: channels/rdpdr/client/CMakeLists.txt + winpr/libwinpr/utils/image.c +Copyright: 2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2014, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2016, David PHAM-VAN <d.phamvan@inuvika.com> + 2016, Inuvika Inc. +License: Apache (v2.0) + FIXME + Files: libfreerdp/core/gateway/rdg.c libfreerdp/core/gateway/rdg.h Copyright: 2015, Denis Vincent <dvincent@devolutions.net> License: Apache (v2.0) FIXME +Files: winpr/libwinpr/sspi/Negotiate/negotiate.c + winpr/libwinpr/sspi/sspi_winpr.c +Copyright: 2011-2014, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2012-2014, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2017, Dorian Ducournau <dorian.ducournau@gmail.com> +License: Apache (v2.0) + FIXME + Files: channels/serial/client/serial_main.c winpr/libwinpr/comm/comm_ioctl.h Copyright: 2011, Eduardo Fiss Beloni <beloni@ossystems.com.br> @@ -1507,6 +2035,13 @@ Copyright: 2009-2011, Jay Sorg License: Apache (v2.0) FIXME +Files: winpr/tools/CMakeLists.txt + winpr/tools/makecert-cli/CMakeLists.txt +Copyright: 2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2016, Thincast Technologies GmbH +License: Apache (v2.0) + FIXME + Files: libfreerdp/codec/rfx_neon.c libfreerdp/codec/rfx_neon.h Copyright: 2011, Martin Fleisz <martin.fleisz@thincast.com> @@ -1551,10 +2086,22 @@ Copyright: 2010, The Android Open Source Project License: BSD (2 clause) FIXME -Files: docs/Doxyfile - scripts/xcode.sh -Copyright: NONE -License: GENERATED FILE +Files: cmake/GetGitRevisionDescription.cmake + cmake/GetGitRevisionDescription.cmake.in +Copyright: Iowa State University 2009-2010. +License: BSL (v1.0) + FIXME + +Files: libfreerdp/codec/test/rfx.bmp + resources/FreeRDP-fav.ico +Copyright: +License: UNKNOWN + FIXME + +Files: packaging/deb/freerdp-nightly/freerdp-nightly-dbg.lintian-overrides + packaging/deb/freerdp-nightly/freerdp-nightly.lintian-overrides +Copyright: -file new-package-should-close-itp-bug dir-or-file-in-opt package-name-doesnt-match-sonames +License: UNKNOWN FIXME Files: winpr/libwinpr/crt/utf.c @@ -1575,6 +2122,11 @@ Copyright: 2005-2014, Lode Vandevenne License: zlib/libpng FIXME +Files: cmake/FindXRandR.cmake +Copyright: 2012, Alam Arias <Alam.GBC@gmail.com> +License: Apache (v2.0) + FIXME + Files: resources/conv_to_ewm_prop.py Copyright: 2011, Anthony Tong <atong@trustedcs.com> License: Apache (v2.0) @@ -1601,6 +2153,12 @@ Copyright: 2011, Anthony Tong <atong@trustedcs.com> License: Apache (v2.0) FIXME +Files: libfreerdp/codec/h264.h +Copyright: 2018, Armin Novak <anovak@thincast.com> + 2018, Thincast Technologies GmbH +License: Apache (v2.0) + FIXME + Files: channels/printer/client/printer_main.c Copyright: 2010-2011, Vic Lee 2015, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> @@ -1786,14 +2344,6 @@ Copyright: 2011, Vic Lee License: Apache (v2.0) FIXME -Files: libfreerdp/primitives/prim_YUV_opt.c -Copyright: 2014, Thomas Erbesdobler - 2016-2017, Armin Novak <armin.novak@thincast.com> - 2016-2017, Norbert Federa <norbert.federa@thincast.com> - 2016-2017, Thincast Technologies GmbH -License: Apache (v2.0) - FIXME - Files: libfreerdp/core/fastpath.c Copyright: 2011, Vic Lee 2014, Norbert Federa <norbert.federa@thincast.com> @@ -1814,6 +2364,30 @@ Copyright: 2016, Armin Novak <armin.novak@thincast.om> License: Apache (v2.0) FIXME +Files: include/freerdp/client/sshagent.h +Copyright: 2017, Ben Cohen +License: Apache (v2.0) + FIXME + +Files: channels/sshagent/client/sshagent_main.h +Copyright: 2013, Christian Hofstaedtler + 2017, Ben Cohen +License: Apache (v2.0) + FIXME + +Files: channels/sshagent/client/sshagent_main.c +Copyright: 2013, Christian Hofstaedtler + 2015, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> + 2015, Thincast Technologies GmbH + 2017, Ben Cohen +License: Apache (v2.0) + FIXME + +Files: cmake/CheckCmakeCompat.cmake +Copyright: 2012, Bernhard Miklautz <bernhard.miklautz@thincast.com> +License: Apache (v2.0) + FIXME + Files: winpr/libwinpr/file/file.c Copyright: 2015, Bernhard Miklautz <bernhard.miklautz@thincast.com> 2015, Thincast Technologies GmbH @@ -1858,6 +2432,14 @@ Copyright: 2011, Vic Lee License: Apache (v2.0) FIXME +Files: cmake/FindXi.cmake +Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2011, O.S. Systems Software Ltda. + 2011, Otavio Salvador <otavio@ossystems.com.br> + 2013, Corey Clayton <can.of.tuna@gmail.com> +License: Apache (v2.0) + FIXME + Files: channels/rdpei/server/rdpei_main.h Copyright: 2014, David Fort <contact@hardening-consulting.com> 2015, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> @@ -1946,6 +2528,15 @@ Copyright: 2012, Dmitrij Jasnov <dmitrij.jasnov@ts.fujitsu.com> License: Apache (v2.0) FIXME +Files: libfreerdp/core/nla.c +Copyright: 2010-2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2015, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> + 2015, Thincast Technologies GmbH + 2016, Martin Fleisz <martin.fleisz@thincast.com> + 2017, Dorian Ducournau <dorian.ducournau@gmail.com> +License: Apache (v2.0) + FIXME + Files: channels/cliprdr/client/cliprdr_main.h Copyright: 2009-2011, Jay Sorg 2010-2011, Vic Lee @@ -1961,14 +2552,6 @@ Copyright: 2011, Jiten Pathy License: Apache (v2.0) FIXME -Files: libfreerdp/core/nla.c -Copyright: 2010-2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> - 2015, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> - 2015, Thincast Technologies GmbH - 2016, Martin Fleisz <martin.fleisz@thincast.com> -License: Apache (v2.0) - FIXME - Files: libfreerdp/core/gcc.c Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> 2014, DI (FH) Martin Haimberger <martin.haimberger@thincast.com> @@ -2005,11 +2588,6 @@ Copyright: 2011, Vic Lee License: Apache (v2.0) FIXME -Files: include/freerdp/session.h -Copyright: 2016, David FORT <contact@hardening-consulting.com> -License: Apache (v2.0) - FIXME - Files: include/freerdp/channels/rdpei.h Copyright: 2013, Marc-Andre Moreau <marcandre.moreau@gmail.com> 2014, David FORT <contact@hardening-consulting.com> @@ -2017,8 +2595,16 @@ Copyright: 2013, Marc-Andre Moreau <marcandre.moreau@gmail.com> License: Apache (v2.0) FIXME -Files: channels/printer/printer.h -Copyright: 2016, David Fort <contact@hardening-consulting.com> +Files: channels/rdpei/server/CMakeLists.txt +Copyright: 2014, David FORT <contact@hardening-consulting.com> + 2014, Thincast Technologies Gmbh. +License: Apache (v2.0) + FIXME + +Files: client/X11/xf_monitor.c +Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2017, David Fort <contact@hardening-consulting.com> + 2018, Kai Harms <kharms@rangee.com> License: Apache (v2.0) FIXME @@ -2041,13 +2627,6 @@ Copyright: 2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> License: Apache (v2.0) FIXME -Files: winpr/libwinpr/utils/image.c -Copyright: 2014, Marc-Andre Moreau <marcandre.moreau@gmail.com> - 2016, David PHAM-VAN <d.phamvan@inuvika.com> - 2016, Inuvika Inc. -License: Apache (v2.0) - FIXME - Files: include/freerdp/autodetect.h Copyright: 2014, Dell Software <Mike.McDonald@software.dell.com> 2014, Vic Lee @@ -2065,6 +2644,14 @@ Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> License: Apache (v2.0) FIXME +Files: CMakeLists.txt +Copyright: 2011, Marc-Andre Moreau <marcandre.moreau@gmail.com> + 2011, O.S. Systems Software Ltda. + 2011, Otavio Salvador <otavio@ossystems.com.br> + 2012, HP Development Company, LLC +License: Apache (v2.0) + FIXME + Files: winpr/libwinpr/synch/wait.c Copyright: 2012, Marc-Andre Moreau <marcandre.moreau@gmail.com> 2014, Hardening <contact@hardening-consulting.com> @@ -2132,6 +2719,17 @@ Copyright: 2014, Mike McDonald <Mike.McDonald@software.dell.com> License: Apache (v2.0) FIXME +Files: cmake/ConfigOptionsiOS.cmake +Copyright: 2013, Martin Fleisz <martin.fleisz@thincast.com> + 2013, Thincast Technologies GmbH +License: Apache (v2.0) + FIXME + +Files: cmake/FindXmlto.cmake +Copyright: 2011, Nils Andresen <nils@nils-andresen.de> +License: Apache (v2.0) + FIXME + Files: libfreerdp/codec/rfx_sse2.c Copyright: 2011, Norbert Federa <norbert.federa@thincast.com> 2011, Stephen Erisman @@ -2145,17 +2743,24 @@ Copyright: 2011, Vic Lee License: Apache (v2.0) FIXME -Files: channels/tsmf/client/oss/tsmf_oss.c -Copyright: 2015, Rozhuk Ivan <rozhuk.im@gmail.com> -License: Apache (v2.0) - FIXME - Files: libfreerdp/codec/nsc_types.h Copyright: 2011, Samsung, Author Jiten Pathy 2012, Vic Lee License: Apache (v2.0) FIXME +Files: LICENSE +Copyright: NONE +License: Apache (v2.0) + FIXME + +Files: channels/sshagent/server/sshagent_main.c +Copyright: 2012-2013, Jay Sorg + 2012-2013, Laxmikant Rashinkar + 2017, Ben Cohen +License: Apache (v2.0) BSD (2 clause) + FIXME + Files: libfreerdp/codec/progressive.h Copyright: 2017, Armin Novak <anovak@thincast.com> 2017, Thincast Technologies GmbH @@ -2167,6 +2772,28 @@ Copyright: 2011, Vic Lee License: Apache (v2.0) CC0 FIXME +Files: uwac/libuwac/CMakeLists.txt +Copyright: 2015, David FORT <contact@hardening-consulting.com> +License: Apache (v2.0) GENERATED FILE + FIXME + +Files: cmake/FindGStreamer_1_0.cmake +Copyright: 2012, Raphael Kubo da Costa <rakuco@webkit.org> +License: BSD (2 clause) + FIXME + +Files: cmake/Findlibusb-1.0.cmake +Copyright: 2006, Andreas Schneider <mail@cynapses.org> + 2008, Kyle Machulis <kyle@nonpolynomial.com> +License: BSD (3 clause) + FIXME + +Files: cmake/AndroidToolchain.cmake +Copyright: 2010-2011, Ethan Rublee + 2011-2014, Andrey Kamaev +License: BSD (3 clause) + FIXME + Files: winpr/libwinpr/crt/casing.c Copyright: was claimed by the wine License: GENERATED FILE @@ -2201,7 +2828,145 @@ Copyright: 2014, Hardening <contact@hardening-consulting.com> License: NTP (legal disclaimer) FIXME +Files: cmake/WindowsDLLVersion.rc.in +Copyright: 2011, -@RC_VERSION_YEAR@" +License: UNKNOWN + FIXME + +Files: cmake/FindOpenSSL.cmake +Copyright: 2006, Alexander Neundorf <neundorf@kde.org> + 2006-2009, Kitware, Inc. + 2009-2011, Mathieu Malaterre <mathieu.malaterre@gmail.com> +License: UNKNOWN + FIXME + +Files: cmake/FindDBus.cmake +Copyright: 2006, Alexander Neundorf, <neundorf@kde.org> + 2008, Kevin Kofler, <kevin.kofler@chello.at> +License: UNKNOWN + FIXME + +Files: cmake/compat_2.8.11/WriteBasicConfigVersionFile.cmake +Copyright: 2004-2009, Kitware, Inc. + 2008-2011, Alexander Neundorf, <neundorf@kde.org> +License: UNKNOWN + FIXME + +Files: cmake/FindUUID.cmake +Copyright: 2006, Andreas Schneider <mail@cynapses.org> +License: UNKNOWN + FIXME + +Files: uwac/protocols/ivi-application.xml +Copyright: 2013, BMW Car IT GmbH + 2013, DENSO CORPORATION +License: UNKNOWN + FIXME + +Files: packaging/rpm/freerdp-nightly.spec +Copyright: 2015, Bernhard Miklautz <bernhard.miklautz@shacknet.at> +License: UNKNOWN + FIXME + Files: winpr/libwinpr/thread/test/TestThreadExitThread.c Copyright: 2015, Hewlett-Packard Development Company, L.P. License: UNKNOWN FIXME + +Files: uwac/protocols/xdg-shell.xml +Copyright: 2008-2013, Kristian Høgsberg + 2010-2013, Intel Corporation + 2013, Jasper St. Pierre + 2013, Rafael Antognolli +License: UNKNOWN + FIXME + +Files: cmake/FindImageMagick.cmake +Copyright: 2007-2008, Miguel A. Figueroa-Villanueva <miguelf at ieee dot org> + 2007-2009, Kitware, Inc. + 2012, Rolf Eike Beer <eike@sf-mail.de> +License: UNKNOWN + FIXME + +Files: cmake/FindDocBookXSL.cmake +Copyright: 2010, Luigi Toscano, <luigi.toscano@tiscali.it> +License: UNKNOWN + FIXME + +Files: cmake/MergeStaticLibs.cmake +Copyright: 2012, Modelon AB +License: UNKNOWN + FIXME + +Files: cmake/FindUDev.cmake +Copyright: 2011, Petr Vanek <petr@scribus.info> +License: UNKNOWN + FIXME + +Files: cmake/FindDevD.cmake +Copyright: 2015, Rozhuk Ivan <rozhuk.im@gmail.com> +License: UNKNOWN + FIXME + +Files: cmake/FindGStreamer_0_10.cmake +Copyright: 2006, Tim Beaulen <tbscope@gmail.com> +License: UNKNOWN + FIXME + +Files: packaging/deb/freerdp-nightly/freerdp-nightly-dev.lintian-overrides +Copyright: -file dir-or-file-in-opt +License: UNKNOWN + FIXME + +Files: debian/copyright +Copyright: -format/1.0/ +License: UNKNOWN + FIXME + +Files: resources/FreeRDP_Install.bmp +Copyright: bνrÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mʺoº§a•AbGQ4Q4Z> + ”QÌ»pijdîéÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ��ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïëߟ‰C¢ŒH£J£J£J£J£J£J£J£J£J£J£J£J£J£J¤ŽK†DO1R5S6R5O1°œW˺oijdïêÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ��ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøöñ£ŒI¡‹H£J£J£J£J£J£J£J£J£J£J£J£J£J£J¥L”}=M0R5S6Q3X; +License: UNKNOWN + FIXME + +Files: resources/FreeRDP_Icon_96px.ico +Copyright: bÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿǵlÿ˜ƒCÿR4ÿR5ÿS6ÿS6ÿS6ÿN0�ÿT8ÿgP&ÿfO%ÿQ3ÿL-�ÿU8ÿ®šVÿÈ·mÿÈ·mÿÈ·mÿȶl£��������������������������������������������������������������������������������������������������������È·m÷È·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿº¨aÿU8ÿJ+�ÿçäÝÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿçãÜÿH)�ÿO1ÿ‰r5ÿ˺oÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿ©–SÿV9 ÿO2ÿR5ÿQ4ÿ€pPÿØâÞÿàíëÿàíëÿÜçäÿž—€ÿN1ÿya(ÿË»pÿÈ·mÿÈ·mÿÈ·m¦��������������������������������������������������������������������������������������������������������ȶmÿÈ·mþÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿʹoÿŽw:ÿJ,�ÿ„oMÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿlIÿN1�ÿS5ÿɸnÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿǶlÿɸnÿÅ´kÿƒk0ÿ + bÿɸmÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿȶmÿȶm‰��������������������������������������������������������������������������������������������������������������������È·lȶmßǶmÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿǶlÿ̼qÿ²ŸYÿjOÿW: ÿR4ÿR5ÿR5ÿR5ÿR5ÿR5ÿR5ÿR4ÿT7ÿ[? + •Rÿ‰r6ÿrX!ÿbGÿ@ÿ@ÿ^CÿjPÿ}e+ÿ™„Dÿ¿­eÿͼqÿÈ·mÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÁ¯gÿš„Dÿ†n3ÿ}e+ÿg-ÿv9í©•R)����������������������������������������������������������������������������������������������������������������������������È·mõÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿǶlÿÈ·mÿÈ·mÿÈ·mÿ±hÿ¿­eÿ½«dÿ½«dÿ¾¬dÿÁ¯gÿÅ´jÿɸmÿÈ·mÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÅ´jÿi.ÿS6ÿQ4ÿQ4ÿQ4ÿR4êU8��������������������������������������������������������������������������������������������������������������������Ƕm�����È·lgÈ·lÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿ½«cÿY< + ȶlÈ·m���������������������������������������������������������������������������������������������������������������������������������������������������������£J£J룍Jÿ¢ŒIÿ¥Lÿ¼ªbÿɹnÿǶlÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mþÈ·mÿÈ·mÝÈ·m����������������������������������������������������������������������������������������������������������������������������������������������������������������£J£J룍Jÿ£Jÿ¢ŒIÿ£Jÿ¶£ÿɸnÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿȶmþÈ·mÿÈ·múȶm����Ƕl�������������������������������������������������������������������������������������������������������������������������������������������������������������£J£J룍Jÿ£Jÿ£Jÿ£Jÿ¢ŒIÿ³ŸYÿƵkÿÈ·mÿǶlÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mþǶlÿȶlòǶl/����È·l�����������������������������������������������������������������������������������������������������������������������������������������������������������������£J£J룍Jÿ£Jÿ£Jÿ£Jÿ¢ŒIÿ¡‹Hÿ¬˜SÿÀ­eÿɸnÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mþÈ·mÿǶlçÈ·m=����È·m���������������������������������������������������������������������������������������������������������������������������������������������������������������������£J£J룍Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ¢ŒIÿ¥Lÿµ¢ÿÈ·mÿÈ·mÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mþȶmÿÈ·m×È·m��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������£J¢J颌Iÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ¢ŒIÿ¡‹Hÿ©”PÿÁ¯fÿǶlÿÈ·mÿÈ·mÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÇ·mþÈ·mÿÇ·lÿȶlùÇ·l§È·m�����È·l�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������£J£JÚ¢Iÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ¢ŒIÿ¢ŒIÿ¯œVÿ¾«dÿɹnÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mþÈ·mÿÈ·mÿÇ·mÐǶmV��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������£J£JÚ¢Iÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ¢ŒIÿ¢ŒIÿ¤ŽKÿ©”Pÿ¾¬cÿɸnÿÈ·mÿÈ·mÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mòÈ·miȶl��������È·m�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������£J£JÊ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ£Jÿ¢ŒIÿ¡ŠHÿ§’Nÿ¹¦^ÿIJiÿƵkÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿǶlÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·lÿǶm¢��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������£ŒI +License: UNKNOWN + FIXME + +Files: docs/FreeRDP.vsd +Copyright: –ÿÿÿˆX2‚P&~J P'‘dAžwW¦‚e÷ôñ¨•L"N$€N$N%žwWžwWÒÀ²ÿÿÿ}IƒQ'|IO&”jGžwW®Žsÿÿÿ£~aN$L"ƒQ)‰[4žwWžwWæÝÕïéä~K!‚P&€M#}J ›sRžwW©–ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿƯ}I€N%¡| +License: UNKNOWN + FIXME + +Files: resources/FreeRDP.ico +Copyright: šƒ�ªœ„�¦¡Œ�´¬™�¸¬˜�º¯œ�º·ž�À±„�´‰�ƹ‘�˾™�ż¬�ÏÀ‚�Є�Óŋ�ÔǏ�Îß�ÕȒ�ØÍš�ÜÑ£�ÝÓ¦�ßÖ¬�ÌĶ�Èʶ�ÎÆ¹�ÐÈ»�àÖ®�à×°�áØ°�âÙ´�ÛÕË�ÜÖÌ�áÛÓ�èäÞ�ëçâ�ëèã�ìéä�òðì�æóó�ìûý�ûúù�üüû�ýýý�����/��P"��p0��>��°M��Ï[��ði��ÿy�ÿŠ1�ÿQ�ÿ¯q�ÿÁ‘�ÿÒ±�ÿåÑ�ÿÿÿ�����/��P��p�� ��° + Ï��Âð��Ñÿ�Øÿ1�ÞÿQ�ãÿq�éÿ‘�ïÿ±�öÿÑ�ÿÿÿ�����/&��PA��p[��t��°Ž��Ï©��ðÃ��ÿÒ�ÿØ1�ÿÝQ�ÿäq�ÿê‘�ÿð±�ÿöÑ�ÿÿÿ�����/��P"��p0��>��°M��Ï[��ði��ÿy�ÿŠ1�ÿQ�ÿ¯q�ÿÁ‘�ÿÒ±�ÿåÑ�ÿÿÿ�����/��P��p�� ��° +License: UNKNOWN + FIXME + +Files: winpr/libwinpr/utils/test/lodepng_32bit.bmp +Copyright: «�î15�í&+�ì!%�ì %�ì$�ì#�ì#�ì#�ì#�ì#�ì#�ì#�ì#�ì#�ì#�ì$�ì$�ì$�ì$�ì %�ì!%�ì!%�ì"'�í#(�í%*�í(,�í(,�í�í+0�í/3�í.2�î15�î16�î38�î49�î6:�î7;�î7;�î8<�î8<�î8<�î8<�î8<�î8<�î8<�î8<�î8=�î8=�ï;?�ï;?�ï@D�ïAF�ðIM�ðJN�ñSW�ñUY�ñ`�ñ +License: UNKNOWN + FIXME + +Files: resources/FreeRDP_OSX.icns +Copyright: »eÈ,ë/¯T} D&o6ۍ,ª=‘z1[4ð'Yó¿©ù¨/P¦ + ¾¹ÆkÌÙRFÊ`±9’w0ૃÖ�Dáw)*‰e/&ù»K.ìy”}H‡Õ#ODXÞ+R§"4f¢´‘N@æIååèÀRE{cªL'Où[H¶.)Ûû·ýþ,üÄ¢âzæa5­Ej‡;C5Ý«YÃý"ÚëRÖÒ&«5’ý'i + Ã[ÿ3dçW§kÁ÷¼ýÀ¼‘¿u‘<³¶“œtžÂµÿ(ƒÊE + Ì Ïñd{øœÇ©ád½Þø¨J4—oˆãú†Ò + ̑O3„5-Z$äX—`(þ×0ðÑ%–8Ä_"€U:j%¨Küˆ[”/ñäm€ªÒ¼rcÀW9îMÁñÚÈÅÊ6Qv`SË#Ꙇ[c%V”ÅÈM¡È¾î�ȏø©&0‘ŸÞçN*© 復§5# + Ñ`Ly%˝ ºˆm + ÑÕÐV»‚þ†gÃÛ_Å>ÙόM؝õ?1nWù3ãW¯ò^:‰HÄ䥷Ô#EŸÎÄ4Még*o–C·Åg©pÇ_ʃ3Ì˧LŽéøaæåc)_€ðZIAϼÚ}æÑ÷�)0ªñN + ٓm´@Én"RØï %vQ + áµóëí2FÛ © ã>®õ:;Ï­^ã + åÌÂGxº—<ÐÌMªtč)ó™,0„èDcFÅB³Ÿç#uŠ6ã3ÁÊ~k$Ê«1i¹åަpåÝ’¼œ¢W÷.ÊBjï;ý &&ýG™O·,~æŒ(z“bÌ´Q%ù¡µ + ë‰9—!&¥$1'>föo§BϘ¢ã"@ŠM›. úZîky±“¬Oò§Ð,Öþ5lLÀÛè3%%Äá£Ñ¥öH(ø,5ûÃkëh8ßæDÄphF¿ŽÆ)^L¼F%ÅV‚þe&Sœ¾˜*B.FMUš?Úe[ñL0ðtÖPm>ÁëKr~FK/E€+ãüèP«'kÓ˜”U4ŠàŽYìÍ_éÌ.Ì¥Íy2-ò¼àmþÿ#Љ:U2›“õŠMÒÒý¿ŸÄAóŸc‰zÇ<—Åez‘rO»l¤ + ðÙÕ×o$qÃÐ(±ÊÆìãS—úzýyy‡øºx`àÌCDâ=¤ïmϼÞ}æñ÷œ€)-«¯,¸L=ô¤I»Áî¿Ø.aÓ²z¬æOÙUÅï“9ÕxÖ7’˜9#[n¯*Ðçͬ^¼*ïÊM+pö6SŸ‡ + ÷#U–k4Ž(cz[Éð~ðáäØÝ +License: UNKNOWN + FIXME + From 0c0c5ed5adc9c8dab9c5a148c5b9a1d84e738cf3 Mon Sep 17 00:00:00 2001 From: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Wed, 9 May 2018 22:16:31 +0200 Subject: [PATCH 07/11] debian/copyright: Update copyright attributions. --- debian/copyright | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/debian/copyright b/debian/copyright index 87c2725..619a3d2 100644 --- a/debian/copyright +++ b/debian/copyright @@ -199,8 +199,6 @@ Files: channels/client/addin.h rdtk/librdtk/rdtk_text_field.c rdtk/librdtk/rdtk_text_field.h rdtk/sample/rdtk_x11.c - scripts/TimeZones.cs - scripts/WindowsZones.cs scripts/xkb.pl server/Mac/mf_rdpsnd.h server/Sample/sf_audin.h @@ -1475,13 +1473,6 @@ Copyright: 2011, Vic Lee 2017, Thincast Technologies GmbH License: Apache-2.0 -Files: libfreerdp/primitives/prim_YUV_opt.c -Copyright: 2014, Thomas Erbesdobler - 2016-2017, Armin Novak <armin.novak@thincast.com> - 2016-2017, Norbert Federa <norbert.federa@thincast.com> - 2016-2017, Thincast Technologies GmbH -License: Apache-2.0 - Files: libfreerdp/core/fastpath.c Copyright: 2011, Vic Lee 2014, Norbert Federa <norbert.federa@thincast.com> @@ -1841,11 +1832,6 @@ Copyright: 2010-2011, Ethan Rublee 2011-2014, Andrey Kamaev License: BSD-3-clause -Files: cmake/AutoVersioning.cmake -Copyright: 2011, O.S. Systems Software Ltda. - 2011, Otavio Salvador <otavio@ossystems.com.br> -License: Apache-2.0 - Files: cmake/ConfigOptionsAndroid.cmake cmake/CheckCmakeCompat.cmake Copyright: 2013 Thincast Technologies GmbH From a3e4ea9854fd25df3c14078e98df8752e032f3ae Mon Sep 17 00:00:00 2001 From: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Wed, 9 May 2018 22:16:59 +0200 Subject: [PATCH 08/11] debian/copyright: Add Comment: field. Explain why we pack our own orig tarball. --- debian/copyright | 3 +++ 1 file changed, 3 insertions(+) diff --git a/debian/copyright b/debian/copyright index 619a3d2..f2aa896 100644 --- a/debian/copyright +++ b/debian/copyright @@ -2,6 +2,9 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: FreeRDP Upstream-Contact: FreeRDP project <freerdp-devel@lists.sourceforge.net> Source: http://github.com/FreeRDP/FreeRDP +Comment: + Upstream Git snapshot gets repacked for Debian and we drop all non-Linux code + while doing so. Files: * Copyright: *No Copyright* From 77129cb59b8d5e7436a8396dd32f5b517bd71c69 Mon Sep 17 00:00:00 2001 From: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Thu, 10 May 2018 01:05:58 +0200 Subject: [PATCH 09/11] upload to unstable (debian/2.0.0~git20180411.1.7a7b1802+dfsg1-1) --- debian/changelog | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/debian/changelog b/debian/changelog index 579e862..b251b95 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,12 +1,10 @@ -freerdp2 (2.0.0~git20170725.1.1648deb+dfsg1-7) unstable; urgency=medium - - * Team upload. +freerdp2 (2.0.0~git20180411.1.7a7b1802+dfsg1-1) unstable; urgency=medium [ Bernhard Miklautz ] - * debian/patches + * debian/patches: + add 0002-fix-nla-don-t-use-server-version.patch to fix NLA connection problems with latest Windows update. - * debian/libwinpr2-2.docs + * debian/libwinpr2-2.docs: + add to fix lintian error "missing-notice-file-for-apache-license" [ Matteo F. Vescovi ] @@ -17,7 +15,26 @@ freerdp2 (2.0.0~git20170725.1.1648deb+dfsg1-7) unstable; urgency=medium * debian/control: autotools-dev b-dep dropped * debian/rules: fix dpkg-architecture variables - -- Matteo F. Vescovi <mfv@debian.org> Thu, 15 Mar 2018 14:35:27 +0100 + [ Mike Gabriel ] + * Import Git snapshot for 2.0.0-rc2 from upstream: + - Obtained from master branch of http://github.com/FreeRDP/FreeRDP. + Commit hash: 7a7b180277a9c04809bf07a54882d7c33eeeb9f9 + * debian/patches: + + Drop 0001-Fix-gstreamer-1.0-detection.patch and + 0002-fix-nla-don-t-use-server-version.patch. Included in this Git + snapshot (i.e. 2.0.0~rc2). + + Drop 1001__Typo-Fixes.patch, 1002_macro-fix-in-man-pages.patch, + 1003_fix-FTBFS-on-kFreeBSD.patch and 1004_FreeBSD-is-not-kFreeBSD.patch. + All issues resolved upstream. + * debian/control: Bump Standards-Version: to 4.1.4. No changes needed. + * debian/copyright: + + Add Comment: field. Explain why we pack our own orig tarball. + + Update copyright attributions. + + Update autogenerated copyright.in file. + * debian/*.symbols: + + Update symbols (libfreerdp-client2-2, libfreerdp2-2 and libwinpr2-2). + + -- Mike Gabriel <sunweaver@debian.org> Wed, 09 May 2018 21:43:46 +0200 freerdp2 (2.0.0~git20170725.1.1648deb+dfsg1-6) unstable; urgency=medium From 5c62b4e3fd991ab2b6f916ecd3a83e2a2afb93bd Mon Sep 17 00:00:00 2001 From: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Tue, 15 May 2018 15:55:48 +0200 Subject: [PATCH 10/11] debian/patches: Add 0001_nsc-context-free-must-not-access-uninit-fields.patch. Fixes segfault in Vinagre when user mistypes the password. (Closes: #898448). --- ...t-free-must-not-access-uninit-fields.patch | 122 ++++++++++++++++++ debian/patches/series | 1 + 2 files changed, 123 insertions(+) create mode 100644 debian/patches/0001_nsc-context-free-must-not-access-uninit-fields.patch create mode 100644 debian/patches/series diff --git a/debian/patches/0001_nsc-context-free-must-not-access-uninit-fields.patch b/debian/patches/0001_nsc-context-free-must-not-access-uninit-fields.patch new file mode 100644 index 0000000..b2e4e24 --- /dev/null +++ b/debian/patches/0001_nsc-context-free-must-not-access-uninit-fields.patch @@ -0,0 +1,122 @@ +From ae765430e980ff2a1daafcb8a3d28930c9e162ac Mon Sep 17 00:00:00 2001 +From: Armin Novak <armin.novak@thincast.com> +Date: Tue, 15 May 2018 09:13:00 +0200 +Subject: [PATCH] Fixed #4647: nsc_context_free must not access possibly + uninitialized fields. + +--- + libfreerdp/codec/nsc.c | 47 ++++++++++++++++++++++----------------------- + libfreerdp/utils/profiler.c | 7 ++++--- + 2 files changed, 27 insertions(+), 27 deletions(-) + +--- a/libfreerdp/codec/nsc.c ++++ b/libfreerdp/codec/nsc.c +@@ -248,13 +248,13 @@ + return TRUE; + } + +-static void nsc_profiler_print(NSC_CONTEXT* context) ++static void nsc_profiler_print(NSC_CONTEXT_PRIV* priv) + { + PROFILER_PRINT_HEADER +- PROFILER_PRINT(context->priv->prof_nsc_rle_decompress_data) +- PROFILER_PRINT(context->priv->prof_nsc_decode) +- PROFILER_PRINT(context->priv->prof_nsc_rle_compress_data) +- PROFILER_PRINT(context->priv->prof_nsc_encode) ++ PROFILER_PRINT(priv->prof_nsc_rle_decompress_data) ++ PROFILER_PRINT(priv->prof_nsc_decode) ++ PROFILER_PRINT(priv->prof_nsc_rle_compress_data) ++ PROFILER_PRINT(priv->prof_nsc_encode) + PROFILER_PRINT_FOOTER + } + +@@ -279,7 +279,7 @@ + context->priv = (NSC_CONTEXT_PRIV*) calloc(1, sizeof(NSC_CONTEXT_PRIV)); + + if (!context->priv) +- goto error_priv; ++ goto error; + + context->priv->log = WLog_Get("com.freerdp.codec.nsc"); + WLog_OpenAppender(context->priv->log); +@@ -289,7 +289,7 @@ + context->priv->PlanePool = BufferPool_New(TRUE, 0, 16); + + if (!context->priv->PlanePool) +- goto error_PlanePool; ++ goto error; + + PROFILER_CREATE(context->priv->prof_nsc_rle_decompress_data, + "nsc_rle_decompress_data") +@@ -303,34 +303,33 @@ + /* init optimized methods */ + NSC_INIT_SIMD(context); + return context; +-error_PlanePool: +- free(context->priv); +-error_priv: +- free(context); ++error: ++ nsc_context_free(context); + return NULL; + } + + void nsc_context_free(NSC_CONTEXT* context) + { +- int i; ++ size_t i; ++ ++ if (!context) ++ return; + +- for (i = 0; i < 4; i++) ++ if (context->priv) + { +- if (context->priv->PlaneBuffers[i]) +- { ++ for (i = 0; i < 4; i++) + free(context->priv->PlaneBuffers[i]); +- context->priv->PlaneBuffers[i] = NULL; +- } ++ ++ BufferPool_Free(context->priv->PlanePool); ++ nsc_profiler_print(context->priv); ++ PROFILER_FREE(context->priv->prof_nsc_rle_decompress_data) ++ PROFILER_FREE(context->priv->prof_nsc_decode) ++ PROFILER_FREE(context->priv->prof_nsc_rle_compress_data) ++ PROFILER_FREE(context->priv->prof_nsc_encode) ++ free(context->priv); + } + + free(context->BitmapData); +- BufferPool_Free(context->priv->PlanePool); +- nsc_profiler_print(context); +- PROFILER_FREE(context->priv->prof_nsc_rle_decompress_data) +- PROFILER_FREE(context->priv->prof_nsc_decode) +- PROFILER_FREE(context->priv->prof_nsc_rle_compress_data) +- PROFILER_FREE(context->priv->prof_nsc_encode) +- free(context->priv); + free(context); + } + +--- a/libfreerdp/utils/profiler.c ++++ b/libfreerdp/utils/profiler.c +@@ -51,7 +51,9 @@ + + void profiler_free(PROFILER* profiler) + { +- stopwatch_free(profiler->stopwatch); ++ if (profiler) ++ stopwatch_free(profiler->stopwatch); ++ + free(profiler); + } + +@@ -76,7 +78,6 @@ + { + double s = stopwatch_get_elapsed_time_in_seconds(profiler->stopwatch); + double avg = profiler->stopwatch->count == 0 ? 0 : s / profiler->stopwatch->count; +- + WLog_INFO(TAG, "%-30s | %10u | %10.4fs | %8.6fs | %6.0f", + profiler->name, profiler->stopwatch->count, s, avg, profiler->stopwatch->count / s); + } diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..53bdebc --- /dev/null +++ b/debian/patches/series @@ -0,0 +1 @@ +0001_nsc-context-free-must-not-access-uninit-fields.patch From 24fd6fd1bc5acf9494827fb45b079b692b917f33 Mon Sep 17 00:00:00 2001 From: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Tue, 15 May 2018 16:18:14 +0200 Subject: [PATCH 11/11] upload to unstable (debian/2.0.0~git20180411.1.7a7b1802+dfsg1-2) --- debian/changelog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/debian/changelog b/debian/changelog index b251b95..fd9bc17 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +freerdp2 (2.0.0~git20180411.1.7a7b1802+dfsg1-2) unstable; urgency=medium + + * debian/patches: + + Add 0001_nsc-context-free-must-not-access-uninit-fields.patch. Fixes + segfault in Vinagre when user mistypes the password. (Closes: #898448). + + -- Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Tue, 15 May 2018 15:55:52 +0200 + freerdp2 (2.0.0~git20180411.1.7a7b1802+dfsg1-1) unstable; urgency=medium [ Bernhard Miklautz ]