FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
server/drdynvc_main.c
1
22#include <freerdp/config.h>
23
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>
29
30#include "drdynvc_main.h"
31
32#define TAG CHANNELS_TAG("drdynvc.server")
33
34static DWORD WINAPI drdynvc_server_thread(WINPR_ATTR_UNUSED LPVOID arg)
35{
36#if 0
37 wStream* s;
38 DWORD status;
39 DWORD nCount;
40 void* buffer;
41 HANDLE events[8];
42 HANDLE ChannelEvent;
43 DWORD BytesReturned;
44 DrdynvcServerContext* context;
45 UINT error = ERROR_INTERNAL_ERROR;
46 context = (DrdynvcServerContext*) arg;
47 buffer = NULL;
48 BytesReturned = 0;
49 ChannelEvent = NULL;
50
51 s = Stream_New(NULL, 4096);
52
53 if (!s)
54 {
55 WLog_ERR(TAG, "Stream_New failed!");
56 ExitThread((DWORD) CHANNEL_RC_NO_MEMORY);
57 return CHANNEL_RC_NO_MEMORY;
58 }
59
60 if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
61 &buffer, &BytesReturned) == TRUE)
62 {
63 if (BytesReturned == sizeof(HANDLE))
64 CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
65
66 WTSFreeMemory(buffer);
67 }
68
69 nCount = 0;
70 events[nCount++] = ChannelEvent;
71 events[nCount++] = context->priv->StopEvent;
72
73 while (1)
74 {
75 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
76
77 if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
78 {
79 error = CHANNEL_RC_OK;
80 break;
81 }
82
83 if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0,
84 &BytesReturned))
85 {
86 WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
87 break;
88 }
89
90 if (BytesReturned < 1)
91 continue;
92
93 if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
94 {
95 WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
96 break;
97 }
98
99 if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
100 Stream_BufferAs(s, char), Stream_Capacity(s), &BytesReturned))
101 {
102 WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
103 break;
104 }
105 }
106
107 Stream_Free(s, TRUE);
108 ExitThread((DWORD) error);
109#endif
110 // WTF ... this code only reads data into the stream until there is no more memory
111 ExitThread(0);
112 return 0;
113}
114
120static UINT drdynvc_server_start(DrdynvcServerContext* context)
121{
122 context->priv->ChannelHandle =
123 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, DRDYNVC_SVC_CHANNEL_NAME);
124
125 if (!context->priv->ChannelHandle)
126 {
127 WLog_ERR(TAG, "WTSVirtualChannelOpen failed!");
128 return CHANNEL_RC_NO_MEMORY;
129 }
130
131 if (!(context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
132 {
133 WLog_ERR(TAG, "CreateEvent failed!");
134 return ERROR_INTERNAL_ERROR;
135 }
136
137 if (!(context->priv->Thread =
138 CreateThread(NULL, 0, drdynvc_server_thread, (void*)context, 0, NULL)))
139 {
140 WLog_ERR(TAG, "CreateThread failed!");
141 (void)CloseHandle(context->priv->StopEvent);
142 context->priv->StopEvent = NULL;
143 return ERROR_INTERNAL_ERROR;
144 }
145
146 return CHANNEL_RC_OK;
147}
148
154static UINT drdynvc_server_stop(DrdynvcServerContext* context)
155{
156 UINT error = 0;
157 (void)SetEvent(context->priv->StopEvent);
158
159 if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
160 {
161 error = GetLastError();
162 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error);
163 return error;
164 }
165
166 (void)CloseHandle(context->priv->Thread);
167 return CHANNEL_RC_OK;
168}
169
170DrdynvcServerContext* drdynvc_server_context_new(HANDLE vcm)
171{
172 DrdynvcServerContext* context = NULL;
173 context = (DrdynvcServerContext*)calloc(1, sizeof(DrdynvcServerContext));
174
175 if (context)
176 {
177 context->vcm = vcm;
178 context->Start = drdynvc_server_start;
179 context->Stop = drdynvc_server_stop;
180 context->priv = (DrdynvcServerPrivate*)calloc(1, sizeof(DrdynvcServerPrivate));
181
182 if (!context->priv)
183 {
184 WLog_ERR(TAG, "calloc failed!");
185 free(context);
186 return NULL;
187 }
188 }
189 else
190 {
191 WLog_ERR(TAG, "calloc failed!");
192 }
193
194 return context;
195}
196
197void drdynvc_server_context_free(DrdynvcServerContext* context)
198{
199 if (context)
200 {
201 free(context->priv);
202 free(context);
203 }
204}