2
Copyright (c) 2009-2010 Jay Sorg
4
Permission is hereby granted, free of charge, to any person obtaining a
5
copy of this software and associated documentation files (the "Software"),
6
to deal in the Software without restriction, including without limitation
7
the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
and/or sell copies of the Software, and to permit persons to whom the
9
Software is furnished to do so, subject to the following conditions:
11
The above copyright notice and this permission notice shall be included
12
in all copies or substantial portions of the Software.
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
DEALINGS IN THE SOFTWARE.
31
#include "rdpdr_types.h"
32
#include "rdpdr_main.h"
33
#include "rdpdr_constants.h"
34
#include "rdpdr_capabilities.h"
38
/* called by main thread
39
add item to linked list and inform worker thread that there is data */
41
signal_data_in(rdpdrPlugin * plugin)
43
struct data_in_item * item;
45
item = (struct data_in_item *) malloc(sizeof(struct data_in_item));
47
item->data = plugin->data_in;
49
item->data_size = plugin->data_in_size;
50
plugin->data_in_size = 0;
51
pthread_mutex_lock(plugin->mutex);
52
if (plugin->list_tail == 0)
54
plugin->list_head = item;
55
plugin->list_tail = item;
59
plugin->list_tail->next = item;
60
plugin->list_tail = item;
62
pthread_mutex_unlock(plugin->mutex);
63
wait_obj_set(plugin->data_in_event);
67
rdpdr_process_server_announce_request(rdpdrPlugin * plugin, char* data, int data_size)
69
/* versionMajor, must be 1 */
70
plugin->versionMinor = GET_UINT16(data, 2); /* versionMinor */
71
plugin->clientID = GET_UINT32(data, 4); /* clientID */
73
LLOGLN(0, ("Version Minor: %d", plugin->versionMinor));
76
switch(plugin->versionMinor)
79
LLOGLN(0, ("Windows Vista, Windows Vista SP1, Windows Server 2008, Windows 7, and Windows Server 2008 R2"));
83
LLOGLN(0, ("Windows Server 2003 SP2"));
87
LLOGLN(0, ("Windows XP SP3"));
91
LLOGLN(0, ("Windows XP, Windows XP SP1, Windows XP SP2, Windows Server 2003, and Windows Server 2003 SP1"));
95
LLOGLN(0, ("Windows 2000"));
102
rdpdr_send_client_announce_reply(rdpdrPlugin * plugin)
105
char* out_data = malloc(12);
107
SET_UINT16(out_data, 0, RDPDR_CTYP_CORE);
108
SET_UINT16(out_data, 2, PAKID_CORE_CLIENTID_CONFIRM);
110
SET_UINT16(out_data, 4, 1); /* versionMajor, must be set to 1 */
111
SET_UINT16(out_data, 6, plugin->versionMinor); /* versionMinor */
112
SET_UINT32(out_data, 8, plugin->clientID); /* clientID, given by the server in a Server Announce Request */
114
error = plugin->ep.pVirtualChannelWrite(plugin->open_handle, out_data, 12, out_data);
116
if (error != CHANNEL_RC_OK)
118
LLOGLN(0, ("thread_process_message_formats: "
119
"VirtualChannelWrite failed %d", error));
127
rdpdr_process_server_clientid_confirm(rdpdrPlugin * plugin, char* data, int data_size)
132
/* versionMajor, must be 1 */
133
versionMinor = GET_UINT16(data, 2); /* versionMinor */
134
clientID = GET_UINT32(data, 4); /* clientID */
136
if (clientID != plugin->clientID)
137
plugin->clientID = clientID;
139
if (versionMinor != plugin->versionMinor)
140
plugin->versionMinor = versionMinor;
144
rdpdr_send_client_name_request(rdpdrPlugin * plugin)
149
char computerName[256];
150
uint32 computerNameLen;
151
uint32 computerNameLenW;
153
gethostname(computerName, sizeof(computerName) - 1);
154
computerNameLen = strlen(computerName);
155
size = 16 + computerNameLen * 2 + 2;
157
memset(data, 0, size);
159
SET_UINT16(data, 0, RDPDR_CTYP_CORE);
160
SET_UINT16(data, 2, PAKID_CORE_CLIENT_NAME);
162
SET_UINT32(data, 4, 1); // unicodeFlag, 0 for ASCII and 1 for Unicode
163
SET_UINT32(data, 8, 0); // codePage, must be set to zero
165
computerNameLenW = set_wstr(&data[16], size - 16, computerName, computerNameLen); /* computerName */
166
SET_UINT32(data, 12, computerNameLenW + 2); /* computerNameLen, including null terminator */
168
error = plugin->ep.pVirtualChannelWrite(plugin->open_handle,
169
data, 16 + computerNameLenW + 2, data);
171
if (error != CHANNEL_RC_OK)
173
LLOGLN(0, ("thread_process_message_formats: "
174
"VirtualChannelWrite failed %d", error));
182
rdpdr_send_device_list_announce_request(rdpdrPlugin * plugin)
192
out_data = malloc(size);
193
memset(out_data, 0, size);
195
SET_UINT16(out_data, 0, RDPDR_CTYP_CORE);
196
SET_UINT16(out_data, 2, PAKID_CORE_DEVICELIST_ANNOUNCE);
197
SET_UINT32(out_data, 4, plugin->devman->count); /* deviceCount */
200
LLOGLN(0, ("%d device(s) registered", plugin->devman->count));
202
devman_rewind(plugin->devman);
204
while (devman_has_next(plugin->devman) != 0)
206
pdev = devman_get_next(plugin->devman);
208
size += 20 + pdev->data_len;
209
out_data = realloc(out_data, size);
211
SET_UINT32(out_data, offset, pdev->service->type); /* deviceType */
212
SET_UINT32(out_data, offset + 4, pdev->id); /* deviceID */
215
/* preferredDosName, Max 8 characters, may not be null terminated */
216
strncpy(&out_data[offset], pdev->name, 8);
217
for (i = 0; i < 8; i++)
219
if (out_data[offset + i] < 0)
221
out_data[offset + i] = '_';
226
LLOGLN(0, ("registered device: %s (type=%d id=%d)", pdev->name, pdev->service->type, pdev->id));
228
SET_UINT32(out_data, offset, pdev->data_len);
230
if (pdev->data_len > 0)
232
memcpy(&out_data[offset], pdev->data, pdev->data_len);
233
offset += pdev->data_len;
237
error = plugin->ep.pVirtualChannelWrite(plugin->open_handle,
238
out_data, offset, out_data);
240
if (error != CHANNEL_RC_OK)
242
LLOGLN(0, ("thread_process_message_formats: "
243
"VirtualChannelWrite failed %d", error));
251
rdpdr_process_irp(rdpdrPlugin * plugin, char* data, int data_size)
259
memset((void*)&irp, '\0', sizeof(IRP));
261
irp.ioStatus = RD_STATUS_SUCCESS;
263
/* Device I/O Request Header */
264
deviceID = GET_UINT32(data, 0); /* deviceID */
265
irp.fileID = GET_UINT32(data, 4); /* fileID */
266
irp.completionID = GET_UINT32(data, 8); /* completionID */
267
irp.majorFunction = GET_UINT32(data, 12); /* majorFunction */
268
irp.minorFunction = GET_UINT32(data, 16); /* minorFunction */
270
irp.dev = devman_get_device_by_id(plugin->devman, deviceID);
272
LLOGLN(10, ("IRP MAJOR: %d MINOR: %d", irp.majorFunction, irp.minorFunction));
274
switch(irp.majorFunction)
277
LLOGLN(10, ("IRP_MJ_CREATE"));
278
irp_process_create_request(&irp, &data[20], data_size - 20);
282
LLOGLN(10, ("IRP_MJ_CLOSE"));
283
irp_process_close_request(&irp, &data[20], data_size - 20);
287
LLOGLN(10, ("IRP_MJ_READ"));
288
irp_process_read_request(&irp, &data[20], data_size - 20);
292
LLOGLN(10, ("IRP_MJ_WRITE"));
293
irp_process_write_request(&irp, &data[20], data_size - 20);
296
case IRP_MJ_QUERY_INFORMATION:
297
LLOGLN(10, ("IRP_MJ_QUERY_INFORMATION"));
298
irp_process_query_information_request(&irp, &data[20], data_size - 20);
301
case IRP_MJ_SET_INFORMATION:
302
LLOGLN(10, ("IRP_MJ_SET_INFORMATION"));
303
irp_process_set_information_request(&irp, &data[20], data_size - 20);
306
case IRP_MJ_QUERY_VOLUME_INFORMATION:
307
LLOGLN(10, ("IRP_MJ_QUERY_VOLUME_INFORMATION"));
308
irp_process_query_volume_information_request(&irp, &data[20], data_size - 20);
311
case IRP_MJ_DIRECTORY_CONTROL:
312
LLOGLN(10, ("IRP_MJ_DIRECTORY_CONTROL"));
313
irp_process_directory_control_request(&irp, &data[20], data_size - 20);
316
case IRP_MJ_DEVICE_CONTROL:
317
LLOGLN(10, ("IRP_MJ_DEVICE_CONTROL"));
318
irp_process_device_control_request(&irp, &data[20], data_size - 20);
321
case IRP_MJ_LOCK_CONTROL:
322
LLOGLN(10, ("IRP_MJ_LOCK_CONTROL"));
323
irp_process_file_lock_control_request(&irp, &data[20], data_size - 20);
327
LLOGLN(0, ("IRP majorFunction=0x%x minorFunction=0x%x not supported", irp.majorFunction, irp.minorFunction));
328
irp.ioStatus = RD_STATUS_NOT_SUPPORTED;
332
if (irp.ioStatus != RD_STATUS_PENDING)
334
out = irp_output_device_io_completion(&irp, &out_size);
335
error = plugin->ep.pVirtualChannelWrite(plugin->open_handle, out, out_size, out);
336
if (error != CHANNEL_RC_OK)
338
LLOGLN(0, ("rdpdr_process_irp: "
339
"VirtualChannelWrite failed %d", error));
342
if (irp.outputBuffer)
343
free(irp.outputBuffer);
347
rdpdr_send_capabilities(rdpdrPlugin * plugin)
355
data = (char*)malloc(size);
356
memset(data, 0, size);
358
SET_UINT16(data, 0, RDPDR_CTYP_CORE);
359
SET_UINT16(data, 2, PAKID_CORE_CLIENT_CAPABILITY);
361
SET_UINT16(data, 4, 5); /* numCapabilities */
362
SET_UINT16(data, 6, 0); /* pad */
366
offset += rdpdr_out_general_capset(&data[offset], size - offset);
367
offset += rdpdr_out_printer_capset(&data[offset], size - offset);
368
offset += rdpdr_out_port_capset(&data[offset], size - offset);
369
offset += rdpdr_out_drive_capset(&data[offset], size - offset);
370
offset += rdpdr_out_smartcard_capset(&data[offset], size - offset);
372
error = plugin->ep.pVirtualChannelWrite(plugin->open_handle,
375
if (error != CHANNEL_RC_OK)
377
LLOGLN(0, ("thread_process_message_formats: "
378
"VirtualChannelWrite failed %d", error));
387
rdpdr_process_prn(rdpdrPlugin * plugin, int type, char * data, int data_size)
391
/* Pass the control to the printer sub-plugin service, if registered */
392
srv = devman_get_service_by_type(plugin->devman, RDPDR_DTYP_PRINT);
395
LLOGLN(0, ("rdpdr_process_prn: printer service not register"));
398
if (srv->process_data == NULL)
400
LLOGLN(0, ("rdpdr_process_prn: printer service does not support"));
403
srv->process_data(srv, type, data, data_size);
407
thread_process_message(rdpdrPlugin * plugin, char * data, int data_size)
414
component = GET_UINT16(data, 0);
415
packetID = GET_UINT16(data, 2);
417
if (component == RDPDR_CTYP_CORE)
419
LLOGLN(10, ("RDPDR_CTYP_CORE"));
422
case PAKID_CORE_SERVER_ANNOUNCE:
423
LLOGLN(10, ("PAKID_CORE_SERVER_ANNOUNCE"));
424
rdpdr_process_server_announce_request(plugin, &data[4], data_size - 4);
425
rdpdr_send_client_announce_reply(plugin);
426
rdpdr_send_client_name_request(plugin);
429
case PAKID_CORE_SERVER_CAPABILITY:
430
/* server capabilities */
431
LLOGLN(10, ("PAKID_CORE_SERVER_CAPABILITY"));
432
rdpdr_process_capabilities(&data[4], data_size - 4);
433
rdpdr_send_capabilities(plugin);
436
case PAKID_CORE_CLIENTID_CONFIRM:
437
LLOGLN(10, ("PAKID_CORE_CLIENTID_CONFIRM"));
438
rdpdr_process_server_clientid_confirm(plugin, &data[4], data_size - 4);
441
case PAKID_CORE_USER_LOGGEDON:
442
LLOGLN(10, ("PAKID_CORE_USER_LOGGEDON"));
443
rdpdr_send_device_list_announce_request(plugin);
446
case PAKID_CORE_DEVICE_REPLY:
447
/* connect to a specific resource */
448
deviceID = GET_UINT32(data, 4);
449
status = GET_UINT32(data, 8);
450
LLOGLN(10, ("PAKID_CORE_DEVICE_REPLY (deviceID=%d status=%d)", deviceID, status));
453
case PAKID_CORE_DEVICE_IOREQUEST:
454
LLOGLN(10, ("PAKID_CORE_DEVICE_IOREQUEST"));
455
rdpdr_process_irp(plugin, &data[4], data_size - 4);
459
LLOGLN(0, ("unknown packetID: 0x%02X", packetID));
464
else if (component == RDPDR_CTYP_PRN)
466
LLOGLN(10, ("RDPDR_CTYP_PRN"));
467
rdpdr_process_prn(plugin, packetID, &data[4], data_size - 4);
471
LLOGLN(0, ("RDPDR component: 0x%02X packetID: 0x%02X\n", component, packetID));
477
/* process the linked list of data that has come in */
479
thread_process_data(rdpdrPlugin * plugin)
483
struct data_in_item * item;
487
if (wait_obj_is_set(plugin->term_event))
492
pthread_mutex_lock(plugin->mutex);
494
if (plugin->list_head == 0)
496
pthread_mutex_unlock(plugin->mutex);
500
data = plugin->list_head->data;
501
data_size = plugin->list_head->data_size;
502
item = plugin->list_head;
503
plugin->list_head = plugin->list_head->next;
505
if (plugin->list_head == 0)
507
plugin->list_tail = 0;
510
pthread_mutex_unlock(plugin->mutex);
513
thread_process_message(plugin, data, data_size);
526
thread_func(void * arg)
528
rdpdrPlugin * plugin;
529
struct wait_obj * listobj[2];
532
plugin = (rdpdrPlugin *) arg;
534
plugin->thread_status = 1;
535
LLOGLN(10, ("thread_func: in"));
539
listobj[0] = plugin->term_event;
540
listobj[1] = plugin->data_in_event;
542
wait_obj_select(listobj, numobj, NULL, 0, -1);
544
if (wait_obj_is_set(plugin->term_event))
548
if (wait_obj_is_set(plugin->data_in_event))
550
wait_obj_clear(plugin->data_in_event);
551
/* process data in */
552
thread_process_data(plugin);
556
LLOGLN(10, ("thread_func: out"));
557
plugin->thread_status = -1;
562
OpenEventProcessReceived(uint32 openHandle, void * pData, uint32 dataLength,
563
uint32 totalLength, uint32 dataFlags)
565
rdpdrPlugin * plugin;
567
plugin = (rdpdrPlugin *) chan_plugin_find_by_open_handle(openHandle);
569
LLOGLN(10, ("OpenEventProcessReceived: receive openHandle %d dataLength %d "
570
"totalLength %d dataFlags %d",
571
openHandle, dataLength, totalLength, dataFlags));
573
if (dataFlags & CHANNEL_FLAG_FIRST)
575
plugin->data_in_read = 0;
576
if (plugin->data_in != 0)
578
free(plugin->data_in);
580
plugin->data_in = (char *) malloc(totalLength);
581
plugin->data_in_size = totalLength;
584
memcpy(plugin->data_in + plugin->data_in_read, pData, dataLength);
585
plugin->data_in_read += dataLength;
587
if (dataFlags & CHANNEL_FLAG_LAST)
589
if (plugin->data_in_read != plugin->data_in_size)
591
LLOGLN(0, ("OpenEventProcessReceived: read error"));
593
signal_data_in(plugin);
598
OpenEvent(uint32 openHandle, uint32 event, void * pData, uint32 dataLength,
599
uint32 totalLength, uint32 dataFlags)
601
LLOGLN(10, ("OpenEvent: event %d", event));
604
case CHANNEL_EVENT_DATA_RECEIVED:
605
OpenEventProcessReceived(openHandle, pData, dataLength,
606
totalLength, dataFlags);
608
case CHANNEL_EVENT_WRITE_COMPLETE:
615
InitEventProcessConnected(void * pInitHandle, void * pData, uint32 dataLength)
617
rdpdrPlugin * plugin;
621
plugin = (rdpdrPlugin *) chan_plugin_find_by_init_handle(pInitHandle);
624
LLOGLN(0, ("InitEventProcessConnected: error no match"));
627
error = plugin->ep.pVirtualChannelOpen(pInitHandle, &(plugin->open_handle),
628
plugin->channel_def.name, OpenEvent);
629
if (error != CHANNEL_RC_OK)
631
LLOGLN(0, ("InitEventProcessConnected: Open failed"));
633
chan_plugin_register_open_handle((rdpChanPlugin *) plugin, plugin->open_handle);
635
pthread_create(&thread, 0, thread_func, plugin);
636
pthread_detach(thread);
640
InitEventProcessTerminated(void * pInitHandle)
642
rdpdrPlugin * plugin;
644
struct data_in_item * in_item;
646
plugin = (rdpdrPlugin *) chan_plugin_find_by_init_handle(pInitHandle);
649
LLOGLN(0, ("InitEventProcessConnected: error no match"));
653
wait_obj_set(plugin->term_event);
655
while ((plugin->thread_status > 0) && (index < 100))
660
wait_obj_free(plugin->term_event);
661
wait_obj_free(plugin->data_in_event);
662
pthread_mutex_destroy(plugin->mutex);
665
/* free the un-processed in/out queue */
666
while (plugin->list_head != 0)
668
in_item = plugin->list_head;
669
plugin->list_head = in_item->next;
674
devman_free(plugin->devman);
675
chan_plugin_uninit((rdpChanPlugin *) plugin);
680
InitEvent(void * pInitHandle, uint32 event, void * pData, uint32 dataLength)
682
LLOGLN(10, ("InitEvent: event %d", event));
685
case CHANNEL_EVENT_CONNECTED:
686
InitEventProcessConnected(pInitHandle, pData, dataLength);
688
case CHANNEL_EVENT_DISCONNECTED:
690
case CHANNEL_EVENT_TERMINATED:
691
InitEventProcessTerminated(pInitHandle);
697
VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
699
rdpdrPlugin * plugin;
702
LLOGLN(10, ("VirtualChannelEntry:"));
704
plugin = (rdpdrPlugin *) malloc(sizeof(rdpdrPlugin));
705
memset(plugin, 0, sizeof(rdpdrPlugin));
707
chan_plugin_init((rdpChanPlugin *) plugin);
709
plugin->data_in_size = 0;
711
plugin->ep = *pEntryPoints;
713
memset(&(plugin->channel_def), 0, sizeof(plugin->channel_def));
714
plugin->channel_def.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP;
715
strcpy(plugin->channel_def.name, "rdpdr");
717
plugin->mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
718
pthread_mutex_init(plugin->mutex, 0);
719
plugin->list_head = 0;
720
plugin->list_tail = 0;
722
plugin->term_event = wait_obj_new("freerdprdpdrterm");
723
plugin->data_in_event = wait_obj_new("freerdprdpdrdatain");
725
plugin->thread_status = 0;
727
if (pEntryPoints->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_EX))
729
data = (((PCHANNEL_ENTRY_POINTS_EX)pEntryPoints)->pExtendedData);
735
plugin->devman = devman_new(data);
736
devman_load_device_service(plugin->devman, "disk");
737
devman_load_device_service(plugin->devman, "printer");
739
plugin->ep.pVirtualChannelInit(&plugin->chan_plugin.init_handle, &plugin->channel_def, 1,
740
VIRTUAL_CHANNEL_VERSION_WIN2000, InitEvent);