/[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 585 - (hide annotations)
Tue Jan 27 21:15:18 2004 UTC (20 years, 4 months ago) by n-ki
File MIME type: text/plain
File size: 17747 byte(s)
send_avail... use switch instead of if else.
disable aio on serial and parallel until finished.

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

  ViewVC Help
Powered by ViewVC 1.1.26