ReactOS 0.4.15-dev-7958-gcd0bb1a
rdpdr.c
Go to the documentation of this file.
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Copyright (C) Matthew Chapman 1999-2005
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18*/
19
20/*
21 Here are some resources, for your IRP hacking pleasure:
22
23 http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/winddk.h?view=markup
24
25 http://win32.mvps.org/ntfs/streams.cpp
26
27 http://www.acc.umu.se/~bosse/ntifs.h
28
29 http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/
30
31 http://us1.samba.org/samba/ftp/specs/smb-nt01.txt
32
33 http://www.osronline.com/
34*/
35
36#include <unistd.h>
37#include <sys/types.h>
38#include <sys/time.h>
39#include <dirent.h> /* opendir, closedir, readdir */
40#include <time.h>
41#include <errno.h>
42#include "rdesktop.h"
43
44#define IRP_MJ_CREATE 0x00
45#define IRP_MJ_CLOSE 0x02
46#define IRP_MJ_READ 0x03
47#define IRP_MJ_WRITE 0x04
48#define IRP_MJ_QUERY_INFORMATION 0x05
49#define IRP_MJ_SET_INFORMATION 0x06
50#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
51#define IRP_MJ_DIRECTORY_CONTROL 0x0c
52#define IRP_MJ_DEVICE_CONTROL 0x0e
53#define IRP_MJ_LOCK_CONTROL 0x11
54
55#define IRP_MN_QUERY_DIRECTORY 0x01
56#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02
57
61extern DEVICE_FNS disk_fns;
62
63/* Return device_id for a given handle */
64int
66{
67 int i;
68 for (i = 0; i < RDPDR_MAX_DEVICES; i++)
69 {
70 if (This->rdpdr_device[i].handle == handle)
71 return i;
72 }
73 return -1;
74}
75
76/* Converts a windows path to a unix path */
77void
79{
80 char *p;
81
82 while ((p = strchr(filename, '\\')))
83 {
84 *p = '/';
85 }
86}
87
88static BOOL
90{
91 switch (This->rdpdr_device[device].device_type)
92 {
97 if (This->rdpdr_device[device].handle != handle)
98 return False;
99 break;
100 case DEVICE_TYPE_DISK:
101 if (This->fileinfo[handle].device_id != device)
102 return False;
103 break;
104 }
105 return True;
106}
107
108/* Add a new io request to the table containing pending io requests so it won't block rdesktop */
109static BOOL
111 DEVICE_FNS * fns, uint32 total_timeout, uint32 interval_timeout, uint8 * buffer,
113{
114 struct async_iorequest *iorq;
115
116 if (This->iorequest == NULL)
117 {
118 This->iorequest = (struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
119 if (!This->iorequest)
120 return False;
121 This->iorequest->fd = 0;
122 This->iorequest->next = NULL;
123 }
124
125 iorq = This->iorequest;
126
127 while (iorq->fd != 0)
128 {
129 /* create new element if needed */
130 if (iorq->next == NULL)
131 {
132 iorq->next =
133 (struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
134 if (!iorq->next)
135 return False;
136 iorq->next->fd = 0;
137 iorq->next->next = NULL;
138 }
139 iorq = iorq->next;
140 }
141 iorq->device = device;
142 iorq->fd = file;
143 iorq->id = id;
144 iorq->major = major;
145 iorq->length = length;
146 iorq->partial_len = 0;
147 iorq->fns = fns;
148 iorq->timeout = total_timeout;
149 iorq->itv_timeout = interval_timeout;
150 iorq->buffer = buffer;
151 iorq->offset = offset;
152 return True;
153}
154
155static void
157{
158 uint8 magic[4] = "rDCC";
159 STREAM s;
160
161 s = channel_init(This, This->rdpdr.channel, 12);
162 out_uint8a(s, magic, 4);
163 out_uint16_le(s, 1); /* unknown */
164 out_uint16_le(s, 5);
165 out_uint32_be(s, 0x815ed39d); /* IP address (use 127.0.0.1) 0x815ed39d */
166 s_mark_end(s);
167 channel_send(This, s, This->rdpdr.channel);
168}
169
170
171static void
173{
174 uint8 magic[4] = "rDNC";
175 STREAM s;
176 uint32 hostlen;
177
178 if (NULL == This->rdpdr_clientname)
179 {
180 This->rdpdr_clientname = This->hostname;
181 }
182 hostlen = (strlen(This->rdpdr_clientname) + 1) * 2;
183
184 s = channel_init(This, This->rdpdr.channel, 16 + hostlen);
185 out_uint8a(s, magic, 4);
186 out_uint16_le(s, 0x63); /* unknown */
187 out_uint16_le(s, 0x72);
188 out_uint32(s, 0);
189 out_uint32_le(s, hostlen);
190 rdp_out_unistr(This, s, This->rdpdr_clientname, hostlen - 2);
191 s_mark_end(s);
192 channel_send(This, s, This->rdpdr.channel);
193}
194
195/* Returns the size of the payload of the announce packet */
196static int
198{
199 int size, i;
200 PRINTER *printerinfo;
201
202 size = 8; /* static announce size */
203 size += This->num_devices * 0x14;
204
205 for (i = 0; i < This->num_devices; i++)
206 {
207 if (This->rdpdr_device[i].device_type == DEVICE_TYPE_PRINTER)
208 {
209 printerinfo = (PRINTER *) This->rdpdr_device[i].pdevice_data;
210 printerinfo->bloblen =
211 printercache_load_blob(printerinfo->printer, &(printerinfo->blob));
212
213 size += 0x18;
214 size += 2 * strlen(printerinfo->driver) + 2;
215 size += 2 * strlen(printerinfo->printer) + 2;
216 size += printerinfo->bloblen;
217 }
218 }
219
220 return size;
221}
222
223static void
225{
226
227 uint8 magic[4] = "rDAD";
228 uint32 driverlen, printerlen, bloblen;
229 int i;
230 STREAM s;
231 PRINTER *printerinfo;
232
233 s = channel_init(This, This->rdpdr.channel, announcedata_size(This));
234 out_uint8a(s, magic, 4);
235 out_uint32_le(s, This->num_devices);
236
237 for (i = 0; i < This->num_devices; i++)
238 {
239 out_uint32_le(s, This->rdpdr_device[i].device_type);
240 out_uint32_le(s, i); /* RDP Device ID */
241 /* Is it possible to use share names longer than 8 chars?
242 /astrand */
243 out_uint8p(s, This->rdpdr_device[i].name, 8);
244
245 switch (This->rdpdr_device[i].device_type)
246 {
248 printerinfo = (PRINTER *) This->rdpdr_device[i].pdevice_data;
249
250 driverlen = 2 * strlen(printerinfo->driver) + 2;
251 printerlen = 2 * strlen(printerinfo->printer) + 2;
252 bloblen = printerinfo->bloblen;
253
254 out_uint32_le(s, 24 + driverlen + printerlen + bloblen); /* length of extra info */
255 out_uint32_le(s, printerinfo->default_printer ? 2 : 0);
256 out_uint8s(s, 8); /* unknown */
257 out_uint32_le(s, driverlen);
258 out_uint32_le(s, printerlen);
259 out_uint32_le(s, bloblen);
260 rdp_out_unistr(This, s, printerinfo->driver, driverlen - 2);
261 rdp_out_unistr(This, s, printerinfo->printer, printerlen - 2);
262 out_uint8a(s, printerinfo->blob, bloblen);
263
264 if (printerinfo->blob)
265 xfree(printerinfo->blob); /* Blob is sent twice if reconnecting */
266 break;
267 default:
268 out_uint32(s, 0);
269 }
270 }
271#if 0
272 out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */
273 out_uint32_le(s, 0);
274 out_uint8p(s, "SCARD", 5);
275 out_uint8s(s, 3);
276 out_uint32(s, 0);
277#endif
278
279 s_mark_end(s);
280 channel_send(This, s, This->rdpdr.channel);
281}
282
283static void
286{
287 uint8 magic[4] = "rDCI";
288 STREAM s;
289
290 s = channel_init(This, This->rdpdr.channel, 20 + length);
291 out_uint8a(s, magic, 4);
293 out_uint32_le(s, id);
297 s_mark_end(s);
298 /* JIF */
299#ifdef WITH_DEBUG_RDP5
300 printf("--> rdpdr_send_completion\n");
301 /* hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
302#endif
303 channel_send(This, s, This->rdpdr.channel);
304}
305
306static void
308{
309 uint32 result = 0,
310 length = 0,
311 desired_access = 0,
312 request,
313 file,
314 info_level,
315 buffer_len,
316 id,
317 major,
318 minor,
319 device,
320 offset,
321 bytes_in,
322 bytes_out,
323 error_mode,
324 share_mode, disposition, total_timeout, interval_timeout, flags_and_attributes = 0;
325
326 char filename[PATH_MAX];
327 uint8 *buffer, *pst_buf;
328 struct stream out;
329 DEVICE_FNS *fns;
330 BOOL rw_blocking = True;
332
335 in_uint32_le(s, id);
338
339 buffer_len = 0;
340 buffer = (uint8 *) xmalloc(1024);
341 buffer[0] = 0;
342
343 switch (This->rdpdr_device[device].device_type)
344 {
346
347 fns = &serial_fns;
348 rw_blocking = False;
349 break;
350
352
353 fns = &parallel_fns;
354 rw_blocking = False;
355 break;
356
358
359 fns = &printer_fns;
360 break;
361
362 case DEVICE_TYPE_DISK:
363
364 fns = &disk_fns;
365 rw_blocking = False;
366 break;
367
369 default:
370
371 error("IRP for bad device %ld\n", device);
372 return;
373 }
374
375 switch (major)
376 {
377 case IRP_MJ_CREATE:
378
379 in_uint32_be(s, desired_access);
380 in_uint8s(s, 0x08); /* unknown */
381 in_uint32_le(s, error_mode);
382 in_uint32_le(s, share_mode);
383 in_uint32_le(s, disposition);
384 in_uint32_le(s, flags_and_attributes);
386
387 if (length && (length / 2) < 256)
388 {
391 }
392 else
393 {
394 filename[0] = 0;
395 }
396
397 if (!fns->create)
398 {
400 break;
401 }
402
403 status = fns->create(This, device, desired_access, share_mode, disposition,
404 flags_and_attributes, filename, &result);
405 buffer_len = 1;
406 break;
407
408 case IRP_MJ_CLOSE:
409 if (!fns->close)
410 {
412 break;
413 }
414
415 status = fns->close(This, file);
416 break;
417
418 case IRP_MJ_READ:
419
420 if (!fns->read)
421 {
423 break;
424 }
425
428#if WITH_DEBUG_RDP5
429 DEBUG(("RDPDR IRP Read (length: %d, offset: %d)\n", length, offset));
430#endif
432 {
434 break;
435 }
436
437 if (rw_blocking) /* Complete read immediately */
438 {
439 buffer = (uint8 *) xrealloc((void *) buffer, length);
440 if (!buffer)
441 {
443 break;
444 }
445 status = fns->read(This, file, buffer, length, offset, &result);
446 buffer_len = result;
447 break;
448 }
449
450 /* Add request to table */
451 pst_buf = (uint8 *) xmalloc(length);
452 if (!pst_buf)
453 {
455 break;
456 }
457 serial_get_timeout(This, file, length, &total_timeout, &interval_timeout);
459 (This, device, file, id, major, length, fns, total_timeout, interval_timeout,
460 pst_buf, offset))
461 {
463 break;
464 }
465
467 break;
468 case IRP_MJ_WRITE:
469
470 buffer_len = 1;
471
472 if (!fns->write)
473 {
475 break;
476 }
477
480 in_uint8s(s, 0x18);
481#if WITH_DEBUG_RDP5
482 DEBUG(("RDPDR IRP Write (length: %d)\n", result));
483#endif
485 {
487 break;
488 }
489
490 if (rw_blocking) /* Complete immediately */
491 {
492 status = fns->write(This, file, s->p, length, offset, &result);
493 break;
494 }
495
496 /* Add to table */
497 pst_buf = (uint8 *) xmalloc(length);
498 if (!pst_buf)
499 {
501 break;
502 }
503
504 in_uint8a(s, pst_buf, length);
505
507 (This, device, file, id, major, length, fns, 0, 0, pst_buf, offset))
508 {
510 break;
511 }
512
514 break;
515
517
518 if (This->rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
519 {
521 break;
522 }
523 in_uint32_le(s, info_level);
524
525 out.data = out.p = buffer;
526 out.size = sizeof(buffer);
527 status = disk_query_information(This, file, info_level, &out);
528 result = buffer_len = out.p - out.data;
529
530 break;
531
533
534 if (This->rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
535 {
537 break;
538 }
539
540 in_uint32_le(s, info_level);
541
542 out.data = out.p = buffer;
543 out.size = sizeof(buffer);
544 status = disk_set_information(This, file, info_level, s, &out);
545 result = buffer_len = out.p - out.data;
546 break;
547
549
550 if (This->rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
551 {
553 break;
554 }
555
556 in_uint32_le(s, info_level);
557
558 out.data = out.p = buffer;
559 out.size = sizeof(buffer);
561 result = buffer_len = out.p - out.data;
562 break;
563
565
566 if (This->rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
567 {
569 break;
570 }
571
572 switch (minor)
573 {
575
576 in_uint32_le(s, info_level);
577 in_uint8s(s, 1);
579 in_uint8s(s, 0x17);
580 if (length && length < 2 * 255)
581 {
584 }
585 else
586 {
587 filename[0] = 0;
588 }
589 out.data = out.p = buffer;
590 out.size = sizeof(buffer);
592 &out);
593 result = buffer_len = out.p - out.data;
594 if (!buffer_len)
595 buffer_len++;
596 break;
597
599
600 /* JIF
601 unimpl("IRP major=0x%x minor=0x%x: IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", major, minor); */
602
603 in_uint32_le(s, info_level); /* notify mask */
604
605 This->notify_stamp = True;
606
607 status = disk_create_notify(This, file, info_level);
608 result = 0;
609
610 if (status == STATUS_PENDING)
612 fns, 0, 0, NULL, 0);
613 break;
614
615 default:
616
618 /* JIF */
619 unimpl("IRP major=0x%x minor=0x%x\n", major, minor);
620 }
621 break;
622
624
625 if (!fns->device_control)
626 {
628 break;
629 }
630
631 in_uint32_le(s, bytes_out);
632 in_uint32_le(s, bytes_in);
634 in_uint8s(s, 0x14);
635
636 buffer = (uint8 *) xrealloc((void *) buffer, bytes_out + 0x14);
637 if (!buffer)
638 {
640 break;
641 }
642
643 out.data = out.p = buffer;
644 out.size = sizeof(buffer);
645 status = fns->device_control(This, file, request, s, &out);
646 result = buffer_len = out.p - out.data;
647
648 /* Serial SERIAL_WAIT_ON_MASK */
649 if (status == STATUS_PENDING)
650 {
652 (This, device, file, id, major, length, fns, 0, 0, NULL, 0))
653 {
655 break;
656 }
657 }
658 break;
659
660
662
663 if (This->rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
664 {
666 break;
667 }
668
669 in_uint32_le(s, info_level);
670
671 out.data = out.p = buffer;
672 out.size = sizeof(buffer);
673 /* FIXME: Perhaps consider actually *do*
674 something here :-) */
676 result = buffer_len = out.p - out.data;
677 break;
678
679 default:
680 unimpl("IRP major=0x%x minor=0x%x\n", major, minor);
681 break;
682 }
683
684 if (status != STATUS_PENDING)
685 {
687 }
688 if (buffer)
689 xfree(buffer);
690 buffer = NULL;
691}
692
693static void
695{
696 uint8 magic[4] = "rDPC";
697 STREAM s;
698
699 s = channel_init(This, This->rdpdr.channel, 0x50);
700 out_uint8a(s, magic, 4);
701 out_uint32_le(s, 5); /* count */
702 out_uint16_le(s, 1); /* first */
703 out_uint16_le(s, 0x28); /* length */
704 out_uint32_le(s, 1);
705 out_uint32_le(s, 2);
706 out_uint16_le(s, 2);
707 out_uint16_le(s, 5);
708 out_uint16_le(s, 1);
709 out_uint16_le(s, 5);
710 out_uint16_le(s, 0xFFFF);
711 out_uint16_le(s, 0);
712 out_uint32_le(s, 0);
713 out_uint32_le(s, 3);
714 out_uint32_le(s, 0);
715 out_uint32_le(s, 0);
716 out_uint16_le(s, 2); /* second */
717 out_uint16_le(s, 8); /* length */
718 out_uint32_le(s, 1);
719 out_uint16_le(s, 3); /* third */
720 out_uint16_le(s, 8); /* length */
721 out_uint32_le(s, 1);
722 out_uint16_le(s, 4); /* fourth */
723 out_uint16_le(s, 8); /* length */
724 out_uint32_le(s, 1);
725 out_uint16_le(s, 5); /* fifth */
726 out_uint16_le(s, 8); /* length */
727 out_uint32_le(s, 1);
728
729 s_mark_end(s);
730 channel_send(This, s, This->rdpdr.channel);
731}
732
733static void
735{
737 uint8 *magic;
738
739#if WITH_DEBUG_RDP5
740 printf("--- rdpdr_process ---\n");
741 hexdump(s->p, s->end - s->p);
742#endif
743 in_uint8p(s, magic, 4);
744
745 if ((magic[0] == 'r') && (magic[1] == 'D'))
746 {
747 if ((magic[2] == 'R') && (magic[3] == 'I'))
748 {
750 return;
751 }
752 if ((magic[2] == 'n') && (magic[3] == 'I'))
753 {
756 return;
757 }
758 if ((magic[2] == 'C') && (magic[3] == 'C'))
759 {
760 /* connect from server */
763 return;
764 }
765 if ((magic[2] == 'r') && (magic[3] == 'd'))
766 {
767 /* connect to a specific resource */
769#if WITH_DEBUG_RDP5
770 DEBUG(("RDPDR: Server connected to resource %d\n", handle));
771#endif
772 return;
773 }
774 if ((magic[2] == 'P') && (magic[3] == 'S'))
775 {
776 /* server capability */
777 return;
778 }
779 }
780 if ((magic[0] == 'R') && (magic[1] == 'P'))
781 {
782 if ((magic[2] == 'C') && (magic[3] == 'P'))
783 {
785 return;
786 }
787 }
788 unimpl("RDPDR packet type %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]);
789}
790
791BOOL
793{
794 if (This->num_devices > 0)
795 {
796 This->rdpdr.channel =
797 channel_register(This, "rdpdr",
800 }
801
802 return (This->rdpdr.channel != NULL);
803}
804
805/* Add file descriptors of pending io request to select() */
806void
807rdpdr_add_fds(RDPCLIENT * This, int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * timeout)
808{
809 uint32 select_timeout = 0; /* Timeout value to be used for select() (in millisecons). */
810 struct async_iorequest *iorq;
811 char c;
812
813 iorq = This->iorequest;
814 while (iorq != NULL)
815 {
816 if (iorq->fd != 0)
817 {
818 switch (iorq->major)
819 {
820 case IRP_MJ_READ:
821 /* Is this FD valid? FDs will
822 be invalid when
823 reconnecting. FIXME: Real
824 support for reconnects. */
825
826 FD_SET(iorq->fd, rfds);
827 *n = MAX(*n, iorq->fd);
828
829 /* Check if io request timeout is smaller than current (but not 0). */
830 if (iorq->timeout
831 && (select_timeout == 0
832 || iorq->timeout < select_timeout))
833 {
834 /* Set new timeout */
835 select_timeout = iorq->timeout;
836 This->min_timeout_fd = iorq->fd; /* Remember fd */
837 tv->tv_sec = select_timeout / 1000;
838 tv->tv_usec = (select_timeout % 1000) * 1000;
839 *timeout = True;
840 break;
841 }
842 if (iorq->itv_timeout && iorq->partial_len > 0
843 && (select_timeout == 0
844 || iorq->itv_timeout < select_timeout))
845 {
846 /* Set new timeout */
847 select_timeout = iorq->itv_timeout;
848 This->min_timeout_fd = iorq->fd; /* Remember fd */
849 tv->tv_sec = select_timeout / 1000;
850 tv->tv_usec = (select_timeout % 1000) * 1000;
851 *timeout = True;
852 break;
853 }
854 break;
855
856 case IRP_MJ_WRITE:
857 /* FD still valid? See above. */
858 if ((write(iorq->fd, &c, 0) != 0) && (errno == EBADF))
859 break;
860
861 FD_SET(iorq->fd, wfds);
862 *n = MAX(*n, iorq->fd);
863 break;
864
866 if (select_timeout > 5)
867 select_timeout = 5; /* serial event queue */
868 break;
869
870 }
871
872 }
873
874 iorq = iorq->next;
875 }
876}
877
878struct async_iorequest *
879rdpdr_remove_iorequest(RDPCLIENT * This, struct async_iorequest *prev, struct async_iorequest *iorq)
880{
881 if (!iorq)
882 return NULL;
883
884 if (iorq->buffer)
885 xfree(iorq->buffer);
886 if (prev)
887 {
888 prev->next = iorq->next;
889 xfree(iorq);
890 iorq = prev->next;
891 }
892 else
893 {
894 /* Even if NULL */
895 This->iorequest = iorq->next;
896 xfree(iorq);
897 iorq = NULL;
898 }
899 return iorq;
900}
901
902/* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */
903static void
904_rdpdr_check_fds(RDPCLIENT * This, fd_set * rfds, fd_set * wfds, BOOL timed_out)
905{
907 uint32 result = 0;
908 DEVICE_FNS *fns;
909 struct async_iorequest *iorq;
910 struct async_iorequest *prev;
911 uint32 req_size = 0;
912 uint32 buffer_len;
913 struct stream out;
914 uint8 *buffer = NULL;
915
916
917 if (timed_out)
918 {
919 /* check serial iv_timeout */
920
921 iorq = This->iorequest;
922 prev = NULL;
923 while (iorq != NULL)
924 {
925 if (iorq->fd == This->min_timeout_fd)
926 {
927 if ((iorq->partial_len > 0) &&
928 (This->rdpdr_device[iorq->device].device_type ==
930 {
931
932 /* iv_timeout between 2 chars, send partial_len */
933 /*printf("RDPDR: IVT total %u bytes read of %u\n", iorq->partial_len, iorq->length); */
934 rdpdr_send_completion(This, iorq->device,
935 iorq->id, STATUS_SUCCESS,
936 iorq->partial_len,
937 iorq->buffer, iorq->partial_len);
938 iorq = rdpdr_remove_iorequest(This, prev, iorq);
939 return;
940 }
941 else
942 {
943 break;
944 }
945
946 }
947 else
948 {
949 break;
950 }
951
952
953 prev = iorq;
954 if (iorq)
955 iorq = iorq->next;
956
957 }
958
959 rdpdr_abort_io(This, This->min_timeout_fd, 0, STATUS_TIMEOUT);
960 return;
961 }
962
963 iorq = This->iorequest;
964 prev = NULL;
965 while (iorq != NULL)
966 {
967 if (iorq->fd != 0)
968 {
969 switch (iorq->major)
970 {
971 case IRP_MJ_READ:
972 if (FD_ISSET(iorq->fd, rfds))
973 {
974 /* Read the data */
975 fns = iorq->fns;
976
977 req_size =
978 (iorq->length - iorq->partial_len) >
979 8192 ? 8192 : (iorq->length -
980 iorq->partial_len);
981 /* never read larger chunks than 8k - chances are that it will block */
982 status = fns->read(This, iorq->fd,
983 iorq->buffer + iorq->partial_len,
984 req_size, iorq->offset, &result);
985
986 if ((long) result > 0)
987 {
988 iorq->partial_len += result;
989 iorq->offset += result;
990 }
991#if WITH_DEBUG_RDP5
992 DEBUG(("RDPDR: %d bytes of data read\n", result));
993#endif
994 /* only delete link if all data has been transfered */
995 /* or if result was 0 and status success - EOF */
996 if ((iorq->partial_len == iorq->length) ||
997 (result == 0))
998 {
999#if WITH_DEBUG_RDP5
1000 DEBUG(("RDPDR: AIO total %u bytes read of %u\n", iorq->partial_len, iorq->length));
1001#endif
1002 rdpdr_send_completion(This, iorq->device,
1003 iorq->id, status,
1004 iorq->partial_len,
1005 iorq->buffer,
1006 iorq->partial_len);
1007 iorq = rdpdr_remove_iorequest(This, prev, iorq);
1008 }
1009 }
1010 break;
1011 case IRP_MJ_WRITE:
1012 if (FD_ISSET(iorq->fd, wfds))
1013 {
1014 /* Write data. */
1015 fns = iorq->fns;
1016
1017 req_size =
1018 (iorq->length - iorq->partial_len) >
1019 8192 ? 8192 : (iorq->length -
1020 iorq->partial_len);
1021
1022 /* never write larger chunks than 8k - chances are that it will block */
1023 status = fns->write(This, iorq->fd,
1024 iorq->buffer +
1025 iorq->partial_len, req_size,
1026 iorq->offset, &result);
1027
1028 if ((long) result > 0)
1029 {
1030 iorq->partial_len += result;
1031 iorq->offset += result;
1032 }
1033
1034#if WITH_DEBUG_RDP5
1035 DEBUG(("RDPDR: %d bytes of data written\n",
1036 result));
1037#endif
1038 /* only delete link if all data has been transfered */
1039 /* or we couldn't write */
1040 if ((iorq->partial_len == iorq->length)
1041 || (result == 0))
1042 {
1043#if WITH_DEBUG_RDP5
1044 DEBUG(("RDPDR: AIO total %u bytes written of %u\n", iorq->partial_len, iorq->length));
1045#endif
1046 rdpdr_send_completion(This, iorq->device,
1047 iorq->id, status,
1048 iorq->partial_len,
1049 (uint8 *) "", 1);
1050
1051 iorq = rdpdr_remove_iorequest(This, prev, iorq);
1052 }
1053 }
1054 break;
1056 if (serial_get_event(This, iorq->fd, &result))
1057 {
1058 buffer = (uint8 *) xrealloc((void *) buffer, 0x14);
1059 out.data = out.p = buffer;
1060 out.size = sizeof(buffer);
1062 result = buffer_len = out.p - out.data;
1064 rdpdr_send_completion(This, iorq->device, iorq->id,
1066 buffer_len);
1067 xfree(buffer);
1068 iorq = rdpdr_remove_iorequest(This, prev, iorq);
1069 }
1070
1071 break;
1072 }
1073
1074 }
1075 prev = iorq;
1076 if (iorq)
1077 iorq = iorq->next;
1078 }
1079
1080 /* Check notify */
1081 iorq = This->iorequest;
1082 prev = NULL;
1083 while (iorq != NULL)
1084 {
1085 if (iorq->fd != 0)
1086 {
1087 switch (iorq->major)
1088 {
1089
1091 if (This->rdpdr_device[iorq->device].device_type ==
1093 {
1094
1095 if (This->notify_stamp)
1096 {
1097 This->notify_stamp = False;
1098 status = disk_check_notify(This, iorq->fd);
1099 if (status != STATUS_PENDING)
1100 {
1101 rdpdr_send_completion(This, iorq->device,
1102 iorq->id,
1103 status, 0,
1104 NULL, 0);
1105 iorq = rdpdr_remove_iorequest(This, prev,
1106 iorq);
1107 }
1108 }
1109 }
1110 break;
1111
1112
1113
1114 }
1115 }
1116
1117 prev = iorq;
1118 if (iorq)
1119 iorq = iorq->next;
1120 }
1121
1122}
1123
1124void
1125rdpdr_check_fds(RDPCLIENT * This, fd_set * rfds, fd_set * wfds, BOOL timed_out)
1126{
1127 fd_set dummy;
1128
1129
1130 FD_ZERO(&dummy);
1131
1132
1133 /* fist check event queue only,
1134 any serial wait event must be done before read block will be sent
1135 */
1136
1138 _rdpdr_check_fds(This, rfds, wfds, timed_out);
1139}
1140
1141
1142/* Abort a pending io request for a given handle and major */
1143BOOL
1145{
1146 uint32 result;
1147 struct async_iorequest *iorq;
1148 struct async_iorequest *prev;
1149
1150 iorq = This->iorequest;
1151 prev = NULL;
1152 while (iorq != NULL)
1153 {
1154 /* Only remove from table when major is not set, or when correct major is supplied.
1155 Abort read should not abort a write io request. */
1156 if ((iorq->fd == fd) && (major == 0 || iorq->major == major))
1157 {
1158 result = 0;
1159 rdpdr_send_completion(This, iorq->device, iorq->id, status, result, (uint8 *) "",
1160 1);
1161
1162 iorq = rdpdr_remove_iorequest(This, prev, iorq);
1163 return True;
1164 }
1165
1166 prev = iorq;
1167 iorq = iorq->next;
1168 }
1169
1170 return False;
1171}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define EBADF
Definition: acclib.h:82
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define write
Definition: acwin.h:97
LONG NTSTATUS
Definition: precomp.h:26
VCHANNEL * channel_register(char *name, uint32 flags, void(*callback)(STREAM))
Definition: channels.c:46
STREAM channel_init(VCHANNEL *channel, uint32 length)
Definition: channels.c:69
void channel_send(STREAM s, VCHANNEL *channel)
Definition: channels.c:79
#define DEVICE_TYPE_DISK
Definition: constants.h:488
#define DEVICE_TYPE_SERIAL
Definition: constants.h:485
#define DEVICE_TYPE_PRINTER
Definition: constants.h:487
#define RDPDR_MAX_DEVICES
Definition: constants.h:484
#define CHANNEL_OPTION_INITIALIZED
Definition: constants.h:431
#define DEVICE_TYPE_SCARD
Definition: constants.h:489
#define DEVICE_TYPE_PARALLEL
Definition: constants.h:486
#define CHANNEL_OPTION_COMPRESS_RDP
Definition: constants.h:433
#define s_mark_end(s)
Definition: parse.h:41
#define out_uint32_le(s, v)
Definition: parse.h:59
#define in_uint32(s, v)
Definition: parse.h:83
#define in_uint32_be(s, v)
Definition: parse.h:76
#define out_uint32_be(s, v)
Definition: parse.h:78
#define in_uint8p(s, v, n)
Definition: parse.h:89
#define in_uint8a(s, v, n)
Definition: parse.h:90
#define in_uint8s(s, n)
Definition: parse.h:91
#define out_uint8s(s, n)
Definition: parse.h:95
#define out_uint16_le(s, v)
Definition: parse.h:58
#define out_uint8p(s, v, n)
Definition: parse.h:93
#define out_uint32(s, v)
Definition: parse.h:85
#define in_uint32_le(s, v)
Definition: parse.h:56
#define out_uint8a(s, v, n)
Definition: parse.h:94
void xfree(void *mem)
Definition: uimain.c:758
int printercache_load_blob(char *printer_name, uint8 **data)
Definition: printercache.c:154
RD_NTSTATUS disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
RD_BOOL serial_get_timeout(RD_NTHANDLE handle, uint32 length, uint32 *timeout, uint32 *itv_timeout)
void printercache_process(STREAM s)
RD_NTSTATUS disk_set_information(RD_NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
RD_NTSTATUS disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREAM out)
void rdp_in_unistr(STREAM s, int in_len, char **string, uint32 *str_size)
Definition: rdp.c:265
void unimpl(char *format,...)
Definition: uimain.c:801
void hexdump(unsigned char *p, unsigned int len)
Definition: shimdbg.c:234
void rdp_out_unistr(STREAM s, char *string, int len)
Definition: rdp.c:188
RD_NTSTATUS disk_check_notify(RD_NTHANDLE handle)
void * xmalloc(int size)
Definition: uimain.c:747
RD_NTSTATUS disk_create_notify(RD_NTHANDLE handle, uint32 info_class)
RD_BOOL rdpdr_init()
void * xrealloc(void *oldmem, size_t size)
Definition: uimain.c:736
RD_NTSTATUS disk_query_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
RD_BOOL serial_get_event(RD_NTHANDLE handle, uint32 *result)
#define DEBUG(args)
Definition: rdesktop.h:129
#define MAX(x, y)
Definition: rdesktop.h:175
unsigned int uint32
Definition: types.h:32
#define False
Definition: types.h:25
#define True
Definition: types.h:24
unsigned char uint8
Definition: types.h:28
#define PATH_MAX
Definition: types.h:280
#define NULL
Definition: types.h:112
unsigned int BOOL
Definition: ntddk_ex.h:94
#define printf
Definition: freeldr.h:97
GLdouble s
Definition: gl.h:2039
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLuint64EXT * result
Definition: glext.h:11304
GLuint id
Definition: glext.h:5910
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
const char * filename
Definition: ioapi.h:137
#define c
Definition: ke_i.h:80
#define error(str)
Definition: mkdosfs.c:1605
u32_t magic(void)
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define minor(rdev)
Definition: propsheet.cpp:929
#define major(rdev)
Definition: propsheet.cpp:928
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
BOOL rdpdr_abort_io(RDPCLIENT *This, uint32 fd, uint32 major, NTSTATUS status)
Definition: rdpdr.c:1144
void convert_to_unix_filename(char *filename)
Definition: rdpdr.c:78
DEVICE_FNS parallel_fns
Definition: parallel.c:181
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
static void rdpdr_send_connect(RDPCLIENT *This)
Definition: rdpdr.c:156
DEVICE_FNS serial_fns
Definition: serial.c:1068
static BOOL rdpdr_handle_ok(RDPCLIENT *This, int device, int handle)
Definition: rdpdr.c:89
DEVICE_FNS printer_fns
Definition: printer.c:156
static void rdpdr_send_available(RDPCLIENT *This)
Definition: rdpdr.c:224
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY
Definition: rdpdr.c:56
static BOOL add_async_iorequest(RDPCLIENT *This, uint32 device, uint32 file, uint32 id, uint32 major, uint32 length, DEVICE_FNS *fns, uint32 total_timeout, uint32 interval_timeout, uint8 *buffer, uint32 offset)
Definition: rdpdr.c:110
static void rdpdr_send_completion(RDPCLIENT *This, uint32 device, uint32 id, uint32 status, uint32 result, uint8 *buffer, uint32 length)
Definition: rdpdr.c:284
#define IRP_MJ_READ
Definition: rdpdr.c:46
int get_device_index(RDPCLIENT *This, NTHANDLE handle)
Definition: rdpdr.c:65
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
DEVICE_FNS disk_fns
Definition: disk.c:1240
#define IRP_MJ_QUERY_VOLUME_INFORMATION
Definition: rdpdr.c:50
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
void rdpdr_check_fds(RDPCLIENT *This, fd_set *rfds, fd_set *wfds, BOOL timed_out)
Definition: rdpdr.c:1125
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
static void rdpdr_send_clientcapabilty(RDPCLIENT *This)
Definition: rdpdr.c:694
static int announcedata_size(RDPCLIENT *This)
Definition: rdpdr.c:197
static void rdpdr_process(RDPCLIENT *This, STREAM s)
Definition: rdpdr.c:734
void rdpdr_add_fds(RDPCLIENT *This, int *n, fd_set *rfds, fd_set *wfds, struct timeval *tv, BOOL *timeout)
Definition: rdpdr.c:807
struct async_iorequest * rdpdr_remove_iorequest(RDPCLIENT *This, struct async_iorequest *prev, struct async_iorequest *iorq)
Definition: rdpdr.c:879
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
static void rdpdr_send_name(RDPCLIENT *This)
Definition: rdpdr.c:172
static void rdpdr_process_irp(RDPCLIENT *This, STREAM s)
Definition: rdpdr.c:307
static void _rdpdr_check_fds(RDPCLIENT *This, fd_set *rfds, fd_set *wfds, BOOL timed_out)
Definition: rdpdr.c:904
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
static FILE * out
Definition: regtests2xml.c:44
#define errno
Definition: errno.h:18
static int fd
Definition: io.c:51
#define STATUS_SUCCESS
Definition: shellext.h:65
RD_NTSTATUS(* read)(RD_NTHANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
Definition: types.h:206
RD_NTSTATUS(* write)(RD_NTHANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
Definition: types.h:208
struct define * next
Definition: compiler.c:65
Definition: devices.h:37
Definition: winsock.h:66
Definition: fci.c:127
char * printer
Definition: types.h:263
char * driver
Definition: types.h:263
uint32 bloblen
Definition: types.h:264
RD_BOOL default_printer
Definition: types.h:266
uint8 * blob
Definition: types.h:265
Definition: tftpd.h:86
Definition: ps.c:97
Definition: parse.h:23
Definition: dhcpd.h:245
unsigned long tv_sec
Definition: linux.h:1738
unsigned long tv_usec
Definition: linux.h:1739
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define FD_ISSET(fd, set)
Definition: winsock.h:100
#define FD_ZERO(set)
Definition: winsock.h:96
#define FD_SET(fd, set)
Definition: winsock.h:89