/[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 592 - (show annotations)
Fri Jan 30 14:10:32 2004 UTC (20 years, 3 months ago) by n-ki
File MIME type: text/plain
File size: 19379 byte(s)
reworked the asyncio some and completed it. parallel and serial uses it now. disk.c is a likely candidate for the future, but there are some problems with disk.c that we will have to look into first. parallel and serial works better, they do not hang the session, but are still yerky at large chunks... possibly we could split the chunks, but the terminal server does not seem to like partial transfers, i've tried some variations.. :) fns->write() could be split in smaller pieces, but what should the thresholds be.

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

  ViewVC Help
Powered by ViewVC 1.1.26