23#include <winpr/stream.h>
24#include <winpr/wlog.h>
26#include <freerdp/addin.h>
27#include <freerdp/client.h>
28#include <freerdp/client/channels.h>
29#include <freerdp/channels/drdynvc.h>
30#include <freerdp/dvc.h>
31#include <freerdp/svc.h>
33#include "../drdynvc_main.h"
35#define TEST_LISTENER_NAME "test"
36#define TEST_OPEN_HANDLE 1
40 PCHANNEL_INIT_EVENT_EX_FN initEvent;
41 PCHANNEL_OPEN_EVENT_EX_FN openEvent;
43 INT32 lastCreateStatus;
44 BOOL haveCreateStatus;
47static test_vc g_vc = WINPR_C_ARRAY_INIT;
48static int g_initHandle = 0;
50static UINT VCAPITYPE test_init_ex(LPVOID lpUserParam, WINPR_ATTR_UNUSED LPVOID clientContext,
51 WINPR_ATTR_UNUSED LPVOID pInitHandle,
53 WINPR_ATTR_UNUSED INT channelCount,
54 WINPR_ATTR_UNUSED ULONG versionRequested,
55 PCHANNEL_INIT_EVENT_EX_FN pChannelInitEventProcEx)
57 g_vc.userParam = lpUserParam;
58 g_vc.initEvent = pChannelInitEventProcEx;
62static UINT VCAPITYPE test_open_ex(WINPR_ATTR_UNUSED LPVOID pInitHandle, LPDWORD pOpenHandle,
63 WINPR_ATTR_UNUSED PCHAR pChannelName,
64 PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx)
66 *pOpenHandle = TEST_OPEN_HANDLE;
67 g_vc.openEvent = pChannelOpenEventProcEx;
71static UINT VCAPITYPE test_close_ex(WINPR_ATTR_UNUSED LPVOID pInitHandle,
72 WINPR_ATTR_UNUSED DWORD openHandle)
77static UINT VCAPITYPE test_write_ex(WINPR_ATTR_UNUSED LPVOID pInitHandle, DWORD openHandle,
78 LPVOID pData, ULONG dataLength, LPVOID pUserData)
81 const BYTE* data = pData;
82 if (data && (dataLength == 6) && ((data[0] >> 4) == CREATE_REQUEST_PDU))
84 g_vc.lastCreateStatus =
85 (INT32)(data[2] | (data[3] << 8) | (data[4] << 16) | ((UINT32)data[5] << 24));
86 g_vc.haveCreateStatus = TRUE;
91 g_vc.openEvent(g_vc.userParam, openHandle, CHANNEL_EVENT_WRITE_COMPLETE, pUserData, 0, 0,
94 Stream_Release((
wStream*)pUserData);
98static UINT test_dvc_on_data_received(WINPR_ATTR_UNUSED IWTSVirtualChannelCallback* pCallback,
99 WINPR_ATTR_UNUSED
wStream* data)
101 return CHANNEL_RC_OK;
104static UINT test_dvc_on_close(IWTSVirtualChannelCallback* pChannelCallback)
106 free(pChannelCallback);
107 return CHANNEL_RC_OK;
110static UINT test_on_new_channel_connection(WINPR_ATTR_UNUSED IWTSListenerCallback* pListener,
111 WINPR_ATTR_UNUSED IWTSVirtualChannel* pChannel,
112 WINPR_ATTR_UNUSED BYTE* Data, BOOL* pbAccept,
113 IWTSVirtualChannelCallback** ppCallback)
115 IWTSVirtualChannelCallback* callback = calloc(1,
sizeof(IWTSVirtualChannelCallback));
117 return CHANNEL_RC_NO_MEMORY;
119 callback->OnDataReceived = test_dvc_on_data_received;
120 callback->OnClose = test_dvc_on_close;
122 *ppCallback = callback;
123 return CHANNEL_RC_OK;
126static IWTSListenerCallback g_listener = { test_on_new_channel_connection,
nullptr };
129static BOOL send_create_request(BYTE channelId,
const char* name, INT32* status)
131 BYTE pdu[64] = WINPR_C_ARRAY_INIT;
132 const size_t nameLength = strlen(name) + 1;
133 if (nameLength + 2 >
sizeof(pdu))
136 pdu[0] = CREATE_REQUEST_PDU << 4;
138 memcpy(&pdu[2], name, nameLength);
140 g_vc.haveCreateStatus = FALSE;
141 g_vc.openEvent(g_vc.userParam, TEST_OPEN_HANDLE, CHANNEL_EVENT_DATA_RECEIVED, pdu,
142 (UINT32)(nameLength + 2), (UINT32)(nameLength + 2),
143 CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST);
144 if (!g_vc.haveCreateStatus)
146 *status = g_vc.lastCreateStatus;
150int TestDrdynvcUnknownChannel(
int argc,
char* argv[])
156 RDP_CLIENT_ENTRY_POINTS entry = WINPR_C_ARRAY_INIT;
157 entry.Version = RDP_CLIENT_INTERFACE_VERSION;
158 entry.Size =
sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
159 entry.ContextSize =
sizeof(rdpContext);
161 rdpContext* context = freerdp_client_context_new(&entry);
170 PVIRTUALCHANNELENTRYEX entryEx =
171 WINPR_FUNC_PTR_CAST(freerdp_channels_load_static_addin_entry(
172 DRDYNVC_SVC_CHANNEL_NAME,
nullptr,
nullptr,
173 FREERDP_ADDIN_CHANNEL_STATIC | FREERDP_ADDIN_CHANNEL_ENTRYEX),
174 PVIRTUALCHANNELENTRYEX);
179 entryPoints.cbSize =
sizeof(entryPoints);
180 entryPoints.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000;
181 entryPoints.pVirtualChannelInitEx = test_init_ex;
182 entryPoints.pVirtualChannelOpenEx = test_open_ex;
183 entryPoints.pVirtualChannelCloseEx = test_close_ex;
184 entryPoints.pVirtualChannelWriteEx = test_write_ex;
185 entryPoints.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER;
186 entryPoints.context = context;
188 if (!entryEx((PCHANNEL_ENTRY_POINTS_EX)&entryPoints, &g_initHandle) || !g_vc.initEvent)
192 g_vc.initEvent(g_vc.userParam, &g_initHandle, CHANNEL_EVENT_INITIALIZED,
nullptr, 0);
193 g_vc.initEvent(g_vc.userParam, &g_initHandle, CHANNEL_EVENT_CONNECTED,
nullptr, 0);
196 drdynvcPlugin* drdynvc = (drdynvcPlugin*)g_vc.userParam;
197 IWTSVirtualChannelManager* mgr = drdynvc->channel_mgr;
200 if (!mgr || !g_vc.openEvent ||
201 (mgr->CreateListener(mgr, TEST_LISTENER_NAME, 0, &g_listener,
nullptr) !=
206 for (
size_t x = 0; x < 2; x++)
208 if (!send_create_request(5,
"unsupported", &status) || (status != STATUS_NOT_FOUND))
210 (void)fprintf(stderr,
"unsupported channel #%" PRIuz
": status 0x%08" PRIx32
"\n",
217 if (!send_create_request(5, TEST_LISTENER_NAME, &status) || (status != 0))
219 (void)fprintf(stderr,
"supported channel after reuse: status 0x%08" PRIx32
"\n",
227 g_vc.initEvent(g_vc.userParam, &g_initHandle, CHANNEL_EVENT_DISCONNECTED,
nullptr, 0);
229 g_vc.initEvent(g_vc.userParam, &g_initHandle, CHANNEL_EVENT_TERMINATED,
nullptr, 0);
232 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.