/[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 554 by stargo, Tue Dec 9 09:57:44 2003 UTC revision 593 by n-ki, Mon Feb 2 07:06:55 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, "COM4", 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);                                  xfree(printerinfo->blob);       /* Blob is sent twice if reconnecting */
224          rdp_out_unistr(s, printer, printerlen - 2);                                  break;
225  #endif                          default:
226  #if 0                                  out_uint32(s, 0);
227          out_uint32_le(s, 0x8);  /* Device type 0x8 - disk */                  }
228          out_uint32_le(s, 0);          }
         out_uint8p(s, "Z:", 2);  
         out_uint8s(s, 6);  
         out_uint32(s, 0);  
 #endif  
229  #if 0  #if 0
230          out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */          out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */
231          out_uint32_le(s, 0);          out_uint32_le(s, 0);
# Line 121  rdpdr_send_completion(uint32 device, uin Line 253  rdpdr_send_completion(uint32 device, uin
253          out_uint32_le(s, result);          out_uint32_le(s, result);
254          out_uint8p(s, buffer, length);          out_uint8p(s, buffer, length);
255          s_mark_end(s);          s_mark_end(s);
256          hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);          /* JIF
257               hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
258          channel_send(s, rdpdr_channel);          channel_send(s, rdpdr_channel);
259  }  }
260    
261  static void  static void
262  rdpdr_process_irp(STREAM s)  rdpdr_process_irp(STREAM s)
263  {  {
264          uint32 device, file, id, major, minor;          uint32 result = 0,
265          NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;                  length = 0,
266          uint32 result = 0, length, request, bytes_in, bytes_out;                  desired_access = 0,
267          uint8 buffer[256];                  request,
268          uint32 buffer_len = 1;                  file,
269                    info_level,
270                    buffer_len,
271                    id,
272                    major,
273                    minor,
274                    device,
275                    offset,
276                    bytes_in,
277                    bytes_out,
278                    error_mode,
279                    share_mode, disposition, total_timeout, interval_timeout, flags_and_attributes = 0;
280    
281            char filename[256];
282            uint8 *buffer, *pst_buf;
283          struct stream out;          struct stream out;
284          DEVICE_FNS *fns;          DEVICE_FNS *fns;
285            BOOL rw_blocking = True;
286            NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
287    
288          in_uint32_le(s, device);          in_uint32_le(s, device);
289          in_uint32_le(s, file);          in_uint32_le(s, file);
# Line 142  rdpdr_process_irp(STREAM s) Line 291  rdpdr_process_irp(STREAM s)
291          in_uint32_le(s, major);          in_uint32_le(s, major);
292          in_uint32_le(s, minor);          in_uint32_le(s, minor);
293    
294          memset(buffer, 0, sizeof(buffer));          buffer_len = 0;
295            buffer = (uint8 *) xmalloc(1024);
296            buffer[0] = 0;
297    
298          /* FIXME: this should probably be a more dynamic mapping */          switch (g_rdpdr_device[device].device_type)
         switch (device)  
299          {          {
300                  case 0:                  case DEVICE_TYPE_SERIAL:
301    
302                          fns = &serial_fns;                          fns = &serial_fns;
303                  case 1:                          rw_blocking = False;
304                            break;
305    
306                    case DEVICE_TYPE_PARALLEL:
307    
308                            fns = &parallel_fns;
309                            rw_blocking = False;
310                            break;
311    
312                    case DEVICE_TYPE_PRINTER:
313    
314                          fns = &printer_fns;                          fns = &printer_fns;
315                            break;
316    
317                    case DEVICE_TYPE_DISK:
318    
319                            fns = &disk_fns;
320                            /*rw_blocking = False; */
321                            break;
322    
323                    case DEVICE_TYPE_SCARD:
324                  default:                  default:
325    
326                          error("IRP for bad device %ld\n", device);                          error("IRP for bad device %ld\n", device);
327                          return;                          return;
328          }          }
# Line 159  rdpdr_process_irp(STREAM s) Line 330  rdpdr_process_irp(STREAM s)
330          switch (major)          switch (major)
331          {          {
332                  case IRP_MJ_CREATE:                  case IRP_MJ_CREATE:
333                          if (fns->create)  
334                                  status = fns->create(&result);                          in_uint32_be(s, desired_access);
335                            in_uint8s(s, 0x08);     // unknown
336                            in_uint32_le(s, error_mode);
337                            in_uint32_le(s, share_mode);
338                            in_uint32_le(s, disposition);
339                            in_uint32_le(s, flags_and_attributes);
340                            in_uint32_le(s, length);
341    
342                            if (length && (length / 2) < 256)
343                            {
344                                    rdp_in_unistr(s, filename, length);
345                                    convert_to_unix_filename(filename);
346                            }
347                            else
348                            {
349                                    filename[0] = 0;
350                            }
351    
352                            if (!fns->create)
353                            {
354                                    status = STATUS_NOT_SUPPORTED;
355                                    break;
356                            }
357    
358                            status = fns->create(device, desired_access, share_mode, disposition,
359                                                 flags_and_attributes, filename, &result);
360                            buffer_len = 1;
361                          break;                          break;
362    
363                  case IRP_MJ_CLOSE:                  case IRP_MJ_CLOSE:
364                          if (fns->close)                          if (!fns->close)
365                                  status = fns->close(file);                          {
366                                    status = STATUS_NOT_SUPPORTED;
367                                    break;
368                            }
369    
370                            status = fns->close(file);
371                          break;                          break;
372    
373                  case IRP_MJ_READ:                  case IRP_MJ_READ:
374                          if (fns->read)  
375                            if (!fns->read)
376                            {
377                                    status = STATUS_NOT_SUPPORTED;
378                                    break;
379                            }
380    
381                            in_uint32_le(s, length);
382                            in_uint32_le(s, offset);
383    #if WITH_DEBUG_RDP5
384                            DEBUG(("RDPDR IRP Read (length: %d, offset: %d)\n", length, offset));
385    #endif
386                            if (rw_blocking)        // Complete read immediately
387                          {                          {
388                                  if (length > sizeof(buffer))                                  buffer = (uint8 *) xrealloc((void *) buffer, length);
389                                          length = sizeof(buffer);                                  status = fns->read(file, buffer, length, offset, &result);
                                 status = fns->read(file, buffer, length, &result);  
390                                  buffer_len = result;                                  buffer_len = result;
391                                    break;
392                            }
393    
394                            // Add request to table
395                            pst_buf = (uint8 *) xmalloc(length);
396                            serial_get_timeout(file, length, &total_timeout, &interval_timeout);
397                            if (add_async_iorequest
398                                (device, file, id, major, length, fns, total_timeout, interval_timeout,
399                                 pst_buf))
400                            {
401                                    status = STATUS_PENDING;
402                                    break;
403                          }                          }
                         break;  
404    
405                            status = STATUS_CANCELLED;
406                            break;
407                  case IRP_MJ_WRITE:                  case IRP_MJ_WRITE:
408                          if (fns->write)  
409                                  status = fns->write(file, s->p, length, &result);                          buffer_len = 1;
410    
411                            if (!fns->write)
412                            {
413                                    status = STATUS_NOT_SUPPORTED;
414                                    break;
415                            }
416    
417                            in_uint32_le(s, length);
418                            in_uint32_le(s, offset);
419                            in_uint8s(s, 0x18);
420    #if WITH_DEBUG_RDP5
421                            DEBUG(("RDPDR IRP Write (length: %d)\n", result));
422    #endif
423                            if (rw_blocking)        // Complete immediately
424                            {
425                                    status = fns->write(file, s->p, length, offset, &result);
426                                    break;
427                            }
428    
429                            // Add to table
430                            pst_buf = (uint8 *) xmalloc(length);
431                            in_uint8a(s, pst_buf, length);
432    
433                            if (add_async_iorequest
434                                (device, file, id, major, length, fns, 0, 0, pst_buf))
435                            {
436                                    status = STATUS_PENDING;
437                                    break;
438                            }
439    
440                            status = STATUS_CANCELLED;
441                            break;
442    
443                    case IRP_MJ_QUERY_INFORMATION:
444    
445                            if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
446                            {
447                                    status = STATUS_INVALID_HANDLE;
448                                    break;
449                            }
450                            in_uint32_le(s, info_level);
451    
452                            out.data = out.p = buffer;
453                            out.size = sizeof(buffer);
454                            status = disk_query_information(file, info_level, &out);
455                            result = buffer_len = out.p - out.data;
456    
457                            break;
458    
459                    case IRP_MJ_SET_INFORMATION:
460    
461                            if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
462                            {
463                                    status = STATUS_INVALID_HANDLE;
464                                    break;
465                            }
466    
467                            in_uint32_le(s, info_level);
468    
469                            out.data = out.p = buffer;
470                            out.size = sizeof(buffer);
471                            status = disk_set_information(file, info_level, s, &out);
472                            result = buffer_len = out.p - out.data;
473                            break;
474    
475                    case IRP_MJ_QUERY_VOLUME_INFORMATION:
476    
477                            if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
478                            {
479                                    status = STATUS_INVALID_HANDLE;
480                                    break;
481                            }
482    
483                            in_uint32_le(s, info_level);
484    
485                            out.data = out.p = buffer;
486                            out.size = sizeof(buffer);
487                            status = disk_query_volume_information(file, info_level, &out);
488                            result = buffer_len = out.p - out.data;
489                            break;
490    
491                    case IRP_MJ_DIRECTORY_CONTROL:
492    
493                            if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
494                            {
495                                    status = STATUS_INVALID_HANDLE;
496                                    break;
497                            }
498    
499                            switch (minor)
500                            {
501                                    case IRP_MN_QUERY_DIRECTORY:
502    
503                                            in_uint32_le(s, info_level);
504                                            in_uint8s(s, 1);
505                                            in_uint32_le(s, length);
506                                            in_uint8s(s, 0x17);
507                                            if (length && length < 2 * 255)
508                                            {
509                                                    rdp_in_unistr(s, filename, length);
510                                                    convert_to_unix_filename(filename);
511                                            }
512                                            else
513                                            {
514                                                    filename[0] = 0;
515                                            }
516                                            out.data = out.p = buffer;
517                                            out.size = sizeof(buffer);
518                                            status = disk_query_directory(file, info_level, filename,
519                                                                          &out);
520                                            result = buffer_len = out.p - out.data;
521                                            if (!buffer_len)
522                                                    buffer_len++;
523                                            break;
524    
525                                    case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
526    
527                                            /* JIF
528                                               unimpl("IRP major=0x%x minor=0x%x: IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", major, minor); */
529                                            status = STATUS_PENDING;        // Don't send completion packet
530                                            break;
531    
532                                    default:
533    
534                                            status = STATUS_INVALID_PARAMETER;
535                                            /* JIF
536                                               unimpl("IRP major=0x%x minor=0x%x\n", major, minor); */
537                            }
538                          break;                          break;
539    
540                  case IRP_MJ_DEVICE_CONTROL:                  case IRP_MJ_DEVICE_CONTROL:
541                          if (fns->device_control)  
542                            if (!fns->device_control)
543                          {                          {
544                                  in_uint32_le(s, bytes_out);                                  status = STATUS_NOT_SUPPORTED;
545                                  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;  
546                          }                          }
547    
548                            in_uint32_le(s, bytes_out);
549                            in_uint32_le(s, bytes_in);
550                            in_uint32_le(s, request);
551                            in_uint8s(s, 0x14);
552    
553                            buffer = (uint8 *) xrealloc((void *) buffer, bytes_out + 0x14);
554                            out.data = out.p = buffer;
555                            out.size = sizeof(buffer);
556                            status = fns->device_control(file, request, s, &out);
557                            result = buffer_len = out.p - out.data;
558                          break;                          break;
559    
560                  default:                  default:
# Line 202  rdpdr_process_irp(STREAM s) Line 562  rdpdr_process_irp(STREAM s)
562                          break;                          break;
563          }          }
564    
565          rdpdr_send_completion(device, id, status, result, buffer, buffer_len);          if (status != STATUS_PENDING)
566            {
567                    rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
568            }
569            xfree(buffer);
570    
571    }
572    
573    void
574    rdpdr_send_clientcapabilty(void)
575    {
576            uint8 magic[4] = "rDPC";
577            STREAM s;
578    
579            s = channel_init(rdpdr_channel, 0x50);
580            out_uint8a(s, magic, 4);
581            out_uint32_le(s, 5);    /* count */
582            out_uint16_le(s, 1);    /* first */
583            out_uint16_le(s, 0x28); /* length */
584            out_uint32_le(s, 1);
585            out_uint32_le(s, 2);
586            out_uint16_le(s, 2);
587            out_uint16_le(s, 5);
588            out_uint16_le(s, 1);
589            out_uint16_le(s, 5);
590            out_uint16_le(s, 0xFFFF);
591            out_uint16_le(s, 0);
592            out_uint32_le(s, 0);
593            out_uint32_le(s, 3);
594            out_uint32_le(s, 0);
595            out_uint32_le(s, 0);
596            out_uint16_le(s, 2);    /* second */
597            out_uint16_le(s, 8);    /* length */
598            out_uint32_le(s, 1);
599            out_uint16_le(s, 3);    /* third */
600            out_uint16_le(s, 8);    /* length */
601            out_uint32_le(s, 1);
602            out_uint16_le(s, 4);    /* fourth */
603            out_uint16_le(s, 8);    /* length */
604            out_uint32_le(s, 1);
605            out_uint16_le(s, 5);    /* fifth */
606            out_uint16_le(s, 8);    /* length */
607            out_uint32_le(s, 1);
608    
609            s_mark_end(s);
610            channel_send(s, rdpdr_channel);
611  }  }
612    
613  static void  static void
# Line 211  rdpdr_process(STREAM s) Line 616  rdpdr_process(STREAM s)
616          uint32 handle;          uint32 handle;
617          uint8 *magic;          uint8 *magic;
618    
619          printf("rdpdr_process\n");  #if WITH_DEBUG_RDP5
620            printf("--- rdpdr_process ---\n");
621          hexdump(s->p, s->end - s->p);          hexdump(s->p, s->end - s->p);
622    #endif
623          in_uint8p(s, magic, 4);          in_uint8p(s, magic, 4);
624    
625          if ((magic[0] == 'r') && (magic[1] == 'D'))          if ((magic[0] == 'r') && (magic[1] == 'D'))
# Line 226  rdpdr_process(STREAM s) Line 633  rdpdr_process(STREAM s)
633                  {                  {
634                          rdpdr_send_connect();                          rdpdr_send_connect();
635                          rdpdr_send_name();                          rdpdr_send_name();
                         rdpdr_send_available();  
636                          return;                          return;
637                  }                  }
638                  else if ((magic[2] == 'C') && (magic[3] == 'C'))                  if ((magic[2] == 'C') && (magic[3] == 'C'))
639                  {                  {
640                          /* connect from server */                          /* connect from server */
641                            rdpdr_send_clientcapabilty();
642                            rdpdr_send_available();
643                          return;                          return;
644                  }                  }
645                  else if ((magic[2] == 'r') && (magic[3] == 'd'))                  if ((magic[2] == 'r') && (magic[3] == 'd'))
646                  {                  {
647                          /* connect to a specific resource */                          /* connect to a specific resource */
648                          in_uint32(s, handle);                          in_uint32(s, handle);
649                          printf("Server connected to resource %d\n", handle);  #if WITH_DEBUG_RDP5
650                            DEBUG(("RDPDR: Server connected to resource %d\n", handle));
651    #endif
652                            return;
653                    }
654                    if ((magic[2] == 'P') && (magic[3] == 'S'))
655                    {
656                            /* server capability */
657                            return;
658                    }
659            }
660            if ((magic[0] == 'R') && (magic[1] == 'P'))
661            {
662                    if ((magic[2] == 'C') && (magic[3] == 'P'))
663                    {
664                            printercache_process(s);
665                          return;                          return;
666                  }                  }
667          }          }
# Line 246  rdpdr_process(STREAM s) Line 669  rdpdr_process(STREAM s)
669  }  }
670    
671  BOOL  BOOL
672  rdpdr_init(void)  rdpdr_init()
673  {  {
674          rdpdr_channel =          if (g_num_devices > 0)
675                  channel_register("rdpdr", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,          {
676                                   rdpdr_process);                  rdpdr_channel =
677                            channel_register("rdpdr",
678                                             CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,
679                                             rdpdr_process);
680            }
681    
682          return (rdpdr_channel != NULL);          return (rdpdr_channel != NULL);
683  }  }
684    
685    /* Add file descriptors of pending io request to select() */
686    void
687    rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * timeout)
688    {
689            long select_timeout = 0;        // Timeout value to be used for select() (in millisecons).
690            struct async_iorequest *iorq;
691    
692            iorq = g_iorequest;
693            while (iorq != NULL)
694            {
695                    if (iorq->fd != 0)
696                    {
697                            switch (iorq->major)
698                            {
699                                    case IRP_MJ_READ:
700    
701                                            FD_SET(iorq->fd, rfds);
702    
703                                            // Check if io request timeout is smaller than current (but not 0).
704                                            if (iorq->timeout
705                                                && (select_timeout == 0
706                                                    || iorq->timeout < select_timeout))
707                                            {
708                                                    // Set new timeout
709                                                    select_timeout = iorq->timeout;
710                                                    g_min_timeout_fd = iorq->fd;    /* Remember fd */
711                                                    tv->tv_sec = select_timeout / 1000;
712                                                    tv->tv_usec = (select_timeout % 1000) * 1000;
713                                                    *timeout = True;
714                                            }
715                                            break;
716    
717                                    case IRP_MJ_WRITE:
718                                            FD_SET(iorq->fd, wfds);
719                                            break;
720    
721                            }
722                            *n = MAX(*n, iorq->fd);
723                    }
724    
725                    iorq = iorq->next;
726            }
727    }
728    
729    
730    /* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */
731    void
732    rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out)
733    {
734            NTSTATUS status;
735            uint32 result = 0;
736            DEVICE_FNS *fns;
737            struct async_iorequest *iorq;
738            struct async_iorequest *prev;
739    
740            if (timed_out)
741            {
742                    rdpdr_abort_io(g_min_timeout_fd, 0, STATUS_TIMEOUT);
743                    return;
744            }
745    
746            iorq = g_iorequest;
747            prev = NULL;
748            while (iorq != NULL)
749            {
750    
751                    if (iorq->fd != 0)
752                    {
753                            switch (iorq->major)
754                            {
755                                    case IRP_MJ_READ:
756                                            if (FD_ISSET(iorq->fd, rfds))
757                                            {
758                                                    /* Read the data */
759                                                    fns = iorq->fns;
760    
761                                                    /* never read larger chunks than 8k - chances are that it will block */
762                                                    status = fns->read(iorq->fd,
763                                                                       iorq->buffer + iorq->partial_len,
764                                                                       (iorq->length -
765                                                                        iorq->partial_len) >
766                                                                       8192 ? 8192 : (iorq->length -
767                                                                                      iorq->
768                                                                                      partial_len), 0,
769                                                                       &result);
770                                                    iorq->partial_len += result;
771    #if WITH_DEBUG_RDP5
772                                                    DEBUG(("RDPDR: %d bytes of data read\n", result));
773    #endif
774                                                    /* only delete link if all data has been transfered */
775                                                    if (iorq->partial_len == iorq->length)
776                                                    {
777                                                            /* send the data */
778                                                            status = STATUS_SUCCESS;
779                                                            rdpdr_send_completion(iorq->device,
780                                                                                  iorq->id, status,
781                                                                                  iorq->length,
782                                                                                  iorq->buffer, result);
783    
784                                                            xfree(iorq->buffer);
785                                                            iorq->fd = 0;
786                                                            if (prev != NULL)
787                                                            {
788                                                                    prev->next = iorq->next;
789                                                                    xfree(iorq);
790                                                            }
791                                                            else
792                                                            {
793                                                                    // Even if NULL
794                                                                    g_iorequest = iorq->next;
795                                                                    xfree(iorq);
796                                                            }
797                                                    }
798                                            }
799                                            break;
800                                    case IRP_MJ_WRITE:
801                                            if (FD_ISSET(iorq->fd, wfds))
802                                            {
803                                                    /* Write data. */
804                                                    fns = iorq->fns;
805    
806                                                    /* never write larger chunks than 8k - chances are that it will block */
807                                                    status = fns->write(iorq->fd,
808                                                                        iorq->buffer +
809                                                                        iorq->partial_len,
810                                                                        (iorq->length -
811                                                                         iorq->partial_len) >
812                                                                        8192 ? 8192 : (iorq->length -
813                                                                                       iorq->
814                                                                                       partial_len), 0,
815                                                                        &result);
816                                                    iorq->partial_len += result;
817    #if WITH_DEBUG_RDP5
818                                                    DEBUG(("RDPDR: %d bytes of data written\n",
819                                                           result));
820    #endif
821                                                    /* only delete link if all data has been transfered */
822                                                    if (iorq->partial_len == iorq->length)
823                                                    {
824                                                            /* send a status success */
825                                                            status = STATUS_SUCCESS;
826                                                            rdpdr_send_completion(iorq->device,
827                                                                                  iorq->id, status,
828                                                                                  iorq->length, "", 1);
829    
830                                                            xfree(iorq->buffer);
831                                                            iorq->fd = 0;
832                                                            if (prev != NULL)
833                                                            {
834                                                                    prev->next = iorq->next;
835                                                                    xfree(iorq);
836                                                            }
837                                                            else
838                                                            {
839                                                                    // Even if NULL
840                                                                    g_iorequest = iorq->next;
841                                                                    xfree(iorq);
842                                                            }
843                                                    }
844                                            }
845                                            break;
846                            }
847    
848                    }
849                    prev = iorq;
850                    iorq = iorq->next;
851            }
852    
853    }
854    
855    /* Abort a pending io request for a given handle and major */
856    BOOL
857    rdpdr_abort_io(uint32 fd, uint32 major, NTSTATUS status)
858    {
859            uint32 result;
860            struct async_iorequest *iorq;
861            struct async_iorequest *prev;
862    
863            iorq = &g_iorequest;
864            prev = NULL;
865            while (iorq != NULL)
866            {
867                    // Only remove from table when major is not set, or when correct major is supplied.
868                    // Abort read should not abort a write io request.
869                    if ((iorq->fd == fd) && (major == 0 || iorq->major == major))
870                    {
871                            result = 0;
872                            rdpdr_send_completion(iorq->device, iorq->id, status, result, "", 1);
873                            xfree(iorq->buffer);
874                            iorq->fd = 0;
875                            if (prev != NULL)
876                            {
877                                    prev->next = iorq->next;
878                                    xfree(iorq);
879                            }
880                            else
881                            {
882                                    // Even if NULL
883                                    g_iorequest = iorq->next;
884                                    xfree(iorq);
885                            }
886                            return True;
887                    }
888    
889                    prev = iorq;
890                    iorq = iorq->next;
891            }
892    
893            return False;
894    }

Legend:
Removed from v.554  
changed lines
  Added in v.593

  ViewVC Help
Powered by ViewVC 1.1.26