ReactOS  0.4.14-dev-608-gd495a4f
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 
58 extern DEVICE_FNS serial_fns;
59 extern DEVICE_FNS printer_fns;
61 extern DEVICE_FNS disk_fns;
62 
63 /* Return device_id for a given handle */
64 int
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 */
77 void
79 {
80  char *p;
81 
82  while ((p = strchr(filename, '\\')))
83  {
84  *p = '/';
85  }
86 }
87 
88 static BOOL
90 {
91  switch (This->rdpdr_device[device].device_type)
92  {
94  case DEVICE_TYPE_SERIAL:
96  case DEVICE_TYPE_SCARD:
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 */
109 static BOOL
111  DEVICE_FNS * fns, uint32 total_timeout, uint32 interval_timeout, uint8 * buffer,
112  uint32 offset)
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 
155 static 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 
171 static 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 */
196 static 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 
223 static 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  {
247  case DEVICE_TYPE_PRINTER:
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 
283 static void
285  uint32 length)
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 
306 static 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 
334  in_uint32_le(s, file);
335  in_uint32_le(s, id);
336  in_uint32_le(s, major);
337  in_uint32_le(s, minor);
338 
339  buffer_len = 0;
340  buffer = (uint8 *) xmalloc(1024);
341  buffer[0] = 0;
342 
343  switch (This->rdpdr_device[device].device_type)
344  {
345  case DEVICE_TYPE_SERIAL:
346 
347  fns = &serial_fns;
348  rw_blocking = False;
349  break;
350 
352 
353  fns = &parallel_fns;
354  rw_blocking = False;
355  break;
356 
357  case DEVICE_TYPE_PRINTER:
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 
368  case DEVICE_TYPE_SCARD:
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);
591  status = disk_query_directory(This, file, info_level, filename,
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 
661  case IRP_MJ_LOCK_CONTROL:
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  {
686  rdpdr_send_completion(This, device, id, status, result, buffer, buffer_len);
687  }
688  if (buffer)
689  xfree(buffer);
690  buffer = NULL;
691 }
692 
693 static 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 
733 static void
735 {
736  uint32 handle;
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 */
768  in_uint32(s, handle);
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 
791 BOOL
793 {
794  if (This->num_devices > 0)
795  {
796  This->rdpdr.channel =
797  channel_register(This, "rdpdr",
799  rdpdr_process);
800  }
801 
802  return (This->rdpdr.channel != NULL);
803 }
804 
805 /* Add file descriptors of pending io request to select() */
806 void
807 rdpdr_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 
878 struct async_iorequest *
879 rdpdr_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 */
903 static 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;
1055  case IRP_MJ_DEVICE_CONTROL:
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,
1065  status, result, buffer,
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 
1124 void
1125 rdpdr_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 */
1143 BOOL
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 }
void rdp_in_unistr(STREAM s, int in_len, char **string, uint32 *str_size)
Definition: rdp.c:265
Definition: winsock.h:66
#define out_uint16_le(s, v)
Definition: parse.h:58
#define out_uint8p(s, v, n)
Definition: parse.h:93
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY
Definition: rdpdr.c:56
int printercache_load_blob(char *printer_name, uint8 **data)
Definition: printercache.c:154
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define DEVICE_TYPE_DISK
Definition: constants.h:488
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
void rdpdr_add_fds(RDPCLIENT *This, int *n, fd_set *rfds, fd_set *wfds, struct timeval *tv, BOOL *timeout)
Definition: rdpdr.c:807
#define error(str)
Definition: mkdosfs.c:1605
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define out_uint8a(s, v, n)
Definition: parse.h:94
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define DEVICE_TYPE_PRINTER
Definition: constants.h:487
unsigned int uint32
Definition: types.h:32
#define DEVICE_TYPE_PARALLEL
Definition: constants.h:486
RD_NTSTATUS disk_create_notify(RD_NTHANDLE handle, uint32 info_class)
unsigned long tv_sec
Definition: linux.h:1738
LONG NTSTATUS
Definition: precomp.h:26
char * printer
Definition: types.h:263
GLintptr offset
Definition: glext.h:5920
RD_NTSTATUS disk_set_information(RD_NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
void printercache_process(STREAM s)
#define out_uint32_le(s, v)
Definition: parse.h:59
GLdouble n
Definition: glext.h:7729
u32_t magic(void)
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
GLuint buffer
Definition: glext.h:5915
static int fd
Definition: io.c:51
Definition: dhcpd.h:245
RD_NTSTATUS disk_check_notify(RD_NTHANDLE handle)
int errno
char * driver
Definition: types.h:263
#define FD_ZERO(set)
Definition: winsock.h:96
const char * filename
Definition: ioapi.h:135
#define FD_SET(fd, set)
Definition: winsock.h:89
Definition: arc.h:36
#define in_uint8p(s, v, n)
Definition: parse.h:89
RD_BOOL serial_get_event(RD_NTHANDLE handle, uint32 *result)
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:231
#define DEVICE_TYPE_SERIAL
Definition: constants.h:485
static void rdpdr_send_connect(RDPCLIENT *This)
Definition: rdpdr.c:156
static void rdpdr_send_clientcapabilty(RDPCLIENT *This)
Definition: rdpdr.c:694
DEVICE_FNS printer_fns
Definition: printer.c:156
VCHANNEL * channel_register(char *name, uint32 flags, void(*callback)(STREAM))
Definition: channels.c:46
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
RD_BOOL serial_get_timeout(RD_NTHANDLE handle, uint32 length, uint32 *timeout, uint32 *itv_timeout)
#define write
Definition: acwin.h:97
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
RD_BOOL default_printer
Definition: types.h:266
BOOL rdpdr_abort_io(RDPCLIENT *This, uint32 fd, uint32 major, NTSTATUS status)
Definition: rdpdr.c:1144
void * xrealloc(void *oldmem, size_t size)
Definition: uimain.c:736
void * xmalloc(int size)
Definition: uimain.c:747
#define CHANNEL_OPTION_INITIALIZED
Definition: constants.h:431
unsigned int BOOL
Definition: ntddk_ex.h:94
#define FD_ISSET(fd, set)
Definition: winsock.h:100
#define RDPDR_MAX_DEVICES
Definition: constants.h:484
Definition: devices.h:37
#define DEVICE_TYPE_SCARD
Definition: constants.h:489
static void rdpdr_send_completion(RDPCLIENT *This, uint32 device, uint32 id, uint32 status, uint32 result, uint8 *buffer, uint32 length)
Definition: rdpdr.c:284
RD_NTSTATUS(* write)(RD_NTHANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
Definition: types.h:208
void rdpdr_check_fds(RDPCLIENT *This, fd_set *rfds, fd_set *wfds, BOOL timed_out)
Definition: rdpdr.c:1125
smooth NULL
Definition: ftsmooth.c:416
unsigned long tv_usec
Definition: linux.h:1739
#define in_uint32_be(s, v)
Definition: parse.h:76
uint8 * blob
Definition: types.h:265
#define in_uint8s(s, n)
Definition: parse.h:91
#define out_uint8s(s, n)
Definition: parse.h:95
#define IRP_MJ_QUERY_VOLUME_INFORMATION
Definition: rdpdr.c:50
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
uint32 bloblen
Definition: types.h:264
#define CHANNEL_OPTION_COMPRESS_RDP
Definition: constants.h:433
#define True
Definition: types.h:24
#define False
Definition: types.h:25
GLsizeiptr size
Definition: glext.h:5919
void xfree(void *mem)
Definition: uimain.c:758
static void rdpdr_send_name(RDPCLIENT *This)
Definition: rdpdr.c:172
DEVICE_FNS parallel_fns
Definition: parallel.c:181
#define STATUS_PENDING
Definition: ntstatus.h:82
static int announcedata_size(RDPCLIENT *This)
Definition: rdpdr.c:197
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
const char file[]
Definition: icontest.c:11
const GLubyte * c
Definition: glext.h:8905
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
static FILE * out
Definition: regtests2xml.c:44
#define PATH_MAX
Definition: types.h:280
unsigned char uint8
Definition: types.h:28
static BOOL rdpdr_handle_ok(RDPCLIENT *This, int device, int handle)
Definition: rdpdr.c:89
int get_device_index(RDPCLIENT *This, NTHANDLE handle)
Definition: rdpdr.c:65
#define in_uint32(s, v)
Definition: parse.h:83
static void _rdpdr_check_fds(RDPCLIENT *This, fd_set *rfds, fd_set *wfds, BOOL timed_out)
Definition: rdpdr.c:904
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
DEVICE_FNS disk_fns
Definition: disk.c:1240
RD_NTSTATUS disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
Definition: parse.h:22
GLdouble s
Definition: gl.h:2039
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
T MAX(T a, T b)
Definition: polytest.cpp:85
RD_NTSTATUS disk_query_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
#define in_uint8a(s, v, n)
Definition: parse.h:90
#define out_uint32_be(s, v)
Definition: parse.h:78
void hexdump(unsigned char *p, unsigned int len)
Definition: shimdbg.c:234
DEVICE_FNS serial_fns
Definition: serial.c:1068
unsigned char dummy
Definition: maze.c:118
struct define * next
Definition: compiler.c:65
#define major(rdev)
Definition: propsheet.cpp:916
void rdp_out_unistr(STREAM s, char *string, int len)
Definition: rdp.c:188
BOOL rdpdr_init(RDPCLIENT *This)
Definition: rdpdr.c:792
Definition: tftpd.h:85
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define IRP_MJ_READ
Definition: rdpdr.c:46
static void rdpdr_send_available(RDPCLIENT *This)
Definition: rdpdr.c:224
void convert_to_unix_filename(char *filename)
Definition: rdpdr.c:78
RD_NTSTATUS disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREAM out)
RD_NTSTATUS(* read)(RD_NTHANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
Definition: types.h:206
#define c
Definition: ke_i.h:80
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
GLenum GLuint id
Definition: glext.h:5579
#define minor(rdev)
Definition: propsheet.cpp:917
#define out_uint32(s, v)
Definition: parse.h:85
void unimpl(char *format,...)
Definition: uimain.c:801
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
#define DEBUG(args)
Definition: rdesktop.h:129
#define s_mark_end(s)
Definition: parse.h:41
GLfloat GLfloat p
Definition: glext.h:8902
static void rdpdr_process(RDPCLIENT *This, STREAM s)
Definition: rdpdr.c:734
#define in_uint32_le(s, v)
Definition: parse.h:56
return STATUS_SUCCESS
Definition: btrfs.c:2938
GLuint64EXT * result
Definition: glext.h:11304
static SERVICE_STATUS status
Definition: service.c:31
struct async_iorequest * rdpdr_remove_iorequest(RDPCLIENT *This, struct async_iorequest *prev, struct async_iorequest *iorq)
Definition: rdpdr.c:879
void channel_send(STREAM s, VCHANNEL *channel)
Definition: channels.c:79
#define printf
Definition: config.h:203
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
static void rdpdr_process_irp(RDPCLIENT *This, STREAM s)
Definition: rdpdr.c:307
Definition: fci.c:126
STREAM channel_init(VCHANNEL *channel, uint32 length)
Definition: channels.c:69
Definition: ps.c:97