FreeRDP
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 
34 static DWORD WINAPI drdynvc_server_thread(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 
120 static 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 
154 static 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 
170 DrdynvcServerContext* 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 
197 void drdynvc_server_context_free(DrdynvcServerContext* context)
198 {
199  if (context)
200  {
201  free(context->priv);
202  free(context);
203  }
204 }