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

📄 rdpdr.c

📁 rdesktop is a client for Microsoft Windows NT Terminal Server, Windows 2000 Terminal Services, Wind
💻 C
📖 第 1 页 / 共 2 页
字号:
			{				case IRP_MN_QUERY_DIRECTORY:					in_uint32_le(s, info_level);					in_uint8s(s, 1);					in_uint32_le(s, length);					in_uint8s(s, 0x17);					if (length && length < 2 * 255)					{						rdp_in_unistr(s, filename, length);						convert_to_unix_filename(filename);					}					else					{						filename[0] = 0;					}					out.data = out.p = buffer;					out.size = sizeof(buffer);					status = disk_query_directory(file, info_level, filename,								      &out);					result = buffer_len = out.p - out.data;					if (!buffer_len)						buffer_len++;					break;				case IRP_MN_NOTIFY_CHANGE_DIRECTORY:					/* JIF					   unimpl("IRP major=0x%x minor=0x%x: IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", major, minor);  */					in_uint32_le(s, info_level);	/* notify mask */					g_notify_stamp = True;					status = disk_create_notify(file, info_level);					result = 0;					if (status == STATUS_PENDING)						add_async_iorequest(device, file, id, major, length,								    fns, 0, 0, NULL, 0);					break;				default:					status = STATUS_INVALID_PARAMETER;					/* JIF */					unimpl("IRP major=0x%x minor=0x%x\n", major, minor);			}			break;		case IRP_MJ_DEVICE_CONTROL:			if (!fns->device_control)			{				status = STATUS_NOT_SUPPORTED;				break;			}			in_uint32_le(s, bytes_out);			in_uint32_le(s, bytes_in);			in_uint32_le(s, request);			in_uint8s(s, 0x14);			buffer = (uint8 *) xrealloc((void *) buffer, bytes_out + 0x14);			if (!buffer)			{				status = STATUS_CANCELLED;				break;			}			out.data = out.p = buffer;			out.size = sizeof(buffer);			status = fns->device_control(file, request, s, &out);			result = buffer_len = out.p - out.data;			/* Serial SERIAL_WAIT_ON_MASK */			if (status == STATUS_PENDING)			{				if (add_async_iorequest				    (device, file, id, major, length, fns, 0, 0, NULL, 0))				{					status = STATUS_PENDING;					break;				}			}			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;	}	if (status != STATUS_PENDING)	{		rdpdr_send_completion(device, id, status, result, buffer, buffer_len);	}	if (buffer)		xfree(buffer);	buffer = NULL;}static voidrdpdr_send_clientcapabilty(void){	uint8 magic[4] = "rDPC";	STREAM s;	s = channel_init(rdpdr_channel, 0x50);	out_uint8a(s, magic, 4);	out_uint32_le(s, 5);	/* count */	out_uint16_le(s, 1);	/* first */	out_uint16_le(s, 0x28);	/* length */	out_uint32_le(s, 1);	out_uint32_le(s, 2);	out_uint16_le(s, 2);	out_uint16_le(s, 5);	out_uint16_le(s, 1);	out_uint16_le(s, 5);	out_uint16_le(s, 0xFFFF);	out_uint16_le(s, 0);	out_uint32_le(s, 0);	out_uint32_le(s, 3);	out_uint32_le(s, 0);	out_uint32_le(s, 0);	out_uint16_le(s, 2);	/* second */	out_uint16_le(s, 8);	/* length */	out_uint32_le(s, 1);	out_uint16_le(s, 3);	/* third */	out_uint16_le(s, 8);	/* length */	out_uint32_le(s, 1);	out_uint16_le(s, 4);	/* fourth */	out_uint16_le(s, 8);	/* length */	out_uint32_le(s, 1);	out_uint16_le(s, 5);	/* fifth */	out_uint16_le(s, 8);	/* length */	out_uint32_le(s, 1);	s_mark_end(s);	channel_send(s, rdpdr_channel);}static voidrdpdr_process(STREAM s){	uint32 handle;	uint8 *magic;#if WITH_DEBUG_RDP5	printf("--- rdpdr_process ---\n");	hexdump(s->p, s->end - s->p);#endif	in_uint8p(s, magic, 4);	if ((magic[0] == 'r') && (magic[1] == 'D'))	{		if ((magic[2] == 'R') && (magic[3] == 'I'))		{			rdpdr_process_irp(s);			return;		}		if ((magic[2] == 'n') && (magic[3] == 'I'))		{			rdpdr_send_connect();			rdpdr_send_name();			return;		}		if ((magic[2] == 'C') && (magic[3] == 'C'))		{			/* connect from server */			rdpdr_send_clientcapabilty();			rdpdr_send_available();			return;		}		if ((magic[2] == 'r') && (magic[3] == 'd'))		{			/* connect to a specific resource */			in_uint32(s, handle);#if WITH_DEBUG_RDP5			DEBUG(("RDPDR: Server connected to resource %d\n", handle));#endif			return;		}		if ((magic[2] == 'P') && (magic[3] == 'S'))		{			/* server capability */			return;		}	}	if ((magic[0] == 'R') && (magic[1] == 'P'))	{		if ((magic[2] == 'C') && (magic[3] == 'P'))		{			printercache_process(s);			return;		}	}	unimpl("RDPDR packet type %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]);}BOOLrdpdr_init(){	if (g_num_devices > 0)	{		rdpdr_channel =			channel_register("rdpdr",					 CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,					 rdpdr_process);	}	return (rdpdr_channel != NULL);}/* Add file descriptors of pending io request to select() */voidrdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * timeout){	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)	{		if (iorq->fd != 0)		{			switch (iorq->major)			{				case IRP_MJ_READ:					/* Is this FD valid? FDs will					   be invalid when					   reconnecting. FIXME: Real					   support for reconnects. */					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					    && (select_timeout == 0						|| iorq->timeout < select_timeout))					{						/* Set new timeout */						select_timeout = iorq->timeout;						g_min_timeout_fd = iorq->fd;	/* Remember fd */						tv->tv_sec = select_timeout / 1000;						tv->tv_usec = (select_timeout % 1000) * 1000;						*timeout = True;						break;					}					if (iorq->itv_timeout && iorq->partial_len > 0					    && (select_timeout == 0						|| iorq->itv_timeout < select_timeout))					{						/* Set new timeout */						select_timeout = iorq->itv_timeout;						g_min_timeout_fd = iorq->fd;	/* Remember fd */						tv->tv_sec = select_timeout / 1000;						tv->tv_usec = (select_timeout % 1000) * 1000;						*timeout = True;						break;					}					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;				case IRP_MJ_DEVICE_CONTROL:					if (select_timeout > 5)						select_timeout = 5;	/* serial event queue */					break;			}		}		iorq = iorq->next;	}}struct async_iorequest *rdpdr_remove_iorequest(struct async_iorequest *prev, struct async_iorequest *iorq){	if (!iorq)		return NULL;	if (iorq->buffer)		xfree(iorq->buffer);	if (prev)	{		prev->next = iorq->next;		xfree(iorq);		iorq = prev->next;	}	else	{		/* Even if NULL */		g_iorequest = iorq->next;		xfree(iorq);		iorq = NULL;	}	return iorq;}/* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */static void_rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out){	NTSTATUS status;	uint32 result = 0;	DEVICE_FNS *fns;	struct async_iorequest *iorq;	struct async_iorequest *prev;	uint32 req_size = 0;	uint32 buffer_len;	struct stream out;	uint8 *buffer = NULL;	if (timed_out)	{		/* check serial iv_timeout */		iorq = g_iorequest;		prev = NULL;		while (iorq != NULL)		{			if (iorq->fd == g_min_timeout_fd)			{				if ((iorq->partial_len > 0) &&				    (g_rdpdr_device[iorq->device].device_type ==				     DEVICE_TYPE_SERIAL))				{					/* iv_timeout between 2 chars, send partial_len */					/*printf("RDPDR: IVT total %u bytes read of %u\n", iorq->partial_len, iorq->length); */					rdpdr_send_completion(iorq->device,							      iorq->id, STATUS_SUCCESS,							      iorq->partial_len,							      iorq->buffer, iorq->partial_len);					iorq = rdpdr_remove_iorequest(prev, iorq);					return;				}				else				{					break;				}			}			else			{				break;			}			prev = iorq;			if (iorq)				iorq = iorq->next;		}		rdpdr_abort_io(g_min_timeout_fd, 0, STATUS_TIMEOUT);		return;	}	iorq = g_iorequest;	prev = NULL;	while (iorq != NULL)	{		if (iorq->fd != 0)		{			switch (iorq->major)			{				case IRP_MJ_READ:					if (FD_ISSET(iorq->fd, rfds))					{						/* Read the data */						fns = iorq->fns;						req_size =							(iorq->length - iorq->partial_len) >							8192 ? 8192 : (iorq->length -								       iorq->partial_len);						/* never read larger chunks than 8k - chances are that it will block */						status = fns->read(iorq->fd,								   iorq->buffer + iorq->partial_len,								   req_size, iorq->offset, &result);						if ((long) result > 0)						{							iorq->partial_len += result;							iorq->offset += result;						}#if WITH_DEBUG_RDP5						DEBUG(("RDPDR: %d bytes of data read\n", result));#endif						/* only delete link if all data has been transfered */						/* or if result was 0 and status success - EOF      */						if ((iorq->partial_len == iorq->length) ||						    (result == 0))						{#if WITH_DEBUG_RDP5							DEBUG(("RDPDR: AIO total %u bytes read of %u\n", iorq->partial_len, iorq->length));#endif							rdpdr_send_completion(iorq->device,									      iorq->id, status,									      iorq->partial_len,									      iorq->buffer,									      iorq->partial_len);							iorq = rdpdr_remove_iorequest(prev, iorq);						}					}					break;				case IRP_MJ_WRITE:					if (FD_ISSET(iorq->fd, wfds))					{						/* Write data. */						fns = iorq->fns;						req_size =							(iorq->length - iorq->partial_len) >							8192 ? 8192 : (iorq->length -								       iorq->partial_len);						/* never write larger chunks than 8k - chances are that it will block */						status = fns->write(iorq->fd,								    iorq->buffer +								    iorq->partial_len, req_size,								    iorq->offset, &result);						if ((long) result > 0)						{							iorq->partial_len += result;							iorq->offset += result;						}#if WITH_DEBUG_RDP5						DEBUG(("RDPDR: %d bytes of data written\n",						       result));#endif						/* only delete link if all data has been transfered */						/* or we couldn't write */						if ((iorq->partial_len == iorq->length)						    || (result == 0))						{#if WITH_DEBUG_RDP5							DEBUG(("RDPDR: AIO total %u bytes written of %u\n", iorq->partial_len, iorq->length));#endif							rdpdr_send_completion(iorq->device,									      iorq->id, status,									      iorq->partial_len,									      (uint8 *) "", 1);							iorq = rdpdr_remove_iorequest(prev, iorq);						}					}					break;				case IRP_MJ_DEVICE_CONTROL:					if (serial_get_event(iorq->fd, &result))					{						buffer = (uint8 *) xrealloc((void *) buffer, 0x14);						out.data = out.p = buffer;						out.size = sizeof(buffer);						out_uint32_le(&out, result);						result = buffer_len = out.p - out.data;						status = STATUS_SUCCESS;						rdpdr_send_completion(iorq->device, iorq->id,								      status, result, buffer,								      buffer_len);						xfree(buffer);						iorq = rdpdr_remove_iorequest(prev, iorq);					}					break;			}		}		prev = iorq;		if (iorq)			iorq = iorq->next;	}	/* Check notify */	iorq = g_iorequest;	prev = NULL;	while (iorq != NULL)	{		if (iorq->fd != 0)		{			switch (iorq->major)			{				case IRP_MJ_DIRECTORY_CONTROL:					if (g_rdpdr_device[iorq->device].device_type ==					    DEVICE_TYPE_DISK)					{						if (g_notify_stamp)						{							g_notify_stamp = False;							status = disk_check_notify(iorq->fd);							if (status != STATUS_PENDING)							{								rdpdr_send_completion(iorq->device,										      iorq->id,										      status, 0,										      NULL, 0);								iorq = rdpdr_remove_iorequest(prev,											      iorq);							}						}					}					break;			}		}		prev = iorq;		if (iorq)			iorq = iorq->next;	}}voidrdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out){	fd_set dummy;	FD_ZERO(&dummy);	/* fist check event queue only,	   any serial wait event must be done before read block will be sent	 */	_rdpdr_check_fds(&dummy, &dummy, False);	_rdpdr_check_fds(rfds, wfds, timed_out);}/* Abort a pending io request for a given handle and major */BOOLrdpdr_abort_io(uint32 fd, uint32 major, NTSTATUS status){	uint32 result;	struct async_iorequest *iorq;	struct async_iorequest *prev;	iorq = g_iorequest;	prev = NULL;	while (iorq != NULL)	{		/* Only remove from table when major is not set, or when correct major is supplied.		   Abort read should not abort a write io request. */		if ((iorq->fd == fd) && (major == 0 || iorq->major == major))		{			result = 0;			rdpdr_send_completion(iorq->device, iorq->id, status, result, (uint8 *) "",					      1);			iorq = rdpdr_remove_iorequest(prev, iorq);			return True;		}		prev = iorq;		iorq = iorq->next;	}	return False;}

⌨️ 快捷键说明

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