/[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 576 - (hide annotations)
Thu Jan 22 20:31:59 2004 UTC (20 years, 3 months ago) by stargo
File MIME type: text/plain
File size: 17597 byte(s)
fix g_null_pointer memleak
fixes for compiles on NetBSD & FreeBSD

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     if (g_rdpdr_device[i].device_type == DEVICE_TYPE_PRINTER)
192     {
193     printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
194    
195     driverlen = 2 * strlen(printerinfo->driver) + 2;
196     printerlen = 2 * strlen(printerinfo->printer) + 2;
197     bloblen = printerinfo->bloblen;
198    
199     out_uint32_le(s, 24 + driverlen + printerlen + bloblen); /* length of extra info */
200     out_uint32_le(s, printerinfo->default_printer ? 2 : 0);
201     out_uint8s(s, 8); /* unknown */
202     out_uint32_le(s, driverlen);
203     out_uint32_le(s, printerlen);
204     out_uint32_le(s, bloblen);
205     rdp_out_unistr(s, printerinfo->driver, driverlen - 2);
206     rdp_out_unistr(s, printerinfo->printer, printerlen - 2);
207     out_uint8a(s, printerinfo->blob, bloblen);
208    
209     xfree(printerinfo->blob); /* Blob is sent twice if reconnecting */
210     }
211     else
212     {
213     out_uint32(s, 0);
214     }
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 569 rw_blocking = False;
292     break;
293    
294     case DEVICE_TYPE_PARALLEL:
295    
296     fns = &parallel_fns;
297     rw_blocking = False;
298     break;
299    
300     case DEVICE_TYPE_PRINTER:
301    
302 matthewc 432 fns = &printer_fns;
303 n-ki 569 break;
304    
305     case DEVICE_TYPE_DISK:
306    
307     fns = &disk_fns;
308     break;
309    
310     case DEVICE_TYPE_SCARD:
311 matthewc 432 default:
312 n-ki 569
313 matthewc 432 error("IRP for bad device %ld\n", device);
314     return;
315     }
316    
317     switch (major)
318     {
319     case IRP_MJ_CREATE:
320 n-ki 569
321     in_uint32_be(s, desired_access);
322     in_uint8s(s, 0x08); // unknown
323     in_uint32_le(s, error_mode);
324     in_uint32_le(s, share_mode);
325     in_uint32_le(s, disposition);
326     in_uint32_le(s, flags_and_attributes);
327     in_uint32_le(s, length);
328    
329     if (length && (length / 2) < 256)
330     {
331     rdp_in_unistr(s, filename, length);
332     convert_to_unix_filename(filename);
333     }
334     else
335     {
336     filename[0] = 0;
337     }
338    
339     if (!fns->create)
340     {
341     status = STATUS_NOT_SUPPORTED;
342     break;
343     }
344    
345     status = fns->create(device, desired_access, share_mode, disposition,
346     flags_and_attributes, filename, &result);
347     buffer_len = 1;
348 matthewc 432 break;
349    
350     case IRP_MJ_CLOSE:
351 n-ki 569 if (!fns->close)
352     {
353     status = STATUS_NOT_SUPPORTED;
354     break;
355     }
356    
357     status = fns->close(file);
358 matthewc 432 break;
359    
360     case IRP_MJ_READ:
361 n-ki 569
362     if (!fns->read)
363 matthewc 432 {
364 n-ki 569 status = STATUS_NOT_SUPPORTED;
365     break;
366     }
367    
368     in_uint32_le(s, length);
369     in_uint32_le(s, offset);
370     #if WITH_DEBUG_RDP5
371     DEBUG(("RDPDR IRP Read (length: %d, offset: %d)\n", length, offset));
372     #endif
373     if (rw_blocking) // Complete read immediately
374     {
375     buffer = (uint8 *) xrealloc((void *) buffer, length);
376     status = fns->read(file, buffer, length, offset, &result);
377 matthewc 432 buffer_len = result;
378 n-ki 569 break;
379 matthewc 432 }
380 n-ki 569
381     // Add request to table
382     pst_buf = (uint8 *) xmalloc(length);
383     serial_get_timeout(file, length, &total_timeout, &interval_timeout);
384     if (add_async_iorequest
385     (device, file, id, major, length, fns, total_timeout, interval_timeout,
386     pst_buf))
387     {
388     status = STATUS_PENDING;
389     break;
390     }
391    
392     status = STATUS_CANCELLED;
393 matthewc 432 break;
394    
395     case IRP_MJ_WRITE:
396 n-ki 569
397     buffer_len = 1;
398    
399     if (!fns->write)
400     {
401     status = STATUS_NOT_SUPPORTED;
402     break;
403     }
404    
405     in_uint32_le(s, length);
406     in_uint32_le(s, offset);
407     in_uint8s(s, 0x18);
408     #if WITH_DEBUG_RDP5
409     DEBUG(("RDPDR IRP Write (length: %d)\n", result));
410     #endif
411     if (rw_blocking) // Complete immediately
412     {
413     status = fns->write(file, s->p, length, offset, &result);
414     break;
415     }
416    
417     // Add to table
418     pst_buf = (uint8 *) xmalloc(length);
419     in_uint8a(s, pst_buf, length);
420    
421     if (add_async_iorequest
422     (device, file, id, major, length, fns, 0, 0, pst_buf))
423     {
424     status = STATUS_PENDING;
425     break;
426     }
427    
428     status = STATUS_CANCELLED;
429 matthewc 432 break;
430    
431 n-ki 569 case IRP_MJ_QUERY_INFORMATION:
432    
433     if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
434     {
435     status = STATUS_INVALID_HANDLE;
436     break;
437     }
438     in_uint32_le(s, info_level);
439    
440     out.data = out.p = buffer;
441     out.size = sizeof(buffer);
442     status = disk_query_information(file, info_level, &out);
443     result = buffer_len = out.p - out.data;
444    
445     break;
446    
447     case IRP_MJ_SET_INFORMATION:
448    
449     if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
450     {
451     status = STATUS_INVALID_HANDLE;
452     break;
453     }
454    
455     in_uint32_le(s, info_level);
456    
457     out.data = out.p = buffer;
458     out.size = sizeof(buffer);
459     status = disk_set_information(file, info_level, s, &out);
460     result = buffer_len = out.p - out.data;
461     break;
462    
463     case IRP_MJ_QUERY_VOLUME_INFORMATION:
464    
465     if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
466     {
467     status = STATUS_INVALID_HANDLE;
468     break;
469     }
470    
471     in_uint32_le(s, info_level);
472    
473     out.data = out.p = buffer;
474     out.size = sizeof(buffer);
475     status = disk_query_volume_information(file, info_level, &out);
476     result = buffer_len = out.p - out.data;
477     break;
478    
479     case IRP_MJ_DIRECTORY_CONTROL:
480    
481     if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
482     {
483     status = STATUS_INVALID_HANDLE;
484     break;
485     }
486    
487     switch (minor)
488     {
489     case IRP_MN_QUERY_DIRECTORY:
490    
491     in_uint32_le(s, info_level);
492     in_uint8s(s, 1);
493     in_uint32_le(s, length);
494     in_uint8s(s, 0x17);
495     if (length && length < 2 * 255)
496     {
497     rdp_in_unistr(s, filename, length);
498     convert_to_unix_filename(filename);
499     }
500     else
501     {
502     filename[0] = 0;
503     }
504     out.data = out.p = buffer;
505     out.size = sizeof(buffer);
506     status = disk_query_directory(file, info_level, filename,
507     &out);
508     result = buffer_len = out.p - out.data;
509     if (!buffer_len)
510     buffer_len++;
511     break;
512    
513     case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
514    
515     /* JIF
516     unimpl("IRP major=0x%x minor=0x%x: IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", major, minor); */
517     status = STATUS_PENDING; // Don't send completion packet
518     break;
519    
520     default:
521    
522     status = STATUS_INVALID_PARAMETER;
523     /* JIF
524     unimpl("IRP major=0x%x minor=0x%x\n", major, minor); */
525     }
526     break;
527    
528 matthewc 432 case IRP_MJ_DEVICE_CONTROL:
529 n-ki 569
530     if (!fns->device_control)
531 matthewc 432 {
532 n-ki 569 status = STATUS_NOT_SUPPORTED;
533     break;
534 matthewc 432 }
535 n-ki 569
536     in_uint32_le(s, bytes_out);
537     in_uint32_le(s, bytes_in);
538     in_uint32_le(s, request);
539     in_uint8s(s, 0x14);
540    
541     buffer = (uint8 *) xrealloc((void *) buffer, bytes_out + 0x14);
542     out.data = out.p = buffer;
543     out.size = sizeof(buffer);
544     status = fns->device_control(file, request, s, &out);
545     result = buffer_len = out.p - out.data;
546 matthewc 432 break;
547    
548     default:
549     unimpl("IRP major=0x%x minor=0x%x\n", major, minor);
550     break;
551     }
552    
553 n-ki 569 if (status != STATUS_PENDING)
554     {
555     rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
556     }
557     xfree(buffer);
558    
559 matthewc 432 }
560    
561 n-ki 569 void
562     rdpdr_send_clientcapabilty(void)
563     {
564     uint8 magic[4] = "rDPC";
565     STREAM s;
566    
567     s = channel_init(rdpdr_channel, 0x50);
568     out_uint8a(s, magic, 4);
569     out_uint32_le(s, 5); /* count */
570     out_uint16_le(s, 1); /* first */
571     out_uint16_le(s, 0x28); /* length */
572     out_uint32_le(s, 1);
573     out_uint32_le(s, 2);
574     out_uint16_le(s, 2);
575     out_uint16_le(s, 5);
576     out_uint16_le(s, 1);
577     out_uint16_le(s, 5);
578     out_uint16_le(s, 0xFFFF);
579     out_uint16_le(s, 0);
580     out_uint32_le(s, 0);
581     out_uint32_le(s, 3);
582     out_uint32_le(s, 0);
583     out_uint32_le(s, 0);
584     out_uint16_le(s, 2); /* second */
585     out_uint16_le(s, 8); /* length */
586     out_uint32_le(s, 1);
587     out_uint16_le(s, 3); /* third */
588     out_uint16_le(s, 8); /* length */
589     out_uint32_le(s, 1);
590     out_uint16_le(s, 4); /* fourth */
591     out_uint16_le(s, 8); /* length */
592     out_uint32_le(s, 1);
593     out_uint16_le(s, 5); /* fifth */
594     out_uint16_le(s, 8); /* length */
595     out_uint32_le(s, 1);
596    
597     s_mark_end(s);
598     channel_send(s, rdpdr_channel);
599     }
600    
601 matthewc 432 static void
602     rdpdr_process(STREAM s)
603     {
604     uint32 handle;
605 matthewc 536 uint8 *magic;
606 matthewc 432
607 n-ki 569 #if WITH_DEBUG_RDP5
608     printf("--- rdpdr_process ---\n");
609 astrand 435 hexdump(s->p, s->end - s->p);
610 n-ki 569 #endif
611 matthewc 432 in_uint8p(s, magic, 4);
612    
613     if ((magic[0] == 'r') && (magic[1] == 'D'))
614     {
615     if ((magic[2] == 'R') && (magic[3] == 'I'))
616     {
617     rdpdr_process_irp(s);
618     return;
619     }
620     if ((magic[2] == 'n') && (magic[3] == 'I'))
621     {
622     rdpdr_send_connect();
623     rdpdr_send_name();
624     return;
625     }
626 n-ki 569 if ((magic[2] == 'C') && (magic[3] == 'C'))
627 matthewc 432 {
628     /* connect from server */
629 n-ki 569 rdpdr_send_clientcapabilty();
630     rdpdr_send_available();
631 matthewc 432 return;
632     }
633 n-ki 569 if ((magic[2] == 'r') && (magic[3] == 'd'))
634 matthewc 432 {
635     /* connect to a specific resource */
636     in_uint32(s, handle);
637 n-ki 569 #if WITH_DEBUG_RDP5
638     DEBUG(("RDPDR: Server connected to resource %d\n", handle));
639     #endif
640 matthewc 432 return;
641     }
642 n-ki 569 if ((magic[2] == 'P') && (magic[3] == 'S'))
643     {
644     /* server capability */
645     return;
646     }
647 matthewc 432 }
648 n-ki 569 if ((magic[0] == 'R') && (magic[1] == 'P'))
649     {
650     if ((magic[2] == 'C') && (magic[3] == 'P'))
651     {
652     printercache_process(s);
653     return;
654     }
655     }
656 matthewc 432 unimpl("RDPDR packet type %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]);
657     }
658    
659     BOOL
660 n-ki 569 rdpdr_init()
661 matthewc 432 {
662 n-ki 569 if (g_num_devices > 0)
663     {
664     rdpdr_channel = channel_register("rdpdr", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP, rdpdr_process);
665     }
666    
667 matthewc 432 return (rdpdr_channel != NULL);
668     }
669 n-ki 569
670     /* Add file descriptors of pending io request to select() */
671     void
672     rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * timeout)
673     {
674     int i;
675     long select_timeout = 0; // Timeout value to be used for select() (in millisecons).
676     struct async_iorequest *iorq;
677    
678     for (i = 0; i < MAX_ASYNC_IO_REQUESTS; i++)
679     {
680     iorq = &g_iorequest[i];
681    
682     if (iorq->fd != 0) // Found a pending io request
683     {
684     switch (iorq->major)
685     {
686     case IRP_MJ_READ:
687    
688     FD_SET(iorq->fd, rfds);
689    
690     // Check if io request timeout is smaller than current (but not 0).
691     if (iorq->timeout
692     && (select_timeout == 0
693     || iorq->timeout < select_timeout))
694     {
695     // Set new timeout
696     select_timeout = iorq->timeout;
697     g_min_timeout_fd = iorq->fd; /* Remember fd */
698     tv->tv_sec = select_timeout / 1000;
699     tv->tv_usec = (select_timeout % 1000) * 1000;
700     *timeout = True;
701     }
702     break;
703    
704     case IRP_MJ_WRITE:
705    
706     FD_SET(iorq->fd, wfds);
707     break;
708    
709     }
710     *n = MAX(*n, iorq->fd);
711     }
712     }
713     }
714    
715     /* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */
716     void
717     rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out)
718     {
719     int i;
720     NTSTATUS status;
721     uint32 result = 0, buffer_len = 0;
722     DEVICE_FNS *fns;
723     struct async_iorequest *iorq;
724    
725     if (timed_out)
726     {
727     rdpdr_abort_io(g_min_timeout_fd, 0, STATUS_TIMEOUT);
728     return;
729     }
730    
731     // Walk through array of pending io_rq's
732     for (i = 0; i < MAX_ASYNC_IO_REQUESTS; i++)
733     {
734     iorq = &g_iorequest[i];
735    
736     if (iorq->fd != 0)
737     {
738     switch (iorq->major)
739     {
740    
741     case IRP_MJ_READ:
742    
743     if (FD_ISSET(iorq->fd, rfds))
744     {
745     // Read, and send data.
746     fns = iorq->fns;
747     status = fns->read(iorq->fd, iorq->buffer,
748     iorq->length, 0, &result);
749     buffer_len = result;
750    
751     rdpdr_send_completion(iorq->device, iorq->id,
752     status, result, iorq->buffer,
753     buffer_len);
754     #if WITH_DEBUG_RDP5
755     DEBUG(("RDPDR: %d bytes of data read\n", result));
756     #endif
757     xfree(iorq->buffer);
758     iorq->fd = 0;
759     }
760     break;
761    
762     case IRP_MJ_WRITE:
763    
764     if (FD_ISSET(iorq->fd, wfds))
765     {
766     // Write data and send completion.
767     fns = iorq->fns;
768     status = fns->write(iorq->fd, iorq->buffer,
769     iorq->length, 0, &result);
770     rdpdr_send_completion(iorq->device, iorq->id,
771     status, result, "", 1);
772    
773     xfree(iorq->buffer);
774     iorq->fd = 0;
775     }
776     break;
777     }
778     }
779     }
780     }
781    
782     /* Abort a pending io request for a given handle and major */
783     BOOL
784     rdpdr_abort_io(uint32 fd, uint32 major, NTSTATUS status)
785     {
786     uint32 result;
787     int i;
788     struct async_iorequest *iorq;
789    
790     for (i = 0; i < MAX_ASYNC_IO_REQUESTS; i++)
791     {
792     iorq = &g_iorequest[i];
793    
794     // Only remove from table when major is not set, or when correct major is supplied.
795     // Abort read should not abort a write io request.
796     if ((iorq->fd == fd) && (major == 0 || iorq->major == major))
797     {
798     result = 0;
799     rdpdr_send_completion(iorq->device, iorq->id, status, result, "", 1);
800     xfree(iorq->buffer);
801     iorq->fd = 0;
802     return True;
803     }
804     }
805     return False;
806     }

  ViewVC Help
Powered by ViewVC 1.1.26