1 |
|
/* -*- c-basic-offset: 8 -*- |
2 |
|
rdesktop: A Remote Desktop Protocol client. |
3 |
|
Copyright (C) Matthew Chapman 1999-2004 |
4 |
|
|
5 |
|
This program is free software; you can redistribute it and/or modify |
6 |
|
it under the terms of the GNU General Public License as published by |
7 |
|
the Free Software Foundation; either version 2 of the License, or |
8 |
|
(at your option) any later version. |
9 |
|
|
10 |
|
This program is distributed in the hope that it will be useful, |
11 |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
|
GNU General Public License for more details. |
14 |
|
|
15 |
|
You should have received a copy of the GNU General Public License |
16 |
|
along with this program; if not, write to the Free Software |
17 |
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
18 |
|
*/ |
19 |
|
|
20 |
|
/* |
21 |
|
Here are some resources, for your IRP hacking pleasure: |
22 |
|
|
23 |
|
http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/winddk.h?view=markup |
24 |
|
|
25 |
|
http://win32.mvps.org/ntfs/streams.cpp |
26 |
|
|
27 |
|
http://www.acc.umu.se/~bosse/ntifs.h |
28 |
|
|
29 |
|
http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/ |
30 |
|
|
31 |
|
http://us1.samba.org/samba/ftp/specs/smb-nt01.txt |
32 |
|
|
33 |
|
http://www.osronline.com/ |
34 |
|
*/ |
35 |
|
|
36 |
#include <unistd.h> |
#include <unistd.h> |
37 |
#include <sys/types.h> |
#include <sys/types.h> |
38 |
#include <sys/time.h> |
#include <sys/time.h> |
39 |
#include <dirent.h> /* opendir, closedir, readdir */ |
#include <dirent.h> /* opendir, closedir, readdir */ |
40 |
#include <time.h> |
#include <time.h> |
41 |
|
#include <errno.h> |
42 |
#include "rdesktop.h" |
#include "rdesktop.h" |
43 |
|
|
|
#define IRP_MJ_CREATE 0x00 |
|
|
#define IRP_MJ_CLOSE 0x02 |
|
|
#define IRP_MJ_READ 0x03 |
|
|
#define IRP_MJ_WRITE 0x04 |
|
|
#define IRP_MJ_DEVICE_CONTROL 0x0e |
|
|
|
|
44 |
#define IRP_MJ_CREATE 0x00 |
#define IRP_MJ_CREATE 0x00 |
45 |
#define IRP_MJ_CLOSE 0x02 |
#define IRP_MJ_CLOSE 0x02 |
46 |
#define IRP_MJ_READ 0x03 |
#define IRP_MJ_READ 0x03 |
50 |
#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a |
#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a |
51 |
#define IRP_MJ_DIRECTORY_CONTROL 0x0c |
#define IRP_MJ_DIRECTORY_CONTROL 0x0c |
52 |
#define IRP_MJ_DEVICE_CONTROL 0x0e |
#define IRP_MJ_DEVICE_CONTROL 0x0e |
53 |
|
#define IRP_MJ_LOCK_CONTROL 0x11 |
54 |
|
|
55 |
#define IRP_MN_QUERY_DIRECTORY 0x01 |
#define IRP_MN_QUERY_DIRECTORY 0x01 |
56 |
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02 |
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02 |
57 |
|
|
58 |
extern char hostname[16]; |
extern char g_hostname[16]; |
59 |
extern DEVICE_FNS serial_fns; |
extern DEVICE_FNS serial_fns; |
60 |
extern DEVICE_FNS printer_fns; |
extern DEVICE_FNS printer_fns; |
61 |
extern DEVICE_FNS parallel_fns; |
extern DEVICE_FNS parallel_fns; |
70 |
|
|
71 |
/* Table with information about rdpdr devices */ |
/* Table with information about rdpdr devices */ |
72 |
RDPDR_DEVICE g_rdpdr_device[RDPDR_MAX_DEVICES]; |
RDPDR_DEVICE g_rdpdr_device[RDPDR_MAX_DEVICES]; |
73 |
char * g_rdpdr_clientname = NULL; |
char *g_rdpdr_clientname = NULL; |
74 |
|
|
75 |
/* Used to store incoming io request, until they are ready to be completed */ |
/* Used to store incoming io request, until they are ready to be completed */ |
76 |
/* using a linked list ensures that they are processed in the right order, */ |
/* using a linked list ensures that they are processed in the right order, */ |
113 |
} |
} |
114 |
} |
} |
115 |
|
|
116 |
BOOL |
static BOOL |
117 |
rdpdr_handle_ok(int device, int handle) |
rdpdr_handle_ok(int device, int handle) |
118 |
{ |
{ |
119 |
switch (g_rdpdr_device[device].device_type) |
switch (g_rdpdr_device[device].device_type) |
134 |
} |
} |
135 |
|
|
136 |
/* Add a new io request to the table containing pending io requests so it won't block rdesktop */ |
/* Add a new io request to the table containing pending io requests so it won't block rdesktop */ |
137 |
BOOL |
static BOOL |
138 |
add_async_iorequest(uint32 device, uint32 file, uint32 id, uint32 major, uint32 length, |
add_async_iorequest(uint32 device, uint32 file, uint32 id, uint32 major, uint32 length, |
139 |
DEVICE_FNS * fns, uint32 total_timeout, uint32 interval_timeout, uint8 * buffer, |
DEVICE_FNS * fns, uint32 total_timeout, uint32 interval_timeout, uint8 * buffer, |
140 |
uint32 offset) |
uint32 offset) |
180 |
return True; |
return True; |
181 |
} |
} |
182 |
|
|
183 |
void |
static void |
184 |
rdpdr_send_connect(void) |
rdpdr_send_connect(void) |
185 |
{ |
{ |
186 |
uint8 magic[4] = "rDCC"; |
uint8 magic[4] = "rDCC"; |
196 |
} |
} |
197 |
|
|
198 |
|
|
199 |
void |
static void |
200 |
rdpdr_send_name(void) |
rdpdr_send_name(void) |
201 |
{ |
{ |
202 |
uint8 magic[4] = "rDNC"; |
uint8 magic[4] = "rDNC"; |
|
if (NULL == g_rdpdr_clientname) { |
|
|
g_rdpdr_clientname = hostname; |
|
|
} |
|
|
uint32 hostlen = (strlen(g_rdpdr_clientname) + 1) * 2; |
|
203 |
STREAM s; |
STREAM s; |
204 |
|
uint32 hostlen; |
205 |
|
|
206 |
|
if (NULL == g_rdpdr_clientname) |
207 |
|
{ |
208 |
|
g_rdpdr_clientname = g_hostname; |
209 |
|
} |
210 |
|
hostlen = (strlen(g_rdpdr_clientname) + 1) * 2; |
211 |
|
|
212 |
s = channel_init(rdpdr_channel, 16 + hostlen); |
s = channel_init(rdpdr_channel, 16 + hostlen); |
213 |
out_uint8a(s, magic, 4); |
out_uint8a(s, magic, 4); |
221 |
} |
} |
222 |
|
|
223 |
/* Returns the size of the payload of the announce packet */ |
/* Returns the size of the payload of the announce packet */ |
224 |
int |
static int |
225 |
announcedata_size() |
announcedata_size() |
226 |
{ |
{ |
227 |
int size, i; |
int size, i; |
248 |
return size; |
return size; |
249 |
} |
} |
250 |
|
|
251 |
void |
static void |
252 |
rdpdr_send_available(void) |
rdpdr_send_available(void) |
253 |
{ |
{ |
254 |
|
|
306 |
channel_send(s, rdpdr_channel); |
channel_send(s, rdpdr_channel); |
307 |
} |
} |
308 |
|
|
309 |
void |
static void |
310 |
rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer, |
rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer, |
311 |
uint32 length) |
uint32 length) |
312 |
{ |
{ |
659 |
result = buffer_len = out.p - out.data; |
result = buffer_len = out.p - out.data; |
660 |
break; |
break; |
661 |
|
|
662 |
|
|
663 |
|
case IRP_MJ_LOCK_CONTROL: |
664 |
|
|
665 |
|
if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK) |
666 |
|
{ |
667 |
|
status = STATUS_INVALID_HANDLE; |
668 |
|
break; |
669 |
|
} |
670 |
|
|
671 |
|
in_uint32_le(s, info_level); |
672 |
|
|
673 |
|
out.data = out.p = buffer; |
674 |
|
out.size = sizeof(buffer); |
675 |
|
/* FIXME: Perhaps consider actually *do* |
676 |
|
something here :-) */ |
677 |
|
status = STATUS_SUCCESS; |
678 |
|
result = buffer_len = out.p - out.data; |
679 |
|
break; |
680 |
|
|
681 |
default: |
default: |
682 |
unimpl("IRP major=0x%x minor=0x%x\n", major, minor); |
unimpl("IRP major=0x%x minor=0x%x\n", major, minor); |
683 |
break; |
break; |
692 |
buffer = NULL; |
buffer = NULL; |
693 |
} |
} |
694 |
|
|
695 |
void |
static void |
696 |
rdpdr_send_clientcapabilty(void) |
rdpdr_send_clientcapabilty(void) |
697 |
{ |
{ |
698 |
uint8 magic[4] = "rDPC"; |
uint8 magic[4] = "rDPC"; |
810 |
{ |
{ |
811 |
uint32 select_timeout = 0; // Timeout value to be used for select() (in millisecons). |
uint32 select_timeout = 0; // Timeout value to be used for select() (in millisecons). |
812 |
struct async_iorequest *iorq; |
struct async_iorequest *iorq; |
813 |
|
char c; |
814 |
|
|
815 |
iorq = g_iorequest; |
iorq = g_iorequest; |
816 |
while (iorq != NULL) |
while (iorq != NULL) |
820 |
switch (iorq->major) |
switch (iorq->major) |
821 |
{ |
{ |
822 |
case IRP_MJ_READ: |
case IRP_MJ_READ: |
823 |
|
/* Is this FD valid? FDs will |
824 |
|
be invalid when |
825 |
|
reconnecting. FIXME: Real |
826 |
|
support for reconnects. */ |
827 |
|
|
828 |
|
if ((read(iorq->fd, &c, 0) != 0) && (errno == EBADF)) |
829 |
|
break; |
830 |
|
|
831 |
FD_SET(iorq->fd, rfds); |
FD_SET(iorq->fd, rfds); |
832 |
|
*n = MAX(*n, iorq->fd); |
833 |
|
|
834 |
// Check if io request timeout is smaller than current (but not 0). |
// Check if io request timeout is smaller than current (but not 0). |
835 |
if (iorq->timeout |
if (iorq->timeout |
843 |
tv->tv_usec = (select_timeout % 1000) * 1000; |
tv->tv_usec = (select_timeout % 1000) * 1000; |
844 |
*timeout = True; |
*timeout = True; |
845 |
} |
} |
846 |
|
|
847 |
break; |
break; |
848 |
|
|
849 |
case IRP_MJ_WRITE: |
case IRP_MJ_WRITE: |
850 |
|
/* FD still valid? See above. */ |
851 |
|
if ((write(iorq->fd, &c, 0) != 0) && (errno == EBADF)) |
852 |
|
break; |
853 |
|
|
854 |
FD_SET(iorq->fd, wfds); |
FD_SET(iorq->fd, wfds); |
855 |
|
*n = MAX(*n, iorq->fd); |
856 |
break; |
break; |
857 |
|
|
858 |
} |
} |
859 |
*n = MAX(*n, iorq->fd); |
|
860 |
} |
} |
861 |
|
|
862 |
iorq = iorq->next; |
iorq = iorq->next; |