/[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 650 - (hide annotations)
Thu Apr 15 20:11:19 2004 UTC (20 years, 1 month ago) by astrand
File MIME type: text/plain
File size: 21230 byte(s)
Removed duplicat IRP_MJ defs. Added def for IRP_MJ_LOCK_CONTROL

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

  ViewVC Help
Powered by ViewVC 1.1.26