Merge pull request #33 from llyzs/svc
rdpdr: completing main module and creating initial disk module sketelon
This commit is contained in:
commit
109e79a030
@ -20,4 +20,5 @@
|
||||
add_subdirectory(cliprdr)
|
||||
add_subdirectory(drdynvc)
|
||||
add_subdirectory(rdpdbg)
|
||||
add_subdirectory(rdpdr)
|
||||
|
||||
|
@ -44,7 +44,7 @@ struct _DVCMAN
|
||||
IWTSListener* listeners[MAX_PLUGINS];
|
||||
int num_listeners;
|
||||
|
||||
struct dvcman_channel_list* channels;
|
||||
LIST* channels;
|
||||
};
|
||||
|
||||
typedef struct _DVCMAN_LISTENER DVCMAN_LISTENER;
|
||||
@ -80,13 +80,6 @@ struct _DVCMAN_CHANNEL
|
||||
STREAM* dvc_data;
|
||||
};
|
||||
|
||||
struct dvcman_channel_list_item
|
||||
{
|
||||
DVCMAN_CHANNEL channel;
|
||||
};
|
||||
|
||||
DEFINE_LIST_TYPE(dvcman_channel_list, dvcman_channel_list_item)
|
||||
|
||||
static int dvcman_get_configuration(IWTSListener* pListener,
|
||||
void** ppPropertyBag)
|
||||
{
|
||||
@ -192,7 +185,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
|
||||
dvcman->iface.CreateListener = dvcman_create_listener;
|
||||
dvcman->iface.PushEvent = dvcman_push_event;
|
||||
dvcman->drdynvc = plugin;
|
||||
dvcman->channels = dvcman_channel_list_new();
|
||||
dvcman->channels = list_new();
|
||||
|
||||
return (IWTSVirtualChannelManager*)dvcman;
|
||||
}
|
||||
@ -220,14 +213,24 @@ int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, FRDP_PLUGIN_DATA*
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dvcman_channel_free(DVCMAN_CHANNEL* channel)
|
||||
{
|
||||
if (channel->channel_callback)
|
||||
channel->channel_callback->OnClose(channel->channel_callback);
|
||||
xfree(channel);
|
||||
}
|
||||
|
||||
void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
|
||||
{
|
||||
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
|
||||
int i;
|
||||
IWTSPlugin* pPlugin;
|
||||
DVCMAN_LISTENER* listener;
|
||||
DVCMAN_CHANNEL* channel;
|
||||
|
||||
dvcman_channel_list_free(dvcman->channels);
|
||||
while ((channel = (DVCMAN_CHANNEL*)list_dequeue(dvcman->channels)) != NULL)
|
||||
dvcman_channel_free(channel);
|
||||
list_free(dvcman->channels);
|
||||
for (i = 0; i < dvcman->num_listeners; i++)
|
||||
{
|
||||
listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
|
||||
@ -268,15 +271,6 @@ static int dvcman_write_channel(IWTSVirtualChannel* pChannel,
|
||||
return drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
|
||||
}
|
||||
|
||||
static void dvcman_channel_list_item_free(struct dvcman_channel_list_item* item)
|
||||
{
|
||||
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)item;
|
||||
|
||||
if (channel->channel_callback)
|
||||
channel->channel_callback->OnClose(channel->channel_callback);
|
||||
xfree(item);
|
||||
}
|
||||
|
||||
static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
|
||||
{
|
||||
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)pChannel;
|
||||
@ -284,9 +278,9 @@ static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
|
||||
|
||||
DEBUG_DVC("id=%d", channel->channel_id);
|
||||
|
||||
if (dvcman_channel_list_remove(dvcman->channels, (struct dvcman_channel_list_item*)channel) == NULL)
|
||||
if (list_remove(dvcman->channels, channel) == NULL)
|
||||
DEBUG_WARN("channel not found");
|
||||
dvcman_channel_list_item_free((struct dvcman_channel_list_item*)channel);
|
||||
dvcman_channel_free(channel);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -297,7 +291,6 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel
|
||||
int i;
|
||||
DVCMAN_LISTENER* listener;
|
||||
DVCMAN_CHANNEL* channel;
|
||||
struct dvcman_channel_list_item* item;
|
||||
int bAccept;
|
||||
IWTSVirtualChannelCallback* pCallback;
|
||||
|
||||
@ -306,8 +299,7 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel
|
||||
listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
|
||||
if (strcmp(listener->channel_name, ChannelName) == 0)
|
||||
{
|
||||
item = dvcman_channel_list_item_new();
|
||||
channel = (DVCMAN_CHANNEL*)item;
|
||||
channel = xnew(DVCMAN_CHANNEL);
|
||||
channel->iface.Write = dvcman_write_channel;
|
||||
channel->iface.Close = dvcman_close_channel_iface;
|
||||
channel->dvcman = dvcman;
|
||||
@ -321,13 +313,13 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel
|
||||
DEBUG_DVC("listener %s created new channel %d",
|
||||
listener->channel_name, channel->channel_id);
|
||||
channel->channel_callback = pCallback;
|
||||
dvcman_channel_list_add(dvcman->channels, item);
|
||||
list_add(dvcman->channels, channel);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_WARN("channel rejected by plugin");
|
||||
dvcman_channel_list_item_free(item);
|
||||
dvcman_channel_free(channel);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -338,13 +330,13 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel
|
||||
static DVCMAN_CHANNEL* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId)
|
||||
{
|
||||
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
|
||||
struct dvcman_channel_list_item* curr;
|
||||
LIST_ITEM* curr;
|
||||
|
||||
for (curr = dvcman->channels->head; curr; curr = dvcman_channel_list_item_next(curr))
|
||||
for (curr = dvcman->channels->head; curr; curr = curr->next)
|
||||
{
|
||||
if (((DVCMAN_CHANNEL*)curr)->channel_id == ChannelId)
|
||||
if (((DVCMAN_CHANNEL*)curr->data)->channel_id == ChannelId)
|
||||
{
|
||||
return (DVCMAN_CHANNEL*)curr;
|
||||
return (DVCMAN_CHANNEL*)curr->data;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
40
channels/rdpdr/CMakeLists.txt
Normal file
40
channels/rdpdr/CMakeLists.txt
Normal file
@ -0,0 +1,40 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Client
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2011 O.S. Systems Software Ltda.
|
||||
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
|
||||
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(RDPDR_SRCS
|
||||
rdpdr_constants.h
|
||||
rdpdr_types.h
|
||||
rdpdr_capabilities.c
|
||||
rdpdr_capabilities.h
|
||||
devman.c
|
||||
devman.h
|
||||
irp.c
|
||||
irp.h
|
||||
rdpdr_main.c
|
||||
rdpdr_main.h
|
||||
)
|
||||
|
||||
add_library(rdpdr SHARED ${RDPDR_SRCS})
|
||||
set_target_properties(rdpdr PROPERTIES PREFIX "")
|
||||
|
||||
target_link_libraries(rdpdr freerdp-utils)
|
||||
|
||||
install(TARGETS rdpdr DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
|
||||
add_subdirectory(disk)
|
103
channels/rdpdr/devman.c
Normal file
103
channels/rdpdr/devman.c
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
|
||||
#include "rdpdr_types.h"
|
||||
#include "devman.h"
|
||||
|
||||
DEVMAN* devman_new(rdpSvcPlugin* plugin)
|
||||
{
|
||||
DEVMAN* devman;
|
||||
|
||||
devman = xnew(DEVMAN);
|
||||
devman->plugin = plugin;
|
||||
devman->id_sequence = 1;
|
||||
devman->devices = list_new();
|
||||
|
||||
return devman;
|
||||
}
|
||||
|
||||
void devman_free(DEVMAN* devman)
|
||||
{
|
||||
DEVICE* device;
|
||||
|
||||
while ((device = (DEVICE*)list_dequeue(devman->devices)) != NULL)
|
||||
IFCALL(device->Free, device);
|
||||
list_free(devman->devices);
|
||||
xfree(devman);
|
||||
}
|
||||
|
||||
static void devman_register_device(DEVMAN* devman, DEVICE* device)
|
||||
{
|
||||
device->id = devman->id_sequence++;
|
||||
list_add(devman->devices, device);
|
||||
|
||||
DEBUG_SVC("device %d.%s registered", device->id, device->name);
|
||||
}
|
||||
|
||||
static void devman_unregister_device(DEVMAN* devman, DEVICE* device)
|
||||
{
|
||||
list_remove(devman->devices, device);
|
||||
|
||||
DEBUG_SVC("device %d.%s unregistered", device->id, device->name);
|
||||
}
|
||||
|
||||
boolean devman_load_device_service(DEVMAN* devman, FRDP_PLUGIN_DATA* plugin_data)
|
||||
{
|
||||
DEVICE_SERVICE_ENTRY_POINTS ep;
|
||||
PDEVICE_SERVICE_ENTRY entry;
|
||||
|
||||
entry = freerdp_load_plugin((char*)plugin_data->data[0], "DeviceServiceEntry");
|
||||
if (entry == NULL)
|
||||
return False;
|
||||
|
||||
ep.devman = devman;
|
||||
ep.RegisterDevice = devman_register_device;
|
||||
ep.UnregisterDevice = devman_unregister_device;
|
||||
ep.plugin_data = plugin_data;
|
||||
|
||||
entry(&ep);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
DEVICE* devman_get_device_by_id(DEVMAN* devman, uint32 id)
|
||||
{
|
||||
LIST_ITEM* item;
|
||||
DEVICE* device;
|
||||
|
||||
for (item = devman->devices->head; item; item = item->next)
|
||||
{
|
||||
device = (DEVICE*)item->data;
|
||||
if (device->id == id)
|
||||
return device;
|
||||
}
|
||||
return NULL;
|
||||
}
|
29
channels/rdpdr/devman.h
Normal file
29
channels/rdpdr/devman.h
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __DEVMAN_H
|
||||
#define __DEVMAN_H
|
||||
|
||||
DEVMAN* devman_new(rdpSvcPlugin* plugin);
|
||||
void devman_free(DEVMAN* devman);
|
||||
boolean devman_load_device_service(DEVMAN* devman, FRDP_PLUGIN_DATA* plugin_data);
|
||||
DEVICE* devman_get_device_by_id(DEVMAN* devman, uint32 id);
|
||||
|
||||
#endif /* __DEVMAN_H */
|
31
channels/rdpdr/disk/CMakeLists.txt
Normal file
31
channels/rdpdr/disk/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Client
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2011 O.S. Systems Software Ltda.
|
||||
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
|
||||
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(DISK_SRCS
|
||||
disk_main.c
|
||||
)
|
||||
|
||||
include_directories(..)
|
||||
|
||||
add_library(disk SHARED ${DISK_SRCS})
|
||||
set_target_properties(disk PROPERTIES PREFIX "")
|
||||
|
||||
target_link_libraries(disk freerdp-utils)
|
||||
|
||||
install(TARGETS disk DESTINATION ${FREERDP_PLUGIN_PATH})
|
116
channels/rdpdr/disk/disk_main.c
Normal file
116
channels/rdpdr/disk/disk_main.c
Normal file
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <utime.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "rdpdr_constants.h"
|
||||
#include "rdpdr_types.h"
|
||||
|
||||
typedef struct _FILE_INFO FILE_INFO;
|
||||
struct _FILE_INFO
|
||||
{
|
||||
uint32 file_id;
|
||||
uint32 file_attr;
|
||||
boolean is_dir;
|
||||
int fd;
|
||||
DIR* dir;
|
||||
char* fullpath;
|
||||
char* pattern;
|
||||
boolean delete_pending;
|
||||
};
|
||||
|
||||
typedef struct _DISK_DEVICE DISK_DEVICE;
|
||||
struct _DISK_DEVICE
|
||||
{
|
||||
DEVICE device;
|
||||
|
||||
char* path;
|
||||
LIST* files;
|
||||
};
|
||||
|
||||
void disk_irp_request(DEVICE* device, IRP* irp)
|
||||
{
|
||||
DISK_DEVICE* disk = (DISK_DEVICE*)device;
|
||||
|
||||
IFCALL(irp->Complete, irp);
|
||||
}
|
||||
|
||||
void disk_free(DEVICE* device)
|
||||
{
|
||||
DISK_DEVICE* disk = (DISK_DEVICE*)device;
|
||||
|
||||
list_free(disk->files);
|
||||
xfree(disk);
|
||||
}
|
||||
|
||||
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
DISK_DEVICE* disk;
|
||||
char* name;
|
||||
char* path;
|
||||
int i, len;
|
||||
|
||||
name = (char*)pEntryPoints->plugin_data->data[1];
|
||||
path = (char*)pEntryPoints->plugin_data->data[2];
|
||||
|
||||
if (name[0] && path[0])
|
||||
{
|
||||
disk = xnew(DISK_DEVICE);
|
||||
|
||||
disk->device.type = RDPDR_DTYP_FILESYSTEM;
|
||||
disk->device.name = name;
|
||||
disk->device.IRPRequest = disk_irp_request;
|
||||
disk->device.Free = disk_free;
|
||||
|
||||
len = strlen(name);
|
||||
disk->device.data = stream_new(len + 1);
|
||||
for (i = 0; i <= len; i++)
|
||||
stream_write_uint8(disk->device.data, name[i] < 0 ? '_' : name[i]);
|
||||
|
||||
disk->path = path;
|
||||
disk->files = list_new();
|
||||
|
||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)disk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
97
channels/rdpdr/irp.c
Normal file
97
channels/rdpdr/irp.c
Normal file
@ -0,0 +1,97 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "rdpdr_types.h"
|
||||
#include "rdpdr_constants.h"
|
||||
#include "devman.h"
|
||||
#include "irp.h"
|
||||
|
||||
static void irp_free(IRP* irp)
|
||||
{
|
||||
DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId);
|
||||
|
||||
stream_free(irp->input);
|
||||
stream_free(irp->output);
|
||||
xfree(irp);
|
||||
}
|
||||
|
||||
static void irp_complete(IRP* irp)
|
||||
{
|
||||
int pos;
|
||||
|
||||
DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId);
|
||||
|
||||
pos = stream_get_pos(irp->output);
|
||||
stream_set_pos(irp->output, 12);
|
||||
stream_write_uint32(irp->output, irp->IoStatus);
|
||||
stream_set_pos(irp->output, pos);
|
||||
|
||||
svc_plugin_send(irp->devman->plugin, irp->output);
|
||||
irp->output = NULL;
|
||||
|
||||
irp_free(irp);
|
||||
}
|
||||
|
||||
IRP* irp_new(DEVMAN* devman, STREAM* data_in)
|
||||
{
|
||||
IRP* irp;
|
||||
uint32 DeviceId;
|
||||
DEVICE* device;
|
||||
|
||||
stream_read_uint32(data_in, DeviceId);
|
||||
device = devman_get_device_by_id(devman, DeviceId);
|
||||
if (device == NULL)
|
||||
{
|
||||
DEBUG_WARN("unknown DeviceId %d", DeviceId);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
irp = xnew(IRP);
|
||||
irp->device = device;
|
||||
irp->devman = devman;
|
||||
stream_read_uint32(data_in, irp->FileId);
|
||||
stream_read_uint32(data_in, irp->CompletionId);
|
||||
stream_read_uint32(data_in, irp->MajorFunction);
|
||||
stream_read_uint32(data_in, irp->MinorFunction);
|
||||
irp->input = data_in;
|
||||
|
||||
irp->output = stream_new(256);
|
||||
stream_write_uint16(irp->output, RDPDR_CTYP_CORE);
|
||||
stream_write_uint16(irp->output, PAKID_CORE_DEVICE_IOCOMPLETION);
|
||||
stream_write_uint32(irp->output, DeviceId);
|
||||
stream_write_uint32(irp->output, irp->CompletionId);
|
||||
stream_seek_uint32(irp->output); /* IoStatus */
|
||||
|
||||
irp->Complete = irp_complete;
|
||||
irp->Discard = irp_free;
|
||||
|
||||
DEBUG_SVC("DeviceId %d FileId %d CompletionId %d MajorFunction 0x%X MinorFunction 0x%x",
|
||||
irp->device->id, irp->FileId, irp->CompletionId, irp->MajorFunction, irp->MinorFunction);
|
||||
|
||||
return irp;
|
||||
}
|
28
channels/rdpdr/irp.h
Normal file
28
channels/rdpdr/irp.h
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __IRP_H
|
||||
#define __IRP_H
|
||||
|
||||
#include "rdpdr_types.h"
|
||||
|
||||
IRP* irp_new(DEVMAN* devman, STREAM* data_in);
|
||||
|
||||
#endif /* __IRP_H */
|
187
channels/rdpdr/rdpdr_capabilities.c
Normal file
187
channels/rdpdr/rdpdr_capabilities.c
Normal file
@ -0,0 +1,187 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "rdpdr_types.h"
|
||||
#include "rdpdr_constants.h"
|
||||
#include "rdpdr_capabilities.h"
|
||||
|
||||
/* Output device redirection capability set header */
|
||||
static void rdpdr_write_capset_header(STREAM* data_out, uint16 capabilityType, uint16 capabilityLength, uint32 version)
|
||||
{
|
||||
stream_write_uint16(data_out, capabilityType);
|
||||
stream_write_uint16(data_out, capabilityLength);
|
||||
stream_write_uint32(data_out, version);
|
||||
}
|
||||
|
||||
/* Output device direction general capability set */
|
||||
static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, STREAM* data_out)
|
||||
{
|
||||
rdpdr_write_capset_header(data_out, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02);
|
||||
|
||||
stream_write_uint32(data_out, 0); /* osType, ignored on receipt */
|
||||
stream_write_uint32(data_out, 0); /* osVersion, unused and must be set to zero */
|
||||
stream_write_uint16(data_out, 1); /* protocolMajorVersion, must be set to 1 */
|
||||
stream_write_uint16(data_out, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */
|
||||
stream_write_uint32(data_out, 0x0000FFFF); /* ioCode1 */
|
||||
stream_write_uint32(data_out, 0); /* ioCode2, must be set to zero, reserved for future use */
|
||||
stream_write_uint32(data_out, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
|
||||
stream_write_uint32(data_out, ENABLE_ASYNCIO); /* extraFlags1 */
|
||||
stream_write_uint32(data_out, 0); /* extraFlags2, must be set to zero, reserved for future use */
|
||||
stream_write_uint32(data_out, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */
|
||||
}
|
||||
|
||||
/* Process device direction general capability set */
|
||||
static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, STREAM* data_in)
|
||||
{
|
||||
uint16 capabilityLength;
|
||||
|
||||
stream_read_uint16(data_in, capabilityLength);
|
||||
stream_seek(data_in, capabilityLength - 4);
|
||||
}
|
||||
|
||||
/* Output printer direction capability set */
|
||||
static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, STREAM* data_out)
|
||||
{
|
||||
rdpdr_write_capset_header(data_out, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01);
|
||||
}
|
||||
|
||||
/* Process printer direction capability set */
|
||||
static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, STREAM* data_in)
|
||||
{
|
||||
uint16 capabilityLength;
|
||||
|
||||
stream_read_uint16(data_in, capabilityLength);
|
||||
stream_seek(data_in, capabilityLength - 4);
|
||||
}
|
||||
|
||||
/* Output port redirection capability set */
|
||||
static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, STREAM* data_out)
|
||||
{
|
||||
rdpdr_write_capset_header(data_out, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01);
|
||||
}
|
||||
|
||||
/* Process port redirection capability set */
|
||||
static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, STREAM* data_in)
|
||||
{
|
||||
uint16 capabilityLength;
|
||||
|
||||
stream_read_uint16(data_in, capabilityLength);
|
||||
stream_seek(data_in, capabilityLength - 4);
|
||||
}
|
||||
|
||||
/* Output drive redirection capability set */
|
||||
static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, STREAM* data_out)
|
||||
{
|
||||
rdpdr_write_capset_header(data_out, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02);
|
||||
}
|
||||
|
||||
/* Process drive redirection capability set */
|
||||
static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, STREAM* data_in)
|
||||
{
|
||||
uint16 capabilityLength;
|
||||
|
||||
stream_read_uint16(data_in, capabilityLength);
|
||||
stream_seek(data_in, capabilityLength - 4);
|
||||
}
|
||||
|
||||
/* Output smart card redirection capability set */
|
||||
static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, STREAM* data_out)
|
||||
{
|
||||
rdpdr_write_capset_header(data_out, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01);
|
||||
}
|
||||
|
||||
/* Process smartcard redirection capability set */
|
||||
static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, STREAM* data_in)
|
||||
{
|
||||
uint16 capabilityLength;
|
||||
|
||||
stream_read_uint16(data_in, capabilityLength);
|
||||
stream_seek(data_in, capabilityLength - 4);
|
||||
}
|
||||
|
||||
void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, STREAM* data_in)
|
||||
{
|
||||
uint16 i;
|
||||
uint16 numCapabilities;
|
||||
uint16 capabilityType;
|
||||
|
||||
stream_read_uint16(data_in, numCapabilities);
|
||||
stream_seek(data_in, 2); /* pad (2 bytes) */
|
||||
|
||||
for(i = 0; i < numCapabilities; i++)
|
||||
{
|
||||
stream_read_uint16(data_in, capabilityType);
|
||||
|
||||
switch (capabilityType)
|
||||
{
|
||||
case CAP_GENERAL_TYPE:
|
||||
rdpdr_process_general_capset(rdpdr, data_in);
|
||||
break;
|
||||
|
||||
case CAP_PRINTER_TYPE:
|
||||
rdpdr_process_printer_capset(rdpdr, data_in);
|
||||
break;
|
||||
|
||||
case CAP_PORT_TYPE:
|
||||
rdpdr_process_port_capset(rdpdr, data_in);
|
||||
break;
|
||||
|
||||
case CAP_DRIVE_TYPE:
|
||||
rdpdr_process_drive_capset(rdpdr, data_in);
|
||||
break;
|
||||
|
||||
case CAP_SMARTCARD_TYPE:
|
||||
rdpdr_process_smartcard_capset(rdpdr, data_in);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_WARN("Unknown capabilityType %d", capabilityType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rdpdr_send_capability_response(rdpdrPlugin* rdpdr)
|
||||
{
|
||||
STREAM* data_out;
|
||||
|
||||
data_out = stream_new(256);
|
||||
|
||||
stream_write_uint16(data_out, RDPDR_CTYP_CORE);
|
||||
stream_write_uint16(data_out, PAKID_CORE_CLIENT_CAPABILITY);
|
||||
|
||||
stream_write_uint16(data_out, 5); /* numCapabilities */
|
||||
stream_write_uint16(data_out, 0); /* pad */
|
||||
|
||||
rdpdr_write_general_capset(rdpdr, data_out);
|
||||
rdpdr_write_printer_capset(rdpdr, data_out);
|
||||
rdpdr_write_port_capset(rdpdr, data_out);
|
||||
rdpdr_write_drive_capset(rdpdr, data_out);
|
||||
rdpdr_write_smartcard_capset(rdpdr, data_out);
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out);
|
||||
}
|
29
channels/rdpdr/rdpdr_capabilities.h
Normal file
29
channels/rdpdr/rdpdr_capabilities.h
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __RDPDR_CAPABILITIES_H
|
||||
#define __RDPDR_CAPABILITIES_H
|
||||
|
||||
#include "rdpdr_main.h"
|
||||
|
||||
void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, STREAM* data_in);
|
||||
void rdpdr_send_capability_response(rdpdrPlugin* rdpdr);
|
||||
|
||||
#endif /* __RDPDR_CAPABILITIES_H */
|
442
channels/rdpdr/rdpdr_constants.h
Normal file
442
channels/rdpdr/rdpdr_constants.h
Normal file
@ -0,0 +1,442 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __RDPDR_CONSTANTS_H
|
||||
#define __RDPDR_CONSTANTS_H
|
||||
|
||||
/* RDPDR_HEADER.Component */
|
||||
enum RDPDR_CTYP
|
||||
{
|
||||
RDPDR_CTYP_CORE = 0x4472,
|
||||
RDPDR_CTYP_PRN = 0x5052
|
||||
};
|
||||
|
||||
/* RDPDR_HEADER.PacketId */
|
||||
enum RDPDR_PAKID
|
||||
{
|
||||
PAKID_CORE_SERVER_ANNOUNCE = 0x496E,
|
||||
PAKID_CORE_CLIENTID_CONFIRM = 0x4343,
|
||||
PAKID_CORE_CLIENT_NAME = 0x434E,
|
||||
PAKID_CORE_DEVICELIST_ANNOUNCE = 0x4441,
|
||||
PAKID_CORE_DEVICE_REPLY = 0x6472,
|
||||
PAKID_CORE_DEVICE_IOREQUEST = 0x4952,
|
||||
PAKID_CORE_DEVICE_IOCOMPLETION = 0x4943,
|
||||
PAKID_CORE_SERVER_CAPABILITY = 0x5350,
|
||||
PAKID_CORE_CLIENT_CAPABILITY = 0x4350,
|
||||
PAKID_CORE_DEVICELIST_REMOVE = 0x444D,
|
||||
PAKID_CORE_USER_LOGGEDON = 0x554C,
|
||||
PAKID_PRN_CACHE_DATA = 0x5043,
|
||||
PAKID_PRN_USING_XPS = 0x5543
|
||||
};
|
||||
|
||||
/* CAPABILITY_HEADER.CapabilityType */
|
||||
enum RDPDR_CAP_TYPE
|
||||
{
|
||||
CAP_GENERAL_TYPE = 0x0001,
|
||||
CAP_PRINTER_TYPE = 0x0002,
|
||||
CAP_PORT_TYPE = 0x0003,
|
||||
CAP_DRIVE_TYPE = 0x0004,
|
||||
CAP_SMARTCARD_TYPE = 0x0005
|
||||
};
|
||||
|
||||
/* CAPABILITY_HEADER.Version */
|
||||
enum RDPDR_CAP_VERSION
|
||||
{
|
||||
GENERAL_CAPABILITY_VERSION_01 = 0x00000001,
|
||||
GENERAL_CAPABILITY_VERSION_02 = 0x00000002,
|
||||
PRINT_CAPABILITY_VERSION_01 = 0x00000001,
|
||||
PORT_CAPABILITY_VERSION_01 = 0x00000001,
|
||||
DRIVE_CAPABILITY_VERSION_01 = 0x00000001,
|
||||
DRIVE_CAPABILITY_VERSION_02 = 0x00000002,
|
||||
SMARTCARD_CAPABILITY_VERSION_01 = 0x00000001
|
||||
};
|
||||
|
||||
/* DEVICE_ANNOUNCE.DeviceType */
|
||||
enum RDPDR_DTYP
|
||||
{
|
||||
RDPDR_DTYP_SERIAL = 0x00000001,
|
||||
RDPDR_DTYP_PARALLEL = 0x00000002,
|
||||
RDPDR_DTYP_PRINT = 0x00000004,
|
||||
RDPDR_DTYP_FILESYSTEM = 0x00000008,
|
||||
RDPDR_DTYP_SMARTCARD = 0x00000020
|
||||
};
|
||||
|
||||
/* DR_DEVICE_IOREQUEST.MajorFunction */
|
||||
enum IRP_MJ
|
||||
{
|
||||
IRP_MJ_CREATE = 0x00000000,
|
||||
IRP_MJ_CLOSE = 0x00000002,
|
||||
IRP_MJ_READ = 0x00000003,
|
||||
IRP_MJ_WRITE = 0x00000004,
|
||||
IRP_MJ_DEVICE_CONTROL = 0x0000000E,
|
||||
IRP_MJ_QUERY_VOLUME_INFORMATION = 0x0000000A,
|
||||
IRP_MJ_SET_VOLUME_INFORMATION = 0x0000000B,
|
||||
IRP_MJ_QUERY_INFORMATION = 0x00000005,
|
||||
IRP_MJ_SET_INFORMATION = 0x00000006,
|
||||
IRP_MJ_DIRECTORY_CONTROL = 0x0000000C,
|
||||
IRP_MJ_LOCK_CONTROL = 0x00000011
|
||||
};
|
||||
|
||||
/* DR_DEVICE_IOREQUEST.MinorFunction */
|
||||
enum IRP_MN
|
||||
{
|
||||
IRP_MN_QUERY_DIRECTORY = 0x00000001,
|
||||
IRP_MN_NOTIFY_CHANGE_DIRECTORY = 0x00000002
|
||||
};
|
||||
|
||||
/* DR_CREATE_REQ.CreateDisposition */
|
||||
enum FILE_CREATE_DISPOSITION
|
||||
{
|
||||
FILE_SUPERSEDE = 0x00000000,
|
||||
FILE_OPEN = 0x00000001,
|
||||
FILE_CREATE = 0x00000002,
|
||||
FILE_OPEN_IF = 0x00000003,
|
||||
FILE_OVERWRITE = 0x00000004,
|
||||
FILE_OVERWRITE_IF = 0x00000005
|
||||
};
|
||||
|
||||
/* DR_CREATE_REQ.CreateOptions [MS-SMB2] */
|
||||
enum FILE_CREATE_OPTION
|
||||
{
|
||||
FILE_DIRECTORY_FILE = 0x00000001,
|
||||
FILE_NON_DIRECTORY_FILE = 0x00000040,
|
||||
FILE_COMPLETE_IF_OPLOCKED = 0x00000100,
|
||||
FILE_DELETE_ON_CLOSE = 0x00001000,
|
||||
FILE_OPEN_REPARSE_POINT = 0x00200000,
|
||||
FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000
|
||||
};
|
||||
|
||||
/* DR_CREATE_REQ.DesiredAccess [MS-SMB2] */
|
||||
enum FILE_ACCESS
|
||||
{
|
||||
FILE_READ_DATA = 0x00000001,
|
||||
FILE_WRITE_DATA = 0x00000002,
|
||||
FILE_APPEND_DATA = 0x00000004,
|
||||
FILE_READ_EA = 0x00000008,
|
||||
FILE_WRITE_EA = 0x00000010,
|
||||
FILE_EXECUTE = 0x00000020,
|
||||
FILE_READ_ATTRIBUTES = 0x00000080,
|
||||
FILE_WRITE_ATTRIBUTES = 0x00000100,
|
||||
DELETE = 0x00010000,
|
||||
READ_CONTROL = 0x00020000,
|
||||
WRITE_DAC = 0x00040000,
|
||||
WRITE_OWNER = 0x00080000,
|
||||
SYNCHRONIZE = 0x00100000,
|
||||
ACCESS_SYSTEM_SECURITY = 0x01000000,
|
||||
MAXIMUM_ALLOWED = 0x02000000,
|
||||
GENERIC_ALL = 0x10000000,
|
||||
GENERIC_EXECUTE = 0x20000000,
|
||||
GENERIC_WRITE = 0x40000000,
|
||||
GENERIC_READ = 0x80000000
|
||||
};
|
||||
|
||||
/* DR_CREATE_RSP.Information */
|
||||
/* DR_DRIVE_CREATE_RSP.DeviceCreateResponse */
|
||||
enum FILE_RESPONSE
|
||||
{
|
||||
FILE_SUPERSEDED = 0x00000000,
|
||||
FILE_OPENED = 0x00000001,
|
||||
FILE_OVERWRITTEN = 0x00000003
|
||||
};
|
||||
|
||||
/* DR_CORE_CLIENT_ANNOUNCE_RSP.VersionMinor */
|
||||
enum RDPDR_MINOR_RDP_VERSION
|
||||
{
|
||||
RDPDR_MINOR_RDP_VERSION_5_0 = 0x0002,
|
||||
RDPDR_MINOR_RDP_VERSION_5_1 = 0x0005,
|
||||
RDPDR_MINOR_RDP_VERSION_5_2 = 0x000A,
|
||||
RDPDR_MINOR_RDP_VERSION_6_X = 0x000C
|
||||
};
|
||||
|
||||
/* DR_CORE_CLIENT_NAME_REQ.UnicodeFlag */
|
||||
enum RDPDR_CLIENT_NAME_FLAG
|
||||
{
|
||||
RDPDR_CLIENT_NAME_UNICODE = 0x00000001,
|
||||
RDPDR_CLIENT_NAME_ASCII = 0x00000000
|
||||
};
|
||||
|
||||
/* GENERAL_CAPS_SET.ioCode1 */
|
||||
enum RDPDR_CAPS_IRP_MJ
|
||||
{
|
||||
RDPDR_IRP_MJ_CREATE = 0x00000001,
|
||||
RDPDR_IRP_MJ_CLEANUP = 0x00000002,
|
||||
RDPDR_IRP_MJ_CLOSE = 0x00000004,
|
||||
RDPDR_IRP_MJ_READ = 0x00000008,
|
||||
RDPDR_IRP_MJ_WRITE = 0x00000010,
|
||||
RDPDR_IRP_MJ_FLUSH_BUFFERS = 0x00000020,
|
||||
RDPDR_IRP_MJ_SHUTDOWN = 0x00000040,
|
||||
RDPDR_IRP_MJ_DEVICE_CONTROL = 0x00000080,
|
||||
RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION = 0x00000100,
|
||||
RDPDR_IRP_MJ_SET_VOLUME_INFORMATION = 0x00000200,
|
||||
RDPDR_IRP_MJ_QUERY_INFORMATION = 0x00000400,
|
||||
RDPDR_IRP_MJ_SET_INFORMATION = 0x00000800,
|
||||
RDPDR_IRP_MJ_DIRECTORY_CONTROL = 0x00001000,
|
||||
RDPDR_IRP_MJ_LOCK_CONTROL = 0x00002000,
|
||||
RDPDR_IRP_MJ_QUERY_SECURITY = 0x00004000,
|
||||
RDPDR_IRP_MJ_SET_SECURITY = 0x00008000
|
||||
};
|
||||
|
||||
/* GENERAL_CAPS_SET.extendedPDU */
|
||||
enum RDPDR_CAPS_PDU
|
||||
{
|
||||
RDPDR_DEVICE_REMOVE_PDUS = 0x00000001,
|
||||
RDPDR_CLIENT_DISPLAY_NAME_PDU = 0x00000002,
|
||||
RDPDR_USER_LOGGEDON_PDU = 0x00000004
|
||||
};
|
||||
|
||||
/* GENERAL_CAPS_SET.extraFlags1 */
|
||||
enum RDPDR_CAPS_FLAG
|
||||
{
|
||||
ENABLE_ASYNCIO = 0x00000001
|
||||
};
|
||||
|
||||
/* DR_DRIVE_LOCK_REQ.Operation */
|
||||
enum RDP_LOWIO_OP
|
||||
{
|
||||
RDP_LOWIO_OP_SHAREDLOCK = 0x00000002,
|
||||
RDP_LOWIO_OP_EXCLUSIVELOCK = 0x00000003,
|
||||
RDP_LOWIO_OP_UNLOCK = 0x00000004,
|
||||
RDP_LOWIO_OP_UNLOCK_MULTIPLE = 0x00000005
|
||||
};
|
||||
|
||||
/* NTSTATUS values */
|
||||
/* http://msdn.microsoft.com/en-us/library/cc704588.aspx */
|
||||
enum NTSTATUS
|
||||
{
|
||||
STATUS_SUCCESS = 0x00000000,
|
||||
STATUS_TIMEOUT = 0x00000102,
|
||||
STATUS_PENDING = 0x00000103,
|
||||
STATUS_REPARSE = 0x00000104,
|
||||
STATUS_MORE_ENTRIES = 0x00000105,
|
||||
STATUS_NOT_ALL_ASSIGNED = 0x00000106,
|
||||
STATUS_OPLOCK_BREAK_IN_PROGRESS = 0x00000108,
|
||||
STATUS_VOLUME_MOUNTED = 0x00000109,
|
||||
STATUS_NOTIFY_CLEANUP = 0x0000010B,
|
||||
STATUS_NOTIFY_ENUM_DIR = 0x0000010C,
|
||||
STATUS_NO_QUOTAS_FOR_ACCOUNT = 0x0000010D,
|
||||
STATUS_FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A,
|
||||
STATUS_FILE_LOCKED_WITH_WRITERS = 0x0000012B,
|
||||
STATUS_WAIT_FOR_OPLOCK = 0x00000367,
|
||||
STATUS_OBJECT_NAME_EXISTS = 0x40000000,
|
||||
STATUS_BAD_CURRENT_DIRECTORY = 0x40000007,
|
||||
STATUS_NO_MORE_FILES = 0x80000006,
|
||||
STATUS_DEVICE_PAPER_EMPTY = 0x8000000E,
|
||||
STATUS_DEVICE_POWERED_OFF = 0x8000000F,
|
||||
STATUS_DEVICE_OFF_LINE = 0x80000010,
|
||||
STATUS_DEVICE_BUSY = 0x80000011,
|
||||
STATUS_NO_MORE_ENTRIES = 0x8000001A,
|
||||
STATUS_UNSUCCESSFUL = 0xC0000001,
|
||||
STATUS_NOT_IMPLEMENTED = 0xC0000002,
|
||||
STATUS_INVALID_INFO_CLASS = 0xC0000003,
|
||||
STATUS_INVALID_HANDLE = 0xC0000008,
|
||||
STATUS_INVALID_PARAMETER = 0xC000000D,
|
||||
STATUS_NO_SUCH_DEVICE = 0xC000000E,
|
||||
STATUS_NO_SUCH_FILE = 0xC000000F,
|
||||
STATUS_INVALID_DEVICE_REQUEST = 0xC0000010,
|
||||
STATUS_END_OF_FILE = 0xC0000011,
|
||||
STATUS_NO_MEDIA_IN_DEVICE = 0xC0000013,
|
||||
STATUS_UNRECOGNIZED_MEDIA = 0xC0000014,
|
||||
STATUS_ACCESS_DENIED = 0xc0000022,
|
||||
STATUS_OBJECT_NAME_INVALID = 0xC0000033,
|
||||
STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034,
|
||||
STATUS_OBJECT_NAME_COLLISION = 0xc0000035,
|
||||
STATUS_PORT_DISCONNECTED = 0xC0000037,
|
||||
STATUS_OBJECT_PATH_INVALID = 0xC0000039,
|
||||
STATUS_OBJECT_PATH_NOT_FOUND = 0xC000003A,
|
||||
STATUS_INVALID_PORT_HANDLE = 0xC0000042,
|
||||
STATUS_DELETE_PENDING = 0xC0000056,
|
||||
STATUS_DISK_FULL = 0xC000007F,
|
||||
STATUS_DEVICE_NOT_READY = 0xC00000A3,
|
||||
STATUS_IO_TIMEOUT = 0xC00000B5,
|
||||
STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA,
|
||||
STATUS_NOT_SUPPORTED = 0xC00000BB,
|
||||
STATUS_PRINT_QUEUE_FULL = 0xC00000C6,
|
||||
STATUS_PRINT_CANCELLED = 0xC00000C8,
|
||||
STATUS_DIRECTORY_NOT_EMPTY = 0xC0000101,
|
||||
STATUS_FILE_CORRUPT_ERROR = 0xC0000102,
|
||||
STATUS_NOT_A_DIRECTORY = 0xC0000103,
|
||||
STATUS_NAME_TOO_LONG = 0xC0000106,
|
||||
STATUS_CANCELLED = 0xC0000120,
|
||||
STATUS_CANNOT_DELETE = 0xC0000121,
|
||||
STATUS_FILE_DELETED = 0xC0000123,
|
||||
STATUS_FILE_CLOSED = 0xC0000128
|
||||
};
|
||||
|
||||
enum RDPDR_PRINTER_ANNOUNCE_FLAG
|
||||
{
|
||||
RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII = 0x00000001,
|
||||
RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER = 0x00000002,
|
||||
RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER = 0x00000004,
|
||||
RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER = 0x00000008,
|
||||
RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT = 0x00000010
|
||||
};
|
||||
|
||||
/* [MS-FSCC] FileAttributes */
|
||||
enum FILE_ATTRIBUTE
|
||||
{
|
||||
FILE_ATTRIBUTE_ARCHIVE = 0x00000020,
|
||||
FILE_ATTRIBUTE_COMPRESSED = 0x00000800,
|
||||
FILE_ATTRIBUTE_DIRECTORY = 0x00000010,
|
||||
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000,
|
||||
FILE_ATTRIBUTE_HIDDEN = 0x00000002,
|
||||
FILE_ATTRIBUTE_NORMAL = 0x00000080,
|
||||
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
|
||||
FILE_ATTRIBUTE_OFFLINE = 0x00001000,
|
||||
FILE_ATTRIBUTE_READONLY = 0x00000001,
|
||||
FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400,
|
||||
FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200,
|
||||
FILE_ATTRIBUTE_SYSTEM = 0x00000004,
|
||||
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
|
||||
};
|
||||
|
||||
/* [MS-FSCC] FSCTL Structures */
|
||||
enum FSCTL_STRUCTURE
|
||||
{
|
||||
FSCTL_CREATE_OR_GET_OBJECT_ID = 0x900c0,
|
||||
FSCTL_GET_REPARSE_POINT = 0x900a8,
|
||||
FSCTL_GET_RETRIEVAL_POINTERS = 0x90073,
|
||||
FSCTL_IS_PATHNAME_VALID = 0x9002c,
|
||||
FSCTL_LMR_SET_LINK_TRACKING_INFORMATION = 0x1400ec,
|
||||
FSCTL_PIPE_PEEK = 0x11400c,
|
||||
FSCTL_PIPE_TRANSCEIVE = 0x11c017,
|
||||
FSCTL_PIPE_WAIT = 0x110018,
|
||||
FSCTL_QUERY_FAT_BPB = 0x90058,
|
||||
FSCTL_QUERY_ALLOCATED_RANGES = 0x940cf,
|
||||
FSCTL_QUERY_ON_DISK_VOLUME_INFO = 0x9013c,
|
||||
FSCTL_QUERY_SPARING_INFO = 0x90138,
|
||||
FSCTL_READ_FILE_USN_DATA = 0x900eb,
|
||||
FSCTL_RECALL_FILE = 0x90117,
|
||||
FSCTL_SET_COMPRESSION = 0x9c040,
|
||||
FSCTL_SET_DEFECT_MANAGEMENT = 0x98134,
|
||||
FSCTL_SET_ENCRYPTION = 0x900D7,
|
||||
FSCTL_SET_OBJECT_ID = 0x90098,
|
||||
FSCTL_SET_OBJECT_ID_EXTENDED = 0x900bc,
|
||||
FSCTL_SET_REPARSE_POINT = 0x900a4,
|
||||
FSCTL_SET_SPARSE = 0x900c4,
|
||||
FSCTL_SET_ZERO_DATA = 0x980c8,
|
||||
FSCTL_SET_ZERO_ON_DEALLOCATION = 0x90194,
|
||||
FSCTL_SIS_COPYFILE = 0x90100,
|
||||
FSCTL_WRITE_USN_CLOSE_RECORD = 0x900ef
|
||||
};
|
||||
|
||||
/* [MS-FSCC] FileFsAttributeInformation.FileSystemAttributes */
|
||||
enum FILE_FS_ATTRIBUTE_INFORMATION
|
||||
{
|
||||
FILE_SUPPORTS_USN_JOURNAL = 0x02000000,
|
||||
FILE_SUPPORTS_OPEN_BY_FILE_ID = 0x01000000,
|
||||
FILE_SUPPORTS_EXTENDED_ATTRIBUTES = 0x00800000,
|
||||
FILE_SUPPORTS_HARD_LINKS = 0x00400000,
|
||||
FILE_SUPPORTS_TRANSACTIONS = 0x00200000,
|
||||
FILE_SEQUENTIAL_WRITE_ONCE = 0x00100000,
|
||||
FILE_READ_ONLY_VOLUME = 0x00080000,
|
||||
FILE_NAMED_STREAMS = 0x00040000,
|
||||
FILE_SUPPORTS_ENCRYPTION = 0x00020000,
|
||||
FILE_SUPPORTS_OBJECT_IDS = 0x00010000,
|
||||
FILE_VOLUME_IS_COMPRESSED = 0x00008000,
|
||||
FILE_SUPPORTS_REMOTE_STORAGE = 0x00000100,
|
||||
FILE_SUPPORTS_REPARSE_POINTS = 0x00000080,
|
||||
FILE_SUPPORTS_SPARSE_FILES = 0x00000040,
|
||||
FILE_VOLUME_QUOTAS = 0x00000020,
|
||||
FILE_FILE_COMPRESSION = 0x00000010,
|
||||
FILE_PERSISTENT_ACLS = 0x00000008,
|
||||
FILE_UNICODE_ON_DISK = 0x00000004,
|
||||
FILE_CASE_PRESERVED_NAMES = 0x00000002,
|
||||
FILE_CASE_SENSITIVE_SEARCH = 0x00000001
|
||||
};
|
||||
|
||||
/* [MS-FSCC] FileFsDeviceInformation.DeviceType */
|
||||
enum FILE_FS_DEVICE_TYPE
|
||||
{
|
||||
FILE_DEVICE_CD_ROM = 0x00000002,
|
||||
FILE_DEVICE_DISK = 0x00000007
|
||||
};
|
||||
|
||||
/* [MS-FSCC] FileFsDeviceInformation.Characteristics */
|
||||
enum FILE_FS_DEVICE_FLAG
|
||||
{
|
||||
FILE_REMOVABLE_MEDIA = 0x00000001,
|
||||
FILE_READ_ONLY_DEVICE = 0x00000002,
|
||||
FILE_FLOPPY_DISKETTE = 0x00000004,
|
||||
FILE_WRITE_ONCE_MEDIA = 0x00000008,
|
||||
FILE_REMOTE_DEVICE = 0x00000010,
|
||||
FILE_DEVICE_IS_MOUNTED = 0x00000020,
|
||||
FILE_VIRTUAL_VOLUME = 0x00000040,
|
||||
FILE_DEVICE_SECURE_OPEN = 0x00000100
|
||||
};
|
||||
|
||||
enum FILE_INFORMATION_CLASS
|
||||
{
|
||||
FileDirectoryInformation = 1,
|
||||
FileFullDirectoryInformation,
|
||||
FileBothDirectoryInformation,
|
||||
FileBasicInformation,
|
||||
FileStandardInformation,
|
||||
FileInternalInformation,
|
||||
FileEaInformation,
|
||||
FileAccessInformation,
|
||||
FileNameInformation,
|
||||
FileRenameInformation,
|
||||
FileLinkInformation,
|
||||
FileNamesInformation,
|
||||
FileDispositionInformation,
|
||||
FilePositionInformation,
|
||||
FileFullEaInformation,
|
||||
FileModeInformation,
|
||||
FileAlignmentInformation,
|
||||
FileAllInformation,
|
||||
FileAllocationInformation,
|
||||
FileEndOfFileInformation,
|
||||
FileAlternateNameInformation,
|
||||
FileStreamInformation,
|
||||
FilePipeInformation,
|
||||
FilePipeLocalInformation,
|
||||
FilePipeRemoteInformation,
|
||||
FileMailslotQueryInformation,
|
||||
FileMailslotSetInformation,
|
||||
FileCompressionInformation,
|
||||
FileObjectIdInformation,
|
||||
FileUnknownInformation1,
|
||||
FileMoveClusterInformation,
|
||||
FileQuotaInformation,
|
||||
FileReparsePointInformation,
|
||||
FileNetworkOpenInformation,
|
||||
FileAttributeTagInformation,
|
||||
FileTrackingInformation,
|
||||
FileIdBothDirectoryInformation,
|
||||
FileIdFullDirectoryInformation,
|
||||
FileValidDataLengthInformation,
|
||||
FileShortNameInformation
|
||||
};
|
||||
|
||||
enum FILE_FS_INFORMATION_CLASS
|
||||
{
|
||||
FileFsVolumeInformation = 1,
|
||||
FileFsLabelInformation,
|
||||
FileFsSizeInformation,
|
||||
FileFsDeviceInformation,
|
||||
FileFsAttributeInformation,
|
||||
FileFsControlInformation,
|
||||
FileFsFullSizeInformation,
|
||||
FileFsObjectIdInformation,
|
||||
FileFsDriverPathInformation,
|
||||
FileFsMaximumInformation
|
||||
};
|
||||
|
||||
#endif /* __RDPDR_CONSTANTS_H */
|
309
channels/rdpdr/rdpdr_main.c
Normal file
309
channels/rdpdr/rdpdr_main.c
Normal file
@ -0,0 +1,309 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "rdpdr_types.h"
|
||||
#include "rdpdr_constants.h"
|
||||
#include "rdpdr_capabilities.h"
|
||||
#include "devman.h"
|
||||
#include "irp.h"
|
||||
#include "rdpdr_main.h"
|
||||
|
||||
static void rdpdr_process_connect(rdpSvcPlugin* plugin)
|
||||
{
|
||||
rdpdrPlugin* rdpdr = (rdpdrPlugin*)plugin;
|
||||
FRDP_PLUGIN_DATA* data;
|
||||
|
||||
rdpdr->devman = devman_new(plugin);
|
||||
data = (FRDP_PLUGIN_DATA*)plugin->channel_entry_points.pExtendedData;
|
||||
while (data && data->size > 0)
|
||||
{
|
||||
if (strcmp((char*)data->data[0], "clientname") == 0)
|
||||
{
|
||||
strncpy(rdpdr->computerName, (char*)data->data[1], sizeof(rdpdr->computerName) - 1);
|
||||
DEBUG_SVC("computerName %s", rdpdr->computerName);
|
||||
}
|
||||
else
|
||||
{
|
||||
devman_load_device_service(rdpdr->devman, data);
|
||||
}
|
||||
data = (FRDP_PLUGIN_DATA*)(((void*)data) + data->size);
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, STREAM* data_in)
|
||||
{
|
||||
stream_read_uint16(data_in, rdpdr->versionMajor);
|
||||
stream_read_uint16(data_in, rdpdr->versionMinor);
|
||||
stream_read_uint32(data_in, rdpdr->clientID);
|
||||
|
||||
DEBUG_SVC("version %d.%d clientID %d", rdpdr->versionMajor, rdpdr->versionMinor, rdpdr->clientID);
|
||||
}
|
||||
|
||||
static void rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr)
|
||||
{
|
||||
STREAM* data_out;
|
||||
|
||||
data_out = stream_new(12);
|
||||
|
||||
stream_write_uint16(data_out, RDPDR_CTYP_CORE);
|
||||
stream_write_uint16(data_out, PAKID_CORE_CLIENTID_CONFIRM);
|
||||
|
||||
stream_write_uint16(data_out, rdpdr->versionMajor);
|
||||
stream_write_uint16(data_out, rdpdr->versionMinor);
|
||||
stream_write_uint32(data_out, rdpdr->clientID);
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out);
|
||||
}
|
||||
|
||||
static void rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
|
||||
{
|
||||
STREAM* data_out;
|
||||
size_t computerNameLenW;
|
||||
UNICONV* uniconv;
|
||||
char* s;
|
||||
|
||||
uniconv = freerdp_uniconv_new();
|
||||
if (!rdpdr->computerName[0])
|
||||
gethostname(rdpdr->computerName, sizeof(rdpdr->computerName) - 1);
|
||||
s = freerdp_uniconv_out(uniconv, rdpdr->computerName, &computerNameLenW);
|
||||
data_out = stream_new(16 + computerNameLenW + 2);
|
||||
|
||||
stream_write_uint16(data_out, RDPDR_CTYP_CORE);
|
||||
stream_write_uint16(data_out, PAKID_CORE_CLIENT_NAME);
|
||||
|
||||
stream_write_uint32(data_out, 1); /* unicodeFlag, 0 for ASCII and 1 for Unicode */
|
||||
stream_write_uint32(data_out, 0); /* codePage, must be set to zero */
|
||||
stream_write_uint32(data_out, computerNameLenW + 2); /* computerNameLen, including null terminator */
|
||||
stream_write(data_out, s, computerNameLenW);
|
||||
stream_write_uint16(data_out, 0); /* null terminator */
|
||||
xfree(s);
|
||||
freerdp_uniconv_free(uniconv);
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out);
|
||||
}
|
||||
|
||||
static void rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, STREAM* data_in)
|
||||
{
|
||||
uint16 versionMajor;
|
||||
uint16 versionMinor;
|
||||
uint32 clientID;
|
||||
|
||||
stream_read_uint16(data_in, versionMajor);
|
||||
stream_read_uint16(data_in, versionMinor);
|
||||
stream_read_uint32(data_in, clientID);
|
||||
|
||||
if (versionMajor != rdpdr->versionMajor || versionMinor != rdpdr->versionMinor)
|
||||
{
|
||||
DEBUG_WARN("unmatched version %d.%d", versionMajor, versionMinor);
|
||||
rdpdr->versionMajor = versionMajor;
|
||||
rdpdr->versionMinor = versionMinor;
|
||||
}
|
||||
|
||||
if (clientID != rdpdr->clientID)
|
||||
{
|
||||
DEBUG_WARN("unmatched clientID %d", clientID);
|
||||
rdpdr->clientID = clientID;
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, boolean user_loggedon)
|
||||
{
|
||||
STREAM* data_out;
|
||||
DEVICE* device;
|
||||
LIST_ITEM* item;
|
||||
uint32 count;
|
||||
uint8 c;
|
||||
int data_len;
|
||||
int i;
|
||||
int count_pos;
|
||||
int pos;
|
||||
|
||||
data_out = stream_new(256);
|
||||
|
||||
stream_write_uint16(data_out, RDPDR_CTYP_CORE);
|
||||
stream_write_uint16(data_out, PAKID_CORE_DEVICELIST_ANNOUNCE);
|
||||
|
||||
count_pos = stream_get_pos(data_out);
|
||||
count = 0;
|
||||
stream_seek_uint32(data_out); /* deviceCount */
|
||||
|
||||
for (item = rdpdr->devman->devices->head; item; item = item->next)
|
||||
{
|
||||
device = (DEVICE*)item->data;
|
||||
|
||||
/**
|
||||
* 1. versionMinor 0x0005 doesn't send PAKID_CORE_USER_LOGGEDON
|
||||
* so all devices should be sent regardless of user_loggedon
|
||||
* 2. smartcard devices should be always sent
|
||||
* 3. other devices are sent only after user_loggedon
|
||||
*/
|
||||
if (rdpdr->versionMinor == 0x0005 ||
|
||||
device->type == RDPDR_DTYP_SMARTCARD ||
|
||||
user_loggedon)
|
||||
{
|
||||
data_len = (device->data == NULL ? 0 : stream_get_length(device->data));
|
||||
stream_check_size(data_out, 20 + data_len);
|
||||
|
||||
stream_write_uint32(data_out, device->type); /* deviceType */
|
||||
stream_write_uint32(data_out, device->id); /* deviceID */
|
||||
strncpy(stream_get_tail(data_out), device->name, 8);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
stream_peek_uint8(data_out, c);
|
||||
if (c > 0x7F)
|
||||
stream_write_uint8(data_out, '_');
|
||||
else
|
||||
stream_seek_uint8(data_out);
|
||||
}
|
||||
|
||||
stream_write_uint32(data_out, data_len);
|
||||
if (data_len > 0)
|
||||
stream_write(data_out, stream_get_data(device->data), data_len);
|
||||
|
||||
count++;
|
||||
printf("registered device #%d: %s (type=%d id=%d)\n",
|
||||
count, device->name, device->type, device->id);
|
||||
}
|
||||
}
|
||||
|
||||
pos = stream_get_pos(data_out);
|
||||
stream_set_pos(data_out, count_pos);
|
||||
stream_write_uint32(data_out, count);
|
||||
stream_set_pos(data_out, pos);
|
||||
stream_seal(data_out);
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out);
|
||||
}
|
||||
|
||||
static boolean rdpdr_process_irp(rdpdrPlugin* rdpdr, STREAM* data_in)
|
||||
{
|
||||
IRP* irp;
|
||||
|
||||
irp = irp_new(rdpdr->devman, data_in);
|
||||
if (irp == NULL)
|
||||
return False;
|
||||
|
||||
IFCALL(irp->device->IRPRequest, irp->device, irp);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static void rdpdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
|
||||
{
|
||||
rdpdrPlugin* rdpdr = (rdpdrPlugin*)plugin;
|
||||
uint16 component;
|
||||
uint16 packetID;
|
||||
uint32 deviceID;
|
||||
uint32 status;
|
||||
|
||||
stream_read_uint16(data_in, component);
|
||||
stream_read_uint16(data_in, packetID);
|
||||
|
||||
if (component == RDPDR_CTYP_CORE)
|
||||
{
|
||||
switch (packetID)
|
||||
{
|
||||
case PAKID_CORE_SERVER_ANNOUNCE:
|
||||
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_SERVER_ANNOUNCE");
|
||||
rdpdr_process_server_announce_request(rdpdr, data_in);
|
||||
rdpdr_send_client_announce_reply(rdpdr);
|
||||
rdpdr_send_client_name_request(rdpdr);
|
||||
break;
|
||||
|
||||
case PAKID_CORE_SERVER_CAPABILITY:
|
||||
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_SERVER_CAPABILITY");
|
||||
rdpdr_process_capability_request(rdpdr, data_in);
|
||||
rdpdr_send_capability_response(rdpdr);
|
||||
break;
|
||||
|
||||
case PAKID_CORE_CLIENTID_CONFIRM:
|
||||
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_CLIENTID_CONFIRM");
|
||||
rdpdr_process_server_clientid_confirm(rdpdr, data_in);
|
||||
rdpdr_send_device_list_announce_request(rdpdr, False);
|
||||
break;
|
||||
|
||||
case PAKID_CORE_USER_LOGGEDON:
|
||||
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_USER_LOGGEDON");
|
||||
rdpdr_send_device_list_announce_request(rdpdr, True);
|
||||
break;
|
||||
|
||||
case PAKID_CORE_DEVICE_REPLY:
|
||||
/* connect to a specific resource */
|
||||
stream_read_uint32(data_in, deviceID);
|
||||
stream_read_uint32(data_in, status);
|
||||
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_DEVICE_REPLY (deviceID=%d status=0x%08X)", deviceID, status);
|
||||
break;
|
||||
|
||||
case PAKID_CORE_DEVICE_IOREQUEST:
|
||||
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_DEVICE_IOREQUEST");
|
||||
if (rdpdr_process_irp(rdpdr, data_in))
|
||||
data_in = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_WARN("RDPDR_CTYP_CORE / unknown packetID: 0x%02X", packetID);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else if (component == RDPDR_CTYP_PRN)
|
||||
{
|
||||
DEBUG_SVC("RDPDR_CTYP_PRN");
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_WARN("RDPDR component: 0x%02X packetID: 0x%02X\n", component, packetID);
|
||||
}
|
||||
|
||||
stream_free(data_in);
|
||||
}
|
||||
|
||||
static void rdpdr_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event)
|
||||
{
|
||||
freerdp_event_free(event);
|
||||
}
|
||||
|
||||
static void rdpdr_process_terminate(rdpSvcPlugin* plugin)
|
||||
{
|
||||
rdpdrPlugin* rdpdr = (rdpdrPlugin*)plugin;
|
||||
|
||||
devman_free(rdpdr->devman);
|
||||
xfree(plugin);
|
||||
}
|
||||
|
||||
DEFINE_SVC_PLUGIN(rdpdr, "rdpdr",
|
||||
CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
|
||||
CHANNEL_OPTION_COMPRESS_RDP)
|
41
channels/rdpdr/rdpdr_main.h
Normal file
41
channels/rdpdr/rdpdr_main.h
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __RDPDR_MAIN_H
|
||||
#define __RDPDR_MAIN_H
|
||||
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "rdpdr_types.h"
|
||||
|
||||
typedef struct rdpdr_plugin rdpdrPlugin;
|
||||
struct rdpdr_plugin
|
||||
{
|
||||
rdpSvcPlugin plugin;
|
||||
|
||||
DEVMAN* devman;
|
||||
|
||||
uint16 versionMajor;
|
||||
uint16 versionMinor;
|
||||
uint16 clientID;
|
||||
char computerName[256];
|
||||
};
|
||||
|
||||
#endif /* __RDPDR_MAIN_H */
|
89
channels/rdpdr/rdpdr_types.h
Normal file
89
channels/rdpdr/rdpdr_types.h
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* File System Virtual Channel
|
||||
*
|
||||
* Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __RDPDR_TYPES_H
|
||||
#define __RDPDR_TYPES_H
|
||||
|
||||
#include "config.h"
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
|
||||
typedef struct _DEVICE DEVICE;
|
||||
typedef struct _IRP IRP;
|
||||
typedef struct _DEVMAN DEVMAN;
|
||||
|
||||
|
||||
typedef void (*pcIRPRequest)(DEVICE* device, IRP* irp);
|
||||
typedef void (*pcFreeDevice)(DEVICE* device);
|
||||
|
||||
struct _DEVICE
|
||||
{
|
||||
uint32 id;
|
||||
|
||||
uint32 type;
|
||||
char* name;
|
||||
STREAM* data;
|
||||
|
||||
pcIRPRequest IRPRequest;
|
||||
pcFreeDevice Free;
|
||||
};
|
||||
|
||||
typedef void (*pcIRPResponse)(IRP* irp);
|
||||
|
||||
struct _IRP
|
||||
{
|
||||
DEVICE* device;
|
||||
DEVMAN* devman;
|
||||
uint32 FileId;
|
||||
uint32 CompletionId;
|
||||
uint32 MajorFunction;
|
||||
uint32 MinorFunction;
|
||||
STREAM* input;
|
||||
|
||||
uint32 IoStatus;
|
||||
STREAM* output;
|
||||
|
||||
pcIRPResponse Complete;
|
||||
pcIRPResponse Discard;
|
||||
};
|
||||
|
||||
struct _DEVMAN
|
||||
{
|
||||
rdpSvcPlugin* plugin;
|
||||
uint32 id_sequence; /* generate unique device id */
|
||||
LIST* devices;
|
||||
};
|
||||
|
||||
typedef void (*pcRegisterDevice)(DEVMAN* devman, DEVICE* device);
|
||||
|
||||
struct _DEVICE_SERVICE_ENTRY_POINTS
|
||||
{
|
||||
DEVMAN* devman;
|
||||
|
||||
pcRegisterDevice RegisterDevice;
|
||||
pcRegisterDevice UnregisterDevice;
|
||||
FRDP_PLUGIN_DATA* plugin_data;
|
||||
};
|
||||
typedef struct _DEVICE_SERVICE_ENTRY_POINTS DEVICE_SERVICE_ENTRY_POINTS;
|
||||
typedef DEVICE_SERVICE_ENTRY_POINTS* PDEVICE_SERVICE_ENTRY_POINTS;
|
||||
|
||||
typedef int (*PDEVICE_SERVICE_ENTRY)(PDEVICE_SERVICE_ENTRY_POINTS);
|
||||
|
||||
#endif /* __RDPDR_TYPES_H */
|
@ -44,57 +44,51 @@ int add_list_suite(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct my_list_item
|
||||
struct _my_list_item
|
||||
{
|
||||
uint32 a;
|
||||
uint32 b;
|
||||
};
|
||||
|
||||
DEFINE_LIST_TYPE(my_list, my_list_item);
|
||||
|
||||
void my_list_item_free(struct my_list_item* item)
|
||||
{
|
||||
item->a = 0;
|
||||
item->b = 0;
|
||||
}
|
||||
typedef struct _my_list_item my_list_item;
|
||||
|
||||
void test_list(void)
|
||||
{
|
||||
struct my_list* list;
|
||||
struct my_list_item* item;
|
||||
struct my_list_item* item1;
|
||||
struct my_list_item* item2;
|
||||
LIST* list;
|
||||
LIST_ITEM* list_item;
|
||||
my_list_item* item;
|
||||
my_list_item* item1;
|
||||
my_list_item* item2;
|
||||
int i;
|
||||
|
||||
list = my_list_new();
|
||||
list = list_new();
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
item = my_list_item_new();
|
||||
item = xnew(my_list_item);
|
||||
item->a = i;
|
||||
item->b = i * i;
|
||||
my_list_enqueue(list, item);
|
||||
list_enqueue(list, item);
|
||||
}
|
||||
|
||||
for (i = 0, item = list->head; item; i++, item = my_list_item_next(item))
|
||||
for (i = 0, list_item = list->head; list_item; i++, list_item = list_item->next)
|
||||
{
|
||||
CU_ASSERT(item->a == i);
|
||||
CU_ASSERT(item->b == i * i);
|
||||
CU_ASSERT(((my_list_item*)list_item->data)->a == i);
|
||||
CU_ASSERT(((my_list_item*)list_item->data)->b == i * i);
|
||||
/*printf("%d %d\n", item->a, item->b);*/
|
||||
}
|
||||
|
||||
item1 = my_list_item_new();
|
||||
my_list_add(list, item1);
|
||||
item2 = my_list_item_new();
|
||||
my_list_add(list, item2);
|
||||
item1 = xnew(my_list_item);
|
||||
list_add(list, item1);
|
||||
item2 = xnew(my_list_item);
|
||||
list_add(list, item2);
|
||||
|
||||
CU_ASSERT(my_list_remove(list, item1) == item1);
|
||||
my_list_item_free(item1);
|
||||
CU_ASSERT(list_remove(list, item1) == item1);
|
||||
xfree(item1);
|
||||
CU_ASSERT(my_list_remove(list, item2) == item2);
|
||||
CU_ASSERT(my_list_remove(list, item2) == NULL);
|
||||
my_list_item_free(item2);
|
||||
CU_ASSERT(list_remove(list, item2) == item2);
|
||||
CU_ASSERT(list_remove(list, item2) == NULL);
|
||||
xfree(item2);
|
||||
|
||||
my_list_free(list);
|
||||
while ((item = list_dequeue(list)) != NULL)
|
||||
xfree(item);
|
||||
list_free(list);
|
||||
}
|
||||
|
@ -22,114 +22,27 @@
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
|
||||
#define DEFINE_LIST_TYPE(_list_type, _item_type) \
|
||||
\
|
||||
struct _item_type##_full \
|
||||
{ \
|
||||
struct _item_type item; \
|
||||
struct _item_type* prev; \
|
||||
struct _item_type* next; \
|
||||
}; \
|
||||
\
|
||||
static struct _item_type* _item_type##_new(void) \
|
||||
{ \
|
||||
struct _item_type* item; \
|
||||
item = (struct _item_type*)xnew(struct _item_type##_full);\
|
||||
return item; \
|
||||
} \
|
||||
\
|
||||
static void _item_type##_free(struct _item_type* item); \
|
||||
\
|
||||
static struct _item_type* _item_type##_next(struct _item_type* item) \
|
||||
{ \
|
||||
return ((struct _item_type##_full*)item)->next; \
|
||||
} \
|
||||
\
|
||||
static struct _item_type* _item_type##_prev(struct _item_type* item) \
|
||||
{ \
|
||||
return ((struct _item_type##_full*)item)->prev; \
|
||||
} \
|
||||
\
|
||||
struct _list_type \
|
||||
{ \
|
||||
struct _item_type* head; \
|
||||
struct _item_type* tail; \
|
||||
}; \
|
||||
\
|
||||
static struct _list_type* _list_type##_new(void) \
|
||||
{ \
|
||||
struct _list_type* list; \
|
||||
list = xnew(struct _list_type); \
|
||||
return list; \
|
||||
} \
|
||||
\
|
||||
static void _list_type##_enqueue(struct _list_type* list, struct _item_type* item) \
|
||||
{ \
|
||||
if (list->tail == NULL) \
|
||||
{ \
|
||||
list->head = item; \
|
||||
list->tail = item; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
((struct _item_type##_full*)item)->prev = list->tail; \
|
||||
((struct _item_type##_full*)(list->tail))->next = item; \
|
||||
list->tail = item; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static struct _item_type* _list_type##_dequeue(struct _list_type* list) \
|
||||
{ \
|
||||
struct _item_type* item; \
|
||||
item = list->head; \
|
||||
if (item != NULL) \
|
||||
{ \
|
||||
list->head = ((struct _item_type##_full*)item)->next; \
|
||||
((struct _item_type##_full*)item)->next = NULL; \
|
||||
if (list->head == NULL) \
|
||||
list->tail = NULL; \
|
||||
else \
|
||||
((struct _item_type##_full*)(list->head))->prev = NULL; \
|
||||
} \
|
||||
return item; \
|
||||
} \
|
||||
\
|
||||
static void _list_type##_add(struct _list_type* list, struct _item_type* item) \
|
||||
{ \
|
||||
_list_type##_enqueue(list, item); \
|
||||
} \
|
||||
\
|
||||
static struct _item_type* _list_type##_remove(struct _list_type* list, struct _item_type* item) \
|
||||
{ \
|
||||
struct _item_type* prev; \
|
||||
struct _item_type* curr; \
|
||||
\
|
||||
for (prev = NULL, curr = (struct _item_type*)list->head; curr; prev = curr, curr = ((struct _item_type##_full*)curr)->next) \
|
||||
{ \
|
||||
if (curr == item) \
|
||||
{ \
|
||||
if (prev) \
|
||||
((struct _item_type##_full*)prev)->next = ((struct _item_type##_full*)curr)->next; \
|
||||
if (list->head == item) \
|
||||
list->head = ((struct _item_type##_full*)curr)->next; \
|
||||
if (list->tail == item) \
|
||||
list->tail = prev; \
|
||||
return item; \
|
||||
} \
|
||||
} \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
void _list_type##_free(struct _list_type* list) \
|
||||
{ \
|
||||
struct _item_type* item; \
|
||||
while (list->head) \
|
||||
{ \
|
||||
item = _list_type##_dequeue(list); \
|
||||
_item_type##_free(item); \
|
||||
xfree(item); \
|
||||
} \
|
||||
xfree(list); \
|
||||
}
|
||||
typedef struct _LIST_ITEM LIST_ITEM;
|
||||
struct _LIST_ITEM
|
||||
{
|
||||
void* data;
|
||||
LIST_ITEM* prev;
|
||||
LIST_ITEM* next;
|
||||
};
|
||||
|
||||
#endif
|
||||
typedef struct _LIST LIST;
|
||||
struct _LIST
|
||||
{
|
||||
int count;
|
||||
LIST_ITEM* head;
|
||||
LIST_ITEM* tail;
|
||||
};
|
||||
|
||||
LIST* list_new(void);
|
||||
void list_free(LIST* list);
|
||||
void list_enqueue(LIST* list, void* data);
|
||||
void* list_dequeue(LIST* list);
|
||||
#define list_add(_l, _d) list_enqueue(_l, _d)
|
||||
void* list_remove(LIST* list, void* data);
|
||||
|
||||
#endif /* __LIST_UTILS_H */
|
||||
|
@ -130,9 +130,9 @@ void stream_extend(STREAM* stream);
|
||||
(((uint64)(*(_s->p + 7))) << 56); \
|
||||
} while (0)
|
||||
|
||||
#define stream_seek_uint8(_s) stream_seek(s, 1)
|
||||
#define stream_seek_uint16(_s) stream_seek(s, 2)
|
||||
#define stream_seek_uint32(_s) stream_seek(s, 4)
|
||||
#define stream_seek_uint8(_s) stream_seek(_s, 1)
|
||||
#define stream_seek_uint16(_s) stream_seek(_s, 2)
|
||||
#define stream_seek_uint32(_s) stream_seek(_s, 4)
|
||||
|
||||
#define stream_read_uint16_be(_s, _v) do { _v = \
|
||||
(((uint16)(*_s->p)) << 8) + \
|
||||
|
@ -120,7 +120,7 @@ void update_read_palette(rdpUpdate* update, STREAM* s, PALETTE_UPDATE* palette_u
|
||||
uint32 color;
|
||||
|
||||
stream_seek_uint16(s); /* pad2Octets (2 bytes) */
|
||||
stream_seek_uint32(palette_update->number); /* numberColors (4 bytes), must be set to 256 */
|
||||
stream_read_uint32(s, palette_update->number); /* numberColors (4 bytes), must be set to 256 */
|
||||
|
||||
if (palette_update->number > 256)
|
||||
palette_update->number = 256;
|
||||
|
@ -25,6 +25,7 @@ set(FREERDP_UTILS_SRCS
|
||||
blob.c
|
||||
event.c
|
||||
hexdump.c
|
||||
list.c
|
||||
load_plugin.c
|
||||
memory.c
|
||||
mutex.c
|
||||
|
@ -25,8 +25,6 @@
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/args.h>
|
||||
|
||||
#define MAX_PLUGIN_DATA 20
|
||||
|
||||
/**
|
||||
* Parse command-line arguments and update rdpSettings members accordingly.
|
||||
* @param settings pointer to rdpSettings struct to be updated.
|
||||
@ -47,7 +45,7 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
||||
int i, j;
|
||||
int index = 1;
|
||||
int num_extensions = 0;
|
||||
FRDP_PLUGIN_DATA plugin_data[MAX_PLUGIN_DATA + 1];
|
||||
FRDP_PLUGIN_DATA* plugin_data;
|
||||
|
||||
while (index < argc)
|
||||
{
|
||||
@ -278,14 +276,16 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
||||
printf("missing plugin name\n");
|
||||
return 0;
|
||||
}
|
||||
memset(plugin_data, 0, sizeof(plugin_data));
|
||||
plugin_data = NULL;
|
||||
if (index < argc - 1 && strcmp("--data", argv[index + 1]) == 0)
|
||||
{
|
||||
index += 2;
|
||||
i = 0;
|
||||
while (index < argc && strcmp("--", argv[index]) != 0 && i < MAX_PLUGIN_DATA)
|
||||
while (index < argc && strcmp("--", argv[index]) != 0)
|
||||
{
|
||||
plugin_data = (FRDP_PLUGIN_DATA*)xrealloc(plugin_data, sizeof(FRDP_PLUGIN_DATA) * (i + 2));
|
||||
plugin_data[i].size = sizeof(FRDP_PLUGIN_DATA);
|
||||
plugin_data[i + 1].size = 0;
|
||||
for (j = 0, p = argv[index]; j < 4 && p != NULL; j++)
|
||||
{
|
||||
if (*p == '\'')
|
||||
|
120
libfreerdp-utils/list.c
Normal file
120
libfreerdp-utils/list.c
Normal file
@ -0,0 +1,120 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* Double-linked List Utils
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
|
||||
static LIST_ITEM* list_item_new(void* data)
|
||||
{
|
||||
LIST_ITEM* item;
|
||||
|
||||
item = xnew(LIST_ITEM);
|
||||
item->data = data;
|
||||
return item;
|
||||
}
|
||||
|
||||
static LIST_ITEM* list_item_find(LIST* list, void* data)
|
||||
{
|
||||
LIST_ITEM* item;
|
||||
|
||||
for (item = list->head; item; item = item->next)
|
||||
{
|
||||
if (item->data == data)
|
||||
return item;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LIST* list_new(void)
|
||||
{
|
||||
LIST* list;
|
||||
|
||||
list = xnew(LIST);
|
||||
return list;
|
||||
}
|
||||
|
||||
void list_free(LIST* list)
|
||||
{
|
||||
while (list->head)
|
||||
list_dequeue(list);
|
||||
xfree(list);
|
||||
}
|
||||
|
||||
void list_enqueue(LIST* list, void* data)
|
||||
{
|
||||
LIST_ITEM* item;
|
||||
|
||||
item = list_item_new(data);
|
||||
if (list->tail == NULL)
|
||||
{
|
||||
list->head = item;
|
||||
list->tail = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->prev = list->tail;
|
||||
list->tail->next = item;
|
||||
list->tail = item;
|
||||
}
|
||||
}
|
||||
|
||||
void* list_dequeue(LIST* list)
|
||||
{
|
||||
LIST_ITEM* item;
|
||||
void* data = NULL;
|
||||
|
||||
item = list->head;
|
||||
if (item != NULL)
|
||||
{
|
||||
list->head = item->next;
|
||||
if (list->head == NULL)
|
||||
list->tail = NULL;
|
||||
else
|
||||
list->head->prev = NULL;
|
||||
|
||||
data = item->data;
|
||||
xfree(item);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void* list_remove(LIST* list, void* data)
|
||||
{
|
||||
LIST_ITEM* item;
|
||||
|
||||
item = list_item_find(list, data);
|
||||
if (item != NULL)
|
||||
{
|
||||
if (item->prev != NULL)
|
||||
item->prev->next = item->next;
|
||||
if (item->next != NULL)
|
||||
item->next->prev = item->prev;
|
||||
if (list->head == item)
|
||||
list->head = item->next;
|
||||
if (list->tail == item)
|
||||
list->tail = item->prev;
|
||||
xfree(item);
|
||||
}
|
||||
else
|
||||
data = NULL;
|
||||
return data;
|
||||
}
|
@ -48,15 +48,14 @@ static rdpSvcPluginList* g_svc_plugin_list = NULL;
|
||||
static freerdp_mutex g_mutex = NULL;
|
||||
|
||||
/* Queue for receiving packets */
|
||||
struct svc_data_in_item
|
||||
struct _svc_data_in_item
|
||||
{
|
||||
STREAM* data_in;
|
||||
FRDP_EVENT* event_in;
|
||||
};
|
||||
typedef struct _svc_data_in_item svc_data_in_item;
|
||||
|
||||
DEFINE_LIST_TYPE(svc_data_in_list, svc_data_in_item);
|
||||
|
||||
void svc_data_in_item_free(struct svc_data_in_item* item)
|
||||
static void svc_data_in_item_free(svc_data_in_item* item)
|
||||
{
|
||||
if (item->data_in)
|
||||
{
|
||||
@ -68,6 +67,7 @@ void svc_data_in_item_free(struct svc_data_in_item* item)
|
||||
freerdp_event_free(item->event_in);
|
||||
item->event_in = NULL;
|
||||
}
|
||||
xfree(item);
|
||||
}
|
||||
|
||||
struct rdp_svc_plugin_private
|
||||
@ -76,7 +76,7 @@ struct rdp_svc_plugin_private
|
||||
uint32 open_handle;
|
||||
STREAM* data_in;
|
||||
|
||||
struct svc_data_in_list* data_in_list;
|
||||
LIST* data_in_list;
|
||||
freerdp_mutex* data_in_mutex;
|
||||
|
||||
struct wait_obj* signals[5];
|
||||
@ -150,7 +150,7 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3
|
||||
uint32 totalLength, uint32 dataFlags)
|
||||
{
|
||||
STREAM* data_in;
|
||||
struct svc_data_in_item* item;
|
||||
svc_data_in_item* item;
|
||||
|
||||
if (dataFlags & CHANNEL_FLAG_FIRST)
|
||||
{
|
||||
@ -173,11 +173,11 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3
|
||||
plugin->priv->data_in = NULL;
|
||||
stream_set_pos(data_in, 0);
|
||||
|
||||
item = svc_data_in_item_new();
|
||||
item = xnew(svc_data_in_item);
|
||||
item->data_in = data_in;
|
||||
|
||||
freerdp_mutex_lock(plugin->priv->data_in_mutex);
|
||||
svc_data_in_list_enqueue(plugin->priv->data_in_list, item);
|
||||
list_enqueue(plugin->priv->data_in_list, item);
|
||||
freerdp_mutex_unlock(plugin->priv->data_in_mutex);
|
||||
|
||||
wait_obj_set(plugin->priv->signals[1]);
|
||||
@ -186,13 +186,13 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3
|
||||
|
||||
static void svc_plugin_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event_in)
|
||||
{
|
||||
struct svc_data_in_item* item;
|
||||
svc_data_in_item* item;
|
||||
|
||||
item = svc_data_in_item_new();
|
||||
item = xnew(svc_data_in_item);
|
||||
item->event_in = event_in;
|
||||
|
||||
freerdp_mutex_lock(plugin->priv->data_in_mutex);
|
||||
svc_data_in_list_enqueue(plugin->priv->data_in_list, item);
|
||||
list_enqueue(plugin->priv->data_in_list, item);
|
||||
freerdp_mutex_unlock(plugin->priv->data_in_mutex);
|
||||
|
||||
wait_obj_set(plugin->priv->signals[1]);
|
||||
@ -228,7 +228,7 @@ static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData,
|
||||
|
||||
static void svc_plugin_process_data_in(rdpSvcPlugin* plugin)
|
||||
{
|
||||
struct svc_data_in_item* item;
|
||||
svc_data_in_item* item;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@ -237,7 +237,7 @@ static void svc_plugin_process_data_in(rdpSvcPlugin* plugin)
|
||||
break;
|
||||
|
||||
freerdp_mutex_lock(plugin->priv->data_in_mutex);
|
||||
item = svc_data_in_list_dequeue(plugin->priv->data_in_list);
|
||||
item = list_dequeue(plugin->priv->data_in_list);
|
||||
freerdp_mutex_unlock(plugin->priv->data_in_mutex);
|
||||
|
||||
if (item != NULL)
|
||||
@ -298,7 +298,7 @@ static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, uint
|
||||
return;
|
||||
}
|
||||
|
||||
plugin->priv->data_in_list = svc_data_in_list_new();
|
||||
plugin->priv->data_in_list = list_new();
|
||||
plugin->priv->data_in_mutex = freerdp_mutex_new();
|
||||
|
||||
/* terminate signal */
|
||||
@ -313,6 +313,7 @@ static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, uint
|
||||
|
||||
static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
|
||||
{
|
||||
svc_data_in_item* item;
|
||||
struct timespec ts;
|
||||
int i;
|
||||
|
||||
@ -327,6 +328,7 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
|
||||
}
|
||||
|
||||
plugin->channel_entry_points.pVirtualChannelClose(plugin->priv->open_handle);
|
||||
xfree(plugin->channel_entry_points.pExtendedData);
|
||||
|
||||
svc_plugin_remove(plugin);
|
||||
|
||||
@ -335,7 +337,10 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
|
||||
plugin->priv->num_signals = 0;
|
||||
|
||||
freerdp_mutex_free(plugin->priv->data_in_mutex);
|
||||
svc_data_in_list_free(plugin->priv->data_in_list);
|
||||
|
||||
while ((item = list_dequeue(plugin->priv->data_in_list)) != NULL)
|
||||
svc_data_in_item_free(item);
|
||||
list_free(plugin->priv->data_in_list);
|
||||
|
||||
if (plugin->priv->data_in != NULL)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user