/[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 608 - (hide annotations)
Sun Feb 15 21:19:28 2004 UTC (20 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 20196 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26