FreeRDP
Loading...
Searching...
No Matches
TestRailHandshake.c
1
18#include <stdio.h>
19#include <winpr/crt.h>
20#include <freerdp/client.h>
21#include <freerdp/client/channels.h>
22#include <freerdp/client/rail.h>
23#include <freerdp/svc.h>
24
25static PCHANNEL_INIT_EVENT_EX_FN g_initEvent = nullptr;
26static LPVOID g_userParam = nullptr;
27static RailClientContext* g_rail = nullptr;
28static int g_initHandle = 0;
29static UINT g_events[2] = WINPR_C_ARRAY_INIT;
30static size_t g_eventCount = 0;
31static UINT32 g_flags = 0;
32static UINT32 g_build = 0;
33static BOOL g_failHandshake = FALSE;
34static BOOL g_failStatus = FALSE;
35static size_t g_execCount = 0;
36
37static UINT VCAPITYPE test_init_ex(LPVOID userParam, LPVOID clientContext,
38 WINPR_ATTR_UNUSED LPVOID initHandle,
39 WINPR_ATTR_UNUSED PCHANNEL_DEF channel,
40 WINPR_ATTR_UNUSED INT channelCount,
41 WINPR_ATTR_UNUSED ULONG version,
42 PCHANNEL_INIT_EVENT_EX_FN initEvent)
43{
44 g_userParam = userParam;
45 g_rail = clientContext;
46 g_initEvent = initEvent;
47 return CHANNEL_RC_OK;
48}
49
50static UINT test_handshake(WINPR_ATTR_UNUSED RailClientContext* context,
51 const RAIL_HANDSHAKE_ORDER* handshake)
52{
53 if (g_eventCount >= ARRAYSIZE(g_events))
54 return ERROR_INTERNAL_ERROR;
55 g_events[g_eventCount++] = TS_RAIL_ORDER_HANDSHAKE;
56 g_build = handshake->buildNumber;
57 return g_failHandshake ? ERROR_INTERNAL_ERROR : CHANNEL_RC_OK;
58}
59
60static UINT test_status(WINPR_ATTR_UNUSED RailClientContext* context,
61 const RAIL_CLIENT_STATUS_ORDER* status)
62{
63 if (g_eventCount >= ARRAYSIZE(g_events))
64 return ERROR_INTERNAL_ERROR;
65 g_events[g_eventCount++] = TS_RAIL_ORDER_CLIENTSTATUS;
66 g_flags = status->flags;
67 return g_failStatus ? ERROR_INTERNAL_ERROR : CHANNEL_RC_OK;
68}
69
70static UINT test_sysparam(WINPR_ATTR_UNUSED RailClientContext* context,
71 WINPR_ATTR_UNUSED const RAIL_SYSPARAM_ORDER* sysparam)
72{
73 return CHANNEL_RC_OK;
74}
75
76static UINT test_execute(WINPR_ATTR_UNUSED RailClientContext* context,
77 WINPR_ATTR_UNUSED const RAIL_EXEC_ORDER* exec)
78{
79 g_execCount++;
80 return CHANNEL_RC_OK;
81}
82
83static BOOL check_handshake(rdpSettings* settings, BOOL extended, BOOL reconnect, UINT32 flags,
84 BOOL failHandshake, BOOL failStatus)
85{
86 if (!freerdp_settings_set_uint32(settings, FreeRDP_RemoteAppFeatureFlags, flags) ||
87 !freerdp_settings_set_bool(settings, FreeRDP_AutoReconnectionEnabled, reconnect))
88 return FALSE;
89 g_eventCount = 0;
90 g_execCount = 0;
91 g_failHandshake = failHandshake;
92 g_failStatus = failStatus;
93 const RAIL_HANDSHAKE_ORDER handshake = WINPR_C_ARRAY_INIT;
94 const RAIL_HANDSHAKE_EX_ORDER handshakeEx = WINPR_C_ARRAY_INIT;
95 const UINT rc = extended ? g_rail->ServerHandshakeEx(g_rail, &handshakeEx)
96 : g_rail->ServerHandshake(g_rail, &handshake);
97 const UINT expected = (failHandshake || failStatus) ? ERROR_INTERNAL_ERROR : CHANNEL_RC_OK;
98 const UINT32 expectedFlags = reconnect ? flags | TS_RAIL_CLIENTSTATUS_AUTORECONNECT
99 : flags & ~TS_RAIL_CLIENTSTATUS_AUTORECONNECT;
100 if ((rc != expected) || (g_eventCount != (failHandshake ? 1 : 2)) ||
101 (g_events[0] != TS_RAIL_ORDER_HANDSHAKE) || (g_execCount != 0) ||
102 (g_build != freerdp_settings_get_uint32(settings, FreeRDP_ClientBuild)))
103 return FALSE;
104 return failHandshake ||
105 ((g_events[1] == TS_RAIL_ORDER_CLIENTSTATUS) && (g_flags == expectedFlags));
106}
107
108int TestRailHandshake(int argc, char* argv[])
109{
110 WINPR_UNUSED(argc);
111 WINPR_UNUSED(argv);
112 int rc = -1;
113 RDP_CLIENT_ENTRY_POINTS entry = WINPR_C_ARRAY_INIT;
114 entry.Version = RDP_CLIENT_INTERFACE_VERSION;
115 entry.Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
116 entry.ContextSize = sizeof(rdpClientContext);
117 rdpContext* context = freerdp_client_context_new(&entry);
118 if (!context)
119 return -1;
120 PVIRTUALCHANNELENTRYEX entryEx =
121 WINPR_FUNC_PTR_CAST(freerdp_channels_load_static_addin_entry(
122 RAIL_SVC_CHANNEL_NAME, nullptr, nullptr,
123 FREERDP_ADDIN_CHANNEL_STATIC | FREERDP_ADDIN_CHANNEL_ENTRYEX),
124 PVIRTUALCHANNELENTRYEX);
125 if (!entryEx)
126 goto fail;
127 CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntry = WINPR_C_ARRAY_INIT;
128 channelEntry.cbSize = sizeof(channelEntry);
129 channelEntry.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000;
130 channelEntry.pVirtualChannelInitEx = test_init_ex;
131 channelEntry.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER;
132 channelEntry.context = context;
133 if (!entryEx((PCHANNEL_ENTRY_POINTS_EX)&channelEntry, &g_initHandle))
134 goto fail;
135 if (!g_rail || !g_initEvent)
136 goto terminate;
137 g_rail->ClientHandshake = test_handshake;
138 g_rail->ClientInformation = test_status;
139 g_rail->ClientSystemParam = test_sysparam;
140 g_rail->ClientExecute = test_execute;
141 const UINT32 flags[] = { 0, TS_RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE |
142 TS_RAIL_CLIENTSTATUS_AUTORECONNECT |
143 TS_RAIL_CLIENTSTATUS_ZORDER_SYNC };
144 for (size_t extended = 0; extended < 2; extended++)
145 {
146 for (size_t reconnect = 0; reconnect < 2; reconnect++)
147 {
148 for (size_t i = 0; i < ARRAYSIZE(flags); i++)
149 {
150 if (!check_handshake(context->settings, extended != 0, reconnect != 0, flags[i],
151 FALSE, FALSE) ||
152 !check_handshake(context->settings, extended != 0, reconnect != 0, flags[i],
153 TRUE, FALSE) ||
154 !check_handshake(context->settings, extended != 0, reconnect != 0, flags[i],
155 FALSE, TRUE))
156 {
157 (void)fprintf(stderr,
158 "RAIL handshake failed: extended=%zu reconnect=%zu flags=%zu\n",
159 extended, reconnect, i);
160 goto terminate;
161 }
162 }
163 }
164 }
165 if (!freerdp_settings_set_bool(context->settings, FreeRDP_RemoteAppLanguageBarSupported,
166 FALSE) ||
167 !freerdp_settings_set_string(context->settings, FreeRDP_RemoteApplicationProgram, "||test"))
168 goto terminate;
169 /* Callback-override clients still initialize status through the launch helper. */
170 for (size_t failure = 0; failure < 2; failure++)
171 {
172 g_eventCount = 0;
173 g_execCount = 0;
174 g_failStatus = failure != 0;
175 const UINT result = client_rail_server_start_cmd(g_rail);
176 if ((result != (g_failStatus ? ERROR_INTERNAL_ERROR : CHANNEL_RC_OK)) ||
177 (g_eventCount != 1) || (g_events[0] != TS_RAIL_ORDER_CLIENTSTATUS) ||
178 (g_execCount != (g_failStatus ? 0 : 1)))
179 goto terminate;
180 }
181 rc = 0;
182terminate:
183 if (g_initEvent)
184 g_initEvent(g_userParam, &g_initHandle, CHANNEL_EVENT_TERMINATED, nullptr, 0);
185fail:
186 freerdp_client_context_free(context);
187 return rc;
188}
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.
Definition svc.h:60