/[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 590 - (hide annotations)
Thu Jan 29 12:27:21 2004 UTC (20 years, 4 months ago) by n-ki
File MIME type: text/plain
File size: 17822 byte(s)
put aio code within ifdefs

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

  ViewVC Help
Powered by ViewVC 1.1.26