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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 627 - (hide annotations)
Thu Mar 4 08:24:40 2004 UTC (20 years, 2 months ago) by n-ki
File MIME type: text/plain
File size: 21192 byte(s)
move disk info define to types.h
extract aio remove
handle errors in aio read / write
function that checks if handle is ok - seems windows cant keep track of them huh
- volker milde

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

  ViewVC Help
Powered by ViewVC 1.1.26