⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rdpdr.c

📁 rdesktop is a client for Microsoft Windows NT Terminal Server, Windows 2000 Terminal Services, Wind
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- c-basic-offset: 8 -*-   rdesktop: A Remote Desktop Protocol client.   Copyright (C) Matthew Chapman 1999-2005   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 <unistd.h>#include <sys/types.h>#include <sys/time.h>#include <dirent.h>		/* opendir, closedir, readdir */#include <time.h>#include <errno.h>#include "rdesktop.h"#define IRP_MJ_CREATE			0x00#define IRP_MJ_CLOSE			0x02#define IRP_MJ_READ			0x03#define IRP_MJ_WRITE			0x04#define	IRP_MJ_QUERY_INFORMATION	0x05#define IRP_MJ_SET_INFORMATION		0x06#define IRP_MJ_QUERY_VOLUME_INFORMATION	0x0a#define IRP_MJ_DIRECTORY_CONTROL	0x0c#define IRP_MJ_DEVICE_CONTROL		0x0e#define IRP_MJ_LOCK_CONTROL             0x11#define IRP_MN_QUERY_DIRECTORY          0x01#define IRP_MN_NOTIFY_CHANGE_DIRECTORY  0x02extern char g_hostname[16];extern DEVICE_FNS serial_fns;extern DEVICE_FNS printer_fns;extern DEVICE_FNS parallel_fns;extern DEVICE_FNS disk_fns;extern FILEINFO g_fileinfo[];extern BOOL g_notify_stamp;static VCHANNEL *rdpdr_channel;/* If select() times out, the request for the device with handle g_min_timeout_fd is aborted */NTHANDLE g_min_timeout_fd;uint32 g_num_devices;/* Table with information about rdpdr devices */RDPDR_DEVICE g_rdpdr_device[RDPDR_MAX_DEVICES];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, *//* if multiple ios are being done on the same fd */struct async_iorequest{	uint32 fd, major, minor, offset, device, id, length, partial_len;	long timeout,		/* Total timeout */	  itv_timeout;		/* Interval timeout (between serial characters) */	uint8 *buffer;	DEVICE_FNS *fns;	struct async_iorequest *next;	/* next element in list */};struct async_iorequest *g_iorequest;/* Return device_id for a given handle */intget_device_index(NTHANDLE handle){	int i;	for (i = 0; i < RDPDR_MAX_DEVICES; i++)	{		if (g_rdpdr_device[i].handle == handle)			return i;	}	return -1;}/* Converts a windows path to a unix path */voidconvert_to_unix_filename(char *filename){	char *p;	while ((p = strchr(filename, '\\')))	{		*p = '/';	}}static BOOLrdpdr_handle_ok(int device, int handle){	switch (g_rdpdr_device[device].device_type)	{		case DEVICE_TYPE_PARALLEL:		case DEVICE_TYPE_SERIAL:		case DEVICE_TYPE_PRINTER:		case DEVICE_TYPE_SCARD:			if (g_rdpdr_device[device].handle != handle)				return False;			break;		case DEVICE_TYPE_DISK:			if (g_fileinfo[handle].device_id != device)				return False;			break;	}	return True;}/* Add a new io request to the table containing pending io requests so it won't block rdesktop */static BOOLadd_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){	struct async_iorequest *iorq;	if (g_iorequest == NULL)	{		g_iorequest = (struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));		if (!g_iorequest)			return False;		g_iorequest->fd = 0;		g_iorequest->next = NULL;	}	iorq = g_iorequest;	while (iorq->fd != 0)	{		/* create new element if needed */		if (iorq->next == NULL)		{			iorq->next =				(struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));			if (!iorq->next)				return False;			iorq->next->fd = 0;			iorq->next->next = NULL;		}		iorq = iorq->next;	}	iorq->device = device;	iorq->fd = file;	iorq->id = id;	iorq->major = major;	iorq->length = length;	iorq->partial_len = 0;	iorq->fns = fns;	iorq->timeout = total_timeout;	iorq->itv_timeout = interval_timeout;	iorq->buffer = buffer;	iorq->offset = offset;	return True;}static voidrdpdr_send_connect(void){	uint8 magic[4] = "rDCC";	STREAM s;	s = channel_init(rdpdr_channel, 12);	out_uint8a(s, magic, 4);	out_uint16_le(s, 1);	/* unknown */	out_uint16_le(s, 5);	out_uint32_be(s, 0x815ed39d);	/* IP address (use 127.0.0.1) 0x815ed39d */	s_mark_end(s);	channel_send(s, rdpdr_channel);}static voidrdpdr_send_name(void){	uint8 magic[4] = "rDNC";	STREAM s;	uint32 hostlen;	if (NULL == g_rdpdr_clientname)	{		g_rdpdr_clientname = g_hostname;	}	hostlen = (strlen(g_rdpdr_clientname) + 1) * 2;	s = channel_init(rdpdr_channel, 16 + hostlen);	out_uint8a(s, magic, 4);	out_uint16_le(s, 0x63);	/* unknown */	out_uint16_le(s, 0x72);	out_uint32(s, 0);	out_uint32_le(s, hostlen);	rdp_out_unistr(s, g_rdpdr_clientname, hostlen - 2);	s_mark_end(s);	channel_send(s, rdpdr_channel);}/* Returns the size of the payload of the announce packet */static intannouncedata_size(){	int size, i;	PRINTER *printerinfo;	size = 8;		/* static announce size */	size += g_num_devices * 0x14;	for (i = 0; i < g_num_devices; i++)	{		if (g_rdpdr_device[i].device_type == DEVICE_TYPE_PRINTER)		{			printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;			printerinfo->bloblen =				printercache_load_blob(printerinfo->printer, &(printerinfo->blob));			size += 0x18;			size += 2 * strlen(printerinfo->driver) + 2;			size += 2 * strlen(printerinfo->printer) + 2;			size += printerinfo->bloblen;		}	}	return size;}static voidrdpdr_send_available(void){	uint8 magic[4] = "rDAD";	uint32 driverlen, printerlen, bloblen;	int i;	STREAM s;	PRINTER *printerinfo;	s = channel_init(rdpdr_channel, announcedata_size());	out_uint8a(s, magic, 4);	out_uint32_le(s, g_num_devices);	for (i = 0; i < g_num_devices; i++)	{		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)		{			case DEVICE_TYPE_PRINTER:				printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;				driverlen = 2 * strlen(printerinfo->driver) + 2;				printerlen = 2 * strlen(printerinfo->printer) + 2;				bloblen = printerinfo->bloblen;				out_uint32_le(s, 24 + driverlen + printerlen + bloblen);	/* length of extra info */				out_uint32_le(s, printerinfo->default_printer ? 2 : 0);				out_uint8s(s, 8);	/* unknown */				out_uint32_le(s, driverlen);				out_uint32_le(s, printerlen);				out_uint32_le(s, bloblen);				rdp_out_unistr(s, printerinfo->driver, driverlen - 2);				rdp_out_unistr(s, printerinfo->printer, printerlen - 2);				out_uint8a(s, printerinfo->blob, bloblen);				if (printerinfo->blob)					xfree(printerinfo->blob);	/* Blob is sent twice if reconnecting */				break;			default:				out_uint32(s, 0);		}	}#if 0	out_uint32_le(s, 0x20);	/* Device type 0x20 - smart card */	out_uint32_le(s, 0);	out_uint8p(s, "SCARD", 5);	out_uint8s(s, 3);	out_uint32(s, 0);#endif	s_mark_end(s);	channel_send(s, rdpdr_channel);}static voidrdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,		      uint32 length){	uint8 magic[4] = "rDCI";	STREAM s;	s = channel_init(rdpdr_channel, 20 + length);	out_uint8a(s, magic, 4);	out_uint32_le(s, device);	out_uint32_le(s, id);	out_uint32_le(s, status);	out_uint32_le(s, result);	out_uint8p(s, buffer, length);	s_mark_end(s);	/* JIF */#ifdef WITH_DEBUG_RDP5	printf("--> rdpdr_send_completion\n");	/* hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */#endif	channel_send(s, rdpdr_channel);}static voidrdpdr_process_irp(STREAM s){	uint32 result = 0,		length = 0,		desired_access = 0,		request,		file,		info_level,		buffer_len,		id,		major,		minor,		device,		offset,		bytes_in,		bytes_out,		error_mode,		share_mode, disposition, total_timeout, interval_timeout, flags_and_attributes = 0;	char filename[PATH_MAX];	uint8 *buffer, *pst_buf;	struct stream out;	DEVICE_FNS *fns;	BOOL rw_blocking = True;	NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;	in_uint32_le(s, device);	in_uint32_le(s, file);	in_uint32_le(s, id);	in_uint32_le(s, major);	in_uint32_le(s, minor);	buffer_len = 0;	buffer = (uint8 *) xmalloc(1024);	buffer[0] = 0;	switch (g_rdpdr_device[device].device_type)	{		case DEVICE_TYPE_SERIAL:			fns = &serial_fns;			rw_blocking = False;			break;		case DEVICE_TYPE_PARALLEL:			fns = &parallel_fns;			rw_blocking = False;			break;		case DEVICE_TYPE_PRINTER:			fns = &printer_fns;			break;		case DEVICE_TYPE_DISK:			fns = &disk_fns;			rw_blocking = False;			break;		case DEVICE_TYPE_SCARD:		default:			error("IRP for bad device %ld\n", device);			return;	}	switch (major)	{		case IRP_MJ_CREATE:			in_uint32_be(s, desired_access);			in_uint8s(s, 0x08);	/* unknown */			in_uint32_le(s, error_mode);			in_uint32_le(s, share_mode);			in_uint32_le(s, disposition);			in_uint32_le(s, flags_and_attributes);			in_uint32_le(s, length);			if (length && (length / 2) < 256)			{				rdp_in_unistr(s, filename, length);				convert_to_unix_filename(filename);			}			else			{				filename[0] = 0;			}			if (!fns->create)			{				status = STATUS_NOT_SUPPORTED;				break;			}			status = fns->create(device, desired_access, share_mode, disposition,					     flags_and_attributes, filename, &result);			buffer_len = 1;			break;		case IRP_MJ_CLOSE:			if (!fns->close)			{				status = STATUS_NOT_SUPPORTED;				break;			}			status = fns->close(file);			break;		case IRP_MJ_READ:			if (!fns->read)			{				status = STATUS_NOT_SUPPORTED;				break;			}			in_uint32_le(s, length);			in_uint32_le(s, offset);#if WITH_DEBUG_RDP5			DEBUG(("RDPDR IRP Read (length: %d, offset: %d)\n", length, offset));#endif			if (!rdpdr_handle_ok(device, file))			{				status = STATUS_INVALID_HANDLE;				break;			}			if (rw_blocking)	/* Complete read immediately */			{				buffer = (uint8 *) xrealloc((void *) buffer, length);				if (!buffer)				{					status = STATUS_CANCELLED;					break;				}				status = fns->read(file, buffer, length, offset, &result);				buffer_len = result;				break;			}			/* Add request to table */			pst_buf = (uint8 *) xmalloc(length);			if (!pst_buf)			{				status = STATUS_CANCELLED;				break;			}			serial_get_timeout(file, length, &total_timeout, &interval_timeout);			if (add_async_iorequest			    (device, file, id, major, length, fns, total_timeout, interval_timeout,			     pst_buf, offset))			{				status = STATUS_PENDING;				break;			}			status = STATUS_CANCELLED;			break;		case IRP_MJ_WRITE:			buffer_len = 1;			if (!fns->write)			{				status = STATUS_NOT_SUPPORTED;				break;			}			in_uint32_le(s, length);			in_uint32_le(s, offset);			in_uint8s(s, 0x18);#if WITH_DEBUG_RDP5			DEBUG(("RDPDR IRP Write (length: %d)\n", result));#endif			if (!rdpdr_handle_ok(device, file))			{				status = STATUS_INVALID_HANDLE;				break;			}			if (rw_blocking)	/* Complete immediately */			{				status = fns->write(file, s->p, length, offset, &result);				break;			}			/* Add to table */			pst_buf = (uint8 *) xmalloc(length);			if (!pst_buf)			{				status = STATUS_CANCELLED;				break;			}			in_uint8a(s, pst_buf, length);			if (add_async_iorequest			    (device, file, id, major, length, fns, 0, 0, pst_buf, offset))			{				status = STATUS_PENDING;				break;			}			status = STATUS_CANCELLED;			break;		case IRP_MJ_QUERY_INFORMATION:			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);			status = disk_query_information(file, info_level, &out);			result = buffer_len = out.p - out.data;			break;		case IRP_MJ_SET_INFORMATION:			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);			status = disk_set_information(file, info_level, s, &out);			result = buffer_len = out.p - out.data;			break;		case IRP_MJ_QUERY_VOLUME_INFORMATION:			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);			status = disk_query_volume_information(file, info_level, &out);			result = buffer_len = out.p - out.data;			break;		case IRP_MJ_DIRECTORY_CONTROL:			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)			{				status = STATUS_INVALID_HANDLE;				break;			}			switch (minor)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -