/[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 614 - (show annotations)
Mon Feb 23 12:07:30 2004 UTC (20 years, 2 months ago) by n-ki
File MIME type: text/plain
File size: 20855 byte(s)
linklist memfree bugfix - volker milde

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

  ViewVC Help
Powered by ViewVC 1.1.26