Codebase list xrdp / upstream/0.9.12
xrdp_0.9.12.orig.tar.gz mirabilos authored 4 years ago mirabilos committed 4 years ago
65 changed file(s) with 7922 addition(s) and 4246 deletion(s). Raw diff Collapse all Expand all
0 # Release notes for xrdp v0.9.9 (2018/12/25)
1
2 # Release cycle
0 # Release notes for xrdp v0.9.12 (2019/12/28)
1
2 ## Bug fixes
3 * Fix "The log reference is NULL" error when sesman startup #1425
4 * Fix behavior when shmem_id changes #1439
5 * Make vsock config accept -1 for cid and port #1441
6 * Cleanup refresh rect and check stream bounds #1437
7 * Significant improvements in drive redirection #1449
8 * Fix build on macOS Catalina #1462
9
10 ## Other changes
11 * Proprietary microphone redirection via rdpsnd is now default off
12 RDP compatible microphone redirection is on instead #1427
13 * Skip connecting to chansrv when no channels enabled #1393
14 * Add openSUSE's pam rules #1442
15 * Do not terminate xrdp daemon when caught SIGHUP #1319
16
17 ## Known issues
18 * FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
19 xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
20 * Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
21
22 # Release notes for xrdp v0.9.11 (2019/08/19)
23
24 ## New features
25 * Suppress output (do not draw screen when client window is minimized) #1330
26 * Audio input (microphone) redirection compatible with [MS-RDPEAI](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeai/d04ffa42-5a0f-4f80-abb1-cc26f71c9452) #1369
27 * Now xrdp can listen on more than one port #1124 #1366
28
29 ## Bug fixes
30 * Fix the issue audio redirection sometimes sounds with long delay #1363
31 * Check term event for more responsive shutdown #1372
32
33 ## Known issues
34 * FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
35 xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
36 * Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
37
38 -----------------------
39
40 # Release notes for xrdp v0.9.11 (2019/08/19)
41
42 ## New features
43 * Suppress output (do not draw screen when client window is minimized) #1330
44 * Audio input (microphone) redirection compatible with [MS-RDPEAI](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeai/d04ffa42-5a0f-4f80-abb1-cc26f71c9452) #1369
45 * Now xrdp can listen on more than one port #1124 #1366
46
47 ## Bug fixes
48 * Fix the issue audio redirection sometimes sounds with long delay #1363
49 * Check term event for more responsive shutdown #1372
50
51 ## Known issues
52 * FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
53 xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
54 * Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
55
56 -----------------------
57
58 # Release notes for xrdp v0.9.10 (2019/04/18)
59
60 ## Special thanks
61 Thank you for matt335672 contributing to lots of improvements in drive redirection!
62
63 ## New features
64 * Restrict outbound (server->client) clipboard transfer, configured in `sesman.ini` #1298
65
66 ## Bug fixes
67 * Fix the issue libscp v1 not setting width but height twice #1293
68 * Fix the issue reconnecting to session causes duplicate drive entries in fuse fs #1299
69 * Fix default_wm and reconnect_sh refer wrong path after sesman caught SIGUP #1315 #1331
70 * Shutdown xrdp more responsively #1325
71 * Improve remote file lookup in drive redirection #996 #1327
72 * Overwriting & appending to existing files is are now supported #1327
73
74 ## Other changes
75 * Add Danish Keyboard #1290
76 * Put xrdp- prefix to some executables appear in man page #1313
77 * Replace some URLs from SF.net to xrdp.org #1313
78
79 ## Known issues
80 * FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
81 xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
82 * Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
83
84 -----------------------
85
86 ## Release notes for xrdp v0.9.9 (2018/12/25)
87
88 ## Release cycle
389 From the next release, release cycle will be changed from quarterly to every
490 4 months. xrdp will be released in April, August, December.
591
6 # New features
92 ## New features
793 * Disconnection by idle timeout (requires xorgxrdp v0.2.9 or later) #1227
894 * Glyph cache v2 (fixes no font issue on iOS/macOS/Android client) #367 #1235
995
10 # Bug fixes
96 ## Bug fixes
1197 * Fix xrdp-chansrv crashes caused in drive redirection #1202 #1225
1298 * Fix build with FDK AAC v2 #1257
1399 * Do not enable RemoteApp if the INFO_RAIL flag is not set (RDP-RDP proxy) #1253
14100
15 # Other changes
101 ## Other changes
16102 * Add Spanish Latin Amarican keyboard #1237 #1240 #1244
17103 * Dynamic channel improvements #1222 #1224
18104 * Remove some deprecated sesman session types #1232
19105 * Refactoring and cleanups
20106
21 # Known issues
22 * FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
23 xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
24 * Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
107 ## Known issues
108 * FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
109 xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
110 * Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
111
112 -----------------------
25113
26114 # Release notes for xrdp v0.9.8 (2018/09/25)
27115
11 [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/neutrinolabs/xrdp)
22 ![Apache-License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)
33
4 *Current Version:* 0.9.9
4 *Current Version:* 0.9.12
55
66 # xrdp - an open source RDP server
77
10391039 return -1;
10401040 #endif
10411041 }
1042
1043 /*****************************************************************************/
1044 int
1045 g_sck_vsock_bind_address(int sck, const char *port, const char *address)
1046 {
1047 #if defined(XRDP_ENABLE_VSOCK)
1048 struct sockaddr_vm s;
1049
1050 g_memset(&s, 0, sizeof(struct sockaddr_vm));
1051 s.svm_family = AF_VSOCK;
1052 s.svm_port = atoi(port);
1053 s.svm_cid = atoi(address);
1054
1055 return bind(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_vm));
1056 #else
1057 return -1;
1058 #endif
1059 }
1060
10421061
10431062 #if defined(XRDP_ENABLE_IPV6)
10441063 /*****************************************************************************/
38223841 return 0;
38233842 }
38243843
3844 /*****************************************************************************/
3845 int
3846 g_tcp4_socket(void)
3847 {
3848 #if defined(XRDP_ENABLE_IPV6ONLY)
3849 return -1;
3850 #else
3851 int rv;
3852 int option_value;
3853 socklen_t option_len;
3854
3855 rv = socket(AF_INET, SOCK_STREAM, 0);
3856 if (rv < 0)
3857 {
3858 return -1;
3859 }
3860 option_len = sizeof(option_value);
3861 if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR,
3862 (char *) &option_value, &option_len) == 0)
3863 {
3864 if (option_value == 0)
3865 {
3866 option_value = 1;
3867 option_len = sizeof(option_value);
3868 if (setsockopt(rv, SOL_SOCKET, SO_REUSEADDR,
3869 (char *) &option_value, option_len) < 0)
3870 {
3871 }
3872 }
3873 }
3874 return rv;
3875 #endif
3876 }
3877
3878 /*****************************************************************************/
3879 int
3880 g_tcp4_bind_address(int sck, const char *port, const char *address)
3881 {
3882 #if defined(XRDP_ENABLE_IPV6ONLY)
3883 return -1;
3884 #else
3885 struct sockaddr_in s;
3886
3887 memset(&s, 0, sizeof(s));
3888 s.sin_family = AF_INET;
3889 s.sin_addr.s_addr = htonl(INADDR_ANY);
3890 s.sin_port = htons((uint16_t) atoi(port));
3891 if (inet_aton(address, &s.sin_addr) < 0)
3892 {
3893 return -1; /* bad address */
3894 }
3895 if (bind(sck, (struct sockaddr*) &s, sizeof(s)) < 0)
3896 {
3897 return -1;
3898 }
3899 return 0;
3900 #endif
3901 }
3902
3903 /*****************************************************************************/
3904 int
3905 g_tcp6_socket(void)
3906 {
3907 #if defined(XRDP_ENABLE_IPV6)
3908 int rv;
3909 int option_value;
3910 socklen_t option_len;
3911
3912 rv = socket(AF_INET6, SOCK_STREAM, 0);
3913 if (rv < 0)
3914 {
3915 return -1;
3916 }
3917 option_len = sizeof(option_value);
3918 if (getsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY,
3919 (char *) &option_value, &option_len) == 0)
3920 {
3921 #if defined(XRDP_ENABLE_IPV6ONLY)
3922 if (option_value == 0)
3923 {
3924 option_value = 1;
3925 #else
3926 if (option_value != 0)
3927 {
3928 option_value = 0;
3929 #endif
3930 option_len = sizeof(option_value);
3931 if (setsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY,
3932 (char *) &option_value, option_len) < 0)
3933 {
3934 }
3935 }
3936 }
3937 option_len = sizeof(option_value);
3938 if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR,
3939 (char *) &option_value, &option_len) == 0)
3940 {
3941 if (option_value == 0)
3942 {
3943 option_value = 1;
3944 option_len = sizeof(option_value);
3945 if (setsockopt(rv, SOL_SOCKET, SO_REUSEADDR,
3946 (char *) &option_value, option_len) < 0)
3947 {
3948 }
3949 }
3950 }
3951 return rv;
3952 #else
3953 return -1;
3954 #endif
3955 }
3956
3957 /*****************************************************************************/
3958 int
3959 g_tcp6_bind_address(int sck, const char *port, const char *address)
3960 {
3961 #if defined(XRDP_ENABLE_IPV6)
3962 int rv;
3963 int error;
3964 struct addrinfo hints;
3965 struct addrinfo *list;
3966 struct addrinfo *i;
3967
3968 rv = -1;
3969 memset(&hints, 0, sizeof(hints));
3970 hints.ai_family = AF_UNSPEC;
3971 hints.ai_flags = 0;
3972 hints.ai_socktype = SOCK_STREAM;
3973 hints.ai_protocol = IPPROTO_TCP;
3974 error = getaddrinfo(address, port, &hints, &list);
3975 if (error == 0)
3976 {
3977 i = list;
3978 while ((i != NULL) && (rv < 0))
3979 {
3980 rv = bind(sck, i->ai_addr, i->ai_addrlen);
3981 i = i->ai_next;
3982 }
3983 freeaddrinfo(list);
3984 }
3985 else
3986 {
3987 return -1;
3988 }
3989 return rv;
3990 #else
3991 return -1;
3992 #endif
3993 }
7070 int g_tcp_bind(int sck, const char *port);
7171 int g_sck_local_bind(int sck, const char* port);
7272 int g_sck_vsock_bind(int sck, const char* port);
73 int g_sck_vsock_bind_address(int sck, const char *port, const char *address);
7374 int g_tcp_bind_address(int sck, const char* port, const char* address);
7475 int g_sck_listen(int sck);
7576 int g_tcp_accept(int sck);
182183 int g_shmdt(const void *shmaddr);
183184 int g_gethostname(char *name, int len);
184185 int g_mirror_memcpy(void *dst, const void *src, int len);
186 int g_tcp4_socket(void);
187 int g_tcp4_bind_address(int sck, const char *port, const char *address);
188 int g_tcp6_socket(void);
189 int g_tcp6_bind_address(int sck, const char *port, const char *address);
185190
186191 /* glib-style wrappers */
187192 #define g_new(struct_type, n_structs) \
711711 now = g_time3();
712712 if (now - start_time < timeout)
713713 {
714 g_sleep(timeout / 5);
714 g_sleep(100);
715715 }
716716 else
717717 {
718718 self->status = TRANS_STATUS_DOWN;
719719 return 1;
720720 }
721 if (self->is_term != NULL)
722 {
723 if (self->is_term())
724 {
725 self->status = TRANS_STATUS_DOWN;
726 return 1;
727 }
728 }
721729 }
722730 }
723731 }
747755 now = g_time3();
748756 if (now - start_time < timeout)
749757 {
750 g_sleep(timeout / 5);
758 g_sleep(100);
751759 }
752760 else
753761 {
754762 self->status = TRANS_STATUS_DOWN;
755763 return 1;
764 }
765 if (self->is_term != NULL)
766 {
767 if (self->is_term())
768 {
769 self->status = TRANS_STATUS_DOWN;
770 return 1;
771 }
756772 }
757773 }
758774 }
858874
859875 g_tcp_set_non_blocking(self->sck);
860876
861 if (g_sck_vsock_bind(self->sck, port) == 0)
877 if (g_sck_vsock_bind_address(self->sck, port, address) == 0)
862878 {
863879 if (g_tcp_listen(self->sck) == 0)
864880 {
868884 }
869885 }
870886 }
871
887 else if (self->mode == TRANS_MODE_TCP4) /* tcp4 */
888 {
889 self->sck = g_tcp4_socket();
890 if (self->sck < 0)
891 {
892 return 1;
893 }
894 g_tcp_set_non_blocking(self->sck);
895 if (g_tcp4_bind_address(self->sck, port, address) == 0)
896 {
897 if (g_tcp_listen(self->sck) == 0)
898 {
899 self->status = TRANS_STATUS_UP; /* ok */
900 self->type1 = TRANS_TYPE_LISTENER; /* listener */
901 return 0;
902 }
903 }
904 }
905 else if (self->mode == TRANS_MODE_TCP6) /* tcp6 */
906 {
907 self->sck = g_tcp6_socket();
908 if (self->sck < 0)
909 {
910 return 1;
911 }
912 g_tcp_set_non_blocking(self->sck);
913 if (g_tcp6_bind_address(self->sck, port, address) == 0)
914 {
915 if (g_tcp_listen(self->sck) == 0)
916 {
917 self->status = TRANS_STATUS_UP; /* ok */
918 self->type1 = TRANS_TYPE_LISTENER; /* listener */
919 return 0;
920 }
921 }
922 }
872923 return 1;
873924 }
874925
2323 #include "arch.h"
2424 #include "parse.h"
2525
26 #define TRANS_MODE_TCP 1
26 #define TRANS_MODE_TCP 1 /* tcp6 if defined, else tcp4 */
2727 #define TRANS_MODE_UNIX 2
2828 #define TRANS_MODE_VSOCK 3
29 #define TRANS_MODE_TCP4 4 /* tcp4 only */
30 #define TRANS_MODE_TCP6 6 /* tcp6 only */
2931
3032 #define TRANS_TYPE_LISTENER 1
3133 #define TRANS_TYPE_SERVER 2
155155 int no_orders_supported;
156156 int use_cache_glyph_v2;
157157 int rail_enable;
158 int suppress_output;
158159 };
159160
160161 #endif
542542 #define RDP_DATA_PDU_POINTER 27
543543 #define RDP_DATA_PDU_INPUT 28
544544 #define RDP_DATA_PDU_SYNCHRONISE 31
545 #define PDUTYPE2_REFRESH_RECT 33
545546 #define RDP_DATA_PDU_PLAY_SOUND 34
546547 #define RDP_DATA_PDU_LOGON 38
547548 #define RDP_DATA_PDU_FONT2 39
00 #! /bin/sh
11 # Guess values for system-dependent variables and create Makefiles.
2 # Generated by GNU Autoconf 2.69 for xrdp 0.9.9.
2 # Generated by GNU Autoconf 2.69 for xrdp 0.9.12.
33 #
44 # Report bugs to <xrdp-devel@googlegroups.com>.
55 #
589589 # Identity of this package.
590590 PACKAGE_NAME='xrdp'
591591 PACKAGE_TARNAME='xrdp'
592 PACKAGE_VERSION='0.9.9'
593 PACKAGE_STRING='xrdp 0.9.9'
592 PACKAGE_VERSION='0.9.12'
593 PACKAGE_STRING='xrdp 0.9.12'
594594 PACKAGE_BUGREPORT='xrdp-devel@googlegroups.com'
595595 PACKAGE_URL=''
596596
657657 OPENSSL_LIBS
658658 OPENSSL_CFLAGS
659659 DLOPEN_LIBS
660 XRDP_RDPSNDAUDIN_FALSE
661 XRDP_RDPSNDAUDIN_TRUE
660662 XRDP_RFXCODEC_FALSE
661663 XRDP_RFXCODEC_TRUE
662664 XRDP_PAINTER_FALSE
855857 enable_pixman
856858 enable_painter
857859 enable_rfxcodec
860 enable_rdpsndaudin
858861 with_x
859862 enable_strict_locations
860863 with_pkgconfigdir
14231426 # Omit some internal or obsolete options to make the list less imposing.
14241427 # This message is too long to be a string in the A/UX 3.1 sh.
14251428 cat <<_ACEOF
1426 \`configure' configures xrdp 0.9.9 to adapt to many kinds of systems.
1429 \`configure' configures xrdp 0.9.12 to adapt to many kinds of systems.
14271430
14281431 Usage: $0 [OPTION]... [VAR=VALUE]...
14291432
14971500
14981501 if test -n "$ac_init_help"; then
14991502 case $ac_init_help in
1500 short | recursive ) echo "Configuration of xrdp 0.9.9:";;
1503 short | recursive ) echo "Configuration of xrdp 0.9.12:";;
15011504 esac
15021505 cat <<\_ACEOF
15031506
15401543 --disable-painter Do not use included painter library (default: no)
15411544 --disable-rfxcodec Do not use included librfxcodec library (default:
15421545 no)
1546 --enable-rdpsndaudin Use rdpsnd audio in (default: no)
15431547 --enable-strict-locations
15441548 Use standard Autoconf install directories unless
15451549 overridden (default: use /etc and /var)
16621666 test -n "$ac_init_help" && exit $ac_status
16631667 if $ac_init_version; then
16641668 cat <<\_ACEOF
1665 xrdp configure 0.9.9
1669 xrdp configure 0.9.12
16661670 generated by GNU Autoconf 2.69
16671671
16681672 Copyright (C) 2012 Free Software Foundation, Inc.
20312035 This file contains any messages produced by compilers while
20322036 running configure, to aid debugging if configure makes a mistake.
20332037
2034 It was created by xrdp $as_me 0.9.9, which was
2038 It was created by xrdp $as_me 0.9.12, which was
20352039 generated by GNU Autoconf 2.69. Invocation command line was
20362040
20372041 $ $0 $@
28962900
28972901 # Define the identity of the package.
28982902 PACKAGE='xrdp'
2899 VERSION='0.9.9'
2903 VERSION='0.9.12'
29002904
29012905
29022906 cat >>confdefs.h <<_ACEOF
1296112965 fi
1296212966
1296312967
12968 # Check whether --enable-rdpsndaudin was given.
12969 if test "${enable_rdpsndaudin+set}" = set; then :
12970 enableval=$enable_rdpsndaudin;
12971 else
12972 enable_rdpsndaudin=no
12973 fi
12974
12975 if test x$enable_rdpsndaudin = xyes; then
12976 XRDP_RDPSNDAUDIN_TRUE=
12977 XRDP_RDPSNDAUDIN_FALSE='#'
12978 else
12979 XRDP_RDPSNDAUDIN_TRUE='#'
12980 XRDP_RDPSNDAUDIN_FALSE=
12981 fi
12982
12983
1296412984 # Don't fail without working nasm if rfxcodec is not enabled
1296512985 if test "x$enable_rfxcodec" != xyes; then
1296612986 with_simd=no
1465314673 as_fn_error $? "conditional \"XRDP_RFXCODEC\" was never defined.
1465414674 Usually this means the macro was only invoked conditionally." "$LINENO" 5
1465514675 fi
14676 if test -z "${XRDP_RDPSNDAUDIN_TRUE}" && test -z "${XRDP_RDPSNDAUDIN_FALSE}"; then
14677 as_fn_error $? "conditional \"XRDP_RDPSNDAUDIN\" was never defined.
14678 Usually this means the macro was only invoked conditionally." "$LINENO" 5
14679 fi
1465614680
1465714681 : "${CONFIG_STATUS=./config.status}"
1465814682 ac_write_fail=0
1505015074 # report actual input values of CONFIG_FILES etc. instead of their
1505115075 # values after options handling.
1505215076 ac_log="
15053 This file was extended by xrdp $as_me 0.9.9, which was
15077 This file was extended by xrdp $as_me 0.9.12, which was
1505415078 generated by GNU Autoconf 2.69. Invocation command line was
1505515079
1505615080 CONFIG_FILES = $CONFIG_FILES
1511615140 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
1511715141 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
1511815142 ac_cs_version="\\
15119 xrdp config.status 0.9.9
15143 xrdp config.status 0.9.12
1512015144 configured by $0, generated by GNU Autoconf 2.69,
1512115145 with options \\"\$ac_cs_config\\"
1512215146
1699217016 echo " pam $enable_pam"
1699317017 echo " kerberos $enable_kerberos"
1699417018 echo " debug $enable_xrdpdebug"
17019 echo " rdpsndaudin $enable_rdpsndaudin"
1699517020 echo ""
1699617021 echo " strict_locations $enable_strict_locations"
1699717022 echo " prefix $prefix"
00 # Process this file with autoconf to produce a configure script
11
22 AC_PREREQ(2.65)
3 AC_INIT([xrdp], [0.9.9], [xrdp-devel@googlegroups.com])
3 AC_INIT([xrdp], [0.9.12], [xrdp-devel@googlegroups.com])
44 AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in)
55 AM_INIT_AUTOMAKE([1.7.2 foreign])
66 AC_CONFIG_MACRO_DIR([m4])
149149 [], [enable_rfxcodec=yes])
150150 AM_CONDITIONAL(XRDP_RFXCODEC, [test x$enable_rfxcodec = xyes])
151151
152 AC_ARG_ENABLE(rdpsndaudin, AS_HELP_STRING([--enable-rdpsndaudin],
153 [Use rdpsnd audio in (default: no)]),
154 [], [enable_rdpsndaudin=no])
155 AM_CONDITIONAL(XRDP_RDPSNDAUDIN, [test x$enable_rdpsndaudin = xyes])
156
152157 # Don't fail without working nasm if rfxcodec is not enabled
153158 if test "x$enable_rfxcodec" != xyes; then
154159 with_simd=no
389394 echo " pam $enable_pam"
390395 echo " kerberos $enable_kerberos"
391396 echo " debug $enable_xrdpdebug"
397 echo " rdpsndaudin $enable_rdpsndaudin"
392398 echo ""
393399 echo " strict_locations $enable_strict_locations"
394400 echo " prefix $prefix"
196196 have session management rights.
197197
198198 .TP
199 \fBRestrictOutboundClipboard\fR=\fI[true|false]\fR
200 If set to \fB1\fR, \fBtrue\fR or \fByes\fR, will restrict the clipboard
201 outbound from the server, to prevent data copied inside the xrdp session
202 to be be pasted in the client host. Default value is \fBfalse\fR.
203
204 .TP
199205 \fBAlwaysGroupCheck\fR=\fI[true|false]\fR
200206 If set to \fB1\fR, \fBtrue\fR or \fByes\fR, require group membership even
201207 if the group specified in \fBTerminalServerUsers\fR doesn't exist.
217223 \fBFuseMountName\fR=\fIstring\fR
218224 Directory for drive redirection, relative to the user home directory.
219225 Created if it doesn't exist. If not specified, defaults to \fIxrdp_client\fR.
226
227 .TP
228 \fBFileUmask\fR=\fImode\fR
229 Additional umask to apply to files in the \fBFuseMountName\fR directory.
230 The default value of 077 prevents other users on the system from reading
231 files on your redirected drives. This may not be approprate for all
232 environents, and so you can change this value to allow other users to
233 access your remote files if required.
220234
221235 .SH "SESSIONS VARIABLES"
222236 All entries in the \fB[SessionVariables]\fR section are set as
2222 Output help information and exit.
2323
2424 .SH "FILES"
25 @bindir@/sesman
25 @bindir@/xrdp\-sesman
2626 .br
27 @bindir@/sesrun
27 @bindir@/xrdp\-sesrun
2828 .br
2929 @sysconfdir@/xrdp/sesman.ini
3030 .br
31 @localstatedir@/log/sesman.log
31 @localstatedir@/log/xrdp\-sesman.log
3232 .br
33 @localstatedir@/run/sesman.pid
33 @localstatedir@/run/xrdp\-sesman.pid
3434
3535 .SH "AUTHORS"
3636 Jay Sorg <jsorg71@users.sourceforge.net>
3131 Session color depth
3232
3333 .SH "FILES"
34 @bindir@/sesman
34 @bindir@/xrdp\-sesman
3535 .br
36 @bindir@/sesrun
36 @bindir@/xrdp\-sesrun
3737
3838 .SH "AUTHORS"
3939 Jay Sorg <jsorg71@users.sourceforge.net>
2929 startwm.sh
3030 xrdp.ini
3131 xrdp_keyboard.ini
32 xrdp.sh
3332
3433 /etc/xrdp/pulse
3534 default.pa
00 EXTRA_DIST = \
11 keymap-names.txt \
2 xrdp.sh \
32 xrdp-sesman.service.in \
43 xrdp.service.in
54
2928 startscriptdir=$(sysconfdir)/xrdp
3029
3130 dist_startscript_DATA = \
31 km-00000406.ini \
3232 km-00000407.ini \
3333 km-00000409.ini \
3434 km-0000040a.ini \
5959 SUBDIRS += \
6060 pam.d \
6161 pulse
62 dist_startscript_SCRIPTS = xrdp.sh
6362 if HAVE_SYSTEMD
6463 systemdsystemunit_DATA = \
6564 xrdp-sesman.service \
1212 # PARTICULAR PURPOSE.
1313
1414 @SET_MAKE@
15
1615
1716 VPATH = @srcdir@
1817 am__is_gnu_make = { \
117116 $(top_srcdir)/configure.ac
118117 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
119118 $(ACLOCAL_M4)
120 DIST_COMMON = $(srcdir)/Makefile.am \
121 $(am__dist_startscript_SCRIPTS_DIST) $(dist_startscript_DATA) \
119 DIST_COMMON = $(srcdir)/Makefile.am $(dist_startscript_DATA) \
122120 $(am__DIST_COMMON)
123121 mkinstalldirs = $(install_sh) -d
124122 CONFIG_HEADER = $(top_builddir)/config_ac.h
125123 CONFIG_CLEAN_FILES =
126124 CONFIG_CLEAN_VPATH_FILES =
127 am__dist_startscript_SCRIPTS_DIST = xrdp.sh
125 AM_V_P = $(am__v_P_@AM_V@)
126 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
127 am__v_P_0 = false
128 am__v_P_1 = :
129 AM_V_GEN = $(am__v_GEN_@AM_V@)
130 am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
131 am__v_GEN_0 = @echo " GEN " $@;
132 am__v_GEN_1 =
133 AM_V_at = $(am__v_at_@AM_V@)
134 am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
135 am__v_at_0 = @
136 am__v_at_1 =
137 SOURCES =
138 DIST_SOURCES =
139 RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
140 ctags-recursive dvi-recursive html-recursive info-recursive \
141 install-data-recursive install-dvi-recursive \
142 install-exec-recursive install-html-recursive \
143 install-info-recursive install-pdf-recursive \
144 install-ps-recursive install-recursive installcheck-recursive \
145 installdirs-recursive pdf-recursive ps-recursive \
146 tags-recursive uninstall-recursive
147 am__can_run_installinfo = \
148 case $$AM_UPDATE_INFO_DIR in \
149 n|no|NO) false;; \
150 *) (install-info --version) >/dev/null 2>&1;; \
151 esac
128152 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
129153 am__vpath_adj = case $$p in \
130154 $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
153177 $(am__cd) "$$dir" && rm -f $$files; }; \
154178 }
155179 am__installdirs = "$(DESTDIR)$(startscriptdir)" \
156 "$(DESTDIR)$(startscriptdir)" \
157180 "$(DESTDIR)$(systemdsystemunitdir)"
158 SCRIPTS = $(dist_startscript_SCRIPTS)
159 AM_V_P = $(am__v_P_@AM_V@)
160 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
161 am__v_P_0 = false
162 am__v_P_1 = :
163 AM_V_GEN = $(am__v_GEN_@AM_V@)
164 am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
165 am__v_GEN_0 = @echo " GEN " $@;
166 am__v_GEN_1 =
167 AM_V_at = $(am__v_at_@AM_V@)
168 am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
169 am__v_at_0 = @
170 am__v_at_1 =
171 SOURCES =
172 DIST_SOURCES =
173 RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
174 ctags-recursive dvi-recursive html-recursive info-recursive \
175 install-data-recursive install-dvi-recursive \
176 install-exec-recursive install-html-recursive \
177 install-info-recursive install-pdf-recursive \
178 install-ps-recursive install-recursive installcheck-recursive \
179 installdirs-recursive pdf-recursive ps-recursive \
180 tags-recursive uninstall-recursive
181 am__can_run_installinfo = \
182 case $$AM_UPDATE_INFO_DIR in \
183 n|no|NO) false;; \
184 *) (install-info --version) >/dev/null 2>&1;; \
185 esac
186181 DATA = $(dist_startscript_DATA) $(systemdsystemunit_DATA)
187182 RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
188183 distclean-recursive maintainer-clean-recursive
384379 top_srcdir = @top_srcdir@
385380 EXTRA_DIST = \
386381 keymap-names.txt \
387 xrdp.sh \
388382 xrdp-sesman.service.in \
389383 xrdp.service.in
390384
411405 #
412406 startscriptdir = $(sysconfdir)/xrdp
413407 dist_startscript_DATA = \
408 km-00000406.ini \
414409 km-00000407.ini \
415410 km-00000409.ini \
416411 km-0000040a.ini \
439434 #
440435 SUBDIRS = $(am__append_1) $(am__append_2) $(am__append_3) \
441436 $(am__append_4)
442 @LINUX_TRUE@dist_startscript_SCRIPTS = xrdp.sh
443437 @HAVE_SYSTEMD_TRUE@@LINUX_TRUE@systemdsystemunit_DATA = \
444438 @HAVE_SYSTEMD_TRUE@@LINUX_TRUE@ xrdp-sesman.service \
445439 @HAVE_SYSTEMD_TRUE@@LINUX_TRUE@ xrdp.service
477471 $(ACLOCAL_M4): $(am__aclocal_m4_deps)
478472 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
479473 $(am__aclocal_m4_deps):
480 install-dist_startscriptSCRIPTS: $(dist_startscript_SCRIPTS)
481 @$(NORMAL_INSTALL)
482 @list='$(dist_startscript_SCRIPTS)'; test -n "$(startscriptdir)" || list=; \
483 if test -n "$$list"; then \
484 echo " $(MKDIR_P) '$(DESTDIR)$(startscriptdir)'"; \
485 $(MKDIR_P) "$(DESTDIR)$(startscriptdir)" || exit 1; \
486 fi; \
487 for p in $$list; do \
488 if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
489 if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
490 done | \
491 sed -e 'p;s,.*/,,;n' \
492 -e 'h;s|.*|.|' \
493 -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
494 $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
495 { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
496 if ($$2 == $$4) { files[d] = files[d] " " $$1; \
497 if (++n[d] == $(am__install_max)) { \
498 print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
499 else { print "f", d "/" $$4, $$1 } } \
500 END { for (d in files) print "f", d, files[d] }' | \
501 while read type dir files; do \
502 if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
503 test -z "$$files" || { \
504 echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(startscriptdir)$$dir'"; \
505 $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(startscriptdir)$$dir" || exit $$?; \
506 } \
507 ; done
508
509 uninstall-dist_startscriptSCRIPTS:
510 @$(NORMAL_UNINSTALL)
511 @list='$(dist_startscript_SCRIPTS)'; test -n "$(startscriptdir)" || exit 0; \
512 files=`for p in $$list; do echo "$$p"; done | \
513 sed -e 's,.*/,,;$(transform)'`; \
514 dir='$(DESTDIR)$(startscriptdir)'; $(am__uninstall_files_from_dir)
515474
516475 mostlyclean-libtool:
517476 -rm -f *.lo
720679 done
721680 check-am: all-am
722681 check: check-recursive
723 all-am: Makefile $(SCRIPTS) $(DATA)
682 all-am: Makefile $(DATA)
724683 installdirs: installdirs-recursive
725684 installdirs-am:
726 for dir in "$(DESTDIR)$(startscriptdir)" "$(DESTDIR)$(startscriptdir)" "$(DESTDIR)$(systemdsystemunitdir)"; do \
685 for dir in "$(DESTDIR)$(startscriptdir)" "$(DESTDIR)$(systemdsystemunitdir)"; do \
727686 test -z "$$dir" || $(MKDIR_P) "$$dir"; \
728687 done
729688 install: install-recursive
779738 info-am:
780739
781740 install-data-am: install-dist_startscriptDATA \
782 install-dist_startscriptSCRIPTS install-systemdsystemunitDATA
741 install-systemdsystemunitDATA
783742 @$(NORMAL_INSTALL)
784743 $(MAKE) $(AM_MAKEFLAGS) install-data-hook
785744 install-dvi: install-dvi-recursive
825784 ps-am:
826785
827786 uninstall-am: uninstall-dist_startscriptDATA \
828 uninstall-dist_startscriptSCRIPTS \
829787 uninstall-systemdsystemunitDATA
830788
831789 .MAKE: $(am__recursive_targets) install-am install-data-am \
836794 ctags-am distclean distclean-generic distclean-libtool \
837795 distclean-tags distdir dvi dvi-am html html-am info info-am \
838796 install install-am install-data install-data-am \
839 install-data-hook install-dist_startscriptDATA \
840 install-dist_startscriptSCRIPTS install-dvi install-dvi-am \
841 install-exec install-exec-am install-html install-html-am \
842 install-info install-info-am install-man install-pdf \
843 install-pdf-am install-ps install-ps-am install-strip \
844 install-systemdsystemunitDATA installcheck installcheck-am \
845 installdirs installdirs-am maintainer-clean \
797 install-data-hook install-dist_startscriptDATA install-dvi \
798 install-dvi-am install-exec install-exec-am install-html \
799 install-html-am install-info install-info-am install-man \
800 install-pdf install-pdf-am install-ps install-ps-am \
801 install-strip install-systemdsystemunitDATA installcheck \
802 installcheck-am installdirs installdirs-am maintainer-clean \
846803 maintainer-clean-generic mostlyclean mostlyclean-generic \
847804 mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
848805 uninstall-am uninstall-dist_startscriptDATA \
849 uninstall-dist_startscriptSCRIPTS \
850806 uninstall-systemdsystemunitDATA
851807
852808 .PRECIOUS: Makefile
0 [noshift]
1 Key8=0:0
2 Key9=65307:27
3 Key10=49:49
4 Key11=50:50
5 Key12=51:51
6 Key13=52:52
7 Key14=53:53
8 Key15=54:54
9 Key16=55:55
10 Key17=56:56
11 Key18=57:57
12 Key19=48:48
13 Key20=43:43
14 Key21=65105:180
15 Key22=65288:8
16 Key23=65289:9
17 Key24=113:113
18 Key25=119:119
19 Key26=101:101
20 Key27=114:114
21 Key28=116:116
22 Key29=121:121
23 Key30=117:117
24 Key31=105:105
25 Key32=111:111
26 Key33=112:112
27 Key34=229:229
28 Key35=168:168
29 Key36=65293:13
30 Key37=65507:0
31 Key38=97:97
32 Key39=115:115
33 Key40=100:100
34 Key41=102:102
35 Key42=103:103
36 Key43=104:104
37 Key44=106:106
38 Key45=107:107
39 Key46=108:108
40 Key47=230:230
41 Key48=248:248
42 Key49=189:189
43 Key50=65505:0
44 Key51=39:39
45 Key52=122:122
46 Key53=120:120
47 Key54=99:99
48 Key55=118:118
49 Key56=98:98
50 Key57=110:110
51 Key58=109:109
52 Key59=44:44
53 Key60=46:46
54 Key61=45:45
55 Key62=65506:0
56 Key63=65450:42
57 Key64=65513:0
58 Key65=32:32
59 Key66=65509:0
60 Key67=65470:0
61 Key68=65471:0
62 Key69=65472:0
63 Key70=65473:0
64 Key71=65474:0
65 Key72=65475:0
66 Key73=65476:0
67 Key74=65477:0
68 Key75=65478:0
69 Key76=65479:0
70 Key77=65407:0
71 Key78=65300:0
72 Key79=65429:0
73 Key80=65431:0
74 Key81=65434:0
75 Key82=65453:45
76 Key83=65430:0
77 Key84=65437:0
78 Key85=65432:0
79 Key86=65451:43
80 Key87=65436:0
81 Key88=65433:0
82 Key89=65435:0
83 Key90=65438:0
84 Key91=65439:0
85 Key92=0:0
86 Key93=65406:0
87 Key94=60:60
88 Key95=65480:0
89 Key96=65481:0
90 Key97=65360:0
91 Key98=65362:0
92 Key99=65365:0
93 Key100=65361:0
94 Key101=0:0
95 Key102=65363:0
96 Key103=65367:0
97 Key104=65364:0
98 Key105=65366:0
99 Key106=65379:0
100 Key107=65535:127
101 Key108=65421:13
102 Key109=65508:0
103 Key110=65299:0
104 Key111=65377:0
105 Key112=65455:47
106 Key113=65027:0
107 Key114=0:0
108 Key115=65515:0
109 Key116=65516:0
110 Key117=65383:0
111 Key118=0:0
112 Key119=0:0
113 Key120=0:0
114 Key121=0:0
115 Key122=0:0
116 Key123=0:0
117 Key124=65027:0
118 Key125=0:0
119 Key126=65469:61
120 Key127=0:0
121 Key128=0:0
122 Key129=0:0
123 Key130=0:0
124 Key131=0:0
125 Key132=0:0
126 Key133=0:0
127 Key134=0:0
128 Key135=0:0
129 Key136=0:0
130 Key137=0:0
131
132 [shift]
133 Key8=0:0
134 Key9=65307:27
135 Key10=33:33
136 Key11=34:34
137 Key12=35:35
138 Key13=164:164
139 Key14=37:37
140 Key15=38:38
141 Key16=47:47
142 Key17=40:40
143 Key18=41:41
144 Key19=61:61
145 Key20=63:63
146 Key21=65104:96
147 Key22=65288:8
148 Key23=65056:0
149 Key24=81:81
150 Key25=87:87
151 Key26=69:69
152 Key27=82:82
153 Key28=84:84
154 Key29=89:89
155 Key30=85:85
156 Key31=73:73
157 Key32=79:79
158 Key33=80:80
159 Key34=197:197
160 Key35=94:94
161 Key36=65293:13
162 Key37=65507:0
163 Key38=65:65
164 Key39=83:83
165 Key40=68:68
166 Key41=70:70
167 Key42=71:71
168 Key43=72:72
169 Key44=74:74
170 Key45=75:75
171 Key46=76:76
172 Key47=198:198
173 Key48=216:216
174 Key49=167:167
175 Key50=65505:0
176 Key51=42:42
177 Key52=90:90
178 Key53=88:88
179 Key54=67:67
180 Key55=86:86
181 Key56=66:66
182 Key57=78:78
183 Key58=77:77
184 Key59=59:59
185 Key60=58:58
186 Key61=95:95
187 Key62=65506:0
188 Key63=65450:42
189 Key64=65511:0
190 Key65=32:32
191 Key66=65509:0
192 Key67=65470:0
193 Key68=65471:0
194 Key69=65472:0
195 Key70=65473:0
196 Key71=65474:0
197 Key72=65475:0
198 Key73=65476:0
199 Key74=65477:0
200 Key75=65478:0
201 Key76=65479:0
202 Key77=65273:0
203 Key78=65300:0
204 Key79=65463:55
205 Key80=65464:56
206 Key81=65465:57
207 Key82=65453:45
208 Key83=65460:52
209 Key84=65461:53
210 Key85=65462:54
211 Key86=65451:43
212 Key87=65457:49
213 Key88=65458:50
214 Key89=65459:51
215 Key90=65456:48
216 Key91=65452:44
217 Key92=0:0
218 Key93=65406:0
219 Key94=62:62
220 Key95=65480:0
221 Key96=65481:0
222 Key97=65360:0
223 Key98=65362:0
224 Key99=65365:0
225 Key100=65361:0
226 Key101=0:0
227 Key102=65363:0
228 Key103=65367:0
229 Key104=65364:0
230 Key105=65366:0
231 Key106=65379:0
232 Key107=65535:127
233 Key108=65421:13
234 Key109=65508:0
235 Key110=65299:0
236 Key111=65377:0
237 Key112=65455:47
238 Key113=65027:0
239 Key114=0:0
240 Key115=65515:0
241 Key116=65516:0
242 Key117=65383:0
243 Key118=0:0
244 Key119=0:0
245 Key120=0:0
246 Key121=0:0
247 Key122=0:0
248 Key123=0:0
249 Key124=65027:0
250 Key125=65513:0
251 Key126=65469:61
252 Key127=65515:0
253 Key128=65517:0
254 Key129=0:0
255 Key130=0:0
256 Key131=0:0
257 Key132=0:0
258 Key133=0:0
259 Key134=0:0
260 Key135=0:0
261 Key136=0:0
262 Key137=0:0
263
264 [altgr]
265 Key8=0:0
266 Key9=65307:27
267 Key10=161:161
268 Key11=64:64
269 Key12=163:163
270 Key13=36:36
271 Key14=8364:8364
272 Key15=165:165
273 Key16=123:123
274 Key17=91:91
275 Key18=93:93
276 Key19=125:125
277 Key20=92:92
278 Key21=124:124
279 Key22=65288:8
280 Key23=65289:9
281 Key24=64:64
282 Key25=435:322
283 Key26=8364:8364
284 Key27=174:174
285 Key28=254:254
286 Key29=2299:8592
287 Key30=2302:8595
288 Key31=2301:8594
289 Key32=5053:339
290 Key33=254:254
291 Key34=65111:168
292 Key35=126:126
293 Key36=65293:13
294 Key37=65507:0
295 Key38=170:170
296 Key39=223:223
297 Key40=240:240
298 Key41=496:273
299 Key42=959:331
300 Key43=689:295
301 Key44=106:106
302 Key45=930:312
303 Key46=435:322
304 Key47=248:248
305 Key48=230:230
306 Key49=182:182
307 Key50=65505:0
308 Key51=180:180
309 Key52=171:171
310 Key53=187:187
311 Key54=169:169
312 Key55=2770:8220
313 Key56=2771:8221
314 Key57=110:110
315 Key58=181:181
316 Key59=65115:184
317 Key60=183:183
318 Key61=65120:0
319 Key62=65506:0
320 Key63=65450:42
321 Key64=65513:0
322 Key65=32:32
323 Key66=65509:0
324 Key67=65470:0
325 Key68=65471:0
326 Key69=65472:0
327 Key70=65473:0
328 Key71=65474:0
329 Key72=65475:0
330 Key73=65476:0
331 Key74=65477:0
332 Key75=65478:0
333 Key76=65479:0
334 Key77=65407:0
335 Key78=65300:0
336 Key79=65429:0
337 Key80=65431:0
338 Key81=65434:0
339 Key82=65453:45
340 Key83=65430:0
341 Key84=65437:0
342 Key85=65432:0
343 Key86=65451:43
344 Key87=65436:0
345 Key88=65433:0
346 Key89=65435:0
347 Key90=65438:0
348 Key91=65439:0
349 Key92=0:0
350 Key93=65406:0
351 Key94=92:92
352 Key95=65480:0
353 Key96=65481:0
354 Key97=65360:0
355 Key98=65362:0
356 Key99=65365:0
357 Key100=65361:0
358 Key101=0:0
359 Key102=65363:0
360 Key103=65367:0
361 Key104=65364:0
362 Key105=65366:0
363 Key106=65379:0
364 Key107=65535:127
365 Key108=65421:13
366 Key109=65508:0
367 Key110=65299:0
368 Key111=0:0
369 Key112=65455:47
370 Key113=65027:0
371 Key114=0:0
372 Key115=65515:0
373 Key116=65516:0
374 Key117=65383:0
375 Key118=0:0
376 Key119=0:0
377 Key120=0:0
378 Key121=0:0
379 Key122=0:0
380 Key123=0:0
381 Key124=65027:0
382 Key125=0:0
383 Key126=65469:61
384 Key127=0:0
385 Key128=0:0
386 Key129=0:0
387 Key130=0:0
388 Key131=0:0
389 Key132=0:0
390 Key133=0:0
391 Key134=0:0
392 Key135=0:0
393 Key136=0:0
394 Key137=0:0
395
396 [capslock]
397 Key8=0:0
398 Key9=65307:27
399 Key10=49:49
400 Key11=50:50
401 Key12=51:51
402 Key13=52:52
403 Key14=53:53
404 Key15=54:54
405 Key16=55:55
406 Key17=56:56
407 Key18=57:57
408 Key19=48:48
409 Key20=43:43
410 Key21=65105:180
411 Key22=65288:8
412 Key23=65289:9
413 Key24=81:81
414 Key25=87:87
415 Key26=69:69
416 Key27=82:82
417 Key28=84:84
418 Key29=89:89
419 Key30=85:85
420 Key31=73:73
421 Key32=79:79
422 Key33=80:80
423 Key34=197:197
424 Key35=65111:168
425 Key36=65293:13
426 Key37=65507:0
427 Key38=65:65
428 Key39=83:83
429 Key40=68:68
430 Key41=70:70
431 Key42=71:71
432 Key43=72:72
433 Key44=74:74
434 Key45=75:75
435 Key46=76:76
436 Key47=214:214
437 Key48=196:196
438 Key49=167:167
439 Key50=65505:0
440 Key51=39:39
441 Key52=90:90
442 Key53=88:88
443 Key54=67:67
444 Key55=86:86
445 Key56=66:66
446 Key57=78:78
447 Key58=77:77
448 Key59=44:44
449 Key60=46:46
450 Key61=45:45
451 Key62=65506:0
452 Key63=65450:42
453 Key64=65513:0
454 Key65=32:32
455 Key66=65509:0
456 Key67=65470:0
457 Key68=65471:0
458 Key69=65472:0
459 Key70=65473:0
460 Key71=65474:0
461 Key72=65475:0
462 Key73=65476:0
463 Key74=65477:0
464 Key75=65478:0
465 Key76=65479:0
466 Key77=65407:0
467 Key78=65300:0
468 Key79=65429:0
469 Key80=65431:0
470 Key81=65434:0
471 Key82=65453:45
472 Key83=65430:0
473 Key84=65437:0
474 Key85=65432:0
475 Key86=65451:43
476 Key87=65436:0
477 Key88=65433:0
478 Key89=65435:0
479 Key90=65438:0
480 Key91=65439:0
481 Key92=0:0
482 Key93=65406:0
483 Key94=60:60
484 Key95=65480:0
485 Key96=65481:0
486 Key97=65360:0
487 Key98=65362:0
488 Key99=65365:0
489 Key100=65361:0
490 Key101=0:0
491 Key102=65363:0
492 Key103=65367:0
493 Key104=65364:0
494 Key105=65366:0
495 Key106=65379:0
496 Key107=65535:127
497 Key108=65421:13
498 Key109=65508:0
499 Key110=65299:0
500 Key111=65377:0
501 Key112=65455:47
502 Key113=65027:0
503 Key114=0:0
504 Key115=65515:0
505 Key116=65516:0
506 Key117=65383:0
507 Key118=0:0
508 Key119=0:0
509 Key120=0:0
510 Key121=0:0
511 Key122=0:0
512 Key123=0:0
513 Key124=65027:0
514 Key125=0:0
515 Key126=65469:61
516 Key127=0:0
517 Key128=0:0
518 Key129=0:0
519 Key130=0:0
520 Key131=0:0
521 Key132=0:0
522 Key133=0:0
523 Key134=0:0
524 Key135=0:0
525 Key136=0:0
526 Key137=0:0
527
528 [shiftcapslock]
529 Key8=0:0
530 Key9=65307:27
531 Key10=33:33
532 Key11=34:34
533 Key12=35:35
534 Key13=164:164
535 Key14=37:37
536 Key15=38:38
537 Key16=47:47
538 Key17=40:40
539 Key18=41:41
540 Key19=61:61
541 Key20=63:63
542 Key21=65104:96
543 Key22=65288:8
544 Key23=65056:0
545 Key24=113:113
546 Key25=119:119
547 Key26=101:101
548 Key27=114:114
549 Key28=116:116
550 Key29=121:121
551 Key30=117:117
552 Key31=105:105
553 Key32=111:111
554 Key33=112:112
555 Key34=229:229
556 Key35=65106:94
557 Key36=65293:13
558 Key37=65507:0
559 Key38=97:97
560 Key39=115:115
561 Key40=100:100
562 Key41=102:102
563 Key42=103:103
564 Key43=104:104
565 Key44=106:106
566 Key45=107:107
567 Key46=108:108
568 Key47=246:246
569 Key48=228:228
570 Key49=189:189
571 Key50=65505:0
572 Key51=42:42
573 Key52=122:122
574 Key53=120:120
575 Key54=99:99
576 Key55=118:118
577 Key56=98:98
578 Key57=110:110
579 Key58=109:109
580 Key59=59:59
581 Key60=58:58
582 Key61=95:95
583 Key62=65506:0
584 Key63=65450:42
585 Key64=65511:0
586 Key65=32:32
587 Key66=65509:0
588 Key67=65470:0
589 Key68=65471:0
590 Key69=65472:0
591 Key70=65473:0
592 Key71=65474:0
593 Key72=65475:0
594 Key73=65476:0
595 Key74=65477:0
596 Key75=65478:0
597 Key76=65479:0
598 Key77=65273:0
599 Key78=65300:0
600 Key79=65463:55
601 Key80=65464:56
602 Key81=65465:57
603 Key82=65453:45
604 Key83=65460:52
605 Key84=65461:53
606 Key85=65462:54
607 Key86=65451:43
608 Key87=65457:49
609 Key88=65458:50
610 Key89=65459:51
611 Key90=65456:48
612 Key91=65452:44
613 Key92=0:0
614 Key93=65406:0
615 Key94=62:62
616 Key95=65480:0
617 Key96=65481:0
618 Key97=65360:0
619 Key98=65362:0
620 Key99=65365:0
621 Key100=65361:0
622 Key101=0:0
623 Key102=65363:0
624 Key103=65367:0
625 Key104=65364:0
626 Key105=65366:0
627 Key106=65379:0
628 Key107=65535:127
629 Key108=65421:13
630 Key109=65508:0
631 Key110=65299:0
632 Key111=65377:0
633 Key112=65455:47
634 Key113=65027:0
635 Key114=0:0
636 Key115=65515:0
637 Key116=65516:0
638 Key117=65383:0
639 Key118=0:0
640 Key119=0:0
641 Key120=0:0
642 Key121=0:0
643 Key122=0:0
644 Key123=0:0
645 Key124=65027:0
646 Key125=65513:0
647 Key126=65469:61
648 Key127=65515:0
649 Key128=65517:0
650 Key129=0:0
651 Key130=0:0
652 Key131=0:0
653 Key132=0:0
654 Key133=0:0
655 Key134=0:0
656 Key135=0:0
657 Key136=0:0
658 Key137=0:0
77
88 service="xrdp-sesman"
99 pamdir="/etc/pam.d"
10 pamdir_suse="/usr/etc/pam.d"
1011
1112 guess_rules ()
1213 {
1314 if test -s "$pamdir/password-auth"; then
1415 rules="redhat"
16 return
17 fi
18
19 if test -s "$pamdir_suse/common-account"; then
20 rules="suse"
1521 return
1622 fi
1723
+0
-153
instfiles/xrdp.sh less more
0 #!/bin/sh
1 # xrdp control script
2 # Written : 1-13-2006 - Mark Balliet - posicat@pobox.com
3 # maintaned by Jay Sorg
4 # chkconfig: 2345 11 89
5 # description: starts xrdp
6
7 ### BEGIN INIT INFO
8 # Provides: xrdp
9 # Required-Start:
10 # Required-Stop:
11 # Should-Start:
12 # Should-Stop:
13 # Default-Start: 2 3 4 5
14 # Default-Stop: 0 1 6
15 # Short-Description: Start and stop xrdp
16 # Description: starts xrdp
17 ### END INIT INFO
18
19 SBINDIR=/usr/local/sbin
20 LOG=/dev/null
21 CFGDIR=/etc/xrdp
22
23 if ! test -x $SBINDIR/xrdp
24 then
25 echo "xrdp is not executable"
26 exit 0
27 fi
28 if ! test -x $SBINDIR/xrdp-sesman
29 then
30 echo "xrdp-sesman is not executable"
31 exit 0
32 fi
33 if ! test -x $CFGDIR/startwm.sh
34 then
35 echo "startwm.sh is not executable"
36 exit 0
37 fi
38
39 xrdp_start()
40 {
41 echo -n "Starting: xrdp and sesman . . "
42 $SBINDIR/xrdp >> $LOG
43 $SBINDIR/xrdp-sesman >> $LOG
44 echo "."
45 sleep 1
46 return 0;
47 }
48
49 xrdp_stop()
50 {
51 echo -n "Stopping: xrdp and sesman . . "
52 $SBINDIR/xrdp-sesman --kill >> $LOG
53 $SBINDIR/xrdp --kill >> $LOG
54 echo "."
55 return 0;
56 }
57
58 is_xrdp_running()
59 {
60 ps u --noheading -C xrdp | grep -q -i xrdp
61 if test $? -eq 0
62 then
63 return 1;
64 else
65 return 0;
66 fi
67 }
68
69 is_sesman_running()
70 {
71 ps u --noheading -C xrdp-sesman | grep -q -i xrdp-sesman
72 if test $? -eq 0
73 then
74 return 1;
75 else
76 return 0;
77 fi
78 }
79
80 check_up()
81 {
82 # Cleanup : If sesman isn't running, but the pid exists, erase it.
83 is_sesman_running
84 if test $? -eq 0
85 then
86 if test -e /var/run/xrdp-sesman.pid
87 then
88 rm /var/run/xrdp-sesman.pid
89 fi
90 fi
91 # Cleanup : If xrdp isn't running, but the pid exists, erase it.
92 is_xrdp_running
93 if test $? -eq 0
94 then
95 if test -e /var/run/xrdp.pid
96 then
97 rm /var/run/xrdp.pid
98 fi
99 fi
100 return 0;
101 }
102
103 case "$1" in
104 start)
105 check_up
106 is_xrdp_running
107 if ! test $? -eq 0
108 then
109 echo "xrdp is already loaded"
110 exit 1
111 fi
112 is_sesman_running
113 if ! test $? -eq 0
114 then
115 echo "sesman is already loaded"
116 exit 1
117 fi
118 xrdp_start
119 ;;
120 stop)
121 check_up
122 is_xrdp_running
123 if test $? -eq 0
124 then
125 echo "xrdp is not loaded."
126 fi
127 is_sesman_running
128 if test $? -eq 0
129 then
130 echo "sesman is not loaded."
131 fi
132 xrdp_stop
133 ;;
134 force-reload|restart)
135 check_up
136 echo "Restarting xrdp ..."
137 xrdp_stop
138 is_xrdp_running
139 while ! test $? -eq 0
140 do
141 check_up
142 sleep 1
143 is_xrdp_running
144 done
145 xrdp_start
146 ;;
147 *)
148 echo "Usage: xrdp.sh {start|stop|restart|force-reload}"
149 exit 1
150 esac
151
152 exit 0
00 #! /bin/sh
11 # Guess values for system-dependent variables and create Makefiles.
2 # Generated by GNU Autoconf 2.69 for rfxcodec 0.1.4.
2 # Generated by GNU Autoconf 2.69 for rfxcodec 0.1.5.
33 #
44 # Report bugs to <xrdp-devel@googlegroups.com>.
55 #
589589 # Identity of this package.
590590 PACKAGE_NAME='rfxcodec'
591591 PACKAGE_TARNAME='rfxcodec'
592 PACKAGE_VERSION='0.1.4'
593 PACKAGE_STRING='rfxcodec 0.1.4'
592 PACKAGE_VERSION='0.1.5'
593 PACKAGE_STRING='rfxcodec 0.1.5'
594594 PACKAGE_BUGREPORT='xrdp-devel@googlegroups.com'
595595 PACKAGE_URL=''
596596
13201320 # Omit some internal or obsolete options to make the list less imposing.
13211321 # This message is too long to be a string in the A/UX 3.1 sh.
13221322 cat <<_ACEOF
1323 \`configure' configures rfxcodec 0.1.4 to adapt to many kinds of systems.
1323 \`configure' configures rfxcodec 0.1.5 to adapt to many kinds of systems.
13241324
13251325 Usage: $0 [OPTION]... [VAR=VALUE]...
13261326
13901390
13911391 if test -n "$ac_init_help"; then
13921392 case $ac_init_help in
1393 short | recursive ) echo "Configuration of rfxcodec 0.1.4:";;
1393 short | recursive ) echo "Configuration of rfxcodec 0.1.5:";;
13941394 esac
13951395 cat <<\_ACEOF
13961396
15031503 test -n "$ac_init_help" && exit $ac_status
15041504 if $ac_init_version; then
15051505 cat <<\_ACEOF
1506 rfxcodec configure 0.1.4
1506 rfxcodec configure 0.1.5
15071507 generated by GNU Autoconf 2.69
15081508
15091509 Copyright (C) 2012 Free Software Foundation, Inc.
17811781 This file contains any messages produced by compilers while
17821782 running configure, to aid debugging if configure makes a mistake.
17831783
1784 It was created by rfxcodec $as_me 0.1.4, which was
1784 It was created by rfxcodec $as_me 0.1.5, which was
17851785 generated by GNU Autoconf 2.69. Invocation command line was
17861786
17871787 $ $0 $@
26462646
26472647 # Define the identity of the package.
26482648 PACKAGE='rfxcodec'
2649 VERSION='0.1.4'
2649 VERSION='0.1.5'
26502650
26512651
26522652 cat >>confdefs.h <<_ACEOF
1315913159 # report actual input values of CONFIG_FILES etc. instead of their
1316013160 # values after options handling.
1316113161 ac_log="
13162 This file was extended by rfxcodec $as_me 0.1.4, which was
13162 This file was extended by rfxcodec $as_me 0.1.5, which was
1316313163 generated by GNU Autoconf 2.69. Invocation command line was
1316413164
1316513165 CONFIG_FILES = $CONFIG_FILES
1322513225 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
1322613226 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
1322713227 ac_cs_version="\\
13228 rfxcodec config.status 0.1.4
13228 rfxcodec config.status 0.1.5
1322913229 configured by $0, generated by GNU Autoconf 2.69,
1323013230 with options \\"\$ac_cs_config\\"
1323113231
00 # Process this file with autoconf to produce a configure script
11
22 AC_PREREQ(2.59)
3 AC_INIT([rfxcodec], [0.1.4], [xrdp-devel@googlegroups.com])
3 AC_INIT([rfxcodec], [0.1.5], [xrdp-devel@googlegroups.com])
44 AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in)
55 AM_INIT_AUTOMAKE([1.6 foreign])
66 AC_CONFIG_MACRO_DIR([m4])
8383 }
8484 while (x < 64)
8585 {
86 *lr_buf++ = r;
87 *lg_buf++ = g;
88 *lb_buf++ = r;
86 *lb_buf++ = b;
87 *lg_buf++ = g;
88 *lr_buf++ = r;
8989 x++;
9090 }
9191 }
154154 }
155155 while (x < 64)
156156 {
157 *lr_buf++ = r;
158 *lg_buf++ = g;
159 *lb_buf++ = b;
157 *lb_buf++ = b;
158 *lg_buf++ = g;
159 *lr_buf++ = r;
160160 x++;
161161 }
162162 }
256256 }
257257 while (x < 64)
258258 {
259 *lb_buf++ = b;
260 *lg_buf++ = g;
261 *lr_buf++ = r;
259262 *la_buf++ = a;
260 *lr_buf++ = r;
261 *lg_buf++ = g;
262 *lb_buf++ = r;
263263 x++;
264264 }
265265 }
297297 }
298298 while (x < 64)
299299 {
300 *lr_buf++ = r;
301 *lg_buf++ = g;
302 *lb_buf++ = b;
300303 *la_buf++ = a;
301 *lr_buf++ = r;
302 *lg_buf++ = g;
303 *lb_buf++ = b;
304304 x++;
305305 }
306306 }
335335 }
336336 while (x < 64)
337337 {
338 *lr_buf++ = r;
339 *lg_buf++ = g;
340 *lb_buf++ = b;
338 *lb_buf++ = b;
339 *lg_buf++ = g;
340 *lr_buf++ = r;
341341 x++;
342342 }
343343 }
809809 out_uint16_le(s, 0); /* Update capability */
810810 out_uint16_le(s, 0); /* Remote unshare capability */
811811 out_uint16_le(s, 0); /* Compression level */
812 out_uint16_le(s, 0); /* Pad */
812 out_uint8(s, 1); /* refreshRectSupport */
813 out_uint8(s, 1); /* suppressOutputSupport */
813814
814815 /* Output bitmap capability set */
815816 caps_count++;
10431043 }
10441044
10451045 /*****************************************************************************/
1046 /* 2.2.11.2.1 Refresh Rect PDU Data (TS_REFRESH_RECT_PDU) */
10461047 static int
10471048 xrdp_rdp_process_screen_update(struct xrdp_rdp *self, struct stream *s)
10481049 {
1050 int index;
1051 int num_rects;
10491052 int left;
10501053 int top;
10511054 int right;
10531056 int cx;
10541057 int cy;
10551058
1056 in_uint8s(s, 4); /* op */
1057 in_uint16_le(s, left);
1058 in_uint16_le(s, top);
1059 in_uint16_le(s, right);
1060 in_uint16_le(s, bottom);
1061 cx = (right - left) + 1;
1062 cy = (bottom - top) + 1;
1063
1064 if (self->session->callback != 0)
1065 {
1066 self->session->callback(self->session->id, 0x4444, left, top, cx, cy);
1067 }
1068
1059 if (!s_check_rem(s, 4))
1060 {
1061 return 1;
1062 }
1063 in_uint8(s, num_rects);
1064 in_uint8s(s, 3); /* pad */
1065 g_writeln("xrdp_rdp_process_screen_update: num_rects %d", num_rects);
1066 for (index = 0; index < num_rects; index++)
1067 {
1068 if (!s_check_rem(s, 8))
1069 {
1070 return 1;
1071 }
1072 /* Inclusive Rectangle (TS_RECTANGLE16) */
1073 in_uint16_le(s, left);
1074 in_uint16_le(s, top);
1075 in_uint16_le(s, right);
1076 in_uint16_le(s, bottom);
1077 g_writeln(" left %d top %d right %d bottom %d",
1078 left, top, right, bottom);
1079 cx = (right - left) + 1;
1080 cy = (bottom - top) + 1;
1081 if (self->session->callback != 0)
1082 {
1083 self->session->callback(self->session->id, 0x4444,
1084 left, top, cx, cy);
1085 }
1086 }
10691087 return 0;
10701088 }
10711089
12091227 }
12101228
12111229 /*****************************************************************************/
1230 static int
1231 xrdp_rdp_process_suppress(struct xrdp_rdp *self, struct stream *s)
1232 {
1233 int allowDisplayUpdates;
1234 int left;
1235 int top;
1236 int right;
1237 int bottom;
1238
1239 if (!s_check_rem(s, 1))
1240 {
1241 return 1;
1242 }
1243 in_uint8(s, allowDisplayUpdates);
1244 g_writeln("xrdp_rdp_process_suppress: allowDisplayUpdates %d bytes "
1245 "left %d", allowDisplayUpdates, (int) (s->end - s->p));
1246 switch (allowDisplayUpdates)
1247 {
1248 case 0: /* SUPPRESS_DISPLAY_UPDATES */
1249 self->client_info.suppress_output = 1;
1250 g_writeln("xrdp_rdp_process_suppress: suppress_output %d",
1251 self->client_info.suppress_output);
1252 if (self->session->callback != 0)
1253 {
1254 self->session->callback(self->session->id, 0x5559, 1,
1255 0, 0, 0);
1256 }
1257 break;
1258 case 1: /* ALLOW_DISPLAY_UPDATES */
1259 self->client_info.suppress_output = 0;
1260 if (!s_check_rem(s, 11))
1261 {
1262 return 1;
1263 }
1264 in_uint8s(s, 3); /* pad */
1265 in_uint16_le(s, left);
1266 in_uint16_le(s, top);
1267 in_uint16_le(s, right);
1268 in_uint16_le(s, bottom);
1269 g_writeln("xrdp_rdp_process_suppress: suppress_output %d "
1270 "left %d top %d right %d bottom %d",
1271 self->client_info.suppress_output,
1272 left, top, right, bottom);
1273 if (self->session->callback != 0)
1274 {
1275 self->session->callback(self->session->id, 0x5559, 0,
1276 MAKELONG(left, top),
1277 MAKELONG(right, bottom), 0);
1278 }
1279 break;
1280 }
1281 return 0;
1282 }
1283
1284 /*****************************************************************************/
12121285 /* RDP_PDU_DATA */
12131286 int
12141287 xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s)
12151288 {
1216 int data_type;
1217
1289 int uncompressedLength;
1290 int pduType2;
1291 int compressedType;
1292 int compressedLength;
1293
1294 if (!s_check_rem(s, 12))
1295 {
1296 return 1;
1297 }
12181298 in_uint8s(s, 6);
1219 in_uint8s(s, 2); /* len */
1220 in_uint8(s, data_type);
1221 in_uint8s(s, 1); /* ctype */
1222 in_uint8s(s, 2); /* clen */
1223 DEBUG(("xrdp_rdp_process_data code %d", data_type));
1224
1225 switch (data_type)
1299 in_uint16_le(s, uncompressedLength);
1300 in_uint8(s, pduType2);
1301 in_uint8(s, compressedType);
1302 in_uint16_le(s, compressedLength);
1303 if (compressedType != 0)
1304 {
1305 /* don't support compression */
1306 return 1;
1307 }
1308 if (compressedLength > uncompressedLength)
1309 {
1310 return 1;
1311 }
1312 DEBUG(("xrdp_rdp_process_data pduType2 %d", pduType2));
1313 switch (pduType2)
12261314 {
12271315 case RDP_DATA_PDU_POINTER: /* 27(0x1b) */
12281316 xrdp_rdp_process_data_pointer(self, s);
12361324 case RDP_DATA_PDU_SYNCHRONISE: /* 31(0x1f) */
12371325 xrdp_rdp_process_data_sync(self);
12381326 break;
1239 case 33: /* 33(0x21) ?? Invalidate an area I think */
1327 case PDUTYPE2_REFRESH_RECT:
12401328 xrdp_rdp_process_screen_update(self, s);
12411329 break;
1242 case 35: /* 35(0x23) */
1243 /* 35 ?? this comes when minimizing a full screen mstsc.exe 2600 */
1244 /* I think this is saying the client no longer wants screen */
1245 /* updates and it will issue a 33 above to catch up */
1246 /* so minimized apps don't take bandwidth */
1330 case 35: /* 35(0x23) PDUTYPE2_SUPPRESS_OUTPUT */
1331 xrdp_rdp_process_suppress(self, s);
12471332 break;
12481333 case 36: /* 36(0x24) ?? disconnect query? */
12491334 /* when this message comes, send a 37 back so the client */
12581343 xrdp_rdp_process_frame_ack(self, s);
12591344 break;
12601345 default:
1261 g_writeln("unknown in xrdp_rdp_process_data %d", data_type);
1346 g_writeln("unknown in xrdp_rdp_process_data pduType2 %d", pduType2);
12621347 break;
12631348 }
1264
12651349 return 0;
12661350 }
12671351 /*****************************************************************************/
2626 #include "log.h"
2727 #include <freerdp/settings.h>
2828
29 #if defined(VERSION_STRUCT_RDP_FREERDP)
30 #if VERSION_STRUCT_RDP_FREERDP > 1
31 #define NEUTRINORDP_HAS_SUPPRESS_OUTPUT
32 #endif
33 #endif
34
2935 #ifdef XRDP_DEBUG
3036 #define LOG_LEVEL 99
3137 #else
537543 return 1;
538544 }
539545
546 return 0;
547 }
548
549 /******************************************************************************/
550 static int
551 lxrdp_frame_ack(struct mod* mod, int flags, int frame_id)
552 {
553 return 0;
554 }
555
556 /******************************************************************************/
557 static int
558 lxrdp_suppress_output(struct mod* mod, int suppress,
559 int left, int top, int right, int bottom)
560 {
561 #if defined(NEUTRINORDP_HAS_SUPPRESS_OUTPUT)
562 mod->inst->SendSuppressOutput(mod->inst, !suppress, left, top, right, bottom);
563 #endif
540564 return 0;
541565 }
542566
20082032 mod->mod_session_change = lxrdp_session_change;
20092033 mod->mod_get_wait_objs = lxrdp_get_wait_objs;
20102034 mod->mod_check_wait_objs = lxrdp_check_wait_objs;
2035 mod->mod_frame_ack = lxrdp_frame_ack;
2036 mod->mod_suppress_output = lxrdp_suppress_output;
20112037
20122038 mod->inst = freerdp_new();
20132039 mod->inst->PreConnect = lfreerdp_pre_connect;
5757 int bpp;
5858 };
5959
60 #define CURRENT_MOD_VER 3
60 #define CURRENT_MOD_VER 4
6161
6262 struct mod
6363 {
7575 int (*mod_get_wait_objs)(struct mod *v, tbus *read_objs, int *rcount,
7676 tbus *write_objs, int *wcount, int *timeout);
7777 int (*mod_check_wait_objs)(struct mod *v);
78 tintptr mod_dumby[100 - 9]; /* align, 100 minus the number of mod
79 functions above */
78 int (*mod_frame_ack)(struct mod* mod, int flags, int frame_id);
79 int (*mod_suppress_output)(struct mod* mod, int suppress,
80 int left, int top, int right, int bottom);
81 tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
82 functions above */
8083 /* server functions */
8184 int (*server_begin_update)(struct mod *v);
8285 int (*server_end_update)(struct mod *v);
3636 CHANSRV_EXTRA_LIBS += -lmp3lame
3737 endif
3838
39 if XRDP_RDPSNDAUDIN
40 AM_CPPFLAGS += -DXRDP_RDPSNDAUDIN
41 endif
42
3943 AM_CFLAGS = $(X_CFLAGS)
4044
4145 sbin_PROGRAMS = \
4852 chansrv_common.h \
4953 chansrv_fuse.c \
5054 chansrv_fuse.h \
55 chansrv_xfs.c \
56 chansrv_xfs.h \
5157 clipboard.c \
5258 clipboard.h \
5359 clipboard_common.h \
6066 irp.c \
6167 irp.h \
6268 mlog.h \
69 ms-erref.h \
70 ms-fscc.h \
71 ms-rdpefs.h \
72 ms-smb2.h \
6373 rail.c \
6474 rail.h \
6575 smartcard.c \
6979 sound.c \
7080 sound.h \
7181 xcommon.c \
72 xcommon.h
82 xcommon.h \
83 audin.c \
84 audin.h
7385
7486 xrdp_chansrv_LDFLAGS = \
7587 $(X_LIBS)
9696 @XRDP_OPUS_TRUE@am__append_7 = -lopus
9797 @XRDP_MP3LAME_TRUE@am__append_8 = -DXRDP_MP3LAME
9898 @XRDP_MP3LAME_TRUE@am__append_9 = -lmp3lame
99 @XRDP_RDPSNDAUDIN_TRUE@am__append_10 = -DXRDP_RDPSNDAUDIN
99100 sbin_PROGRAMS = xrdp-chansrv$(EXEEXT)
100101 subdir = sesman/chansrv
101102 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
120121 am__installdirs = "$(DESTDIR)$(sbindir)"
121122 PROGRAMS = $(sbin_PROGRAMS)
122123 am_xrdp_chansrv_OBJECTS = chansrv.$(OBJEXT) chansrv_common.$(OBJEXT) \
123 chansrv_fuse.$(OBJEXT) clipboard.$(OBJEXT) \
124 clipboard_file.$(OBJEXT) devredir.$(OBJEXT) fifo.$(OBJEXT) \
125 irp.$(OBJEXT) rail.$(OBJEXT) smartcard.$(OBJEXT) \
126 smartcard_pcsc.$(OBJEXT) sound.$(OBJEXT) xcommon.$(OBJEXT)
124 chansrv_fuse.$(OBJEXT) chansrv_xfs.$(OBJEXT) \
125 clipboard.$(OBJEXT) clipboard_file.$(OBJEXT) \
126 devredir.$(OBJEXT) fifo.$(OBJEXT) irp.$(OBJEXT) rail.$(OBJEXT) \
127 smartcard.$(OBJEXT) smartcard_pcsc.$(OBJEXT) sound.$(OBJEXT) \
128 xcommon.$(OBJEXT) audin.$(OBJEXT)
127129 xrdp_chansrv_OBJECTS = $(am_xrdp_chansrv_OBJECTS)
128130 am__DEPENDENCIES_1 =
129131 @XRDP_FUSE_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
155157 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
156158 depcomp = $(SHELL) $(top_srcdir)/depcomp
157159 am__maybe_remake_depfiles = depfiles
158 am__depfiles_remade = ./$(DEPDIR)/chansrv.Po \
160 am__depfiles_remade = ./$(DEPDIR)/audin.Po ./$(DEPDIR)/chansrv.Po \
159161 ./$(DEPDIR)/chansrv_common.Po ./$(DEPDIR)/chansrv_fuse.Po \
160 ./$(DEPDIR)/clipboard.Po ./$(DEPDIR)/clipboard_file.Po \
161 ./$(DEPDIR)/devredir.Po ./$(DEPDIR)/fifo.Po ./$(DEPDIR)/irp.Po \
162 ./$(DEPDIR)/rail.Po ./$(DEPDIR)/smartcard.Po \
163 ./$(DEPDIR)/smartcard_pcsc.Po ./$(DEPDIR)/sound.Po \
164 ./$(DEPDIR)/xcommon.Po
162 ./$(DEPDIR)/chansrv_xfs.Po ./$(DEPDIR)/clipboard.Po \
163 ./$(DEPDIR)/clipboard_file.Po ./$(DEPDIR)/devredir.Po \
164 ./$(DEPDIR)/fifo.Po ./$(DEPDIR)/irp.Po ./$(DEPDIR)/rail.Po \
165 ./$(DEPDIR)/smartcard.Po ./$(DEPDIR)/smartcard_pcsc.Po \
166 ./$(DEPDIR)/sound.Po ./$(DEPDIR)/xcommon.Po
165167 am__mv = mv -f
166168 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
167169 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
363365 -DXRDP_PID_PATH=\"${localstatedir}/run\" \
364366 -DXRDP_SOCKET_PATH=\"${socketdir}\" -I$(top_srcdir)/common \
365367 $(am__append_1) $(am__append_2) $(am__append_4) \
366 $(am__append_6) $(am__append_8)
368 $(am__append_6) $(am__append_8) $(am__append_10)
367369 CHANSRV_EXTRA_LIBS = $(am__append_3) $(am__append_5) $(am__append_7) \
368370 $(am__append_9)
369371 AM_CFLAGS = $(X_CFLAGS)
374376 chansrv_common.h \
375377 chansrv_fuse.c \
376378 chansrv_fuse.h \
379 chansrv_xfs.c \
380 chansrv_xfs.h \
377381 clipboard.c \
378382 clipboard.h \
379383 clipboard_common.h \
386390 irp.c \
387391 irp.h \
388392 mlog.h \
393 ms-erref.h \
394 ms-fscc.h \
395 ms-rdpefs.h \
396 ms-smb2.h \
389397 rail.c \
390398 rail.h \
391399 smartcard.c \
395403 sound.c \
396404 sound.h \
397405 xcommon.c \
398 xcommon.h
406 xcommon.h \
407 audin.c \
408 audin.h
399409
400410 xrdp_chansrv_LDFLAGS = \
401411 $(X_LIBS)
498508 distclean-compile:
499509 -rm -f *.tab.c
500510
511 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audin.Po@am__quote@ # am--include-marker
501512 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chansrv.Po@am__quote@ # am--include-marker
502513 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chansrv_common.Po@am__quote@ # am--include-marker
503514 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chansrv_fuse.Po@am__quote@ # am--include-marker
515 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chansrv_xfs.Po@am__quote@ # am--include-marker
504516 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clipboard.Po@am__quote@ # am--include-marker
505517 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clipboard_file.Po@am__quote@ # am--include-marker
506518 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devredir.Po@am__quote@ # am--include-marker
673685 mostlyclean-am
674686
675687 distclean: distclean-am
676 -rm -f ./$(DEPDIR)/chansrv.Po
688 -rm -f ./$(DEPDIR)/audin.Po
689 -rm -f ./$(DEPDIR)/chansrv.Po
677690 -rm -f ./$(DEPDIR)/chansrv_common.Po
678691 -rm -f ./$(DEPDIR)/chansrv_fuse.Po
692 -rm -f ./$(DEPDIR)/chansrv_xfs.Po
679693 -rm -f ./$(DEPDIR)/clipboard.Po
680694 -rm -f ./$(DEPDIR)/clipboard_file.Po
681695 -rm -f ./$(DEPDIR)/devredir.Po
731745 installcheck-am:
732746
733747 maintainer-clean: maintainer-clean-am
734 -rm -f ./$(DEPDIR)/chansrv.Po
748 -rm -f ./$(DEPDIR)/audin.Po
749 -rm -f ./$(DEPDIR)/chansrv.Po
735750 -rm -f ./$(DEPDIR)/chansrv_common.Po
736751 -rm -f ./$(DEPDIR)/chansrv_fuse.Po
752 -rm -f ./$(DEPDIR)/chansrv_xfs.Po
737753 -rm -f ./$(DEPDIR)/clipboard.Po
738754 -rm -f ./$(DEPDIR)/clipboard_file.Po
739755 -rm -f ./$(DEPDIR)/devredir.Po
0 /**
1 * xrdp: A Remote Desktop Protocol server.
2 *
3 * Copyright (C) Jay Sorg 2019
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * MS-RDPEAI
18 *
19 */
20
21 #if defined(HAVE_CONFIG_H)
22 #include <config_ac.h>
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "os_calls.h"
30 #include "chansrv.h"
31 #include "log.h"
32 #include "xrdp_constants.h"
33 #include "fifo.h"
34
35 #define MSG_SNDIN_VERSION 1
36 #define MSG_SNDIN_FORMATS 2
37 #define MSG_SNDIN_OPEN 3
38 #define MSG_SNDIN_OPEN_REPLY 4
39 #define MSG_SNDIN_DATA_INCOMING 5
40 #define MSG_SNDIN_DATA 6
41 #define MSG_SNDIN_FORMATCHANGE 7
42
43 #define AUDIN_VERSION 0x00000001
44
45 #define AUDIN_NAME "AUDIO_INPUT"
46 #define AUDIN_FLAGS 1 /* WTS_CHANNEL_OPTION_DYNAMIC */
47
48 extern FIFO g_in_fifo; /* in sound.c */
49 extern int g_bytes_in_fifo; /* in sound.c */
50
51 struct xr_wave_format_ex
52 {
53 int wFormatTag;
54 int nChannels;
55 int nSamplesPerSec;
56 int nAvgBytesPerSec;
57 int nBlockAlign;
58 int wBitsPerSample;
59 int cbSize;
60 uint8_t *data;
61 };
62
63 static uint8_t g_pcm_44100_data[] = { 0 };
64 static struct xr_wave_format_ex g_pcm_44100 =
65 {
66 WAVE_FORMAT_PCM, /* wFormatTag */
67 2, /* num of channels */
68 44100, /* samples per sec */
69 176400, /* avg bytes per sec */
70 4, /* block align */
71 16, /* bits per sample */
72 0, /* data size */
73 g_pcm_44100_data /* data */
74 };
75
76 static struct chansrv_drdynvc_procs g_audin_info;
77 static int g_audin_chanid;
78 static struct stream *g_in_s;
79
80 static struct xr_wave_format_ex *g_server_formats[] =
81 {
82 &g_pcm_44100,
83 NULL
84 };
85
86 static struct xr_wave_format_ex **g_client_formats = NULL;
87
88 static int g_current_format = 0; /* index in g_client_formats */
89
90 /*****************************************************************************/
91 static int
92 cleanup_client_formats(void)
93 {
94 int index;
95
96 if (g_client_formats == NULL)
97 {
98 return 0;
99 }
100 index = 0;
101 while (g_client_formats[index] != NULL)
102 {
103 g_free(g_client_formats[index]->data);
104 g_free(g_client_formats[index]);
105 index++;
106 }
107 g_free(g_client_formats);
108 g_client_formats = NULL;
109 return 0;
110 }
111
112 /*****************************************************************************/
113 static int
114 audin_send_version(int chan_id)
115 {
116 int error;
117 int bytes;
118 struct stream *s;
119
120 LOG(0, ("audin_send_version:"));
121 make_stream(s);
122 init_stream(s, 32);
123 out_uint8(s, MSG_SNDIN_VERSION);
124 out_uint32_le(s, AUDIN_VERSION);
125 s_mark_end(s);
126 bytes = (int) (s->end - s->data);
127 error = chansrv_drdynvc_data(chan_id, s->data, bytes);
128 free_stream(s);
129 return error;
130 }
131
132 /*****************************************************************************/
133 static int
134 audin_send_formats(int chan_id)
135 {
136 int error;
137 int bytes;
138 int num_formats;
139 int index;
140 struct stream *s;
141 struct xr_wave_format_ex *wf;
142
143 LOG(0, ("audin_send_formats:"));
144 num_formats = sizeof(g_server_formats) /
145 sizeof(g_server_formats[0]) - 1;
146 make_stream(s);
147 init_stream(s, 8192 * num_formats);
148 out_uint8(s, MSG_SNDIN_FORMATS);
149 out_uint32_le(s, num_formats);
150 out_uint32_le(s, 0); /* cbSizeFormatsPacket */
151 for (index = 0; index < num_formats; index++)
152 {
153 wf = g_server_formats[index];
154 LOG(0, ("audin_send_formats: sending format wFormatTag 0x%4.4x "
155 "nChannels %d nSamplesPerSec %d",
156 wf->wFormatTag, wf->nChannels, wf->nSamplesPerSec));
157 out_uint16_le(s, wf->wFormatTag);
158 out_uint16_le(s, wf->nChannels);
159 out_uint32_le(s, wf->nSamplesPerSec);
160 out_uint32_le(s, wf->nAvgBytesPerSec);
161 out_uint16_le(s, wf->nBlockAlign);
162 out_uint16_le(s, wf->wBitsPerSample);
163 out_uint16_le(s, wf->cbSize);
164 if (wf->cbSize > 0)
165 {
166 out_uint8p(s, wf->data, wf->cbSize);
167 }
168 }
169 s_mark_end(s);
170 bytes = (int) (s->end - s->data);
171 error = chansrv_drdynvc_data(chan_id, s->data, bytes);
172 free_stream(s);
173 return error;
174 }
175
176 /*****************************************************************************/
177 static int
178 audin_send_open(int chan_id)
179 {
180 int error;
181 int bytes;
182 struct stream *s;
183 struct xr_wave_format_ex *wf;
184
185 LOG(0, ("audin_send_open:"));
186 make_stream(s);
187 init_stream(s, 8192);
188 out_uint8(s, MSG_SNDIN_OPEN);
189 out_uint32_le(s, 2048); /* FramesPerPacket */
190 out_uint32_le(s, g_current_format); /* initialFormat */
191 wf = g_client_formats[g_current_format];
192 out_uint16_le(s, wf->wFormatTag);
193 out_uint16_le(s, wf->nChannels);
194 out_uint32_le(s, wf->nSamplesPerSec);
195 out_uint32_le(s, wf->nAvgBytesPerSec);
196 out_uint16_le(s, wf->nBlockAlign);
197 out_uint16_le(s, wf->wBitsPerSample);
198 bytes = wf->cbSize;
199 out_uint16_le(s, bytes);
200 if (bytes > 0)
201 {
202 out_uint8p(s, wf->data, bytes);
203 }
204 s_mark_end(s);
205 bytes = (int) (s->end - s->data);
206 error = chansrv_drdynvc_data(chan_id, s->data, bytes);
207 free_stream(s);
208 return error;
209 }
210
211 /*****************************************************************************/
212 static int
213 audin_process_version(int chan_id, struct stream *s)
214 {
215 int version;
216
217 LOG(0, ("audin_process_version:"));
218 if (!s_check_rem(s, 4))
219 {
220 LOG(0, ("audin_process_version: parse error"));
221 return 1;
222 }
223 in_uint32_le(s, version);
224 LOG(0, ("audin_process_version: version %d", version));
225 return audin_send_formats(chan_id);
226 }
227
228 /*****************************************************************************/
229 static int
230 audin_process_formats(int chan_id, struct stream *s)
231 {
232 int index;
233 int num_formats;
234 struct xr_wave_format_ex *wf;
235
236 LOG(0, ("audin_process_formats:"));
237 cleanup_client_formats();
238 if (!s_check_rem(s, 8))
239 {
240 LOG(0, ("audin_process_formats: parse error"));
241 return 1;
242 }
243 in_uint32_le(s, num_formats);
244 in_uint8s(s, 4); /* cbSizeFormatsPacket */
245 g_client_formats = g_new0(struct xr_wave_format_ex *, num_formats + 1);
246 for (index = 0; index < num_formats; index++)
247 {
248 if (!s_check_rem(s, 18))
249 {
250 LOG(0, ("audin_process_formats: parse error"));
251 return 1;
252 }
253 wf = g_new0(struct xr_wave_format_ex, 1);
254 g_client_formats[index] = wf;
255 in_uint16_le(s, wf->wFormatTag);
256 in_uint16_le(s, wf->nChannels);
257 in_uint32_le(s, wf->nSamplesPerSec);
258 in_uint32_le(s, wf->nAvgBytesPerSec);
259 in_uint16_le(s, wf->nBlockAlign);
260 in_uint16_le(s, wf->wBitsPerSample);
261 in_uint16_le(s, wf->cbSize);
262 LOG(0, ("audin_process_formats: recved format wFormatTag 0x%4.4x "
263 "nChannels %d nSamplesPerSec %d",
264 wf->wFormatTag, wf->nChannels, wf->nSamplesPerSec));
265 if (wf->cbSize > 0)
266 {
267 if (!s_check_rem(s, wf->cbSize))
268 {
269 LOG(0, ("audin_process_formats: parse error"));
270 return 1;
271 }
272 wf->data = g_new0(uint8_t, wf->cbSize);
273 in_uint8a(s, wf->data, wf->cbSize);
274 }
275 }
276 audin_send_open(chan_id);
277 return 0;
278 }
279
280 /*****************************************************************************/
281 static int
282 audin_process_open_reply(int chan_id, struct stream *s)
283 {
284 int result;
285
286 if (!s_check_rem(s, 4))
287 {
288 LOG(0, ("audin_process_open_reply: parse error"));
289 return 1;
290 }
291 in_uint32_le(s, result);
292 LOG(0, ("audin_process_open_reply: result 0x%8.8x", result));
293 return 0;
294 }
295
296 /*****************************************************************************/
297 static int
298 audin_process_incoming_data(int chan_id, struct stream *s)
299 {
300 LOG(10, ("audin_process_incoming_data:"));
301 return 0;
302 }
303
304 /*****************************************************************************/
305 static int
306 audin_process_data(int chan_id, struct stream *s)
307 {
308 int data_bytes;
309 struct stream *ls;
310
311 data_bytes = (int) (s->end - s->p);
312 LOG(10, ("audin_process_data: data_bytes %d", data_bytes));
313
314 xstream_new(ls, data_bytes);
315 g_memcpy(ls->data, s->p, data_bytes);
316 ls->p += data_bytes;
317 s_mark_end(ls);
318 fifo_insert(&g_in_fifo, (void *) ls);
319 g_bytes_in_fifo += data_bytes;
320
321 return 0;
322 }
323
324 /*****************************************************************************/
325 static int
326 audin_process_format_change(int chan_id, struct stream *s)
327 {
328 LOG(0, ("audin_process_format_change:"));
329 if (!s_check_rem(s, 4))
330 {
331 LOG(0, ("audin_process_format_change: parse error"));
332 return 1;
333 }
334 in_uint32_le(s, g_current_format);
335 LOG(0, ("audin_process_format_change: g_current_format %d",
336 g_current_format));
337 return 0;
338 }
339
340 /*****************************************************************************/
341 static int
342 audin_process_msg(int chan_id, struct stream *s)
343 {
344 int code;
345
346 LOG(10, ("audin_process_msg:"));
347 if (!s_check_rem(s, 1))
348 {
349 LOG(0, ("audin_process_msg: parse error"));
350 return 1;
351 }
352 in_uint8(s, code);
353 LOG(10, ("audin_process_msg: code %d", code));
354 switch (code)
355 {
356 case MSG_SNDIN_VERSION:
357 return audin_process_version(chan_id, s);
358 case MSG_SNDIN_FORMATS:
359 return audin_process_formats(chan_id, s);
360 case MSG_SNDIN_OPEN_REPLY:
361 return audin_process_open_reply(chan_id, s);
362 case MSG_SNDIN_DATA_INCOMING:
363 return audin_process_incoming_data(chan_id, s);
364 case MSG_SNDIN_DATA:
365 return audin_process_data(chan_id, s);
366 case MSG_SNDIN_FORMATCHANGE:
367 return audin_process_format_change(chan_id, s);
368 default:
369 LOG(0, ("audin_process_msg: unprocessed code %d", code));
370 break;
371 }
372 return 0;
373 }
374
375 /*****************************************************************************/
376 static int
377 audin_open_response(int chan_id, int creation_status)
378 {
379 LOG(0, ("audin_open_response: creation_status 0x%8.8x", creation_status));
380 if (creation_status == 0)
381 {
382 return audin_send_version(chan_id);
383 }
384 return 0;
385 }
386
387 /*****************************************************************************/
388 static int
389 audin_close_response(int chan_id)
390 {
391 LOG(0, ("audin_close_response:"));
392 g_audin_chanid = 0;
393 cleanup_client_formats();
394 free_stream(g_in_s);
395 g_in_s = NULL;
396 return 0;
397 }
398
399 /*****************************************************************************/
400 static int
401 audin_data_fragment(int chan_id, char *data, int bytes)
402 {
403 int rv;
404 int left;
405
406 LOG(10, ("audin_data_fragment:"));
407 if (!s_check_rem(g_in_s, bytes))
408 {
409 left = (int) (g_in_s->end - g_in_s->p);
410 LOG(0, ("audin_data_fragment: error bytes %d left %d", bytes, left));
411 return 1;
412 }
413 out_uint8a(g_in_s, data, bytes);
414 if (g_in_s->p == g_in_s->end)
415 {
416 g_in_s->p = g_in_s->data;
417 rv = audin_process_msg(chan_id, g_in_s);
418 free_stream(g_in_s);
419 g_in_s = NULL;
420 return rv;
421 }
422 return 0;
423 }
424
425 /*****************************************************************************/
426 static int
427 audin_data_first(int chan_id, char *data, int bytes, int total_bytes)
428 {
429 LOG(10, ("audin_data_first:"));
430 if (g_in_s != NULL)
431 {
432 LOG(0, ("audin_data_first: warning g_in_s is not nil"));
433 free_stream(g_in_s);
434 }
435 make_stream(g_in_s);
436 init_stream(g_in_s, total_bytes);
437 g_in_s->end = g_in_s->data + total_bytes;
438 return audin_data_fragment(chan_id, data, bytes);
439 }
440
441 /*****************************************************************************/
442 static int
443 audin_data(int chan_id, char *data, int bytes)
444 {
445 struct stream ls;
446
447 LOG(10, ("audin_data:"));
448 //g_hexdump(data, bytes);
449 if (g_in_s == NULL)
450 {
451 g_memset(&ls, 0, sizeof(ls));
452 ls.data = data;
453 ls.p = ls.data;
454 ls.end = ls.p + bytes;
455 return audin_process_msg(chan_id, &ls);
456 }
457 return audin_data_fragment(chan_id, data, bytes);
458 }
459
460 /*****************************************************************************/
461 int
462 audin_init(void)
463 {
464 LOG(0, ("audin_init:"));
465 g_memset(&g_audin_info, 0, sizeof(g_audin_info));
466 g_audin_info.open_response = audin_open_response;
467 g_audin_info.close_response = audin_close_response;
468 g_audin_info.data_first = audin_data_first;
469 g_audin_info.data = audin_data;
470 g_audin_chanid = 0;
471 g_in_s = NULL;
472 return 0;
473 }
474
475 /*****************************************************************************/
476 int
477 audin_deinit(void)
478 {
479 LOG(0, ("audin_deinit:"));
480 return 0;
481 }
482
483 /*****************************************************************************/
484 int
485 audin_start(void)
486 {
487 int error;
488 struct stream* s;
489
490 LOG(0, ("audin_start:"));
491 if (g_audin_chanid != 0)
492 {
493 return 1;
494 }
495
496 /* if there is any data in FIFO, discard it */
497 while ((s = (struct stream *) fifo_remove(&g_in_fifo)) != NULL)
498 {
499 xstream_free(s);
500 }
501 g_bytes_in_fifo = 0;
502
503 error = chansrv_drdynvc_open(AUDIN_NAME, AUDIN_FLAGS,
504 &g_audin_info, /* callback functions */
505 &g_audin_chanid); /* chansrv chan_id */
506 LOG(0, ("audin_start: error %d g_audin_chanid %d", error, g_audin_chanid));
507 return error;
508 }
509
510 /*****************************************************************************/
511 int
512 audin_stop(void)
513 {
514 LOG(0, ("audin_stop:"));
515 chansrv_drdynvc_close(g_audin_chanid);
516 return 0;
517 }
0 /**
1 * xrdp: A Remote Desktop Protocol server.
2 *
3 * Copyright (C) Jay Sorg 2019
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * MS-RDPEAI
18 *
19 */
20
21 #ifndef _AUDIN_H_
22 #define _AUDIN_H_
23
24 int
25 audin_init(void);
26 int
27 audin_deinit(void);
28 int
29 audin_start(void);
30 int
31 audin_stop(void);
32
33 #endif
3636 #include "xcommon.h"
3737 #include "chansrv_fuse.h"
3838 #include "xrdp_sockets.h"
39 #include "audin.h"
3940
4041 static struct trans *g_lis_trans = 0;
4142 static struct trans *g_con_trans = 0;
5859 int g_rdpsnd_chan_id = -1; /* rdpsnd */
5960 int g_rdpdr_chan_id = -1; /* rdpdr */
6061 int g_rail_chan_id = -1; /* rail */
62 int g_restrict_outbound_clipboard = 0;
6163
6264 char *g_exec_name;
6365 tbus g_exec_event;
404406
405407 if (g_rdpdr_index >= 0)
406408 {
407 dev_redir_init();
409 devredir_init();
408410 xfuse_init();
409411 }
410412
412414 {
413415 rail_init();
414416 }
417
418 audin_init();
415419
416420 return rv;
417421 }
453457 }
454458 else if (chan_id == g_rdpdr_chan_id)
455459 {
456 rv = dev_redir_data_in(s, chan_id, chan_flags, length, total_length);
460 rv = devredir_data_in(s, chan_id, chan_flags, length, total_length);
457461 }
458462 else if (chan_id == g_rail_chan_id)
459463 {
14071411 LOGM((LOG_LEVEL_INFO, "channel_thread_loop: g_term_event set"));
14081412 clipboard_deinit();
14091413 sound_deinit();
1410 dev_redir_deinit();
1414 devredir_deinit();
14111415 rail_deinit();
14121416 break;
14131417 }
14291433 "trans_check_wait_objs error resetting"));
14301434 clipboard_deinit();
14311435 sound_deinit();
1432 dev_redir_deinit();
1436 devredir_deinit();
14331437 rail_deinit();
14341438 /* delete g_con_trans */
14351439 trans_delete(g_con_trans);
14551459 api_con_trans_list_check_wait_objs();
14561460 xcommon_check_wait_objs();
14571461 sound_check_wait_objs();
1458 dev_redir_check_wait_objs();
1462 devredir_check_wait_objs();
14591463 xfuse_check_wait_objs();
14601464 timeout = -1;
14611465 num_objs = 0;
14741478 &timeout);
14751479 xcommon_get_wait_objs(objs, &num_objs, &timeout);
14761480 sound_get_wait_objs(objs, &num_objs, &timeout);
1477 dev_redir_get_wait_objs(objs, &num_objs, &timeout);
1481 devredir_get_wait_objs(objs, &num_objs, &timeout);
14781482 xfuse_get_wait_objs(objs, &num_objs, &timeout);
14791483 get_timeout(&timeout);
14801484 } /* end while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) */
17791783 enum logReturns error;
17801784 struct log_config logconfig;
17811785 enum logLevels log_level;
1782
1786 char *restrict_outbound_clipboard_env;
17831787 g_init("xrdp-chansrv"); /* os_calls */
17841788
17851789 log_path[255] = 0;
17881792 g_writeln("error reading CHANSRV_LOG_PATH and HOME environment variable");
17891793 g_deinit();
17901794 return 1;
1795 }
1796
1797 restrict_outbound_clipboard_env = g_getenv("CHANSRV_RESTRICT_OUTBOUND_CLIPBOARD");
1798 if (restrict_outbound_clipboard_env != 0)
1799 {
1800 if (g_strcmp(restrict_outbound_clipboard_env, "1") == 0)
1801 {
1802 g_restrict_outbound_clipboard = 1;
1803 }
17911804 }
17921805
17931806 read_ini();
1515 * limitations under the License.
1616 */
1717
18 /*
19 * TODO
20 * o when creating dir/file, ensure it does not already exist
21 * o do not allow dirs to be created in ino==1 except for .clipboard and share mounts
22 * o fix the HACK where I have to use my own buf instead of g_buffer
23 * this is in func xfuse_check_wait_objs()
24 * o if fuse mount point is already mounted, I get segfault
25 * o in open, check for modes such as O_TRUNC, O_APPEND
26 * o copying over an existing file does not work
27 * o after a dir is created, the device cannot be unmounted on the client side
28 * so something is holding it up
29 * o in thunar, when I move a file by dragging to another folder, the file
30 * is getting copied instead of being moved
31 * o unable to edit files in vi
32 * o fuse ops to support
33 * o touch does not work
34 * o chmod must work
35 * o cat >> file is not working
36 *
37 */
38
39 //#define USE_SYNC_FLAG
40
4118 /* FUSE mount point */
4219 char g_fuse_root_path[256] = "";
4320 char g_fuse_clipboard_path[256] = ""; /* for clipboard use */
5734 #include <stdio.h>
5835 #include <stdlib.h>
5936 #include <string.h>
60 #include <time.h>
6137
6238 #include "arch.h"
6339 #include "chansrv_fuse.h"
40 #include "chansrv_xfs.h"
6441
6542 /* dummy calls when XRDP_FUSE is not defined */
6643 int xfuse_init(void) { return 0; }
6744 int xfuse_deinit(void) { return 0; }
6845 int xfuse_check_wait_objs(void) { return 0; }
6946 int xfuse_get_wait_objs(tbus *objs, int *count, int *timeout) { return 0; }
47 int xfuse_create_share(tui32 device_id, const char *dirname) { return 0; }
48 void xfuse_delete_share(tui32 share_id) {}
7049 int xfuse_clear_clip_dir(void) { return 0; }
7150 int xfuse_file_contents_range(int stream_id, const char *data, int data_bytes) { return 0; }
72 int xfuse_file_contents_size(int stream_id, int file_size) { return 0; }
73 int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex) { return 0; }
74 int xfuse_create_share(tui32 device_id, const char *dirname) { return 0; }
75 void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId) {}
76 void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length) {}
77 void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length) {}
78 int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) { return 0; }
79 void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) {}
80 void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus) {}
81 void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus) {}
82 void xfuse_devredir_cb_file_close(void *vp) {}
51 int xfuse_file_contents_size(int stream_id, int file_size)
52 { return 0; }
53 int xfuse_add_clip_dir_item(const char *filename,
54 int flags, int size, int lindex) { return 0; }
55
56 void xfuse_devredir_cb_enum_dir_add_entry(
57 struct state_dirscan *fip,
58 const char *name,
59 const struct file_attr *fattr)
60 {}
61 void xfuse_devredir_cb_enum_dir_done(struct state_dirscan *fip,
62 enum NTSTATUS IoStatus)
63 {}
64 void xfuse_devredir_cb_lookup_entry(struct state_lookup *fip,
65 enum NTSTATUS IoStatus,
66 const struct file_attr *file_info)
67 {}
68 void xfuse_devredir_cb_setattr(struct state_setattr *fip,
69 enum NTSTATUS IoStatus)
70 {}
71 void xfuse_devredir_cb_create_file(struct state_create *fip,
72 enum NTSTATUS IoStatus,
73 tui32 DeviceId, tui32 FileId)
74 {}
75 void xfuse_devredir_cb_open_file(struct state_open *fip,
76 enum NTSTATUS IoStatus,
77 tui32 DeviceId, tui32 FileId)
78 {}
79 void xfuse_devredir_cb_read_file(struct state_read *fip,
80 const char *buf, size_t length)
81 {}
82 void xfuse_devredir_cb_write_file(
83 struct state_write *fip,
84 enum NTSTATUS IoStatus,
85 off_t offset,
86 size_t length)
87 {}
88 void xfuse_devredir_cb_rmdir_or_file(struct state_remove *fip,
89 enum NTSTATUS IoStatus)
90 {}
91 void xfuse_devredir_cb_rename_file(struct state_rename *fip,
92 enum NTSTATUS IoStatus)
93 {}
94 void xfuse_devredir_cb_file_close(struct state_close *fip)
95 {}
8396
8497 #else
8598
105118 #include "os_calls.h"
106119 #include "clipboard_file.h"
107120 #include "chansrv_fuse.h"
121 #include "chansrv_xfs.h"
108122 #include "devredir.h"
109123 #include "list.h"
110 #include "fifo.h"
111124 #include "file.h"
112125
113126 #ifndef EREMOTEIO
114127 #define EREMOTEIO EIO
115128 #endif
116129
117 #define min(x, y) ((x) < (y) ? (x) : (y))
118
119 #define XFUSE_ATTR_TIMEOUT 1.0
120 #define XFUSE_ENTRY_TIMEOUT 1.0
121
122 #define DOTDOT_INODE 0
123 #define DOT_INODE 0
124 #define FIRST_INODE 1
130 #define XFUSE_ATTR_TIMEOUT 5.0
131 #define XFUSE_ENTRY_TIMEOUT 5.0
125132
126133 /* module based logging */
127134 #define LOG_ERROR 0
128135 #define LOG_INFO 1
129136 #define LOG_DEBUG 2
137 #ifndef LOG_LEVEL
130138 #define LOG_LEVEL LOG_ERROR
139 #endif
131140
132141 #define log_error(_params...) \
133142 { \
163172 } \
164173 }
165174
166 #define OP_RENAME_FILE 0x01
167
168 /* the xrdp file system in memory */
169 struct xrdp_fs
170 {
171 struct xrdp_inode **inode_table; /* a table of entries; can grow */
172 unsigned int max_entries; /* size of inode_table[] */
173 unsigned int num_entries; /* num entries available in inode_table */
174 unsigned int next_node; /* next free node number */
175
176 /* Type of buffer used for fuse_add_direntry() calls */
177 struct dirbuf1
178 {
179 char buf[4096];
180 size_t len;
175181 };
176182
177 struct dirbuf
178 {
179 char *p;
180 size_t size;
183 /*
184 * Record type used to maintain state when running a directory scan
185 */
186 struct state_dirscan
187 {
188 fuse_req_t req; /* Original FUSE request from opendir */
189 struct fuse_file_info fi; /* File info struct passed to opendir */
190 fuse_ino_t pinum; /* inum of parent directory */
181191 };
182192
183 struct dirbuf1
184 {
185 char buf[4096];
186 int bytes_in_buf;
187 int first_time;
193
194 /*
195 * Record type used to maintain state when running an entry lookup
196 */
197 struct state_lookup
198 {
199 fuse_req_t req; /* Original FUSE request from lookup */
200 fuse_ino_t pinum; /* inum of parent directory */
201 char name[XFS_MAXFILENAMELEN];
202 /* Name to look up */
203 fuse_ino_t existing_inum;
204 /* inum of an existing entry */
205 tui32 existing_generation;
206 /* generation of the above */
188207 };
189208
190 /* FUSE reply types */
191 #define RT_FUSE_REPLY_OPEN 1
192 #define RT_FUSE_REPLY_CREATE 2
193
194 struct xfuse_info
195 {
196 struct fuse_file_info *fi;
197 fuse_req_t req;
198 fuse_ino_t inode;
199 fuse_ino_t new_inode;
200 int invoke_fuse;
201 char name[1024];
202 char new_name[1024];
203 tui32 device_id;
204 int reply_type;
205 int mode;
206 int type;
207 size_t size;
208 off_t off;
209 struct dirbuf1 dirbuf1;
209 /*
210 * Record type used to maintain state when running an entry setattr
211 */
212 struct state_setattr
213 {
214 fuse_req_t req; /* Original FUSE request from lookup */
215 fuse_ino_t inum; /* inum of entry */
216 struct file_attr fattr; /* File attributes to set */
217 tui32 change_mask; /* Attributes to set in fattr */
210218 };
211 typedef struct xfuse_info XFUSE_INFO;
219
220
221 /*
222 * Record type used to maintain state when running an open
223 */
224 struct state_open
225 {
226 fuse_req_t req; /* Original FUSE request from lookup */
227 struct fuse_file_info fi; /* File info struct passed to open */
228 fuse_ino_t inum; /* inum of file to open */
229 };
230
231
232 /*
233 * Record type used to maintain state when running a create
234 */
235 struct state_create
236 {
237 fuse_req_t req; /* Original FUSE request from lookup */
238 struct fuse_file_info fi; /* File info struct passed to open */
239 fuse_ino_t pinum; /* inum of parent directory */
240 char name[XFS_MAXFILENAMELEN];
241 /* Name of file in parent directory */
242 mode_t mode; /* Mode of file to create */
243 };
244
245 /*
246 * Record type used to maintain state when running a read
247 */
248 struct state_read
249 {
250 fuse_req_t req; /* Original FUSE request from lookup */
251 };
252
253 /*
254 * Record type used to maintain state when running a write
255 */
256 struct state_write
257 {
258 fuse_req_t req; /* Original FUSE request from lookup */
259 fuse_ino_t inum; /* inum of file we're writing */
260 };
261
262 /*
263 * Record type used to maintain state when running a remove
264 */
265 struct state_remove
266 {
267 fuse_req_t req; /* Original FUSE request from lookup */
268 fuse_ino_t inum; /* inum of file we're removing */
269 };
270
271 /*
272 * Record type used to maintain state when running a rename
273 */
274 struct state_rename
275 {
276 fuse_req_t req; /* Original FUSE request from lookup */
277 fuse_ino_t pinum; /* inum of parent of file */
278 fuse_ino_t new_pinum; /* inum of new parent of file */
279 char name[XFS_MAXFILENAMELEN];
280 /* New name of file in new parent dir */
281 };
282
283 /*
284 * Record type used to maintain state when running a close
285 */
286 struct state_close
287 {
288 fuse_req_t req; /* Original FUSE request from lookup */
289 struct fuse_file_info fi; /* File info struct passed to open */
290 fuse_ino_t inum; /* inum of file to open */
291 };
212292
213293 struct xfuse_handle
214294 {
228308 int size;
229309 };
230310
231 struct dir_info
232 {
233 /* last index accessed in g_xrdp_fs.inode_table[] */
234 int index;
235 };
236
237 /* queue FUSE opendir commands so we run only one at a time */
238 struct opendir_req
239 {
240 fuse_req_t req;
241 fuse_ino_t ino;
242 struct fuse_file_info *fi;
243 };
244
245311 static char g_fuse_mount_name[256] = "xrdp_client";
246
247 FIFO g_fifo_opendir;
312 static mode_t g_umask = 077; /* Umask for files in fs */
248313
249314 static struct list *g_req_list = 0;
250 static struct xrdp_fs g_xrdp_fs; /* an inst of xrdp file system */
315 static struct xfs_fs *g_xfs; /* an inst of xrdp file system */
316 static ino_t g_clipboard_inum; /* inode of clipboard dir */
251317 static char *g_mount_point = 0; /* our FUSE mount point */
252318 static struct fuse_lowlevel_ops g_xfuse_ops; /* setup FUSE callbacks */
253319 static int g_xfuse_inited = 0; /* true when FUSE is inited */
261327 static int xfuse_init_xrdp_fs(void);
262328 static int xfuse_deinit_xrdp_fs(void);
263329 static int xfuse_init_lib(struct fuse_args *args);
264 static int xfuse_is_inode_valid(fuse_ino_t ino);
265
266 // LK_TODO
267 #if 0
268 static void xfuse_create_file(fuse_req_t req, fuse_ino_t parent,
269 const char *name, mode_t mode, int type);
270 #endif
271
272 static void xfuse_dump_fs(void);
273 static tui32 xfuse_get_device_id_for_inode(fuse_ino_t ino, char *full_path);
274 static void fuse_reverse_pathname(char *full_path, char *reverse_path);
275
276 static struct xrdp_inode * xfuse_get_inode_from_pinode_name(fuse_ino_t pinode,
277 const char *name);
278
279 static struct xrdp_inode *
280 xfuse_create_file_in_xrdp_fs(tui32 device_id, int pinode, const char *name,
281 int type);
282
283 static int xfuse_does_file_exist(fuse_ino_t parent, char *name);
284 static int xfuse_delete_file_with_xinode(XRDP_INODE *xinode);
285 static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode);
286 static int xfuse_recursive_delete_dir_with_xinode(XRDP_INODE *xinode);
287 static void xfuse_update_xrdpfs_size(void);
288
289 #ifdef USE_SYNC_FLAG
290 static void xfuse_enum_dir(fuse_req_t req, fuse_ino_t ino, size_t size,
291 off_t off, struct fuse_file_info *fi);
292 #endif
293330
294331 /* forward declarations for FUSE callbacks */
295332 static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent,
300337
301338 /* this is not a callback, but it's used by xfuse_cb_readdir() */
302339 static int xfuse_dirbuf_add1(fuse_req_t req, struct dirbuf1 *b,
303 const char *name, fuse_ino_t ino);
340 XFS_INODE *xinode, off_t offset);
304341
305342 static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
306343 off_t off, struct fuse_file_info *fi);
307344
308345 static void xfuse_cb_mkdir(fuse_req_t req, fuse_ino_t parent,
309346 const char *name, mode_t mode);
310
311 static void xfuse_cb_rmdir(fuse_req_t req, fuse_ino_t parent,
312 const char *name);
313347
314348 static void xfuse_cb_unlink(fuse_req_t req, fuse_ino_t parent,
315349 const char *name);
318352 fuse_ino_t old_parent, const char *old_name,
319353 fuse_ino_t new_parent, const char *new_name);
320354
321 /* this is not a callback, but it is used by the above two functions */
322 static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent,
323 const char *name, int type);
324
355 /* Whether to create a dir of file depends on whether S_IFDIR is set in the
356 mode field */
325357 static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
326358 const char *name, mode_t mode,
327 struct fuse_file_info *fi, int type);
359 struct fuse_file_info *fi);
328360
329361 static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
330362 struct fuse_file_info *fi);
353385 static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
354386 struct fuse_file_info *fi);
355387
356 static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino,
357 struct fuse_file_info *fi);
358
359388 static void xfuse_cb_releasedir(fuse_req_t req, fuse_ino_t ino,
360389 struct fuse_file_info *fi);
361390
362 /* misc calls */
363 static void xfuse_mark_as_stale(fuse_ino_t pinode);
364 static void xfuse_delete_stale_entries(fuse_ino_t pinode);
391 /* miscellaneous functions */
392 static void xfs_inode_to_fuse_entry_param(const XFS_INODE *xinode,
393 struct fuse_entry_param *e);
394 static void make_fuse_entry_reply(fuse_req_t req, const XFS_INODE *xinode);
395 static void make_fuse_attr_reply(fuse_req_t req, const XFS_INODE *xinode);
396 static const char *filename_on_device(const char *full_path);
397 static void update_inode_file_attributes(const struct file_attr *fattr,
398 tui32 change_mask, XFS_INODE *xinode);
399 static char *get_name_for_entry_in_parent(fuse_ino_t parent, const char *name);
365400
366401 /*****************************************************************************/
367402 int
388423 {
389424 g_strncpy(g_fuse_mount_name, value, 255);
390425 }
426 else if (g_strcasecmp(item, "FileUmask") == 0)
427 {
428 g_umask = strtol(value, NULL, 0);
429 log_info("g_umask set to 0%o", g_umask);
430 }
391431 }
392432 list_delete(items);
393433 list_delete(values);
445485 if (xfuse_init_xrdp_fs())
446486 return -1;
447487
448 /* setup FIFOs */
449 fifo_init(&g_fifo_opendir, 30);
450
451488 /* setup FUSE callbacks */
452489 g_memset(&g_xfuse_ops, 0, sizeof(g_xfuse_ops));
453490 g_xfuse_ops.lookup = xfuse_cb_lookup;
454491 g_xfuse_ops.readdir = xfuse_cb_readdir;
455492 g_xfuse_ops.mkdir = xfuse_cb_mkdir;
456 g_xfuse_ops.rmdir = xfuse_cb_rmdir;
493 g_xfuse_ops.rmdir = xfuse_cb_unlink;
457494 g_xfuse_ops.unlink = xfuse_cb_unlink;
458495 g_xfuse_ops.rename = xfuse_cb_rename;
459496 g_xfuse_ops.open = xfuse_cb_open;
491528 int
492529 xfuse_deinit(void)
493530 {
494 xfuse_deinit_xrdp_fs();
495 fifo_deinit(&g_fifo_opendir);
496
497531 if (g_ch != 0)
498532 {
499533 fuse_session_remove_chan(g_ch);
519553 g_req_list = 0;
520554 }
521555
556 xfuse_deinit_xrdp_fs();
557
522558 g_xfuse_inited = 0;
523559 return 0;
524560 }
533569 struct fuse_chan *tmpch;
534570 int rval;
535571
536 #define HACK
537
538 #ifdef HACK
539 char buf[135168];
540 #endif
541
542572 if (g_ch == 0)
543573 return 0;
544574
546576 {
547577 tmpch = g_ch;
548578
549 #ifdef HACK
550 rval = fuse_chan_recv(&tmpch, buf, g_bufsize);
551 #else
552579 rval = fuse_chan_recv(&tmpch, g_buffer, g_bufsize);
553 #endif
554580 if (rval == -EINTR)
555581 return -1;
556582
560586 if (rval <= 0)
561587 return -1;
562588
563 #ifdef HACK
564 fuse_session_process(g_se, buf, rval, tmpch);
565 #else
566589 fuse_session_process(g_se, g_buffer, rval, tmpch);
567 #endif
568590 }
569591
570592 return 0;
601623
602624 int xfuse_create_share(tui32 device_id, const char *dirname)
603625 {
604 #if 0
605 XFUSE_INFO *fip;
606 #endif
607 XRDP_INODE *xinode;
608 /* tui32 saved_inode; */
609
610 if (dirname == NULL || strlen(dirname) == 0)
611 return -1;
612
613 /* Do we have an inode table yet? */
614 if (xfuse_init_xrdp_fs())
615 {
616 return -1;
617 }
618
619 xinode = g_new0(struct xrdp_inode, 1);
620 if (xinode == NULL)
621 {
622 log_debug("g_new0() failed");
623 return -1;
624 }
625
626 /* create directory entry */
627 xinode->parent_inode = 1;
628 xinode->inode = g_xrdp_fs.next_node++;
629 xinode->mode = 0755 | S_IFDIR;
630 xinode->nlink = 1;
631 xinode->uid = getuid();
632 xinode->gid = getgid();
633 xinode->size = 0;
634 xinode->atime = time(0);
635 xinode->mtime = time(0);
636 xinode->ctime = time(0);
637 strcpy(xinode->name, dirname);
638 xinode->device_id = device_id;
639
640 g_xrdp_fs.num_entries++;
641 /* saved_inode = xinode->inode; */
642
643 /* insert it in xrdp fs */
644 g_xrdp_fs.inode_table[xinode->inode] = xinode;
645 log_debug("created new share named %s at inode_table[%d]",
646 dirname, xinode->inode);
647
648 /* update nentries in parent inode */
649 xinode = g_xrdp_fs.inode_table[1];
650 if (xinode == NULL)
651 return -1;
652 xinode->nentries++;
653
654 #if 0
655 fip = g_new0(XFUSE_INFO, 1);
656 if (fip == NULL)
657 {
658 log_error("system out of memory");
659 return -1;
660 }
661
662 /* enumerate root dir, do not call FUSE when done */
663 fip->req = NULL;
664 fip->inode = 1; /* TODO saved_inode; */
665 strncpy(fip->name, dirname, 1024);
666 fip->name[1023] = 0;
667 fip->device_id = device_id;
668
669 dev_redir_get_dir_listing((void *) fip, device_id, "\\");
670 #endif
671
672 return 0;
626 int result = -1;
627 XFS_INODE *xinode;
628
629 if (dirname != NULL && strlen(dirname) > 0 &&
630 xfuse_init_xrdp_fs() == 0)
631 {
632 xinode = xfs_add_entry(g_xfs, FUSE_ROOT_ID, dirname, (0777 | S_IFDIR));
633 if (xinode == NULL)
634 {
635 log_debug("xfs_add_entry() failed");
636 }
637 else
638 {
639 xinode->device_id = device_id;
640 result = 0;
641 }
642 }
643
644 return result;
645 }
646
647 /**
648 * @brief Remove specified share directory.
649 *
650 * This code gets called from devredir
651 *****************************************************************************/
652
653 void xfuse_delete_share(tui32 device_id)
654 {
655 xfs_delete_entries_with_device_id(g_xfs, device_id);
673656 }
674657
675658 /**
682665
683666 int xfuse_clear_clip_dir(void)
684667 {
685 fuse_ino_t i;
686 XRDP_INODE *xinode;
687 XRDP_INODE *xip;
688
689 log_debug("entered");
690
691 if (g_xrdp_fs.inode_table == NULL)
692 {
693 return 0;
694 }
695
696 /* xinode for .clipboard */
697 xip = g_xrdp_fs.inode_table[2];
698
699 for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
700 {
701 if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
702 continue;
703
704 if (xinode->parent_inode == 2)
705 {
706 g_xrdp_fs.inode_table[i] = NULL;
707 free(xinode);
708 xip->nentries--;
709 }
710 }
711
712 return 0;
668 int result = 0;
669
670 if (g_xfs != NULL && g_clipboard_inum > 0)
671 {
672 xfs_remove_directory_contents(g_xfs, g_clipboard_inum);
673 }
674
675 return result;
713676 }
714677
715678 /**
773736 filename, flags, size, lindex);
774737
775738 /* add entry to xrdp_fs */
776 XRDP_INODE *xinode = xfuse_create_file_in_xrdp_fs(0, /* device id */
777 2, /* parent inode */
778 filename,
779 S_IFREG);
739 XFS_INODE *xinode = xfs_add_entry( g_xfs,
740 g_clipboard_inum, /* parent inode */
741 filename,
742 (0666 | S_IFREG));
780743 if (xinode == NULL)
781744 {
782745 log_debug("failed to create file in xrdp filesystem");
784747 }
785748 xinode->size = size;
786749 xinode->lindex = lindex;
787 xinode->is_loc_resource = 1;
788750
789751 return 0;
790752 }
861823
862824 static int xfuse_init_xrdp_fs(void)
863825 {
864 struct xrdp_inode *xino;
826 XFS_INODE *xino;
827 int result = -1;
865828
866829 /* Already called? */
867 if (g_xrdp_fs.inode_table != NULL)
868 {
869 return 0;
870 }
871
872 g_xrdp_fs.inode_table = g_new0(struct xrdp_inode *, 4096);
873 if (g_xrdp_fs.inode_table == NULL)
830 if (g_xfs != NULL)
831 {
832 result = 0;
833 }
834 else if ((g_xfs = xfs_create_xfs_fs(0, g_getuid(), g_getgid())) == NULL)
874835 {
875836 log_error("system out of memory");
876 return -1;
877 }
878
879 /*
880 * index 0 is our .. dir
881 */
882
883 xino = g_new0(struct xrdp_inode, 1);
884 if (xino == NULL)
885 {
886 log_error("system out of memory");
887 free(g_xrdp_fs.inode_table);
888 return -1;
889 }
890 g_xrdp_fs.inode_table[0] = xino;
891 xino->parent_inode = 0;
892 xino->inode = 0;
893 xino->mode = S_IFDIR | 0755;
894 xino->nentries = 1;
895 xino->uid = getuid();
896 xino->gid = getgid();
897 xino->size = 0;
898 xino->atime = time(0);
899 xino->mtime = time(0);
900 xino->ctime = time(0);
901 strcpy(xino->name, "..");
902
903 /*
904 * index 1 is our . dir
905 */
906
907 xino = g_new0(struct xrdp_inode, 1);
908 if (xino == NULL)
909 {
910 log_error("system out of memory");
911 free(g_xrdp_fs.inode_table[0]);
912 free(g_xrdp_fs.inode_table);
913 return -1;
914 }
915 g_xrdp_fs.inode_table[1] = xino;
916 xino->parent_inode = 0;
917 xino->inode = 1;
918 xino->mode = S_IFDIR | 0755;
919 xino->nentries = 1;
920 xino->uid = getuid();
921 xino->gid = getgid();
922 xino->size = 0;
923 xino->atime = time(0);
924 xino->mtime = time(0);
925 xino->ctime = time(0);
926 strcpy(xino->name, ".");
927
928 /*
929 * index 2 is for clipboard use
930 */
931
932 xino = g_new0(struct xrdp_inode, 1);
933 if (xino == NULL)
934 {
935 log_error("system out of memory");
936 free(g_xrdp_fs.inode_table[0]);
937 free(g_xrdp_fs.inode_table[1]);
938 free(g_xrdp_fs.inode_table);
939 return -1;
940 }
941
942 g_xrdp_fs.inode_table[2] = xino;
943 xino->parent_inode = 1;
944 xino->inode = 2;
945 xino->nentries = 0;
946 xino->mode = S_IFDIR | 0755;
947 xino->uid = getuid();
948 xino->gid = getgid();
949 xino->size = 0;
950 xino->atime = time(0);
951 xino->mtime = time(0);
952 xino->ctime = time(0);
953 xino->is_loc_resource = 1;
954 strcpy(xino->name, ".clipboard");
955
956 g_xrdp_fs.max_entries = 4096;
957 g_xrdp_fs.num_entries = 3;
958 g_xrdp_fs.next_node = 3;
837 }
838 else
839 {
840 /* Need a top-level .clipboard directory */
841 xino = xfs_add_entry(g_xfs, FUSE_ROOT_ID, ".clipboard",
842 (0777 | S_IFDIR));
843 if (xino == NULL)
844 {
845 log_error("system out of memory");
846 xfs_delete_xfs_fs(g_xfs);
847 g_xfs = NULL;
848 }
849 else
850 {
851 g_clipboard_inum = xino->inum;
852 result = 0;
853 }
854 }
855 return result;
856 }
857
858 /**
859 * zap the xrdp file system
860 *
861 * @return 0 on success, -1 on failure
862 *****************************************************************************/
863
864 static int xfuse_deinit_xrdp_fs(void)
865 {
866 xfs_delete_xfs_fs(g_xfs);
867 g_xfs = NULL;
868 g_clipboard_inum = 0;
959869
960870 return 0;
961 }
962
963 /**
964 * zap the xrdp file system
965 *
966 * @return 0 on success, -1 on failure
967 *****************************************************************************/
968
969 static int xfuse_deinit_xrdp_fs(void)
970 {
971 return 0;
972 }
973
974 /**
975 * determine if specified ino exists in xrdp file system
976 *
977 * @return 1 if it does, 0 otherwise
978 *****************************************************************************/
979
980 static int xfuse_is_inode_valid(fuse_ino_t ino)
981 {
982 /* is ino present in our table? */
983 if ((ino < FIRST_INODE) || (ino >= g_xrdp_fs.next_node))
984 return 0;
985
986 if (g_xrdp_fs.inode_table[ino] == NULL)
987 return 0;
988
989 return 1;
990 }
991
992 /**
993 * @brief Create a directory or regular file.
994 *****************************************************************************/
995
996 // LK_TODO
997 #if 0
998 static void xfuse_create_file(fuse_req_t req, fuse_ino_t parent,
999 const char *name, mode_t mode, int type)
1000 {
1001 struct xrdp_inode *xinode;
1002 struct fuse_entry_param e;
1003
1004 log_debug("parent=%ld name=%s", parent, name);
1005
1006 /* do we have a valid parent inode? */
1007 if (!xfuse_is_inode_valid(parent))
1008 {
1009 log_error("inode %ld is not valid", parent);
1010 fuse_reply_err(req, EBADF);
1011 }
1012
1013 xinode = g_new0(struct xrdp_inode, 1);
1014 if (xinode == NULL)
1015 {
1016 log_error("g_new0() failed");
1017 fuse_reply_err(req, ENOMEM);
1018 }
1019
1020 /* create directory entry */
1021 xinode->parent_inode = parent;
1022 xinode->inode = g_xrdp_fs.next_node++; /* TODO should be thread safe */
1023 xinode->mode = mode | type;
1024 xinode->uid = getuid();
1025 xinode->gid = getgid();
1026 xinode->size = 0;
1027 xinode->atime = time(0);
1028 xinode->mtime = time(0);
1029 xinode->ctime = time(0);
1030 strcpy(xinode->name, name);
1031
1032 g_xrdp_fs.num_entries++;
1033
1034 /* insert it in xrdp fs */
1035 g_xrdp_fs.inode_table[xinode->inode] = xinode;
1036 xfuse_update_xrdpfs_size();
1037 log_debug("inserted new dir at inode_table[%d]", xinode->inode);
1038
1039 xfuse_dump_fs();
1040
1041 log_debug("new inode=%d", xinode->inode);
1042
1043 /* setup return value */
1044 memset(&e, 0, sizeof(e));
1045 e.ino = xinode->inode;
1046 e.attr_timeout = XFUSE_ATTR_TIMEOUT;
1047 e.entry_timeout = XFUSE_ENTRY_TIMEOUT;
1048 e.attr.st_ino = xinode->inode;
1049 e.attr.st_mode = xinode->mode;
1050 e.attr.st_nlink = xinode->nlink;
1051 e.attr.st_uid = xinode->uid;
1052 e.attr.st_gid = xinode->gid;
1053 e.attr.st_size = 0;
1054 e.attr.st_atime = xinode->atime;
1055 e.attr.st_mtime = xinode->mtime;
1056 e.attr.st_ctime = xinode->ctime;
1057 e.generation = 1;
1058
1059 fuse_reply_entry(req, &e);
1060 }
1061 #endif
1062
1063 static void xfuse_dump_fs(void)
1064 {
1065 fuse_ino_t i;
1066 struct xrdp_inode *xinode;
1067
1068 log_debug("found %d entries", g_xrdp_fs.num_entries - FIRST_INODE);
1069
1070 #if 0
1071 log_debug("not dumping xrdp fs");
1072 return;
1073 #endif
1074
1075 for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
1076 {
1077 if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
1078 continue;
1079
1080 log_debug("pinode=%d inode=%d nentries=%d nopen=%d is_synced=%d name=%s",
1081 xinode->parent_inode, xinode->inode,
1082 xinode->nentries, xinode->nopen, xinode->is_synced,
1083 xinode->name);
1084 }
1085 log_debug("%s", "");
1086 }
1087
1088 /**
1089 * Dump contents of xinode structure
1090 *
1091 * @param xino xinode structure to dump
1092 *****************************************************************************/
1093
1094 #if 0
1095 static void xfuse_dump_xrdp_inode(struct xrdp_inode *xino)
1096 {
1097 log_debug("--- dumping struct xinode ---");
1098 log_debug("name: %s", xino->name);
1099 log_debug("parent_inode: %d", xino->parent_inode);
1100 log_debug("inode: %d", xino->inode);
1101 log_debug("mode: %o", xino->mode);
1102 log_debug("nlink: %d", xino->nlink);
1103 log_debug("uid: %d", xino->uid);
1104 log_debug("gid: %d", xino->gid);
1105 log_debug("size: %zd", xino->size);
1106 log_debug("device_id: %d", xino->device_id);
1107 log_debug("%s", "");
1108 }
1109 #endif
1110
1111 /**
1112 * Return the device_id associated with specified inode and copy the
1113 * full path to the specified inode into full_path
1114 *
1115 * @param ino the inode
1116 * @param full_path full path to the inode
1117 *
1118 * @return the device_id of specified inode
1119 *****************************************************************************/
1120
1121 static tui32 xfuse_get_device_id_for_inode(fuse_ino_t ino, char *full_path)
1122 {
1123 fuse_ino_t parent_inode = 0;
1124 fuse_ino_t child_inode = ino;
1125 char reverse_path[4096];
1126
1127 /* ino == 1 is a special case; we already know that it is not */
1128 /* associated with any device redirection */
1129 if (ino == 1)
1130 {
1131 /* just return the device_id for the file in full_path */
1132 log_debug("looking for file with pinode=%ld name=%s", ino, full_path);
1133 xfuse_dump_fs();
1134
1135 XRDP_INODE *xinode = xfuse_get_inode_from_pinode_name(ino, full_path);
1136 full_path[0] = 0;
1137 if (xinode)
1138 return xinode->device_id;
1139 else
1140 return 0;
1141 }
1142
1143 reverse_path[0] = 0;
1144 full_path[0] = 0;
1145
1146 while (1)
1147 {
1148 strcat(reverse_path, g_xrdp_fs.inode_table[child_inode]->name);
1149
1150 parent_inode = g_xrdp_fs.inode_table[child_inode]->parent_inode;
1151 if (parent_inode == 1)
1152 break;
1153
1154 strcat(reverse_path, "/");
1155 child_inode = parent_inode;
1156 }
1157
1158 fuse_reverse_pathname(full_path, reverse_path);
1159
1160 return g_xrdp_fs.inode_table[child_inode]->device_id;
1161 }
1162
1163 /**
1164 * Reverse the pathname in 'reverse_path' and insert it into 'full_path'
1165 *
1166 * Example: abba/music/share1 becomes share1/music/abba
1167 *
1168 * @param full_path path name in the correct order
1169 * @param reverse_path path name in the reverse order
1170 *****************************************************************************/
1171
1172 static void fuse_reverse_pathname(char *full_path, char *reverse_path)
1173 {
1174 char *cptr;
1175
1176 full_path[0] = 0;
1177
1178 while ((cptr = strrchr(reverse_path, '/')) != NULL)
1179 {
1180 strcat(full_path, cptr + 1);
1181 strcat(full_path, "/");
1182 cptr[0] = 0;
1183 }
1184 strcat(full_path, reverse_path);
1185 }
1186
1187 /**
1188 * Return the inode that matches the name and parent inode
1189 *****************************************************************************/
1190
1191 static struct xrdp_inode * xfuse_get_inode_from_pinode_name(fuse_ino_t pinode,
1192 const char *name)
1193 {
1194 fuse_ino_t i;
1195 struct xrdp_inode * xinode;
1196
1197 for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
1198 {
1199 if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
1200 continue;
1201
1202 /* match parent inode */
1203 if (xinode->parent_inode != pinode)
1204 continue;
1205
1206 /* match name */
1207 if (strcmp(xinode->name, name) != 0)
1208 continue;
1209
1210 return xinode;
1211 }
1212 return NULL;
1213 }
1214
1215 /**
1216 * Create file in xrdp file system
1217 *
1218 * @param pinode the parent inode
1219 * @param name filename
1220 *
1221 * @return XRDP_INODE on success, NULL on failure
1222 *****************************************************************************/
1223
1224 static struct xrdp_inode *
1225 xfuse_create_file_in_xrdp_fs(tui32 device_id, int pinode, const char *name,
1226 int type)
1227 {
1228 XRDP_INODE *xinode;
1229 XRDP_INODE *xinodep;
1230 time_t cur_time;
1231
1232 if ((name == NULL) || (strlen(name) == 0))
1233 return NULL;
1234
1235 /* Do we have an inode table yet? */
1236 if (xfuse_init_xrdp_fs())
1237 {
1238 return NULL;
1239 }
1240
1241 xinode = g_new0(XRDP_INODE, 1);
1242 if (xinode == NULL)
1243 {
1244 log_error("system out of memory");
1245 return NULL;
1246 }
1247
1248 cur_time = time(0);
1249
1250 xinode->parent_inode = pinode;
1251 xinode->inode = g_xrdp_fs.next_node++;
1252 xinode->nlink = 1;
1253 xinode->uid = getuid();
1254 xinode->gid = getgid();
1255 xinode->atime = cur_time;
1256 xinode->mtime = cur_time;
1257 xinode->ctime = cur_time;
1258 xinode->device_id = device_id;
1259 xinode->is_synced = 1;
1260 strcpy(xinode->name, name);
1261
1262 if (type == S_IFDIR)
1263 {
1264 xinode->mode = 0755 | type;
1265 xinode->size = 4096;
1266 }
1267 else
1268 {
1269 xinode->mode = 0644 | type;
1270 xinode->size = 0;
1271 }
1272
1273 g_xrdp_fs.inode_table[xinode->inode] = xinode;
1274 g_xrdp_fs.num_entries++;
1275
1276 /* bump up lookup count in parent dir */
1277 xinodep = g_xrdp_fs.inode_table[pinode];
1278 xinodep->nentries++;
1279 xfuse_update_xrdpfs_size();
1280
1281 log_debug("incremented nentries; parent=%d nentries=%d",
1282 pinode, xinodep->nentries);
1283
1284 return xinode;
1285 }
1286
1287 /**
1288 * Check if specified file exists
1289 *
1290 * @param parent parent inode of file
1291 * @param name filename or dirname
1292 *
1293 * @return 1 if specified file exists, 0 otherwise
1294 *****************************************************************************/
1295
1296 static int xfuse_does_file_exist(fuse_ino_t parent, char *name)
1297 {
1298 fuse_ino_t i;
1299 XRDP_INODE *xinode;
1300
1301 for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
1302 {
1303 if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
1304 continue;
1305
1306 if ((xinode->parent_inode == parent) &&
1307 (strcmp(xinode->name, name) == 0))
1308 {
1309 return 1;
1310 }
1311 }
1312
1313 return 0;
1314 }
1315
1316 static int xfuse_delete_file_with_xinode(XRDP_INODE *xinode)
1317 {
1318 /* make sure it is not a dir */
1319 if ((xinode == NULL) || (xinode->mode & S_IFDIR))
1320 return -1;
1321
1322 log_always("deleting: inode=%d name=%s", xinode->inode, xinode->name);
1323 log_debug("deleting: inode=%d name=%s", xinode->inode, xinode->name);
1324
1325 g_xrdp_fs.inode_table[xinode->parent_inode]->nentries--;
1326 g_xrdp_fs.inode_table[xinode->inode] = NULL;
1327 free(xinode);
1328
1329 return 0;
1330 }
1331
1332 static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode)
1333 {
1334 XRDP_INODE *xip;
1335 fuse_ino_t i;
1336
1337 /* make sure it is not a file */
1338 if ((xinode == NULL) || (xinode->mode & S_IFREG))
1339 return -1;
1340
1341 for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
1342 {
1343 if ((xip = g_xrdp_fs.inode_table[i]) == NULL)
1344 continue;
1345
1346 /* look for child inodes */
1347 if (xip->parent_inode == xinode->inode)
1348 {
1349 /* got one, delete it */
1350 g_xrdp_fs.inode_table[xip->inode] = NULL;
1351 free(xip);
1352 }
1353 }
1354
1355 /* our parent will have one less dir */
1356 g_xrdp_fs.inode_table[xinode->parent_inode]->nentries--;
1357
1358 g_xrdp_fs.inode_table[xinode->inode] = NULL;
1359 free(xinode);
1360
1361 return 0;
1362 }
1363
1364 /**
1365 * Recursively delete dir with specified inode
1366 *****************************************************************************/
1367
1368 static int xfuse_recursive_delete_dir_with_xinode(XRDP_INODE *xinode)
1369 {
1370 XRDP_INODE *xip;
1371 fuse_ino_t i;
1372
1373 /* make sure it is not a file */
1374 if ((xinode == NULL) || (xinode->mode & S_IFREG))
1375 return -1;
1376
1377 log_always("recursively deleting dir with inode=%d name=%s",
1378 xinode->inode, xinode->name);
1379
1380 log_debug("recursively deleting dir with inode=%d name=%s",
1381 xinode->inode, xinode->name);
1382
1383 for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
1384 {
1385 if ((xip = g_xrdp_fs.inode_table[i]) == NULL)
1386 continue;
1387
1388 /* look for child inodes */
1389 if (xip->parent_inode == xinode->inode)
1390 {
1391 /* got one */
1392 if (xip->mode & S_IFREG)
1393 {
1394 /* regular file */
1395 g_xrdp_fs.inode_table[xip->parent_inode]->nentries--;
1396 g_xrdp_fs.inode_table[xip->inode] = NULL;
1397 free(xip);
1398 }
1399 else
1400 {
1401 /* got another dir */
1402 xfuse_recursive_delete_dir_with_xinode(xip);
1403 }
1404 }
1405 }
1406
1407 /* our parent will have one less dir */
1408 g_xrdp_fs.inode_table[xinode->parent_inode]->nentries--;
1409
1410 g_xrdp_fs.inode_table[xinode->inode] = NULL;
1411 free(xinode);
1412
1413 return 0;
1414 }
1415
1416 static void xfuse_update_xrdpfs_size(void)
1417 {
1418 void *vp;
1419 int diff;
1420
1421 diff = g_xrdp_fs.max_entries - g_xrdp_fs.num_entries;
1422 if (diff > 100)
1423 return;
1424
1425 /* extend memory */
1426 vp = realloc(g_xrdp_fs.inode_table,
1427 (g_xrdp_fs.max_entries + 100) * sizeof(struct xrdp_inode *));
1428
1429 if (vp == NULL)
1430 {
1431 log_error("system out of memory");
1432 return;
1433 }
1434
1435 /* zero newly added memory */
1436 memset((char *) vp + g_xrdp_fs.max_entries * sizeof(struct xrdp_inode *),
1437 0,
1438 100 * sizeof(struct xrdp_inode *));
1439
1440 g_xrdp_fs.max_entries += 100;
1441 g_xrdp_fs.inode_table = (struct xrdp_inode **) vp;
1442871 }
1443872
1444873 /******************************************************************************
1447876 ** **
1448877 ******************************************************************************/
1449878
1450 /**
1451 * Add a file or directory to xrdp file system
1452 *****************************************************************************/
1453
1454 int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
1455 {
1456 XFUSE_INFO *fip = (XFUSE_INFO *) vp;
1457 XRDP_INODE *xip = NULL;
1458
1459 if ((fip == NULL) || (xinode == NULL))
1460 {
1461 log_error("fip or xinode are NULL");
1462 return -1;
1463 }
1464
1465 if (!xfuse_is_inode_valid(fip->inode))
1466 {
1467 log_error("inode %ld is not valid", fip->inode);
1468 g_free(xinode);
1469 return -1;
1470 }
1471
1472 log_debug("parent_inode=%ld name=%s", fip->inode, xinode->name);
1473
1474 /* if filename is . or .. don't add it */
1475 if ((strcmp(xinode->name, ".") == 0) || (strcmp(xinode->name, "..") == 0))
1476 {
1477 g_free(xinode);
1478 return -1;
1479 }
1480
1481 xfuse_dump_fs();
1482
1483 if ((xip = xfuse_get_inode_from_pinode_name(fip->inode, xinode->name)) != NULL)
1484 {
1485 log_debug("inode=%ld name=%s already exists in xrdp_fs; not adding it",
1486 fip->inode, xinode->name);
1487 g_free(xinode);
1488 xip->stale = 0;
1489 return -1;
1490 }
1491
1492 xinode->parent_inode = fip->inode;
1493 xinode->inode = g_xrdp_fs.next_node++;
1494 xinode->uid = getuid();
1495 xinode->gid = getgid();
1496 xinode->device_id = fip->device_id;
1497
1498 g_xrdp_fs.num_entries++;
1499
1500 /* insert it in xrdp fs and update lookup count */
1501 g_xrdp_fs.inode_table[xinode->inode] = xinode;
1502 g_xrdp_fs.inode_table[fip->inode]->nentries++;
1503 xfuse_update_xrdpfs_size();
1504
1505 xfuse_dump_fs();
1506 return 0;
1507 }
1508
1509 /**
1510 *****************************************************************************/
1511
1512 void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
1513 {
1514 XFUSE_INFO *fip;
1515 struct dir_info *di;
1516 struct opendir_req *odreq;
1517
1518 log_debug("vp=%p IoStatus=0x%x", vp, IoStatus);
1519
1520 fip = (XFUSE_INFO *) vp;
1521 if (fip == NULL)
1522 {
1523 log_debug("fip is NULL");
1524 goto done;
1525 }
879
880 /**
881 * Add a file or directory to xrdp file system as part of a
882 * directory request
883 *
884 * If the file or directory already exists, no changes are made to it.
885 *****************************************************************************/
886
887 void xfuse_devredir_cb_enum_dir_add_entry(
888 struct state_dirscan *fip,
889 const char *name,
890 const struct file_attr *fattr)
891 {
892 XFS_INODE *xinode = NULL;
893
894 if (!xfs_get(g_xfs, fip->pinum))
895 {
896 log_error("inode %ld is not valid", fip->pinum);
897 }
898 else if ((strcmp(name, ".") == 0) ||
899 (strcmp(name, "..") == 0))
900 {
901 ; /* filename is . or .. - don't add it */
902 }
903 else
904 {
905 log_debug("parent_inode=%ld name=%s", fip->pinum, name);
906
907 /* Does the file already exist ? If it does it's important we
908 * don't mess with it, as we're only enumerating the directory, and
909 * we don't want to disrupt any existing operations on the file
910 */
911 xinode = xfs_lookup_in_dir(g_xfs, fip->pinum, name);
912 if (xinode == NULL)
913 {
914 /* Add a new node to the file system */
915 log_debug("Creating name=%s in parent=%ld in xrdp_fs",
916 name, fip->pinum);
917 xinode = xfs_add_entry(g_xfs, fip->pinum, name, fattr->mode);
918 if (xinode == NULL)
919 {
920 log_error("xfs_add_entry() failed");
921 }
922 else
923 {
924 xinode->size = fattr->size;
925 xinode->atime = fattr->atime;
926 xinode->mtime = fattr->mtime;
927 /* Initially, set the attribute change time to the file data
928 change time */
929 xinode->ctime = fattr->mtime;
930
931 /* device_id is inherited from parent */
932 }
933 }
934 }
935 }
936
937 /**
938 * This routine is called by devredir when the opendir request has
939 * completed
940 *****************************************************************************/
941
942 void xfuse_devredir_cb_enum_dir_done(struct state_dirscan *fip,
943 enum NTSTATUS IoStatus)
944 {
945 log_debug("fip=%p IoStatus=0x%x", fip, IoStatus);
946
947 /*
948 * NT_STATUS_NO_SUCH_FILE is returned for empty directories
949 */
950 if (IoStatus != NT_STATUS_SUCCESS && IoStatus != NT_STATUS_NO_SUCH_FILE)
951 {
952 int status;
953 switch (IoStatus)
954 {
955 case NT_STATUS_ACCESS_DENIED:
956 status = EACCES;
957 break;
958 default:
959 status = ENOENT;
960 }
961 fuse_reply_err(fip->req, status);
962 }
963 else if (!xfs_get(g_xfs, fip->pinum))
964 {
965 log_error("inode %ld is not valid", fip->pinum);
966 fuse_reply_err(fip->req, ENOENT);
967 }
968 else
969 {
970 struct fuse_file_info *fi = &fip->fi;
971
972 if ((fi->fh = (tintptr) xfs_opendir(g_xfs, fip->pinum)) == 0)
973 {
974 fuse_reply_err(fip->req, ENOMEM);
975 }
976 else
977 {
978 fuse_reply_open(fip->req, &fip->fi);
979 }
980 }
981
982 free(fip);
983 }
984
985 /**
986 * This routine is caused as a result of a devredir remote lookup
987 * instigated by xfuse_cb_lookup()
988 *****************************************************************************/
989
990 void xfuse_devredir_cb_lookup_entry(struct state_lookup *fip,
991 enum NTSTATUS IoStatus,
992 const struct file_attr *file_info)
993 {
994 XFS_INODE *xinode = NULL;
995
996 if (IoStatus != NT_STATUS_SUCCESS)
997 {
998 switch (IoStatus)
999 {
1000 case NT_STATUS_SHARING_VIOLATION:
1001 /* This can happen when trying to read the attributes of
1002 * some system files (e.g. pagefile.sys) */
1003 case NT_STATUS_ACCESS_DENIED:
1004 fuse_reply_err(fip->req, EACCES);
1005 break;
1006
1007 case NT_STATUS_UNSUCCESSFUL:
1008 /* Happens if we try to lookup an illegal filename (e.g.
1009 * one with a '*' in it) */
1010 fuse_reply_err(fip->req, ENOENT);
1011 break;
1012
1013 case NT_STATUS_NO_SUCH_FILE:
1014 /* Remove our copy, if any */
1015 if (fip->existing_inum &&
1016 (xinode = xfs_get(g_xfs, fip->existing_inum)) != NULL &&
1017 xinode->generation == fip->existing_generation)
1018 {
1019 xfs_remove_entry(g_xfs, fip->existing_inum);
1020 }
1021 fuse_reply_err(fip->req, ENOENT);
1022 break;
1023
1024 default:
1025 log_info("Error code %08x - fallthrough", (int) IoStatus);
1026 fuse_reply_err(fip->req, EIO);
1027 break;
1028 }
1029 }
1030 else if (!xfs_get(g_xfs, fip->pinum))
1031 {
1032 log_error("parent inode %ld is not valid", fip->pinum);
1033 fuse_reply_err(fip->req, ENOENT);
1034 }
1035 else
1036 {
1037 log_debug("parent_inode=%ld name=%s", fip->pinum, fip->name);
1038
1039 /* Does the file already exist ? */
1040 xinode = xfs_lookup_in_dir(g_xfs, fip->pinum, fip->name);
1041 if (xinode != NULL)
1042 {
1043 /* Is the existing file the same type ? */
1044 if ((xinode->mode & (S_IFREG | S_IFDIR)) ==
1045 (file_info->mode & (S_IFREG | S_IFDIR)))
1046 {
1047 log_debug("inode=%ld name=%s already exists in xrdp_fs as %ld",
1048 fip->pinum, fip->name, xinode->inum);
1049 if (xfs_get_file_open_count(g_xfs, xinode->inum) > 0)
1050 {
1051 /*
1052 * Don't mess with open files. The local attributes are
1053 * almost certainly more up-to-date. A worst case scenario
1054 * would be truncating a file we're currently writing
1055 * to, as the lookup value for the size is stale.
1056 */
1057 log_debug("inode=%ld is open - "
1058 "preferring local attributes", xinode->inum);
1059 }
1060 else
1061 {
1062 log_debug("Updating attributes of inode=%ld", xinode->inum);
1063 update_inode_file_attributes(file_info, TO_SET_ALL, xinode);
1064 }
1065 }
1066 else
1067 {
1068 /* Type has changed from file to directory, or vice-versa */
1069 log_debug("inode=%ld name=%s of different type in xrdp_fs"
1070 " - removing",
1071 fip->pinum, xinode->name);
1072 xfs_remove_entry(g_xfs, xinode->inum);
1073 xinode = NULL;
1074 }
1075 }
1076
1077 if (xinode == NULL)
1078 {
1079 /* Add a new node to the file system */
1080 log_debug("Creating name=%s in parent=%ld in xrdp_fs",
1081 fip->name, fip->pinum);
1082 xinode = xfs_add_entry(g_xfs, fip->pinum, fip->name,
1083 file_info->mode);
1084 if (xinode == NULL)
1085 {
1086 log_debug("xfs_add_entry() failed");
1087 }
1088 else
1089 {
1090 xinode->size = file_info->size;
1091 xinode->atime = file_info->atime;
1092 xinode->mtime = file_info->mtime;
1093 /* Initially, set the attribute change time to the file data
1094 change time */
1095 xinode->ctime = file_info->mtime;
1096 /* device_id is inherited from parent */
1097 }
1098 }
1099 if (xinode != NULL)
1100 {
1101 make_fuse_entry_reply(fip->req, xinode);
1102 }
1103 else
1104 {
1105 fuse_reply_err(fip->req, EIO);
1106 }
1107 }
1108
1109 free(fip);
1110 }
1111
1112 /**
1113 * This routine is caused as a result of a devredir remote setattr
1114 * instigated by xfuse_cb_setattr()
1115 *****************************************************************************/
1116 void xfuse_devredir_cb_setattr(struct state_setattr *fip,
1117 enum NTSTATUS IoStatus)
1118 {
1119 XFS_INODE *xinode;
1120
1121 if (IoStatus != NT_STATUS_SUCCESS)
1122 {
1123 switch (IoStatus)
1124 {
1125 case NT_STATUS_SHARING_VIOLATION:
1126 /* This can happen when trying to read the attributes of
1127 * some system files (e.g. pagefile.sys) */
1128 case NT_STATUS_ACCESS_DENIED:
1129 fuse_reply_err(fip->req, EACCES);
1130 break;
1131
1132 case NT_STATUS_UNSUCCESSFUL:
1133 /* Happens if we try to lookup an illegal filename */
1134 case NT_STATUS_NO_SUCH_FILE:
1135 fuse_reply_err(fip->req, ENOENT);
1136 break;
1137
1138 default:
1139 log_info("Error code %08x - fallthrough", (int) IoStatus);
1140 fuse_reply_err(fip->req, EIO);
1141 break;
1142 }
1143 }
1144 else if ((xinode = xfs_get(g_xfs, fip->inum)) == NULL)
1145 {
1146 fuse_reply_err(fip->req, ENOENT);
1147 }
1148 else
1149 {
1150 update_inode_file_attributes(&fip->fattr, fip->change_mask, xinode);
1151 make_fuse_attr_reply(fip->req, xinode);
1152 }
1153 free(fip);
1154 }
1155
1156 /**
1157 * This routine is caused as a result of a file or directory
1158 * create request */
1159 void xfuse_devredir_cb_create_file(struct state_create *fip,
1160 enum NTSTATUS IoStatus,
1161 tui32 DeviceId, tui32 FileId)
1162 {
1163 XFUSE_HANDLE *fh = NULL;
15261164
15271165 if (IoStatus != 0)
15281166 {
1529 /* command failed */
1530 if (fip->invoke_fuse)
1531 fuse_reply_err(fip->req, ENOENT);
1532 goto done;
1533 }
1534
1535 /* do we have a valid inode? */
1536 if (!xfuse_is_inode_valid(fip->inode))
1537 {
1538 log_error("inode %ld is not valid", fip->inode);
1539 if (fip->invoke_fuse)
1540 fuse_reply_err(fip->req, EBADF);
1541 goto done;
1542 }
1543
1544 xfuse_delete_stale_entries(fip->inode);
1545
1546 /* this will be used by xfuse_cb_readdir() */
1547 di = g_new0(struct dir_info, 1);
1548 di->index = FIRST_INODE;
1549 fip->fi->fh = (tintptr) di;
1550
1551 fuse_reply_open(fip->req, fip->fi);
1552
1553 done:
1554
1555 if (fip)
1556 free(fip);
1557
1558 /* remove current request */
1559 g_free(fifo_remove(&g_fifo_opendir));
1560
1561 while (1)
1562 {
1563 /* process next request */
1564 odreq = (struct opendir_req *) fifo_peek(&g_fifo_opendir);
1565 if (!odreq)
1566 return;
1567
1568 if (xfuse_proc_opendir_req(odreq->req, odreq->ino, odreq->fi))
1569 g_free(fifo_remove(&g_fifo_opendir)); /* req failed */
1570 else
1571 break; /* req has been queued */
1572 }
1573 }
1574
1575 void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
1576 tui32 FileId)
1577 {
1578 XFUSE_HANDLE *fh;
1579 XRDP_INODE *xinode;
1580
1581 XFUSE_INFO *fip = (XFUSE_INFO *) vp;
1582 if (fip == NULL)
1583 {
1584 log_debug("fip is NULL");
1585 goto done;
1586 }
1587
1588 log_debug("+++ XFUSE_INFO=%p XFUSE_INFO->fi=%p DeviceId=%d FileId=%d",
1589 fip, fip->fi, DeviceId, FileId);
1590
1591 if (IoStatus != 0)
1592 {
1593 if (!fip->invoke_fuse)
1594 goto done;
1595
15961167 switch (IoStatus)
15971168 {
1598 case 0xC0000022:
1169 case NT_STATUS_ACCESS_DENIED:
15991170 fuse_reply_err(fip->req, EACCES);
16001171 break;
16011172
1602 case 0xC0000033:
1603 case 0xC0000034:
1173 case NT_STATUS_OBJECT_NAME_INVALID:
1174 case NT_STATUS_OBJECT_NAME_NOT_FOUND:
16041175 fuse_reply_err(fip->req, ENOENT);
16051176 break;
16061177
16081179 fuse_reply_err(fip->req, EIO);
16091180 break;
16101181 }
1611
1612 goto done;
1613 }
1614
1615 if (fip->fi != NULL)
1616 {
1617 fh = g_new0(XFUSE_HANDLE, 1);
1618 if (fh == NULL)
1619 {
1182 }
1183 else
1184 {
1185 if ((fip->mode & S_IFREG) != 0)
1186 {
1187 /* We've created a regular file */
1188 /* Allocate an XFUSE_HANDLE for future file operations */
1189 if ((fh = g_new0(XFUSE_HANDLE, 1)) != NULL)
1190 {
1191 /* save file handle for later use */
1192 fh->DeviceId = DeviceId;
1193 fh->FileId = FileId;
1194
1195 fip->fi.fh = (tintptr) fh;
1196 }
1197 }
1198
1199 if ((fip->mode & S_IFREG) != 0 && fh == NULL)
1200 {
1201 /* We failed to allocate a file handle */
16201202 log_error("system out of memory");
1621 if (fip->invoke_fuse)
1622 fuse_reply_err(fip->req, ENOMEM);
1623
1624 free(fip);
1625 return;
1626 }
1627
1628 /* save file handle for later use */
1629 fh->DeviceId = DeviceId;
1630 fh->FileId = FileId;
1631
1632 fip->fi->fh = (tintptr) fh;
1633 log_debug("+++ XFUSE_INFO=%p XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
1634 fip, fip->fi, (long long) fip->fi->fh);
1635 }
1636
1637 if (fip->invoke_fuse)
1638 {
1639 if (fip->reply_type == RT_FUSE_REPLY_OPEN)
1640 {
1641 log_debug("sending fuse_reply_open(); "
1642 "DeviceId=%d FileId=%d req=%p fi=%p",
1643 fh->DeviceId, fh->FileId, fip->req, fip->fi);
1644
1645 /* update open count */
1646 if ((xinode = g_xrdp_fs.inode_table[fip->inode]) != NULL)
1647 xinode->nopen++;
1648
1649 fuse_reply_open(fip->req, fip->fi);
1650 }
1651 else if (fip->reply_type == RT_FUSE_REPLY_CREATE)
1652 {
1653 struct fuse_entry_param e;
1654
1655 // LK_TODO
1656 #if 0
1657 if ((xinode = g_xrdp_fs.inode_table[fip->inode]) == NULL)
1658 {
1659 log_error("inode at inode_table[%ld] is NULL", fip->inode);
1660 fuse_reply_err(fip->req, EBADF);
1661 goto done;
1662 }
1663 #else
1203 fuse_reply_err(fip->req, ENOMEM);
1204 }
1205 else
1206 {
1207 XFS_INODE *xinode;
16641208 /* create entry in xrdp file system */
1665 xinode = xfuse_create_file_in_xrdp_fs(fip->device_id, fip->inode,
1666 fip->name, fip->mode);
1209 xinode = xfs_add_entry(g_xfs, fip->pinum, fip->name, fip->mode);
16671210 if (xinode == NULL)
16681211 {
1212 /* It's possible xfs_add_entry() has failed, as the
1213 * file has already been added (by a lookup request)
1214 * in the time between our request and the response
1215 * This can happen if an 'ls' is happening in the same
1216 * directory as this file is being created.
1217 *
1218 * We'll check for this before we fail the create */
1219 if ((xinode = xfs_lookup_in_dir(g_xfs,
1220 fip->pinum,
1221 fip->name)) != NULL)
1222 {
1223 /*
1224 * The mode should be correct anyway, but we'll
1225 * set it to the mode requested at creation
1226 */
1227 xinode->mode = fip->mode;
1228 }
1229 }
1230
1231 if (xinode == NULL)
1232 {
1233 log_error("Out of memory!");
16691234 fuse_reply_err(fip->req, ENOMEM);
1670 return;
1671 }
1672 #endif
1673 memset(&e, 0, sizeof(struct fuse_entry_param));
1674
1675 e.ino = xinode->inode;
1676 e.attr_timeout = XFUSE_ATTR_TIMEOUT;
1677 e.entry_timeout = XFUSE_ENTRY_TIMEOUT;
1678 e.attr.st_ino = xinode->inode;
1679 e.attr.st_mode = xinode->mode;
1680 e.attr.st_nlink = xinode->nlink;
1681 e.attr.st_uid = xinode->uid;
1682 e.attr.st_gid = xinode->gid;
1683 e.attr.st_size = xinode->size;
1684 e.attr.st_atime = xinode->atime;
1685 e.attr.st_mtime = xinode->mtime;
1686 e.attr.st_ctime = xinode->ctime;
1687 e.generation = 1;
1688
1689 if (fip->mode == S_IFDIR)
1690 {
1691 fuse_reply_entry(fip->req, &e);
16921235 }
16931236 else
16941237 {
1695 xinode->nopen++;
1696 fuse_reply_create(fip->req, &e, fip->fi);
1238
1239 if ((fip->mode & S_IFDIR) != 0)
1240 {
1241 make_fuse_entry_reply(fip->req, xinode);
1242 }
1243 else
1244 {
1245 struct fuse_entry_param e;
1246 xfs_inode_to_fuse_entry_param(xinode, &e);
1247 fuse_reply_create(fip->req, &e, &fip->fi);
1248 xfs_increment_file_open_count(g_xfs, xinode->inum);
1249 }
16971250 }
16981251 }
1252 }
1253
1254 free(fip);
1255 }
1256
1257
1258 /**
1259 * This routine is caused as a result of a file open request */
1260 void xfuse_devredir_cb_open_file(struct state_open *fip,
1261 enum NTSTATUS IoStatus,
1262 tui32 DeviceId, tui32 FileId)
1263 {
1264 XFUSE_HANDLE *fh;
1265
1266 if (IoStatus != 0)
1267 {
1268 switch (IoStatus)
1269 {
1270 case NT_STATUS_ACCESS_DENIED:
1271 fuse_reply_err(fip->req, EACCES);
1272 break;
1273
1274 case NT_STATUS_OBJECT_NAME_INVALID:
1275 case NT_STATUS_OBJECT_NAME_NOT_FOUND:
1276 fuse_reply_err(fip->req, ENOENT);
1277 break;
1278
1279 default:
1280 fuse_reply_err(fip->req, EIO);
1281 break;
1282 }
1283 }
1284 else
1285 {
1286 /* Allocate an XFUSE_HANDLE for future file operations */
1287 if ((fh = g_new0(XFUSE_HANDLE, 1)) == NULL)
1288 {
1289 log_error("system out of memory");
1290 fuse_reply_err(fip->req, ENOMEM);
1291 }
16991292 else
17001293 {
1701 log_error("invalid reply type: %d", fip->reply_type);
1702 }
1703 }
1704
1705 done:
1294 /* save file handle for later use */
1295 fh->DeviceId = DeviceId;
1296 fh->FileId = FileId;
1297
1298 fip->fi.fh = (tintptr) fh;
1299
1300 log_debug("sending fuse_reply_open(); "
1301 "DeviceId=%d FileId=%d req=%p",
1302 fh->DeviceId, fh->FileId, fip->req);
1303
1304 /* update open count */
1305 xfs_increment_file_open_count(g_xfs, fip->inum);
1306
1307 fuse_reply_open(fip->req, &fip->fi);
1308 }
1309 }
17061310
17071311 free(fip);
17081312 }
17091313
1710 void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length)
1711 {
1712 XFUSE_INFO *fip;
1713
1714 fip = (XFUSE_INFO *) vp;
1715 if ((fip == NULL) || (fip->req == NULL))
1716 {
1717 log_error("fip for fip->req is NULL");
1718 return;
1719 }
1720
1314 void xfuse_devredir_cb_read_file(struct state_read *fip,
1315 const char *buf, size_t length)
1316 {
17211317 fuse_reply_buf(fip->req, buf, length);
17221318 free(fip);
17231319 }
17241320
1725 void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length)
1726 {
1727 XRDP_INODE *xinode;
1728 XFUSE_INFO *fip;
1729
1730 fip = (XFUSE_INFO *) vp;
1731 if ((fip == NULL) || (fip->req == NULL) || (fip->fi == NULL))
1732 {
1733 log_error("fip, fip->req or fip->fi is NULL");
1734 return;
1735 }
1736
1737 log_debug("+++ XFUSE_INFO=%p, XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
1738 fip, fip->fi, (long long) fip->fi->fh);
1739
1740 fuse_reply_write(fip->req, length);
1741
1742 /* update file size */
1743 if ((xinode = g_xrdp_fs.inode_table[fip->inode]) != NULL)
1744 xinode->size += length;
1321 void xfuse_devredir_cb_write_file(
1322 struct state_write *fip,
1323 enum NTSTATUS IoStatus,
1324 off_t offset,
1325 size_t length)
1326 {
1327 XFS_INODE *xinode;
1328
1329 if (IoStatus != NT_STATUS_SUCCESS)
1330 {
1331 log_error("Write NTSTATUS is %d", (int) IoStatus);
1332 fuse_reply_err(fip->req, EIO);
1333 }
17451334 else
1746 log_error("inode at inode_table[%ld] is NULL", fip->inode);
1335 {
1336 off_t new_size = offset + length;
1337 fuse_reply_write(fip->req, length);
1338
1339 /* update file size */
1340 if ((xinode = xfs_get(g_xfs, fip->inum)) != NULL)
1341 {
1342 if (new_size > xinode->size)
1343 {
1344 xinode->size = new_size;
1345 }
1346 }
1347 else
1348 {
1349 log_error("inode %ld is invalid", fip->inum);
1350 }
1351 }
17471352
17481353 free(fip);
17491354 }
17501355
1751 void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus)
1752 {
1753 XFUSE_INFO *fip;
1754 XRDP_INODE *xinode;
1755
1756 fip = (XFUSE_INFO *) vp;
1757 if (fip == NULL)
1758 return;
1759
1760 if (IoStatus != 0)
1761 {
1762 fuse_reply_err(fip->req, EBADF);
1763 free(fip);
1764 return;
1765 }
1766
1767 /* now delete the item in xrdp fs */
1768 xinode = xfuse_get_inode_from_pinode_name(fip->inode, fip->name);
1769 if (xinode == NULL)
1770 {
1771 fuse_reply_err(fip->req, EBADF);
1772 free(fip);
1773 return;
1774 }
1775
1776 g_xrdp_fs.inode_table[xinode->inode] = NULL;
1777 free(xinode);
1778
1779 /* update parent */
1780 xinode = g_xrdp_fs.inode_table[fip->inode];
1781 xinode->nentries--;
1782
1356 void xfuse_devredir_cb_rmdir_or_file(struct state_remove *fip,
1357 enum NTSTATUS IoStatus)
1358 {
1359 XFS_INODE *xinode = xfs_get(g_xfs, fip->inum);
1360
1361 switch (IoStatus)
1362 {
1363 case NT_STATUS_SUCCESS:
1364 case NT_STATUS_NO_SUCH_FILE:
1365 xfs_remove_entry(g_xfs, xinode->inum); /* Remove local copy */
1366 fuse_reply_err(fip->req, 0);
1367 break;
1368
1369 case NT_STATUS_SHARING_VIOLATION:
1370 case NT_STATUS_ACCESS_DENIED:
1371 fuse_reply_err(fip->req, EACCES);
1372 break;
1373
1374 default:
1375 log_info("Error code %08x - fallthrough", (int) IoStatus);
1376 fuse_reply_err(fip->req, EBADF);
1377 break;
1378 }
1379 free(fip);
1380 }
1381
1382 void xfuse_devredir_cb_rename_file(struct state_rename *fip,
1383 enum NTSTATUS IoStatus)
1384 {
1385 int status;
1386
1387 if (IoStatus != NT_STATUS_SUCCESS)
1388 {
1389 status =
1390 (IoStatus == NT_STATUS_SHARING_VIOLATION) ? EBUSY :
1391 (IoStatus == NT_STATUS_ACCESS_DENIED) ? EACCES :
1392 /* default */ EEXIST ;
1393 }
1394 else
1395 {
1396 status = xfs_move_entry(g_xfs, fip->pinum,
1397 fip->new_pinum, fip->name);
1398 }
1399
1400 fuse_reply_err(fip->req, status);
1401 free(fip);
1402 }
1403
1404 void xfuse_devredir_cb_file_close(struct state_close *fip)
1405 {
17831406 fuse_reply_err(fip->req, 0);
1407 xfs_decrement_file_open_count(g_xfs, fip->inum);
1408
17841409 free(fip);
1785 }
1786
1787 void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus)
1788 {
1789 XFUSE_INFO *fip;
1790 XRDP_INODE *old_xinode;
1791 XRDP_INODE *new_xinode;
1792
1793 fip = (XFUSE_INFO *) vp;
1794 if (fip == NULL)
1795 return;
1796
1797 if (IoStatus != 0)
1798 {
1799 fuse_reply_err(fip->req, EEXIST);
1800 free(fip);
1801 return;
1802 }
1803
1804 /*
1805 * update xrdp file system
1806 */
1807
1808 /* if destination dir/file exists, delete it */
1809 if (xfuse_does_file_exist(fip->new_inode, fip->new_name))
1810 {
1811 new_xinode = xfuse_get_inode_from_pinode_name(fip->new_inode,
1812 fip->new_name);
1813
1814 if (new_xinode)
1815 {
1816 if (new_xinode->mode & S_IFREG)
1817 xfuse_delete_file_with_xinode(new_xinode);
1818 else
1819 xfuse_delete_dir_with_xinode(new_xinode);
1820
1821 new_xinode = NULL;
1822 }
1823 }
1824
1825 old_xinode = xfuse_get_inode_from_pinode_name(fip->inode, fip->name);
1826 if (old_xinode == NULL)
1827 {
1828 fuse_reply_err(fip->req, EBADF);
1829 free(fip);
1830 return;
1831 }
1832
1833 old_xinode->parent_inode = fip->new_inode;
1834 strncpy(old_xinode->name, fip->new_name, 1023);
1835 old_xinode->name[1023] = 0;
1836
1837 if (fip->inode != fip->new_inode)
1838 {
1839 /* file has been moved to a different dir */
1840 old_xinode->is_synced = 1;
1841 g_xrdp_fs.inode_table[fip->inode]->nentries--;
1842 g_xrdp_fs.inode_table[fip->new_inode]->nentries++;
1843 }
1844
1845 fuse_reply_err(fip->req, 0);
1846 free(fip);
1847 }
1848
1849 void xfuse_devredir_cb_file_close(void *vp)
1850 {
1851 XFUSE_INFO *fip;
1852 XRDP_INODE *xinode;
1853
1854 fip = (XFUSE_INFO *) vp;
1855 if (fip == NULL)
1856 {
1857 log_error("fip is NULL");
1858 return;
1859 }
1860
1861 if (fip->fi == NULL)
1862 {
1863 log_error("fip->fi is NULL");
1864 return;
1865 }
1866
1867 log_debug("+++ XFUSE_INFO=%p XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
1868 fip, fip->fi, (long long) fip->fi->fh);
1869
1870 if ((xinode = g_xrdp_fs.inode_table[fip->inode]) == NULL)
1871 {
1872 log_debug("inode_table[%ld] is NULL", fip->inode);
1873 fuse_reply_err(fip->req, EBADF);
1874 return;
1875 }
1876
1877 log_debug("before: inode=%d nopen=%d", xinode->inode, xinode->nopen);
1878
1879 if (xinode->nopen > 0)
1880 xinode->nopen--;
1881
1882 /* LK_TODO */
1883 #if 0
1884 if ((xinode->nopen == 0) && fip->fi && fip->fi->fh)
1885 {
1886 printf("LK_TODO: ################################ fi=%p fi->fh=0x%llx\n",
1887 fip->fi, (long long) fip->fi->fh);
1888
1889 free((char *) (tintptr) (fip->fi->fh));
1890 fip->fi->fh = 0;
1891 }
1892 #endif
1893
1894 fuse_reply_err(fip->req, 0);
18951410 }
18961411
18971412 /******************************************************************************
19021417
19031418 /**
19041419 * Look up a directory entry by name and get its attributes
1905 *
19061420 *****************************************************************************/
19071421
19081422 static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
19091423 {
1910 XRDP_INODE *xinode;
1911 struct fuse_entry_param e;
1424 XFS_INODE *parent_xinode;
1425 XFS_INODE *xinode = NULL;
19121426
19131427 log_debug("looking for parent=%ld name=%s", parent, name);
1914 xfuse_dump_fs();
1915
1916 if (!xfuse_is_inode_valid(parent))
1428
1429 if (strlen(name) > XFS_MAXFILENAMELEN)
1430 {
1431 fuse_reply_err(req, ENAMETOOLONG);
1432 }
1433 else if ((parent_xinode = xfs_get(g_xfs, parent)) == NULL)
19171434 {
19181435 log_error("inode %ld is not valid", parent);
1919 fuse_reply_err(req, EBADF);
1920 return;
1921 }
1922
1923 xinode = xfuse_get_inode_from_pinode_name(parent, name);
1924 if (xinode == NULL)
1925 {
1926 log_debug("did not find entry for parent=%ld name=%s", parent, name);
19271436 fuse_reply_err(req, ENOENT);
1928 return;
1929 }
1930
1931 memset(&e, 0, sizeof(e));
1932 e.ino = xinode->inode;
1933 e.attr_timeout = XFUSE_ATTR_TIMEOUT;
1934 e.entry_timeout = XFUSE_ENTRY_TIMEOUT;
1935 e.attr.st_ino = xinode->inode;
1936 e.attr.st_mode = xinode->mode;
1937 e.attr.st_nlink = xinode->nlink;
1938 e.attr.st_uid = xinode->uid;
1939 e.attr.st_gid = xinode->gid;
1940 e.attr.st_size = xinode->size;
1941 e.attr.st_atime = xinode->atime;
1942 e.attr.st_mtime = xinode->mtime;
1943 e.attr.st_ctime = xinode->ctime;
1944 e.generation = 1;
1945
1946 fuse_reply_entry(req, &e);
1947 log_debug("found entry for parent=%ld name=%s uid=%d gid=%d",
1948 parent, name, xinode->uid, xinode->gid);
1949 return;
1437 }
1438 else
1439 {
1440 if (parent_xinode->device_id == 0)
1441 {
1442 /* File cannot be remote - we either know about it or we don't */
1443 if ((xinode = xfs_lookup_in_dir(g_xfs, parent, name)) != NULL)
1444 {
1445 log_debug("found entry for parent=%ld name=%s",
1446 parent, name);
1447 make_fuse_entry_reply(req, xinode);
1448 }
1449 else
1450 {
1451 fuse_reply_err(req, ENOENT);
1452 }
1453 }
1454 else
1455 {
1456 /* specified file resides on redirected share
1457 *
1458 * We always look these up, and relying on libfuse to do sane
1459 * caching */
1460 struct state_lookup *fip = g_new0(struct state_lookup, 1);
1461 char *full_path = get_name_for_entry_in_parent(parent, name);
1462
1463 if (fip == NULL || full_path == NULL)
1464 {
1465 log_error("system out of memory");
1466 fuse_reply_err(req, ENOMEM);
1467 free(fip);
1468 free(full_path);
1469 }
1470 else
1471 {
1472 const char *cptr;
1473
1474 fip->req = req;
1475 fip->pinum = parent;
1476 strcpy(fip->name, name);
1477
1478 /* we want path minus 'root node of the share' */
1479 cptr = filename_on_device(full_path);
1480
1481 /* If the file already exists on our side, save the inum
1482 * and generation. If it's not remote any more this means we
1483 * can remove it when we get the response
1484 */
1485 if ((xinode = xfs_lookup_in_dir(g_xfs, parent, name)) != NULL)
1486 {
1487 fip->existing_inum = xinode->inum;
1488 fip->existing_generation = xinode->generation;
1489 }
1490 log_debug("Looking up %s in %s on %d", name, cptr,
1491 parent_xinode->device_id);
1492 /*
1493 * If this call succeeds, further request processing happens in
1494 * xfuse_devredir_cb_lookup_entry()
1495 */
1496 if (devredir_lookup_entry(fip, parent_xinode->device_id, cptr))
1497 {
1498 log_error("failed to send devredir_lookup_entry() cmd");
1499 fuse_reply_err(req, EREMOTEIO);
1500 free(fip);
1501 }
1502 free(full_path);
1503 }
1504 }
1505 }
19501506 }
19511507
19521508 /**
19531509 * Get file attributes
1510 * GOTCHA : For FUSE 2.9 at least, the 'fi' parameter is allocated on the
1511 * stack by the caller, so must be copied if we're not using it
1512 * to reply to FUSE immediately
19541513 *****************************************************************************/
19551514
19561515 static void xfuse_cb_getattr(fuse_req_t req, fuse_ino_t ino,
19571516 struct fuse_file_info *fi)
19581517 {
1959 struct xrdp_inode *xino;
1960 struct stat stbuf;
1961
1962 (void) fi;
1518 XFS_INODE *xino;
19631519
19641520 log_debug("req=%p ino=%ld", req, ino);
19651521
19661522 /* if ino is not valid, just return */
1967 if (!xfuse_is_inode_valid(ino))
1523 if ((xino = xfs_get(g_xfs, ino)) == NULL)
19681524 {
19691525 log_error("inode %ld is not valid", ino);
1970 fuse_reply_err(req, EBADF);
1971 return;
1972 }
1973
1974 xino = g_xrdp_fs.inode_table[ino];
1975 if (!xino)
1976 {
1977 log_debug("****** invalid ino=%ld", ino);
1978 fuse_reply_err(req, EBADF);
1979 return;
1980 }
1526 fuse_reply_err(req, ENOENT);
1527 }
1528 else
1529 {
1530 make_fuse_attr_reply(req, xino);
1531 }
1532 }
1533
1534 /**
1535 *
1536 *****************************************************************************/
1537
1538 /*
1539 * Adds an entry to the buffer, using fuse_add_direnty()
1540 *
1541 * Returns 1 for success, or zero if the entry couldn't be added
1542 */
1543 static int xfuse_dirbuf_add1(fuse_req_t req, struct dirbuf1 *b,
1544 XFS_INODE *xinode, off_t offset)
1545 {
1546 struct stat stbuf;
1547 size_t len;
1548 int result = 0;
19811549
19821550 memset(&stbuf, 0, sizeof(stbuf));
1983 stbuf.st_ino = ino;
1984 stbuf.st_mode = xino->mode;
1985 stbuf.st_nlink = xino->nlink;
1986 stbuf.st_size = xino->size;
1987 fuse_reply_attr(req, &stbuf, 1.0);
1988 }
1989
1990 /**
1991 *
1992 *****************************************************************************/
1993
1994 #if 0
1995 static void xfuse_dirbuf_add(fuse_req_t req, struct dirbuf *b,
1996 const char *name, fuse_ino_t ino)
1997 {
1998 struct stat stbuf;
1999 size_t oldsize = b->size;
2000
2001 log_debug("adding ino=%ld name=%s", ino, name);
2002
2003 b->size += fuse_add_direntry(req, NULL, 0, name, NULL, 0);
2004 b->p = (char *) realloc(b->p, b->size);
2005
2006 memset(&stbuf, 0, sizeof(stbuf));
2007 stbuf.st_ino = ino;
2008 fuse_add_direntry(req, b->p + oldsize, b->size - oldsize, name, &stbuf,
2009 b->size);
2010 }
2011 #endif
2012
2013 static int xfuse_dirbuf_add1(fuse_req_t req, struct dirbuf1 *b,
2014 const char *name, fuse_ino_t ino)
2015 {
2016 struct stat stbuf;
2017 int len;
2018
2019 len = fuse_add_direntry(req, NULL, 0, name, NULL, 0);
2020 if (b->bytes_in_buf + len > 4096)
2021 {
2022 log_debug("not adding entry because dirbuf overflow would occur");
2023 return -1;
2024 }
2025
2026 memset(&stbuf, 0, sizeof(stbuf));
2027 stbuf.st_ino = ino;
2028
2029 fuse_add_direntry(req,
2030 &b->buf[b->bytes_in_buf], /* index where new entry will be added to buf */
2031 4096 - len, /* remaining size of buf */
2032 name, /* name of entry */
1551 stbuf.st_ino = xinode->inum;
1552 stbuf.st_mode = xinode->mode & ~g_umask;
1553
1554 /*
1555 * Try to add the entry. From the docs for fuse_add_direntry():-
1556 * "Buffer needs to be large enough to hold the entry. If it's not,
1557 * then the entry is not filled in but the size of the entry is
1558 * still returned."
1559 */
1560 len = fuse_add_direntry(req,
1561 &b->buf[b->len], /* index where new entry will be added to buf */
1562 sizeof(b->buf) - b->len, /* Space left */
1563 xinode->name, /* name of entry */
20331564 &stbuf, /* file attributes */
2034 b->bytes_in_buf + len /* offset of next entry */
1565 offset /* offset of next entry */
20351566 );
2036
2037 b->bytes_in_buf += len;
2038 return 0;
2039 }
2040
2041 /**
2042 *
1567 if (len + b->len <= sizeof(b->buf))
1568 {
1569 /* Entry fitted in OK */
1570 b->len += len;
1571 result = 1;
1572 }
1573
1574 return result;
1575 }
1576
1577 /**
1578 * GOTCHA : For FUSE 2.9 at least, the 'fi' parameter is allocated on the
1579 * stack by the caller, so must be copied if we're not using it
1580 * to reply to FUSE immediately
20431581 *****************************************************************************/
20441582
20451583 static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
20461584 off_t off, struct fuse_file_info *fi)
20471585 {
2048 XRDP_INODE *xinode;
2049 XRDP_INODE *ti;
2050 struct dir_info *di;
1586 XFS_INODE *xinode;
1587 struct xfs_dir_handle *dh;
20511588 struct dirbuf1 b;
2052 fuse_ino_t i;
2053 int first_time;
20541589
20551590 log_debug("req=%p inode=%ld size=%zd offset=%lld", req, ino, size, (long long) off);
20561591
2057 /* do we have a valid inode? */
2058 if (!xfuse_is_inode_valid(ino))
1592 /* On the first call, check the inode is valid */
1593 if (off == 0 && !xfs_get(g_xfs, ino))
20591594 {
20601595 log_error("inode %ld is not valid", ino);
2061 fuse_reply_err(req, EBADF);
2062 return;
2063 }
2064
2065 di = (struct dir_info *) (tintptr) (fi->fh);
2066 if (di == NULL)
1596 fuse_reply_err(req, ENOENT);
1597 }
1598 else if ((dh = (struct xfs_dir_handle *) fi->fh) == NULL)
20671599 {
20681600 /* something seriously wrong somewhere! */
20691601 fuse_reply_buf(req, 0, 0);
2070 return;
2071 }
2072
2073 b.bytes_in_buf = 0;
2074 first_time = (di->index == FIRST_INODE) ? 1 : 0;
2075
2076 for (i = di->index; i < g_xrdp_fs.num_entries; i++, di->index++)
2077 {
2078 if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
2079 continue;
2080
2081 /* match parent inode */
2082 if (xinode->parent_inode != ino)
2083 continue;
2084
2085 xinode->is_synced = 1;
2086
2087 if (first_time)
2088 {
2089 first_time = 0;
2090 ti = g_xrdp_fs.inode_table[ino];
2091 if (!ti)
1602 }
1603 else
1604 {
1605 b.len = 0;
1606
1607 off_t new_off = off;
1608 while ((xinode = xfs_readdir(g_xfs, dh, &new_off)) != NULL)
1609 {
1610 if (xfuse_dirbuf_add1(req, &b, xinode, new_off) == 0)
20921611 {
2093 log_debug("****** g_xrdp_fs.inode_table[%ld] is NULL", ino);
2094 fuse_reply_buf(req, NULL, 0);
2095 return;
1612 break; /* buffer is full */
20961613 }
2097 xfuse_dirbuf_add1(req, &b, ".", ino);
2098 xfuse_dirbuf_add1(req, &b, "..", ti->parent_inode);
2099 }
2100
2101 if (xfuse_dirbuf_add1(req, &b, xinode->name, xinode->inode))
2102 break; /* buffer is full */
2103 }
2104
2105 if (b.bytes_in_buf)
2106 fuse_reply_buf(req, b.buf, b.bytes_in_buf);
2107 else
2108 fuse_reply_buf(req, NULL, 0);
2109 }
1614 /* Make sure we get the next entry next time */
1615 off = new_off;
1616 }
1617
1618 fuse_reply_buf(req, b.buf, b.len);
1619 }
1620 }
1621
21101622
21111623 /**
21121624 * Create a directory
21151627 static void xfuse_cb_mkdir(fuse_req_t req, fuse_ino_t parent,
21161628 const char *name, mode_t mode)
21171629 {
2118 XRDP_INODE *xinode;
2119 struct fuse_entry_param e;
1630 XFS_INODE *xinode;
21201631
21211632 log_debug("entered: parent_inode=%ld name=%s", parent, name);
21221633
2123 if ((xinode = xfuse_get_inode_from_pinode_name(parent, name)) != NULL)
1634 if ((xinode = xfs_lookup_in_dir(g_xfs, parent, name)) != NULL)
21241635 {
21251636 /* dir already exists, just return it */
2126 memset(&e, 0, sizeof(struct fuse_entry_param));
2127
2128 e.ino = xinode->inode;
2129 e.attr_timeout = XFUSE_ATTR_TIMEOUT;
2130 e.entry_timeout = XFUSE_ENTRY_TIMEOUT;
2131 e.attr.st_ino = xinode->inode;
2132 e.attr.st_mode = xinode->mode;
2133 e.attr.st_nlink = xinode->nlink;
2134 e.attr.st_uid = xinode->uid;
2135 e.attr.st_gid = xinode->gid;
2136 e.attr.st_size = xinode->size;
2137 e.attr.st_atime = xinode->atime;
2138 e.attr.st_mtime = xinode->mtime;
2139 e.attr.st_ctime = xinode->ctime;
2140 e.generation = 1;
2141
2142 fuse_reply_entry(req, &e);
2143 return;
2144 }
2145
2146 /* dir does not exist, create it */
2147 xfuse_create_dir_or_file(req, parent, name, mode, NULL, S_IFDIR);
2148 }
2149
2150 /**
2151 * Remove specified dir
2152 *****************************************************************************/
2153
2154 static void xfuse_cb_rmdir(fuse_req_t req, fuse_ino_t parent,
2155 const char *name)
2156 {
2157 xfuse_remove_dir_or_file(req, parent, name, 1);
2158 }
1637 make_fuse_entry_reply(req, xinode);
1638 }
1639 else
1640 {
1641 /* dir does not exist, create it */
1642 xfuse_create_dir_or_file(req, parent, name, mode | S_IFDIR, NULL);
1643 }
1644 }
1645
1646 /**
1647 * Remove a dir or file
1648 *
1649 *****************************************************************************/
21591650
21601651 static void xfuse_cb_unlink(fuse_req_t req, fuse_ino_t parent,
21611652 const char *name)
21621653 {
2163 xfuse_remove_dir_or_file(req, parent, name, 2);
2164 }
2165
2166 /**
2167 * Remove a dir or file
2168 *
2169 * @param type 1=dir, 2=file
2170 *****************************************************************************/
2171
2172 static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent,
2173 const char *name, int type)
2174 {
2175 XFUSE_INFO *fip;
2176 XRDP_INODE *xinode;
2177 char *cptr;
2178 char full_path[4096];
2179 tui32 device_id;
1654 XFS_INODE *xinode;
21801655
21811656 log_debug("entered: parent=%ld name=%s", parent, name);
21821657
2183 /* is parent inode valid? */
2184 if (!xfuse_is_inode_valid(parent))
2185 {
2186 log_error("inode %ld is not valid", parent);
2187 fuse_reply_err(req, EBADF);
2188 return;
2189 }
2190
2191 if ((xinode = xfuse_get_inode_from_pinode_name(parent, name)) == NULL)
1658 if (strlen(name) > XFS_MAXFILENAMELEN)
1659 {
1660 fuse_reply_err(req, ENAMETOOLONG);
1661 }
1662 else if ((xinode = xfs_lookup_in_dir(g_xfs, parent, name)) == NULL)
21921663 {
21931664 log_error("did not find file with pinode=%ld name=%s", parent, name);
2194 fuse_reply_err(req, EBADF);
2195 return;
2196 }
2197
2198 device_id = xfuse_get_device_id_for_inode(parent, full_path);
2199
2200 log_debug("path=%s nentries=%d", full_path, xinode->nentries);
2201
2202 if ((type == 1) && (xinode->nentries != 0))
2203 {
2204 log_debug("cannot rmdir; lookup count is %d", xinode->nentries);
1665 fuse_reply_err(req, ENOENT);
1666 }
1667
1668 else if ((xinode->mode & S_IFDIR) != 0 &&
1669 !xfs_is_dir_empty(g_xfs, xinode->inum))
1670 {
1671 log_debug("cannot rmdir; directory is not empty");
22051672 fuse_reply_err(req, ENOTEMPTY);
2206 return;
2207 }
2208 else if (type == 2)
2209 {
2210 if ((xinode->nopen > 1) || ((xinode->nopen == 1) &&
2211 (xinode->close_in_progress == 0)))
2212 {
2213 log_debug("cannot unlink; open count is %d", xinode->nopen);
2214 fuse_reply_err(req, EBUSY);
2215 return;
2216 }
2217 }
2218
2219 strcat(full_path, "/");
2220 strncat(full_path, name, sizeof(full_path) - strlen(full_path) - 1);
2221
2222 if (xinode->is_loc_resource)
1673 }
1674
1675 else if (xinode->device_id == 0)
22231676 {
22241677 /* specified file is a local resource */
22251678 //XFUSE_HANDLE *fh;
22261679
22271680 log_debug("LK_TODO: this is still a TODO");
22281681 fuse_reply_err(req, EINVAL);
2229 return;
2230 }
2231
2232 /* specified file resides on redirected share */
2233
2234 fip = g_new0(XFUSE_INFO, 1);
2235 if (fip == NULL)
2236 {
2237 log_error("system out of memory");
2238 fuse_reply_err(req, ENOMEM);
2239 return;
2240 }
2241
2242 fip->req = req;
2243 fip->inode = parent;
2244 fip->invoke_fuse = 1;
2245 fip->device_id = device_id;
2246 strncpy(fip->name, name, 1024);
2247 fip->name[1023] = 0;
2248 fip->type = type;
2249
2250 /* we want path minus 'root node of the share' */
2251 if ((cptr = strchr(full_path, '/')) == NULL)
2252 {
2253 /* get dev_redir to open the remote file */
2254 if (devredir_rmdir_or_file((void *) fip, device_id, "\\", O_RDWR))
2255 {
2256 log_error("failed to send dev_redir_open_file() cmd");
2257 fuse_reply_err(req, EREMOTEIO);
1682 }
1683 else
1684 {
1685 /* specified file resides on redirected share */
1686 struct state_remove *fip = g_new0(struct state_remove, 1);
1687 char *full_path = xfs_get_full_path(g_xfs, xinode->inum);
1688 if (!full_path || !fip)
1689 {
1690 log_error("system out of memory");
1691 fuse_reply_err(req, ENOMEM);
22581692 free(fip);
2259 return;
2260 }
2261 }
2262 else
2263 {
2264 if (devredir_rmdir_or_file((void *) fip, device_id, cptr, O_RDWR))
2265 {
2266 log_error("failed to send dev_redir_get_dir_listing() cmd");
2267 fuse_reply_err(req, EREMOTEIO);
2268 free(fip);
2269 return;
2270 }
1693 free(full_path);
1694 }
1695 else
1696 {
1697 const char *cptr;
1698
1699 fip->req = req;
1700 fip->inum = xinode->inum;
1701
1702 /* we want path minus 'root node of the share' */
1703 cptr = filename_on_device(full_path);
1704
1705 /* get devredir to open the remote file
1706 *
1707 * If this call succeeds, further request processing happens in
1708 * xfuse_devredir_cb_rmdir_or_file()
1709 */
1710 if (devredir_rmdir_or_file(fip, xinode->device_id, cptr))
1711 {
1712 log_error("failed to send devredir_rmdir_or_file() cmd");
1713 fuse_reply_err(req, EREMOTEIO);
1714 free(fip);
1715 }
1716
1717 }
1718 free(full_path);
22711719 }
22721720 }
22731721
22751723 fuse_ino_t old_parent, const char *old_name,
22761724 fuse_ino_t new_parent, const char *new_name)
22771725 {
2278 XRDP_INODE *old_xinode;
2279 XFUSE_INFO *fip;
2280 tui32 new_device_id;
2281 char *cptr;
2282 char old_full_path[1024];
2283 char new_full_path[1024];
2284 const char *cp;
2285
2286 tui32 device_id;
1726 XFS_INODE *old_xinode;
1727 XFS_INODE *new_parent_xinode;
22871728
22881729 log_debug("entered: old_parent=%ld old_name=%s new_parent=%ld new_name=%s",
22891730 old_parent, old_name, new_parent, new_name);
2290 xfuse_dump_fs();
2291
2292 /* is old_parent inode valid? */
2293 if (!xfuse_is_inode_valid(old_parent))
2294 {
2295 log_error("inode %ld is not valid", old_parent);
2296 fuse_reply_err(req, EINVAL);
2297 return;
2298 }
2299
2300 /* is new_parent inode valid? */
2301 if (!xfuse_is_inode_valid(new_parent))
1731
1732 if (strlen(old_name) > XFS_MAXFILENAMELEN ||
1733 strlen(new_name) > XFS_MAXFILENAMELEN)
1734 {
1735 fuse_reply_err(req, ENAMETOOLONG);
1736 }
1737 else if (!(old_xinode = xfs_lookup_in_dir(g_xfs, old_parent, old_name)))
1738 {
1739 log_error("did not find file with pinode=%ld name=%s",
1740 old_parent, old_name);
1741 fuse_reply_err(req, ENOENT);
1742 }
1743
1744 else if (!(new_parent_xinode = xfs_get(g_xfs, new_parent)))
23021745 {
23031746 log_error("inode %ld is not valid", new_parent);
23041747 fuse_reply_err(req, EINVAL);
2305 return;
2306 }
2307
2308 if ((old_name == NULL) || (strlen(old_name) == 0))
1748 }
1749
1750 else if (!xfs_check_move_entry(g_xfs, old_xinode->inum,
1751 new_parent, new_name))
23091752 {
23101753 fuse_reply_err(req, EINVAL);
2311 return;
2312 }
2313
2314 if ((new_name == NULL) || (strlen(new_name) == 0))
2315 {
2316 fuse_reply_err(req, EINVAL);
2317 return;
2318 }
2319
2320 old_xinode = xfuse_get_inode_from_pinode_name(old_parent, old_name);
2321 if (old_xinode == NULL)
2322 {
2323 log_error("did not find file with pinode=%ld name=%s",
2324 old_parent, old_name);
2325 fuse_reply_err(req, EBADF);
2326 return;
2327 }
2328
2329 /* if file is open, cannot rename */
2330 if (old_xinode->nopen != 0)
2331 {
2332 fuse_reply_err(req, EBUSY);
2333 return;
2334 }
2335
2336 /* rename across file systems not yet supported */
2337 new_device_id = xfuse_get_device_id_for_inode(new_parent, new_full_path);
2338 strcat(new_full_path, "/");
2339 strcat(new_full_path, new_name);
2340
2341 if (new_device_id != old_xinode->device_id)
1754 }
1755
1756 else if (new_parent_xinode->device_id != old_xinode->device_id)
23421757 {
23431758 log_error("rename across file systems not supported");
23441759 fuse_reply_err(req, EINVAL);
2345 return;
2346 }
2347
2348 if (old_xinode->is_loc_resource)
1760 }
1761
1762 else if (old_xinode->device_id == 0)
23491763 {
23501764 /* specified file is a local resource */
23511765 log_debug("LK_TODO: this is still a TODO");
23521766 fuse_reply_err(req, EINVAL);
2353 return;
2354 }
2355
2356 /* resource is on a redirected share */
2357
2358 device_id = old_xinode->device_id;
2359
2360 xfuse_get_device_id_for_inode(old_parent, old_full_path);
2361 strcat(old_full_path, "/");
2362 strcat(old_full_path, old_name);
2363
2364 fip = g_new0(XFUSE_INFO, 1);
2365 if (fip == NULL)
2366 {
2367 log_error("system out of memory");
2368 fuse_reply_err(req, ENOMEM);
2369 return;
2370 }
2371
2372 fip->req = req;
2373 fip->inode = old_parent;
2374 fip->new_inode = new_parent;
2375 strncpy(fip->name, old_name, 1024);
2376 strncpy(fip->new_name, new_name, 1024);
2377 fip->name[1023] = 0;
2378 fip->new_name[1023] = 0;
2379 fip->invoke_fuse = 1;
2380 fip->device_id = device_id;
2381
2382 if ((cp = strchr(new_full_path, '/')) == NULL)
2383 cp = "\\";
2384
2385 /* we want path minus 'root node of the share' */
2386 if ((cptr = strchr(old_full_path, '/')) == NULL)
2387 {
2388 /* get dev_redir to open the remote file */
2389 if (dev_redir_file_open((void *) fip, device_id, "\\",
2390 O_RDWR, S_IFREG | OP_RENAME_FILE, cp))
2391 {
2392 log_error("failed to send dev_redir_file_open() cmd");
2393 fuse_reply_err(req, EREMOTEIO);
1767 }
1768
1769 else
1770 {
1771 /* resource is on a redirected share */
1772 struct state_rename *fip = g_new0(struct state_rename, 1);
1773 char *old_full_path = xfs_get_full_path(g_xfs, old_xinode->inum);
1774 char *new_full_path = get_name_for_entry_in_parent(new_parent,
1775 new_name);
1776
1777 if (!old_full_path || !new_full_path || !fip)
1778 {
1779 log_error("system out of memory");
1780 fuse_reply_err(req, ENOMEM);
23941781 free(fip);
2395 return;
2396 }
2397 }
2398 else
2399 {
2400 if (dev_redir_file_open((void *) fip, device_id, cptr,
2401 O_RDWR, S_IFREG | OP_RENAME_FILE, cp))
2402 {
2403 log_error("failed to send dev_redir_file_open() cmd");
2404 fuse_reply_err(req, EREMOTEIO);
2405 free(fip);
2406 return;
1782 free(old_full_path);
1783 free(new_full_path);
1784 }
1785 else
1786 {
1787 const char *cptr;
1788 const char *cp;
1789
1790 fip->req = req;
1791 fip->pinum = old_xinode->inum;
1792 fip->new_pinum = new_parent;
1793 strcpy(fip->name, new_name);
1794
1795 /* we want path minus 'root node of the share' */
1796 cptr = filename_on_device(old_full_path);
1797 cp = filename_on_device(new_full_path);
1798
1799 /*
1800 * If this call succeeds, further request processing happens in
1801 * xfuse_devredir_cb_rename_file()
1802 */
1803 if (devredir_file_rename(fip, old_xinode->device_id, cptr, cp))
1804 {
1805 log_error("failed to send devredir_file_rename() cmd");
1806 fuse_reply_err(req, EREMOTEIO);
1807 free(fip);
1808 }
1809 free(old_full_path);
1810 free(new_full_path);
24071811 }
24081812 }
24091813 }
24151819 * @param parent parent inode
24161820 * @param name name of dir or file to create
24171821 * @param mode creation mode
2418 * @param fi for storing file handles
2419 * @param type S_IFDIR for dir and S_IFREG for file
1822 * @param fi File info from fuse_lowlevel_ops.create, or NULL.
1823 * This may need to be copied if we're not replying immediately
24201824 *****************************************************************************/
24211825
24221826 static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
24231827 const char *name, mode_t mode,
2424 struct fuse_file_info *fi, int type)
2425 {
2426 XFUSE_INFO *fip;
2427 char *cptr;
2428 char full_path[1024];
2429 tui32 device_id;
2430
2431 full_path[0] = 0;
2432
2433 log_debug("entered: parent_ino=%ld name=%s type=%s",
2434 parent, name, (type == S_IFDIR) ? "dir" : "file");
1828 struct fuse_file_info *fi)
1829 {
1830 XFS_INODE *xinode;
1831
1832 log_debug("entered: parent_ino=%ld name=%s mode=%o type=%s",
1833 parent, name, mode, (mode & S_IFDIR) ? "dir" : "file");
24351834
24361835 /* name must be valid */
2437 if ((name == NULL) || (strlen(name) == 0))
2438 {
2439 log_error("invalid name");
2440 fuse_reply_err(req, EBADF);
2441 return;
2442 }
2443
2444 /* is parent inode valid? */
2445 if ((parent == 1) || (!xfuse_is_inode_valid(parent)))
2446 {
2447 log_error("inode %ld is not valid", parent);
2448 fuse_reply_err(req, EBADF);
2449 return;
2450 }
2451
2452 device_id = xfuse_get_device_id_for_inode(parent, full_path);
2453 strcat(full_path, "/");
2454 strcat(full_path, name);
2455
2456 XRDP_INODE *xinode = g_xrdp_fs.inode_table[parent];
2457 if (xinode->is_loc_resource)
2458 {
2459 /* specified file is a local resource */
2460 //XFUSE_HANDLE *fh;
2461
2462 log_debug("LK_TODO: this is still a TODO");
2463 fuse_reply_err(req, EINVAL);
2464 return;
2465 }
2466
2467 /* specified file resides on redirected share */
2468
2469 fip = g_new0(XFUSE_INFO, 1);
2470 if (fip == NULL)
2471 {
2472 log_error("system out of memory");
2473 fuse_reply_err(req, ENOMEM);
2474 return;
2475 }
2476
2477 fip->req = req;
2478 fip->fi = fi;
2479 fip->inode = parent;
2480 fip->invoke_fuse = 1;
2481 fip->device_id = device_id;
2482 fip->mode = type;
2483 fip->reply_type = RT_FUSE_REPLY_CREATE;
2484 strncpy(fip->name, name, 1024);
2485 fip->name[1023] = 0;
2486
2487 log_debug("+++ created XFUSE_INFO=%p XFUSE_INFO->fi=%p", fip, fip->fi);
2488
2489 /* LK_TODO need to handle open permissions */
2490
2491 /* we want path minus 'root node of the share' */
2492 if ((cptr = strchr(full_path, '/')) == NULL)
2493 {
2494 /* get dev_redir to open the remote file */
2495 if (dev_redir_file_open((void *) fip, device_id, "\\",
2496 O_CREAT, type, NULL))
2497 {
2498 log_error("failed to send dev_redir_open_file() cmd");
2499 fuse_reply_err(req, EREMOTEIO);
2500 }
1836 if (strlen(name) > XFS_MAXFILENAMELEN)
1837 {
1838 fuse_reply_err(req, ENAMETOOLONG);
25011839 }
25021840 else
25031841 {
2504 if (dev_redir_file_open((void *) fip, device_id, cptr,
2505 O_CREAT, type, NULL))
2506 {
2507 log_error("failed to send dev_redir_get_dir_listing() cmd");
2508 fuse_reply_err(req, EREMOTEIO);
2509 }
1842 /* Sanitise the mode
1843 *
1844 * Currently group/world write is not allowed.
1845 */
1846 if (mode & S_IFDIR)
1847 {
1848 mode = (mode & 0777) | S_IFDIR;
1849 }
1850 else
1851 {
1852 mode = (mode & 0777) | S_IFREG;
1853 }
1854
1855 /* is parent inode valid? */
1856 if (parent == FUSE_ROOT_ID ||
1857 (xinode = xfs_get(g_xfs, parent)) == NULL ||
1858 (xinode->mode & S_IFDIR) == 0)
1859 {
1860 log_error("inode %ld is not valid", parent);
1861 fuse_reply_err(req, ENOENT);
1862 }
1863 else if (xinode->device_id == 0)
1864 {
1865 /* specified file is a local resource */
1866 //XFUSE_HANDLE *fh;
1867
1868 log_debug("LK_TODO: this is still a TODO");
1869 fuse_reply_err(req, EINVAL);
1870 }
1871 else
1872 {
1873 struct state_create *fip = g_new0(struct state_create, 1);
1874 char *full_path = get_name_for_entry_in_parent(parent, name);
1875
1876 if (full_path == NULL || fip == NULL)
1877 {
1878 log_error("Out of memory");
1879 fuse_reply_err(req, ENOMEM);
1880 free(fip);
1881 free(full_path);
1882 }
1883 else
1884 {
1885 const char *cptr;
1886
1887 fip->req = req;
1888 if (fi != NULL)
1889 {
1890 fip->fi = *fi;
1891 }
1892 fip->pinum = parent;
1893 strcpy(fip->name, name);
1894 fip->mode = mode;
1895
1896 /* we want path minus 'root node of the share' */
1897 cptr = filename_on_device(full_path);
1898
1899 /*
1900 * If this call succeeds, further request processing happens
1901 * in xfuse_devredir_cb_create_file()
1902 */
1903 if (devredir_file_create(fip, xinode->device_id, cptr, mode))
1904 {
1905 log_error("failed to send devredir_file_create() cmd");
1906 fuse_reply_err(req, EREMOTEIO);
1907 free(fip);
1908 }
1909 free(full_path);
1910 }
1911 }
25101912 }
25111913 }
25121914
25131915 /**
25141916 * Open specified file
1917 *
1918 * GOTCHA : For FUSE 2.9 at least, the 'fi' parameter is allocated on the
1919 * stack by the caller, so must be copied if we're not using it
1920 * to reply to FUSE immediately
25151921 *****************************************************************************/
25161922
25171923 static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
25181924 struct fuse_file_info *fi)
25191925 {
2520 XRDP_INODE *xinode;
2521 XFUSE_INFO *fip;
2522 char *cptr;
2523 char full_path[4096];
2524 tui32 device_id;
1926 XFS_INODE *xinode;
25251927
25261928 log_debug("entered: ino=%ld", ino);
25271929
2528 if (!xfuse_is_inode_valid(ino))
1930 if (!(xinode = xfs_get(g_xfs, ino)))
25291931 {
25301932 log_error("inode %ld is not valid", ino);
2531 fuse_reply_err(req, EBADF);
2532 return;
2533 }
2534
2535 /* if ino points to a dir, fail the open request */
2536 xinode = g_xrdp_fs.inode_table[ino];
2537 if (!xinode)
2538 {
2539 log_debug("****** g_xrdp_fs.inode_table[%ld] is NULL", ino);
2540 fuse_reply_err(req, EBADF);
2541 return;
2542 }
2543 if (xinode->mode & S_IFDIR)
2544 {
2545 log_debug("reading a dir not allowed!");
1933 fuse_reply_err(req, ENOENT);
1934 }
1935 else if (xinode->mode & S_IFDIR)
1936 {
1937 /* Can't open directories like this */
1938 log_debug("reading/writing a dir not allowed!");
25461939 fuse_reply_err(req, EISDIR);
2547 return;
2548 }
2549
2550 device_id = xfuse_get_device_id_for_inode(ino, full_path);
2551
2552 if (xinode->is_loc_resource)
1940 }
1941 else if ((fi->flags & O_ACCMODE) != O_RDONLY &&
1942 (fi->flags & O_ACCMODE) != O_WRONLY &&
1943 (fi->flags & O_ACCMODE) != O_RDWR)
1944 {
1945 log_debug("Invalid access mode specified");
1946 fuse_reply_err(req, EINVAL);
1947 }
1948 else if (xinode->device_id == 0)
25531949 {
25541950 /* specified file is a local resource */
25551951 XFUSE_HANDLE *fh = g_new0(XFUSE_HANDLE, 1);
25561952 fh->is_loc_resource = 1;
25571953 fi->fh = (tintptr) fh;
25581954 fuse_reply_open(req, fi);
2559 return;
2560 }
2561
2562 /* specified file resides on redirected share */
2563
2564 fip = g_new0(XFUSE_INFO, 1);
2565 if (fip == NULL)
2566 {
2567 log_error("system out of memory");
2568 fuse_reply_err(req, ENOMEM);
2569 return;
2570 }
2571
2572 fip->req = req;
2573 fip->inode = ino;
2574 fip->invoke_fuse = 1;
2575 fip->device_id = device_id;
2576 fip->fi = fi;
2577
2578 log_debug("LK_TODO: fip->fi = %p", fip->fi);
2579
2580 strncpy(fip->name, full_path, 1024);
2581 fip->name[1023] = 0;
2582 fip->reply_type = RT_FUSE_REPLY_OPEN;
2583
2584 /* we want path minus 'root node of the share' */
2585 if ((cptr = strchr(full_path, '/')) == NULL)
2586 {
2587 /* get dev_redir to open the remote file */
2588 if (dev_redir_file_open((void *) fip, device_id, "\\",
2589 fi->flags, S_IFREG, NULL))
2590 {
2591 log_error("failed to send dev_redir_open_file() cmd");
2592 fuse_reply_err(req, EREMOTEIO);
2593 }
25941955 }
25951956 else
25961957 {
2597 if (dev_redir_file_open((void *) fip, device_id, cptr,
2598 fi->flags, S_IFREG, NULL))
2599 {
2600 log_error("failed to send dev_redir_get_dir_listing() cmd");
2601 fuse_reply_err(req, EREMOTEIO);
2602 }
2603 }
2604 }
2605
1958 /* specified file resides on redirected share */
1959 struct state_open *fip = g_new0(struct state_open, 1);
1960 char *full_path = xfs_get_full_path(g_xfs, ino);
1961
1962 if (!full_path || !fip)
1963 {
1964 log_error("system out of memory");
1965 fuse_reply_err(req, ENOMEM);
1966 free(fip);
1967 free(full_path);
1968 }
1969 else
1970 {
1971 const char *cptr;
1972
1973 fip->req = req;
1974 fip->fi = *fi;
1975 fip->inum = ino;
1976
1977 /* we want path minus 'root node of the share' */
1978 cptr = filename_on_device(full_path);
1979
1980 /* get devredir to open the remote file
1981 *
1982 * If the caller has set O_TRUNC when writing the file,
1983 * fuse should call us back via fuse_cb_setattr() to set
1984 * the size to zero - we don't need to do this ourselves.
1985 *
1986 * If this call succeeds, further request processing happens in
1987 * xfuse_devredir_cb_open_file()
1988 */
1989 if (devredir_file_open(fip, xinode->device_id, cptr, fi->flags))
1990 {
1991 log_error("failed to send devredir_file_open() cmd");
1992 fuse_reply_err(req, EREMOTEIO);
1993 free(fip);
1994 }
1995 free(full_path);
1996 }
1997 }
1998 }
1999
2000 /*
2001 * GOTCHA : For FUSE 2.9 at least, the 'fi' parameter is allocated on the
2002 * stack by the caller, so must be copied if we're not using it
2003 * to reply to FUSE immediately
2004 */
26062005 static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct
26072006 fuse_file_info *fi)
26082007 {
2609 XFUSE_INFO *fip = NULL;
2008 XFS_INODE *xinode;
2009
26102010 XFUSE_HANDLE *handle = (XFUSE_HANDLE *) (tintptr) (fi->fh);
26112011
26122012 log_debug("entered: ino=%ld fi=%p fi->fh=0x%llx", ino, fi,
26132013 (long long) fi->fh);
26142014
2615 if (!xfuse_is_inode_valid(ino))
2015 if ((xinode = xfs_get(g_xfs, ino)) == NULL)
26162016 {
26172017 log_error("inode %ld is not valid", ino);
2618 fuse_reply_err(req, EBADF);
2619 return;
2620 }
2621
2622 XRDP_INODE *xinode = g_xrdp_fs.inode_table[ino];
2623 if (!xinode)
2624 {
2625 log_debug("****** g_xrdp_fs.inode_table[%ld] is NULL", ino);
2626 fuse_reply_err(req, 0);
2627 return;
2628 }
2629 if (xinode->is_loc_resource)
2018 fuse_reply_err(req, ENOENT);
2019 }
2020 else if (xinode->device_id == 0)
26302021 {
26312022 /* specified file is a local resource */
26322023 fuse_reply_err(req, 0);
2633 return;
2634 }
2635
2636 /* specified file resides on redirected share */
2637
2638 log_debug("nopen=%d", xinode->nopen);
2639
2640 /* if file is not opened, just return */
2641 if (xinode->nopen == 0)
2642 {
2643 log_debug("cannot close because file not opened");
2644 fuse_reply_err(req, 0);
2645 return;
2646 }
2647
2648 fip = g_new0(XFUSE_INFO, 1);
2649 if (fip == NULL)
2650 {
2651 log_error("system out of memory");
2652 fuse_reply_err(req, ENOMEM);
2653 return;
2654 }
2655
2656 fip->req = req;
2657 fip->inode = ino;
2658 fip->invoke_fuse = 1;
2659 fip->device_id = handle->DeviceId;
2660 fip->fi = fi;
2661
2662 log_debug(" +++ created XFUSE_INFO=%p XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
2663 fip, fip->fi, (long long) fip->fi->fh);
2664
2665 fip->fi->fh = 0;
2666 xinode->close_in_progress = 1;
2667
2668 if (devredir_file_close((void *) fip, fip->device_id, handle->FileId))
2669 {
2670 log_error("failed to send devredir_close_file() cmd");
2671 fuse_reply_err(req, EREMOTEIO);
2672 }
2673
2674 free(handle);
2675 }
2676
2677 /**
2024 }
2025 else
2026 {
2027 /* specified file resides on redirected share */
2028
2029 struct state_close *fip = g_new0(struct state_close, 1);
2030 if (fip == NULL)
2031 {
2032 log_error("system out of memory");
2033 fuse_reply_err(req, ENOMEM);
2034 return;
2035 }
2036
2037 fip->req = req;
2038 fip->inum = ino;
2039 fip->fi = *fi;
2040
2041 fi->fh = 0;
2042
2043 /*
2044 * If this call succeeds, further request processing happens in
2045 * xfuse_devredir_cb_file_close()
2046 */
2047 if (devredir_file_close(fip, xinode->device_id, handle->FileId))
2048 {
2049 log_error("failed to send devredir_close_file() cmd");
2050 fuse_reply_err(req, EREMOTEIO);
2051 free(fip);
2052 }
2053
2054 free(handle);
2055 }
2056 }
2057
2058 /**
2059 * GOTCHA : For FUSE 2.9 at least, the 'fi' parameter is allocated on the
2060 * stack by the caller, so must be copied if we're not using it
2061 * to reply to FUSE immediately
26782062 *****************************************************************************/
26792063
26802064 static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size,
26812065 off_t off, struct fuse_file_info *fi)
26822066 {
26832067 XFUSE_HANDLE *fh;
2684 XFUSE_INFO *fusep;
2685 XRDP_INODE *xinode;
2068 struct state_read *fusep;
2069 XFS_INODE *xinode;
26862070 struct req_list_item *rli;
2687 long handle;
26882071
26892072 log_debug("want_bytes %zd bytes at off %lld", size, (long long) off);
26902073
2691 if (fi->fh == 0)
2074 if ((fh = (XFUSE_HANDLE *)fi->fh) == NULL)
26922075 {
26932076 fuse_reply_err(req, EINVAL);
2694 return;
2695 }
2696
2697 handle = fi->fh;
2698 fh = (XFUSE_HANDLE *) handle;
2699
2700 if (fh->is_loc_resource)
2077 }
2078 else if (fh->is_loc_resource)
27012079 {
27022080 /* target file is in .clipboard dir */
27032081
27042082 log_debug("target file is in .clipboard dir");
27052083
2706 if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL)
2084 if ((xinode = xfs_get(g_xfs, ino)) == NULL)
27072085 {
27082086 log_error("ino does not exist in xrdp_fs");
27092087 fuse_reply_buf(req, 0, 0);
27272105 clipboard_request_file_data(rli->stream_id, rli->lindex,
27282106 (int) off, (int) size);
27292107 }
2730
2731 return;
2732 }
2733
2734 /* target file is on a remote device */
2735
2736 fusep = g_new0(XFUSE_INFO, 1);
2737 if (fusep == NULL)
2738 {
2739 log_error("system out of memory");
2740 fuse_reply_err(req, ENOMEM);
2741 return;
2742 }
2743 fusep->req = req;
2744 fusep->inode = ino;
2745 fusep->invoke_fuse = 1;
2746 fusep->device_id = fh->DeviceId;
2747 fusep->fi = fi;
2748
2749 devredir_file_read(fusep, fh->DeviceId, fh->FileId, size, off);
2750 }
2751
2752 /**
2108 }
2109 else
2110 {
2111 /* target file is on a remote device */
2112
2113 fusep = g_new0(struct state_read, 1);
2114 if (fusep == NULL)
2115 {
2116 log_error("system out of memory");
2117 fuse_reply_err(req, ENOMEM);
2118 }
2119 else
2120 {
2121 fusep->req = req;
2122
2123 /*
2124 * If this call succeeds, further request processing happens in
2125 * xfuse_devredir_cb_read_file()
2126 */
2127 devredir_file_read(fusep, fh->DeviceId, fh->FileId, size, off);
2128 }
2129 }
2130 }
2131
2132 /**
2133 * GOTCHA : For FUSE 2.9 at least, the 'fi' parameter is allocated on the
2134 * stack by the caller, so must be copied if we're not using it
2135 * to reply to FUSE immediately
27532136 *****************************************************************************/
27542137
27552138 static void xfuse_cb_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
27562139 size_t size, off_t off, struct fuse_file_info *fi)
27572140 {
27582141 XFUSE_HANDLE *fh;
2759 XFUSE_INFO *fusep;
2760 long handle;
2142 struct state_write *fusep;
27612143
27622144 log_debug("write %zd bytes at off %lld to inode=%ld",
27632145 size, (long long) off, ino);
27642146
2765 if (fi->fh == 0)
2147 if ((fh = (XFUSE_HANDLE *)fi->fh) == NULL)
27662148 {
27672149 log_error("file handle fi->fh is NULL");
27682150 fuse_reply_err(req, EINVAL);
2769 return;
2770 }
2771
2772 handle = fi->fh;
2773 fh = (XFUSE_HANDLE *) handle;
2774
2775 if (fh->is_loc_resource)
2151 }
2152 else if (fh->is_loc_resource)
27762153 {
27772154 /* target file is in .clipboard dir */
27782155 log_debug("THIS IS STILL A TODO!");
2779 return;
2780 }
2781
2782 /* target file is on a remote device */
2783
2784 fusep = g_new0(XFUSE_INFO, 1);
2785 if (fusep == NULL)
2786 {
2787 log_error("system out of memory");
2788 fuse_reply_err(req, ENOMEM);
2789 return;
2790 }
2791
2792 fusep->req = req;
2793 fusep->inode = ino;
2794 fusep->invoke_fuse = 1;
2795 fusep->device_id = fh->DeviceId;
2796 fusep->fi = fi;
2797
2798 log_debug("+++ created XFUSE_INFO=%p XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
2799 fusep, fusep->fi, (long long) fusep->fi->fh);
2800
2801 dev_redir_file_write(fusep, fh->DeviceId, fh->FileId, buf, size, off);
2802 log_debug("exiting");
2803 }
2804
2805 /**
2806 *****************************************************************************/
2807
2156 fuse_reply_err(req, EINVAL);
2157 }
2158 else
2159 {
2160 /* target file is on a remote device */
2161
2162 fusep = g_new0(struct state_write, 1);
2163 if (fusep == NULL)
2164 {
2165 log_error("system out of memory");
2166 fuse_reply_err(req, ENOMEM);
2167 }
2168 else
2169 {
2170 fusep->req = req;
2171 fusep->inum = ino;
2172
2173 /*
2174 * If this call succeeds, further request processing happens in
2175 * xfuse_devredir_cb_write_file()
2176 */
2177 devredir_file_write(fusep, fh->DeviceId, fh->FileId, buf,
2178 size, off);
2179 }
2180 }
2181 }
2182
2183 /**
2184 *****************************************************************************/
2185
2186 /*
2187 * GOTCHA : For FUSE 2.9 at least, the 'fi' parameter is allocated on the
2188 * stack by the caller, so must be copied if we're not using it
2189 * to reply to FUSE immediately
2190 */
28082191 static void xfuse_cb_create(fuse_req_t req, fuse_ino_t parent,
28092192 const char *name, mode_t mode,
28102193 struct fuse_file_info *fi)
28122195 log_debug("entered: parent_inode=%ld, name=%s fi=%p",
28132196 parent, name, fi);
28142197
2815 xfuse_create_dir_or_file(req, parent, name, mode, fi, S_IFREG);
2198 xfuse_create_dir_or_file(req, parent, name, mode & ~S_IFDIR , fi);
28162199 }
28172200
28182201 /**
28292212 #endif
28302213
28312214 /**
2215 * Sets attributes for a directory entry.
2216 *
2217 * If the file resides on a remote share, devredir
2218 * is asked to update it. This will result in the following
2219 * callbacks:-
2220 * - xfuse_devredir_cb_setattr() to update our copy and return status
2221 *
2222 * GOTCHA : For FUSE 2.9 at least, the 'fi' parameter is allocated on the
2223 * stack by the caller, so must be copied if we're not using it
2224 * to reply to FUSE immediately
28322225 *****************************************************************************/
28332226
28342227 static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
28352228 int to_set, struct fuse_file_info *fi)
28362229 {
2837 XRDP_INODE *xinode;
2838 struct stat st;
2230 XFS_INODE *xinode;
28392231
28402232 log_debug("entered to_set=0x%x", to_set);
28412233
2842 if (!xfuse_is_inode_valid(ino))
2234 if ((xinode = xfs_get(g_xfs, ino)) == NULL)
28432235 {
28442236 log_error("inode %ld is not valid", ino);
2845 fuse_reply_err(req, EBADF);
2846 return;
2847 }
2848
2849 if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL)
2850 {
2851 log_debug("g_xrdp_fs.inode_table[%ld] is NULL", ino);
2852 fuse_reply_err(req, EBADF);
2853 return;
2854 }
2855
2856 if (to_set & FUSE_SET_ATTR_MODE)
2857 {
2858 xinode->mode = attr->st_mode;
2859 log_debug("FUSE_SET_ATTR_MODE");
2860
2861 }
2862
2863 if (to_set & FUSE_SET_ATTR_UID)
2864 {
2865 xinode->uid = attr->st_uid;
2866 log_debug("FUSE_SET_ATTR_UID");
2867 }
2868
2869 if (to_set & FUSE_SET_ATTR_GID)
2870 {
2871 xinode->gid = attr->st_gid;
2872 log_debug("FUSE_SET_ATTR_GID");
2873 }
2874
2875 if (to_set & FUSE_SET_ATTR_SIZE)
2876 {
2877 log_debug("previous file size: %lld", (long long) attr->st_size);
2878 xinode->size = attr->st_size;
2879 log_debug("returning file size: %zd", xinode->size);
2880 }
2881
2882 if (to_set & FUSE_SET_ATTR_ATIME)
2883 {
2884 xinode->atime = attr->st_atime;
2885 log_debug("FUSE_SET_ATTR_ATIME");
2886 }
2887
2888 if (to_set & FUSE_SET_ATTR_MTIME)
2889 {
2890 xinode->mtime = attr->st_mtime;
2891 log_debug("FUSE_SET_ATTR_MTIME");
2892 }
2893
2894 if (to_set & FUSE_SET_ATTR_ATIME_NOW)
2895 {
2896 xinode->atime = attr->st_atime;
2897 log_debug("FUSE_SET_ATTR_ATIME_NOW");
2898 }
2899
2900 if (to_set & FUSE_SET_ATTR_MTIME_NOW)
2901 {
2902 xinode->mtime = attr->st_mtime;
2903 log_debug("FUSE_SET_ATTR_MTIME_NOW");
2904 }
2237 fuse_reply_err(req, ENOENT);
2238 }
2239 else if (((to_set & FUSE_SET_ATTR_UID) && attr->st_uid != xinode->uid) ||
2240 ((to_set & FUSE_SET_ATTR_GID) && attr->st_gid != xinode->gid))
2241 {
2242 /* We don't allow any of these */
2243 fuse_reply_err(req, EPERM);
2244 }
2245 else if ((to_set & FUSE_SET_ATTR_MODE) &&
2246 (attr->st_mode & ~(0777 | S_IFDIR | S_IFREG)) != 0)
2247 {
2248 /* We only support standard mode bits and S_IFDIR / S_IFREG */
2249 log_error("Asking for invalid mode bits 0%o to be set", attr->st_mode);
2250 fuse_reply_err(req, EINVAL);
2251 }
2252 else
2253 {
2254 struct file_attr attrs = {0};
2255 tui32 change_mask = 0;
2256
2257 if ((to_set & FUSE_SET_ATTR_MODE) && xinode->mode != attr->st_mode)
2258 {
2259 attrs.mode = attr->st_mode & (0777 | S_IFDIR | S_IFREG);
2260 change_mask |= TO_SET_MODE;
2261 }
2262
2263 if ((to_set & FUSE_SET_ATTR_SIZE) && xinode->size != attr->st_size)
2264 {
2265 attrs.size = attr->st_size;
2266 change_mask |= TO_SET_SIZE;
2267 }
2268
2269 if ((to_set & FUSE_SET_ATTR_ATIME) && xinode->atime != attr->st_atime)
2270 {
2271 attrs.atime = attr->st_atime;
2272 change_mask |= TO_SET_ATIME;
2273 }
2274
2275 if ((to_set & FUSE_SET_ATTR_MTIME) && xinode->mtime != attr->st_mtime)
2276 {
2277 attrs.mtime = attr->st_mtime;
2278 change_mask |= TO_SET_MTIME;
2279 }
2280
2281 if (change_mask == 0)
2282 {
2283 /* No changes have been made */
2284 make_fuse_attr_reply(req, xinode);
2285 }
2286 else if (xinode->device_id == 0)
2287 {
2288 /* Update the local fs */
2289 update_inode_file_attributes(&attrs, change_mask, xinode);
2290 make_fuse_attr_reply(req, xinode);
2291 }
2292 else
2293 {
2294 struct state_setattr *fip = g_new0(struct state_setattr, 1);
2295 char *full_path = xfs_get_full_path(g_xfs, ino);
2296 if (!full_path || !fip)
2297 {
2298 log_error("system out of memory");
2299 fuse_reply_err(req, ENOMEM);
2300 free(fip);
2301 free(full_path);
2302 }
2303 else
2304 {
2305 const char *cptr;
2306 fip->req = req;
2307 fip->inum = ino;
2308 /* Save the important stuff so we can update our node if the
2309 * remote update is successful */
2310 fip->fattr = attrs;
2311 fip->change_mask = change_mask;
2312
2313 /* we want path minus 'root node of the share' */
2314 cptr = filename_on_device(full_path);
2315
2316 /*
2317 * If this call succeeds, further request processing happens
2318 * in xfuse_devredir_cb_setattr()
2319 */
2320 if (devredir_setattr_for_entry(fip, xinode->device_id,
2321 cptr, &attrs, change_mask) < 0)
2322 {
2323 fuse_reply_err(req, EIO);
2324 free(fip);
2325 }
2326
2327 free(full_path);
2328 }
2329 }
2330 }
2331 }
2332
2333 /**
2334 * Get dir listing
2335 *
2336 * GOTCHA : For FUSE 2.9 at least, the 'fi' parameter is allocated on the
2337 * stack by the caller, so must be copied if we're not using it
2338 * to reply to FUSE immediately
2339 *****************************************************************************/
2340 static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
2341 struct fuse_file_info *fi)
2342 {
2343 XFS_INODE *xinode;
2344
2345 log_debug("inode=%ld", ino);
2346
2347 if ((xinode = xfs_get(g_xfs, ino)) == NULL)
2348 {
2349 log_error("inode %ld is not valid", ino);
2350 fuse_reply_err(req, ENOENT);
2351 }
2352 else if (xinode->device_id == 0)
2353 {
2354 if ((fi->fh = (tintptr) xfs_opendir(g_xfs, ino)) == 0)
2355 {
2356 fuse_reply_err(req, ENOMEM);
2357 }
2358 else
2359 {
2360 fuse_reply_open(req, fi);
2361 }
2362 }
2363 else
2364 {
2365 log_debug("did not find entry; redirecting call to devredir");
2366 struct state_dirscan *fip = g_new0(struct state_dirscan, 1);
2367 char *full_path = xfs_get_full_path(g_xfs, ino);
2368
2369 if (full_path == NULL || fip == NULL)
2370 {
2371 fuse_reply_err(req, ENOMEM);
2372 free(fip);
2373 free(full_path);
2374 }
2375 else
2376 {
2377 const char *cptr;
2378 log_debug("dev_id=%d ino=%ld full_path=%s",
2379 xinode->device_id, ino, full_path);
2380
2381 fip->req = req;
2382 fip->pinum = ino;
2383 fip->fi = *fi;
2384
2385 /* we want path minus 'root node of the share' */
2386 cptr = filename_on_device(full_path);
2387
2388 /*
2389 * If this call succeeds, further request processing happens in:-
2390 * - xfuse_devredir_cb_enum_dir_add_entry()
2391 * Called for every file in the directory
2392 * - xfuse_devredir_cb_enum_dir_done()
2393 * Called at the end of the directory scan
2394 */
2395 if (devredir_get_dir_listing(fip, xinode->device_id, cptr))
2396 {
2397 log_error("failed to send devredir_get_dir_listing() cmd");
2398 fuse_reply_buf(req, NULL, 0);
2399 free(fip);
2400 }
2401 free(full_path);
2402 }
2403 }
2404 }
2405
2406 /**
2407 * GOTCHA : For FUSE 2.9 at least, the 'fi' parameter is allocated on the
2408 * stack by the caller, so must be copied if we're not using it
2409 * to reply to FUSE immediately
2410 *****************************************************************************/
2411
2412 static void xfuse_cb_releasedir(fuse_req_t req, fuse_ino_t ino,
2413 struct fuse_file_info *fi)
2414 {
2415 struct xfs_dir_handle *dh = (struct xfs_dir_handle *) fi->fh;
2416 xfs_closedir(g_xfs, dh);
2417 fuse_reply_err(req, 0);
2418 }
2419
2420 /******************************************************************************
2421 * miscellaneous functions
2422 *****************************************************************************/
2423
2424 static void xfs_inode_to_fuse_entry_param(const XFS_INODE *xinode,
2425 struct fuse_entry_param *e)
2426 {
2427 memset(e, 0, sizeof(*e));
2428 e->ino = xinode->inum;
2429 e->attr_timeout = XFUSE_ATTR_TIMEOUT;
2430 e->entry_timeout = XFUSE_ENTRY_TIMEOUT;
2431 e->attr.st_ino = xinode->inum;
2432 e->attr.st_mode = xinode->mode & ~g_umask;
2433 e->attr.st_nlink = 1;
2434 e->attr.st_uid = xinode->uid;
2435 e->attr.st_gid = xinode->gid;
2436 e->attr.st_size = xinode->size;
2437 e->attr.st_atime = xinode->atime;
2438 e->attr.st_mtime = xinode->mtime;
2439 e->attr.st_ctime = xinode->ctime;
2440 e->generation = xinode->generation;
2441 }
2442
2443 static void make_fuse_entry_reply(fuse_req_t req, const XFS_INODE *xinode)
2444 {
2445 struct fuse_entry_param e;
2446 xfs_inode_to_fuse_entry_param(xinode, &e);
2447 fuse_reply_entry(req, &e);
2448 }
2449
2450 static void make_fuse_attr_reply(fuse_req_t req, const XFS_INODE *xinode)
2451 {
2452 struct stat st;
29052453
29062454 memset(&st, 0, sizeof(st));
2907 st.st_ino = xinode->inode;
2908 st.st_mode = xinode->mode;
2909 st.st_size = xinode->size;
2910 st.st_uid = xinode->uid;
2911 st.st_gid = xinode->gid;
2455 st.st_ino = xinode->inum;
2456 st.st_mode = xinode->mode & ~g_umask;
2457 st.st_nlink = 1;
2458 st.st_uid = xinode->uid;
2459 st.st_gid = xinode->gid;
2460 st.st_size = xinode->size;
29122461 st.st_atime = xinode->atime;
29132462 st.st_mtime = xinode->mtime;
29142463 st.st_ctime = xinode->ctime;
29152464
2916 fuse_reply_attr(req, &st, 1.0); /* LK_TODO just faking for now */
2917 }
2918
2919 /**
2920 * Get dir listing
2921 *****************************************************************************/
2922 static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
2923 struct fuse_file_info *fi)
2924 {
2925 struct opendir_req *odreq;
2926
2927 /* save request */
2928 odreq = g_new(struct opendir_req, 1);
2929 odreq->req = req;
2930 odreq->ino = ino;
2931 odreq->fi = fi;
2932
2933 if (fifo_is_empty(&g_fifo_opendir))
2934 {
2935 fifo_insert(&g_fifo_opendir, odreq);
2936 xfuse_proc_opendir_req(req, ino, fi);
2937 }
2938 else
2939 {
2940 /* place req in FIFO; xfuse_devredir_cb_enum_dir_done() will handle it */
2941 fifo_insert(&g_fifo_opendir, odreq);
2942 }
2943 }
2944
2945 /**
2946 * Process the next opendir req
2947 *
2948 * @return 0 of the request was sent for remote lookup, -1 otherwise
2949 *****************************************************************************/
2950 static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino,
2951 struct fuse_file_info *fi)
2952 {
2953 struct dir_info *di;
2954 XRDP_INODE *xinode;
2955 XFUSE_INFO *fip;
2956 tui32 device_id;
2957 char full_path[4096];
2958 char *cptr;
2959
2960 log_debug("inode=%ld", ino);
2961
2962 if (!xfuse_is_inode_valid(ino))
2963 {
2964 log_error("inode %ld is not valid", ino);
2965 fuse_reply_err(req, EBADF);
2966 g_free(fifo_remove(&g_fifo_opendir));
2967 return -1;
2968 }
2969
2970 if (ino == 1)
2971 goto done; /* special case; enumerate top level dir */
2972
2973 if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL)
2974 {
2975 log_debug("g_xrdp_fs.inode_table[%ld] is NULL", ino);
2976 fuse_reply_err(req, EBADF);
2977 g_free(fifo_remove(&g_fifo_opendir));
2978 return -1;
2979 }
2980
2981 if (xinode->is_loc_resource)
2982 goto done;
2983
2984 /* enumerate resources on a remote device */
2985
2986 #ifdef USE_SYNC_FLAG
2987 if (xinode->is_synced)
2988 {
2989 xfuse_enum_dir(req, ino, size, off, fi);
2990 g_free(fifo_remove(&g_fifo_opendir));
2991 return -1;
2992 }
2993 else
2994 {
2995 goto do_remote_lookup;
2996 }
2997
2998 do_remote_lookup:
2999 #endif
3000
3001 xfuse_mark_as_stale(ino);
3002
3003 log_debug("did not find entry; redirecting call to dev_redir");
3004 device_id = xfuse_get_device_id_for_inode(ino, full_path);
3005
3006 log_debug("dev_id=%d ino=%ld full_path=%s", device_id, ino, full_path);
3007
3008 fip = g_new0(XFUSE_INFO, 1);
3009 if (fip == NULL)
3010 {
3011 log_error("system out of memory");
3012 fuse_reply_err(req, ENOMEM);
3013 g_free(fifo_remove(&g_fifo_opendir));
3014 return -1;
3015 }
3016
3017 fip->req = req;
3018 fip->inode = ino;
3019 fip->size = 0;
3020 fip->off = 0;
3021 fip->fi = fi;
3022 fip->dirbuf1.first_time = 1;
3023 fip->dirbuf1.bytes_in_buf = 0;
3024
3025 fip->invoke_fuse = 1;
3026 fip->device_id = device_id;
3027
3028 /* we want path minus 'root node of the share' */
3029 if ((cptr = strchr(full_path, '/')) == NULL)
3030 {
3031 /* enumerate root dir */
3032 if (dev_redir_get_dir_listing((void *) fip, device_id, "\\"))
3033 {
3034 log_error("failed to send dev_redir_get_dir_listing() cmd");
3035 fuse_reply_buf(req, NULL, 0);
3036 }
3037 }
3038 else
3039 {
3040 if (dev_redir_get_dir_listing((void *) fip, device_id, cptr))
3041 {
3042 log_error("failed to send dev_redir_get_dir_listing() cmd");
3043 fuse_reply_buf(req, NULL, 0);
3044 }
3045 }
3046
3047 return 0;
3048
3049 done:
3050
3051 di = g_new0(struct dir_info, 1);
3052 di->index = FIRST_INODE;
3053 fi->fh = (tintptr) di;
3054 fuse_reply_open(req, fi);
3055 g_free(fifo_remove(&g_fifo_opendir));
3056 return -1;
3057 }
3058
3059 /**
3060 *****************************************************************************/
3061
3062 static void xfuse_cb_releasedir(fuse_req_t req, fuse_ino_t ino,
3063 struct fuse_file_info *fi)
3064 {
3065 struct dir_info *di;
3066
3067 di = (struct dir_info *) (tintptr) fi->fh;
3068 if (di)
3069 free(di);
3070
3071 fuse_reply_err(req, 0);
3072 }
3073
3074 /******************************************************************************
3075 * miscellaneous functions
3076 *****************************************************************************/
3077
3078 /**
3079 * Mark all files with matching parent inode as stale
3080 *
3081 * @param pinode the parent inode
3082 *****************************************************************************/
3083
3084 static void
3085 xfuse_mark_as_stale(fuse_ino_t pinode)
3086 {
3087 fuse_ino_t i;
3088 XRDP_INODE *xinode;
3089
3090 if ((pinode < FIRST_INODE) || (pinode >= g_xrdp_fs.num_entries))
3091 return;
3092
3093 for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
3094 {
3095 if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
3096 continue;
3097
3098 /* match parent inode */
3099 if (xinode->parent_inode != pinode)
3100 continue;
3101
3102 /* got a match */
3103 xinode->stale = 1;
3104 }
3105 }
3106
3107 /**
3108 * Delete all files with matching parent inode that are marked as stale
3109 *
3110 * @param pinode the parent inode
3111 *****************************************************************************/
3112
3113 static void
3114 xfuse_delete_stale_entries(fuse_ino_t pinode)
3115 {
3116 fuse_ino_t i;
3117 XRDP_INODE *xinode;
3118
3119 if ((pinode < FIRST_INODE) || (pinode >= g_xrdp_fs.num_entries))
3120 return;
3121
3122 for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
3123 {
3124 if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
3125 continue;
3126
3127 /* match parent inode */
3128 if (xinode->parent_inode != pinode)
3129 continue;
3130
3131 /* got a match, but is it stale? */
3132 if (!xinode->stale)
3133 continue;
3134
3135 /* ok to delete */
3136 if (xinode->mode & S_IFREG)
3137 xfuse_delete_file_with_xinode(xinode);
2465 fuse_reply_attr(req, &st, XFUSE_ATTR_TIMEOUT);
2466 }
2467
2468 /*
2469 * Get the name of a file on the device
2470 *
2471 * For redirected devices, the routine xfs_get_full_path() returns names
2472 * like "/C:/Windows/System32".
2473 * This routine simply returns a pointer to the part of the name following
2474 * the device specification.
2475 */
2476 static const char *filename_on_device(const char *full_path)
2477 {
2478 const char *result = NULL;
2479 if (full_path[0] != '\0')
2480 {
2481 result = strchr(full_path + 1, '/');
2482 }
2483 return result ? result : "/";
2484 }
2485
2486 /*
2487 * Updates attributes on the filesystem, and bumps the inode ctime
2488 *
2489 * This call is used to set attributes, either locally, or following a
2490 * setattr devredir call
2491 */
2492 static void update_inode_file_attributes(const struct file_attr *fattr,
2493 tui32 change_mask, XFS_INODE *xinode)
2494 {
2495 int updated = 0;
2496
2497 if ((change_mask & TO_SET_MODE) != 0 && xinode->mode != fattr->mode)
2498 {
2499 xinode->mode = fattr->mode;
2500 updated = 1;
2501 }
2502 if ((change_mask & TO_SET_SIZE) != 0 && xinode->size != fattr->size)
2503 {
2504 xinode->size = fattr->size;
2505 updated = 1;
2506 }
2507 if ((change_mask & TO_SET_ATIME) != 0 && xinode->atime != fattr->atime)
2508 {
2509 xinode->atime = fattr->atime;
2510 updated = 1;
2511 }
2512 if ((change_mask & TO_SET_MTIME) != 0 && xinode->mtime != fattr->mtime)
2513 {
2514 xinode->mtime = fattr->mtime;
2515 updated = 1;
2516 }
2517
2518 if (updated)
2519 {
2520 xinode->ctime = time(0);
2521 }
2522 }
2523
2524 /*
2525 * Gets the name for a file where we know the parent inode and the
2526 * name for the file under that inode
2527 *
2528 * Result must be freed after use
2529 */
2530 static char *get_name_for_entry_in_parent(fuse_ino_t parent, const char *name)
2531 {
2532 char *result;
2533
2534 if ((result = xfs_get_full_path(g_xfs, parent)) != NULL)
2535 {
2536 char * p = (char *) realloc(result,
2537 strlen(result) + 1 + strlen(name) + 1);
2538 if (p == NULL)
2539 {
2540 free(result);
2541 result = NULL;
2542 }
31382543 else
3139 xfuse_recursive_delete_dir_with_xinode(xinode);
3140 }
2544 {
2545 result = p;
2546 strcat(result, "/");
2547 strcat(result, name);
2548 }
2549 }
2550
2551 return result;
31412552 }
31422553
31432554 #endif /* end else #ifndef XRDP_FUSE */
1818 #ifndef _CHANSRV_FUSE_H
1919 #define _CHANSRV_FUSE_H
2020
21 /* a file or dir entry in the xrdp file system */
22 struct xrdp_inode
21 #include <sys/types.h>
22 #include <time.h>
23
24 #include "arch.h"
25 #include "ms-erref.h"
26
27 /* Used to pass file info back to chansrv_fuse from devredir */
28 struct file_attr
2329 {
24 tui32 parent_inode; /* Parent serial number. */
25 tui32 inode; /* File serial number. */
2630 tui32 mode; /* File mode. */
27 tui32 nlink; /* symbolic link count. */
28 tui32 nentries; /* number of entries in a dir */
29 tui32 nopen; /* number of simultaneous opens */
30 tui32 uid; /* User ID of the file's owner. */
31 tui32 gid; /* Group ID of the file's group. */
32 size_t size; /* Size of file, in bytes. */
31 off_t size; /* Size of file, in bytes. */
3332 time_t atime; /* Time of last access. */
3433 time_t mtime; /* Time of last modification. */
35 time_t ctime; /* Time of last status change. */
36 char name[1024]; /* Dir or filename */
37 tui32 device_id; /* for file system redirection */
38 char is_synced; /* dir struct has been read from */
39 /* remote device, done just once */
40 int lindex; /* used in clipboard operations */
41 int is_loc_resource; /* this is not a redirected resource */
42 int close_in_progress; /* close cmd sent to client */
43 int stale; /* mark file as stale, ok to remove */
4434 };
45 typedef struct xrdp_inode XRDP_INODE; // LK_TODO use this instead of using struct xrdp_inode
35
36 /* Bitmask values used to identify individual elements in
37 * struct file_attr
38 */
39 #define TO_SET_MODE (1<<0)
40 #define TO_SET_SIZE (1<<1)
41 #define TO_SET_ATIME (1<<2)
42 #define TO_SET_MTIME (1<<3)
43 #define TO_SET_ALL (TO_SET_MODE | TO_SET_SIZE | TO_SET_ATIME | TO_SET_MTIME)
44
45 /* Private type passed into and back-from devredir */
46 typedef struct xfuse_info XFUSE_INFO;
4647
4748 int xfuse_init(void);
4849 int xfuse_deinit(void);
4950 int xfuse_check_wait_objs(void);
5051 int xfuse_get_wait_objs(tbus *objs, int *count, int *timeout);
5152 int xfuse_create_share(tui32 share_id, const char *dirname);
53 void xfuse_delete_share(tui32 share_id);
5254
5355 int xfuse_clear_clip_dir(void);
5456 int xfuse_file_contents_range(int stream_id, const char *data, int data_bytes);
5557 int xfuse_file_contents_size(int stream_id, int file_size);
56 int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex);
58 int xfuse_add_clip_dir_item(const char *filename,
59 int flags, int size, int lindex);
60
61 /* State pointer types (opaque outside this module), used for
62 * callback data
63 */
64 struct state_dirscan;
65 struct state_lookup;
66 struct state_setattr;
67 struct state_open;
68 struct state_create;
69 struct state_read;
70 struct state_write;
71 struct state_remove;
72 struct state_rename;
73 struct state_close;
74
5775
5876 /* functions that are invoked from devredir */
59 int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode);
60 void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus);
61 void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId);
62 void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length);
63 void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus);
64 void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus);
65 void xfuse_devredir_cb_file_close(void *vp);
77 void xfuse_devredir_cb_enum_dir_add_entry(
78 struct state_dirscan *fip,
79 const char *name,
80 const struct file_attr *fattr);
81 void xfuse_devredir_cb_enum_dir_done(struct state_dirscan *fip,
82 enum NTSTATUS IoStatus);
83
84 void xfuse_devredir_cb_lookup_entry(struct state_lookup *fip,
85 enum NTSTATUS IoStatus,
86 const struct file_attr *file_info);
87
88 void xfuse_devredir_cb_setattr(struct state_setattr *fip,
89 enum NTSTATUS IoStatus);
90
91 void xfuse_devredir_cb_create_file(struct state_create *fip,
92 enum NTSTATUS IoStatus,
93 tui32 DeviceId, tui32 FileId);
94
95 void xfuse_devredir_cb_open_file(struct state_open *fip,
96 enum NTSTATUS IoStatus,
97 tui32 DeviceId, tui32 FileId);
98
99 void xfuse_devredir_cb_read_file(struct state_read *fip,
100 const char *buf, size_t length);
101 void xfuse_devredir_cb_write_file(
102 struct state_write *fip,
103 enum NTSTATUS IoStatus,
104 off_t offset,
105 size_t length);
106
107 void xfuse_devredir_cb_rmdir_or_file(struct state_remove *fip,
108 enum NTSTATUS IoStatus);
109
110 void xfuse_devredir_cb_rename_file(struct state_rename *fip,
111 enum NTSTATUS IoStatus);
112
113 void xfuse_devredir_cb_file_close(struct state_close *fip);
66114
67115 #endif
0 /**
1 * xrdp: A Remote Desktop Protocol server.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 * This file implements the interface in chansrv_fuse_fs.h
16 */
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <errno.h>
23
24 #if defined(HAVE_CONFIG_H)
25 #include <config_ac.h>
26 #endif
27
28 #include "os_calls.h"
29
30 #include "chansrv_xfs.h"
31
32 /*
33 * Skip this module if FUSE is not supported. A standards-compliant C
34 * translation unit must contain at least one declaration (C99:6.9), and we've
35 * fulfilled that requirement by this stage.
36 */
37 #ifdef XRDP_FUSE
38
39 #define INODE_TABLE_ALLOCATION_INITIAL 4096
40 #define INODE_TABLE_ALLOCATION_GRANULARITY 100
41
42 /* inum of the delete pending directory */
43 #define DELETE_PENDING_ID 2
44
45 /*
46 * A double-linked list of inodes, sorted by inum
47 *
48 * The elements in the list are sorted in increasing inum order, as this
49 * allows a directory enumeration to be easily resumed if elements
50 * are removed or added. See xfs_readdir() for details on this.
51 */
52 typedef struct xfs_inode_all XFS_INODE_ALL;
53 typedef struct xfs_list
54 {
55 XFS_INODE_ALL *begin;
56 XFS_INODE_ALL *end;
57 } XFS_LIST;
58
59 /*
60 * A complete inode, including the private elements used by the
61 * implementation
62 */
63 typedef struct xfs_inode_all
64 {
65 XFS_INODE pub; /* Public elements */
66 /*
67 * Directory linkage elements
68 *
69 * Because we don't support hard-linking, elements can be stored in
70 * one and only one directory:-
71 */
72 struct xfs_inode_all *parent; /* Parent inode */
73 struct xfs_inode_all *next; /* Next entry in parent */
74 struct xfs_inode_all *previous; /* Previous entry in parent */
75 XFS_LIST dir; /* Directory only - children */
76 /*
77 * Other private elements
78 */
79 unsigned int open_count; /* Regular files only */
80 } XFS_INODE_ALL;
81
82
83 /* the xrdp file system in memory
84 *
85 * inode_table allows for O(1) access to any file based on the inum.
86 * Index 0 is unused, so we can use an inode of zero for
87 * an invalid inode, and avoid off-by-one errors index
88 * 1 is our '.' directory.
89 * 2 is the delete pending directory, where we can place
90 * inodes with a positive open count which are
91 * deleted.
92 * free_list List of free inode numbers. Allows for O(1) access to
93 * a free node, provided the free list is not empty.
94 */
95 struct xfs_fs
96 {
97 XFS_INODE_ALL **inode_table; /* a table of entries; can grow. */
98 fuse_ino_t *free_list; /* Free inodes */
99 unsigned int inode_count; /* Current number of inodes */
100 unsigned int free_count; /* Size of free_list */
101 unsigned int generation; /* Changes when an inode is deleted */
102 };
103
104 /* A directory handle
105 *
106 * inum inum of the directory being scanned
107 * generation Generation of the inum we opened
108 */
109 struct xfs_dir_handle
110 {
111 fuse_ino_t inum;
112 tui32 generation;
113 };
114
115 /* module based logging */
116 #define LOG_ERROR 0
117 #define LOG_INFO 1
118 #define LOG_DEBUG 2
119 #ifndef LOG_LEVEL
120 #define LOG_LEVEL LOG_ERROR
121 #endif
122
123 #define log_error(_params...) \
124 { \
125 g_write("[%10.10u]: XFS %s: %d : ERROR: ", \
126 g_time3(), __func__, __LINE__); \
127 g_writeln (_params); \
128 }
129
130 #define log_always(_params...) \
131 { \
132 g_write("[%10.10u]: XFS %s: %d : ALWAYS: ", \
133 g_time3(), __func__, __LINE__); \
134 g_writeln (_params); \
135 }
136
137 #define log_info(_params...) \
138 { \
139 if (LOG_INFO <= LOG_LEVEL) \
140 { \
141 g_write("[%10.10u]: XFS %s: %d : ", \
142 g_time3(), __func__, __LINE__); \
143 g_writeln (_params); \
144 } \
145 }
146
147 #define log_debug(_params...) \
148 { \
149 if (LOG_DEBUG <= LOG_LEVEL) \
150 { \
151 g_write("[%10.10u]: XFS %s: %d : ", \
152 g_time3(), __func__, __LINE__); \
153 g_writeln (_params); \
154 } \
155 }
156
157 /* ------------------------------------------------------------------------ */
158 static int
159 grow_xfs(struct xfs_fs *xfs, unsigned int extra_inodes)
160 {
161 int result = 0;
162 unsigned int new_count = xfs->inode_count + extra_inodes;
163 XFS_INODE_ALL **new_table;
164 fuse_ino_t *new_free_list;
165
166 new_table = (XFS_INODE_ALL **)
167 realloc(xfs->inode_table, new_count * sizeof(new_table[0]));
168 if (new_table != NULL)
169 {
170 unsigned int i;
171 for (i = xfs->inode_count ; i < new_count ; ++i)
172 {
173 new_table[i] = NULL;
174 }
175 xfs->inode_table = new_table;
176
177 new_free_list = (fuse_ino_t *)
178 realloc(xfs->free_list,
179 new_count * sizeof(new_free_list[0]));
180 if (new_free_list)
181 {
182 /* Add the new inodes in to the new_free_list, so the lowest
183 * number is allocated first
184 */
185 i = new_count;
186 while (i > xfs->inode_count)
187 {
188 new_free_list[xfs->free_count++] = --i;
189 }
190
191 xfs->free_list = new_free_list;
192 xfs->inode_count = new_count;
193
194 result = 1;
195 }
196 }
197
198 return result;
199 }
200
201 /* ------------------------------------------------------------------------ */
202 static void
203 add_inode_to_list(XFS_LIST *list, XFS_INODE_ALL *xino)
204 {
205 fuse_ino_t inum = xino->pub.inum;
206
207 /* Find the element we need to insert after */
208 XFS_INODE_ALL *predecessor = list->end;
209 while (predecessor != NULL && predecessor->pub.inum > inum)
210 {
211 predecessor = predecessor->previous;
212 }
213
214 if (predecessor == NULL)
215 {
216 /* Inserting at the beginning */
217 /* Set up links in node */
218 xino->next = list->begin;
219 xino->previous = NULL;
220
221 /* Set up back-link to node */
222 if (list->begin == NULL)
223 {
224 /* We are the last node */
225 list->end = xino;
226 }
227 else
228 {
229 list->begin->previous = xino;
230 }
231 /* Set up forward-link to node */
232 list->begin = xino;
233 }
234 else
235 {
236 /* Set up links in node */
237 xino->next = predecessor->next;
238 xino->previous = predecessor;
239
240 /* Set up back-link to node */
241 if (predecessor->next == NULL)
242 {
243 list->end = xino;
244 }
245 else
246 {
247 predecessor->next->previous = xino;
248 }
249 /* Set up forward-link to node */
250 predecessor->next = xino;
251 }
252 }
253
254 /* ------------------------------------------------------------------------ */
255 static void
256 remove_inode_from_list(XFS_LIST *list, XFS_INODE_ALL *xino)
257 {
258 if (xino->previous == NULL)
259 {
260 /* First element */
261 list->begin = xino->next;
262 }
263 else
264 {
265 xino->previous->next = xino->next;
266 }
267
268 if (xino->next == NULL)
269 {
270 /* Last element */
271 list->end = xino->previous;
272 }
273 else
274 {
275 xino->next->previous = xino->previous;
276 }
277
278 }
279
280 /* ------------------------------------------------------------------------ */
281 static void
282 link_inode_into_directory_node(XFS_INODE_ALL *dinode, XFS_INODE_ALL *xino)
283 {
284 xino->parent = dinode;
285 add_inode_to_list(&dinode->dir, xino);
286 }
287
288 /* ------------------------------------------------------------------------ */
289 static void
290 unlink_inode_from_parent(XFS_INODE_ALL *xino)
291 {
292 remove_inode_from_list(&xino->parent->dir, xino);
293
294 xino->next = NULL;
295 xino->previous = NULL;
296 xino->parent = NULL;
297 }
298
299 /* ------------------------------------------------------------------------ */
300 struct xfs_fs *
301 xfs_create_xfs_fs(mode_t umask, uid_t uid, gid_t gid)
302 {
303 struct xfs_fs *xfs = g_new0(struct xfs_fs, 1);
304 XFS_INODE_ALL *xino1 = NULL;
305 XFS_INODE_ALL *xino2 = NULL;
306
307 if (xfs != NULL)
308 {
309 xfs->inode_count = 0;
310 xfs->free_count = 0;
311 xfs->inode_table = NULL;
312 xfs->free_list = NULL;
313 xfs->generation = 1;
314
315 if (!grow_xfs(xfs, INODE_TABLE_ALLOCATION_INITIAL) ||
316 (xino1 = g_new0(XFS_INODE_ALL, 1)) == NULL ||
317 (xino2 = g_new0(XFS_INODE_ALL, 1)) == NULL)
318 {
319 free(xino1);
320 free(xino2);
321 xfs_delete_xfs_fs(xfs);
322 xfs = NULL;
323 }
324 else
325 {
326 /*
327 * The use of grow_xfs to allocate the inode table will make
328 * inodes 0, 1 (FUSE_ROOT_ID) and 2 (DELETE_PENDING_ID) the first
329 * available free inodes. We can ignore these */
330 xfs->free_count -= 3;
331
332 xfs->inode_table[0] = NULL;
333 xfs->inode_table[FUSE_ROOT_ID] = xino1;
334 xfs->inode_table[DELETE_PENDING_ID] = xino2;
335
336 xino1->pub.inum = FUSE_ROOT_ID;
337 xino1->pub.mode = (S_IFDIR | 0777) & ~umask;
338 xino1->pub.uid = uid;
339 xino1->pub.gid = gid;
340 xino1->pub.size = 0;
341 xino1->pub.atime = time(0);
342 xino1->pub.mtime = xino1->pub.atime;
343 xino1->pub.ctime = xino1->pub.atime;
344 strcpy(xino1->pub.name, ".");
345 xino1->pub.generation = xfs->generation;
346 xino1->pub.device_id = 0;
347
348 /*
349 * FUSE_ROOT_ID has no parent rather than being a parent
350 * of itself. This is intentional */
351 xino1->parent = NULL;
352 xino1->next = NULL;
353 xino1->previous = NULL;
354 xino1->dir.begin = NULL;
355 xino1->dir.end = NULL;
356
357 xino2->pub.inum = DELETE_PENDING_ID;
358 xino2->pub.mode = (S_IFDIR | 0777) & ~umask;
359 xino2->pub.uid = uid;
360 xino2->pub.gid = gid;
361 xino2->pub.size = 0;
362 xino2->pub.atime = time(0);
363 xino2->pub.mtime = xino2->pub.atime;
364 xino2->pub.ctime = xino2->pub.atime;
365 strcpy(xino2->pub.name, ".delete-pending");
366 xino2->pub.generation = xfs->generation;
367 xino2->pub.device_id = 0;
368
369 xino2->parent = NULL;
370 xino2->next = NULL;
371 xino2->previous = NULL;
372 xino2->dir.begin = NULL;
373 xino2->dir.end = NULL;
374 /*
375 * Uncomment this line to make the .delete-pending
376 * directory visible to the user in the root
377 */
378 /* link_inode_into_directory_node(xino1, xino2); */
379 }
380 }
381
382 return xfs;
383 }
384
385 /* ------------------------------------------------------------------------ */
386 void
387 xfs_delete_xfs_fs(struct xfs_fs *xfs)
388 {
389 if (xfs != NULL && xfs->inode_table != NULL)
390 {
391 size_t i;
392 for (i = 0 ; i < xfs->inode_count; ++i)
393 {
394 free(xfs->inode_table[i]);
395 }
396 }
397 free(xfs->inode_table);
398 free(xfs->free_list);
399 free(xfs);
400 }
401
402 /* ------------------------------------------------------------------------ */
403 XFS_INODE *
404 xfs_add_entry(struct xfs_fs *xfs, fuse_ino_t parent_inum,
405 const char *name, mode_t mode)
406 {
407 XFS_INODE *result = NULL;
408 XFS_INODE_ALL *parent = NULL;
409
410 /* Checks:-
411 * 1) the parent exists (and is a directory)
412 * 2) the caller is not inserting into the .delete-pending directory,
413 * 3) Name's not too long
414 * 4) Entry does not already exist
415 */
416 if (parent_inum < xfs->inode_count &&
417 ((parent = xfs->inode_table[parent_inum]) != NULL) &&
418 (parent->pub.mode & S_IFDIR) != 0 &&
419 parent_inum != DELETE_PENDING_ID &&
420 strlen(name) <= XFS_MAXFILENAMELEN &&
421 !xfs_lookup_in_dir(xfs, parent_inum, name))
422 {
423 /* Sanitise the mode so one-and-only-one of S_IFDIR and
424 * S_IFREG is set */
425 if ((mode & S_IFDIR) != 0)
426 {
427 mode = (mode & 0777) | S_IFDIR;
428 }
429 else
430 {
431 mode = (mode & 0777) | S_IFREG;
432 }
433
434 /* Space for a new entry? */
435 if (xfs->free_count > 0 ||
436 grow_xfs(xfs, INODE_TABLE_ALLOCATION_GRANULARITY))
437 {
438 XFS_INODE_ALL *xino = NULL;
439
440 if ((xino = g_new0(XFS_INODE_ALL, 1)) != NULL)
441 {
442 fuse_ino_t inum = xfs->free_list[--xfs->free_count];
443 if (xfs->inode_table[inum] != NULL)
444 {
445 log_error("Unexpected non-NULL value in inode table "
446 "entry %ld", inum);
447 }
448 xfs->inode_table[inum] = xino;
449 xino->pub.inum = inum;
450 xino->pub.mode = mode;
451 xino->pub.uid = parent->pub.uid;
452 xino->pub.gid = parent->pub.gid;
453 if (mode & S_IFDIR)
454 {
455 xino->pub.size = 4096;
456 }
457 else
458 {
459 xino->pub.size = 0;
460 }
461 xino->pub.atime = time(0);
462 xino->pub.mtime = xino->pub.atime;
463 xino->pub.ctime = xino->pub.atime;
464 strcpy(xino->pub.name, name);
465 xino->pub.generation = xfs->generation;
466 xino->pub.device_id = parent->pub.device_id;
467 xino->pub.lindex = 0;
468
469 xino->parent = NULL;
470 xino->next = NULL;
471 xino->previous = NULL;
472 link_inode_into_directory_node(parent, xino);
473 result = &xino->pub;
474 }
475 }
476 }
477
478 return result;
479 }
480
481 /* ------------------------------------------------------------------------ */
482 void
483 xfs_remove_directory_contents(struct xfs_fs *xfs, fuse_ino_t inum)
484 {
485 XFS_INODE_ALL *xino = NULL;
486
487 if (inum < xfs->inode_count &&
488 ((xino = xfs->inode_table[inum]) != NULL) &&
489 ((xino->pub.mode & S_IFDIR) != 0))
490 {
491 XFS_INODE_ALL *e;
492 while ((e = xino->dir.end) != NULL)
493 {
494 xfs_remove_entry(xfs, e->pub.inum);
495 }
496 }
497 }
498
499 /* ------------------------------------------------------------------------ */
500 void
501 xfs_remove_entry(struct xfs_fs *xfs, fuse_ino_t inum)
502 {
503 XFS_INODE_ALL *xino = NULL;
504
505 if (inum < xfs->inode_count &&
506 ((xino = xfs->inode_table[inum]) != NULL))
507 {
508 if ((xino->pub.mode & S_IFDIR) != 0)
509 {
510 xfs_remove_directory_contents(xfs, inum);
511 }
512
513 unlink_inode_from_parent(xino);
514 if ((xino->pub.mode & S_IFREG) != 0 && xino->open_count > 0)
515 {
516 link_inode_into_directory_node(
517 xfs->inode_table[DELETE_PENDING_ID], xino);
518 }
519 else
520 {
521 xfs->free_list[xfs->free_count++] = inum;
522 xfs->inode_table[inum] = NULL;
523 /*
524 * Bump the generation when we return an inum to the free list,
525 * so that the caller can distinguish re-uses of the same inum.
526 */
527 ++xfs->generation;
528 free(xino);
529 }
530 }
531 }
532
533 /* ------------------------------------------------------------------------ */
534 XFS_INODE *
535 xfs_get(struct xfs_fs *xfs, fuse_ino_t inum)
536 {
537 return (inum < xfs->inode_count) ? &xfs->inode_table[inum]->pub : NULL;
538 }
539
540 /* ------------------------------------------------------------------------ */
541 char *
542 xfs_get_full_path(struct xfs_fs *xfs, fuse_ino_t inum)
543 {
544 char *result = NULL;
545 XFS_INODE_ALL *xino = NULL;
546
547 if (inum < xfs->inode_count &&
548 ((xino = xfs->inode_table[inum]) != NULL))
549 {
550 if (xino->pub.inum == FUSE_ROOT_ID)
551 {
552 return strdup("/");
553 }
554 else
555 {
556 /*
557 * Add up the lengths of all the names up to the root,
558 * allowing one extra char for a '/' prefix for each element
559 */
560 size_t len = 0;
561 XFS_INODE_ALL *p;
562 for (p = xino ; p->pub.inum != FUSE_ROOT_ID ; p = p->parent)
563 {
564 len += strlen(p->pub.name);
565 ++len; /* Allow for '/' prefix */
566 }
567
568 result = (char *) malloc(len + 1);
569 if (result != NULL)
570 {
571 /* Construct the path from the end */
572 char *end = result + len;
573 *end = '\0';
574
575 for (p = xino ; p->pub.inum != FUSE_ROOT_ID ; p = p->parent)
576 {
577 len = strlen(p->pub.name);
578 end -= (len + 1);
579 *end = '/';
580 memcpy(end + 1, p->pub.name, len);
581 }
582 }
583 }
584 }
585
586 return result;
587 }
588
589 /* ------------------------------------------------------------------------ */
590 XFS_INODE *
591 xfs_lookup_in_dir(struct xfs_fs *xfs, fuse_ino_t inum, const char *name)
592 {
593 XFS_INODE_ALL *xino;
594 XFS_INODE *result = NULL;
595 if (inum < xfs->inode_count &&
596 ((xino = xfs->inode_table[inum]) != NULL) &&
597 (xino->pub.mode & S_IFDIR) != 0)
598 {
599 XFS_INODE_ALL *p;
600 for (p = xino->dir.begin ; p != NULL; p = p->next)
601 {
602 if (strcmp(p->pub.name, name) == 0)
603 {
604 result = &p->pub;
605 break;
606 }
607 }
608 }
609
610 return result;
611 }
612
613 /* ------------------------------------------------------------------------ */
614 int
615 xfs_is_dir_empty(struct xfs_fs *xfs, fuse_ino_t inum)
616 {
617 XFS_INODE_ALL *xino = NULL;
618 int result = 0;
619
620 if (inum < xfs->inode_count &&
621 ((xino = xfs->inode_table[inum]) != NULL) &&
622 (xino->pub.mode & S_IFDIR) != 0)
623 {
624 result = (xino->dir.begin == NULL);
625 }
626
627 return result;
628 }
629
630 /* ------------------------------------------------------------------------ */
631 unsigned int
632 xfs_is_under(struct xfs_fs *xfs, fuse_ino_t dir, fuse_ino_t entry)
633 {
634 unsigned int result = 0;
635
636 XFS_INODE_ALL *dxino = NULL;
637 XFS_INODE_ALL *exino = NULL;
638
639 if (dir < xfs->inode_count &&
640 ((dxino = xfs->inode_table[dir]) != NULL) &&
641 (dxino->pub.mode & S_IFDIR) != 0 &&
642 entry < xfs->inode_count &&
643 ((exino = xfs->inode_table[entry]) != NULL))
644 {
645 unsigned int count = 0;
646
647 while (exino != NULL && exino != dxino)
648 {
649 ++count;
650 exino = exino->parent;
651 }
652
653 if (exino != NULL)
654 {
655 result = count;
656 }
657 }
658
659 return result;
660 }
661
662 /* ------------------------------------------------------------------------ */
663 struct xfs_dir_handle *
664 xfs_opendir(struct xfs_fs *xfs, fuse_ino_t dir)
665 {
666 XFS_INODE_ALL *xino = NULL;
667 struct xfs_dir_handle *result = NULL;
668
669 if (dir < xfs->inode_count &&
670 ((xino = xfs->inode_table[dir]) != NULL) &&
671 (xino->pub.mode & S_IFDIR) != 0)
672 {
673 result = g_new0(struct xfs_dir_handle, 1);
674 if (result)
675 {
676 result->inum = xino->pub.inum;
677 result->generation = xino->pub.generation;
678 }
679 }
680
681 return result;
682 }
683
684 /* ------------------------------------------------------------------------ */
685 XFS_INODE *
686 xfs_readdir(struct xfs_fs *xfs, struct xfs_dir_handle *handle, off_t *off)
687 {
688 XFS_INODE_ALL *result = NULL;
689 XFS_INODE_ALL *dxino = NULL;
690 XFS_INODE_ALL *xino = NULL;
691
692 /* Check the direcory is still valid */
693 if (handle->inum < xfs->inode_count &&
694 ((dxino = xfs->inode_table[handle->inum]) != NULL) &&
695 (dxino->pub.mode & S_IFDIR) != 0 &&
696 handle->generation == dxino->pub.generation)
697 {
698 fuse_ino_t inum;
699
700 if (*off == (off_t) -1)
701 {
702 /* We're at the end already */
703 }
704 else if ((inum = *off) == 0)
705 {
706 /* First call */
707 result = dxino->dir.begin;
708 }
709 else if (inum < xfs->inode_count &&
710 (xino = xfs->inode_table[inum]) != 0 &&
711 xino->parent == dxino)
712 {
713 /* The node we're pointing to is still valid */
714 result = xino;
715 }
716 else
717 {
718 /*
719 * The file we wanted has been pulled out from under us.
720 * We will look forward in the inode table to try to
721 * discover the next inode in the directory. Because
722 * files are stored in inode order, this guarantees
723 * we'll meet POSIX requirements.
724 */
725 for (inum = inum + 1 ; inum < xfs->inode_count ; ++inum)
726 {
727 if ((xino = xfs->inode_table[inum]) != 0 &&
728 xino->parent == dxino)
729 {
730 result = xino;
731 break;
732 }
733 }
734 }
735 }
736
737 /* Update the offset */
738 if (result == NULL || result->next == NULL)
739 {
740 /* We're done */
741 *off = (off_t) -1;
742 }
743 else
744 {
745 *off = (off_t)result->next->pub.inum;
746 }
747
748 /* Caller only sees public interface to the result */
749 return (result) ? &result->pub : NULL;
750 }
751
752 /* ------------------------------------------------------------------------ */
753 void
754 xfs_closedir(struct xfs_fs *xfs, struct xfs_dir_handle *handle)
755 {
756 free(handle);
757 }
758
759 /* ------------------------------------------------------------------------ */
760 void
761 xfs_increment_file_open_count(struct xfs_fs *xfs, fuse_ino_t inum)
762 {
763 XFS_INODE_ALL *xino;
764 if (inum < xfs->inode_count &&
765 ((xino = xfs->inode_table[inum]) != NULL) &&
766 (xino->pub.mode & S_IFREG) != 0)
767 {
768 ++xino->open_count;
769 }
770 }
771
772 /* ------------------------------------------------------------------------ */
773 void
774 xfs_decrement_file_open_count(struct xfs_fs *xfs, fuse_ino_t inum)
775 {
776 XFS_INODE_ALL *xino;
777 if (inum < xfs->inode_count &&
778 ((xino = xfs->inode_table[inum]) != NULL) &&
779 (xino->pub.mode & S_IFREG) != 0)
780 {
781 if (xino->open_count > 0)
782 {
783 --xino->open_count;
784 }
785
786 if (xino->open_count == 0 &&
787 xino->parent == xfs->inode_table[DELETE_PENDING_ID])
788 {
789 /* We can get rid of this one now */
790 xfs_remove_entry(xfs, inum);
791 }
792 }
793 }
794
795 /* ------------------------------------------------------------------------ */
796 unsigned int
797 xfs_get_file_open_count(struct xfs_fs *xfs, fuse_ino_t inum)
798 {
799 unsigned int result = 0;
800 XFS_INODE_ALL *xino;
801 if (inum < xfs->inode_count &&
802 ((xino = xfs->inode_table[inum]) != NULL) &&
803 (xino->pub.mode & S_IFREG) != 0)
804 {
805 result = xino->open_count;
806 }
807
808 return result;
809 }
810
811 /* ------------------------------------------------------------------------ */
812 void
813 xfs_delete_entries_with_device_id(struct xfs_fs *xfs, tui32 device_id)
814 {
815 fuse_ino_t inum;
816 XFS_INODE_ALL *xino;
817
818 if (device_id != 0)
819 {
820 /* Using xfs_remove_entry() is convenient, but it recurses
821 * in to directories. To make sure all entries are removed, set the
822 * open_count of all affected files to 0 first
823 */
824 for (inum = FUSE_ROOT_ID; inum < xfs->inode_count; ++inum)
825 {
826 if ((xino = xfs->inode_table[inum]) != NULL &&
827 xino->pub.device_id == device_id &&
828 (xino->pub.mode & S_IFREG) != 0)
829 {
830 xino->open_count = 0;
831 }
832 }
833
834 /* Now we can be sure everything will be deleted correctly */
835 for (inum = FUSE_ROOT_ID; inum < xfs->inode_count; ++inum)
836 {
837 if ((xino = xfs->inode_table[inum]) != NULL &&
838 xino->pub.device_id == device_id)
839 {
840 xfs_remove_entry(xfs, xino->pub.inum);
841 }
842 }
843 }
844 }
845
846 /* ------------------------------------------------------------------------ */
847 int
848 xfs_check_move_entry(struct xfs_fs *xfs, fuse_ino_t inum,
849 fuse_ino_t new_parent_inum, const char *name)
850 {
851 XFS_INODE_ALL *xino;
852 XFS_INODE_ALL *parent;
853
854 return
855 (strlen(name) <= XFS_MAXFILENAMELEN &&
856 inum < xfs->inode_count &&
857 ((xino = xfs->inode_table[inum]) != NULL) &&
858 new_parent_inum != DELETE_PENDING_ID &&
859 new_parent_inum < xfs->inode_count &&
860 ((parent = xfs->inode_table[new_parent_inum]) != NULL) &&
861 (parent->pub.mode & S_IFDIR) != 0 &&
862 xfs_is_under(xfs, inum, new_parent_inum) == 0);
863 }
864
865 /* ------------------------------------------------------------------------ */
866 int
867 xfs_move_entry(struct xfs_fs *xfs, fuse_ino_t inum,
868 fuse_ino_t new_parent_inum, const char *name)
869 {
870 int result = EINVAL;
871 XFS_INODE_ALL *xino;
872 XFS_INODE_ALL *parent;
873 XFS_INODE *dest;
874
875 if (xfs_check_move_entry(xfs, inum, new_parent_inum, name))
876 {
877 xino = xfs->inode_table[inum];
878 parent = xfs->inode_table[new_parent_inum];
879
880 if (xino->parent != parent)
881 {
882 /* We're moving between directories */
883
884 /* Does the target name already exist in the destination? */
885 if ((dest = xfs_lookup_in_dir(xfs, new_parent_inum, name)) != NULL)
886 {
887 xfs_remove_entry(xfs, dest->inum);
888 }
889
890 unlink_inode_from_parent(xino);
891 link_inode_into_directory_node(parent, xino);
892 strcpy(xino->pub.name, name);
893 }
894 else if (strcmp(xino->pub.name, name) != 0)
895 {
896 /* Same directory, but name has changed */
897 if ((dest = xfs_lookup_in_dir(xfs, new_parent_inum, name)) != NULL)
898 {
899 xfs_remove_entry(xfs, dest->inum);
900 }
901 strcpy(xino->pub.name, name);
902 }
903 result = 0;
904 }
905
906 return result;
907 }
908 #endif /* XRDP_FUSE */
0 /**
1 * xrdp: A Remote Desktop Protocol server.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 * This file is the interface to the FUSE file system used by
16 * chansrv
17 */
18
19 #ifndef _CHANSRV_XFS
20 #define _CHANSRV_XFS
21
22 /* Skip this include if there's no FUSE */
23 #ifdef XRDP_FUSE
24
25 #include <stddef.h>
26 #include <fuse_lowlevel.h>
27 #include <time.h>
28
29 #include "arch.h"
30
31 #define XFS_MAXFILENAMELEN 255
32
33 /*
34 * Incomplete types for the public interface
35 */
36 struct xfs_fs;
37 struct xfs_dir_handle;
38
39 typedef struct xfs_inode
40 {
41 fuse_ino_t inum; /* File serial number. */
42 mode_t mode; /* File mode. */
43 uid_t uid; /* User ID of the file's owner. */
44 gid_t gid; /* Group ID of the file's group. */
45 off_t size; /* Size of file, in bytes. */
46 time_t atime; /* Time of last access. */
47 time_t mtime; /* Time of last modification. */
48 time_t ctime; /* Time of last status change. */
49 char name[XFS_MAXFILENAMELEN + 1]; /* Short name */
50 tui32 generation; /* Changes if inode is reused */
51 tui32 device_id; /* for file system redirection
52 * Non-redirected devices are guaranteed
53 * to have a device_id or zero */
54 int lindex; /* used in clipboard operations */
55 } XFS_INODE;
56
57 /*
58 * Create a new filesystem instance
59 *
60 * @param umask Umask to apply to initial data structures
61 * @param uid Owner UID for initial root directory
62 * @param gid Owner GID for initial root directory
63 * @return Pointer to instance, or NULL if no memory
64 */
65 struct xfs_fs *
66 xfs_create_xfs_fs(mode_t umask, uid_t uid, gid_t gid);
67
68 /*
69 * Delete a filesystem instance
70 *
71 * @param xfs Filesystem instance
72 */
73 void
74 xfs_delete_xfs_fs(struct xfs_fs *xfs);
75
76 /*
77 * Add an entry to the filesystem
78 *
79 * The returned element has default values inherited from the parent
80 *
81 * The specified mode is sanitised in that:-
82 * - Bits other than the lowest nine permissions bits, the directory
83 * bit (S_IFDIR) and the regular bit (S_IFREG) are cleared.
84 * - S_IFREG is cleared if S_IFDIR is set
85 * - S_IFREG is set if neither S_IFDIR or S_IFREG is set
86 *
87 * NULL is returned for one of the following conditions:-
88 * - the parent does not exist
89 * - the parent is not a directory
90 * - the name length exceeds XFS_MAXFILENAMELEN
91 * - the entry already exists
92 * - memory is exhausted.
93 *
94 * @param xfs filesystem instance
95 * @param parent_inode parent inode
96 * @param name Name of entry
97 * @param mode Initial mode for file.
98 * @return inode, or NULL
99 */
100 XFS_INODE *
101 xfs_add_entry(struct xfs_fs *xfs, fuse_ino_t parent_inum,
102 const char *name, mode_t mode);
103
104 /*
105 * Delete the contents of a directory
106 *
107 * If normal files are opened when they are deleted, the inode is not
108 * released until the open count goes to zero.
109 *
110 * @param xfs filesystem instance
111 * @param inode Reference to entry to delete
112 *
113 */
114 void
115 xfs_remove_directory_contents(struct xfs_fs *xfs, fuse_ino_t inum);
116
117 /*
118 * Delete an entry from the filesystem
119 *
120 * If normal files are opened when they are deleted, the inode is not
121 * released until the open count goes to zero.
122 *
123 * For directories, the contents are removed first.
124 *
125 * @param xfs filesystem instance
126 * @param inode Reference to entry to delete
127 *
128 */
129 void
130 xfs_remove_entry(struct xfs_fs *xfs, fuse_ino_t inum);
131
132 /*
133 * Get an XFS_INODE for an inum
134 *
135 * @param xfs filesystem instance
136 * @param inum Inumber
137 * @return Pointer to XFS_INODE
138 */
139 XFS_INODE *
140 xfs_get(struct xfs_fs *xfs, fuse_ino_t inum);
141
142 /*
143 * Get the full path for an inum
144 *
145 * The path is dynamically allocated, and must be freed after use
146 *
147 * @param xfs filesystem instance
148 * @param inum Inumber to get path for
149 * @return Full path (free after use)
150 */
151 char *
152 xfs_get_full_path(struct xfs_fs *xfs, fuse_ino_t inum);
153
154 /*
155 * Lookup a file in a directory
156 *
157 * @param xfs filesystem instance
158 * @param inum Inumber of the directory
159 * @param name Name of the file to lookup
160 * @return Pointer to XFS_INODE if found
161 */
162 XFS_INODE *
163 xfs_lookup_in_dir(struct xfs_fs *xfs, fuse_ino_t inum, const char *name);
164
165 /*
166 * Inquires as to whether a directory is empty.
167 *
168 * The caller must check that the inum is actually a directory, or
169 * the result is undefined.
170 *
171 * @param xfs filesystem instance
172 * @param inum Inumber of the directory
173 * @return True if the directory is empty
174 */
175 int
176 xfs_is_dir_empty(struct xfs_fs *xfs, fuse_ino_t inum);
177
178 /*
179 * Inquires as to whether an entry is under a directory.
180 *
181 * This can be used to check for invalid renames, where we try to
182 * rename a directory into one of its sub-directories.
183 *
184 * Returned value means one of the following:-
185 * 0 Entry is not related to the directory
186 * 1 Entry is an immediate member of the directory
187 * 2.. Entry is a few levels below the directory
188 *
189 * @param xfs filesystem instance
190 * @param dir Inumber of the directory
191 * @param entry Inumber of the entry
192 * @return Nesting count of entry in the directory, or 0 for
193 * no nesting
194 */
195 unsigned int
196 xfs_is_under(struct xfs_fs *xfs, fuse_ino_t dir, fuse_ino_t entry);
197
198 /*
199 * Opens a directory for reading
200 *
201 * @param xfs filesystem instance
202 * @param dir Inumber of the directory
203 * @return handle to be passed to xfs_readdir() and xfs_closedir()
204 */
205 struct xfs_dir_handle *
206 xfs_opendir(struct xfs_fs *xfs, fuse_ino_t dir);
207
208 /*
209 * Gets the next entry from a directory
210 *
211 * This function is safe to call while the filesystem is being modified.
212 * Whether files added or removed from the directory in question are
213 * returned or not is unspecified by this interface.
214 *
215 * @param xfs filesystem instance
216 * @param handle Handle from xfs_opendir
217 * @param off Offset (by reference). Pass in zero to get the first
218 * entry. After the call, the offset is updated so that
219 * the next call gets the next entry.
220 *
221 * @return pointer to details of file entry, or NULL if no more
222 * entries are available.
223 */
224 XFS_INODE *
225 xfs_readdir(struct xfs_fs *xfs, struct xfs_dir_handle *handle, off_t *off);
226
227
228 /*
229 * Closes a directory opened for reading
230 *
231 * @param xfs filesystem instance
232 * @param handle Earlier result of readdir() call
233 */
234 void
235 xfs_closedir(struct xfs_fs *xfs, struct xfs_dir_handle *handle);
236
237 /*
238 * Increment the file open count
239 *
240 * The file open count is used to be sure when an entry can be deleted from
241 * the data structures. It allows us to remove an entry while still retaining
242 * enough state to manage the file
243 *
244 * This call is only necessary for regular files - not directories
245 *
246 * @param xfs filesystem instance
247 * @param inum File to increment the count of
248 */
249 void
250 xfs_increment_file_open_count(struct xfs_fs *xfs, fuse_ino_t inum);
251
252 /*
253 * Decrement the file open count
254 *
255 * This call will ensure that deleted inodes are cleared up at the appropriate
256 * time.
257 *
258 * This call is only necessary for regular files - not directories
259 *
260 * @param xfs filesystem instance
261 * @param inum File to decrement the count of
262 */
263 void
264 xfs_decrement_file_open_count(struct xfs_fs *xfs, fuse_ino_t inum);
265
266 /*
267 * Return the file open count for a regular file
268 */
269 unsigned int
270 xfs_get_file_open_count(struct xfs_fs *xfs, fuse_ino_t inum);
271
272 /*
273 * Deletes all entries with the matching device id
274 *
275 * Files are deleted even if they are open
276 *
277 * The specified device_id must be non-zero so that the root
278 * filesystem is not deleted!
279 *
280 * @param device_id Device ID
281 */
282 void
283 xfs_delete_entries_with_device_id(struct xfs_fs *xfs, tui32 device_id);
284
285 /*
286 * Check an entry move will be successful
287 *
288 * A move will fail if:-
289 * - Any of the parameters are invalid
290 * - if the entry is a directory, and the new parent is below the
291 * entry in the existing hierarchy.
292 *
293 * @param xfs filesystem instance
294 * @param inum Inumber of entry
295 * @param new_parent New parent
296 * @param name New name
297 *
298 * @result != 0 if all looks OK
299 */
300 int
301 xfs_check_move_entry(struct xfs_fs *xfs, fuse_ino_t inum,
302 fuse_ino_t new_parent_inum, const char *name);
303
304
305 /*
306 * Move (rename) an entry
307 *
308 * @param xfs filesystem instance
309 * @param inum Inumber of entry
310 * @param new_parent New parent
311 * @param name New name
312 *
313 * @result 0, or a suitable errno value.
314 */
315 int
316 xfs_move_entry(struct xfs_fs *xfs, fuse_ino_t inum,
317 fuse_ino_t new_parent_inum, const char *name);
318
319 #endif /* XRDP_FUSE */
320 #endif /* _CHANSRV_XFS */
184184 #define LOG_LEVEL LOG_ERROR
185185
186186 #define log_error(_params...) \
187 { \
188 g_write("[%10.10u]: CLIPBOARD %s: %d : ERROR: ", \
189 g_time3(), __func__, __LINE__); \
190 g_writeln (_params); \
191 }
187 { \
188 g_write("[%10.10u]: CLIPBOARD %s: %d : ERROR: ", \
189 g_time3(), __func__, __LINE__); \
190 g_writeln (_params); \
191 }
192192
193193 #define log_always(_params...) \
194 { \
195 g_write("[%10.10u]: CLIPBOARD %s: %d : ALWAYS: ", \
196 g_time3(), __func__, __LINE__); \
197 g_writeln (_params); \
198 }
194 { \
195 g_write("[%10.10u]: CLIPBOARD %s: %d : ALWAYS: ", \
196 g_time3(), __func__, __LINE__); \
197 g_writeln (_params); \
198 }
199199
200200 #define log_info(_params...) \
201 { \
202 if (LOG_INFO <= LOG_LEVEL) \
203 { \
204 g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
205 g_time3(), __func__, __LINE__); \
206 g_writeln (_params); \
207 } \
208 }
201 { \
202 if (LOG_INFO <= LOG_LEVEL) \
203 { \
204 g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
205 g_time3(), __func__, __LINE__); \
206 g_writeln (_params); \
207 } \
208 }
209209
210210 #define log_debug(_params...) \
211 { \
212 if (LOG_DEBUG <= LOG_LEVEL) \
213 { \
214 g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
215 g_time3(), __func__, __LINE__); \
216 g_writeln (_params); \
217 } \
218 }
211 { \
212 if (LOG_DEBUG <= LOG_LEVEL) \
213 { \
214 g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
215 g_time3(), __func__, __LINE__); \
216 g_writeln (_params); \
217 } \
218 }
219219
220220 static char g_bmp_image_header[] =
221221 {
233233 extern tbus g_x_wait_obj; /* in xcommon.c */
234234 extern Screen *g_screen; /* in xcommon.c */
235235 extern int g_screen_num; /* in xcommon.c */
236
237 extern int g_restrict_outbound_clipboard; /* in chansrv.c */
236238
237239 int g_clip_up = 0;
238240
285287 static char g_last_atom_name[256] = "";
286288
287289 /*****************************************************************************/
288 static char*
290 static char *
289291 get_atom_text(Atom atom)
290292 {
291 char* name;
293 char *name;
292294 int failed;
293295
294296 failed = 0;
404406 if (rv == 0)
405407 {
406408 log_debug("clipboard_init: g_xfixes_event_base %d",
407 g_xfixes_event_base);
409 g_xfixes_event_base);
408410 st = XFixesQueryVersion(g_display, &ver_maj, &ver_min);
409411 log_debug("clipboard_init st %d, maj %d min %d", st,
410 ver_maj, ver_min);
412 ver_maj, ver_min);
411413 g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM",
412414 False);
413415 g_get_time_atom = XInternAtom(g_display, "XRDP_GET_TIME_ATOM",
427429 if (g_image_bmp_atom == None)
428430 {
429431 log_error("clipboard_init: g_image_bmp_atom was "
430 "not allocated");
432 "not allocated");
431433 }
432434
433435 g_wnd = XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen),
462464 s_mark_end(s);
463465 size = (int)(s->end - s->data);
464466 log_debug("clipboard_init: data out, sending "
465 "CB_CLIP_CAPS (clip_msg_id = 1)");
467 "CB_CLIP_CAPS (clip_msg_id = 1)");
466468 rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
467469 if (rv != 0)
468470 {
469471 log_error("clipboard_init: send_channel_data failed "
470 "rv = %d", rv);
472 "rv = %d", rv);
471473 rv = 4;
472474 }
473475 }
483485 s_mark_end(s);
484486 size = (int)(s->end - s->data);
485487 log_debug("clipboard_init: data out, sending "
486 "CB_MONITOR_READY (clip_msg_id = 1)");
488 "CB_MONITOR_READY (clip_msg_id = 1)");
487489 rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
488490 if (rv != 0)
489491 {
490492 log_error("clipboard_init: send_channel_data failed "
491 "rv = %d", rv);
493 "rv = %d", rv);
492494 rv = 4;
493495 }
494496 }
553555 s_mark_end(s);
554556 size = (int)(s->end - s->data);
555557 log_debug("clipboard_send_data_request: data out, sending "
556 "CLIPRDR_DATA_REQUEST (clip_msg_id = 4)");
558 "CLIPRDR_DATA_REQUEST (clip_msg_id = 4)");
557559 rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
558560 free_stream(s);
559561 return rv;
576578 s_mark_end(s);
577579 size = (int)(s->end - s->data);
578580 log_debug("clipboard_send_format_ack: data out, sending "
579 "CLIPRDR_FORMAT_ACK (clip_msg_id = 3)");
581 "CLIPRDR_FORMAT_ACK (clip_msg_id = 3)");
580582 rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
581583 free_stream(s);
582584 return rv;
714716 break;
715717 default:
716718 log_debug("clipboard_send_format_announce: unknown "
717 "xrdp_clip_type %d", xrdp_clip_type);
719 "xrdp_clip_type %d", xrdp_clip_type);
718720 break;
719721 }
720722 }
758760 break;
759761 default:
760762 log_debug("clipboard_send_format_announce: unknown "
761 "xrdp_clip_type %d", xrdp_clip_type);
763 "xrdp_clip_type %d", xrdp_clip_type);
762764 break;
763765 }
764766 }
773775 size = (int)(s->end - s->data);
774776 //g_hexdump(s->data, size);
775777 log_debug("clipboard_send_format_announce: data out, sending "
776 "CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)");
778 "CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)");
777779 rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
778780 free_stream(s);
779781 return rv;
788790 int rv;
789791
790792 log_debug("clipboard_send_data_response_for_image: data_size %d",
791 data_size);
793 data_size);
792794 make_stream(s);
793795 init_stream(s, 64 + data_size);
794796 out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */
813815 int num_chars;
814816
815817 log_debug("clipboard_send_data_response_for_text: data_size %d",
816 data_size);
818 data_size);
817819 //g_hexdump(data, data_size);
818820 num_chars = g_mbstowcs(0, data, 0);
819821 if (num_chars < 0)
820822 {
821823 log_error("clipboard_send_data_response_for_text: "
822 "bad string");
824 "bad string");
823825 num_chars = 0;
824826 }
825827 log_debug("clipboard_send_data_response_for_text: data_size %d "
826 "num_chars %d", data_size, num_chars);
828 "num_chars %d", data_size, num_chars);
827829 make_stream(s);
828830 init_stream(s, 64 + num_chars * 2);
829831 out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */
832834 if (clipboard_out_unicode(s, data, num_chars) != num_chars * 2)
833835 {
834836 log_error("clipboard_send_data_response_for_text: error "
835 "clipboard_out_unicode didn't write right number of bytes");
837 "clipboard_out_unicode didn't write right number of bytes");
836838 }
837839 out_uint16_le(s, 0); /* nil for string */
838840 out_uint32_le(s, 0);
839841 s_mark_end(s);
840842 size = (int)(s->end - s->data);
841843 log_debug("clipboard_send_data_response_for_text: data out, "
842 "sending CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d "
843 "num_chars %d", size, num_chars);
844 "sending CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d "
845 "num_chars %d", size, num_chars);
844846 rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
845847 free_stream(s);
846848 return rv;
868870 else
869871 {
870872 log_debug("clipboard_send_data_response: unknown "
871 "xrdp_clip_type %d", xrdp_clip_type);
873 "xrdp_clip_type %d", xrdp_clip_type);
872874 }
873875 }
874876 else
907909 long val1[2];
908910
909911 log_debug("clipboard_provide_selection_c2s: bytes %d",
910 g_clip_c2s.total_bytes);
912 g_clip_c2s.total_bytes);
911913 if (g_clip_c2s.total_bytes < g_incr_max_req_size)
912914 {
913915 XChangeProperty(g_display, req->requestor, req->property,
933935 g_clip_c2s.property = req->property;
934936 g_clip_c2s.window = req->requestor;
935937 log_debug("clipboard_provide_selection_c2s: start INCR property %s "
936 "type %s", get_atom_text(req->property),
937 get_atom_text(type));
938 "type %s", get_atom_text(req->property),
939 get_atom_text(type));
938940 val1[0] = g_clip_c2s.total_bytes;
939941 val1[1] = 0;
940942 XChangeProperty(g_display, req->requestor, req->property,
10191021 char *holdp;
10201022
10211023 log_debug("clipboard_process_format_announce: "
1022 "CLIPRDR_FORMAT_ANNOUNCE");
1024 "CLIPRDR_FORMAT_ANNOUNCE");
10231025 log_debug("clipboard_process_format_announce %d", clip_msg_len);
10241026 clipboard_send_format_ack();
10251027
10511053 clip_msg_len -= 32;
10521054 }
10531055 log_debug("clipboard_process_format_announce: formatId 0x%8.8x "
1054 "wszFormatName [%s] clip_msg_len %d", formatId, desc,
1055 clip_msg_len);
1056 "wszFormatName [%s] clip_msg_len %d", formatId, desc,
1057 clip_msg_len);
10561058 if (g_num_formatIds <= 15)
10571059 {
10581060 g_formatIds[g_num_formatIds] = formatId;
10721074 }
10731075
10741076 if ((g_num_formatIds > 0) &&
1075 (g_clip_c2s.incr_in_progress == 0) && /* don't interrupt incr */
1076 (g_clip_s2c.incr_in_progress == 0))
1077 (g_clip_c2s.incr_in_progress == 0) && /* don't interrupt incr */
1078 (g_clip_s2c.incr_in_progress == 0))
10771079 {
10781080 if (clipboard_set_selection_owner() != 0)
10791081 {
10801082 log_error("clipboard_process_format_announce: "
1081 "XSetSelectionOwner failed");
1083 "XSetSelectionOwner failed");
10821084 }
10831085 }
10841086
11291131 int requestedFormatId;
11301132
11311133 log_debug("clipboard_process_data_request: "
1132 "CLIPRDR_DATA_REQUEST");
1134 "CLIPRDR_DATA_REQUEST");
11331135 log_debug("clipboard_process_data_request:");
11341136 log_debug(" %d", g_clip_s2c.xrdp_clip_type);
11351137 in_uint32_le(s, requestedFormatId);
11451147 else
11461148 {
11471149 log_debug("clipboard_process_data_request: CB_FORMAT_FILE, "
1148 "calling XConvertSelection to g_utf8_atom");
1150 "calling XConvertSelection to g_utf8_atom");
11491151 g_clip_s2c.xrdp_clip_type = XRDP_CB_FILE;
11501152 XConvertSelection(g_display, g_clipboard_atom, g_clip_s2c.type,
11511153 g_clip_property_atom, g_wnd, CurrentTime);
11611163 else
11621164 {
11631165 log_debug("clipboard_process_data_request: CB_FORMAT_DIB, "
1164 "calling XConvertSelection to g_image_bmp_atom");
1166 "calling XConvertSelection to g_image_bmp_atom");
11651167 g_clip_s2c.xrdp_clip_type = XRDP_CB_BITMAP;
11661168 XConvertSelection(g_display, g_clipboard_atom, g_image_bmp_atom,
11671169 g_clip_property_atom, g_wnd, CurrentTime);
11771179 else
11781180 {
11791181 log_debug("clipboard_process_data_request: CB_FORMAT_UNICODETEXT, "
1180 "calling XConvertSelection to g_utf8_atom");
1182 "calling XConvertSelection to g_utf8_atom");
11811183 g_clip_s2c.xrdp_clip_type = XRDP_CB_TEXT;
11821184 XConvertSelection(g_display, g_clipboard_atom, g_utf8_atom,
11831185 g_clip_property_atom, g_wnd, CurrentTime);
11851187 break;
11861188 default:
11871189 log_debug("clipboard_process_data_request: unknown type %d",
1188 requestedFormatId);
1190 requestedFormatId);
11891191 clipboard_send_data_response_failed();
11901192 break;
11911193 }
12001202 clipboard data. */
12011203 static int
12021204 clipboard_process_data_response_for_image(struct stream *s,
1203 int clip_msg_status,
1204 int clip_msg_len)
1205 int clip_msg_status,
1206 int clip_msg_len)
12051207 {
12061208 XSelectionRequestEvent *lxev;
12071209 int len;
12081210
12091211 log_debug("clipboard_process_data_response_for_image: "
1210 "CLIPRDR_DATA_RESPONSE_FOR_IMAGE");
1212 "CLIPRDR_DATA_RESPONSE_FOR_IMAGE");
12111213 lxev = &g_saved_selection_req_event;
12121214 len = (int)(s->end - s->p);
12131215 if (len < 1)
12301232 g_memcpy(g_clip_c2s.data, g_bmp_image_header, 14);
12311233 in_uint8a(s, g_clip_c2s.data + 14, len);
12321234 log_debug("clipboard_process_data_response_for_image: calling "
1233 "clipboard_provide_selection_c2s");
1235 "clipboard_provide_selection_c2s");
12341236 clipboard_provide_selection_c2s(lxev, lxev->target);
12351237 return 0;
12361238 }
12581260 if (g_clip_c2s.xrdp_clip_type == XRDP_CB_BITMAP)
12591261 {
12601262 clipboard_process_data_response_for_image(s, clip_msg_status,
1261 clip_msg_len);
1263 clip_msg_len);
12621264 return 0;
12631265 }
12641266 if (g_clip_c2s.xrdp_clip_type == XRDP_CB_FILE)
12861288 return 0;
12871289 }
12881290 log_debug("clipboard_process_data_response: "
1289 "CLIPRDR_DATA_RESPONSE");
1291 "CLIPRDR_DATA_RESPONSE");
12901292 len = (int)(s->end - s->p);
12911293 if (len < 1)
12921294 {
13611363 in_uint32_le(s, version); /* version */
13621364 in_uint32_le(s, flags); /* generalFlags */
13631365 log_debug("clipboard_process_clip_caps: "
1364 "g_cliprdr_version %d version %d "
1365 "g_cliprdr_flags 0x%x flags 0x%x",
1366 g_cliprdr_version, version,
1367 g_cliprdr_flags, flags);
1366 "g_cliprdr_version %d version %d "
1367 "g_cliprdr_flags 0x%x flags 0x%x",
1368 g_cliprdr_version, version,
1369 g_cliprdr_flags, flags);
13681370 if (version < g_cliprdr_version)
13691371 {
13701372 g_cliprdr_version = version;
13731375 break;
13741376 default:
13751377 log_debug("clipboard_process_clip_caps: unknown "
1376 "capabilitySetType %d", capabilitySetType);
1378 "capabilitySetType %d", capabilitySetType);
13771379 break;
13781380 }
13791381 s->p = holdp + lengthCapability;
15511553 if (!g_clip_up)
15521554 {
15531555 log_error("aborting clipboard_data_in - clipboard has not "
1554 "been initialized");
1556 "been initialized");
15551557 /* we return 0 here to indicate no protocol problem occurred */
15561558 return 0;
15571559 }
15581560
15591561 log_debug("clipboard_data_in: chan_id %d "
1560 "chan_flags 0x%x length %d total_length %d "
1561 "in_request %d g_ins->size %d",
1562 chan_id, chan_flags, length, total_length,
1563 g_clip_c2s.in_request, g_ins->size);
1562 "chan_flags 0x%x length %d total_length %d "
1563 "in_request %d g_ins->size %d",
1564 chan_id, chan_flags, length, total_length,
1565 g_clip_c2s.in_request, g_ins->size);
15641566
15651567 if (g_clip_c2s.doing_response_ss)
15661568 {
16201622 in_uint32_le(ls, clip_msg_len);
16211623
16221624 log_debug("clipboard_data_in: clip_msg_id %d "
1623 "clip_msg_status %d clip_msg_len %d",
1624 clip_msg_id, clip_msg_status, clip_msg_len);
1625 "clip_msg_status %d clip_msg_len %d",
1626 clip_msg_id, clip_msg_status, clip_msg_len);
16251627 rv = 0;
16261628
16271629 log_debug("clipboard_data_in: %d", clip_msg_id);
16281630 switch (clip_msg_id)
16291631 {
1630 /* sent by client or server when its local system clipboard is */
1631 /* updated with new clipboard data; contains Clipboard Format ID */
1632 /* and name pairs of new Clipboard Formats on the clipboard. */
1632 /* sent by client or server when its local system clipboard is */
1633 /* updated with new clipboard data; contains Clipboard Format ID */
1634 /* and name pairs of new Clipboard Formats on the clipboard. */
16331635 case CB_FORMAT_LIST: /* 2 CLIPRDR_FORMAT_ANNOUNCE */
16341636 rv = clipboard_process_format_announce(ls, clip_msg_status,
16351637 clip_msg_len);
16361638 break;
1637 /* response to CB_FORMAT_LIST; used to indicate whether */
1638 /* processing of the Format List PDU was successful */
1639 /* response to CB_FORMAT_LIST; used to indicate whether */
1640 /* processing of the Format List PDU was successful */
16391641 case CB_FORMAT_LIST_RESPONSE: /* 3 CLIPRDR_FORMAT_ACK */
16401642 rv = clipboard_process_format_ack(ls, clip_msg_status,
16411643 clip_msg_len);
16421644 break;
1643 /* sent by recipient of CB_FORMAT_LIST; used to request data for one */
1644 /* of the formats that was listed in CB_FORMAT_LIST */
1645 /* sent by recipient of CB_FORMAT_LIST; used to request data for one */
1646 /* of the formats that was listed in CB_FORMAT_LIST */
16451647 case CB_FORMAT_DATA_REQUEST: /* 4 CLIPRDR_DATA_REQUEST */
16461648 rv = clipboard_process_data_request(ls, clip_msg_status,
16471649 clip_msg_len);
16481650 break;
1649 /* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate */
1650 /* whether processing of the CB_FORMAT_DATA_REQUEST was */
1651 /* successful; if processing was successful, */
1652 /* CB_FORMAT_DATA_RESPONSE includes contents of requested */
1653 /* clipboard data. */
1651 /* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate */
1652 /* whether processing of the CB_FORMAT_DATA_REQUEST was */
1653 /* successful; if processing was successful, */
1654 /* CB_FORMAT_DATA_RESPONSE includes contents of requested */
1655 /* clipboard data. */
16541656 case CB_FORMAT_DATA_RESPONSE: /* 5 CLIPRDR_DATA_RESPONSE */
16551657 rv = clipboard_process_data_response(ls, clip_msg_status,
16561658 clip_msg_len);
16701672 default:
16711673 log_debug("clipboard_data_in: unknown clip_msg_id %d", clip_msg_id);
16721674 log_error("clipboard_data_in: unknown clip_msg_id %d",
1673 clip_msg_id);
1675 clip_msg_id);
16741676 break;
16751677 }
16761678
17021704 lxevent = (XFixesSelectionNotifyEvent *)xevent;
17031705 log_debug("clipboard_event_selection_owner_notify: 0x%lx", lxevent->owner);
17041706 log_debug("clipboard_event_selection_owner_notify: "
1705 "window %ld subtype %d owner %ld g_wnd %ld",
1706 lxevent->window, lxevent->subtype, lxevent->owner, g_wnd);
1707 "window %ld subtype %d owner %ld g_wnd %ld",
1708 lxevent->window, lxevent->subtype, lxevent->owner, g_wnd);
17071709
17081710 if (lxevent->owner == g_wnd)
17091711 {
17101712 log_debug("clipboard_event_selection_owner_notify: matches g_wnd");
17111713 log_debug("clipboard_event_selection_owner_notify: skipping, "
1712 "owner == g_wnd");
1714 "owner == g_wnd");
17131715 g_got_selection = 1;
17141716 return 0;
17151717 }
17161718
17171719 g_got_selection = 0;
17181720 if (lxevent->owner != 0) /* nil owner comes when selection */
1719 { /* window is closed */
1721 {
1722 /* window is closed */
17201723 XConvertSelection(g_display, g_clipboard_atom, g_targets_atom,
17211724 g_clip_property_atom, g_wnd, lxevent->timestamp);
17221725 }
18701873 if (lxevent->property == None)
18711874 {
18721875 log_error("clipboard_event_selection_notify: clip could "
1873 "not be converted");
1876 "not be converted");
18741877 rv = 1;
18751878 }
18761879
18771880 if (rv == 0)
18781881 {
18791882 log_debug("clipboard_event_selection_notify: wnd 0x%lx prop %s",
1880 lxevent->requestor,
1881 get_atom_text(lxevent->property));
1883 lxevent->requestor,
1884 get_atom_text(lxevent->property));
18821885 rv = clipboard_get_window_property(lxevent->requestor, lxevent->property,
18831886 &type, &fmt,
18841887 &n_items, &data, &data_size);
18851888 if (rv != 0)
18861889 {
18871890 log_error("clipboard_event_selection_notify: "
1888 "clipboard_get_window_property failed error %d", rv);
1891 "clipboard_get_window_property failed error %d", rv);
18891892 return 0;
18901893 }
18911894 //g_hexdump(data, data_size);
18951898 /* nothing more to do here, the data is coming in through
18961899 PropertyNotify */
18971900 log_debug("clipboard_event_selection_notify: type is INCR "
1898 "data_size %d property name %s type %s", data_size,
1899 get_atom_text(lxevent->property),
1900 get_atom_text(lxevent->type));
1901 "data_size %d property name %s type %s", data_size,
1902 get_atom_text(lxevent->property),
1903 get_atom_text(lxevent->type));
19011904 g_clip_s2c.incr_in_progress = 1;
19021905 g_clip_s2c.property = lxevent->property;
19031906 g_clip_s2c.type = lxevent->target;
19271930 "clipboard_event_selection_notify: 0x%lx %s 0x%lx",
19281931 atom, get_atom_text(atom), XA_STRING));
19291932 log_debug("clipboard_event_selection_notify: 0x%lx %s",
1930 atom, get_atom_text(atom));
1933 atom, get_atom_text(atom));
19311934 if (atom == g_utf8_atom)
19321935 {
19331936 got_utf8 = 1;
19541957 else
19551958 {
19561959 log_error("clipboard_event_selection_notify: error, "
1957 "target is 'TARGETS' and type[%ld] or fmt[%d] not right, "
1958 "should be type[%ld], fmt[%d]", type, fmt, XA_ATOM, 32);
1960 "target is 'TARGETS' and type[%ld] or fmt[%d] not right, "
1961 "should be type[%ld], fmt[%d]", type, fmt, XA_ATOM, 32);
19591962 }
19601963 }
19611964 else if (lxevent->target == g_utf8_atom)
19621965 {
19631966 log_debug("clipboard_event_selection_notify: UTF8_STRING "
1964 "data_size %d", data_size);
1967 "data_size %d", data_size);
19651968 log_debug("clipboard_event_selection_notify: UTF8_STRING "
1966 "data_size %d", data_size);
1969 "data_size %d", data_size);
19671970 if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
19681971 {
19691972 g_free(g_clip_s2c.data);
19861989 else if (lxevent->target == XA_STRING)
19871990 {
19881991 log_debug("clipboard_event_selection_notify: XA_STRING "
1989 "data_size %d", data_size);
1992 "data_size %d", data_size);
19901993 log_debug("clipboard_event_selection_notify: XA_STRING "
1991 "data_size %d", data_size);
1994 "data_size %d", data_size);
19921995 if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
19931996 {
19941997 g_free(g_clip_s2c.data);
20032006 else if (lxevent->target == g_image_bmp_atom)
20042007 {
20052008 log_debug("clipboard_event_selection_notify: image/bmp "
2006 "data_size %d", data_size);
2009 "data_size %d", data_size);
20072010 log_debug("clipboard_event_selection_notify: image/bmp "
2008 "data_size %d", data_size);
2011 "data_size %d", data_size);
20092012 if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 14))
20102013 {
20112014 g_free(g_clip_s2c.data);
20192022 else if (lxevent->target == g_file_atom1)
20202023 {
20212024 log_debug("clipboard_event_selection_notify: text/uri-list "
2022 "data_size %d", data_size);
2025 "data_size %d", data_size);
20232026 log_debug("clipboard_event_selection_notify: text/uri-list "
2024 "data_size %d", data_size);
2027 "data_size %d", data_size);
20252028 if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
20262029 {
20272030 g_free(g_clip_s2c.data);
20362039 else if (lxevent->target == g_file_atom2)
20372040 {
20382041 log_debug("clipboard_event_selection_notify: text/uri-list "
2039 "data_size %d", data_size);
2042 "data_size %d", data_size);
20402043 log_debug("clipboard_event_selection_notify: text/uri-list "
2041 "data_size %d", data_size);
2044 "data_size %d", data_size);
20422045 if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
20432046 {
20442047 g_free(g_clip_s2c.data);
20532056 else
20542057 {
20552058 log_error("clipboard_event_selection_notify: "
2056 "unknown target");
2059 "unknown target");
20572060 }
20582061 }
20592062 else
20602063 {
20612064 log_error("clipboard_event_selection_notify: "
2062 "unknown selection");
2065 "unknown selection");
20632066 }
20642067 }
20652068
21442147 lxev = (XSelectionRequestEvent *)xevent;
21452148 log_debug("clipboard_event_selection_request: 0x%lx", lxev->property);
21462149 log_debug("clipboard_event_selection_request: g_wnd %ld, "
2147 ".requestor %ld .owner %ld .selection %ld '%s' .target %ld .property %ld",
2148 g_wnd, lxev->requestor, lxev->owner, lxev->selection,
2149 get_atom_text(lxev->selection),
2150 lxev->target, lxev->property);
2150 ".requestor %ld .owner %ld .selection %ld '%s' .target %ld .property %ld",
2151 g_wnd, lxev->requestor, lxev->owner, lxev->selection,
2152 get_atom_text(lxev->selection),
2153 lxev->target, lxev->property);
21512154
21522155 if (lxev->property == None)
21532156 {
21542157 log_debug("clipboard_event_selection_request: lxev->property "
2155 "is None");
2158 "is None");
21562159 log_debug("clipboard_event_selection_request: "
2157 "lxev->property is None");
2160 "lxev->property is None");
21582161 }
21592162 else if (lxev->target == g_targets_atom)
21602163 {
21612164 log_debug("clipboard_event_selection_request: g_targets_atom");
21622165 /* requestor is asking what the selection can be converted to */
21632166 log_debug("clipboard_event_selection_request: "
2164 "g_targets_atom");
2167 "g_targets_atom");
21652168 atom_buf[0] = g_targets_atom;
21662169 atom_buf[1] = g_timestamp_atom;
21672170 atom_buf[2] = g_multiple_atom;
21922195 {
21932196 /* requestor is asking the time I got the selection */
21942197 log_debug("clipboard_event_selection_request: "
2195 "g_timestamp_atom");
2198 "g_timestamp_atom");
21962199 atom_buf[0] = g_selection_time;
21972200 atom_buf[1] = 0;
21982201 return clipboard_provide_selection(lxev, XA_INTEGER, 32,
22022205 {
22032206 /* target, property pairs */
22042207 log_debug("clipboard_event_selection_request: "
2205 "g_multiple_atom");
2208 "g_multiple_atom");
22062209
22072210 xdata = 0;
22082211 if (clipboard_get_window_property(lxev->requestor, lxev->property,
22102213 &xdata_size) == 0)
22112214 {
22122215 log_debug("clipboard_event_selection_request: g_multiple_atom "
2213 "n_items %d", n_items);
2216 "n_items %d", n_items);
22142217 /* todo */
22152218 g_free(xdata);
22162219 }
22752278 else
22762279 {
22772280 log_debug("clipboard_event_selection_request: unknown "
2278 "target %s", get_atom_text(lxev->target));
2281 "target %s", get_atom_text(lxev->target));
22792282 LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_request: unknown "
22802283 "target %s", get_atom_text(lxev->target)));
22812284 }
23312334
23322335 log_debug("clipboard_event_property_notify:");
23332336 log_debug("clipboard_event_property_notify: PropertyNotify .window %ld "
2334 ".state %d .atom %ld %s", xevent->xproperty.window,
2335 xevent->xproperty.state, xevent->xproperty.atom,
2336 get_atom_text(xevent->xproperty.atom));
2337 ".state %d .atom %ld %s", xevent->xproperty.window,
2338 xevent->xproperty.state, xevent->xproperty.atom,
2339 get_atom_text(xevent->xproperty.atom));
23372340
23382341 if (g_clip_c2s.incr_in_progress &&
23392342 (xevent->xproperty.window == g_clip_c2s.window) &&
23522355 data = (tui8 *)(g_clip_c2s.data + g_clip_c2s.incr_bytes_done);
23532356 data_bytes = g_clip_c2s.read_bytes_done - g_clip_c2s.incr_bytes_done;
23542357 if ((data_bytes < 1) &&
2355 (g_clip_c2s.read_bytes_done < g_clip_c2s.total_bytes))
2358 (g_clip_c2s.read_bytes_done < g_clip_c2s.total_bytes))
23562359 {
23572360 g_clip_c2s.incr_in_progress = 0;
23582361 return 0;
24222425 else
24232426 {
24242427 log_error("clipboard_event_property_notify: error unknown type %ld",
2425 g_clip_s2c.type);
2428 g_clip_s2c.type);
24262429 clipboard_send_data_response_failed();
24272430 }
24282431
24832486 {
24842487 XEvent *lxevent;
24852488
2489 log_debug("clipboard_xevent: event detected");
2490
24862491 if (!g_clip_up)
24872492 {
24882493 return 1;
24932498 switch (lxevent->type)
24942499 {
24952500 case SelectionNotify:
2496 clipboard_event_selection_notify(lxevent);
2501 if (g_restrict_outbound_clipboard == 0)
2502 {
2503 clipboard_event_selection_notify(lxevent);
2504 }
2505 else
2506 {
2507 log_debug("outbound clipboard is restricted because of config");
2508 return 1;
2509 }
24972510 break;
24982511 case SelectionRequest:
24992512 clipboard_event_selection_request(lxevent);
5353 #include "chansrv_fuse.h"
5454 #include "devredir.h"
5555 #include "smartcard.h"
56 #include "ms-rdpefs.h"
57 #include "ms-smb2.h"
58 #include "ms-fscc.h"
59 #include "ms-erref.h"
5660
5761 /* module based logging */
5862 #define LOG_ERROR 0
5963 #define LOG_INFO 1
6064 #define LOG_DEBUG 2
6165
62 #ifndef LOG_LEVEL
66 #undef LOG_LEVEL
6367 #define LOG_LEVEL LOG_ERROR
64 #endif
6568
6669 #define log_error(_params...) \
6770 { \
8992 g_writeln (_params); \
9093 } \
9194 }
95
96 /* client minor versions */
97 #define RDP_CLIENT_50 0x0002
98 #define RDP_CLIENT_51 0x0005
99 #define RDP_CLIENT_52 0x000a
100 #define RDP_CLIENT_60_61 0x000c
101
102 /* Windows time starts on Jan 1, 1601 */
103 /* Linux time starts on Jan 1, 1970 */
104 #define EPOCH_DIFF 11644473600LL
105 #define WINDOWS_TO_LINUX_TIME(_t) (((_t) / 10000000) - EPOCH_DIFF);
106 #define LINUX_TO_WINDOWS_TIME(_t) (((_t) + EPOCH_DIFF) * 10000000)
107
108 /*
109 * CompletionID types, used in IRPs to indicate I/O operation
110 */
111
112 enum COMPLETION_TYPE
113 {
114 CID_CREATE_DIR_REQ = 1,
115 CID_DIRECTORY_CONTROL,
116 CID_CREATE_REQ,
117 CID_OPEN_REQ,
118 CID_READ,
119 CID_WRITE,
120 CID_CLOSE,
121 CID_FILE_CLOSE,
122 CID_RMDIR_OR_FILE,
123 CID_RMDIR_OR_FILE_RESP,
124 CID_RENAME_FILE,
125 CID_RENAME_FILE_RESP,
126 CID_LOOKUP,
127 CID_SETATTR
128 };
129
92130
93131 /* globals */
94132 extern int g_rdpdr_chan_id; /* in chansrv.c */
105143 tui16 g_client_rdp_version; /* returned by client */
106144 struct stream *g_input_stream = NULL;
107145
108 void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length);
146 /*
147 * Local functions called from devredir_proc_device_iocompletion()
148 */
149 static void devredir_proc_cid_rmdir_or_file(IRP *irp, enum NTSTATUS IoStatus);
150 static void devredir_proc_cid_rmdir_or_file_resp(IRP *irp,
151 enum NTSTATUS IoStatus);
152 static void devredir_proc_cid_rename_file(IRP *irp, enum NTSTATUS IoStatus);
153 static void devredir_proc_cid_rename_file_resp(IRP *irp,
154 enum NTSTATUS IoStatus);
155 static void devredir_proc_cid_lookup( IRP *irp,
156 struct stream *s_in,
157 enum NTSTATUS IoStatus);
158 static void devredir_proc_cid_setattr( IRP *irp,
159 struct stream *s_in,
160 enum NTSTATUS IoStatus);
161 /* Other local functions */
162 static void devredir_send_server_core_cap_req(void);
163 static void devredir_send_server_clientID_confirm(void);
164 static void devredir_send_server_user_logged_on(void);
165
166 static void devredir_proc_client_core_cap_resp(struct stream *s);
167 static void devredir_proc_client_devlist_announce_req(struct stream *s);
168 static void devredir_proc_client_devlist_remove_req(struct stream *s);
169 static void devredir_proc_device_iocompletion(struct stream *s);
170 static void devredir_proc_query_dir_response(IRP *irp,
171 struct stream *s_in,
172 tui32 DeviceId,
173 tui32 CompletionId,
174 enum NTSTATUS IoStatus);
175
176 static void devredir_cvt_slash(char *path);
177 static void devredir_cvt_to_unicode(char *unicode, const char *path);
178 static void devredir_cvt_from_unicode_len(char *path, char *unicode, int len);
179 static int devredir_string_ends_with(const char *string, char c);
109180
110181 /*****************************************************************************/
111182 int
112 dev_redir_init(void)
183 devredir_init(void)
113184 {
114185 struct stream *s;
115186 int bytes;
156227
157228 /*****************************************************************************/
158229 int
159 dev_redir_deinit(void)
230 devredir_deinit(void)
160231 {
161232 scard_deinit();
162233 return 0;
163234 }
235
236 /*****************************************************************************/
237
238 /*
239 * Convert a COMPLETION_TYPE to a string
240 */
241 const char *completion_type_to_str(enum COMPLETION_TYPE cid)
242 {
243 return
244 (cid == CID_CREATE_DIR_REQ) ? "CID_CREATE_DIR_REQ" :
245 (cid == CID_DIRECTORY_CONTROL) ? "CID_DIRECTORY_CONTROL" :
246 (cid == CID_CREATE_REQ) ? "CID_CREATE_REQ" :
247 (cid == CID_OPEN_REQ) ? "CID_OPEN_REQ" :
248 (cid == CID_READ) ? "CID_READ" :
249 (cid == CID_WRITE) ? "CID_WRITE" :
250 (cid == CID_CLOSE) ? "CID_CLOSE" :
251 (cid == CID_FILE_CLOSE) ? "CID_FILE_CLOSE" :
252 (cid == CID_RMDIR_OR_FILE) ? "CID_RMDIR_OR_FILE" :
253 (cid == CID_RMDIR_OR_FILE_RESP) ? "CID_RMDIR_OR_FILE_RESP" :
254 (cid == CID_RENAME_FILE) ? "CID_RENAME_FILE" :
255 (cid == CID_RENAME_FILE_RESP) ? "CID_RENAME_FILE_RESP" :
256 (cid == CID_LOOKUP) ? "CID_LOOKUP" :
257 (cid == CID_SETATTR) ? "CID_SETATTR" :
258 /* default */ "<unknown>";
259 };
260
261 /*****************************************************************************/
262
263 /*
264 * Convert Windows permssions to Linux permissions.
265 *
266 * We can't curently support group or other permissions as separate from the
267 * owner (not that there's much point). We'll assume our caller will provide
268 * a umask if appropriate
269 */
270 static tui32
271 WindowsToLinuxFilePerm(tui32 wperm)
272 {
273 tui32 result;
274 if (wperm & W_FILE_ATTRIBUTE_DIRECTORY)
275 {
276 result = S_IFDIR | 0555; /* dirs are always readable and executable */
277 }
278 else
279 {
280 result = S_IFREG | 0444; /* files are always readable */
281 if (wperm & W_FILE_ATTRIBUTE_SYSTEM) result |= 0111; /* Executable */
282 }
283
284 if ((wperm & W_FILE_ATTRIBUTE_READONLY) == 0) result |= 0222;
285
286 return result;
287 }
288
289 /*****************************************************************************/
290 static tui32
291 LinuxToWindowsFilePerm(tui32 lperm)
292 {
293 tui32 result = 0;
294
295 /* Writeable flag is common to files and directories */
296 if ((lperm & S_IWUSR) == 0)
297 {
298 result |= W_FILE_ATTRIBUTE_READONLY;
299 }
300
301 if (lperm & S_IFDIR)
302 {
303 result |= W_FILE_ATTRIBUTE_DIRECTORY;
304 }
305 else
306 {
307 /* For normal files the system attribute is used to store the owner
308 executable bit */
309 if (lperm & S_IXUSR)
310 {
311 result |= W_FILE_ATTRIBUTE_SYSTEM;
312 }
313 if (result == 0)
314 {
315 /* See MS-FSCC section 2.6 */
316 result = W_FILE_ATTRIBUTE_NORMAL;
317 }
318 }
319
320 return result;
321 }
322
164323
165324 /**
166325 * @brief process incoming data
169328 *****************************************************************************/
170329
171330 int
172 dev_redir_data_in(struct stream *s, int chan_id, int chan_flags, int length,
173 int total_length)
331 devredir_data_in(struct stream *s, int chan_id, int chan_flags, int length,
332 int total_length)
174333 {
175334 struct stream *ls;
176335 tui16 comp_type;
240399 case RDP_CLIENT_60_61:
241400 break;
242401 }
243 // LK_TODO dev_redir_send_server_clientID_confirm();
402 // LK_TODO devredir_send_server_clientID_confirm();
244403 break;
245404
246405 case PAKID_CORE_CLIENT_NAME:
247406 /* client is telling us its computer name; do we even care? */
248407
249408 /* let client know login was successful */
250 dev_redir_send_server_user_logged_on();
409 devredir_send_server_user_logged_on();
251410 usleep(1000 * 100);
252411
253412 /* let client know our capabilities */
254 dev_redir_send_server_core_cap_req();
413 devredir_send_server_core_cap_req();
255414
256415 /* send confirm clientID */
257 dev_redir_send_server_clientID_confirm();
416 devredir_send_server_clientID_confirm();
258417 break;
259418
260419 case PAKID_CORE_CLIENT_CAPABILITY:
261 dev_redir_proc_client_core_cap_resp(ls);
420 devredir_proc_client_core_cap_resp(ls);
262421 break;
263422
264423 case PAKID_CORE_DEVICELIST_ANNOUNCE:
265424 devredir_proc_client_devlist_announce_req(ls);
266425 break;
267426
427 case PAKID_CORE_DEVICELIST_REMOVE:
428 devredir_proc_client_devlist_remove_req(ls);
429 break;
430
268431 case PAKID_CORE_DEVICE_IOCOMPLETION:
269 dev_redir_proc_device_iocompletion(ls);
432 devredir_proc_device_iocompletion(ls);
270433 break;
271434
272435 default:
287450
288451 /*****************************************************************************/
289452 int
290 dev_redir_get_wait_objs(tbus *objs, int *count, int *timeout)
453 devredir_get_wait_objs(tbus *objs, int *count, int *timeout)
291454 {
292455 if (g_is_smartcard_redir_supported)
293456 {
298461
299462 /*****************************************************************************/
300463 int
301 dev_redir_check_wait_objs(void)
464 devredir_check_wait_objs(void)
302465 {
303466 if (g_is_smartcard_redir_supported)
304467 {
311474 * @brief let client know our capabilities
312475 *****************************************************************************/
313476
314 void dev_redir_send_server_core_cap_req(void)
477 static void
478 devredir_send_server_core_cap_req(void)
315479 {
316480 struct stream *s;
317481 int bytes;
371535 xstream_free(s);
372536 }
373537
374 void dev_redir_send_server_clientID_confirm(void)
538 static void
539 devredir_send_server_clientID_confirm(void)
375540 {
376541 struct stream *s;
377542 int bytes;
392557 xstream_free(s);
393558 }
394559
395 void dev_redir_send_server_user_logged_on(void)
560 static void
561 devredir_send_server_user_logged_on(void)
396562 {
397563 struct stream *s;
398564 int bytes;
410576 xstream_free(s);
411577 }
412578
413 void devredir_send_server_device_announce_resp(tui32 device_id)
579 static void
580 devredir_send_server_device_announce_resp(tui32 device_id)
414581 {
415582 struct stream *s;
416583 int bytes;
434601 * @return 0 on success, -1 on failure
435602 *****************************************************************************/
436603
437 int dev_redir_send_drive_create_request(tui32 device_id,
438 const char *path,
439 tui32 DesiredAccess,
440 tui32 CreateOptions,
441 tui32 CreateDisposition,
442 tui32 completion_id)
604 static int
605 devredir_send_drive_create_request(tui32 device_id,
606 const char *path,
607 tui32 DesiredAccess,
608 tui32 CreateOptions,
609 tui32 FileAttributes,
610 tui32 CreateDisposition,
611 tui32 completion_id)
443612 {
444613 struct stream *s;
445614 int bytes;
446615 int len;
447
448 log_debug("DesiredAccess=0x%x CreateDisposition=0x%x CreateOptions=0x%x",
449 DesiredAccess, CreateDisposition, CreateOptions);
616 tui32 SharedAccess;
617
618 log_debug("device_id=%d path=\"%s\""
619 " DesiredAccess=0x%x CreateDisposition=0x%x"
620 " FileAttributes=0x%x CreateOptions=0x%x"
621 " CompletionId=%d",
622 device_id, path,
623 DesiredAccess, CreateDisposition,
624 FileAttributes, CreateOptions,
625 completion_id);
450626
451627 /* path in unicode needs this much space */
452628 len = ((g_mbstowcs(NULL, path, 0) * sizeof(twchar)) / 2) + 2;
453629
454630 xstream_new(s, 1024 + len);
631
632 /* FILE_SHARE_DELETE allows files to be renamed while in use
633 (in some circumstances) */
634 SharedAccess = SA_FILE_SHARE_READ | SA_FILE_SHARE_WRITE |
635 SA_FILE_SHARE_DELETE;
455636
456637 devredir_insert_DeviceIoRequest(s,
457638 device_id,
458639 0,
459640 completion_id,
460641 IRP_MJ_CREATE,
461 0);
642 IRP_MN_NONE);
462643
463644 xstream_wr_u32_le(s, DesiredAccess); /* DesiredAccess */
464645 xstream_wr_u32_le(s, 0); /* AllocationSize high unused */
465646 xstream_wr_u32_le(s, 0); /* AllocationSize low unused */
466 xstream_wr_u32_le(s, 0); /* FileAttributes */
467 xstream_wr_u32_le(s, 3); /* SharedAccess LK_TODO */
647 xstream_wr_u32_le(s, FileAttributes); /* FileAttributes */
648 xstream_wr_u32_le(s, SharedAccess); /* SharedAccess */
468649 xstream_wr_u32_le(s, CreateDisposition); /* CreateDisposition */
469650 xstream_wr_u32_le(s, CreateOptions); /* CreateOptions */
470651 xstream_wr_u32_le(s, len); /* PathLength */
480661 }
481662
482663 /**
483 * Close a request previously created by dev_redir_send_drive_create_request()
664 * Close a request previously created by devredir_send_drive_create_request()
484665 *****************************************************************************/
485666
486 int dev_redir_send_drive_close_request(tui16 Component, tui16 PacketId,
487 tui32 DeviceId,
488 tui32 FileId,
489 tui32 CompletionId,
490 tui32 MajorFunction,
491 tui32 MinorFunc,
492 int pad_len)
667 static int
668 devredir_send_drive_close_request(tui16 Component, tui16 PacketId,
669 tui32 DeviceId,
670 tui32 FileId,
671 tui32 CompletionId,
672 enum IRP_MJ MajorFunction,
673 enum IRP_MN MinorFunc,
674 int pad_len)
493675 {
494676 struct stream *s;
495677 int bytes;
519701 *
520702 *****************************************************************************/
521703 // LK_TODO Path needs to be Unicode
522 void dev_redir_send_drive_dir_request(IRP *irp, tui32 device_id,
523 tui32 InitialQuery, char *Path)
704 static void
705 devredir_send_drive_dir_request(IRP *irp, tui32 device_id,
706 tui32 InitialQuery, char *Path)
524707 {
525708 struct stream *s;
526709 int bytes;
550733 IRP_MJ_DIRECTORY_CONTROL,
551734 IRP_MN_QUERY_DIRECTORY);
552735
553 #ifdef USE_SHORT_NAMES_IN_DIR_LISTING
554 xstream_wr_u32_le(s, FileBothDirectoryInformation); /* FsInformationClass */
555 #else
556736 xstream_wr_u32_le(s, FileDirectoryInformation); /* FsInformationClass */
557 #endif
558737 xstream_wr_u8(s, InitialQuery); /* InitialQuery */
559738
560739 if (!InitialQuery)
585764 *
586765 * @param s stream containing client's response
587766 *****************************************************************************/
588 void dev_redir_proc_client_core_cap_resp(struct stream *s)
767 static void
768 devredir_proc_client_core_cap_resp(struct stream *s)
589769 {
590770 int i;
591771 tui16 num_caps;
639819 }
640820 }
641821
642 void devredir_proc_client_devlist_announce_req(struct stream *s)
822 static void
823 devredir_proc_client_devlist_announce_req(struct stream *s)
643824 {
644825 unsigned int i;
645826 int j;
719900 }
720901 }
721902
722 void
723 dev_redir_proc_device_iocompletion(struct stream *s)
724 {
725 FUSE_DATA *fuse_data = NULL;
903 static void
904 devredir_proc_client_devlist_remove_req(struct stream *s)
905 {
906 unsigned int i;
907 tui32 device_count;
908 tui32 device_id;
909
910 /* get number of devices being announced */
911 xstream_rd_u32_le(s, device_count);
912
913 log_debug("num of devices removed: %d", device_count);
914 {
915 for (i = 0; i < device_count; i++)
916 {
917 xstream_rd_u32_le(s, device_id);
918 xfuse_delete_share(device_id);
919 }
920 }
921 }
922
923 static void
924 devredir_proc_device_iocompletion(struct stream *s)
925 {
726926 IRP *irp = NULL;
727927
728928 tui32 DeviceId;
729929 tui32 CompletionId;
730 tui32 IoStatus;
930 tui32 IoStatus32;
731931 tui32 Length;
932 enum COMPLETION_TYPE comp_type;
732933
733934 xstream_rd_u32_le(s, DeviceId);
734935 xstream_rd_u32_le(s, CompletionId);
735 xstream_rd_u32_le(s, IoStatus);
736
737 log_debug("entered: IoStatus=0x%x CompletionId=%d", IoStatus, CompletionId);
936 xstream_rd_u32_le(s, IoStatus32);
937 enum NTSTATUS IoStatus = (enum NTSTATUS) IoStatus32; /* Needed by C++ */
738938
739939 if ((irp = devredir_irp_find(CompletionId)) == NULL)
740940 {
741941 log_error("IRP with completion ID %d not found", CompletionId);
742 return;
743 }
744
745 /* if callback has been set, call it */
942 }
943 else
746944 if (irp->callback)
747945 {
946 /* Callback has been set - call it */
748947 (*irp->callback)(s, irp, DeviceId, CompletionId, IoStatus);
749 goto done;
750 }
751
752 switch (irp->completion_type)
753 {
754 case CID_CREATE_DIR_REQ:
755 log_debug("got CID_CREATE_DIR_REQ");
756 if (IoStatus != NT_STATUS_SUCCESS)
948 }
949 else
950 {
951 comp_type = (enum COMPLETION_TYPE) irp->completion_type;
952 /* Log something about the IRP */
953 if (IoStatus == NT_STATUS_SUCCESS ||
954 IoStatus == NT_STATUS_NO_MORE_FILES ||
955 (IoStatus == NT_STATUS_NO_SUCH_FILE && comp_type == CID_LOOKUP))
757956 {
758 /* we were trying to create a request to enumerate a dir */
759 /* that does not exist; let FUSE know */
760 fuse_data = devredir_fuse_data_dequeue(irp);
761 if (fuse_data)
762 {
763 xfuse_devredir_cb_enum_dir_done(fuse_data->data_ptr,
764 IoStatus);
765 free(fuse_data);
766 }
767 devredir_irp_delete(irp);
768 return;
769 }
770
771 xstream_rd_u32_le(s, irp->FileId);
772 log_debug("got CID_CREATE_DIR_REQ IoStatus=0x%x FileId=%d",
773 IoStatus, irp->FileId);
774
775 dev_redir_send_drive_dir_request(irp, DeviceId, 1, irp->pathname);
776 break;
777
778 case CID_CREATE_OPEN_REQ:
779 xstream_rd_u32_le(s, irp->FileId);
780
781 log_debug("got CID_CREATE_OPEN_REQ IoStatus=0x%x FileId=%d",
782 IoStatus, irp->FileId);
783
784 fuse_data = devredir_fuse_data_dequeue(irp);
785 xfuse_devredir_cb_open_file(fuse_data->data_ptr, IoStatus,
786 DeviceId, irp->FileId);
787 if ((irp->type == S_IFDIR) || (IoStatus != NT_STATUS_SUCCESS))
788 devredir_irp_delete(irp);
789 break;
790
791 case CID_READ:
792 log_debug("got CID_READ");
793 xstream_rd_u32_le(s, Length);
794 fuse_data = devredir_fuse_data_dequeue(irp);
795
796 if (fuse_data == NULL)
797 {
798 log_error("fuse_data is NULL");
957 /* Successes or common occurrences - debug logging only */
958 log_debug("got %s", completion_type_to_str(comp_type));
799959 }
800960 else
801961 {
802 xfuse_devredir_cb_read_file(fuse_data->data_ptr, s->p, Length);
962 const char *pathname = (irp->pathname) ? irp->pathname : "<none>";
963 log_error("CompletionType = %s, IoStatus=%08x "
964 "Pathname = %s",
965 completion_type_to_str(comp_type),
966 IoStatus,
967 pathname);
968 }
969
970 switch (comp_type)
971 {
972 case CID_CREATE_DIR_REQ:
973 if (IoStatus != NT_STATUS_SUCCESS)
974 {
975 xfuse_devredir_cb_enum_dir_done(
976 (struct state_dirscan *) irp->fuse_info, IoStatus);
977 devredir_irp_delete(irp);
978 }
979 else
980 {
981 xstream_rd_u32_le(s, irp->FileId);
982 devredir_send_drive_dir_request(irp, DeviceId,
983 1, irp->pathname);
984 }
985 break;
986
987 case CID_CREATE_REQ:
988 xstream_rd_u32_le(s, irp->FileId);
989
990 xfuse_devredir_cb_create_file(
991 (struct state_create *) irp->fuse_info,
992 IoStatus, DeviceId, irp->FileId);
993 if (irp->gen.create.creating_dir || IoStatus != NT_STATUS_SUCCESS)
994 {
995 devredir_irp_delete(irp);
996 }
997 break;
998
999 case CID_OPEN_REQ:
1000 xstream_rd_u32_le(s, irp->FileId);
1001
1002 xfuse_devredir_cb_open_file((struct state_open *) irp->fuse_info,
1003 IoStatus, DeviceId, irp->FileId);
1004 if (IoStatus != NT_STATUS_SUCCESS)
1005 {
1006 devredir_irp_delete(irp);
1007 }
1008 break;
1009
1010 case CID_READ:
1011 xstream_rd_u32_le(s, Length);
1012 xfuse_devredir_cb_read_file((struct state_read *) irp->fuse_info,
1013 s->p, Length);
8031014 devredir_irp_delete(irp);
1015 break;
1016
1017 case CID_WRITE:
1018 xstream_rd_u32_le(s, Length);
1019 xfuse_devredir_cb_write_file((struct state_write *) irp->fuse_info,
1020 IoStatus,
1021 irp->gen.write.offset, Length);
1022 devredir_irp_delete(irp);
1023 break;
1024
1025 case CID_CLOSE:
1026 devredir_irp_delete(irp);
1027 break;
1028
1029 case CID_FILE_CLOSE:
1030 xfuse_devredir_cb_file_close((struct state_close *) irp->fuse_info);
1031 devredir_irp_delete(irp);
1032 break;
1033
1034 case CID_DIRECTORY_CONTROL:
1035 devredir_proc_query_dir_response(irp, s, DeviceId,
1036 CompletionId, IoStatus);
1037 break;
1038
1039 case CID_RMDIR_OR_FILE:
1040 xstream_rd_u32_le(s, irp->FileId);
1041 devredir_proc_cid_rmdir_or_file(irp, IoStatus);
1042 break;
1043
1044 case CID_RMDIR_OR_FILE_RESP:
1045 devredir_proc_cid_rmdir_or_file_resp(irp, IoStatus);
1046 break;
1047
1048 case CID_RENAME_FILE:
1049 xstream_rd_u32_le(s, irp->FileId);
1050 devredir_proc_cid_rename_file(irp, IoStatus);
1051 break;
1052
1053 case CID_RENAME_FILE_RESP:
1054 devredir_proc_cid_rename_file_resp(irp, IoStatus);
1055 break;
1056
1057 case CID_LOOKUP:
1058 devredir_proc_cid_lookup(irp, s, IoStatus);
1059 break;
1060
1061 case CID_SETATTR:
1062 devredir_proc_cid_setattr(irp, s, IoStatus);
1063 break;
1064
1065 default:
1066 log_error("got unknown CompletionID: DeviceId=0x%x "
1067 "CompletionId=0x%x IoStatus=0x%x",
1068 DeviceId, CompletionId, IoStatus);
1069 break;
8041070 }
805 break;
806
807 case CID_WRITE:
808 log_debug("got CID_WRITE");
809 xstream_rd_u32_le(s, Length);
810 fuse_data = devredir_fuse_data_dequeue(irp);
811
812 if (fuse_data == NULL)
1071 }
1072 }
1073
1074 static void
1075 devredir_proc_query_dir_response(IRP *irp,
1076 struct stream *s_in,
1077 tui32 DeviceId,
1078 tui32 CompletionId,
1079 enum NTSTATUS IoStatus)
1080 {
1081 tui32 Length;
1082 xstream_rd_u32_le(s_in, Length);
1083
1084 if (IoStatus == NT_STATUS_SUCCESS)
1085 {
1086 unsigned int i;
1087 /* process FILE_DIRECTORY_INFORMATION structures */
1088 for (i = 0 ; i < Length ; ++i)
8131089 {
814 log_error("fuse_data is NULL");
1090 char filename[256];
1091 tui64 LastAccessTime;
1092 tui64 LastWriteTime;
1093 tui64 EndOfFile;
1094 tui32 FileAttributes;
1095 tui32 FileNameLength;
1096 struct file_attr fattr;
1097
1098 xstream_seek(s_in, 4); /* NextEntryOffset */
1099 xstream_seek(s_in, 4); /* FileIndex */
1100 xstream_seek(s_in, 8); /* CreationTime */
1101 xstream_rd_u64_le(s_in, LastAccessTime);
1102 xstream_rd_u64_le(s_in, LastWriteTime);
1103 xstream_seek(s_in, 8); /* ChangeTime */
1104 xstream_rd_u64_le(s_in, EndOfFile);
1105 xstream_seek(s_in, 8); /* AllocationSize */
1106 xstream_rd_u32_le(s_in, FileAttributes);
1107 xstream_rd_u32_le(s_in, FileNameLength);
1108
1109 devredir_cvt_from_unicode_len(filename, s_in->p, FileNameLength);
1110
1111 i += 64 + FileNameLength;
1112
1113 //log_debug("LastAccessTime: 0x%llx", LastAccessTime);
1114 //log_debug("LastWriteTime: 0x%llx", LastWriteTime);
1115 //log_debug("EndOfFile: %lld", EndOfFile);
1116 //log_debug("FileAttributes: 0x%x", FileAttributes);
1117 //log_debug("FileNameLength: %d", FileNameLength);
1118 log_debug("FileName: %s", filename);
1119
1120 fattr.mode = WindowsToLinuxFilePerm(FileAttributes);
1121 fattr.size = (size_t) EndOfFile;
1122 fattr.atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
1123 fattr.mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
1124
1125 /* add this entry to xrdp file system */
1126 xfuse_devredir_cb_enum_dir_add_entry(
1127 (struct state_dirscan *) irp->fuse_info,
1128 filename, &fattr);
8151129 }
816 else
1130
1131 /* Ask for more directory entries */
1132 devredir_send_drive_dir_request(irp, DeviceId, 0, NULL);
1133 }
1134 else
1135 {
1136 if (IoStatus == NT_STATUS_NO_MORE_FILES)
8171137 {
818 xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length);
819 devredir_irp_delete(irp);
1138 IoStatus = NT_STATUS_SUCCESS;
8201139 }
821 break;
822
823 case CID_CLOSE:
824 log_debug("got CID_CLOSE");
825 log_debug("deleting irp with completion_id=%d comp_type=%d",
826 irp->CompletionId, irp->completion_type);
827 devredir_irp_delete(irp);
828 break;
829
830 case CID_FILE_CLOSE:
831 log_debug("got CID_FILE_CLOSE");
832 fuse_data = devredir_fuse_data_dequeue(irp);
833 xfuse_devredir_cb_file_close(fuse_data->data_ptr);
834 devredir_irp_delete(irp);
835 break;
836
837 case CID_DIRECTORY_CONTROL:
838 log_debug("got CID_DIRECTORY_CONTROL");
839
840 dev_redir_proc_query_dir_response(irp, s, DeviceId,
841 CompletionId, IoStatus);
842 break;
843
844 case CID_RMDIR_OR_FILE:
845 log_debug("got CID_RMDIR_OR_FILE");
846 xstream_rd_u32_le(s, irp->FileId);
847 devredir_proc_cid_rmdir_or_file(irp, IoStatus);
848 return;
849 break;
850
851 case CID_RMDIR_OR_FILE_RESP:
852 log_debug("got CID_RMDIR_OR_FILE_RESP");
853 devredir_proc_cid_rmdir_or_file_resp(irp, IoStatus);
854 break;
855
856 case CID_RENAME_FILE:
857 log_debug("got CID_RENAME_FILE");
858 xstream_rd_u32_le(s, irp->FileId);
859 devredir_proc_cid_rename_file(irp, IoStatus);
860 return;
861 break;
862
863 case CID_RENAME_FILE_RESP:
864 log_debug("got CID_RENAME_FILE_RESP");
865 devredir_proc_cid_rename_file_resp(irp, IoStatus);
866 break;
867
868 default:
869 log_error("got unknown CompletionID: DeviceId=0x%x "
870 "CompletionId=0x%x IoStatus=0x%x",
871 DeviceId, CompletionId, IoStatus);
872 break;
873 }
874
875 done:
876
877 if (fuse_data)
878 {
879 log_debug("free FUSE_DATA=%p", fuse_data);
880 free(fuse_data);
881 }
882
883 log_debug("exiting");
884 }
885
886 void
887 dev_redir_proc_query_dir_response(IRP *irp,
888 struct stream *s_in,
889 tui32 DeviceId,
890 tui32 CompletionId,
891 tui32 IoStatus)
892 {
893 FUSE_DATA *fuse_data = NULL;
894 XRDP_INODE *xinode;
895
896 tui32 Length;
897 tui64 CreationTime;
898 tui64 LastAccessTime;
899 tui64 LastWriteTime;
900 tui64 EndOfFile;
901 tui32 FileAttributes;
902 tui32 FileNameLength;
903 tui32 status;
904
905 char filename[256];
906 unsigned int i = 0;
907
908 xstream_rd_u32_le(s_in, Length);
909
910 if ((IoStatus == NT_STATUS_UNSUCCESSFUL) ||
911 (IoStatus == STATUS_NO_MORE_FILES))
912 {
913 status = (IoStatus == STATUS_NO_MORE_FILES) ? 0 : IoStatus;
914 fuse_data = devredir_fuse_data_dequeue(irp);
915 xfuse_devredir_cb_enum_dir_done(fuse_data->data_ptr, status);
1140 xfuse_devredir_cb_enum_dir_done((struct state_dirscan *)irp->fuse_info,
1141 IoStatus);
9161142 irp->completion_type = CID_CLOSE;
917 dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
918 PAKID_CORE_DEVICE_IOREQUEST,
919 DeviceId,
920 irp->FileId,
921 irp->CompletionId,
922 IRP_MJ_CLOSE, 0, 32);
923 free(fuse_data);
924 return;
925 }
926
927 /* TODO check status for errors */
928
929 /* process FILE_DIRECTORY_INFORMATION structures */
930 while (i < Length)
931 {
932 log_debug("processing FILE_DIRECTORY_INFORMATION structs");
933
934 xstream_seek(s_in, 4); /* NextEntryOffset */
935 xstream_seek(s_in, 4); /* FileIndex */
936 xstream_rd_u64_le(s_in, CreationTime);
937 xstream_rd_u64_le(s_in, LastAccessTime);
938 xstream_rd_u64_le(s_in, LastWriteTime);
939 xstream_seek(s_in, 8); /* ChangeTime */
940 xstream_rd_u64_le(s_in, EndOfFile);
941 xstream_seek(s_in, 8); /* AllocationSize */
942 xstream_rd_u32_le(s_in, FileAttributes);
943 xstream_rd_u32_le(s_in, FileNameLength);
944
945 #ifdef USE_SHORT_NAMES_IN_DIR_LISTING
946 xstream_seek(s_in, 4); /* EaSize */
947 xstream_seek(s_in, 1); /* ShortNameLength */
948 xstream_seek(s_in, 1); /* Reserved */
949 xstream_seek(s_in, 23); /* ShortName in Unicode */
950 #endif
951 devredir_cvt_from_unicode_len(filename, s_in->p, FileNameLength);
952
953 #ifdef USE_SHORT_NAMES_IN_DIR_LISTING
954 i += 70 + 23 + FileNameLength;
955 #else
956 i += 64 + FileNameLength;
957 #endif
958 //log_debug("CreationTime: 0x%llx", CreationTime);
959 //log_debug("LastAccessTime: 0x%llx", LastAccessTime);
960 //log_debug("LastWriteTime: 0x%llx", LastWriteTime);
961 //log_debug("EndOfFile: %lld", EndOfFile);
962 //log_debug("FileAttributes: 0x%x", FileAttributes);
963 #ifdef USE_SHORT_NAMES_IN_DIR_LISTING
964 //log_debug("ShortNameLength: %d", ShortNameLength);
965 #endif
966 //log_debug("FileNameLength: %d", FileNameLength);
967 log_debug("FileName: %s", filename);
968
969 xinode = g_new0(struct xrdp_inode, 1);
970 if (xinode == NULL)
971 {
972 log_error("system out of memory");
973 fuse_data = devredir_fuse_data_peek(irp);
974 xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, NULL);
975 return;
976 }
977
978 strcpy(xinode->name, filename);
979 xinode->size = (size_t) EndOfFile;
980 xinode->mode = WINDOWS_TO_LINUX_FILE_PERM(FileAttributes);
981 xinode->atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
982 xinode->mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
983 xinode->ctime = WINDOWS_TO_LINUX_TIME(CreationTime);
984
985 /* add this entry to xrdp file system */
986 fuse_data = devredir_fuse_data_peek(irp);
987 xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, xinode);
988 }
989
990 dev_redir_send_drive_dir_request(irp, DeviceId, 0, NULL);
1143 devredir_send_drive_close_request(RDPDR_CTYP_CORE,
1144 PAKID_CORE_DEVICE_IOREQUEST,
1145 DeviceId,
1146 irp->FileId,
1147 irp->CompletionId,
1148 IRP_MJ_CLOSE, IRP_MN_NONE, 32);
1149 }
9911150 }
9921151
9931152 /**
10011160 *****************************************************************************/
10021161
10031162 int
1004 dev_redir_get_dir_listing(void *fusep, tui32 device_id, const char *path)
1163 devredir_get_dir_listing(struct state_dirscan *fusep, tui32 device_id,
1164 const char *path)
10051165 {
10061166 tui32 DesiredAccess;
10071167 tui32 CreateOptions;
10081168 tui32 CreateDisposition;
1009 int rval;
1169 int rval = -1;
10101170 IRP *irp;
10111171
1012 log_debug("fusep=%p", fusep);
1013
1014 if ((irp = devredir_irp_new()) == NULL)
1015 return -1;
1016
1017 strncpy(irp->pathname, path, 255);
1018
1019 /* convert / to windows compatible \ */
1020 devredir_cvt_slash(irp->pathname);
1021
1022 irp->CompletionId = g_completion_id++;
1023 irp->completion_type = CID_CREATE_DIR_REQ;
1024 irp->DeviceId = device_id;
1025
1026 devredir_fuse_data_enqueue(irp, fusep);
1027
1028 DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
1029 CreateOptions = CO_FILE_DIRECTORY_FILE | CO_FILE_SYNCHRONOUS_IO_NONALERT;
1030 CreateDisposition = CD_FILE_OPEN;
1031
1032 rval = dev_redir_send_drive_create_request(device_id, irp->pathname,
1033 DesiredAccess, CreateOptions,
1034 CreateDisposition,
1035 irp->CompletionId);
1036
1037 log_debug("looking for device_id=%d path=%s", device_id, irp->pathname);
1038
1039 /* when we get a response to dev_redir_send_drive_create_request(), we */
1040 /* call dev_redir_send_drive_dir_request(), which needs the following */
1041 /* at the end of the path argument */
1042 if (dev_redir_string_ends_with(irp->pathname, '\\'))
1043 strcat(irp->pathname, "*");
1044 else
1045 strcat(irp->pathname, "\\*");
1046
1172 /*
1173 * We need to be able to append two additional characters to the
1174 * path after we create the IRP
1175 */
1176 if ((irp = devredir_irp_with_pathnamelen_new(strlen(path) + 2)) != NULL)
1177 {
1178 /* convert / to windows compatible \ */
1179 strcpy(irp->pathname, path);
1180 devredir_cvt_slash(irp->pathname);
1181
1182 irp->CompletionId = g_completion_id++;
1183 irp->completion_type = CID_CREATE_DIR_REQ;
1184 irp->DeviceId = device_id;
1185 irp->fuse_info = fusep;
1186
1187 DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
1188 CreateOptions = CO_FILE_DIRECTORY_FILE |
1189 CO_FILE_SYNCHRONOUS_IO_NONALERT;
1190 CreateDisposition = CD_FILE_OPEN;
1191
1192 rval = devredir_send_drive_create_request(device_id, irp->pathname,
1193 DesiredAccess, CreateOptions,
1194 0, CreateDisposition,
1195 irp->CompletionId);
1196
1197 log_debug("looking for device_id=%d path=%s", device_id, irp->pathname);
1198
1199 /* when we get a response to devredir_send_drive_create_request(), we
1200 * call devredir_send_drive_dir_request(), which needs the following
1201 * at the end of the path argument */
1202 if (devredir_string_ends_with(irp->pathname, '\\'))
1203 {
1204 strcat(irp->pathname, "*");
1205 }
1206 else
1207 {
1208 strcat(irp->pathname, "\\*");
1209 }
1210 }
10471211 return rval;
10481212 }
10491213
1214 /**
1215 * FUSE calls this function whenever it wants us to lookup a file or directory
1216 *
1217 * @param fusep opaque data struct that we just pass back to FUSE when done
1218 * @param device_id device_id of the redirected share
1219 * @param path the name of the directory containing the file
1220 * @param file the filename
1221 *
1222 * @return 0 on success, -1 on failure
1223 *****************************************************************************/
1224
10501225 int
1051 dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
1052 int mode, int type, const char *gen_buf)
1226 devredir_lookup_entry(struct state_lookup *fusep, tui32 device_id,
1227 const char *path)
10531228 {
10541229 tui32 DesiredAccess;
10551230 tui32 CreateOptions;
10561231 tui32 CreateDisposition;
1057 int rval;
1232 int rval = -1;
10581233 IRP *irp;
10591234
1060 log_debug("device_id=%d path=%s mode=0x%x", device_id, path, mode);
1061
1062 if ((irp = devredir_irp_new()) == NULL)
1063 return -1;
1064
1065 if (type & OP_RENAME_FILE)
1066 {
1067 irp->completion_type = CID_RENAME_FILE;
1068 strncpy(irp->gen_buf, gen_buf, 1023);
1069 }
1070 else
1071 {
1072 irp->completion_type = CID_CREATE_OPEN_REQ;
1073 }
1074
1075 irp->CompletionId = g_completion_id++;
1076 irp->DeviceId = device_id;
1077
1078 strncpy(irp->pathname, path, 255);
1079 devredir_fuse_data_enqueue(irp, fusep);
1080
1081 if (mode & O_CREAT)
1082 {
1083 log_debug("open file in O_CREAT");
1235 log_debug("fusep=%p", fusep);
1236
1237 if ((irp = devredir_irp_with_pathname_new(path)) != NULL)
1238 {
1239 /* convert / to windows compatible \ */
1240 devredir_cvt_slash(irp->pathname);
1241
1242 /*
1243 * Allocate an IRP to open the file, read the basic attributes,
1244 * read the standard attributes, and then close the file
1245 */
1246 irp->CompletionId = g_completion_id++;
1247 irp->completion_type = CID_LOOKUP;
1248 irp->DeviceId = device_id;
1249 irp->gen.lookup.state = E_LOOKUP_GET_FH;
1250 irp->fuse_info = fusep;
1251
1252 DesiredAccess = DA_FILE_READ_ATTRIBUTES | DA_SYNCHRONIZE;
1253 CreateOptions = 0;
1254 CreateDisposition = CD_FILE_OPEN;
1255
1256 log_debug("lookup for device_id=%d path=%s CompletionId=%d",
1257 device_id, irp->pathname, irp->CompletionId);
1258
1259 rval = devredir_send_drive_create_request(device_id,
1260 irp->pathname,
1261 DesiredAccess, CreateOptions,
1262 0, CreateDisposition,
1263 irp->CompletionId);
1264 }
1265
1266 return rval;
1267 }
1268
1269 /**
1270 * FUSE calls this function whenever it wants us to set the attributes for
1271 * a file or directory.
1272 *
1273 * @param fusep opaque data struct that we just pass back to FUSE when done
1274 * @param device_id device_id of the redirected share
1275 * @param filename the name of the file
1276 * @param fattr the file attributes to set for the file
1277 * @param to_set Which bits of the file attributes have changed
1278 *
1279 * @return 0 on success, -1 on failure
1280 *****************************************************************************/
1281 int
1282 devredir_setattr_for_entry(struct state_setattr *fusep, tui32 device_id,
1283 const char *filename,
1284 const struct file_attr *fattr,
1285 tui32 to_set)
1286 {
1287 tui32 DesiredAccess;
1288 tui32 CreateOptions;
1289 tui32 CreateDisposition;
1290 int rval = -1;
1291 IRP *irp;
1292
1293 log_debug("fusep=%p", fusep);
1294
1295 if ((irp = devredir_irp_with_pathname_new(filename)) != NULL)
1296 {
1297 /* convert / to windows compatible \ */
1298 devredir_cvt_slash(irp->pathname);
1299
1300 /*
1301 * Allocate an IRP to open the file, update the attributes
1302 * and close the file.
1303 */
1304 irp->CompletionId = g_completion_id++;
1305 irp->completion_type = CID_SETATTR;
1306 irp->DeviceId = device_id;
1307 irp->fuse_info = fusep;
1308
1309 irp->gen.setattr.state = E_SETATTR_GET_FH;
1310 irp->gen.setattr.to_set = to_set;
1311 irp->gen.setattr.fattr = *fattr;
1312
1313 /*
1314 * Don't set DA_FILE_WRITE_DATA unless we're changing the
1315 * EndOfFile pointer. Otherwise we can't change the attributes
1316 * of read-only files! */
1317 DesiredAccess = DA_FILE_WRITE_ATTRIBUTES;
1318 if (to_set & TO_SET_SIZE)
1319 {
1320 DesiredAccess |= DA_FILE_WRITE_DATA;
1321 }
1322 CreateOptions = 0;
1323 CreateDisposition = CD_FILE_OPEN;
1324
1325 log_debug("lookup for device_id=%d path=%s",
1326 device_id, irp->pathname);
1327
1328 rval = devredir_send_drive_create_request(device_id,
1329 irp->pathname,
1330 DesiredAccess, CreateOptions,
1331 0, CreateDisposition,
1332 irp->CompletionId);
1333 }
1334
1335 return rval;
1336 }
1337
1338 int
1339 devredir_file_create(struct state_create *fusep, tui32 device_id,
1340 const char *path, int mode)
1341 {
1342 tui32 DesiredAccess;
1343 tui32 CreateOptions;
1344 tui32 FileAttributes = 0;
1345 tui32 CreateDisposition;
1346 int rval = -1;
1347 IRP *irp;
1348
1349 log_debug("device_id=%d path=%s mode=0%o", device_id, path, mode);
1350
1351 if ((irp = devredir_irp_with_pathname_new(path)) != NULL)
1352 {
1353 /* convert / to windows compatible \ */
1354 devredir_cvt_slash(irp->pathname);
1355
1356 irp->completion_type = CID_CREATE_REQ;
1357 irp->CompletionId = g_completion_id++;
1358 irp->DeviceId = device_id;
1359 irp->fuse_info = fusep;
1360
10841361 DesiredAccess = 0x0016019f; /* got this value from windows */
1085
1086 if (type & S_IFDIR)
1362 FileAttributes = LinuxToWindowsFilePerm(mode);
1363 if (mode & S_IFDIR)
10871364 {
10881365 log_debug("creating dir");
10891366 CreateOptions = CO_FILE_DIRECTORY_FILE | CO_FILE_SYNCHRONOUS_IO_NONALERT;
1090 irp->type = S_IFDIR;
1367 irp->gen.create.creating_dir = 1;
10911368 }
10921369 else
10931370 {
10941371 log_debug("creating file");
10951372 CreateOptions = 0x44; /* got this value from windows */
1373 irp->gen.create.creating_dir = 0;
10961374 }
10971375
10981376 //CreateDisposition = CD_FILE_CREATE;
10991377 CreateDisposition = 0x02; /* got this value from windows */
1100 }
1101 else
1102 {
1103 log_debug("open file in O_RDWR");
1104 #if 1
1105 /* without the 0x00000010 rdesktop opens files in */
1106 /* O_RDONLY instead of O_RDWR mode */
1107 if (mode & O_RDWR)
1108 DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010;
1109 else
1110 DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
1378
1379 rval = devredir_send_drive_create_request(device_id, path,
1380 DesiredAccess, CreateOptions,
1381 FileAttributes,
1382 CreateDisposition,
1383 irp->CompletionId);
1384 }
1385
1386 return rval;
1387 }
1388
1389 int
1390 devredir_file_open(struct state_open *fusep, tui32 device_id,
1391 const char *path, int flags)
1392 {
1393 tui32 DesiredAccess;
1394 tui32 CreateOptions;
1395 tui32 FileAttributes = 0;
1396 tui32 CreateDisposition;
1397 int rval = -1;
1398 IRP *irp;
1399
1400 log_debug("device_id=%d path=%s flags=0%x",
1401 device_id, path, flags);
1402
1403 if ((irp = devredir_irp_with_pathname_new(path)) != NULL)
1404 {
1405 /* convert / to windows compatible \ */
1406 devredir_cvt_slash(irp->pathname);
1407
1408 irp->completion_type = CID_OPEN_REQ;
1409 irp->CompletionId = g_completion_id++;
1410 irp->DeviceId = device_id;
1411
1412 irp->fuse_info = fusep;
1413
1414 switch(flags & O_ACCMODE)
1415 {
1416 case O_RDONLY:
1417 log_debug("open file in O_RDONLY");
1418 DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
1419 break;
1420
1421 case O_WRONLY:
1422 log_debug("open file in O_WRONLY");
1423 DesiredAccess = DA_FILE_WRITE_DATA | DA_SYNCHRONIZE;
1424 break;
1425
1426 default:
1427 /*
1428 * The access mode could conceivably be invalid here,
1429 * but we assume this has been checked by the caller
1430 */
1431 log_debug("open file in O_RDWR");
1432 /* without the 0x00000010 rdesktop opens files in */
1433 /* O_RDONLY instead of O_RDWR mode */
1434 DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA |
1435 DA_SYNCHRONIZE | 0x00000010;
1436 }
11111437
11121438 CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT;
11131439 CreateDisposition = CD_FILE_OPEN; // WAS 1
1114 #else
1115 /* got this value from windows; the 0x00000010 was added by LK; */
1116 /* without this rdesktop opens files in O_RDONLY instead of */
1117 /* O_RDWR mode */
1118 DesiredAccess = 0x00120089 | 0x00000010;
1119 CreateOptions = 0x20060;
1120 CreateDisposition = 0x01;
1121 #endif
1122 }
1123
1124 rval = dev_redir_send_drive_create_request(device_id, path,
1125 DesiredAccess, CreateOptions,
1126 CreateDisposition,
1127 irp->CompletionId);
1440
1441 rval = devredir_send_drive_create_request(device_id, path,
1442 DesiredAccess, CreateOptions,
1443 FileAttributes,
1444 CreateDisposition,
1445 irp->CompletionId);
1446 }
11281447
11291448 return rval;
11301449 }
11311450
1132 int devredir_file_close(void *fusep, tui32 device_id, tui32 FileId)
1451 int devredir_file_close(struct state_close *fusep, tui32 device_id,
1452 tui32 FileId)
11331453 {
11341454 IRP *irp;
11351455
11501470 #endif
11511471 irp->completion_type = CID_FILE_CLOSE;
11521472 irp->DeviceId = device_id;
1153 devredir_fuse_data_enqueue(irp, fusep);
1154
1155 return dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
1156 PAKID_CORE_DEVICE_IOREQUEST,
1157 device_id,
1158 FileId,
1159 irp->CompletionId,
1160 IRP_MJ_CLOSE,
1161 0, 32);
1473 irp->fuse_info = fusep;
1474
1475 return devredir_send_drive_close_request(RDPDR_CTYP_CORE,
1476 PAKID_CORE_DEVICE_IOREQUEST,
1477 device_id,
1478 FileId,
1479 irp->CompletionId,
1480 IRP_MJ_CLOSE,
1481 IRP_MN_NONE, 32);
11621482 }
11631483
11641484 /**
11661486 *****************************************************************************/
11671487
11681488 int
1169 devredir_rmdir_or_file(void *fusep, tui32 device_id, const char *path, int mode)
1489 devredir_rmdir_or_file(struct state_remove *fusep, tui32 device_id,
1490 const char *path)
11701491 {
11711492 tui32 DesiredAccess;
11721493 tui32 CreateOptions;
11731494 tui32 CreateDisposition;
1174 int rval;
1495 int rval = -1;
11751496 IRP *irp;
11761497
1177 if ((irp = devredir_irp_new()) == NULL)
1178 return -1;
1179
1180 irp->CompletionId = g_completion_id++;
1181 irp->completion_type = CID_RMDIR_OR_FILE;
1182 irp->DeviceId = device_id;
1183
1184 strncpy(irp->pathname, path, 255);
1185 devredir_fuse_data_enqueue(irp, fusep);
1186
1187 //DesiredAccess = DA_DELETE | DA_FILE_READ_ATTRIBUTES | DA_SYNCHRONIZE;
1188 DesiredAccess = 0x00100080; /* got this value from windows */
1189
1190 //CreateOptions = CO_FILE_DELETE_ON_CLOSE | CO_FILE_DIRECTORY_FILE |
1191 // CO_FILE_SYNCHRONOUS_IO_NONALERT;
1192 CreateOptions = 0x020; /* got this value from windows */
1193
1194 //CreateDisposition = CD_FILE_OPEN; // WAS 1
1195 CreateDisposition = 0x01; /* got this value from windows */
1196
1197 rval = dev_redir_send_drive_create_request(device_id, path,
1198 DesiredAccess, CreateOptions,
1199 CreateDisposition,
1200 irp->CompletionId);
1498 if ((irp = devredir_irp_with_pathname_new(path)) != NULL)
1499 {
1500 /* convert / to windows compatible \ */
1501 devredir_cvt_slash(irp->pathname);
1502
1503 irp->CompletionId = g_completion_id++;
1504 irp->completion_type = CID_RMDIR_OR_FILE;
1505 irp->DeviceId = device_id;
1506
1507 irp->fuse_info = fusep;
1508
1509 //DesiredAccess = DA_DELETE | DA_FILE_READ_ATTRIBUTES | DA_SYNCHRONIZE;
1510 DesiredAccess = 0x00100080; /* got this value from windows */
1511
1512 //CreateOptions = CO_FILE_DELETE_ON_CLOSE | CO_FILE_DIRECTORY_FILE |
1513 // CO_FILE_SYNCHRONOUS_IO_NONALERT;
1514 CreateOptions = 0x020; /* got this value from windows */
1515
1516 //CreateDisposition = CD_FILE_OPEN; // WAS 1
1517 CreateDisposition = 0x01; /* got this value from windows */
1518
1519 rval = devredir_send_drive_create_request(device_id, path,
1520 DesiredAccess, CreateOptions,
1521 0, CreateDisposition,
1522 irp->CompletionId);
1523 }
12011524
12021525 return rval;
12031526 }
12091532 *****************************************************************************/
12101533
12111534 int
1212 devredir_file_read(void *fusep, tui32 DeviceId, tui32 FileId,
1535 devredir_file_read(struct state_read *fusep, tui32 DeviceId, tui32 FileId,
12131536 tui32 Length, tui64 Offset)
12141537 {
12151538 struct stream *s;
12161539 IRP *irp;
12171540 IRP *new_irp;
12181541 int bytes;
1542 int rval = -1;
12191543
12201544 xstream_new(s, 1024);
12211545
1546 /* Check we've got an open IRP for this file already */
12221547 if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
12231548 {
12241549 log_error("no IRP found with FileId = %d", FileId);
12251550 xfuse_devredir_cb_read_file(fusep, NULL, 0);
12261551 xstream_free(s);
1227 return -1;
1228 }
1229
1552 }
12301553 /* create a new IRP for this request */
1231 if ((new_irp = devredir_irp_clone(irp)) == NULL)
1554 else if ((new_irp = devredir_irp_new()) == NULL)
12321555 {
12331556 /* system out of memory */
12341557 xfuse_devredir_cb_read_file(fusep, NULL, 0);
12351558 xstream_free(s);
1236 return -1;
1237 }
1238 new_irp->FileId = 0;
1239 new_irp->completion_type = CID_READ;
1240 new_irp->CompletionId = g_completion_id++;
1241 devredir_fuse_data_enqueue(new_irp, fusep);
1242
1243 devredir_insert_DeviceIoRequest(s,
1244 DeviceId,
1245 FileId,
1246 new_irp->CompletionId,
1247 IRP_MJ_READ,
1248 0);
1249
1250 xstream_wr_u32_le(s, Length);
1251 xstream_wr_u64_le(s, Offset);
1252 xstream_seek(s, 20);
1253
1254 /* send to client */
1255 bytes = xstream_len(s);
1256 send_channel_data(g_rdpdr_chan_id, s->data, bytes);
1257 xstream_free(s);
1258
1259 return 0;
1559 }
1560 else
1561 {
1562 new_irp->DeviceId = DeviceId;
1563 new_irp->FileId = FileId;
1564 new_irp->completion_type = CID_READ;
1565 new_irp->CompletionId = g_completion_id++;
1566 new_irp->fuse_info = fusep;
1567
1568 devredir_insert_DeviceIoRequest(s,
1569 DeviceId,
1570 FileId,
1571 new_irp->CompletionId,
1572 IRP_MJ_READ,
1573 IRP_MN_NONE);
1574
1575 xstream_wr_u32_le(s, Length);
1576 xstream_wr_u64_le(s, Offset);
1577 xstream_seek(s, 20);
1578
1579 /* send to client */
1580 bytes = xstream_len(s);
1581 send_channel_data(g_rdpdr_chan_id, s->data, bytes);
1582 xstream_free(s);
1583 rval = 0;
1584 }
1585
1586 return rval;
12601587 }
12611588
12621589 int
1263 dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
1264 const char *buf, int Length, tui64 Offset)
1590 devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId,
1591 const char *buf, int Length, tui64 Offset)
12651592 {
12661593 struct stream *s;
12671594 IRP *irp;
12681595 IRP *new_irp;
12691596 int bytes;
1597 int rval = -1;
12701598
12711599 log_debug("DeviceId=%d FileId=%d Length=%d Offset=%lld",
12721600 DeviceId, FileId, Length, (long long)Offset);
12761604 if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
12771605 {
12781606 log_error("no IRP found with FileId = %d", FileId);
1279 xfuse_devredir_cb_write_file(fusep, NULL, 0);
1607 xfuse_devredir_cb_write_file(fusep, NT_STATUS_UNSUCCESSFUL, 0, 0);
12801608 xstream_free(s);
1281 return -1;
1282 }
1283
1609 }
12841610 /* create a new IRP for this request */
1285 if ((new_irp = devredir_irp_clone(irp)) == NULL)
1611 else if ((new_irp = devredir_irp_new()) == NULL)
12861612 {
12871613 /* system out of memory */
1288 xfuse_devredir_cb_write_file(fusep, NULL, 0);
1614 xfuse_devredir_cb_write_file(fusep, NT_STATUS_UNSUCCESSFUL, 0, 0);
12891615 xstream_free(s);
1290 return -1;
1291 }
1292 new_irp->FileId = 0;
1293 new_irp->completion_type = CID_WRITE;
1294 new_irp->CompletionId = g_completion_id++;
1295 devredir_fuse_data_enqueue(new_irp, fusep);
1296
1297 devredir_insert_DeviceIoRequest(s,
1298 DeviceId,
1299 FileId,
1300 new_irp->CompletionId,
1301 IRP_MJ_WRITE,
1302 0);
1303
1304 xstream_wr_u32_le(s, Length);
1305 xstream_wr_u64_le(s, Offset);
1306 xstream_seek(s, 20); /* padding */
1307
1308 /* now insert real data */
1309 xstream_copyin(s, buf, Length);
1310
1311 /* send to client */
1312 bytes = xstream_len(s);
1313 send_channel_data(g_rdpdr_chan_id, s->data, bytes);
1314 xstream_free(s);
1315
1316 return 0;
1317 }
1318
1319 /******************************************************************************
1320 ** FIFO for FUSE_DATA **
1321 ******************************************************************************/
1322
1323 /**
1324 * Return FUSE_DATA at the head of the queue without removing it
1325 *
1326 * @return FUSE_DATA on success, or NULL on failure
1327 *****************************************************************************/
1328
1329 FUSE_DATA *
1330 devredir_fuse_data_peek(IRP *irp)
1331 {
1332 log_debug("returning %p", irp->fd_head);
1333 return irp->fd_head;
1334 }
1335
1336 /**
1337 * Return oldest FUSE_DATA from queue
1338 *
1339 * @return FUSE_DATA on success, NULL on failure
1340 *****************************************************************************/
1341
1342 FUSE_DATA *
1343 devredir_fuse_data_dequeue(IRP *irp)
1344 {
1345 FUSE_DATA *head;
1346
1347 if ((irp == NULL) || (irp->fd_head == NULL))
1348 {
1349 log_debug("+++ returning NULL");
1350 return NULL;
1351 }
1352
1353 if (irp->fd_head->next == NULL)
1354 {
1355 /* only one element in queue */
1356 head = irp->fd_head;
1357 irp->fd_head = NULL;
1358 irp->fd_tail = NULL;
1359 log_debug("+++ returning FUSE_DATA=%p containing FUSE_INFO=%p",
1360 head, head->data_ptr);
1361 return head;
1362 }
1363
1364 /* more than one element in queue */
1365 head = irp->fd_head;
1366 irp->fd_head = head->next;
1367 log_debug("+++ returning FUSE_DATA=%p containing FUSE_INFO=%p",
1368 head, head->data_ptr);
1369 return head;
1370 }
1371
1372 /**
1373 * Insert specified FUSE_DATA at the end of our queue
1374 *
1375 * @return 0 on success, -1 on failure
1376 *****************************************************************************/
1377
1378 int
1379 devredir_fuse_data_enqueue(IRP *irp, void *vp)
1380 {
1381 FUSE_DATA *fd;
1382 FUSE_DATA *tail;
1383
1384 if (irp == NULL)
1385 return -1;
1386
1387 fd = g_new0(FUSE_DATA, 1);
1388 if (fd == NULL)
1389 return -1;
1390
1391 fd->data_ptr = vp;
1392 fd->next = NULL;
1393
1394 if (irp->fd_tail == NULL)
1395 {
1396 /* queue is empty, insert at head */
1397 irp->fd_head = fd;
1398 irp->fd_tail = fd;
1399 log_debug("+++ inserted FUSE_DATA=%p containing FUSE_INFO=%p at head",
1400 fd, vp);
1401 return 0;
1402 }
1403
1404 /* queue is not empty, insert at tail end */
1405 tail = irp->fd_tail;
1406 tail->next = fd;
1407 irp->fd_tail = fd;
1408 log_debug("+++ inserted FUSE_DATA=%p containing FUSE_INFO=%p at tail",
1409 fd, vp);
1410 return 0;
1411 }
1616 }
1617 else
1618 {
1619 new_irp->DeviceId = DeviceId;
1620 new_irp->FileId = FileId;
1621 new_irp->completion_type = CID_WRITE;
1622 new_irp->CompletionId = g_completion_id++;
1623 new_irp->fuse_info = fusep;
1624 /* Offset needed after write to calculate new EOF */
1625 new_irp->gen.write.offset = Offset;
1626
1627 devredir_insert_DeviceIoRequest(s,
1628 DeviceId,
1629 FileId,
1630 new_irp->CompletionId,
1631 IRP_MJ_WRITE,
1632 IRP_MN_NONE);
1633
1634 xstream_wr_u32_le(s, Length);
1635 xstream_wr_u64_le(s, Offset);
1636 xstream_seek(s, 20); /* padding */
1637
1638 /* now insert real data */
1639 xstream_copyin(s, buf, Length);
1640
1641 /* send to client */
1642 bytes = xstream_len(s);
1643 send_channel_data(g_rdpdr_chan_id, s->data, bytes);
1644 xstream_free(s);
1645 rval = 0;
1646 }
1647
1648 return rval;
1649 }
1650
1651
1652 int devredir_file_rename(struct state_rename *fusep, tui32 device_id,
1653 const char *old_name,
1654 const char *new_name)
1655 {
1656 tui32 DesiredAccess;
1657 tui32 CreateOptions;
1658 tui32 FileAttributes = 0;
1659 tui32 CreateDisposition;
1660 int rval = -1;
1661 IRP *irp;
1662 unsigned int len;
1663
1664 log_debug("device_id=%d old_name=%s new_name=%s",
1665 device_id, old_name, new_name);
1666
1667 /*
1668 * Allocate an IRP with enough space for both the old and new names.
1669 * We'll store the new name after the old name:-
1670 *
1671 * | n | a | m | e | 1 | \0 | n | a | m | e | 2 | \0 |
1672 * ^ ^
1673 * irp->pathname ----+ |
1674 * irp->gen.rename.new_name ------------------+
1675 */
1676 len = strlen(old_name) + 1 + strlen(new_name);
1677 if ((irp = devredir_irp_with_pathnamelen_new(len)) != NULL)
1678 {
1679 /* Set up pointer to new name string */
1680 irp->gen.rename.new_name = irp->pathname + strlen(old_name) + 1;
1681
1682 /* Copy both strings, and change'/' to '\\' characters */
1683 strcpy(irp->pathname, old_name);
1684 devredir_cvt_slash(irp->pathname);
1685 strcpy(irp->gen.rename.new_name, new_name);
1686 devredir_cvt_slash(irp->gen.rename.new_name);
1687
1688 irp->completion_type = CID_RENAME_FILE;
1689 irp->CompletionId = g_completion_id++;
1690 irp->DeviceId = device_id;
1691
1692 irp->fuse_info = fusep;
1693
1694 DesiredAccess = DA_FILE_WRITE_ATTRIBUTES | DA_DELETE;
1695 CreateOptions = 0;
1696 CreateDisposition = CD_FILE_OPEN; // WAS 1
1697
1698 rval = devredir_send_drive_create_request(device_id, old_name,
1699 DesiredAccess, CreateOptions,
1700 FileAttributes,
1701 CreateDisposition,
1702 irp->CompletionId);
1703 }
1704
1705 return rval;
1706 }
1707
14121708
14131709 /******************************************************************************
14141710 ** miscellaneous stuff **
14191715 tui32 DeviceId,
14201716 tui32 FileId,
14211717 tui32 CompletionId,
1422 tui32 MajorFunction,
1423 tui32 MinorFunction)
1718 enum IRP_MJ MajorFunction,
1719 enum IRP_MN MinorFunction)
14241720 {
14251721 /* setup DR_DEVICE_IOREQUEST header */
14261722 xstream_wr_u16_le(s, RDPDR_CTYP_CORE);
14361732 * Convert / to windows compatible \
14371733 *****************************************************************************/
14381734
1439 void
1735 static void
14401736 devredir_cvt_slash(char *path)
14411737 {
14421738 char *cptr = path;
14491745 }
14501746 }
14511747
1452 void
1748 static void
14531749 devredir_cvt_to_unicode(char *unicode, const char *path)
14541750 {
14551751 char *dest;
14751771 *dest++ = 0;
14761772 }
14771773
1478 void
1774 static void
14791775 devredir_cvt_from_unicode_len(char *path, char *unicode, int len)
14801776 {
14811777 char *dest;
15121808 g_free(dest_saved);
15131809 }
15141810
1515 int
1516 dev_redir_string_ends_with(char *string, char c)
1517 {
1518 int len;
1811 static int
1812 devredir_string_ends_with(const char *string, char c)
1813 {
1814 size_t len;
15191815
15201816 len = strlen(string);
1521 return (string[len - 1] == c) ? 1 : 0;
1522 }
1523
1524 void
1525 devredir_insert_RDPDR_header(struct stream *s, tui16 Component,
1526 tui16 PacketId)
1527 {
1528 xstream_wr_u16_le(s, Component);
1529 xstream_wr_u16_le(s, PacketId);
1530 }
1531
1532 void
1533 devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus)
1817 return (len > 0 && string[len - 1] == c) ? 1 : 0;
1818 }
1819
1820 static void
1821 devredir_proc_cid_rmdir_or_file(IRP *irp, enum NTSTATUS IoStatus)
15341822 {
15351823 struct stream *s;
15361824 int bytes;
15371825
15381826 if (IoStatus != NT_STATUS_SUCCESS)
15391827 {
1540 FUSE_DATA *fuse_data = devredir_fuse_data_dequeue(irp);
1541 if (fuse_data)
1542 {
1543 xfuse_devredir_cb_rmdir_or_file(fuse_data->data_ptr, IoStatus);
1544 free(fuse_data);
1545 }
1828 xfuse_devredir_cb_rmdir_or_file((struct state_remove *) irp->fuse_info,
1829 IoStatus);
15461830 devredir_irp_delete(irp);
15471831 return;
15481832 }
15521836 irp->completion_type = CID_RMDIR_OR_FILE_RESP;
15531837 devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
15541838 irp->CompletionId,
1555 IRP_MJ_SET_INFORMATION, 0);
1839 IRP_MJ_SET_INFORMATION, IRP_MN_NONE);
15561840
15571841 xstream_wr_u32_le(s, FileDispositionInformation);
15581842 xstream_wr_u32_le(s, 0); /* length is zero */
15661850 return;
15671851 }
15681852
1569 void
1570 devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus)
1571 {
1572 FUSE_DATA *fuse_data;
1573
1574 fuse_data = devredir_fuse_data_dequeue(irp);
1575 if (fuse_data)
1576 {
1577 xfuse_devredir_cb_rmdir_or_file(fuse_data->data_ptr, IoStatus);
1578 free(fuse_data);
1579 }
1853 static void
1854 devredir_proc_cid_rmdir_or_file_resp(IRP *irp, enum NTSTATUS IoStatus)
1855 {
1856 xfuse_devredir_cb_rmdir_or_file((struct state_remove *)irp->fuse_info,
1857 IoStatus);
15801858
15811859 if (IoStatus != NT_STATUS_SUCCESS)
15821860 {
15851863 }
15861864
15871865 irp->completion_type = CID_CLOSE;
1588 dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
1589 PAKID_CORE_DEVICE_IOREQUEST,
1590 irp->DeviceId,
1591 irp->FileId,
1592 irp->CompletionId,
1593 IRP_MJ_CLOSE, 0, 32);
1594 }
1595
1596 void
1597 devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
1866 devredir_send_drive_close_request(RDPDR_CTYP_CORE,
1867 PAKID_CORE_DEVICE_IOREQUEST,
1868 irp->DeviceId,
1869 irp->FileId,
1870 irp->CompletionId,
1871 IRP_MJ_CLOSE, IRP_MN_NONE, 32);
1872 }
1873
1874 static void
1875 devredir_proc_cid_rename_file(IRP *irp, enum NTSTATUS IoStatus)
15981876 {
15991877 struct stream *s;
16001878 int bytes;
16061884 {
16071885 log_debug("rename returned with IoStatus=0x%x", IoStatus);
16081886
1609 FUSE_DATA *fuse_data = devredir_fuse_data_dequeue(irp);
1610 if (fuse_data)
1611 {
1612 xfuse_devredir_cb_rename_file(fuse_data->data_ptr, IoStatus);
1613 free(fuse_data);
1614 }
1887 xfuse_devredir_cb_rename_file((struct state_rename *)irp->fuse_info,
1888 IoStatus);
16151889 devredir_irp_delete(irp);
16161890 return;
16171891 }
16181892
16191893 /* Path in unicode needs this much space */
1620 flen = ((g_mbstowcs(NULL, irp->gen_buf, 0) * sizeof(twchar)) / 2) + 2;
1894 flen = ((g_mbstowcs(NULL, irp->gen.rename.new_name, 0)
1895 * sizeof(twchar)) / 2) + 2;
16211896 sblen = 6 + flen;
16221897
16231898 xstream_new(s, 1024 + flen);
16251900 irp->completion_type = CID_RENAME_FILE_RESP;
16261901 devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
16271902 irp->CompletionId,
1628 IRP_MJ_SET_INFORMATION, 0);
1903 IRP_MJ_SET_INFORMATION, IRP_MN_NONE);
16291904
16301905 xstream_wr_u32_le(s, FileRenameInformation);
16311906 xstream_wr_u32_le(s, sblen); /* number of bytes after padding */
16351910 xstream_wr_u32_le(s, flen); /* FileNameLength */
16361911
16371912 /* filename in unicode */
1638 devredir_cvt_to_unicode(s->p, irp->gen_buf); /* UNICODE_TODO */
1913 devredir_cvt_to_unicode(s->p, irp->gen.rename.new_name); /* UNICODE_TODO */
16391914 xstream_seek(s, flen);
16401915
16411916 /* send to client */
16461921 return;
16471922 }
16481923
1649 void
1650 devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus)
1651 {
1652 FUSE_DATA *fuse_data;
1653
1924 static void
1925 devredir_proc_cid_rename_file_resp(IRP *irp, enum NTSTATUS IoStatus)
1926 {
16541927 log_debug("entered");
16551928
1656 fuse_data = devredir_fuse_data_dequeue(irp);
1657 if (fuse_data)
1658 {
1659 xfuse_devredir_cb_rename_file(fuse_data->data_ptr, IoStatus);
1660 free(fuse_data);
1661 }
1929 xfuse_devredir_cb_rename_file((struct state_rename *)irp->fuse_info,
1930 IoStatus);
16621931
16631932 if (IoStatus != NT_STATUS_SUCCESS)
16641933 {
16671936 }
16681937
16691938 irp->completion_type = CID_CLOSE;
1670 dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
1939 devredir_send_drive_close_request(RDPDR_CTYP_CORE,
16711940 PAKID_CORE_DEVICE_IOREQUEST,
16721941 irp->DeviceId,
16731942 irp->FileId,
16741943 irp->CompletionId,
1675 IRP_MJ_CLOSE, 0, 32);
1676 }
1944 IRP_MJ_CLOSE, IRP_MN_NONE, 32);
1945 }
1946
1947
1948 /*
1949 * Re-uses the specified IRP to issue a request to get file attributes
1950 * of varying types
1951 *
1952 * References : [MS-RDPEFS] 2.2.3.3.9 [MS-FSCC] 2.4
1953 *****************************************************************************/
1954 static void issue_lookup(IRP *irp, int lookup_type)
1955 {
1956 struct stream *s;
1957 int bytes;
1958
1959 bytes =
1960 lookup_type == FileBasicInformation ? FILE_BASIC_INFORMATION_SIZE :
1961 lookup_type == FileStandardInformation ? FILE_STD_INFORMATION_SIZE :
1962 0;
1963 xstream_new(s, 1024);
1964 devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
1965 irp->CompletionId,
1966 IRP_MJ_QUERY_INFORMATION, IRP_MN_NONE);
1967
1968 xstream_wr_u32_le(s, lookup_type);
1969 xstream_wr_u32_le(s, bytes); /* buffer length */
1970 xstream_seek(s, 24); /* padding */
1971 xstream_seek(s, bytes); /* buffer */
1972
1973 /* send to client */
1974 bytes = xstream_len(s);
1975 send_channel_data(g_rdpdr_chan_id, s->data, bytes);
1976 xstream_free(s);
1977 }
1978
1979 /*
1980 * Parses an incoming FileBasicInformation structure
1981 *****************************************************************************/
1982 static void lookup_read_basic_attributes(IRP *irp, struct stream *s_in)
1983 {
1984 tui64 LastAccessTime;
1985 tui64 LastWriteTime;
1986 tui32 FileAttributes;
1987
1988 log_debug("processing FILE_BASIC_INFORMATION");
1989
1990 xstream_seek(s_in, 8); /* CreationTime */
1991 xstream_rd_u64_le(s_in, LastAccessTime);
1992 xstream_rd_u64_le(s_in, LastWriteTime);
1993 xstream_seek(s_in, 8); /* ChangeTime */
1994 xstream_rd_u32_le(s_in, FileAttributes);
1995
1996 //log_debug("LastAccessTime: 0x%llx",
1997 // (unsigned long long)LastAccessTime);
1998 //log_debug("LastWriteTime: 0x%llx",
1999 // (unsigned long long)LastWriteTime);
2000 //log_debug("ChangeTime: 0x%llx",
2001 // (unsigned long long)ChangeTime);
2002 //log_debug("FileAttributes: 0x%x", (unsigned int)FileAttributes);
2003
2004 /* Save the basic attributes in the IRP */
2005 irp->gen.lookup.fattr.mode = WindowsToLinuxFilePerm(FileAttributes);
2006 irp->gen.lookup.fattr.atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
2007 irp->gen.lookup.fattr.mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
2008 }
2009
2010 /*
2011 * Parses an incoming FileStandardInformation structure
2012 *****************************************************************************/
2013 static void lookup_read_standard_attributes(IRP *irp, struct stream *s_in)
2014 {
2015 tui64 EndOfFile;
2016 log_debug("processing FILE_STD_INFORMATION");
2017 xstream_seek(s_in, 8); /* AllocationSize */
2018 xstream_rd_u64_le(s_in, EndOfFile);
2019 //log_debug("EndOfFile: %lld",
2020 // (unsigned long long)EndOfFile);
2021
2022 irp->gen.lookup.fattr.size = EndOfFile;
2023 }
2024
2025 /*
2026 * Completes a lookup request and returns status to the caller.
2027 *
2028 * Unless IoStatus is NT_STATUS_SUCCESS, the lookup has failed.
2029 *****************************************************************************/
2030 static void lookup_done(IRP *irp, enum NTSTATUS IoStatus)
2031 {
2032 log_debug("Lookup with completion_id=%d returning 0x%x",
2033 irp->CompletionId, IoStatus);
2034 xfuse_devredir_cb_lookup_entry((struct state_lookup *)irp->fuse_info,
2035 IoStatus,
2036 &irp->gen.lookup.fattr);
2037
2038 if (irp->FileId == 0)
2039 {
2040 /* Open failed - no file handle */
2041 devredir_irp_delete(irp);
2042 }
2043 else
2044 {
2045 /* Close the file handle */
2046 irp->completion_type = CID_CLOSE;
2047 devredir_send_drive_close_request(RDPDR_CTYP_CORE,
2048 PAKID_CORE_DEVICE_IOREQUEST,
2049 irp->DeviceId,
2050 irp->FileId,
2051 irp->CompletionId,
2052 IRP_MJ_CLOSE, IRP_MN_NONE, 32);
2053 }
2054 }
2055
2056
2057 /*
2058 * lookup has a mini state machine built-in, as it needs to issue
2059 * multiple I/O requests, but unlike lookup these are not always the same.
2060 */
2061 static void
2062 devredir_proc_cid_lookup(IRP *irp,
2063 struct stream *s_in,
2064 enum NTSTATUS IoStatus)
2065 {
2066 tui32 Length;
2067
2068 log_debug("entry state is %d",irp->gen.lookup.state);
2069 if (IoStatus != NT_STATUS_SUCCESS)
2070 {
2071 /* This is common to all setattr states */
2072 log_debug("last lookup returned with IoStatus=0x%08x", IoStatus);
2073 lookup_done(irp, IoStatus);
2074 }
2075 else
2076 {
2077 /* Read and validate any data we've got queued up */
2078 switch(irp->gen.lookup.state)
2079 {
2080 case E_LOOKUP_GET_FH:
2081 /* We've been sent the file ID */
2082 xstream_rd_u32_le(s_in, irp->FileId);
2083 issue_lookup(irp, FileBasicInformation);
2084 irp->gen.lookup.state = E_LOOKUP_CHECK_BASIC;
2085 break;
2086
2087 case E_LOOKUP_CHECK_BASIC:
2088 /* Returned length what we expected? */
2089 xstream_rd_u32_le(s_in, Length);
2090 if (Length != FILE_BASIC_INFORMATION_SIZE)
2091 {
2092 log_error("Expected FILE_BASIC_INFORMATION length"
2093 "%d, got len=%d",
2094 FILE_BASIC_INFORMATION_SIZE, Length);
2095 IoStatus = NT_STATUS_UNSUCCESSFUL;
2096 lookup_done(irp, IoStatus);
2097 }
2098 else
2099 {
2100 lookup_read_basic_attributes(irp, s_in);
2101 issue_lookup(irp, FileStandardInformation);
2102 irp->gen.lookup.state = E_LOOKUP_CHECK_EOF;
2103 }
2104 break;
2105
2106 case E_LOOKUP_CHECK_EOF:
2107 /* Returned length what we expected? */
2108 xstream_rd_u32_le(s_in, Length);
2109 if (Length != FILE_STD_INFORMATION_SIZE)
2110 {
2111 log_error("Expected FILE_STD_INFORMATION length"
2112 "%d, got len=%d",
2113 FILE_STD_INFORMATION_SIZE, Length);
2114 IoStatus = NT_STATUS_UNSUCCESSFUL;
2115 }
2116 else
2117 {
2118 lookup_read_standard_attributes(irp, s_in);
2119 }
2120 lookup_done(irp, IoStatus);
2121 break;
2122 }
2123 }
2124 }
2125
2126
2127 /*
2128 * Re-uses the specified IRP to issue a request to set basic file attributes
2129 *
2130 * References : [MS-RDPEFS] 2.2.3.3.9 [MS-FSCC] 2.4.7
2131 *****************************************************************************/
2132 static void issue_setattr_basic(IRP *irp)
2133 {
2134 struct stream *s;
2135 int bytes;
2136 const struct file_attr *fattr = &irp->gen.setattr.fattr;
2137 tui32 to_set = irp->gen.setattr.to_set;
2138
2139 tui32 FileAttributes = 0;
2140 tui64 atime = 0;
2141 tui64 mtime = 0;
2142
2143 if (to_set & TO_SET_MODE)
2144 {
2145 FileAttributes = LinuxToWindowsFilePerm(fattr->mode);
2146 }
2147 if (to_set & TO_SET_ATIME)
2148 {
2149 atime = LINUX_TO_WINDOWS_TIME(fattr->atime);
2150 }
2151 if (to_set & TO_SET_MTIME)
2152 {
2153 mtime = LINUX_TO_WINDOWS_TIME(fattr->mtime);
2154 }
2155
2156 xstream_new(s, 1024);
2157 devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
2158 irp->CompletionId,
2159 IRP_MJ_SET_INFORMATION, IRP_MN_NONE);
2160
2161 xstream_wr_u32_le(s, FileBasicInformation);
2162 xstream_wr_u32_le(s, FILE_BASIC_INFORMATION_SIZE);
2163 /* buffer length */
2164 xstream_seek(s, 24); /* padding */
2165
2166 xstream_wr_u64_le(s, 0LL); /* CreationTime */
2167 xstream_wr_u64_le(s, atime); /* LastAccessTime */
2168 xstream_wr_u64_le(s, mtime); /* LastWriteTime */
2169 xstream_wr_u64_le(s, 0LL); /* ChangeTime */
2170 xstream_wr_u32_le(s, FileAttributes); /* FileAttributes */
2171
2172 /* send to client */
2173 bytes = xstream_len(s);
2174 send_channel_data(g_rdpdr_chan_id, s->data, bytes);
2175 xstream_free(s);
2176 }
2177
2178
2179 /*
2180 * Re-uses the specified IRP to issue a request to set file EOF
2181 *
2182 * References : [MS-RDPEFS] 2.2.3.3.9 [MS-FSCC] 2.4.13
2183 *****************************************************************************/
2184 static void issue_setattr_eof(IRP *irp)
2185 {
2186 struct stream *s;
2187 int bytes;
2188
2189 xstream_new(s, 1024);
2190 devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
2191 irp->CompletionId,
2192 IRP_MJ_SET_INFORMATION, IRP_MN_NONE);
2193
2194 xstream_wr_u32_le(s, FileEndOfFileInformation);
2195 xstream_wr_u32_le(s, FILE_END_OF_FILE_INFORMATION_SIZE);
2196 /* buffer length */
2197 xstream_seek(s, 24); /* padding */
2198 xstream_wr_u64_le(s, (tui64)irp->gen.setattr.fattr.size);
2199 /* File size */
2200 /* send to client */
2201 bytes = xstream_len(s);
2202 send_channel_data(g_rdpdr_chan_id, s->data, bytes);
2203 xstream_free(s);
2204 }
2205
2206 /*
2207 * Completes a setattr request and returns status to the caller.
2208 *****************************************************************************/
2209 static void setattr_done(IRP *irp, enum NTSTATUS IoStatus)
2210 {
2211 xfuse_devredir_cb_setattr((struct state_setattr *) irp->fuse_info,
2212 IoStatus);
2213
2214 if (irp->FileId == 0)
2215 {
2216 /* Open failed - no file handle */
2217 devredir_irp_delete(irp);
2218 }
2219 else
2220 {
2221 /* Close the file handle */
2222 irp->completion_type = CID_CLOSE;
2223 devredir_send_drive_close_request(RDPDR_CTYP_CORE,
2224 PAKID_CORE_DEVICE_IOREQUEST,
2225 irp->DeviceId,
2226 irp->FileId,
2227 irp->CompletionId,
2228 IRP_MJ_CLOSE, IRP_MN_NONE, 32);
2229 }
2230 }
2231
2232
2233 /*
2234 * setattr has a mini state machine built-in, as it needs to issue
2235 * multiple I/O requests, but unlike lookup these are not always the same.
2236 */
2237 static void
2238 devredir_proc_cid_setattr(IRP *irp,
2239 struct stream *s_in,
2240 enum NTSTATUS IoStatus)
2241 {
2242 #define TO_SET_BASIC_ATTRS (TO_SET_MODE | \
2243 TO_SET_ATIME | TO_SET_MTIME)
2244 tui32 Length;
2245
2246 log_debug("entry state is %d",irp->gen.setattr.state);
2247 if (IoStatus != NT_STATUS_SUCCESS)
2248 {
2249 /* This is common to all setattr states */
2250 log_debug("last setattr returned with IoStatus=0x%08x", IoStatus);
2251 setattr_done(irp, IoStatus);
2252 }
2253 else
2254 {
2255 /* Read and validate any data we've got queued up */
2256 switch(irp->gen.setattr.state)
2257 {
2258 case E_SETATTR_GET_FH:
2259 /* We've been sent the file ID */
2260 xstream_rd_u32_le(s_in, irp->FileId);
2261 break;
2262
2263 case E_SETATTR_CHECK_BASIC:
2264 /* Returned length what we expected? */
2265 xstream_rd_u32_le(s_in, Length);
2266 if (Length != FILE_BASIC_INFORMATION_SIZE)
2267 {
2268 log_error("Expected FILE_BASIC_INFORMATION length"
2269 "%d, got len=%d",
2270 FILE_BASIC_INFORMATION_SIZE, Length);
2271 }
2272
2273 /* Clear the basic bits so we don't end up in here again */
2274 irp->gen.setattr.to_set &= ~TO_SET_BASIC_ATTRS;
2275 break;
2276
2277 case E_SETATTR_CHECK_EOF:
2278 /* Returned length what we expected? */
2279 xstream_rd_u32_le(s_in, Length);
2280 if (Length != FILE_END_OF_FILE_INFORMATION_SIZE)
2281 {
2282 log_error("Expected FILE_END_OF_FILE_INFORMATION length"
2283 "%d, got len=%d",
2284 FILE_END_OF_FILE_INFORMATION_SIZE, Length);
2285 }
2286
2287 /* Clear the size bits so we don't end up in here again */
2288 irp->gen.setattr.to_set &= ~TO_SET_SIZE;
2289 break;
2290 }
2291
2292 /* Work out the next call to issue */
2293 if (irp->gen.setattr.to_set & TO_SET_BASIC_ATTRS)
2294 {
2295 issue_setattr_basic(irp);
2296 irp->gen.setattr.state = E_SETATTR_CHECK_BASIC;
2297 }
2298 else if (irp->gen.setattr.to_set & TO_SET_SIZE)
2299 {
2300 issue_setattr_eof(irp);
2301 irp->gen.setattr.state = E_SETATTR_CHECK_EOF;
2302 }
2303 else
2304 {
2305 setattr_done(irp, IoStatus);
2306 }
2307 }
2308 #undef TO_SET_BASIC_ATTRS
2309 }
1717 * limitations under the License.
1818 */
1919
20 // LK_TODO dev_redir_xxx should become devredir_xxx
21
2220 #if !defined(DEVREDIR_H)
2321 #define DEVREDIR_H
2422
2523 #include "irp.h"
24 #include "ms-rdpefs.h"
2625
27 #define USE_SHORT_NAMES_IN_DIR_LISTING
26 int devredir_init(void);
27 int devredir_deinit(void);
2828
29 FUSE_DATA *devredir_fuse_data_peek(IRP *irp);
30 FUSE_DATA *devredir_fuse_data_dequeue(IRP *irp);
31 int devredir_fuse_data_enqueue(IRP *irp, void *vp);
29 int devredir_data_in(struct stream* s, int chan_id, int chan_flags,
30 int length, int total_length);
3231
33 int dev_redir_init(void);
34 int dev_redir_deinit(void);
35
36 int dev_redir_data_in(struct stream* s, int chan_id, int chan_flags,
37 int length, int total_length);
38
39 int dev_redir_get_wait_objs(tbus* objs, int* count, int* timeout);
40 int dev_redir_check_wait_objs(void);
41
42 void dev_redir_send_server_core_cap_req(void);
43 void dev_redir_send_server_clientID_confirm(void);
44 void dev_redir_send_server_user_logged_on(void);
45 void devredir_send_server_device_announce_resp(tui32 device_id);
46
47 void dev_redir_send_drive_dir_request(IRP *irp, tui32 device_id,
48 tui32 InitialQuery, char *Path);
49
50 int dev_redir_send_drive_create_request(tui32 device_id,
51 const char *path,
52 tui32 DesiredAccess,
53 tui32 CreateOptions,
54 tui32 CreateDisposition,
55 tui32 completion_id);
56
57 int dev_redir_send_drive_close_request(tui16 Component, tui16 PacketId,
58 tui32 DeviceId,
59 tui32 FileId,
60 tui32 CompletionId,
61 tui32 MajorFunction,
62 tui32 MinorFunc,
63 int pad_len);
64
65 void devredir_proc_client_devlist_announce_req(struct stream *s);
66 void dev_redir_proc_client_core_cap_resp(struct stream *s);
67 void dev_redir_proc_device_iocompletion(struct stream *s);
68
69 void dev_redir_proc_query_dir_response(IRP *irp,
70 struct stream *s,
71 tui32 DeviceId,
72 tui32 CompletionId,
73 tui32 IoStatus);
32 int devredir_get_wait_objs(tbus* objs, int* count, int* timeout);
33 int devredir_check_wait_objs(void);
7434
7535 /* misc stuff */
7636 void devredir_insert_DeviceIoRequest(struct stream *s,
7737 tui32 DeviceId,
7838 tui32 FileId,
7939 tui32 CompletionId,
80 tui32 MajorFunction,
81 tui32 MinorFunction);
40 enum IRP_MJ MajorFunction,
41 enum IRP_MN MinorFunction);
8242
83 void devredir_cvt_slash(char *path);
84 void devredir_cvt_to_unicode(char *unicode, const char *path);
85 void devredir_cvt_from_unicode_len(char *path, char *unicode, int len);
86 int dev_redir_string_ends_with(char *string, char c);
87
88 void devredir_insert_RDPDR_header(struct stream *s, tui16 Component,
89 tui16 PacketId);
90
91 void devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus);
92 void devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus);
93 void devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus);
94 void devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus);
43 /* State pointer types (opaque outside this module), used for
44 * callback data
45 */
46 struct state_dirscan;
47 struct state_lookup;
48 struct state_setattr;
49 struct state_open;
50 struct state_create;
51 struct state_read;
52 struct state_write;
53 struct state_remove;
54 struct state_close;
9555
9656 /* called from FUSE module */
97 int dev_redir_get_dir_listing(void *fusep, tui32 device_id, const char *path);
9857
99 int dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
100 int mode, int type, const char *gen_buf);
58 int devredir_get_dir_listing(struct state_dirscan *fusep, tui32 device_id,
59 const char *path);
10160
102 int devredir_file_close(void *fusep, tui32 device_id, tui32 file_id);
61 int devredir_lookup_entry(struct state_lookup *fusep, tui32 device_id,
62 const char *path);
10363
104 int devredir_file_read(void *fusep, tui32 device_id, tui32 FileId,
64 int devredir_setattr_for_entry(
65 struct state_setattr *fusep, tui32 device_id,
66 const char *filename,
67 const struct file_attr *fattr,
68 tui32 to_set);
69
70 int devredir_file_create(
71 struct state_create *fusep, tui32 device_id,
72 const char *path, int mode);
73
74 int devredir_file_open(struct state_open *fusep, tui32 device_id,
75 const char *path, int flags);
76
77 int devredir_file_close(struct state_close *fusep, tui32 device_id,
78 tui32 file_id);
79
80 int devredir_file_read(struct state_read *fusep, tui32 device_id, tui32 FileId,
10581 tui32 Length, tui64 Offset);
10682
10783 int
108 dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
84 devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId,
10985 const char *buf, int Length, tui64 Offset);
11086
87 int devredir_file_rename(
88 struct state_rename *fusep, tui32 device_id,
89 const char *old_name,
90 const char *new_name);
91
11192 int
112 devredir_rmdir_or_file(void *fusep, tui32 device_id, const char *path, int mode);
113
114 /*
115 * RDPDR_HEADER definitions
116 */
117
118 /* device redirector core component; most of the packets in this protocol */
119 /* are sent under this component ID */
120 #define RDPDR_CTYP_CORE 0x4472
121
122 /* printing component. the packets that use this ID are typically about */
123 /* printer cache management and identifying XPS printers */
124 #define RDPDR_CTYP_PRN 0x5052
125
126 /* Server Announce Request, as specified in section 2.2.2.2 */
127 #define PAKID_CORE_SERVER_ANNOUNCE 0x496E
128
129 /* Client Announce Reply and Server Client ID Confirm, as specified in */
130 /* sections 2.2.2.3 and 2.2.2.6. */
131 #define PAKID_CORE_CLIENTID_CONFIRM 0x4343
132
133 /* Client Name Request, as specified in section 2.2.2.4 */
134 #define PAKID_CORE_CLIENT_NAME 0x434E
135
136 /* Client Device List Announce Request, as specified in section 2.2.2.9 */
137 #define PAKID_CORE_DEVICELIST_ANNOUNCE 0x4441
138
139 /* Server Device Announce Response, as specified in section 2.2.2.1 */
140 #define PAKID_CORE_DEVICE_REPLY 0x6472
141
142 /* Device I/O Request, as specified in section 2.2.1.4 */
143 #define PAKID_CORE_DEVICE_IOREQUEST 0x4952
144
145 /* Device I/O Response, as specified in section 2.2.1.5 */
146 #define PAKID_CORE_DEVICE_IOCOMPLETION 0x4943
147
148 /* Server Core Capability Request, as specified in section 2.2.2.7 */
149 #define PAKID_CORE_SERVER_CAPABILITY 0x5350
150
151 /* Client Core Capability Response, as specified in section 2.2.2.8 */
152 #define PAKID_CORE_CLIENT_CAPABILITY 0x4350
153
154 /* Client Drive Device List Remove, as specified in section 2.2.3.2 */
155 #define PAKID_CORE_DEVICELIST_REMOVE 0x444D
156
157 /* Add Printer Cachedata, as specified in [MS-RDPEPC] section 2.2.2.3 */
158 #define PAKID_PRN_CACHE_DATA 0x5043
159
160 /* Server User Logged On, as specified in section 2.2.2.5 */
161 #define PAKID_CORE_USER_LOGGEDON 0x554C
162
163 /* Server Printer Set XPS Mode, as specified in [MS-RDPEPC] section 2.2.2.2 */
164 #define PAKID_PRN_USING_XPS 0x5543
165
166 /*
167 * Capability header definitions
168 */
169
170 #define CAP_GENERAL_TYPE 0x0001 /* General cap set - GENERAL_CAPS_SET */
171 #define CAP_PRINTER_TYPE 0x0002 /* Print cap set - PRINTER_CAPS_SET */
172 #define CAP_PORT_TYPE 0x0003 /* Port cap set - PORT_CAPS_SET */
173 #define CAP_DRIVE_TYPE 0x0004 /* Drive cap set - DRIVE_CAPS_SET */
174 #define CAP_SMARTCARD_TYPE 0x0005 /* Smart card cap set - SMARTCARD_CAPS_SET */
175
176 /* client minor versions */
177 #define RDP_CLIENT_50 0x0002
178 #define RDP_CLIENT_51 0x0005
179 #define RDP_CLIENT_52 0x000a
180 #define RDP_CLIENT_60_61 0x000c
181
182 /* used in device announce list */
183 #define RDPDR_DTYP_SERIAL 0x0001
184 #define RDPDR_DTYP_PARALLEL 0x0002
185 #define RDPDR_DTYP_PRINT 0x0004
186 #define RDPDR_DTYP_FILESYSTEM 0x0008
187 #define RDPDR_DTYP_SMARTCARD 0x0020
188
189 /*
190 * DesiredAccess Mask [MS-SMB2] section 2.2.13.1.1
191 */
192
193 #define DA_FILE_READ_DATA 0x00000001
194 #define DA_FILE_WRITE_DATA 0x00000002
195 #define DA_FILE_APPEND_DATA 0x00000004
196 #define DA_FILE_READ_EA 0x00000008 /* rd extended attributes */
197 #define DA_FILE_WRITE_EA 0x00000010 /* wr extended attributes */
198 #define DA_FILE_EXECUTE 0x00000020
199 #define DA_FILE_READ_ATTRIBUTES 0x00000080
200 #define DA_FILE_WRITE_ATTRIBUTES 0x00000100
201 #define DA_DELETE 0x00010000
202 #define DA_READ_CONTROL 0x00020000 /* rd security descriptor */
203 #define DA_WRITE_DAC 0x00040000
204 #define DA_WRITE_OWNER 0x00080000
205 #define DA_SYNCHRONIZE 0x00100000
206 #define DA_ACCESS_SYSTEM_SECURITY 0x01000000
207 #define DA_MAXIMUM_ALLOWED 0x02000000
208 #define DA_GENERIC_ALL 0x10000000
209 #define DA_GENERIC_EXECUTE 0x20000000
210 #define DA_GENERIC_WRITE 0x40000000
211 #define DA_GENERIC_READ 0x80000000
212
213 /*
214 * CreateOptions Mask [MS-SMB2] section 2.2.13 SMB2 CREATE Request
215 */
216
217 enum CREATE_OPTIONS
218 {
219 CO_FILE_DIRECTORY_FILE = 0x00000001,
220 CO_FILE_WRITE_THROUGH = 0x00000002,
221 CO_FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020,
222 CO_FILE_DELETE_ON_CLOSE = 0x00001000
223 };
224
225 /*
226 * CreateDispositions Mask [MS-SMB2] section 2.2.13
227 */
228
229 #define CD_FILE_SUPERSEDE 0x00000000
230 #define CD_FILE_OPEN 0x00000001
231 #define CD_FILE_CREATE 0x00000002
232 #define CD_FILE_OPEN_IF 0x00000003
233 #define CD_FILE_OVERWRITE 0x00000004
234 #define CD_FILE_OVERWRITE_IF 0x00000005
235
236 /*
237 * Device I/O Request MajorFunction definitions
238 */
239
240 #define IRP_MJ_CREATE 0x00000000
241 #define IRP_MJ_CLOSE 0x00000002
242 #define IRP_MJ_READ 0x00000003
243 #define IRP_MJ_WRITE 0x00000004
244 #define IRP_MJ_DEVICE_CONTROL 0x0000000E
245 #define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0000000A
246 #define IRP_MJ_SET_VOLUME_INFORMATION 0x0000000B
247 #define IRP_MJ_QUERY_INFORMATION 0x00000005
248 #define IRP_MJ_SET_INFORMATION 0x00000006
249 #define IRP_MJ_DIRECTORY_CONTROL 0x0000000C
250 #define IRP_MJ_LOCK_CONTROL 0x00000011
251
252 /*
253 * Device I/O Request MinorFunction definitions
254 *
255 * Only valid when MajorFunction code = IRP_MJ_DIRECTORY_CONTROL
256 */
257
258 #define IRP_MN_QUERY_DIRECTORY 0x00000001
259 #define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x00000002
260
261 /*
262 * NTSTATUS codes (used by IoStatus)
263 */
264
265 #define NT_STATUS_SUCCESS 0x00000000
266 #define NT_STATUS_UNSUCCESSFUL 0xC0000001
267
268 /*
269 * File system ioctl codes
270 * MS-FSCC section 2.3 FSCTL Structures
271 */
272 #define FSCTL_DELETE_OBJECT_ID 0x900a0
273
274
275 /*
276 * CompletionID types, used in IRPs to indicate I/O operation
277 */
278
279 enum COMPLETION_ID
280 {
281 CID_CREATE_DIR_REQ = 1,
282 CID_DIRECTORY_CONTROL,
283 CID_CREATE_OPEN_REQ,
284 CID_READ,
285 CID_WRITE,
286 CID_CLOSE,
287 CID_FILE_CLOSE,
288 CID_RMDIR_OR_FILE,
289 CID_RMDIR_OR_FILE_RESP,
290 CID_RENAME_FILE,
291 CID_RENAME_FILE_RESP
292 };
293
294 enum FS_INFORMATION_CLASS
295 {
296 FileBasicInformation = 0x00000004, /* set atime, mtime, ctime etc */
297 FileEndOfFileInformation = 0x00000014, /* set EOF info */
298 FileDispositionInformation = 0x0000000D, /* mark a file for deletion */
299 FileRenameInformation = 0x0000000A, /* rename a file */
300 FileAllocationInformation = 0x00000013 /* set file allocation size */
301 };
302
303 /*
304 * constants for drive dir query
305 */
306
307 /* Basic information about a file or directory. Basic information is */
308 /* defined as the file's name, time stamp, and size, or its attributes */
309 #define FileDirectoryInformation 0x00000001
310
311 /* Full information about a file or directory. Full information is defined */
312 /* as all the basic information, plus extended attribute size. */
313 #define FileFullDirectoryInformation 0x00000002
314
315 /* Basic information plus extended attribute size and short name */
316 /* about a file or directory. */
317 #define FileBothDirectoryInformation 0x00000003
318
319 /* Detailed information on the names of files in a directory. */
320 #define FileNamesInformation 0x0000000C
321
322 /*
323 * NTSTATUS Codes of interest to us
324 */
325
326 /* No more files were found which match the file specification */
327 #define STATUS_NO_MORE_FILES 0x80000006
328
329 /* Windows file attributes */
330 #define W_FILE_ATTRIBUTE_DIRECTORY 0x00000010
331 #define W_FILE_ATTRIBUTE_READONLY 0x00000001
332
333 #define WINDOWS_TO_LINUX_FILE_PERM(_a) \
334 (((_a) & W_FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR | 0100 : S_IFREG) |\
335 (((_a) & W_FILE_ATTRIBUTE_READONLY) ? 0444 : 0644)
336
337 /* Windows time starts on Jan 1, 1601 */
338 /* Linux time starts on Jan 1, 1970 */
339 #define EPOCH_DIFF 11644473600LL
340 #define WINDOWS_TO_LINUX_TIME(_t) ((_t) / 10000000) - EPOCH_DIFF;
341
342 #define OP_RENAME_FILE 0x01
93 devredir_rmdir_or_file(struct state_remove *fusep, tui32 device_id,
94 const char *path);
34395
34496 #endif
104104 }
105105
106106 /**
107 * Clone specified IRP
107 * Create a new IRP with a copied pathname, and append to linked list.
108 *
109 * Allocation is made in such a way that the IRP can be freed with a single
110 * free() operation
108111 *
109112 * @return new IRP or NULL on error
110113 *****************************************************************************/
111114
112 IRP * devredir_irp_clone(IRP *irp)
113 {
114 IRP *new_irp;
115 IRP *prev;
116 IRP *next;
117
118 if ((new_irp = devredir_irp_new()) == NULL)
115 IRP * devredir_irp_with_pathname_new(const char *pathname)
116 {
117 unsigned int len = g_strlen(pathname);
118 IRP * irp = devredir_irp_with_pathnamelen_new(len);
119 if (irp != NULL)
120 {
121 g_strcpy(irp->pathname, pathname);
122 }
123
124 return irp;
125 }
126
127 /**
128 * Create a new IRP with space allocated for a pathname, and append to
129 * linked list.
130 *
131 * Allocation is made in such a way that the IRP can be freed with a single
132 * free() operation
133 *
134 * @return new IRP or NULL on error
135 *****************************************************************************/
136
137 IRP * devredir_irp_with_pathnamelen_new(unsigned int pathnamelen)
138 {
139 IRP *irp;
140 IRP *irp_last;
141
142 log_debug("entered");
143
144 /* create new IRP with space on end for the pathname and a terminator */
145 irp = (IRP *)g_malloc(sizeof(IRP) + (pathnamelen + 1), 1);
146 if (irp == NULL)
147 {
148 log_error("system out of memory!");
119149 return NULL;
120
121 /* save link pointers */
122 prev = new_irp->prev;
123 next = new_irp->next;
124
125 /* copy all members */
126 g_memcpy(new_irp, irp, sizeof(IRP));
127
128 /* restore link pointers */
129 new_irp->prev = prev;
130 new_irp->next = next;
131
132 return new_irp;
150 }
151
152 irp->pathname = (char *)irp + sizeof(IRP); /* Initialise pathname pointer */
153
154 /* insert at end of linked list */
155 if ((irp_last = devredir_irp_get_last()) == NULL)
156 {
157 /* list is empty, this is the first entry */
158 g_irp_head = irp;
159 }
160 else
161 {
162 irp_last->next = irp;
163 irp->prev = irp_last;
164 }
165
166 log_debug("new IRP=%p", irp);
167 return irp;
133168 }
134169
135170 /**
2323 #ifndef __IRP_H
2424 #define __IRP_H
2525
26 typedef struct fuse_data FUSE_DATA;
27 struct fuse_data
26 #ifndef _TIME_H_
27 #include <time.h>
28 #endif
29 #include "chansrv_fuse.h"
30
31 /* Opaque data types to us */
32 typedef struct xfuse_info XFUSE_INFO;
33
34 enum irp_lookup_state
2835 {
29 void *data_ptr;
30 FUSE_DATA *next;
36 E_LOOKUP_GET_FH = 0,
37 E_LOOKUP_CHECK_BASIC,
38 E_LOOKUP_CHECK_EOF
39 } ;
40
41 enum irp_setattr_state
42 {
43 E_SETATTR_GET_FH = 0,
44 E_SETATTR_CHECK_BASIC,
45 E_SETATTR_CHECK_EOF
46 } ;
47
48 struct irp_lookup
49 {
50 enum irp_lookup_state state; /* Next state to consider */
51 struct file_attr fattr; /* Attributes to get */
52 };
53
54 struct irp_setattr
55 {
56 enum irp_setattr_state state; /* Next state to consider */
57 tui32 to_set; /* Bit mask for elements in use */
58 struct file_attr fattr; /* Attributes to set */
59 };
60
61 struct irp_write
62 {
63 tui64 offset; /* Offset the write was made at */
64 };
65
66 struct irp_create
67 {
68 int creating_dir; /* We're creating a directory */
69 };
70
71 struct irp_rename
72 {
73 char *new_name; /* New name for file */
3174 };
3275
3376 /* An I/O Resource Packet to track I/O calls */
4083 tui32 DeviceId; /* identifies remote device */
4184 tui32 FileId; /* RDP client provided unique number */
4285 char completion_type; /* describes I/O type */
43 char pathname[256]; /* absolute pathname */
44 char gen_buf[1024]; /* for general use */
45 int type;
46 FUSE_DATA *fd_head; /* point to first FUSE opaque object */
47 FUSE_DATA *fd_tail; /* point to last FUSE opaque object */
86 char *pathname; /* absolute pathname
87 * Allocate with
88 * devredir_irp_with_pathname_new() */
89 union
90 {
91 struct irp_lookup lookup; /* Used by lookup */
92 struct irp_setattr setattr; /* Used by setattr */
93 struct irp_write write; /* Used by write */
94 struct irp_create create; /* Used by create */
95 struct irp_rename rename; /* Use by rename */
96 } gen; /* Additional state data for some ops */
97 void *fuse_info; /* Fuse info pointer for FUSE calls */
4898 IRP *next; /* point to next IRP */
4999 IRP *prev; /* point to previous IRP */
50100 int scard_index; /* used to smart card to locate dev */
55105 };
56106
57107 IRP * devredir_irp_new(void);
58 IRP * devredir_irp_clone(IRP *irp);
108 /* As above, but allocates sufficent space for the specified
109 * pathname, and copies it in to the pathname field */
110 IRP * devredir_irp_with_pathname_new(const char *pathname);
111 /* As above, but specifies a pathname length with pathname
112 * initially set to "". Use if you need to modify the pathname
113 * significantly */
114 IRP * devredir_irp_with_pathnamelen_new(unsigned int pathnamelen);
59115 int devredir_irp_delete(IRP *irp);
60116 IRP * devredir_irp_find(tui32 completion_id);
61117 IRP * devredir_irp_find_by_fileid(tui32 FileId);
0 /**
1 * xrdp: A Remote Desktop Protocol server.
2 *
3 * MS-ERREF : Definitions from [MS-ERREF]
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * References to MS-ERREF are currently correct for v20180912 of that
18 * document
19 */
20
21 #if !defined(MS_ERREF_H)
22 #define MS_ERREF_H
23
24 /*
25 * NTSTATUS codes (section 2.3)
26 */
27 enum NTSTATUS
28 {
29 NT_STATUS_SUCCESS = 0x00000000,
30 NT_STATUS_UNSUCCESSFUL = 0xC0000001,
31 NT_STATUS_NO_SUCH_FILE = 0xC000000F,
32 NT_STATUS_ACCESS_DENIED = 0xC0000022,
33 NT_STATUS_OBJECT_NAME_INVALID = 0xC0000033,
34 NT_STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034,
35 NT_STATUS_SHARING_VIOLATION = 0xC0000043,
36 NT_STATUS_NO_MORE_FILES = 0x80000006
37 };
38
39 #endif /* MS_ERREF_H */
40
41
42
43
0 /**
1 * xrdp: A Remote Desktop Protocol server.
2 *
3 * MS-FSCC : Definitions from [MS-FSCC]
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * References to MS-FSCC are currently correct for v20190923 of that
18 * document
19 */
20
21 #if !defined(MS_FSCC_H)
22 #define MS_FSCC_H
23
24 /*
25 * File system ioctl codes (section 2.3)
26 */
27 #define FSCTL_DELETE_OBJECT_ID 0x900a0
28
29 /*
30 * File information classes (section 2.4)
31 */
32 enum FS_INFORMATION_CLASS
33 {
34 FileAllocationInformation = 19, /* Set */
35 FileBasicInformation = 4, /* Query, Set */
36 FileBothDirectoryInformation = 3, /* Query */
37 FileDirectoryInformation = 1, /* Query */
38 FileDispositionInformation = 13, /* Set */
39 FileEndOfFileInformation = 20, /* Set */
40 FileFullDirectoryInformation = 2, /* Query */
41 FileNamesInformation = 12, /* Query */
42 FileRenameInformation = 10, /* Set */
43 FileStandardInformation = 5 /* Query */
44 };
45
46 /*
47 * Size of structs above without trailing RESERVED fields (MS-RDPEFS
48 * 2.2.3.3.8)
49 */
50 #define FILE_BASIC_INFORMATION_SIZE 36
51 #define FILE_STD_INFORMATION_SIZE 22
52 #define FILE_END_OF_FILE_INFORMATION_SIZE 8
53
54 /* Windows file attributes (section 2.6) */
55 #define W_FILE_ATTRIBUTE_DIRECTORY 0x00000010
56 #define W_FILE_ATTRIBUTE_READONLY 0x00000001
57 #define W_FILE_ATTRIBUTE_SYSTEM 0x00000004
58 #define W_FILE_ATTRIBUTE_NORMAL 0x00000080
59
60 #endif /* MS_FSCC_H */
61
62
63
0 /**
1 * xrdp: A Remote Desktop Protocol server.
2 *
3 * MS-RDPEFS : Definitions from [MS-RDPEFS]
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * References to MS-RDPEFS are currently correct for v20180912 of that
18 * document
19 */
20
21 #if !defined(MS_RDPEFS_H)
22 #define MS_RDPEFS_H
23
24 /*
25 * RDPDR_HEADER definitions (2.2.1.1)
26 */
27
28 /* device redirector core component; most of the packets in this protocol */
29 /* are sent under this component ID */
30 #define RDPDR_CTYP_CORE 0x4472
31
32 /* printing component. the packets that use this ID are typically about */
33 /* printer cache management and identifying XPS printers */
34 #define RDPDR_CTYP_PRN 0x5052
35
36 /* Server Announce Request, as specified in section 2.2.2.2 */
37 #define PAKID_CORE_SERVER_ANNOUNCE 0x496E
38
39 /* Client Announce Reply and Server Client ID Confirm, as specified in */
40 /* sections 2.2.2.3 and 2.2.2.6. */
41 #define PAKID_CORE_CLIENTID_CONFIRM 0x4343
42
43 /* Client Name Request, as specified in section 2.2.2.4 */
44 #define PAKID_CORE_CLIENT_NAME 0x434E
45
46 /* Client Device List Announce Request, as specified in section 2.2.2.9 */
47 #define PAKID_CORE_DEVICELIST_ANNOUNCE 0x4441
48
49 /* Server Device Announce Response, as specified in section 2.2.2.1 */
50 #define PAKID_CORE_DEVICE_REPLY 0x6472
51
52 /* Device I/O Request, as specified in section 2.2.1.4 */
53 #define PAKID_CORE_DEVICE_IOREQUEST 0x4952
54
55 /* Device I/O Response, as specified in section 2.2.1.5 */
56 #define PAKID_CORE_DEVICE_IOCOMPLETION 0x4943
57
58 /* Server Core Capability Request, as specified in section 2.2.2.7 */
59 #define PAKID_CORE_SERVER_CAPABILITY 0x5350
60
61 /* Client Core Capability Response, as specified in section 2.2.2.8 */
62 #define PAKID_CORE_CLIENT_CAPABILITY 0x4350
63
64 /* Client Drive Device List Remove, as specified in section 2.2.3.2 */
65 #define PAKID_CORE_DEVICELIST_REMOVE 0x444D
66
67 /* Add Printer Cachedata, as specified in [MS-RDPEPC] section 2.2.2.3 */
68 #define PAKID_PRN_CACHE_DATA 0x5043
69
70 /* Server User Logged On, as specified in section 2.2.2.5 */
71 #define PAKID_CORE_USER_LOGGEDON 0x554C
72
73 /* Server Printer Set XPS Mode, as specified in [MS-RDPEPC] section 2.2.2.2 */
74 #define PAKID_PRN_USING_XPS 0x5543
75
76 /*
77 * Capability header definitions (2.2.1.2)
78 */
79
80 #define CAP_GENERAL_TYPE 0x0001 /* General cap set - GENERAL_CAPS_SET */
81 #define CAP_PRINTER_TYPE 0x0002 /* Print cap set - PRINTER_CAPS_SET */
82 #define CAP_PORT_TYPE 0x0003 /* Port cap set - PORT_CAPS_SET */
83 #define CAP_DRIVE_TYPE 0x0004 /* Drive cap set - DRIVE_CAPS_SET */
84 #define CAP_SMARTCARD_TYPE 0x0005 /* Smart card cap set - SMARTCARD_CAPS_SET */
85
86 /*
87 * Device announce header (2.2.1.3)
88 */
89 #define RDPDR_DTYP_SERIAL 0x0001
90 #define RDPDR_DTYP_PARALLEL 0x0002
91 #define RDPDR_DTYP_PRINT 0x0004
92 #define RDPDR_DTYP_FILESYSTEM 0x0008
93 #define RDPDR_DTYP_SMARTCARD 0x0020
94
95 /* Device I/O Request definitions (2.2.1.4) */
96 /* MajorFunction */
97 enum IRP_MJ
98 {
99 IRP_MJ_CREATE = 0x00000000,
100 IRP_MJ_CLOSE = 0x00000002,
101 IRP_MJ_READ = 0x00000003,
102 IRP_MJ_WRITE = 0x00000004,
103 IRP_MJ_DEVICE_CONTROL = 0x0000000E,
104 IRP_MJ_QUERY_VOLUME_INFORMATION = 0x0000000A,
105 IRP_MJ_SET_VOLUME_INFORMATION = 0x0000000B,
106 IRP_MJ_QUERY_INFORMATION = 0x00000005,
107 IRP_MJ_SET_INFORMATION = 0x00000006,
108 IRP_MJ_DIRECTORY_CONTROL = 0x0000000C,
109 IRP_MJ_LOCK_CONTROL = 0x00000011
110 };
111
112 /* MinorFunction */
113 /* Set to zero unless MajorFunction code == IRP_MJ_DIRECTORY_CONTROL */
114 enum IRP_MN
115 {
116 IRP_MN_NONE = 0x00000000, /* Name not in MS docs */
117 IRP_MN_QUERY_DIRECTORY = 0x00000001,
118 IRP_MN_NOTIFY_CHANGE_DIRECTORY = 0x00000002
119 };
120
121
122 #endif /* MS_RDPEFS_H */
123
124
0 /**
1 * xrdp: A Remote Desktop Protocol server.
2 *
3 * MS-SMB2 : Definitions from [MS-SMB2]
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * References to MS-SMB2 are currently correct for v20190923 of that
18 * document
19 */
20
21 #if !defined(MS_SMB2_H)
22 #define MS_SMB2_H
23
24 /* SMB2 CREATE request values (section 2.2.13) */
25
26 /*
27 * ShareAccess Mask. Currently, this is referred
28 * to in MS-RDPEFS 2.2.1.4.1 as 'SharedAccess' rather than 'ShareAccess'.
29 */
30 #define SA_FILE_SHARE_READ 0x00000001
31 #define SA_FILE_SHARE_WRITE 0x00000002
32 #define SA_FILE_SHARE_DELETE 0x00000004
33
34 /* CreateDisposition Mask */
35 #define CD_FILE_SUPERSEDE 0x00000000
36 #define CD_FILE_OPEN 0x00000001
37 #define CD_FILE_CREATE 0x00000002
38 #define CD_FILE_OPEN_IF 0x00000003
39 #define CD_FILE_OVERWRITE 0x00000004
40 #define CD_FILE_OVERWRITE_IF 0x00000005
41
42 /* CreateOptions Mask */
43 enum CREATE_OPTIONS
44 {
45 CO_FILE_DIRECTORY_FILE = 0x00000001,
46 CO_FILE_WRITE_THROUGH = 0x00000002,
47 CO_FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020,
48 CO_FILE_DELETE_ON_CLOSE = 0x00001000
49 };
50
51 /*
52 * DesiredAccess Mask (section 2.2.13.1.1)
53 */
54
55 #define DA_FILE_READ_DATA 0x00000001
56 #define DA_FILE_WRITE_DATA 0x00000002
57 #define DA_FILE_APPEND_DATA 0x00000004
58 #define DA_FILE_READ_EA 0x00000008 /* rd extended attributes */
59 #define DA_FILE_WRITE_EA 0x00000010 /* wr extended attributes */
60 #define DA_FILE_EXECUTE 0x00000020
61 #define DA_FILE_READ_ATTRIBUTES 0x00000080
62 #define DA_FILE_WRITE_ATTRIBUTES 0x00000100
63 #define DA_DELETE 0x00010000
64 #define DA_READ_CONTROL 0x00020000 /* rd security descriptor */
65 #define DA_WRITE_DAC 0x00040000
66 #define DA_WRITE_OWNER 0x00080000
67 #define DA_SYNCHRONIZE 0x00100000
68 #define DA_ACCESS_SYSTEM_SECURITY 0x01000000
69 #define DA_MAXIMUM_ALLOWED 0x02000000
70 #define DA_GENERIC_ALL 0x10000000
71 #define DA_GENERIC_EXECUTE 0x20000000
72 #define DA_GENERIC_WRITE 0x40000000
73 #define DA_GENERIC_READ 0x80000000
74
75 #endif /* MS_SMB2_H */
76
77
78
870870 irp->FileId,
871871 irp->CompletionId,
872872 IRP_MJ_DEVICE_CONTROL,
873 0);
873 IRP_MN_NONE);
874874
875875 xstream_wr_u32_le(s, 2048); /* OutputBufferLength */
876876 s_push_layer(s, iso_hdr, 4); /* InputBufferLength - insert later */
3333 #include "xrdp_constants.h"
3434 #include "xrdp_sockets.h"
3535 #include "chansrv_common.h"
36 #include "list.h"
37 #include "audin.h"
3638
3739 #if defined(XRDP_FDK_AAC)
3840 #include <fdk-aac/aacenc_lib.h>
6971 static int g_training_sent_time = 0;
7072 static int g_cBlockNo = 0;
7173 static int g_bytes_in_stream = 0;
72 static FIFO g_in_fifo;
73 static int g_bytes_in_fifo = 0;
74 static int g_unacked_frames = 0;
74 FIFO g_in_fifo;
75 int g_bytes_in_fifo = 0;
76 static int g_time_diff = 0;
77 static int g_best_time_diff = 0;
78
7579
7680 static struct stream *g_stream_inp = NULL;
7781 static struct stream *g_stream_incoming_packet = NULL;
8084 static char g_buffer[MAX_BBUF_SIZE];
8185 static int g_buf_index = 0;
8286 static int g_sent_time[256];
83 static int g_sent_flag[256];
8487
8588 static int g_bbuf_size = 1024 * 8; /* may change later */
89
90 static struct list *g_ack_time_diff = 0;
8691
8792 struct xr_wave_format_ex
8893 {
235240 0
236241 };
237242
243 static int g_rdpsnd_can_rec = 0;
244
238245 static int g_client_input_format_index = 0;
239246 static int g_server_input_format_index = 0;
240247
339346 out_uint16_le(s, SNDC_TRAINING);
340347 size_ptr = s->p;
341348 out_uint16_le(s, 0); /* size, set later */
342 time = g_time2();
349 time = g_time3();
343350 g_training_sent_time = time;
344351 out_uint16_le(s, time);
345352 out_uint16_le(s, 1024);
882889 return 1;
883890 }
884891
885 LOG(20, ("sound_send_wave_data_chunk: g_sent_flag[%d] = %d",
886 g_cBlockNo + 1, g_sent_flag[(g_cBlockNo + 1) & 0xff]));
887 if (g_sent_flag[(g_cBlockNo + 1) & 0xff] & 1)
888 {
889 LOG(10, ("sound_send_wave_data_chunk: no room"));
890 return 2;
891 }
892 else
893 {
894 LOG(10, ("sound_send_wave_data_chunk: got room"));
895 }
896
897892 /* compress, if available */
898893 format_index = g_current_client_format_index;
899894 data_bytes = sound_wave_compress(data, data_bytes, &format_index);
907902 out_uint16_le(s, SNDC_WAVE);
908903 size_ptr = s->p;
909904 out_uint16_le(s, 0); /* size, set later */
910 time = g_time2();
905 time = g_time3();
911906 out_uint16_le(s, time);
912907 out_uint16_le(s, format_index); /* wFormatNo */
913908 g_cBlockNo++;
914 g_unacked_frames++;
915909 out_uint8(s, g_cBlockNo);
916910 g_sent_time[g_cBlockNo & 0xff] = time;
917 g_sent_flag[g_cBlockNo & 0xff] = 1;
918911
919912 LOG(10, ("sound_send_wave_data_chunk: sending time %d, g_cBlockNo %d",
920913 time & 0xffff, g_cBlockNo & 0xff));
955948 int res;
956949
957950 LOG(10, ("sound_send_wave_data: sending %d bytes", data_bytes));
951 if (g_time_diff > g_best_time_diff + 250)
952 {
953 data_bytes = data_bytes / 4;
954 data_bytes = data_bytes & ~3;
955 g_memset(data, 0, data_bytes);
956 g_time_diff = 0;
957 }
958958 data_index = 0;
959959 error = 0;
960960 while (data_bytes > 0)
10041004
10051005 LOG(10, ("sound_send_close:"));
10061006
1007 /* send any left over data */
1008 if (g_buf_index)
1009 {
1010 if (sound_send_wave_data_chunk(g_buffer, g_buf_index) != 0)
1011 {
1012 LOG(10, ("sound_send_close: sound_send_wave_data_chunk failed"));
1013 return 1;
1014 }
1015 }
1007 g_best_time_diff = 0;
10161008 g_buf_index = 0;
1017 g_memset(g_sent_flag, 0, sizeof(g_sent_flag));
10181009
10191010 /* send close msg */
10201011 make_stream(s);
10391030 {
10401031 int time_diff;
10411032
1042 time_diff = g_time2() - g_training_sent_time;
1033 time_diff = g_time3() - g_training_sent_time;
10431034 LOG(0, ("sound_process_training: round trip time %u", time_diff));
10441035 return 0;
10451036 }
10511042 {
10521043 int wTimeStamp;
10531044 int cConfirmedBlockNo;
1054 int cleared_count;
10551045 int time;
10561046 int time_diff;
1057 int block_no;
1058 int block_no_clamped;
1059 int found;
10601047 int index;
1061
1062 time = g_time2();
1048 int acc;
1049
1050 time = g_time3();
10631051 in_uint16_le(s, wTimeStamp);
10641052 in_uint8(s, cConfirmedBlockNo);
10651053 time_diff = time - g_sent_time[cConfirmedBlockNo & 0xff];
1066 cleared_count = 0;
1067 found = 0;
1068 block_no = g_cBlockNo;
1069 for (index = 0; index < g_unacked_frames; index++)
1070 {
1071 block_no_clamped = block_no & 0xff;
1072 if ((cConfirmedBlockNo == block_no_clamped) || found)
1073 {
1074 found = 1;
1075 if (g_sent_flag[block_no_clamped] & 1)
1076 {
1077 LOG(10, ("sound_process_wave_confirm: clearing %d",
1078 block_no_clamped));
1079 g_sent_flag[block_no_clamped] &= ~1;
1080 cleared_count++;
1081 }
1082 }
1083 block_no--;
1084 }
1054
10851055 LOG(10, ("sound_process_wave_confirm: wTimeStamp %d, "
1086 "cConfirmedBlockNo %d time diff %d cleared_count %d "
1087 "g_unacked_frames %d", wTimeStamp, cConfirmedBlockNo, time_diff,
1088 cleared_count, g_unacked_frames));
1089 g_unacked_frames -= cleared_count;
1056 "cConfirmedBlockNo %d time diff %d",
1057 wTimeStamp, cConfirmedBlockNo, time_diff));
1058
1059 acc = 0;
1060 list_add_item(g_ack_time_diff, time_diff);
1061 if (g_ack_time_diff->count >= 50)
1062 {
1063 while (g_ack_time_diff->count > 50)
1064 {
1065 list_remove_item(g_ack_time_diff, 0);
1066 }
1067 for (index = 0; index < g_ack_time_diff->count; index++)
1068 {
1069 acc += list_get_item(g_ack_time_diff, index);
1070 }
1071 acc = acc / g_ack_time_diff->count;
1072 if ((g_best_time_diff < 1) || (g_best_time_diff > acc))
1073 {
1074 g_best_time_diff = acc;
1075 }
1076 }
1077 g_time_diff = acc;
10901078 return 0;
10911079 }
10921080
12181206 {
12191207 LOG(0, ("sound_init:"));
12201208
1221 g_memset(g_sent_flag, 0, sizeof(g_sent_flag));
12221209 g_stream_incoming_packet = NULL;
12231210
12241211 /* init sound output */
12401227
12411228 g_client_does_mp3lame = 0;
12421229 g_client_mp3lame_index = 0;
1230
1231 if (g_ack_time_diff == 0)
1232 {
1233 g_ack_time_diff = list_create();
1234 }
1235 list_clear(g_ack_time_diff);
12431236
12441237 return 0;
12451238 }
14441437 static int
14451438 sound_send_server_input_formats(void)
14461439 {
1440 #if defined(XRDP_RDPSNDAUDIN)
14471441 struct stream *s;
14481442 int bytes;
14491443 int index;
14981492 bytes = (int)(s->end - s->data);
14991493 send_channel_data(g_rdpsnd_chan_id, s->data, bytes);
15001494 free_stream(s);
1495 #else
1496 /* avoid warning */
1497 (void)g_wave_inp_formats;
1498 #endif
15011499 return 0;
15021500 }
15031501
15691567
15701568 LOG(10, ("sound_process_input_formats: size=%d", size));
15711569
1570 if (g_getenv("XRDP_NO_RDPSND_REC") == NULL)
1571 {
1572 g_rdpsnd_can_rec = 1;
1573 }
15721574 in_uint8s(s, 8); /* skip 8 bytes */
15731575 in_uint16_le(s, num_formats);
15741576 in_uint8s(s, 2); /* skip version */
17811783 }
17821784 else if (cmd == PA_CMD_START_REC)
17831785 {
1784 sound_input_start_recording();
1786 if (g_rdpsnd_can_rec)
1787 {
1788 sound_input_start_recording();
1789 }
1790 else
1791 {
1792 audin_start();
1793 }
17851794 }
17861795 else if (cmd == PA_CMD_STOP_REC)
17871796 {
1788 sound_input_stop_recording();
1797 if (g_rdpsnd_can_rec)
1798 {
1799 sound_input_stop_recording();
1800 }
1801 else
1802 {
1803 audin_stop();
1804 }
17891805 }
17901806
17911807 xstream_free(s);
3333 #include "sesman.h"
3434 #include "log.h"
3535
36 extern struct config_sesman *g_cfg; /* in sesman.c */
37
3836
3937
4038 /******************************************************************************/
5250
5351 if (-1 == fd)
5452 {
55 //if (g_cfg->log.fd >= 0)
56 //{
57 /* logging is already active */
58 log_message(LOG_LEVEL_ALWAYS, "error opening %s in \
59 config_read", cfg_file);
60 //}
61 //else
62 //{
63 g_printf("error opening %s in config_read", cfg_file);
64 //}
6553 return 1;
6654 }
6755
184172 if (cf->default_wm[0] != '/')
185173 {
186174 /* sizeof operator returns string length including null terminator */
187 length = sizeof(XRDP_CFG_PATH) + g_strlen(g_cfg->default_wm) + 1; /* '/' */
175 length = sizeof(XRDP_CFG_PATH) + g_strlen(cf->default_wm) + 1; /* '/' */
188176 buf = (char *)g_malloc(length, 0);
189 g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, g_cfg->default_wm);
190 g_free(g_cfg->default_wm);
191 g_cfg->default_wm = g_strdup(buf);
177 g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, cf->default_wm);
178 g_free(cf->default_wm);
179 cf->default_wm = g_strdup(buf);
192180 g_free(buf);
193181 }
194182
205193 if (cf->reconnect_sh[0] != '/')
206194 {
207195 /* sizeof operator returns string length including null terminator */
208 length = sizeof(XRDP_CFG_PATH) + g_strlen(g_cfg->reconnect_sh) + 1; /* '/' */
196 length = sizeof(XRDP_CFG_PATH) + g_strlen(cf->reconnect_sh) + 1; /* '/' */
209197 buf = (char *)g_malloc(length, 0);
210 g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, g_cfg->reconnect_sh);
211 g_free(g_cfg->reconnect_sh);
212 g_cfg->reconnect_sh = g_strdup(buf);
198 g_sprintf(buf, "%s/%s", XRDP_CFG_PATH, cf->reconnect_sh);
199 g_free(cf->reconnect_sh);
200 cf->reconnect_sh = g_strdup(buf);
213201 g_free(buf);
214202 }
215203
234222 sc->login_retry = 3;
235223 sc->ts_users_enable = 0;
236224 sc->ts_admins_enable = 0;
225 sc->restrict_outbound_clipboard = 0;
237226
238227 file_read_section(file, SESMAN_CFG_SECURITY, param_n, param_v);
239228
272261 {
273262 sc->ts_always_group_check = g_text2bool((char *)list_get_item(param_v, i));
274263 }
264
265 if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD))
266 {
267 sc->restrict_outbound_clipboard = g_text2bool((char *)list_get_item(param_v, i));
268 }
269
275270 }
276271
277272 return 0;
480475 g_writeln(" DefaultWindowManager: %s", config->default_wm);
481476 g_writeln(" ReconnectScript: %s", config->reconnect_sh);
482477 g_writeln(" AuthFilePath: %s",
483 ((config->auth_file_path) ? (config->auth_file_path) : ("disabled")));
478 ((config->auth_file_path) ? (config->auth_file_path) : ("disabled")));
484479
485480 /* Session configuration */
486481 g_writeln("Session configuration:");
496491 g_writeln(" AllowRootLogin: %d", sc->allow_root);
497492 g_writeln(" MaxLoginRetry: %d", sc->login_retry);
498493 g_writeln(" AlwaysGroupCheck: %d", sc->ts_always_group_check);
494 g_writeln(" RestrictOutboundClipboard: %d", sc->restrict_outbound_clipboard);
499495
500496 g_printf( " TSUsersGroup: ");
501497 if (sc->ts_users_enable)
529525 for (i = 0; i < config->xorg_params->count; i++)
530526 {
531527 g_writeln(" Parameter %02d %s",
532 i, (char *) list_get_item(config->xorg_params, i));
528 i, (char *) list_get_item(config->xorg_params, i));
533529 }
534530
535531 /* Xvnc */
541537 for (i = 0; i < config->vnc_params->count; i++)
542538 {
543539 g_writeln(" Parameter %02d %s",
544 i, (char *)list_get_item(config->vnc_params, i));
540 i, (char *)list_get_item(config->vnc_params, i));
545541 }
546542
547543 /* X11rdp */
553549 for (i = 0; i < config->rdp_params->count; i++)
554550 {
555551 g_writeln(" Parameter %02d %s",
556 i, (char *)list_get_item(config->rdp_params, i));
552 i, (char *)list_get_item(config->rdp_params, i));
557553 }
558554
559555 /* SessionVariables */
566562 {
567563 g_writeln(" Parameter %02d %s=%s",
568564 i, (char *) list_get_item(config->env_names, i),
569 (char *) list_get_item(config->env_values, i));
565 (char *) list_get_item(config->env_values, i));
570566 }
571567 }
572568
5353 #define SESMAN_CFG_LOG_ENABLE_SYSLOG "EnableSyslog"
5454 #define SESMAN_CFG_LOG_SYSLOG_LEVEL "SyslogLevel"
5555 */
56 #define SESMAN_CFG_SECURITY "Security"
57 #define SESMAN_CFG_SEC_LOGIN_RETRY "MaxLoginRetry"
58 #define SESMAN_CFG_SEC_ALLOW_ROOT "AllowRootLogin"
59 #define SESMAN_CFG_SEC_USR_GROUP "TerminalServerUsers"
60 #define SESMAN_CFG_SEC_ADM_GROUP "TerminalServerAdmins"
61 #define SESMAN_CFG_SEC_ALWAYSGROUPCHECK "AlwaysGroupCheck"
56 #define SESMAN_CFG_SECURITY "Security"
57 #define SESMAN_CFG_SEC_LOGIN_RETRY "MaxLoginRetry"
58 #define SESMAN_CFG_SEC_ALLOW_ROOT "AllowRootLogin"
59 #define SESMAN_CFG_SEC_USR_GROUP "TerminalServerUsers"
60 #define SESMAN_CFG_SEC_ADM_GROUP "TerminalServerAdmins"
61 #define SESMAN_CFG_SEC_ALWAYSGROUPCHECK "AlwaysGroupCheck"
62 #define SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD "RestrictOutboundClipboard"
6263
6364 #define SESMAN_CFG_SESSIONS "Sessions"
6465 #define SESMAN_CFG_SESS_MAX "MaxSessions"
125126 * @brief if the Groups are not found deny access
126127 */
127128 int ts_always_group_check;
129 /**
130 * @var restrict_outbound_clipboard
131 * @brief if the clipboard should be enforced restricted. If true only allow client -> server, not vice versa.
132 */
133 int restrict_outbound_clipboard;
128134 };
129135
130136 /**
132132 in_uint16_be(c->in_s, cmd);
133133 scp_session_set_height(session, cmd);
134134 in_uint16_be(c->in_s, cmd);
135 scp_session_set_height(session, cmd);
135 scp_session_set_width(session, cmd);
136136 in_uint8(c->in_s, sz);
137137 if (0 != scp_session_set_bpp(session, sz))
138138 {
341341 g_exit(1);
342342 }
343343
344 log_message(LOG_LEVEL_TRACE, "config loaded in %s at %s:%d", __func__, __FILE__, __LINE__);
345 log_message(LOG_LEVEL_TRACE, " listen_address = %s", g_cfg->listen_address);
346 log_message(LOG_LEVEL_TRACE, " listen_port = %s", g_cfg->listen_port);
347 log_message(LOG_LEVEL_TRACE, " enable_user_wm = %d", g_cfg->enable_user_wm);
348 log_message(LOG_LEVEL_TRACE, " default_wm = %s", g_cfg->default_wm);
349 log_message(LOG_LEVEL_TRACE, " user_wm = %s", g_cfg->user_wm);
350 log_message(LOG_LEVEL_TRACE, " reconnect_sh = %s", g_cfg->reconnect_sh);
351 log_message(LOG_LEVEL_TRACE, " auth_file_path = %s", g_cfg->auth_file_path);
352
344353 if (daemon)
345354 {
346355 /* not to spit on the console, shut up stdout/stderr before anything's logged */
347356 g_file_close(0);
348357 g_file_close(1);
349358 g_file_close(2);
359
360 if (g_file_open("/dev/null") < 0)
361 {
362 }
363
364 if (g_file_open("/dev/null") < 0)
365 {
366 }
367
368 if (g_file_open("/dev/null") < 0)
369 {
370 }
350371 }
351372
352373 /* libscp initialization */
371392 g_exit(0);
372393 }
373394
374 if (g_file_open("/dev/null") < 0)
375 {
376 }
377
378 if (g_file_open("/dev/null") < 0)
379 {
380 }
381
382 if (g_file_open("/dev/null") < 0)
383 {
384 }
385395 }
386396
387397 /* signal handling */
1818 ; When AlwaysGroupCheck=false access will be permitted
1919 ; if the group TerminalServerUsers is not defined.
2020 AlwaysGroupCheck=false
21 ; When RestrictOutboundClipboard=true clipboard from the
22 ; server is not pushed to the client.
23 RestrictOutboundClipboard=false
2124
2225 [Sessions]
2326 ;; X11DisplayOffset - x11 display number offset
101104 [Chansrv]
102105 ; drive redirection, defaults to xrdp_client if not set
103106 FuseMountName=thinclient_drives
107 ; this value allows only the user to acess their own mapped drives.
108 ; Make this more permissive (e.g. 022) if required.
109 FileUmask=077
104110
105111 [SessionVariables]
106112 PULSE_SCRIPT=/etc/xrdp/pulse/default.pa
372372 env_set_user(username, 0, display,
373373 g_cfg->env_names,
374374 g_cfg->env_values);
375
376 if (g_cfg->sec.restrict_outbound_clipboard == 1)
377 {
378 g_setenv("CHANSRV_RESTRICT_OUTBOUND_CLIPBOARD", "1", 1);
379 }
375380
376381 /* executing chansrv */
377382 g_execvp(exe_path, (char **) (chansrv_params->items));
379379 }
380380 else if (msg == 200) /* invalidate */
381381 {
382 /* FramebufferUpdateRequest */
383 init_stream(s, 8192);
384 out_uint8(s, 3);
385 out_uint8(s, 0);
386 x = (param1 >> 16) & 0xffff;
387 out_uint16_be(s, x);
388 y = param1 & 0xffff;
389 out_uint16_be(s, y);
390 cx = (param2 >> 16) & 0xffff;
391 out_uint16_be(s, cx);
392 cy = param2 & 0xffff;
393 out_uint16_be(s, cy);
394 s_mark_end(s);
395 error = lib_send_copy(v, s);
382 if (v->suppress_output == 0)
383 {
384 /* FramebufferUpdateRequest */
385 init_stream(s, 8192);
386 out_uint8(s, 3);
387 out_uint8(s, 0);
388 x = (param1 >> 16) & 0xffff;
389 out_uint16_be(s, x);
390 y = param1 & 0xffff;
391 out_uint16_be(s, y);
392 cx = (param2 >> 16) & 0xffff;
393 out_uint16_be(s, cx);
394 cy = param2 & 0xffff;
395 out_uint16_be(s, cy);
396 s_mark_end(s);
397 error = lib_send_copy(v, s);
398 }
396399 }
397400
398401 free_stream(s);
741744
742745 if (error == 0)
743746 {
744 /* FramebufferUpdateRequest */
745 init_stream(s, 8192);
746 out_uint8(s, 3);
747 out_uint8(s, 1);
748 out_uint16_be(s, 0);
749 out_uint16_be(s, 0);
750 out_uint16_be(s, v->mod_width);
751 out_uint16_be(s, v->mod_height);
752 s_mark_end(s);
753 error = lib_send_copy(v, s);
747 if (v->suppress_output == 0)
748 {
749 /* FramebufferUpdateRequest */
750 init_stream(s, 8192);
751 out_uint8(s, 3);
752 out_uint8(s, 1);
753 out_uint16_be(s, 0);
754 out_uint16_be(s, 0);
755 out_uint16_be(s, v->mod_width);
756 out_uint16_be(s, v->mod_height);
757 s_mark_end(s);
758 error = lib_send_copy(v, s);
759 }
754760 }
755761
756762 free_stream(s);
915921 }
916922 else
917923 {
918 g_sprintf(text, "VNC unknown in lib_mod_signal %d", type);
924 g_sprintf(text, "VNC unknown in lib_mod_process_message %d", type);
919925 v->server_msg(v, text, 1);
920926 }
921927 }
13391345
13401346 if (error == 0)
13411347 {
1342 /* FramebufferUpdateRequest */
1343 init_stream(s, 8192);
1344 out_uint8(s, 3);
1345 out_uint8(s, 0);
1346 out_uint16_be(s, 0);
1347 out_uint16_be(s, 0);
1348 out_uint16_be(s, v->mod_width);
1349 out_uint16_be(s, v->mod_height);
1350 v->server_msg(v, "VNC sending framebuffer update request", 0);
1351 s_mark_end(s);
1352 error = trans_force_write_s(v->trans, s);
1348 if (v->suppress_output == 0)
1349 {
1350 /* FramebufferUpdateRequest */
1351 init_stream(s, 8192);
1352 out_uint8(s, 3);
1353 out_uint8(s, 0);
1354 out_uint16_be(s, 0);
1355 out_uint16_be(s, 0);
1356 out_uint16_be(s, v->mod_width);
1357 out_uint16_be(s, v->mod_height);
1358 v->server_msg(v, "VNC sending framebuffer update request", 0);
1359 s_mark_end(s);
1360 error = trans_force_write_s(v->trans, s);
1361 }
13531362 }
13541363
13551364 if (error == 0)
14891498 }
14901499 }
14911500 return rv;
1501 }
1502
1503 /******************************************************************************/
1504 /* return error */
1505 int
1506 lib_mod_frame_ack(struct vnc* v, int flags, int frame_id)
1507 {
1508 return 0;
1509 }
1510
1511 /******************************************************************************/
1512 /* return error */
1513 int
1514 lib_mod_suppress_output(struct vnc* v, int suppress,
1515 int left, int top, int right, int bottom)
1516 {
1517 int error;
1518 struct stream *s;
1519
1520 error = 0;
1521 v->suppress_output = suppress;
1522 if (suppress == 0)
1523 {
1524 /* FramebufferUpdateRequest */
1525 make_stream(s);
1526 init_stream(s, 8192);
1527 out_uint8(s, 3);
1528 out_uint8(s, 0);
1529 out_uint16_be(s, 0);
1530 out_uint16_be(s, 0);
1531 out_uint16_be(s, v->mod_width);
1532 out_uint16_be(s, v->mod_height);
1533 s_mark_end(s);
1534 error = lib_send_copy(v, s);
1535 free_stream(s);
1536 }
1537 return error;
14921538 }
14931539
14941540 /******************************************************************************/
15101556 v->mod_set_param = lib_mod_set_param;
15111557 v->mod_get_wait_objs = lib_mod_get_wait_objs;
15121558 v->mod_check_wait_objs = lib_mod_check_wait_objs;
1559 v->mod_frame_ack = lib_mod_frame_ack;
1560 v->mod_suppress_output = lib_mod_suppress_output;
15131561 return (tintptr) v;
15141562 }
15151563
2323 #include "os_calls.h"
2424 #include "defines.h"
2525
26 #define CURRENT_MOD_VER 3
26 #define CURRENT_MOD_VER 4
2727
2828 struct vnc
2929 {
4141 int (*mod_get_wait_objs)(struct vnc* v, tbus* read_objs, int* rcount,
4242 tbus* write_objs, int* wcount, int* timeout);
4343 int (*mod_check_wait_objs)(struct vnc* v);
44 tintptr mod_dumby[100 - 9]; /* align, 100 minus the number of mod
45 functions above */
44 int (*mod_frame_ack)(struct vnc* v, int flags, int frame_id);
45 int (*mod_suppress_output)(struct vnc* v, int suppress,
46 int left, int top, int right, int bottom);
47 tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
48 functions above */
4649 /* server functions */
4750 int (*server_begin_update)(struct vnc* v);
4851 int (*server_end_update)(struct vnc* v);
115118 struct trans *trans;
116119 int got_guid;
117120 tui8 guid[16];
121 int suppress_output;
118122 };
163163 }
164164
165165 /*****************************************************************************/
166 void
167 xrdp_hang_up(int sig)
168 {
169 log_message(LOG_LEVEL_INFO, "caught SIGHUP, noop...");
170 }
171
172 /*****************************************************************************/
166173 /* called in child just after fork */
167174 int
168175 xrdp_child_fork(void)
574581
575582 if (!no_daemon)
576583 {
584 /* if can't listen, exit with failure status */
585 if (xrdp_listen_test(startup_params) != 0)
586 {
587 log_message(LOG_LEVEL_ERROR, "Failed to start xrdp daemon, "
588 "possibly address already in use.");
589 g_deinit();
590 /* must exit with failure status,
591 or systemd cannot detect xrdp daemon couldn't start properly */
592 g_exit(1);
593 }
577594 /* start of daemonizing code */
578595 pid = g_fork();
579596
586603
587604 if (0 != pid)
588605 {
589 /* if can't listen, exit with failure status */
590 if (xrdp_listen_test() != 0)
591 {
592 log_message(LOG_LEVEL_ERROR, "Failed to start xrdp daemon, "
593 "possibly address already in use.");
594 g_deinit();
595 /* must exit with failure status,
596 or systemd cannot detect xrdp daemon couldn't start properly */
597 g_exit(1);
598 }
599606 g_writeln("daemon process %d started ok", pid);
600607 /* exit, this is the main process */
601608 g_deinit();
643650 g_threadid = tc_get_threadid();
644651 g_listen = xrdp_listen_create();
645652 g_signal_user_interrupt(xrdp_shutdown); /* SIGINT */
646 g_signal_pipe(pipe_sig); /* SIGPIPE */
647 g_signal_terminate(xrdp_shutdown); /* SIGTERM */
648 g_signal_child_stop(xrdp_child); /* SIGCHLD */
653 g_signal_pipe(pipe_sig); /* SIGPIPE */
654 g_signal_terminate(xrdp_shutdown); /* SIGTERM */
655 g_signal_child_stop(xrdp_child); /* SIGCHLD */
656 g_signal_hang_up(xrdp_hang_up); /* SIGHUP */
649657 g_sync_mutex = tc_mutex_create();
650658 g_sync1_mutex = tc_mutex_create();
651659 pid = g_getpid();
169169 int
170170 xrdp_listen_main_loop(struct xrdp_listen* self);
171171 int
172 xrdp_listen_test(void);
172 xrdp_listen_test(struct xrdp_startup_params *startup_params);
173173
174174 /* xrdp_region.c */
175175 struct xrdp_region*
370370 /* xrdp_mm.c */
371371 int
372372 xrdp_mm_drdynvc_up(struct xrdp_mm* self);
373 int
374 xrdp_mm_suppress_output(struct xrdp_mm* self, int suppress,
375 int left, int top, int right, int bottom);
373376 struct xrdp_mm*
374377 xrdp_mm_create(struct xrdp_wm* owner);
375378 void
33
44 ; fork a new process for each incoming connection
55 fork=true
6 ; tcp port to listen
6
7 ; ports to listen on, number alone means listen on all interfaces
8 ; 0.0.0.0 or :: if ipv6 is configured
9 ; space between multiple occurrences
10 ;
11 ; Examples:
12 ; port=3389
13 ; port=unix://./tmp/xrdp.socket
14 ; port=tcp://.:3389 127.0.0.1:3389
15 ; port=tcp://:3389 *:3389
16 ; port=tcp://<any ipv4 format addr>:3389 192.168.1.1:3389
17 ; port=tcp6://.:3389 ::1:3389
18 ; port=tcp6://:3389 *:3389
19 ; port=tcp6://{<any ipv6 format addr>}:3389 {FC00:0:0:0:0:0:0:1}:3389
20 ; port=vsock://<cid>:<port>
721 port=3389
22
823 ; 'port' above should be connected to with vsock instead of tcp
24 ; use this only with number alone in port above
25 ; prefer use vsock://<cid>:<port> above
926 use_vsock=false
27
1028 ; regulate if the listening socket use socket option tcp_nodelay
1129 ; no buffering will be performed in the TCP stack
1230 tcp_nodelay=true
31
1332 ; regulate if the listening socket use socket option keepalive
1433 ; if the network connection disappear without close messages the connection will be closed
1534 tcp_keepalive=true
35
36 ; set tcp send/recv buffer (for experts)
1637 #tcp_send_buffer_bytes=32768
1738 #tcp_recv_buffer_bytes=32768
1839
1940 ; security layer can be 'tls', 'rdp' or 'negotiate'
2041 ; for client compatible layer
2142 security_layer=negotiate
22 ; minimum security level allowed for client
43
44 ; minimum security level allowed for client for classic RDP encryption
45 ; use tls_ciphers to configure TLS encryption
2346 ; can be 'none', 'low', 'medium', 'high', 'fips'
2447 crypt_level=high
48
2549 ; X.509 certificate and private key
2650 ; openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 365
2751 certificate=
2852 key_file=
53
2954 ; set SSL protocols
3055 ; can be comma separated list of 'SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3'
3156 ssl_protocols=TLSv1.2, TLSv1.3
5858 [default_rdp_layouts]
5959 rdp_layout_us=0x00000409
6060 rdp_layout_us_dvorak=0x00010409
61 rdp_layout_dk=0x00000406
6162 rdp_layout_de=0x00000407
6263 rdp_layout_es=0x0000040A
6364 rdp_layout_fi=0x0000040B
8384 [default_layouts_map]
8485 rdp_layout_us=us
8586 rdp_layout_us_dvorak=dvorak
87 rdp_layout_dk=dk
8688 rdp_layout_de=de
8789 rdp_layout_es=es
8890 rdp_layout_fi=fi
119121 [rdp_layouts_map_mac]
120122 rdp_layout_us=us
121123 rdp_layout_us_dvorak=dvorak
124 rdp_layout_dk=dk
122125 rdp_layout_de=de
123126 rdp_layout_es=es
124127 rdp_layout_fi=fi
2929 static tbus g_process_sem = 0;
3030 static struct xrdp_process *g_process = 0;
3131
32 int
33 xrdp_listen_conn_in(struct trans *self, struct trans *new_self);
34
3235 /*****************************************************************************/
3336 static int
3437 xrdp_listen_create_pro_done(struct xrdp_listen *self)
5659
5760 self = (struct xrdp_listen *)g_malloc(sizeof(struct xrdp_listen), 1);
5861 xrdp_listen_create_pro_done(self);
62 self->trans_list = list_create();
5963 self->process_list = list_create();
64 self->fork_list = list_create();
6065
6166 if (g_process_sem == 0)
6267 {
6368 g_process_sem = tc_sem_create(0);
6469 }
65
66 /* setting TCP mode now, may change later */
67 self->listen_trans = trans_create(TRANS_MODE_TCP, 16, 16);
68
69 if (self->listen_trans == 0)
70 {
71 log_message(LOG_LEVEL_ERROR,"xrdp_listen_create: trans_create failed");
72 }
73 else
74 {
75 self->listen_trans->is_term = g_is_term;
76 }
77
7870 return self;
7971 }
8072
8274 void
8375 xrdp_listen_delete(struct xrdp_listen *self)
8476 {
85 if (self->listen_trans != 0)
86 {
87 trans_delete(self->listen_trans);
77 int index;
78 struct trans *ltrans;
79
80 if (self == NULL)
81 {
82 return;
83 }
84 if (self->trans_list != NULL)
85 {
86 for (index = 0; index < self->trans_list->count; index++)
87 {
88 ltrans = (struct trans *) list_get_item(self->trans_list, index);
89 trans_delete(ltrans);
90 }
91 list_delete(self->trans_list);
8892 }
8993
9094 if (g_process_sem != 0)
9599
96100 g_delete_wait_obj(self->pro_done_event);
97101 list_delete(self->process_list);
102 list_delete(self->fork_list);
98103 g_free(self);
99104 }
100105
149154
150155 /*****************************************************************************/
151156 static int
152 xrdp_listen_get_port_address(char *port, int port_bytes,
153 char *address, int address_bytes,
154 int *tcp_nodelay, int *tcp_keepalive,
155 int *mode,
156 struct xrdp_startup_params *startup_param)
157 xrdp_listen_get_startup_params(struct xrdp_listen *self)
157158 {
158159 int fd;
159 int error;
160160 int index;
161 int port_override;
162 int fork_override;
161163 char *val;
162164 struct list *names;
163165 struct list *values;
164166 char cfg_file[256];
165
166 /* default to port 3389 */
167 g_strncpy(port, "3389", port_bytes - 1);
168 /* Default to all */
169 g_strncpy(address, "0.0.0.0", address_bytes - 1);
170 /* see if port or address is in xrdp.ini file */
167 struct xrdp_startup_params *startup_params;
168
169 startup_params = self->startup_params;
170 port_override = startup_params->port[0] != 0;
171 fork_override = startup_params->fork;
171172 g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH);
172173 fd = g_file_open(cfg_file);
173 *mode = TRANS_MODE_TCP;
174 *tcp_nodelay = 0 ;
175 *tcp_keepalive = 0 ;
176
177174 if (fd != -1)
178175 {
179176 names = list_create();
180177 names->auto_free = 1;
181178 values = list_create();
182179 values->auto_free = 1;
183
184180 if (file_read_section(fd, "globals", names, values) == 0)
185181 {
186182 for (index = 0; index < names->count; index++)
187183 {
188184 val = (char *)list_get_item(names, index);
189
190185 if (val != 0)
191186 {
192187 if (g_strcasecmp(val, "port") == 0)
193188 {
194 val = (char *)list_get_item(values, index);
195 if (val[0] == '/')
189 if (port_override == 0)
196190 {
197 g_strncpy(port, val, port_bytes - 1);
198 }
199 else
200 {
201 error = g_atoi(val);
202 if ((error > 0) && (error < 65000))
203 {
204 g_strncpy(port, val, port_bytes - 1);
205 }
191 val = (char *) list_get_item(values, index);
192 g_strncpy(startup_params->port, val,
193 sizeof(startup_params->port) - 1);
206194 }
207195 }
196 if (g_strcasecmp(val, "fork") == 0)
197 {
198 if (fork_override == 0)
199 {
200 val = (char *) list_get_item(values, index);
201 startup_params->fork = g_text2bool(val);
202 }
203 }
204
205 if (g_strcasecmp(val, "tcp_nodelay") == 0)
206 {
207 val = (char *)list_get_item(values, index);
208 startup_params->tcp_nodelay = g_text2bool(val);
209 }
210
211 if (g_strcasecmp(val, "tcp_keepalive") == 0)
212 {
213 val = (char *)list_get_item(values, index);
214 startup_params->tcp_keepalive = g_text2bool(val);
215 }
216
217 if (g_strcasecmp(val, "tcp_send_buffer_bytes") == 0)
218 {
219 val = (char *)list_get_item(values, index);
220 startup_params->tcp_send_buffer_bytes = g_atoi(val);
221 }
222
223 if (g_strcasecmp(val, "tcp_recv_buffer_bytes") == 0)
224 {
225 val = (char *)list_get_item(values, index);
226 startup_params->tcp_recv_buffer_bytes = g_atoi(val);
227 }
228
208229 if (g_strcasecmp(val, "use_vsock") == 0)
209230 {
210231 val = (char *)list_get_item(values, index);
211 if (g_text2bool(val) == 1)
212 {
213 *mode = TRANS_MODE_VSOCK;
214 }
215 }
216 if (g_strcasecmp(val, "address") == 0)
217 {
218 val = (char *)list_get_item(values, index);
219 g_strncpy(address, val, address_bytes - 1);
220 }
221
222 if (g_strcasecmp(val, "fork") == 0)
223 {
224 val = (char *)list_get_item(values, index);
225 startup_param->fork = g_text2bool(val);
226 }
227
228 if (g_strcasecmp(val, "tcp_nodelay") == 0)
229 {
230 val = (char *)list_get_item(values, index);
231 *tcp_nodelay = g_text2bool(val);
232 }
233
234 if (g_strcasecmp(val, "tcp_keepalive") == 0)
235 {
236 val = (char *)list_get_item(values, index);
237 *tcp_keepalive = g_text2bool(val);
238 }
239
240 if (g_strcasecmp(val, "tcp_send_buffer_bytes") == 0)
241 {
242 val = (char *)list_get_item(values, index);
243 startup_param->send_buffer_bytes = g_atoi(val);
244 }
245
246 if (g_strcasecmp(val, "tcp_recv_buffer_bytes") == 0)
247 {
248 val = (char *)list_get_item(values, index);
249 startup_param->recv_buffer_bytes = g_atoi(val);
232 startup_params->use_vsock = g_text2bool(val);
250233 }
251234 }
252235 }
254237
255238 list_delete(names);
256239 list_delete(values);
257 }
258
259 if (fd != -1)
260240 g_file_close(fd);
261
262 /* startup_param overrides */
263 if (startup_param->port[0] != 0)
264 {
265 g_strncpy(port, startup_param->port, port_bytes - 1);
266 }
267
241 }
242 return 0;
243 }
244
245 /*****************************************************************************/
246 static int
247 xrdp_listen_stop_all_listen(struct xrdp_listen *self)
248 {
249 int index;
250 struct trans *ltrans;
251
252 if (self->trans_list == NULL)
253 {
254 return 0;
255 }
256 for (index = 0; index < self->trans_list->count; index++)
257 {
258 ltrans = (struct trans *)
259 list_get_item(self->trans_list, index);
260 trans_delete(ltrans);
261 }
262 list_clear(self->trans_list);
263 return 0;
264 }
265
266 /*****************************************************************************/
267 static int
268 xrdp_listen_parse_filename(char *strout, int strout_max,
269 const char *strin, int strin_max)
270 {
271 int count;
272 int in;
273 int strin_index;
274 int strout_index;
275
276 strin_index = 0;
277 strout_index = 0;
278 in = 0;
279 count = 0;
280 while ((strin_index < strin_max) && (strout_index < strout_max))
281 {
282 if (in)
283 {
284 if ((strin[strin_index] > ' ') && (strin[strin_index] != ','))
285 {
286 strout[strout_index++] = strin[strin_index++];
287 count++;
288 continue;
289 }
290 else
291 {
292 break;
293 }
294 }
295 else
296 {
297 if ((strin[strin_index] > ' ') && (strin[strin_index] != ','))
298 {
299 in = 1;
300 strout[strout_index++] = strin[strin_index++];
301 count++;
302 continue;
303 }
304 }
305 strin_index++;
306 count++;
307 }
308 strout[strout_index] = 0;
309 return count;
310 }
311
312 /*****************************************************************************/
313 static int
314 xrdp_listen_parse_integer(char *strout, int strout_max,
315 const char *strin, int strin_max)
316 {
317 int count;
318 int in;
319 int strin_index;
320 int strout_index;
321
322 strin_index = 0;
323 strout_index = 0;
324 in = 0;
325 count = 0;
326 while ((strin_index < strin_max) && (strout_index < strout_max))
327 {
328 if (in)
329 {
330 if ((strin[strin_index] >= '0') && (strin[strin_index] <= '9'))
331 {
332 strout[strout_index++] = strin[strin_index++];
333 count++;
334 continue;
335 }
336 else
337 {
338 break;
339 }
340 }
341 else
342 {
343 if ((strin[strin_index] >= '0') && (strin[strin_index] <= '9'))
344 {
345 in = 1;
346 strout[strout_index++] = strin[strin_index++];
347 count++;
348 continue;
349 }
350 }
351 strin_index++;
352 count++;
353 }
354 strout[strout_index] = 0;
355 return count;
356 }
357
358 /*****************************************************************************/
359 static int
360 xrdp_listen_parse_vsock(char *strout, int strout_max,
361 const char *strin, int strin_max)
362 {
363 int count;
364 int in;
365 int strin_index;
366 int strout_index;
367
368 strin_index = 0;
369 strout_index = 0;
370 in = 0;
371 count = 0;
372 while ((strin_index < strin_max) && (strout_index < strout_max))
373 {
374 if (in)
375 {
376 if ((strin[strin_index] >= '0') && (strin[strin_index] <= '9'))
377 {
378 strout[strout_index++] = strin[strin_index++];
379 count++;
380 continue;
381 }
382 else
383 {
384 break;
385 }
386 }
387 else
388 {
389 if (((strin[strin_index] >= '0') && (strin[strin_index] <= '9')) ||
390 (strin[strin_index] == '-'))
391 {
392 in = 1;
393 strout[strout_index++] = strin[strin_index++];
394 count++;
395 continue;
396 }
397 }
398 strin_index++;
399 count++;
400 }
401 strout[strout_index] = 0;
402 return count;
403 }
404
405 /*****************************************************************************/
406 static int
407 xrdp_listen_parse_ipv4(char *strout, int strout_max,
408 const char *strin, int strin_max)
409 {
410 int count;
411 int in;
412 int strin_index;
413 int strout_index;
414
415 strin_index = 0;
416 strout_index = 0;
417 in = 0;
418 count = 0;
419 while ((strin_index < strin_max) && (strout_index < strout_max))
420 {
421 if (in)
422 {
423 if (((strin[strin_index] >= '0') && (strin[strin_index] <= '9')) ||
424 (strin[strin_index] == '.'))
425 {
426 strout[strout_index++] = strin[strin_index++];
427 count++;
428 continue;
429 }
430 else
431 {
432 break;
433 }
434 }
435 else
436 {
437 if ((strin[strin_index] >= '0') && (strin[strin_index] <= '9'))
438 {
439 in = 1;
440 strout[strout_index++] = strin[strin_index++];
441 count++;
442 continue;
443 }
444 }
445 strin_index++;
446 count++;
447 }
448 strout[strout_index] = 0;
449 return count;
450 }
451
452 /*****************************************************************************/
453 static int
454 xrdp_listen_parse_ipv6(char *strout, int strout_max,
455 const char *strin, int strin_max)
456 {
457 int count;
458 int in;
459 int strin_index;
460 int strout_index;
461
462 strin_index = 0;
463 strout_index = 0;
464 in = 0;
465 count = 0;
466 while ((strin_index < strin_max) && (strout_index < strout_max))
467 {
468 if (in)
469 {
470 if (strin[strin_index] != '}')
471 {
472 strout[strout_index++] = strin[strin_index++];
473 count++;
474 continue;
475 }
476 else
477 {
478 break;
479 }
480 }
481 else
482 {
483 if (strin[strin_index] == '{')
484 {
485 in = 1;
486 strin_index++;
487 count++;
488 continue;
489 }
490 }
491 strin_index++;
492 count++;
493 }
494 strout[strout_index] = 0;
495 return count;
496 }
497
498 /*****************************************************************************/
499 /* address and port are assumed 128 bytes */
500 static int
501 xrdp_listen_pp(struct xrdp_listen *self, int *index,
502 char *address, char *port, int *mode)
503 {
504 struct xrdp_startup_params *startup_params;
505 const char *str;
506 const char *str_end;
507 int lindex;
508 int bytes;
509
510 startup_params = self->startup_params;
511 lindex = *index;
512 str = startup_params->port + lindex;
513 str_end = startup_params->port + g_strlen(startup_params->port);
514 while (str < str_end)
515 {
516 if (g_strncmp(str, "unix://.", 8) == 0)
517 {
518 str += 8;
519 lindex += 8;
520 address[0] = 0;
521 bytes = xrdp_listen_parse_filename(port, 128, str, str_end - str);
522 str += bytes;
523 lindex += bytes;
524 *mode = TRANS_MODE_UNIX;
525 *index = lindex;
526 return 0;
527 }
528 else if (g_strncmp(str, "tcp://.:", 8) == 0)
529 {
530 str += 8;
531 lindex += 8;
532 g_strncpy(address, "127.0.0.1", 127);
533 bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str);
534 str += bytes;
535 lindex += bytes;
536 *mode = TRANS_MODE_TCP4;
537 *index = lindex;
538 return 0;
539 }
540 else if (g_strncmp(str, "tcp://:", 7) == 0)
541 {
542 str += 7;
543 lindex += 7;
544 g_strncpy(address, "0.0.0.0", 127);
545 bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str);
546 str += bytes;
547 lindex += bytes;
548 *mode = TRANS_MODE_TCP4;
549 *index = lindex;
550 return 0;
551 }
552 else if (g_strncmp(str, "tcp://", 6) == 0)
553 {
554 str += 6;
555 lindex += 6;
556 bytes = xrdp_listen_parse_ipv4(address, 128, str, str_end - str);
557 str += bytes;
558 lindex += bytes;
559 bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str);
560 str += bytes;
561 lindex += bytes;
562 *mode = TRANS_MODE_TCP4;
563 *index = lindex;
564 return 0;
565 }
566 else if (g_strncmp(str, "tcp6://.:", 9) == 0)
567 {
568 str += 9;
569 lindex += 9;
570 g_strncpy(address, "::1", 127);
571 bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str);
572 str += bytes;
573 lindex += bytes;
574 *mode = TRANS_MODE_TCP6;
575 *index = lindex;
576 return 0;
577 }
578 else if (g_strncmp(str, "tcp6://:", 8) == 0)
579 {
580 str += 8;
581 lindex += 8;
582 g_strncpy(address, "::", 127);
583 bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str);
584 str += bytes;
585 lindex += bytes;
586 *mode = TRANS_MODE_TCP6;
587 *index = lindex;
588 return 0;
589 }
590 else if (g_strncmp(str, "tcp6://", 7) == 0)
591 {
592 str += 7;
593 lindex += 7;
594 bytes = xrdp_listen_parse_ipv6(address, 128, str, str_end - str);
595 str += bytes;
596 lindex += bytes;
597 bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str);
598 str += bytes;
599 lindex += bytes;
600 *mode = TRANS_MODE_TCP6;
601 *index = lindex;
602 return 0;
603 }
604 else if (g_strncmp(str, "vsock://", 8) == 0)
605 {
606 str += 8;
607 lindex += 8;
608 bytes = xrdp_listen_parse_vsock(address, 128, str, str_end - str);
609 str += bytes;
610 lindex += bytes;
611 bytes = xrdp_listen_parse_vsock(port, 128, str, str_end - str);
612 str += bytes;
613 lindex += bytes;
614 *mode = TRANS_MODE_VSOCK;
615 *index = lindex;
616 return 0;
617 }
618 else if ((str[0] >= '0') && (str[0] <= '9'))
619 {
620 g_strncpy(address, "0.0.0.0", 127);
621 bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str);
622 str += bytes;
623 lindex += bytes;
624 if (startup_params->use_vsock)
625 {
626 *mode = TRANS_MODE_VSOCK;
627 }
628 else
629 {
630 *mode = TRANS_MODE_TCP;
631 }
632 *index = lindex;
633 return 0;
634 }
635 else
636 {
637 str++;
638 lindex++;
639 }
640 }
641 if (lindex == *index)
642 {
643 return 1;
644 }
645 if (str >= str_end)
646 {
647 return 1;
648 }
649 *index = lindex;
650 return 0;
651 }
652
653 /*****************************************************************************/
654 static int
655 xrdp_listen_process_startup_params(struct xrdp_listen *self)
656 {
657 int mode; /* TRANS_MODE_TCP*, TRANS_MODE_UNIX, TRANS_MODE_VSOCK */
658 int error;
659 int cont;
660 int bytes;
661 int index;
662 struct trans *ltrans;
663 char address[128];
664 char port[128];
665 struct xrdp_startup_params *startup_params;
666
667 startup_params = self->startup_params;
668 index = 0;
669 cont = 1;
670 while (cont)
671 {
672 if (xrdp_listen_pp(self, &index, address, port, &mode) != 0)
673 {
674 log_message(LOG_LEVEL_INFO, "xrdp_listen_pp done");
675 cont = 0;
676 break;
677 }
678 log_message(LOG_LEVEL_INFO, "address [%s] port [%s] mode %d",
679 address, port, mode);
680 ltrans = trans_create(mode, 16, 16);
681 if (ltrans == NULL)
682 {
683 log_message(LOG_LEVEL_ERROR, "trans_create failed");
684 xrdp_listen_stop_all_listen(self);
685 return 1;
686 }
687 log_message(LOG_LEVEL_INFO, "listening to port %s on %s",
688 port, address);
689 error = trans_listen_address(ltrans, port, address);
690 if (error != 0)
691 {
692 log_message(LOG_LEVEL_ERROR, "trans_listen_address failed");
693 trans_delete(ltrans);
694 xrdp_listen_stop_all_listen(self);
695 return 1;
696 }
697 if ((mode == TRANS_MODE_TCP) ||
698 (mode == TRANS_MODE_TCP4) ||
699 (mode == TRANS_MODE_TCP6))
700 {
701 if (startup_params->tcp_nodelay)
702 {
703 if (g_tcp_set_no_delay(ltrans->sck))
704 {
705 log_message(LOG_LEVEL_ERROR, "Error setting tcp_nodelay");
706 }
707 }
708 if (startup_params->tcp_keepalive)
709 {
710 if (g_tcp_set_keepalive(ltrans->sck))
711 {
712 log_message(LOG_LEVEL_ERROR, "Error setting "
713 "tcp_keepalive");
714 }
715 }
716 if (startup_params->tcp_send_buffer_bytes > 0)
717 {
718 bytes = startup_params->tcp_send_buffer_bytes;
719 log_message(LOG_LEVEL_INFO, "setting send buffer to %d bytes",
720 bytes);
721 if (g_sck_set_send_buffer_bytes(ltrans->sck, bytes) != 0)
722 {
723 log_message(LOG_LEVEL_ERROR, "error setting send buffer");
724 }
725 else
726 {
727 if (g_sck_get_send_buffer_bytes(ltrans->sck, &bytes) != 0)
728 {
729 log_message(LOG_LEVEL_ERROR, "error getting send "
730 "buffer");
731 }
732 else
733 {
734 log_message(LOG_LEVEL_INFO, "send buffer set to %d "
735 "bytes", bytes);
736 }
737 }
738 }
739 if (startup_params->tcp_recv_buffer_bytes > 0)
740 {
741 bytes = startup_params->tcp_recv_buffer_bytes;
742 log_message(LOG_LEVEL_INFO, "setting recv buffer to %d bytes",
743 bytes);
744 if (g_sck_set_recv_buffer_bytes(ltrans->sck, bytes) != 0)
745 {
746 log_message(LOG_LEVEL_ERROR, "error setting recv buffer");
747 }
748 else
749 {
750 if (g_sck_get_recv_buffer_bytes(ltrans->sck, &bytes) != 0)
751 {
752 log_message(LOG_LEVEL_ERROR, "error getting recv "
753 "buffer");
754 }
755 else
756 {
757 log_message(LOG_LEVEL_INFO, "recv buffer set to %d "
758 "bytes", bytes);
759 }
760 }
761 }
762 }
763 ltrans->trans_conn_in = xrdp_listen_conn_in;
764 ltrans->callback_data = self;
765 list_add_item(self->trans_list, (intptr_t) ltrans);
766 }
268767 return 0;
269768 }
270769
273772 xrdp_listen_fork(struct xrdp_listen *self, struct trans *server_trans)
274773 {
275774 int pid;
775 int index;
276776 struct xrdp_process *process;
777 struct trans *ltrans;
277778
278779 pid = g_fork();
279780
287788 g_close_wait_obj(self->pro_done_event);
288789 xrdp_listen_create_pro_done(self);
289790 /* delete listener, child need not listen */
290 trans_delete_from_child(self->listen_trans);
291 self->listen_trans = 0;
791 for (index = 0; index < self->trans_list->count; index++)
792 {
793 ltrans = (struct trans *) list_get_item(self->trans_list, index);
794 trans_delete_from_child(ltrans);
795 }
796 list_delete(self->trans_list);
797 self->trans_list = NULL;
292798 /* new connect instance */
293799 process = xrdp_process_create(self, 0);
294800 process->server_trans = server_trans;
295801 g_process = process;
296802 xrdp_process_run(0);
803 tc_sem_dec(g_process_sem);
297804 xrdp_process_delete(process);
298805 /* mark this process to exit */
299806 g_set_term(1);
300 return 0;
807 return 1;
301808 }
302809
303810 /* parent */
317824
318825 if (lis->startup_params->fork)
319826 {
320 return xrdp_listen_fork(lis, new_self);
827 list_add_item(lis->fork_list, (intptr_t) new_self);
828 return 0;
321829 }
322830
323831 process = xrdp_process_create(lis, lis->pro_done_event);
344852 int
345853 xrdp_listen_main_loop(struct xrdp_listen *self)
346854 {
347 int error;
348855 int robjs_count;
349856 int cont;
350 int timeout = 0;
351 char port[128];
352 char address[256];
353 tbus robjs[8];
354 tbus term_obj;
355 tbus sync_obj;
356 tbus done_obj;
357 int tcp_nodelay;
358 int tcp_keepalive;
359 int bytes;
857 int index;
858 int timeout;
859 intptr_t robjs[32];
860 intptr_t term_obj;
861 intptr_t sync_obj;
862 intptr_t done_obj;
863 struct trans *ltrans;
360864
361865 self->status = 1;
362
363 if (xrdp_listen_get_port_address(port, sizeof(port),
364 address, sizeof(address),
365 &tcp_nodelay, &tcp_keepalive,
366 &self->listen_trans->mode,
367 self->startup_params) != 0)
866 if (xrdp_listen_get_startup_params(self) != 0)
368867 {
369868 log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: xrdp_listen_get_port failed");
370869 self->status = -1;
371870 return 1;
372871 }
373
374 if (port[0] == '/')
375 {
376 /* set UDS mode */
377 self->listen_trans->mode = TRANS_MODE_UNIX;
378 /* not valid with UDS */
379 tcp_nodelay = 0;
380 }
381 else if (self->listen_trans->mode == TRANS_MODE_VSOCK)
382 {
383 /* not valid with VSOCK */
384 tcp_nodelay = 0;
385 }
386
387 /* Create socket */
388 error = trans_listen_address(self->listen_trans, port, address);
389 if (port[0] == '/')
390 {
391 g_chmod_hex(port, 0x0666);
392 }
393
394 if (error == 0)
395 {
396 log_message(LOG_LEVEL_INFO, "listening to port %s on %s",
397 port, address);
398 if (tcp_nodelay)
399 {
400 if (g_tcp_set_no_delay(self->listen_trans->sck))
401 {
402 log_message(LOG_LEVEL_ERROR,"Error setting tcp_nodelay");
403 }
404 }
405
406 if (tcp_keepalive)
407 {
408 if (g_tcp_set_keepalive(self->listen_trans->sck))
409 {
410 log_message(LOG_LEVEL_ERROR,"Error setting tcp_keepalive");
411 }
412 }
413
414 if (self->startup_params->send_buffer_bytes > 0)
415 {
416 bytes = self->startup_params->send_buffer_bytes;
417 log_message(LOG_LEVEL_INFO, "setting send buffer to %d bytes",
418 bytes);
419 if (g_sck_set_send_buffer_bytes(self->listen_trans->sck,
420 bytes) != 0)
421 {
422 log_message(LOG_LEVEL_ERROR, "error setting send buffer");
423 }
424 else
425 {
426 if (g_sck_get_send_buffer_bytes(self->listen_trans->sck,
427 &bytes) != 0)
428 {
429 log_message(LOG_LEVEL_ERROR, "error getting send buffer");
430 }
431 else
432 {
433 log_message(LOG_LEVEL_INFO, "send buffer set to %d bytes", bytes);
434 }
435 }
436 }
437
438 if (self->startup_params->recv_buffer_bytes > 0)
439 {
440 bytes = self->startup_params->recv_buffer_bytes;
441 log_message(LOG_LEVEL_INFO, "setting recv buffer to %d bytes",
442 bytes);
443 if (g_sck_set_recv_buffer_bytes(self->listen_trans->sck,
444 bytes) != 0)
445 {
446 log_message(LOG_LEVEL_ERROR, "error setting recv buffer");
447 }
448 else
449 {
450 if (g_sck_get_recv_buffer_bytes(self->listen_trans->sck,
451 &bytes) != 0)
452 {
453 log_message(LOG_LEVEL_ERROR, "error getting recv buffer");
454 }
455 else
456 {
457 log_message(LOG_LEVEL_INFO, "recv buffer set to %d bytes", bytes);
458 }
459 }
460 }
461
462 self->listen_trans->trans_conn_in = xrdp_listen_conn_in;
463 self->listen_trans->callback_data = self;
464 term_obj = g_get_term_event(); /*Global termination event */
465 sync_obj = g_get_sync_event();
466 done_obj = self->pro_done_event;
467 cont = 1;
468
469 while (cont)
470 {
471 /* build the wait obj list */
472 robjs_count = 0;
473 robjs[robjs_count++] = term_obj;
474 robjs[robjs_count++] = sync_obj;
475 robjs[robjs_count++] = done_obj;
476 timeout = -1;
477
478 if (trans_get_wait_objs(self->listen_trans, robjs,
479 &robjs_count) != 0)
480 {
872 if (xrdp_listen_process_startup_params(self) != 0)
873 {
874 log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: xrdp_listen_get_port failed");
875 self->status = -1;
876 return 1;
877 }
878 term_obj = g_get_term_event(); /*Global termination event */
879 sync_obj = g_get_sync_event();
880 done_obj = self->pro_done_event;
881 cont = 1;
882 while (cont)
883 {
884 /* build the wait obj list */
885 robjs_count = 0;
886 robjs[robjs_count++] = term_obj;
887 robjs[robjs_count++] = sync_obj;
888 robjs[robjs_count++] = done_obj;
889 timeout = -1;
890
891 for (index = 0; index < self->trans_list->count; index++)
892 {
893 ltrans = (struct trans *)
894 list_get_item(self->trans_list, index);
895 if (trans_get_wait_objs(ltrans, robjs, &robjs_count) != 0)
896 {
897 cont = 0;
481898 break;
482899 }
483
484 /* wait - timeout -1 means wait indefinitely*/
485 if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
486 {
487 /* error, should not get here */
488 g_sleep(100);
489 }
490
491 if (g_is_wait_obj_set(term_obj)) /* termination called */
492 {
900 }
901 if (cont == 0)
902 {
903 break;
904 }
905
906 /* wait - timeout -1 means wait indefinitely*/
907 if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
908 {
909 /* error, should not get here */
910 g_sleep(100);
911 }
912
913 if (g_is_wait_obj_set(term_obj)) /* termination called */
914 {
915 break;
916 }
917
918 /* some function must be processed by this thread */
919 if (g_is_wait_obj_set(sync_obj))
920 {
921 g_reset_wait_obj(sync_obj);
922 g_process_waiting_function(); /* run the function */
923 }
924
925 if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
926 {
927 g_reset_wait_obj(done_obj);
928 /* a process has died remove it from lists*/
929 xrdp_listen_delete_done_pro(self);
930 }
931
932 /* Run the callback when accept() returns a new socket*/
933 for (index = 0; index < self->trans_list->count; index++)
934 {
935 ltrans = (struct trans *)
936 list_get_item(self->trans_list, index);
937 if (trans_check_wait_objs(ltrans) != 0)
938 {
939 cont = 0;
493940 break;
494941 }
495
496 /* some function must be processed by this thread */
497 if (g_is_wait_obj_set(sync_obj))
498 {
499 g_reset_wait_obj(sync_obj);
500 g_process_waiting_function(); /* run the function */
501 }
502
503 if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
504 {
505 g_reset_wait_obj(done_obj);
506 /* a process has died remove it from lists*/
507 xrdp_listen_delete_done_pro(self);
508 }
509
510 /* Run the callback when accept() returns a new socket*/
511 if (trans_check_wait_objs(self->listen_trans) != 0)
512 {
942 }
943 if (cont == 0)
944 {
945 break;
946 }
947 while (self->fork_list->count > 0)
948 {
949 ltrans = (struct trans *) list_get_item(self->fork_list, 0);
950 list_remove_item(self->fork_list, 0);
951 if (xrdp_listen_fork(self, ltrans) != 0)
952 {
953 cont = 0;
513954 break;
514955 }
515956 }
516
517 /* stop listening */
518 trans_delete(self->listen_trans);
519 self->listen_trans = 0;
520 /* second loop to wait for all process threads to close */
521 cont = 1;
522
523 while (cont)
524 {
525 if (self->process_list->count == 0)
526 {
527 break;
528 }
529
530 timeout = -1;
531 /* build the wait obj list */
532 robjs_count = 0;
533 robjs[robjs_count++] = sync_obj;
534 robjs[robjs_count++] = done_obj;
535
536 /* wait - timeout -1 means wait indefinitely*/
537 if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
538 {
539 /* error, should not get here */
540 g_sleep(100);
541 }
542
543 /* some function must be processed by this thread */
544 if (g_is_wait_obj_set(sync_obj))
545 {
546 g_reset_wait_obj(sync_obj);
547 g_process_waiting_function(); /* run the function that is waiting*/
548 }
549
550 if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
551 {
552 g_reset_wait_obj(done_obj);
553 xrdp_listen_delete_done_pro(self);
554 }
555 }
556 }
557 else
558 {
559 log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: listen error, possible port "
560 "already in use");
561 #if !defined(XRDP_ENABLE_VSOCK)
562 if (self->listen_trans->mode == TRANS_MODE_VSOCK)
563 {
564 log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: listen error, "
565 "vsock support not compiled and config requested");
566 }
567 #endif
957 if (cont == 0)
958 {
959 break;
960 }
961 }
962
963 /* stop listening */
964 xrdp_listen_stop_all_listen(self);
965
966 /* second loop to wait for all process threads to close */
967 cont = 1;
968
969 while (cont)
970 {
971 if (self->process_list->count == 0)
972 {
973 break;
974 }
975
976 timeout = -1;
977 /* build the wait obj list */
978 robjs_count = 0;
979 robjs[robjs_count++] = sync_obj;
980 robjs[robjs_count++] = done_obj;
981
982 /* wait - timeout -1 means wait indefinitely*/
983 if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
984 {
985 /* error, should not get here */
986 g_sleep(100);
987 }
988
989 /* some function must be processed by this thread */
990 if (g_is_wait_obj_set(sync_obj))
991 {
992 g_reset_wait_obj(sync_obj);
993 g_process_waiting_function(); /* run the function that is waiting*/
994 }
995
996 if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
997 {
998 g_reset_wait_obj(done_obj);
999 xrdp_listen_delete_done_pro(self);
1000 }
5681001 }
5691002
5701003 self->status = -1;
571 return error;
1004 return 0;
5721005 }
5731006
5741007 /*****************************************************************************/
5751008 /* returns 0 if xrdp can listen
5761009 returns 1 if xrdp cannot listen */
5771010 int
578 xrdp_listen_test(void)
579 {
580 int rv = 0;
581 char port[128];
582 int mode;
583 char address[256];
584 int tcp_nodelay;
585 int tcp_keepalive;
1011 xrdp_listen_test(struct xrdp_startup_params *startup_params)
1012 {
5861013 struct xrdp_listen *xrdp_listen;
587 struct xrdp_startup_params *startup_params;
588
589
590 startup_params = (struct xrdp_startup_params *)
591 g_malloc(sizeof(struct xrdp_startup_params), 1);
1014
5921015 xrdp_listen = xrdp_listen_create();
5931016 xrdp_listen->startup_params = startup_params;
594
595
596 if (xrdp_listen_get_port_address(port, sizeof(port),
597 address, sizeof(address),
598 &tcp_nodelay, &tcp_keepalive,
599 &mode,
600 xrdp_listen->startup_params) != 0)
601 {
602 log_message(LOG_LEVEL_DEBUG, "xrdp_listen_test: "
603 "xrdp_listen_get_port_address failed");
604 rv = 1;
605 goto done;
606 }
607
608 /* try to listen */
609 log_message(LOG_LEVEL_DEBUG, "Testing if xrdp can listen on %s port %s.",
610 address, port);
611 rv = trans_listen_address(xrdp_listen->listen_trans, port, address);
612 if (rv == 0)
613 {
614 /* if listen succeeded, stop listen immediately */
615 trans_delete(xrdp_listen->listen_trans);
616 xrdp_listen->listen_trans = 0;
617 }
618
619 goto done;
620
621 done:
1017 if (xrdp_listen_get_startup_params(xrdp_listen) != 0)
1018 {
1019 xrdp_listen_delete(xrdp_listen);
1020 return 1;
1021 }
1022 if (xrdp_listen_process_startup_params(xrdp_listen) != 0)
1023 {
1024 xrdp_listen_delete(xrdp_listen);
1025 return 1;
1026 }
6221027 xrdp_listen_delete(xrdp_listen);
623 g_free(startup_params);
624 return rv;
625 }
1028 return 0;
1029 }
998998 return 0;
999999 }
10001000
1001 /******************************************************************************/
1002 int
1003 xrdp_mm_suppress_output(struct xrdp_mm* self, int suppress,
1004 int left, int top, int right, int bottom)
1005 {
1006 LLOGLN(0, ("xrdp_mm_suppress_output: suppress %d "
1007 "left %d top %d right %d bottom %d",
1008 suppress, left, top, right, bottom));
1009 if (self->mod != NULL)
1010 {
1011 if (self->mod->mod_suppress_output != NULL)
1012 {
1013 self->mod->mod_suppress_output(self->mod, suppress,
1014 left, top, right, bottom);
1015 }
1016 }
1017 return 0;
1018 }
1019
10011020 /*****************************************************************************/
10021021 /* open response from client going to channel server */
10031022 static int
14101429
14111430 self->usechansrv = 1;
14121431
1432 if (self->wm->client_info->channels_allowed == 0)
1433 {
1434 log_message(LOG_LEVEL_DEBUG, "%s: "
1435 "skip connecting to chansrv because all channels are disabled",
1436 __func__);
1437 return 0;
1438 }
1439
14131440 /* connect channel redir */
14141441 if ((g_strcmp(ip, "127.0.0.1") == 0) || (ip[0] == 0))
14151442 {
14391466 self->chan_trans_up = 1;
14401467 break;
14411468 }
1442
1469 if (g_is_term())
1470 {
1471 break;
1472 }
14431473 g_sleep(1000);
14441474 log_message(LOG_LEVEL_ERROR,"xrdp_mm_connect_chansrv: connect failed "
14451475 "trying again...");
22742304 ok = 1;
22752305 break;
22762306 }
2277
2307 if (g_is_term())
2308 {
2309 break;
2310 }
22782311 g_sleep(1000);
22792312 g_writeln("xrdp_mm_connect: connect failed "
22802313 "trying again...");
4747 tbus* write_objs, int* wcount, int* timeout);
4848 int (*mod_check_wait_objs)(struct xrdp_mod* v);
4949 int (*mod_frame_ack)(struct xrdp_mod* v, int flags, int frame_id);
50 tintptr mod_dumby[100 - 10]; /* align, 100 minus the number of mod
50 int (*mod_suppress_output)(struct xrdp_mod* v, int suppress,
51 int left, int top, int right, int bottom);
52 tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
5153 functions above */
5254 /* server functions */
5355 int (*server_begin_update)(struct xrdp_mod* v);
402404 struct xrdp_listen
403405 {
404406 int status;
405 struct trans* listen_trans; /* in tcp listen mode */
406 struct list* process_list;
407 struct list *trans_list; /* list of struct trans* */
408 struct list *process_list;
409 struct list *fork_list;
407410 tbus pro_done_event;
408411 struct xrdp_startup_params* startup_params;
409412 };
524527
525528 struct xrdp_startup_params
526529 {
527 char port[128];
530 char port[1024];
528531 int kill;
529532 int no_daemon;
530533 int help;
531534 int version;
532535 int fork;
533 int send_buffer_bytes;
534 int recv_buffer_bytes;
536 int tcp_send_buffer_bytes;
537 int tcp_recv_buffer_bytes;
538 int tcp_nodelay;
539 int tcp_keepalive;
540 int use_vsock;
535541 };
536542
537543 /*
19151915 case 0x5558:
19161916 xrdp_mm_drdynvc_up(wm->mm);
19171917 break;
1918 case 0x5559:
1919 xrdp_mm_suppress_output(wm->mm, param1,
1920 LOWORD(param2), HIWORD(param2),
1921 LOWORD(param3), HIWORD(param3));
1922 break;
19181923 }
19191924 return rv;
19201925 }
350350 g_writeln("%s", "");
351351 g_writeln("xrdp: A Remote Desktop Protocol server.");
352352 g_writeln("Copyright (C) Jay Sorg 2004-2011");
353 g_writeln("See http://xrdp.sourceforge.net for more information.");
353 g_writeln("See http://www.xrdp.org for more information.");
354354 g_writeln("%s", "");
355355 g_writeln("Usage: xrdp [options]");
356356 g_writeln(" -h: show help");
505505 g_writeln("%s", "");
506506 g_writeln("xrdp: A Remote Desktop Protocol server.");
507507 g_writeln("Copyright (C) Jay Sorg 2004-2011");
508 g_writeln("See http://xrdp.sourceforge.net for more information.");
508 g_writeln("See http://www.xrdp.org for more information.");
509509 g_writeln("%s", "");
510510 g_writeln("Usage: xrdp [options]");
511511 g_writeln(" -h: show help");
520520 g_writeln("%s", "");
521521 g_writeln("xrdp: A Remote Desktop Protocol server.");
522522 g_writeln("Copyright (C) Jay Sorg 2004-2011");
523 g_writeln("See http://xrdp.sourceforge.net for more information.");
523 g_writeln("See http://www.xrdp.org for more information.");
524524 g_writeln("Version %s", PACKAGE_VERSION);
525525 g_writeln("%s", "");
526526 g_exit(0);
225225 break;
226226 }
227227
228 if (mod->server_is_term(mod))
229 {
230 break;
231 }
232
228233 i++;
229234
230235 if (i >= 60)
11051110 amod->screen_shmem_id_mapped = 1;
11061111 }
11071112 }
1113 else if (amod->screen_shmem_id != shmem_id)
1114 {
1115 amod->screen_shmem_id = shmem_id;
1116 g_shmdt(amod->screen_shmem_pixels);
1117 amod->screen_shmem_pixels = (char *) g_shmat(amod->screen_shmem_id);
1118 if (amod->screen_shmem_pixels == (void*)-1)
1119 {
1120 /* failed */
1121 amod->screen_shmem_id = 0;
1122 amod->screen_shmem_pixels = 0;
1123 amod->screen_shmem_id_mapped = 0;
1124 }
1125 }
11081126 if (amod->screen_shmem_pixels != 0)
11091127 {
11101128 bmpdata = amod->screen_shmem_pixels + shmem_offset;
11451163 /******************************************************************************/
11461164 /* return error */
11471165 static int
1166 send_suppress_output(struct mod *mod, int suppress,
1167 int left, int top, int right, int bottom)
1168 {
1169 int len;
1170 struct stream *s;
1171
1172 make_stream(s);
1173 init_stream(s, 8192);
1174 s_push_layer(s, iso_hdr, 4);
1175 out_uint16_le(s, 108);
1176 out_uint32_le(s, suppress);
1177 out_uint32_le(s, left);
1178 out_uint32_le(s, top);
1179 out_uint32_le(s, right);
1180 out_uint32_le(s, bottom);
1181 s_mark_end(s);
1182 len = (int)(s->end - s->data);
1183 s_pop_layer(s, iso_hdr);
1184 out_uint32_le(s, len);
1185 lib_send_copy(mod, s);
1186 free_stream(s);
1187 return 0;
1188 }
1189
1190 /******************************************************************************/
1191 /* return error */
1192 static int
11481193 process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
11491194 {
11501195 int num_drects;
12141259 else
12151260 {
12161261 amod->screen_shmem_id_mapped = 1;
1262 }
1263 }
1264 else if (amod->screen_shmem_id != shmem_id)
1265 {
1266 amod->screen_shmem_id = shmem_id;
1267 g_shmdt(amod->screen_shmem_pixels);
1268 amod->screen_shmem_pixels = (char *) g_shmat(amod->screen_shmem_id);
1269 if (amod->screen_shmem_pixels == (void*)-1)
1270 {
1271 /* failed */
1272 amod->screen_shmem_id = 0;
1273 amod->screen_shmem_pixels = 0;
1274 amod->screen_shmem_id_mapped = 0;
12171275 }
12181276 }
12191277 if (amod->screen_shmem_pixels != 0)
15561614 }
15571615
15581616 /******************************************************************************/
1617 /* return error */
1618 int
1619 lib_mod_suppress_output(struct mod *amod, int suppress,
1620 int left, int top, int right, int bottom)
1621 {
1622 LLOGLN(10, ("lib_mod_suppress_output: suppress 0x%8.8x left %d top %d "
1623 "right %d bottom %d", suppress, left, top, right, bottom));
1624 send_suppress_output(amod, suppress, left, top, right, bottom);
1625 return 0;
1626 }
1627
1628 /******************************************************************************/
15591629 tintptr EXPORT_CC
15601630 mod_init(void)
15611631 {
15741644 mod->mod_get_wait_objs = lib_mod_get_wait_objs;
15751645 mod->mod_check_wait_objs = lib_mod_check_wait_objs;
15761646 mod->mod_frame_ack = lib_mod_frame_ack;
1647 mod->mod_suppress_output = lib_mod_suppress_output;
15771648 return (tintptr) mod;
15781649 }
15791650
2525 #include "xrdp_client_info.h"
2626 #include "xrdp_rail.h"
2727
28 #define CURRENT_MOD_VER 3
28 #define CURRENT_MOD_VER 4
2929
3030 struct mod
3131 {
4444 tbus* write_objs, int* wcount, int* timeout);
4545 int (*mod_check_wait_objs)(struct mod* v);
4646 int (*mod_frame_ack)(struct mod* v, int flags, int frame_id);
47 tintptr mod_dumby[100 - 10]; /* align, 100 minus the number of mod
47 int (*mod_suppress_output)(struct mod* v, int suppress,
48 int left, int top, int right, int bottom);
49 tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
4850 functions above */
4951 /* server functions */
5052 int (*server_begin_update)(struct mod* v);