/[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 595 - (show 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 #include <unistd.h>
2 #include <sys/types.h>
3 #include <time.h>
4 #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 #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 extern char hostname[16];
26 extern DEVICE_FNS serial_fns;
27 extern DEVICE_FNS printer_fns;
28 extern DEVICE_FNS parallel_fns;
29 extern DEVICE_FNS disk_fns;
30
31 static VCHANNEL *rdpdr_channel;
32
33 /* 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 /* 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 struct async_iorequest
44 {
45 uint32 fd, major, minor, offset, device, id, length, partial_len;
46 long timeout, /* Total timeout */
47 itv_timeout; /* Interval timeout (between serial characters) */
48 uint8 *buffer;
49 DEVICE_FNS *fns;
50
51 struct async_iorequest *next; /* next element in list */
52 };
53
54 struct async_iorequest *g_iorequest;
55
56 /* 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 void
71 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 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 while (iorq->fd != 0)
98 {
99 // create new element if needed
100 if (iorq->next == NULL)
101 {
102 iorq->next =
103 (struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
104 iorq->next->fd = 0;
105 iorq->next->next = NULL;
106 }
107 iorq = iorq->next;
108 }
109 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 }
121
122 void
123 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 out_uint16_le(s, 1); /* unknown */
131 out_uint16_le(s, 5);
132 out_uint32_be(s, 0x815ed39d); /* IP address (use 127.0.0.1) 0x815ed39d */
133 s_mark_end(s);
134 channel_send(s, rdpdr_channel);
135 }
136
137
138 void
139 rdpdr_send_name(void)
140 {
141 uint8 magic[4] = "rDNC";
142 uint32 hostlen = (strlen(hostname) + 1) * 2;
143 STREAM s;
144
145 s = channel_init(rdpdr_channel, 16 + hostlen);
146 out_uint8a(s, magic, 4);
147 out_uint16_le(s, 0x63); /* unknown */
148 out_uint16_le(s, 0x72);
149 out_uint32(s, 0);
150 out_uint32_le(s, hostlen);
151 rdp_out_unistr(s, hostname, hostlen - 2);
152 s_mark_end(s);
153 channel_send(s, rdpdr_channel);
154 }
155
156 /* 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 void
185 rdpdr_send_available(void)
186 {
187
188 uint8 magic[4] = "rDAD";
189 uint32 driverlen, printerlen, bloblen;
190 int i;
191 STREAM s;
192 PRINTER *printerinfo;
193
194 s = channel_init(rdpdr_channel, announcedata_size());
195 out_uint8a(s, magic, 4);
196 out_uint32_le(s, g_num_devices);
197
198 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 switch (g_rdpdr_device[i].device_type)
205 {
206 case DEVICE_TYPE_PRINTER:
207 printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
208
209 driverlen = 2 * strlen(printerinfo->driver) + 2;
210 printerlen = 2 * strlen(printerinfo->printer) + 2;
211 bloblen = printerinfo->bloblen;
212
213 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
223 xfree(printerinfo->blob); /* Blob is sent twice if reconnecting */
224 break;
225 default:
226 out_uint32(s, 0);
227 }
228 }
229 #if 0
230 out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */
231 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 rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
243 uint32 length)
244 {
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 /* JIF
257 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
258 channel_send(s, rdpdr_channel);
259 }
260
261 static void
262 rdpdr_process_irp(STREAM s)
263 {
264 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 struct stream out;
284 DEVICE_FNS *fns;
285 BOOL rw_blocking = True;
286 NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
287
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 buffer_len = 0;
295 buffer = (uint8 *) xmalloc(1024);
296 buffer[0] = 0;
297
298 switch (g_rdpdr_device[device].device_type)
299 {
300 case DEVICE_TYPE_SERIAL:
301
302 fns = &serial_fns;
303 rw_blocking = False;
304 break;
305
306 case DEVICE_TYPE_PARALLEL:
307
308 fns = &parallel_fns;
309 rw_blocking = False;
310 break;
311
312 case DEVICE_TYPE_PRINTER:
313
314 fns = &printer_fns;
315 break;
316
317 case DEVICE_TYPE_DISK:
318
319 fns = &disk_fns;
320 rw_blocking = False;
321 break;
322
323 case DEVICE_TYPE_SCARD:
324 default:
325
326 error("IRP for bad device %ld\n", device);
327 return;
328 }
329
330 switch (major)
331 {
332 case IRP_MJ_CREATE:
333
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 break;
362
363 case IRP_MJ_CLOSE:
364 if (!fns->close)
365 {
366 status = STATUS_NOT_SUPPORTED;
367 break;
368 }
369
370 status = fns->close(file);
371 break;
372
373 case IRP_MJ_READ:
374
375 if (!fns->read)
376 {
377 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 if (rw_blocking) // Complete read immediately
387 {
388 buffer = (uint8 *) xrealloc((void *) buffer, length);
389 status = fns->read(file, buffer, length, offset, &result);
390 buffer_len = result;
391 break;
392 }
393
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 break;
407 case IRP_MJ_WRITE:
408
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 if (rw_blocking) // Complete immediately
424 {
425 status = fns->write(file, s->p, length, offset, &result);
426 break;
427 }
428
429 // 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 break;
442
443 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 case IRP_MJ_DEVICE_CONTROL:
541
542 if (!fns->device_control)
543 {
544 status = STATUS_NOT_SUPPORTED;
545 break;
546 }
547
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 break;
559
560 default:
561 unimpl("IRP major=0x%x minor=0x%x\n", major, minor);
562 break;
563 }
564
565 if (status != STATUS_PENDING)
566 {
567 rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
568 }
569 xfree(buffer);
570
571 }
572
573 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 static void
614 rdpdr_process(STREAM s)
615 {
616 uint32 handle;
617 uint8 *magic;
618
619 #if WITH_DEBUG_RDP5
620 printf("--- rdpdr_process ---\n");
621 hexdump(s->p, s->end - s->p);
622 #endif
623 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 if ((magic[2] == 'C') && (magic[3] == 'C'))
639 {
640 /* connect from server */
641 rdpdr_send_clientcapabilty();
642 rdpdr_send_available();
643 return;
644 }
645 if ((magic[2] == 'r') && (magic[3] == 'd'))
646 {
647 /* connect to a specific resource */
648 in_uint32(s, handle);
649 #if WITH_DEBUG_RDP5
650 DEBUG(("RDPDR: Server connected to resource %d\n", handle));
651 #endif
652 return;
653 }
654 if ((magic[2] == 'P') && (magic[3] == 'S'))
655 {
656 /* server capability */
657 return;
658 }
659 }
660 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 unimpl("RDPDR packet type %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]);
669 }
670
671 BOOL
672 rdpdr_init()
673 {
674 if (g_num_devices > 0)
675 {
676 rdpdr_channel =
677 channel_register("rdpdr",
678 CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,
679 rdpdr_process);
680 }
681
682 return (rdpdr_channel != NULL);
683 }
684
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 iorq = g_iorequest;
693 while (iorq != NULL)
694 {
695 if (iorq->fd != 0)
696 {
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
725 iorq = iorq->next;
726 }
727 }
728
729
730 /* 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 uint32 result = 0;
736 DEVICE_FNS *fns;
737 struct async_iorequest *iorq;
738 struct async_iorequest *prev;
739 uint32 req_size = 0;
740
741 if (timed_out)
742 {
743 rdpdr_abort_io(g_min_timeout_fd, 0, STATUS_TIMEOUT);
744 return;
745 }
746
747 iorq = g_iorequest;
748 prev = NULL;
749 while (iorq != NULL)
750 {
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 /* Read the data */
759 fns = iorq->fns;
760
761 req_size =
762 (iorq->length - iorq->partial_len) >
763 8192 ? 8192 : (iorq->length -
764 iorq->partial_len);
765 /* never read larger chunks than 8k - chances are that it will block */
766 status = fns->read(iorq->fd,
767 iorq->buffer + iorq->partial_len,
768 req_size, 0, &result);
769 iorq->partial_len += result;
770
771 #if WITH_DEBUG_RDP5
772 DEBUG(("RDPDR: %d bytes of data read\n", result));
773 #endif
774 /* only delete link if all data has been transfered */
775 /* or if result was 0 and status success - EOF */
776 if ((iorq->partial_len == iorq->length) ||
777 (result == 0))
778 {
779 #if WITH_DEBUG_RDP5
780 DEBUG(("RDPDR: AIO total %u bytes read of %u\n", iorq->partial_len, iorq->length));
781 #endif
782 /* send the data */
783 status = STATUS_SUCCESS;
784 rdpdr_send_completion(iorq->device,
785 iorq->id, status,
786 iorq->partial_len,
787 iorq->buffer,
788 iorq->partial_len);
789 xfree(iorq->buffer);
790 iorq->fd = 0;
791 if (prev != NULL)
792 {
793 prev->next = iorq->next;
794 xfree(iorq);
795 }
796 else
797 {
798 // Even if NULL
799 g_iorequest = iorq->next;
800 xfree(iorq);
801 }
802 }
803 }
804 break;
805 case IRP_MJ_WRITE:
806 if (FD_ISSET(iorq->fd, wfds))
807 {
808 /* Write data. */
809 fns = iorq->fns;
810
811 req_size =
812 (iorq->length - iorq->partial_len) >
813 8192 ? 8192 : (iorq->length -
814 iorq->partial_len);
815
816 /* never write larger chunks than 8k - chances are that it will block */
817 status = fns->write(iorq->fd,
818 iorq->buffer +
819 iorq->partial_len, req_size, 0,
820 &result);
821 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 /* or we couldn't write */
828 if ((iorq->partial_len == iorq->length)
829 || (result == 0))
830 {
831 #if WITH_DEBUG_RDP5
832 DEBUG(("RDPDR: AIO total %u bytes written of %u\n", iorq->partial_len, iorq->length));
833 #endif
834 /* send a status success */
835 status = STATUS_SUCCESS;
836 rdpdr_send_completion(iorq->device,
837 iorq->id, status,
838 iorq->partial_len, "",
839 1);
840
841 xfree(iorq->buffer);
842 iorq->fd = 0;
843 if (prev != NULL)
844 {
845 prev->next = iorq->next;
846 xfree(iorq);
847 }
848 else
849 {
850 // Even if NULL
851 g_iorequest = iorq->next;
852 xfree(iorq);
853 }
854 }
855 }
856 break;
857 }
858
859 }
860 prev = iorq;
861 iorq = iorq->next;
862 }
863
864 }
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 struct async_iorequest *prev;
873
874 iorq = &g_iorequest;
875 prev = NULL;
876 while (iorq != NULL)
877 {
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 if (prev != NULL)
887 {
888 prev->next = iorq->next;
889 xfree(iorq);
890 }
891 else
892 {
893 // Even if NULL
894 g_iorequest = iorq->next;
895 xfree(iorq);
896 }
897 return True;
898 }
899
900 prev = iorq;
901 iorq = iorq->next;
902 }
903
904 return False;
905 }

  ViewVC Help
Powered by ViewVC 1.1.26