20#include <freerdp/client.h>
21#include <freerdp/client/channels.h>
22#include <freerdp/client/rail.h>
23#include <freerdp/svc.h>
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;
37static UINT VCAPITYPE test_init_ex(LPVOID userParam, LPVOID clientContext,
38 WINPR_ATTR_UNUSED LPVOID initHandle,
40 WINPR_ATTR_UNUSED INT channelCount,
41 WINPR_ATTR_UNUSED ULONG version,
42 PCHANNEL_INIT_EVENT_EX_FN initEvent)
44 g_userParam = userParam;
45 g_rail = clientContext;
46 g_initEvent = initEvent;
50static UINT test_handshake(WINPR_ATTR_UNUSED RailClientContext* context,
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;
60static UINT test_status(WINPR_ATTR_UNUSED RailClientContext* context,
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;
70static UINT test_sysparam(WINPR_ATTR_UNUSED RailClientContext* context,
76static UINT test_execute(WINPR_ATTR_UNUSED RailClientContext* context,
83static BOOL check_handshake(rdpSettings* settings, BOOL extended, BOOL reconnect, UINT32 flags,
84 BOOL failHandshake, BOOL failStatus)
91 g_failHandshake = failHandshake;
92 g_failStatus = failStatus;
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) ||
104 return failHandshake ||
105 ((g_events[1] == TS_RAIL_ORDER_CLIENTSTATUS) && (g_flags == expectedFlags));
108int TestRailHandshake(
int argc,
char* argv[])
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);
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);
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))
135 if (!g_rail || !g_initEvent)
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++)
146 for (
size_t reconnect = 0; reconnect < 2; reconnect++)
148 for (
size_t i = 0; i < ARRAYSIZE(flags); i++)
150 if (!check_handshake(context->settings, extended != 0, reconnect != 0, flags[i],
152 !check_handshake(context->settings, extended != 0, reconnect != 0, flags[i],
154 !check_handshake(context->settings, extended != 0, reconnect != 0, flags[i],
157 (void)fprintf(stderr,
158 "RAIL handshake failed: extended=%zu reconnect=%zu flags=%zu\n",
159 extended, reconnect, i);
170 for (
size_t failure = 0; failure < 2; failure++)
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)))
184 g_initEvent(g_userParam, &g_initHandle, CHANNEL_EVENT_TERMINATED,
nullptr, 0);
186 freerdp_client_context_free(context);
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.