22 #include <freerdp/config.h>
24 #include <winpr/crt.h>
25 #include <winpr/print.h>
26 #include <winpr/stream.h>
27 #include <freerdp/channels/log.h>
28 #include <freerdp/channels/drdynvc.h>
30 #include "drdynvc_main.h"
32 #define TAG CHANNELS_TAG("drdynvc.server")
34 static DWORD WINAPI drdynvc_server_thread(LPVOID arg)
44 DrdynvcServerContext* context;
45 UINT error = ERROR_INTERNAL_ERROR;
46 context = (DrdynvcServerContext*) arg;
51 s = Stream_New(NULL, 4096);
55 WLog_ERR(TAG,
"Stream_New failed!");
56 ExitThread((DWORD) CHANNEL_RC_NO_MEMORY);
57 return CHANNEL_RC_NO_MEMORY;
60 if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
61 &buffer, &BytesReturned) == TRUE)
63 if (BytesReturned ==
sizeof(HANDLE))
64 CopyMemory(&ChannelEvent, buffer,
sizeof(HANDLE));
66 WTSFreeMemory(buffer);
70 events[nCount++] = ChannelEvent;
71 events[nCount++] = context->priv->StopEvent;
75 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
77 if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
79 error = CHANNEL_RC_OK;
83 if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0,
86 WLog_ERR(TAG,
"WTSVirtualChannelRead failed!");
90 if (BytesReturned < 1)
93 if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
95 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
99 if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
100 Stream_BufferAs(s,
char), Stream_Capacity(s), &BytesReturned))
102 WLog_ERR(TAG,
"WTSVirtualChannelRead failed!");
107 Stream_Free(s, TRUE);
108 ExitThread((DWORD) error);
120 static UINT drdynvc_server_start(DrdynvcServerContext* context)
122 context->priv->ChannelHandle =
123 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, DRDYNVC_SVC_CHANNEL_NAME);
125 if (!context->priv->ChannelHandle)
127 WLog_ERR(TAG,
"WTSVirtualChannelOpen failed!");
128 return CHANNEL_RC_NO_MEMORY;
131 if (!(context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
133 WLog_ERR(TAG,
"CreateEvent failed!");
134 return ERROR_INTERNAL_ERROR;
137 if (!(context->priv->Thread =
138 CreateThread(NULL, 0, drdynvc_server_thread, (
void*)context, 0, NULL)))
140 WLog_ERR(TAG,
"CreateThread failed!");
141 (void)CloseHandle(context->priv->StopEvent);
142 context->priv->StopEvent = NULL;
143 return ERROR_INTERNAL_ERROR;
146 return CHANNEL_RC_OK;
154 static UINT drdynvc_server_stop(DrdynvcServerContext* context)
157 (void)SetEvent(context->priv->StopEvent);
159 if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
161 error = GetLastError();
162 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
166 (void)CloseHandle(context->priv->Thread);
167 return CHANNEL_RC_OK;
170 DrdynvcServerContext* drdynvc_server_context_new(HANDLE vcm)
172 DrdynvcServerContext* context = NULL;
173 context = (DrdynvcServerContext*)calloc(1,
sizeof(DrdynvcServerContext));
178 context->Start = drdynvc_server_start;
179 context->Stop = drdynvc_server_stop;
180 context->priv = (DrdynvcServerPrivate*)calloc(1,
sizeof(DrdynvcServerPrivate));
184 WLog_ERR(TAG,
"calloc failed!");
191 WLog_ERR(TAG,
"calloc failed!");
197 void drdynvc_server_context_free(DrdynvcServerContext* context)