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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 570 - (show annotations)
Wed Jan 21 18:02:38 2004 UTC (20 years, 4 months ago) by stargo
File MIME type: text/plain
File size: 17556 byte(s)
some fixes for solaris compiles.
toupper was redefined to handle strings, now renamed to toupper_str
disk.c has some more problems (it uses statfs and dirfd)

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

  ViewVC Help
Powered by ViewVC 1.1.26