/[rdesktop]/sourceforge.net/trunk/rdesktop/rdpdr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/trunk/rdesktop/rdpdr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 592 - (hide annotations)
Fri Jan 30 14:10:32 2004 UTC (20 years, 3 months ago) by n-ki
File MIME type: text/plain
File size: 19379 byte(s)
reworked the asyncio some and completed it. parallel and serial uses it now. disk.c is a likely candidate for the future, but there are some problems with disk.c that we will have to look into first. parallel and serial works better, they do not hang the session, but are still yerky at large chunks... possibly we could split the chunks, but the terminal server does not seem to like partial transfers, i've tried some variations.. :) fns->write() could be split in smaller pieces, but what should the thresholds be.

1 stargo 570 #include <unistd.h>
2 stargo 576 #include <sys/types.h>
3     #include <time.h>
4 matthewc 432 #include "rdesktop.h"
5    
6     #define IRP_MJ_CREATE 0x00
7     #define IRP_MJ_CLOSE 0x02
8     #define IRP_MJ_READ 0x03
9     #define IRP_MJ_WRITE 0x04
10     #define IRP_MJ_DEVICE_CONTROL 0x0e
11    
12 n-ki 569 #define IRP_MJ_CREATE 0x00
13     #define IRP_MJ_CLOSE 0x02
14     #define IRP_MJ_READ 0x03
15     #define IRP_MJ_WRITE 0x04
16     #define IRP_MJ_QUERY_INFORMATION 0x05
17     #define IRP_MJ_SET_INFORMATION 0x06
18     #define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
19     #define IRP_MJ_DIRECTORY_CONTROL 0x0c
20     #define IRP_MJ_DEVICE_CONTROL 0x0e
21    
22     #define IRP_MN_QUERY_DIRECTORY 0x01
23     #define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02
24    
25 matthewc 432 extern char hostname[16];
26     extern DEVICE_FNS serial_fns;
27     extern DEVICE_FNS printer_fns;
28 n-ki 569 extern DEVICE_FNS parallel_fns;
29     extern DEVICE_FNS disk_fns;
30 matthewc 432
31     static VCHANNEL *rdpdr_channel;
32    
33 n-ki 569 /* If select() times out, the request for the device with handle g_min_timeout_fd is aborted */
34     HANDLE g_min_timeout_fd;
35     uint32 g_num_devices;
36    
37     /* Table with information about rdpdr devices */
38     RDPDR_DEVICE g_rdpdr_device[RDPDR_MAX_DEVICES];
39    
40     /* Used to store incoming io request, until they are ready to be completed */
41 n-ki 592 /* using a linked list ensures that they are processed in the right order, */
42     /* if multiple ios are being done on the same fd */
43 n-ki 569 struct async_iorequest
44     {
45 n-ki 592 uint32 fd, major, minor, offset, device, id, length, partial_len;
46 n-ki 569 long timeout, /* Total timeout */
47     itv_timeout; /* Interval timeout (between serial characters) */
48     uint8 *buffer;
49     DEVICE_FNS *fns;
50    
51 n-ki 592 struct async_iorequest *next; /* next element in list */
52     } g_iorequest;
53    
54 n-ki 569 /* Return device_id for a given handle */
55     int
56     get_device_index(HANDLE handle)
57     {
58     int i;
59     for (i = 0; i < RDPDR_MAX_DEVICES; i++)
60     {
61     if (g_rdpdr_device[i].handle == handle)
62     return i;
63     }
64     return -1;
65     }
66    
67     /* Converts a windows path to a unix path */
68 matthewc 432 void
69 n-ki 569 convert_to_unix_filename(char *filename)
70     {
71     char *p;
72    
73     while ((p = strchr(filename, '\\')))
74     {
75     *p = '/';
76     }
77     }
78    
79     /* Add a new io request to the table containing pending io requests so it won't block rdesktop */
80     BOOL
81     add_async_iorequest(uint32 device, uint32 file, uint32 id, uint32 major, uint32 length,
82     DEVICE_FNS * fns, long total_timeout, long interval_timeout, uint8 * buffer)
83     {
84     struct async_iorequest *iorq;
85    
86 n-ki 592 iorq = &g_iorequest;
87     while (iorq->fd != 0)
88 n-ki 569 {
89 n-ki 592 // create new element if needed
90     if (iorq->next == NULL)
91     iorq->next =
92     (struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
93 n-ki 569
94 n-ki 592 iorq = iorq->next;
95     }
96    
97     /* first element is special since it doesn't get deleted */
98     /* don't want to get io out of order */
99     if (g_iorequest.fd == 0)
100     {
101     iorq = &g_iorequest;
102     /* look for first occurrence of fd */
103     while (iorq->next != NULL)
104 n-ki 569 {
105 n-ki 592 if (iorq->fd == file)
106     break;
107     iorq = iorq->next;
108 n-ki 569 }
109 n-ki 592 /* if same create new link at end of chain instead */
110     if (iorq->fd == file)
111     {
112     while (iorq->next != NULL)
113     iorq = iorq->next;
114     iorq->next =
115     (struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
116     iorq = iorq->next;
117     }
118     else
119     iorq = &g_iorequest; /* didn't find fs use first entry */
120 n-ki 569 }
121 n-ki 592
122     iorq->device = device;
123     iorq->fd = file;
124     iorq->id = id;
125     iorq->major = major;
126     iorq->length = length;
127     iorq->partial_len = 0;
128     iorq->fns = fns;
129     iorq->timeout = total_timeout;
130     iorq->itv_timeout = interval_timeout;
131     iorq->buffer = buffer;
132     return True;
133 n-ki 569 }
134    
135     void
136 matthewc 432 rdpdr_send_connect(void)
137     {
138     uint8 magic[4] = "rDCC";
139     STREAM s;
140    
141     s = channel_init(rdpdr_channel, 12);
142     out_uint8a(s, magic, 4);
143 astrand 435 out_uint16_le(s, 1); /* unknown */
144 matthewc 432 out_uint16_le(s, 5);
145 astrand 435 out_uint32_be(s, 0x815ed39d); /* IP address (use 127.0.0.1) 0x815ed39d */
146 matthewc 432 s_mark_end(s);
147     channel_send(s, rdpdr_channel);
148     }
149    
150 n-ki 569
151 matthewc 432 void
152     rdpdr_send_name(void)
153     {
154     uint8 magic[4] = "rDNC";
155 astrand 435 uint32 hostlen = (strlen(hostname) + 1) * 2;
156 matthewc 432 STREAM s;
157    
158 astrand 435 s = channel_init(rdpdr_channel, 16 + hostlen);
159 matthewc 432 out_uint8a(s, magic, 4);
160 astrand 435 out_uint16_le(s, 0x63); /* unknown */
161 matthewc 432 out_uint16_le(s, 0x72);
162     out_uint32(s, 0);
163     out_uint32_le(s, hostlen);
164 astrand 435 rdp_out_unistr(s, hostname, hostlen - 2);
165 matthewc 432 s_mark_end(s);
166     channel_send(s, rdpdr_channel);
167     }
168    
169 n-ki 569 /* Returns the size of the payload of the announce packet */
170     int
171     announcedata_size()
172     {
173     int size, i;
174     PRINTER *printerinfo;
175    
176     size = 8; //static announce size
177     size += g_num_devices * 0x14;
178    
179     for (i = 0; i < g_num_devices; i++)
180     {
181     if (g_rdpdr_device[i].device_type == DEVICE_TYPE_PRINTER)
182     {
183     printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
184     printerinfo->bloblen =
185     printercache_load_blob(printerinfo->printer, &(printerinfo->blob));
186    
187     size += 0x18;
188     size += 2 * strlen(printerinfo->driver) + 2;
189     size += 2 * strlen(printerinfo->printer) + 2;
190     size += printerinfo->bloblen;
191     }
192     }
193    
194     return size;
195     }
196    
197 matthewc 432 void
198     rdpdr_send_available(void)
199     {
200 n-ki 569
201 matthewc 432 uint8 magic[4] = "rDAD";
202 n-ki 569 uint32 driverlen, printerlen, bloblen;
203     int i;
204 matthewc 432 STREAM s;
205 n-ki 569 PRINTER *printerinfo;
206 matthewc 432
207 n-ki 569 s = channel_init(rdpdr_channel, announcedata_size());
208 matthewc 432 out_uint8a(s, magic, 4);
209 n-ki 569 out_uint32_le(s, g_num_devices);
210 matthewc 432
211 n-ki 569 for (i = 0; i < g_num_devices; i++)
212     {
213     out_uint32_le(s, g_rdpdr_device[i].device_type);
214     out_uint32_le(s, i); /* RDP Device ID */
215     out_uint8p(s, g_rdpdr_device[i].name, 8);
216    
217 n-ki 585 switch (g_rdpdr_device[i].device_type)
218 n-ki 569 {
219 n-ki 585 case DEVICE_TYPE_PRINTER:
220     printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
221 n-ki 569
222 n-ki 585 driverlen = 2 * strlen(printerinfo->driver) + 2;
223     printerlen = 2 * strlen(printerinfo->printer) + 2;
224     bloblen = printerinfo->bloblen;
225 n-ki 569
226 n-ki 585 out_uint32_le(s, 24 + driverlen + printerlen + bloblen); /* length of extra info */
227     out_uint32_le(s, printerinfo->default_printer ? 2 : 0);
228     out_uint8s(s, 8); /* unknown */
229     out_uint32_le(s, driverlen);
230     out_uint32_le(s, printerlen);
231     out_uint32_le(s, bloblen);
232     rdp_out_unistr(s, printerinfo->driver, driverlen - 2);
233     rdp_out_unistr(s, printerinfo->printer, printerlen - 2);
234     out_uint8a(s, printerinfo->blob, bloblen);
235 n-ki 569
236 n-ki 585 xfree(printerinfo->blob); /* Blob is sent twice if reconnecting */
237     break;
238     default:
239     out_uint32(s, 0);
240 n-ki 569 }
241     }
242 matthewc 432 #if 0
243 astrand 435 out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */
244 matthewc 432 out_uint32_le(s, 0);
245     out_uint8p(s, "SCARD", 5);
246     out_uint8s(s, 3);
247     out_uint32(s, 0);
248     #endif
249    
250     s_mark_end(s);
251     channel_send(s, rdpdr_channel);
252     }
253    
254     void
255 astrand 435 rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
256     uint32 length)
257 matthewc 432 {
258     uint8 magic[4] = "rDCI";
259     STREAM s;
260    
261     s = channel_init(rdpdr_channel, 20 + length);
262     out_uint8a(s, magic, 4);
263     out_uint32_le(s, device);
264     out_uint32_le(s, id);
265     out_uint32_le(s, status);
266     out_uint32_le(s, result);
267     out_uint8p(s, buffer, length);
268     s_mark_end(s);
269 n-ki 569 /* JIF
270     hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
271 matthewc 432 channel_send(s, rdpdr_channel);
272     }
273    
274     static void
275     rdpdr_process_irp(STREAM s)
276     {
277 n-ki 569 uint32 result = 0,
278     length = 0,
279     desired_access = 0,
280     request,
281     file,
282     info_level,
283     buffer_len,
284     id,
285     major,
286     minor,
287     device,
288     offset,
289     bytes_in,
290     bytes_out,
291     error_mode,
292     share_mode, disposition, total_timeout, interval_timeout, flags_and_attributes = 0;
293    
294     char filename[256];
295     uint8 *buffer, *pst_buf;
296 matthewc 432 struct stream out;
297     DEVICE_FNS *fns;
298 n-ki 569 BOOL rw_blocking = True;
299     NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
300 matthewc 432
301     in_uint32_le(s, device);
302     in_uint32_le(s, file);
303     in_uint32_le(s, id);
304     in_uint32_le(s, major);
305     in_uint32_le(s, minor);
306    
307 n-ki 569 buffer_len = 0;
308     buffer = (uint8 *) xmalloc(1024);
309     buffer[0] = 0;
310 matthewc 432
311 n-ki 569 switch (g_rdpdr_device[device].device_type)
312 matthewc 432 {
313 n-ki 569 case DEVICE_TYPE_SERIAL:
314    
315 matthewc 432 fns = &serial_fns;
316 n-ki 592 rw_blocking = False;
317 n-ki 569 break;
318    
319     case DEVICE_TYPE_PARALLEL:
320    
321     fns = &parallel_fns;
322 n-ki 592 rw_blocking = False;
323 n-ki 569 break;
324    
325     case DEVICE_TYPE_PRINTER:
326    
327 matthewc 432 fns = &printer_fns;
328 n-ki 569 break;
329    
330     case DEVICE_TYPE_DISK:
331    
332 n-ki 592 /*rw_blocking = False; */
333 n-ki 569 fns = &disk_fns;
334     break;
335    
336     case DEVICE_TYPE_SCARD:
337 matthewc 432 default:
338 n-ki 569
339 matthewc 432 error("IRP for bad device %ld\n", device);
340     return;
341     }
342    
343     switch (major)
344     {
345     case IRP_MJ_CREATE:
346 n-ki 569
347     in_uint32_be(s, desired_access);
348     in_uint8s(s, 0x08); // unknown
349     in_uint32_le(s, error_mode);
350     in_uint32_le(s, share_mode);
351     in_uint32_le(s, disposition);
352     in_uint32_le(s, flags_and_attributes);
353     in_uint32_le(s, length);
354    
355     if (length && (length / 2) < 256)
356     {
357     rdp_in_unistr(s, filename, length);
358     convert_to_unix_filename(filename);
359     }
360     else
361     {
362     filename[0] = 0;
363     }
364    
365     if (!fns->create)
366     {
367     status = STATUS_NOT_SUPPORTED;
368     break;
369     }
370    
371     status = fns->create(device, desired_access, share_mode, disposition,
372     flags_and_attributes, filename, &result);
373     buffer_len = 1;
374 matthewc 432 break;
375    
376     case IRP_MJ_CLOSE:
377 n-ki 569 if (!fns->close)
378     {
379     status = STATUS_NOT_SUPPORTED;
380     break;
381     }
382    
383     status = fns->close(file);
384 matthewc 432 break;
385    
386     case IRP_MJ_READ:
387 n-ki 569
388     if (!fns->read)
389 matthewc 432 {
390 n-ki 569 status = STATUS_NOT_SUPPORTED;
391     break;
392     }
393    
394     in_uint32_le(s, length);
395     in_uint32_le(s, offset);
396     #if WITH_DEBUG_RDP5
397     DEBUG(("RDPDR IRP Read (length: %d, offset: %d)\n", length, offset));
398     #endif
399 n-ki 592 if (rw_blocking) // Complete read immediately
400     {
401 n-ki 569 buffer = (uint8 *) xrealloc((void *) buffer, length);
402     status = fns->read(file, buffer, length, offset, &result);
403 matthewc 432 buffer_len = result;
404 n-ki 569 break;
405 n-ki 592 }
406 n-ki 569
407     // Add request to table
408     pst_buf = (uint8 *) xmalloc(length);
409     serial_get_timeout(file, length, &total_timeout, &interval_timeout);
410     if (add_async_iorequest
411     (device, file, id, major, length, fns, total_timeout, interval_timeout,
412     pst_buf))
413     {
414     status = STATUS_PENDING;
415     break;
416     }
417    
418     status = STATUS_CANCELLED;
419 matthewc 432 break;
420     case IRP_MJ_WRITE:
421 n-ki 569
422     buffer_len = 1;
423    
424     if (!fns->write)
425     {
426     status = STATUS_NOT_SUPPORTED;
427     break;
428     }
429    
430     in_uint32_le(s, length);
431     in_uint32_le(s, offset);
432     in_uint8s(s, 0x18);
433     #if WITH_DEBUG_RDP5
434     DEBUG(("RDPDR IRP Write (length: %d)\n", result));
435     #endif
436 n-ki 592 if (rw_blocking) // Complete immediately
437     {
438 n-ki 569 status = fns->write(file, s->p, length, offset, &result);
439     break;
440 n-ki 592 }
441    
442 n-ki 569 // Add to table
443     pst_buf = (uint8 *) xmalloc(length);
444     in_uint8a(s, pst_buf, length);
445    
446     if (add_async_iorequest
447     (device, file, id, major, length, fns, 0, 0, pst_buf))
448     {
449     status = STATUS_PENDING;
450     break;
451     }
452    
453     status = STATUS_CANCELLED;
454 matthewc 432 break;
455    
456 n-ki 569 case IRP_MJ_QUERY_INFORMATION:
457    
458     if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
459     {
460     status = STATUS_INVALID_HANDLE;
461     break;
462     }
463     in_uint32_le(s, info_level);
464    
465     out.data = out.p = buffer;
466     out.size = sizeof(buffer);
467     status = disk_query_information(file, info_level, &out);
468     result = buffer_len = out.p - out.data;
469    
470     break;
471    
472     case IRP_MJ_SET_INFORMATION:
473    
474     if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
475     {
476     status = STATUS_INVALID_HANDLE;
477     break;
478     }
479    
480     in_uint32_le(s, info_level);
481    
482     out.data = out.p = buffer;
483     out.size = sizeof(buffer);
484     status = disk_set_information(file, info_level, s, &out);
485     result = buffer_len = out.p - out.data;
486     break;
487    
488     case IRP_MJ_QUERY_VOLUME_INFORMATION:
489    
490     if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
491     {
492     status = STATUS_INVALID_HANDLE;
493     break;
494     }
495    
496     in_uint32_le(s, info_level);
497    
498     out.data = out.p = buffer;
499     out.size = sizeof(buffer);
500     status = disk_query_volume_information(file, info_level, &out);
501     result = buffer_len = out.p - out.data;
502     break;
503    
504     case IRP_MJ_DIRECTORY_CONTROL:
505    
506     if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
507     {
508     status = STATUS_INVALID_HANDLE;
509     break;
510     }
511    
512     switch (minor)
513     {
514     case IRP_MN_QUERY_DIRECTORY:
515    
516     in_uint32_le(s, info_level);
517     in_uint8s(s, 1);
518     in_uint32_le(s, length);
519     in_uint8s(s, 0x17);
520     if (length && length < 2 * 255)
521     {
522     rdp_in_unistr(s, filename, length);
523     convert_to_unix_filename(filename);
524     }
525     else
526     {
527     filename[0] = 0;
528     }
529     out.data = out.p = buffer;
530     out.size = sizeof(buffer);
531     status = disk_query_directory(file, info_level, filename,
532     &out);
533     result = buffer_len = out.p - out.data;
534     if (!buffer_len)
535     buffer_len++;
536     break;
537    
538     case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
539    
540     /* JIF
541     unimpl("IRP major=0x%x minor=0x%x: IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", major, minor); */
542     status = STATUS_PENDING; // Don't send completion packet
543     break;
544    
545     default:
546    
547     status = STATUS_INVALID_PARAMETER;
548     /* JIF
549     unimpl("IRP major=0x%x minor=0x%x\n", major, minor); */
550     }
551     break;
552    
553 matthewc 432 case IRP_MJ_DEVICE_CONTROL:
554 n-ki 569
555     if (!fns->device_control)
556 matthewc 432 {
557 n-ki 569 status = STATUS_NOT_SUPPORTED;
558     break;
559 matthewc 432 }
560 n-ki 569
561     in_uint32_le(s, bytes_out);
562     in_uint32_le(s, bytes_in);
563     in_uint32_le(s, request);
564     in_uint8s(s, 0x14);
565    
566     buffer = (uint8 *) xrealloc((void *) buffer, bytes_out + 0x14);
567     out.data = out.p = buffer;
568     out.size = sizeof(buffer);
569     status = fns->device_control(file, request, s, &out);
570     result = buffer_len = out.p - out.data;
571 matthewc 432 break;
572    
573     default:
574     unimpl("IRP major=0x%x minor=0x%x\n", major, minor);
575     break;
576     }
577    
578 n-ki 569 if (status != STATUS_PENDING)
579     {
580     rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
581     }
582     xfree(buffer);
583    
584 matthewc 432 }
585    
586 n-ki 569 void
587     rdpdr_send_clientcapabilty(void)
588     {
589     uint8 magic[4] = "rDPC";
590     STREAM s;
591    
592     s = channel_init(rdpdr_channel, 0x50);
593     out_uint8a(s, magic, 4);
594     out_uint32_le(s, 5); /* count */
595     out_uint16_le(s, 1); /* first */
596     out_uint16_le(s, 0x28); /* length */
597     out_uint32_le(s, 1);
598     out_uint32_le(s, 2);
599     out_uint16_le(s, 2);
600     out_uint16_le(s, 5);
601     out_uint16_le(s, 1);
602     out_uint16_le(s, 5);
603     out_uint16_le(s, 0xFFFF);
604     out_uint16_le(s, 0);
605     out_uint32_le(s, 0);
606     out_uint32_le(s, 3);
607     out_uint32_le(s, 0);
608     out_uint32_le(s, 0);
609     out_uint16_le(s, 2); /* second */
610     out_uint16_le(s, 8); /* length */
611     out_uint32_le(s, 1);
612     out_uint16_le(s, 3); /* third */
613     out_uint16_le(s, 8); /* length */
614     out_uint32_le(s, 1);
615     out_uint16_le(s, 4); /* fourth */
616     out_uint16_le(s, 8); /* length */
617     out_uint32_le(s, 1);
618     out_uint16_le(s, 5); /* fifth */
619     out_uint16_le(s, 8); /* length */
620     out_uint32_le(s, 1);
621    
622     s_mark_end(s);
623     channel_send(s, rdpdr_channel);
624     }
625    
626 matthewc 432 static void
627     rdpdr_process(STREAM s)
628     {
629     uint32 handle;
630 matthewc 536 uint8 *magic;
631 matthewc 432
632 n-ki 569 #if WITH_DEBUG_RDP5
633     printf("--- rdpdr_process ---\n");
634 astrand 435 hexdump(s->p, s->end - s->p);
635 n-ki 569 #endif
636 matthewc 432 in_uint8p(s, magic, 4);
637    
638     if ((magic[0] == 'r') && (magic[1] == 'D'))
639     {
640     if ((magic[2] == 'R') && (magic[3] == 'I'))
641     {
642     rdpdr_process_irp(s);
643     return;
644     }
645     if ((magic[2] == 'n') && (magic[3] == 'I'))
646     {
647     rdpdr_send_connect();
648     rdpdr_send_name();
649     return;
650     }
651 n-ki 569 if ((magic[2] == 'C') && (magic[3] == 'C'))
652 matthewc 432 {
653     /* connect from server */
654 n-ki 569 rdpdr_send_clientcapabilty();
655     rdpdr_send_available();
656 matthewc 432 return;
657     }
658 n-ki 569 if ((magic[2] == 'r') && (magic[3] == 'd'))
659 matthewc 432 {
660     /* connect to a specific resource */
661     in_uint32(s, handle);
662 n-ki 569 #if WITH_DEBUG_RDP5
663     DEBUG(("RDPDR: Server connected to resource %d\n", handle));
664     #endif
665 matthewc 432 return;
666     }
667 n-ki 569 if ((magic[2] == 'P') && (magic[3] == 'S'))
668     {
669     /* server capability */
670     return;
671     }
672 matthewc 432 }
673 n-ki 569 if ((magic[0] == 'R') && (magic[1] == 'P'))
674     {
675     if ((magic[2] == 'C') && (magic[3] == 'P'))
676     {
677     printercache_process(s);
678     return;
679     }
680     }
681 matthewc 432 unimpl("RDPDR packet type %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]);
682     }
683    
684     BOOL
685 n-ki 569 rdpdr_init()
686 matthewc 432 {
687 n-ki 569 if (g_num_devices > 0)
688     {
689 astrand 580 rdpdr_channel =
690     channel_register("rdpdr",
691     CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,
692     rdpdr_process);
693 n-ki 569 }
694    
695 matthewc 432 return (rdpdr_channel != NULL);
696     }
697 n-ki 569
698     /* Add file descriptors of pending io request to select() */
699     void
700     rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * timeout)
701     {
702     long select_timeout = 0; // Timeout value to be used for select() (in millisecons).
703     struct async_iorequest *iorq;
704    
705 n-ki 592 iorq = &g_iorequest;
706     while (iorq != NULL)
707 n-ki 569 {
708 n-ki 592 if (iorq->fd != 0)
709 n-ki 569 {
710     switch (iorq->major)
711     {
712     case IRP_MJ_READ:
713    
714     FD_SET(iorq->fd, rfds);
715    
716     // Check if io request timeout is smaller than current (but not 0).
717     if (iorq->timeout
718     && (select_timeout == 0
719     || iorq->timeout < select_timeout))
720     {
721     // Set new timeout
722     select_timeout = iorq->timeout;
723     g_min_timeout_fd = iorq->fd; /* Remember fd */
724     tv->tv_sec = select_timeout / 1000;
725     tv->tv_usec = (select_timeout % 1000) * 1000;
726     *timeout = True;
727     }
728     break;
729    
730     case IRP_MJ_WRITE:
731     FD_SET(iorq->fd, wfds);
732     break;
733    
734     }
735     *n = MAX(*n, iorq->fd);
736     }
737 n-ki 592
738     iorq = iorq->next;
739 n-ki 569 }
740     }
741    
742 n-ki 590
743 n-ki 569 /* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */
744     void
745     rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out)
746     {
747     NTSTATUS status;
748 n-ki 592 uint32 result = 0;
749 n-ki 569 DEVICE_FNS *fns;
750     struct async_iorequest *iorq;
751 n-ki 592 struct async_iorequest *prev;
752 n-ki 569
753     if (timed_out)
754     {
755     rdpdr_abort_io(g_min_timeout_fd, 0, STATUS_TIMEOUT);
756     return;
757     }
758    
759 n-ki 592 iorq = &g_iorequest;
760     prev = NULL;
761     while (iorq != NULL)
762 n-ki 569 {
763    
764     if (iorq->fd != 0)
765     {
766     switch (iorq->major)
767     {
768     case IRP_MJ_READ:
769     if (FD_ISSET(iorq->fd, rfds))
770     {
771 n-ki 592 /* Read the data */
772 n-ki 569 fns = iorq->fns;
773 n-ki 592 status = fns->read(iorq->fd,
774     iorq->buffer + iorq->partial_len,
775     iorq->length - iorq->partial_len,
776     0, &result);
777     iorq->partial_len += result;
778 n-ki 569 #if WITH_DEBUG_RDP5
779     DEBUG(("RDPDR: %d bytes of data read\n", result));
780     #endif
781 n-ki 592 /* only delete link if all data has been transfered */
782     if (iorq->partial_len == iorq->length)
783     {
784     /* send the data */
785     status = STATUS_SUCCESS;
786     rdpdr_send_completion(iorq->device,
787     iorq->id, status,
788     iorq->length,
789     iorq->buffer, result);
790    
791     xfree(iorq->buffer);
792     iorq->fd = 0;
793     if (prev != NULL)
794     {
795     prev->next = iorq->next;
796     xfree(iorq);
797     }
798     }
799 n-ki 569 }
800     break;
801     case IRP_MJ_WRITE:
802     if (FD_ISSET(iorq->fd, wfds))
803     {
804 n-ki 592 /* Write data. */
805 n-ki 569 fns = iorq->fns;
806 n-ki 592 status = fns->write(iorq->fd,
807     iorq->buffer +
808     iorq->partial_len,
809     iorq->length -
810     iorq->partial_len, 0, &result);
811     iorq->partial_len += result;
812     #if WITH_DEBUG_RDP5
813     DEBUG(("RDPDR: %d bytes of data written\n",
814     result));
815     #endif
816     /* only delete link if all data has been transfered */
817     if (iorq->partial_len == iorq->length)
818     {
819     /* send a status success */
820     status = STATUS_SUCCESS;
821     rdpdr_send_completion(iorq->device,
822     iorq->id, status,
823     iorq->length, "", 1);
824 n-ki 569
825 n-ki 592 xfree(iorq->buffer);
826     iorq->fd = 0;
827     if (prev != NULL)
828     {
829     prev->next = iorq->next;
830     xfree(iorq);
831     }
832     }
833 n-ki 569 }
834     break;
835     }
836 n-ki 592
837 n-ki 569 }
838 n-ki 592 prev = iorq;
839     iorq = iorq->next;
840 n-ki 569 }
841 n-ki 592
842 n-ki 569 }
843    
844     /* Abort a pending io request for a given handle and major */
845     BOOL
846     rdpdr_abort_io(uint32 fd, uint32 major, NTSTATUS status)
847     {
848     uint32 result;
849     struct async_iorequest *iorq;
850 n-ki 592 struct async_iorequest *prev;
851 n-ki 569
852 n-ki 592 iorq = &g_iorequest;
853     prev = NULL;
854     while (iorq != NULL)
855 n-ki 569 {
856     // Only remove from table when major is not set, or when correct major is supplied.
857     // Abort read should not abort a write io request.
858     if ((iorq->fd == fd) && (major == 0 || iorq->major == major))
859     {
860     result = 0;
861     rdpdr_send_completion(iorq->device, iorq->id, status, result, "", 1);
862     xfree(iorq->buffer);
863     iorq->fd = 0;
864 n-ki 592 if (prev != NULL)
865     {
866     prev->next = iorq->next;
867     xfree(iorq);
868     }
869 n-ki 569 return True;
870     }
871 n-ki 592
872     prev = iorq;
873     iorq = iorq->next;
874 n-ki 569 }
875 n-ki 592
876 n-ki 569 return False;
877     }

  ViewVC Help
Powered by ViewVC 1.1.26