FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
libfreerdp/core/channels.c
1
21#include <freerdp/config.h>
22
23#include "settings.h"
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <winpr/crt.h>
30#include <winpr/assert.h>
31#include <winpr/stream.h>
32#include <winpr/wtsapi.h>
33
34#include <freerdp/freerdp.h>
35#include <freerdp/constants.h>
36
37#include <freerdp/log.h>
38#include <freerdp/svc.h>
39#include <freerdp/peer.h>
40#include <freerdp/addin.h>
41
42#include <freerdp/client/channels.h>
43#include <freerdp/client/drdynvc.h>
44#include <freerdp/channels/channels.h>
45
46#include "rdp.h"
47#include "client.h"
48#include "server.h"
49#include "channels.h"
50
51#define TAG FREERDP_TAG("core.channels")
52
53BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size_t size)
54{
55 size_t left = 0;
56 UINT32 flags = 0;
57 size_t chunkSize = 0;
58 rdpMcs* mcs = NULL;
59 const rdpMcsChannel* channel = NULL;
60
61 WINPR_ASSERT(rdp);
62 WINPR_ASSERT(data || (size == 0));
63
64 mcs = rdp->mcs;
65 WINPR_ASSERT(mcs);
66 for (UINT32 i = 0; i < mcs->channelCount; i++)
67 {
68 const rdpMcsChannel* cur = &mcs->channels[i];
69 if (cur->ChannelId == channelId)
70 {
71 channel = cur;
72 break;
73 }
74 }
75
76 if (!channel)
77 {
78 WLog_ERR(TAG, "freerdp_channel_send: unknown channelId %" PRIu16 "", channelId);
79 return FALSE;
80 }
81
82 flags = CHANNEL_FLAG_FIRST;
83 left = size;
84
85 while (left > 0)
86 {
87 if (left > rdp->settings->VCChunkSize)
88 {
89 chunkSize = rdp->settings->VCChunkSize;
90 }
91 else
92 {
93 chunkSize = left;
94 flags |= CHANNEL_FLAG_LAST;
95 }
96
97 if (!rdp->settings->ServerMode && (channel->options & CHANNEL_OPTION_SHOW_PROTOCOL))
98 {
99 flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
100 }
101
102 if (!freerdp_channel_send_packet(rdp, channelId, size, flags, data, chunkSize))
103 return FALSE;
104
105 data += chunkSize;
106 left -= chunkSize;
107 flags = 0;
108 }
109
110 return TRUE;
111}
112
113BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId, size_t packetLength)
114{
115 BOOL rc = FALSE;
116 UINT32 length = 0;
117 UINT32 flags = 0;
118 size_t chunkLength = 0;
119
120 WINPR_ASSERT(instance);
121
122 if (packetLength < 8)
123 {
124 WLog_ERR(TAG, "Header length %" PRIdz " bytes promised, none available", packetLength);
125 return FALSE;
126 }
127 packetLength -= 8;
128
129 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
130 return FALSE;
131
132 /* [MS-RDPBCGR] 3.1.5.2.2 Processing of Virtual Channel PDU
133 * chunked data. Length is the total size of the combined data,
134 * chunkLength is the actual data received.
135 * check chunkLength against packetLength, which is the TPKT header size.
136 */
137 Stream_Read_UINT32(s, length);
138 Stream_Read_UINT32(s, flags);
139 chunkLength = Stream_GetRemainingLength(s);
140 if (packetLength != chunkLength)
141 {
142 WLog_ERR(TAG, "Header length %" PRIdz " != actual length %" PRIdz, packetLength,
143 chunkLength);
144 return FALSE;
145 }
146
147 IFCALLRET(instance->ReceiveChannelData, rc, instance, channelId, Stream_Pointer(s), chunkLength,
148 flags, length);
149 if (!rc)
150 {
151 WLog_WARN(TAG, "ReceiveChannelData returned %d", rc);
152 return FALSE;
153 }
154
155 return Stream_SafeSeek(s, chunkLength);
156}
157
158BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId)
159{
160 UINT32 length = 0;
161 UINT32 flags = 0;
162
163 WINPR_ASSERT(client);
164 WINPR_ASSERT(s);
165
166 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
167 return FALSE;
168
169 Stream_Read_UINT32(s, length);
170 Stream_Read_UINT32(s, flags);
171 const size_t chunkLength = Stream_GetRemainingLength(s);
172 if (chunkLength > UINT32_MAX)
173 return FALSE;
174
175 if (client->VirtualChannelRead)
176 {
177 int rc = 0;
178 BOOL found = FALSE;
179 HANDLE hChannel = 0;
180 rdpContext* context = client->context;
181 rdpMcs* mcs = context->rdp->mcs;
182
183 for (UINT32 index = 0; index < mcs->channelCount; index++)
184 {
185 const rdpMcsChannel* mcsChannel = &(mcs->channels[index]);
186
187 if (mcsChannel->ChannelId == channelId)
188 {
189 hChannel = (HANDLE)mcsChannel->handle;
190 found = TRUE;
191 break;
192 }
193 }
194
195 if (!found)
196 return FALSE;
197
198 rc = client->VirtualChannelRead(client, hChannel, Stream_Pointer(s), (UINT32)chunkLength);
199 if (rc < 0)
200 return FALSE;
201 }
202 else if (client->ReceiveChannelData)
203 {
204 BOOL rc = client->ReceiveChannelData(client, channelId, Stream_Pointer(s),
205 (UINT32)chunkLength, flags, length);
206 if (!rc)
207 return FALSE;
208 }
209 if (!Stream_SafeSeek(s, chunkLength))
210 {
211 WLog_WARN(TAG, "Short PDU, need %" PRIuz " bytes, got %" PRIuz, chunkLength,
212 Stream_GetRemainingLength(s));
213 return FALSE;
214 }
215 return TRUE;
216}
217
218static const WtsApiFunctionTable FreeRDP_WtsApiFunctionTable = {
219 0, /* dwVersion */
220 0, /* dwFlags */
221
222 FreeRDP_WTSStopRemoteControlSession, /* StopRemoteControlSession */
223 FreeRDP_WTSStartRemoteControlSessionW, /* StartRemoteControlSessionW */
224 FreeRDP_WTSStartRemoteControlSessionA, /* StartRemoteControlSessionA */
225 FreeRDP_WTSConnectSessionW, /* ConnectSessionW */
226 FreeRDP_WTSConnectSessionA, /* ConnectSessionA */
227 FreeRDP_WTSEnumerateServersW, /* EnumerateServersW */
228 FreeRDP_WTSEnumerateServersA, /* EnumerateServersA */
229 FreeRDP_WTSOpenServerW, /* OpenServerW */
230 FreeRDP_WTSOpenServerA, /* OpenServerA */
231 FreeRDP_WTSOpenServerExW, /* OpenServerExW */
232 FreeRDP_WTSOpenServerExA, /* OpenServerExA */
233 FreeRDP_WTSCloseServer, /* CloseServer */
234 FreeRDP_WTSEnumerateSessionsW, /* EnumerateSessionsW */
235 FreeRDP_WTSEnumerateSessionsA, /* EnumerateSessionsA */
236 FreeRDP_WTSEnumerateSessionsExW, /* EnumerateSessionsExW */
237 FreeRDP_WTSEnumerateSessionsExA, /* EnumerateSessionsExA */
238 FreeRDP_WTSEnumerateProcessesW, /* EnumerateProcessesW */
239 FreeRDP_WTSEnumerateProcessesA, /* EnumerateProcessesA */
240 FreeRDP_WTSTerminateProcess, /* TerminateProcess */
241 FreeRDP_WTSQuerySessionInformationW, /* QuerySessionInformationW */
242 FreeRDP_WTSQuerySessionInformationA, /* QuerySessionInformationA */
243 FreeRDP_WTSQueryUserConfigW, /* QueryUserConfigW */
244 FreeRDP_WTSQueryUserConfigA, /* QueryUserConfigA */
245 FreeRDP_WTSSetUserConfigW, /* SetUserConfigW */
246 FreeRDP_WTSSetUserConfigA, /* SetUserConfigA */
247 FreeRDP_WTSSendMessageW, /* SendMessageW */
248 FreeRDP_WTSSendMessageA, /* SendMessageA */
249 FreeRDP_WTSDisconnectSession, /* DisconnectSession */
250 FreeRDP_WTSLogoffSession, /* LogoffSession */
251 FreeRDP_WTSShutdownSystem, /* ShutdownSystem */
252 FreeRDP_WTSWaitSystemEvent, /* WaitSystemEvent */
253 FreeRDP_WTSVirtualChannelOpen, /* VirtualChannelOpen */
254 FreeRDP_WTSVirtualChannelOpenEx, /* VirtualChannelOpenEx */
255 FreeRDP_WTSVirtualChannelClose, /* VirtualChannelClose */
256 FreeRDP_WTSVirtualChannelRead, /* VirtualChannelRead */
257 FreeRDP_WTSVirtualChannelWrite, /* VirtualChannelWrite */
258 FreeRDP_WTSVirtualChannelPurgeInput, /* VirtualChannelPurgeInput */
259 FreeRDP_WTSVirtualChannelPurgeOutput, /* VirtualChannelPurgeOutput */
260 FreeRDP_WTSVirtualChannelQuery, /* VirtualChannelQuery */
261 FreeRDP_WTSFreeMemory, /* FreeMemory */
262 FreeRDP_WTSRegisterSessionNotification, /* RegisterSessionNotification */
263 FreeRDP_WTSUnRegisterSessionNotification, /* UnRegisterSessionNotification */
264 FreeRDP_WTSRegisterSessionNotificationEx, /* RegisterSessionNotificationEx */
265 FreeRDP_WTSUnRegisterSessionNotificationEx, /* UnRegisterSessionNotificationEx */
266 FreeRDP_WTSQueryUserToken, /* QueryUserToken */
267 FreeRDP_WTSFreeMemoryExW, /* FreeMemoryExW */
268 FreeRDP_WTSFreeMemoryExA, /* FreeMemoryExA */
269 FreeRDP_WTSEnumerateProcessesExW, /* EnumerateProcessesExW */
270 FreeRDP_WTSEnumerateProcessesExA, /* EnumerateProcessesExA */
271 FreeRDP_WTSEnumerateListenersW, /* EnumerateListenersW */
272 FreeRDP_WTSEnumerateListenersA, /* EnumerateListenersA */
273 FreeRDP_WTSQueryListenerConfigW, /* QueryListenerConfigW */
274 FreeRDP_WTSQueryListenerConfigA, /* QueryListenerConfigA */
275 FreeRDP_WTSCreateListenerW, /* CreateListenerW */
276 FreeRDP_WTSCreateListenerA, /* CreateListenerA */
277 FreeRDP_WTSSetListenerSecurityW, /* SetListenerSecurityW */
278 FreeRDP_WTSSetListenerSecurityA, /* SetListenerSecurityA */
279 FreeRDP_WTSGetListenerSecurityW, /* GetListenerSecurityW */
280 FreeRDP_WTSGetListenerSecurityA, /* GetListenerSecurityA */
281 FreeRDP_WTSEnableChildSessions, /* EnableChildSessions */
282 FreeRDP_WTSIsChildSessionsEnabled, /* IsChildSessionsEnabled */
283 FreeRDP_WTSGetChildSessionId, /* GetChildSessionId */
284 FreeRDP_WTSGetActiveConsoleSessionId, /* GetActiveConsoleSessionId */
285 FreeRDP_WTSLogonUser,
286 FreeRDP_WTSLogoffUser,
287 FreeRDP_WTSStartRemoteControlSessionExW,
288 FreeRDP_WTSStartRemoteControlSessionExA
289};
290
291const WtsApiFunctionTable* FreeRDP_InitWtsApi(void)
292{
293 return &FreeRDP_WtsApiFunctionTable;
294}
295
296BOOL freerdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize, UINT32 flags,
297 const BYTE* data, size_t chunkSize)
298{
299 if (totalSize > UINT32_MAX)
300 return FALSE;
301
302 UINT16 sec_flags = 0;
303 wStream* s = rdp_send_stream_init(rdp, &sec_flags);
304
305 if (!s)
306 return FALSE;
307
308 if (!Stream_EnsureRemainingCapacity(s, chunkSize + 8))
309 {
310 Stream_Release(s);
311 return FALSE;
312 }
313
314 Stream_Write_UINT32(s, (UINT32)totalSize);
315 Stream_Write_UINT32(s, flags);
316
317 Stream_Write(s, data, chunkSize);
318
319 /* WLog_DBG(TAG, "sending data (flags=0x%x size=%d)", flags, size); */
320 return rdp_send(rdp, s, channelId, sec_flags);
321}