--- sourceforge.net/trunk/rdesktop/rdpdr.c 2004/04/15 20:11:19 650 +++ sourceforge.net/trunk/rdesktop/rdpdr.c 2004/08/09 13:50:41 747 @@ -1,8 +1,44 @@ +/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + Copyright (C) Matthew Chapman 1999-2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Here are some resources, for your IRP hacking pleasure: + + http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/winddk.h?view=markup + + http://win32.mvps.org/ntfs/streams.cpp + + http://www.acc.umu.se/~bosse/ntifs.h + + http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/ + + http://us1.samba.org/samba/ftp/specs/smb-nt01.txt + + http://www.osronline.com/ +*/ + #include #include #include #include /* opendir, closedir, readdir */ #include +#include #include "rdesktop.h" #define IRP_MJ_CREATE 0x00 @@ -19,7 +55,7 @@ #define IRP_MN_QUERY_DIRECTORY 0x01 #define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02 -extern char hostname[16]; +extern char g_hostname[16]; extern DEVICE_FNS serial_fns; extern DEVICE_FNS printer_fns; extern DEVICE_FNS parallel_fns; @@ -34,7 +70,7 @@ /* Table with information about rdpdr devices */ RDPDR_DEVICE g_rdpdr_device[RDPDR_MAX_DEVICES]; -char * g_rdpdr_clientname = NULL; +char *g_rdpdr_clientname = NULL; /* Used to store incoming io request, until they are ready to be completed */ /* using a linked list ensures that they are processed in the right order, */ @@ -77,7 +113,7 @@ } } -BOOL +static BOOL rdpdr_handle_ok(int device, int handle) { switch (g_rdpdr_device[device].device_type) @@ -98,7 +134,7 @@ } /* Add a new io request to the table containing pending io requests so it won't block rdesktop */ -BOOL +static BOOL add_async_iorequest(uint32 device, uint32 file, uint32 id, uint32 major, uint32 length, DEVICE_FNS * fns, uint32 total_timeout, uint32 interval_timeout, uint8 * buffer, uint32 offset) @@ -144,7 +180,7 @@ return True; } -void +static void rdpdr_send_connect(void) { uint8 magic[4] = "rDCC"; @@ -160,15 +196,16 @@ } -void +static void rdpdr_send_name(void) { uint8 magic[4] = "rDNC"; STREAM s; uint32 hostlen; - if (NULL == g_rdpdr_clientname) { - g_rdpdr_clientname = hostname; + if (NULL == g_rdpdr_clientname) + { + g_rdpdr_clientname = g_hostname; } hostlen = (strlen(g_rdpdr_clientname) + 1) * 2; @@ -184,7 +221,7 @@ } /* Returns the size of the payload of the announce packet */ -int +static int announcedata_size() { int size, i; @@ -211,7 +248,7 @@ return size; } -void +static void rdpdr_send_available(void) { @@ -229,6 +266,8 @@ { out_uint32_le(s, g_rdpdr_device[i].device_type); out_uint32_le(s, i); /* RDP Device ID */ + /* Is it possible to use share names longer than 8 chars? + /astrand */ out_uint8p(s, g_rdpdr_device[i].name, 8); switch (g_rdpdr_device[i].device_type) @@ -269,7 +308,7 @@ channel_send(s, rdpdr_channel); } -void +static void rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer, uint32 length) { @@ -622,6 +661,25 @@ result = buffer_len = out.p - out.data; break; + + case IRP_MJ_LOCK_CONTROL: + + if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK) + { + status = STATUS_INVALID_HANDLE; + break; + } + + in_uint32_le(s, info_level); + + out.data = out.p = buffer; + out.size = sizeof(buffer); + /* FIXME: Perhaps consider actually *do* + something here :-) */ + status = STATUS_SUCCESS; + result = buffer_len = out.p - out.data; + break; + default: unimpl("IRP major=0x%x minor=0x%x\n", major, minor); break; @@ -636,7 +694,7 @@ buffer = NULL; } -void +static void rdpdr_send_clientcapabilty(void) { uint8 magic[4] = "rDPC"; @@ -754,6 +812,7 @@ { uint32 select_timeout = 0; // Timeout value to be used for select() (in millisecons). struct async_iorequest *iorq; + char c; iorq = g_iorequest; while (iorq != NULL) @@ -763,8 +822,16 @@ switch (iorq->major) { case IRP_MJ_READ: + /* Is this FD valid? FDs will + be invalid when + reconnecting. FIXME: Real + support for reconnects. */ + + if ((read(iorq->fd, &c, 0) != 0) && (errno == EBADF)) + break; FD_SET(iorq->fd, rfds); + *n = MAX(*n, iorq->fd); // Check if io request timeout is smaller than current (but not 0). if (iorq->timeout @@ -778,14 +845,20 @@ tv->tv_usec = (select_timeout % 1000) * 1000; *timeout = True; } + break; case IRP_MJ_WRITE: + /* FD still valid? See above. */ + if ((write(iorq->fd, &c, 0) != 0) && (errno == EBADF)) + break; + FD_SET(iorq->fd, wfds); + *n = MAX(*n, iorq->fd); break; } - *n = MAX(*n, iorq->fd); + } iorq = iorq->next;