/[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 602 - (show annotations)
Sat Feb 7 17:32:21 2004 UTC (20 years, 2 months ago) by stargo
File MIME type: text/plain
File size: 20175 byte(s)
Cleanup some warnings (from SUNWspro-compiler)

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 if (printerinfo->blob)
224 xfree(printerinfo->blob); /* Blob is sent twice if reconnecting */
225 break;
226 default:
227 out_uint32(s, 0);
228 }
229 }
230 #if 0
231 out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */
232 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 rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
244 uint32 length)
245 {
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 /* JIF
258 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
259 channel_send(s, rdpdr_channel);
260 }
261
262 static void
263 rdpdr_process_irp(STREAM s)
264 {
265 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 struct stream out;
285 DEVICE_FNS *fns;
286 BOOL rw_blocking = True;
287 NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
288
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 buffer_len = 0;
296 buffer = (uint8 *) xmalloc(1024);
297 buffer[0] = 0;
298
299 switch (g_rdpdr_device[device].device_type)
300 {
301 case DEVICE_TYPE_SERIAL:
302
303 fns = &serial_fns;
304 rw_blocking = False;
305 break;
306
307 case DEVICE_TYPE_PARALLEL:
308
309 fns = &parallel_fns;
310 rw_blocking = False;
311 break;
312
313 case DEVICE_TYPE_PRINTER:
314
315 fns = &printer_fns;
316 break;
317
318 case DEVICE_TYPE_DISK:
319
320 fns = &disk_fns;
321 rw_blocking = False;
322 break;
323
324 case DEVICE_TYPE_SCARD:
325 default:
326
327 error("IRP for bad device %ld\n", device);
328 return;
329 }
330
331 switch (major)
332 {
333 case IRP_MJ_CREATE:
334
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 break;
363
364 case IRP_MJ_CLOSE:
365 if (!fns->close)
366 {
367 status = STATUS_NOT_SUPPORTED;
368 break;
369 }
370
371 status = fns->close(file);
372 break;
373
374 case IRP_MJ_READ:
375
376 if (!fns->read)
377 {
378 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 if (rw_blocking) // Complete read immediately
388 {
389 buffer = (uint8 *) xrealloc((void *) buffer, length);
390 status = fns->read(file, buffer, length, offset, &result);
391 buffer_len = result;
392 break;
393 }
394
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 break;
408 case IRP_MJ_WRITE:
409
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 if (rw_blocking) // Complete immediately
425 {
426 status = fns->write(file, s->p, length, offset, &result);
427 break;
428 }
429
430 // 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 break;
443
444 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 case IRP_MJ_DEVICE_CONTROL:
542
543 if (!fns->device_control)
544 {
545 status = STATUS_NOT_SUPPORTED;
546 break;
547 }
548
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 break;
560
561 default:
562 unimpl("IRP major=0x%x minor=0x%x\n", major, minor);
563 break;
564 }
565
566 if (status != STATUS_PENDING)
567 {
568 rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
569 }
570 xfree(buffer);
571
572 }
573
574 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 static void
615 rdpdr_process(STREAM s)
616 {
617 uint32 handle;
618 uint8 *magic;
619
620 #if WITH_DEBUG_RDP5
621 printf("--- rdpdr_process ---\n");
622 hexdump(s->p, s->end - s->p);
623 #endif
624 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 if ((magic[2] == 'C') && (magic[3] == 'C'))
640 {
641 /* connect from server */
642 rdpdr_send_clientcapabilty();
643 rdpdr_send_available();
644 return;
645 }
646 if ((magic[2] == 'r') && (magic[3] == 'd'))
647 {
648 /* connect to a specific resource */
649 in_uint32(s, handle);
650 #if WITH_DEBUG_RDP5
651 DEBUG(("RDPDR: Server connected to resource %d\n", handle));
652 #endif
653 return;
654 }
655 if ((magic[2] == 'P') && (magic[3] == 'S'))
656 {
657 /* server capability */
658 return;
659 }
660 }
661 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 unimpl("RDPDR packet type %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]);
670 }
671
672 BOOL
673 rdpdr_init()
674 {
675 if (g_num_devices > 0)
676 {
677 rdpdr_channel =
678 channel_register("rdpdr",
679 CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,
680 rdpdr_process);
681 }
682
683 return (rdpdr_channel != NULL);
684 }
685
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 long select_timeout = 0; // Timeout value to be used for select() (in millisecons).
691 struct async_iorequest *iorq;
692
693 iorq = g_iorequest;
694 while (iorq != NULL)
695 {
696 if (iorq->fd != 0)
697 {
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
726 iorq = iorq->next;
727 }
728 }
729
730
731 /* 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 uint32 result = 0;
737 DEVICE_FNS *fns;
738 struct async_iorequest *iorq;
739 struct async_iorequest *prev;
740 uint32 req_size = 0;
741
742 if (timed_out)
743 {
744 rdpdr_abort_io(g_min_timeout_fd, 0, STATUS_TIMEOUT);
745 return;
746 }
747
748 iorq = g_iorequest;
749 prev = NULL;
750 while (iorq != NULL)
751 {
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 /* Read the data */
760 fns = iorq->fns;
761
762 req_size =
763 (iorq->length - iorq->partial_len) >
764 8192 ? 8192 : (iorq->length -
765 iorq->partial_len);
766 /* never read larger chunks than 8k - chances are that it will block */
767 status = fns->read(iorq->fd,
768 iorq->buffer + iorq->partial_len,
769 req_size, 0, &result);
770 iorq->partial_len += result;
771
772 #if WITH_DEBUG_RDP5
773 DEBUG(("RDPDR: %d bytes of data read\n", result));
774 #endif
775 /* only delete link if all data has been transfered */
776 /* or if result was 0 and status success - EOF */
777 if ((iorq->partial_len == iorq->length) ||
778 (result == 0))
779 {
780 #if WITH_DEBUG_RDP5
781 DEBUG(("RDPDR: AIO total %u bytes read of %u\n", iorq->partial_len, iorq->length));
782 #endif
783 /* send the data */
784 status = STATUS_SUCCESS;
785 rdpdr_send_completion(iorq->device,
786 iorq->id, status,
787 iorq->partial_len,
788 iorq->buffer,
789 iorq->partial_len);
790 xfree(iorq->buffer);
791 iorq->fd = 0;
792 if (prev != NULL)
793 {
794 prev->next = iorq->next;
795 xfree(iorq);
796 }
797 else
798 {
799 // Even if NULL
800 g_iorequest = iorq->next;
801 xfree(iorq);
802 }
803 }
804 }
805 break;
806 case IRP_MJ_WRITE:
807 if (FD_ISSET(iorq->fd, wfds))
808 {
809 /* Write data. */
810 fns = iorq->fns;
811
812 req_size =
813 (iorq->length - iorq->partial_len) >
814 8192 ? 8192 : (iorq->length -
815 iorq->partial_len);
816
817 /* never write larger chunks than 8k - chances are that it will block */
818 status = fns->write(iorq->fd,
819 iorq->buffer +
820 iorq->partial_len, req_size, 0,
821 &result);
822 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 /* or we couldn't write */
829 if ((iorq->partial_len == iorq->length)
830 || (result == 0))
831 {
832 #if WITH_DEBUG_RDP5
833 DEBUG(("RDPDR: AIO total %u bytes written of %u\n", iorq->partial_len, iorq->length));
834 #endif
835 /* send a status success */
836 status = STATUS_SUCCESS;
837 rdpdr_send_completion(iorq->device,
838 iorq->id, status,
839 iorq->partial_len, (uint8*)"",
840 1);
841
842 xfree(iorq->buffer);
843 iorq->fd = 0;
844 if (prev != NULL)
845 {
846 prev->next = iorq->next;
847 xfree(iorq);
848 }
849 else
850 {
851 // Even if NULL
852 g_iorequest = iorq->next;
853 xfree(iorq);
854 }
855 }
856 }
857 break;
858 }
859
860 }
861 prev = iorq;
862 iorq = iorq->next;
863 }
864
865 }
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 struct async_iorequest *prev;
874
875 iorq = g_iorequest;
876 prev = NULL;
877 while (iorq != NULL)
878 {
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 rdpdr_send_completion(iorq->device, iorq->id, status, result, (uint8*)"", 1);
885 xfree(iorq->buffer);
886 iorq->fd = 0;
887 if (prev != NULL)
888 {
889 prev->next = iorq->next;
890 xfree(iorq);
891 }
892 else
893 {
894 // Even if NULL
895 g_iorequest = iorq->next;
896 xfree(iorq);
897 }
898 return True;
899 }
900
901 prev = iorq;
902 iorq = iorq->next;
903 }
904
905 return False;
906 }

  ViewVC Help
Powered by ViewVC 1.1.26