/[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 432 by matthewc, Tue Jul 1 09:31:25 2003 UTC revision 609 by stargo, Mon Feb 16 20:28:09 2004 UTC
# Line 1  Line 1 
1    #include <unistd.h>
2    #include <sys/types.h>
3    #include <sys/time.h>
4    #include <time.h>
5  #include "rdesktop.h"  #include "rdesktop.h"
6    
7  #define IRP_MJ_CREATE           0x00  #define IRP_MJ_CREATE           0x00
# Line 6  Line 10 
10  #define IRP_MJ_WRITE            0x04  #define IRP_MJ_WRITE            0x04
11  #define IRP_MJ_DEVICE_CONTROL   0x0e  #define IRP_MJ_DEVICE_CONTROL   0x0e
12    
13    #define IRP_MJ_CREATE                   0x00
14    #define IRP_MJ_CLOSE                    0x02
15    #define IRP_MJ_READ                     0x03
16    #define IRP_MJ_WRITE                    0x04
17    #define IRP_MJ_QUERY_INFORMATION        0x05
18    #define IRP_MJ_SET_INFORMATION          0x06
19    #define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
20    #define IRP_MJ_DIRECTORY_CONTROL        0x0c
21    #define IRP_MJ_DEVICE_CONTROL           0x0e
22    
23    #define IRP_MN_QUERY_DIRECTORY          0x01
24    #define IRP_MN_NOTIFY_CHANGE_DIRECTORY  0x02
25    
26  extern char hostname[16];  extern char hostname[16];
27  extern DEVICE_FNS serial_fns;  extern DEVICE_FNS serial_fns;
28  extern DEVICE_FNS printer_fns;  extern DEVICE_FNS printer_fns;
29    extern DEVICE_FNS parallel_fns;
30    extern DEVICE_FNS disk_fns;
31    
32  static VCHANNEL *rdpdr_channel;  static VCHANNEL *rdpdr_channel;
33    
34    /* If select() times out, the request for the device with handle g_min_timeout_fd is aborted */
35    HANDLE g_min_timeout_fd;
36    uint32 g_num_devices;
37    
38    /* Table with information about rdpdr devices */
39    RDPDR_DEVICE g_rdpdr_device[RDPDR_MAX_DEVICES];
40    
41    /* Used to store incoming io request, until they are ready to be completed */
42    /* using a linked list ensures that they are processed in the right order, */
43    /* if multiple ios are being done on the same fd */
44    struct async_iorequest
45    {
46            uint32 fd, major, minor, offset, device, id, length, partial_len;
47            long timeout,           /* Total timeout */
48              itv_timeout;          /* Interval timeout (between serial characters) */
49            uint8 *buffer;
50            DEVICE_FNS *fns;
51    
52            struct async_iorequest *next;   /* next element in list */
53    };
54    
55    struct async_iorequest *g_iorequest;
56    
57    /* Return device_id for a given handle */
58    int
59    get_device_index(HANDLE handle)
60    {
61            int i;
62            for (i = 0; i < RDPDR_MAX_DEVICES; i++)
63            {
64                    if (g_rdpdr_device[i].handle == handle)
65                            return i;
66            }
67            return -1;
68    }
69    
70    /* Converts a windows path to a unix path */
71    void
72    convert_to_unix_filename(char *filename)
73    {
74            char *p;
75    
76            while ((p = strchr(filename, '\\')))
77            {
78                    *p = '/';
79            }
80    }
81    
82    /* Add a new io request to the table containing pending io requests so it won't block rdesktop */
83    BOOL
84    add_async_iorequest(uint32 device, uint32 file, uint32 id, uint32 major, uint32 length,
85                        DEVICE_FNS * fns, uint32 total_timeout, uint32 interval_timeout, uint8 * buffer)
86    {
87            struct async_iorequest *iorq;
88    
89            if (g_iorequest == NULL)
90            {
91                    g_iorequest = (struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
92                    g_iorequest->fd = 0;
93                    g_iorequest->next = NULL;
94            }
95    
96            iorq = g_iorequest;
97    
98            while (iorq->fd != 0)
99            {
100                    // create new element if needed
101                    if (iorq->next == NULL)
102                    {
103                            iorq->next =
104                                    (struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
105                            iorq->next->fd = 0;
106                            iorq->next->next = NULL;
107                    }
108                    iorq = iorq->next;
109            }
110            iorq->device = device;
111            iorq->fd = file;
112            iorq->id = id;
113            iorq->major = major;
114            iorq->length = length;
115            iorq->partial_len = 0;
116            iorq->fns = fns;
117            iorq->timeout = total_timeout;
118            iorq->itv_timeout = interval_timeout;
119            iorq->buffer = buffer;
120            return True;
121    }
122    
123  void  void
124  rdpdr_send_connect(void)  rdpdr_send_connect(void)
125  {  {
# Line 20  rdpdr_send_connect(void) Line 128  rdpdr_send_connect(void)
128    
129          s = channel_init(rdpdr_channel, 12);          s = channel_init(rdpdr_channel, 12);
130          out_uint8a(s, magic, 4);          out_uint8a(s, magic, 4);
131          out_uint16_le(s, 1); /* unknown */          out_uint16_le(s, 1);    /* unknown */
132          out_uint16_le(s, 5);          out_uint16_le(s, 5);
133          out_uint32_be(s, 0x815ed39d); /* IP address (use 127.0.0.1) 0x815ed39d */          out_uint32_be(s, 0x815ed39d);   /* IP address (use 127.0.0.1) 0x815ed39d */
134          s_mark_end(s);          s_mark_end(s);
135          channel_send(s, rdpdr_channel);          channel_send(s, rdpdr_channel);
136  }  }
137    
138    
139  void  void
140  rdpdr_send_name(void)  rdpdr_send_name(void)
141  {  {
142          uint8 magic[4] = "rDNC";          uint8 magic[4] = "rDNC";
143          uint32 hostlen = (strlen(hostname)+1)*2;          uint32 hostlen = (strlen(hostname) + 1) * 2;
144          STREAM s;          STREAM s;
145    
146          s = channel_init(rdpdr_channel, 16+hostlen);          s = channel_init(rdpdr_channel, 16 + hostlen);
147          out_uint8a(s, magic, 4);          out_uint8a(s, magic, 4);
148          out_uint16_le(s, 0x63); /* unknown */          out_uint16_le(s, 0x63); /* unknown */
149          out_uint16_le(s, 0x72);          out_uint16_le(s, 0x72);
150          out_uint32(s, 0);          out_uint32(s, 0);
151          out_uint32_le(s, hostlen);          out_uint32_le(s, hostlen);
152          rdp_out_unistr(s, hostname, hostlen-2);          rdp_out_unistr(s, hostname, hostlen - 2);
153          s_mark_end(s);          s_mark_end(s);
154          channel_send(s, rdpdr_channel);          channel_send(s, rdpdr_channel);
155  }  }
156    
157    /* Returns the size of the payload of the announce packet */
158    int
159    announcedata_size()
160    {
161            int size, i;
162            PRINTER *printerinfo;
163    
164            size = 8;               //static announce size
165            size += g_num_devices * 0x14;
166    
167            for (i = 0; i < g_num_devices; i++)
168            {
169                    if (g_rdpdr_device[i].device_type == DEVICE_TYPE_PRINTER)
170                    {
171                            printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
172                            printerinfo->bloblen =
173                                    printercache_load_blob(printerinfo->printer, &(printerinfo->blob));
174    
175                            size += 0x18;
176                            size += 2 * strlen(printerinfo->driver) + 2;
177                            size += 2 * strlen(printerinfo->printer) + 2;
178                            size += printerinfo->bloblen;
179                    }
180            }
181    
182            return size;
183    }
184    
185  void  void
186  rdpdr_send_available(void)  rdpdr_send_available(void)
187  {  {
188    
189          uint8 magic[4] = "rDAD";          uint8 magic[4] = "rDAD";
190          char *driver = "Digital turbo PrintServer 20"; /* Fairly generic PostScript driver */          uint32 driverlen, printerlen, bloblen;
191          char *printer = "PostScript";          int i;
         uint32 driverlen = (strlen(driver)+1)*2;  
         uint32 printerlen = (strlen(printer)+1)*2;  
192          STREAM s;          STREAM s;
193            PRINTER *printerinfo;
194    
195          s = channel_init(rdpdr_channel, 8+20);          s = channel_init(rdpdr_channel, announcedata_size());
196          out_uint8a(s, magic, 4);          out_uint8a(s, magic, 4);
197          out_uint32_le(s, 1); /* Number of devices */          out_uint32_le(s, g_num_devices);
198    
199  #if 1          for (i = 0; i < g_num_devices; i++)
200          out_uint32_le(s, 0x1);  /* Device type 0x1 - serial */          {
201          out_uint32_le(s, 0);    /* Handle */                  out_uint32_le(s, g_rdpdr_device[i].device_type);
202          out_uint8p(s, "COM2", 4);                  out_uint32_le(s, i);    /* RDP Device ID */
203          out_uint8s(s, 4);       /* Pad to 8 */                  out_uint8p(s, g_rdpdr_device[i].name, 8);
204          out_uint32(s, 0);  
205  #endif                  switch (g_rdpdr_device[i].device_type)
206  #if 0                  {
207          out_uint32_le(s, 0x2); /* Device type 0x2 - parallel */                          case DEVICE_TYPE_PRINTER:
208          out_uint32_le(s, 0);                                  printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
209          out_uint8p(s, "LPT2", 4);  
210          out_uint8s(s, 4);                                  driverlen = 2 * strlen(printerinfo->driver) + 2;
211          out_uint32(s, 0);                                  printerlen = 2 * strlen(printerinfo->printer) + 2;
212  #endif                                  bloblen = printerinfo->bloblen;
213  #if 1  
214          out_uint32_le(s, 0x4); /* Device type 0x4 - printer */                                  out_uint32_le(s, 24 + driverlen + printerlen + bloblen);        /* length of extra info */
215          out_uint32_le(s, 1);                                  out_uint32_le(s, printerinfo->default_printer ? 2 : 0);
216          out_uint8p(s, "PRN1", 4);                                  out_uint8s(s, 8);       /* unknown */
217          out_uint8s(s, 4);                                  out_uint32_le(s, driverlen);
218          out_uint32_le(s, 24+driverlen+printerlen); /* length of extra info */                                  out_uint32_le(s, printerlen);
219          out_uint32_le(s, 2); /* unknown */                                  out_uint32_le(s, bloblen);
220          out_uint8s(s, 8); /* unknown */                                  rdp_out_unistr(s, printerinfo->driver, driverlen - 2);
221          out_uint32_le(s, driverlen); /* length of driver name */                                  rdp_out_unistr(s, printerinfo->printer, printerlen - 2);
222          out_uint32_le(s, printerlen); /* length of printer name */                                  out_uint8a(s, printerinfo->blob, bloblen);
223          out_uint32(s, 0); /* unknown */  
224          rdp_out_unistr(s, driver, driverlen-2);                                  if (printerinfo->blob)
225          rdp_out_unistr(s, printer, printerlen-2);                                          xfree(printerinfo->blob);       /* Blob is sent twice if reconnecting */
226  #endif                                  break;
227  #if 0                          default:
228          out_uint32_le(s, 0x8); /* Device type 0x8 - disk */                                  out_uint32(s, 0);
229          out_uint32_le(s, 0);                  }
230          out_uint8p(s, "Z:", 2);          }
         out_uint8s(s, 6);  
         out_uint32(s, 0);  
 #endif  
231  #if 0  #if 0
232          out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */          out_uint32_le(s, 0x20); /* Device type 0x20 - smart card */
233          out_uint32_le(s, 0);          out_uint32_le(s, 0);
234          out_uint8p(s, "SCARD", 5);          out_uint8p(s, "SCARD", 5);
235          out_uint8s(s, 3);          out_uint8s(s, 3);
# Line 107  rdpdr_send_available(void) Line 241  rdpdr_send_available(void)
241  }  }
242    
243  void  void
244  rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 *buffer, uint32 length)  rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
245                          uint32 length)
246  {  {
247          uint8 magic[4] = "rDCI";          uint8 magic[4] = "rDCI";
248          STREAM s;          STREAM s;
# Line 120  rdpdr_send_completion(uint32 device, uin Line 255  rdpdr_send_completion(uint32 device, uin
255          out_uint32_le(s, result);          out_uint32_le(s, result);
256          out_uint8p(s, buffer, length);          out_uint8p(s, buffer, length);
257          s_mark_end(s);          s_mark_end(s);
258          hexdump(s->channel_hdr+8, s->end-s->channel_hdr-8);          /* JIF
259               hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
260          channel_send(s, rdpdr_channel);          channel_send(s, rdpdr_channel);
261  }  }
262    
263  static void  static void
264  rdpdr_process_irp(STREAM s)  rdpdr_process_irp(STREAM s)
265  {  {
266          uint32 device, file, id, major, minor;          uint32 result = 0,
267          NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;                  length = 0,
268          uint32 result = 0, length, request, bytes_in, bytes_out;                  desired_access = 0,
269          uint8 buffer[256];                  request,
270          uint32 buffer_len = 1;                  file,
271                    info_level,
272                    buffer_len,
273                    id,
274                    major,
275                    minor,
276                    device,
277                    offset,
278                    bytes_in,
279                    bytes_out,
280                    error_mode,
281                    share_mode, disposition, total_timeout, interval_timeout, flags_and_attributes = 0;
282    
283            char filename[256];
284            uint8 *buffer, *pst_buf;
285          struct stream out;          struct stream out;
286          DEVICE_FNS *fns;          DEVICE_FNS *fns;
287            BOOL rw_blocking = True;
288            NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
289    
290          in_uint32_le(s, device);          in_uint32_le(s, device);
291          in_uint32_le(s, file);          in_uint32_le(s, file);
# Line 141  rdpdr_process_irp(STREAM s) Line 293  rdpdr_process_irp(STREAM s)
293          in_uint32_le(s, major);          in_uint32_le(s, major);
294          in_uint32_le(s, minor);          in_uint32_le(s, minor);
295    
296          memset(buffer, 0, sizeof(buffer));          buffer_len = 0;
297            buffer = (uint8 *) xmalloc(1024);
298            buffer[0] = 0;
299    
300          /* FIXME: this should probably be a more dynamic mapping */          switch (g_rdpdr_device[device].device_type)
         switch (device)  
301          {          {
302                  case 0:                  case DEVICE_TYPE_SERIAL:
303    
304                          fns = &serial_fns;                          fns = &serial_fns;
305                  case 1:                          rw_blocking = False;
306                            break;
307    
308                    case DEVICE_TYPE_PARALLEL:
309    
310                            fns = &parallel_fns;
311                            rw_blocking = False;
312                            break;
313    
314                    case DEVICE_TYPE_PRINTER:
315    
316                          fns = &printer_fns;                          fns = &printer_fns;
317                            break;
318    
319                    case DEVICE_TYPE_DISK:
320    
321                            fns = &disk_fns;
322                            rw_blocking = False;
323                            break;
324    
325                    case DEVICE_TYPE_SCARD:
326                  default:                  default:
327    
328                          error("IRP for bad device %ld\n", device);                          error("IRP for bad device %ld\n", device);
329                          return;                          return;
330          }          }
# Line 158  rdpdr_process_irp(STREAM s) Line 332  rdpdr_process_irp(STREAM s)
332          switch (major)          switch (major)
333          {          {
334                  case IRP_MJ_CREATE:                  case IRP_MJ_CREATE:
335                          if (fns->create)  
336                                  status = fns->create(&result);                          in_uint32_be(s, desired_access);
337                            in_uint8s(s, 0x08);     // unknown
338                            in_uint32_le(s, error_mode);
339                            in_uint32_le(s, share_mode);
340                            in_uint32_le(s, disposition);
341                            in_uint32_le(s, flags_and_attributes);
342                            in_uint32_le(s, length);
343    
344                            if (length && (length / 2) < 256)
345                            {
346                                    rdp_in_unistr(s, filename, length);
347                                    convert_to_unix_filename(filename);
348                            }
349                            else
350                            {
351                                    filename[0] = 0;
352                            }
353    
354                            if (!fns->create)
355                            {
356                                    status = STATUS_NOT_SUPPORTED;
357                                    break;
358                            }
359    
360                            status = fns->create(device, desired_access, share_mode, disposition,
361                                                 flags_and_attributes, filename, &result);
362                            buffer_len = 1;
363                          break;                          break;
364    
365                  case IRP_MJ_CLOSE:                  case IRP_MJ_CLOSE:
366                          if (fns->close)                          if (!fns->close)
367                                  status = fns->close(file);                          {
368                                    status = STATUS_NOT_SUPPORTED;
369                                    break;
370                            }
371    
372                            status = fns->close(file);
373                          break;                          break;
374    
375                  case IRP_MJ_READ:                  case IRP_MJ_READ:
376                          if (fns->read)  
377                            if (!fns->read)
378                            {
379                                    status = STATUS_NOT_SUPPORTED;
380                                    break;
381                            }
382    
383                            in_uint32_le(s, length);
384                            in_uint32_le(s, offset);
385    #if WITH_DEBUG_RDP5
386                            DEBUG(("RDPDR IRP Read (length: %d, offset: %d)\n", length, offset));
387    #endif
388                            if (rw_blocking)        // Complete read immediately
389                          {                          {
390                                  if (length > sizeof(buffer))                                  buffer = (uint8 *) xrealloc((void *) buffer, length);
391                                          length = sizeof(buffer);                                  status = fns->read(file, buffer, length, offset, &result);
                                 status = fns->read(file, buffer, length, &result);  
392                                  buffer_len = result;                                  buffer_len = result;
393                                    break;
394                          }                          }
                         break;  
395    
396                            // Add request to table
397                            pst_buf = (uint8 *) xmalloc(length);
398                            serial_get_timeout(file, length, &total_timeout, &interval_timeout);
399                            if (add_async_iorequest
400                                (device, file, id, major, length, fns, total_timeout, interval_timeout,
401                                 pst_buf))
402                            {
403                                    status = STATUS_PENDING;
404                                    break;
405                            }
406    
407                            status = STATUS_CANCELLED;
408                            break;
409                  case IRP_MJ_WRITE:                  case IRP_MJ_WRITE:
410                          if (fns->write)  
411                                  status = fns->write(file, s->p, length, &result);                          buffer_len = 1;
412    
413                            if (!fns->write)
414                            {
415                                    status = STATUS_NOT_SUPPORTED;
416                                    break;
417                            }
418    
419                            in_uint32_le(s, length);
420                            in_uint32_le(s, offset);
421                            in_uint8s(s, 0x18);
422    #if WITH_DEBUG_RDP5
423                            DEBUG(("RDPDR IRP Write (length: %d)\n", result));
424    #endif
425                            if (rw_blocking)        // Complete immediately
426                            {
427                                    status = fns->write(file, s->p, length, offset, &result);
428                                    break;
429                            }
430    
431                            // Add to table
432                            pst_buf = (uint8 *) xmalloc(length);
433                            in_uint8a(s, pst_buf, length);
434    
435                            if (add_async_iorequest
436                                (device, file, id, major, length, fns, 0, 0, pst_buf))
437                            {
438                                    status = STATUS_PENDING;
439                                    break;
440                            }
441    
442                            status = STATUS_CANCELLED;
443                            break;
444    
445                    case IRP_MJ_QUERY_INFORMATION:
446    
447                            if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
448                            {
449                                    status = STATUS_INVALID_HANDLE;
450                                    break;
451                            }
452                            in_uint32_le(s, info_level);
453    
454                            out.data = out.p = buffer;
455                            out.size = sizeof(buffer);
456                            status = disk_query_information(file, info_level, &out);
457                            result = buffer_len = out.p - out.data;
458    
459                            break;
460    
461                    case IRP_MJ_SET_INFORMATION:
462    
463                            if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
464                            {
465                                    status = STATUS_INVALID_HANDLE;
466                                    break;
467                            }
468    
469                            in_uint32_le(s, info_level);
470    
471                            out.data = out.p = buffer;
472                            out.size = sizeof(buffer);
473                            status = disk_set_information(file, info_level, s, &out);
474                            result = buffer_len = out.p - out.data;
475                            break;
476    
477                    case IRP_MJ_QUERY_VOLUME_INFORMATION:
478    
479                            if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
480                            {
481                                    status = STATUS_INVALID_HANDLE;
482                                    break;
483                            }
484    
485                            in_uint32_le(s, info_level);
486    
487                            out.data = out.p = buffer;
488                            out.size = sizeof(buffer);
489                            status = disk_query_volume_information(file, info_level, &out);
490                            result = buffer_len = out.p - out.data;
491                            break;
492    
493                    case IRP_MJ_DIRECTORY_CONTROL:
494    
495                            if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
496                            {
497                                    status = STATUS_INVALID_HANDLE;
498                                    break;
499                            }
500    
501                            switch (minor)
502                            {
503                                    case IRP_MN_QUERY_DIRECTORY:
504    
505                                            in_uint32_le(s, info_level);
506                                            in_uint8s(s, 1);
507                                            in_uint32_le(s, length);
508                                            in_uint8s(s, 0x17);
509                                            if (length && length < 2 * 255)
510                                            {
511                                                    rdp_in_unistr(s, filename, length);
512                                                    convert_to_unix_filename(filename);
513                                            }
514                                            else
515                                            {
516                                                    filename[0] = 0;
517                                            }
518                                            out.data = out.p = buffer;
519                                            out.size = sizeof(buffer);
520                                            status = disk_query_directory(file, info_level, filename,
521                                                                          &out);
522                                            result = buffer_len = out.p - out.data;
523                                            if (!buffer_len)
524                                                    buffer_len++;
525                                            break;
526    
527                                    case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
528    
529                                            /* JIF
530                                               unimpl("IRP major=0x%x minor=0x%x: IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", major, minor); */
531                                            status = STATUS_PENDING;        // Don't send completion packet
532                                            break;
533    
534                                    default:
535    
536                                            status = STATUS_INVALID_PARAMETER;
537                                            /* JIF
538                                               unimpl("IRP major=0x%x minor=0x%x\n", major, minor); */
539                            }
540                          break;                          break;
541    
542                  case IRP_MJ_DEVICE_CONTROL:                  case IRP_MJ_DEVICE_CONTROL:
543                          if (fns->device_control)  
544                            if (!fns->device_control)
545                          {                          {
546                                  in_uint32_le(s, bytes_out);                                  status = STATUS_NOT_SUPPORTED;
547                                  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;  
548                          }                          }
549    
550                            in_uint32_le(s, bytes_out);
551                            in_uint32_le(s, bytes_in);
552                            in_uint32_le(s, request);
553                            in_uint8s(s, 0x14);
554    
555                            buffer = (uint8 *) xrealloc((void *) buffer, bytes_out + 0x14);
556                            out.data = out.p = buffer;
557                            out.size = sizeof(buffer);
558                            status = fns->device_control(file, request, s, &out);
559                            result = buffer_len = out.p - out.data;
560                          break;                          break;
561    
562                  default:                  default:
# Line 201  rdpdr_process_irp(STREAM s) Line 564  rdpdr_process_irp(STREAM s)
564                          break;                          break;
565          }          }
566    
567          rdpdr_send_completion(device, id, status, result, buffer, buffer_len);          if (status != STATUS_PENDING)
568            {
569                    rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
570            }
571            xfree(buffer);
572    
573    }
574    
575    void
576    rdpdr_send_clientcapabilty(void)
577    {
578            uint8 magic[4] = "rDPC";
579            STREAM s;
580    
581            s = channel_init(rdpdr_channel, 0x50);
582            out_uint8a(s, magic, 4);
583            out_uint32_le(s, 5);    /* count */
584            out_uint16_le(s, 1);    /* first */
585            out_uint16_le(s, 0x28); /* length */
586            out_uint32_le(s, 1);
587            out_uint32_le(s, 2);
588            out_uint16_le(s, 2);
589            out_uint16_le(s, 5);
590            out_uint16_le(s, 1);
591            out_uint16_le(s, 5);
592            out_uint16_le(s, 0xFFFF);
593            out_uint16_le(s, 0);
594            out_uint32_le(s, 0);
595            out_uint32_le(s, 3);
596            out_uint32_le(s, 0);
597            out_uint32_le(s, 0);
598            out_uint16_le(s, 2);    /* second */
599            out_uint16_le(s, 8);    /* length */
600            out_uint32_le(s, 1);
601            out_uint16_le(s, 3);    /* third */
602            out_uint16_le(s, 8);    /* length */
603            out_uint32_le(s, 1);
604            out_uint16_le(s, 4);    /* fourth */
605            out_uint16_le(s, 8);    /* length */
606            out_uint32_le(s, 1);
607            out_uint16_le(s, 5);    /* fifth */
608            out_uint16_le(s, 8);    /* length */
609            out_uint32_le(s, 1);
610    
611            s_mark_end(s);
612            channel_send(s, rdpdr_channel);
613  }  }
614    
615  static void  static void
616  rdpdr_process(STREAM s)  rdpdr_process(STREAM s)
617  {  {
618          uint32 handle;          uint32 handle;
619          char *magic;          uint8 *magic;
620    
621          printf("rdpdr_process\n");  #if WITH_DEBUG_RDP5
622          hexdump(s->p, s->end-s->p);          printf("--- rdpdr_process ---\n");
623            hexdump(s->p, s->end - s->p);
624    #endif
625          in_uint8p(s, magic, 4);          in_uint8p(s, magic, 4);
626    
627          if ((magic[0] == 'r') && (magic[1] == 'D'))          if ((magic[0] == 'r') && (magic[1] == 'D'))
# Line 225  rdpdr_process(STREAM s) Line 635  rdpdr_process(STREAM s)
635                  {                  {
636                          rdpdr_send_connect();                          rdpdr_send_connect();
637                          rdpdr_send_name();                          rdpdr_send_name();
                         rdpdr_send_available();  
638                          return;                          return;
639                  }                  }
640                  else if ((magic[2] == 'C') && (magic[3] == 'C'))                  if ((magic[2] == 'C') && (magic[3] == 'C'))
641                  {                  {
642                          /* connect from server */                          /* connect from server */
643                            rdpdr_send_clientcapabilty();
644                            rdpdr_send_available();
645                          return;                          return;
646                  }                  }
647                  else if ((magic[2] == 'r') && (magic[3] == 'd'))                  if ((magic[2] == 'r') && (magic[3] == 'd'))
648                  {                  {
649                          /* connect to a specific resource */                          /* connect to a specific resource */
650                          in_uint32(s, handle);                          in_uint32(s, handle);
651                          printf("Server connected to resource %d\n", handle);  #if WITH_DEBUG_RDP5
652                            DEBUG(("RDPDR: Server connected to resource %d\n", handle));
653    #endif
654                            return;
655                    }
656                    if ((magic[2] == 'P') && (magic[3] == 'S'))
657                    {
658                            /* server capability */
659                            return;
660                    }
661            }
662            if ((magic[0] == 'R') && (magic[1] == 'P'))
663            {
664                    if ((magic[2] == 'C') && (magic[3] == 'P'))
665                    {
666                            printercache_process(s);
667                          return;                          return;
668                  }                  }
669          }          }
# Line 245  rdpdr_process(STREAM s) Line 671  rdpdr_process(STREAM s)
671  }  }
672    
673  BOOL  BOOL
674  rdpdr_init(void)  rdpdr_init()
675  {  {
676          rdpdr_channel = channel_register("rdpdr", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP, rdpdr_process);          if (g_num_devices > 0)
677            {
678                    rdpdr_channel =
679                            channel_register("rdpdr",
680                                             CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,
681                                             rdpdr_process);
682            }
683    
684          return (rdpdr_channel != NULL);          return (rdpdr_channel != NULL);
685  }  }
686    
687    /* Add file descriptors of pending io request to select() */
688    void
689    rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * timeout)
690    {
691            uint32 select_timeout = 0;      // Timeout value to be used for select() (in millisecons).
692            struct async_iorequest *iorq;
693    
694            iorq = g_iorequest;
695            while (iorq != NULL)
696            {
697                    if (iorq->fd != 0)
698                    {
699                            switch (iorq->major)
700                            {
701                                    case IRP_MJ_READ:
702    
703                                            FD_SET(iorq->fd, rfds);
704    
705                                            // Check if io request timeout is smaller than current (but not 0).
706                                            if (iorq->timeout
707                                                && (select_timeout == 0
708                                                    || iorq->timeout < select_timeout))
709                                            {
710                                                    // Set new timeout
711                                                    select_timeout = iorq->timeout;
712                                                    g_min_timeout_fd = iorq->fd;    /* Remember fd */
713                                                    tv->tv_sec = select_timeout / 1000;
714                                                    tv->tv_usec = (select_timeout % 1000) * 1000;
715                                                    *timeout = True;
716                                            }
717                                            break;
718    
719                                    case IRP_MJ_WRITE:
720                                            FD_SET(iorq->fd, wfds);
721                                            break;
722    
723                            }
724                            *n = MAX(*n, iorq->fd);
725                    }
726    
727                    iorq = iorq->next;
728            }
729    }
730    
731    
732    /* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */
733    void
734    rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out)
735    {
736            NTSTATUS status;
737            uint32 result = 0;
738            DEVICE_FNS *fns;
739            struct async_iorequest *iorq;
740            struct async_iorequest *prev;
741            uint32 req_size = 0;
742    
743            if (timed_out)
744            {
745                    rdpdr_abort_io(g_min_timeout_fd, 0, STATUS_TIMEOUT);
746                    return;
747            }
748    
749            iorq = g_iorequest;
750            prev = NULL;
751            while (iorq != NULL)
752            {
753                    if (iorq->fd != 0)
754                    {
755                            switch (iorq->major)
756                            {
757                                    case IRP_MJ_READ:
758                                            if (FD_ISSET(iorq->fd, rfds))
759                                            {
760                                                    /* Read the data */
761                                                    fns = iorq->fns;
762    
763                                                    req_size =
764                                                            (iorq->length - iorq->partial_len) >
765                                                            8192 ? 8192 : (iorq->length -
766                                                                           iorq->partial_len);
767                                                    /* never read larger chunks than 8k - chances are that it will block */
768                                                    status = fns->read(iorq->fd,
769                                                                       iorq->buffer + iorq->partial_len,
770                                                                       req_size, 0, &result);
771                                                    iorq->partial_len += result;
772    
773    #if WITH_DEBUG_RDP5
774                                                    DEBUG(("RDPDR: %d bytes of data read\n", result));
775    #endif
776                                                    /* only delete link if all data has been transfered */
777                                                    /* or if result was 0 and status success - EOF      */
778                                                    if ((iorq->partial_len == iorq->length) ||
779                                                        (result == 0))
780                                                    {
781    #if WITH_DEBUG_RDP5
782                                                            DEBUG(("RDPDR: AIO total %u bytes read of %u\n", iorq->partial_len, iorq->length));
783    #endif
784                                                            /* send the data */
785                                                            status = STATUS_SUCCESS;
786                                                            rdpdr_send_completion(iorq->device,
787                                                                                  iorq->id, status,
788                                                                                  iorq->partial_len,
789                                                                                  iorq->buffer,
790                                                                                  iorq->partial_len);
791                                                            xfree(iorq->buffer);
792                                                            iorq->fd = 0;
793                                                            if (prev != NULL)
794                                                            {
795                                                                    prev->next = iorq->next;
796                                                                    xfree(iorq);
797                                                            }
798                                                            else
799                                                            {
800                                                                    // Even if NULL
801                                                                    g_iorequest = iorq->next;
802                                                                    xfree(iorq);
803                                                            }
804                                                    }
805                                            }
806                                            break;
807                                    case IRP_MJ_WRITE:
808                                            if (FD_ISSET(iorq->fd, wfds))
809                                            {
810                                                    /* Write data. */
811                                                    fns = iorq->fns;
812    
813                                                    req_size =
814                                                            (iorq->length - iorq->partial_len) >
815                                                            8192 ? 8192 : (iorq->length -
816                                                                           iorq->partial_len);
817    
818                                                    /* never write larger chunks than 8k - chances are that it will block */
819                                                    status = fns->write(iorq->fd,
820                                                                        iorq->buffer +
821                                                                        iorq->partial_len, req_size, 0,
822                                                                        &result);
823                                                    iorq->partial_len += result;
824    #if WITH_DEBUG_RDP5
825                                                    DEBUG(("RDPDR: %d bytes of data written\n",
826                                                           result));
827    #endif
828                                                    /* only delete link if all data has been transfered */
829                                                    /* or we couldn't write */
830                                                    if ((iorq->partial_len == iorq->length)
831                                                        || (result == 0))
832                                                    {
833    #if WITH_DEBUG_RDP5
834                                                            DEBUG(("RDPDR: AIO total %u bytes written of %u\n", iorq->partial_len, iorq->length));
835    #endif
836                                                            /* send a status success */
837                                                            status = STATUS_SUCCESS;
838                                                            rdpdr_send_completion(iorq->device,
839                                                                                  iorq->id, status,
840                                                                                  iorq->partial_len,
841                                                                                  (uint8 *) "", 1);
842    
843                                                            xfree(iorq->buffer);
844                                                            iorq->fd = 0;
845                                                            if (prev != NULL)
846                                                            {
847                                                                    prev->next = iorq->next;
848                                                                    xfree(iorq);
849                                                            }
850                                                            else
851                                                            {
852                                                                    // Even if NULL
853                                                                    g_iorequest = iorq->next;
854                                                                    xfree(iorq);
855                                                            }
856                                                    }
857                                            }
858                                            break;
859                            }
860    
861                    }
862                    prev = iorq;
863                    iorq = iorq->next;
864            }
865    
866    }
867    
868    /* Abort a pending io request for a given handle and major */
869    BOOL
870    rdpdr_abort_io(uint32 fd, uint32 major, NTSTATUS status)
871    {
872            uint32 result;
873            struct async_iorequest *iorq;
874            struct async_iorequest *prev;
875    
876            iorq = g_iorequest;
877            prev = NULL;
878            while (iorq != NULL)
879            {
880                    // Only remove from table when major is not set, or when correct major is supplied.
881                    // Abort read should not abort a write io request.
882                    if ((iorq->fd == fd) && (major == 0 || iorq->major == major))
883                    {
884                            result = 0;
885                            rdpdr_send_completion(iorq->device, iorq->id, status, result, (uint8 *) "",
886                                                  1);
887                            xfree(iorq->buffer);
888                            iorq->fd = 0;
889                            if (prev != NULL)
890                            {
891                                    prev->next = iorq->next;
892                                    xfree(iorq);
893                            }
894                            else
895                            {
896                                    // Even if NULL
897                                    g_iorequest = iorq->next;
898                                    xfree(iorq);
899                            }
900                            return True;
901                    }
902    
903                    prev = iorq;
904                    iorq = iorq->next;
905            }
906    
907            return False;
908    }

Legend:
Removed from v.432  
changed lines
  Added in v.609

  ViewVC Help
Powered by ViewVC 1.1.26