Merge branch 'master' into spikes/hyperv

This commit is contained in:
Lysann Kessler 2012-07-24 18:27:20 +02:00
commit 2068263193
149 changed files with 9726 additions and 2525 deletions

View File

@ -4,6 +4,7 @@
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2012 HP Development Company, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -107,6 +108,7 @@ if(APPLE)
include_directories(/opt/local/include)
link_directories(/opt/local/lib)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mmacosx-version-min=10.4")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -framework CoreFoundation")
endif()
if(NOT WIN32)
@ -117,6 +119,8 @@ if(NOT WIN32)
if(NOT APPLE)
find_suggested_package(FFmpeg)
find_suggested_package(XRandR)
find_suggested_package(Gstreamer)
find_suggested_package(ALSA)
else(NOT APPLE)
find_optional_package(FFmpeg)
@ -130,6 +134,9 @@ set(FREERDP_KEYMAP_PATH "${FREERDP_DATA_PATH}/keymaps")
# Path to put plugins
set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/freerdp")
# Path to put extensions
set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/freerdp/extensions")
# Include directories
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR}/include)

View File

@ -23,4 +23,5 @@ add_subdirectory(rdpdbg)
add_subdirectory(rdpdr)
add_subdirectory(rail)
add_subdirectory(rdpsnd)
add_subdirectory(skel)

View File

@ -4,6 +4,7 @@
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2012 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -47,6 +48,12 @@ if(WITH_FFMPEG)
add_subdirectory(ffmpeg)
endif()
if(WITH_XRANDR)
if(GSTREAMER_FOUND)
add_subdirectory(gstreamer)
endif()
endif()
if(WITH_ALSA)
add_subdirectory(alsa)
endif()

View File

@ -499,7 +499,6 @@ TSMFDecoderEntry(void)
if (!initialized)
{
avcodec_init();
avcodec_register_all();
initialized = true;
}

View File

@ -0,0 +1,34 @@
# FreeRDP: A Remote Desktop Protocol Client
# FreeRDP cmake build script for gstreamer plugin
#
# (C) Copyright 2012 Hewlett-Packard Development Company, L.P.
#
# 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(TSMF_GSTREAMER_SRCS
tsmf_gstreamer.c
)
include_directories(..)
include_directories(${GSTREAMER_INCLUDE_DIRS})
add_library(tsmf_gstreamer ${TSMF_GSTREAMER_SRCS})
set_target_properties(tsmf_gstreamer PROPERTIES PREFIX "")
target_link_libraries(tsmf_gstreamer freerdp-utils)
target_link_libraries(tsmf_gstreamer ${GSTREAMER_LIBRARIES} gstapp-0.10 gstinterfaces-0.10 Xrandr X11 Xext)
install(TARGETS tsmf_gstreamer DESTINATION ${FREERDP_PLUGIN_PATH})

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
* Video Redirection Virtual Channel - Codec
*
* Copyright 2010-2011 Vic Lee
* Copyright 2012 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -103,6 +104,20 @@ static const TSMFMediaTypeMap tsmf_sub_type_map[] =
TSMF_SUB_TYPE_MP2V
},
/* 31564D57-0000-0010-8000-00AA00389B71 */
{
{ 0x57, 0x4D, 0x56, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
"MEDIASUBTYPE_WMV1",
TSMF_SUB_TYPE_WMV1
},
/* 32564D57-0000-0010-8000-00AA00389B71 */
{
{ 0x57, 0x4D, 0x56, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
"MEDIASUBTYPE_WMV2",
TSMF_SUB_TYPE_WMV2
},
/* 33564D57-0000-0010-8000-00AA00389B71 */
{
{ 0x57, 0x4D, 0x56, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
@ -131,12 +146,62 @@ static const TSMFMediaTypeMap tsmf_sub_type_map[] =
TSMF_SUB_TYPE_AVC1
},
/* 3334504D-0000-0010-8000-00AA00389B71 */
{
{ 0x4D, 0x50, 0x34, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
"MEDIASUBTYPE_MP43",
TSMF_SUB_TYPE_MP43
},
/* 5634504D-0000-0010-8000-00AA00389B71 */
{
{ 0x4D, 0x50, 0x34, 0x56, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
"MEDIASUBTYPE_MP4S",
TSMF_SUB_TYPE_MP4S
},
/* 3234504D-0000-0010-8000-00AA00389B71 */
{
{ 0x4D, 0x50, 0x34, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
"MEDIASUBTYPE_MP42",
TSMF_SUB_TYPE_MP42
},
/* E436EB81-524F-11CE-9F53-0020AF0BA770 */
/*
{
{ 0x81, 0xEB, 0x36, 0xE4, 0x4F, 0x52, 0xCE, 0x11, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 },
"MEDIASUBTYPE_MP1V",
TSMF_SUB_TYPE_MP1V
},
*/
/* 00000050-0000-0010-8000-00AA00389B71 */
/*
{
{ 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
"MEDIASUBTYPE_MP1A",
TSMF_SUB_TYPE_MP1A
},
*/
/* E06D802C-DB46-11CF-B4D1-00805F6CBBEA */
/*
{
{ 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA },
"MEDIASUBTYPE_DOLBY_AC3",
TSMF_SUB_TYPE_AC3
},
*/
/* 32595559-0000-0010-8000-00AA00389B71 */
/*
{
{ 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
"MEDIASUBTYPE_YUY2",
TSMF_SUB_TYPE_YUY2
},
*/
{
{ 0 },
@ -176,6 +241,13 @@ static const TSMFMediaTypeMap tsmf_format_type_map[] =
TSMF_FORMAT_TYPE_VIDEOINFO2
},
/* 05589F82-C356-11CE-BF01-00AA0055595A */
{
{ 0x82, 0x9F, 0x58, 0x05, 0x56, 0xC3, 0xCE, 0x11, 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59, 0x5A },
"FORMAT_MPEG1_VIDEO",
TSMF_FORMAT_TYPE_MPEG1VIDEOINFO
},
{
{ 0 },
"Unknown",
@ -257,6 +329,40 @@ static uint32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, STR
return 72;
}
/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
static uint32 tsmf_codec_parse_VIDEOINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, STREAM* s)
{
/*
typedef struct tagVIDEOINFOHEADER {
RECT rcSource; //16
RECT rcTarget; //16 32
DWORD dwBitRate; //4 36
DWORD dwBitErrorRate; //4 40
REFERENCE_TIME AvgTimePerFrame; //8 48
BITMAPINFOHEADER bmiHeader;
} VIDEOINFOHEADER;
*/
uint64 AvgTimePerFrame;
/* VIDEOINFOHEADER.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
stream_seek_uint32(s);
stream_seek_uint32(s);
stream_read_uint32(s, mediatype->Width);
stream_read_uint32(s, mediatype->Height);
/* VIDEOINFOHEADER.rcTarget */
stream_seek(s, 16);
/* VIDEOINFOHEADER.dwBitRate */
stream_read_uint32(s, mediatype->BitRate);
/* VIDEOINFOHEADER.dwBitErrorRate */
stream_seek_uint32(s);
/* VIDEOINFOHEADER.AvgTimePerFrame */
stream_read_uint64(s, AvgTimePerFrame);
mediatype->SamplesPerSecond.Numerator = 1000000;
mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL);
return 48;
}
boolean tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, STREAM* s)
{
int i;
@ -358,6 +464,18 @@ boolean tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, STREAM* s)
break;
case TSMF_FORMAT_TYPE_MPEG1VIDEOINFO:
/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
i = tsmf_codec_parse_VIDEOINFOHEADER(mediatype, s);
i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, true);
if (cbFormat > i)
{
mediatype->ExtraDataSize = cbFormat - i;
mediatype->ExtraData = stream_get_tail(s);
}
break;
case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO:
/* http://msdn.microsoft.com/en-us/library/dd390707.aspx */

View File

@ -3,6 +3,7 @@
* Video Redirection Virtual Channel - Constants
*
* Copyright 2010-2011 Vic Lee
* Copyright 2012 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -108,6 +109,14 @@
#define TSMF_SUB_TYPE_H264 9
#define TSMF_SUB_TYPE_AVC1 10
#define TSMF_SUB_TYPE_AC3 11
#define TSMF_SUB_TYPE_WMV2 12
#define TSMF_SUB_TYPE_WMV1 13
#define TSMF_SUB_TYPE_MP1V 14
#define TSMF_SUB_TYPE_MP1A 15
#define TSMF_SUB_TYPE_YUY2 16
#define TSMF_SUB_TYPE_MP43 17
#define TSMF_SUB_TYPE_MP4S 18
#define TSMF_SUB_TYPE_MP42 19
/* FormatType */
#define TSMF_FORMAT_TYPE_UNKNOWN 0
@ -115,6 +124,7 @@
#define TSMF_FORMAT_TYPE_WAVEFORMATEX 2
#define TSMF_FORMAT_TYPE_MPEG2VIDEOINFO 3
#define TSMF_FORMAT_TYPE_VIDEOINFO2 4
#define TSMF_FORMAT_TYPE_MPEG1VIDEOINFO 5
#endif

View File

@ -3,6 +3,7 @@
* Video Redirection Virtual Channel - Decoder
*
* Copyright 2010-2011 Vic Lee
* Copyright 2012 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,6 +24,14 @@
#include "drdynvc_types.h"
#include "tsmf_types.h"
typedef enum _ITSMFControlMsg
{
Control_Pause,
Control_Restart,
Control_Flush,
Control_EndOfStream
} ITSMFControlMsg;
typedef struct _ITSMFDecoder ITSMFDecoder;
struct _ITSMFDecoder
@ -38,7 +47,20 @@ struct _ITSMFDecoder
/* Get the width and height of decoded video frame */
boolean (*GetDecodedDimension) (ITSMFDecoder* decoder, uint32* width, uint32* height);
/* Free the decoder */
void (*Free) (ITSMFDecoder* decoder);
void (*Free) (ITSMFDecoder * decoder);
/* Optional Contol function */
void (*Control) (ITSMFDecoder * decoder, ITSMFControlMsg control_msg, uint32 *arg);
/* Decode a sample with extended interface. */
int (*DecodeEx) (ITSMFDecoder * decoder, const uint8 * data, uint32 data_size, uint32 extensions,
uint64 start_time, uint64 end_time, uint64 duration);
/* Get current play time */
uint64 (*GetRunningTime) (ITSMFDecoder * decoder);
/* Update Gstreamer Rendering Area */
void (*UpdateRenderingArea) (ITSMFDecoder * decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles);
/* Change Gstreamer Audio Volume */
void (*ChangeVolume) (ITSMFDecoder * decoder, uint32 newVolume, uint32 muted);
/* Check buffer level */
uint32 (*BufferLevel) (ITSMFDecoder * decoder);
};
#define TSMF_DECODER_EXPORT_FUNC_NAME "TSMFDecoderEntry"

View File

@ -3,6 +3,7 @@
* Video Redirection Virtual Channel - Interface Manipulation
*
* Copyright 2010-2011 Vic Lee
* Copyright 2012 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -118,14 +119,23 @@ int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
return 0;
}
static TSMF_PRESENTATION* pexisted = 0;
int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
{
int error = 0;
TSMF_PRESENTATION* presentation;
DEBUG_DVC("");
if (pexisted)
{
ifman->output_pending = false;
return 0;
}
presentation = tsmf_presentation_new(stream_get_tail(ifman->input), ifman->channel_callback);
pexisted = presentation;
if (presentation == NULL)
error = 1;
else
@ -208,6 +218,8 @@ int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
if (presentation)
tsmf_presentation_free(presentation);
pexisted = 0;
stream_check_size(ifman->output, 4);
stream_write_uint32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
@ -216,14 +228,42 @@ int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
int tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman)
{
DEBUG_DVC("");
DEBUG_DVC("on stream volume");
TSMF_PRESENTATION* presentation;
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
if (presentation)
{
stream_seek(ifman->input, 16);
uint32 newVolume;
uint32 muted;
stream_read_uint32(ifman->input, newVolume);
DEBUG_DVC("on stream volume: new volume=[%d]", newVolume);
stream_read_uint32(ifman->input, muted);
DEBUG_DVC("on stream volume: muted=[%d]", muted);
tsmf_presentation_volume_changed(presentation, newVolume, muted);
}
else
DEBUG_WARN("unknown presentation id");
ifman->output_pending = true;
return 0;
}
int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman)
{
DEBUG_DVC("");
DEBUG_DVC("on channel volume");
TSMF_PRESENTATION* presentation;
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
if (presentation)
{
stream_seek(ifman->input, 16);
uint32 channelVolume;
uint32 changedChannel;
stream_read_uint32(ifman->input, channelVolume);
DEBUG_DVC("on channel volume: channel volume=[%d]", channelVolume);
stream_read_uint32(ifman->input, changedChannel);
DEBUG_DVC("on stream volume: changed channel=[%d]", changedChannel);
}
ifman->output_pending = true;
return 0;
}
@ -434,6 +474,14 @@ int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman)
{
DEBUG_DVC("");
ifman->output_pending = true;
/* Added pause control so gstreamer pipeline can be paused accordingly */
TSMF_PRESENTATION* presentation;
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
if (presentation)
tsmf_presentation_paused(presentation);
else
DEBUG_WARN("unknown presentation id");
return 0;
}
@ -441,6 +489,14 @@ int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman)
{
DEBUG_DVC("");
ifman->output_pending = true;
/* Added restart control so gstreamer pipeline can be resumed accordingly */
TSMF_PRESENTATION* presentation;
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
if (presentation)
tsmf_presentation_restarted(presentation);
else
DEBUG_WARN("unknown presentation id");
return 0;
}

View File

@ -3,6 +3,7 @@
* Video Redirection Virtual Channel - Media Container
*
* Copyright 2010-2011 Vic Lee
* Copyright 2012 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,6 +21,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/stream.h>
@ -123,6 +126,9 @@ struct _TSMF_SAMPLE
};
static LIST* presentation_list = NULL;
static uint64 last_played_audio_time = 0;
static pthread_mutex_t tsmf_mutex = PTHREAD_MUTEX_INITIALIZER;
static int TERMINATING = 0;
static uint64 get_current_time(void)
{
@ -145,33 +151,41 @@ static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
if (sync)
{
if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
if (stream->decoder)
{
/* Check if some other stream has earlier sample that needs to be played first */
if (stream->last_end_time > AUDIO_TOLERANCE)
if (stream->decoder->GetDecodedData)
{
freerdp_mutex_lock(presentation->mutex);
for (item = presentation->stream_list->head; item; item = item->next)
if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
{
s = (TSMF_STREAM*) item->data;
if (s != stream && !s->eos && s->last_end_time &&
s->last_end_time < stream->last_end_time - AUDIO_TOLERANCE)
/* Check if some other stream has earlier sample that needs to be played first */
if (stream->last_end_time > AUDIO_TOLERANCE)
{
pending = true;
break;
freerdp_mutex_lock(presentation->mutex);
for (item = presentation->stream_list->head; item; item = item->next)
{
s = (TSMF_STREAM*) item->data;
if (s != stream && !s->eos && s->last_end_time &&
s->last_end_time < stream->last_end_time - AUDIO_TOLERANCE)
{
pending = true;
break;
}
}
freerdp_mutex_unlock(presentation->mutex);
}
}
freerdp_mutex_unlock(presentation->mutex);
}
}
else
{
if (stream->last_end_time > presentation->audio_end_time)
{
pending = true;
else
{
if (stream->last_end_time > presentation->audio_end_time)
{
pending = true;
}
}
}
}
}
if (pending)
return NULL;
@ -224,6 +238,15 @@ static void tsmf_stream_process_ack(TSMF_STREAM* stream)
TSMF_PRESENTATION* tsmf_presentation_new(const uint8* guid, IWTSVirtualChannelCallback* pChannelCallback)
{
pthread_t thid = pthread_self();
FILE* fout = NULL;
fout = fopen("/tmp/tsmf.tid", "wt");
if (fout)
{
fprintf(fout, "%d\n", (int) thid);
fclose(fout);
}
TSMF_PRESENTATION* presentation;
presentation = tsmf_presentation_find_by_id(guid);
@ -423,7 +446,14 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample)
TSMF_STREAM* stream = sample->stream;
if (stream->decoder)
ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size, sample->extensions);
{
if (stream->decoder->DecodeEx)
ret = stream->decoder->DecodeEx(stream->decoder, sample->data, sample->data_size, sample->extensions,
sample->start_time, sample->end_time, sample->duration);
else
ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size, sample->extensions);
}
if (!ret)
{
tsmf_sample_ack(sample);
@ -450,32 +480,139 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample)
ret = false ;
if (stream->decoder->GetDecodedDimension)
ret = stream->decoder->GetDecodedDimension(stream->decoder, &width, &height);
if (ret && (width != stream->width || height != stream->height))
{
DEBUG_DVC("video dimension changed to %d x %d", width, height);
stream->width = width;
stream->height = height;
ret = stream->decoder->GetDecodedDimension(stream->decoder, &width, &height);
if (ret && (width != stream->width || height != stream->height))
{
DEBUG_DVC("video dimension changed to %d x %d", width, height);
stream->width = width;
stream->height = height;
}
}
}
if (stream->decoder->GetDecodedData)
{
sample->data = stream->decoder->GetDecodedData(stream->decoder, &sample->decoded_size);
switch (sample->stream->major_type)
{
case TSMF_MAJOR_TYPE_VIDEO:
tsmf_sample_playback_video(sample);
tsmf_sample_ack(sample);
tsmf_sample_free(sample);
break;
case TSMF_MAJOR_TYPE_AUDIO:
tsmf_sample_playback_audio(sample);
tsmf_sample_queue_ack(sample);
break;
}
}
switch (sample->stream->major_type)
else
{
case TSMF_MAJOR_TYPE_VIDEO:
tsmf_sample_playback_video(sample);
tsmf_sample_ack(sample);
tsmf_sample_free(sample);
break;
case TSMF_MAJOR_TYPE_AUDIO:
tsmf_sample_playback_audio(sample);
tsmf_sample_queue_ack(sample);
break;
}
TSMF_STREAM * stream = sample->stream;
uint64 ack_anticipation_time = get_current_time();
uint64 currentRunningTime = sample->start_time;
uint32 bufferLevel = 0;
if (stream->decoder->GetRunningTime)
{
currentRunningTime = stream->decoder->GetRunningTime(stream->decoder);
}
if (stream->decoder->BufferLevel)
{
bufferLevel = stream->decoder->BufferLevel(stream->decoder);
}
switch (sample->stream->major_type)
{
case TSMF_MAJOR_TYPE_VIDEO:
{
TSMF_PRESENTATION * presentation = sample->stream->presentation;
/*
* Tell gstreamer that presentation screen area has moved.
* So it can render on the new area.
*/
if (presentation->last_x != presentation->output_x || presentation->last_y != presentation->output_y ||
presentation->last_width != presentation->output_width || presentation->last_height != presentation->output_height)
{
presentation->last_x = presentation->output_x;
presentation->last_y = presentation->output_y;
presentation->last_width = presentation->output_width;
presentation->last_height = presentation->output_height;
if(stream->decoder->UpdateRenderingArea)
{
stream->decoder->UpdateRenderingArea(stream->decoder, presentation->output_x, presentation->output_y,
presentation->output_width, presentation->output_height, presentation->output_num_rects, presentation->output_rects);
}
}
if ( presentation->last_num_rects != presentation->output_num_rects || (presentation->last_rects && presentation->output_rects &&
memcmp(presentation->last_rects, presentation->output_rects, presentation->last_num_rects * sizeof(RDP_RECT)) != 0))
{
if (presentation->last_rects)
{
xfree(presentation->last_rects);
presentation->last_rects = NULL;
}
presentation->last_num_rects = presentation->output_num_rects;
if (presentation->last_num_rects > 0)
{
presentation->last_rects = xzalloc(presentation->last_num_rects * sizeof(RDP_RECT));
memcpy(presentation->last_rects, presentation->output_rects, presentation->last_num_rects * sizeof(RDP_RECT));
}
if(stream->decoder->UpdateRenderingArea)
{
stream->decoder->UpdateRenderingArea(stream->decoder, presentation->output_x, presentation->output_y,
presentation->output_width, presentation->output_height, presentation->output_num_rects, presentation->output_rects);
}
}
if (bufferLevel < 24)
{
ack_anticipation_time += sample->duration;
}
else
{
if (currentRunningTime > sample->start_time)
{
ack_anticipation_time += sample->duration;
}
else if(currentRunningTime == 0)
{
ack_anticipation_time += sample->duration;
}
else
{
ack_anticipation_time += (sample->start_time - currentRunningTime);
}
}
break;
}
case TSMF_MAJOR_TYPE_AUDIO:
{
last_played_audio_time = currentRunningTime;
if (bufferLevel < 2)
{
ack_anticipation_time += sample->duration;
}
else
{
if (currentRunningTime > sample->start_time)
{
ack_anticipation_time += sample->duration;
}
else if(currentRunningTime == 0)
{
ack_anticipation_time += sample->duration;
}
else
{
ack_anticipation_time += (sample->start_time - currentRunningTime);
}
}
break;
}
}
sample->ack_time = ack_anticipation_time;
tsmf_sample_queue_ack(sample);
}
}
static void* tsmf_stream_playback_func(void* arg)
@ -489,13 +626,19 @@ static void* tsmf_stream_playback_func(void* arg)
if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO &&
stream->sample_rate && stream->channels && stream->bits_per_sample)
{
stream->audio = tsmf_load_audio_device(
presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL,
presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL);
if (stream->audio)
if (stream->decoder)
{
stream->audio->SetFormat(stream->audio,
stream->sample_rate, stream->channels, stream->bits_per_sample);
if (stream->decoder->GetDecodedData)
{
stream->audio = tsmf_load_audio_device(
presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL,
presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL);
if (stream->audio)
{
stream->audio->SetFormat(stream->audio,
stream->sample_rate, stream->channels, stream->bits_per_sample);
}
}
}
}
while (!freerdp_thread_is_stopped(stream->thread))
@ -535,10 +678,99 @@ static void tsmf_stream_start(TSMF_STREAM* stream)
static void tsmf_stream_stop(TSMF_STREAM* stream)
{
if (!stream)
return;
if (!stream->decoder)
return;
if (freerdp_thread_is_running(stream->thread))
{
freerdp_thread_stop(stream->thread);
}
if (stream->decoder->Control)
{
stream->decoder->Control(stream->decoder, Control_Flush, NULL);
}
}
static void tsmf_stream_pause(TSMF_STREAM* stream)
{
if (!stream)
return;
if (!stream->decoder)
return;
if (stream->decoder->Control)
{
stream->decoder->Control(stream->decoder, Control_Pause, NULL);
}
}
static void tsmf_stream_restart(TSMF_STREAM* stream)
{
if (!stream)
return;
if (!stream->decoder)
return;
if (stream->decoder->Control)
{
stream->decoder->Control(stream->decoder, Control_Restart, NULL);
}
}
static void tsmf_stream_change_volume(TSMF_STREAM* stream, uint32 newVolume, uint32 muted)
{
if (!stream)
return;
if (!stream->decoder)
return;
if (stream->decoder->ChangeVolume)
{
stream->decoder->ChangeVolume(stream->decoder, newVolume, muted);
}
}
void tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, uint32 newVolume, uint32 muted)
{
LIST_ITEM* item;
TSMF_STREAM* stream;
for (item = presentation->stream_list->head; item; item = item->next)
{
stream = (TSMF_STREAM*) item->data;
tsmf_stream_change_volume(stream, newVolume, muted);
}
}
void tsmf_presentation_paused(TSMF_PRESENTATION* presentation)
{
LIST_ITEM* item;
TSMF_STREAM* stream;
for (item = presentation->stream_list->head; item; item = item->next)
{
stream = (TSMF_STREAM*) item->data;
tsmf_stream_pause(stream);
}
}
void tsmf_presentation_restarted(TSMF_PRESENTATION* presentation)
{
LIST_ITEM* item;
TSMF_STREAM* stream;
for (item = presentation->stream_list->head; item; item = item->next)
{
stream = (TSMF_STREAM*) item->data;
tsmf_stream_restart(stream);
}
}
void tsmf_presentation_start(TSMF_PRESENTATION* presentation)
@ -645,7 +877,9 @@ void tsmf_presentation_free(TSMF_PRESENTATION* presentation)
TSMF_STREAM* stream;
tsmf_presentation_stop(presentation);
freerdp_mutex_lock(presentation->mutex);
list_remove(presentation_list, presentation);
freerdp_mutex_unlock(presentation->mutex);
while (list_size(presentation->stream_list) > 0)
{
@ -757,17 +991,28 @@ void tsmf_stream_free(TSMF_STREAM* stream)
list_free(stream->sample_ack_list);
if (stream->decoder)
{
stream->decoder->Free(stream->decoder);
stream->decoder = 0;
}
freerdp_thread_free(stream->thread);
xfree(stream);
stream = 0;
}
void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pChannelCallback,
uint32 sample_id, uint64 start_time, uint64 end_time, uint64 duration, uint32 extensions,
uint32 data_size, uint8* data)
{
pthread_mutex_lock(&tsmf_mutex);
if (TERMINATING)
{
pthread_mutex_unlock(&tsmf_mutex);
return;
}
pthread_mutex_unlock(&tsmf_mutex);
TSMF_SAMPLE* sample;
sample = xnew(TSMF_SAMPLE);
@ -788,8 +1033,51 @@ void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pC
freerdp_thread_unlock(stream->thread);
}
static void tsmf_signal_handler(int s)
{
pthread_mutex_lock(&tsmf_mutex);
TERMINATING = 1;
pthread_mutex_unlock(&tsmf_mutex);
LIST_ITEM* p_item;
TSMF_PRESENTATION* presentation;
LIST_ITEM* s_item;
TSMF_STREAM* _stream;
if (presentation_list)
{
for (p_item = presentation_list->head; p_item; p_item = p_item->next)
{
presentation = (TSMF_PRESENTATION*) p_item->data;
for (s_item = presentation->stream_list->head; s_item; s_item = s_item->next)
{
_stream = (TSMF_STREAM*) s_item->data;
tsmf_stream_free(_stream);
}
tsmf_presentation_free(presentation);
}
}
unlink("/tmp/tsmf.tid");
if (s == SIGINT)
{
signal(s, SIG_DFL);
kill(getpid(), s);
}
else if (s == SIGUSR1)
{
signal(s, SIG_DFL);
}
}
void tsmf_media_init(void)
{
struct sigaction sigtrap;
sigtrap.sa_handler = tsmf_signal_handler;
sigemptyset(&sigtrap.sa_mask);
sigtrap.sa_flags = 0;
sigaction(SIGINT, &sigtrap, 0);
sigaction(SIGUSR1, &sigtrap, 0);
if (presentation_list == NULL)
presentation_list = list_new();
}

View File

@ -3,6 +3,7 @@
* Video Redirection Virtual Channel - Media Container
*
* Copyright 2010-2011 Vic Lee
* Copyright 2012 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -35,6 +36,9 @@ TSMF_PRESENTATION* tsmf_presentation_new(const uint8* guid, IWTSVirtualChannelCa
TSMF_PRESENTATION* tsmf_presentation_find_by_id(const uint8* guid);
void tsmf_presentation_start(TSMF_PRESENTATION* presentation);
void tsmf_presentation_stop(TSMF_PRESENTATION* presentation);
void tsmf_presentation_paused(TSMF_PRESENTATION* presentation);
void tsmf_presentation_restarted(TSMF_PRESENTATION* presentation);
void tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, uint32 newVolume, uint32 muted);
void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation,
uint32 x, uint32 y, uint32 width, uint32 height,
int num_rects, RDP_RECT* rects);

View File

@ -60,7 +60,7 @@ static const char* const RAIL_ORDER_TYPE_STRINGS[] =
"Execute Result"
};
void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, UNICODE_STRING* unicode_string)
void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, RAIL_UNICODE_STRING* unicode_string)
{
char* buffer;
size_t length = 0;

View File

@ -54,7 +54,7 @@
#define RAIL_GET_APPID_REQ_ORDER_LENGTH 4 /* fixed */
#define RAIL_LANGBAR_INFO_ORDER_LENGTH 4 /* fixed */
void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, UNICODE_STRING* unicode_string);
void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, RAIL_UNICODE_STRING* unicode_string);
void rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake);
void rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result);

View File

@ -0,0 +1,30 @@
# 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(SKEL_SRCS
skel_main.c
skel_main.h
)
add_library(skel ${SKEL_SRCS})
set_target_properties(skel PROPERTIES PREFIX "")
target_link_libraries(skel freerdp-utils)
install(TARGETS skel DESTINATION ${FREERDP_PLUGIN_PATH})

7
channels/skel/readme.txt Normal file
View File

@ -0,0 +1,7 @@
This is a skeleton virtual channel plugin for freerdp
To create your own virtual channel plugin, copy this directory
then change all references of "skel" to your plugin name
remember, plugin name are 7 chars or less, no spaces or funny chars
Jay

125
channels/skel/skel_main.c Normal file
View File

@ -0,0 +1,125 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* Audio Output Virtual Channel
*
* Copyright 2009-2012 Jay Sorg
* Copyright 2010-2012 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 _WIN32
#include <sys/time.h>
#endif
#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/list.h>
#include <freerdp/utils/load_plugin.h>
#include <freerdp/utils/svc_plugin.h>
#include "skel_main.h"
struct skel_plugin
{
rdpSvcPlugin plugin;
/* put your private data here */
};
static void skel_process_interval(rdpSvcPlugin* plugin)
{
printf("skel_process_interval:\n");
}
static void skel_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
{
skelPlugin* skel = (skelPlugin*)plugin;
STREAM* data_out;
int bytes;
printf("skel_process_receive:\n");
if (skel == NULL)
{
return;
}
/* process data in(from server) here */
/* here we just send the same data back */
bytes = stream_get_length(data_in);
if (bytes > 0)
{
data_out = stream_new(bytes);
stream_copy(data_out, data_in, bytes);
/* svc_plugin_send takes ownership of data_out, that is why
we do not free it */
svc_plugin_send(plugin, data_out);
}
stream_free(data_in);
}
static void skel_process_connect(rdpSvcPlugin* plugin)
{
skelPlugin* skel = (skelPlugin*)plugin;
DEBUG_SVC("connecting");
printf("skel_process_connect:\n");
if (skel == NULL)
{
return;
}
/* if you want a call from channel thread once is a while do this */
plugin->interval_ms = 1000;
plugin->interval_callback = skel_process_interval;
}
static void skel_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event)
{
printf("skel_process_event:\n");
/* events comming from main freerdp window to plugin */
/* send them back with svc_plugin_send_event */
freerdp_event_free(event);
}
static void skel_process_terminate(rdpSvcPlugin* plugin)
{
skelPlugin* skel = (skelPlugin*)plugin;
printf("skel_process_terminate:\n");
if (skel == NULL)
{
return;
}
/* put your cleanup here */
xfree(plugin);
}
DEFINE_SVC_PLUGIN(skel, "skel",
CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP)

26
channels/skel/skel_main.h Normal file
View File

@ -0,0 +1,26 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* Audio Output Virtual Channel
*
* Copyright 2012 Jay Sorg
* Copyright 2010-2012 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 __SKEL_MAIN_H
#define __SKEL_MAIN_H
typedef struct skel_plugin skelPlugin;
#endif /* __SKEL_MAIN_H */

View File

@ -3,6 +3,7 @@
* X11 Windows
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2012 HP Development Company, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,9 +19,14 @@
*/
#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <freerdp/rail.h>
#include <freerdp/utils/rail.h>
@ -61,6 +67,9 @@
#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
/*to be accessed by gstreamer plugin*/
#define SHARED_MEM_KEY 7777
struct _PropMotifWmHints
{
unsigned long flags;
@ -269,6 +278,19 @@ void xf_SetWindowText(xfInfo *xfi, xfWindow* window, char *name)
XStoreName(xfi->display, window->handle, name);
}
static void xf_SetWindowPID(xfInfo* xfi, xfWindow* window, pid_t pid)
{
Atom am_wm_pid;
if (pid == 0)
pid = getpid();
am_wm_pid = XInternAtom(xfi->display, "_NET_WM_PID", False);
XChangeProperty(xfi->display, window->handle, am_wm_pid, XA_CARDINAL,
32, PropModeReplace, (unsigned char *)&pid, 1);
}
xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height, boolean decorations)
{
xfWindow* window;
@ -294,6 +316,24 @@ xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height,
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
CWBorderPixel | CWWinGravity | CWBitGravity, &xfi->attribs);
int shmid = shmget(SHARED_MEM_KEY, sizeof(int), IPC_CREAT | 0666);
if (shmid < 0)
{
DEBUG_X11("xf_CreateDesktopWindow: failed to get access to shared memory - shmget()\n");
}
else
{
int *xfwin = shmat(shmid, NULL, 0);
if (xfwin == (int *) -1)
{
DEBUG_X11("xf_CreateDesktopWindow: failed to assign pointer to the memory address - shmat()\n");
}
else
{
*xfwin = (int)window->handle;
}
}
class_hints = XAllocClassHint();
if (class_hints != NULL)
@ -306,6 +346,7 @@ xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height,
xf_ResizeDesktopWindow(xfi, window, width, height);
xf_SetWindowDecorations(xfi, window, decorations);
xf_SetWindowPID(xfi, window, 0);
input_mask =
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
@ -463,6 +504,7 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, rdpWindow* wnd, int x, int y, int width,
xf_SetWindowDecorations(xfi, window, window->decorations);
xf_SetWindowStyle(xfi, window, wnd->style, wnd->extendedStyle);
xf_SetWindowPID(xfi, window, 0);
xf_ShowWindow(xfi, window, WINDOW_SHOW);
XMapWindow(xfi->display, window->handle);

View File

@ -288,6 +288,26 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--authonly</term>
<listitem>
<para>
Only authenticates. This is useful to test your credentials (username and password).
Returns status code 0 if the client can connect, 1 otherwise. Requires a username,
password and connection host at the command line.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--from-stdin</term>
<listitem>
<para>
Prompts for unspecified arguments -u username, -p password, -d domain and connection host.
This is useful to hide arguments from ps. Also useful for scripts that will feed these arguments
to the client via (what else?) stdin.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--no-fastpath</term>
<listitem>

View File

@ -3,6 +3,7 @@
* X11 Client
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2012 HP Development Company, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -245,6 +246,14 @@ void xf_hw_desktop_resize(rdpContext* context)
xfi->drawing = xfi->primary;
}
}
else
{
XSetFunction(xfi->display, xfi->gc, GXcopy);
XSetFillStyle(xfi->display, xfi->gc, FillSolid);
XSetForeground(xfi->display, xfi->gc, 0);
XFillRectangle(xfi->display, xfi->drawable, xfi->gc,
0, 0, xfi->width, xfi->height);
}
}
boolean xf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
@ -280,6 +289,8 @@ void xf_create_window(xfInfo* xfi)
char* win_title;
int width, height;
memset(&xevent, 0x00, sizeof(xevent));
width = xfi->width;
height = xfi->height;
@ -479,7 +490,7 @@ boolean xf_pre_connect(freerdp* instance)
if (arg_parse_result < 0)
{
if (arg_parse_result == FREERDP_ARGS_PARSE_FAILURE)
printf("failed to parse arguments.\n");
fprintf(stderr, "%s:%d: failed to parse arguments.\n", __FILE__, __LINE__);
exit(XF_EXIT_PARSE_ARGUMENTS);
}
@ -521,6 +532,21 @@ boolean xf_pre_connect(freerdp* instance)
freerdp_channels_pre_connect(xfi->_context->channels, instance);
if (settings->authentication_only) {
/* Check --authonly has a username and password. */
if (settings->username == NULL ) {
fprintf(stderr, "--authonly, but no -u username. Please provide one.\n");
exit(1);
}
if (settings->password == NULL ) {
fprintf(stderr, "--authonly, but no -p password. Please provide one.\n");
exit(1);
}
fprintf(stderr, "%s:%d: Authenication only. Don't connect to X.\n", __FILE__, __LINE__);
// Avoid XWindows initialization and configuration below.
return true;
}
xfi->display = XOpenDisplay(NULL);
if (xfi->display == NULL)
@ -775,7 +801,7 @@ boolean xf_authenticate(freerdp* instance, char** username, char** password, cha
// But it doesn't do anything to fix it...
*password = xmalloc(password_size * sizeof(char));
if (freerdp_passphrase_read("Password: ", *password, password_size) == NULL)
if (freerdp_passphrase_read("Password: ", *password, password_size, instance->settings->from_stdin) == NULL)
return false;
return true;
@ -1067,7 +1093,15 @@ int xfreerdp_run(freerdp* instance)
memset(wfds, 0, sizeof(wfds));
memset(&timeout, 0, sizeof(struct timeval));
if (!freerdp_connect(instance))
boolean status = freerdp_connect(instance);
/* Connection succeeded. --authonly ? */
if (instance->settings->authentication_only) {
freerdp_disconnect(instance);
fprintf(stderr, "%s:%d: Authentication only, exit status %d\n", __FILE__, __LINE__, !status);
exit(!status);
}
if (!status)
{
xf_free(((xfContext*) instance->context)->xfi);
return XF_EXIT_CONN_FAILED;
@ -1156,6 +1190,31 @@ int xfreerdp_run(freerdp* instance)
xf_process_channel_event(channels, instance);
}
FILE *fin = fopen("/tmp/tsmf.tid", "rt");
if(fin)
{
int thid = 0;
fscanf(fin, "%d", &thid);
fclose(fin);
pthread_kill((pthread_t) thid, SIGUSR1);
FILE *fin1 = fopen("/tmp/tsmf.tid", "rt");
int timeout = 5;
while (fin1)
{
fclose(fin1);
sleep(1);
timeout--;
if (timeout <= 0)
{
unlink("/tmp/tsmf.tid");
pthread_kill((pthread_t) thid, SIGKILL);
break;
}
fin1 = fopen("/tmp/tsmf.tid", "rt");
}
}
if (!ret)
ret = freerdp_error_info(instance);

View File

@ -24,3 +24,4 @@ target_link_libraries(freerdp-test freerdp-core)
target_link_libraries(freerdp-test freerdp-gdi)
target_link_libraries(freerdp-test freerdp-utils)
target_link_libraries(freerdp-test freerdp-channels ${CMAKE_DL_LIBS})

View File

@ -231,6 +231,7 @@ int tfreerdp_run(freerdp* instance)
max_fds = 0;
FD_ZERO(&rfds_set);
FD_ZERO(&wfds_set);
for (i = 0; i < rcount; i++)
{

View File

@ -0,0 +1,2 @@
pkg_check_modules(GSTREAMER gstreamer-plugins-base-0.10 gstreamer-0.10)

47
cmake/FindXRandR.cmake Normal file
View File

@ -0,0 +1,47 @@
# - Find XRANDR
# Find the XRANDR libraries
#
# This module defines the following variables:
# XRANDR_FOUND - true if XRANDR_INCLUDE_DIR & XRANDR_LIBRARY are found
# XRANDR_LIBRARIES - Set when XRANDR_LIBRARY is found
# XRANDR_INCLUDE_DIRS - Set when XRANDR_INCLUDE_DIR is found
#
# XRANDR_INCLUDE_DIR - where to find Xrandr.h, etc.
# XRANDR_LIBRARY - the XRANDR library
#
#=============================================================================
# Copyright 2012 Alam Arias <Alam.GBC@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.
#=============================================================================
find_path(XRANDR_INCLUDE_DIR NAMES X11/extensions/Xrandr.h
PATH_SUFFIXES X11/extensions
DOC "The XRANDR include directory"
)
find_library(XRANDR_LIBRARY NAMES Xrandr
DOC "The XRANDR library"
)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(XRANDR DEFAULT_MSG XRANDR_LIBRARY XRANDR_INCLUDE_DIR)
if(XRANDR_FOUND)
set( XRANDR_LIBRARIES ${XRANDR_LIBRARY} )
set( XRANDR_INCLUDE_DIRS ${XRANDR_INCLUDE_DIR} )
endif()
mark_as_advanced(XRANDR_INCLUDE_DIR XRANDR_LIBRARY)

View File

@ -25,6 +25,7 @@
#cmakedefine WITH_PROFILER
#cmakedefine WITH_SSE2
#cmakedefine WITH_NEON
#cmakedefine WITH_NATIVE_SSPI
/* Debug */
#cmakedefine WITH_DEBUG_CERTIFICATE

View File

@ -133,7 +133,7 @@ void test_InitializeSecurityContext(void)
uint32 fContextReq;
void* output_buffer;
CtxtHandle context;
uint32 pfContextAttr;
ULONG pfContextAttr;
SECURITY_STATUS status;
CredHandle credentials;
TimeStamp expiration;
@ -194,11 +194,11 @@ void test_InitializeSecurityContext(void)
return;
}
printf("cBuffers: %d ulVersion: %d\n", output_SecBuffer_desc.cBuffers, output_SecBuffer_desc.ulVersion);
printf("cBuffers: %ld ulVersion: %ld\n", output_SecBuffer_desc.cBuffers, output_SecBuffer_desc.ulVersion);
p_SecBuffer = &output_SecBuffer_desc.pBuffers[0];
printf("BufferType: 0x%04X cbBuffer:%d\n", p_SecBuffer->BufferType, p_SecBuffer->cbBuffer);
printf("BufferType: 0x%04lX cbBuffer:%ld\n", p_SecBuffer->BufferType, p_SecBuffer->cbBuffer);
freerdp_hexdump((uint8*) p_SecBuffer->pvBuffer, p_SecBuffer->cbBuffer);

View File

@ -177,7 +177,7 @@ void passphrase_read_prompts_to_tty()
{
static const int read_nbyte = 11;
int masterfd;
char* slavedevice;
char* slavedevice = NULL;
char read_buf[read_nbyte];
fd_set fd_set_write;
@ -207,7 +207,7 @@ void passphrase_read_prompts_to_tty()
close(STDOUT_FILENO);
close(STDERR_FILENO);
close(masterfd);
freerdp_passphrase_read("Password: ", buffer, password_size);
freerdp_passphrase_read("Password: ", buffer, password_size, 0);
close(slavefd);
exit(EXIT_SUCCESS);
}
@ -233,7 +233,7 @@ void passphrase_read_reads_from_tty()
static const int read_nbyte = 11;
int masterfd;
int pipe_ends[2];
char* slavedevice;
char* slavedevice = NULL;
char read_buf[read_nbyte];
fd_set fd_set_write;
@ -267,7 +267,7 @@ void passphrase_read_reads_from_tty()
close(STDERR_FILENO);
close(masterfd);
close(pipe_ends[0]);
freerdp_passphrase_read("Password: ", buffer, password_size);
freerdp_passphrase_read("Password: ", buffer, password_size, 0);
write(pipe_ends[1], buffer, password_size);
close(slavefd);
close(pipe_ends[1]);
@ -298,7 +298,7 @@ void passphrase_read_turns_off_echo_during_read()
{
static const int read_nbyte = 11;
int masterfd, slavefd;
char* slavedevice;
char* slavedevice = NULL;
char read_buf[read_nbyte];
fd_set fd_set_write;
struct termios term_flags;
@ -343,7 +343,7 @@ void passphrase_read_turns_off_echo_during_read()
close(STDERR_FILENO);
close(masterfd);
close(slavefd);
freerdp_passphrase_read("Password: ", buffer, password_size);
freerdp_passphrase_read("Password: ", buffer, password_size, 0);
close(child_slavefd);
exit(EXIT_SUCCESS);
}
@ -371,7 +371,7 @@ void passphrase_read_resets_terminal_after_read()
{
static const int read_nbyte = 11;
int masterfd, slavefd, status;
char* slavedevice;
char* slavedevice = NULL;
char read_buf[read_nbyte];
fd_set fd_set_write;
struct termios term_flags;
@ -417,7 +417,7 @@ void passphrase_read_resets_terminal_after_read()
close(STDERR_FILENO);
close(masterfd);
close(slavefd);
freerdp_passphrase_read("Password: ", buffer, password_size);
freerdp_passphrase_read("Password: ", buffer, password_size, 0);
close(child_slavefd);
exit(EXIT_SUCCESS);
}
@ -446,7 +446,7 @@ void passphrase_read_turns_on_newline_echo_during_read()
{
static const int read_nbyte = 11;
int masterfd, slavefd;
char* slavedevice;
char* slavedevice = NULL;
char read_buf[read_nbyte];
fd_set fd_set_write;
struct termios term_flags;
@ -491,7 +491,7 @@ void passphrase_read_turns_on_newline_echo_during_read()
close(STDERR_FILENO);
close(masterfd);
close(slavefd);
freerdp_passphrase_read("Password: ", buffer, password_size);
freerdp_passphrase_read("Password: ", buffer, password_size, 0);
close(child_slavefd);
exit(EXIT_SUCCESS);
}
@ -543,7 +543,7 @@ void passphrase_read_prompts_to_stderr_when_no_tty()
dup2(stdin_pipe[0], STDIN_FILENO);
dup2(stderr_pipe[1], STDERR_FILENO);
freerdp_passphrase_read("Password: ", buffer, password_size);
freerdp_passphrase_read("Password: ", buffer, password_size, 0);
exit(EXIT_SUCCESS);
}
}
@ -595,7 +595,7 @@ void passphrase_read_reads_from_stdin_when_no_tty()
dup2(stdin_pipe[0], STDIN_FILENO);
dup2(stderr_pipe[1], STDERR_FILENO);
freerdp_passphrase_read("Password: ", buffer, password_size);
freerdp_passphrase_read("Password: ", buffer, password_size, 0);
write(result_pipe[1], buffer, strlen(buffer) + (size_t) 1);
exit(EXIT_SUCCESS);
}
@ -636,7 +636,7 @@ void test_passphrase_read(void)
void handle_signals_resets_terminal(void)
{
int status, masterfd;
char* slavedevice;
char* slavedevice = NULL;
struct termios test_flags;
pid_t child_pid;

View File

@ -42,7 +42,8 @@ typedef struct WTSVirtualChannelManager WTSVirtualChannelManager;
typedef enum _WTS_VIRTUAL_CLASS
{
WTSVirtualClientData,
WTSVirtualFileHandle
WTSVirtualFileHandle,
WTSVirtualChannelReady
} WTS_VIRTUAL_CLASS;
/**
@ -61,7 +62,8 @@ FREERDP_API boolean WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChanne
* The original MS API has 'DWORD SessionId' as the first argument, while we
* use our WTSVirtualChannelManager object instead.
*
* This functions should be called only from the main thread.
* Static virtual channels must be opened from the main thread. Dynamic virtual channels
* can be opened from any thread.
*/
FREERDP_API void* WTSVirtualChannelOpenEx(
/* __in */ WTSVirtualChannelManager* vcm,

View File

@ -50,6 +50,7 @@ struct rdp_certificate_store
FREERDP_API rdpCertificateData* certificate_data_new(char* hostname, char* fingerprint);
FREERDP_API void certificate_data_free(rdpCertificateData* certificate_data);
FREERDP_API rdpCertificateStore* certificate_store_new(rdpSettings* settings);
FREERDP_API void certificate_data_replace(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data);
FREERDP_API void certificate_store_free(rdpCertificateStore* certificate_store);
FREERDP_API int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data);
FREERDP_API void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data);

View File

@ -23,41 +23,14 @@
#include <freerdp/crypto/er.h>
#include <freerdp/utils/memory.h>
#define der_read_length er_read_length
#define _der_skip_length _er_skip_length
#define der_get_content_length er_get_content_length
#define der_read_universal_tag er_read_universal_tag
#define der_write_universal_tag er_write_universal_tag
#define der_read_application_tag er_read_application_tag
#define der_read_enumerated er_read_enumerated
#define der_read_contextual_tag er_read_contextual_tag
#define der_skip_contextual_tag er_skip_contextual_tag
#define der_read_sequence_tag er_read_sequence_tag
#define der_skip_sequence er_skip_sequence
#define der_skip_sequence_tag er_skip_sequence_tag
#define der_read_bit_string er_read_bit_string
#define der_read_octet_string er_read_octet_string
#define der_skip_octet_string er_skip_octet_string
#define der_read_boolean er_read_boolean
#define der_write_boolean er_write_boolean
#define der_read_integer er_read_integer
#define der_write_integer er_write_integer
#define der_read_integer_length er_read_integer_length
#define der_skip_integer er_skip_integer
#define der_write_sequence_tag(_a, _b) er_write_sequence_tag(_a, _b, true)
#define der_write_octet_string_tag(_a, _b) er_write_octet_string_tag(_a, _b, true)
#define der_write_octet_string(_a, _b, _c) er_write_octet_string(_a, _b, _c, true)
#define der_write_bit_string_tag(_a, _b, _c) er_write_bit_string_tag(_a, _b, _c, true);
#define der_write_contextual_tag(_a, _b, _c, _d) er_write_contextual_tag(_a, _b, _c, _d, true);
#define der_write_enumerated(_a, _b, _c) er_write_enumerated(_a, _b, _c, true)
#define der_write_application_tag(_a, _b, _c) er_write_application_tag(_a, _b, _c, true)
FREERDP_API int _der_skip_length(int length);
FREERDP_API int der_write_length(STREAM* s, int length);
FREERDP_API boolean der_write_bit_string(STREAM* s, uint32 length, uint8 padding);
FREERDP_API boolean der_write_general_string(STREAM* s, char* str);
FREERDP_API char* der_read_general_string(STREAM* s, int *length);
FREERDP_API int der_write_principal_name(STREAM* s, uint8 ntype, char** name);
FREERDP_API int der_write_generalized_time(STREAM* s, char* tstr);
FREERDP_API boolean der_read_generalized_time(STREAM* s, char** tstr);
FREERDP_API int der_get_content_length(int length);
FREERDP_API int der_skip_octet_string(int length);
FREERDP_API int der_skip_sequence_tag(int length);
FREERDP_API int der_write_sequence_tag(STREAM* s, int length);
FREERDP_API int der_skip_contextual_tag(int length);
FREERDP_API int der_write_contextual_tag(STREAM* s, uint8 tag, int length, boolean pc);
FREERDP_API void der_write_octet_string(STREAM* s, uint8* oct_str, int length);
#endif /* FREERDP_CRYPTO_DER_H */

View File

@ -30,6 +30,7 @@ typedef struct rdp_credssp rdpCredssp;
#include <freerdp/crypto/tls.h>
#include <freerdp/crypto/ber.h>
#include <freerdp/crypto/der.h>
#include <freerdp/crypto/crypto.h>
struct rdp_credssp
@ -47,6 +48,7 @@ struct rdp_credssp
SecBuffer PublicKey;
SecBuffer ts_credentials;
CryptoRc4 rc4_seal_state;
LPTSTR ServicePrincipalName;
SEC_WINNT_AUTH_IDENTITY identity;
PSecurityFunctionTable table;
SecPkgContext_Sizes ContextSizes;

View File

@ -49,6 +49,7 @@ FREERDP_API boolean tls_disconnect(rdpTls* tls);
FREERDP_API int tls_read(rdpTls* tls, uint8* data, int length);
FREERDP_API int tls_write(rdpTls* tls, uint8* data, int length);
FREERDP_API int tls_read_all(rdpTls* tls, uint8* data, int length);
FREERDP_API int tls_write_all(rdpTls* tls, uint8* data, int length);
FREERDP_API boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname);

View File

@ -52,6 +52,7 @@ typedef boolean (*pPreConnect)(freerdp* instance);
typedef boolean (*pPostConnect)(freerdp* instance);
typedef boolean (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain);
typedef boolean (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint);
typedef boolean (*pVerifyChangedCertificate)(freerdp* instance, char* subject, char* issuer, char* new_fingerprint, char* old_fingerprint);
typedef int (*pSendChannelData)(freerdp* instance, int channelId, uint8* data, int size);
typedef int (*pReceiveChannelData)(freerdp* instance, int channelId, uint8* data, int size, int flags, int total_size);
@ -163,7 +164,11 @@ struct rdp_freerdp
pVerifyCertificate VerifyCertificate; /**< (offset 51)
Callback for certificate validation.
Used to verify that an unknown certificate is trusted. */
uint32 paddingD[64 - 52]; /* 52 */
pVerifyChangedCertificate VerifyChangedCertificate; /**< (offset 52)
Callback for changed certificate validation.
Used when a certificate differs from stored fingerprint.
If returns true, the new fingerprint will be trusted and old thrown out. */
uint32 paddingD[64 - 51]; /* 51 */
pSendChannelData SendChannelData; /* (offset 64)
Callback for sending data to a channel.

View File

@ -70,6 +70,7 @@ struct rdp_freerdp_peer
uint32 ack_frame_id;
boolean local;
boolean activated;
};
FREERDP_API void freerdp_peer_context_new(freerdp_peer* client);

View File

@ -150,18 +150,18 @@ enum SPI_MASK
#define TF_SFT_NOEXTRAICONSONMINIMIZED 0x00000400
#define TF_SFT_DESKBAND 0x00000800
struct _UNICODE_STRING
struct _RAIL_UNICODE_STRING
{
uint16 length;
uint8* string;
};
typedef struct _UNICODE_STRING UNICODE_STRING;
typedef struct _RAIL_UNICODE_STRING RAIL_UNICODE_STRING;
struct _HIGH_CONTRAST
{
uint32 flags;
uint32 colorSchemeLength;
UNICODE_STRING colorScheme;
RAIL_UNICODE_STRING colorScheme;
};
typedef struct _HIGH_CONTRAST HIGH_CONTRAST;
@ -182,9 +182,9 @@ typedef struct _RAIL_CLIENT_STATUS_ORDER RAIL_CLIENT_STATUS_ORDER;
struct _RAIL_EXEC_ORDER
{
uint16 flags;
UNICODE_STRING exeOrFile;
UNICODE_STRING workingDir;
UNICODE_STRING arguments;
RAIL_UNICODE_STRING exeOrFile;
RAIL_UNICODE_STRING workingDir;
RAIL_UNICODE_STRING arguments;
};
typedef struct _RAIL_EXEC_ORDER RAIL_EXEC_ORDER;
@ -193,7 +193,7 @@ struct _RAIL_EXEC_RESULT_ORDER
uint16 flags;
uint16 execResult;
uint32 rawResult;
UNICODE_STRING exeOrFile;
RAIL_UNICODE_STRING exeOrFile;
};
typedef struct _RAIL_EXEC_RESULT_ORDER RAIL_EXEC_RESULT_ORDER;
@ -287,7 +287,7 @@ typedef struct _RAIL_GET_APPID_REQ_ORDER RAIL_GET_APPID_REQ_ORDER;
struct _RAIL_GET_APPID_RESP_ORDER
{
uint32 windowId;
UNICODE_STRING applicationId;
RAIL_UNICODE_STRING applicationId;
uint8 applicationIdBuffer[512];
};
typedef struct _RAIL_GET_APPID_RESP_ORDER RAIL_GET_APPID_RESP_ORDER;

View File

@ -46,7 +46,7 @@ struct rdp_window
uint32 style;
uint32 extendedStyle;
uint8 showState;
UNICODE_STRING titleInfo;
RAIL_UNICODE_STRING titleInfo;
uint32 clientOffsetX;
uint32 clientOffsetY;
uint32 clientAreaWidth;

View File

@ -0,0 +1,95 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* Server Audio Input Virtual Channel
*
* Copyright 2012 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 __SERVER_AUDIN_H
#define __SERVER_AUDIN_H
#include <freerdp/channels/wtsvc.h>
#include <freerdp/channels/rdpsnd.h>
typedef struct _audin_server_context audin_server_context;
typedef void (*psAudinServerSelectFormat)(audin_server_context* context, int client_format_index);
typedef boolean (*psAudinServerOpen)(audin_server_context* context);
typedef boolean (*psAudinServerClose)(audin_server_context* context);
typedef void (*psAudinServerOpening)(audin_server_context* context);
typedef void (*psAudinServerOpenResult)(audin_server_context* context, uint32 result);
typedef void (*psAudinServerReceiveSamples)(audin_server_context* context, const void* buf, int nframes);
struct _audin_server_context
{
WTSVirtualChannelManager* vcm;
/* Server self-defined pointer. */
void* data;
/* Server supported formats. Set by server. */
const rdpsndFormat* server_formats;
int num_server_formats;
/* Server destination PCM audio format. Set by server. */
rdpsndFormat dst_format;
/* Server preferred frames per packet. */
int frames_per_packet;
/* Client supported formats. */
rdpsndFormat* client_formats;
int num_client_formats;
int selected_client_format;
/*** APIs called by the server. ***/
/**
* Choose the audio format to be received. The index argument is an index into
* the client_formats array and must be smaller than num_client_formats.
*/
psAudinServerSelectFormat SelectFormat;
/**
* Open the audio input stream.
*/
psAudinServerOpen Open;
/**
* Close the audio stream.
*/
psAudinServerClose Close;
/*** Callbacks registered by the server. ***/
/**
* It's ready to open the audio input stream. The server should examine client
* formats and call SelectFormat to choose the desired one in this callback.
*/
psAudinServerOpening Opening;
/**
* Client replied HRESULT of the open operation.
*/
psAudinServerOpenResult OpenResult;
/**
* Receive audio samples. Actual bytes in the buffer is:
* nframes * dst_format.nBitsPerSample * dst_format.nChannels / 8
* Note that this callback is called from a different thread context so the
* server must be careful of thread synchronization.
*/
psAudinServerReceiveSamples ReceiveSamples;
};
FREERDP_API audin_server_context* audin_server_context_new(WTSVirtualChannelManager* vcm);
FREERDP_API void audin_server_context_free(audin_server_context* context);
#endif

View File

@ -293,7 +293,9 @@ struct rdp_settings
ALIGN64 char* tsg_username; /* 66 */
ALIGN64 char* tsg_password; /* 67 */
ALIGN64 boolean local; /* 68 */
ALIGN64 uint64 paddingC[80 - 69]; /* 69 */
ALIGN64 boolean authentication_only; /* 69 */
ALIGN64 boolean from_stdin; /* 70 */
ALIGN64 uint64 paddingC[80 - 71]; /* 71 */
/* User Interface Parameters */
ALIGN64 boolean sw_gdi; /* 80 */

View File

@ -29,5 +29,7 @@ FREERDP_API boolean freerdp_close_library(void* library);
FREERDP_API void* freerdp_load_library_symbol(const char* file, const char* name);
FREERDP_API void* freerdp_load_plugin(const char* name, const char* entry_name);
FREERDP_API void* freerdp_load_channel_plugin(rdpSettings* settings, const char* name, const char* entry_name);
FREERDP_API boolean freerdp_register_static_plugin(const char* name, const char* entry_name, void* entry_addr);
FREERDP_API void* freerdp_load_static_plugin(const char* name, const char* entry_name);
#endif /* __LOAD_PLUGIN_UTILS_H */

View File

@ -23,6 +23,6 @@
#include <stdlib.h>
#include <freerdp/api.h>
FREERDP_API char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz);
FREERDP_API char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz, int from_stdin);
#endif /* __UTILS_PASSPHRASE_H */

View File

@ -25,11 +25,11 @@
#include <freerdp/utils/rect.h>
#include <freerdp/utils/stream.h>
FREERDP_API void rail_unicode_string_alloc(UNICODE_STRING* unicode_string, uint16 cbString);
FREERDP_API void rail_unicode_string_free(UNICODE_STRING* unicode_string);
FREERDP_API void rail_read_unicode_string(STREAM* s, UNICODE_STRING* unicode_string);
FREERDP_API void rail_write_unicode_string(STREAM* s, UNICODE_STRING* unicode_string);
FREERDP_API void rail_write_unicode_string_value(STREAM* s, UNICODE_STRING* unicode_string);
FREERDP_API void rail_unicode_string_alloc(RAIL_UNICODE_STRING* unicode_string, uint16 cbString);
FREERDP_API void rail_unicode_string_free(RAIL_UNICODE_STRING* unicode_string);
FREERDP_API void rail_read_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string);
FREERDP_API void rail_write_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string);
FREERDP_API void rail_write_unicode_string_value(STREAM* s, RAIL_UNICODE_STRING* unicode_string);
FREERDP_API void* rail_clone_order(uint32 event_type, void* order);
FREERDP_API void rail_free_cloned_order(uint32 event_type, void* order);

View File

@ -65,7 +65,7 @@ FREERDP_API void stream_extend(STREAM* stream, int request_size);
#define stream_read_uint8(_s, _v) do { _v = *_s->p++; } while (0)
#define stream_read_uint16(_s, _v) do { _v = \
(uint16)(*_s->p) + \
(((uint16)(*(_s->p + 1))) << 8); \
(uint16)(((uint16)(*(_s->p + 1))) << 8); \
_s->p += 2; } while (0)
#define stream_read_uint32(_s, _v) do { _v = \
(uint32)(*_s->p) + \

View File

@ -60,9 +60,15 @@ FREERDP_API int svc_plugin_send_event(rdpSvcPlugin* plugin, RDP_EVENT* event);
#define DEBUG_SVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
#ifdef WITH_STATIC_PLUGINS
#define DEFINE_SVC_PLUGIN_ENTRY(_prefix) int _prefix##_entry(PCHANNEL_ENTRY_POINTS pEntryPoints)
#else
#define DEFINE_SVC_PLUGIN_ENTRY(_prefix) int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
#endif
#define DEFINE_SVC_PLUGIN(_prefix, _name, _options) \
\
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) \
DEFINE_SVC_PLUGIN_ENTRY(_prefix) \
{ \
_prefix##Plugin* _p; \
\

View File

@ -155,8 +155,8 @@ struct _NOTIFY_ICON_INFOTIP
{
uint32 timeout;
uint32 flags;
UNICODE_STRING text;
UNICODE_STRING title;
RAIL_UNICODE_STRING text;
RAIL_UNICODE_STRING title;
};
typedef struct _NOTIFY_ICON_INFOTIP NOTIFY_ICON_INFOTIP;
@ -166,7 +166,7 @@ struct _WINDOW_STATE_ORDER
uint32 style;
uint32 extendedStyle;
uint32 showState;
UNICODE_STRING titleInfo;
RAIL_UNICODE_STRING titleInfo;
uint32 clientOffsetX;
uint32 clientOffsetY;
uint32 clientAreaWidth;
@ -203,7 +203,7 @@ typedef struct _WINDOW_CACHED_ICON_ORDER WINDOW_CACHED_ICON_ORDER;
struct _NOTIFY_ICON_STATE_ORDER
{
uint32 version;
UNICODE_STRING toolTip;
RAIL_UNICODE_STRING toolTip;
NOTIFY_ICON_INFOTIP infoTip;
uint32 state;
ICON_INFO icon;

383
include/winpr/asn1.h Normal file
View File

@ -0,0 +1,383 @@
/**
* WinPR: Windows Portable Runtime
* ASN.1 Encoding & Decoding Engine
*
* Copyright 2012 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.
*/
#ifndef WINPR_ASN1_H
#define WINPR_ASN1_H
#ifdef _WIN32
#include <msasn1.h>
#include <msber.h>
#else
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
typedef unsigned char ASN1uint8_t;
typedef signed char ASN1int8_t;
typedef unsigned short ASN1uint16_t;
typedef signed short ASN1int16_t;
typedef unsigned long ASN1uint32_t;
typedef signed long ASN1int32_t;
typedef ASN1uint8_t ASN1octet_t;
typedef ASN1uint8_t ASN1bool_t;
struct tagASN1intx_t
{
ASN1uint32_t length;
ASN1octet_t* value;
};
typedef struct tagASN1intx_t ASN1intx_t;
struct tagASN1octetstring_t
{
ASN1uint32_t length;
ASN1octet_t* value;
};
typedef struct tagASN1octetstring_t ASN1octetstring_t;
struct tagASN1octetstring2_t
{
ASN1uint32_t length;
ASN1octet_t value[1];
};
typedef struct tagASN1octetstring2_t ASN1octetstring2_t;
struct ASN1iterator_s
{
struct ASN1iterator_s* next;
void* value;
};
typedef struct ASN1iterator_s ASN1iterator_t;
struct tagASN1bitstring_t
{
ASN1uint32_t length;
ASN1octet_t* value;
};
typedef struct tagASN1bitstring_t ASN1bitstring_t;
typedef char ASN1char_t;
struct tagASN1charstring_t
{
ASN1uint32_t length;
ASN1char_t* value;
};
typedef struct tagASN1charstring_t ASN1charstring_t;
typedef ASN1uint16_t ASN1char16_t;
struct tagASN1char16string_t
{
ASN1uint32_t length;
ASN1char16_t* value;
};
typedef struct tagASN1char16string_t ASN1char16string_t;
typedef ASN1uint32_t ASN1char32_t;
struct tagASN1char32string_t
{
ASN1uint32_t length;
ASN1char32_t* value;
};
typedef struct tagASN1char32string_t ASN1char32string_t;
typedef ASN1char_t* ASN1ztcharstring_t;
typedef ASN1char16_t* ASN1ztchar16string_t;
typedef ASN1char32_t* ASN1ztchar32string_t;
struct tagASN1wstring_t
{
ASN1uint32_t length;
WCHAR* value;
};
typedef struct tagASN1wstring_t ASN1wstring_t;
struct ASN1objectidentifier_s
{
struct ASN1objectidentifier_s* next;
ASN1uint32_t value;
};
typedef struct ASN1objectidentifier_s* ASN1objectidentifier_t;
struct tagASN1objectidentifier2_t
{
ASN1uint16_t count;
ASN1uint32_t value[16];
};
typedef struct tagASN1objectidentifier2_t ASN1objectidentifier2_t;
struct tagASN1encodedOID_t
{
ASN1uint16_t length;
ASN1octet_t* value;
};
typedef struct tagASN1encodedOID_t ASN1encodedOID_t;
typedef ASN1ztcharstring_t ASN1objectdescriptor_t;
struct tagASN1generalizedtime_t
{
ASN1uint16_t year;
ASN1uint8_t month;
ASN1uint8_t day;
ASN1uint8_t hour;
ASN1uint8_t minute;
ASN1uint8_t second;
ASN1uint16_t millisecond;
ASN1bool_t universal;
ASN1int16_t diff;
};
typedef struct tagASN1generalizedtime_t ASN1generalizedtime_t;
struct tagASN1utctime_t
{
ASN1uint8_t year;
ASN1uint8_t month;
ASN1uint8_t day;
ASN1uint8_t hour;
ASN1uint8_t minute;
ASN1uint8_t second;
ASN1bool_t universal;
ASN1int16_t diff;
};
typedef struct tagASN1utctime_t ASN1utctime_t;
struct tagASN1open_t
{
ASN1uint32_t length;
union
{
void* encoded;
void* value;
};
};
typedef struct tagASN1open_t ASN1open_t;
enum tagASN1blocktype_e
{
ASN1_DER_SET_OF_BLOCK,
};
typedef enum tagASN1blocktype_e ASN1blocktype_e;
typedef ASN1int32_t ASN1enum_t;
typedef ASN1uint16_t ASN1choice_t;
typedef ASN1uint32_t ASN1magic_t;
enum
{
ASN1_CHOICE_BASE = 1,
ASN1_CHOICE_INVALID = -1,
ASN1_CHOICE_EXTENSION = 0,
};
enum tagASN1error_e
{
ASN1_SUCCESS = 0,
ASN1_ERR_INTERNAL = -1001,
ASN1_ERR_EOD = -1002,
ASN1_ERR_CORRUPT = -1003,
ASN1_ERR_LARGE = -1004,
ASN1_ERR_CONSTRAINT = -1005,
ASN1_ERR_MEMORY = -1006,
ASN1_ERR_OVERFLOW = -1007,
ASN1_ERR_BADPDU = -1008,
ASN1_ERR_BADARGS = -1009,
ASN1_ERR_BADREAL = -1010,
ASN1_ERR_BADTAG = -1011,
ASN1_ERR_CHOICE = -1012,
ASN1_ERR_RULE = -1013,
ASN1_ERR_UTF8 = -1014,
ASN1_ERR_PDU_TYPE = -1051,
ASN1_ERR_NYI = -1052,
ASN1_WRN_EXTENDED = 1001,
ASN1_WRN_NOEOD = 1002,
};
typedef enum tagASN1error_e ASN1error_e;
enum tagASN1encodingrule_e
{
ASN1_BER_RULE_BER = 0x0100,
ASN1_BER_RULE_CER = 0x0200,
ASN1_BER_RULE_DER = 0x0400,
ASN1_BER_RULE = ASN1_BER_RULE_BER | ASN1_BER_RULE_CER | ASN1_BER_RULE_DER,
};
typedef enum tagASN1encodingrule_e ASN1encodingrule_e;
typedef struct ASN1encoding_s* ASN1encoding_t;
typedef struct ASN1decoding_s* ASN1decoding_t;
typedef ASN1int32_t (*ASN1BerEncFun_t)(ASN1encoding_t enc, ASN1uint32_t tag, void* data);
typedef ASN1int32_t (*ASN1BerDecFun_t)(ASN1decoding_t enc, ASN1uint32_t tag, void* data);
struct tagASN1BerFunArr_t
{
const ASN1BerEncFun_t* apfnEncoder;
const ASN1BerDecFun_t* apfnDecoder;
};
typedef struct tagASN1BerFunArr_t ASN1BerFunArr_t;
typedef void (*ASN1GenericFun_t)(void);
typedef void (*ASN1FreeFun_t)(void* data);
struct tagASN1module_t
{
ASN1magic_t nModuleName;
ASN1encodingrule_e eRule;
ASN1uint32_t dwFlags;
ASN1uint32_t cPDUs;
const ASN1FreeFun_t* apfnFreeMemory;
const ASN1uint32_t* acbStructSize;
ASN1BerFunArr_t BER;
}
typedef struct tagASN1module_t* ASN1module_t;
struct ASN1encoding_s
{
ASN1magic_t magic;
ASN1uint32_t version;
ASN1module_t module;
ASN1octet_t* buf;
ASN1uint32_t size;
ASN1uint32_t len;
ASN1error_e err;
ASN1uint32_t bit;
ASN1octet_t* pos;
ASN1uint32_t cbExtraHeader;
ASN1encodingrule_e eRule;
ASN1uint32_t dwFlags;
};
struct ASN1decoding_s
{
ASN1magic_t magic;
ASN1uint32_t version;
ASN1module_t module;
ASN1octet_t* buf;
ASN1uint32_t size;
ASN1uint32_t len;
ASN1error_e err;
ASN1uint32_t bit;
ASN1octet_t* pos;
ASN1encodingrule_e eRule;
ASN1uint32_t dwFlags;
};
enum
{
ASN1FLAGS_NONE = 0x00000000L,
ASN1FLAGS_NOASSERT = 0x00001000L,
};
enum
{
ASN1ENCODE_APPEND = 0x00000001L,
ASN1ENCODE_REUSEBUFFER = 0x00000004L,
ASN1ENCODE_SETBUFFER = 0x00000008L,
ASN1ENCODE_ALLOCATEBUFFER = 0x00000010L,
ASN1ENCODE_NOASSERT = ASN1FLAGS_NOASSERT,
};
enum
{
ASN1DECODE_APPENDED = 0x00000001L,
ASN1DECODE_REWINDBUFFER = 0x00000004L,
ASN1DECODE_SETBUFFER = 0x00000008L,
ASN1DECODE_AUTOFREEBUFFER = 0x00000010L,
ASN1DECODE_NOASSERT = ASN1FLAGS_NOASSERT,
};
WINPR_API ASN1module_t ASN1_CreateModule(ASN1uint32_t nVersion, ASN1encodingrule_e eRule,
ASN1uint32_t dwFlags, ASN1uint32_t cPDU, const ASN1GenericFun_t apfnEncoder[],
const ASN1GenericFun_t apfnDecoder[], const ASN1FreeFun_t apfnFreeMemory[],
const ASN1uint32_t acbStructSize[], ASN1magic_t nModuleName);
WINPR_API void ASN1_CloseModule(ASN1module_t pModule);
WINPR_API ASN1error_e ASN1_CreateEncoder(ASN1module_t pModule, ASN1encoding_t* ppEncoderInfo,
ASN1octet_t* pbBuf, ASN1uint32_t cbBufSize, ASN1encoding_t pParent);
WINPR_API ASN1error_e ASN1_Encode(ASN1encoding_t pEncoderInfo, void* pDataStruct, ASN1uint32_t nPduNum,
ASN1uint32_t dwFlags, ASN1octet_t* pbBuf, ASN1uint32_t cbBufSize);
WINPR_API void ASN1_CloseEncoder(ASN1encoding_t pEncoderInfo);
WINPR_API void ASN1_CloseEncoder2(ASN1encoding_t pEncoderInfo);
WINPR_API ASN1error_e ASN1_CreateDecoder(ASN1module_t pModule, ASN1decoding_t* ppDecoderInfo,
ASN1octet_t* pbBuf, ASN1uint32_t cbBufSize, ASN1decoding_t pParent);
WINPR_API ASN1error_e ASN1_Decode(ASN1decoding_t pDecoderInfo, void** ppDataStruct, ASN1uint32_t nPduNum,
ASN1uint32_t dwFlags, ASN1octet_t* pbBuf, ASN1uint32_t cbBufSize);
WINPR_API void ASN1_CloseDecoder(ASN1decoding_t pDecoderInfo);
WINPR_API void ASN1_FreeEncoded(ASN1encoding_t pEncoderInfo, void* pBuf);
WINPR_API void ASN1_FreeDecoded(ASN1decoding_t pDecoderInfo, void* pDataStruct, ASN1uint32_t nPduNum);
enum tagASN1option_e
{
ASN1OPT_CHANGE_RULE = 0x101,
ASN1OPT_GET_RULE = 0x201,
ASN1OPT_NOT_REUSE_BUFFER = 0x301,
ASN1OPT_REWIND_BUFFER = 0x302,
ASN1OPT_SET_DECODED_BUFFER = 0x501,
ASN1OPT_DEL_DECODED_BUFFER = 0x502,
ASN1OPT_GET_DECODED_BUFFER_SIZE = 0x601,
};
typedef enum ASN1option_e;
struct tagASN1optionparam_t
{
ASN1option_e eOption;
union
{
ASN1encodingrule_e eRule;
ASN1uint32_t cbRequiredDecodedBufSize;
struct
{
ASN1octet_t* pbBuf;
ASN1uint32_t cbBufSize;
} Buffer;
};
};
typedef struct tagASN1optionparam_t ASN1optionparam_t;
typedef struct tagASN1optionparam_t ASN1optionparam_s;
WINPR_API ASN1error_e ASN1_SetEncoderOption(ASN1encoding_t pEncoderInfo, ASN1optionparam_t* pOptParam);
WINPR_API ASN1error_e ASN1_GetEncoderOption(ASN1encoding_t pEncoderInfo, ASN1optionparam_t* pOptParam);
WINPR_API ASN1error_e ASN1_SetDecoderOption(ASN1decoding_t pDecoderInfo, ASN1optionparam_t* pOptParam);
WINPR_API ASN1error_e ASN1_GetDecoderOption(ASN1decoding_t pDecoderInfo, ASN1optionparam_t* pOptParam);
#endif
#endif /* WINPR_ASN1_H */

59
include/winpr/dsparse.h Normal file
View File

@ -0,0 +1,59 @@
/**
* WinPR: Windows Portable Runtime
* Active Directory Domain Services Parsing Functions
*
* Copyright 2012 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.
*/
#ifndef WINPR_DSPARSE_H
#define WINPR_DSPARSE_H
#ifdef _WIN32
#include <winpr/windows.h>
#else
#include <winpr/crt.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
WINPR_API DWORD DsCrackSpnW(LPCWSTR pszSpn, DWORD* pcServiceClass, LPWSTR ServiceClass, DWORD* pcServiceName,
LPWSTR ServiceName, DWORD* pcInstanceName, LPWSTR InstanceName, USHORT* pInstancePort);
WINPR_API DWORD DsCrackSpnA(LPCSTR pszSpn, LPDWORD pcServiceClass, LPSTR ServiceClass, LPDWORD pcServiceName,
LPSTR ServiceName, LPDWORD pcInstanceName, LPSTR InstanceName, USHORT* pInstancePort);
#ifdef UNICODE
#define DsCrackSpn DsCrackSpnW
#else
#define DsCrackSpn DsCrackSpnA
#endif
WINPR_API DWORD DsMakeSpnW(LPCWSTR ServiceClass, LPCWSTR ServiceName, LPCWSTR InstanceName,
USHORT InstancePort, LPCWSTR Referrer, DWORD* pcSpnLength, LPWSTR pszSpn);
WINPR_API DWORD DsMakeSpnA(LPCSTR ServiceClass, LPCSTR ServiceName, LPCSTR InstanceName,
USHORT InstancePort, LPCSTR Referrer, DWORD* pcSpnLength, LPSTR pszSpn);
#ifdef UNICODE
#define DsMakeSpn DsMakeSpnW
#else
#define DsMakeSpn DsMakeSpnA
#endif
#endif
#endif /* WINPR_DSPARSE_H */

45
include/winpr/handle.h Normal file
View File

@ -0,0 +1,45 @@
/**
* WinPR: Windows Portable Runtime
* Handle Management
*
* Copyright 2012 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.
*/
#ifndef WINPR_HANDLE_H
#define WINPR_HANDLE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#ifndef _WIN32
#define HANDLE_FLAG_INHERIT 0x00000001
#define HANDLE_FLAG_PROTECT_FROM_CLOSE 0x00000002
WINPR_API BOOL CloseHandle(HANDLE hObject);
WINPR_API BOOL DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle,
LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions);
WINPR_API BOOL GetHandleInformation(HANDLE hObject, LPDWORD lpdwFlags);
WINPR_API BOOL SetHandleInformation(HANDLE hObject, DWORD dwMask, DWORD dwFlags);
#endif
#endif /* WINPR_HANDLE_H */

44
include/winpr/heap.h Normal file
View File

@ -0,0 +1,44 @@
/**
* WinPR: Windows Portable Runtime
* Heap Memory Allocation
*
* Copyright 2012 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.
*/
#ifndef WINPR_HEAP_H
#define WINPR_HEAP_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#ifndef _WIN32
#define HEAP_GENERATE_EXCEPTIONS 0x00000004
#define HEAP_NO_SERIALIZE 0x00000001
#define HEAP_ZERO_MEMORY 0x00000008
#define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010
WINPR_API HANDLE GetProcessHeap(void);
WINPR_API LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
WINPR_API LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes);
WINPR_API BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
#endif
#endif /* WINPR_HEAP_H */

View File

@ -38,16 +38,9 @@
#define RtlFillMemory(Destination, Length, Fill) memset((Destination), (Fill), (Length))
#define RtlZeroMemory(Destination, Length) memset((Destination), 0, (Length))
#define HEAP_GENERATE_EXCEPTIONS 0x00000004
#define HEAP_NO_SERIALIZE 0x00000001
#define HEAP_ZERO_MEMORY 0x00000008
#define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010
WINPR_API HANDLE GetProcessHeap(void);
WINPR_API LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
WINPR_API LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes);
WINPR_API BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
#endif
#include <winpr/heap.h>
#endif /* WINPR_CRT_MEMORY_H */

53
include/winpr/ntlm.h Normal file
View File

@ -0,0 +1,53 @@
/**
* WinPR: Windows Portable Runtime
* NTLM Utils
*
* Copyright 2012 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.
*/
#ifndef WINPR_UTILS_NTLM_H
#define WINPR_UTILS_NTLM_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
WINPR_API BYTE* NTOWFv1W(LPWSTR Password, UINT32 PasswordLength, BYTE* NtHash);
WINPR_API BYTE* NTOWFv1A(LPSTR Password, UINT32 PasswordLength, BYTE* NtHash);
WINPR_API BYTE* NTOWFv2W(LPWSTR Password, UINT32 PasswordLength, LPWSTR User,
UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength, BYTE* NtHash);
WINPR_API BYTE* NTOWFv2A(LPSTR Password, UINT32 PasswordLength, LPSTR User,
UINT32 UserLength, LPSTR Domain, UINT32 DomainLength, BYTE* NtHash);
WINPR_API BYTE* NTOWFv2FromHashW(BYTE* NtHashV1, LPWSTR User, UINT32 UserLength,
LPWSTR Domain, UINT32 DomainLength, BYTE* NtHash);
WINPR_API BYTE* NTOWFv2FromHashA(BYTE* NtHashV1, LPSTR User, UINT32 UserLength,
LPSTR Domain, UINT32 DomainLength, BYTE* NtHash);
#ifdef UNICODE
#define NTOWFv1 NTOWFv1W
#define NTOWFv2 NTOWFv2W
#define NTOWFv2FromHash NTOWFv2FromHashW
#else
#define NTOWFv1 NTOWFv1A
#define NTOWFv2 NTOWFv2A
#define NTOWFv2FromHash NTOWFv2FromHashA
#endif
#endif /* WINPR_UTILS_NTLM_H */

View File

@ -148,13 +148,6 @@ typedef ACCESS_MASK REGSAM;
#define RRF_NOEXPAND 0x10000000
#define RRF_ZEROONFAILURE 0x20000000
typedef struct _SECURITY_ATTRIBUTES
{
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
struct val_context
{
int valuelen;
@ -214,15 +207,6 @@ typedef PVALENTA PVALENT;
WINPR_API LONG RegCloseKey(HKEY hKey);
WINPR_API LONG RegConnectRegistryW(LPCWSTR lpMachineName, HKEY hKey, PHKEY phkResult);
WINPR_API LONG RegConnectRegistryA(LPCSTR lpMachineName, HKEY hKey, PHKEY phkResult);
#ifdef UNICODE
#define RegConnectRegistry RegConnectRegistryW
#else
#define RegConnectRegistry RegConnectRegistryA
#endif
WINPR_API LONG RegCopyTreeW(HKEY hKeySrc, LPCWSTR lpSubKey, HKEY hKeyDest);
WINPR_API LONG RegCopyTreeA(HKEY hKeySrc, LPCSTR lpSubKey, HKEY hKeyDest);
@ -243,28 +227,6 @@ WINPR_API LONG RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR
#define RegCreateKeyEx RegCreateKeyExA
#endif
WINPR_API LONG RegCreateKeyTransactedW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass,
DWORD dwOptions, REGSAM samDesired, const LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult, LPDWORD lpdwDisposition, HANDLE hTransaction, PVOID pExtendedParemeter);
WINPR_API LONG RegCreateKeyTransactedA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass,
DWORD dwOptions, REGSAM samDesired, const LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult, LPDWORD lpdwDisposition, HANDLE hTransaction, PVOID pExtendedParemeter);
#ifdef UNICODE
#define RegCreateKeyTransacted RegCreateKeyTransactedW
#else
#define RegCreateKeyTransacted RegCreateKeyTransactedA
#endif
WINPR_API LONG RegDeleteKeyW(HKEY hKey, LPCWSTR lpSubKey);
WINPR_API LONG RegDeleteKeyA(HKEY hKey, LPCSTR lpSubKey);
#ifdef UNICODE
#define RegDeleteKey RegDeleteKeyW
#else
#define RegDeleteKey RegDeleteKeyA
#endif
WINPR_API LONG RegDeleteKeyExW(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved);
WINPR_API LONG RegDeleteKeyExA(HKEY hKey, LPCSTR lpSubKey, REGSAM samDesired, DWORD Reserved);
@ -274,26 +236,6 @@ WINPR_API LONG RegDeleteKeyExA(HKEY hKey, LPCSTR lpSubKey, REGSAM samDesired, DW
#define RegDeleteKeyEx RegDeleteKeyExA
#endif
WINPR_API LONG RegDeleteKeyTransactedW(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired,
DWORD Reserved, HANDLE hTransaction, PVOID pExtendedParameter);
WINPR_API LONG RegDeleteKeyTransactedA(HKEY hKey, LPCSTR lpSubKey, REGSAM samDesired,
DWORD Reserved, HANDLE hTransaction, PVOID pExtendedParameter);
#ifdef UNICODE
#define RegDeleteKeyTransacted RegDeleteKeyTransactedW
#else
#define RegDeleteKeyTransacted RegDeleteKeyTransactedA
#endif
WINPR_API LONG RegDeleteKeyValueW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName);
WINPR_API LONG RegDeleteKeyValueA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValueName);
#ifdef UNICODE
#define RegDeleteKeyValue RegDeleteKeyValueW
#else
#define RegDeleteKeyValue RegDeleteKeyValueA
#endif
WINPR_API LONG RegDeleteTreeW(HKEY hKey, LPCWSTR lpSubKey);
WINPR_API LONG RegDeleteTreeA(HKEY hKey, LPCSTR lpSubKey);
@ -312,14 +254,8 @@ WINPR_API LONG RegDeleteValueA(HKEY hKey, LPCSTR lpValueName);
#define RegDeleteValue RegDeleteValueA
#endif
WINPR_API LONG RegDisablePredefinedCache(void);
WINPR_API LONG RegDisablePredefinedCacheEx(void);
WINPR_API LONG RegDisableReflectionKey(HKEY hBase);
WINPR_API LONG RegEnableReflectionKey(HKEY hBase);
WINPR_API LONG RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcName,
LPDWORD lpReserved, LPWSTR lpClass, LPDWORD lpcClass, PFILETIME lpftLastWriteTime);
WINPR_API LONG RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcName,
@ -358,6 +294,17 @@ WINPR_API LONG RegGetValueA(HKEY hkey, LPCSTR lpSubKey, LPCSTR lpValue,
#define RegGetValue RegGetValueA
#endif
WINPR_API LONG RegLoadAppKeyW(LPCWSTR lpFile, PHKEY phkResult,
REGSAM samDesired, DWORD dwOptions, DWORD Reserved);
WINPR_API LONG RegLoadAppKeyA(LPCSTR lpFile, PHKEY phkResult,
REGSAM samDesired, DWORD dwOptions, DWORD Reserved);
#ifdef UNICODE
#define RegLoadAppKey RegLoadAppKeyW
#else
#define RegLoadAppKey RegLoadAppKeyA
#endif
WINPR_API LONG RegLoadKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpFile);
WINPR_API LONG RegLoadKeyA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpFile);
@ -391,21 +338,8 @@ WINPR_API LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM
#define RegOpenKeyEx RegOpenKeyExA
#endif
WINPR_API LONG RegOpenKeyTransactedW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions,
REGSAM samDesired, PHKEY phkResult, HANDLE hTransaction, PVOID pExtendedParameter);
WINPR_API LONG RegOpenKeyTransactedA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions,
REGSAM samDesired, PHKEY phkResult, HANDLE hTransaction, PVOID pExtendedParameter);
#ifdef UNICODE
#define RegOpenKeyTransacted RegOpenKeyTransactedW
#else
#define RegOpenKeyTransacted RegOpenKeyTransactedA
#endif
WINPR_API LONG RegOpenUserClassesRoot(HANDLE hToken, DWORD dwOptions, REGSAM samDesired, PHKEY phkResult);
WINPR_API LONG RegOverridePredefKey(HKEY hKey, HKEY hNewHKey);
WINPR_API LONG RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved,
LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen,
LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen,
@ -421,10 +355,6 @@ WINPR_API LONG RegQueryInfoKeyA(HKEY hKey, LPSTR lpClass, LPDWORD lpcClass, LPDW
#define RegQueryInfoKey RegQueryInfoKeyA
#endif
WINPR_API LONG RegQueryMultipleValues(HKEY hKey, PVALENT val_list, DWORD num_vals, LPTSTR lpValueBuf, LPDWORD ldwTotsize);
WINPR_API LONG RegQueryReflectionKey(HKEY hBase, BOOL* bIsReflectionDisabled);
WINPR_API LONG RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName,
LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
WINPR_API LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName,
@ -436,15 +366,6 @@ WINPR_API LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName,
#define RegQueryValueEx RegQueryValueExA
#endif
WINPR_API LONG RegReplaceKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpNewFile, LPCWSTR lpOldFile);
WINPR_API LONG RegReplaceKeyA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpNewFile, LPCSTR lpOldFile);
#ifdef UNICODE
#define RegReplaceKey RegReplaceKeyW
#else
#define RegReplaceKey RegReplaceKeyA
#endif
WINPR_API LONG RegRestoreKeyW(HKEY hKey, LPCWSTR lpFile, DWORD dwFlags);
WINPR_API LONG RegRestoreKeyA(HKEY hKey, LPCSTR lpFile, DWORD dwFlags);
@ -454,15 +375,6 @@ WINPR_API LONG RegRestoreKeyA(HKEY hKey, LPCSTR lpFile, DWORD dwFlags);
#define RegRestoreKey RegRestoreKeyA
#endif
WINPR_API LONG RegSaveKeyW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
WINPR_API LONG RegSaveKeyA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
#ifdef UNICODE
#define RegSaveKey RegSaveKeyW
#else
#define RegSaveKey RegSaveKeyA
#endif
WINPR_API LONG RegSaveKeyExW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD Flags);
WINPR_API LONG RegSaveKeyExA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD Flags);
@ -472,15 +384,6 @@ WINPR_API LONG RegSaveKeyExA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpS
#define RegSaveKeyEx RegSaveKeyExA
#endif
WINPR_API LONG RegSetKeyValueW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData);
WINPR_API LONG RegSetKeyValueA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData);
#ifdef UNICODE
#define RegSetKeyValue RegSetKeyValueW
#else
#define RegSetKeyValue RegSetKeyValueA
#endif
WINPR_API LONG RegSetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor);
WINPR_API LONG RegSetValueExW(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE* lpData, DWORD cbData);

55
include/winpr/sam.h Normal file
View File

@ -0,0 +1,55 @@
/**
* WinPR: Windows Portable Runtime
* Security Accounts Manager (SAM)
*
* Copyright 2012 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.
*/
#ifndef WINPR_UTILS_SAM_H
#define WINPR_UTILS_SAM_H
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
struct winpr_sam
{
FILE* fp;
char* line;
char* buffer;
BOOL read_only;
};
typedef struct winpr_sam WINPR_SAM;
struct winpr_sam_entry
{
LPSTR User;
UINT32 UserLength;
LPSTR Domain;
UINT32 DomainLength;
BYTE LmHash[16];
BYTE NtHash[16];
};
typedef struct winpr_sam_entry WINPR_SAM_ENTRY;
WINPR_API WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, LPSTR Domain, UINT32 DomainLength);
WINPR_API WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength);
WINPR_API void SamFreeEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry);
WINPR_API WINPR_SAM* SamOpen(BOOL read_only);
WINPR_API void SamClose(WINPR_SAM* sam);
#endif /* WINPR_UTILS_SAM_H */

34
include/winpr/security.h Normal file
View File

@ -0,0 +1,34 @@
/**
* WinPR: Windows Portable Runtime
* Security Definitions
*
* Copyright 2012 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.
*/
#ifndef WINPR_SECURITY_H
#define WINPR_SECURITY_H
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
typedef struct _LSA_UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
#endif /* WINPR_SECURITY_H */

View File

@ -22,19 +22,18 @@
#include "config.h"
//#define NATIVE_SSPI
#include <wchar.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/windows.h>
#include <winpr/security.h>
#ifdef _WIN32
#include <tchar.h>
#include <winerror.h>
#ifdef NATIVE_SSPI
#ifdef WITH_NATIVE_SSPI
#define SECURITY_WIN32
#include <sspi.h>
#include <security.h>
@ -103,6 +102,7 @@ typedef SecPkgInfoW* PSecPkgInfoW;
#endif
#define NTLMSP_NAME _T("NTLM")
#define NEGOSSP_NAME _T("Negotiate")
#endif

90
include/winpr/sspicli.h Normal file
View File

@ -0,0 +1,90 @@
/**
* WinPR: Windows Portable Runtime
* Security Support Provider Interface
*
* Copyright 2012 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.
*/
#ifndef WINPR_SSPICLI_H
#define WINPR_SSPICLI_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#ifndef _WIN32
typedef enum
{
/* An unknown name type */
NameUnknown = 0,
/* The fully qualified distinguished name (for example, CN=Jeff Smith,OU=Users,DC=Engineering,DC=Microsoft,DC=Com) */
NameFullyQualifiedDN = 1,
/*
* A legacy account name (for example, Engineering\JSmith).
* The domain-only version includes trailing backslashes (\\)
*/
NameSamCompatible = 2,
/*
* A "friendly" display name (for example, Jeff Smith).
* The display name is not necessarily the defining relative distinguished name (RDN)
*/
NameDisplay = 3,
/* A GUID string that the IIDFromString function returns (for example, {4fa050f0-f561-11cf-bdd9-00aa003a77b6}) */
NameUniqueId = 6,
/*
* The complete canonical name (for example, engineering.microsoft.com/software/someone).
* The domain-only version includes a trailing forward slash (/)
*/
NameCanonical = 7,
/* The user principal name (for example, someone@example.com) */
NameUserPrincipal = 8,
/*
* The same as NameCanonical except that the rightmost forward slash (/)
* is replaced with a new line character (\n), even in a domain-only case
* (for example, engineering.microsoft.com/software\nJSmith)
*/
NameCanonicalEx = 9,
/* The generalized service principal name (for example, www/www.microsoft.com@microsoft.com) */
NameServicePrincipal = 10,
/* The DNS domain name followed by a backward-slash and the SAM user name */
NameDnsDomain = 12
} EXTENDED_NAME_FORMAT, *PEXTENDED_NAME_FORMAT;
WINPR_API BOOL GetUserNameExA(EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize);
WINPR_API BOOL GetUserNameExW(EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize);
#ifdef UNICODE
#define GetUserNameEx GetUserNameExW
#else
#define GetUserNameEx GetUserNameExA
#endif
#endif
#endif /* WINPR_SSPICLI_H */

View File

@ -26,10 +26,10 @@
struct stream
{
BYTE* p;
BYTE* end;
BYTE* data;
BYTE* pointer;
BYTE* buffer;
size_t size;
size_t length;
};
typedef struct stream Stream;
typedef struct stream* PStream;
@ -37,74 +37,74 @@ typedef struct stream* PStream;
WINPR_API PStream PStreamAlloc(size_t size);
WINPR_API void StreamAlloc(PStream s, size_t size);
WINPR_API void StreamReAlloc(PStream s, size_t size);
WINPR_API PStream PStreamAllocAttach(BYTE* data, size_t size);
WINPR_API void StreamAllocAttach(PStream s, BYTE* data, size_t size);
WINPR_API PStream PStreamAllocAttach(BYTE* buffer, size_t size);
WINPR_API void StreamAllocAttach(PStream s, BYTE* buffer, size_t size);
WINPR_API void PStreamFree(PStream s);
WINPR_API void StreamFree(PStream s);
WINPR_API void PStreamFreeDetach(PStream s);
WINPR_API void StreamFreeDetach(PStream s);
WINPR_API void StreamAttach(PStream s, BYTE* data, size_t size);
WINPR_API void StreamAttach(PStream s, BYTE* buffer, size_t size);
WINPR_API void StreamDetach(PStream s);
#define StreamRead_UINT8(_s, _v) do { _v = \
*_s->p++; } while (0)
*_s->pointer++; } while (0)
#define StreamRead_UINT16(_s, _v) do { _v = \
(UINT16)(*_s->p) + \
(((UINT16)(*(_s->p + 1))) << 8); \
_s->p += 2; } while (0)
(UINT16)(*_s->pointer) + \
(((UINT16)(*(_s->pointer + 1))) << 8); \
_s->pointer += 2; } while (0)
#define StreamRead_UINT16_BE(_s, _v) do { _v = \
(((UINT16)(*_s->p)) << 8) + \
(UINT16)(*(_s->p + 1)); \
_s->p += 2; } while (0)
(((UINT16)(*_s->pointer)) << 8) + \
(UINT16)(*(_s->pointer + 1)); \
_s->pointer += 2; } while (0)
#define StreamRead_UINT32(_s, _v) do { _v = \
(UINT32)(*_s->p) + \
(((UINT32)(*(_s->p + 1))) << 8) + \
(((UINT32)(*(_s->p + 2))) << 16) + \
(((UINT32)(*(_s->p + 3))) << 24); \
_s->p += 4; } while (0)
(UINT32)(*_s->pointer) + \
(((UINT32)(*(_s->pointer + 1))) << 8) + \
(((UINT32)(*(_s->pointer + 2))) << 16) + \
(((UINT32)(*(_s->pointer + 3))) << 24); \
_s->pointer += 4; } while (0)
#define StreamRead_UINT32_BE(_s, _v) do { _v = \
(((uint32)(*(_s->p))) << 24) + \
(((uint32)(*(_s->p + 1))) << 16) + \
(((uint32)(*(_s->p + 2))) << 8) + \
(((uint32)(*(_s->p + 3)))); \
_s->p += 4; } while (0)
(((uint32)(*(_s->pointer))) << 24) + \
(((uint32)(*(_s->pointer + 1))) << 16) + \
(((uint32)(*(_s->pointer + 2))) << 8) + \
(((uint32)(*(_s->pointer + 3)))); \
_s->pointer += 4; } while (0)
#define StreamRead_UINT64(_s, _v) do { _v = \
(UINT64)(*_s->p) + \
(((UINT64)(*(_s->p + 1))) << 8) + \
(((UINT64)(*(_s->p + 2))) << 16) + \
(((UINT64)(*(_s->p + 3))) << 24) + \
(((UINT64)(*(_s->p + 4))) << 32) + \
(((UINT64)(*(_s->p + 5))) << 40) + \
(((UINT64)(*(_s->p + 6))) << 48) + \
(((UINT64)(*(_s->p + 7))) << 56); \
_s->p += 8; } while (0)
(UINT64)(*_s->pointer) + \
(((UINT64)(*(_s->pointer + 1))) << 8) + \
(((UINT64)(*(_s->pointer + 2))) << 16) + \
(((UINT64)(*(_s->pointer + 3))) << 24) + \
(((UINT64)(*(_s->pointer + 4))) << 32) + \
(((UINT64)(*(_s->pointer + 5))) << 40) + \
(((UINT64)(*(_s->pointer + 6))) << 48) + \
(((UINT64)(*(_s->pointer + 7))) << 56); \
_s->pointer += 8; } while (0)
#define StreamRead(_s, _b, _n) do { \
memcpy(_b, (_s->p), (_n)); \
_s->p += (_n); \
memcpy(_b, (_s->pointer), (_n)); \
_s->pointer += (_n); \
} while (0)
#define StreamWrite_UINT8(_s, _v) do { \
*_s->p++ = (UINT8)(_v); } while (0)
*_s->pointer++ = (UINT8)(_v); } while (0)
#define StreamWrite_UINT16(_s, _v) do { \
*_s->p++ = (_v) & 0xFF; \
*_s->p++ = ((_v) >> 8) & 0xFF; } while (0)
*_s->pointer++ = (_v) & 0xFF; \
*_s->pointer++ = ((_v) >> 8) & 0xFF; } while (0)
#define StreamWrite_UINT16_BE(_s, _v) do { \
*_s->p++ = ((_v) >> 8) & 0xFF; \
*_s->p++ = (_v) & 0xFF; } while (0)
*_s->pointer++ = ((_v) >> 8) & 0xFF; \
*_s->pointer++ = (_v) & 0xFF; } while (0)
#define StreamWrite_UINT32(_s, _v) do { \
*_s->p++ = (_v) & 0xFF; \
*_s->p++ = ((_v) >> 8) & 0xFF; \
*_s->p++ = ((_v) >> 16) & 0xFF; \
*_s->p++ = ((_v) >> 24) & 0xFF; } while (0)
*_s->pointer++ = (_v) & 0xFF; \
*_s->pointer++ = ((_v) >> 8) & 0xFF; \
*_s->pointer++ = ((_v) >> 16) & 0xFF; \
*_s->pointer++ = ((_v) >> 24) & 0xFF; } while (0)
#define StreamWrite_UINT32_BE(_s, _v) do { \
StreamWrite_UINT16_BE(_s, ((_v) >> 16 & 0xFFFF)); \
@ -112,52 +112,52 @@ WINPR_API void StreamDetach(PStream s);
} while (0)
#define StreamWrite_UINT64(_s, _v) do { \
*_s->p++ = (UINT64)(_v) & 0xFF; \
*_s->p++ = ((UINT64)(_v) >> 8) & 0xFF; \
*_s->p++ = ((UINT64)(_v) >> 16) & 0xFF; \
*_s->p++ = ((UINT64)(_v) >> 24) & 0xFF; \
*_s->p++ = ((UINT64)(_v) >> 32) & 0xFF; \
*_s->p++ = ((UINT64)(_v) >> 40) & 0xFF; \
*_s->p++ = ((UINT64)(_v) >> 48) & 0xFF; \
*_s->p++ = ((UINT64)(_v) >> 56) & 0xFF; } while (0)
*_s->pointer++ = (UINT64)(_v) & 0xFF; \
*_s->pointer++ = ((UINT64)(_v) >> 8) & 0xFF; \
*_s->pointer++ = ((UINT64)(_v) >> 16) & 0xFF; \
*_s->pointer++ = ((UINT64)(_v) >> 24) & 0xFF; \
*_s->pointer++ = ((UINT64)(_v) >> 32) & 0xFF; \
*_s->pointer++ = ((UINT64)(_v) >> 40) & 0xFF; \
*_s->pointer++ = ((UINT64)(_v) >> 48) & 0xFF; \
*_s->pointer++ = ((UINT64)(_v) >> 56) & 0xFF; } while (0)
#define StreamWrite(_s, _b, _n) do { \
memcpy(_s->p, (_b), (_n)); \
_s->p += (_n); \
memcpy(_s->pointer, (_b), (_n)); \
_s->pointer += (_n); \
} while (0)
#define StreamPeek_UINT8(_s, _v) do { _v = \
*_s->p; } while (0)
*_s->pointer; } while (0)
#define StreamPeek_UINT16(_s, _v) do { _v = \
(UINT16)(*_s->p) + \
(((UINT16)(*(_s->p + 1))) << 8); \
(UINT16)(*_s->pointer) + \
(((UINT16)(*(_s->pointer + 1))) << 8); \
} while (0)
#define StreamPeek_UINT32(_s, _v) do { _v = \
(UINT32)(*_s->p) + \
(((UINT32)(*(_s->p + 1))) << 8) + \
(((UINT32)(*(_s->p + 2))) << 16) + \
(((UINT32)(*(_s->p + 3))) << 24); \
(UINT32)(*_s->pointer) + \
(((UINT32)(*(_s->pointer + 1))) << 8) + \
(((UINT32)(*(_s->pointer + 2))) << 16) + \
(((UINT32)(*(_s->pointer + 3))) << 24); \
} while (0)
#define StreamPeek_UINT64(_s, _v) do { _v = \
(UINT64)(*_s->p) + \
(((UINT64)(*(_s->p + 1))) << 8) + \
(((UINT64)(*(_s->p + 2))) << 16) + \
(((UINT64)(*(_s->p + 3))) << 24) + \
(((UINT64)(*(_s->p + 4))) << 32) + \
(((UINT64)(*(_s->p + 5))) << 40) + \
(((UINT64)(*(_s->p + 6))) << 48) + \
(((UINT64)(*(_s->p + 7))) << 56); \
(UINT64)(*_s->pointer) + \
(((UINT64)(*(_s->pointer + 1))) << 8) + \
(((UINT64)(*(_s->pointer + 2))) << 16) + \
(((UINT64)(*(_s->pointer + 3))) << 24) + \
(((UINT64)(*(_s->pointer + 4))) << 32) + \
(((UINT64)(*(_s->pointer + 5))) << 40) + \
(((UINT64)(*(_s->pointer + 6))) << 48) + \
(((UINT64)(*(_s->pointer + 7))) << 56); \
} while (0)
#define StreamPeek(_s, _b, _n) do { \
memcpy(_b, (_s->p), (_n)); \
memcpy(_b, (_s->pointer), (_n)); \
} while (0)
#define StreamSeek(_s,_offset) _s->p += (_offset)
#define StreamRewind(_s,_offset) _s->p -= (_offset)
#define StreamSeek(_s,_offset) _s->pointer += (_offset)
#define StreamRewind(_s,_offset) _s->pointer -= (_offset)
#define StreamSeek_UINT8(_s) StreamSeek(_s, 1)
#define StreamSeek_UINT16(_s) StreamSeek(_s, 2)
@ -170,37 +170,33 @@ WINPR_API void StreamDetach(PStream s);
#define StreamRewind_UINT64(_s) StreamRewind(_s, 8)
#define StreamZero(_s, _n) do { \
memset(_s->p, '\0', (_n)); \
_s->p += (_n); \
memset(_s->pointer, '\0', (_n)); \
_s->pointer += (_n); \
} while (0)
#define StreamFill(_s, _v, _n) do { \
memset(_s->p, _v, (_n)); \
_s->p += (_n); \
memset(_s->pointer, _v, (_n)); \
_s->pointer += (_n); \
} while (0)
#define StreamCopy(_dst, _src, _n) do { \
memcpy(_dst->p, _src->p, _n); \
_dst->p += _n; \
_src->p += _n; \
memcpy(_dst->pointer, _src->pointer, _n); \
_dst->pointer += _n; \
_src->pointer += _n; \
} while (0)
#define StreamGetOffset(_s) (_s->p - _s->data)
#define StreamSetOffset(_s, _m) _s->p = _s->data + (_m)
#define StreamGetPointer(_s, _p) _p = _s->pointer
#define StreamSetPointer(_s, _p) _s->pointer = _p
#define StreamSeal(_s) _s->end = (_s->p - _s->data)
#define StreamGetPosition(_s) (_s->pointer - _s->buffer)
#define StreamSetPosition(_s, _p) _s->pointer = _s->buffer + (_p)
#define StreamGetMark(_s, _m) _m = _s->p
#define StreamSetMark(_s, _m) _s->p = _m
#define StreamPointer(_s) _s->pointer
#define StreamBuffer(_s) _s->buffer
#define StreamSize(_s) _s->size
#define StreamLength(_s) _s->length
#define StreamGetData(_s) _s->data
#define StreamGetPointer(_s) _s->p
#define StreamSetPointer(_s, _m) _s->p = _m
#define StreamGetEnd(_s) _s->end
#define StreamGetSize(_s) _s->size
#define StreamSize(_s) (_s->p - _s->data)
#define StreamSealedSize(_s) (_s->end - _s->data)
#define StreamRemainingSize(_s) (_s->size - (_s->p - _s->data))
#define StreamRemainingSize(_s) (_s->size - (_s->pointer - _s->buffer))
#define StreamRemainingLength(_s) (_s->length - (_s->pointer - _s->buffer))
#endif /* WINPR_UTILS_STREAM_H */

View File

@ -45,7 +45,7 @@
#define MB_ERR_INVALID_CHARS 0x00000008
WINPR_API char* _strdup(const char* strSource);
WINPR_API wchar_t* _wcsdup(const wchar_t* strSource);
WINPR_API WCHAR* _wcsdup(const WCHAR* strSource);
WINPR_API LPSTR CharUpperA(LPSTR lpsz);
WINPR_API LPWSTR CharUpperW(LPWSTR lpsz);
@ -125,6 +125,24 @@ WINPR_API int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiBy
WINPR_API int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);
WINPR_API int lstrlenA(LPCSTR lpString);
WINPR_API int lstrlenW(LPCWSTR lpString);
#ifdef UNICODE
#define lstrlen lstrlenW
#else
#define lstrlen lstrlenA
#endif
WINPR_API int lstrcmpA(LPCSTR lpString1, LPCSTR lpString2);
WINPR_API int lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2);
#ifdef UNICODE
#define lstrcmp lstrcmpW
#else
#define lstrcmp lstrcmpA
#endif
#endif
#endif /* WINPR_CRT_STRING_H */

64
include/winpr/synch.h Normal file
View File

@ -0,0 +1,64 @@
/**
* WinPR: Windows Portable Runtime
* Synchronization Functions
*
* Copyright 2012 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.
*/
#ifndef WINPR_SYNCH_H
#define WINPR_SYNCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/handle.h>
#ifndef _WIN32
WINPR_API HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCSTR lpName);
WINPR_API HANDLE CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName);
#ifdef UNICODE
#define CreateSemaphore CreateSemaphoreW
#else
#define CreateSemaphore CreateSemaphoreA
#endif
WINPR_API HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName);
WINPR_API HANDLE OpenSemaphoreW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName);
#ifdef UNICODE
#define OpenSemaphore OpenSemaphoreW
#else
#define OpenSemaphore OpenSemaphoreA
#endif
WINPR_API BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount);
#define WAIT_OBJECT_0 0x00000000L
#define WAIT_ABANDONED 0x00000080L
#define WAIT_TIMEOUT 0x00000102L
#define WAIT_FAILED ((DWORD) 0xFFFFFFFF)
WINPR_API DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
WINPR_API DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds);
#endif
#endif /* WINPR_SYNCH_H */

153
include/winpr/sysinfo.h Normal file
View File

@ -0,0 +1,153 @@
/**
* WinPR: Windows Portable Runtime
* System Information
*
* Copyright 2012 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.
*/
#ifndef WINPR_SYSINFO_H
#define WINPR_SYSINFO_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#ifndef _WIN32
typedef enum _COMPUTER_NAME_FORMAT
{
ComputerNameNetBIOS,
ComputerNameDnsHostname,
ComputerNameDnsDomain,
ComputerNameDnsFullyQualified,
ComputerNamePhysicalNetBIOS,
ComputerNamePhysicalDnsHostname,
ComputerNamePhysicalDnsDomain,
ComputerNamePhysicalDnsFullyQualified,
ComputerNameMax
} COMPUTER_NAME_FORMAT;
WINPR_API BOOL GetComputerNameExA(COMPUTER_NAME_FORMAT NameType, LPSTR lpBuffer, LPDWORD nSize);
WINPR_API BOOL GetComputerNameExW(COMPUTER_NAME_FORMAT NameType, LPWSTR lpBuffer, LPDWORD nSize);
#ifdef UNICODE
#define GetComputerNameEx GetComputerNameExW
#else
#define GetComputerNameEx GetComputerNameExA
#endif
typedef struct _OSVERSIONINFOA
{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
CHAR szCSDVersion[128];
} OSVERSIONINFOA, *POSVERSIONINFOA, *LPOSVERSIONINFOA;
typedef struct _OSVERSIONINFOW
{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
WCHAR szCSDVersion[128];
} OSVERSIONINFOW, *POSVERSIONINFOW, *LPOSVERSIONINFOW;
typedef struct _OSVERSIONINFOEXA
{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
CHAR szCSDVersion[128];
WORD wServicePackMajor;
WORD wServicePackMinor;
WORD wSuiteMask;
BYTE wProductType;
BYTE wReserved;
} OSVERSIONINFOEXA, *POSVERSIONINFOEXA, *LPOSVERSIONINFOEXA;
typedef struct _OSVERSIONINFOEXW
{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
WCHAR szCSDVersion[128];
WORD wServicePackMajor;
WORD wServicePackMinor;
WORD wSuiteMask;
BYTE wProductType;
BYTE wReserved;
} OSVERSIONINFOEXW, *POSVERSIONINFOEXW, *LPOSVERSIONINFOEXW;
#ifdef UNICODE
#define OSVERSIONINFO OSVERSIONINFOW
#define OSVERSIONINFOEX OSVERSIONINFOEXW
#define POSVERSIONINFO POSVERSIONINFOW
#define POSVERSIONINFOEX POSVERSIONINFOEXW
#define LPOSVERSIONINFO LPOSVERSIONINFOW
#define LPOSVERSIONINFOEX LPOSVERSIONINFOEXW
#else
#define OSVERSIONINFO OSVERSIONINFOA
#define OSVERSIONINFOEX OSVERSIONINFOEXA
#define POSVERSIONINFO POSVERSIONINFOA
#define POSVERSIONINFOEX POSVERSIONINFOEXA
#define LPOSVERSIONINFO LPOSVERSIONINFOA
#define LPOSVERSIONINFOEX LPOSVERSIONINFOEXA
#endif
#define VER_PLATFORM_WIN32_NT 0x00000002
#define VER_SUITE_BACKOFFICE 0x00000004
#define VER_SUITE_BLADE 0x00000400
#define VER_SUITE_COMPUTE_SERVER 0x00004000
#define VER_SUITE_DATACENTER 0x00000080
#define VER_SUITE_ENTERPRISE 0x00000002
#define VER_SUITE_EMBEDDEDNT 0x00000040
#define VER_SUITE_PERSONAL 0x00000200
#define VER_SUITE_SINGLEUSERTS 0x00000100
#define VER_SUITE_SMALLBUSINESS 0x00000001
#define VER_SUITE_SMALLBUSINESS_RESTRICTED 0x00000020
#define VER_SUITE_STORAGE_SERVER 0x00002000
#define VER_SUITE_TERMINAL 0x00000010
#define VER_SUITE_WH_SERVER 0x00008000
#define VER_NT_DOMAIN_CONTROLLER 0x0000002
#define VER_NT_SERVER 0x0000003
#define VER_NT_WORKSTATION 0x0000001
WINPR_API BOOL GetVersionExA(LPOSVERSIONINFOA lpVersionInformation);
WINPR_API BOOL GetVersionExW(LPOSVERSIONINFOW lpVersionInformation);
#ifdef UNICODE
#define GetVersionEx GetVersionExW
#else
#define GetVersionEx GetVersionExA
#endif
WINPR_API VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime);
#endif
#endif /* WINPR_SYSINFO_H */

View File

@ -1,6 +1,6 @@
/**
* WinPR: Windows Portable Runtime
* Windows Registry
* TCHAR
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
@ -17,16 +17,25 @@
* limitations under the License.
*/
#include <libxml/parser.h>
#include <libxml/xmlmemory.h>
#ifndef WINPR_TCHAR_H
#define WINPR_TCHAR_H
struct _registry_xml
{
xmlDocPtr doc;
xmlNodePtr node;
};
typedef struct _registry_xml RegistryXml;
#include <winpr/wtypes.h>
RegistryXml* registry_xml_new();
RegistryXml* registry_xml_open();
void registry_xml_close(RegistryXml* registry);
#ifdef _WIN32
#include <tchar.h>
#else
#ifdef UNICODE
typedef WCHAR TCHAR;
#define _tprintf wprintf
#else
typedef CHAR TCHAR;
#define _tprintf printf
#endif
#endif
#endif /* WINPR_TCHAR_H */

View File

@ -42,7 +42,7 @@
typedef int BOOL, *PBOOL, *LPBOOL;
typedef unsigned char BYTE, *PBYTE, *LPBYTE;
typedef BYTE BOOLEAN, *PBOOLEAN;
typedef wchar_t WCHAR, *PWCHAR;
typedef unsigned short WCHAR, *PWCHAR;
typedef WCHAR* BSTR;
typedef char CHAR, *PCHAR;
typedef unsigned long DWORD, *PDWORD, *LPDWORD;
@ -54,14 +54,22 @@ typedef float FLOAT;
typedef unsigned char UCHAR, *PUCHAR;
typedef short SHORT;
typedef void* HANDLE;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
typedef void* HANDLE, *LPHANDLE;
typedef DWORD HCALL;
typedef int INT, *LPINT;
typedef signed char INT8;
typedef signed short INT16;
typedef signed int INT32;
typedef signed __int64 INT64;
typedef const wchar_t* LMCSTR;
typedef const WCHAR* LMCSTR;
typedef WCHAR* LMSTR;
typedef long LONG, *PLONG, *LPLONG;
typedef signed __int64 LONGLONG;
@ -74,10 +82,10 @@ typedef signed int LONG32;
typedef signed __int64 LONG64;
typedef const char* LPCSTR;
typedef const wchar_t* LPCWSTR;
typedef const WCHAR* LPCWSTR;
typedef char* PSTR, *LPSTR;
typedef wchar_t* LPWSTR, *PWSTR;
typedef WCHAR* LPWSTR, *PWSTR;
typedef unsigned __int64 QWORD;
typedef UCHAR* STRING;
@ -135,6 +143,23 @@ typedef LPSTR LPTSTR;
typedef LPCSTR LPCTSTR;
#endif
typedef union _ULARGE_INTEGER
{
struct
{
DWORD LowPart;
DWORD HighPart;
};
struct
{
DWORD LowPart;
DWORD HighPart;
} u;
ULONGLONG QuadPart;
} ULARGE_INTEGER, *PULARGE_INTEGER;
typedef struct _FILETIME
{
DWORD dwLowDateTime;
@ -176,6 +201,13 @@ typedef struct _SECURITY_DESCRIPTOR
PACL Dacl;
} SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR;
typedef struct _SECURITY_ATTRIBUTES
{
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
#endif
typedef BYTE byte;

View File

@ -78,7 +78,7 @@ void* brush_cache_get(rdpBrushCache* brush, uint32 index, uint32* bpp)
if (*bpp == 1)
{
if (index > brush->maxMonoEntries)
if (index >= brush->maxMonoEntries)
{
printf("invalid brush (%d bpp) index: 0x%04X\n", *bpp, index);
return NULL;
@ -89,7 +89,7 @@ void* brush_cache_get(rdpBrushCache* brush, uint32 index, uint32* bpp)
}
else
{
if (index > brush->maxEntries)
if (index >= brush->maxEntries)
{
printf("invalid brush (%d bpp) index: 0x%04X\n", *bpp, index);
return NULL;
@ -114,7 +114,7 @@ void brush_cache_put(rdpBrushCache* brush, uint32 index, void* entry, uint32 bpp
if (bpp == 1)
{
if (index > brush->maxMonoEntries)
if (index >= brush->maxMonoEntries)
{
printf("invalid brush (%d bpp) index: 0x%04X\n", bpp, index);
return;
@ -130,7 +130,7 @@ void brush_cache_put(rdpBrushCache* brush, uint32 index, void* entry, uint32 bpp
}
else
{
if (index > brush->maxEntries)
if (index >= brush->maxEntries)
{
printf("invalid brush (%d bpp) index: 0x%04X\n", bpp, index);
return;

View File

@ -51,7 +51,7 @@ void* nine_grid_cache_get(rdpNineGridCache* nine_grid, uint32 index)
{
void* entry;
if (index > nine_grid->maxEntries)
if (index >= nine_grid->maxEntries)
{
printf("invalid NineGrid index: 0x%04X\n", index);
return NULL;
@ -72,7 +72,7 @@ void nine_grid_cache_put(rdpNineGridCache* nine_grid, uint32 index, void* entry)
{
void* prevEntry;
if (index > nine_grid->maxEntries)
if (index >= nine_grid->maxEntries)
{
printf("invalid NineGrid index: 0x%04X\n", index);
return;

View File

@ -71,7 +71,7 @@ rdpBitmap* offscreen_cache_get(rdpOffscreenCache* offscreen_cache, uint32 index)
{
rdpBitmap* bitmap;
if (index > offscreen_cache->maxEntries)
if (index >= offscreen_cache->maxEntries)
{
printf("invalid offscreen bitmap index: 0x%04X\n", index);
return NULL;
@ -90,7 +90,7 @@ rdpBitmap* offscreen_cache_get(rdpOffscreenCache* offscreen_cache, uint32 index)
void offscreen_cache_put(rdpOffscreenCache* offscreen, uint32 index, rdpBitmap* bitmap)
{
if (index > offscreen->maxEntries)
if (index >= offscreen->maxEntries)
{
printf("invalid offscreen bitmap index: 0x%04X\n", index);
return;
@ -104,7 +104,7 @@ void offscreen_cache_delete(rdpOffscreenCache* offscreen, uint32 index)
{
rdpBitmap* prevBitmap;
if (index > offscreen->maxEntries)
if (index >= offscreen->maxEntries)
{
printf("invalid offscreen bitmap index (delete): 0x%04X\n", index);
return;

View File

@ -32,7 +32,7 @@ void* palette_cache_get(rdpPaletteCache* palette_cache, uint32 index)
{
void* entry;
if (index > palette_cache->maxEntries)
if (index >= palette_cache->maxEntries)
{
printf("invalid color table index: 0x%04X\n", index);
return NULL;
@ -51,7 +51,7 @@ void* palette_cache_get(rdpPaletteCache* palette_cache, uint32 index)
void palette_cache_put(rdpPaletteCache* palette_cache, uint32 index, void* entry)
{
if (index > palette_cache->maxEntries)
if (index >= palette_cache->maxEntries)
{
printf("invalid color table index: 0x%04X\n", index);
return;

View File

@ -26,6 +26,12 @@
#include "wtsvc.h"
#define CREATE_REQUEST_PDU 0x01
#define DATA_FIRST_PDU 0x02
#define DATA_PDU 0x03
#define CLOSE_REQUEST_PDU 0x04
#define CAPABILITY_REQUEST_PDU 0x05
typedef struct wts_data_item
{
uint16 channel_id;
@ -39,10 +45,267 @@ static void wts_data_item_free(wts_data_item* item)
xfree(item);
}
static void WTSProcessChannelData(rdpPeerChannel* channel, int channelId, uint8* data, int size, int flags, int total_size)
static rdpPeerChannel* wts_get_dvc_channel_by_id(WTSVirtualChannelManager* vcm, uint32 ChannelId)
{
LIST_ITEM* item;
rdpPeerChannel* channel = NULL;
for (item = vcm->dvc_channel_list->head; item; item = item->next)
{
channel = (rdpPeerChannel*) item->data;
if (channel->channel_id == ChannelId)
break;
}
return channel;
}
static void wts_queue_receive_data(rdpPeerChannel* channel, const uint8* buffer, uint32 length)
{
wts_data_item* item;
item = xnew(wts_data_item);
item->length = length;
item->buffer = xmalloc(length);
memcpy(item->buffer, buffer, length);
freerdp_mutex_lock(channel->mutex);
list_enqueue(channel->receive_queue, item);
freerdp_mutex_unlock(channel->mutex);
wait_obj_set(channel->receive_event);
}
static void wts_queue_send_item(rdpPeerChannel* channel, wts_data_item* item)
{
WTSVirtualChannelManager* vcm;
vcm = channel->vcm;
item->channel_id = channel->channel_id;
freerdp_mutex_lock(vcm->mutex);
list_enqueue(vcm->send_queue, item);
freerdp_mutex_unlock(vcm->mutex);
wait_obj_set(vcm->send_event);
}
static int wts_read_variable_uint(STREAM* s, int cbLen, uint32 *val)
{
switch (cbLen)
{
case 0:
if (stream_get_left(s) < 1)
return 0;
stream_read_uint8(s, *val);
return 1;
case 1:
if (stream_get_left(s) < 2)
return 0;
stream_read_uint16(s, *val);
return 2;
default:
if (stream_get_left(s) < 4)
return 0;
stream_read_uint32(s, *val);
return 4;
}
}
static void wts_read_drdynvc_capabilities_response(rdpPeerChannel* channel, uint32 length)
{
uint16 Version;
if (length < 3)
return;
stream_seek_uint8(channel->receive_data); /* Pad (1 byte) */
stream_read_uint16(channel->receive_data, Version);
DEBUG_DVC("Version: %d", Version);
channel->vcm->drdynvc_state = DRDYNVC_STATE_READY;
}
static void wts_read_drdynvc_create_response(rdpPeerChannel* channel, STREAM* s, uint32 length)
{
uint32 CreationStatus;
if (length < 4)
return;
stream_read_uint32(s, CreationStatus);
if ((sint32)CreationStatus < 0)
{
DEBUG_DVC("ChannelId %d creation failed (%d)", channel->channel_id, (sint32)CreationStatus);
channel->dvc_open_state = DVC_OPEN_STATE_FAILED;
}
else
{
DEBUG_DVC("ChannelId %d creation succeeded", channel->channel_id);
channel->dvc_open_state = DVC_OPEN_STATE_SUCCEEDED;
}
wait_obj_set(channel->receive_event);
}
static void wts_read_drdynvc_data_first(rdpPeerChannel* channel, STREAM* s, int cbLen, uint32 length)
{
int value;
value = wts_read_variable_uint(s, cbLen, &channel->dvc_total_length);
if (value == 0)
return;
length -= value;
if (length > channel->dvc_total_length)
return;
stream_set_pos(channel->receive_data, 0);
stream_check_size(channel->receive_data, channel->dvc_total_length);
stream_write(channel->receive_data, stream_get_tail(s), length);
}
static void wts_read_drdynvc_data(rdpPeerChannel* channel, STREAM* s, uint32 length)
{
if (channel->dvc_total_length > 0)
{
if (stream_get_length(channel->receive_data) + length > channel->dvc_total_length)
{
channel->dvc_total_length = 0;
printf("wts_read_drdynvc_data: incorrect fragment data, discarded.\n");
return;
}
stream_write(channel->receive_data, stream_get_tail(s), length);
if (stream_get_length(channel->receive_data) >= channel->dvc_total_length)
{
wts_queue_receive_data(channel, stream_get_head(channel->receive_data), channel->dvc_total_length);
channel->dvc_total_length = 0;
}
}
else
{
wts_queue_receive_data(channel, stream_get_tail(s), length);
}
}
static void wts_read_drdynvc_close_response(rdpPeerChannel* channel)
{
DEBUG_DVC("ChannelId %d close response", channel->channel_id);
channel->dvc_open_state = DVC_OPEN_STATE_CLOSED;
}
static void wts_read_drdynvc_pdu(rdpPeerChannel* channel)
{
uint32 length;
int value;
int Cmd;
int Sp;
int cbChId;
uint32 ChannelId;
rdpPeerChannel* dvc;
length = stream_get_pos(channel->receive_data);
if (length < 1)
return;
stream_set_pos(channel->receive_data, 0);
stream_read_uint8(channel->receive_data, value);
length--;
Cmd = (value & 0xf0) >> 4;
Sp = (value & 0x0c) >> 2;
cbChId = (value & 0x03) >> 0;
if (Cmd == CAPABILITY_REQUEST_PDU)
{
wts_read_drdynvc_capabilities_response(channel, length);
}
else if (channel->vcm->drdynvc_state == DRDYNVC_STATE_READY)
{
value = wts_read_variable_uint(channel->receive_data, cbChId, &ChannelId);
if (value == 0)
return;
length -= value;
DEBUG_DVC("Cmd %d ChannelId %d length %d", Cmd, ChannelId, length);
dvc = wts_get_dvc_channel_by_id(channel->vcm, ChannelId);
if (dvc)
{
switch (Cmd)
{
case CREATE_REQUEST_PDU:
wts_read_drdynvc_create_response(dvc, channel->receive_data, length);
break;
case DATA_FIRST_PDU:
wts_read_drdynvc_data_first(dvc, channel->receive_data, Sp, length);
break;
case DATA_PDU:
wts_read_drdynvc_data(dvc, channel->receive_data, length);
break;
case CLOSE_REQUEST_PDU:
wts_read_drdynvc_close_response(dvc);
break;
default:
printf("wts_read_drdynvc_pdu: Cmd %d not recognized.\n", Cmd);
break;
}
}
else
{
DEBUG_DVC("ChannelId %d not exists.", ChannelId);
}
}
else
{
printf("wts_read_drdynvc_pdu: received Cmd %d but channel is not ready.\n", Cmd);
}
}
static int wts_write_variable_uint(STREAM* stream, uint32 val)
{
int cb;
if (val <= 0xFF)
{
cb = 0;
stream_write_uint8(stream, val);
}
else if (val <= 0xFFFF)
{
cb = 1;
stream_write_uint16(stream, val);
}
else
{
cb = 3;
stream_write_uint32(stream, val);
}
return cb;
}
static void wts_write_drdynvc_header(STREAM *s, uint8 Cmd, uint32 ChannelId)
{
uint8* bm;
int cbChId;
stream_get_mark(s, bm);
stream_seek_uint8(s);
cbChId = wts_write_variable_uint(s, ChannelId);
*bm = ((Cmd & 0x0F) << 4) | cbChId;
}
static void wts_write_drdynvc_create_request(STREAM *s, uint32 ChannelId, const char *ChannelName)
{
uint32 len;
wts_write_drdynvc_header(s, CREATE_REQUEST_PDU, ChannelId);
len = strlen(ChannelName) + 1;
stream_check_size(s, len);
stream_write(s, ChannelName, len);
}
static void WTSProcessChannelData(rdpPeerChannel* channel, int channelId, uint8* data, int size, int flags, int total_size)
{
if (flags & CHANNEL_FLAG_FIRST)
{
stream_set_pos(channel->receive_data, 0);
@ -57,22 +320,13 @@ static void WTSProcessChannelData(rdpPeerChannel* channel, int channelId, uint8*
{
printf("WTSProcessChannelData: read error\n");
}
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_DVC)
if (channel == channel->vcm->drdynvc_channel)
{
/* TODO: Receive DVC channel data */
wts_read_drdynvc_pdu(channel);
}
else
{
item = xnew(wts_data_item);
item->length = stream_get_length(channel->receive_data);
item->buffer = xmalloc(item->length);
memcpy(item->buffer, stream_get_head(channel->receive_data), item->length);
freerdp_mutex_lock(channel->mutex);
list_enqueue(channel->receive_queue, item);
freerdp_mutex_unlock(channel->mutex);
wait_obj_set(channel->receive_event);
wts_queue_receive_data(channel, stream_get_head(channel->receive_data), stream_get_length(channel->receive_data));
}
stream_set_pos(channel->receive_data, 0);
}
@ -113,6 +367,8 @@ WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client)
vcm->send_event = wait_obj_new();
vcm->send_queue = list_new();
vcm->mutex = freerdp_mutex_new();
vcm->dvc_channel_id_seq = 1;
vcm->dvc_channel_list = list_new();
client->ReceiveChannelData = WTSReceiveChannelData;
}
@ -123,9 +379,15 @@ WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client)
void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm)
{
wts_data_item* item;
rdpPeerChannel* channel;
if (vcm != NULL)
{
while ((channel = (rdpPeerChannel*) list_dequeue(vcm->dvc_channel_list)) != NULL)
{
WTSVirtualChannelClose(channel);
}
list_free(vcm->dvc_channel_list);
if (vcm->drdynvc_channel != NULL)
{
WTSVirtualChannelClose(vcm->drdynvc_channel);
@ -147,12 +409,32 @@ void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm,
void** fds, int* fds_count)
{
wait_obj_get_fds(vcm->send_event, fds, fds_count);
if (vcm->drdynvc_channel)
{
wait_obj_get_fds(vcm->drdynvc_channel->receive_event, fds, fds_count);
}
}
boolean WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm)
{
boolean result = true;
wts_data_item* item;
rdpPeerChannel* channel;
uint32 dynvc_caps;
if (vcm->drdynvc_state == DRDYNVC_STATE_NONE && vcm->client->activated)
{
/* Initialize drdynvc channel once and only once. */
vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
channel = WTSVirtualChannelOpenEx(vcm, "drdynvc", 0);
if (channel)
{
vcm->drdynvc_channel = channel;
dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */
WTSVirtualChannelWrite(channel, (uint8*) &dynvc_caps, sizeof(dynvc_caps), NULL);
}
}
wait_obj_clear(vcm->send_event);
@ -180,55 +462,71 @@ void* WTSVirtualChannelOpenEx(
int i;
int len;
rdpPeerChannel* channel;
const char* channel_name;
freerdp_peer* client = vcm->client;
STREAM* s;
channel_name = ((flags & WTS_CHANNEL_OPTION_DYNAMIC) != 0 ? "drdynvc" : pVirtualName);
len = strlen(channel_name);
if (len > 8)
return NULL;
for (i = 0; i < client->settings->num_channels; i++)
if ((flags & WTS_CHANNEL_OPTION_DYNAMIC) != 0)
{
if (client->settings->channels[i].joined &&
strncmp(client->settings->channels[i].name, channel_name, len) == 0)
if (vcm->drdynvc_channel == NULL || vcm->drdynvc_state != DRDYNVC_STATE_READY)
{
break;
DEBUG_DVC("Dynamic virtual channel not ready.");
return NULL;
}
}
if (i >= client->settings->num_channels)
return NULL;
channel = (rdpPeerChannel*) client->settings->channels[i].handle;
if (channel == NULL)
{
channel = xnew(rdpPeerChannel);
channel->vcm = vcm;
channel->client = client;
channel->channel_id = client->settings->channels[i].channel_id;
channel->index = i;
channel->channel_type = RDP_PEER_CHANNEL_TYPE_DVC;
channel->receive_data = stream_new(client->settings->vc_chunk_size);
if ((flags & WTS_CHANNEL_OPTION_DYNAMIC) != 0)
channel->receive_event = wait_obj_new();
channel->receive_queue = list_new();
channel->mutex = freerdp_mutex_new();
freerdp_mutex_lock(vcm->mutex);
channel->channel_id = vcm->dvc_channel_id_seq++;
list_enqueue(vcm->dvc_channel_list, channel);
freerdp_mutex_unlock(vcm->mutex);
s = stream_new(64);
wts_write_drdynvc_create_request(s, channel->channel_id, pVirtualName);
WTSVirtualChannelWrite(vcm->drdynvc_channel, stream_get_head(s), stream_get_length(s), NULL);
stream_free(s);
DEBUG_DVC("ChannelId %d.%s (total %d)", channel->channel_id, pVirtualName, list_size(vcm->dvc_channel_list));
}
else
{
len = strlen(pVirtualName);
if (len > 8)
return NULL;
for (i = 0; i < client->settings->num_channels; i++)
{
channel->channel_type = RDP_PEER_CHANNEL_TYPE_DVC;
vcm->drdynvc_channel = channel;
if (client->settings->channels[i].joined &&
strncmp(client->settings->channels[i].name, pVirtualName, len) == 0)
{
break;
}
}
else
if (i >= client->settings->num_channels)
return NULL;
channel = (rdpPeerChannel*) client->settings->channels[i].handle;
if (channel == NULL)
{
channel = xnew(rdpPeerChannel);
channel->vcm = vcm;
channel->client = client;
channel->channel_id = client->settings->channels[i].channel_id;
channel->index = i;
channel->channel_type = RDP_PEER_CHANNEL_TYPE_SVC;
channel->receive_data = stream_new(client->settings->vc_chunk_size);
channel->receive_event = wait_obj_new();
channel->receive_queue = list_new();
channel->mutex = freerdp_mutex_new();
}
client->settings->channels[i].handle = channel;
}
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_DVC)
{
/* TODO: do DVC channel initialization here using pVirtualName */
/* A sub-channel should be created and returned, instead of using the main drdynvc channel */
/* Set channel->index to num_channels */
client->settings->channels[i].handle = channel;
}
}
return channel;
@ -240,6 +538,7 @@ boolean WTSVirtualChannelQuery(
/* __out */ void** ppBuffer,
/* __out */ uint32* pBytesReturned)
{
boolean bval;
void* fds[10];
int fds_count = 0;
boolean result = false;
@ -255,6 +554,35 @@ boolean WTSVirtualChannelQuery(
result = true;
break;
case WTSVirtualChannelReady:
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
{
bval = true;
result = true;
}
else
{
switch (channel->dvc_open_state)
{
case DVC_OPEN_STATE_NONE:
bval = false;
result = true;
break;
case DVC_OPEN_STATE_SUCCEEDED:
bval = true;
result = true;
break;
default:
bval = false;
result = false;
break;
}
}
*ppBuffer = xmalloc(sizeof(boolean));
memcpy(*ppBuffer, &bval, sizeof(boolean));
*pBytesReturned = sizeof(boolean);
break;
default:
break;
}
@ -307,55 +635,107 @@ boolean WTSVirtualChannelWrite(
/* __in */ uint32 Length,
/* __out */ uint32* pBytesWritten)
{
uint32 written = 0;
wts_data_item* item;
boolean result = false;
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
WTSVirtualChannelManager* vcm ;
wts_data_item* item;
STREAM* s;
int cbLen;
int cbChId;
int first;
uint32 written;
if (channel == NULL)
return false;
vcm = channel->vcm ;
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
{
item = xnew(wts_data_item);
item->channel_id = channel->channel_id;
item->buffer = xmalloc(Length);
item->length = Length;
memcpy(item->buffer, Buffer, Length);
freerdp_mutex_lock(vcm->mutex);
list_enqueue(vcm->send_queue, item);
freerdp_mutex_unlock(vcm->mutex);
wait_obj_set(vcm->send_event);
written = Length;
result = true;
wts_queue_send_item(channel, item);
}
else if (channel->vcm->drdynvc_channel == NULL || channel->vcm->drdynvc_state != DRDYNVC_STATE_READY)
{
DEBUG_DVC("drdynvc not ready");
return false;
}
else
{
/* TODO: Send to DVC channel */
s = stream_new(0);
first = true;
while (Length > 0)
{
item = xnew(wts_data_item);
item->buffer = xmalloc(channel->client->settings->vc_chunk_size);
stream_attach(s, item->buffer, channel->client->settings->vc_chunk_size);
stream_seek_uint8(s);
cbChId = wts_write_variable_uint(s, channel->channel_id);
if (first && Length > stream_get_left(s))
{
cbLen = wts_write_variable_uint(s, Length);
item->buffer[0] = (DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId;
}
else
{
item->buffer[0] = (DATA_PDU << 4) | cbChId;
}
first = false;
written = stream_get_left(s);
if (written > Length)
written = Length;
stream_write(s, Buffer, written);
item->length = stream_get_length(s);
stream_detach(s);
Length -= written;
Buffer += written;
wts_queue_send_item(channel->vcm->drdynvc_channel, item);
}
stream_free(s);
}
if (pBytesWritten != NULL)
*pBytesWritten = written;
return result;
*pBytesWritten = Length;
return true;
}
boolean WTSVirtualChannelClose(
/* __in */ void* hChannelHandle)
{
STREAM* s;
wts_data_item* item;
WTSVirtualChannelManager* vcm;
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
if (channel != NULL)
if (channel)
{
if (channel->index < channel->client->settings->num_channels)
channel->client->settings->channels[channel->index].handle = NULL;
stream_free(channel->receive_data);
vcm = channel->vcm;
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
{
if (channel->index < channel->client->settings->num_channels)
channel->client->settings->channels[channel->index].handle = NULL;
}
else
{
freerdp_mutex_lock(vcm->mutex);
list_remove(vcm->dvc_channel_list, channel);
freerdp_mutex_unlock(vcm->mutex);
if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED)
{
s = stream_new(8);
wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channel_id);
WTSVirtualChannelWrite(vcm->drdynvc_channel, stream_get_head(s), stream_get_length(s), NULL);
stream_free(s);
}
}
if (channel->receive_data)
stream_free(channel->receive_data);
if (channel->receive_event)
wait_obj_free(channel->receive_event);
if (channel->receive_queue)
@ -370,6 +750,5 @@ boolean WTSVirtualChannelClose(
freerdp_mutex_free(channel->mutex);
xfree(channel);
}
return true;
}

View File

@ -24,21 +24,43 @@
#include <freerdp/utils/stream.h>
#include <freerdp/utils/list.h>
#include <freerdp/utils/mutex.h>
#include <freerdp/utils/debug.h>
#include <freerdp/utils/wait_obj.h>
#include <freerdp/channels/wtsvc.h>
#ifdef WITH_DEBUG_DVC
#define DEBUG_DVC(fmt, ...) DEBUG_CLASS(DVC, fmt, ## __VA_ARGS__)
#else
#define DEBUG_DVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
enum
{
RDP_PEER_CHANNEL_TYPE_SVC = 0,
RDP_PEER_CHANNEL_TYPE_DVC = 1,
RDP_PEER_CHANNEL_TYPE_DVC_SUB = 2
RDP_PEER_CHANNEL_TYPE_DVC = 1
};
typedef struct rdp_peer_channel
enum
{
DRDYNVC_STATE_NONE = 0,
DRDYNVC_STATE_INITIALIZED = 1,
DRDYNVC_STATE_READY = 2
};
enum
{
DVC_OPEN_STATE_NONE = 0,
DVC_OPEN_STATE_SUCCEEDED = 1,
DVC_OPEN_STATE_FAILED = 2,
DVC_OPEN_STATE_CLOSED = 3
};
typedef struct rdp_peer_channel rdpPeerChannel;
struct rdp_peer_channel
{
WTSVirtualChannelManager* vcm;
freerdp_peer* client;
uint16 channel_id;
uint32 channel_id;
uint16 channel_type;
uint16 index;
@ -46,7 +68,10 @@ typedef struct rdp_peer_channel
struct wait_obj* receive_event;
LIST* receive_queue;
freerdp_mutex mutex;
} rdpPeerChannel;
uint8 dvc_open_state;
uint32 dvc_total_length;
};
struct WTSVirtualChannelManager
{
@ -56,6 +81,9 @@ struct WTSVirtualChannelManager
freerdp_mutex mutex;
rdpPeerChannel* drdynvc_channel;
uint8 drdynvc_state;
uint32 dvc_channel_id_seq;
LIST* dvc_channel_list;
};
#endif /* __WTSVC_H */

View File

@ -1445,5 +1445,10 @@ void mppc_dec_free(struct rdp_mppc_dec* dec)
dec->history_buf = NULL;
dec->history_ptr = NULL;
}
if (dec->offset_cache)
{
xfree(dec->offset_cache);
dec->offset_cache = NULL;
}
xfree(dec);
}

View File

@ -17,7 +17,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
add_definitions(-DEXT_PATH="/usr/lib/freerdp/extensions")
add_definitions(-DEXT_PATH="${FREERDP_EXTENSION_PATH}")
include_directories(${OPENSSL_INCLUDE_DIR})
include_directories(${ZLIB_INCLUDE_DIRS})
@ -110,6 +110,10 @@ target_link_libraries(freerdp-core winpr-utils)
target_link_libraries(freerdp-core winpr-rpc)
target_link_libraries(freerdp-core winpr-sspi)
if(NOT WIN32)
target_link_libraries(freerdp-core winpr-registry)
endif()
target_link_libraries(freerdp-core freerdp-crypto)
target_link_libraries(freerdp-core ${OPENSSL_LIBRARIES})

View File

@ -1061,7 +1061,7 @@ void rdp_write_virtual_channel_capability_set(STREAM* s, rdpSettings* settings)
header = rdp_capability_set_start(s);
flags = (settings->server_mode) ? VCCAPS_COMPR_CS_8K : VCCAPS_NO_COMPR;
flags = VCCAPS_NO_COMPR;
stream_write_uint32(s, flags); /* flags (4 bytes) */
stream_write_uint32(s, settings->vc_chunk_size); /* VCChunkSize (4 bytes) */

View File

@ -573,6 +573,7 @@ boolean rdp_client_connect_finalize(rdpRdp* rdp)
boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s)
{
boolean status;
rdpSettings* settings = rdp->settings;
transport_set_blocking_mode(rdp->transport, true);
@ -581,38 +582,35 @@ boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s)
rdp->nego->selected_protocol = 0;
printf("Requested protocols:");
if ((rdp->nego->requested_protocols & PROTOCOL_TLS))
printf("Client Security: NLA:%d TLS:%d RDP:%d\n",
(rdp->nego->requested_protocols & PROTOCOL_NLA) ? 1 : 0,
(rdp->nego->requested_protocols & PROTOCOL_TLS) ? 1 : 0,
(rdp->nego->requested_protocols == PROTOCOL_RDP) ? 1: 0);
printf("Server Security: NLA:%d TLS:%d RDP:%d\n",
settings->nla_security, settings->tls_security, settings->rdp_security);
if ((settings->nla_security) && (rdp->nego->requested_protocols & PROTOCOL_NLA))
{
printf(" TLS");
if (rdp->settings->tls_security)
{
printf("(Y)");
rdp->nego->selected_protocol |= PROTOCOL_TLS;
}
else
printf("(n)");
rdp->nego->selected_protocol = PROTOCOL_NLA;
}
if ((rdp->nego->requested_protocols & PROTOCOL_NLA))
else if ((settings->tls_security) && (rdp->nego->requested_protocols & PROTOCOL_TLS))
{
printf(" NLA");
if (rdp->settings->nla_security)
{
printf("(Y)");
rdp->nego->selected_protocol |= PROTOCOL_NLA;
}
else
printf("(n)");
rdp->nego->selected_protocol = PROTOCOL_TLS;
}
printf(" RDP");
if (rdp->settings->rdp_security && rdp->nego->selected_protocol == 0)
else if ((settings->rdp_security) && (rdp->nego->selected_protocol == PROTOCOL_RDP))
{
printf("(Y)");
rdp->nego->selected_protocol = PROTOCOL_RDP;
}
else
printf("(n)");
printf("\n");
{
printf("Protocol security negotiation failure\n");
}
printf("Negotiated Security: NLA:%d TLS:%d RDP:%d\n",
(rdp->nego->selected_protocol & PROTOCOL_NLA) ? 1 : 0,
(rdp->nego->selected_protocol & PROTOCOL_TLS) ? 1 : 0,
(rdp->nego->selected_protocol == PROTOCOL_RDP) ? 1: 0);
if (!nego_send_negotiation_response(rdp->nego))
return false;

View File

@ -52,20 +52,26 @@ boolean freerdp_connect(freerdp* instance)
rdp = instance->context->rdp;
extension_pre_connect(rdp->extension);
IFCALLRET(instance->PreConnect, status, instance);
rdp->extension = extension_new(instance);
extension_pre_connect(rdp->extension);
if (status != true)
{
if(!connectErrorCode){
connectErrorCode = PREECONNECTERROR;
}
printf("freerdp_pre_connect failed\n");
fprintf(stderr, "%s:%d: freerdp_pre_connect failed\n", __FILE__, __LINE__);
return false;
}
status = rdp_client_connect(rdp);
// --authonly tests the connection without a UI
if (instance->settings->authentication_only) {
fprintf(stderr, "%s:%d: Authentication only, exit status %d\n", __FILE__, __LINE__, !status);
return status;
}
if (status)
{

View File

@ -543,7 +543,7 @@ boolean gcc_read_client_core_data(STREAM* s, rdpSettings* settings, uint16 block
break;
str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64);
stream_seek(s, 64);
snprintf(settings->client_product_id, sizeof(settings->client_product_id), "%s", str);
snprintf(settings->client_product_id, 32, "%s", str);
xfree(str);
blockLength -= 64;

View File

@ -40,7 +40,7 @@
static boolean freerdp_listener_open(freerdp_listener* instance, const char* bind_address, uint16 port)
{
rdpListener* listener = (rdpListener*)instance->listener;
rdpListener* listener = (rdpListener*) instance->listener;
int status;
int sockfd;
char servname[10];
@ -56,14 +56,20 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bin
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (bind_address == NULL)
hints.ai_flags = AI_PASSIVE;
snprintf(servname, sizeof(servname), "%d", port);
status = getaddrinfo(bind_address, servname, &hints, &res);
if (status != 0)
{
#ifdef _WIN32
_tprintf(_T("getaddrinfo error: %s\n"), gai_strerror(status));
#else
perror("getaddrinfo");
#endif
return false;
}
@ -73,6 +79,7 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bin
continue;
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd == -1)
{
perror("socket");
@ -92,14 +99,21 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bin
#endif
status = bind(sockfd, ai->ai_addr, ai->ai_addrlen);
if (status != 0)
{
#ifdef _WIN32
_tprintf(L"bind() failed with error: %u\n", WSAGetLastError());
WSACleanup();
#else
perror("bind");
close(sockfd);
#endif
continue;
}
status = listen(sockfd, 10);
if (status != 0)
{
perror("listen");
@ -110,9 +124,9 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bin
listener->sockfds[listener->num_sockfds++] = sockfd;
if (ai->ai_family == AF_INET)
sin_addr = &(((struct sockaddr_in*)ai->ai_addr)->sin_addr);
sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr);
else
sin_addr = &(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr);
sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr);
printf("Listening on %s port %s.\n", inet_ntop(ai->ai_family, sin_addr, buf, sizeof(buf)), servname);
}
@ -125,12 +139,13 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bin
static boolean freerdp_listener_open_local(freerdp_listener* instance, const char* path)
{
#ifndef _WIN32
rdpListener* listener = (rdpListener*)instance->listener;
int status;
int sockfd;
struct sockaddr_un addr;
rdpListener* listener = (rdpListener*) instance->listener;
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd == -1)
{
perror("socket");
@ -142,7 +157,9 @@ static boolean freerdp_listener_open_local(freerdp_listener* instance, const cha
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, sizeof(addr.sun_path));
unlink(path);
status = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
status = bind(sockfd, (struct sockaddr*) &addr, sizeof(addr));
if (status != 0)
{
perror("bind");
@ -151,6 +168,7 @@ static boolean freerdp_listener_open_local(freerdp_listener* instance, const cha
}
status = listen(sockfd, 10);
if (status != 0)
{
perror("listen");
@ -164,7 +182,7 @@ static boolean freerdp_listener_open_local(freerdp_listener* instance, const cha
return true;
#else
return false;
return true;
#endif
}
@ -172,19 +190,20 @@ static void freerdp_listener_close(freerdp_listener* instance)
{
int i;
rdpListener* listener = (rdpListener*)instance->listener;
rdpListener* listener = (rdpListener*) instance->listener;
for (i = 0; i < listener->num_sockfds; i++)
{
close(listener->sockfds[i]);
}
listener->num_sockfds = 0;
}
static boolean freerdp_listener_get_fds(freerdp_listener* instance, void** rfds, int* rcount)
{
rdpListener* listener = (rdpListener*)instance->listener;
int i;
rdpListener* listener = (rdpListener*) instance->listener;
if (listener->num_sockfds < 1)
return false;

View File

@ -297,15 +297,24 @@ boolean nego_recv(rdpTransport* transport, STREAM* s, void* extra)
DEBUG_NEGO("selected_protocol: %d", nego->selected_protocol);
/* enhanced security selected ? */
if (nego->selected_protocol) {
if (nego->selected_protocol == PROTOCOL_NLA &&
!nego->enabled_protocols[PROTOCOL_NLA])
if (nego->selected_protocol)
{
if ((nego->selected_protocol == PROTOCOL_NLA) &&
(!nego->enabled_protocols[PROTOCOL_NLA]))
{
nego->state = NEGO_STATE_FAIL;
if (nego->selected_protocol == PROTOCOL_TLS &&
!nego->enabled_protocols[PROTOCOL_TLS])
}
if ((nego->selected_protocol == PROTOCOL_TLS) &&
(!nego->enabled_protocols[PROTOCOL_TLS]))
{
nego->state = NEGO_STATE_FAIL;
} else if (!nego->enabled_protocols[PROTOCOL_RDP])
}
}
else if (!nego->enabled_protocols[PROTOCOL_RDP])
{
nego->state = NEGO_STATE_FAIL;
}
break;
case TYPE_RDP_NEG_FAILURE:
@ -316,6 +325,7 @@ boolean nego_recv(rdpTransport* transport, STREAM* s, void* extra)
else
{
DEBUG_NEGO("no rdpNegData");
if (!nego->enabled_protocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_FAIL;
else
@ -368,6 +378,7 @@ boolean nego_read_request(rdpNego* nego, STREAM* s)
/* rdpNegData (optional) */
stream_read_uint8(s, type); /* Type */
if (type != TYPE_RDP_NEG_REQ)
{
printf("Incorrect negotiation request type %d\n", type);
@ -470,6 +481,8 @@ void nego_process_negotiation_request(rdpNego* nego, STREAM* s)
stream_read_uint16(s, length);
stream_read_uint32(s, nego->requested_protocols);
DEBUG_NEGO("requested_protocols: %d", nego->requested_protocols);
nego->state = NEGO_STATE_FINAL;
}
@ -543,12 +556,13 @@ void nego_process_negotiation_failure(rdpNego* nego, STREAM* s)
boolean nego_send_negotiation_response(rdpNego* nego)
{
STREAM* s;
rdpSettings* settings;
uint8* bm;
uint8* em;
int length;
uint8 *bm, *em;
boolean ret;
boolean status;
rdpSettings* settings;
ret = true;
status = true;
settings = nego->transport->settings;
s = transport_send_stream_init(nego->transport, 256);
@ -577,7 +591,7 @@ boolean nego_send_negotiation_response(rdpNego* nego)
printf("nego_send_negotiation_response: client supports only Standard RDP Security\n");
stream_write_uint32(s, SSL_REQUIRED_BY_SERVER);
length += 8;
ret = false;
status = false;
}
stream_get_mark(s, em);
@ -589,7 +603,7 @@ boolean nego_send_negotiation_response(rdpNego* nego)
if (transport_write(nego->transport, s) < 0)
return false;
if (ret)
if (status)
{
/* update settings with negotiated protocol security */
settings->requested_protocols = nego->requested_protocols;
@ -600,12 +614,14 @@ boolean nego_send_negotiation_response(rdpNego* nego)
settings->tls_security = false;
settings->nla_security = false;
settings->rdp_security = true;
if (!settings->local)
{
settings->encryption = true;
settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
}
if (settings->encryption && settings->server_key == NULL && settings->rdp_key_file == NULL)
return false;
}
@ -629,7 +645,7 @@ boolean nego_send_negotiation_response(rdpNego* nego)
}
}
return ret;
return status;
}
/**

View File

@ -116,6 +116,8 @@ static boolean peer_recv_data_pdu(freerdp_peer* client, STREAM* s)
return false;
}
client->activated = true;
break;
case DATA_PDU_TYPE_SHUTDOWN_REQUEST:
@ -392,6 +394,7 @@ void freerdp_peer_free(freerdp_peer* client)
if (client)
{
rdp_free(client->context->rdp);
xfree(client->context);
xfree(client);
}
}

View File

@ -912,9 +912,10 @@ rdpRdp* rdp_new(freerdp* instance)
{
rdp->instance = instance;
rdp->settings = settings_new((void*) instance);
if (instance != NULL)
instance->settings = rdp->settings;
rdp->extension = extension_new(instance);
rdp->transport = transport_new(rdp->settings);
rdp->license = license_new(rdp);
rdp->input = input_new(rdp);

View File

@ -38,7 +38,7 @@ boolean ntlm_client_init(rdpNtlm* ntlm, boolean confidentiality, char* user, cha
ntlm->confidentiality = confidentiality;
#ifdef NATIVE_SSPI
#ifdef WITH_NATIVE_SSPI
{
HMODULE hSSPI;
INIT_SECURITY_INTERFACE InitSecurityInterface;

View File

@ -29,8 +29,53 @@
#include <freerdp/settings.h>
#include <freerdp/utils/file.h>
#include <winpr/registry.h>
static const char client_dll[] = "C:\\Windows\\System32\\mstscax.dll";
void settings_load_hkey_local_machine(rdpSettings* settings)
{
HKEY hKey;
LONG status;
DWORD dwType;
DWORD dwSize;
DWORD dwValue;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Client"), 0, KEY_READ, &hKey);
if (status != ERROR_SUCCESS)
return;
if (RegQueryValueEx(hKey, _T("DesktopWidth"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
settings->width = dwValue;
if (RegQueryValueEx(hKey, _T("DesktopHeight"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
settings->height = dwValue;
if (RegQueryValueEx(hKey, _T("KeyboardType"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
settings->kbd_type = dwValue;
if (RegQueryValueEx(hKey, _T("KeyboardSubType"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
settings->kbd_subtype = dwValue;
if (RegQueryValueEx(hKey, _T("KeyboardFunctionKeys"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
settings->kbd_fn_keys = dwValue;
if (RegQueryValueEx(hKey, _T("KeyboardLayout"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
settings->kbd_layout = dwValue;
if (RegQueryValueEx(hKey, _T("NlaSecurity"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
settings->nla_security = dwValue ? 1 : 0;
if (RegQueryValueEx(hKey, _T("TlsSecurity"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
settings->tls_security = dwValue ? 1 : 0;
if (RegQueryValueEx(hKey, _T("RdpSecurity"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
settings->rdp_security = dwValue ? 1 : 0;
RegCloseKey(hKey);
}
rdpSettings* settings_new(void* instance)
{
rdpSettings* settings;
@ -73,6 +118,8 @@ rdpSettings* settings_new(void* instance)
settings->encryption_level = ENCRYPTION_LEVEL_NONE;
settings->authentication = true;
settings->authentication_only = false;
settings->from_stdin = false;
settings->received_caps = xzalloc(32);
settings->order_support = xzalloc(32);
@ -186,6 +233,8 @@ rdpSettings* settings_new(void* instance)
settings->server_certificate = xnew(rdpBlob);
freerdp_detect_paths(settings);
settings_load_hkey_local_machine(settings);
}
return settings;

View File

@ -189,8 +189,14 @@ boolean tcp_set_blocking_mode(rdpTcp* tcp, boolean blocking)
else
fcntl(tcp->sockfd, F_SETFL, flags | O_NONBLOCK);
#else
int status;
u_long arg = blocking;
ioctlsocket(tcp->sockfd, FIONBIO, &arg);
status = ioctlsocket(tcp->sockfd, FIONBIO, &arg);
if (status != NO_ERROR)
printf("ioctlsocket() failed with error: %ld\n", status);
tcp->wsa_event = WSACreateEvent();
WSAEventSelect(tcp->sockfd, tcp->wsa_event, FD_READ);
#endif

View File

@ -526,6 +526,7 @@ void transport_free(rdpTransport* transport)
tls_free(transport->tls);
tcp_free(transport->tcp);
tcp_free(transport->tcp_in);
tsg_free(transport->tsg);
xfree(transport);

View File

@ -129,6 +129,68 @@ int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificat
return match;
}
void certificate_data_replace(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data)
{
FILE* fp;
int length;
char* data;
char* pline;
long int size;
fp = certificate_store->fp;
if (!fp)
return;
// Read the current contents of the file.
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
if (size < 1)
return;
data = (char*) xmalloc(size + 2);
if (fread(data, size, 1, fp) != 1)
{
xfree(data);
return;
}
// Write the file back out, with appropriate fingerprint substitutions
fp = fopen(certificate_store->file, "w+");
data[size] = '\n';
data[size + 1] = '\0';
pline = strtok(data, "\n"); // xxx: use strsep
while (pline != NULL)
{
length = strlen(pline);
if (length > 0)
{
char* hostname = pline, *fingerprint;
length = strcspn(pline, " \t");
hostname[length] = '\0';
/* If this is the replaced hostname, use the updated fingerprint. */
if (strcmp(hostname, certificate_data->hostname) == 0)
fingerprint = certificate_data->fingerprint;
else
fingerprint = &hostname[length + 1];
fprintf(fp, "%s %s\n", hostname, fingerprint);
}
pline = strtok(NULL, "\n");
}
fclose(fp);
xfree(data);
}
void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data)
{
FILE* fp;

View File

@ -69,7 +69,8 @@ void crypto_rc4(CryptoRc4 rc4, uint32 length, const uint8* in_data, uint8* out_d
void crypto_rc4_free(CryptoRc4 rc4)
{
xfree(rc4);
if (rc4)
xfree(rc4);
}
CryptoDes3 crypto_des3_encrypt_init(const uint8* key, const uint8* ivec)
@ -315,7 +316,7 @@ char* crypto_cert_fingerprint(X509* xcert)
for (i = 0; i < (int) (fp_len - 1); i++)
{
sprintf(p, "%02x:", fp[i]);
p = &fp_buffer[i * 3];
p = &fp_buffer[(i + 1) * 3];
}
sprintf(p, "%02x", fp[i]);

View File

@ -19,6 +19,16 @@
#include <freerdp/crypto/der.h>
int _der_skip_length(int length)
{
if (length > 0x7F && length <= 0xFF)
return 2;
else if (length > 0xFF)
return 3;
else
return 1;
}
int der_write_length(STREAM* s, int length)
{
if (length > 0x7F && length <= 0xFF)
@ -40,114 +50,52 @@ int der_write_length(STREAM* s, int length)
}
}
boolean der_write_general_string(STREAM* s, char* str)
int der_get_content_length(int length)
{
STREAM* tmp_s;
tmp_s = stream_new(0);
stream_attach(tmp_s, (uint8*)str, strlen(str));
der_write_universal_tag(s, ER_TAG_GENERAL_STRING, false);
der_write_length(s, strlen(str));
stream_copy(s, tmp_s, strlen(str));
stream_detach(tmp_s);
stream_free(tmp_s) ;
return true;
if (length > 0x7F && length <= 0xFF)
return length - 3;
else if (length > 0xFF)
return length - 4;
else
return length - 2;
}
char* der_read_general_string(STREAM* s, int *length)
int der_skip_contextual_tag(int length)
{
char* str;
int len;
if(der_read_universal_tag(s, ER_TAG_GENERAL_STRING, false))
{
der_read_length(s, &len);
str = (char*)xzalloc((len + 1) * sizeof(char));
memcpy(str, s->p, len);
stream_seek(s, len);
*length = len + 2;
return str;
}
stream_rewind(s, 1);
*length = 0;
return NULL;
return _der_skip_length(length) + 1;
}
int der_write_principal_name(STREAM* s, uint8 ntype, char** name)
int der_write_contextual_tag(STREAM* s, uint8 tag, int length, boolean pc)
{
uint8 len;
char** p;
len = 0;
p = name;
while (*p != NULL)
{
len += strlen(*p) + 2;
p++;
}
p = name;
der_write_sequence_tag(s, len+9);
der_write_contextual_tag(s, 0, 3, true);
der_write_integer(s, ntype);
der_write_contextual_tag(s, 1, len + 2, true);
der_write_sequence_tag(s, len);
while (*p != NULL)
{
der_write_general_string(s, *p);
p++;
}
return len + 11;
stream_write_uint8(s, (ER_CLASS_CTXT | ER_PC(pc)) | (ER_TAG_MASK & tag));
return der_write_length(s, length) + 1;
}
int der_write_generalized_time(STREAM* s, char* tstr)
void der_write_universal_tag(STREAM* s, uint8 tag, boolean pc)
{
uint8 len;
STREAM* tmp_s;
len = strlen(tstr);
tmp_s = stream_new(0);
stream_attach(tmp_s, (uint8*) tstr, strlen(tstr));
der_write_universal_tag(s, ER_TAG_GENERALIZED_TIME, false);
der_write_length(s, len);
stream_copy(s, tmp_s, len);
stream_detach(tmp_s);
stream_free(tmp_s) ;
return len + 2;
stream_write_uint8(s, (ER_CLASS_UNIV | ER_PC(pc)) | (ER_TAG_MASK & tag));
}
boolean der_read_generalized_time(STREAM* s, char** tstr)
int der_skip_octet_string(int length)
{
int length;
uint8* bm;
stream_get_mark(s, bm);
if (!der_read_universal_tag(s, ER_TAG_GENERALIZED_TIME, false))
goto err;
der_read_length(s, &length);
if (length != 15)
goto err;
*tstr = xzalloc(length + 1);
stream_read(s, *tstr, length);
return true;
err:
stream_set_mark(s, bm);
return false;
return 1 + _der_skip_length(length) + length;
}
void der_write_octet_string(STREAM* s, uint8* oct_str, int length)
{
der_write_universal_tag(s, ER_TAG_OCTET_STRING, false);
der_write_length(s, length);
stream_write(s, oct_str, length);
}
int der_skip_sequence_tag(int length)
{
return 1 + _der_skip_length(length);
}
int der_write_sequence_tag(STREAM* s, int length)
{
stream_write_uint8(s, (ER_CLASS_UNIV | ER_CONSTRUCT) | (ER_TAG_MASK & ER_TAG_SEQUENCE));
return der_write_length(s, length) + 1;
}

View File

@ -76,12 +76,20 @@
#define WITH_DEBUG_CREDSSP
#endif
#ifdef WITH_NATIVE_SSPI
#define NLA_PKG_NAME NEGOSSP_NAME
#else
#define NLA_PKG_NAME NTLMSP_NAME
#endif
#define TERMSRV_SPN_PREFIX "TERMSRV/"
void credssp_send(rdpCredssp* credssp);
int credssp_recv(rdpCredssp* credssp);
void credssp_buffer_print(rdpCredssp* credssp);
void credssp_buffer_free(rdpCredssp* credssp);
SECURITY_STATUS credssp_verify_public_key_echo(rdpCredssp* credssp);
void credssp_encode_ts_credentials(rdpCredssp* credssp);
SECURITY_STATUS credssp_encrypt_public_key_echo(rdpCredssp* credssp);
SECURITY_STATUS credssp_decrypt_public_key_echo(rdpCredssp* credssp);
SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp);
SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp);
@ -92,8 +100,12 @@ SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp);
int credssp_ntlm_client_init(rdpCredssp* credssp)
{
char* spn;
int length;
freerdp* instance;
rdpSettings* settings = credssp->settings;
rdpSettings* settings;
settings = credssp->settings;
instance = (freerdp*) settings->instance;
if ((settings->password == NULL) || (settings->username == NULL))
@ -112,6 +124,20 @@ int credssp_ntlm_client_init(rdpCredssp* credssp)
sspi_SecBufferAlloc(&credssp->PublicKey, credssp->tls->public_key.length);
CopyMemory(credssp->PublicKey.pvBuffer, credssp->tls->public_key.data, credssp->tls->public_key.length);
length = sizeof(TERMSRV_SPN_PREFIX) + strlen(settings->hostname);
spn = (SEC_CHAR*) malloc(length + 1);
sprintf(spn, "%s%s", TERMSRV_SPN_PREFIX, settings->hostname);
#ifdef UNICODE
credssp->ServicePrincipalName = (LPTSTR) malloc(length * 2 + 2);
MultiByteToWideChar(CP_ACP, 0, spn, length,
(LPWSTR) credssp->ServicePrincipalName, length);
free(spn);
#else
credssp->ServicePrincipalName = spn;
#endif
return 1;
}
@ -126,8 +152,6 @@ int credssp_ntlm_server_init(rdpCredssp* credssp)
rdpSettings* settings = credssp->settings;
instance = (freerdp*) settings->instance;
sspi_SetAuthIdentity(&(credssp->identity), "username", NULL, NULL);
sspi_SecBufferAlloc(&credssp->PublicKey, credssp->tls->public_key.length);
CopyMemory(credssp->PublicKey.pvBuffer, credssp->tls->public_key.data, credssp->tls->public_key.length);
@ -157,7 +181,7 @@ int credssp_client_authenticate(rdpCredssp* credssp)
if (credssp_ntlm_client_init(credssp) == 0)
return 0;
#ifdef NATIVE_SSPI
#ifdef WITH_NATIVE_SSPI
{
HMODULE hSSPI;
INIT_SECURITY_INTERFACE InitSecurityInterface;
@ -176,7 +200,7 @@ int credssp_client_authenticate(rdpCredssp* credssp)
credssp->table = InitSecurityInterface();
#endif
status = credssp->table->QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo);
status = credssp->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &pPackageInfo);
if (status != SEC_E_OK)
{
@ -186,7 +210,7 @@ int credssp_client_authenticate(rdpCredssp* credssp)
cbMaxToken = pPackageInfo->cbMaxToken;
status = credssp->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME,
status = credssp->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME,
SECPKG_CRED_OUTBOUND, NULL, &credssp->identity, NULL, NULL, &credentials, &expiration);
if (status != SEC_E_OK)
@ -198,12 +222,19 @@ int credssp_client_authenticate(rdpCredssp* credssp)
have_context = false;
have_input_buffer = false;
have_pub_key_auth = false;
memset(&input_buffer, 0, sizeof(SecBuffer));
memset(&output_buffer, 0, sizeof(SecBuffer));
memset(&credssp->ContextSizes, 0, sizeof(SecPkgContext_Sizes));
ZeroMemory(&input_buffer, sizeof(SecBuffer));
ZeroMemory(&output_buffer, sizeof(SecBuffer));
ZeroMemory(&credssp->ContextSizes, sizeof(SecPkgContext_Sizes));
fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |
ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE;
/*
* from tspkg.dll: 0x00000132
* ISC_REQ_MUTUAL_AUTH
* ISC_REQ_CONFIDENTIALITY
* ISC_REQ_USE_SESSION_KEY
* ISC_REQ_ALLOCATE_MEMORY
*/
fContextReq = ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY;
while (true)
{
@ -216,8 +247,8 @@ int credssp_client_authenticate(rdpCredssp* credssp)
status = credssp->table->InitializeSecurityContext(&credentials,
(have_context) ? &credssp->context : NULL,
NULL, fContextReq, 0, SECURITY_NETWORK_DREP,
(have_input_buffer) ? &input_buffer_desc : NULL,
credssp->ServicePrincipalName, fContextReq, 0,
SECURITY_NATIVE_DREP, (have_input_buffer) ? &input_buffer_desc : NULL,
0, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration);
if (input_buffer.pvBuffer != NULL)
@ -239,52 +270,7 @@ int credssp_client_authenticate(rdpCredssp* credssp)
return 0;
}
if (have_pub_key_auth)
{
BYTE* p;
SecBuffer Buffers[2];
SecBufferDesc Message;
SECURITY_STATUS encrypt_status;
Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */
Buffers[0].cbBuffer = credssp->ContextSizes.cbMaxSignature;
Buffers[0].pvBuffer = xzalloc(Buffers[0].cbBuffer);
Buffers[1].cbBuffer = credssp->PublicKey.cbBuffer;
Buffers[1].pvBuffer = malloc(Buffers[1].cbBuffer);
CopyMemory(Buffers[1].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[1].cbBuffer);
Message.cBuffers = 2;
Message.ulVersion = SECBUFFER_VERSION;
Message.pBuffers = (PSecBuffer) &Buffers;
sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer);
encrypt_status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, 0);
if (encrypt_status != SEC_E_OK)
{
printf("EncryptMessage status: 0x%08X\n", encrypt_status);
return 0;
}
#ifdef WITH_DEBUG_CREDSSP
printf("CredSSP.Signature: (%d)\n", (int) Buffers[0].cbBuffer);
winpr_HexDump((BYTE*) Buffers[0].pvBuffer, Buffers[0].cbBuffer);
printf("CredSSP.PublicKey: (%d)\n", (int) credssp->PublicKey.cbBuffer);
winpr_HexDump((BYTE*) credssp->PublicKey.pvBuffer, credssp->PublicKey.cbBuffer);
printf("CredSSP.PublicKey (encrypted) (%d):\n", (int) Buffers[1].cbBuffer);
winpr_HexDump((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer);
#endif
p = (BYTE*) credssp->pubKeyAuth.pvBuffer;
CopyMemory(p, Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Message Signature */
CopyMemory(&p[Buffers[0].cbBuffer], Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Encrypted Public Key */
free(Buffers[0].pvBuffer);
free(Buffers[1].pvBuffer);
}
credssp_encrypt_public_key_echo(credssp);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
@ -324,7 +310,7 @@ int credssp_client_authenticate(rdpCredssp* credssp)
return -1;
#ifdef WITH_DEBUG_CREDSSP
printf("Receiving Authentication Token\n");
printf("Receiving Authentication Token (%d)\n", (int) credssp->negoToken.cbBuffer);
winpr_HexDump(credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer);
#endif
@ -342,11 +328,14 @@ int credssp_client_authenticate(rdpCredssp* credssp)
/* Verify Server Public Key Echo */
status = credssp_verify_public_key_echo(credssp);
status = credssp_decrypt_public_key_echo(credssp);
credssp_buffer_free(credssp);
if (status != SEC_E_OK)
return 0;
{
printf("Could not verify public key echo!\n");
return -1;
}
/* Send encrypted credentials */
@ -398,7 +387,7 @@ int credssp_server_authenticate(rdpCredssp* credssp)
if (credssp_ntlm_server_init(credssp) == 0)
return 0;
#ifdef NATIVE_SSPI
#ifdef WITH_NATIVE_SSPI
{
HMODULE hSSPI;
INIT_SECURITY_INTERFACE InitSecurityInterface;
@ -417,7 +406,7 @@ int credssp_server_authenticate(rdpCredssp* credssp)
credssp->table = InitSecurityInterface();
#endif
status = credssp->table->QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo);
status = credssp->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &pPackageInfo);
if (status != SEC_E_OK)
{
@ -427,8 +416,8 @@ int credssp_server_authenticate(rdpCredssp* credssp)
cbMaxToken = pPackageInfo->cbMaxToken;
status = credssp->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME,
SECPKG_CRED_INBOUND, NULL, &credssp->identity, NULL, NULL, &credentials, &expiration);
status = credssp->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME,
SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &credentials, &expiration);
if (status != SEC_E_OK)
{
@ -439,12 +428,29 @@ int credssp_server_authenticate(rdpCredssp* credssp)
have_context = false;
have_input_buffer = false;
have_pub_key_auth = false;
memset(&input_buffer, 0, sizeof(SecBuffer));
memset(&output_buffer, 0, sizeof(SecBuffer));
memset(&credssp->ContextSizes, 0, sizeof(SecPkgContext_Sizes));
ZeroMemory(&input_buffer, sizeof(SecBuffer));
ZeroMemory(&output_buffer, sizeof(SecBuffer));
ZeroMemory(&credssp->ContextSizes, sizeof(SecPkgContext_Sizes));
fContextReq = ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT |
ASC_REQ_CONFIDENTIALITY | ASC_REQ_DELEGATE;
/*
* from tspkg.dll: 0x00000112
* ASC_REQ_MUTUAL_AUTH
* ASC_REQ_CONFIDENTIALITY
* ASC_REQ_ALLOCATE_MEMORY
*/
fContextReq = 0;
fContextReq |= ASC_REQ_MUTUAL_AUTH;
fContextReq |= ASC_REQ_CONFIDENTIALITY;
fContextReq |= ASC_REQ_CONNECTION;
fContextReq |= ASC_REQ_USE_SESSION_KEY;
fContextReq |= ASC_REQ_CONFIDENTIALITY;
fContextReq |= ASC_REQ_REPLAY_DETECT;
fContextReq |= ASC_REQ_SEQUENCE_DETECT;
fContextReq |= ASC_REQ_EXTENDED_ERROR;
while (true)
{
@ -472,6 +478,12 @@ int credssp_server_authenticate(rdpCredssp* credssp)
p_buffer->pvBuffer = credssp->negoToken.pvBuffer;
p_buffer->cbBuffer = credssp->negoToken.cbBuffer;
if (credssp->negoToken.cbBuffer < 1)
{
printf("CredSSP: invalid negoToken!\n");
return -1;
}
output_buffer_desc.ulVersion = SECBUFFER_VERSION;
output_buffer_desc.cBuffers = 1;
output_buffer_desc.pBuffers = &output_buffer;
@ -481,7 +493,7 @@ int credssp_server_authenticate(rdpCredssp* credssp)
status = credssp->table->AcceptSecurityContext(&credentials,
have_context? &credssp->context: NULL,
&input_buffer_desc, fContextReq, SECURITY_NETWORK_DREP, &credssp->context,
&input_buffer_desc, fContextReq, SECURITY_NATIVE_DREP, &credssp->context,
&output_buffer_desc, &pfContextAttr, &expiration);
if (input_buffer.pvBuffer != NULL)
@ -507,43 +519,17 @@ int credssp_server_authenticate(rdpCredssp* credssp)
return 0;
}
credssp_verify_public_key_echo(credssp);
if (credssp_decrypt_public_key_echo(credssp) != SEC_E_OK)
{
printf("Error: could not verify client's public key echo\n");
return -1;
}
sspi_SecBufferFree(&credssp->negoToken);
credssp->negoToken.pvBuffer = NULL;
credssp->negoToken.cbBuffer = 0;
if (have_pub_key_auth)
{
BYTE* p;
SecBuffer Buffers[2];
SecBufferDesc Message;
Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */
Buffers[1].BufferType = SECBUFFER_TOKEN; /* Signature */
Buffers[0].cbBuffer = credssp->PublicKey.cbBuffer;
Buffers[0].pvBuffer = malloc(Buffers[0].cbBuffer);
CopyMemory(Buffers[0].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[0].cbBuffer);
Buffers[1].cbBuffer = credssp->ContextSizes.cbMaxSignature;
Buffers[1].pvBuffer = xzalloc(Buffers[1].cbBuffer);
Message.cBuffers = 2;
Message.ulVersion = SECBUFFER_VERSION;
Message.pBuffers = (PSecBuffer) &Buffers;
p = (BYTE*) Buffers[0].pvBuffer;
p[0]++; /* Public Key +1 */
sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer);
credssp->table->EncryptMessage(&credssp->context, 0, &Message, 0);
p = (BYTE*) credssp->pubKeyAuth.pvBuffer;
CopyMemory(p, Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Message Signature */
CopyMemory(&p[Buffers[1].cbBuffer], Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Encrypted Public Key */
}
credssp_encrypt_public_key_echo(credssp);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
@ -551,6 +537,12 @@ int credssp_server_authenticate(rdpCredssp* credssp)
status = SEC_I_CONTINUE_NEEDED;
}
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED))
{
printf("AcceptSecurityContext status: 0x%08X\n", status);
return -1;
}
/* send authentication token */
#ifdef WITH_DEBUG_CREDSSP
@ -617,38 +609,124 @@ int credssp_authenticate(rdpCredssp* credssp)
return credssp_client_authenticate(credssp);
}
SECURITY_STATUS credssp_verify_public_key_echo(rdpCredssp* credssp)
void ap_integer_increment_le(BYTE* number, int size)
{
int index;
for (index = 0; index < size; index++)
{
if (number[index] < 0xFF)
{
number[index]++;
break;
}
else
{
number[index] = 0;
continue;
}
}
}
void ap_integer_decrement_le(BYTE* number, int size)
{
int index;
for (index = 0; index < size; index++)
{
if (number[index] > 0)
{
number[index]--;
break;
}
else
{
number[index] = 0xFF;
continue;
}
}
}
SECURITY_STATUS credssp_encrypt_public_key_echo(rdpCredssp* credssp)
{
SecBuffer Buffers[2];
SecBufferDesc Message;
SECURITY_STATUS status;
int public_key_length;
public_key_length = credssp->PublicKey.cbBuffer;
Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */
sspi_SecBufferAlloc(&credssp->pubKeyAuth, credssp->ContextSizes.cbMaxSignature + public_key_length);
Buffers[0].cbBuffer = credssp->ContextSizes.cbMaxSignature;
Buffers[0].pvBuffer = credssp->pubKeyAuth.pvBuffer;
Buffers[1].cbBuffer = public_key_length;
Buffers[1].pvBuffer = ((BYTE*) credssp->pubKeyAuth.pvBuffer) + credssp->ContextSizes.cbMaxSignature;
CopyMemory(Buffers[1].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[1].cbBuffer);
if (credssp->server)
{
/* server echos the public key +1 */
ap_integer_increment_le((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer);
}
Message.cBuffers = 2;
Message.ulVersion = SECBUFFER_VERSION;
Message.pBuffers = (PSecBuffer) &Buffers;
status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, credssp->send_seq_num++);
if (status != SEC_E_OK)
{
printf("EncryptMessage status: 0x%08X\n", status);
return status;
}
return status;
}
SECURITY_STATUS credssp_decrypt_public_key_echo(rdpCredssp* credssp)
{
int length;
BYTE* buffer;
ULONG pfQOP;
BYTE* public_key1;
BYTE* public_key2;
BYTE* pub_key_auth;
int public_key_length;
SecBuffer Buffers[2];
SecBufferDesc Message;
SECURITY_STATUS status;
if (credssp->PublicKey.cbBuffer + credssp->ContextSizes.cbMaxSignature != credssp->pubKeyAuth.cbBuffer)
{
printf("unexpected pubKeyAuth buffer size:%d\n", (int) credssp->pubKeyAuth.cbBuffer);
return SEC_E_INVALID_TOKEN;
}
length = credssp->pubKeyAuth.cbBuffer;
pub_key_auth = (BYTE*) credssp->pubKeyAuth.pvBuffer;
buffer = (BYTE*) malloc(length);
CopyMemory(buffer, credssp->pubKeyAuth.pvBuffer, length);
public_key_length = credssp->PublicKey.cbBuffer;
Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */
Buffers[0].cbBuffer = credssp->ContextSizes.cbMaxSignature;
Buffers[0].pvBuffer = malloc(Buffers[0].cbBuffer);
CopyMemory(Buffers[0].pvBuffer, pub_key_auth, Buffers[0].cbBuffer);
Buffers[0].pvBuffer = buffer;
Buffers[1].cbBuffer = length - Buffers[0].cbBuffer;
Buffers[1].pvBuffer = malloc(Buffers[1].cbBuffer);
CopyMemory(Buffers[1].pvBuffer, &pub_key_auth[Buffers[0].cbBuffer], Buffers[1].cbBuffer);
Buffers[1].cbBuffer = length - credssp->ContextSizes.cbMaxSignature;
Buffers[1].pvBuffer = buffer + credssp->ContextSizes.cbMaxSignature;
Message.cBuffers = 2;
Message.ulVersion = SECBUFFER_VERSION;
Message.pBuffers = (PSecBuffer) &Buffers;
status = credssp->table->DecryptMessage(&credssp->context, &Message, 0, &pfQOP);
status = credssp->table->DecryptMessage(&credssp->context, &Message, credssp->recv_seq_num++, &pfQOP);
if (status != SEC_E_OK)
{
@ -660,7 +738,10 @@ SECURITY_STATUS credssp_verify_public_key_echo(rdpCredssp* credssp)
public_key2 = (BYTE*) Buffers[1].pvBuffer;
if (!credssp->server)
public_key2[0]--; /* server echos the public key +1 */
{
/* server echos the public key +1 */
ap_integer_decrement_le(public_key2, public_key_length);
}
if (memcmp(public_key1, public_key2, public_key_length) != 0)
{
@ -675,10 +756,7 @@ SECURITY_STATUS credssp_verify_public_key_echo(rdpCredssp* credssp)
return SEC_E_MESSAGE_ALTERED; /* DO NOT SEND CREDENTIALS! */
}
public_key2[0]++;
free(Buffers[0].pvBuffer);
free(Buffers[1].pvBuffer);
free(buffer);
return SEC_E_OK;
}
@ -688,15 +766,15 @@ int credssp_skip_ts_password_creds(rdpCredssp* credssp)
int length;
int ts_password_creds_length = 0;
length = ber_skip_octet_string(credssp->identity.DomainLength);
length = ber_skip_octet_string(credssp->identity.DomainLength * 2);
length += ber_skip_contextual_tag(length);
ts_password_creds_length += length;
length = ber_skip_octet_string(credssp->identity.UserLength);
length = ber_skip_octet_string(credssp->identity.UserLength * 2);
length += ber_skip_contextual_tag(length);
ts_password_creds_length += length;
length = ber_skip_octet_string(credssp->identity.PasswordLength);
length = ber_skip_octet_string(credssp->identity.PasswordLength * 2);
length += ber_skip_contextual_tag(length);
ts_password_creds_length += length;
@ -719,6 +797,7 @@ void credssp_read_ts_password_creds(rdpCredssp* credssp, STREAM* s)
credssp->identity.Domain = (UINT16*) malloc(length);
CopyMemory(credssp->identity.Domain, s->p, credssp->identity.DomainLength);
stream_seek(s, credssp->identity.DomainLength);
credssp->identity.DomainLength /= 2;
/* [1] userName (OCTET STRING) */
ber_read_contextual_tag(s, 1, &length, true);
@ -727,6 +806,7 @@ void credssp_read_ts_password_creds(rdpCredssp* credssp, STREAM* s)
credssp->identity.User = (UINT16*) malloc(length);
CopyMemory(credssp->identity.User, s->p, credssp->identity.UserLength);
stream_seek(s, credssp->identity.UserLength);
credssp->identity.UserLength /= 2;
/* [2] password (OCTET STRING) */
ber_read_contextual_tag(s, 2, &length, true);
@ -735,6 +815,7 @@ void credssp_read_ts_password_creds(rdpCredssp* credssp, STREAM* s)
credssp->identity.Password = (UINT16*) malloc(length);
CopyMemory(credssp->identity.Password, s->p, credssp->identity.PasswordLength);
stream_seek(s, credssp->identity.PasswordLength);
credssp->identity.PasswordLength /= 2;
}
void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s)
@ -748,16 +829,16 @@ void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s)
ber_write_sequence_tag(s, length);
/* [0] domainName (OCTET STRING) */
ber_write_contextual_tag(s, 0, credssp->identity.DomainLength + 2, true);
ber_write_octet_string(s, (BYTE*) credssp->identity.Domain, credssp->identity.DomainLength);
ber_write_contextual_tag(s, 0, credssp->identity.DomainLength * 2 + 2, true);
ber_write_octet_string(s, (BYTE*) credssp->identity.Domain, credssp->identity.DomainLength * 2);
/* [1] userName (OCTET STRING) */
ber_write_contextual_tag(s, 1, credssp->identity.UserLength + 2, true);
ber_write_octet_string(s, (BYTE*) credssp->identity.User, credssp->identity.UserLength);
ber_write_contextual_tag(s, 1, credssp->identity.UserLength * 2 + 2, true);
ber_write_octet_string(s, (BYTE*) credssp->identity.User, credssp->identity.UserLength * 2);
/* [2] password (OCTET STRING) */
ber_write_contextual_tag(s, 2, credssp->identity.PasswordLength + 2, true);
ber_write_octet_string(s, (BYTE*) credssp->identity.Password, credssp->identity.PasswordLength);
ber_write_contextual_tag(s, 2, credssp->identity.PasswordLength * 2 + 2, true);
ber_write_octet_string(s, (BYTE*) credssp->identity.Password, credssp->identity.PasswordLength * 2);
}
int credssp_skip_ts_credentials(rdpCredssp* credssp)
@ -852,7 +933,6 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp)
SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp)
{
BYTE* p;
SecBuffer Buffers[2];
SecBufferDesc Message;
SECURITY_STATUS status;
@ -862,37 +942,33 @@ SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp)
Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
Buffers[0].cbBuffer = 16;
Buffers[0].pvBuffer = xzalloc(Buffers[0].cbBuffer);
sspi_SecBufferAlloc(&credssp->authInfo, credssp->ContextSizes.cbMaxSignature + credssp->ts_credentials.cbBuffer);
Buffers[0].cbBuffer = credssp->ContextSizes.cbMaxSignature;
Buffers[0].pvBuffer = credssp->authInfo.pvBuffer;
ZeroMemory(Buffers[0].pvBuffer, Buffers[0].cbBuffer);
Buffers[1].cbBuffer = credssp->ts_credentials.cbBuffer;
Buffers[1].pvBuffer = malloc(Buffers[1].cbBuffer);
Buffers[1].pvBuffer = &((BYTE*) credssp->authInfo.pvBuffer)[Buffers[0].cbBuffer];
CopyMemory(Buffers[1].pvBuffer, credssp->ts_credentials.pvBuffer, Buffers[1].cbBuffer);
Message.cBuffers = 2;
Message.ulVersion = SECBUFFER_VERSION;
Message.pBuffers = (PSecBuffer) &Buffers;
sspi_SecBufferAlloc(&credssp->authInfo, Buffers[0].cbBuffer + Buffers[1].cbBuffer);
status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, 1);
status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, credssp->send_seq_num++);
if (status != SEC_E_OK)
return status;
p = (BYTE*) credssp->authInfo.pvBuffer;
CopyMemory(p, Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Message Signature */
CopyMemory(&p[Buffers[0].cbBuffer], Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Encrypted TSCredentials */
free(Buffers[0].pvBuffer);
free(Buffers[1].pvBuffer);
return SEC_E_OK;
}
SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp)
{
BYTE* p;
int length;
BYTE* buffer;
ULONG pfQOP;
SecBuffer Buffers[2];
SecBufferDesc Message;
SECURITY_STATUS status;
@ -900,47 +976,51 @@ SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp)
Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
Buffers[0].cbBuffer = 16;
Buffers[0].pvBuffer = malloc(Buffers[0].cbBuffer);
CopyMemory(Buffers[0].pvBuffer, credssp->authInfo.pvBuffer, Buffers[0].cbBuffer);
if (credssp->authInfo.cbBuffer < 1)
{
printf("credssp_decrypt_ts_credentials missing authInfo buffer\n");
return SEC_E_INVALID_TOKEN;
}
Buffers[1].cbBuffer = credssp->authInfo.cbBuffer - Buffers[0].cbBuffer;
Buffers[1].pvBuffer = malloc(Buffers[1].cbBuffer);
p = (BYTE*) credssp->authInfo.pvBuffer;
CopyMemory(Buffers[1].pvBuffer, &p[Buffers[0].cbBuffer], Buffers[1].cbBuffer);
length = credssp->authInfo.cbBuffer;
buffer = (BYTE*) malloc(length);
CopyMemory(buffer, credssp->authInfo.pvBuffer, length);
Buffers[0].cbBuffer = credssp->ContextSizes.cbMaxSignature;
Buffers[0].pvBuffer = buffer;
Buffers[1].cbBuffer = length - credssp->ContextSizes.cbMaxSignature;
Buffers[1].pvBuffer = &buffer[credssp->ContextSizes.cbMaxSignature];
Message.cBuffers = 2;
Message.ulVersion = SECBUFFER_VERSION;
Message.pBuffers = (PSecBuffer) &Buffers;
sspi_SecBufferAlloc(&credssp->authInfo, Buffers[0].cbBuffer + Buffers[1].cbBuffer);
status = credssp->table->DecryptMessage(&credssp->context, &Message, 1, 0);
status = credssp->table->DecryptMessage(&credssp->context, &Message, credssp->recv_seq_num++, &pfQOP);
if (status != SEC_E_OK)
return status;
credssp_read_ts_credentials(credssp, &Buffers[1]);
free(Buffers[0].pvBuffer);
free(Buffers[1].pvBuffer);
free(buffer);
return SEC_E_OK;
}
int credssp_skip_nego_token(int length)
{
length = ber_skip_octet_string(length);
length += ber_skip_contextual_tag(length);
length = der_skip_octet_string(length);
length += der_skip_contextual_tag(length);
return length;
}
int credssp_skip_nego_tokens(int length)
{
length = credssp_skip_nego_token(length);
length += ber_skip_sequence_tag(length);
length += ber_skip_sequence_tag(length);
length += ber_skip_contextual_tag(length);
length += der_skip_sequence_tag(length);
length += der_skip_sequence_tag(length);
length += der_skip_contextual_tag(length);
return length;
}
@ -962,7 +1042,7 @@ int credssp_skip_ts_request(int length)
{
length += ber_skip_integer(2);
length += ber_skip_contextual_tag(3);
length += ber_skip_sequence_tag(length);
length += der_skip_sequence_tag(length);
return length;
}
@ -990,20 +1070,22 @@ void credssp_send(rdpCredssp* credssp)
s = stream_new(ts_request_length);
/* TSRequest */
length = ber_get_content_length(ts_request_length);
ber_write_sequence_tag(s, length); /* SEQUENCE */
ber_write_contextual_tag(s, 0, 3, true); /* [0] version */
length = der_get_content_length(ts_request_length);
der_write_sequence_tag(s, length); /* SEQUENCE */
/* [0] version */
ber_write_contextual_tag(s, 0, 3, true);
ber_write_integer(s, 2); /* INTEGER */
/* [1] negoTokens (NegoData) */
if (nego_tokens_length > 0)
{
length = ber_get_content_length(nego_tokens_length);
length -= ber_write_contextual_tag(s, 1, length, true); /* NegoData */
length -= ber_write_sequence_tag(s, length); /* SEQUENCE OF NegoDataItem */
length -= ber_write_sequence_tag(s, length); /* NegoDataItem */
length -= ber_write_contextual_tag(s, 0, length, true); /* [0] negoToken */
ber_write_octet_string(s, credssp->negoToken.pvBuffer, length); /* OCTET STRING */
length = der_get_content_length(nego_tokens_length);
length -= der_write_contextual_tag(s, 1, length, true); /* NegoData */
length -= der_write_sequence_tag(s, length); /* SEQUENCE OF NegoDataItem */
length -= der_write_sequence_tag(s, length); /* NegoDataItem */
length -= der_write_contextual_tag(s, 0, length, true); /* [0] negoToken */
der_write_octet_string(s, (uint8*) credssp->negoToken.pvBuffer, length); /* OCTET STRING */
}
/* [2] authInfo (OCTET STRING) */
@ -1022,6 +1104,9 @@ void credssp_send(rdpCredssp* credssp)
ber_write_octet_string(s, credssp->pubKeyAuth.pvBuffer, length);
}
//printf("Sending TSRequest: (%d)\n", stream_get_length(s));
//freerdp_hexdump(s->data, stream_get_length(s));
tls_write(credssp->tls, s->data, stream_get_length(s));
stream_free(s);
}
@ -1039,15 +1124,21 @@ int credssp_recv(rdpCredssp* credssp)
int status;
UINT32 version;
s = stream_new(2048);
status = tls_read(credssp->tls, s->data, stream_get_left(s));
s = stream_new(4096);
status = tls_read_all(credssp->tls, s->p, stream_get_left(s));
s->size = status;
if (status < 0)
{
stream_free(s) ;
printf("credssp_recv() error: %d\n", status);
stream_free(s);
return -1;
}
//printf("Receiving TSRequest: (%d)\n", s->size);
//freerdp_hexdump(s->data, s->size);
/* TSRequest */
ber_read_sequence_tag(s, &length);
ber_read_contextual_tag(s, 0, &length, true);
@ -1136,9 +1227,9 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTls* tls, rdpSettings* settings)
credssp->tls = tls;
credssp->send_seq_num = 0;
credssp->recv_seq_num = 0;
memset(&credssp->negoToken, 0, sizeof(SecBuffer));
memset(&credssp->pubKeyAuth, 0, sizeof(SecBuffer));
memset(&credssp->authInfo, 0, sizeof(SecBuffer));
ZeroMemory(&credssp->negoToken, sizeof(SecBuffer));
ZeroMemory(&credssp->pubKeyAuth, sizeof(SecBuffer));
ZeroMemory(&credssp->authInfo, sizeof(SecBuffer));
}
return credssp;

View File

@ -53,10 +53,10 @@ static void tls_free_certificate(CryptoCert cert)
xfree(cert);
}
boolean tls_connect(rdpTls* tls)
{
CryptoCert cert;
long options = 0;
int connection_status;
tls->ctx = SSL_CTX_new(TLSv1_client_method());
@ -67,15 +67,36 @@ boolean tls_connect(rdpTls* tls)
return false;
}
/*
* This is necessary, because the Microsoft TLS implementation is not perfect.
* SSL_OP_ALL enables a couple of workarounds for buggy TLS implementations,
* but the most important workaround being SSL_OP_TLS_BLOCK_PADDING_BUG.
* As the size of the encrypted payload may give hints about its contents,
* block padding is normally used, but the Microsoft TLS implementation
* won't recognize it and will disconnect you after sending a TLS alert.
/**
* SSL_OP_NO_COMPRESSION:
*
* The Microsoft RDP server does not advertise support
* for TLS compression, but alternative servers may support it.
* This was observed between early versions of the FreeRDP server
* and the FreeRDP client, and caused major performance issues,
* which is why we're disabling it.
*/
SSL_CTX_set_options(tls->ctx, SSL_OP_ALL);
#ifdef SSL_OP_NO_COMPRESSION
options |= SSL_OP_NO_COMPRESSION;
#endif
/**
* SSL_OP_TLS_BLOCK_PADDING_BUG:
*
* The Microsoft RDP server does *not* support TLS padding.
* It absolutely needs to be disabled otherwise it won't work.
*/
options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
/**
* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
*
* Just like TLS padding, the Microsoft RDP server does not
* support empty fragments. This needs to be disabled.
*/
options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
SSL_CTX_set_options(tls->ctx, options);
tls->ssl = SSL_new(tls->ctx);
@ -116,7 +137,8 @@ boolean tls_connect(rdpTls* tls)
return false;
}
if (!tls_verify_certificate(tls, cert, tls->settings->hostname)) {
if (!tls_verify_certificate(tls, cert, tls->settings->hostname))
{
printf("tls_connect: certificate not trusted, aborting.\n");
tls_disconnect(tls);
tls_free_certificate(cert);
@ -131,6 +153,7 @@ boolean tls_connect(rdpTls* tls)
boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file)
{
CryptoCert cert;
long options = 0;
int connection_status;
tls->ctx = SSL_CTX_new(SSLv23_server_method());
@ -142,10 +165,43 @@ boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_fi
}
/*
* SSL_OP_NO_SSLv2:
*
* We only want SSLv3 and TLSv1, so disable SSLv2.
* SSLv3 is used by, eg. Microsoft RDC for Mac OS X.
*/
SSL_CTX_set_options(tls->ctx, SSL_OP_NO_SSLv2);
options |= SSL_OP_NO_SSLv2;
/**
* SSL_OP_NO_COMPRESSION:
*
* The Microsoft RDP server does not advertise support
* for TLS compression, but alternative servers may support it.
* This was observed between early versions of the FreeRDP server
* and the FreeRDP client, and caused major performance issues,
* which is why we're disabling it.
*/
#ifdef SSL_OP_NO_COMPRESSION
options |= SSL_OP_NO_COMPRESSION;
#endif
/**
* SSL_OP_TLS_BLOCK_PADDING_BUG:
*
* The Microsoft RDP server does *not* support TLS padding.
* It absolutely needs to be disabled otherwise it won't work.
*/
options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
/**
* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
*
* Just like TLS padding, the Microsoft RDP server does not
* support empty fragments. This needs to be disabled.
*/
options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
SSL_CTX_set_options(tls->ctx, options);
if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0)
{
@ -182,18 +238,37 @@ boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_fi
return false;
}
xfree(cert);
if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
{
printf("SSL_set_fd failed\n");
return false;
}
connection_status = SSL_accept(tls->ssl);
if (connection_status <= 0)
while (1)
{
if (tls_print_error("SSL_accept", tls->ssl, connection_status))
return false;
connection_status = SSL_accept(tls->ssl);
if (connection_status <= 0)
{
switch (SSL_get_error(tls->ssl, connection_status))
{
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
break;
default:
if (tls_print_error("SSL_accept", tls->ssl, connection_status))
return false;
break;
}
}
else
{
break;
}
}
printf("TLS connection accepted\n");
@ -232,6 +307,19 @@ int tls_read(rdpTls* tls, uint8* data, int length)
return status;
}
int tls_read_all(rdpTls* tls, uint8* data, int length)
{
int status;
do
{
status = tls_read(tls, data, length);
}
while (status == 0);
return status;
}
int tls_write(rdpTls* tls, uint8* data, int length)
{
int status;
@ -298,11 +386,11 @@ boolean tls_print_error(char* func, SSL* connection, int value)
return true;
case SSL_ERROR_WANT_READ:
printf("SSL_ERROR_WANT_READ\n");
printf("%s: SSL_ERROR_WANT_READ\n", func);
return false;
case SSL_ERROR_WANT_WRITE:
printf("SSL_ERROR_WANT_WRITE\n");
printf("%s: SSL_ERROR_WANT_WRITE\n", func);
return false;
case SSL_ERROR_SYSCALL:
@ -385,7 +473,7 @@ boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
if (common_name)
{
xfree(common_name);
common_name=NULL ;
common_name = NULL;
}
verification_status = true; /* success! */
@ -402,6 +490,7 @@ boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
char* issuer;
char* subject;
char* fingerprint;
freerdp* instance = (freerdp*) tls->settings->instance;
boolean accept_certificate = false;
issuer = crypto_cert_issuer(cert->px509);
@ -414,9 +503,6 @@ boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
if (match == 1)
{
/* no entry was found in known_hosts file, prompt user for manual verification */
freerdp* instance = (freerdp*) tls->settings->instance;
if (!hostname_match)
tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count);
@ -426,7 +512,7 @@ boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
if (!accept_certificate)
{
/* user did not accept, abort and do not add entry in known_hosts file */
verification_status = false; /* failure! */
verification_status = false; /* failure! */
}
else
{
@ -437,9 +523,23 @@ boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
}
else if (match == -1)
{
/* entry was found in known_hosts file, but fingerprint does not match */
/* entry was found in known_hosts file, but fingerprint does not match. ask user to use it */
tls_print_certificate_error(hostname, fingerprint);
verification_status = false; /* failure! */
if (instance->VerifyChangedCertificate)
accept_certificate = instance->VerifyChangedCertificate(instance, subject, issuer, fingerprint, "");
if (!accept_certificate)
{
/* user did not accept, abort and do not change known_hosts file */
verification_status = false; /* failure! */
}
else
{
/* user accepted new certificate, add replace fingerprint for this host in known_hosts file */
certificate_data_replace(tls->certificate_store, certificate_data);
verification_status = true; /* success! */
}
}
else if (match == 0)
{
@ -451,20 +551,6 @@ boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
xfree(fingerprint);
}
#ifndef _WIN32
if (common_name)
xfree(common_name);
if (alt_names)
{
for (index = 0; index < alt_names_count; index++)
xfree(alt_names[index]);
xfree(alt_names);
xfree(alt_names_lengths) ;
}
#endif
if (certificate_data)
{
xfree(certificate_data->fingerprint);

View File

@ -27,6 +27,30 @@
#include <freerdp/utils/memory.h>
#include <freerdp/utils/args.h>
void freerdp_parse_hostname(rdpSettings* settings, char* hostname) {
char* p;
if (hostname[0] == '[' && (p = strchr(hostname, ']'))
&& (p[1] == 0 || (p[1] == ':' && !strchr(p + 2, ':')))) {
/* Either "[...]" or "[...]:..." with at most one : after the brackets */
settings->hostname = xstrdup(hostname + 1);
if ((p = strchr((char*)settings->hostname, ']'))) {
*p = 0;
if (p[1] == ':')
settings->port = atoi(p + 2);
}
} else {
/* Port number is cut off and used if exactly one : in the string */
settings->hostname = xstrdup(hostname);
if ((p = strchr((char*)settings->hostname, ':')) && !strchr(p + 1, ':')) {
*p = 0;
settings->port = atoi(p + 1);
}
}
}
/**
* Parse command-line arguments and update rdpSettings members accordingly.
* @param settings pointer to rdpSettings struct to be updated.
@ -81,6 +105,8 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
" --app: RemoteApp connection. This implies -g workarea\n"
" --ext: load an extension\n"
" --no-auth: disable authentication\n"
" --authonly: authentication only, no UI\n"
" --from-stdin: unspecified username, password, domain and hostname params are prompted\n"
" --no-fastpath: disable fast-path\n"
" --no-motion: don't send mouse motion events\n"
" --gdi: graphics rendering (hw, sw)\n"
@ -306,6 +332,14 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
{
settings->authentication = false;
}
else if (strcmp("--authonly", argv[index]) == 0)
{
settings->authentication_only = true;
}
else if (strcmp("--from-stdin", argv[index]) == 0)
{
settings->from_stdin = true;
}
else if (strcmp("--ignore-certificate", argv[index]) == 0)
{
settings->ignore_certificate = true;
@ -671,28 +705,8 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
}
else if (argv[index][0] != '-')
{
if (argv[index][0] == '[' && (p = strchr(argv[index], ']'))
&& (p[1] == 0 || (p[1] == ':' && !strchr(p + 2, ':'))))
{
/* Either "[...]" or "[...]:..." with at most one : after the brackets */
settings->hostname = xstrdup(argv[index] + 1);
if ((p = strchr((char*)settings->hostname, ']')))
{
*p = 0;
if (p[1] == ':')
settings->port = atoi(p + 2);
}
}
else
{
/* Port number is cut off and used if exactly one : in the string */
settings->hostname = xstrdup(argv[index]);
if ((p = strchr((char*)settings->hostname, ':')) && !strchr(p + 1, ':'))
{
*p = 0;
settings->port = atoi(p + 1);
}
}
freerdp_parse_hostname(settings, argv[index]);
/* server is the last argument for the current session. arguments
followed will be parsed for the next session. */
index++;
@ -715,7 +729,8 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
if (settings->disable_theming)
settings->performance_flags |= PERF_DISABLE_THEMING;
return index;
break; /* post process missing arguments */
}
else
{
@ -733,6 +748,49 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
}
index++;
}
printf("missing server name\n");
return FREERDP_ARGS_PARSE_FAILURE;
/* --from-stdin will prompt for missing arguments only.
You can prompt for username, password, domain and hostname to avoid disclosing
these settings to ps. */
if (settings->from_stdin) {
/* username */
if (NULL == settings->username) {
char input[512];
printf("username: ");
scanf("%511s", input);
settings->username = xstrdup(input);
}
/* password */
if (NULL == settings->password) {
char input[512];
printf("password: ");
scanf("%511s", input);
settings->password = xstrdup(input);
}
/* domain */
if (NULL == settings->domain) {
char input[512];
printf("domain (control-D to skip): ");
scanf("%511s", input);
settings->domain = xstrdup(input);
}
/* hostname */
if (NULL == settings->hostname) {
char input[512];
printf("hostname: ");
scanf("%511s", input);
freerdp_parse_hostname(settings, input);
}
}
/* Must have a hostname. Do you? */
if (NULL == settings->hostname) {
printf("missing server name\n");
return FREERDP_ARGS_PARSE_FAILURE;
} else {
return index;
}
}

View File

@ -46,6 +46,21 @@
#endif
#define MAX_STATIC_PLUGINS 50
struct static_plugin
{
const char* name;
const char* entry_name;
void* entry_addr;
};
typedef struct static_plugin staticPlugin;
static staticPlugin g_static_plugins[MAX_STATIC_PLUGINS];
static int g_static_plugins_count;
/**
* UNUSED
* This function opens a handle on the specified library in order to load symbols from it.
@ -185,6 +200,10 @@ void* freerdp_load_plugin(const char* name, const char* entry_name)
void* entry;
char* suffixed_name;
/* first attempt to load a static plugin */
entry = freerdp_load_static_plugin(name, entry_name);
if (entry != NULL) return entry;
suffixed_name = freerdp_append_shared_library_suffix((char*) name);
if (!freerdp_path_contains_separator(suffixed_name))
@ -276,3 +295,58 @@ void* freerdp_load_channel_plugin(rdpSettings* settings, const char* name, const
return entry;
}
/**
* This function is used to register a static plugin so that it can be loaded later on using freerdp_load_plugin.
*
* @param name [IN] - name of the library to load
* @param entry_name [IN] - name of the symbol to register for later loading
* @param entry [IN] - function pointer to the entry function
*
* @return true on success, otherwise false.
*/
boolean freerdp_register_static_plugin(const char* name, const char* entry_name, void* entry_addr)
{
staticPlugin* plugin;
if (g_static_plugins_count >= MAX_STATIC_PLUGINS)
{
printf("freerdp_register_static_plugin: cannot register %s/%s", name, entry_name);
return false;
}
/* add the static plugin to the vector */
plugin = &g_static_plugins[g_static_plugins_count++];
plugin->name = name;
plugin->entry_name = entry_name;
plugin->entry_addr = entry_addr;
return true;
}
/**
* This is a helper function, used by freerdp_load_plugin to return a function pointer from the static plugin table
*
* @param name [IN] - name of the library to load
* @param entry_name [IN] - name of the symbol to register for later loading
*
* @return Pointer to the entry function, NULL if no matching plugin could be found
*/
void* freerdp_load_static_plugin(const char* name, const char* entry_name)
{
staticPlugin* plugin;
int i;
for (i = 0; i < g_static_plugins_count; i++)
{
plugin = &g_static_plugins[i];
if (!strcmp(plugin->name, name) && !strcmp(plugin->entry_name, entry_name))
{
return plugin->entry_addr;
}
}
return NULL;
}

View File

@ -20,7 +20,7 @@
#include <errno.h>
#include <freerdp/utils/passphrase.h>
#ifdef _WIN32
char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz, int from_stdin)
{
errno=ENOSYS;
return NULL;
@ -34,7 +34,7 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
#include <unistd.h>
#include <freerdp/utils/signal.h>
char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz, int from_stdin)
{
char read_char;
char* buf_iter;
@ -50,7 +50,7 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz)
}
ctermid(term_name);
if(strcmp(term_name, "") == 0
if(from_stdin || strcmp(term_name, "") == 0
|| (term_file = open(term_name, O_RDWR)) == -1)
{
write_file = STDERR_FILENO;

View File

@ -23,13 +23,13 @@
#include <freerdp/utils/rail.h>
#include <freerdp/rail.h>
void rail_unicode_string_alloc(UNICODE_STRING* unicode_string, uint16 cbString)
void rail_unicode_string_alloc(RAIL_UNICODE_STRING* unicode_string, uint16 cbString)
{
unicode_string->length = cbString;
unicode_string->string = xzalloc(cbString);
}
void rail_unicode_string_free(UNICODE_STRING* unicode_string)
void rail_unicode_string_free(RAIL_UNICODE_STRING* unicode_string)
{
unicode_string->length = 0;
@ -37,7 +37,7 @@ void rail_unicode_string_free(UNICODE_STRING* unicode_string)
xfree(unicode_string->string);
}
void rail_read_unicode_string(STREAM* s, UNICODE_STRING* unicode_string)
void rail_read_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string)
{
stream_read_uint16(s, unicode_string->length); /* cbString (2 bytes) */
@ -49,14 +49,14 @@ void rail_read_unicode_string(STREAM* s, UNICODE_STRING* unicode_string)
stream_read(s, unicode_string->string, unicode_string->length);
}
void rail_write_unicode_string(STREAM* s, UNICODE_STRING* unicode_string)
void rail_write_unicode_string(STREAM* s, RAIL_UNICODE_STRING* unicode_string)
{
stream_check_size(s, 2 + unicode_string->length);
stream_write_uint16(s, unicode_string->length); /* cbString (2 bytes) */
stream_write(s, unicode_string->string, unicode_string->length); /* string */
}
void rail_write_unicode_string_value(STREAM* s, UNICODE_STRING* unicode_string)
void rail_write_unicode_string_value(STREAM* s, RAIL_UNICODE_STRING* unicode_string)
{
if (unicode_string->length > 0)
{

View File

@ -32,4 +32,6 @@ if(NOT WIN32)
# Build Server Channels library
add_subdirectory(channels)
else()
add_subdirectory(Windows)
endif()

View File

@ -0,0 +1,26 @@
# FreeRDP: A Remote Desktop Protocol Client
# FreeRDP Windows Server 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.
add_executable(wfreerdp-server
wfreerdp.c)
target_link_libraries(wfreerdp-server freerdp-core)
target_link_libraries(wfreerdp-server freerdp-utils)
target_link_libraries(wfreerdp-server freerdp-codec)
target_link_libraries(wfreerdp-server freerdp-channels)

17
server/Windows/server.crt Normal file
View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICyzCCAbOgAwIBAgIJANbqtAWwlQZuMA0GCSqGSIb3DQEBBQUAMBIxEDAOBgNV
BAMTB0ZyZWVSRFAwHhcNMDkxMDI5MDA0MTQ5WhcNMDkxMTI4MDA0MTQ5WjASMRAw
DgYDVQQDEwdGcmVlUkRQMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
q7mxFgRbS2FYJZX7BzpNd4T/n4nEVDBY6YaObLjGpaB1TptzXTcmfDrDslTGwcEY
hTFAC4ZvY6yOURExqbph4LSgvkoa6J722RjVPfshGa4mlh2SXvTiaV26VPPxddGb
o6fbs2u029lbtBlpIVbhx5RN9vstNkll26oSZ6wfEdBNHQJLd2SU4ItWHj8zjz1f
eGxjgChHihUlwcBYKDJsKFkzHZmLrMgB37KsGlXi/WV+eEsjgvz4yP7I3TL8+GsN
MjV8fRGVEKTbKSmgunO67d5u+IaqUQb0Ad1ha1jzDQ+a6hdymrulJSIhoOVfKkwi
ptTe43FgwxVRIygJP9HjHQIDAQABoyQwIjATBgNVHSUEDDAKBggrBgEFBQcDATAL
BgNVHQ8EBAMCBDAwDQYJKoZIhvcNAQEFBQADggEBAIOdEDhOX2kbl02znltd9hCr
nV4kRPKm979RKwBNkrEuwYSlcsjAHg5MZ5itH3wFOUo2s5pjt7/vMOAg+6rOBbIa
nqr22/gKBtOmuaJLG1yjxDC2vfez7f3B26pKgxa/krM8oxiFdT9n8QbdxdkN7/D9
3RLU/aCfgrMzXxRus7eq3kR00jnSs6ggnAfE1E9gric3vFgr1wCzdcriRXmXDfUb
hRq+4VG+ZWk16TwCofV5GVU39XWCv5HNO2swAdjkNXgI5e3tQbV3wWLZLqqYzBco
iWulAXtoCGmE81+u1Ms7hLLzpXitLZSGPu1r+sDdkKPLCmOvkAaljDQ4nBz7fIA=
-----END CERTIFICATE-----

27
server/Windows/server.key Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAq7mxFgRbS2FYJZX7BzpNd4T/n4nEVDBY6YaObLjGpaB1Tptz
XTcmfDrDslTGwcEYhTFAC4ZvY6yOURExqbph4LSgvkoa6J722RjVPfshGa4mlh2S
XvTiaV26VPPxddGbo6fbs2u029lbtBlpIVbhx5RN9vstNkll26oSZ6wfEdBNHQJL
d2SU4ItWHj8zjz1feGxjgChHihUlwcBYKDJsKFkzHZmLrMgB37KsGlXi/WV+eEsj
gvz4yP7I3TL8+GsNMjV8fRGVEKTbKSmgunO67d5u+IaqUQb0Ad1ha1jzDQ+a6hdy
mrulJSIhoOVfKkwiptTe43FgwxVRIygJP9HjHQIDAQABAoIBAAVv5K54xtc1JtBR
1lfdPbSqDlnjx8aOnVIPg5TnqMp3sR8jBt0NsPc/+RA9ZOmfjoIxFAEJaZ9zSDJC
5BqmnxC5R1mfCQkSd2haQ+4pdFvWyrv4Bblh8YU6hXrJGn0LfO0KlIcywtAvKpsi
LtTyZkWmaW2HeF/+pO32jYygw38R1wd8Tl6GwjOXwTF6lFACJXOT4YAzcfp3FKSB
AiKBIGuMzozoSND7KPFNRrhGhNumJpdS5A8Fb8D2c/ZMv6Cq5IbwOgTfKun+Bz+s
mFbnzeb1uWRqQbsVXOBBW/zHfuG3SU5qeZsaAyuu4DTy+LE1oAHF9uhBSHuT5C6i
vCJ8A8ECgYEA1iaOmiEJYBrs25iAc4SjCKqhY0mwR3wtu3I06vmgUoML5fhPMv36
SvYQIqDyNw3p7TE6mZtw9+G+kK3PqhuJhogwSwg0a6o51RdKnhXH3/68oNWtKCLC
1AmR8q/Gd3FwAR3b49CuOIZ9uOiJrc/ejzKdFEJTDR1/TX1frWfZznECgYEAzUiz
XxFf7YrGel7JgmfRD2eZRYngOoteFlg5Tee42UjeAY2Pt2aiDLk+2TqQEdI9+Xg7
LcFdBqcSNd8bh33xSzgNthIkX+lTDzx0SmKGfyxfFBJcY8nzsLvvnNt3YeuMeaJQ
CPszwoZ0jcD46jTCjbrKhaLyEWmUkDp1O71NTW0CgYAXKF49Xpsz8FVyvcAOPeaf
dkwzf3F3mX8ciRId4taqdY9g1AREgGCDoK5IAF2RBIkqZCtxFvUVaS0BWjpdq9Ko
YKvQQVfh2KueVoF0LOjLWTGutsydzXyCD3Lf6pAstHCnPkJcFWHxrOGFkGfrCtKH
a7K+0RlIDsuIZqllCBjukQKBgA31+MTpYJW+D1t5IMkumEgs6n6RLt+sZLyuSU9k
B+03CGogn3qAj1rAKmcJlYywuKhDpfqpoNL3/8QMJUokpYlRCZWtTC39pzltCheY
9b6mXNz3lrLupBUL4vLO9iKBq28GO90wgEelbz3ItuTuq6CJ6IYIG+BVRtY8M4bZ
i+1NAoGANXZjYnJYDnh8Je9SDxDSc5byzK7ddkQoId64RCIfNHqNKH63P81vjgnH
YBIPtagY75ZVVNxujCF7m8Rety+d8tEFwfQKDin2EVI7PD2rOJra385/izp7HuBR
vqxvLzG9Xv3cNOU2l7PttVw4Pa2i5E37atKi3V3Zp2kMW+KaKPQ=
-----END RSA PRIVATE KEY-----

288
server/Windows/wfreerdp.c Normal file
View File

@ -0,0 +1,288 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Windows Server
*
* Copyright 2012 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <winpr/windows.h>
#include <freerdp/constants.h>
#include <freerdp/utils/sleep.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/thread.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/codec/nsc.h>
#include <freerdp/listener.h>
HANDLE g_done_event;
int g_thread_count = 0;
struct wf_peer_context
{
rdpContext _p;
boolean activated;
};
typedef struct wf_peer_context wfPeerContext;
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context)
{
}
void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context)
{
if (context)
{
}
}
static void wf_peer_init(freerdp_peer* client)
{
client->context_size = sizeof(wfPeerContext);
client->ContextNew = (psPeerContextNew) wf_peer_context_new;
client->ContextFree = (psPeerContextFree) wf_peer_context_free;
freerdp_peer_context_new(client);
}
boolean wf_peer_post_connect(freerdp_peer* client)
{
wfPeerContext* context = (wfPeerContext*) client->context;
/**
* This callback is called when the entire connection sequence is done, i.e. we've received the
* Font List PDU from the client and sent out the Font Map PDU.
* The server may start sending graphics output and receiving keyboard/mouse input after this
* callback returns.
*/
printf("Client %s is activated (osMajorType %d osMinorType %d)", client->local ? "(local)" : client->hostname,
client->settings->os_major_type, client->settings->os_minor_type);
if (client->settings->autologon)
{
printf(" and wants to login automatically as %s\\%s",
client->settings->domain ? client->settings->domain : "",
client->settings->username);
/* A real server may perform OS login here if NLA is not executed previously. */
}
printf("\n");
printf("Client requested desktop: %dx%dx%d\n",
client->settings->width, client->settings->height, client->settings->color_depth);
/* A real server should tag the peer as activated here and start sending updates in main loop. */
/* Return false here would stop the execution of the peer mainloop. */
return true;
}
boolean wf_peer_activate(freerdp_peer* client)
{
wfPeerContext* context = (wfPeerContext*) client->context;
context->activated = true;
return true;
}
void wf_peer_synchronize_event(rdpInput* input, uint32 flags)
{
printf("Client sent a synchronize event (flags:0x%X)\n", flags);
}
void wf_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
{
freerdp_peer* client = input->context->peer;
rdpUpdate* update = client->update;
wfPeerContext* context = (wfPeerContext*) input->context;
printf("Client sent a keyboard event (flags:0x%X code:0x%X)\n", flags, code);
if ((flags & 0x4000) && code == 0x1F) /* 's' key */
{
if (client->settings->width != 800)
{
client->settings->width = 800;
client->settings->height = 600;
}
else
{
client->settings->width = 640;
client->settings->height = 480;
}
update->DesktopResize(update->context);
context->activated = false;
}
else if ((flags & 0x4000) && code == 0x2D) /* 'x' key */
{
client->Close(client);
}
}
void wf_peer_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
{
printf("Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code);
}
void wf_peer_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
{
printf("Client sent a mouse event (flags:0x%X pos:%d,%d)\n", flags, x, y);
}
void wf_peer_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
{
printf("Client sent an extended mouse event (flags:0x%X pos:%d,%d)\n", flags, x, y);
}
static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
{
int rcount;
void* rfds[32];
wfPeerContext* context;
freerdp_peer* client = (freerdp_peer*) lpParam;
memset(rfds, 0, sizeof(rfds));
wf_peer_init(client);
/* Initialize the real server settings here */
client->settings->cert_file = xstrdup("server.crt");
client->settings->privatekey_file = xstrdup("server.key");
client->settings->nla_security = true;
client->settings->tls_security = false;
client->settings->rdp_security = false;
client->PostConnect = wf_peer_post_connect;
client->Activate = wf_peer_activate;
client->input->SynchronizeEvent = wf_peer_synchronize_event;
client->input->KeyboardEvent = wf_peer_keyboard_event;
client->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event;
client->input->MouseEvent = wf_peer_mouse_event;
client->input->ExtendedMouseEvent = wf_peer_extended_mouse_event;
client->Initialize(client);
context = (wfPeerContext*) client->context;
printf("We've got a client %s\n", client->local ? "(local)" : client->hostname);
while (1)
{
rcount = 0;
if (client->GetFileDescriptor(client, rfds, &rcount) != true)
{
printf("Failed to get FreeRDP file descriptor\n");
break;
}
if (client->CheckFileDescriptor(client) != true)
{
printf("Failed to check FreeRDP file descriptor\n");
break;
}
}
printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname);
client->Disconnect(client);
freerdp_peer_context_free(client);
freerdp_peer_free(client);
return 0;
}
static void wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
{
/* start peer main loop thread */
if (CreateThread(NULL, 0, wf_peer_main_loop, client, 0, NULL) != 0)
g_thread_count++;
}
static void wf_server_main_loop(freerdp_listener* instance)
{
int rcount;
void* rfds[32];
memset(rfds, 0, sizeof(rfds));
while (1)
{
rcount = 0;
if (instance->GetFileDescriptor(instance, rfds, &rcount) != true)
{
printf("Failed to get FreeRDP file descriptor\n");
break;
}
if (instance->CheckFileDescriptor(instance) != true)
{
printf("Failed to check FreeRDP file descriptor\n");
break;
}
}
instance->Close(instance);
}
int main(int argc, char* argv[])
{
int port = 3389;
WSADATA wsa_data;
freerdp_listener* instance;
instance = freerdp_listener_new();
instance->PeerAccepted = wf_peer_accepted;
if (WSAStartup(0x101, &wsa_data) != 0)
return 1;
g_done_event = CreateEvent(0, 1, 0, 0);
if (argc == 2)
port = atoi(argv[1]);
/* Open the server socket and start listening. */
if (instance->Open(instance, NULL, port))
{
/* Entering the server main loop. In a real server the listener can be run in its own thread. */
wf_server_main_loop(instance);
}
if (g_thread_count > 0)
WaitForSingleObject(g_done_event, INFINITE);
else
MessageBox(GetConsoleWindow(),
L"Failed to start wfreerdp-server.\n\nPlease check the debug output.",
L"FreeRDP Error", MB_ICONSTOP);
WSACleanup();
freerdp_listener_free(instance);
return 0;
}

View File

@ -273,7 +273,6 @@ void xf_peer_context_free(freerdp_peer* client, xfPeerContext* context)
{
stream_free(context->s);
rfx_context_free(context->rfx_context);
xfree(context);
}
}
@ -634,6 +633,8 @@ void* xf_peer_main_loop(void* arg)
settings->privatekey_file = freerdp_construct_path(server_file_path, "server.key");
settings->nla_security = true;
settings->tls_security = false;
settings->rdp_security = false;
settings->rfx_codec = true;

View File

@ -18,6 +18,7 @@
# limitations under the License.
set(FREERDP_SERVER_CHANNELS_SRCS
audin.c
rdpsnd.c
)

427
server/channels/audin.c Normal file
View File

@ -0,0 +1,427 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* Server Audio Input Virtual Channel
*
* Copyright 2012 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 <freerdp/utils/stream.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/dsp.h>
#include <freerdp/utils/thread.h>
#include <freerdp/utils/wait_obj.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/server/audin.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MSG_SNDIN_VERSION 0x01
#define MSG_SNDIN_FORMATS 0x02
#define MSG_SNDIN_OPEN 0x03
#define MSG_SNDIN_OPEN_REPLY 0x04
#define MSG_SNDIN_DATA_INCOMING 0x05
#define MSG_SNDIN_DATA 0x06
#define MSG_SNDIN_FORMATCHANGE 0x07
typedef struct _audin_server
{
audin_server_context context;
void* audin_channel;
freerdp_thread* audin_channel_thread;
FREERDP_DSP_CONTEXT* dsp_context;
boolean opened;
} audin_server;
static void audin_server_select_format(audin_server_context* context, int client_format_index)
{
audin_server* audin = (audin_server*) context;
if (client_format_index >= context->num_client_formats)
return;
context->selected_client_format = client_format_index;
if (audin->opened)
{
/* TODO: send MSG_SNDIN_FORMATCHANGE */
}
}
static void audin_server_send_version(audin_server* audin, STREAM* s)
{
stream_write_uint8(s, MSG_SNDIN_VERSION);
stream_write_uint32(s, 1); /* Version (4 bytes) */
WTSVirtualChannelWrite(audin->audin_channel, stream_get_head(s), stream_get_length(s), NULL);
}
static boolean audin_server_recv_version(audin_server* audin, STREAM* s, uint32 length)
{
uint32 Version;
if (length < 4)
return false;
stream_read_uint32(s, Version);
if (Version < 1)
return false;
return true;
}
static void audin_server_send_formats(audin_server* audin, STREAM* s)
{
int i;
uint32 nAvgBytesPerSec;
stream_set_pos(s, 0);
stream_write_uint8(s, MSG_SNDIN_FORMATS);
stream_write_uint32(s, audin->context.num_server_formats); /* NumFormats (4 bytes) */
stream_write_uint32(s, 0); /* cbSizeFormatsPacket (4 bytes), client-to-server only */
for (i = 0; i < audin->context.num_server_formats; i++)
{
nAvgBytesPerSec = audin->context.server_formats[i].nSamplesPerSec *
audin->context.server_formats[i].nChannels *
audin->context.server_formats[i].wBitsPerSample / 8;
stream_check_size(s, 18);
stream_write_uint16(s, audin->context.server_formats[i].wFormatTag);
stream_write_uint16(s, audin->context.server_formats[i].nChannels);
stream_write_uint32(s, audin->context.server_formats[i].nSamplesPerSec);
stream_write_uint32(s, nAvgBytesPerSec);
stream_write_uint16(s, audin->context.server_formats[i].nBlockAlign);
stream_write_uint16(s, audin->context.server_formats[i].wBitsPerSample);
stream_write_uint16(s, audin->context.server_formats[i].cbSize);
if (audin->context.server_formats[i].cbSize)
{
stream_check_size(s, audin->context.server_formats[i].cbSize);
stream_write(s, audin->context.server_formats[i].data,
audin->context.server_formats[i].cbSize);
}
}
WTSVirtualChannelWrite(audin->audin_channel, stream_get_head(s), stream_get_length(s), NULL);
}
static boolean audin_server_recv_formats(audin_server* audin, STREAM* s, uint32 length)
{
int i;
if (length < 8)
return false;
stream_read_uint32(s, audin->context.num_client_formats); /* NumFormats (4 bytes) */
stream_seek_uint32(s); /* cbSizeFormatsPacket (4 bytes) */
length -= 8;
if (audin->context.num_client_formats <= 0)
return false;
audin->context.client_formats = xzalloc(audin->context.num_client_formats * sizeof(rdpsndFormat));
for (i = 0; i < audin->context.num_client_formats; i++)
{
if (length < 18)
{
xfree(audin->context.client_formats);
audin->context.client_formats = NULL;
return false;
}
stream_read_uint16(s, audin->context.client_formats[i].wFormatTag);
stream_read_uint16(s, audin->context.client_formats[i].nChannels);
stream_read_uint32(s, audin->context.client_formats[i].nSamplesPerSec);
stream_seek_uint32(s); /* nAvgBytesPerSec */
stream_read_uint16(s, audin->context.client_formats[i].nBlockAlign);
stream_read_uint16(s, audin->context.client_formats[i].wBitsPerSample);
stream_read_uint16(s, audin->context.client_formats[i].cbSize);
if (audin->context.client_formats[i].cbSize > 0)
{
stream_seek(s, audin->context.client_formats[i].cbSize);
}
}
IFCALL(audin->context.Opening, &audin->context);
return true;
}
static void audin_server_send_open(audin_server* audin, STREAM* s)
{
if (audin->context.selected_client_format < 0)
return;
audin->opened = true;
stream_set_pos(s, 0);
stream_write_uint8(s, MSG_SNDIN_OPEN);
stream_write_uint32(s, audin->context.frames_per_packet); /* FramesPerPacket (4 bytes) */
stream_write_uint32(s, audin->context.selected_client_format); /* initialFormat (4 bytes) */
/*
* [MS-RDPEAI] 3.2.5.1.6
* The second format specify the format that SHOULD be used to capture data from
* the actual audio input device.
*/
stream_write_uint16(s, 1); /* wFormatTag = PCM */
stream_write_uint16(s, 2); /* nChannels */
stream_write_uint32(s, 44100); /* nSamplesPerSec */
stream_write_uint32(s, 44100 * 2 * 2); /* nAvgBytesPerSec */
stream_write_uint16(s, 4); /* nBlockAlign */
stream_write_uint16(s, 16); /* wBitsPerSample */
stream_write_uint16(s, 0); /* cbSize */
WTSVirtualChannelWrite(audin->audin_channel, stream_get_head(s), stream_get_length(s), NULL);
}
static boolean audin_server_recv_open_reply(audin_server* audin, STREAM* s, uint32 length)
{
uint32 Result;
if (length < 4)
return false;
stream_read_uint32(s, Result);
IFCALL(audin->context.OpenResult, &audin->context, Result);
return true;
}
static boolean audin_server_recv_data(audin_server* audin, STREAM* s, uint32 length)
{
rdpsndFormat* format;
int sbytes_per_sample;
int sbytes_per_frame;
uint8* src;
int size;
int frames;
if (audin->context.selected_client_format < 0)
return false;
format = &audin->context.client_formats[audin->context.selected_client_format];
if (format->wFormatTag == 2)
{
audin->dsp_context->decode_ms_adpcm(audin->dsp_context,
stream_get_tail(s), length, format->nChannels, format->nBlockAlign);
size = audin->dsp_context->adpcm_size;
src = audin->dsp_context->adpcm_buffer;
sbytes_per_sample = 2;
sbytes_per_frame = format->nChannels * 2;
}
else if (format->wFormatTag == 0x11)
{
audin->dsp_context->decode_ima_adpcm(audin->dsp_context,
stream_get_tail(s), length, format->nChannels, format->nBlockAlign);
size = audin->dsp_context->adpcm_size;
src = audin->dsp_context->adpcm_buffer;
sbytes_per_sample = 2;
sbytes_per_frame = format->nChannels * 2;
}
else
{
size = length;
src = stream_get_tail(s);
sbytes_per_sample = format->wBitsPerSample / 8;
sbytes_per_frame = format->nChannels * sbytes_per_sample;
}
if (format->nSamplesPerSec == audin->context.dst_format.nSamplesPerSec && format->nChannels == audin->context.dst_format.nChannels)
{
frames = size / sbytes_per_frame;
}
else
{
audin->dsp_context->resample(audin->dsp_context, src, sbytes_per_sample,
format->nChannels, format->nSamplesPerSec, size / sbytes_per_frame,
audin->context.dst_format.nChannels, audin->context.dst_format.nSamplesPerSec);
frames = audin->dsp_context->resampled_frames;
src = audin->dsp_context->resampled_buffer;
}
IFCALL(audin->context.ReceiveSamples, &audin->context, src, frames);
return true;
}
static void* audin_server_thread_func(void* arg)
{
void* fd;
STREAM* s;
void* buffer;
uint8 MessageId;
boolean ready = false;
uint32 bytes_returned = 0;
audin_server* audin = (audin_server*) arg;
freerdp_thread* thread = audin->audin_channel_thread;
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == true)
{
fd = *((void**)buffer);
WTSFreeMemory(buffer);
thread->signals[thread->num_signals++] = wait_obj_new_with_fd(fd);
}
/* Wait for the client to confirm that the Audio Input dynamic channel is ready */
while (1)
{
freerdp_thread_wait(thread);
if (freerdp_thread_is_stopped(thread))
break;
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &bytes_returned) == false)
break;
ready = *((boolean*)buffer);
WTSFreeMemory(buffer);
if (ready)
break;
}
s = stream_new(4096);
if (ready)
{
audin_server_send_version(audin, s);
}
while (ready)
{
freerdp_thread_wait(thread);
if (freerdp_thread_is_stopped(thread))
break;
stream_set_pos(s, 0);
if (WTSVirtualChannelRead(audin->audin_channel, 0, stream_get_head(s),
stream_get_size(s), &bytes_returned) == false)
{
if (bytes_returned == 0)
break;
stream_check_size(s, bytes_returned);
if (WTSVirtualChannelRead(audin->audin_channel, 0, stream_get_head(s),
stream_get_size(s), &bytes_returned) == false)
break;
}
if (bytes_returned < 1)
continue;
stream_read_uint8(s, MessageId);
bytes_returned--;
switch (MessageId)
{
case MSG_SNDIN_VERSION:
if (audin_server_recv_version(audin, s, bytes_returned))
audin_server_send_formats(audin, s);
break;
case MSG_SNDIN_FORMATS:
if (audin_server_recv_formats(audin, s, bytes_returned))
audin_server_send_open(audin, s);
break;
case MSG_SNDIN_OPEN_REPLY:
audin_server_recv_open_reply(audin, s, bytes_returned);
break;
case MSG_SNDIN_DATA_INCOMING:
break;
case MSG_SNDIN_DATA:
audin_server_recv_data(audin, s, bytes_returned);
break;
case MSG_SNDIN_FORMATCHANGE:
break;
default:
printf("audin_server_thread_func: unknown MessageId %d\n", MessageId);
break;
}
}
stream_free(s);
WTSVirtualChannelClose(audin->audin_channel);
audin->audin_channel = NULL;
freerdp_thread_quit(thread);
return NULL;
}
static boolean audin_server_open(audin_server_context* context)
{
audin_server* audin = (audin_server*) context;
if (audin->audin_channel_thread == NULL)
{
audin->audin_channel = WTSVirtualChannelOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
if (audin->audin_channel == NULL)
return false;
audin->audin_channel_thread = freerdp_thread_new();
freerdp_thread_start(audin->audin_channel_thread, audin_server_thread_func, audin);
return true;
}
return false;
}
static boolean audin_server_close(audin_server_context* context)
{
audin_server* audin = (audin_server*) context;
if (audin->audin_channel_thread)
{
freerdp_thread_stop(audin->audin_channel_thread);
freerdp_thread_free(audin->audin_channel_thread);
audin->audin_channel_thread = NULL;
}
if (audin->audin_channel)
{
WTSVirtualChannelClose(audin->audin_channel);
audin->audin_channel = NULL;
}
audin->context.selected_client_format = -1;
return true;
}
audin_server_context* audin_server_context_new(WTSVirtualChannelManager* vcm)
{
audin_server* audin;
audin = xnew(audin_server);
audin->context.vcm = vcm;
audin->context.selected_client_format = -1;
audin->context.frames_per_packet = 4096;
audin->context.SelectFormat = audin_server_select_format;
audin->context.Open = audin_server_open;
audin->context.Close = audin_server_close;
audin->dsp_context = freerdp_dsp_context_new();
return (audin_server_context*) audin;
}
void audin_server_context_free(audin_server_context* context)
{
audin_server* audin = (audin_server*) context;
audin_server_close(context);
if (audin->dsp_context)
freerdp_dsp_context_free(audin->dsp_context);
if (audin->context.client_formats)
xfree(audin->context.client_formats);
xfree(audin);
}

View File

@ -24,3 +24,4 @@ target_link_libraries(tfreerdp-server freerdp-core)
target_link_libraries(tfreerdp-server freerdp-utils)
target_link_libraries(tfreerdp-server freerdp-codec)
target_link_libraries(tfreerdp-server freerdp-channels)
target_link_libraries(tfreerdp-server freerdp-server-channels)

Some files were not shown because too many files have changed in this diff Show More