~ubuntu-branches/ubuntu/raring/freerdp/raring

« back to all changes in this revision

Viewing changes to channels/rdpdr/rdpdr_main.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2010-06-23 21:39:09 UTC
  • Revision ID: james.westby@ubuntu.com-20100623213909-bb9pvvv03913tdv6
Tags: upstream-0.7.1
ImportĀ upstreamĀ versionĀ 0.7.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright (c) 2009-2010 Jay Sorg
 
3
 
 
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:
 
10
 
 
11
   The above copyright notice and this permission notice shall be included
 
12
   in all copies or substantial portions of the Software.
 
13
 
 
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.
 
21
 
 
22
*/
 
23
 
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
#include <pthread.h>
 
28
#include <unistd.h>
 
29
#include <sys/time.h>
 
30
 
 
31
#include "rdpdr_types.h"
 
32
#include "rdpdr_main.h"
 
33
#include "rdpdr_constants.h"
 
34
#include "rdpdr_capabilities.h"
 
35
#include "devman.h"
 
36
#include "irp.h"
 
37
 
 
38
/* called by main thread
 
39
   add item to linked list and inform worker thread that there is data */
 
40
static void
 
41
signal_data_in(rdpdrPlugin * plugin)
 
42
{
 
43
        struct data_in_item * item;
 
44
 
 
45
        item = (struct data_in_item *) malloc(sizeof(struct data_in_item));
 
46
        item->next = 0;
 
47
        item->data = plugin->data_in;
 
48
        plugin->data_in = 0;
 
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)
 
53
        {
 
54
                plugin->list_head = item;
 
55
                plugin->list_tail = item;
 
56
        }
 
57
        else
 
58
        {
 
59
                plugin->list_tail->next = item;
 
60
                plugin->list_tail = item;
 
61
        }
 
62
        pthread_mutex_unlock(plugin->mutex);
 
63
        wait_obj_set(plugin->data_in_event);
 
64
}
 
65
 
 
66
static void
 
67
rdpdr_process_server_announce_request(rdpdrPlugin * plugin, char* data, int data_size)
 
68
{
 
69
        /* versionMajor, must be 1 */
 
70
        plugin->versionMinor = GET_UINT16(data, 2); /* versionMinor */
 
71
        plugin->clientID = GET_UINT32(data, 4); /* clientID */
 
72
 
 
73
        LLOGLN(0, ("Version Minor: %d", plugin->versionMinor));
 
74
 
 
75
#if 0
 
76
        switch(plugin->versionMinor)
 
77
        {
 
78
                case 0x000C:
 
79
                        LLOGLN(0, ("Windows Vista, Windows Vista SP1, Windows Server 2008, Windows 7, and Windows Server 2008 R2"));
 
80
                        break;
 
81
 
 
82
                case 0x000A:
 
83
                        LLOGLN(0, ("Windows Server 2003 SP2"));
 
84
                        break;
 
85
 
 
86
                case 0x0006:
 
87
                        LLOGLN(0, ("Windows XP SP3"));
 
88
                        break;
 
89
 
 
90
                case 0x0005:
 
91
                        LLOGLN(0, ("Windows XP, Windows XP SP1, Windows XP SP2, Windows Server 2003, and Windows Server 2003 SP1"));
 
92
                        break;
 
93
 
 
94
                case 0x0002:
 
95
                        LLOGLN(0, ("Windows 2000"));
 
96
                        break;
 
97
        }
 
98
#endif
 
99
}
 
100
 
 
101
static int
 
102
rdpdr_send_client_announce_reply(rdpdrPlugin * plugin)
 
103
{
 
104
        uint32 error;
 
105
        char* out_data = malloc(12);
 
106
 
 
107
        SET_UINT16(out_data, 0, RDPDR_CTYP_CORE);
 
108
        SET_UINT16(out_data, 2, PAKID_CORE_CLIENTID_CONFIRM);
 
109
 
 
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 */
 
113
 
 
114
        error = plugin->ep.pVirtualChannelWrite(plugin->open_handle, out_data, 12, out_data);
 
115
 
 
116
        if (error != CHANNEL_RC_OK)
 
117
        {
 
118
                LLOGLN(0, ("thread_process_message_formats: "
 
119
                        "VirtualChannelWrite failed %d", error));
 
120
                return 1;
 
121
        }
 
122
 
 
123
        return 0;
 
124
}
 
125
 
 
126
static void
 
127
rdpdr_process_server_clientid_confirm(rdpdrPlugin * plugin, char* data, int data_size)
 
128
{
 
129
        uint16 versionMinor;
 
130
        uint32 clientID;
 
131
 
 
132
        /* versionMajor, must be 1 */
 
133
        versionMinor = GET_UINT16(data, 2); /* versionMinor */
 
134
        clientID = GET_UINT32(data, 4); /* clientID */
 
135
 
 
136
        if (clientID != plugin->clientID)
 
137
                plugin->clientID = clientID;
 
138
 
 
139
        if (versionMinor != plugin->versionMinor)
 
140
                plugin->versionMinor = versionMinor;
 
141
}
 
142
 
 
143
static int
 
144
rdpdr_send_client_name_request(rdpdrPlugin * plugin)
 
145
{
 
146
        char * data;
 
147
        int size;
 
148
        uint32 error;
 
149
        char computerName[256];
 
150
        uint32 computerNameLen;
 
151
        uint32 computerNameLenW;
 
152
 
 
153
        gethostname(computerName, sizeof(computerName) - 1);
 
154
        computerNameLen = strlen(computerName);
 
155
        size = 16 + computerNameLen * 2 + 2;
 
156
        data = malloc(size);
 
157
        memset(data, 0, size);
 
158
 
 
159
        SET_UINT16(data, 0, RDPDR_CTYP_CORE);
 
160
        SET_UINT16(data, 2, PAKID_CORE_CLIENT_NAME);
 
161
 
 
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
 
164
 
 
165
        computerNameLenW = set_wstr(&data[16], size - 16, computerName, computerNameLen); /* computerName */
 
166
        SET_UINT32(data, 12, computerNameLenW + 2); /* computerNameLen, including null terminator */
 
167
 
 
168
        error = plugin->ep.pVirtualChannelWrite(plugin->open_handle,
 
169
                                data, 16 + computerNameLenW + 2, data);
 
170
 
 
171
        if (error != CHANNEL_RC_OK)
 
172
        {
 
173
                LLOGLN(0, ("thread_process_message_formats: "
 
174
                        "VirtualChannelWrite failed %d", error));
 
175
                return 1;
 
176
        }
 
177
 
 
178
        return 0;
 
179
}
 
180
 
 
181
static int
 
182
rdpdr_send_device_list_announce_request(rdpdrPlugin * plugin)
 
183
{
 
184
        char* out_data;
 
185
        int size;
 
186
        uint32 error;
 
187
        DEVICE* pdev;
 
188
        int offset = 0;
 
189
        int i;
 
190
 
 
191
        size = 8;
 
192
        out_data = malloc(size);
 
193
        memset(out_data, 0, size);
 
194
 
 
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 */
 
198
        offset = 8;
 
199
 
 
200
        LLOGLN(0, ("%d device(s) registered", plugin->devman->count));
 
201
 
 
202
        devman_rewind(plugin->devman);
 
203
 
 
204
        while (devman_has_next(plugin->devman) != 0)
 
205
        {
 
206
                pdev = devman_get_next(plugin->devman);
 
207
 
 
208
                size += 20 + pdev->data_len;
 
209
                out_data = realloc(out_data, size);
 
210
 
 
211
                SET_UINT32(out_data, offset, pdev->service->type); /* deviceType */
 
212
                SET_UINT32(out_data, offset + 4, pdev->id); /* deviceID */
 
213
                offset += 8;
 
214
 
 
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++)
 
218
                {
 
219
                        if (out_data[offset + i] < 0)
 
220
                        {
 
221
                                out_data[offset + i] = '_';
 
222
                        }
 
223
                }
 
224
                offset += 8;
 
225
 
 
226
                LLOGLN(0, ("registered device: %s (type=%d id=%d)", pdev->name, pdev->service->type, pdev->id));
 
227
 
 
228
                SET_UINT32(out_data, offset, pdev->data_len);
 
229
                offset += 4;
 
230
                if (pdev->data_len > 0)
 
231
                {
 
232
                        memcpy(&out_data[offset], pdev->data, pdev->data_len);
 
233
                        offset += pdev->data_len;
 
234
                }
 
235
        }
 
236
 
 
237
        error = plugin->ep.pVirtualChannelWrite(plugin->open_handle,
 
238
                        out_data, offset, out_data);
 
239
 
 
240
        if (error != CHANNEL_RC_OK)
 
241
        {
 
242
                LLOGLN(0, ("thread_process_message_formats: "
 
243
                        "VirtualChannelWrite failed %d", error));
 
244
                return 1;
 
245
        }
 
246
 
 
247
        return 0;
 
248
}
 
249
 
 
250
static void
 
251
rdpdr_process_irp(rdpdrPlugin * plugin, char* data, int data_size)
 
252
{
 
253
        IRP irp;
 
254
        int deviceID;
 
255
        char * out;
 
256
        int out_size;
 
257
        int error;
 
258
 
 
259
        memset((void*)&irp, '\0', sizeof(IRP));
 
260
 
 
261
        irp.ioStatus = RD_STATUS_SUCCESS;
 
262
 
 
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 */
 
269
 
 
270
        irp.dev = devman_get_device_by_id(plugin->devman, deviceID);
 
271
 
 
272
        LLOGLN(10, ("IRP MAJOR: %d MINOR: %d", irp.majorFunction, irp.minorFunction));
 
273
 
 
274
        switch(irp.majorFunction)
 
275
        {
 
276
                case IRP_MJ_CREATE:
 
277
                        LLOGLN(10, ("IRP_MJ_CREATE"));
 
278
                        irp_process_create_request(&irp, &data[20], data_size - 20);
 
279
                        break;
 
280
 
 
281
                case IRP_MJ_CLOSE:
 
282
                        LLOGLN(10, ("IRP_MJ_CLOSE"));
 
283
                        irp_process_close_request(&irp, &data[20], data_size - 20);
 
284
                        break;
 
285
 
 
286
                case IRP_MJ_READ:
 
287
                        LLOGLN(10, ("IRP_MJ_READ"));
 
288
                        irp_process_read_request(&irp, &data[20], data_size - 20);
 
289
                        break;
 
290
 
 
291
                case IRP_MJ_WRITE:
 
292
                        LLOGLN(10, ("IRP_MJ_WRITE"));
 
293
                        irp_process_write_request(&irp, &data[20], data_size - 20);
 
294
                        break;
 
295
 
 
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);
 
299
                        break;
 
300
 
 
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);
 
304
                        break;
 
305
 
 
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);
 
309
                        break;
 
310
 
 
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);
 
314
                        break;
 
315
 
 
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);
 
319
                        break;
 
320
 
 
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);
 
324
                        break;
 
325
 
 
326
                default:
 
327
                        LLOGLN(0, ("IRP majorFunction=0x%x minorFunction=0x%x not supported", irp.majorFunction, irp.minorFunction));
 
328
                        irp.ioStatus = RD_STATUS_NOT_SUPPORTED;
 
329
                        break;
 
330
        }
 
331
 
 
332
        if (irp.ioStatus != RD_STATUS_PENDING)
 
333
        {
 
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)
 
337
                {
 
338
                        LLOGLN(0, ("rdpdr_process_irp: "
 
339
                                "VirtualChannelWrite failed %d", error));
 
340
                }
 
341
        }
 
342
        if (irp.outputBuffer)
 
343
                free(irp.outputBuffer);
 
344
}
 
345
 
 
346
static int
 
347
rdpdr_send_capabilities(rdpdrPlugin * plugin)
 
348
{
 
349
        int size;
 
350
        int offset;
 
351
        char* data;
 
352
        uint32 error;
 
353
 
 
354
        size = 256;
 
355
        data = (char*)malloc(size);
 
356
        memset(data, 0, size);
 
357
 
 
358
        SET_UINT16(data, 0, RDPDR_CTYP_CORE);
 
359
        SET_UINT16(data, 2, PAKID_CORE_CLIENT_CAPABILITY);
 
360
 
 
361
        SET_UINT16(data, 4, 5); /* numCapabilities */
 
362
        SET_UINT16(data, 6, 0); /* pad */
 
363
 
 
364
        offset = 8;
 
365
 
 
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);
 
371
 
 
372
        error = plugin->ep.pVirtualChannelWrite(plugin->open_handle,
 
373
                        data, offset, data);
 
374
 
 
375
        if (error != CHANNEL_RC_OK)
 
376
        {
 
377
                LLOGLN(0, ("thread_process_message_formats: "
 
378
                        "VirtualChannelWrite failed %d", error));
 
379
 
 
380
                return -1;
 
381
        }
 
382
 
 
383
        return 0;
 
384
}
 
385
 
 
386
static void
 
387
rdpdr_process_prn(rdpdrPlugin * plugin, int type, char * data, int data_size)
 
388
{
 
389
        SERVICE * srv;
 
390
 
 
391
        /* Pass the control to the printer sub-plugin service, if registered */
 
392
        srv = devman_get_service_by_type(plugin->devman, RDPDR_DTYP_PRINT);
 
393
        if (srv == NULL)
 
394
        {
 
395
                LLOGLN(0, ("rdpdr_process_prn: printer service not register"));
 
396
                return;
 
397
        }
 
398
        if (srv->process_data == NULL)
 
399
        {
 
400
                LLOGLN(0, ("rdpdr_process_prn: printer service does not support"));
 
401
                return;
 
402
        }
 
403
        srv->process_data(srv, type, data, data_size);
 
404
}
 
405
 
 
406
static int
 
407
thread_process_message(rdpdrPlugin * plugin, char * data, int data_size)
 
408
{
 
409
        uint16 component;
 
410
        uint16 packetID;
 
411
        uint32 deviceID;
 
412
        uint32 status;
 
413
 
 
414
        component = GET_UINT16(data, 0);
 
415
        packetID = GET_UINT16(data, 2);
 
416
 
 
417
        if (component == RDPDR_CTYP_CORE)
 
418
        {
 
419
                LLOGLN(10, ("RDPDR_CTYP_CORE"));
 
420
                switch (packetID)
 
421
                {
 
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);
 
427
                                break;
 
428
 
 
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);
 
434
                                break;
 
435
 
 
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);
 
439
                                break;
 
440
 
 
441
                        case PAKID_CORE_USER_LOGGEDON:
 
442
                                LLOGLN(10, ("PAKID_CORE_USER_LOGGEDON"));
 
443
                                rdpdr_send_device_list_announce_request(plugin);
 
444
                                break;
 
445
 
 
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));
 
451
                                break;
 
452
 
 
453
                        case PAKID_CORE_DEVICE_IOREQUEST:
 
454
                                LLOGLN(10, ("PAKID_CORE_DEVICE_IOREQUEST"));
 
455
                                rdpdr_process_irp(plugin, &data[4], data_size - 4);
 
456
                                break;
 
457
 
 
458
                        default:
 
459
                                LLOGLN(0, ("unknown packetID: 0x%02X", packetID));
 
460
                                break;
 
461
 
 
462
                }
 
463
        }
 
464
        else if (component == RDPDR_CTYP_PRN)
 
465
        {
 
466
                LLOGLN(10, ("RDPDR_CTYP_PRN"));
 
467
                rdpdr_process_prn(plugin, packetID, &data[4], data_size - 4);
 
468
        }
 
469
        else
 
470
        {
 
471
                LLOGLN(0, ("RDPDR component: 0x%02X packetID: 0x%02X\n", component, packetID));
 
472
        }
 
473
 
 
474
        return 0;
 
475
}
 
476
 
 
477
/* process the linked list of data that has come in */
 
478
static int
 
479
thread_process_data(rdpdrPlugin * plugin)
 
480
{
 
481
        char * data;
 
482
        int data_size;
 
483
        struct data_in_item * item;
 
484
 
 
485
        while (1)
 
486
        {
 
487
                if (wait_obj_is_set(plugin->term_event))
 
488
                {
 
489
                        break;
 
490
                }
 
491
 
 
492
                pthread_mutex_lock(plugin->mutex);
 
493
 
 
494
                if (plugin->list_head == 0)
 
495
                {
 
496
                        pthread_mutex_unlock(plugin->mutex);
 
497
                        break;
 
498
                }
 
499
 
 
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;
 
504
 
 
505
                if (plugin->list_head == 0)
 
506
                {
 
507
                        plugin->list_tail = 0;
 
508
                }
 
509
 
 
510
                pthread_mutex_unlock(plugin->mutex);
 
511
                if (data != 0)
 
512
                {
 
513
                        thread_process_message(plugin, data, data_size);
 
514
                        free(data);
 
515
                }
 
516
                if (item != 0)
 
517
                {
 
518
                        free(item);
 
519
                }
 
520
        }
 
521
 
 
522
        return 0;
 
523
}
 
524
 
 
525
static void *
 
526
thread_func(void * arg)
 
527
{
 
528
        rdpdrPlugin * plugin;
 
529
        struct wait_obj * listobj[2];
 
530
        int numobj;
 
531
 
 
532
        plugin = (rdpdrPlugin *) arg;
 
533
 
 
534
        plugin->thread_status = 1;
 
535
        LLOGLN(10, ("thread_func: in"));
 
536
 
 
537
        while (1)
 
538
        {
 
539
                listobj[0] = plugin->term_event;
 
540
                listobj[1] = plugin->data_in_event;
 
541
                numobj = 2;
 
542
                wait_obj_select(listobj, numobj, NULL, 0, -1);
 
543
 
 
544
                if (wait_obj_is_set(plugin->term_event))
 
545
                {
 
546
                        break;
 
547
                }
 
548
                if (wait_obj_is_set(plugin->data_in_event))
 
549
                {
 
550
                        wait_obj_clear(plugin->data_in_event);
 
551
                        /* process data in */
 
552
                        thread_process_data(plugin);
 
553
                }
 
554
        }
 
555
 
 
556
        LLOGLN(10, ("thread_func: out"));
 
557
        plugin->thread_status = -1;
 
558
        return 0;
 
559
}
 
560
 
 
561
static void
 
562
OpenEventProcessReceived(uint32 openHandle, void * pData, uint32 dataLength,
 
563
        uint32 totalLength, uint32 dataFlags)
 
564
{
 
565
        rdpdrPlugin * plugin;
 
566
 
 
567
        plugin = (rdpdrPlugin *) chan_plugin_find_by_open_handle(openHandle);
 
568
 
 
569
        LLOGLN(10, ("OpenEventProcessReceived: receive openHandle %d dataLength %d "
 
570
                "totalLength %d dataFlags %d",
 
571
                openHandle, dataLength, totalLength, dataFlags));
 
572
 
 
573
        if (dataFlags & CHANNEL_FLAG_FIRST)
 
574
        {
 
575
                plugin->data_in_read = 0;
 
576
                if (plugin->data_in != 0)
 
577
                {
 
578
                        free(plugin->data_in);
 
579
                }
 
580
                plugin->data_in = (char *) malloc(totalLength);
 
581
                plugin->data_in_size = totalLength;
 
582
        }
 
583
 
 
584
        memcpy(plugin->data_in + plugin->data_in_read, pData, dataLength);
 
585
        plugin->data_in_read += dataLength;
 
586
 
 
587
        if (dataFlags & CHANNEL_FLAG_LAST)
 
588
        {
 
589
                if (plugin->data_in_read != plugin->data_in_size)
 
590
                {
 
591
                        LLOGLN(0, ("OpenEventProcessReceived: read error"));
 
592
                }
 
593
                signal_data_in(plugin);
 
594
        }
 
595
}
 
596
 
 
597
static void
 
598
OpenEvent(uint32 openHandle, uint32 event, void * pData, uint32 dataLength,
 
599
        uint32 totalLength, uint32 dataFlags)
 
600
{
 
601
        LLOGLN(10, ("OpenEvent: event %d", event));
 
602
        switch (event)
 
603
        {
 
604
                case CHANNEL_EVENT_DATA_RECEIVED:
 
605
                        OpenEventProcessReceived(openHandle, pData, dataLength,
 
606
                                totalLength, dataFlags);
 
607
                        break;
 
608
                case CHANNEL_EVENT_WRITE_COMPLETE:
 
609
                        free(pData);
 
610
                        break;
 
611
        }
 
612
}
 
613
 
 
614
static void
 
615
InitEventProcessConnected(void * pInitHandle, void * pData, uint32 dataLength)
 
616
{
 
617
        rdpdrPlugin * plugin;
 
618
        uint32 error;
 
619
        pthread_t thread;
 
620
 
 
621
        plugin = (rdpdrPlugin *) chan_plugin_find_by_init_handle(pInitHandle);
 
622
        if (plugin == NULL)
 
623
        {
 
624
                LLOGLN(0, ("InitEventProcessConnected: error no match"));
 
625
        }
 
626
 
 
627
        error = plugin->ep.pVirtualChannelOpen(pInitHandle, &(plugin->open_handle),
 
628
                plugin->channel_def.name, OpenEvent);
 
629
        if (error != CHANNEL_RC_OK)
 
630
        {
 
631
                LLOGLN(0, ("InitEventProcessConnected: Open failed"));
 
632
        }
 
633
        chan_plugin_register_open_handle((rdpChanPlugin *) plugin, plugin->open_handle);
 
634
 
 
635
        pthread_create(&thread, 0, thread_func, plugin);
 
636
        pthread_detach(thread);
 
637
}
 
638
 
 
639
static void
 
640
InitEventProcessTerminated(void * pInitHandle)
 
641
{
 
642
        rdpdrPlugin * plugin;
 
643
        int index;
 
644
        struct data_in_item * in_item;
 
645
 
 
646
        plugin = (rdpdrPlugin *) chan_plugin_find_by_init_handle(pInitHandle);
 
647
        if (plugin == NULL)
 
648
        {
 
649
                LLOGLN(0, ("InitEventProcessConnected: error no match"));
 
650
                return;
 
651
        }
 
652
 
 
653
        wait_obj_set(plugin->term_event);
 
654
        index = 0;
 
655
        while ((plugin->thread_status > 0) && (index < 100))
 
656
        {
 
657
                index++;
 
658
                usleep(250 * 1000);
 
659
        }
 
660
        wait_obj_free(plugin->term_event);
 
661
        wait_obj_free(plugin->data_in_event);
 
662
        pthread_mutex_destroy(plugin->mutex);
 
663
        free(plugin->mutex);
 
664
 
 
665
        /* free the un-processed in/out queue */
 
666
        while (plugin->list_head != 0)
 
667
        {
 
668
                in_item = plugin->list_head;
 
669
                plugin->list_head = in_item->next;
 
670
                free(in_item->data);
 
671
                free(in_item);
 
672
        }
 
673
 
 
674
        devman_free(plugin->devman);
 
675
        chan_plugin_uninit((rdpChanPlugin *) plugin);
 
676
        free(plugin);
 
677
}
 
678
 
 
679
static void
 
680
InitEvent(void * pInitHandle, uint32 event, void * pData, uint32 dataLength)
 
681
{
 
682
        LLOGLN(10, ("InitEvent: event %d", event));
 
683
        switch (event)
 
684
        {
 
685
                case CHANNEL_EVENT_CONNECTED:
 
686
                        InitEventProcessConnected(pInitHandle, pData, dataLength);
 
687
                        break;
 
688
                case CHANNEL_EVENT_DISCONNECTED:
 
689
                        break;
 
690
                case CHANNEL_EVENT_TERMINATED:
 
691
                        InitEventProcessTerminated(pInitHandle);
 
692
                        break;
 
693
        }
 
694
}
 
695
 
 
696
int
 
697
VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
 
698
{
 
699
        rdpdrPlugin * plugin;
 
700
        void * data;
 
701
 
 
702
        LLOGLN(10, ("VirtualChannelEntry:"));
 
703
 
 
704
        plugin = (rdpdrPlugin *) malloc(sizeof(rdpdrPlugin));
 
705
        memset(plugin, 0, sizeof(rdpdrPlugin));
 
706
 
 
707
        chan_plugin_init((rdpChanPlugin *) plugin);
 
708
 
 
709
        plugin->data_in_size = 0;
 
710
        plugin->data_in = 0;
 
711
        plugin->ep = *pEntryPoints;
 
712
 
 
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");
 
716
 
 
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;
 
721
 
 
722
        plugin->term_event = wait_obj_new("freerdprdpdrterm");
 
723
        plugin->data_in_event = wait_obj_new("freerdprdpdrdatain");
 
724
 
 
725
        plugin->thread_status = 0;
 
726
 
 
727
        if (pEntryPoints->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_EX))
 
728
        {
 
729
                data = (((PCHANNEL_ENTRY_POINTS_EX)pEntryPoints)->pExtendedData);
 
730
        }
 
731
        else
 
732
        {
 
733
                data = NULL;
 
734
        }
 
735
        plugin->devman = devman_new(data);
 
736
        devman_load_device_service(plugin->devman, "disk");
 
737
        devman_load_device_service(plugin->devman, "printer");
 
738
 
 
739
        plugin->ep.pVirtualChannelInit(&plugin->chan_plugin.init_handle, &plugin->channel_def, 1,
 
740
                VIRTUAL_CHANNEL_VERSION_WIN2000, InitEvent);
 
741
 
 
742
        return 1;
 
743
}
 
744