/[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

Diff of /sourceforge.net/trunk/rdesktop/rdpdr.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 536 by matthewc, Fri Oct 31 04:29:57 2003 UTC revision 602 by stargo, Sat Feb 7 17:32:21 2004 UTC
# Line 1  Line 1 
1    #include <unistd.h>
2    #include <sys/types.h>
3    #include <time.h>
4  #include "rdesktop.h"  #include "rdesktop.h"
5    
6  #define IRP_MJ_CREATE           0x00  #define IRP_MJ_CREATE           0x00
# Line 6  Line 9 
9  #define IRP_MJ_WRITE            0x04  #define IRP_MJ_WRITE            0x04
10  #define IRP_MJ_DEVICE_CONTROL   0x0e  #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];  extern char hostname[16];
26  extern DEVICE_FNS serial_fns;  extern DEVICE_FNS serial_fns;
27  extern DEVICE_FNS printer_fns;  extern DEVICE_FNS printer_fns;
28    extern DEVICE_FNS parallel_fns;
29    extern DEVICE_FNS disk_fns;
30    
31  static VCHANNEL *rdpdr_channel;  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  void
123  rdpdr_send_connect(void)  rdpdr_send_connect(void)
124  {  {
# Line 27  rdpdr_send_connect(void) Line 134  rdpdr_send_connect(void)
134          channel_send(s, rdpdr_channel);          channel_send(s, rdpdr_channel);
135  }  }
136    
137    
138  void  void
139  rdpdr_send_name(void)  rdpdr_send_name(void)
140  {  {
# Line 45  rdpdr_send_name(void) Line 153  rdpdr_send_name(void)
153          channel_send(s, rdpdr_channel);          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  void
185  rdpdr_send_available(void)  rdpdr_send_available(void)
186  {  {
187    
188          uint8 magic[4] = "rDAD";          uint8 magic[4] = "rDAD";
189          char *driver = "Digital turbo PrintServer 20";  /* Fairly generic PostScript driver */          uint32 driverlen, printerlen, bloblen;
190          char *printer = "PostScript";          int i;
         uint32 driverlen = (strlen(driver) + 1) * 2;  
         uint32 printerlen = (strlen(printer) + 1) * 2;  
191          STREAM s;          STREAM s;
192            PRINTER *printerinfo;
193    
194          s = channel_init(rdpdr_channel, 8 + 20);          s = channel_init(rdpdr_channel, announcedata_size());
195          out_uint8a(s, magic, 4);          out_uint8a(s, magic, 4);
196          out_uint32_le(s, 1);    /* Number of devices */          out_uint32_le(s, g_num_devices);
197    
198  #if 1          for (i = 0; i < g_num_devices; i++)
199          out_uint32_le(s, 0x1);  /* Device type 0x1 - serial */          {
200          out_uint32_le(s, 0);    /* Handle */                  out_uint32_le(s, g_rdpdr_device[i].device_type);
201          out_uint8p(s, "COM2", 4);                  out_uint32_le(s, i);    /* RDP Device ID */
202          out_uint8s(s, 4);       /* Pad to 8 */                  out_uint8p(s, g_rdpdr_device[i].name, 8);
203          out_uint32(s, 0);  
204  #endif                  switch (g_rdpdr_device[i].device_type)
205  #if 0                  {
206          out_uint32_le(s, 0x2);  /* Device type 0x2 - parallel */                          case DEVICE_TYPE_PRINTER:
207          out_uint32_le(s, 0);                                  printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
208          out_uint8p(s, "LPT2", 4);  
209          out_uint8s(s, 4);                                  driverlen = 2 * strlen(printerinfo->driver) + 2;
210          out_uint32(s, 0);                                  printerlen = 2 * strlen(printerinfo->printer) + 2;
211  #endif                                  bloblen = printerinfo->bloblen;
212  #if 1  
213          out_uint32_le(s, 0x4);  /* Device type 0x4 - printer */                                  out_uint32_le(s, 24 + driverlen + printerlen + bloblen);        /* length of extra info */
214          out_uint32_le(s, 1);                                  out_uint32_le(s, printerinfo->default_printer ? 2 : 0);
215          out_uint8p(s, "PRN1", 4);                                  out_uint8s(s, 8);       /* unknown */
216          out_uint8s(s, 4);                                  out_uint32_le(s, driverlen);
217          out_uint32_le(s, 24 + driverlen + printerlen);  /* length of extra info */                                  out_uint32_le(s, printerlen);
218          out_uint32_le(s, 2);    /* unknown */                                  out_uint32_le(s, bloblen);
219          out_uint8s(s, 8);       /* unknown */                                  rdp_out_unistr(s, printerinfo->driver, driverlen - 2);
220          out_uint32_le(s, driverlen);    /* length of driver name */                                  rdp_out_unistr(s, printerinfo->printer, printerlen - 2);
221          out_uint32_le(s, printerlen);   /* length of printer name */                                  out_uint8a(s, printerinfo->blob, bloblen);
222          out_uint32(s, 0);       /* unknown */  
223          rdp_out_unistr(s, driver, driverlen - 2);                                  if (printerinfo->blob)
224          rdp_out_unistr(s, printer, printerlen - 2);                                          xfree(printerinfo->blob);       /* Blob is sent twice if reconnecting */
225  #endif                                  break;
226  #if 0                          default:
227          out_uint32_le(s, 0x8);  /* Device type 0x8 - disk */                                  out_uint32(s, 0);
228          out_uint32_le(s, 0);                  }
229          out_uint8p(s, "Z:", 2);          }
         out_uint8s(s, 6);  
         out_uint32(s, 0);  
 #endif  
230  #if 0  #if 0
231          out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */          out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */
232          out_uint32_le(s, 0);          out_uint32_le(s, 0);
# Line 121  rdpdr_send_completion(uint32 device, uin Line 254  rdpdr_send_completion(uint32 device, uin
254          out_uint32_le(s, result);          out_uint32_le(s, result);
255          out_uint8p(s, buffer, length);          out_uint8p(s, buffer, length);
256          s_mark_end(s);          s_mark_end(s);
257          hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);          /* JIF
258               hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
259          channel_send(s, rdpdr_channel);          channel_send(s, rdpdr_channel);
260  }  }
261    
262  static void  static void
263  rdpdr_process_irp(STREAM s)  rdpdr_process_irp(STREAM s)
264  {  {
265          uint32 device, file, id, major, minor;          uint32 result = 0,
266          NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;                  length = 0,
267          uint32 result = 0, length, request, bytes_in, bytes_out;                  desired_access = 0,
268          uint8 buffer[256];                  request,
269          uint32 buffer_len = 1;                  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;          struct stream out;
285          DEVICE_FNS *fns;          DEVICE_FNS *fns;
286            BOOL rw_blocking = True;
287            NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
288    
289          in_uint32_le(s, device);          in_uint32_le(s, device);
290          in_uint32_le(s, file);          in_uint32_le(s, file);
# Line 142  rdpdr_process_irp(STREAM s) Line 292  rdpdr_process_irp(STREAM s)
292          in_uint32_le(s, major);          in_uint32_le(s, major);
293          in_uint32_le(s, minor);          in_uint32_le(s, minor);
294    
295          memset(buffer, 0, sizeof(buffer));          buffer_len = 0;
296            buffer = (uint8 *) xmalloc(1024);
297            buffer[0] = 0;
298    
299          /* FIXME: this should probably be a more dynamic mapping */          switch (g_rdpdr_device[device].device_type)
         switch (device)  
300          {          {
301                  case 0:                  case DEVICE_TYPE_SERIAL:
302    
303                          fns = &serial_fns;                          fns = &serial_fns;
304                  case 1:                          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;                          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:                  default:
326    
327                          error("IRP for bad device %ld\n", device);                          error("IRP for bad device %ld\n", device);
328                          return;                          return;
329          }          }
# Line 159  rdpdr_process_irp(STREAM s) Line 331  rdpdr_process_irp(STREAM s)
331          switch (major)          switch (major)
332          {          {
333                  case IRP_MJ_CREATE:                  case IRP_MJ_CREATE:
334                          if (fns->create)  
335                                  status = fns->create(&result);                          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;                          break;
363    
364                  case IRP_MJ_CLOSE:                  case IRP_MJ_CLOSE:
365                          if (fns->close)                          if (!fns->close)
366                                  status = fns->close(file);                          {
367                                    status = STATUS_NOT_SUPPORTED;
368                                    break;
369                            }
370    
371                            status = fns->close(file);
372                          break;                          break;
373    
374                  case IRP_MJ_READ:                  case IRP_MJ_READ:
375                          if (fns->read)  
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                                  if (length > sizeof(buffer))                                  buffer = (uint8 *) xrealloc((void *) buffer, length);
390                                          length = sizeof(buffer);                                  status = fns->read(file, buffer, length, offset, &result);
                                 status = fns->read(file, buffer, length, &result);  
391                                  buffer_len = result;                                  buffer_len = result;
392                                    break;
393                          }                          }
                         break;  
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:                  case IRP_MJ_WRITE:
409                          if (fns->write)  
410                                  status = fns->write(file, s->p, length, &result);                          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;                          break;
540    
541                  case IRP_MJ_DEVICE_CONTROL:                  case IRP_MJ_DEVICE_CONTROL:
542                          if (fns->device_control)  
543                            if (!fns->device_control)
544                          {                          {
545                                  in_uint32_le(s, bytes_out);                                  status = STATUS_NOT_SUPPORTED;
546                                  in_uint32_le(s, bytes_in);                                  break;
                                 in_uint32_le(s, request);  
                                 in_uint8s(s, 0x14);  
                                 out.data = out.p = buffer;  
                                 out.size = sizeof(buffer);  
                                 status = fns->device_control(file, request, s, &out);  
                                 result = buffer_len = out.p - out.data;  
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;                          break;
560    
561                  default:                  default:
# Line 202  rdpdr_process_irp(STREAM s) Line 563  rdpdr_process_irp(STREAM s)
563                          break;                          break;
564          }          }
565    
566          rdpdr_send_completion(device, id, status, result, buffer, buffer_len);          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  static void
# Line 211  rdpdr_process(STREAM s) Line 617  rdpdr_process(STREAM s)
617          uint32 handle;          uint32 handle;
618          uint8 *magic;          uint8 *magic;
619    
620          printf("rdpdr_process\n");  #if WITH_DEBUG_RDP5
621            printf("--- rdpdr_process ---\n");
622          hexdump(s->p, s->end - s->p);          hexdump(s->p, s->end - s->p);
623    #endif
624          in_uint8p(s, magic, 4);          in_uint8p(s, magic, 4);
625    
626          if ((magic[0] == 'r') && (magic[1] == 'D'))          if ((magic[0] == 'r') && (magic[1] == 'D'))
# Line 226  rdpdr_process(STREAM s) Line 634  rdpdr_process(STREAM s)
634                  {                  {
635                          rdpdr_send_connect();                          rdpdr_send_connect();
636                          rdpdr_send_name();                          rdpdr_send_name();
                         rdpdr_send_available();  
637                          return;                          return;
638                  }                  }
639                  else if ((magic[2] == 'C') && (magic[3] == 'C'))                  if ((magic[2] == 'C') && (magic[3] == 'C'))
640                  {                  {
641                          /* connect from server */                          /* connect from server */
642                            rdpdr_send_clientcapabilty();
643                            rdpdr_send_available();
644                          return;                          return;
645                  }                  }
646                  else if ((magic[2] == 'r') && (magic[3] == 'd'))                  if ((magic[2] == 'r') && (magic[3] == 'd'))
647                  {                  {
648                          /* connect to a specific resource */                          /* connect to a specific resource */
649                          in_uint32(s, handle);                          in_uint32(s, handle);
650                          printf("Server connected to resource %d\n", handle);  #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;                          return;
667                  }                  }
668          }          }
# Line 246  rdpdr_process(STREAM s) Line 670  rdpdr_process(STREAM s)
670  }  }
671    
672  BOOL  BOOL
673  rdpdr_init(void)  rdpdr_init()
674  {  {
675          rdpdr_channel =          if (g_num_devices > 0)
676                  channel_register("rdpdr", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,          {
677                                   rdpdr_process);                  rdpdr_channel =
678                            channel_register("rdpdr",
679                                             CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,
680                                             rdpdr_process);
681            }
682    
683          return (rdpdr_channel != NULL);          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    }

Legend:
Removed from v.536  
changed lines
  Added in v.602

  ViewVC Help
Powered by ViewVC 1.1.26