Merge branch 'master' of git://github.com/awakecoding/FreeRDP
This commit is contained in:
commit
c82fd89860
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,6 +19,7 @@ LICENSE.txt
|
||||
!external/README
|
||||
*Config.cmake
|
||||
*ConfigVersion.cmake
|
||||
include/freerdp/version.h
|
||||
|
||||
*.a.objlist.cmake
|
||||
*.a.objlist
|
||||
|
@ -463,6 +463,7 @@ set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp/extensions")
|
||||
|
||||
# Include directories
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
# Configure files
|
||||
|
@ -227,6 +227,7 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
|
||||
cb_event->raw_format_data = (BYTE*) malloc(dataLen);
|
||||
memcpy(cb_event->raw_format_data, Stream_Pointer(s), dataLen);
|
||||
cb_event->raw_format_data_size = dataLen;
|
||||
cb_event->raw_format_unicode = (msgFlags & CB_ASCII_NAMES) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
if (cliprdr->use_long_format_names)
|
||||
|
@ -110,6 +110,7 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
|
||||
{
|
||||
UINT32 version;
|
||||
UINT32 generalFlags;
|
||||
RDP_CB_CLIP_CAPS *caps_event;
|
||||
|
||||
Stream_Read_UINT32(s, version); /* version (4 bytes) */
|
||||
Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
|
||||
@ -120,6 +121,9 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
|
||||
cliprdr_print_general_capability_flags(generalFlags);
|
||||
#endif
|
||||
|
||||
caps_event = (RDP_CB_CLIP_CAPS *)freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_ClipCaps, NULL, NULL);
|
||||
caps_event->capabilities = generalFlags;
|
||||
|
||||
if (generalFlags & CB_USE_LONG_FORMAT_NAMES)
|
||||
cliprdr->use_long_format_names = TRUE;
|
||||
|
||||
@ -133,6 +137,9 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
|
||||
cliprdr->can_lock_clipdata = TRUE;
|
||||
|
||||
cliprdr->received_caps = TRUE;
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin *)cliprdr, (wMessage *)caps_event);
|
||||
|
||||
}
|
||||
|
||||
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
|
||||
@ -188,14 +195,14 @@ static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr)
|
||||
|
||||
static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
|
||||
{
|
||||
wMessage* event;
|
||||
RDP_CB_MONITOR_READY_EVENT* event;
|
||||
|
||||
if (cliprdr->received_caps)
|
||||
cliprdr_send_clip_caps(cliprdr);
|
||||
|
||||
event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
|
||||
event = (RDP_CB_MONITOR_READY_EVENT *)freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event);
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage *)event);
|
||||
}
|
||||
|
||||
static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
|
||||
|
@ -740,31 +740,6 @@ static void rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_process_terminate(rdpsndPlugin* rdpsnd)
|
||||
{
|
||||
if (rdpsnd->device)
|
||||
IFCALL(rdpsnd->device->Free, rdpsnd->device);
|
||||
|
||||
MessageQueue_PostQuit(rdpsnd->MsgPipe->Out, 0);
|
||||
|
||||
WaitForSingleObject(rdpsnd->ScheduleThread, INFINITE);
|
||||
CloseHandle(rdpsnd->ScheduleThread);
|
||||
|
||||
if (rdpsnd->subsystem)
|
||||
free(rdpsnd->subsystem);
|
||||
|
||||
if (rdpsnd->device_name)
|
||||
free(rdpsnd->device_name);
|
||||
|
||||
rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats);
|
||||
rdpsnd->NumberOfServerFormats = 0;
|
||||
rdpsnd->ServerFormats = NULL;
|
||||
|
||||
rdpsnd_free_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats);
|
||||
rdpsnd->NumberOfClientFormats = 0;
|
||||
rdpsnd->ClientFormats = NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
@ -951,26 +926,41 @@ static void rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, void* p
|
||||
(LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) plugin, 0, NULL);
|
||||
}
|
||||
|
||||
static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* plugin)
|
||||
static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
|
||||
{
|
||||
MessagePipe_PostQuit(plugin->MsgPipe, 0);
|
||||
WaitForSingleObject(plugin->thread, INFINITE);
|
||||
MessagePipe_PostQuit(rdpsnd->MsgPipe, 0);
|
||||
WaitForSingleObject(rdpsnd->thread, INFINITE);
|
||||
|
||||
MessagePipe_Free(plugin->MsgPipe);
|
||||
CloseHandle(plugin->thread);
|
||||
MessagePipe_Free(rdpsnd->MsgPipe);
|
||||
CloseHandle(rdpsnd->thread);
|
||||
|
||||
plugin->channelEntryPoints.pVirtualChannelClose(plugin->OpenHandle);
|
||||
rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle);
|
||||
|
||||
if (plugin->data_in)
|
||||
if (rdpsnd->data_in)
|
||||
{
|
||||
Stream_Free(plugin->data_in, TRUE);
|
||||
plugin->data_in = NULL;
|
||||
Stream_Free(rdpsnd->data_in, TRUE);
|
||||
rdpsnd->data_in = NULL;
|
||||
}
|
||||
|
||||
rdpsnd_process_terminate(plugin);
|
||||
if (rdpsnd->device)
|
||||
IFCALL(rdpsnd->device->Free, rdpsnd->device);
|
||||
|
||||
rdpsnd_remove_open_handle_data(plugin->OpenHandle);
|
||||
rdpsnd_remove_init_handle_data(plugin->InitHandle);
|
||||
if (rdpsnd->subsystem)
|
||||
free(rdpsnd->subsystem);
|
||||
|
||||
if (rdpsnd->device_name)
|
||||
free(rdpsnd->device_name);
|
||||
|
||||
rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats);
|
||||
rdpsnd->NumberOfServerFormats = 0;
|
||||
rdpsnd->ServerFormats = NULL;
|
||||
|
||||
rdpsnd_free_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats);
|
||||
rdpsnd->NumberOfClientFormats = 0;
|
||||
rdpsnd->ClientFormats = NULL;
|
||||
|
||||
rdpsnd_remove_open_handle_data(rdpsnd->OpenHandle);
|
||||
rdpsnd_remove_init_handle_data(rdpsnd->InitHandle);
|
||||
}
|
||||
|
||||
static void rdpsnd_virtual_channel_init_event(void* pInitHandle, UINT32 event, void* pData, UINT32 dataLength)
|
||||
|
@ -170,6 +170,7 @@ DWORD mac_client_thread(void* param)
|
||||
mfContext* mfc = (mfContext*) context;
|
||||
freerdp* instance = context->instance;
|
||||
MRDPView* view = mfc->view;
|
||||
rdpSettings* settings = context->settings;
|
||||
|
||||
status = freerdp_connect(context->instance);
|
||||
|
||||
@ -185,17 +186,17 @@ DWORD mac_client_thread(void* param)
|
||||
|
||||
events[nCount++] = mfc->stopEvent;
|
||||
|
||||
if (instance->settings->AsyncUpdate)
|
||||
if (settings->AsyncUpdate)
|
||||
{
|
||||
events[nCount++] = update_event = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
|
||||
}
|
||||
|
||||
if (instance->settings->AsyncInput)
|
||||
if (settings->AsyncInput)
|
||||
{
|
||||
events[nCount++] = input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
|
||||
}
|
||||
|
||||
if (instance->settings->AsyncChannels)
|
||||
if (settings->AsyncChannels)
|
||||
{
|
||||
events[nCount++] = channels_event = freerdp_channels_get_event_handle(instance);
|
||||
}
|
||||
@ -206,10 +207,11 @@ DWORD mac_client_thread(void* param)
|
||||
|
||||
if (WaitForSingleObject(mfc->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
freerdp_disconnect(instance);
|
||||
break;
|
||||
}
|
||||
|
||||
if (instance->settings->AsyncUpdate)
|
||||
if (settings->AsyncUpdate)
|
||||
{
|
||||
if (WaitForSingleObject(update_event, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
@ -217,7 +219,7 @@ DWORD mac_client_thread(void* param)
|
||||
}
|
||||
}
|
||||
|
||||
if (instance->settings->AsyncInput)
|
||||
if (settings->AsyncInput)
|
||||
{
|
||||
if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
@ -225,7 +227,7 @@ DWORD mac_client_thread(void* param)
|
||||
}
|
||||
}
|
||||
|
||||
if (instance->settings->AsyncChannels)
|
||||
if (settings->AsyncChannels)
|
||||
{
|
||||
if (WaitForSingleObject(channels_event, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
|
@ -46,12 +46,12 @@ int mfreerdp_client_start(rdpContext* context)
|
||||
MRDPView* view;
|
||||
mfContext* mfc = (mfContext*) context;
|
||||
|
||||
if (mfc->view == NULL)
|
||||
{
|
||||
// view not specified beforehand. Create view dynamically
|
||||
mfc->view = [[MRDPView alloc] initWithFrame : NSMakeRect(0, 0, context->settings->DesktopWidth, context->settings->DesktopHeight)];
|
||||
mfc->view_ownership = TRUE;
|
||||
}
|
||||
if (mfc->view == NULL)
|
||||
{
|
||||
// view not specified beforehand. Create view dynamically
|
||||
mfc->view = [[MRDPView alloc] initWithFrame : NSMakeRect(0, 0, context->settings->DesktopWidth, context->settings->DesktopHeight)];
|
||||
mfc->view_ownership = TRUE;
|
||||
}
|
||||
|
||||
view = (MRDPView*) mfc->view;
|
||||
[view rdpStart:context];
|
||||
@ -62,45 +62,22 @@ int mfreerdp_client_start(rdpContext* context)
|
||||
int mfreerdp_client_stop(rdpContext* context)
|
||||
{
|
||||
mfContext* mfc = (mfContext*) context;
|
||||
|
||||
if (context->settings->AsyncUpdate)
|
||||
|
||||
if (mfc->thread)
|
||||
{
|
||||
wMessageQueue* queue;
|
||||
queue = freerdp_get_message_queue(context->instance, FREERDP_UPDATE_MESSAGE_QUEUE);
|
||||
if (queue)
|
||||
{
|
||||
MessageQueue_PostQuit(queue, 0);
|
||||
}
|
||||
}
|
||||
else if (context->settings->AsyncInput)
|
||||
{
|
||||
wMessageQueue* queue;
|
||||
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
|
||||
if (queue)
|
||||
{
|
||||
MessageQueue_PostQuit(queue, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mfc->disconnect = TRUE;
|
||||
SetEvent(mfc->stopEvent);
|
||||
WaitForSingleObject(mfc->thread, INFINITE);
|
||||
CloseHandle(mfc->thread);
|
||||
mfc->thread = NULL;
|
||||
}
|
||||
|
||||
if (mfc->thread)
|
||||
{
|
||||
SetEvent(mfc->stopEvent);
|
||||
WaitForSingleObject(mfc->thread, INFINITE);
|
||||
CloseHandle(mfc->thread);
|
||||
mfc->thread = NULL;
|
||||
}
|
||||
|
||||
if (mfc->view_ownership)
|
||||
{
|
||||
MRDPView* view = (MRDPView*) mfc->view;
|
||||
[view releaseResources];
|
||||
[view release];
|
||||
mfc->view = nil;
|
||||
}
|
||||
if (mfc->view_ownership)
|
||||
{
|
||||
MRDPView* view = (MRDPView*) mfc->view;
|
||||
[view releaseResources];
|
||||
[view release];
|
||||
mfc->view = nil;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -112,22 +89,21 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context)
|
||||
|
||||
mfc = (mfContext*) instance->context;
|
||||
|
||||
mfc->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
mfc->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
context->instance->PreConnect = mac_pre_connect;
|
||||
context->instance->PostConnect = mac_post_connect;
|
||||
context->instance->ReceiveChannelData = mac_receive_channel_data;
|
||||
context->instance->Authenticate = mac_authenticate;
|
||||
context->instance->PreConnect = mac_pre_connect;
|
||||
context->instance->PostConnect = mac_post_connect;
|
||||
context->instance->ReceiveChannelData = mac_receive_channel_data;
|
||||
context->instance->Authenticate = mac_authenticate;
|
||||
|
||||
context->channels = freerdp_channels_new();
|
||||
context->channels = freerdp_channels_new();
|
||||
|
||||
settings = instance->settings;
|
||||
|
||||
settings->AsyncUpdate = TRUE;
|
||||
settings->AsyncInput = TRUE;
|
||||
settings->AsyncUpdate = TRUE;
|
||||
settings->AsyncInput = TRUE;
|
||||
settings->AsyncChannels = TRUE;
|
||||
settings->AsyncTransport = TRUE;
|
||||
settings->RedirectClipboard = TRUE;
|
||||
|
||||
settings->OsMajorType = OSMAJORTYPE_MACINTOSH;
|
||||
settings->OsMinorType = OSMINORTYPE_MACINTOSH;
|
||||
@ -195,35 +171,35 @@ void freerdp_client_mouse_event(rdpContext* cfc, DWORD flags, int x, int y)
|
||||
|
||||
void mf_scale_mouse_event(void* context, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
||||
{
|
||||
mfContext* mfc = (mfContext*) context;
|
||||
mfContext* mfc = (mfContext*) context;
|
||||
MRDPView* view = (MRDPView*) mfc->view;
|
||||
|
||||
int ww, wh, dw, dh;
|
||||
|
||||
|
||||
int ww, wh, dw, dh;
|
||||
|
||||
ww = mfc->client_width;
|
||||
wh = mfc->client_height;
|
||||
dw = mfc->context.settings->DesktopWidth;
|
||||
dh = mfc->context.settings->DesktopHeight;
|
||||
|
||||
dh = mfc->context.settings->DesktopHeight;
|
||||
|
||||
// Convert to windows coordinates
|
||||
y = [view frame].size.height - y;
|
||||
|
||||
if (!mfc->context.settings->SmartSizing || ((ww == dw) && (wh == dh)))
|
||||
{
|
||||
y = y + mfc->yCurrentScroll;
|
||||
|
||||
if (wh != dh)
|
||||
{
|
||||
y -= (dh - wh);
|
||||
}
|
||||
|
||||
input->MouseEvent(input, flags, x + mfc->xCurrentScroll, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
y = y * dh / wh + mfc->yCurrentScroll;
|
||||
input->MouseEvent(input, flags, x * dw / ww + mfc->xCurrentScroll, y);
|
||||
}
|
||||
|
||||
if (!mfc->context.settings->SmartSizing || ((ww == dw) && (wh == dh)))
|
||||
{
|
||||
y = y + mfc->yCurrentScroll;
|
||||
|
||||
if (wh != dh)
|
||||
{
|
||||
y -= (dh - wh);
|
||||
}
|
||||
|
||||
input->MouseEvent(input, flags, x + mfc->xCurrentScroll, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
y = y * dh / wh + mfc->yCurrentScroll;
|
||||
input->MouseEvent(input, flags, x * dw / ww + mfc->xCurrentScroll, y);
|
||||
}
|
||||
}
|
||||
|
||||
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/event.h>
|
||||
@ -29,54 +30,575 @@
|
||||
|
||||
#include "wf_cliprdr.h"
|
||||
|
||||
/* this macro will update _p pointer */
|
||||
#define Read_UINT32(_p, _v) do { _v = \
|
||||
(UINT32)(*_p) + \
|
||||
(((UINT32)(*(_p + 1))) << 8) + \
|
||||
(((UINT32)(*(_p + 2))) << 16) + \
|
||||
(((UINT32)(*(_p + 3))) << 24); \
|
||||
_p += 4; } while (0)
|
||||
|
||||
/* this macro will NOT update _p pointer */
|
||||
#define Write_UINT32(_p, _v) do { \
|
||||
*(_p) = (_v) & 0xFF; \
|
||||
*(_p + 1) = ((_v) >> 8) & 0xFF; \
|
||||
*(_p + 2) = ((_v) >> 16) & 0xFF; \
|
||||
*(_p + 3) = ((_v) >> 24) & 0xFF; } while (0)
|
||||
|
||||
|
||||
static UINT32 get_local_format_id_by_name(cliprdrContext *cliprdr, void *format_name)
|
||||
{
|
||||
formatMapping *map;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cliprdr->map_size; i++) {
|
||||
map = &cliprdr->format_mappings[i];
|
||||
if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) {
|
||||
if (map->name) {
|
||||
if (memcmp(map->name, format_name, wcslen((LPCWSTR)format_name)) == 0)
|
||||
return map->local_format_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT32 get_remote_format_id(cliprdrContext *cliprdr, UINT32 local_format)
|
||||
{
|
||||
formatMapping *map;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cliprdr->map_size; i++) {
|
||||
map = &cliprdr->format_mappings[i];
|
||||
if (map->local_format_id == local_format) {
|
||||
return map->remote_format_id;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void map_ensure_capacity(cliprdrContext *cliprdr)
|
||||
{
|
||||
if (cliprdr->map_size >= cliprdr->map_capacity) {
|
||||
cliprdr->format_mappings = (formatMapping *)realloc(cliprdr->format_mappings,
|
||||
cliprdr->map_capacity * 2);
|
||||
cliprdr->map_capacity *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_format_map(cliprdrContext *cliprdr)
|
||||
{
|
||||
formatMapping *map;
|
||||
int i;
|
||||
|
||||
if (cliprdr->format_mappings) {
|
||||
for (i = 0; i < cliprdr->map_size; i++) {
|
||||
map = &cliprdr->format_mappings[i];
|
||||
map->remote_format_id = 0;
|
||||
map->local_format_id = 0;
|
||||
|
||||
if (map->name) {
|
||||
free(map->name);
|
||||
map->name = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cliprdr->map_size= 0;
|
||||
}
|
||||
|
||||
static void cliprdr_send_format_list(cliprdrContext *cliprdr)
|
||||
{
|
||||
RDP_CB_FORMAT_LIST_EVENT *cliprdr_event;
|
||||
BYTE *format_data;
|
||||
int format = 0;
|
||||
int data_size;
|
||||
int format_count;
|
||||
int len = 0;
|
||||
int namelen;
|
||||
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard)) {
|
||||
DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
format_count = CountClipboardFormats();
|
||||
data_size = format_count * (4 + MAX_PATH * 2);
|
||||
|
||||
format_data = (BYTE *)calloc(1, data_size);
|
||||
assert(format_data != NULL);
|
||||
|
||||
while (format = EnumClipboardFormats(format)) {
|
||||
Write_UINT32(format_data + len, format);
|
||||
len += 4;
|
||||
if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) {
|
||||
if (format >= CF_MAX) {
|
||||
namelen = GetClipboardFormatNameW(format, (LPWSTR)(format_data + len), MAX_PATH);
|
||||
len += namelen * sizeof(WCHAR);
|
||||
}
|
||||
len += 2; /* end of Unicode string */
|
||||
} else {
|
||||
ZeroMemory(format_data + len, 32);
|
||||
if (format >= CF_MAX) {
|
||||
static wchar_t wName[MAX_PATH] = {0};
|
||||
|
||||
ZeroMemory(wName, MAX_PATH*2);
|
||||
GetClipboardFormatNameW(format, wName, MAX_PATH);
|
||||
memcpy(format_data + len, wName, 32); /* truncate the long name to 32 bytes */
|
||||
}
|
||||
len += 32;
|
||||
}
|
||||
}
|
||||
|
||||
CloseClipboard();
|
||||
|
||||
cliprdr_event = (RDP_CB_FORMAT_LIST_EVENT *) freerdp_event_new(CliprdrChannel_Class,
|
||||
CliprdrChannel_FormatList, NULL, NULL);
|
||||
|
||||
cliprdr_event->raw_format_data = (BYTE *)calloc(1, len);
|
||||
assert(cliprdr_event->raw_format_data != NULL);
|
||||
|
||||
CopyMemory(cliprdr_event->raw_format_data, format_data, len);
|
||||
cliprdr_event->raw_format_data_size = len;
|
||||
|
||||
free(format_data);
|
||||
|
||||
freerdp_channels_send_event(cliprdr->channels, (wMessage *) cliprdr_event);
|
||||
}
|
||||
|
||||
int cliprdr_send_data_request(cliprdrContext *cliprdr, UINT32 format)
|
||||
{
|
||||
RDP_CB_DATA_REQUEST_EVENT *cliprdr_event;
|
||||
int ret;
|
||||
|
||||
cliprdr_event = (RDP_CB_DATA_REQUEST_EVENT *)freerdp_event_new(CliprdrChannel_Class,
|
||||
CliprdrChannel_DataRequest, NULL, NULL);
|
||||
|
||||
if (!cliprdr_event)
|
||||
return -1;
|
||||
|
||||
cliprdr_event->format = get_remote_format_id(cliprdr, format);
|
||||
|
||||
ret = freerdp_channels_send_event(cliprdr->channels, (wMessage *)cliprdr_event);
|
||||
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
|
||||
WaitForSingleObject(cliprdr->response_data_event, INFINITE);
|
||||
ResetEvent(cliprdr->response_data_event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static cliprdrContext *cliprdr = NULL;
|
||||
|
||||
switch (Msg) {
|
||||
case WM_CREATE:
|
||||
cliprdr = (cliprdrContext *)((CREATESTRUCT *)lParam)->lpCreateParams;
|
||||
cliprdr->hwndNextViewer = SetClipboardViewer(hWnd);
|
||||
|
||||
if (cliprdr->hwndNextViewer == NULL && GetLastError() != 0) {
|
||||
DEBUG_CLIPRDR("error: SetClipboardViewer failed with 0x%0x.", GetLastError());
|
||||
}
|
||||
cliprdr->hwndClipboard = hWnd;
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
ChangeClipboardChain(hWnd, cliprdr->hwndNextViewer);
|
||||
break;
|
||||
|
||||
case WM_CHANGECBCHAIN:
|
||||
if (cliprdr->hwndNextViewer == (HWND)wParam) {
|
||||
cliprdr->hwndNextViewer = (HWND)lParam;
|
||||
} else if (cliprdr->hwndNextViewer != NULL) {
|
||||
SendMessage(cliprdr->hwndNextViewer, Msg, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_DRAWCLIPBOARD:
|
||||
if (cliprdr->channel_initialized) {
|
||||
if (GetClipboardOwner() != cliprdr->hwndClipboard) {
|
||||
if (!cliprdr->hmem) {
|
||||
cliprdr->hmem = GlobalFree(cliprdr->hmem);
|
||||
}
|
||||
cliprdr_send_format_list(cliprdr);
|
||||
}
|
||||
}
|
||||
if (cliprdr->hwndNextViewer != NULL && cliprdr->hwndNextViewer != hWnd)
|
||||
SendMessage(cliprdr->hwndNextViewer, Msg, wParam, lParam);
|
||||
break;
|
||||
|
||||
case WM_RENDERALLFORMATS:
|
||||
/* discard all contexts in clipboard */
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard)) {
|
||||
DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
|
||||
break;
|
||||
}
|
||||
EmptyClipboard();
|
||||
CloseClipboard();
|
||||
break;
|
||||
|
||||
case WM_RENDERFORMAT:
|
||||
if (cliprdr_send_data_request(cliprdr, (UINT32)wParam) != 0) {
|
||||
DEBUG_CLIPRDR("error: cliprdr_send_data_request failed.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (SetClipboardData(wParam, cliprdr->hmem) == NULL) {
|
||||
DEBUG_CLIPRDR("SetClipboardData failed with 0x%x", GetLastError());
|
||||
cliprdr->hmem = GlobalFree(cliprdr->hmem);
|
||||
}
|
||||
/* Note: GlobalFree() is not needed when success */
|
||||
break;
|
||||
|
||||
case WM_CLIPBOARDUPDATE:
|
||||
case WM_DESTROYCLIPBOARD:
|
||||
case WM_ASKCBFORMATNAME:
|
||||
case WM_HSCROLLCLIPBOARD:
|
||||
case WM_PAINTCLIPBOARD:
|
||||
case WM_SIZECLIPBOARD:
|
||||
case WM_VSCROLLCLIPBOARD:
|
||||
default:
|
||||
return DefWindowProc(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int create_cliprdr_window(cliprdrContext *cliprdr)
|
||||
{
|
||||
WNDCLASSEX wnd_cls;
|
||||
|
||||
ZeroMemory(&wnd_cls, sizeof(WNDCLASSEX));
|
||||
wnd_cls.cbSize = sizeof(WNDCLASSEX);
|
||||
wnd_cls.style = CS_OWNDC;
|
||||
wnd_cls.lpfnWndProc = cliprdr_proc;
|
||||
wnd_cls.cbClsExtra = 0;
|
||||
wnd_cls.cbWndExtra = 0;
|
||||
wnd_cls.hIcon = NULL;
|
||||
wnd_cls.hCursor = NULL;
|
||||
wnd_cls.hbrBackground = NULL;
|
||||
wnd_cls.lpszMenuName = NULL;
|
||||
wnd_cls.lpszClassName = L"ClipboardHiddenMessageProcessor";
|
||||
wnd_cls.hInstance = GetModuleHandle(NULL);
|
||||
wnd_cls.hIconSm = NULL;
|
||||
RegisterClassEx(&wnd_cls);
|
||||
|
||||
cliprdr->hwndClipboard = CreateWindowEx(WS_EX_LEFT,
|
||||
L"ClipboardHiddenMessageProcessor",
|
||||
L"rdpclip",
|
||||
0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), cliprdr);
|
||||
|
||||
if (cliprdr->hwndClipboard == NULL) {
|
||||
DEBUG_CLIPRDR("error: CreateWindowEx failed with %x.", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *cliprdr_thread_func(void *arg)
|
||||
{
|
||||
cliprdrContext *cliprdr = (cliprdrContext *)arg;
|
||||
BOOL mcode;
|
||||
MSG msg;
|
||||
int ret;
|
||||
HRESULT result;
|
||||
|
||||
if ((ret = create_cliprdr_window(cliprdr)) != 0) {
|
||||
DEBUG_CLIPRDR("error: create clipboard window failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((mcode = GetMessage(&msg, 0, 0, 0) != 0)) {
|
||||
if (mcode == -1) {
|
||||
DEBUG_CLIPRDR("error: clipboard thread GetMessage failed.");
|
||||
break;
|
||||
} else {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void wf_cliprdr_init(wfContext* wfc, rdpChannels* channels)
|
||||
{
|
||||
cliprdrContext *cliprdr;
|
||||
|
||||
wfc->cliprdr_context = (cliprdrContext *) calloc(1, sizeof(cliprdrContext));
|
||||
cliprdr = (cliprdrContext *) wfc->cliprdr_context;
|
||||
assert(cliprdr != NULL);
|
||||
|
||||
cliprdr->channels = channels;
|
||||
cliprdr->channel_initialized = FALSE;
|
||||
|
||||
cliprdr->map_capacity = 32;
|
||||
cliprdr->map_size = 0;
|
||||
|
||||
cliprdr->format_mappings = (formatMapping *)calloc(1, sizeof(formatMapping) * cliprdr->map_capacity);
|
||||
assert(cliprdr->format_mappings != NULL);
|
||||
|
||||
cliprdr->response_data_event = CreateEvent(NULL, TRUE, FALSE, L"response_data_event");
|
||||
assert(cliprdr->response_data_event != NULL);
|
||||
|
||||
cliprdr->cliprdr_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)cliprdr_thread_func, cliprdr, 0, NULL);
|
||||
assert(cliprdr->cliprdr_thread != NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void wf_cliprdr_uninit(wfContext* wfc)
|
||||
{
|
||||
cliprdrContext *cliprdr = (cliprdrContext *) wfc->cliprdr_context;
|
||||
|
||||
if (!cliprdr)
|
||||
return;
|
||||
|
||||
if (cliprdr->hwndClipboard)
|
||||
PostMessage(cliprdr->hwndClipboard, WM_QUIT, 0, 0);
|
||||
|
||||
if (cliprdr->cliprdr_thread) {
|
||||
WaitForSingleObject(cliprdr->cliprdr_thread, INFINITE);
|
||||
CloseHandle(cliprdr->cliprdr_thread);
|
||||
}
|
||||
|
||||
if (cliprdr->response_data_event)
|
||||
CloseHandle(cliprdr->response_data_event);
|
||||
|
||||
clear_format_map(cliprdr);
|
||||
|
||||
if (cliprdr->format_mappings)
|
||||
free(cliprdr->format_mappings);
|
||||
|
||||
free(cliprdr);
|
||||
}
|
||||
|
||||
static void wf_cliprdr_process_cb_monitor_ready_event(wfContext* wfc)
|
||||
static void wf_cliprdr_process_cb_clip_caps_event(wfContext *wfc, RDP_CB_CLIP_CAPS *caps_event)
|
||||
{
|
||||
cliprdrContext *cliprdr = (cliprdrContext *)wfc->cliprdr_context;
|
||||
|
||||
cliprdr->capabilities = caps_event->capabilities;
|
||||
}
|
||||
|
||||
static void wf_cliprdr_process_cb_data_request_event(wfContext* wfc, RDP_CB_DATA_REQUEST_EVENT* event)
|
||||
static void wf_cliprdr_process_cb_monitor_ready_event(wfContext *wfc, RDP_CB_MONITOR_READY_EVENT *ready_event)
|
||||
{
|
||||
cliprdrContext *cliprdr = (cliprdrContext *)wfc->cliprdr_context;
|
||||
|
||||
cliprdr->channel_initialized = TRUE;
|
||||
|
||||
cliprdr_send_format_list(wfc->cliprdr_context);
|
||||
}
|
||||
|
||||
static void wf_cliprdr_process_cb_format_list_event(wfContext* wfc, RDP_CB_FORMAT_LIST_EVENT* event)
|
||||
static void wf_cliprdr_process_cb_data_request_event(wfContext *wfc, RDP_CB_DATA_REQUEST_EVENT *event)
|
||||
{
|
||||
cliprdrContext *cliprdr = (cliprdrContext *)wfc->cliprdr_context;
|
||||
RDP_CB_DATA_RESPONSE_EVENT *responce_event;
|
||||
HANDLE hClipdata;
|
||||
int size = 0;
|
||||
char *buff = NULL;
|
||||
char *globlemem = NULL;
|
||||
UINT32 local_format;
|
||||
|
||||
local_format = event->format;
|
||||
|
||||
if (local_format == 0x9) { /* FORMAT_ID_PALETTE */
|
||||
/* TODO: implement this */
|
||||
DEBUG_CLIPRDR("FORMAT_ID_PALETTE is not supported yet.");
|
||||
} else if (local_format == 0x3) { /* FORMAT_ID_MATEFILE */
|
||||
/* TODO: implement this */
|
||||
DEBUG_CLIPRDR("FORMAT_ID_MATEFILE is not supported yet.");
|
||||
} else if (local_format == RegisterClipboardFormatW(L"FileGroupDescriptorW")) {
|
||||
/* TODO: implement this */
|
||||
DEBUG_CLIPRDR("FileGroupDescriptorW is not supported yet.");
|
||||
} else {
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard)) {
|
||||
DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
hClipdata = GetClipboardData(event->format);
|
||||
if (!hClipdata) {
|
||||
DEBUG_CLIPRDR("GetClipboardData failed.");
|
||||
CloseClipboard();
|
||||
return;
|
||||
}
|
||||
|
||||
globlemem = (char *)GlobalLock(hClipdata);
|
||||
size = GlobalSize(hClipdata);
|
||||
|
||||
buff = (char *)malloc(size);
|
||||
memcpy(buff, globlemem, size);
|
||||
|
||||
GlobalUnlock(hClipdata);
|
||||
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
responce_event = (RDP_CB_DATA_RESPONSE_EVENT *)freerdp_event_new(CliprdrChannel_Class,
|
||||
CliprdrChannel_DataResponse, NULL, NULL);
|
||||
|
||||
responce_event->data = (BYTE *)buff;
|
||||
responce_event->size = size;
|
||||
|
||||
freerdp_channels_send_event(cliprdr->channels, (wMessage *) responce_event);
|
||||
|
||||
/* Note: don't free buff here. */
|
||||
}
|
||||
|
||||
static void wf_cliprdr_process_cb_data_response_event(wfContext* wfc, RDP_CB_DATA_RESPONSE_EVENT* event)
|
||||
static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMAT_LIST_EVENT *event)
|
||||
{
|
||||
cliprdrContext *cliprdr = (cliprdrContext *)wfc->cliprdr_context;
|
||||
UINT32 left_size = event->raw_format_data_size;
|
||||
int i = 0;
|
||||
BYTE *p;
|
||||
BYTE* end_mark;
|
||||
BOOL format_forbidden = FALSE;
|
||||
|
||||
/* ignore the formats member in event struct, only parsing raw_format_data */
|
||||
|
||||
p = event->raw_format_data;
|
||||
end_mark = p + event->raw_format_data_size;
|
||||
|
||||
clear_format_map(cliprdr);
|
||||
|
||||
if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) {
|
||||
while (left_size >= 6) {
|
||||
formatMapping *map;
|
||||
BYTE* tmp;
|
||||
int name_len;
|
||||
|
||||
map = &cliprdr->format_mappings[i++];
|
||||
|
||||
Read_UINT32(p, map->remote_format_id);
|
||||
|
||||
/* get name_len */
|
||||
for (tmp = p, name_len = 0; tmp + 1 < end_mark; tmp += 2, name_len += 2) {
|
||||
if (*((unsigned short*) tmp) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (name_len > 0) {
|
||||
map->name = malloc(name_len + 2);
|
||||
memcpy(map->name, p, name_len + 2);
|
||||
|
||||
map->local_format_id = RegisterClipboardFormatW((LPCWSTR)map->name);
|
||||
} else {
|
||||
map->local_format_id = map->remote_format_id;
|
||||
}
|
||||
|
||||
left_size -= name_len + 4 + 2;
|
||||
p += name_len + 2; /* p's already +4 when Read_UINT32() is called. */
|
||||
|
||||
cliprdr->map_size++;
|
||||
|
||||
map_ensure_capacity(cliprdr);
|
||||
}
|
||||
} else {
|
||||
int k;
|
||||
|
||||
for (k = 0; k < event->raw_format_data_size / 36; k++) {
|
||||
formatMapping *map;
|
||||
int name_len;
|
||||
|
||||
map = &cliprdr->format_mappings[i++];
|
||||
|
||||
Read_UINT32(p, map->remote_format_id);
|
||||
|
||||
if (event->raw_format_unicode) {
|
||||
/* get name_len, in bytes, if the file name is truncated, no terminated null will be included. */
|
||||
for (name_len = 0; name_len < 32; name_len += 2) {
|
||||
if (*((unsigned short*) (p + name_len)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (name_len > 0) {
|
||||
map->name = calloc(1, name_len + 2);
|
||||
memcpy(map->name, p, name_len);
|
||||
map->local_format_id = RegisterClipboardFormatW((LPCWSTR)map->name);
|
||||
} else {
|
||||
map->local_format_id = map->remote_format_id;
|
||||
}
|
||||
} else {
|
||||
/* get name_len, in bytes, if the file name is truncated, no terminated null will be included. */
|
||||
for (name_len = 0; name_len < 32; name_len += 1) {
|
||||
if (*((unsigned char*) (p + name_len)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (name_len > 0) {
|
||||
map->name = calloc(1, name_len + 1);
|
||||
memcpy(map->name, p, name_len);
|
||||
map->local_format_id = RegisterClipboardFormatA((LPCSTR)map->name);
|
||||
} else {
|
||||
map->local_format_id = map->remote_format_id;
|
||||
}
|
||||
}
|
||||
|
||||
p += 32; /* p's already +4 when Read_UINT32() is called. */
|
||||
cliprdr->map_size++;
|
||||
map_ensure_capacity(cliprdr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard)) {
|
||||
DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EmptyClipboard()) {
|
||||
DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError());
|
||||
CloseClipboard();
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < cliprdr->map_size; i++) {
|
||||
SetClipboardData(cliprdr->format_mappings[i].local_format_id, NULL);
|
||||
}
|
||||
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
void wf_process_cliprdr_event(wfContext* wfc, wMessage* event)
|
||||
static void wf_cliprdr_process_cb_data_response_event(wfContext *wfc, RDP_CB_DATA_RESPONSE_EVENT *event)
|
||||
{
|
||||
switch (GetMessageType(event->id))
|
||||
{
|
||||
cliprdrContext *cliprdr = (cliprdrContext *)wfc->cliprdr_context;
|
||||
HANDLE hMem;
|
||||
char *buff;
|
||||
|
||||
hMem = GlobalAlloc(GMEM_FIXED, event->size);
|
||||
buff = (char *) GlobalLock(hMem);
|
||||
memcpy(buff, event->data, event->size);
|
||||
GlobalUnlock(hMem);
|
||||
|
||||
cliprdr->hmem = hMem;
|
||||
SetEvent(cliprdr->response_data_event);
|
||||
}
|
||||
|
||||
void wf_process_cliprdr_event(wfContext *wfc, wMessage *event)
|
||||
{
|
||||
switch (GetMessageType(event->id)) {
|
||||
case CliprdrChannel_ClipCaps:
|
||||
wf_cliprdr_process_cb_clip_caps_event(wfc, (RDP_CB_CLIP_CAPS *)event);
|
||||
break;
|
||||
|
||||
case CliprdrChannel_MonitorReady:
|
||||
wf_cliprdr_process_cb_monitor_ready_event(wfc);
|
||||
wf_cliprdr_process_cb_monitor_ready_event(wfc, (RDP_CB_MONITOR_READY_EVENT *)event);
|
||||
break;
|
||||
|
||||
case CliprdrChannel_FormatList:
|
||||
wf_cliprdr_process_cb_format_list_event(wfc, (RDP_CB_FORMAT_LIST_EVENT*) event);
|
||||
wf_cliprdr_process_cb_format_list_event(wfc, (RDP_CB_FORMAT_LIST_EVENT *) event);
|
||||
break;
|
||||
|
||||
case CliprdrChannel_DataRequest:
|
||||
wf_cliprdr_process_cb_data_request_event(wfc, (RDP_CB_DATA_REQUEST_EVENT*) event);
|
||||
wf_cliprdr_process_cb_data_request_event(wfc, (RDP_CB_DATA_REQUEST_EVENT *) event);
|
||||
break;
|
||||
|
||||
case CliprdrChannel_DataResponse:
|
||||
wf_cliprdr_process_cb_data_response_event(wfc, (RDP_CB_DATA_RESPONSE_EVENT*) event);
|
||||
wf_cliprdr_process_cb_data_response_event(wfc, (RDP_CB_DATA_RESPONSE_EVENT *) event);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -21,6 +21,40 @@
|
||||
|
||||
#include "wf_interface.h"
|
||||
|
||||
#ifdef WITH_DEBUG_CLIPRDR
|
||||
#define DEBUG_CLIPRDR(fmt, ...) DEBUG_CLASS(WIN_CLIPRDR, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_CLIPRDR(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
typedef struct format_mapping formatMapping;
|
||||
struct format_mapping {
|
||||
UINT32 remote_format_id;
|
||||
UINT32 local_format_id;
|
||||
void *name; /* Unicode or ASCII characters with NULL terminate */
|
||||
};
|
||||
|
||||
typedef struct cliprdr_context cliprdrContext;
|
||||
struct cliprdr_context {
|
||||
rdpChannels *channels;
|
||||
|
||||
UINT32 capabilities;
|
||||
|
||||
formatMapping *format_mappings;
|
||||
int map_capacity;
|
||||
int map_size;
|
||||
|
||||
UINT32 request_format;
|
||||
BOOL channel_initialized;
|
||||
|
||||
HWND hwndClipboard;
|
||||
HWND hwndNextViewer;
|
||||
|
||||
HANDLE cliprdr_thread;
|
||||
HANDLE hmem;
|
||||
HANDLE response_data_event;
|
||||
};
|
||||
|
||||
void wf_cliprdr_init(wfContext* wfc, rdpChannels* channels);
|
||||
void wf_cliprdr_uninit(wfContext* wfc);
|
||||
void wf_process_cliprdr_event(wfContext* wfc, wMessage* event);
|
||||
|
@ -543,12 +543,26 @@ int wf_receive_channel_data(freerdp* instance, int channelId, BYTE* data, int si
|
||||
|
||||
void wf_process_channel_event(rdpChannels* channels, freerdp* instance)
|
||||
{
|
||||
wfContext* wfc;
|
||||
wMessage* event;
|
||||
|
||||
wfc = (wfContext*) instance->context;
|
||||
event = freerdp_channels_pop_event(channels);
|
||||
|
||||
if (event)
|
||||
{
|
||||
switch (GetMessageClass(event->id))
|
||||
{
|
||||
case CliprdrChannel_Class:
|
||||
wf_process_cliprdr_event(wfc, event);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
freerdp_event_free(event);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL wf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
|
||||
|
@ -63,6 +63,7 @@ struct wf_pointer
|
||||
};
|
||||
typedef struct wf_pointer wfPointer;
|
||||
|
||||
typedef struct cliprdr_context cliprdrContext;
|
||||
struct wf_context
|
||||
{
|
||||
rdpContext context;
|
||||
@ -130,6 +131,7 @@ struct wf_context
|
||||
int yMinScroll; // minimum vertical scroll value
|
||||
int yCurrentScroll; // current vertical scroll value
|
||||
int yMaxScroll; // maximum vertical scroll value
|
||||
cliprdrContext *cliprdr_context;
|
||||
};
|
||||
typedef struct wf_context wfContext;
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include <freerdp/client/cmdline.h>
|
||||
#include <freerdp/version.h>
|
||||
|
||||
#include "compatibility.h"
|
||||
|
||||
@ -51,6 +52,8 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
||||
{ "kbd-subtype", COMMAND_LINE_VALUE_REQUIRED, "<subtype id>", NULL, NULL, -1, NULL, "Keyboard subtype" },
|
||||
{ "kbd-fn-key", COMMAND_LINE_VALUE_REQUIRED, "<function key count>", NULL, NULL, -1, NULL, "Keyboard function key count" },
|
||||
{ "admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "console", "Admin (or console) session" },
|
||||
{ "restricted-admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "restrictedAdmin", "Restricted admin mode" },
|
||||
{ "pth", COMMAND_LINE_VALUE_REQUIRED, "<password hash>", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" },
|
||||
{ "multimon", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Use multiple monitors" },
|
||||
{ "workarea", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Use available work area" },
|
||||
{ "monitors", COMMAND_LINE_VALUE_REQUIRED, "<0,1,2...>", NULL, NULL, -1, NULL, "Select monitors to use" },
|
||||
@ -1231,6 +1234,17 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
{
|
||||
settings->ConsoleSession = TRUE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "restricted-admin")
|
||||
{
|
||||
settings->ConsoleSession = TRUE;
|
||||
settings->RestrictedAdminModeRequired = TRUE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "pth")
|
||||
{
|
||||
settings->ConsoleSession = TRUE;
|
||||
settings->RestrictedAdminModeRequired = TRUE;
|
||||
settings->PasswordHash = _strdup(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "kbd")
|
||||
{
|
||||
int id;
|
||||
@ -1747,7 +1761,7 @@ int freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpSettings*
|
||||
{
|
||||
void* entry;
|
||||
|
||||
entry = freerdp_load_channel_addin_entry(name, NULL, NULL, 0);
|
||||
entry = freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
|
@ -481,6 +481,7 @@ BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, const BYTE* buffer, siz
|
||||
|
||||
BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name)
|
||||
{
|
||||
BOOL status;
|
||||
BYTE* buffer;
|
||||
FILE* fp = NULL;
|
||||
size_t read_size;
|
||||
@ -521,7 +522,11 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name)
|
||||
buffer[file_size] = '\0';
|
||||
buffer[file_size + 1] = '\0';
|
||||
|
||||
return freerdp_client_parse_rdp_file_buffer(file, buffer, file_size);
|
||||
status = freerdp_client_parse_rdp_file_buffer(file, buffer, file_size);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#define WRITE_ALL_SETTINGS TRUE
|
||||
@ -966,6 +971,12 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void freerdp_client_file_string_check_free(LPSTR str)
|
||||
{
|
||||
if (~((size_t) str))
|
||||
free(str);
|
||||
}
|
||||
|
||||
rdpFile* freerdp_client_rdp_file_new()
|
||||
{
|
||||
rdpFile* file;
|
||||
@ -1000,6 +1011,26 @@ void freerdp_client_rdp_file_free(rdpFile* file)
|
||||
free(file->argv);
|
||||
}
|
||||
|
||||
freerdp_client_file_string_check_free(file->Username);
|
||||
freerdp_client_file_string_check_free(file->Domain);
|
||||
freerdp_client_file_string_check_free(file->FullAddress);
|
||||
freerdp_client_file_string_check_free(file->AlternateFullAddress);
|
||||
freerdp_client_file_string_check_free(file->UsbDevicesToRedirect);
|
||||
freerdp_client_file_string_check_free(file->LoadBalanceInfo);
|
||||
freerdp_client_file_string_check_free(file->RemoteApplicationName);
|
||||
freerdp_client_file_string_check_free(file->RemoteApplicationIcon);
|
||||
freerdp_client_file_string_check_free(file->RemoteApplicationProgram);
|
||||
freerdp_client_file_string_check_free(file->RemoteApplicationFile);
|
||||
freerdp_client_file_string_check_free(file->RemoteApplicationGuid);
|
||||
freerdp_client_file_string_check_free(file->RemoteApplicationCmdLine);
|
||||
freerdp_client_file_string_check_free(file->AlternateShell);
|
||||
freerdp_client_file_string_check_free(file->ShellWorkingDirectory);
|
||||
freerdp_client_file_string_check_free(file->GatewayHostname);
|
||||
freerdp_client_file_string_check_free(file->KdcProxyName);
|
||||
freerdp_client_file_string_check_free(file->DrivesToRedirect);
|
||||
freerdp_client_file_string_check_free(file->DevicesToRedirect);
|
||||
freerdp_client_file_string_check_free(file->WinPosStr);
|
||||
|
||||
free(file);
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,6 @@
|
||||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
|
||||
#define FREERDP_VERSION_MAJOR ${FREERDP_VERSION_MAJOR}
|
||||
#define FREERDP_VERSION_MINOR ${FREERDP_VERSION_MINOR}
|
||||
#define FREERDP_VERSION_REVISION ${FREERDP_VERSION_REVISION}
|
||||
#define FREERDP_VERSION_SUFFIX "${FREERDP_VERSION_SUFFIX}"
|
||||
#define FREERDP_API_VERSION "${FREERDP_API_VERSION}"
|
||||
#define FREERDP_VERSION "${FREERDP_VERSION}"
|
||||
#define FREERDP_VERSION_FULL "${FREERDP_VERSION_FULL}"
|
||||
#define GIT_REVISION "${GIT_REVISION}"
|
||||
|
||||
#define FREERDP_DATA_PATH "${FREERDP_DATA_PATH}"
|
||||
#define FREERDP_KEYMAP_PATH "${FREERDP_KEYMAP_PATH}"
|
||||
#define FREERDP_PLUGIN_PATH "${FREERDP_PLUGIN_PATH}"
|
||||
|
@ -17,8 +17,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp/version.h)
|
||||
|
||||
file(GLOB FREERDP_HEADERS "freerdp/*.h")
|
||||
install(FILES ${FREERDP_HEADERS} DESTINATION include/freerdp COMPONENT headers)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp/version.h DESTINATION include/freerdp COMPONENT headers)
|
||||
|
||||
install(DIRECTORY freerdp/cache DESTINATION include/freerdp COMPONENT headers FILES_MATCHING PATTERN "*.h")
|
||||
install(DIRECTORY freerdp/codec DESTINATION include/freerdp COMPONENT headers FILES_MATCHING PATTERN "*.h")
|
||||
|
@ -99,7 +99,24 @@ typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME;
|
||||
/**
|
||||
* Clipboard Events
|
||||
*/
|
||||
typedef wMessage RDP_CB_MONITOR_READY_EVENT;
|
||||
#define CAPS_USE_LONG_FORMAT_NAMES 0x00000002
|
||||
#define CAPS_STREAM_FILECLIP_ENABLED 0x00000004
|
||||
#define CAPS_FILECLIP_NO_FILE_PATH 0x00000008
|
||||
#define CAPS_CAN_LOCK_CLIPDATA 0x00000010
|
||||
|
||||
struct _RDP_CB_CLIP_CAPS
|
||||
{
|
||||
wMessage event;
|
||||
UINT32 capabilities;
|
||||
};
|
||||
typedef struct _RDP_CB_CLIP_CAPS RDP_CB_CLIP_CAPS;
|
||||
|
||||
struct _RDP_CB_MONITOR_READY_EVENT
|
||||
{
|
||||
wMessage event;
|
||||
UINT32 capabilities;
|
||||
};
|
||||
typedef struct _RDP_CB_MONITOR_READY_EVENT RDP_CB_MONITOR_READY_EVENT;
|
||||
|
||||
struct _RDP_CB_FORMAT_LIST_EVENT
|
||||
{
|
||||
@ -108,6 +125,7 @@ struct _RDP_CB_FORMAT_LIST_EVENT
|
||||
UINT16 num_formats;
|
||||
BYTE* raw_format_data;
|
||||
UINT32 raw_format_data_size;
|
||||
BOOL raw_format_unicode;
|
||||
};
|
||||
typedef struct _RDP_CB_FORMAT_LIST_EVENT RDP_CB_FORMAT_LIST_EVENT;
|
||||
|
||||
|
@ -260,11 +260,13 @@
|
||||
#define CliprdrChannel_FormatList 2
|
||||
#define CliprdrChannel_DataRequest 3
|
||||
#define CliprdrChannel_DataResponse 4
|
||||
#define CliprdrChannel_ClipCaps 5
|
||||
|
||||
#define FREERDP_CLIPRDR_CHANNEL_MONITOR_READY MakeMessageId(CliprdrChannel, MonitorReady)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_FORMAT_LIST MakeMessageId(CliprdrChannel, FormatList)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_FORMAT_LIST MakeMessageId(CliprdrChannel, FormatList)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_DATA_REQUEST MakeMessageId(CliprdrChannel, DataRequest)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_DATA_RESPONSE MakeMessageId(CliprdrChannel, DataResponse)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_CLIP_CAPS MakeMessageId(CliprdrChannel, ClipCaps)
|
||||
|
||||
/**
|
||||
* Multimedia Redirection Channel
|
||||
|
@ -476,6 +476,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
|
||||
#define FreeRDP_Username 21
|
||||
#define FreeRDP_Password 22
|
||||
#define FreeRDP_Domain 23
|
||||
#define FreeRDP_PasswordHash 24
|
||||
#define FreeRDP_RdpVersion 128
|
||||
#define FreeRDP_DesktopWidth 129
|
||||
#define FreeRDP_DesktopHeight 130
|
||||
@ -562,6 +563,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
|
||||
#define FreeRDP_SelectedProtocol 1094
|
||||
#define FreeRDP_NegotiationFlags 1095
|
||||
#define FreeRDP_NegotiateSecurityLayer 1096
|
||||
#define FreeRDP_RestrictedAdminModeRequired 1097
|
||||
#define FreeRDP_MstscCookieMode 1152
|
||||
#define FreeRDP_CookieMaxLength 1153
|
||||
#define FreeRDP_PreconnectionId 1154
|
||||
@ -759,7 +761,8 @@ struct rdp_settings
|
||||
ALIGN64 char* Username; /* 21 */
|
||||
ALIGN64 char* Password; /* 22 */
|
||||
ALIGN64 char* Domain; /* 23 */
|
||||
UINT64 padding0064[64 - 24]; /* 24 */
|
||||
ALIGN64 char* PasswordHash; /* 24 */
|
||||
UINT64 padding0064[64 - 25]; /* 25 */
|
||||
UINT64 padding0128[128 - 64]; /* 64 */
|
||||
|
||||
/**
|
||||
@ -907,7 +910,8 @@ struct rdp_settings
|
||||
ALIGN64 UINT32 SelectedProtocol; /* 1094 */
|
||||
ALIGN64 UINT32 NegotiationFlags; /* 1095 */
|
||||
ALIGN64 BOOL NegotiateSecurityLayer; /* 1096 */
|
||||
UINT64 padding1152[1152 - 1097]; /* 1097 */
|
||||
ALIGN64 BOOL RestrictedAdminModeRequired; /* 1097 */
|
||||
UINT64 padding1152[1152 - 1098]; /* 1098 */
|
||||
|
||||
/* Connection Cookie */
|
||||
ALIGN64 BOOL MstscCookieMode; /* 1152 */
|
||||
|
32
include/freerdp/version.h.in
Normal file
32
include/freerdp/version.h.in
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Version includes
|
||||
*
|
||||
* Copyright 2013 Thinstuff Technologies GmbH
|
||||
* Copyright 2013 Bernhard Miklautz <bmiklautz@thinstuff.at>
|
||||
*
|
||||
* 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 _FREERDP_VERSION_H_
|
||||
#define _FREERDP_VERSION_H_
|
||||
|
||||
#define FREERDP_VERSION_MAJOR ${FREERDP_VERSION_MAJOR}
|
||||
#define FREERDP_VERSION_MINOR ${FREERDP_VERSION_MINOR}
|
||||
#define FREERDP_VERSION_REVISION ${FREERDP_VERSION_REVISION}
|
||||
#define FREERDP_VERSION_SUFFIX "${FREERDP_VERSION_SUFFIX}"
|
||||
#define FREERDP_API_VERSION "${FREERDP_API_VERSION}"
|
||||
#define FREERDP_VERSION "${FREERDP_VERSION}"
|
||||
#define FREERDP_VERSION_FULL "${FREERDP_VERSION_FULL}"
|
||||
#define GIT_REVISION "${GIT_REVISION}"
|
||||
|
||||
#endif // _FREERDP_VERSION_H_
|
@ -649,6 +649,10 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
|
||||
return settings->NegotiateSecurityLayer;
|
||||
break;
|
||||
|
||||
case FreeRDP_RestrictedAdminModeRequired:
|
||||
return settings->RestrictedAdminModeRequired;
|
||||
break;
|
||||
|
||||
case FreeRDP_MstscCookieMode:
|
||||
return settings->MstscCookieMode;
|
||||
break;
|
||||
@ -1109,6 +1113,10 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
|
||||
settings->NegotiateSecurityLayer = param;
|
||||
break;
|
||||
|
||||
case FreeRDP_RestrictedAdminModeRequired:
|
||||
settings->RestrictedAdminModeRequired = param;
|
||||
break;
|
||||
|
||||
case FreeRDP_MstscCookieMode:
|
||||
settings->MstscCookieMode = param;
|
||||
break;
|
||||
@ -2088,6 +2096,10 @@ char* freerdp_get_param_string(rdpSettings* settings, int id)
|
||||
return settings->Domain;
|
||||
break;
|
||||
|
||||
case FreeRDP_PasswordHash:
|
||||
return settings->PasswordHash;
|
||||
break;
|
||||
|
||||
case FreeRDP_ClientHostname:
|
||||
return settings->ClientHostname;
|
||||
break;
|
||||
@ -2237,154 +2249,197 @@ int freerdp_set_param_string(rdpSettings* settings, int id, const char* param)
|
||||
switch (id)
|
||||
{
|
||||
case FreeRDP_ServerHostname:
|
||||
free(settings->ServerHostname);
|
||||
settings->ServerHostname = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_Username:
|
||||
free(settings->Username);
|
||||
settings->Username = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_Password:
|
||||
free(settings->Password);
|
||||
settings->Password = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_Domain:
|
||||
free(settings->Domain);
|
||||
settings->Domain = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_PasswordHash:
|
||||
free(settings->PasswordHash);
|
||||
settings->PasswordHash = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_ClientHostname:
|
||||
free(settings->ClientHostname);
|
||||
settings->ClientHostname = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_ClientProductId:
|
||||
free(settings->ClientProductId);
|
||||
settings->ClientProductId = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_AlternateShell:
|
||||
free(settings->AlternateShell);
|
||||
settings->AlternateShell = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_ShellWorkingDirectory:
|
||||
free(settings->ShellWorkingDirectory);
|
||||
settings->ShellWorkingDirectory = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_ClientAddress:
|
||||
free(settings->ClientAddress);
|
||||
settings->ClientAddress = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_ClientDir:
|
||||
free(settings->ClientDir);
|
||||
settings->ClientDir = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_DynamicDSTTimeZoneKeyName:
|
||||
free(settings->DynamicDSTTimeZoneKeyName);
|
||||
settings->DynamicDSTTimeZoneKeyName = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_PreconnectionBlob:
|
||||
free(settings->PreconnectionBlob);
|
||||
settings->PreconnectionBlob = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_KerberosKdc:
|
||||
free(settings->KerberosKdc);
|
||||
settings->KerberosKdc = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_KerberosRealm:
|
||||
free(settings->KerberosRealm);
|
||||
settings->KerberosRealm = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_CertificateName:
|
||||
free(settings->CertificateName);
|
||||
settings->CertificateName = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_CertificateFile:
|
||||
free(settings->CertificateFile);
|
||||
settings->CertificateFile = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_PrivateKeyFile:
|
||||
free(settings->PrivateKeyFile);
|
||||
settings->PrivateKeyFile = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_RdpKeyFile:
|
||||
free(settings->RdpKeyFile);
|
||||
settings->RdpKeyFile = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_WindowTitle:
|
||||
free(settings->WindowTitle);
|
||||
settings->WindowTitle = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_ComputerName:
|
||||
free(settings->ComputerName);
|
||||
settings->ComputerName = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_ConnectionFile:
|
||||
free(settings->ConnectionFile);
|
||||
settings->ConnectionFile = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_HomePath:
|
||||
free(settings->HomePath);
|
||||
settings->HomePath = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_ConfigPath:
|
||||
free(settings->ConfigPath);
|
||||
settings->ConfigPath = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_CurrentPath:
|
||||
free(settings->CurrentPath);
|
||||
settings->CurrentPath = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_DumpRemoteFxFile:
|
||||
free(settings->DumpRemoteFxFile);
|
||||
settings->DumpRemoteFxFile = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_PlayRemoteFxFile:
|
||||
free(settings->PlayRemoteFxFile);
|
||||
settings->PlayRemoteFxFile = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_GatewayHostname:
|
||||
free(settings->GatewayHostname);
|
||||
settings->GatewayHostname = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_GatewayUsername:
|
||||
free(settings->GatewayUsername);
|
||||
settings->GatewayUsername = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_GatewayPassword:
|
||||
free(settings->GatewayPassword);
|
||||
settings->GatewayPassword = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_GatewayDomain:
|
||||
free(settings->GatewayDomain);
|
||||
settings->GatewayDomain = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_RemoteApplicationName:
|
||||
free(settings->RemoteApplicationName);
|
||||
settings->RemoteApplicationName = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_RemoteApplicationIcon:
|
||||
free(settings->RemoteApplicationIcon);
|
||||
settings->RemoteApplicationIcon = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_RemoteApplicationProgram:
|
||||
free(settings->RemoteApplicationProgram);
|
||||
settings->RemoteApplicationProgram = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_RemoteApplicationFile:
|
||||
free(settings->RemoteApplicationFile);
|
||||
settings->RemoteApplicationFile = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_RemoteApplicationGuid:
|
||||
free(settings->RemoteApplicationGuid);
|
||||
settings->RemoteApplicationGuid = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_RemoteApplicationCmdLine:
|
||||
free(settings->RemoteApplicationCmdLine);
|
||||
settings->RemoteApplicationCmdLine = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_ImeFileName:
|
||||
free(settings->ImeFileName);
|
||||
settings->ImeFileName = _strdup(param);
|
||||
break;
|
||||
|
||||
case FreeRDP_DrivesToRedirect:
|
||||
free(settings->DrivesToRedirect);
|
||||
settings->DrivesToRedirect = _strdup(param);
|
||||
break;
|
||||
|
||||
|
@ -228,6 +228,7 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
||||
nego_set_preconnection_blob(rdp->nego, settings->PreconnectionBlob);
|
||||
|
||||
nego_set_negotiation_enabled(rdp->nego, settings->NegotiateSecurityLayer);
|
||||
nego_set_restricted_admin_mode_required(rdp->nego, settings->RestrictedAdminModeRequired);
|
||||
|
||||
nego_enable_rdp(rdp->nego, settings->RdpSecurity);
|
||||
nego_enable_tls(rdp->nego, settings->TlsSecurity);
|
||||
@ -598,15 +599,19 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_client_connect_license(rdpRdp* rdp, wStream* s)
|
||||
int rdp_client_connect_license(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
if (!license_recv(rdp->license, s))
|
||||
return FALSE;
|
||||
int status;
|
||||
|
||||
status = license_recv(rdp->license, s);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
if (rdp->license->state == LICENSE_STATE_ABORTED)
|
||||
{
|
||||
fprintf(stderr, "license connection sequence aborted.\n");
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rdp->license->state == LICENSE_STATE_COMPLETED)
|
||||
@ -614,10 +619,10 @@ BOOL rdp_client_connect_license(rdpRdp* rdp, wStream* s)
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
|
||||
int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
BYTE* mark;
|
||||
UINT16 width;
|
||||
@ -631,24 +636,23 @@ BOOL rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
|
||||
if (!rdp_recv_demand_active(rdp, s))
|
||||
{
|
||||
UINT16 channelId;
|
||||
|
||||
Stream_SetPointer(s, mark);
|
||||
rdp_recv_get_active_header(rdp, s, &channelId);
|
||||
|
||||
/* Was Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH);
|
||||
* but the headers aren't always that length,
|
||||
* so that could result in a bad offset.
|
||||
*/
|
||||
|
||||
if (!rdp_recv_out_of_sequence_pdu(rdp, s))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
return rdp_recv_out_of_sequence_pdu(rdp, s);
|
||||
}
|
||||
|
||||
if (rdp->disconnect)
|
||||
return TRUE;
|
||||
return 0;
|
||||
|
||||
if (!rdp_send_confirm_active(rdp))
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
input_register_client_callbacks(rdp->input);
|
||||
|
||||
@ -666,7 +670,7 @@ BOOL rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
|
||||
return rdp_client_connect_finalize(rdp);
|
||||
}
|
||||
|
||||
BOOL rdp_client_connect_finalize(rdpRdp* rdp)
|
||||
int rdp_client_connect_finalize(rdpRdp* rdp)
|
||||
{
|
||||
/**
|
||||
* [MS-RDPBCGR] 1.3.1.1 - 8.
|
||||
@ -675,13 +679,13 @@ BOOL rdp_client_connect_finalize(rdpRdp* rdp)
|
||||
*/
|
||||
|
||||
if (!rdp_send_client_synchronize_pdu(rdp))
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
if (!rdp_send_client_control_pdu(rdp, CTRLACTION_COOPERATE))
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
if (!rdp_send_client_control_pdu(rdp, CTRLACTION_REQUEST_CONTROL))
|
||||
return FALSE;
|
||||
return -1;
|
||||
/**
|
||||
* [MS-RDPBCGR] 2.2.1.17
|
||||
* Client persistent key list must be sent if a bitmap is
|
||||
@ -692,13 +696,13 @@ BOOL rdp_client_connect_finalize(rdpRdp* rdp)
|
||||
if (!rdp->deactivation_reactivation && rdp->settings->BitmapCachePersistEnabled)
|
||||
{
|
||||
if (!rdp_send_client_persistent_key_list_pdu(rdp))
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!rdp_send_client_font_list_pdu(rdp, FONTLIST_FIRST | FONTLIST_LAST))
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
return TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rdp_client_transition_to_state(rdpRdp* rdp, int state)
|
||||
|
@ -52,9 +52,9 @@ BOOL rdp_client_redirect(rdpRdp* rdp);
|
||||
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s);
|
||||
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s);
|
||||
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s);
|
||||
BOOL rdp_client_connect_license(rdpRdp* rdp, wStream* s);
|
||||
BOOL rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s);
|
||||
BOOL rdp_client_connect_finalize(rdpRdp* rdp);
|
||||
int rdp_client_connect_license(rdpRdp* rdp, wStream* s);
|
||||
int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s);
|
||||
int rdp_client_connect_finalize(rdpRdp* rdp);
|
||||
int rdp_client_transition_to_state(rdpRdp* rdp, int state);
|
||||
|
||||
BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s);
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <freerdp/error.h>
|
||||
#include <freerdp/event.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#include <freerdp/version.h>
|
||||
|
||||
/* connectErrorCode is 'extern' in error.h. See comment there.*/
|
||||
|
||||
|
@ -229,7 +229,7 @@ BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
|
||||
* @return if the operation completed successfully
|
||||
*/
|
||||
|
||||
BOOL license_recv(rdpLicense* license, wStream* s)
|
||||
int license_recv(rdpLicense* license, wStream* s)
|
||||
{
|
||||
BYTE flags;
|
||||
BYTE bMsgType;
|
||||
@ -241,37 +241,41 @@ BOOL license_recv(rdpLicense* license, wStream* s)
|
||||
if (!rdp_read_header(license->rdp, s, &length, &channelId))
|
||||
{
|
||||
fprintf(stderr, "Incorrect RDP header.\n");
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!rdp_read_security_header(s, &securityFlags))
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
if (securityFlags & SEC_ENCRYPT)
|
||||
{
|
||||
if (!rdp_decrypt(license->rdp, s, length - 4, securityFlags))
|
||||
{
|
||||
fprintf(stderr, "rdp_decrypt failed\n");
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(securityFlags & SEC_LICENSE_PKT))
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!(securityFlags & SEC_ENCRYPT))
|
||||
Stream_Rewind(s, RDP_SECURITY_HEADER_LENGTH);
|
||||
|
||||
if (rdp_recv_out_of_sequence_pdu(license->rdp, s) != TRUE)
|
||||
status = rdp_recv_out_of_sequence_pdu(license->rdp, s);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
fprintf(stderr, "Unexpected license packet.\n");
|
||||
return FALSE;
|
||||
return status;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!license_read_preamble(s, &bMsgType, &flags, &wMsgSize)) /* preamble (4 bytes) */
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
DEBUG_LICENSE("Receiving %s Packet", LICENSE_MESSAGE_STRINGS[bMsgType & 0x1F]);
|
||||
|
||||
@ -279,13 +283,13 @@ BOOL license_recv(rdpLicense* license, wStream* s)
|
||||
{
|
||||
case LICENSE_REQUEST:
|
||||
if (!license_read_license_request_packet(license, s))
|
||||
return FALSE;
|
||||
return -1;
|
||||
license_send_new_license_request_packet(license);
|
||||
break;
|
||||
|
||||
case PLATFORM_CHALLENGE:
|
||||
if (!license_read_platform_challenge_packet(license, s))
|
||||
return FALSE;
|
||||
return -1;
|
||||
license_send_platform_challenge_response_packet(license);
|
||||
break;
|
||||
|
||||
@ -299,7 +303,7 @@ BOOL license_recv(rdpLicense* license, wStream* s)
|
||||
|
||||
case ERROR_ALERT:
|
||||
if (!license_read_error_alert_packet(license, s))
|
||||
return FALSE;
|
||||
return -1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -307,7 +311,7 @@ BOOL license_recv(rdpLicense* license, wStream* s)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void license_generate_randoms(rdpLicense* license)
|
||||
|
@ -200,7 +200,7 @@ struct rdp_license
|
||||
SCOPE_LIST* ScopeList;
|
||||
};
|
||||
|
||||
BOOL license_recv(rdpLicense* license, wStream* s);
|
||||
int license_recv(rdpLicense* license, wStream* s);
|
||||
BOOL license_send(rdpLicense* license, wStream* s, BYTE type);
|
||||
wStream* license_send_stream_init(rdpLicense* license);
|
||||
|
||||
|
@ -669,6 +669,7 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
|
||||
wStream* s;
|
||||
int length;
|
||||
int bm, em;
|
||||
BYTE flags = 0;
|
||||
int cookie_length;
|
||||
|
||||
s = Stream_New(NULL, 512);
|
||||
@ -703,8 +704,12 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
|
||||
if ((nego->requested_protocols > PROTOCOL_RDP) || (nego->sendNegoData))
|
||||
{
|
||||
/* RDP_NEG_DATA must be present for TLS and NLA */
|
||||
|
||||
if (nego->RestrictedAdminModeRequired)
|
||||
flags |= RESTRICTED_ADMIN_MODE_REQUIRED;
|
||||
|
||||
Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
|
||||
Stream_Write_UINT8(s, 0); /* flags, must be set to zero */
|
||||
Stream_Write_UINT8(s, flags);
|
||||
Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
|
||||
Stream_Write_UINT32(s, nego->requested_protocols); /* requestedProtocols */
|
||||
length += 8;
|
||||
@ -1016,6 +1021,18 @@ void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer)
|
||||
nego->NegotiateSecurityLayer = NegotiateSecurityLayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable restricted admin mode.
|
||||
* @param nego pointer to the negotiation structure
|
||||
* @param enable_restricted whether to enable security layer negotiation (TRUE for enabled, FALSE for disabled)
|
||||
*/
|
||||
|
||||
void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired)
|
||||
{
|
||||
DEBUG_NEGO("Enabling restricted admin mode: %s", RestrictedAdminModeRequired ? "TRUE" : "FALSE");
|
||||
nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable RDP security protocol.
|
||||
* @param nego pointer to the negotiation structure
|
||||
@ -1033,13 +1050,13 @@ void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
|
||||
* @param nego pointer to the negotiation structure
|
||||
* @param enable_tls whether to enable TLS + RDP protocol (TRUE for enabled, FALSE for disabled)
|
||||
*/
|
||||
|
||||
void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
|
||||
{
|
||||
DEBUG_NEGO("Enabling TLS security: %s", enable_tls ? "TRUE" : "FALSE");
|
||||
nego->enabled_protocols[PROTOCOL_TLS] = enable_tls;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable NLA security protocol.
|
||||
* @param nego pointer to the negotiation structure
|
||||
|
@ -84,6 +84,9 @@ enum RDP_NEG_MSG
|
||||
#define PRECONNECTION_PDU_V1 1
|
||||
#define PRECONNECTION_PDU_V2 2
|
||||
|
||||
#define RESTRICTED_ADMIN_MODE_REQUIRED 0x01
|
||||
#define CORRELATION_INFO_PRESENT 0x08
|
||||
|
||||
struct rdp_nego
|
||||
{
|
||||
int port;
|
||||
@ -106,6 +109,7 @@ struct rdp_nego
|
||||
UINT32 requested_protocols;
|
||||
BOOL NegotiateSecurityLayer;
|
||||
BYTE enabled_protocols[16];
|
||||
BOOL RestrictedAdminModeRequired;
|
||||
|
||||
rdpTransport* transport;
|
||||
};
|
||||
@ -137,6 +141,7 @@ void nego_free(rdpNego* nego);
|
||||
void nego_init(rdpNego* nego);
|
||||
void nego_set_target(rdpNego* nego, char* hostname, int port);
|
||||
void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer_enabled);
|
||||
void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired);
|
||||
void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp);
|
||||
void nego_enable_tls(rdpNego* nego, BOOL enable_tls);
|
||||
void nego_enable_nla(rdpNego* nego, BOOL enable_nla);
|
||||
|
@ -113,20 +113,39 @@ int credssp_ntlm_client_init(rdpCredssp* credssp)
|
||||
{
|
||||
char* spn;
|
||||
int length;
|
||||
BOOL PromptPassword;
|
||||
rdpTls* tls = NULL;
|
||||
freerdp* instance;
|
||||
rdpSettings* settings;
|
||||
|
||||
PromptPassword = FALSE;
|
||||
settings = credssp->settings;
|
||||
instance = (freerdp*) settings->instance;
|
||||
|
||||
if ((settings->Password == NULL ) || (settings->Username == NULL)
|
||||
if ((!settings->Password) || (!settings->Username)
|
||||
|| (!strlen(settings->Password)) || (!strlen(settings->Username)))
|
||||
{
|
||||
PromptPassword = TRUE;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
if (PromptPassword)
|
||||
{
|
||||
if (settings->RestrictedAdminModeRequired)
|
||||
{
|
||||
if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
|
||||
PromptPassword = FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (PromptPassword)
|
||||
{
|
||||
if (instance->Authenticate)
|
||||
{
|
||||
BOOL proceed = instance->Authenticate(instance,
|
||||
&settings->Username, &settings->Password, &settings->Domain);
|
||||
|
||||
if (!proceed)
|
||||
return 0;
|
||||
}
|
||||
@ -134,6 +153,33 @@ int credssp_ntlm_client_init(rdpCredssp* credssp)
|
||||
|
||||
sspi_SetAuthIdentity(&(credssp->identity), settings->Username, settings->Domain, settings->Password);
|
||||
|
||||
#ifndef _WIN32
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY* identity = &(credssp->identity);
|
||||
|
||||
if (settings->RestrictedAdminModeRequired)
|
||||
{
|
||||
if (settings->PasswordHash)
|
||||
{
|
||||
if (strlen(settings->PasswordHash) == 32)
|
||||
{
|
||||
if (identity->Password)
|
||||
free(identity->Password);
|
||||
|
||||
identity->PasswordLength = ConvertToUnicode(CP_UTF8, 0,
|
||||
settings->PasswordHash, -1, &identity->Password, 0) - 1;
|
||||
|
||||
/**
|
||||
* Multiply password hash length by 64 to obtain a length exceeding
|
||||
* the maximum (256) and use it this for hash identification in WinPR.
|
||||
*/
|
||||
identity->PasswordLength = 32 * 64; /* 2048 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_DEBUG_NLA
|
||||
_tprintf(_T("User: %s Domain: %s Password: %s\n"),
|
||||
(char*) credssp->identity.User, (char*) credssp->identity.Domain, (char*) credssp->identity.Password);
|
||||
@ -939,6 +985,20 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp)
|
||||
{
|
||||
wStream* s;
|
||||
int length;
|
||||
int DomainLength;
|
||||
int UserLength;
|
||||
int PasswordLength;
|
||||
|
||||
DomainLength = credssp->identity.DomainLength;
|
||||
UserLength = credssp->identity.UserLength;
|
||||
PasswordLength = credssp->identity.PasswordLength;
|
||||
|
||||
if (credssp->settings->RestrictedAdminModeRequired)
|
||||
{
|
||||
credssp->identity.DomainLength = 0;
|
||||
credssp->identity.UserLength = 0;
|
||||
credssp->identity.PasswordLength = 0;
|
||||
}
|
||||
|
||||
length = ber_sizeof_sequence(credssp_sizeof_ts_credentials(credssp));
|
||||
sspi_SecBufferAlloc(&credssp->ts_credentials, length);
|
||||
@ -946,6 +1006,13 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp)
|
||||
s = Stream_New(credssp->ts_credentials.pvBuffer, length);
|
||||
credssp_write_ts_credentials(credssp, s);
|
||||
|
||||
if (credssp->settings->RestrictedAdminModeRequired)
|
||||
{
|
||||
credssp->identity.DomainLength = DomainLength;
|
||||
credssp->identity.UserLength = UserLength;
|
||||
credssp->identity.PasswordLength = PasswordLength;
|
||||
}
|
||||
|
||||
Stream_Free(s, FALSE);
|
||||
}
|
||||
|
||||
|
@ -672,18 +672,18 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
|
||||
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
UINT16 type;
|
||||
UINT16 length;
|
||||
UINT16 channelId;
|
||||
|
||||
if (!rdp_read_share_control_header(s, &length, &type, &channelId))
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
if (type == PDU_TYPE_DATA)
|
||||
{
|
||||
return (rdp_recv_data_pdu(rdp, s) < 0) ? FALSE : TRUE;
|
||||
return rdp_recv_data_pdu(rdp, s);
|
||||
}
|
||||
else if (type == PDU_TYPE_SERVER_REDIRECTION)
|
||||
{
|
||||
@ -691,7 +691,7 @@ BOOL rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -815,8 +815,8 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
||||
* - no share control header, nor the 2 byte pad
|
||||
*/
|
||||
Stream_Rewind(s, 2);
|
||||
rdp_recv_enhanced_security_redirection_packet(rdp, s);
|
||||
return 1; /* 1 = redirection */
|
||||
|
||||
return rdp_recv_enhanced_security_redirection_packet(rdp, s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -854,8 +854,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
||||
break;
|
||||
|
||||
case PDU_TYPE_SERVER_REDIRECTION:
|
||||
if (!rdp_recv_enhanced_security_redirection_packet(rdp, s))
|
||||
return -1;
|
||||
return rdp_recv_enhanced_security_redirection_packet(rdp, s);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -928,13 +927,11 @@ static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_LICENSING:
|
||||
if (!rdp_client_connect_license(rdp, s))
|
||||
status = -1;
|
||||
status = rdp_client_connect_license(rdp, s);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE:
|
||||
if (!rdp_client_connect_demand_active(rdp, s))
|
||||
status = -1;
|
||||
status = rdp_client_connect_demand_active(rdp, s);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_FINALIZATION:
|
||||
|
@ -191,7 +191,7 @@ BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channel_id);
|
||||
|
||||
int rdp_send_channel_data(rdpRdp* rdp, int channel_id, BYTE* data, int size);
|
||||
|
||||
BOOL rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
|
||||
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
||||
void rdp_set_blocking_mode(rdpRdp* rdp, BOOL blocking);
|
||||
int rdp_check_fds(rdpRdp* rdp);
|
||||
|
@ -175,7 +175,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
|
||||
rdpRedirection* redirection = rdp->redirection;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 12)
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
Stream_Read_UINT16(s, flags); /* flags (2 bytes) */
|
||||
Stream_Read_UINT16(s, length); /* length (2 bytes) */
|
||||
@ -192,18 +192,18 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
|
||||
if (redirection->flags & LB_TARGET_NET_ADDRESS)
|
||||
{
|
||||
if (!rdp_redirection_read_string(s, &(redirection->TargetNetAddress)))
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (redirection->flags & LB_LOAD_BALANCE_INFO)
|
||||
{
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
Stream_Read_UINT32(s, redirection->LoadBalanceInfoLength);
|
||||
|
||||
if (Stream_GetRemainingLength(s) < redirection->LoadBalanceInfoLength)
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
redirection->LoadBalanceInfo = (BYTE*) malloc(redirection->LoadBalanceInfoLength);
|
||||
Stream_Read(s, redirection->LoadBalanceInfo, redirection->LoadBalanceInfoLength);
|
||||
@ -216,7 +216,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
|
||||
if (redirection->flags & LB_USERNAME)
|
||||
{
|
||||
if (!rdp_redirection_read_string(s, &(redirection->Username)))
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
WLog_Print(redirection->log, WLOG_DEBUG, "Username: %s", redirection->Username);
|
||||
}
|
||||
@ -233,7 +233,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
/* Note: length (hopefully) includes double zero termination */
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
Stream_Read_UINT32(s, redirection->PasswordLength);
|
||||
redirection->Password = (BYTE*) malloc(redirection->PasswordLength);
|
||||
@ -248,7 +248,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
|
||||
if (redirection->flags & LB_TARGET_FQDN)
|
||||
{
|
||||
if (!rdp_redirection_read_string(s, &(redirection->TargetFQDN)))
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
WLog_Print(redirection->log, WLOG_DEBUG, "TargetFQDN: %s", redirection->TargetFQDN);
|
||||
}
|
||||
@ -256,7 +256,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
|
||||
if (redirection->flags & LB_TARGET_NETBIOS_NAME)
|
||||
{
|
||||
if (!rdp_redirection_read_string(s, &(redirection->TargetNetBiosName)))
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
WLog_Print(redirection->log, WLOG_DEBUG, "TargetNetBiosName: %s", redirection->TargetNetBiosName);
|
||||
}
|
||||
@ -264,12 +264,12 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
|
||||
if (redirection->flags & LB_CLIENT_TSV_URL)
|
||||
{
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
Stream_Read_UINT32(s, redirection->TsvUrlLength);
|
||||
|
||||
if (Stream_GetRemainingLength(s) < redirection->TsvUrlLength)
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
redirection->TsvUrl = (BYTE*) malloc(redirection->TsvUrlLength);
|
||||
Stream_Read(s, redirection->TsvUrl, redirection->TsvUrlLength);
|
||||
@ -287,7 +287,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
|
||||
UINT32 targetNetAddressesLength;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 8)
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
Stream_Read_UINT32(s, targetNetAddressesLength);
|
||||
|
||||
@ -309,24 +309,37 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
|
||||
}
|
||||
|
||||
if (!Stream_SafeSeek(s, 8)) /* pad (8 bytes) */
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
if (redirection->flags & LB_NOREDIRECT)
|
||||
return TRUE;
|
||||
else
|
||||
return rdp_client_redirect(rdp);
|
||||
return 0;
|
||||
|
||||
return rdp_client_redirect(rdp);
|
||||
}
|
||||
|
||||
BOOL rdp_recv_redirection_packet(rdpRdp* rdp, wStream* s)
|
||||
int rdp_recv_redirection_packet(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
return rdp_recv_server_redirection_pdu(rdp, s);
|
||||
int status = 0;
|
||||
status = rdp_recv_server_redirection_pdu(rdp, s);
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOL rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s)
|
||||
int rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
return Stream_SafeSeek(s, 2) && /* pad2Octets (2 bytes) */
|
||||
rdp_recv_server_redirection_pdu(rdp, s) &&
|
||||
Stream_SafeSeek(s, 1); /* pad2Octets (1 byte) */
|
||||
int status = 0;
|
||||
|
||||
if (!Stream_SafeSeek(s, 2)) /* pad2Octets (2 bytes) */
|
||||
return -1;
|
||||
|
||||
status = rdp_recv_server_redirection_pdu(rdp, s);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
if (!Stream_SafeSeek(s, 1)) /* pad2Octets (1 byte) */
|
||||
return -1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
rdpRedirection* redirection_new()
|
||||
|
@ -50,8 +50,7 @@ struct rdp_redirection
|
||||
char** TargetNetAddresses;
|
||||
};
|
||||
|
||||
BOOL rdp_recv_redirection_packet(rdpRdp* rdp, wStream* s);
|
||||
BOOL rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s);
|
||||
int rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s);
|
||||
|
||||
int rdp_redirection_apply_settings(rdpRdp* rdp);
|
||||
|
||||
|
@ -223,6 +223,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
||||
settings->TlsSecurity = TRUE;
|
||||
settings->RdpSecurity = TRUE;
|
||||
settings->NegotiateSecurityLayer = TRUE;
|
||||
settings->RestrictedAdminModeRequired = FALSE;
|
||||
settings->MstscCookieMode = FALSE;
|
||||
settings->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
|
||||
settings->ClientBuild = 2600;
|
||||
@ -444,6 +445,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
||||
_settings->Username = _strdup(settings->Username); /* 21 */
|
||||
_settings->Password = _strdup(settings->Password); /* 22 */
|
||||
_settings->Domain = _strdup(settings->Domain); /* 23 */
|
||||
_settings->PasswordHash = _strdup(settings->PasswordHash); /* 24 */
|
||||
//_settings->ClientHostname = _strdup(settings->ClientHostname); /* 134 */
|
||||
//_settings->ClientProductId = _strdup(settings->ClientProductId); /* 135 */
|
||||
_settings->AlternateShell = _strdup(settings->AlternateShell); /* 640 */
|
||||
@ -614,6 +616,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
||||
_settings->ExtSecurity = settings->ExtSecurity; /* 1091 */
|
||||
_settings->Authentication = settings->Authentication; /* 1092 */
|
||||
_settings->NegotiateSecurityLayer = settings->NegotiateSecurityLayer; /* 1096 */
|
||||
_settings->RestrictedAdminModeRequired = settings->RestrictedAdminModeRequired; /* 1097 */
|
||||
_settings->MstscCookieMode = settings->MstscCookieMode; /* 1152 */
|
||||
_settings->SendPreconnectionPdu = settings->SendPreconnectionPdu; /* 1156 */
|
||||
_settings->IgnoreCertificate = settings->IgnoreCertificate; /* 1408 */
|
||||
@ -778,6 +781,7 @@ void freerdp_settings_free(rdpSettings* settings)
|
||||
free(settings->Username);
|
||||
free(settings->Password);
|
||||
free(settings->Domain);
|
||||
free(settings->PasswordHash);
|
||||
free(settings->AlternateShell);
|
||||
free(settings->ShellWorkingDirectory);
|
||||
free(settings->ComputerName);
|
||||
|
@ -727,7 +727,6 @@ int transport_write(rdpTransport* transport, wStream* s)
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
|
||||
{
|
||||
void* pfd;
|
||||
@ -955,7 +954,7 @@ static void* transport_client_thread(void* arg)
|
||||
{
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
HANDLE events[32];
|
||||
HANDLE handles[8];
|
||||
freerdp* instance;
|
||||
rdpContext* context;
|
||||
rdpTransport* transport;
|
||||
@ -969,31 +968,43 @@ static void* transport_client_thread(void* arg)
|
||||
|
||||
context = instance->context;
|
||||
assert(NULL != instance->context);
|
||||
|
||||
WLog_Print(transport->log, WLOG_DEBUG, "Starting transport thread");
|
||||
|
||||
nCount = 0;
|
||||
handles[nCount++] = transport->stopEvent;
|
||||
handles[nCount++] = transport->connectedEvent;
|
||||
|
||||
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread");
|
||||
ExitThread(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WLog_Print(transport->log, WLOG_DEBUG, "Asynchronous transport activated");
|
||||
|
||||
while (1)
|
||||
{
|
||||
nCount = 0;
|
||||
events[nCount++] = transport->stopEvent;
|
||||
events[nCount] = transport->connectedEvent;
|
||||
handles[nCount++] = transport->stopEvent;
|
||||
|
||||
status = WaitForMultipleObjects(nCount + 1, events, FALSE, INFINITE);
|
||||
transport_get_read_handles(transport, (HANDLE*) &handles, &nCount);
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
break;
|
||||
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
|
||||
|
||||
transport_get_read_handles(transport, (HANDLE*) &events, &nCount);
|
||||
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
if (!freerdp_check_fds(instance))
|
||||
break;
|
||||
}
|
||||
|
||||
ExitThread(0);
|
||||
WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread");
|
||||
|
||||
ExitThread(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,12 @@ static wMessage* freerdp_cliprdr_event_new(UINT16 event_type)
|
||||
ZeroMemory(event.v, sizeof(RDP_CB_DATA_RESPONSE_EVENT));
|
||||
event.m->id = MakeMessageId(CliprdrChannel, DataResponse);
|
||||
break;
|
||||
|
||||
case CliprdrChannel_ClipCaps:
|
||||
event.v = malloc(sizeof(RDP_CB_CLIP_CAPS));
|
||||
ZeroMemory(event.v, sizeof(RDP_CB_CLIP_CAPS));
|
||||
event.m->id = MakeMessageId(CliprdrChannel, ClipCaps);
|
||||
break;
|
||||
}
|
||||
|
||||
return event.v;
|
||||
|
@ -34,10 +34,10 @@ set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SO
|
||||
if(MONOLITHIC_BUILD)
|
||||
|
||||
else()
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT WinPRTargets)
|
||||
endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR" EXPORT WinPRTargets)
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR")
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
|
@ -282,9 +282,43 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
|
||||
SamClose(sam);
|
||||
}
|
||||
|
||||
void ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
|
||||
{
|
||||
int i, hn, ln;
|
||||
char* PasswordHash = NULL;
|
||||
UINT32 PasswordHashLength = 0;
|
||||
|
||||
/* Password contains a password hash of length (PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR) */
|
||||
|
||||
PasswordHashLength = context->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
|
||||
ConvertFromUnicode(CP_UTF8, 0, context->identity.Password, PasswordHashLength, &PasswordHash, 0, NULL, NULL);
|
||||
CharUpperBuffA(PasswordHash, PasswordHashLength);
|
||||
|
||||
for (i = 0; i < 32; i += 2)
|
||||
{
|
||||
hn = PasswordHash[i] > '9' ? PasswordHash[i] - 'A' + 10 : PasswordHash[i] - '0';
|
||||
ln = PasswordHash[i + 1] > '9' ? PasswordHash[i + 1] - 'A' + 10 : PasswordHash[i + 1] - '0';
|
||||
hash[i / 2] = (hn << 4) | ln;
|
||||
}
|
||||
|
||||
free(PasswordHash);
|
||||
}
|
||||
|
||||
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
|
||||
{
|
||||
if (context->identity.PasswordLength > 0)
|
||||
if (context->identity.PasswordLength > 256)
|
||||
{
|
||||
BYTE PasswordHash[16];
|
||||
|
||||
/* Special case for WinPR: password hash */
|
||||
ntlm_convert_password_hash(context, PasswordHash);
|
||||
|
||||
NTOWFv2FromHashW(PasswordHash,
|
||||
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
|
||||
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2,
|
||||
(BYTE*) hash);
|
||||
}
|
||||
else if (context->identity.PasswordLength > 0)
|
||||
{
|
||||
NTOWFv2W((LPWSTR) context->identity.Password, context->identity.PasswordLength * 2,
|
||||
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
|
||||
|
@ -192,11 +192,10 @@ CREDENTIALS* sspi_CredentialsNew()
|
||||
CREDENTIALS* credentials;
|
||||
|
||||
credentials = (CREDENTIALS*) malloc(sizeof(CREDENTIALS));
|
||||
ZeroMemory(credentials, sizeof(CREDENTIALS));
|
||||
|
||||
if (credentials != NULL)
|
||||
if (credentials)
|
||||
{
|
||||
|
||||
ZeroMemory(credentials, sizeof(CREDENTIALS));
|
||||
}
|
||||
|
||||
return credentials;
|
||||
@ -319,7 +318,7 @@ void sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, char* user, char* d
|
||||
identity->DomainLength = 0;
|
||||
}
|
||||
|
||||
if (password != NULL)
|
||||
if (password)
|
||||
{
|
||||
identity->PasswordLength = ConvertToUnicode(CP_UTF8, 0, password, -1, &identity->Password, 0) - 1;
|
||||
}
|
||||
@ -366,12 +365,17 @@ void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDE
|
||||
|
||||
identity->PasswordLength = srcIdentity->PasswordLength;
|
||||
|
||||
if (identity->PasswordLength > 256)
|
||||
identity->PasswordLength /= SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
|
||||
|
||||
if (identity->PasswordLength > 0)
|
||||
{
|
||||
identity->Password = (UINT16*) malloc((identity->PasswordLength + 1) * sizeof(WCHAR));
|
||||
CopyMemory(identity->Password, srcIdentity->Password, identity->PasswordLength * sizeof(WCHAR));
|
||||
identity->Password[identity->PasswordLength] = 0;
|
||||
}
|
||||
|
||||
identity->PasswordLength = srcIdentity->PasswordLength;
|
||||
}
|
||||
|
||||
PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType)
|
||||
|
@ -24,8 +24,13 @@
|
||||
|
||||
#define SCHANNEL_CB_MAX_TOKEN 0x00006000
|
||||
|
||||
#define SSPI_CREDENTIALS_PASSWORD_HASH 0x00000001
|
||||
|
||||
#define SSPI_CREDENTIALS_HASH_LENGTH_FACTOR 64
|
||||
|
||||
struct _CREDENTIALS
|
||||
{
|
||||
DWORD flags;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
};
|
||||
typedef struct _CREDENTIALS CREDENTIALS;
|
||||
|
@ -140,7 +140,7 @@ char* FindApplicationPath(char* application)
|
||||
return NULL;
|
||||
|
||||
if (application[0] == '/')
|
||||
return application;
|
||||
return _strdup(application);
|
||||
|
||||
nSize = GetEnvironmentVariableA("PATH", NULL, 0);
|
||||
|
||||
@ -183,7 +183,7 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
||||
int numArgs;
|
||||
LPSTR* pArgs;
|
||||
char** envp;
|
||||
char* filename;
|
||||
char* filename = NULL;
|
||||
WINPR_THREAD* thread;
|
||||
WINPR_PROCESS* process;
|
||||
WINPR_ACCESS_TOKEN* token;
|
||||
|
@ -206,7 +206,7 @@ void ListDictionary_Clear(wListDictionary* listDictionary)
|
||||
{
|
||||
nextItem = item->next;
|
||||
if (listDictionary->object.fnObjectFree)
|
||||
listDictionary->object.fnObjectFree(item);
|
||||
listDictionary->object.fnObjectFree(item->value);
|
||||
free(item);
|
||||
item = nextItem;
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ int WLog_ParseName(wLog* log, LPCSTR name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
wLog* WLog_New(LPCSTR name)
|
||||
wLog* WLog_New(LPCSTR name , wLog* rootLogger)
|
||||
{
|
||||
wLog* log;
|
||||
char* env;
|
||||
@ -284,7 +284,12 @@ wLog* WLog_New(LPCSTR name)
|
||||
|
||||
log->Appender = NULL;
|
||||
|
||||
log->Level = WLOG_WARN;
|
||||
if (rootLogger) {
|
||||
log->Level = rootLogger->Level;
|
||||
} else {
|
||||
log->Level = WLOG_WARN;
|
||||
}
|
||||
|
||||
|
||||
nSize = GetEnvironmentVariableA("WLOG_LEVEL", NULL, 0);
|
||||
|
||||
@ -351,7 +356,7 @@ wLog* WLog_GetRoot()
|
||||
|
||||
if (!g_RootLog)
|
||||
{
|
||||
g_RootLog = WLog_New("");
|
||||
g_RootLog = WLog_New("",NULL);
|
||||
g_RootLog->IsRoot = TRUE;
|
||||
|
||||
logAppenderType = WLOG_APPENDER_CONSOLE;
|
||||
@ -430,7 +435,7 @@ wLog* WLog_Get(LPCSTR name)
|
||||
|
||||
if (!log)
|
||||
{
|
||||
log = WLog_New(name);
|
||||
log = WLog_New(name,root);
|
||||
WLog_AddChild(root, log);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user