/[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 595 - (hide annotations)
Tue Feb 3 14:02:59 2004 UTC (20 years, 3 months ago) by n-ki
File MIME type: text/plain
File size: 20132 byte(s)
fix aio when data written/read is not equ buffer enable disk.c aio

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

  ViewVC Help
Powered by ViewVC 1.1.26