/[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

Contents of /sourceforge.net/trunk/rdesktop/rdpdr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 627 - (show annotations)
Thu Mar 4 08:24:40 2004 UTC (20 years, 2 months ago) by n-ki
File MIME type: text/plain
File size: 21192 byte(s)
move disk info define to types.h
extract aio remove
handle errors in aio read / write
function that checks if handle is ok - seems windows cant keep track of them huh
- volker milde

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

  ViewVC Help
Powered by ViewVC 1.1.26