Merge branch 'master' of github.com:awakecoding/FreeRDP into egfx

Conflicts:
	channels/drdynvc/client/dvcman.c
	client/X11/xf_client.c
	include/freerdp/dvc.h
This commit is contained in:
Marc-André Moreau 2014-06-12 12:03:08 -04:00
commit 6f9a256c5c
72 changed files with 7715 additions and 5789 deletions

View File

@ -417,9 +417,13 @@ set(FFMPEG_FEATURE_TYPE "RECOMMENDED")
set(FFMPEG_FEATURE_PURPOSE "multimedia") set(FFMPEG_FEATURE_PURPOSE "multimedia")
set(FFMPEG_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback") set(FFMPEG_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
set(GSTREAMER_FEATURE_TYPE "RECOMMENDED") set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL")
set(GSTREAMER_FEATURE_PURPOSE "multimedia") set(GSTREAMER_0_10_FEATURE_PURPOSE "multimedia")
set(GSTREAMER_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback") set(GSTREAMER_0_10_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback, gstreamer 0.10 version")
set(GSTREAMER_1_0_FEATURE_TYPE "RECOMMENDED")
set(GSTREAMER_1_0_FEATURE_PURPOSE "multimedia")
set(GSTREAMER_1_0_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
set(IPP_FEATURE_TYPE "OPTIONAL") set(IPP_FEATURE_TYPE "OPTIONAL")
set(IPP_FEATURE_PURPOSE "performance") set(IPP_FEATURE_PURPOSE "performance")
@ -442,14 +446,15 @@ if(WIN32)
set(CUPS_FEATURE_TYPE "DISABLED") set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED") set(PCSC_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "DISABLED") set(FFMPEG_FEATURE_TYPE "DISABLED")
set(GSTREAMER_FEATURE_TYPE "DISABLED") set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED")
set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL")
set(OPENSLES_FEATURE_TYPE "DISABLED") set(OPENSLES_FEATURE_TYPE "DISABLED")
endif() endif()
if(APPLE) if(APPLE)
set(DIRECTFB_FEATURE_TYPE "DISABLED") set(DIRECTFB_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "OPTIONAL") set(FFMPEG_FEATURE_TYPE "OPTIONAL")
set(GSTREAMER_FEATURE_TYPE "OPTIONAL") set(GSTREAMER_1_0_FEATURE_TYPE "OPTIONAL")
set(X11_FEATURE_TYPE "OPTIONAL") set(X11_FEATURE_TYPE "OPTIONAL")
if(IOS) if(IOS)
set(X11_FEATURE_TYPE "DISABLED") set(X11_FEATURE_TYPE "DISABLED")
@ -457,7 +462,8 @@ if(APPLE)
set(PULSE_FEATURE_TYPE "DISABLED") set(PULSE_FEATURE_TYPE "DISABLED")
set(CUPS_FEATURE_TYPE "DISABLED") set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED") set(PCSC_FEATURE_TYPE "DISABLED")
set(GSTREAMER_FEATURE_TYPE "DISABLED") set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED")
set(GSTREAMER_0_10_FEATURE_TYPE "DISABLED")
endif() endif()
set(OPENSLES_FEATURE_TYPE "DISABLED") set(OPENSLES_FEATURE_TYPE "DISABLED")
endif() endif()
@ -470,7 +476,8 @@ if(ANDROID)
set(CUPS_FEATURE_TYPE "DISABLED") set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED") set(PCSC_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "DISABLED") set(FFMPEG_FEATURE_TYPE "DISABLED")
set(GSTREAMER_FEATURE_TYPE "DISABLED") set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED")
set(GSTREAMER_0_10_FEATURE_TYPE "DISABLED")
set(OPENSLES_FEATURE_TYPE "REQUIRED") set(OPENSLES_FEATURE_TYPE "REQUIRED")
endif() endif()
@ -492,7 +499,9 @@ find_feature(Cups ${CUPS_FEATURE_TYPE} ${CUPS_FEATURE_PURPOSE} ${CUPS_FEATURE_DE
find_feature(PCSC ${PCSC_FEATURE_TYPE} ${PCSC_FEATURE_PURPOSE} ${PCSC_FEATURE_DESCRIPTION}) find_feature(PCSC ${PCSC_FEATURE_TYPE} ${PCSC_FEATURE_PURPOSE} ${PCSC_FEATURE_DESCRIPTION})
find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FEATURE_DESCRIPTION}) find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FEATURE_DESCRIPTION})
find_feature(Gstreamer ${GSTREAMER_FEATURE_TYPE} ${GSTREAMER_FEATURE_PURPOSE} ${GSTREAMER_FEATURE_DESCRIPTION})
find_feature(GStreamer_0_10 ${GSTREAMER_0_10_FEATURE_TYPE} ${GSTREAMER_0_10_FEATURE_PURPOSE} ${GSTREAMER_0_10_FEATURE_DESCRIPTION})
find_feature(GStreamer_1_0 ${GSTREAMER_1_0_FEATURE_TYPE} ${GSTREAMER_1_0_FEATURE_PURPOSE} ${GSTREAMER_1_0_FEATURE_DESCRIPTION})
find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION}) find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION})
find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION}) find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})

View File

@ -29,7 +29,6 @@
#include <winpr/stream.h> #include <winpr/stream.h>
#include <freerdp/constants.h> #include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include "dvcman.h" #include "dvcman.h"
#include "drdynvc_types.h" #include "drdynvc_types.h"
@ -298,8 +297,7 @@ static int drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId
if (status) if (status)
return status; return status;
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s);
Stream_Pointer(s), Stream_GetRemainingLength(s));
} }
static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s)
@ -309,8 +307,7 @@ static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStr
ChannelId = drdynvc_read_variable_uint(s, cbChId); ChannelId = drdynvc_read_variable_uint(s, cbChId);
DEBUG_DVC("ChannelId=%d", ChannelId); DEBUG_DVC("ChannelId=%d", ChannelId);
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s);
Stream_Pointer(s), Stream_GetRemainingLength(s));
} }
static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s)
@ -382,8 +379,6 @@ static void drdynvc_process_receive(rdpSvcPlugin* plugin, wStream* s)
DEBUG_WARN("unknown drdynvc cmd 0x%x", Cmd); DEBUG_WARN("unknown drdynvc cmd 0x%x", Cmd);
break; break;
} }
Stream_Free(s, TRUE);
} }
static void drdynvc_process_connect(rdpSvcPlugin* plugin) static void drdynvc_process_connect(rdpSvcPlugin* plugin)
@ -425,6 +420,8 @@ static void drdynvc_process_terminate(rdpSvcPlugin* plugin)
if (drdynvc->channel_mgr) if (drdynvc->channel_mgr)
dvcman_free(drdynvc->channel_mgr); dvcman_free(drdynvc->channel_mgr);
svc_plugin_terminate(plugin);
free(drdynvc); free(drdynvc);
} }
@ -482,3 +479,4 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
return 1; return 1;
} }

View File

@ -195,8 +195,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
{ {
DVCMAN* dvcman; DVCMAN* dvcman;
dvcman = (DVCMAN*) malloc(sizeof(DVCMAN)); dvcman = (DVCMAN*) calloc(1, sizeof(DVCMAN));
ZeroMemory(dvcman, sizeof(DVCMAN));
dvcman->iface.CreateListener = dvcman_create_listener; dvcman->iface.CreateListener = dvcman_create_listener;
dvcman->iface.PushEvent = dvcman_push_event; dvcman->iface.PushEvent = dvcman_push_event;
@ -204,6 +203,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
dvcman->iface.GetChannelId = dvcman_get_channel_id; dvcman->iface.GetChannelId = dvcman_get_channel_id;
dvcman->drdynvc = plugin; dvcman->drdynvc = plugin;
dvcman->channels = ArrayList_New(TRUE); dvcman->channels = ArrayList_New(TRUE);
dvcman->pool = StreamPool_New(TRUE, 10);
return (IWTSVirtualChannelManager*) dvcman; return (IWTSVirtualChannelManager*) dvcman;
} }
@ -278,6 +278,7 @@ void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
pPlugin->Terminated(pPlugin); pPlugin->Terminated(pPlugin);
} }
StreamPool_Free(dvcman->pool);
free(dvcman); free(dvcman);
} }
@ -424,7 +425,7 @@ int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelI
if (channel->dvc_data) if (channel->dvc_data)
{ {
Stream_Free(channel->dvc_data, TRUE); Stream_Release(channel->dvc_data);
channel->dvc_data = NULL; channel->dvc_data = NULL;
} }
@ -457,17 +458,19 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UI
} }
if (channel->dvc_data) if (channel->dvc_data)
Stream_Free(channel->dvc_data, TRUE); Stream_Release(channel->dvc_data);
channel->dvc_data = Stream_New(NULL, length); channel->dvc_data = StreamPool_Take(channel->dvcman->pool, length);
Stream_AddRef(channel->dvc_data);
return 0; return 0;
} }
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, BYTE* data, UINT32 data_size) int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data)
{ {
int error = 0; int error = 0;
DVCMAN_CHANNEL* channel; DVCMAN_CHANNEL* channel;
UINT32 dataSize = Stream_GetRemainingLength(data);
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
@ -480,28 +483,30 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 C
if (channel->dvc_data) if (channel->dvc_data)
{ {
/* Fragmented data */ /* Fragmented data */
if (Stream_GetPosition(channel->dvc_data) + data_size > (UINT32) Stream_Capacity(channel->dvc_data)) if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(channel->dvc_data))
{ {
DEBUG_WARN("data exceeding declared length!"); DEBUG_WARN("data exceeding declared length!");
Stream_Free(channel->dvc_data, TRUE); Stream_Release(channel->dvc_data);
channel->dvc_data = NULL; channel->dvc_data = NULL;
return 1; return 1;
} }
Stream_Write(channel->dvc_data, data, data_size); Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize);
if (((size_t) Stream_GetPosition(channel->dvc_data)) >= Stream_Capacity(channel->dvc_data)) if (((size_t) Stream_GetPosition(channel->dvc_data)) >= Stream_Capacity(channel->dvc_data))
{ {
error = channel->channel_callback->OnDataReceived(channel->channel_callback, Stream_SealLength(channel->dvc_data);
Stream_Capacity(channel->dvc_data), Stream_Buffer(channel->dvc_data)); Stream_SetPosition(channel->dvc_data, 0);
Stream_Free(channel->dvc_data, TRUE); error = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data);
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL; channel->dvc_data = NULL;
} }
} }
else else
{ {
error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data); error = channel->channel_callback->OnDataReceived(channel->channel_callback, data);
} }
return error; return error;
} }

View File

@ -43,6 +43,7 @@ struct _DVCMAN
int num_listeners; int num_listeners;
wArrayList* channels; wArrayList* channels;
wStreamPool* pool;
}; };
typedef struct _DVCMAN DVCMAN; typedef struct _DVCMAN DVCMAN;
@ -90,7 +91,7 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId); int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId);
int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId); int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId);
int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length); int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length);
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, BYTE* data, UINT32 data_size); int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream *data);
void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName); void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName);

View File

@ -55,7 +55,7 @@ if(WITH_FFMPEG)
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "ffmpeg" "decoder") add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "ffmpeg" "decoder")
endif() endif()
if(WITH_GSTREAMER) if(WITH_GSTREAMER_0_10 OR WITH_GSTREAMER_1_0)
set(XRANDR_FEATURE_TYPE "REQUIRED") set(XRANDR_FEATURE_TYPE "REQUIRED")
set(XRANDR_FEATURE_PURPOSE "X11 randr") set(XRANDR_FEATURE_PURPOSE "X11 randr")
set(XRANDR_FEATURE_DESCRIPTION "X11 randr extension") set(XRANDR_FEATURE_DESCRIPTION "X11 randr extension")

View File

@ -24,7 +24,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <pthread.h>
#include <unistd.h> #include <unistd.h>
#include <winpr/crt.h> #include <winpr/crt.h>
@ -54,23 +53,19 @@ typedef struct _TSMFALSAAudioDevice
static BOOL tsmf_alsa_open_device(TSMFAlsaAudioDevice *alsa) static BOOL tsmf_alsa_open_device(TSMFAlsaAudioDevice *alsa)
{ {
int error; int error;
error = snd_pcm_open(&alsa->out_handle, alsa->device, SND_PCM_STREAM_PLAYBACK, 0); error = snd_pcm_open(&alsa->out_handle, alsa->device, SND_PCM_STREAM_PLAYBACK, 0);
if(error < 0) if(error < 0)
{ {
DEBUG_WARN("failed to open device %s", alsa->device); DEBUG_WARN("failed to open device %s", alsa->device);
return FALSE; return FALSE;
} }
DEBUG_TSMF("open device %s", alsa->device);
DEBUG_DVC("open device %s", alsa->device);
return TRUE; return TRUE;
} }
static BOOL tsmf_alsa_open(ITSMFAudioDevice *audio, const char *device) static BOOL tsmf_alsa_open(ITSMFAudioDevice *audio, const char *device)
{ {
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio; TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
if(!device) if(!device)
{ {
if(!alsa->device[0]) if(!alsa->device[0])
@ -80,7 +75,6 @@ static BOOL tsmf_alsa_open(ITSMFAudioDevice* audio, const char* device)
{ {
strncpy(alsa->device, device, sizeof(alsa->device)); strncpy(alsa->device, device, sizeof(alsa->device));
} }
return tsmf_alsa_open_device(alsa); return tsmf_alsa_open_device(alsa);
} }
@ -92,24 +86,18 @@ static BOOL tsmf_alsa_set_format(ITSMFAudioDevice* audio,
snd_pcm_hw_params_t *hw_params; snd_pcm_hw_params_t *hw_params;
snd_pcm_sw_params_t *sw_params; snd_pcm_sw_params_t *sw_params;
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio; TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
if(!alsa->out_handle) if(!alsa->out_handle)
return FALSE; return FALSE;
snd_pcm_drop(alsa->out_handle); snd_pcm_drop(alsa->out_handle);
alsa->actual_rate = alsa->source_rate = sample_rate; alsa->actual_rate = alsa->source_rate = sample_rate;
alsa->actual_channels = alsa->source_channels = channels; alsa->actual_channels = alsa->source_channels = channels;
alsa->bytes_per_sample = bits_per_sample / 8; alsa->bytes_per_sample = bits_per_sample / 8;
error = snd_pcm_hw_params_malloc(&hw_params); error = snd_pcm_hw_params_malloc(&hw_params);
if(error < 0) if(error < 0)
{ {
DEBUG_WARN("snd_pcm_hw_params_malloc failed"); DEBUG_WARN("snd_pcm_hw_params_malloc failed");
return FALSE; return FALSE;
} }
snd_pcm_hw_params_any(alsa->out_handle, hw_params); snd_pcm_hw_params_any(alsa->out_handle, hw_params);
snd_pcm_hw_params_set_access(alsa->out_handle, hw_params, snd_pcm_hw_params_set_access(alsa->out_handle, hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED); SND_PCM_ACCESS_RW_INTERLEAVED);
@ -124,36 +112,29 @@ static BOOL tsmf_alsa_set_format(ITSMFAudioDevice* audio,
&frames); &frames);
snd_pcm_hw_params(alsa->out_handle, hw_params); snd_pcm_hw_params(alsa->out_handle, hw_params);
snd_pcm_hw_params_free(hw_params); snd_pcm_hw_params_free(hw_params);
error = snd_pcm_sw_params_malloc(&sw_params); error = snd_pcm_sw_params_malloc(&sw_params);
if(error < 0) if(error < 0)
{ {
DEBUG_WARN("snd_pcm_sw_params_malloc"); DEBUG_WARN("snd_pcm_sw_params_malloc");
return FALSE; return FALSE;
} }
snd_pcm_sw_params_current(alsa->out_handle, sw_params); snd_pcm_sw_params_current(alsa->out_handle, sw_params);
snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params, snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params,
frames / 2); frames / 2);
snd_pcm_sw_params(alsa->out_handle, sw_params); snd_pcm_sw_params(alsa->out_handle, sw_params);
snd_pcm_sw_params_free(sw_params); snd_pcm_sw_params_free(sw_params);
snd_pcm_prepare(alsa->out_handle); snd_pcm_prepare(alsa->out_handle);
DEBUG_TSMF("sample_rate %d channels %d bits_per_sample %d",
DEBUG_DVC("sample_rate %d channels %d bits_per_sample %d",
sample_rate, channels, bits_per_sample); sample_rate, channels, bits_per_sample);
DEBUG_DVC("hardware buffer %d frames", (int)frames); DEBUG_TSMF("hardware buffer %d frames", (int)frames);
if((alsa->actual_rate != alsa->source_rate) || if((alsa->actual_rate != alsa->source_rate) ||
(alsa->actual_channels != alsa->source_channels)) (alsa->actual_channels != alsa->source_channels))
{ {
DEBUG_DVC("actual rate %d / channel %d is different " DEBUG_TSMF("actual rate %d / channel %d is different "
"from source rate %d / channel %d, resampling required.", "from source rate %d / channel %d, resampling required.",
alsa->actual_rate, alsa->actual_channels, alsa->actual_rate, alsa->actual_channels,
alsa->source_rate, alsa->source_channels); alsa->source_rate, alsa->source_channels);
} }
return TRUE; return TRUE;
} }
@ -168,14 +149,11 @@ static BOOL tsmf_alsa_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size
int rbytes_per_frame; int rbytes_per_frame;
int sbytes_per_frame; int sbytes_per_frame;
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio; TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
DEBUG_TSMF("data_size %d", data_size);
DEBUG_DVC("data_size %d", data_size);
if(alsa->out_handle) if(alsa->out_handle)
{ {
sbytes_per_frame = alsa->source_channels * alsa->bytes_per_sample; sbytes_per_frame = alsa->source_channels * alsa->bytes_per_sample;
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_sample; rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_sample;
if((alsa->source_rate == alsa->actual_rate) && if((alsa->source_rate == alsa->actual_rate) &&
(alsa->source_channels == alsa->actual_channels)) (alsa->source_channels == alsa->actual_channels))
{ {
@ -187,12 +165,11 @@ static BOOL tsmf_alsa_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size
alsa->source_channels, alsa->source_rate, data_size / sbytes_per_frame, alsa->source_channels, alsa->source_rate, data_size / sbytes_per_frame,
alsa->actual_channels, alsa->actual_rate); alsa->actual_channels, alsa->actual_rate);
frames = alsa->dsp_context->resampled_frames; frames = alsa->dsp_context->resampled_frames;
DEBUG_DVC("resampled %d frames at %d to %d frames at %d", DEBUG_TSMF("resampled %d frames at %d to %d frames at %d",
data_size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate); data_size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate);
data_size = frames * rbytes_per_frame; data_size = frames * rbytes_per_frame;
src = alsa->dsp_context->resampled_buffer; src = alsa->dsp_context->resampled_buffer;
} }
pindex = src; pindex = src;
end = pindex + data_size; end = pindex + data_size;
while(pindex < end) while(pindex < end)
@ -200,31 +177,27 @@ static BOOL tsmf_alsa_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size
len = end - pindex; len = end - pindex;
frames = len / rbytes_per_frame; frames = len / rbytes_per_frame;
error = snd_pcm_writei(alsa->out_handle, pindex, frames); error = snd_pcm_writei(alsa->out_handle, pindex, frames);
if(error == -EPIPE) if(error == -EPIPE)
{ {
snd_pcm_recover(alsa->out_handle, error, 0); snd_pcm_recover(alsa->out_handle, error, 0);
error = 0; error = 0;
} }
else if (error < 0) else
if(error < 0)
{ {
DEBUG_DVC("error len %d", error); DEBUG_TSMF("error len %d", error);
snd_pcm_close(alsa->out_handle); snd_pcm_close(alsa->out_handle);
alsa->out_handle = 0; alsa->out_handle = 0;
tsmf_alsa_open_device(alsa); tsmf_alsa_open_device(alsa);
break; break;
} }
DEBUG_TSMF("%d frames played.", error);
DEBUG_DVC("%d frames played.", error);
if(error == 0) if(error == 0)
break; break;
pindex += error * rbytes_per_frame; pindex += error * rbytes_per_frame;
} }
} }
free(data); free(data);
return TRUE; return TRUE;
} }
@ -233,14 +206,12 @@ static UINT64 tsmf_alsa_get_latency(ITSMFAudioDevice* audio)
UINT64 latency = 0; UINT64 latency = 0;
snd_pcm_sframes_t frames = 0; snd_pcm_sframes_t frames = 0;
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio; TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
if(alsa->out_handle && alsa->actual_rate > 0 && if(alsa->out_handle && alsa->actual_rate > 0 &&
snd_pcm_delay(alsa->out_handle, &frames) == 0 && snd_pcm_delay(alsa->out_handle, &frames) == 0 &&
frames > 0) frames > 0)
{ {
latency = ((UINT64)frames) * 10000000LL / (UINT64) alsa->actual_rate; latency = ((UINT64)frames) * 10000000LL / (UINT64) alsa->actual_rate;
} }
return latency; return latency;
} }
@ -251,15 +222,12 @@ static void tsmf_alsa_flush(ITSMFAudioDevice* audio)
static void tsmf_alsa_free(ITSMFAudioDevice *audio) static void tsmf_alsa_free(ITSMFAudioDevice *audio)
{ {
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio; TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
DEBUG_TSMF("");
DEBUG_DVC("");
if(alsa->out_handle) if(alsa->out_handle)
{ {
snd_pcm_drain(alsa->out_handle); snd_pcm_drain(alsa->out_handle);
snd_pcm_close(alsa->out_handle); snd_pcm_close(alsa->out_handle);
} }
freerdp_dsp_context_free(alsa->dsp_context); freerdp_dsp_context_free(alsa->dsp_context);
free(alsa); free(alsa);
} }
@ -271,18 +239,14 @@ static void tsmf_alsa_free(ITSMFAudioDevice* audio)
ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void) ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)
{ {
TSMFAlsaAudioDevice *alsa; TSMFAlsaAudioDevice *alsa;
alsa = (TSMFAlsaAudioDevice *) malloc(sizeof(TSMFAlsaAudioDevice)); alsa = (TSMFAlsaAudioDevice *) malloc(sizeof(TSMFAlsaAudioDevice));
ZeroMemory(alsa, sizeof(TSMFAlsaAudioDevice)); ZeroMemory(alsa, sizeof(TSMFAlsaAudioDevice));
alsa->iface.Open = tsmf_alsa_open; alsa->iface.Open = tsmf_alsa_open;
alsa->iface.SetFormat = tsmf_alsa_set_format; alsa->iface.SetFormat = tsmf_alsa_set_format;
alsa->iface.Play = tsmf_alsa_play; alsa->iface.Play = tsmf_alsa_play;
alsa->iface.GetLatency = tsmf_alsa_get_latency; alsa->iface.GetLatency = tsmf_alsa_get_latency;
alsa->iface.Flush = tsmf_alsa_flush; alsa->iface.Flush = tsmf_alsa_flush;
alsa->iface.Free = tsmf_alsa_free; alsa->iface.Free = tsmf_alsa_free;
alsa->dsp_context = freerdp_dsp_context_new(); alsa->dsp_context = freerdp_dsp_context_new();
return (ITSMFAudioDevice *) alsa; return (ITSMFAudioDevice *) alsa;
} }

View File

@ -32,8 +32,6 @@
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <pthread.h>
#include "tsmf_constants.h" #include "tsmf_constants.h"
#include "tsmf_decoder.h" #include "tsmf_decoder.h"
@ -72,42 +70,34 @@ typedef struct _TSMFFFmpegDecoder
static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder *decoder) static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder *decoder)
{ {
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
mdecoder->codec_context = avcodec_alloc_context3(NULL); mdecoder->codec_context = avcodec_alloc_context3(NULL);
if(!mdecoder->codec_context) if(!mdecoder->codec_context)
{ {
DEBUG_WARN("avcodec_alloc_context failed."); DEBUG_WARN("avcodec_alloc_context failed.");
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type) static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type)
{ {
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
mdecoder->codec_context->width = media_type->Width; mdecoder->codec_context->width = media_type->Width;
mdecoder->codec_context->height = media_type->Height; mdecoder->codec_context->height = media_type->Height;
mdecoder->codec_context->bit_rate = media_type->BitRate; mdecoder->codec_context->bit_rate = media_type->BitRate;
mdecoder->codec_context->time_base.den = media_type->SamplesPerSecond.Numerator; mdecoder->codec_context->time_base.den = media_type->SamplesPerSecond.Numerator;
mdecoder->codec_context->time_base.num = media_type->SamplesPerSecond.Denominator; mdecoder->codec_context->time_base.num = media_type->SamplesPerSecond.Denominator;
mdecoder->frame = avcodec_alloc_frame(); mdecoder->frame = avcodec_alloc_frame();
return TRUE; return TRUE;
} }
static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type) static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type)
{ {
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
mdecoder->codec_context->sample_rate = media_type->SamplesPerSecond.Numerator; mdecoder->codec_context->sample_rate = media_type->SamplesPerSecond.Numerator;
mdecoder->codec_context->bit_rate = media_type->BitRate; mdecoder->codec_context->bit_rate = media_type->BitRate;
mdecoder->codec_context->channels = media_type->Channels; mdecoder->codec_context->channels = media_type->Channels;
mdecoder->codec_context->block_align = media_type->BlockAlign; mdecoder->codec_context->block_align = media_type->BlockAlign;
#if LIBAVCODEC_VERSION_MAJOR < 55 #if LIBAVCODEC_VERSION_MAJOR < 55
#ifdef AV_CPU_FLAG_SSE2 #ifdef AV_CPU_FLAG_SSE2
mdecoder->codec_context->dsp_mask = AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2; mdecoder->codec_context->dsp_mask = AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2;
@ -125,7 +115,6 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED
av_set_cpu_flags_mask(FF_MM_SSE2 | FF_MM_MMX2); av_set_cpu_flags_mask(FF_MM_SSE2 | FF_MM_MMX2);
#endif #endif
#endif /* LIBAVCODEC_VERSION_MAJOR < 55 */ #endif /* LIBAVCODEC_VERSION_MAJOR < 55 */
return TRUE; return TRUE;
} }
@ -135,29 +124,25 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
UINT32 size; UINT32 size;
const BYTE *s; const BYTE *s;
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id); mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id);
if(!mdecoder->codec) if(!mdecoder->codec)
{ {
DEBUG_WARN("avcodec_find_decoder failed."); DEBUG_WARN("avcodec_find_decoder failed.");
return FALSE; return FALSE;
} }
mdecoder->codec_context->codec_id = mdecoder->codec_id; mdecoder->codec_context->codec_id = mdecoder->codec_id;
mdecoder->codec_context->codec_type = mdecoder->media_type; mdecoder->codec_context->codec_type = mdecoder->media_type;
if(mdecoder->media_type == AVMEDIA_TYPE_VIDEO) if(mdecoder->media_type == AVMEDIA_TYPE_VIDEO)
{ {
if(!tsmf_ffmpeg_init_video_stream(decoder, media_type)) if(!tsmf_ffmpeg_init_video_stream(decoder, media_type))
return FALSE; return FALSE;
} }
else if (mdecoder->media_type == AVMEDIA_TYPE_AUDIO) else
if(mdecoder->media_type == AVMEDIA_TYPE_AUDIO)
{ {
if(!tsmf_ffmpeg_init_audio_stream(decoder, media_type)) if(!tsmf_ffmpeg_init_audio_stream(decoder, media_type))
return FALSE; return FALSE;
} }
if(media_type->ExtraData) if(media_type->ExtraData)
{ {
if(media_type->SubType == TSMF_SUB_TYPE_AVC1 && if(media_type->SubType == TSMF_SUB_TYPE_AVC1 &&
@ -194,32 +179,26 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8); memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8);
} }
} }
if(mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED) if(mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED)
mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED; mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED;
return TRUE; return TRUE;
} }
static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder *decoder) static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder *decoder)
{ {
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0) if(avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0)
{ {
DEBUG_WARN("avcodec_open2 failed."); DEBUG_WARN("avcodec_open2 failed.");
return FALSE; return FALSE;
} }
mdecoder->prepared = 1; mdecoder->prepared = 1;
return TRUE; return TRUE;
} }
static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *media_type) static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *media_type)
{ {
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
switch(media_type->MajorType) switch(media_type->MajorType)
{ {
case TSMF_MAJOR_TYPE_VIDEO: case TSMF_MAJOR_TYPE_VIDEO:
@ -275,14 +254,12 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* medi
default: default:
return FALSE; return FALSE;
} }
if(!tsmf_ffmpeg_init_context(decoder)) if(!tsmf_ffmpeg_init_context(decoder))
return FALSE; return FALSE;
if(!tsmf_ffmpeg_init_stream(decoder, media_type)) if(!tsmf_ffmpeg_init_stream(decoder, media_type))
return FALSE; return FALSE;
if(!tsmf_ffmpeg_prepare(decoder)) if(!tsmf_ffmpeg_prepare(decoder))
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
@ -293,7 +270,6 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE* data, UI
int len; int len;
AVFrame *frame; AVFrame *frame;
BOOL ret = TRUE; BOOL ret = TRUE;
#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20) #if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
len = avcodec_decode_video(mdecoder->codec_context, mdecoder->frame, &decoded, data, data_size); len = avcodec_decode_video(mdecoder->codec_context, mdecoder->frame, &decoded, data, data_size);
#else #else
@ -307,26 +283,25 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE* data, UI
len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt); len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt);
} }
#endif #endif
if(len < 0) if(len < 0)
{ {
DEBUG_WARN("data_size %d, avcodec_decode_video failed (%d)", data_size, len); DEBUG_WARN("data_size %d, avcodec_decode_video failed (%d)", data_size, len);
ret = FALSE; ret = FALSE;
} }
else if (!decoded) else
if(!decoded)
{ {
DEBUG_WARN("data_size %d, no frame is decoded.", data_size); DEBUG_WARN("data_size %d, no frame is decoded.", data_size);
ret = FALSE; ret = FALSE;
} }
else else
{ {
DEBUG_DVC("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d " DEBUG_TSMF("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d "
"pix_fmt %d width %d height %d", "pix_fmt %d width %d height %d",
mdecoder->frame->linesize[0], mdecoder->frame->linesize[1], mdecoder->frame->linesize[0], mdecoder->frame->linesize[1],
mdecoder->frame->linesize[2], mdecoder->frame->linesize[3], mdecoder->frame->linesize[2], mdecoder->frame->linesize[3],
mdecoder->codec_context->pix_fmt, mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height); mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt, mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height); mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->decoded_data = malloc(mdecoder->decoded_size); mdecoder->decoded_data = malloc(mdecoder->decoded_size);
@ -335,14 +310,11 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE* data, UI
avpicture_fill((AVPicture *) frame, mdecoder->decoded_data, avpicture_fill((AVPicture *) frame, mdecoder->decoded_data,
mdecoder->codec_context->pix_fmt, mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height); mdecoder->codec_context->width, mdecoder->codec_context->height);
av_picture_copy((AVPicture *) frame, (AVPicture *) mdecoder->frame, av_picture_copy((AVPicture *) frame, (AVPicture *) mdecoder->frame,
mdecoder->codec_context->pix_fmt, mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height); mdecoder->codec_context->width, mdecoder->codec_context->height);
av_free(frame); av_free(frame);
} }
return ret; return ret;
} }
@ -355,7 +327,6 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
const BYTE *src; const BYTE *src;
BYTE *dst; BYTE *dst;
int dst_offset; int dst_offset;
#if 0 #if 0
LLOGLN(0, ("tsmf_ffmpeg_decode_audio: data_size %d", data_size)); LLOGLN(0, ("tsmf_ffmpeg_decode_audio: data_size %d", data_size));
int i; int i;
@ -367,7 +338,6 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
} }
LLOG(0, ("\n")); LLOG(0, ("\n"));
#endif #endif
if(mdecoder->decoded_size_max == 0) if(mdecoder->decoded_size_max == 0)
mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16; mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16;
mdecoder->decoded_data = malloc(mdecoder->decoded_size_max); mdecoder->decoded_data = malloc(mdecoder->decoded_size_max);
@ -377,7 +347,6 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
dst_offset = dst - mdecoder->decoded_data; dst_offset = dst - mdecoder->decoded_data;
src = data; src = data;
src_size = data_size; src_size = data_size;
while(src_size > 0) while(src_size > 0)
{ {
/* Ensure enough space for decoding */ /* Ensure enough space for decoding */
@ -394,7 +363,6 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
} }
dst += mdecoder->decoded_size; dst += mdecoder->decoded_size;
} }
frame_size = mdecoder->decoded_size_max - mdecoder->decoded_size; frame_size = mdecoder->decoded_size_max - mdecoder->decoded_size;
#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20) #if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
len = avcodec_decode_audio2(mdecoder->codec_context, len = avcodec_decode_audio2(mdecoder->codec_context,
@ -408,14 +376,12 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
pkt.data = (BYTE *) src; pkt.data = (BYTE *) src;
pkt.size = src_size; pkt.size = src_size;
len = avcodec_decode_audio4(mdecoder->codec_context, decoded_frame, &got_frame, &pkt); len = avcodec_decode_audio4(mdecoder->codec_context, decoded_frame, &got_frame, &pkt);
if(len >= 0 && got_frame) if(len >= 0 && got_frame)
{ {
frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels, frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels,
decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1); decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1);
memcpy(dst, decoded_frame->data[0], frame_size); memcpy(dst, decoded_frame->data[0], frame_size);
} }
av_free(decoded_frame); av_free(decoded_frame);
} }
#endif #endif
@ -424,41 +390,36 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
DEBUG_WARN("error decoding"); DEBUG_WARN("error decoding");
break; break;
} }
src += len; src += len;
src_size -= len; src_size -= len;
mdecoder->decoded_size += frame_size; mdecoder->decoded_size += frame_size;
dst += frame_size; dst += frame_size;
} }
if(mdecoder->decoded_size == 0) if(mdecoder->decoded_size == 0)
{ {
free(mdecoder->decoded_data); free(mdecoder->decoded_data);
mdecoder->decoded_data = NULL; mdecoder->decoded_data = NULL;
} }
else if (dst_offset) else
if(dst_offset)
{ {
/* move the aligned decoded data to original place */ /* move the aligned decoded data to original place */
memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size); memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
} }
DEBUG_TSMF("data_size %d decoded_size %d",
DEBUG_DVC("data_size %d decoded_size %d",
data_size, mdecoder->decoded_size); data_size, mdecoder->decoded_size);
return TRUE; return TRUE;
} }
static BOOL tsmf_ffmpeg_decode(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions) static BOOL tsmf_ffmpeg_decode(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
{ {
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(mdecoder->decoded_data) if(mdecoder->decoded_data)
{ {
free(mdecoder->decoded_data); free(mdecoder->decoded_data);
mdecoder->decoded_data = NULL; mdecoder->decoded_data = NULL;
} }
mdecoder->decoded_size = 0; mdecoder->decoded_size = 0;
switch(mdecoder->media_type) switch(mdecoder->media_type)
{ {
case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_VIDEO:
@ -475,24 +436,20 @@ static BYTE* tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32* size)
{ {
BYTE *buf; BYTE *buf;
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
*size = mdecoder->decoded_size; *size = mdecoder->decoded_size;
buf = mdecoder->decoded_data; buf = mdecoder->decoded_data;
mdecoder->decoded_data = NULL; mdecoder->decoded_data = NULL;
mdecoder->decoded_size = 0; mdecoder->decoded_size = 0;
return buf; return buf;
} }
static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder *decoder) static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder *decoder)
{ {
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
switch(mdecoder->codec_context->pix_fmt) switch(mdecoder->codec_context->pix_fmt)
{ {
case PIX_FMT_YUV420P: case PIX_FMT_YUV420P:
return RDP_PIXFMT_I420; return RDP_PIXFMT_I420;
default: default:
DEBUG_WARN("unsupported pixel format %u", DEBUG_WARN("unsupported pixel format %u",
mdecoder->codec_context->pix_fmt); mdecoder->codec_context->pix_fmt);
@ -503,7 +460,6 @@ static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder* decoder)
static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder *decoder, UINT32 *width, UINT32 *height) static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder *decoder, UINT32 *width, UINT32 *height)
{ {
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0) if(mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0)
{ {
*width = mdecoder->codec_context->width; *width = mdecoder->codec_context->width;
@ -519,13 +475,10 @@ static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32* wid
static void tsmf_ffmpeg_free(ITSMFDecoder *decoder) static void tsmf_ffmpeg_free(ITSMFDecoder *decoder)
{ {
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(mdecoder->frame) if(mdecoder->frame)
av_free(mdecoder->frame); av_free(mdecoder->frame);
if(mdecoder->decoded_data) if(mdecoder->decoded_data)
free(mdecoder->decoded_data); free(mdecoder->decoded_data);
if(mdecoder->codec_context) if(mdecoder->codec_context)
{ {
if(mdecoder->prepared) if(mdecoder->prepared)
@ -534,7 +487,6 @@ static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
free(mdecoder->codec_context->extradata); free(mdecoder->codec_context->extradata);
av_free(mdecoder->codec_context); av_free(mdecoder->codec_context);
} }
free(decoder); free(decoder);
} }
@ -547,24 +499,19 @@ static BOOL initialized = FALSE;
ITSMFDecoder *freerdp_tsmf_client_decoder_subsystem_entry(void) ITSMFDecoder *freerdp_tsmf_client_decoder_subsystem_entry(void)
{ {
TSMFFFmpegDecoder *decoder; TSMFFFmpegDecoder *decoder;
if(!initialized) if(!initialized)
{ {
avcodec_register_all(); avcodec_register_all();
initialized = TRUE; initialized = TRUE;
} }
fprintf(stderr, "TSMFDecoderEntry FFMPEG\n"); fprintf(stderr, "TSMFDecoderEntry FFMPEG\n");
decoder = (TSMFFFmpegDecoder *) malloc(sizeof(TSMFFFmpegDecoder)); decoder = (TSMFFFmpegDecoder *) malloc(sizeof(TSMFFFmpegDecoder));
ZeroMemory(decoder, sizeof(TSMFFFmpegDecoder)); ZeroMemory(decoder, sizeof(TSMFFFmpegDecoder));
decoder->iface.SetFormat = tsmf_ffmpeg_set_format; decoder->iface.SetFormat = tsmf_ffmpeg_set_format;
decoder->iface.Decode = tsmf_ffmpeg_decode; decoder->iface.Decode = tsmf_ffmpeg_decode;
decoder->iface.GetDecodedData = tsmf_ffmpeg_get_decoded_data; decoder->iface.GetDecodedData = tsmf_ffmpeg_get_decoded_data;
decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format; decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format;
decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension; decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension;
decoder->iface.Free = tsmf_ffmpeg_free; decoder->iface.Free = tsmf_ffmpeg_free;
return (ITSMFDecoder *) decoder; return (ITSMFDecoder *) decoder;
} }

View File

@ -17,11 +17,48 @@
define_channel_client_subsystem("tsmf" "gstreamer" "decoder") define_channel_client_subsystem("tsmf" "gstreamer" "decoder")
set(${MODULE_PREFIX}_SRCS if(NOT GSTREAMER_0_10_FOUND AND NOT GSTREAMER_1_0_FOUND)
tsmf_gstreamer.c) message(FATAL_ERROR "GStreamer library not found, but required for TSMF module.")
elseif (GSTREAMER_0_10_FOUND AND GSTREAMER_1_0_FOUND)
message(FATAL_ERROR "GStreamer 0.10 and GStreamer 1.0 support are mutually exclusive!")
endif()
set(SRC "tsmf_gstreamer.c")
if (GSTREAMER_1_0_FOUND)
set(LIBS ${GSTREAMER_1_0_LIBRARIES})
include_directories(${GSTREAMER_1_0_INCLUDE_DIRS})
elseif (GSTREAMER_0_10_FOUND)
set(LIBS ${GSTREAMER_0_10_LIBRARIES})
include_directories(${GSTREAMER_0_10_INCLUDE_DIRS})
endif()
if(ANDROID)
set(SRC ${SRC}
tsmf_android.c)
set(LIBS ${LIBS})
else()
set(XEXT_FEATURE_TYPE "RECOMMENDED")
set(XEXT_FEATURE_PURPOSE "X11 extension")
set(XEXT_FEATURE_DESCRIPTION "X11 core extensions")
find_feature(Xext ${XEXT_FEATURE_TYPE} ${XEXT_FEATURE_PURPOSE} ${XEXT_FEATURE_DESCRIPTION})
set(SRC ${SRC}
tsmf_X11.c)
set(LIBS ${LIBS} ${X11_LIBRARIES} ${XEXT_LIBRARIES})
if(NOT XEXT_FOUND)
message(FATAL_ERROR "Xext library not found, but required for TSMF module.")
else()
add_definitions(-DWITH_XEXT=1)
endif()
endif()
set(${MODULE_PREFIX}_SRCS "${SRC}")
include_directories(..) include_directories(..)
include_directories(${GSTREAMER_INCLUDE_DIRS})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "") add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
@ -33,10 +70,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MODULES freerdp-utils) MODULES freerdp-utils)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
${GSTREAMER_LIBRARIES} ${LIBS})
gstapp-0.10
gstinterfaces-0.10
Xrandr X11 Xext)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})

View File

@ -0,0 +1,316 @@
/*
* FreeRDP: A Remote Desktop Protocol Implementation
* Video Redirection Virtual Channel - GStreamer Decoder X11 specifics
*
* (C) Copyright 2014 Thincast Technologies GmbH
* (C) Copyright 2014 Armin Novak <armin.novak@thincast.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 <assert.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <fcntl.h>
#include <winpr/thread.h>
#include <gst/gst.h>
#if GST_VERSION_MAJOR > 0
#include <gst/video/videooverlay.h>
#else
#include <gst/interfaces/xoverlay.h>
#endif
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/shape.h>
#include <freerdp/channels/tsmf.h>
#include "tsmf_platform.h"
#include "tsmf_constants.h"
#include "tsmf_decoder.h"
#if !defined(WITH_XEXT)
#warning "Building TSMF without shape extension support"
#endif
struct X11Handle
{
int shmid;
int *xfwin;
#if defined(WITH_XEXT)
BOOL has_shape;
#endif
Display *disp;
Window subwin;
};
static const char *get_shm_id()
{
static char shm_id[64];
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId());
return shm_id;
}
const char *tsmf_platform_get_video_sink(void)
{
return "xvimagesink";
}
const char *tsmf_platform_get_audio_sink(void)
{
return "autoaudiosink";
}
int tsmf_platform_create(TSMFGstreamerDecoder *decoder)
{
struct X11Handle *hdl;
assert(decoder);
assert(!decoder->platform);
hdl = malloc(sizeof(struct X11Handle));
if (!hdl)
{
DEBUG_WARN("%s: Could not allocate handle.", __func__);
return -1;
}
memset(hdl, 0, sizeof(struct X11Handle));
decoder->platform = hdl;
hdl->shmid = shm_open(get_shm_id(), O_RDWR, PROT_READ | PROT_WRITE);;
if (hdl->shmid < 0)
{
DEBUG_WARN("%s: failed to get access to shared memory - shmget()",
__func__);
return -2;
}
else
hdl->xfwin = mmap(0, sizeof(void *), PROT_READ | PROT_WRITE, MAP_SHARED, hdl->shmid, 0);
if (hdl->xfwin == (int *)-1)
{
DEBUG_WARN("%s: shmat failed!", __func__);
return -3;
}
hdl->disp = XOpenDisplay(NULL);
if (!hdl->disp)
{
DEBUG_WARN("Failed to open display");
return -4;
}
return 0;
}
int tsmf_platform_set_format(TSMFGstreamerDecoder *decoder)
{
assert(decoder);
if (decoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
{
}
return 0;
}
int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder)
{
assert(decoder);
assert(decoder->pipe);
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(decoder->pipe));
if (!bus)
{
DEBUG_WARN("gst_pipeline_get_bus failed!");
return 1;
}
return 0;
}
int tsmf_platform_free(TSMFGstreamerDecoder *decoder)
{
struct X11Handle *hdl = decoder->platform;
if (!hdl)
return -1;
if (hdl->disp)
XCloseDisplay(hdl->disp);
if (hdl->xfwin)
munmap(0, sizeof(void *));
if (hdl->shmid >= 0)
close(hdl->shmid);
free(hdl);
decoder->platform = NULL;
return 0;
}
int tsmf_window_create(TSMFGstreamerDecoder *decoder)
{
if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
{
decoder->ready = TRUE;
return -3;
}
else
{
#if GST_VERSION_MAJOR > 0
GstVideoOverlay *overlay = GST_VIDEO_OVERLAY(decoder->outsink);
#else
GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink);
#endif
struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
assert(decoder);
assert(hdl);
if (!hdl->subwin)
{
int event, error;
hdl->subwin = XCreateSimpleWindow(hdl->disp, *(int *)hdl->xfwin, 0, 0, 1, 1, 0, 0, 0);
if (!hdl->subwin)
{
DEBUG_WARN("Could not create subwindow!");
}
XMapWindow(hdl->disp, hdl->subwin);
XSync(hdl->disp, FALSE);
#if GST_VERSION_MAJOR > 0
gst_video_overlay_set_window_handle(overlay, hdl->subwin);
#else
gst_x_overlay_set_window_handle(overlay, hdl->subwin);
#endif
decoder->ready = TRUE;
#if defined(WITH_XEXT)
hdl->has_shape = XShapeQueryExtension(hdl->disp, &event, &error);
#endif
}
#if GST_VERSION_MAJOR > 0
gst_video_overlay_handle_events(overlay, TRUE);
#else
gst_x_overlay_handle_events(overlay, TRUE);
#endif
return 0;
}
}
int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y, int width,
int height, int nr_rects, RDP_RECT *rects)
{
if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
return -3;
else
{
#if GST_VERSION_MAJOR > 0
GstVideoOverlay *overlay = GST_VIDEO_OVERLAY(decoder->outsink);
#else
GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink);
#endif
struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
DEBUG_TSMF("resize: x=%d, y=%d, w=%d, h=%d", x, y, width, height);
assert(decoder);
assert(hdl);
#if GST_VERSION_MAJOR > 0
if (!gst_video_overlay_set_render_rectangle(overlay, 0, 0, width, height))
{
DEBUG_WARN("Could not resize overlay!");
}
gst_video_overlay_expose(overlay);
#else
if (!gst_x_overlay_set_render_rectangle(overlay, 0, 0, width, height))
{
DEBUG_WARN("Could not resize overlay!");
}
gst_x_overlay_expose(overlay);
#endif
if (hdl->subwin)
{
XMoveResizeWindow(hdl->disp, hdl->subwin, x, y, width, height);
#if defined(WITH_XEXT)
if (hdl->has_shape)
{
int i;
XRectangle *xrects = calloc(nr_rects, sizeof(XRectangle));
for (i=0; i<nr_rects; i++)
{
xrects[i].x = rects[i].x - x;
xrects[i].y = rects[i].y - y;
xrects[i].width = rects[i].width;
xrects[i].height = rects[i].height;
}
XShapeCombineRectangles(hdl->disp, hdl->subwin, ShapeBounding, x, y, xrects, nr_rects, ShapeSet, 0);
free(xrects);
}
#endif
XSync(hdl->disp, FALSE);
}
return 0;
}
}
int tsmf_window_pause(TSMFGstreamerDecoder *decoder)
{
assert(decoder);
return 0;
}
int tsmf_window_resume(TSMFGstreamerDecoder *decoder)
{
assert(decoder);
return 0;
}
int tsmf_window_destroy(TSMFGstreamerDecoder *decoder)
{
struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
decoder->ready = FALSE;
if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
return -3;
assert(decoder);
assert(hdl);
if (hdl->subwin)
{
XDestroyWindow(hdl->disp, hdl->subwin);
XSync(hdl->disp, FALSE);
}
hdl->subwin = 0;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
/*
* FreeRDP: A Remote Desktop Protocol Implementation
* Video Redirection Virtual Channel - GStreamer Decoder
* platform specific functions
*
* (C) Copyright 2014 Thincast Technologies GmbH
* (C) Copyright 2014 Armin Novak <armin.novak@thincast.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 _TSMF_PLATFORM_H_
#define _TSMF_PLATFORM_H_
#include <gst/gst.h>
#include <tsmf_decoder.h>
typedef struct _TSMFGstreamerDecoder
{
ITSMFDecoder iface;
int media_type; /* TSMF_MAJOR_TYPE_AUDIO or TSMF_MAJOR_TYPE_VIDEO */
gint64 duration;
GstState state;
GstCaps *gst_caps;
GstElement *pipe;
GstElement *src;
GstElement *outsink;
GstElement *volume;
BOOL ready;
BOOL paused;
UINT64 last_sample_end_time;
double gstVolume;
BOOL gstMuted;
int pipeline_start_time_valid; /* We've set the start time and have not reset the pipeline */
int shutdown; /* The decoder stream is shutting down */
void *platform;
BOOL (*ack_cb)(void *,BOOL);
void (*sync_cb)(void *);
void *stream;
} TSMFGstreamerDecoder;
const char *get_type(TSMFGstreamerDecoder *mdecoder);
const char *tsmf_platform_get_video_sink(void);
const char *tsmf_platform_get_audio_sink(void);
int tsmf_platform_create(TSMFGstreamerDecoder *decoder);
int tsmf_platform_set_format(TSMFGstreamerDecoder *decoder);
int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder);
int tsmf_platform_free(TSMFGstreamerDecoder *decoder);
int tsmf_window_create(TSMFGstreamerDecoder *decoder);
int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y,
int width, int height, int nr_rect, RDP_RECT *visible);
int tsmf_window_destroy(TSMFGstreamerDecoder *decoder);
int tsmf_window_pause(TSMFGstreamerDecoder *decoder);
int tsmf_window_resume(TSMFGstreamerDecoder *decoder);
BOOL tsmf_gstreamer_add_pad(TSMFGstreamerDecoder *mdecoder);
void tsmf_gstreamer_remove_pad(TSMFGstreamerDecoder *mdecoder);
#endif

View File

@ -47,23 +47,20 @@ static void tsmf_pulse_context_state_callback(pa_context* context, void* userdat
{ {
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata; TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata;
pa_context_state_t state; pa_context_state_t state;
state = pa_context_get_state(context); state = pa_context_get_state(context);
switch(state) switch(state)
{ {
case PA_CONTEXT_READY: case PA_CONTEXT_READY:
DEBUG_DVC("PA_CONTEXT_READY"); DEBUG_TSMF("PA_CONTEXT_READY");
pa_threaded_mainloop_signal(pulse->mainloop, 0); pa_threaded_mainloop_signal(pulse->mainloop, 0);
break; break;
case PA_CONTEXT_FAILED: case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED: case PA_CONTEXT_TERMINATED:
DEBUG_DVC("state %d", (int)state); DEBUG_TSMF("state %d", (int)state);
pa_threaded_mainloop_signal(pulse->mainloop, 0); pa_threaded_mainloop_signal(pulse->mainloop, 0);
break; break;
default: default:
DEBUG_DVC("state %d", (int)state); DEBUG_TSMF("state %d", (int)state);
break; break;
} }
} }
@ -71,10 +68,8 @@ static void tsmf_pulse_context_state_callback(pa_context* context, void* userdat
static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice *pulse) static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice *pulse)
{ {
pa_context_state_t state; pa_context_state_t state;
if(!pulse->context) if(!pulse->context)
return FALSE; return FALSE;
if(pa_context_connect(pulse->context, NULL, 0, NULL)) if(pa_context_connect(pulse->context, NULL, 0, NULL))
{ {
DEBUG_WARN("pa_context_connect failed (%d)", DEBUG_WARN("pa_context_connect failed (%d)",
@ -96,7 +91,7 @@ static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice* pulse)
break; break;
if(!PA_CONTEXT_IS_GOOD(state)) if(!PA_CONTEXT_IS_GOOD(state))
{ {
DEBUG_DVC("bad context state (%d)", DEBUG_TSMF("bad context state (%d)",
pa_context_errno(pulse->context)); pa_context_errno(pulse->context));
break; break;
} }
@ -105,7 +100,7 @@ static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice* pulse)
pa_threaded_mainloop_unlock(pulse->mainloop); pa_threaded_mainloop_unlock(pulse->mainloop);
if(state == PA_CONTEXT_READY) if(state == PA_CONTEXT_READY)
{ {
DEBUG_DVC("connected"); DEBUG_TSMF("connected");
return TRUE; return TRUE;
} }
else else
@ -118,12 +113,10 @@ static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice* pulse)
static BOOL tsmf_pulse_open(ITSMFAudioDevice *audio, const char *device) static BOOL tsmf_pulse_open(ITSMFAudioDevice *audio, const char *device)
{ {
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio; TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
if(device) if(device)
{ {
strcpy(pulse->device, device); strcpy(pulse->device, device);
} }
pulse->mainloop = pa_threaded_mainloop_new(); pulse->mainloop = pa_threaded_mainloop_new();
if(!pulse->mainloop) if(!pulse->mainloop)
{ {
@ -142,15 +135,13 @@ static BOOL tsmf_pulse_open(ITSMFAudioDevice* audio, const char* device)
DEBUG_WARN("tsmf_pulse_connect failed"); DEBUG_WARN("tsmf_pulse_connect failed");
return FALSE; return FALSE;
} }
DEBUG_TSMF("open device %s", pulse->device);
DEBUG_DVC("open device %s", pulse->device);
return TRUE; return TRUE;
} }
static void tsmf_pulse_stream_success_callback(pa_stream *stream, int success, void *userdata) static void tsmf_pulse_stream_success_callback(pa_stream *stream, int success, void *userdata)
{ {
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata; TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata;
pa_threaded_mainloop_signal(pulse->mainloop, 0); pa_threaded_mainloop_signal(pulse->mainloop, 0);
} }
@ -169,23 +160,20 @@ static void tsmf_pulse_stream_state_callback(pa_stream* stream, void* userdata)
{ {
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata; TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata;
pa_stream_state_t state; pa_stream_state_t state;
state = pa_stream_get_state(stream); state = pa_stream_get_state(stream);
switch(state) switch(state)
{ {
case PA_STREAM_READY: case PA_STREAM_READY:
DEBUG_DVC("PA_STREAM_READY"); DEBUG_TSMF("PA_STREAM_READY");
pa_threaded_mainloop_signal(pulse->mainloop, 0); pa_threaded_mainloop_signal(pulse->mainloop, 0);
break; break;
case PA_STREAM_FAILED: case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED: case PA_STREAM_TERMINATED:
DEBUG_DVC("state %d", (int)state); DEBUG_TSMF("state %d", (int)state);
pa_threaded_mainloop_signal(pulse->mainloop, 0); pa_threaded_mainloop_signal(pulse->mainloop, 0);
break; break;
default: default:
DEBUG_DVC("state %d", (int)state); DEBUG_TSMF("state %d", (int)state);
break; break;
} }
} }
@ -193,9 +181,7 @@ static void tsmf_pulse_stream_state_callback(pa_stream* stream, void* userdata)
static void tsmf_pulse_stream_request_callback(pa_stream *stream, size_t length, void *userdata) static void tsmf_pulse_stream_request_callback(pa_stream *stream, size_t length, void *userdata)
{ {
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata; TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata;
DEBUG_TSMF("%d", (int) length);
DEBUG_DVC("%d", (int) length);
pa_threaded_mainloop_signal(pulse->mainloop, 0); pa_threaded_mainloop_signal(pulse->mainloop, 0);
} }
@ -203,9 +189,7 @@ static BOOL tsmf_pulse_close_stream(TSMFPulseAudioDevice* pulse)
{ {
if(!pulse->context || !pulse->stream) if(!pulse->context || !pulse->stream)
return FALSE; return FALSE;
DEBUG_TSMF("");
DEBUG_DVC("");
pa_threaded_mainloop_lock(pulse->mainloop); pa_threaded_mainloop_lock(pulse->mainloop);
pa_stream_set_write_callback(pulse->stream, NULL, NULL); pa_stream_set_write_callback(pulse->stream, NULL, NULL);
tsmf_pulse_wait_for_operation(pulse, tsmf_pulse_wait_for_operation(pulse,
@ -214,7 +198,6 @@ static BOOL tsmf_pulse_close_stream(TSMFPulseAudioDevice* pulse)
pa_stream_unref(pulse->stream); pa_stream_unref(pulse->stream);
pulse->stream = NULL; pulse->stream = NULL;
pa_threaded_mainloop_unlock(pulse->mainloop); pa_threaded_mainloop_unlock(pulse->mainloop);
return TRUE; return TRUE;
} }
@ -222,12 +205,9 @@ static BOOL tsmf_pulse_open_stream(TSMFPulseAudioDevice* pulse)
{ {
pa_stream_state_t state; pa_stream_state_t state;
pa_buffer_attr buffer_attr = { 0 }; pa_buffer_attr buffer_attr = { 0 };
if(!pulse->context) if(!pulse->context)
return FALSE; return FALSE;
DEBUG_TSMF("");
DEBUG_DVC("");
pa_threaded_mainloop_lock(pulse->mainloop); pa_threaded_mainloop_lock(pulse->mainloop);
pulse->stream = pa_stream_new(pulse->context, "freerdp", pulse->stream = pa_stream_new(pulse->context, "freerdp",
&pulse->sample_spec, NULL); &pulse->sample_spec, NULL);
@ -257,7 +237,6 @@ static BOOL tsmf_pulse_open_stream(TSMFPulseAudioDevice* pulse)
pa_context_errno(pulse->context)); pa_context_errno(pulse->context));
return FALSE; return FALSE;
} }
for(;;) for(;;)
{ {
state = pa_stream_get_state(pulse->stream); state = pa_stream_get_state(pulse->stream);
@ -274,7 +253,7 @@ static BOOL tsmf_pulse_open_stream(TSMFPulseAudioDevice* pulse)
pa_threaded_mainloop_unlock(pulse->mainloop); pa_threaded_mainloop_unlock(pulse->mainloop);
if(state == PA_STREAM_READY) if(state == PA_STREAM_READY)
{ {
DEBUG_DVC("connected"); DEBUG_TSMF("connected");
return TRUE; return TRUE;
} }
else else
@ -288,14 +267,11 @@ static BOOL tsmf_pulse_set_format(ITSMFAudioDevice* audio,
UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample) UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample)
{ {
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio; TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
DEBUG_TSMF("sample_rate %d channels %d bits_per_sample %d",
DEBUG_DVC("sample_rate %d channels %d bits_per_sample %d",
sample_rate, channels, bits_per_sample); sample_rate, channels, bits_per_sample);
pulse->sample_spec.rate = sample_rate; pulse->sample_spec.rate = sample_rate;
pulse->sample_spec.channels = channels; pulse->sample_spec.channels = channels;
pulse->sample_spec.format = PA_SAMPLE_S16LE; pulse->sample_spec.format = PA_SAMPLE_S16LE;
return tsmf_pulse_open_stream(pulse); return tsmf_pulse_open_stream(pulse);
} }
@ -305,19 +281,16 @@ static BOOL tsmf_pulse_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_siz
BYTE *src; BYTE *src;
int len; int len;
int ret; int ret;
DEBUG_TSMF("data_size %d", data_size);
DEBUG_DVC("data_size %d", data_size);
if(pulse->stream) if(pulse->stream)
{ {
pa_threaded_mainloop_lock(pulse->mainloop); pa_threaded_mainloop_lock(pulse->mainloop);
src = data; src = data;
while(data_size > 0) while(data_size > 0)
{ {
while((len = pa_stream_writable_size(pulse->stream)) == 0) while((len = pa_stream_writable_size(pulse->stream)) == 0)
{ {
DEBUG_DVC("waiting"); DEBUG_TSMF("waiting");
pa_threaded_mainloop_wait(pulse->mainloop); pa_threaded_mainloop_wait(pulse->mainloop);
} }
if(len < 0) if(len < 0)
@ -327,18 +300,16 @@ static BOOL tsmf_pulse_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_siz
ret = pa_stream_write(pulse->stream, src, len, NULL, 0LL, PA_SEEK_RELATIVE); ret = pa_stream_write(pulse->stream, src, len, NULL, 0LL, PA_SEEK_RELATIVE);
if(ret < 0) if(ret < 0)
{ {
DEBUG_DVC("pa_stream_write failed (%d)", DEBUG_TSMF("pa_stream_write failed (%d)",
pa_context_errno(pulse->context)); pa_context_errno(pulse->context));
break; break;
} }
src += len; src += len;
data_size -= len; data_size -= len;
} }
pa_threaded_mainloop_unlock(pulse->mainloop); pa_threaded_mainloop_unlock(pulse->mainloop);
} }
free(data); free(data);
return TRUE; return TRUE;
} }
@ -347,7 +318,6 @@ static UINT64 tsmf_pulse_get_latency(ITSMFAudioDevice* audio)
pa_usec_t usec; pa_usec_t usec;
UINT64 latency = 0; UINT64 latency = 0;
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio; TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
if(pulse->stream && pa_stream_get_latency(pulse->stream, &usec, NULL) == 0) if(pulse->stream && pa_stream_get_latency(pulse->stream, &usec, NULL) == 0)
{ {
latency = ((UINT64)usec) * 10LL; latency = ((UINT64)usec) * 10LL;
@ -358,7 +328,6 @@ static UINT64 tsmf_pulse_get_latency(ITSMFAudioDevice* audio)
static void tsmf_pulse_flush(ITSMFAudioDevice *audio) static void tsmf_pulse_flush(ITSMFAudioDevice *audio)
{ {
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio; TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
pa_threaded_mainloop_lock(pulse->mainloop); pa_threaded_mainloop_lock(pulse->mainloop);
tsmf_pulse_wait_for_operation(pulse, tsmf_pulse_wait_for_operation(pulse,
pa_stream_flush(pulse->stream, tsmf_pulse_stream_success_callback, pulse)); pa_stream_flush(pulse->stream, tsmf_pulse_stream_success_callback, pulse));
@ -368,9 +337,7 @@ static void tsmf_pulse_flush(ITSMFAudioDevice* audio)
static void tsmf_pulse_free(ITSMFAudioDevice *audio) static void tsmf_pulse_free(ITSMFAudioDevice *audio)
{ {
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio; TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
DEBUG_TSMF("");
DEBUG_DVC("");
tsmf_pulse_close_stream(pulse); tsmf_pulse_close_stream(pulse);
if(pulse->mainloop) if(pulse->mainloop)
{ {
@ -397,17 +364,14 @@ static void tsmf_pulse_free(ITSMFAudioDevice* audio)
ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void) ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)
{ {
TSMFPulseAudioDevice *pulse; TSMFPulseAudioDevice *pulse;
pulse = (TSMFPulseAudioDevice *) malloc(sizeof(TSMFPulseAudioDevice)); pulse = (TSMFPulseAudioDevice *) malloc(sizeof(TSMFPulseAudioDevice));
ZeroMemory(pulse, sizeof(TSMFPulseAudioDevice)); ZeroMemory(pulse, sizeof(TSMFPulseAudioDevice));
pulse->iface.Open = tsmf_pulse_open; pulse->iface.Open = tsmf_pulse_open;
pulse->iface.SetFormat = tsmf_pulse_set_format; pulse->iface.SetFormat = tsmf_pulse_set_format;
pulse->iface.Play = tsmf_pulse_play; pulse->iface.Play = tsmf_pulse_play;
pulse->iface.GetLatency = tsmf_pulse_get_latency; pulse->iface.GetLatency = tsmf_pulse_get_latency;
pulse->iface.Flush = tsmf_pulse_flush; pulse->iface.Flush = tsmf_pulse_flush;
pulse->iface.Free = tsmf_pulse_free; pulse->iface.Free = tsmf_pulse_free;
return (ITSMFAudioDevice *) pulse; return (ITSMFAudioDevice *) pulse;
} }

View File

@ -261,9 +261,8 @@ static const TSMFMediaTypeMap tsmf_format_type_map[] =
static void tsmf_print_guid(const BYTE *guid) static void tsmf_print_guid(const BYTE *guid)
{ {
#ifdef WITH_DEBUG_DVC #ifdef WITH_DEBUG_TSMF
int i; int i;
for(i = 3; i >= 0; i--) for(i = 3; i >= 0; i--)
fprintf(stderr, "%02X", guid[i]); fprintf(stderr, "%02X", guid[i]);
fprintf(stderr, "-"); fprintf(stderr, "-");
@ -289,21 +288,17 @@ static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wSt
UINT32 biSize; UINT32 biSize;
UINT32 biWidth; UINT32 biWidth;
UINT32 biHeight; UINT32 biHeight;
Stream_Read_UINT32(s, biSize); Stream_Read_UINT32(s, biSize);
Stream_Read_UINT32(s, biWidth); Stream_Read_UINT32(s, biWidth);
Stream_Read_UINT32(s, biHeight); Stream_Read_UINT32(s, biHeight);
Stream_Seek(s, 28); Stream_Seek(s, 28);
if(mediatype->Width == 0) if(mediatype->Width == 0)
mediatype->Width = biWidth; mediatype->Width = biWidth;
if(mediatype->Height == 0) if(mediatype->Height == 0)
mediatype->Height = biHeight; mediatype->Height = biHeight;
/* Assume there will be no color table for video? */ /* Assume there will be no color table for video? */
if(bypass && biSize > 40) if(bypass && biSize > 40)
Stream_Seek(s, biSize - 40); Stream_Seek(s, biSize - 40);
return (bypass ? biSize : 40); return (bypass ? biSize : 40);
} }
@ -311,7 +306,6 @@ static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wSt
static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE *mediatype, wStream *s) static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE *mediatype, wStream *s)
{ {
UINT64 AvgTimePerFrame; UINT64 AvgTimePerFrame;
/* VIDEOINFOHEADER2.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */ /* VIDEOINFOHEADER2.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
Stream_Seek_UINT32(s); Stream_Seek_UINT32(s);
Stream_Seek_UINT32(s); Stream_Seek_UINT32(s);
@ -329,7 +323,6 @@ static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, wSt
mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL); mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL);
/* Remaining fields before bmiHeader */ /* Remaining fields before bmiHeader */
Stream_Seek(s, 24); Stream_Seek(s, 24);
return 72; return 72;
} }
@ -347,7 +340,6 @@ typedef struct tagVIDEOINFOHEADER {
} VIDEOINFOHEADER; } VIDEOINFOHEADER;
*/ */
UINT64 AvgTimePerFrame; UINT64 AvgTimePerFrame;
/* VIDEOINFOHEADER.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */ /* VIDEOINFOHEADER.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
Stream_Seek_UINT32(s); Stream_Seek_UINT32(s);
Stream_Seek_UINT32(s); Stream_Seek_UINT32(s);
@ -363,7 +355,6 @@ typedef struct tagVIDEOINFOHEADER {
Stream_Read_UINT64(s, AvgTimePerFrame); Stream_Read_UINT64(s, AvgTimePerFrame);
mediatype->SamplesPerSecond.Numerator = 1000000; mediatype->SamplesPerSecond.Numerator = 1000000;
mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL); mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL);
return 48; return 48;
} }
@ -372,11 +363,9 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
int i; int i;
UINT32 cbFormat; UINT32 cbFormat;
BOOL ret = TRUE; BOOL ret = TRUE;
memset(mediatype, 0, sizeof(TS_AM_MEDIA_TYPE)); memset(mediatype, 0, sizeof(TS_AM_MEDIA_TYPE));
/* MajorType */ /* MajorType */
DEBUG_DVC("MajorType:"); DEBUG_TSMF("MajorType:");
tsmf_print_guid(Stream_Pointer(s)); tsmf_print_guid(Stream_Pointer(s));
for(i = 0; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++) for(i = 0; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++)
{ {
@ -386,11 +375,10 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
mediatype->MajorType = tsmf_major_type_map[i].type; mediatype->MajorType = tsmf_major_type_map[i].type;
if(mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN) if(mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
ret = FALSE; ret = FALSE;
DEBUG_DVC("MajorType %s", tsmf_major_type_map[i].name); DEBUG_TSMF("MajorType %s", tsmf_major_type_map[i].name);
Stream_Seek(s, 16); Stream_Seek(s, 16);
/* SubType */ /* SubType */
DEBUG_DVC("SubType:"); DEBUG_TSMF("SubType:");
tsmf_print_guid(Stream_Pointer(s)); tsmf_print_guid(Stream_Pointer(s));
for(i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++) for(i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++)
{ {
@ -400,14 +388,12 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
mediatype->SubType = tsmf_sub_type_map[i].type; mediatype->SubType = tsmf_sub_type_map[i].type;
if(mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN) if(mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
ret = FALSE; ret = FALSE;
DEBUG_DVC("SubType %s", tsmf_sub_type_map[i].name); DEBUG_TSMF("SubType %s", tsmf_sub_type_map[i].name);
Stream_Seek(s, 16); Stream_Seek(s, 16);
/* bFixedSizeSamples, bTemporalCompression, SampleSize */ /* bFixedSizeSamples, bTemporalCompression, SampleSize */
Stream_Seek(s, 12); Stream_Seek(s, 12);
/* FormatType */ /* FormatType */
DEBUG_DVC("FormatType:"); DEBUG_TSMF("FormatType:");
tsmf_print_guid(Stream_Pointer(s)); tsmf_print_guid(Stream_Pointer(s));
for(i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++) for(i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++)
{ {
@ -417,22 +403,18 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
mediatype->FormatType = tsmf_format_type_map[i].type; mediatype->FormatType = tsmf_format_type_map[i].type;
if(mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN) if(mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
ret = FALSE; ret = FALSE;
DEBUG_DVC("FormatType %s", tsmf_format_type_map[i].name); DEBUG_TSMF("FormatType %s", tsmf_format_type_map[i].name);
Stream_Seek(s, 16); Stream_Seek(s, 16);
/* cbFormat */ /* cbFormat */
Stream_Read_UINT32(s, cbFormat); Stream_Read_UINT32(s, cbFormat);
DEBUG_DVC("cbFormat %d", cbFormat); DEBUG_TSMF("cbFormat %d", cbFormat);
#ifdef WITH_DEBUG_TSMF
#ifdef WITH_DEBUG_DVC
winpr_HexDump(Stream_Pointer(s), cbFormat); winpr_HexDump(Stream_Pointer(s), cbFormat);
#endif #endif
switch(mediatype->FormatType) switch(mediatype->FormatType)
{ {
case TSMF_FORMAT_TYPE_MFVIDEOFORMAT: case TSMF_FORMAT_TYPE_MFVIDEOFORMAT:
/* http://msdn.microsoft.com/en-us/library/aa473808.aspx */ /* http://msdn.microsoft.com/en-us/library/aa473808.aspx */
Stream_Seek(s, 8); /* dwSize and ? */ Stream_Seek(s, 8); /* dwSize and ? */
Stream_Read_UINT32(s, mediatype->Width); /* videoInfo.dwWidth */ Stream_Read_UINT32(s, mediatype->Width); /* videoInfo.dwWidth */
Stream_Read_UINT32(s, mediatype->Height); /* videoInfo.dwHeight */ Stream_Read_UINT32(s, mediatype->Height); /* videoInfo.dwHeight */
@ -443,17 +425,14 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
Stream_Seek(s, 80); Stream_Seek(s, 80);
Stream_Read_UINT32(s, mediatype->BitRate); /* compressedInfo.AvgBitrate */ Stream_Read_UINT32(s, mediatype->BitRate); /* compressedInfo.AvgBitrate */
Stream_Seek(s, 36); Stream_Seek(s, 36);
if(cbFormat > 176) if(cbFormat > 176)
{ {
mediatype->ExtraDataSize = cbFormat - 176; mediatype->ExtraDataSize = cbFormat - 176;
mediatype->ExtraData = Stream_Pointer(s); mediatype->ExtraData = Stream_Pointer(s);
} }
break; break;
case TSMF_FORMAT_TYPE_WAVEFORMATEX: case TSMF_FORMAT_TYPE_WAVEFORMATEX:
/* http://msdn.microsoft.com/en-us/library/dd757720.aspx */ /* http://msdn.microsoft.com/en-us/library/dd757720.aspx */
Stream_Seek_UINT16(s); Stream_Seek_UINT16(s);
Stream_Read_UINT16(s, mediatype->Channels); Stream_Read_UINT16(s, mediatype->Channels);
Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator); Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator);
@ -465,12 +444,9 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
Stream_Read_UINT16(s, mediatype->ExtraDataSize); Stream_Read_UINT16(s, mediatype->ExtraDataSize);
if(mediatype->ExtraDataSize > 0) if(mediatype->ExtraDataSize > 0)
mediatype->ExtraData = Stream_Pointer(s); mediatype->ExtraData = Stream_Pointer(s);
break; break;
case TSMF_FORMAT_TYPE_MPEG1VIDEOINFO: case TSMF_FORMAT_TYPE_MPEG1VIDEOINFO:
/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */ /* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
i = tsmf_codec_parse_VIDEOINFOHEADER(mediatype, s); i = tsmf_codec_parse_VIDEOINFOHEADER(mediatype, s);
i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE); i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
if(cbFormat > i) if(cbFormat > i)
@ -479,10 +455,8 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
mediatype->ExtraData = Stream_Pointer(s); mediatype->ExtraData = Stream_Pointer(s);
} }
break; break;
case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO: case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO:
/* http://msdn.microsoft.com/en-us/library/dd390707.aspx */ /* http://msdn.microsoft.com/en-us/library/dd390707.aspx */
i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s); i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE); i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
if(cbFormat > i) if(cbFormat > i)
@ -491,7 +465,6 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
mediatype->ExtraData = Stream_Pointer(s); mediatype->ExtraData = Stream_Pointer(s);
} }
break; break;
case TSMF_FORMAT_TYPE_VIDEOINFO2: case TSMF_FORMAT_TYPE_VIDEOINFO2:
i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s); i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, FALSE); i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, FALSE);
@ -501,16 +474,13 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
mediatype->ExtraData = Stream_Pointer(s); mediatype->ExtraData = Stream_Pointer(s);
} }
break; break;
default: default:
break; break;
} }
if(mediatype->SamplesPerSecond.Numerator == 0) if(mediatype->SamplesPerSecond.Numerator == 0)
mediatype->SamplesPerSecond.Numerator = 1; mediatype->SamplesPerSecond.Numerator = 1;
if(mediatype->SamplesPerSecond.Denominator == 0) if(mediatype->SamplesPerSecond.Denominator == 0)
mediatype->SamplesPerSecond.Denominator = 1; mediatype->SamplesPerSecond.Denominator = 1;
return ret; return ret;
} }
@ -519,10 +489,8 @@ BOOL tsmf_codec_check_media_type(wStream* s)
BYTE *m; BYTE *m;
BOOL ret; BOOL ret;
TS_AM_MEDIA_TYPE mediatype; TS_AM_MEDIA_TYPE mediatype;
Stream_GetPointer(s, m); Stream_GetPointer(s, m);
ret = tsmf_codec_parse_media_type(&mediatype, s); ret = tsmf_codec_parse_media_type(&mediatype, s);
Stream_SetPointer(s, m); Stream_SetPointer(s, m);
return ret; return ret;
} }

View File

@ -36,41 +36,37 @@ static ITSMFDecoder* tsmf_load_decoder_by_name(const char* name, TS_AM_MEDIA_TYP
{ {
ITSMFDecoder *decoder; ITSMFDecoder *decoder;
TSMF_DECODER_ENTRY entry; TSMF_DECODER_ENTRY entry;
entry = (TSMF_DECODER_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "decoder", 0); entry = (TSMF_DECODER_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "decoder", 0);
if(entry == NULL) if(entry == NULL)
return NULL; return NULL;
decoder = entry(); decoder = entry();
if(decoder == NULL) if(decoder == NULL)
{ {
DEBUG_WARN("failed to call export function in %s", name); DEBUG_WARN("failed to call export function in %s", name);
return NULL; return NULL;
} }
if(!decoder->SetFormat(decoder, media_type)) if(!decoder->SetFormat(decoder, media_type))
{ {
decoder->Free(decoder); decoder->Free(decoder);
decoder = NULL; decoder = NULL;
} }
return decoder; return decoder;
} }
ITSMFDecoder *tsmf_load_decoder(const char *name, TS_AM_MEDIA_TYPE *media_type) ITSMFDecoder *tsmf_load_decoder(const char *name, TS_AM_MEDIA_TYPE *media_type)
{ {
ITSMFDecoder* decoder; ITSMFDecoder *decoder = NULL;
if(name) if(name)
{ {
decoder = tsmf_load_decoder_by_name(name, media_type); decoder = tsmf_load_decoder_by_name(name, media_type);
} }
else #if defined(WITH_GSTREAMER_1_0) || defined(WITH_GSTREAMER_0_10)
{ if(!decoder)
decoder = tsmf_load_decoder_by_name("gstreamer", media_type);
#endif
#if defined(WITH_FFMPEG)
if(!decoder)
decoder = tsmf_load_decoder_by_name("ffmpeg", media_type); decoder = tsmf_load_decoder_by_name("ffmpeg", media_type);
} #endif
return decoder; return decoder;
} }

View File

@ -26,9 +26,8 @@
typedef enum _ITSMFControlMsg typedef enum _ITSMFControlMsg
{ {
Control_Pause, Control_Pause,
Control_Restart, Control_Resume,
Control_Flush, Control_Stop
Control_EndOfStream
} ITSMFControlMsg; } ITSMFControlMsg;
typedef struct _ITSMFDecoder ITSMFDecoder; typedef struct _ITSMFDecoder ITSMFDecoder;
@ -59,7 +58,11 @@ struct _ITSMFDecoder
/* Change Gstreamer Audio Volume */ /* Change Gstreamer Audio Volume */
void (*ChangeVolume)(ITSMFDecoder *decoder, UINT32 newVolume, UINT32 muted); void (*ChangeVolume)(ITSMFDecoder *decoder, UINT32 newVolume, UINT32 muted);
/* Check buffer level */ /* Check buffer level */
UINT32 (*BufferLevel) (ITSMFDecoder * decoder); BOOL (*BufferFilled)(ITSMFDecoder *decoder);
/* Register a callback for frame ack. */
BOOL (*SetAckFunc)(ITSMFDecoder *decoder, BOOL (*cb)(void *,BOOL), void *stream);
/* Register a callback for stream seek detection. */
BOOL (*SetSyncFunc)(ITSMFDecoder *decoder, void (*cb)(void *), void *stream);
}; };
#define TSMF_DECODER_EXPORT_FUNC_NAME "TSMFDecoderEntry" #define TSMF_DECODER_EXPORT_FUNC_NAME "TSMFDecoderEntry"

View File

@ -40,14 +40,11 @@
int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN *ifman) int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN *ifman)
{ {
UINT32 CapabilityValue; UINT32 CapabilityValue;
Stream_Read_UINT32(ifman->input, CapabilityValue); Stream_Read_UINT32(ifman->input, CapabilityValue);
DEBUG_DVC("server CapabilityValue %d", CapabilityValue); DEBUG_TSMF("server CapabilityValue %d", CapabilityValue);
Stream_EnsureRemainingCapacity(ifman->output, 8); Stream_EnsureRemainingCapacity(ifman->output, 8);
Stream_Write_UINT32(ifman->output, 1); /* CapabilityValue */ Stream_Write_UINT32(ifman->output, 1); /* CapabilityValue */
Stream_Write_UINT32(ifman->output, 0); /* Result */ Stream_Write_UINT32(ifman->output, 0); /* Result */
return 0; return 0;
} }
@ -59,29 +56,25 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
UINT32 CapabilityType; UINT32 CapabilityType;
UINT32 cbCapabilityLength; UINT32 cbCapabilityLength;
UINT32 numHostCapabilities; UINT32 numHostCapabilities;
pos = Stream_GetPosition(ifman->output); pos = Stream_GetPosition(ifman->output);
Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4); Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4);
Stream_Copy(ifman->output, ifman->input, ifman->input_size); Stream_Copy(ifman->output, ifman->input, ifman->input_size);
Stream_SetPosition(ifman->output, pos); Stream_SetPosition(ifman->output, pos);
Stream_Read_UINT32(ifman->output, numHostCapabilities); Stream_Read_UINT32(ifman->output, numHostCapabilities);
for(i = 0; i < numHostCapabilities; i++) for(i = 0; i < numHostCapabilities; i++)
{ {
Stream_Read_UINT32(ifman->output, CapabilityType); Stream_Read_UINT32(ifman->output, CapabilityType);
Stream_Read_UINT32(ifman->output, cbCapabilityLength); Stream_Read_UINT32(ifman->output, cbCapabilityLength);
pos = Stream_GetPosition(ifman->output); pos = Stream_GetPosition(ifman->output);
switch(CapabilityType) switch(CapabilityType)
{ {
case 1: /* Protocol version request */ case 1: /* Protocol version request */
Stream_Read_UINT32(ifman->output, v); Stream_Read_UINT32(ifman->output, v);
DEBUG_DVC("server protocol version %d", v); DEBUG_TSMF("server protocol version %d", v);
break; break;
case 2: /* Supported platform */ case 2: /* Supported platform */
Stream_Peek_UINT32(ifman->output, v); Stream_Peek_UINT32(ifman->output, v);
DEBUG_DVC("server supported platform %d", v); DEBUG_TSMF("server supported platform %d", v);
/* Claim that we support both MF and DShow platforms. */ /* Claim that we support both MF and DShow platforms. */
Stream_Write_UINT32(ifman->output, Stream_Write_UINT32(ifman->output,
MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW); MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW);
@ -93,9 +86,7 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
Stream_SetPosition(ifman->output, pos + cbCapabilityLength); Stream_SetPosition(ifman->output, pos + cbCapabilityLength);
} }
Stream_Write_UINT32(ifman->output, 0); /* Result */ Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0; return 0;
} }
@ -104,26 +95,19 @@ int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
UINT32 numMediaType; UINT32 numMediaType;
UINT32 PlatformCookie; UINT32 PlatformCookie;
UINT32 FormatSupported = 1; UINT32 FormatSupported = 1;
Stream_Read_UINT32(ifman->input, PlatformCookie); Stream_Read_UINT32(ifman->input, PlatformCookie);
Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */ Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */
Stream_Read_UINT32(ifman->input, numMediaType); Stream_Read_UINT32(ifman->input, numMediaType);
DEBUG_TSMF("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType);
DEBUG_DVC("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType);
if(!tsmf_codec_check_media_type(ifman->input)) if(!tsmf_codec_check_media_type(ifman->input))
FormatSupported = 0; FormatSupported = 0;
if(FormatSupported) if(FormatSupported)
DEBUG_DVC("format ok."); DEBUG_TSMF("format ok.");
Stream_EnsureRemainingCapacity(ifman->output, 12); Stream_EnsureRemainingCapacity(ifman->output, 12);
Stream_Write_UINT32(ifman->output, FormatSupported); Stream_Write_UINT32(ifman->output, FormatSupported);
Stream_Write_UINT32(ifman->output, PlatformCookie); Stream_Write_UINT32(ifman->output, PlatformCookie);
Stream_Write_UINT32(ifman->output, 0); /* Result */ Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0; return 0;
} }
@ -131,27 +115,20 @@ int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
{ {
int status = 0; int status = 0;
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
DEBUG_DVC("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation) if(presentation)
{ {
DEBUG_DVC("Presentation already exists"); DEBUG_TSMF("Presentation already exists");
ifman->output_pending = FALSE; ifman->output_pending = FALSE;
return 0; return 0;
} }
presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback); presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback);
if(presentation == NULL) if(presentation == NULL)
status = 1; status = 1;
else else
tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device); tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device);
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return status; return status;
} }
@ -161,12 +138,9 @@ int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
int status = 0; int status = 0;
TSMF_STREAM *stream; TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
DEBUG_DVC("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16); Stream_Seek(ifman->input, 16);
if(presentation == NULL) if(presentation == NULL)
{ {
status = 1; status = 1;
@ -176,25 +150,20 @@ int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
Stream_Read_UINT32(ifman->input, StreamId); Stream_Read_UINT32(ifman->input, StreamId);
Stream_Seek_UINT32(ifman->input); /* numMediaType */ Stream_Seek_UINT32(ifman->input); /* numMediaType */
stream = tsmf_stream_new(presentation, StreamId); stream = tsmf_stream_new(presentation, StreamId);
if(stream) if(stream)
tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input); tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input);
} }
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return status; return status;
} }
int tsmf_ifman_set_topology_request(TSMF_IFMAN *ifman) int tsmf_ifman_set_topology_request(TSMF_IFMAN *ifman)
{ {
DEBUG_DVC(""); DEBUG_TSMF("");
Stream_EnsureRemainingCapacity(ifman->output, 8); Stream_EnsureRemainingCapacity(ifman->output, 8);
Stream_Write_UINT32(ifman->output, 1); /* TopologyReady */ Stream_Write_UINT32(ifman->output, 1); /* TopologyReady */
Stream_Write_UINT32(ifman->output, 0); /* Result */ Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0; return 0;
} }
@ -204,12 +173,9 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
UINT32 StreamId; UINT32 StreamId;
TSMF_STREAM *stream; TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
DEBUG_DVC("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16); Stream_Seek(ifman->input, 16);
if(presentation == NULL) if(presentation == NULL)
{ {
status = 1; status = 1;
@ -223,9 +189,7 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
else else
status = 1; status = 1;
} }
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return status; return status;
} }
@ -233,10 +197,8 @@ float tsmf_stream_read_float(wStream* s)
{ {
float fValue; float fValue;
UINT32 iValue; UINT32 iValue;
Stream_Read_UINT32(s, iValue); Stream_Read_UINT32(s, iValue);
CopyMemory(&fValue, &iValue, 4); CopyMemory(&fValue, &iValue, 4);
return fValue; return fValue;
} }
@ -246,12 +208,9 @@ int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman)
float Left, Top; float Left, Top;
float Right, Bottom; float Right, Bottom;
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
DEBUG_DVC("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16); Stream_Seek(ifman->input, 16);
if(!presentation) if(!presentation)
{ {
status = 1; status = 1;
@ -262,94 +221,74 @@ int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman)
Top = tsmf_stream_read_float(ifman->input); /* Top (4 bytes) */ Top = tsmf_stream_read_float(ifman->input); /* Top (4 bytes) */
Right = tsmf_stream_read_float(ifman->input); /* Right (4 bytes) */ Right = tsmf_stream_read_float(ifman->input); /* Right (4 bytes) */
Bottom = tsmf_stream_read_float(ifman->input); /* Bottom (4 bytes) */ Bottom = tsmf_stream_read_float(ifman->input); /* Bottom (4 bytes) */
DEBUG_TSMF("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f",
DEBUG_DVC("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f",
Left, Top, Right, Bottom); Left, Top, Right, Bottom);
} }
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return status; return status;
} }
int tsmf_ifman_shutdown_presentation(TSMF_IFMAN *ifman) int tsmf_ifman_shutdown_presentation(TSMF_IFMAN *ifman)
{ {
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
DEBUG_DVC("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation) if(presentation)
tsmf_presentation_free(presentation); tsmf_presentation_free(presentation);
else else
DEBUG_WARN("unknown presentation id"); DEBUG_WARN("unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 4); Stream_EnsureRemainingCapacity(ifman->output, 4);
Stream_Write_UINT32(ifman->output, 0); /* Result */ Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0; return 0;
} }
int tsmf_ifman_on_stream_volume(TSMF_IFMAN *ifman) int tsmf_ifman_on_stream_volume(TSMF_IFMAN *ifman)
{ {
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("on stream volume");
DEBUG_DVC("on stream volume");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation) if(presentation)
{ {
UINT32 newVolume; UINT32 newVolume;
UINT32 muted; UINT32 muted;
Stream_Seek(ifman->input, 16); Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, newVolume); Stream_Read_UINT32(ifman->input, newVolume);
DEBUG_DVC("on stream volume: new volume=[%d]", newVolume); DEBUG_TSMF("on stream volume: new volume=[%d]", newVolume);
Stream_Read_UINT32(ifman->input, muted); Stream_Read_UINT32(ifman->input, muted);
DEBUG_DVC("on stream volume: muted=[%d]", muted); DEBUG_TSMF("on stream volume: muted=[%d]", muted);
tsmf_presentation_volume_changed(presentation, newVolume, muted); tsmf_presentation_volume_changed(presentation, newVolume, muted);
} }
else else
{ {
DEBUG_WARN("unknown presentation id"); DEBUG_WARN("unknown presentation id");
} }
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return 0; return 0;
} }
int tsmf_ifman_on_channel_volume(TSMF_IFMAN *ifman) int tsmf_ifman_on_channel_volume(TSMF_IFMAN *ifman)
{ {
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("on channel volume");
DEBUG_DVC("on channel volume");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation) if(presentation)
{ {
UINT32 channelVolume; UINT32 channelVolume;
UINT32 changedChannel; UINT32 changedChannel;
Stream_Seek(ifman->input, 16); Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, channelVolume); Stream_Read_UINT32(ifman->input, channelVolume);
DEBUG_DVC("on channel volume: channel volume=[%d]", channelVolume); DEBUG_TSMF("on channel volume: channel volume=[%d]", channelVolume);
Stream_Read_UINT32(ifman->input, changedChannel); Stream_Read_UINT32(ifman->input, changedChannel);
DEBUG_DVC("on stream volume: changed channel=[%d]", changedChannel); DEBUG_TSMF("on stream volume: changed channel=[%d]", changedChannel);
} }
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return 0; return 0;
} }
int tsmf_ifman_set_video_window(TSMF_IFMAN *ifman) int tsmf_ifman_set_video_window(TSMF_IFMAN *ifman)
{ {
DEBUG_DVC(""); DEBUG_TSMF("");
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return 0; return 0;
} }
@ -368,26 +307,20 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
int error = 0; int error = 0;
int i; int i;
int pos; int pos;
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16); Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, numGeometryInfo); Stream_Read_UINT32(ifman->input, numGeometryInfo);
pos = Stream_GetPosition(ifman->input); pos = Stream_GetPosition(ifman->input);
Stream_Seek(ifman->input, 12); /* VideoWindowId (8 bytes), VideoWindowState (4 bytes) */ Stream_Seek(ifman->input, 12); /* VideoWindowId (8 bytes), VideoWindowState (4 bytes) */
Stream_Read_UINT32(ifman->input, Width); Stream_Read_UINT32(ifman->input, Width);
Stream_Read_UINT32(ifman->input, Height); Stream_Read_UINT32(ifman->input, Height);
Stream_Read_UINT32(ifman->input, Left); Stream_Read_UINT32(ifman->input, Left);
Stream_Read_UINT32(ifman->input, Top); Stream_Read_UINT32(ifman->input, Top);
Stream_SetPosition(ifman->input, pos + numGeometryInfo); Stream_SetPosition(ifman->input, pos + numGeometryInfo);
Stream_Read_UINT32(ifman->input, cbVisibleRect); Stream_Read_UINT32(ifman->input, cbVisibleRect);
num_rects = cbVisibleRect / 16; num_rects = cbVisibleRect / 16;
DEBUG_TSMF("numGeometryInfo %d Width %d Height %d Left %d Top %d cbVisibleRect %d num_rects %d",
DEBUG_DVC("numGeometryInfo %d Width %d Height %d Left %d Top %d cbVisibleRect %d num_rects %d",
numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects); numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);
if(presentation == NULL) if(presentation == NULL)
{ {
error = 1; error = 1;
@ -398,7 +331,6 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
{ {
rects = (RDP_RECT *) malloc(sizeof(RDP_RECT) * num_rects); rects = (RDP_RECT *) malloc(sizeof(RDP_RECT) * num_rects);
ZeroMemory(rects, sizeof(RDP_RECT) * num_rects); ZeroMemory(rects, sizeof(RDP_RECT) * num_rects);
for(i = 0; i < num_rects; i++) for(i = 0; i < num_rects; i++)
{ {
Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */ Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */
@ -411,29 +343,26 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
Stream_Seek_UINT16(ifman->input); Stream_Seek_UINT16(ifman->input);
rects[i].width -= rects[i].x; rects[i].width -= rects[i].x;
rects[i].height -= rects[i].y; rects[i].height -= rects[i].y;
DEBUG_TSMF("rect %d: %d %d %d %d", i,
DEBUG_DVC("rect %d: %d %d %d %d", i,
rects[i].x, rects[i].y, rects[i].width, rects[i].height); rects[i].x, rects[i].y, rects[i].width, rects[i].height);
} }
} }
tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects); tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects);
} }
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return error; return error;
} }
int tsmf_ifman_set_allocator(TSMF_IFMAN *ifman) int tsmf_ifman_set_allocator(TSMF_IFMAN *ifman)
{ {
DEBUG_DVC(""); DEBUG_TSMF("");
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return 0; return 0;
} }
int tsmf_ifman_notify_preroll(TSMF_IFMAN *ifman) int tsmf_ifman_notify_preroll(TSMF_IFMAN *ifman)
{ {
DEBUG_DVC(""); DEBUG_TSMF("");
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return 0; return 0;
} }
@ -448,7 +377,6 @@ int tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
UINT64 ThrottleDuration; UINT64 ThrottleDuration;
UINT32 SampleExtensions; UINT32 SampleExtensions;
UINT32 cbData; UINT32 cbData;
Stream_Seek(ifman->input, 16); Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId); Stream_Read_UINT32(ifman->input, StreamId);
Stream_Seek_UINT32(ifman->input); /* numSample */ Stream_Seek_UINT32(ifman->input); /* numSample */
@ -458,34 +386,27 @@ int tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
Stream_Seek_UINT32(ifman->input); /* SampleFlags */ Stream_Seek_UINT32(ifman->input); /* SampleFlags */
Stream_Read_UINT32(ifman->input, SampleExtensions); Stream_Read_UINT32(ifman->input, SampleExtensions);
Stream_Read_UINT32(ifman->input, cbData); Stream_Read_UINT32(ifman->input, cbData);
DEBUG_TSMF("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d "
DEBUG_DVC("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d "
"ThrottleDuration %d SampleExtensions %d cbData %d", "ThrottleDuration %d SampleExtensions %d cbData %d",
ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime, ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime,
(int)ThrottleDuration, SampleExtensions, cbData); (int)ThrottleDuration, SampleExtensions, cbData);
presentation = tsmf_presentation_find_by_id(ifman->presentation_id); presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
if(presentation == NULL) if(presentation == NULL)
{ {
DEBUG_WARN("unknown presentation id"); DEBUG_WARN("unknown presentation id");
return 1; return 1;
} }
stream = tsmf_stream_find_by_id(presentation, StreamId); stream = tsmf_stream_find_by_id(presentation, StreamId);
if(stream == NULL) if(stream == NULL)
{ {
DEBUG_WARN("unknown stream id"); DEBUG_WARN("unknown stream id");
return 1; return 1;
} }
tsmf_stream_push_sample(stream, ifman->channel_callback, tsmf_stream_push_sample(stream, ifman->channel_callback,
ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions, ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions,
cbData, Stream_Pointer(ifman->input)); cbData, Stream_Pointer(ifman->input));
tsmf_presentation_sync(presentation);
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return 0; return 0;
} }
@ -493,23 +414,17 @@ int tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
{ {
UINT32 StreamId; UINT32 StreamId;
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
Stream_Seek(ifman->input, 16); Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId); Stream_Read_UINT32(ifman->input, StreamId);
DEBUG_DVC("StreamId %d", StreamId); DEBUG_TSMF("StreamId %d", StreamId);
presentation = tsmf_presentation_find_by_id(ifman->presentation_id); presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
if(presentation == NULL) if(presentation == NULL)
{ {
DEBUG_WARN("unknown presentation id"); DEBUG_WARN("unknown presentation id");
return 1; return 1;
} }
tsmf_presentation_flush(presentation); tsmf_presentation_flush(presentation);
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
return 0; return 0;
} }
@ -518,123 +433,97 @@ int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman)
UINT32 StreamId; UINT32 StreamId;
TSMF_STREAM *stream; TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16); Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId); Stream_Read_UINT32(ifman->input, StreamId);
if(presentation) if(presentation)
{ {
stream = tsmf_stream_find_by_id(presentation, StreamId); stream = tsmf_stream_find_by_id(presentation, StreamId);
if(stream) if(stream)
tsmf_stream_end(stream); tsmf_stream_end(stream);
} }
DEBUG_DVC("StreamId %d", StreamId); DEBUG_TSMF("StreamId %d", StreamId);
Stream_EnsureRemainingCapacity(ifman->output, 16); Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, StreamId); /* StreamId */ Stream_Write_UINT32(ifman->output, StreamId); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_ENDOFSTREAM); /* EventId */ Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_ENDOFSTREAM); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */ Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
return 0; return 0;
} }
int tsmf_ifman_on_playback_started(TSMF_IFMAN *ifman) int tsmf_ifman_on_playback_started(TSMF_IFMAN *ifman)
{ {
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
DEBUG_DVC("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation) if(presentation)
tsmf_presentation_start(presentation); tsmf_presentation_start(presentation);
else else
DEBUG_WARN("unknown presentation id"); DEBUG_WARN("unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 16); Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, 0); /* StreamId */ Stream_Write_UINT32(ifman->output, 0); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_START_COMPLETED); /* EventId */ Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_START_COMPLETED); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */ Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
return 0; return 0;
} }
int tsmf_ifman_on_playback_paused(TSMF_IFMAN *ifman) int tsmf_ifman_on_playback_paused(TSMF_IFMAN *ifman)
{ {
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
DEBUG_DVC("");
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
/* Added pause control so gstreamer pipeline can be paused accordingly */ /* Added pause control so gstreamer pipeline can be paused accordingly */
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation) if(presentation)
tsmf_presentation_paused(presentation); tsmf_presentation_paused(presentation);
else else
DEBUG_WARN("unknown presentation id"); DEBUG_WARN("unknown presentation id");
return 0; return 0;
} }
int tsmf_ifman_on_playback_restarted(TSMF_IFMAN *ifman) int tsmf_ifman_on_playback_restarted(TSMF_IFMAN *ifman)
{ {
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
DEBUG_DVC("");
ifman->output_pending = TRUE; ifman->output_pending = TRUE;
/* Added restart control so gstreamer pipeline can be resumed accordingly */ /* Added restart control so gstreamer pipeline can be resumed accordingly */
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation) if(presentation)
tsmf_presentation_restarted(presentation); tsmf_presentation_restarted(presentation);
else else
DEBUG_WARN("unknown presentation id"); DEBUG_WARN("unknown presentation id");
return 0; return 0;
} }
int tsmf_ifman_on_playback_stopped(TSMF_IFMAN *ifman) int tsmf_ifman_on_playback_stopped(TSMF_IFMAN *ifman)
{ {
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
DEBUG_DVC("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation) if(presentation)
tsmf_presentation_stop(presentation); tsmf_presentation_stop(presentation);
else else
DEBUG_WARN("unknown presentation id"); DEBUG_WARN("unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 16); Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, 0); /* StreamId */ Stream_Write_UINT32(ifman->output, 0); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_STOP_COMPLETED); /* EventId */ Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_STOP_COMPLETED); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */ Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
return 0; return 0;
} }
int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN *ifman) int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN *ifman)
{ {
DEBUG_DVC(""); DEBUG_TSMF("");
Stream_EnsureRemainingCapacity(ifman->output, 16); Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, 0); /* StreamId */ Stream_Write_UINT32(ifman->output, 0); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_MONITORCHANGED); /* EventId */ Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_MONITORCHANGED); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */ Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
return 0; return 0;
} }

View File

@ -59,7 +59,7 @@ struct _TSMF_CHANNEL_CALLBACK
IWTSVirtualChannelManager *channel_mgr; IWTSVirtualChannelManager *channel_mgr;
IWTSVirtualChannel *channel; IWTSVirtualChannel *channel;
BYTE presentation_id[16]; BYTE presentation_id[GUID_SIZE];
UINT32 stream_id; UINT32 stream_id;
}; };
@ -78,9 +78,8 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
UINT32 message_id, UINT64 duration, UINT32 data_size) UINT32 message_id, UINT64 duration, UINT32 data_size)
{ {
wStream *s; wStream *s;
int status; int status = -1;
TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback; TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
s = Stream_New(NULL, 32); s = Stream_New(NULL, 32);
Stream_Write_UINT32(s, TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY); Stream_Write_UINT32(s, TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY);
Stream_Write_UINT32(s, message_id); Stream_Write_UINT32(s, message_id);
@ -88,15 +87,17 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
Stream_Write_UINT32(s, callback->stream_id); /* StreamId */ Stream_Write_UINT32(s, callback->stream_id); /* StreamId */
Stream_Write_UINT64(s, duration); /* DataDuration */ Stream_Write_UINT64(s, duration); /* DataDuration */
Stream_Write_UINT64(s, data_size); /* cbData */ Stream_Write_UINT64(s, data_size); /* cbData */
DEBUG_TSMF("response size %d", (int) Stream_GetPosition(s));
DEBUG_DVC("response size %d", (int) Stream_GetPosition(s)); if(!callback || !callback->channel || !callback->channel->Write)
status = callback->channel->Write(callback->channel, Stream_GetPosition(s), Stream_Buffer(s), NULL); DEBUG_WARN("callback=%p, channel=%p, write=%p", callback,
callback->channel, callback->channel->Write);
else
status = callback->channel->Write(callback->channel,
Stream_GetPosition(s), Stream_Buffer(s), NULL);
if(status) if(status)
{ {
DEBUG_WARN("response error %d", status); DEBUG_WARN("response error %d", status);
} }
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
} }
@ -104,15 +105,12 @@ BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, wMessage* eve
{ {
int status; int status;
TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback; TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
status = callback->channel_mgr->PushEvent(callback->channel_mgr, event); status = callback->channel_mgr->PushEvent(callback->channel_mgr, event);
if(status) if(status)
{ {
DEBUG_WARN("response error %d", status); DEBUG_WARN("response error %d", status);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
@ -129,30 +127,26 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
UINT32 FunctionId; UINT32 FunctionId;
UINT32 InterfaceId; UINT32 InterfaceId;
TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback; TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
/* 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */ /* 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */
if(cbSize < 12) if(cbSize < 12)
{ {
DEBUG_WARN("invalid size. cbSize=%d", cbSize); DEBUG_WARN("invalid size. cbSize=%d", cbSize);
return 1; return 1;
} }
input = Stream_New((BYTE *) pBuffer, cbSize); input = Stream_New((BYTE *) pBuffer, cbSize);
output = Stream_New(NULL, 256); output = Stream_New(NULL, 256);
Stream_Seek(output, 8); Stream_Seek(output, 8);
Stream_Read_UINT32(input, InterfaceId); Stream_Read_UINT32(input, InterfaceId);
Stream_Read_UINT32(input, MessageId); Stream_Read_UINT32(input, MessageId);
Stream_Read_UINT32(input, FunctionId); Stream_Read_UINT32(input, FunctionId);
DEBUG_DVC("cbSize=%d InterfaceId=0x%X MessageId=0x%X FunctionId=0x%X", DEBUG_TSMF("cbSize=%d InterfaceId=0x%X MessageId=0x%X FunctionId=0x%X",
cbSize, InterfaceId, MessageId, FunctionId); cbSize, InterfaceId, MessageId, FunctionId);
memset(&ifman, 0, sizeof(TSMF_IFMAN)); memset(&ifman, 0, sizeof(TSMF_IFMAN));
ifman.channel_callback = pChannelCallback; ifman.channel_callback = pChannelCallback;
ifman.decoder_name = ((TSMF_PLUGIN *) callback->plugin)->decoder_name; ifman.decoder_name = ((TSMF_PLUGIN *) callback->plugin)->decoder_name;
ifman.audio_name = ((TSMF_PLUGIN *) callback->plugin)->audio_name; ifman.audio_name = ((TSMF_PLUGIN *) callback->plugin)->audio_name;
ifman.audio_device = ((TSMF_PLUGIN *) callback->plugin)->audio_device; ifman.audio_device = ((TSMF_PLUGIN *) callback->plugin)->audio_device;
memcpy(ifman.presentation_id, callback->presentation_id, 16); memcpy(ifman.presentation_id, callback->presentation_id, GUID_SIZE);
ifman.stream_id = callback->stream_id; ifman.stream_id = callback->stream_id;
ifman.message_id = MessageId; ifman.message_id = MessageId;
ifman.input = input; ifman.input = input;
@ -160,136 +154,105 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
ifman.output = output; ifman.output = output;
ifman.output_pending = FALSE; ifman.output_pending = FALSE;
ifman.output_interface_id = InterfaceId; ifman.output_interface_id = InterfaceId;
switch(InterfaceId) switch(InterfaceId)
{ {
case TSMF_INTERFACE_CAPABILITIES | STREAM_ID_NONE: case TSMF_INTERFACE_CAPABILITIES | STREAM_ID_NONE:
switch(FunctionId) switch(FunctionId)
{ {
case RIM_EXCHANGE_CAPABILITY_REQUEST: case RIM_EXCHANGE_CAPABILITY_REQUEST:
status = tsmf_ifman_rim_exchange_capability_request(&ifman); status = tsmf_ifman_rim_exchange_capability_request(&ifman);
break; break;
default: default:
break; break;
} }
break; break;
case TSMF_INTERFACE_DEFAULT | STREAM_ID_PROXY: case TSMF_INTERFACE_DEFAULT | STREAM_ID_PROXY:
switch(FunctionId) switch(FunctionId)
{ {
case SET_CHANNEL_PARAMS: case SET_CHANNEL_PARAMS:
memcpy(callback->presentation_id, Stream_Pointer(input), 16); memcpy(callback->presentation_id, Stream_Pointer(input), GUID_SIZE);
Stream_Seek(input, 16); Stream_Seek(input, GUID_SIZE);
Stream_Read_UINT32(input, callback->stream_id); Stream_Read_UINT32(input, callback->stream_id);
DEBUG_DVC("SET_CHANNEL_PARAMS StreamId=%d", callback->stream_id); DEBUG_TSMF("SET_CHANNEL_PARAMS StreamId=%d", callback->stream_id);
ifman.output_pending = TRUE; ifman.output_pending = TRUE;
status = 0; status = 0;
break; break;
case EXCHANGE_CAPABILITIES_REQ: case EXCHANGE_CAPABILITIES_REQ:
status = tsmf_ifman_exchange_capability_request(&ifman); status = tsmf_ifman_exchange_capability_request(&ifman);
break; break;
case CHECK_FORMAT_SUPPORT_REQ: case CHECK_FORMAT_SUPPORT_REQ:
status = tsmf_ifman_check_format_support_request(&ifman); status = tsmf_ifman_check_format_support_request(&ifman);
break; break;
case ON_NEW_PRESENTATION: case ON_NEW_PRESENTATION:
status = tsmf_ifman_on_new_presentation(&ifman); status = tsmf_ifman_on_new_presentation(&ifman);
break; break;
case ADD_STREAM: case ADD_STREAM:
status = tsmf_ifman_add_stream(&ifman); status = tsmf_ifman_add_stream(&ifman);
break; break;
case SET_TOPOLOGY_REQ: case SET_TOPOLOGY_REQ:
status = tsmf_ifman_set_topology_request(&ifman); status = tsmf_ifman_set_topology_request(&ifman);
break; break;
case REMOVE_STREAM: case REMOVE_STREAM:
status = tsmf_ifman_remove_stream(&ifman); status = tsmf_ifman_remove_stream(&ifman);
break; break;
case SET_SOURCE_VIDEO_RECT: case SET_SOURCE_VIDEO_RECT:
status = tsmf_ifman_set_source_video_rect(&ifman); status = tsmf_ifman_set_source_video_rect(&ifman);
break; break;
case SHUTDOWN_PRESENTATION_REQ: case SHUTDOWN_PRESENTATION_REQ:
status = tsmf_ifman_shutdown_presentation(&ifman); status = tsmf_ifman_shutdown_presentation(&ifman);
break; break;
case ON_STREAM_VOLUME: case ON_STREAM_VOLUME:
status = tsmf_ifman_on_stream_volume(&ifman); status = tsmf_ifman_on_stream_volume(&ifman);
break; break;
case ON_CHANNEL_VOLUME: case ON_CHANNEL_VOLUME:
status = tsmf_ifman_on_channel_volume(&ifman); status = tsmf_ifman_on_channel_volume(&ifman);
break; break;
case SET_VIDEO_WINDOW: case SET_VIDEO_WINDOW:
status = tsmf_ifman_set_video_window(&ifman); status = tsmf_ifman_set_video_window(&ifman);
break; break;
case UPDATE_GEOMETRY_INFO: case UPDATE_GEOMETRY_INFO:
status = tsmf_ifman_update_geometry_info(&ifman); status = tsmf_ifman_update_geometry_info(&ifman);
break; break;
case SET_ALLOCATOR: case SET_ALLOCATOR:
status = tsmf_ifman_set_allocator(&ifman); status = tsmf_ifman_set_allocator(&ifman);
break; break;
case NOTIFY_PREROLL: case NOTIFY_PREROLL:
status = tsmf_ifman_notify_preroll(&ifman); status = tsmf_ifman_notify_preroll(&ifman);
break; break;
case ON_SAMPLE: case ON_SAMPLE:
status = tsmf_ifman_on_sample(&ifman); status = tsmf_ifman_on_sample(&ifman);
break; break;
case ON_FLUSH: case ON_FLUSH:
status = tsmf_ifman_on_flush(&ifman); status = tsmf_ifman_on_flush(&ifman);
break; break;
case ON_END_OF_STREAM: case ON_END_OF_STREAM:
status = tsmf_ifman_on_end_of_stream(&ifman); status = tsmf_ifman_on_end_of_stream(&ifman);
break; break;
case ON_PLAYBACK_STARTED: case ON_PLAYBACK_STARTED:
status = tsmf_ifman_on_playback_started(&ifman); status = tsmf_ifman_on_playback_started(&ifman);
break; break;
case ON_PLAYBACK_PAUSED: case ON_PLAYBACK_PAUSED:
status = tsmf_ifman_on_playback_paused(&ifman); status = tsmf_ifman_on_playback_paused(&ifman);
break; break;
case ON_PLAYBACK_RESTARTED: case ON_PLAYBACK_RESTARTED:
status = tsmf_ifman_on_playback_restarted(&ifman); status = tsmf_ifman_on_playback_restarted(&ifman);
break; break;
case ON_PLAYBACK_STOPPED: case ON_PLAYBACK_STOPPED:
status = tsmf_ifman_on_playback_stopped(&ifman); status = tsmf_ifman_on_playback_stopped(&ifman);
break; break;
case ON_PLAYBACK_RATE_CHANGED: case ON_PLAYBACK_RATE_CHANGED:
status = tsmf_ifman_on_playback_rate_changed(&ifman); status = tsmf_ifman_on_playback_rate_changed(&ifman);
break; break;
default: default:
break; break;
} }
break; break;
default: default:
break; break;
} }
Stream_Free(input, FALSE); Stream_Free(input, FALSE);
input = NULL; input = NULL;
ifman.input = NULL; ifman.input = NULL;
if(status == -1) if(status == -1)
{ {
switch(FunctionId) switch(FunctionId)
@ -300,14 +263,12 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
status = 0; status = 0;
ifman.output_pending = 1; ifman.output_pending = 1;
break; break;
case RIMCALL_QUERYINTERFACE: case RIMCALL_QUERYINTERFACE:
/* [MS-RDPEXPS] 2.2.2.1.2 Query Interface Response (QI_RSP) /* [MS-RDPEXPS] 2.2.2.1.2 Query Interface Response (QI_RSP)
This message is not supported in this channel. */ This message is not supported in this channel. */
status = 0; status = 0;
break; break;
} }
if(status == -1) if(status == -1)
{ {
DEBUG_WARN("InterfaceId 0x%X FunctionId 0x%X not processed.", DEBUG_WARN("InterfaceId 0x%X FunctionId 0x%X not processed.",
@ -316,7 +277,6 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
} }
status = 0; status = 0;
} }
if(status == 0 && !ifman.output_pending) if(status == 0 && !ifman.output_pending)
{ {
/* Response packet does not have FunctionId */ /* Response packet does not have FunctionId */
@ -324,17 +284,14 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
Stream_SetPosition(output, 0); Stream_SetPosition(output, 0);
Stream_Write_UINT32(output, ifman.output_interface_id); Stream_Write_UINT32(output, ifman.output_interface_id);
Stream_Write_UINT32(output, MessageId); Stream_Write_UINT32(output, MessageId);
DEBUG_TSMF("response size %d", length);
DEBUG_DVC("response size %d", length);
status = callback->channel->Write(callback->channel, length, Stream_Buffer(output), NULL); status = callback->channel->Write(callback->channel, length, Stream_Buffer(output), NULL);
if(status) if(status)
{ {
DEBUG_WARN("response error %d", status); DEBUG_WARN("response error %d", status);
} }
} }
Stream_Free(output, TRUE); Stream_Free(output, TRUE);
return status; return status;
} }
@ -343,24 +300,18 @@ static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback)
TSMF_STREAM *stream; TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation; TSMF_PRESENTATION *presentation;
TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback; TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
DEBUG_TSMF("");
DEBUG_DVC("");
if(callback->stream_id) if(callback->stream_id)
{ {
presentation = tsmf_presentation_find_by_id(callback->presentation_id); presentation = tsmf_presentation_find_by_id(callback->presentation_id);
if(presentation) if(presentation)
{ {
stream = tsmf_stream_find_by_id(presentation, callback->stream_id); stream = tsmf_stream_find_by_id(presentation, callback->stream_id);
if(stream) if(stream)
tsmf_stream_free(stream); tsmf_stream_free(stream);
} }
} }
free(pChannelCallback); free(pChannelCallback);
return 0; return 0;
} }
@ -372,35 +323,27 @@ static int tsmf_on_new_channel_connection(IWTSListenerCallback* pListenerCallbac
{ {
TSMF_CHANNEL_CALLBACK *callback; TSMF_CHANNEL_CALLBACK *callback;
TSMF_LISTENER_CALLBACK *listener_callback = (TSMF_LISTENER_CALLBACK *) pListenerCallback; TSMF_LISTENER_CALLBACK *listener_callback = (TSMF_LISTENER_CALLBACK *) pListenerCallback;
DEBUG_TSMF("");
DEBUG_DVC("");
callback = (TSMF_CHANNEL_CALLBACK *) malloc(sizeof(TSMF_CHANNEL_CALLBACK)); callback = (TSMF_CHANNEL_CALLBACK *) malloc(sizeof(TSMF_CHANNEL_CALLBACK));
ZeroMemory(callback, sizeof(TSMF_CHANNEL_CALLBACK)); ZeroMemory(callback, sizeof(TSMF_CHANNEL_CALLBACK));
callback->iface.OnDataReceived = tsmf_on_data_received; callback->iface.OnDataReceived = tsmf_on_data_received;
callback->iface.OnClose = tsmf_on_close; callback->iface.OnClose = tsmf_on_close;
callback->plugin = listener_callback->plugin; callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr; callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel; callback->channel = pChannel;
*ppCallback = (IWTSVirtualChannelCallback *) callback; *ppCallback = (IWTSVirtualChannelCallback *) callback;
return 0; return 0;
} }
static int tsmf_plugin_initialize(IWTSPlugin *pPlugin, IWTSVirtualChannelManager *pChannelMgr) static int tsmf_plugin_initialize(IWTSPlugin *pPlugin, IWTSVirtualChannelManager *pChannelMgr)
{ {
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin; TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
DEBUG_TSMF("");
DEBUG_DVC("");
tsmf->listener_callback = (TSMF_LISTENER_CALLBACK *) malloc(sizeof(TSMF_LISTENER_CALLBACK)); tsmf->listener_callback = (TSMF_LISTENER_CALLBACK *) malloc(sizeof(TSMF_LISTENER_CALLBACK));
ZeroMemory(tsmf->listener_callback, sizeof(TSMF_LISTENER_CALLBACK)); ZeroMemory(tsmf->listener_callback, sizeof(TSMF_LISTENER_CALLBACK));
tsmf->listener_callback->iface.OnNewChannelConnection = tsmf_on_new_channel_connection; tsmf->listener_callback->iface.OnNewChannelConnection = tsmf_on_new_channel_connection;
tsmf->listener_callback->plugin = pPlugin; tsmf->listener_callback->plugin = pPlugin;
tsmf->listener_callback->channel_mgr = pChannelMgr; tsmf->listener_callback->channel_mgr = pChannelMgr;
return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0, return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0,
(IWTSListenerCallback *) tsmf->listener_callback, NULL); (IWTSListenerCallback *) tsmf->listener_callback, NULL);
} }
@ -408,13 +351,10 @@ static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager
static int tsmf_plugin_terminated(IWTSPlugin *pPlugin) static int tsmf_plugin_terminated(IWTSPlugin *pPlugin)
{ {
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin; TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
DEBUG_TSMF("");
DEBUG_DVC("");
if(tsmf->listener_callback) if(tsmf->listener_callback)
free(tsmf->listener_callback); free(tsmf->listener_callback);
free(tsmf); free(tsmf);
return 0; return 0;
} }
@ -432,21 +372,15 @@ static void tsmf_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
DWORD flags; DWORD flags;
COMMAND_LINE_ARGUMENT_A *arg; COMMAND_LINE_ARGUMENT_A *arg;
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin; TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
status = CommandLineParseArgumentsA(args->argc, (const char **) args->argv, status = CommandLineParseArgumentsA(args->argc, (const char **) args->argv,
tsmf_args, flags, tsmf, NULL, NULL); tsmf_args, flags, tsmf, NULL, NULL);
arg = tsmf_args; arg = tsmf_args;
do do
{ {
if(!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) if(!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
continue; continue;
CommandLineSwitchStart(arg) CommandLineSwitchStart(arg)
CommandLineSwitchCase(arg, "audio") CommandLineSwitchCase(arg, "audio")
{ {
tsmf->audio_name = _strdup(arg->Value); tsmf->audio_name = _strdup(arg->Value);
@ -461,9 +395,7 @@ static void tsmf_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
} }
CommandLineSwitchDefault(arg) CommandLineSwitchDefault(arg)
{ {
} }
CommandLineSwitchEnd(arg) CommandLineSwitchEnd(arg)
} }
while((arg = CommandLineFindNextArgumentA(arg)) != NULL); while((arg = CommandLineFindNextArgumentA(arg)) != NULL);
@ -477,27 +409,21 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{ {
int status = 0; int status = 0;
TSMF_PLUGIN *tsmf; TSMF_PLUGIN *tsmf;
tsmf = (TSMF_PLUGIN *) pEntryPoints->GetPlugin(pEntryPoints, "tsmf"); tsmf = (TSMF_PLUGIN *) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
if(tsmf == NULL) if(tsmf == NULL)
{ {
tsmf = (TSMF_PLUGIN *) malloc(sizeof(TSMF_PLUGIN)); tsmf = (TSMF_PLUGIN *) malloc(sizeof(TSMF_PLUGIN));
ZeroMemory(tsmf, sizeof(TSMF_PLUGIN)); ZeroMemory(tsmf, sizeof(TSMF_PLUGIN));
tsmf->iface.Initialize = tsmf_plugin_initialize; tsmf->iface.Initialize = tsmf_plugin_initialize;
tsmf->iface.Connected = NULL; tsmf->iface.Connected = NULL;
tsmf->iface.Disconnected = NULL; tsmf->iface.Disconnected = NULL;
tsmf->iface.Terminated = tsmf_plugin_terminated; tsmf->iface.Terminated = tsmf_plugin_terminated;
status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin *) tsmf); status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin *) tsmf);
tsmf_media_init(); tsmf_media_init();
} }
if(status == 0) if(status == 0)
{ {
tsmf_process_addin_args((IWTSPlugin *) tsmf, pEntryPoints->GetPluginData(pEntryPoints)); tsmf_process_addin_args((IWTSPlugin *) tsmf, pEntryPoints->GetPluginData(pEntryPoints));
} }
return status; return status;
} }

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,7 @@ TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCal
TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid); TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid);
void tsmf_presentation_start(TSMF_PRESENTATION *presentation); void tsmf_presentation_start(TSMF_PRESENTATION *presentation);
void tsmf_presentation_stop(TSMF_PRESENTATION *presentation); void tsmf_presentation_stop(TSMF_PRESENTATION *presentation);
void tsmf_presentation_sync(TSMF_PRESENTATION *presentation);
void tsmf_presentation_paused(TSMF_PRESENTATION *presentation); void tsmf_presentation_paused(TSMF_PRESENTATION *presentation);
void tsmf_presentation_restarted(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_volume_changed(TSMF_PRESENTATION *presentation, UINT32 newVolume, UINT32 muted);

View File

@ -28,10 +28,10 @@
#include <freerdp/types.h> #include <freerdp/types.h>
#include <freerdp/utils/debug.h> #include <freerdp/utils/debug.h>
#ifdef WITH_DEBUG_DVC #ifdef WITH_DEBUG_TSMF
#define DEBUG_DVC(fmt, ...) DEBUG_CLASS(DVC, fmt, ## __VA_ARGS__) #define DEBUG_TSMF(fmt, ...) DEBUG_CLASS(TSMF, fmt, ## __VA_ARGS__)
#else #else
#define DEBUG_DVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #define DEBUG_TSMF(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif #endif
typedef struct _TS_AM_MEDIA_TYPE typedef struct _TS_AM_MEDIA_TYPE

View File

@ -9,33 +9,28 @@
* the argument struct. */ * the argument struct. */
#include "../common/cmdline.c" #include "../common/cmdline.c"
LPSTR tmp = NULL;
LPSTR tr_esc_str(LPCSTR arg) LPSTR tr_esc_str(LPCSTR arg)
{ {
LPSTR tmp = NULL;
size_t cs = 0, x, ds; size_t cs = 0, x, ds;
size_t s; size_t s;
if(NULL == arg) if(NULL == arg)
return NULL; return NULL;
s = strlen(arg); s = strlen(arg);
/* Find trailing whitespaces */ /* Find trailing whitespaces */
while((s > 0) && isspace(arg[s-1])) while((s > 0) && isspace(arg[s-1]))
s--; s--;
/* Prepare a initial buffer with the size of the result string. */ /* Prepare a initial buffer with the size of the result string. */
ds = s + 1;
if(s) if(s)
tmp = (LPSTR)malloc(s * sizeof(CHAR)); tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if(NULL == tmp) if(NULL == tmp)
{ {
fprintf(stderr, "Could not allocate string buffer."); fprintf(stderr, "Could not allocate string buffer.");
exit(-2); exit(-2);
} }
/* Copy character for character and check, if it is necessary to escape. */ /* Copy character for character and check, if it is necessary to escape. */
ds = s + 1; memset(tmp, 0, ds * sizeof(CHAR));
for(x=0; x<s; x++) for(x=0; x<s; x++)
{ {
switch(arg[x]) switch(arg[x])
@ -114,11 +109,9 @@ LPSTR tr_esc_str(LPCSTR arg)
tmp[cs++] = arg[x]; tmp[cs++] = arg[x];
break; break;
} }
/* Assure, the string is '\0' terminated. */ /* Assure, the string is '\0' terminated. */
tmp[ds-1] = '\0'; tmp[ds-1] = '\0';
} }
return tmp; return tmp;
} }
@ -128,7 +121,6 @@ int main(int argc, char *argv[])
size_t x; size_t x;
const char *fname = "xfreerdp-argument.1.xml"; const char *fname = "xfreerdp-argument.1.xml";
FILE *fp = NULL; FILE *fp = NULL;
/* Open output file for writing, truncate if existing. */ /* Open output file for writing, truncate if existing. */
fp = fopen(fname, "w"); fp = fopen(fname, "w");
if(NULL == fp) if(NULL == fp)
@ -136,12 +128,10 @@ int main(int argc, char *argv[])
fprintf(stderr, "Could not open '%s' for writing.", fname); fprintf(stderr, "Could not open '%s' for writing.", fname);
return -1; return -1;
} }
/* The tag used as header in the manpage */ /* The tag used as header in the manpage */
fprintf(fp, "<refsect1>\n"); fprintf(fp, "<refsect1>\n");
fprintf(fp, "\t<title>Options</title>\n"); fprintf(fp, "\t<title>Options</title>\n");
fprintf(fp, "\t\t<variablelist>\n"); fprintf(fp, "\t\t<variablelist>\n");
/* Iterate over argument struct and write data to docbook 4.5 /* Iterate over argument struct and write data to docbook 4.5
* compatible XML */ * compatible XML */
if(elements < 2) if(elements < 2)
@ -149,30 +139,28 @@ int main(int argc, char *argv[])
fprintf(stderr, "The argument array 'args' is empty, writing an empty file."); fprintf(stderr, "The argument array 'args' is empty, writing an empty file.");
elements = 1; elements = 1;
} }
for(x=0; x<elements - 1; x++) for(x=0; x<elements - 1; x++)
{ {
const COMMAND_LINE_ARGUMENT_A *arg = &args[x]; const COMMAND_LINE_ARGUMENT_A *arg = &args[x];
const char *name = tr_esc_str((LPSTR) arg->Name);
const char *format = tr_esc_str(arg->Format);
const char *text = tr_esc_str((LPSTR) arg->Text);
fprintf(fp, "\t\t\t<varlistentry>\n"); fprintf(fp, "\t\t\t<varlistentry>\n");
if(COMMAND_LINE_VALUE_REQUIRED == arg->Flags) if(COMMAND_LINE_VALUE_REQUIRED == arg->Flags)
fprintf(fp, "\t\t\t\t<term><option>/%s</option> <replaceable>%s</replaceable></term>\n", tr_esc_str((LPSTR) arg->Name), tr_esc_str(arg->Format) ); fprintf(fp, "\t\t\t\t<term><option>/%s</option> <replaceable>%s</replaceable></term>\n", name, format);
else else
fprintf(fp, "\t\t\t\t<term><option>/%s</option></term>\n", tr_esc_str((LPSTR) arg->Name)); fprintf(fp, "\t\t\t\t<term><option>/%s</option></term>\n", name);
fprintf(fp, "\t\t\t\t<listitem>\n"); fprintf(fp, "\t\t\t\t<listitem>\n");
fprintf(fp, "\t\t\t\t\t<para>%s</para>\n", tr_esc_str((LPSTR) arg->Text)); fprintf(fp, "\t\t\t\t\t<para>%s</para>\n", format);
fprintf(fp, "\t\t\t\t</listitem>\n"); fprintf(fp, "\t\t\t\t</listitem>\n");
fprintf(fp, "\t\t\t</varlistentry>\n"); fprintf(fp, "\t\t\t</varlistentry>\n");
free(name);
free(format);
free(text);
} }
fprintf(fp, "\t\t</variablelist>\n"); fprintf(fp, "\t\t</variablelist>\n");
fprintf(fp, "\t</refsect1>\n"); fprintf(fp, "\t</refsect1>\n");
fclose(fp); fclose(fp);
if(NULL != tmp)
free(tmp);
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@ -30,9 +30,11 @@
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <sys/shm.h> #include <sys/mman.h>
#include <sys/ipc.h> #include <sys/stat.h>
#include <fcntl.h>
#include <winpr/thread.h>
#include <winpr/crt.h> #include <winpr/crt.h>
#include <freerdp/rail.h> #include <freerdp/rail.h>
@ -93,9 +95,6 @@
#define PROP_MOTIF_WM_HINTS_ELEMENTS 5 #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
/* to be accessed by gstreamer plugin */
#define SHARED_MEM_KEY 7777
struct _PropMotifWmHints struct _PropMotifWmHints
{ {
unsigned long flags; unsigned long flags;
@ -114,9 +113,7 @@ void xf_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned in
XEvent xevent; XEvent xevent;
unsigned int i; unsigned int i;
va_list argp; va_list argp;
va_start(argp, numArgs); va_start(argp, numArgs);
xevent.xclient.type = ClientMessage; xevent.xclient.type = ClientMessage;
xevent.xclient.serial = 0; xevent.xclient.serial = 0;
xevent.xclient.send_event = False; xevent.xclient.send_event = False;
@ -124,18 +121,14 @@ void xf_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned in
xevent.xclient.window = window->handle; xevent.xclient.window = window->handle;
xevent.xclient.message_type = atom; xevent.xclient.message_type = atom;
xevent.xclient.format = 32; xevent.xclient.format = 32;
for(i=0; i<numArgs; i++) for(i=0; i<numArgs; i++)
{ {
xevent.xclient.data.l[i] = va_arg(argp, int); xevent.xclient.data.l[i] = va_arg(argp, int);
} }
DEBUG_X11("Send ClientMessage Event: wnd=0x%04X", (unsigned int) xevent.xclient.window); DEBUG_X11("Send ClientMessage Event: wnd=0x%04X", (unsigned int) xevent.xclient.window);
XSendEvent(xfc->display, RootWindowOfScreen(xfc->screen), False, XSendEvent(xfc->display, RootWindowOfScreen(xfc->screen), False,
SubstructureRedirectMask | SubstructureNotifyMask, &xevent); SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
XSync(xfc->display, False); XSync(xfc->display, False);
va_end(argp); va_end(argp);
} }
@ -144,12 +137,9 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen)
if(fullscreen) if(fullscreen)
{ {
rdpSettings *settings = xfc->instance->settings; rdpSettings *settings = xfc->instance->settings;
xf_SetWindowDecorations(xfc, window, FALSE); xf_SetWindowDecorations(xfc, window, FALSE);
XMoveResizeWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY, window->width, window->height); XMoveResizeWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY, window->width, window->height);
XMapRaised(xfc->display, window->handle); XMapRaised(xfc->display, window->handle);
window->fullscreen = TRUE; window->fullscreen = TRUE;
} }
} }
@ -162,23 +152,18 @@ BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int leng
int status; int status;
Atom actual_type; Atom actual_type;
int actual_format; int actual_format;
if(property == None) if(property == None)
return FALSE; return FALSE;
status = XGetWindowProperty(xfc->display, window, status = XGetWindowProperty(xfc->display, window,
property, 0, length, FALSE, AnyPropertyType, property, 0, length, FALSE, AnyPropertyType,
&actual_type, &actual_format, nitems, bytes, prop); &actual_type, &actual_format, nitems, bytes, prop);
if(status != Success) if(status != Success)
return FALSE; return FALSE;
if(actual_type == None) if(actual_type == None)
{ {
DEBUG_WARN("Property %lu does not exist", property); DEBUG_WARN("Property %lu does not exist", property);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
@ -188,16 +173,12 @@ BOOL xf_GetCurrentDesktop(xfContext* xfc)
unsigned long nitems; unsigned long nitems;
unsigned long bytes; unsigned long bytes;
unsigned char *prop; unsigned char *prop;
status = xf_GetWindowProperty(xfc, DefaultRootWindow(xfc->display), status = xf_GetWindowProperty(xfc, DefaultRootWindow(xfc->display),
xfc->_NET_CURRENT_DESKTOP, 1, &nitems, &bytes, &prop); xfc->_NET_CURRENT_DESKTOP, 1, &nitems, &bytes, &prop);
if(!status) if(!status)
return FALSE; return FALSE;
xfc->current_desktop = (int) *prop; xfc->current_desktop = (int) *prop;
free(prop); free(prop);
return TRUE; return TRUE;
} }
@ -208,45 +189,35 @@ BOOL xf_GetWorkArea(xfContext* xfc)
unsigned long nitems; unsigned long nitems;
unsigned long bytes; unsigned long bytes;
unsigned char *prop; unsigned char *prop;
status = xf_GetCurrentDesktop(xfc); status = xf_GetCurrentDesktop(xfc);
if(status != TRUE) if(status != TRUE)
return FALSE; return FALSE;
status = xf_GetWindowProperty(xfc, DefaultRootWindow(xfc->display), status = xf_GetWindowProperty(xfc, DefaultRootWindow(xfc->display),
xfc->_NET_WORKAREA, 32 * 4, &nitems, &bytes, &prop); xfc->_NET_WORKAREA, 32 * 4, &nitems, &bytes, &prop);
if(status != TRUE) if(status != TRUE)
return FALSE; return FALSE;
if((xfc->current_desktop * 4 + 3) >= nitems) if((xfc->current_desktop * 4 + 3) >= nitems)
{ {
free(prop); free(prop);
return FALSE; return FALSE;
} }
plong = (long *) prop; plong = (long *) prop;
xfc->workArea.x = plong[xfc->current_desktop * 4 + 0]; xfc->workArea.x = plong[xfc->current_desktop * 4 + 0];
xfc->workArea.y = plong[xfc->current_desktop * 4 + 1]; xfc->workArea.y = plong[xfc->current_desktop * 4 + 1];
xfc->workArea.width = plong[xfc->current_desktop * 4 + 2]; xfc->workArea.width = plong[xfc->current_desktop * 4 + 2];
xfc->workArea.height = plong[xfc->current_desktop * 4 + 3]; xfc->workArea.height = plong[xfc->current_desktop * 4 + 3];
free(prop); free(prop);
return TRUE; return TRUE;
} }
void xf_SetWindowDecorations(xfContext *xfc, xfWindow *window, BOOL show) void xf_SetWindowDecorations(xfContext *xfc, xfWindow *window, BOOL show)
{ {
PropMotifWmHints hints; PropMotifWmHints hints;
hints.decorations = (show) ? MWM_DECOR_ALL : 0; hints.decorations = (show) ? MWM_DECOR_ALL : 0;
hints.functions = MWM_FUNC_ALL ; hints.functions = MWM_FUNC_ALL ;
hints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; hints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS;
hints.inputMode = 0; hints.inputMode = 0;
hints.status = 0; hints.status = 0;
XChangeProperty(xfc->display, window->handle, xfc->_MOTIF_WM_HINTS, xfc->_MOTIF_WM_HINTS, 32, XChangeProperty(xfc->display, window->handle, xfc->_MOTIF_WM_HINTS, xfc->_MOTIF_WM_HINTS, 32,
PropModeReplace, (BYTE *) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS); PropModeReplace, (BYTE *) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
} }
@ -254,10 +225,8 @@ void xf_SetWindowDecorations(xfContext* xfc, xfWindow* window, BOOL show)
void xf_SetWindowUnlisted(xfContext *xfc, xfWindow *window) void xf_SetWindowUnlisted(xfContext *xfc, xfWindow *window)
{ {
Atom window_state[2]; Atom window_state[2];
window_state[0] = xfc->_NET_WM_STATE_SKIP_PAGER; window_state[0] = xfc->_NET_WM_STATE_SKIP_PAGER;
window_state[1] = xfc->_NET_WM_STATE_SKIP_TASKBAR; window_state[1] = xfc->_NET_WM_STATE_SKIP_TASKBAR;
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_STATE, XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_STATE,
XA_ATOM, 32, PropModeReplace, (BYTE *) &window_state, 2); XA_ATOM, 32, PropModeReplace, (BYTE *) &window_state, 2);
} }
@ -265,7 +234,6 @@ void xf_SetWindowUnlisted(xfContext* xfc, xfWindow* window)
void xf_SetWindowStyle(xfContext *xfc, xfWindow *window, UINT32 style, UINT32 ex_style) void xf_SetWindowStyle(xfContext *xfc, xfWindow *window, UINT32 style, UINT32 ex_style)
{ {
Atom window_type; Atom window_type;
if(/*(ex_style & WS_EX_TOPMOST) ||*/ (ex_style & WS_EX_TOOLWINDOW)) if(/*(ex_style & WS_EX_TOPMOST) ||*/ (ex_style & WS_EX_TOOLWINDOW))
{ {
/* /*
@ -280,7 +248,6 @@ void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex
XSetWindowAttributes attrs; XSetWindowAttributes attrs;
attrs.override_redirect = True; attrs.override_redirect = True;
XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &attrs); XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &attrs);
window->is_transient = TRUE; window->is_transient = TRUE;
xf_SetWindowUnlisted(xfc, window); xf_SetWindowUnlisted(xfc, window);
window_type = xfc->_NET_WM_WINDOW_TYPE_POPUP; window_type = xfc->_NET_WM_WINDOW_TYPE_POPUP;
@ -289,11 +256,13 @@ void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex
* TOPMOST window that is not a toolwindow is treated like a regular window(ie. task manager). * TOPMOST window that is not a toolwindow is treated like a regular window(ie. task manager).
* Want to do this here, since the window may have type WS_POPUP * Want to do this here, since the window may have type WS_POPUP
*/ */
else if (ex_style & WS_EX_TOPMOST) else
if(ex_style & WS_EX_TOPMOST)
{ {
window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL; window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
} }
else if (style & WS_POPUP) else
if(style & WS_POPUP)
{ {
/* this includes dialogs, popups, etc, that need to be full-fledged windows */ /* this includes dialogs, popups, etc, that need to be full-fledged windows */
window->is_transient = TRUE; window->is_transient = TRUE;
@ -304,10 +273,8 @@ void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex
{ {
window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL; window_type = xfc->_NET_WM_WINDOW_TYPE_NORMAL;
} }
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_WINDOW_TYPE, XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_WINDOW_TYPE,
XA_ATOM, 32, PropModeReplace, (BYTE *) &window_type, 1); XA_ATOM, 32, PropModeReplace, (BYTE *) &window_type, 1);
} }
void xf_SetWindowText(xfContext *xfc, xfWindow *window, char *name) void xf_SetWindowText(xfContext *xfc, xfWindow *window, char *name)
@ -318,32 +285,32 @@ void xf_SetWindowText(xfContext* xfc, xfWindow* window, char *name)
static void xf_SetWindowPID(xfContext *xfc, xfWindow *window, pid_t pid) static void xf_SetWindowPID(xfContext *xfc, xfWindow *window, pid_t pid)
{ {
Atom am_wm_pid; Atom am_wm_pid;
if(!pid) if(!pid)
pid = getpid(); pid = getpid();
am_wm_pid = XInternAtom(xfc->display, "_NET_WM_PID", False); am_wm_pid = XInternAtom(xfc->display, "_NET_WM_PID", False);
XChangeProperty(xfc->display, window->handle, am_wm_pid, XA_CARDINAL, XChangeProperty(xfc->display, window->handle, am_wm_pid, XA_CARDINAL,
32, PropModeReplace, (unsigned char *)&pid, 1); 32, PropModeReplace, (unsigned char *)&pid, 1);
} }
static const char *get_shm_id()
{
static char shm_id[64];
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId());
return shm_id;
}
xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations) xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations)
{ {
xfWindow *window; xfWindow *window;
XEvent xevent; XEvent xevent;
rdpSettings *settings; rdpSettings *settings;
window = (xfWindow *) malloc(sizeof(xfWindow)); window = (xfWindow *) malloc(sizeof(xfWindow));
ZeroMemory(window, sizeof(xfWindow)); ZeroMemory(window, sizeof(xfWindow));
settings = xfc->instance->settings; settings = xfc->instance->settings;
if(window) if(window)
{ {
int shmid;
int input_mask; int input_mask;
XClassHint *class_hints; XClassHint *class_hints;
window->width = width; window->width = width;
window->height = height; window->height = height;
window->fullscreen = FALSE; window->fullscreen = FALSE;
@ -351,71 +318,56 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int heig
window->local_move.state = LMS_NOT_ACTIVE; window->local_move.state = LMS_NOT_ACTIVE;
window->is_mapped = FALSE; window->is_mapped = FALSE;
window->is_transient = FALSE; window->is_transient = FALSE;
window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen), window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen),
xfc->workArea.x, xfc->workArea.y, xfc->workArea.width, xfc->workArea.height, 0, xfc->depth, InputOutput, xfc->visual, xfc->workArea.x, xfc->workArea.y, xfc->workArea.width, xfc->workArea.height, 0, xfc->depth, InputOutput, xfc->visual,
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap | CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs); CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs);
window->shmid = shm_open(get_shm_id(), O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
shmid = shmget(SHARED_MEM_KEY, sizeof(int), IPC_CREAT | 0666); if(window->shmid < 0)
if (shmid < 0)
{ {
DEBUG_X11("xf_CreateDesktopWindow: failed to get access to shared memory - shmget()\n"); DEBUG_X11("xf_CreateDesktopWindow: failed to get access to shared memory - shmget()\n");
} }
else else
{ {
int* xfwin = shmat(shmid, NULL, 0); ftruncate(window->shmid, sizeof(window->handle));
window->xfwin = mmap(0, sizeof(window->handle), PROT_READ | PROT_WRITE, MAP_SHARED, window->shmid, 0);
if (xfwin == (int*) -1) if(window->xfwin == (int *) -1)
{ {
DEBUG_X11("xf_CreateDesktopWindow: failed to assign pointer to the memory address - shmat()\n"); DEBUG_X11("xf_CreateDesktopWindow: failed to assign pointer to the memory address - shmat()\n");
} }
else else
{ {
*xfwin = (int) window->handle; *window->xfwin = window->handle;
} }
} }
class_hints = XAllocClassHint(); class_hints = XAllocClassHint();
if(class_hints) if(class_hints)
{ {
class_hints->res_name = "xfreerdp"; class_hints->res_name = "xfreerdp";
if(xfc->instance->settings->WmClass) if(xfc->instance->settings->WmClass)
class_hints->res_class = xfc->instance->settings->WmClass; class_hints->res_class = xfc->instance->settings->WmClass;
else else
class_hints->res_class = "xfreerdp"; class_hints->res_class = "xfreerdp";
XSetClassHint(xfc->display, window->handle, class_hints); XSetClassHint(xfc->display, window->handle, class_hints);
XFree(class_hints); XFree(class_hints);
} }
xf_ResizeDesktopWindow(xfc, window, width, height); xf_ResizeDesktopWindow(xfc, window, width, height);
xf_SetWindowDecorations(xfc, window, decorations); xf_SetWindowDecorations(xfc, window, decorations);
xf_SetWindowPID(xfc, window, 0); xf_SetWindowPID(xfc, window, 0);
input_mask = input_mask =
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
VisibilityChangeMask | FocusChangeMask | StructureNotifyMask | VisibilityChangeMask | FocusChangeMask | StructureNotifyMask |
PointerMotionMask | ExposureMask | PropertyChangeMask; PointerMotionMask | ExposureMask | PropertyChangeMask;
if(xfc->grab_keyboard) if(xfc->grab_keyboard)
input_mask |= EnterWindowMask | LeaveWindowMask; input_mask |= EnterWindowMask | LeaveWindowMask;
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32, XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32,
PropModeReplace, (BYTE *) xf_icon_prop, ARRAYSIZE(xf_icon_prop)); PropModeReplace, (BYTE *) xf_icon_prop, ARRAYSIZE(xf_icon_prop));
if(xfc->settings->ParentWindowId) if(xfc->settings->ParentWindowId)
XReparentWindow(xfc->display, window->handle, (Window) xfc->settings->ParentWindowId, 0, 0); XReparentWindow(xfc->display, window->handle, (Window) xfc->settings->ParentWindowId, 0, 0);
XSelectInput(xfc->display, window->handle, input_mask); XSelectInput(xfc->display, window->handle, input_mask);
XClearWindow(xfc->display, window->handle); XClearWindow(xfc->display, window->handle);
XMapWindow(xfc->display, window->handle); XMapWindow(xfc->display, window->handle);
xf_input_init(xfc, window->handle); xf_input_init(xfc, window->handle);
/* /*
* NOTE: This must be done here to handle reparenting the window, * NOTE: This must be done here to handle reparenting the window,
* so that we don't miss the event and hang waiting for the next one * so that we don't miss the event and hang waiting for the next one
@ -425,34 +377,29 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int heig
XMaskEvent(xfc->display, VisibilityChangeMask, &xevent); XMaskEvent(xfc->display, VisibilityChangeMask, &xevent);
} }
while(xevent.type != VisibilityNotify); while(xevent.type != VisibilityNotify);
/* /*
* The XCreateWindow call will start the window in the upper-left corner of our current * The XCreateWindow call will start the window in the upper-left corner of our current
* monitor instead of the upper-left monitor for remote app mode(which uses all monitors). * monitor instead of the upper-left monitor for remote app mode(which uses all monitors).
* This extra call after the window is mapped will position the login window correctly * This extra call after the window is mapped will position the login window correctly
*/ */
if(xfc->instance->settings->RemoteApplicationMode) if(xfc->instance->settings->RemoteApplicationMode)
{ {
XMoveWindow(xfc->display, window->handle, 0, 0); XMoveWindow(xfc->display, window->handle, 0, 0);
} }
else if (settings->DesktopPosX || settings->DesktopPosY) else
if(settings->DesktopPosX || settings->DesktopPosY)
{ {
XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY); XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY);
} }
} }
xf_SetWindowText(xfc, window, name); xf_SetWindowText(xfc, window, name);
return window; return window;
} }
void xf_ResizeDesktopWindow(xfContext *xfc, xfWindow *window, int width, int height) void xf_ResizeDesktopWindow(xfContext *xfc, xfWindow *window, int width, int height)
{ {
XSizeHints *size_hints; XSizeHints *size_hints;
size_hints = XAllocSizeHints(); size_hints = XAllocSizeHints();
if(size_hints) if(size_hints)
{ {
size_hints->flags = PMinSize | PMaxSize; size_hints->flags = PMinSize | PMaxSize;
@ -468,10 +415,8 @@ void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, int* he
{ {
int vscreen_width; int vscreen_width;
int vscreen_height; int vscreen_height;
vscreen_width = xfc->vscreen.area.right - xfc->vscreen.area.left + 1; vscreen_width = xfc->vscreen.area.right - xfc->vscreen.area.left + 1;
vscreen_height = xfc->vscreen.area.bottom - xfc->vscreen.area.top + 1; vscreen_height = xfc->vscreen.area.bottom - xfc->vscreen.area.top + 1;
if(*width < 1) if(*width < 1)
{ {
*width = 1; *width = 1;
@ -509,26 +454,20 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
xfWindow *window; xfWindow *window;
XWMHints *InputModeHint; XWMHints *InputModeHint;
XClassHint *class_hints; XClassHint *class_hints;
window = (xfWindow *) malloc(sizeof(xfWindow)); window = (xfWindow *) malloc(sizeof(xfWindow));
ZeroMemory(window, sizeof(xfWindow)); ZeroMemory(window, sizeof(xfWindow));
xf_FixWindowCoordinates(xfc, &x, &y, &width, &height); xf_FixWindowCoordinates(xfc, &x, &y, &width, &height);
window->left = x; window->left = x;
window->top = y; window->top = y;
window->right = x + width - 1; window->right = x + width - 1;
window->bottom = y + height - 1; window->bottom = y + height - 1;
window->width = width; window->width = width;
window->height = height; window->height = height;
/* /*
* WS_EX_DECORATIONS is used by XRDP and instructs * WS_EX_DECORATIONS is used by XRDP and instructs
* the client to use local window decorations * the client to use local window decorations
*/ */
window->decorations = (wnd->extendedStyle & WS_EX_DECORATIONS) ? TRUE : FALSE; window->decorations = (wnd->extendedStyle & WS_EX_DECORATIONS) ? TRUE : FALSE;
window->fullscreen = FALSE; window->fullscreen = FALSE;
window->window = wnd; window->window = wnd;
window->local_move.state = LMS_NOT_ACTIVE; window->local_move.state = LMS_NOT_ACTIVE;
@ -536,24 +475,18 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
window->is_transient = FALSE; window->is_transient = FALSE;
window->rail_state = 0; window->rail_state = 0;
window->rail_ignore_configure = FALSE; window->rail_ignore_configure = FALSE;
window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen), window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen),
x, y, window->width, window->height, 0, xfc->depth, InputOutput, xfc->visual, x, y, window->width, window->height, 0, xfc->depth, InputOutput, xfc->visual,
0, &xfc->attribs); 0, &xfc->attribs);
DEBUG_X11_LMS("Create window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d rdp=0x%X", DEBUG_X11_LMS("Create window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d rdp=0x%X",
(UINT32) window->handle, window->left, window->top, window->right, window->bottom, (UINT32) window->handle, window->left, window->top, window->right, window->bottom,
window->width, window->height, wnd->windowId); window->width, window->height, wnd->windowId);
ZeroMemory(&gcv, sizeof(gcv)); ZeroMemory(&gcv, sizeof(gcv));
window->gc = XCreateGC(xfc->display, window->handle, GCGraphicsExposures, &gcv); window->gc = XCreateGC(xfc->display, window->handle, GCGraphicsExposures, &gcv);
class_hints = XAllocClassHint(); class_hints = XAllocClassHint();
if(class_hints) if(class_hints)
{ {
char *class = NULL; char *class = NULL;
if(xfc->instance->settings->WmClass != NULL) if(xfc->instance->settings->WmClass != NULL)
{ {
class_hints->res_class = xfc->instance->settings->WmClass; class_hints->res_class = xfc->instance->settings->WmClass;
@ -564,24 +497,19 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
snprintf(class, sizeof(rail_window_class), "RAIL:%08X", id); snprintf(class, sizeof(rail_window_class), "RAIL:%08X", id);
class_hints->res_class = class; class_hints->res_class = class;
} }
class_hints->res_name = "RAIL"; class_hints->res_name = "RAIL";
XSetClassHint(xfc->display, window->handle, class_hints); XSetClassHint(xfc->display, window->handle, class_hints);
XFree(class_hints); XFree(class_hints);
if(class) if(class)
free(class); free(class);
} }
/* Set the input mode hint for the WM */ /* Set the input mode hint for the WM */
InputModeHint = XAllocWMHints(); InputModeHint = XAllocWMHints();
InputModeHint->flags = (1L << 0); InputModeHint->flags = (1L << 0);
InputModeHint->input = True; InputModeHint->input = True;
XSetWMHints(xfc->display, window->handle, InputModeHint); XSetWMHints(xfc->display, window->handle, InputModeHint);
XFree(InputModeHint); XFree(InputModeHint);
XSetWMProtocols(xfc->display, window->handle, &(xfc->WM_DELETE_WINDOW), 1); XSetWMProtocols(xfc->display, window->handle, &(xfc->WM_DELETE_WINDOW), 1);
input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask |
ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
PointerMotionMask | Button1MotionMask | Button2MotionMask | PointerMotionMask | Button1MotionMask | Button2MotionMask |
@ -590,20 +518,15 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
VisibilityChangeMask | StructureNotifyMask | SubstructureNotifyMask | VisibilityChangeMask | StructureNotifyMask | SubstructureNotifyMask |
SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask | SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask |
ColormapChangeMask | OwnerGrabButtonMask; ColormapChangeMask | OwnerGrabButtonMask;
XSelectInput(xfc->display, window->handle, input_mask); XSelectInput(xfc->display, window->handle, input_mask);
xf_SetWindowDecorations(xfc, window, window->decorations); xf_SetWindowDecorations(xfc, window, window->decorations);
xf_SetWindowStyle(xfc, window, wnd->style, wnd->extendedStyle); xf_SetWindowStyle(xfc, window, wnd->style, wnd->extendedStyle);
xf_SetWindowPID(xfc, window, 0); xf_SetWindowPID(xfc, window, 0);
xf_ShowWindow(xfc, window, WINDOW_SHOW); xf_ShowWindow(xfc, window, WINDOW_SHOW);
XClearWindow(xfc->display, window->handle); XClearWindow(xfc->display, window->handle);
XMapWindow(xfc->display, window->handle); XMapWindow(xfc->display, window->handle);
/* Move doesn't seem to work until window is mapped. */ /* Move doesn't seem to work until window is mapped. */
xf_MoveWindow(xfc, window, x, y, width, height); xf_MoveWindow(xfc, window, x, y, width, height);
return window; return window;
} }
@ -612,22 +535,16 @@ void xf_SetWindowMinMaxInfo(xfContext* xfc, xfWindow* window,
int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight) int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight)
{ {
XSizeHints *size_hints; XSizeHints *size_hints;
size_hints = XAllocSizeHints(); size_hints = XAllocSizeHints();
if(size_hints) if(size_hints)
{ {
size_hints->flags = PMinSize | PMaxSize | PResizeInc; size_hints->flags = PMinSize | PMaxSize | PResizeInc;
size_hints->min_width = minTrackWidth; size_hints->min_width = minTrackWidth;
size_hints->min_height = minTrackHeight; size_hints->min_height = minTrackHeight;
size_hints->max_width = maxTrackWidth; size_hints->max_width = maxTrackWidth;
size_hints->max_height = maxTrackHeight; size_hints->max_height = maxTrackHeight;
/* to speedup window drawing we need to select optimal value for sizing step. */ /* to speedup window drawing we need to select optimal value for sizing step. */
size_hints->width_inc = size_hints->height_inc = 1; size_hints->width_inc = size_hints->height_inc = 1;
XSetWMNormalHints(xfc->display, window->handle, size_hints); XSetWMNormalHints(xfc->display, window->handle, size_hints);
XFree(size_hints); XFree(size_hints);
} }
@ -637,7 +554,6 @@ void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int
{ {
if(window->local_move.state != LMS_NOT_ACTIVE) if(window->local_move.state != LMS_NOT_ACTIVE)
return; return;
DEBUG_X11_LMS("direction=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d " DEBUG_X11_LMS("direction=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d "
"RDP=0x%X rc={l=%d t=%d} w=%d h=%d mouse_x=%d mouse_y=%d", "RDP=0x%X rc={l=%d t=%d} w=%d h=%d mouse_x=%d mouse_y=%d",
direction, (UINT32) window->handle, direction, (UINT32) window->handle,
@ -645,7 +561,6 @@ void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int
window->width, window->height, window->window->windowId, window->width, window->height, window->window->windowId,
window->window->windowOffsetX, window->window->windowOffsetY, window->window->windowOffsetX, window->window->windowOffsetY,
window->window->windowWidth, window->window->windowHeight, x, y); window->window->windowWidth, window->window->windowHeight, x, y);
/* /*
* Save original mouse location relative to root. This will be needed * Save original mouse location relative to root. This will be needed
* to end local move to RDP server and/or X server * to end local move to RDP server and/or X server
@ -654,9 +569,7 @@ void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int
window->local_move.root_y = y; window->local_move.root_y = y;
window->local_move.state = LMS_STARTING; window->local_move.state = LMS_STARTING;
window->local_move.direction = direction; window->local_move.direction = direction;
XUngrabPointer(xfc->display, CurrentTime); XUngrabPointer(xfc->display, CurrentTime);
xf_SendClientEvent(xfc, window, xf_SendClientEvent(xfc, window,
xfc->_NET_WM_MOVERESIZE, /* request X window manager to initiate a local move */ xfc->_NET_WM_MOVERESIZE, /* request X window manager to initiate a local move */
5, /* 5 arguments to follow */ 5, /* 5 arguments to follow */
@ -669,7 +582,6 @@ void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int
void xf_EndLocalMoveSize(xfContext *xfc, xfWindow *window) void xf_EndLocalMoveSize(xfContext *xfc, xfWindow *window)
{ {
DEBUG_X11_LMS("state=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d " DEBUG_X11_LMS("state=%d window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d "
"RDP=0x%X rc={l=%d t=%d} w=%d h=%d", "RDP=0x%X rc={l=%d t=%d} w=%d h=%d",
window->local_move.state, window->local_move.state,
@ -677,10 +589,8 @@ void xf_EndLocalMoveSize(xfContext* xfc, xfWindow *window)
window->width, window->height, window->window->windowId, window->width, window->height, window->window->windowId,
window->window->windowOffsetX, window->window->windowOffsetY, window->window->windowOffsetX, window->window->windowOffsetY,
window->window->windowWidth, window->window->windowHeight); window->window->windowWidth, window->window->windowHeight);
if(window->local_move.state == LMS_NOT_ACTIVE) if(window->local_move.state == LMS_NOT_ACTIVE)
return; return;
if(window->local_move.state == LMS_STARTING) if(window->local_move.state == LMS_STARTING)
{ {
/* /*
@ -698,24 +608,19 @@ void xf_EndLocalMoveSize(xfContext* xfc, xfWindow *window)
1, /* simulated mouse button 1 */ 1, /* simulated mouse button 1 */
1); /* 1 == application request per extended ICCM */ 1); /* 1 == application request per extended ICCM */
} }
window->local_move.state = LMS_NOT_ACTIVE; window->local_move.state = LMS_NOT_ACTIVE;
} }
void xf_MoveWindow(xfContext *xfc, xfWindow *window, int x, int y, int width, int height) void xf_MoveWindow(xfContext *xfc, xfWindow *window, int x, int y, int width, int height)
{ {
BOOL resize = FALSE; BOOL resize = FALSE;
if((width * height) < 1) if((width * height) < 1)
return; return;
if((window->width != width) || (window->height != height)) if((window->width != width) || (window->height != height))
resize = TRUE; resize = TRUE;
if(window->local_move.state == LMS_STARTING || if(window->local_move.state == LMS_STARTING ||
window->local_move.state == LMS_ACTIVE) window->local_move.state == LMS_ACTIVE)
return; return;
DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u " DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u "
"new rc={l=%d t=%d r=%d b=%d} w=%u h=%u" "new rc={l=%d t=%d r=%d b=%d} w=%u h=%u"
" RDP=0x%X rc={l=%d t=%d} w=%d h=%d", " RDP=0x%X rc={l=%d t=%d} w=%d h=%d",
@ -725,19 +630,16 @@ void xf_MoveWindow(xfContext* xfc, xfWindow* window, int x, int y, int width, in
window->window->windowId, window->window->windowId,
window->window->windowOffsetX, window->window->windowOffsetY, window->window->windowOffsetX, window->window->windowOffsetY,
window->window->windowWidth, window->window->windowHeight); window->window->windowWidth, window->window->windowHeight);
window->left = x; window->left = x;
window->top = y; window->top = y;
window->right = x + width - 1; window->right = x + width - 1;
window->bottom = y + height - 1; window->bottom = y + height - 1;
window->width = width; window->width = width;
window->height = height; window->height = height;
if(resize) if(resize)
XMoveResizeWindow(xfc->display, window->handle, x, y, width, height); XMoveResizeWindow(xfc->display, window->handle, x, y, width, height);
else else
XMoveWindow(xfc->display, window->handle, x, y); XMoveWindow(xfc->display, window->handle, x, y);
xf_UpdateWindowArea(xfc, window, 0, 0, width, height); xf_UpdateWindowArea(xfc, window, 0, 0, width, height);
} }
@ -748,53 +650,42 @@ void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state)
case WINDOW_HIDE: case WINDOW_HIDE:
XWithdrawWindow(xfc->display, window->handle, xfc->screen_number); XWithdrawWindow(xfc->display, window->handle, xfc->screen_number);
break; break;
case WINDOW_SHOW_MINIMIZED: case WINDOW_SHOW_MINIMIZED:
XIconifyWindow(xfc->display, window->handle, xfc->screen_number); XIconifyWindow(xfc->display, window->handle, xfc->screen_number);
break; break;
case WINDOW_SHOW_MAXIMIZED: case WINDOW_SHOW_MAXIMIZED:
/* Set the window as maximized */ /* Set the window as maximized */
xf_SendClientEvent(xfc, window, xfc->_NET_WM_STATE, 4, 1, xf_SendClientEvent(xfc, window, xfc->_NET_WM_STATE, 4, 1,
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False), XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0); XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
/* /*
* This is a workaround for the case where the window is maximized locally before the rail server is told to maximize * This is a workaround for the case where the window is maximized locally before the rail server is told to maximize
* the window, this appears to be a race condition where the local window with incomplete data and once the window is * the window, this appears to be a race condition where the local window with incomplete data and once the window is
* actually maximized on the server - an update of the new areas may not happen. So, we simply to do a full update of * actually maximized on the server - an update of the new areas may not happen. So, we simply to do a full update of
* the entire window once the rail server notifies us that the window is now maximized. * the entire window once the rail server notifies us that the window is now maximized.
*/ */
if(window->rail_state == WINDOW_SHOW_MAXIMIZED) if(window->rail_state == WINDOW_SHOW_MAXIMIZED)
xf_UpdateWindowArea(xfc, window, 0, 0, window->window->windowWidth, window->window->windowHeight); xf_UpdateWindowArea(xfc, window, 0, 0, window->window->windowWidth, window->window->windowHeight);
break; break;
case WINDOW_SHOW: case WINDOW_SHOW:
/* Ensure the window is not maximized */ /* Ensure the window is not maximized */
xf_SendClientEvent(xfc, window, xfc->_NET_WM_STATE, 4, 0, xf_SendClientEvent(xfc, window, xfc->_NET_WM_STATE, 4, 0,
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False), XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False),
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0); XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False), 0);
/* /*
* Ignore configure requests until both the Maximized properties have been processed * Ignore configure requests until both the Maximized properties have been processed
* to prevent condition where WM overrides size of request due to one or both of these properties * to prevent condition where WM overrides size of request due to one or both of these properties
* still being set - which causes a position adjustment to be sent back to the server * still being set - which causes a position adjustment to be sent back to the server
* thus causing the window to not return to its original size * thus causing the window to not return to its original size
*/ */
if(window->rail_state == WINDOW_SHOW_MAXIMIZED) if(window->rail_state == WINDOW_SHOW_MAXIMIZED)
window->rail_ignore_configure = TRUE; window->rail_ignore_configure = TRUE;
if(window->is_transient) if(window->is_transient)
xf_SetWindowUnlisted(xfc, window); xf_SetWindowUnlisted(xfc, window);
break; break;
} }
/* Save the current rail state of this window */ /* Save the current rail state of this window */
window->rail_state = state; window->rail_state = state;
XFlush(xfc->display); XFlush(xfc->display);
} }
@ -806,19 +697,15 @@ void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon)
long *propdata; long *propdata;
long *dstp; long *dstp;
UINT32 *srcp; UINT32 *srcp;
if(!icon->big) if(!icon->big)
return; return;
pixels = icon->entry->width * icon->entry->height; pixels = icon->entry->width * icon->entry->height;
propsize = 2 + pixels; propsize = 2 + pixels;
propdata = malloc(propsize * sizeof(long)); propdata = malloc(propsize * sizeof(long));
propdata[0] = icon->entry->width; propdata[0] = icon->entry->width;
propdata[1] = icon->entry->height; propdata[1] = icon->entry->height;
dstp = &(propdata[2]); dstp = &(propdata[2]);
srcp = (UINT32 *) icon->extra; srcp = (UINT32 *) icon->extra;
for(y = 0; y < icon->entry->height; y++) for(y = 0; y < icon->entry->height; y++)
{ {
for(x = 0; x < icon->entry->width; x++) for(x = 0; x < icon->entry->width; x++)
@ -826,10 +713,8 @@ void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon)
*dstp++ = *srcp++; *dstp++ = *srcp++;
} }
} }
XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32, XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32,
PropModeReplace, (BYTE *) propdata, propsize); PropModeReplace, (BYTE *) propdata, propsize);
XFlush(xfc->display); XFlush(xfc->display);
free(propdata); free(propdata);
} }
@ -838,12 +723,9 @@ void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, in
{ {
int i; int i;
XRectangle *xrects; XRectangle *xrects;
if(nrects == 0) if(nrects == 0)
return; return;
xrects = malloc(sizeof(XRectangle) * nrects); xrects = malloc(sizeof(XRectangle) * nrects);
for(i = 0; i < nrects; i++) for(i = 0; i < nrects; i++)
{ {
xrects[i].x = rects[i].left; xrects[i].x = rects[i].left;
@ -851,7 +733,6 @@ void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, in
xrects[i].width = rects[i].right - rects[i].left; xrects[i].width = rects[i].right - rects[i].left;
xrects[i].height = rects[i].bottom - rects[i].top; xrects[i].height = rects[i].bottom - rects[i].top;
} }
#ifdef WITH_XEXT #ifdef WITH_XEXT
/* /*
* This is currently unsupported with the new logic to handle window placement with VisibleOffset variables * This is currently unsupported with the new logic to handle window placement with VisibleOffset variables
@ -860,7 +741,6 @@ void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, in
*/ */
XShapeCombineRectangles(xfc->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0); XShapeCombineRectangles(xfc->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
#endif #endif
free(xrects); free(xrects);
} }
@ -868,12 +748,9 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16*
{ {
int i; int i;
XRectangle *xrects; XRectangle *xrects;
if(nrects == 0) if(nrects == 0)
return; return;
xrects = malloc(sizeof(XRectangle) * nrects); xrects = malloc(sizeof(XRectangle) * nrects);
for(i = 0; i < nrects; i++) for(i = 0; i < nrects; i++)
{ {
xrects[i].x = rects[i].left; xrects[i].x = rects[i].left;
@ -881,7 +758,6 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16*
xrects[i].width = rects[i].right - rects[i].left; xrects[i].width = rects[i].right - rects[i].left;
xrects[i].height = rects[i].bottom - rects[i].top; xrects[i].height = rects[i].bottom - rects[i].top;
} }
#ifdef WITH_XEXT #ifdef WITH_XEXT
/* /*
* This is currently unsupported with the new logic to handle window placement with VisibleOffset variables * This is currently unsupported with the new logic to handle window placement with VisibleOffset variables
@ -890,7 +766,6 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16*
*/ */
XShapeCombineRectangles(xfc->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0); XShapeCombineRectangles(xfc->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
#endif #endif
free(xrects); free(xrects);
} }
@ -899,17 +774,13 @@ void xf_UpdateWindowArea(xfContext* xfc, xfWindow* window, int x, int y, int wid
int ax, ay; int ax, ay;
rdpWindow *wnd; rdpWindow *wnd;
wnd = window->window; wnd = window->window;
/* RemoteApp mode uses visibleOffset instead of windowOffset */ /* RemoteApp mode uses visibleOffset instead of windowOffset */
if(!xfc->remote_app) if(!xfc->remote_app)
{ {
ax = x + wnd->windowOffsetX; ax = x + wnd->windowOffsetX;
ay = y + wnd->windowOffsetY; ay = y + wnd->windowOffsetY;
if(ax + width > wnd->windowOffsetX + wnd->windowWidth) if(ax + width > wnd->windowOffsetX + wnd->windowWidth)
width = (wnd->windowOffsetX + wnd->windowWidth - 1) - ax; width = (wnd->windowOffsetX + wnd->windowWidth - 1) - ax;
if(ay + height > wnd->windowOffsetY + wnd->windowHeight) if(ay + height > wnd->windowOffsetY + wnd->windowHeight)
height = (wnd->windowOffsetY + wnd->windowHeight - 1) - ay; height = (wnd->windowOffsetY + wnd->windowHeight - 1) - ay;
} }
@ -917,27 +788,20 @@ void xf_UpdateWindowArea(xfContext* xfc, xfWindow* window, int x, int y, int wid
{ {
ax = x + wnd->visibleOffsetX; ax = x + wnd->visibleOffsetX;
ay = y + wnd->visibleOffsetY; ay = y + wnd->visibleOffsetY;
if(ax + width > wnd->visibleOffsetX + wnd->windowWidth) if(ax + width > wnd->visibleOffsetX + wnd->windowWidth)
width = (wnd->visibleOffsetX + wnd->windowWidth - 1) - ax; width = (wnd->visibleOffsetX + wnd->windowWidth - 1) - ax;
if(ay + height > wnd->visibleOffsetY + wnd->windowHeight) if(ay + height > wnd->visibleOffsetY + wnd->windowHeight)
height = (wnd->visibleOffsetY + wnd->windowHeight - 1) - ay; height = (wnd->visibleOffsetY + wnd->windowHeight - 1) - ay;
} }
WaitForSingleObject(xfc->mutex, INFINITE); WaitForSingleObject(xfc->mutex, INFINITE);
if(xfc->settings->SoftwareGdi) if(xfc->settings->SoftwareGdi)
{ {
XPutImage(xfc->display, xfc->primary, window->gc, xfc->image, XPutImage(xfc->display, xfc->primary, window->gc, xfc->image,
ax, ay, ax, ay, width, height); ax, ay, ax, ay, width, height);
} }
XCopyArea(xfc->display, xfc->primary, window->handle, window->gc, XCopyArea(xfc->display, xfc->primary, window->handle, window->gc,
ax, ay, width, height, x, y); ax, ay, width, height, x, y);
XFlush(xfc->display); XFlush(xfc->display);
ReleaseMutex(xfc->mutex); ReleaseMutex(xfc->mutex);
} }
@ -946,17 +810,13 @@ BOOL xf_IsWindowBorder(xfContext* xfc, xfWindow* xfw, int x, int y)
rdpWindow *wnd; rdpWindow *wnd;
BOOL clientArea = FALSE; BOOL clientArea = FALSE;
BOOL windowArea = FALSE; BOOL windowArea = FALSE;
wnd = xfw->window; wnd = xfw->window;
if(((x > wnd->clientOffsetX) && (x < wnd->clientOffsetX + wnd->clientAreaWidth)) && if(((x > wnd->clientOffsetX) && (x < wnd->clientOffsetX + wnd->clientAreaWidth)) &&
((y > wnd->clientOffsetY) && (y < wnd->clientOffsetY + wnd->clientAreaHeight))) ((y > wnd->clientOffsetY) && (y < wnd->clientOffsetY + wnd->clientAreaHeight)))
clientArea = TRUE; clientArea = TRUE;
if(((x > wnd->windowOffsetX) && (x < wnd->windowOffsetX + wnd->windowWidth)) && if(((x > wnd->windowOffsetX) && (x < wnd->windowOffsetX + wnd->windowWidth)) &&
((y > wnd->windowOffsetY) && (y < wnd->windowOffsetY + wnd->windowHeight))) ((y > wnd->windowOffsetY) && (y < wnd->windowOffsetY + wnd->windowHeight)))
windowArea = TRUE; windowArea = TRUE;
return (windowArea && !(clientArea)); return (windowArea && !(clientArea));
} }
@ -964,36 +824,36 @@ void xf_DestroyWindow(xfContext* xfc, xfWindow* window)
{ {
if(window == NULL) if(window == NULL)
return; return;
if(xfc->window == window) if(xfc->window == window)
xfc->window = NULL; xfc->window = NULL;
if(window->gc) if(window->gc)
XFreeGC(xfc->display, window->gc); XFreeGC(xfc->display, window->gc);
if(window->handle) if(window->handle)
{ {
XUnmapWindow(xfc->display, window->handle); XUnmapWindow(xfc->display, window->handle);
XDestroyWindow(xfc->display, window->handle); XDestroyWindow(xfc->display, window->handle);
} }
free(window); free(window);
if(window->xfwin)
munmap(0, sizeof(*window->xfwin));
if(window->shmid >= 0)
close(window->shmid);
shm_unlink(get_shm_id());
window->xfwin = -1;
window->shmid = -1;
} }
rdpWindow *xf_rdpWindowFromWindow(xfContext *xfc, Window wnd) rdpWindow *xf_rdpWindowFromWindow(xfContext *xfc, Window wnd)
{ {
rdpRail *rail; rdpRail *rail;
if(xfc) if(xfc)
{ {
if(wnd) if(wnd)
{ {
rail = ((rdpContext *) xfc)->rail; rail = ((rdpContext *) xfc)->rail;
if(rail) if(rail)
return window_list_get_by_extra_id(rail->list, (void *)(long) wnd); return window_list_get_by_extra_id(rail->list, (void *)(long) wnd);
} }
} }
return NULL; return NULL;
} }

View File

@ -71,7 +71,9 @@ struct xf_window
int bottom; int bottom;
int width; int width;
int height; int height;
int shmid;
Window handle; Window handle;
Window *xfwin;
BOOL fullscreen; BOOL fullscreen;
BOOL decorations; BOOL decorations;
rdpWindow *window; rdpWindow *window;

View File

@ -814,6 +814,38 @@ int freerdp_parse_username(char* username, char** user, char** domain)
return 0; return 0;
} }
int freerdp_parse_hostname(char* hostname, char** host, int* port)
{
char* p;
int length;
p = strrchr(hostname, ':');
if (p)
{
length = (p - hostname);
*host = (char*) malloc(length + 1);
if (!(*host))
return -1;
CopyMemory(*host, hostname, length);
(*host)[length] = '\0';
*port = atoi(p + 1);
}
else
{
*host = _strdup(hostname);
if (!(*host))
return -1;
*port = -1;
}
return 0;
}
int freerdp_set_connection_type(rdpSettings* settings, int type) int freerdp_set_connection_type(rdpSettings* settings, int type)
{ {
settings->ConnectionType = type; settings->ConnectionType = type;

View File

@ -767,10 +767,23 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
free(domain); free(domain);
} }
if (~((size_t) file->FullAddress))
{
int port = -1;
char* host = NULL;
freerdp_parse_hostname(file->FullAddress, &host, &port);
freerdp_set_param_string(settings, FreeRDP_ServerHostname, host);
if (port > 0)
freerdp_set_param_uint32(settings, FreeRDP_ServerPort, (UINT32) port);
free(host);
}
if (~file->ServerPort) if (~file->ServerPort)
freerdp_set_param_uint32(settings, FreeRDP_ServerPort, file->ServerPort); freerdp_set_param_uint32(settings, FreeRDP_ServerPort, file->ServerPort);
if (~((size_t) file->FullAddress))
freerdp_set_param_string(settings, FreeRDP_ServerHostname, file->FullAddress);
if (~file->DesktopWidth) if (~file->DesktopWidth)
freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, file->DesktopWidth); freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, file->DesktopWidth);
@ -867,7 +880,19 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
freerdp_set_param_bool(settings, FreeRDP_CompressionEnabled, file->Compression); freerdp_set_param_bool(settings, FreeRDP_CompressionEnabled, file->Compression);
if (~((size_t) file->GatewayHostname)) if (~((size_t) file->GatewayHostname))
freerdp_set_param_string(settings, FreeRDP_GatewayHostname, file->GatewayHostname); {
int port = -1;
char* host = NULL;
freerdp_parse_hostname(file->GatewayHostname, &host, &port);
freerdp_set_param_string(settings, FreeRDP_GatewayHostname, host);
if (port > 0)
freerdp_set_param_uint32(settings, FreeRDP_GatewayPort, (UINT32) port);
free(host);
}
if (~file->GatewayUsageMethod) if (~file->GatewayUsageMethod)
freerdp_set_gateway_usage_method(settings, file->GatewayUsageMethod); freerdp_set_gateway_usage_method(settings, file->GatewayUsageMethod);

View File

@ -100,6 +100,7 @@ option(WITH_DEBUG_CAPABILITIES "Print capability negotiation debug messages." ${
option(WITH_DEBUG_CHANNELS "Print channel manager debug messages." ${DEFAULT_DEBUG_OPTION}) option(WITH_DEBUG_CHANNELS "Print channel manager debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_CLIPRDR "Print clipboard redirection debug messages" ${DEFAULT_DEBUG_OPTION}) option(WITH_DEBUG_CLIPRDR "Print clipboard redirection debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_DVC "Print dynamic virtual channel debug messages." ${DEFAULT_DEBUG_OPTION}) option(WITH_DEBUG_DVC "Print dynamic virtual channel debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_TSMF "Print TSMF virtual channel debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_GDI "Print graphics debug messages." ${DEFAULT_DEBUG_OPTION}) option(WITH_DEBUG_GDI "Print graphics debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_KBD "Print keyboard related debug messages." ${DEFAULT_DEBUG_OPTION}) option(WITH_DEBUG_KBD "Print keyboard related debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_LICENSE "Print license debug messages." ${DEFAULT_DEBUG_OPTION}) option(WITH_DEBUG_LICENSE "Print license debug messages." ${DEFAULT_DEBUG_OPTION})

View File

@ -0,0 +1,118 @@
# - Try to find GStreamer
# Once done this will define
#
# GSTREAMER_0_10_FOUND - system has GStreamer
# GSTREAMER_0_10_INCLUDE_DIRS - the GStreamer include directory
# GSTREAMER_0_10_LIBRARIES - the libraries needed to use GStreamer
# GSTREAMER_0_10_DEFINITIONS - Compiler switches required for using GStreamer
# Copyright (c) 2006, Tim Beaulen <tbscope@gmail.com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# TODO: Other versions --> GSTREAMER_X_Y_FOUND (Example: GSTREAMER_0_8_FOUND and GSTREAMER_0_10_FOUND etc)
IF (GSTREAMER_0_10_INCLUDE_DIRS AND GSTREAMER_0_10_LIBRARIES AND GSTREAMER_0_10_BASE_LIBRARY AND GSTREAMER_0_10_INTERFACE_LIBRARY)
# in cache already
SET(GSTREAMER_0_10_FIND_QUIETLY TRUE)
ELSE (GSTREAMER_0_10_INCLUDE_DIRS AND GSTREAMER_0_10_LIBRARIES AND GSTREAMER_0_10_BASE_LIBRARY AND GSTREAMER_0_10_INTERFACE_LIBRARY)
SET(GSTREAMER_0_10_FIND_QUIETLY FALSE)
ENDIF (GSTREAMER_0_10_INCLUDE_DIRS AND GSTREAMER_0_10_LIBRARIES AND GSTREAMER_0_10_BASE_LIBRARY AND GSTREAMER_0_10_INTERFACE_LIBRARY)
IF (NOT WIN32)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(PC_GSTREAMER_0_10 QUIET gstreamer-0.10)
#MESSAGE(STATUS "DEBUG: GStreamer include directory = ${GSTREAMER_0_10_INCLUDE_DIRSS}")
#MESSAGE(STATUS "DEBUG: GStreamer link directory = ${GSTREAMER_0_10_LIBRARY_DIRS}")
#MESSAGE(STATUS "DEBUG: GStreamer CFlags = ${GSTREAMER_0_10_CFLAGS_OTHER}")
SET(GSTREAMER_0_10_DEFINITIONS ${PC_GSTREAMER_0_10_CFLAGS_OTHER})
ENDIF (NOT WIN32)
FIND_PATH(GSTREAMER_0_10_INCLUDE_DIRS gst/gst.h
PATHS
${PC_GSTREAMER_0_10_INCLUDEDIR}
${PC_GSTREAMER_0_10_INCLUDE_DIRSS}
#PATH_SUFFIXES gst
)
FIND_LIBRARY(GSTREAMER_0_10_LIBRARIES NAMES gstreamer-0.10
PATHS
${PC_GSTREAMER_0_10_LIBDIR}
${PC_GSTREAMER_0_10_LIBRARY_DIRS}
)
FIND_LIBRARY(GSTREAMER_0_10_BASE_LIBRARY NAMES gstbase-0.10
PATHS
${PC_GSTREAMER_0_10_LIBDIR}
${PC_GSTREAMER_0_10_LIBRARY_DIRS}
)
FIND_LIBRARY(GSTREAMER_0_10_APP_LIBRARY NAMES gstapp-0.10
PATHS
${PC_GSTREAMER_0_10_LIBDIR}
${PC_GSTREAMER_0_10_LIBRARY_DIRS}
)
FIND_LIBRARY(GSTREAMER_0_10_INTERFACE_LIBRARY NAMES gstinterfaces-0.10
PATHS
${PC_GSTREAMER_0_10_LIBDIR}
${PC_GSTREAMER_0_10_LIBRARY_DIRS}
)
FIND_PACKAGE(Glib REQUIRED)
FIND_PACKAGE(LibXml2 REQUIRED)
IF (GSTREAMER_0_10_INCLUDE_DIRS)
#MESSAGE(STATUS "DEBUG: Found GStreamer include dir: ${GSTREAMER_0_10_INCLUDE_DIRS}")
ELSE (GSTREAMER_0_10_INCLUDE_DIRS)
MESSAGE(STATUS "GStreamer: WARNING: include dir not found")
ENDIF (GSTREAMER_0_10_INCLUDE_DIRS)
IF (GSTREAMER_0_10_LIBRARIES)
#MESSAGE(STATUS "DEBUG: Found GStreamer library: ${GSTREAMER_0_10_LIBRARIES}")
ELSE (GSTREAMER_0_10_LIBRARIES)
MESSAGE(STATUS "GStreamer: WARNING: library not found")
ENDIF (GSTREAMER_0_10_LIBRARIES)
IF (GSTREAMER_0_10_INTERFACE_LIBRARY)
#MESSAGE(STATUS "DEBUG: Found GStreamer interface library: ${GSTREAMER_0_10_INTERFACE_LIBRARY}")
ELSE (GSTREAMER_0_10_INTERFACE_LIBRARY)
MESSAGE(STATUS "GStreamer: WARNING: interface library not found")
ENDIF (GSTREAMER_0_10_INTERFACE_LIBRARY)
set(_GSTREAMER_0_10_REQUIRED_VARS
Glib_INCLUDE_DIRS
Glib_LIBRARIES
LIBXML2_INCLUDE_DIR
LIBXML2_LIBRARIES
GSTREAMER_0_10_INCLUDE_DIRS
GSTREAMER_0_10_LIBRARIES
VERSION_OK
GSTREAMER_0_10_BASE_INCLUDE_DIRS
GSTREAMER_0_10_BASE_LIBRARY
GSTREAMER_0_10_INTERFACE_INCLUDE_DIRS
GSTREAMER_0_10_INTERFACE_LIBRARY)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GSTREAMER_0_10 DEFAULT_MSG
GSTREAMER_0_10_LIBRARIES
GSTREAMER_0_10_INCLUDE_DIRS
GSTREAMER_0_10_BASE_LIBRARY
GSTREAMER_0_10_INTERFACE_LIBRARY)
list(APPEND GSTREAMER_0_10_INCLUDE_DIRS ${Glib_INCLUDE_DIRS})
list(APPEND GSTREAMER_0_10_LIBRARIES ${Glib_LIBRARIES})
list(APPEND GSTREAMER_0_10_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR})
list(APPEND GSTREAMER_0_10_LIBRARIES ${LIBXML2_LIBRARIES})
list(APPEND GSTREAMER_0_10_INCLUDE_DIRS ${GSTREAMER_0_10_BASE_INCLUDE_DIR})
list(APPEND GSTREAMER_0_10_LIBRARIES ${GSTREAMER_0_10_BASE_LIBRARY})
list(APPEND GSTREAMER_0_10_INCLUDE_DIRS ${GSTREAMER_0_10_APP_INCLUDE_DIR})
list(APPEND GSTREAMER_0_10_LIBRARIES ${GSTREAMER_0_10_APP_LIBRARY})
list(APPEND GSTREAMER_0_10_INCLUDE_DIRS ${GSTREAMER_0_10_INTERFACE_INCLUDE_DIR})
list(APPEND GSTREAMER_0_10_LIBRARIES ${GSTREAMER_0_10_INTERFACE_LIBRARY})
MARK_AS_ADVANCED(GSTREAMER_0_10_INCLUDE_DIRS GSTREAMER_0_10_LIBRARIES GSTREAMER_0_10_BASE_LIBRARY GSTREAMER_0_10_INTERFACE_LIBRARY)

View File

@ -0,0 +1,153 @@
# - Try to find Gstreamer and its plugins
# Once done, this will define
#
# GSTREAMER_1_0_FOUND - system has Gstreamer
# GSTREAMER_1_0_INCLUDE_DIRS - the Gstreamer include directories
# GSTREAMER_1_0_LIBRARIES - link these to use Gstreamer
#
# Additionally, gstreamer-base is always looked for and required, and
# the following related variables are defined:
#
# GSTREAMER_1_0_BASE_INCLUDE_DIRS - gstreamer-base's include directory
# GSTREAMER_1_0_BASE_LIBRARIES - link to these to use gstreamer-base
#
# Optionally, the COMPONENTS keyword can be passed to find_package()
# and Gstreamer plugins can be looked for. Currently, the following
# plugins can be searched, and they define the following variables if
# found:
#
# gstreamer-app: GSTREAMER_1_0_APP_INCLUDE_DIRS and GSTREAMER_1_0_APP_LIBRARIES
# gstreamer-audio: GSTREAMER_1_0_AUDIO_INCLUDE_DIRS and GSTREAMER_1_0_AUDIO_LIBRARIES
# gstreamer-fft: GSTREAMER_1_0_FFT_INCLUDE_DIRS and GSTREAMER_1_0_FFT_LIBRARIES
# gstreamer-pbutils: GSTREAMER_1_0_PBUTILS_INCLUDE_DIRS and GSTREAMER_1_0_PBUTILS_LIBRARIES
# gstreamer-video: GSTREAMER_1_0_VIDEO_INCLUDE_DIRS and GSTREAMER_1_0_VIDEO_LIBRARIES
#
# Copyright (C) 2012 Raphael Kubo da Costa <rakuco@webkit.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
find_package(PkgConfig)
# The minimum Gstreamer version we support.
set(GSTREAMER_1_0_MINIMUM_VERSION 1.0.5)
# Helper macro to find a Gstreamer plugin (or Gstreamer itself)
# _component_prefix is prepended to the _INCLUDE_DIRS and _LIBRARIES variables (eg. "GSTREAMER_1_0_AUDIO")
# _pkgconfig_name is the component's pkg-config name (eg. "gstreamer-1.0", or "gstreamer-video-1.0").
# _header is the component's header, relative to the gstreamer-1.0 directory (eg. "gst/gst.h").
# _library is the component's library name (eg. "gstreamer-1.0" or "gstvideo-1.0")
macro(FIND_GSTREAMER_COMPONENT _component_prefix _pkgconfig_name _header _library)
# FIXME: The QUIET keyword can be used once we require CMake 2.8.2.
pkg_check_modules(PC_${_component_prefix} ${_pkgconfig_name})
find_path(${_component_prefix}_INCLUDE_DIRS
NAMES ${_header}
HINTS ${PC_${_component_prefix}_INCLUDE_DIRS} ${PC_${_component_prefix}_INCLUDEDIR}
PATH_SUFFIXES gstreamer-1.0
)
find_library(${_component_prefix}_LIBRARIES
NAMES ${_library} gstreamer_android
HINTS ${PC_${_component_prefix}_LIBRARY_DIRS} ${PC_${_component_prefix}_LIBDIR} ${GSTREAMER_1_0_ROOT_DIR}
)
endmacro()
# ------------------------
# 1. Find Gstreamer itself
# ------------------------
# 1.1. Find headers and libraries
set(GLIB_ROOT_DIR ${GSTREAMER_1_0_ROOT_DIR})
find_package(Glib REQUIRED)
FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0 gstreamer-1.0 gst/gst.h gstreamer-1.0)
FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_BASE gstreamer-base-1.0 gst/gst.h gstbase-1.0)
# 1.2. Check Gstreamer version
if (GSTREAMER_1_0_INCLUDE_DIRS)
if (EXISTS "${GSTREAMER_1_0_INCLUDE_DIRS}/gst/gstversion.h")
file(READ "${GSTREAMER_1_0_INCLUDE_DIRS}/gst/gstversion.h" GSTREAMER_VERSION_CONTENTS)
string(REGEX MATCH "#define +GST_VERSION_MAJOR +\\(([0-9]+)\\)" _dummy "${GSTREAMER_VERSION_CONTENTS}")
set(GSTREAMER_1_0_VERSION_MAJOR "${CMAKE_MATCH_1}")
string(REGEX MATCH "#define +GST_VERSION_MINOR +\\(([0-9]+)\\)" _dummy "${GSTREAMER_1_0_VERSION_CONTENTS}")
set(GSTREAMER_1_0_VERSION_MINOR "${CMAKE_MATCH_1}")
string(REGEX MATCH "#define +GST_VERSION_MICRO +\\(([0-9]+)\\)" _dummy "${GSTREAMER_1_0_VERSION_CONTENTS}")
set(GSTREAMER_1_0_VERSION_MICRO "${CMAKE_MATCH_1}")
set(GSTREAMER_1_0_VERSION "${GSTREAMER_1_0_VERSION_MAJOR}.${GSTREAMER_1_0_VERSION_MINOR}.${GSTREAMER_1_0_VERSION_MICRO}")
endif ()
endif ()
# FIXME: With CMake 2.8.3 we can just pass GSTREAMER_1_0_VERSION to FIND_PACKAGE_HANDLE_STANDARD_ARGS as VERSION_VAR
# and remove the version check here (GSTREAMER_1_0_MINIMUM_VERSION would be passed to FIND_PACKAGE).
set(VERSION_OK TRUE)
if ("${GSTREAMER_1_0_VERSION}" VERSION_LESS "${GSTREAMER_1_0_MINIMUM_VERSION}")
set(VERSION_OK FALSE)
endif ()
# -------------------------
# 2. Find Gstreamer plugins
# -------------------------
FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_APP gstreamer-app-1.0 gst/app/gstappsink.h gstapp-1.0)
FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_AUDIO gstreamer-audio-1.0 gst/audio/audio.h gstaudio-1.0)
FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_FFT gstreamer-fft-1.0 gst/fft/gstfft.h gstfft-1.0)
FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_PBUTILS gstreamer-pbutils-1.0 gst/pbutils/pbutils.h gstpbutils-1.0)
FIND_GSTREAMER_COMPONENT(GSTREAMER_1_0_VIDEO gstreamer-video-1.0 gst/video/video.h gstvideo-1.0)
# ------------------------------------------------
# 3. Process the COMPONENTS passed to FIND_PACKAGE
# ------------------------------------------------
set(_GSTREAMER_1_0_REQUIRED_VARS
Glib_INCLUDE_DIRS
Glib_LIBRARIES
GSTREAMER_1_0_INCLUDE_DIRS
GSTREAMER_1_0_LIBRARIES
VERSION_OK
GSTREAMER_1_0_BASE_INCLUDE_DIRS
GSTREAMER_1_0_BASE_LIBRARIES)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GSTREAMER_1_0 DEFAULT_MSG GSTREAMER_1_0_LIBRARIES GSTREAMER_1_0_INCLUDE_DIRS)
list(APPEND GSTREAMER_1_0_INCLUDE_DIRS ${Glib_INCLUDE_DIRS})
list(APPEND GSTREAMER_1_0_LIBRARIES ${Glib_LIBRARIES})
list(APPEND GSTREAMER_1_0_INCLUDE_DIRS ${GSTREAMER_1_0_BASE_INCLUDE_DIRS})
list(APPEND GSTREAMER_1_0_LIBRARIES ${GSTREAMER_1_0_BASE_LIBRARIES})
list(APPEND GSTREAMER_1_0_INCLUDE_DIRS ${GSTREAMER_1_0_APP_INCLUDE_DIRS})
list(APPEND GSTREAMER_1_0_LIBRARIES ${GSTREAMER_1_0_APP_LIBRARIES})
list(APPEND GSTREAMER_1_0_INCLUDE_DIRS ${GSTREAMER_1_0_VIDEO_INCLUDE_DIRS})
list(APPEND GSTREAMER_1_0_LIBRARIES ${GSTREAMER_1_0_VIDEO_LIBRARIES})
foreach (_component ${Gstreamer_FIND_COMPONENTS})
set(_gst_component "GSTREAMER_1_0_${_component}")
string(TOUPPER ${_gst_component} _UPPER_NAME)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(${_UPPER_NAME} DEFAULT_MSG ${_UPPER_NAME}_INCLUDE_DIRS ${_UPPER_NAME}_LIBRARIES)
list(APPEND GSTREAMER_1_0_INCLUDE_DIRS ${${_UPPER_NAME}_INCLUDE_DIRS})
list(APPEND GSTREAMER_1_0_LIBRARIES ${${_UPPER_NAME}_LIBRARIES})
endforeach ()
MARK_AS_ADVANCED(GSTREAMER_1_0_INCLUDE_DIRS GSTREAMER_1_0_LIBRARIES GSTREAMER_1_0_BASE_LIBRARY GSTREAMER_1_0_APP_LIBRARY)

43
cmake/FindGlib.cmake Normal file
View File

@ -0,0 +1,43 @@
# - Try to find Glib-2.0 (with gobject)
# Once done, this will define
#
# Glib_FOUND - system has Glib
# Glib_INCLUDE_DIRS - the Glib include directories
# Glib_LIBRARIES - link these to use Glib
#
# GLIB_ROOT_DIR - Primary search directory
include(LibFindMacros)
# Use pkg-config to get hints about paths
libfind_pkg_check_modules(Glib_PKGCONF glib-2.0)
# Main include dir
find_path(Glib_INCLUDE_DIR
NAMES glib.h
PATHS ${Glib_PKGCONF_INCLUDE_DIRS} ${GLIB_ROOT_DIR}
PATH_SUFFIXES glib-2.0
)
# Finally the library itself
find_library(Glib_LIBRARY
NAMES glib-2.0 gstreamer_android
PATHS ${Glib_PKGCONF_LIBRARY_DIRS} ${GLIB_ROOT_DIR}
)
find_library(Gobject_LIBRARY
NAMES gobject-2.0 gstreamer_android
PATHS ${Glib_PKGCONF_LIBRARY_DIRS} ${GLIB_ROOT_DIR}
)
# Glib-related libraries also use a separate config header, which is in lib dir
find_path(GlibConfig_INCLUDE_DIR
NAMES glibconfig.h
PATHS ${Glib_PKGCONF_INCLUDE_DIRS} /usr ${GLIB_ROOT_DIR}
PATH_SUFFIXES lib/glib-2.0/include glib-2.0/include
)
# Set the include dir variables and the libraries and let libfind_process do the rest.
# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
set(Glib_PROCESS_INCLUDES Glib_INCLUDE_DIR GlibConfig_INCLUDE_DIR)
set(Glib_PROCESS_LIBS Glib_LIBRARY Gobject_LIBRARY)
libfind_process(Glib)

View File

@ -1,12 +0,0 @@
include(FindPkgConfig)
pkg_check_modules(PC_GSTREAMER_0_10 gstreamer-0.10)
pkg_check_modules(PC_GSTREAMER_PLUGINS_BASE_0_10 gstreamer-plugins-base-0.10)
if(PC_GSTREAMER_0_10_FOUND AND PC_GSTREAMER_PLUGINS_BASE_0_10_FOUND)
set(GSTREAMER_INCLUDE_DIRS ${PC_GSTREAMER_0_10_INCLUDE_DIRS} ${PC_GSTREAMER_PLUGINS_BASE_0_10_INCLUDE_DIRS})
set(GSTREAMER_LIBRARIES ${PC_GSTREAMER_0_10_LIBRARIES} ${PC_GSTREAMER_PLUGINS_BASE_0_10_LIBRARIES})
endif()
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GSTREAMER DEFAULT_MSG GSTREAMER_LIBRARIES GSTREAMER_INCLUDE_DIRS)

116
cmake/LibFindMacros.cmake Normal file
View File

@ -0,0 +1,116 @@
# Works the same as find_package, but forwards the "REQUIRED" and "QUIET" arguments
# used for the current package. For this to work, the first parameter must be the
# prefix of the current package, then the prefix of the new package etc, which are
# passed to find_package.
macro(libfind_package PREFIX)
set(LIBFIND_PACKAGE_ARGS $ {ARGN})
if($ {PREFIX} _FIND_QUIETLY)
set(LIBFIND_PACKAGE_ARGS $ {LIBFIND_PACKAGE_ARGS} QUIET)
endif($ {PREFIX} _FIND_QUIETLY)
if($ {PREFIX} _FIND_REQUIRED)
set(LIBFIND_PACKAGE_ARGS $ {LIBFIND_PACKAGE_ARGS} REQUIRED)
endif($ {PREFIX} _FIND_REQUIRED)
find_package($ {LIBFIND_PACKAGE_ARGS})
endmacro(libfind_package)
# CMake developers made the UsePkgConfig system deprecated in the same release (2.6)
# where they added pkg_check_modules. Consequently I need to support both in my scripts
# to avoid those deprecated warnings. Here's a helper that does just that.
# Works identically to pkg_check_modules, except that no checks are needed prior to use.
macro (libfind_pkg_check_modules PREFIX PKGNAME)
if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
include(UsePkgConfig)
pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS)
else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(${PREFIX} ${PKGNAME})
endif (PKG_CONFIG_FOUND)
endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
endmacro (libfind_pkg_check_modules)
# Do the final processing once the paths have been detected.
# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain
# all the variables, each of which contain one include directory.
# Ditto for ${PREFIX}_PROCESS_LIBS and library files.
# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.
# Also handles errors in case library detection was required, etc.
macro (libfind_process PREFIX)
# Skip processing if already processed during this run
if (NOT ${PREFIX}_FOUND)
# Start with the assumption that the library was found
set (${PREFIX}_FOUND TRUE)
# Process all includes and set _FOUND to false if any are missing
foreach (i ${${PREFIX}_PROCESS_INCLUDES})
if (${i})
set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}})
mark_as_advanced(${i})
else (${i})
set (${PREFIX}_FOUND FALSE)
endif (${i})
endforeach (i)
# Process all libraries and set _FOUND to false if any are missing
foreach (i ${${PREFIX}_PROCESS_LIBS})
if (${i})
set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}})
mark_as_advanced(${i})
else (${i})
set (${PREFIX}_FOUND FALSE)
endif (${i})
endforeach (i)
# Print message and/or exit on fatal error
if (${PREFIX}_FOUND)
if (NOT ${PREFIX}_FIND_QUIETLY)
message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}")
endif (NOT ${PREFIX}_FIND_QUIETLY)
else (${PREFIX}_FOUND)
if (${PREFIX}_FIND_REQUIRED)
foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS})
message("${i}=${${i}}")
endforeach (i)
message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.")
endif (${PREFIX}_FIND_REQUIRED)
endif (${PREFIX}_FOUND)
endif (NOT ${PREFIX}_FOUND)
endmacro (libfind_process)
macro(libfind_library PREFIX basename)
set(TMP "")
if(MSVC80)
set(TMP -vc80)
endif(MSVC80)
if(MSVC90)
set(TMP -vc90)
endif(MSVC90)
set(${PREFIX}_LIBNAMES ${basename}${TMP})
if(${ARGC} GREATER 2)
set(${PREFIX}_LIBNAMES ${basename}${TMP}-${ARGV2})
string(REGEX REPLACE "\\." "_" TMP ${${PREFIX}_LIBNAMES})
set(${PREFIX}_LIBNAMES ${${PREFIX}_LIBNAMES} ${TMP})
endif(${ARGC} GREATER 2)
find_library(${PREFIX}_LIBRARY
NAMES ${${PREFIX}_LIBNAMES}
PATHS ${${PREFIX}_PKGCONF_LIBRARY_DIRS})
endmacro(libfind_library)
SET(THREE_PART_VERSION_REGEX "[0-9]+\\.[0-9]+\\.[0-9]+")
# Breaks up a string in the form n1.n2.n3 into three parts and stores
# them in major, minor, and patch. version should be a value, not a
# variable, while major, minor and patch should be variables.
MACRO(THREE_PART_VERSION_TO_VARS version major minor patch)
IF(${version} MATCHES ${THREE_PART_VERSION_REGEX})
STRING(REPLACE "." " " version_list ${version})
SEPARATE_ARGUMENTS(version_list)
LIST(GET version_list 0 ${major})
LIST(GET version_list 1 ${minor})
LIST(GET version_list 2 ${patch})
ELSE(${version} MATCHES ${THREE_PART_VERSION_REGEX})
MESSAGE("MACRO(THREE_PART_VERSION_TO_VARS ${version} ${major} ${minor} ${patch}")
MESSAGE(FATAL_ERROR "Problem parsing version string, I can't parse it properly.")
ENDIF(${version} MATCHES ${THREE_PART_VERSION_REGEX})
ENDMACRO(THREE_PART_VERSION_TO_VARS)

View File

@ -39,6 +39,9 @@
#cmakedefine WITH_WIN8 #cmakedefine WITH_WIN8
#cmakedefine WITH_RDPSND_DSOUND #cmakedefine WITH_RDPSND_DSOUND
#cmakedefine WITH_FFMPEG
#cmakedefine WITH_GSTREAMER_1_0
#cmakedefine WITH_GSTREAMER_0_10
#cmakedefine WITH_WINMM #cmakedefine WITH_WINMM
#cmakedefine WITH_MACAUDIO #cmakedefine WITH_MACAUDIO
#cmakedefine WITH_ALSA #cmakedefine WITH_ALSA
@ -58,6 +61,7 @@
#cmakedefine WITH_DEBUG_CHANNELS #cmakedefine WITH_DEBUG_CHANNELS
#cmakedefine WITH_DEBUG_CLIPRDR #cmakedefine WITH_DEBUG_CLIPRDR
#cmakedefine WITH_DEBUG_DVC #cmakedefine WITH_DEBUG_DVC
#cmakedefine WITH_DEBUG_TSMF
#cmakedefine WITH_DEBUG_GDI #cmakedefine WITH_DEBUG_GDI
#cmakedefine WITH_DEBUG_KBD #cmakedefine WITH_DEBUG_KBD
#cmakedefine WITH_DEBUG_LICENSE #cmakedefine WITH_DEBUG_LICENSE

View File

@ -0,0 +1,63 @@
/*
* FreeRDP: A Remote Desktop Protocol Implementation
* Video Redirection Virtual Channel - Callback interface
*
* (C) Copyright 2014 Thincast Technologies GmbH
* (C) Copyright 2014 Armin Novak <armin.novak@thincast.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 _TSMF_H_
#define _TSMF_H_
#include <freerdp/types.h>
/* Callback function setup order:
*
* When the channel is loaded, it calls TSMF_REGISTER to register the
* decoder handle with the client.
* The client then stores the handle and calls TSMF_REGISTER_INSTANCE
* to give the channel the current handle to the session necessary
* to call other functions.
* After this initial setup the other functions can be used.
*/
/* Functions called from client -> registered by channel */
#define TSMF_GET_INSTANCE "tsmf_get_instance"
typedef void (*tsmf_get_instance)(void *instance, void *decoder);
#define TSMF_ADD_WINDOW_HANDLE "tsmf_add_window_handle"
typedef void (*tsmf_add_window_handle)(void *instance, void *decoder, void *window);
#define TSMF_DEL_WINDOW_HANDLE "tsmf_del_window_handle"
typedef void (*tsmf_del_window_handle)(void *instance, void *decoder);
/* Functions called from channel -> registered by client */
#define TSMF_REGISTER "tsmf_register"
typedef void (*tsmf_register)(void *instance, void *decoder);
#define TSMF_DESTROY "tsmf_destroy"
typedef void (*tsmf_destroy)(void *instance, void *decoder);
#define TSMF_PLAY "tsmf_play"
typedef void (*tsmf_play)(void *instance, void *decoder);
#define TSMF_PAUSE "tsmf_pause"
typedef void (*tsmf_pause)(void *instance, void *decoder);
#define TSMF_RESIZE_WINDOW "tsmf_resize_window"
typedef void (*tsmf_resize_window)(void *instance, void *decoder, int x, int y, int width,
int height, int nr_rect, RDP_RECT *visible);
#endif

View File

@ -35,6 +35,7 @@ FREERDP_API int freerdp_client_print_version(void);
FREERDP_API int freerdp_client_print_command_line_help(int argc, char** argv); FREERDP_API int freerdp_client_print_command_line_help(int argc, char** argv);
FREERDP_API int freerdp_parse_username(char* username, char** user, char** domain); FREERDP_API int freerdp_parse_username(char* username, char** user, char** domain);
FREERDP_API int freerdp_parse_hostname(char* hostname, char** host, int* port);
FREERDP_API int freerdp_set_connection_type(rdpSettings* settings, int type); FREERDP_API int freerdp_set_connection_type(rdpSettings* settings, int type);
FREERDP_API int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** params); FREERDP_API int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** params);

View File

@ -137,9 +137,7 @@ struct _IWTSListenerCallback
struct _IWTSVirtualChannelCallback struct _IWTSVirtualChannelCallback
{ {
/* Notifies the user about data that is being received. */ /* Notifies the user about data that is being received. */
int (*OnDataReceived) (IWTSVirtualChannelCallback* pChannelCallback, int (*OnDataReceived) (IWTSVirtualChannelCallback* pChannelCallback, wStream* data);
UINT32 cbSize,
BYTE* pBuffer);
/* Notifies the user that the channel has been opened. */ /* Notifies the user that the channel has been opened. */
int (*OnOpen) (IWTSVirtualChannelCallback* pChannelCallback); int (*OnOpen) (IWTSVirtualChannelCallback* pChannelCallback);
/* Notifies the user that the channel has been closed. */ /* Notifies the user that the channel has been closed. */
@ -159,4 +157,8 @@ struct _IDRDYNVC_ENTRY_POINTS
typedef int (*PDVC_PLUGIN_ENTRY)(IDRDYNVC_ENTRY_POINTS *); typedef int (*PDVC_PLUGIN_ENTRY)(IDRDYNVC_ENTRY_POINTS *);
void *get_callback_by_name(const char *name, void **context);
void add_callback_by_name(const char *name, void *fkt, void *context);
void remove_callback_by_name(const char *name, void *context);
#endif /* FREERDP_DVC_H */ #endif /* FREERDP_DVC_H */

View File

@ -85,11 +85,7 @@
#define WITH_DEBUG_CREDSSP #define WITH_DEBUG_CREDSSP
#endif #endif
#ifdef WITH_NATIVE_SSPI #define NLA_PKG_NAME NEGOSSP_NAME
#define NLA_PKG_NAME NTLMSP_NAME
#else
#define NLA_PKG_NAME NTLMSP_NAME
#endif
#define TERMSRV_SPN_PREFIX "TERMSRV/" #define TERMSRV_SPN_PREFIX "TERMSRV/"
@ -267,24 +263,7 @@ int credssp_client_authenticate(rdpCredssp* credssp)
if (credssp_ntlm_client_init(credssp) == 0) if (credssp_ntlm_client_init(credssp) == 0)
return 0; return 0;
#ifdef WITH_NATIVE_SSPI credssp->table = InitSecurityInterfaceEx(0);
{
HMODULE hSSPI;
INIT_SECURITY_INTERFACE InitSecurityInterface;
PSecurityFunctionTable pSecurityInterface = NULL;
hSSPI = LoadLibrary(_T("secur32.dll"));
#ifdef UNICODE
InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW");
#else
InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA");
#endif
credssp->table = (*InitSecurityInterface)();
}
#else
credssp->table = InitSecurityInterface();
#endif
status = credssp->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &pPackageInfo); status = credssp->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &pPackageInfo);
@ -337,17 +316,25 @@ int credssp_client_authenticate(rdpCredssp* credssp)
SECURITY_NATIVE_DREP, (have_input_buffer) ? &input_buffer_desc : NULL, SECURITY_NATIVE_DREP, (have_input_buffer) ? &input_buffer_desc : NULL,
0, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration); 0, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration);
if (have_input_buffer && (input_buffer.pvBuffer != NULL)) if (have_input_buffer && (input_buffer.pvBuffer))
{ {
free(input_buffer.pvBuffer); free(input_buffer.pvBuffer);
input_buffer.pvBuffer = NULL; input_buffer.pvBuffer = NULL;
} }
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK)) if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
{ {
if (credssp->table->CompleteAuthToken != NULL) if (credssp->table->CompleteAuthToken)
credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc); credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
else if (status == SEC_I_COMPLETE_AND_CONTINUE)
status = SEC_I_CONTINUE_NEEDED;
}
if (status == SEC_E_OK)
{
have_pub_key_auth = TRUE; have_pub_key_auth = TRUE;
if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK) if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK)
@ -357,11 +344,6 @@ int credssp_client_authenticate(rdpCredssp* credssp)
} }
credssp_encrypt_public_key_echo(credssp); credssp_encrypt_public_key_echo(credssp);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
else if (status == SEC_I_COMPLETE_AND_CONTINUE)
status = SEC_I_CONTINUE_NEEDED;
} }
/* send authentication token to server */ /* send authentication token to server */
@ -469,11 +451,6 @@ int credssp_server_authenticate(rdpCredssp* credssp)
if (credssp_ntlm_server_init(credssp) == 0) if (credssp_ntlm_server_init(credssp) == 0)
return 0; return 0;
#ifdef WITH_NATIVE_SSPI
if (!credssp->SspiModule)
credssp->SspiModule = _tcsdup(_T("secur32.dll"));
#endif
if (credssp->SspiModule) if (credssp->SspiModule)
{ {
HMODULE hSSPI; HMODULE hSSPI;
@ -493,14 +470,12 @@ int credssp_server_authenticate(rdpCredssp* credssp)
pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA"); pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA");
#endif #endif
credssp->table = (*pInitSecurityInterface)(); credssp->table = pInitSecurityInterface();
} }
#ifndef WITH_NATIVE_SSPI
else else
{ {
credssp->table = InitSecurityInterface(); credssp->table = InitSecurityInterfaceEx(0);
} }
#endif
status = credssp->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &pPackageInfo); status = credssp->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &pPackageInfo);
@ -597,7 +572,7 @@ int credssp_server_authenticate(rdpCredssp* credssp)
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED)) if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
{ {
if (credssp->table->CompleteAuthToken != NULL) if (credssp->table->CompleteAuthToken)
credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc); credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc);
if (status == SEC_I_COMPLETE_NEEDED) if (status == SEC_I_COMPLETE_NEEDED)
@ -1385,7 +1360,7 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings*
{ {
rdpCredssp* credssp; rdpCredssp* credssp;
credssp = (rdpCredssp*) malloc(sizeof(rdpCredssp)); credssp = (rdpCredssp*) calloc(1, sizeof(rdpCredssp));
if (credssp) if (credssp)
{ {
@ -1394,8 +1369,6 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings*
DWORD dwType; DWORD dwType;
DWORD dwSize; DWORD dwSize;
ZeroMemory(credssp, sizeof(rdpCredssp));
credssp->instance = instance; credssp->instance = instance;
credssp->settings = settings; credssp->settings = settings;
credssp->server = settings->ServerMode; credssp->server = settings->ServerMode;

23
scripts/format_code.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/sh
ASTYLE=`which astyle`
if [ ! -x $ASTYLE ];
then
echo "No astyle found in path, please install."
exit 1
fi
if [ $# -le 0 ]; then
echo "Usage:"
echo "\t$0 <file1> [<file2> ...]"
# echo "\t$0 -r <directory>"
exit 2
fi
$ASTYLE --lineend=linux --mode=c --indent=force-tab=4 --brackets=linux --pad-header \
--indent-switches --indent-cases --indent-preprocessor \
--indent-col1-comments --delete-empty-lines --break-closing-brackets \
--align-pointer=name --indent-labels --brackets=break \
--unpad-paren --break-blocks $@
exit $?

View File

@ -541,6 +541,10 @@ static void* xf_peer_main_loop(void* arg)
settings->RemoteFxCodec = TRUE; settings->RemoteFxCodec = TRUE;
settings->ColorDepth = 32; settings->ColorDepth = 32;
settings->NlaSecurity = FALSE;
settings->TlsSecurity = TRUE;
settings->RdpSecurity = FALSE;
client->Capabilities = xf_peer_capabilities; client->Capabilities = xf_peer_capabilities;
client->PostConnect = xf_peer_post_connect; client->PostConnect = xf_peer_post_connect;
client->Activate = xf_peer_activate; client->Activate = xf_peer_activate;

View File

@ -67,9 +67,6 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINPR_EXPORTS")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/winpr/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/winpr/config.h)
add_subdirectory(include) add_subdirectory(include)
add_subdirectory(libwinpr) add_subdirectory(libwinpr)

View File

@ -29,7 +29,22 @@
#include <wincrypt.h> #include <wincrypt.h>
#else #endif
#ifndef ALG_TYPE_RESERVED7
#define ALG_TYPE_RESERVED7 (7 << 9)
#endif
#if (NTDDI_VERSION <= 0x05010200)
#define ALG_SID_SHA_256 12
#define ALG_SID_SHA_384 13
#define ALG_SID_SHA_512 14
#define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
#define CALG_SHA_384 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384)
#define CALG_SHA_512 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512)
#endif
#ifndef _WIN32
/* ncrypt.h */ /* ncrypt.h */
@ -60,7 +75,6 @@ typedef ULONG_PTR NCRYPT_SECRET_HANDLE;
#define ALG_TYPE_STREAM (4 << 9) #define ALG_TYPE_STREAM (4 << 9)
#define ALG_TYPE_DH (5 << 9) #define ALG_TYPE_DH (5 << 9)
#define ALG_TYPE_SECURECHANNEL (6 << 9) #define ALG_TYPE_SECURECHANNEL (6 << 9)
#define ALG_TYPE_RESERVED7 (7 << 9)
#define ALG_SID_ANY (0) #define ALG_SID_ANY (0)
@ -74,8 +88,6 @@ typedef ULONG_PTR NCRYPT_SECRET_HANDLE;
#define ALG_SID_DSS_PKCS 1 #define ALG_SID_DSS_PKCS 1
#define ALG_SID_DSS_DMS 2 #define ALG_SID_DSS_DMS 2
#define ALG_SID_ECDSA 3
#define ALG_SID_DES 1 #define ALG_SID_DES 1
#define ALG_SID_3DES 3 #define ALG_SID_3DES 3
#define ALG_SID_DESX 4 #define ALG_SID_DESX 4
@ -192,7 +204,6 @@ typedef ULONG_PTR NCRYPT_SECRET_HANDLE;
#define CALG_ECDH (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_ECDH) #define CALG_ECDH (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_ECDH)
#define CALG_ECMQV (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_ANY | ALG_SID_ECMQV) #define CALG_ECMQV (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_ANY | ALG_SID_ECMQV)
#define CALG_ECDSA (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_ECDSA)
typedef struct _CRYPTOAPI_BLOB typedef struct _CRYPTOAPI_BLOB
{ {
@ -594,5 +605,10 @@ BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, L
#endif #endif
#ifndef ALG_SID_ECSDA
#define ALG_SID_ECDSA 3
#define CALG_ECDSA (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_ECDSA)
#endif
#endif /* WINPR_CRYPTO_H */ #endif /* WINPR_CRYPTO_H */

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* Security Support Provider Interface (SSPI) * Security Support Provider Interface (SSPI)
* *
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,37 +20,23 @@
#ifndef WINPR_SSPI_H #ifndef WINPR_SSPI_H
#define WINPR_SSPI_H #define WINPR_SSPI_H
#include <winpr/config.h>
#include <wchar.h>
#include <winpr/winpr.h> #include <winpr/winpr.h>
#include <winpr/wtypes.h> #include <winpr/wtypes.h>
#include <winpr/windows.h> #include <winpr/windows.h>
#include <winpr/security.h> #include <winpr/security.h>
#define _NO_KSECDD_IMPORT_ 1
#ifdef _WIN32 #ifdef _WIN32
#include <tchar.h> #include <tchar.h>
#include <winerror.h> #include <winerror.h>
#ifdef WITH_NATIVE_SSPI
#define SECURITY_WIN32 #define SECURITY_WIN32
#include <sspi.h> #include <sspi.h>
#include <security.h> #include <security.h>
#else
#define WINPR_SSPI
#define SEC_ENTRY __stdcall
#endif
#else
#define WINPR_SSPI
#endif #endif
#ifdef WINPR_SSPI #ifndef _WIN32
#ifndef SEC_ENTRY #ifndef SEC_ENTRY
#define SEC_ENTRY #define SEC_ENTRY
@ -266,7 +252,7 @@ typedef SecPkgInfoW* PSecPkgInfoW;
#define SECPKG_ATTR_NEGO_STATUS 32 #define SECPKG_ATTR_NEGO_STATUS 32
#define SECPKG_ATTR_CONTEXT_DELETED 33 #define SECPKG_ATTR_CONTEXT_DELETED 33
#ifdef WINPR_SSPI #ifndef _WIN32
struct _SecPkgContext_AccessToken struct _SecPkgContext_AccessToken
{ {
@ -593,7 +579,7 @@ typedef SecPkgCredentials_NamesW* PSecPkgCredentials_NamesW;
#define SEC_WINNT_AUTH_IDENTITY_ANSI 0x1 #define SEC_WINNT_AUTH_IDENTITY_ANSI 0x1
#define SEC_WINNT_AUTH_IDENTITY_UNICODE 0x2 #define SEC_WINNT_AUTH_IDENTITY_UNICODE 0x2
#ifdef WINPR_SSPI #ifndef _WIN32
typedef struct _SEC_WINNT_AUTH_IDENTITY_W typedef struct _SEC_WINNT_AUTH_IDENTITY_W
{ {
@ -679,7 +665,7 @@ typedef CtxtHandle* PCtxtHandle;
#define SECBUFFER_READONLY_WITH_CHECKSUM 0x10000000 #define SECBUFFER_READONLY_WITH_CHECKSUM 0x10000000
#define SECBUFFER_RESERVED 0x60000000 #define SECBUFFER_RESERVED 0x60000000
#ifdef WINPR_SSPI #ifndef _WIN32
struct _SecBuffer struct _SecBuffer
{ {
@ -1000,8 +986,7 @@ WINPR_API SECURITY_STATUS SEC_ENTRY VerifySignature(PCtxtHandle phContext, PSecB
} }
#endif #endif
#endif // WINPR_SSPI #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -1009,14 +994,56 @@ extern "C" {
/* Custom API */ /* Custom API */
#define SECPKG_ATTR_AUTH_IDENTITY 1001
#define SECPKG_ATTR_AUTH_PASSWORD 1002
#define SECPKG_ATTR_AUTH_NTLM_HASH 1003
struct _SecPkgContext_AuthIdentity
{
char User[256 + 1];
char Domain[256 + 1];
};
typedef struct _SecPkgContext_AuthIdentity SecPkgContext_AuthIdentity;
struct _SecPkgContext_AuthPassword
{
char Password[256 + 1];
};
typedef struct _SecPkgContext_AuthPassword SecPkgContext_AuthPassword;
struct _SecPkgContext_AuthNtlmHash
{
BYTE NtlmHash[16];
};
typedef struct _SecPkgContext_AuthNtlmHash SecPkgContext_AuthNtlmHash;
#define SSPI_INTERFACE_WINPR 0x00000001
#define SSPI_INTERFACE_NATIVE 0x00000002
typedef PSecurityFunctionTableA (SEC_ENTRY * INIT_SECURITY_INTERFACE_EX_A)(DWORD flags);
typedef PSecurityFunctionTableW (SEC_ENTRY * INIT_SECURITY_INTERFACE_EX_W)(DWORD flags);
WINPR_API void sspi_GlobalInit(void); WINPR_API void sspi_GlobalInit(void);
WINPR_API void sspi_GlobalFinish(void); WINPR_API void sspi_GlobalFinish(void);
WINPR_API void sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size); WINPR_API void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size);
WINPR_API void sspi_SecBufferFree(PSecBuffer SecBuffer); WINPR_API void sspi_SecBufferFree(PSecBuffer SecBuffer);
WINPR_API void sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, char* user, char* domain, char* password); WINPR_API int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain, const char* password);
WINPR_API void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDENTITY* srcIdentity); WINPR_API int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDENTITY* srcIdentity);
WINPR_API const char* GetSecurityStatusString(SECURITY_STATUS status);
WINPR_API SecurityFunctionTableW* SEC_ENTRY InitSecurityInterfaceExW(DWORD flags);
WINPR_API SecurityFunctionTableA* SEC_ENTRY InitSecurityInterfaceExA(DWORD flags);
#ifdef UNICODE
#define InitSecurityInterfaceEx InitSecurityInterfaceExW
#define INIT_SECURITY_INTERFACE_EX INIT_SECURITY_INTERFACE_EX_W
#else
#define InitSecurityInterfaceEx InitSecurityInterfaceExA
#define INIT_SECURITY_INTERFACE_EX INIT_SECURITY_INTERFACE_EX_A
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -62,7 +62,11 @@ WINPR_API BOOL TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZon
#endif #endif
#if !defined(_WIN32) || (defined(_WIN32) && (_WIN32_WINNT < 0x0600)) /* Windows Vista */ /*
* GetDynamicTimeZoneInformation is provided by the SDK if _WIN32_WINNT >= 0x0600 in SDKs above 7.1A
* and incorrectly if _WIN32_WINNT >= 0x0501 in older SDKs
*/
#if !defined(_WIN32) || (defined(_WIN32) && (defined(NTDDI_WIN8) && _WIN32_WINNT < 0x0600 || !defined(NTDDI_WIN8) && _WIN32_WINNT < 0x0501)) /* Windows Vista */
WINPR_API DWORD GetDynamicTimeZoneInformation(PDYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation); WINPR_API DWORD GetDynamicTimeZoneInformation(PDYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation);
WINPR_API BOOL SetDynamicTimeZoneInformation(const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation); WINPR_API BOOL SetDynamicTimeZoneInformation(const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation);

View File

@ -25,6 +25,7 @@
#include <wctype.h> #include <wctype.h>
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/error.h>
#include <winpr/print.h> #include <winpr/print.h>
#ifndef _WIN32 #ifndef _WIN32
@ -303,7 +304,15 @@ int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
allocate = TRUE; allocate = TRUE;
if (allocate) if (allocate)
*lpWideCharStr = (LPWSTR) malloc(cchWideChar * sizeof(WCHAR)); {
*lpWideCharStr = (LPWSTR) calloc(cchWideChar, sizeof(WCHAR));
if (!(*lpWideCharStr))
{
//SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
}
status = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, *lpWideCharStr, cchWideChar); status = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, *lpWideCharStr, cchWideChar);
@ -342,15 +351,22 @@ int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int
if (allocate) if (allocate)
{ {
*lpMultiByteStr = (LPSTR) malloc(cbMultiByte + 1); *lpMultiByteStr = (LPSTR) calloc(1, cbMultiByte + 1);
ZeroMemory(*lpMultiByteStr, cbMultiByte + 1);
if (!(*lpMultiByteStr))
{
//SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
} }
status = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, status = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar,
*lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar); *lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
if (status != cbMultiByte) if ((status != cbMultiByte) && allocate)
{
status = 0; status = 0;
}
if ((status <= 0) && allocate) if ((status <= 0) && allocate)
{ {

View File

@ -193,7 +193,6 @@ static void* named_pipe_single_thread(void* arg)
{ {
HANDLE servers[TESTNUMPIPESST]; HANDLE servers[TESTNUMPIPESST];
HANDLE clients[TESTNUMPIPESST]; HANDLE clients[TESTNUMPIPESST];
WINPR_NAMED_PIPE* p;
char sndbuf[PIPE_BUFFER_SIZE]; char sndbuf[PIPE_BUFFER_SIZE];
char rcvbuf[PIPE_BUFFER_SIZE]; char rcvbuf[PIPE_BUFFER_SIZE];
DWORD dwRead; DWORD dwRead;
@ -201,6 +200,9 @@ static void* named_pipe_single_thread(void* arg)
int i; int i;
int numPipes; int numPipes;
BOOL bSuccess = FALSE; BOOL bSuccess = FALSE;
#ifndef _WIN32
WINPR_NAMED_PIPE* p;
#endif
numPipes = TESTNUMPIPESST; numPipes = TESTNUMPIPESST;
@ -220,6 +222,7 @@ static void* named_pipe_single_thread(void* arg)
} }
} }
#ifndef _WIN32
for (i = 0; i < numPipes; i++) for (i = 0; i < numPipes; i++)
{ {
p = (WINPR_NAMED_PIPE*)servers[i]; p = (WINPR_NAMED_PIPE*)servers[i];
@ -252,6 +255,7 @@ static void* named_pipe_single_thread(void* arg)
goto out; goto out;
} }
} }
#endif
for (i = 0; i < numPipes; i++) for (i = 0; i < numPipes; i++)
{ {
@ -269,9 +273,11 @@ static void* named_pipe_single_thread(void* arg)
} }
} }
#ifndef _WIN32
for (i = 0; i < numPipes; i++) for (i = 0; i < numPipes; i++)
{ {
p = servers[i]; p = servers[i];
if (p->clientfd < 1) if (p->clientfd < 1)
{ {
printf("%s: Unexpected client fd value for pipe #%d (%d is not > 0)\n", printf("%s: Unexpected client fd value for pipe #%d (%d is not > 0)\n",
@ -279,7 +285,7 @@ static void* named_pipe_single_thread(void* arg)
goto out; goto out;
} }
if (p->ServerMode == TRUE) if (p->ServerMode)
{ {
printf("%s: Unexpected ServerMode value for pipe #%d (1 instead of 0)\n", printf("%s: Unexpected ServerMode value for pipe #%d (1 instead of 0)\n",
__FUNCTION__, i); __FUNCTION__, i);
@ -291,11 +297,12 @@ static void* named_pipe_single_thread(void* arg)
{ {
/* Test writing from clients to servers */ /* Test writing from clients to servers */
memset(sndbuf, 0, sizeof(sndbuf)); ZeroMemory(sndbuf, sizeof(sndbuf));
memset(rcvbuf, 0, sizeof(rcvbuf)); ZeroMemory(rcvbuf, sizeof(rcvbuf));
snprintf(sndbuf, sizeof(sndbuf), "CLIENT->SERVER ON PIPE #%05d", i); sprintf_s(sndbuf, sizeof(sndbuf), "CLIENT->SERVER ON PIPE #%05d", i);
p = servers[i]; p = servers[i];
if (!WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL) || if (!WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL) ||
dwWritten != sizeof(sndbuf)) dwWritten != sizeof(sndbuf))
{ {
@ -319,9 +326,9 @@ static void* named_pipe_single_thread(void* arg)
/* Test writing from servers to clients */ /* Test writing from servers to clients */
memset(sndbuf, 0, sizeof(sndbuf)); ZeroMemory(sndbuf, sizeof(sndbuf));
memset(rcvbuf, 0, sizeof(rcvbuf)); ZeroMemory(rcvbuf, sizeof(rcvbuf));
snprintf(sndbuf, sizeof(sndbuf), "SERVER->CLIENT ON PIPE #%05d", i); sprintf_s(sndbuf, sizeof(sndbuf), "SERVER->CLIENT ON PIPE #%05d", i);
p = servers[i]; p = servers[i];
if (!WriteFile(servers[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL) || if (!WriteFile(servers[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL) ||
@ -345,6 +352,7 @@ static void* named_pipe_single_thread(void* arg)
goto out; goto out;
} }
} }
#endif
/** /**
* After DisconnectNamedPipe on server end * After DisconnectNamedPipe on server end

View File

@ -43,20 +43,21 @@ set(${MODULE_PREFIX}_CREDSSP_SRCS
set(${MODULE_PREFIX}_SRCS set(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_CREDSSP_SRCS} ${${MODULE_PREFIX}_CREDSSP_SRCS}
sspi_winpr.c
sspi_winpr.h
sspi_export.c
sspi.c sspi.c
sspi.h) sspi.h)
if(NOT WITH_NATIVE_SSPI)
set(${MODULE_PREFIX}_SRCS set(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_NTLM_SRCS} ${${MODULE_PREFIX}_NTLM_SRCS}
${${MODULE_PREFIX}_KERBEROS_SRCS} ${${MODULE_PREFIX}_KERBEROS_SRCS}
${${MODULE_PREFIX}_NEGOTIATE_SRCS} ${${MODULE_PREFIX}_NEGOTIATE_SRCS}
${${MODULE_PREFIX}_SCHANNEL_SRCS} ${${MODULE_PREFIX}_SCHANNEL_SRCS}
${${MODULE_PREFIX}_SRCS}) ${${MODULE_PREFIX}_SRCS})
endif()
if(MSVC AND (NOT MONOLITHIC_BUILD)) if(MSVC AND (NOT MONOLITHIC_BUILD))
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) #set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def)
endif() endif()
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
@ -80,7 +81,7 @@ endif()
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL
MODULE winpr MODULE winpr
MODULES winpr-crt winpr-sysinfo winpr-registry winpr-crypto winpr-utils) MODULES winpr-crt winpr-sysinfo winpr-registry winpr-crypto winpr-library winpr-utils)
if(MONOLITHIC_BUILD) if(MONOLITHIC_BUILD)
set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* Credential Security Support Provider (CredSSP) * Credential Security Support Provider (CredSSP)
* *
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2010-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -35,7 +35,7 @@ SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextW(PCredHandle phCrede
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{ {
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
@ -44,22 +44,24 @@ SECURITY_STATUS SEC_ENTRY credssp_InitializeSecurityContextA(PCredHandle phCrede
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{ {
CREDSSP_CONTEXT* context; CREDSSP_CONTEXT* context;
CREDENTIALS* credentials; SSPI_CREDENTIALS* credentials;
context = sspi_SecureHandleGetLowerPointer(phContext); context = (CREDSSP_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context) if (!context)
{ {
context = credssp_ContextNew(); context = credssp_ContextNew();
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); if (!context)
return SEC_E_INSUFFICIENT_MEMORY;
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) CREDSSP_PACKAGE_NAME); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) CREDSSP_PACKAGE_NAME);
} }
return SEC_E_OK; return SEC_E_OK;
} }
CREDSSP_CONTEXT* credssp_ContextNew() CREDSSP_CONTEXT* credssp_ContextNew()
@ -68,10 +70,8 @@ CREDSSP_CONTEXT* credssp_ContextNew()
context = (CREDSSP_CONTEXT*) calloc(1, sizeof(CREDSSP_CONTEXT)); context = (CREDSSP_CONTEXT*) calloc(1, sizeof(CREDSSP_CONTEXT));
if (context != NULL) if (!context)
{ return NULL;
}
return context; return context;
} }
@ -99,19 +99,23 @@ SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleW(SEC_WCHAR* pszPrinci
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{ {
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{ {
CREDENTIALS* credentials; SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity; SEC_WINNT_AUTH_IDENTITY* identity;
if (fCredentialUse == SECPKG_CRED_OUTBOUND) if (fCredentialUse == SECPKG_CRED_OUTBOUND)
{ {
credentials = sspi_CredentialsNew(); credentials = sspi_CredentialsNew();
if (!credentials)
return SEC_E_INSUFFICIENT_MEMORY;
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
@ -122,21 +126,21 @@ SECURITY_STATUS SEC_ENTRY credssp_AcquireCredentialsHandleA(SEC_CHAR* pszPrincip
return SEC_E_OK; return SEC_E_OK;
} }
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{ {
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{ {
if (ulAttribute == SECPKG_CRED_ATTR_NAMES) if (ulAttribute == SECPKG_CRED_ATTR_NAMES)
{ {
CREDENTIALS* credentials; SSPI_CREDENTIALS* credentials;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
return SEC_E_OK; return SEC_E_OK;
} }
@ -146,12 +150,12 @@ SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCred
SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle phCredential) SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle phCredential)
{ {
CREDENTIALS* credentials; SSPI_CREDENTIALS* credentials;
if (!phCredential) if (!phCredential)
return SEC_E_INVALID_HANDLE; return SEC_E_INVALID_HANDLE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials) if (!credentials)
return SEC_E_INVALID_HANDLE; return SEC_E_INVALID_HANDLE;
@ -163,22 +167,22 @@ SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle phCredential
SECURITY_STATUS SEC_ENTRY credssp_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) SECURITY_STATUS SEC_ENTRY credssp_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{ {
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY credssp_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) SECURITY_STATUS SEC_ENTRY credssp_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
{ {
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY credssp_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) SECURITY_STATUS SEC_ENTRY credssp_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{ {
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY credssp_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) SECURITY_STATUS SEC_ENTRY credssp_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
{ {
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
const SecurityFunctionTableA CREDSSP_SecurityFunctionTableA = const SecurityFunctionTableA CREDSSP_SecurityFunctionTableA =

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* NTLM Security Package * NTLM Security Package
* *
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -41,80 +41,126 @@
char* NTLM_PACKAGE_NAME = "NTLM"; char* NTLM_PACKAGE_NAME = "NTLM";
void ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation) int ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation)
{ {
char *ws = Workstation; int status;
DWORD nSize = 0; DWORD nSize = 0;
char* ws = Workstation;
if (!Workstation) if (!Workstation)
{ {
GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize); GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize);
ws = malloc(nSize);
GetComputerNameExA(ComputerNameNetBIOS, ws, &nSize); ws = (char*) malloc(nSize);
if (!ws)
return -1;
if (!GetComputerNameExA(ComputerNameNetBIOS, ws, &nSize))
return 0;
} }
context->Workstation.Length = ConvertToUnicode(CP_UTF8, 0, context->Workstation.Buffer = NULL;
ws, -1, &context->Workstation.Buffer, 0) - 1; status = ConvertToUnicode(CP_UTF8, 0, ws, -1, &context->Workstation.Buffer, 0);
free(ws);
if (status <= 0)
return -1;
context->Workstation.Length = (USHORT) (status - 1);
context->Workstation.Length *= 2; context->Workstation.Length *= 2;
if (!Workstation) if (!Workstation)
free(Workstation); free(Workstation);
return 1;
} }
void ntlm_SetContextServicePrincipalNameW(NTLM_CONTEXT* context, LPWSTR ServicePrincipalName) int ntlm_SetContextServicePrincipalNameW(NTLM_CONTEXT* context, LPWSTR ServicePrincipalName)
{ {
context->ServicePrincipalName.Length = _wcslen(ServicePrincipalName) * 2;
if (!ServicePrincipalName) if (!ServicePrincipalName)
{ {
context->ServicePrincipalName.Buffer = NULL; context->ServicePrincipalName.Buffer = NULL;
return; context->ServicePrincipalName.Length = 0;
return 1;
} }
context->ServicePrincipalName.Length = _wcslen(ServicePrincipalName) * 2;
context->ServicePrincipalName.Buffer = (PWSTR) malloc(context->ServicePrincipalName.Length + 2); context->ServicePrincipalName.Buffer = (PWSTR) malloc(context->ServicePrincipalName.Length + 2);
if (!context->ServicePrincipalName.Buffer)
return -1;
CopyMemory(context->ServicePrincipalName.Buffer, ServicePrincipalName, context->ServicePrincipalName.Length + 2); CopyMemory(context->ServicePrincipalName.Buffer, ServicePrincipalName, context->ServicePrincipalName.Length + 2);
return 1;
} }
void ntlm_SetContextServicePrincipalNameA(NTLM_CONTEXT* context, char* ServicePrincipalName) int ntlm_SetContextServicePrincipalNameA(NTLM_CONTEXT* context, char* ServicePrincipalName)
{ {
context->ServicePrincipalName.Length = ConvertToUnicode(CP_UTF8, 0, int status;
ServicePrincipalName, -1, &context->ServicePrincipalName.Buffer, 0) - 1;
context->ServicePrincipalName.Length *= 2; context->ServicePrincipalName.Buffer = NULL;
status = ConvertToUnicode(CP_UTF8, 0, ServicePrincipalName, -1, &context->ServicePrincipalName.Buffer, 0);
if (status <= 0)
return -1;
context->ServicePrincipalName.Length = (USHORT) ((status - 1) * 2);
return 1;
} }
void ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName) int ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName)
{ {
char *name = TargetName; int status;
DWORD nSize = 0; DWORD nSize = 0;
char* name = TargetName;
if (!TargetName) if (!TargetName)
{ {
GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize); if (!GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize))
name = malloc(nSize); return -1;
GetComputerNameExA(ComputerNameDnsHostname, name, &nSize);
name = (char*) malloc(nSize);
if (!name)
return -1;
if (!GetComputerNameExA(ComputerNameDnsHostname, name, &nSize))
return -1;
CharUpperA(TargetName); CharUpperA(TargetName);
} }
context->TargetName.cbBuffer = ConvertToUnicode(CP_UTF8, 0, context->TargetName.pvBuffer = NULL;
name, -1, (LPWSTR*) &context->TargetName.pvBuffer, 0) - 1; status = ConvertToUnicode(CP_UTF8, 0, name, -1, (LPWSTR*) &context->TargetName.pvBuffer, 0);
context->TargetName.cbBuffer *= 2;
if (status <= 0)
return -1;
context->TargetName.cbBuffer = (USHORT) ((status - 1) * 2);
if (!TargetName) if (!TargetName)
free(name); free(name);
return 1;
} }
NTLM_CONTEXT* ntlm_ContextNew() NTLM_CONTEXT* ntlm_ContextNew()
{
NTLM_CONTEXT* context;
context = (NTLM_CONTEXT*) malloc(sizeof(NTLM_CONTEXT));
ZeroMemory(context, sizeof(NTLM_CONTEXT));
if (context != NULL)
{ {
HKEY hKey; HKEY hKey;
LONG status; LONG status;
DWORD dwType; DWORD dwType;
DWORD dwSize; DWORD dwSize;
DWORD dwValue; DWORD dwValue;
NTLM_CONTEXT* context;
context = (NTLM_CONTEXT*) calloc(1, sizeof(NTLM_CONTEXT));
if (!context)
return NULL;
context->NTLMv2 = TRUE; context->NTLMv2 = TRUE;
context->UseMIC = FALSE; context->UseMIC = FALSE;
@ -145,10 +191,15 @@ NTLM_CONTEXT* ntlm_ContextNew()
{ {
char* workstation = (char*) malloc(dwSize + 1); char* workstation = (char*) malloc(dwSize + 1);
if (!workstation)
return NULL;
status = RegQueryValueExA(hKey, "WorkstationName", NULL, &dwType, (BYTE*) workstation, &dwSize); status = RegQueryValueExA(hKey, "WorkstationName", NULL, &dwType, (BYTE*) workstation, &dwSize);
workstation[dwSize] = '\0'; workstation[dwSize] = '\0';
ntlm_SetContextWorkstation(context, workstation); if (ntlm_SetContextWorkstation(context, workstation) < 0)
return NULL;
free(workstation); free(workstation);
} }
@ -174,11 +225,10 @@ NTLM_CONTEXT* ntlm_ContextNew()
context->NegotiateFlags = 0; context->NegotiateFlags = 0;
context->LmCompatibilityLevel = 3; context->LmCompatibilityLevel = 3;
context->state = NTLM_STATE_INITIAL; context->state = NTLM_STATE_INITIAL;
memset(context->MachineID, 0xAA, sizeof(context->MachineID)); FillMemory(context->MachineID, sizeof(context->MachineID), 0xAA);
if (context->NTLMv2) if (context->NTLMv2)
context->UseMIC = TRUE; context->UseMIC = TRUE;
}
return context; return context;
} }
@ -197,10 +247,6 @@ void ntlm_ContextFree(NTLM_CONTEXT* context)
sspi_SecBufferFree(&context->LmChallengeResponse); sspi_SecBufferFree(&context->LmChallengeResponse);
free(context->ServicePrincipalName.Buffer); free(context->ServicePrincipalName.Buffer);
free(context->identity.User);
free(context->identity.Password);
free(context->identity.Domain);
free(context->Workstation.Buffer); free(context->Workstation.Buffer);
free(context); free(context);
} }
@ -209,33 +255,29 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{ {
CREDENTIALS* credentials; SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity; SEC_WINNT_AUTH_IDENTITY* identity;
if (fCredentialUse == SECPKG_CRED_OUTBOUND) if ((fCredentialUse != SECPKG_CRED_OUTBOUND) &&
(fCredentialUse != SECPKG_CRED_INBOUND) &&
(fCredentialUse != SECPKG_CRED_BOTH))
{ {
credentials = sspi_CredentialsNew(); return SEC_E_INVALID_PARAMETER;
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity != NULL)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
return SEC_E_OK;
} }
else if (fCredentialUse == SECPKG_CRED_INBOUND)
{
credentials = sspi_CredentialsNew(); credentials = sspi_CredentialsNew();
if (!credentials)
return SEC_E_INTERNAL_ERROR;
credentials->fCredentialUse = fCredentialUse;
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity) if (identity)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); sspi_CopyAuthIdentity(&(credentials->identity), identity);
else
ZeroMemory(&(credentials->identity), sizeof(SEC_WINNT_AUTH_IDENTITY));
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME); sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
@ -243,56 +285,48 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal
return SEC_E_OK; return SEC_E_OK;
} }
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{ {
CREDENTIALS* credentials; SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity; SEC_WINNT_AUTH_IDENTITY* identity;
if (fCredentialUse == SECPKG_CRED_OUTBOUND) if ((fCredentialUse != SECPKG_CRED_OUTBOUND) &&
(fCredentialUse != SECPKG_CRED_INBOUND) &&
(fCredentialUse != SECPKG_CRED_BOTH))
{ {
return SEC_E_INVALID_PARAMETER;
}
credentials = sspi_CredentialsNew(); credentials = sspi_CredentialsNew();
if (!credentials)
return SEC_E_INTERNAL_ERROR;
credentials->fCredentialUse = fCredentialUse;
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity != NULL) if (identity)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); sspi_CopyAuthIdentity(&(credentials->identity), identity);
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME); sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
return SEC_E_OK; return SEC_E_OK;
} }
else if (fCredentialUse == SECPKG_CRED_INBOUND)
{
credentials = sspi_CredentialsNew();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity != NULL)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
return SEC_E_OK;
}
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential) SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential)
{ {
CREDENTIALS* credentials; SSPI_CREDENTIALS* credentials;
if (!phCredential) if (!phCredential)
return SEC_E_INVALID_HANDLE; return SEC_E_INVALID_HANDLE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials) if (!credentials)
return SEC_E_INVALID_HANDLE; return SEC_E_INVALID_HANDLE;
@ -326,7 +360,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
{ {
NTLM_CONTEXT* context; NTLM_CONTEXT* context;
SECURITY_STATUS status; SECURITY_STATUS status;
CREDENTIALS* credentials; SSPI_CREDENTIALS* credentials;
PSecBuffer input_buffer; PSecBuffer input_buffer;
PSecBuffer output_buffer; PSecBuffer output_buffer;
@ -339,13 +373,13 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
if (!context) if (!context)
return SEC_E_INSUFFICIENT_MEMORY; return SEC_E_INSUFFICIENT_MEMORY;
context->server = 1; context->server = TRUE;
if (fContextReq & ASC_REQ_CONFIDENTIALITY) if (fContextReq & ASC_REQ_CONFIDENTIALITY)
context->confidentiality = 1; context->confidentiality = TRUE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
sspi_CopyAuthIdentity(&context->identity, &credentials->identity); context->credentials = credentials;
ntlm_SetContextTargetName(context, NULL); ntlm_SetContextTargetName(context, NULL);
@ -414,7 +448,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
if (pOutput) if (pOutput)
{ {
int i; ULONG i;
for (i = 0; i < pOutput->cBuffers; i++) for (i = 0; i < pOutput->cBuffers; i++)
{ {
@ -441,7 +475,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
{ {
NTLM_CONTEXT* context; NTLM_CONTEXT* context;
SECURITY_STATUS status; SECURITY_STATUS status;
CREDENTIALS* credentials; SSPI_CREDENTIALS* credentials;
PSecBuffer input_buffer = NULL; PSecBuffer input_buffer = NULL;
PSecBuffer output_buffer = NULL; PSecBuffer output_buffer = NULL;
PSecBuffer channel_bindings = NULL; PSecBuffer channel_bindings = NULL;
@ -456,15 +490,19 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
return SEC_E_INSUFFICIENT_MEMORY; return SEC_E_INSUFFICIENT_MEMORY;
if (fContextReq & ISC_REQ_CONFIDENTIALITY) if (fContextReq & ISC_REQ_CONFIDENTIALITY)
context->confidentiality = 1; context->confidentiality = TRUE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
context->credentials = credentials;
if (context->Workstation.Length < 1) if (context->Workstation.Length < 1)
ntlm_SetContextWorkstation(context, NULL); {
if (ntlm_SetContextWorkstation(context, NULL) < 0)
return SEC_E_INTERNAL_ERROR;
}
ntlm_SetContextServicePrincipalNameW(context, pszTargetName); if (ntlm_SetContextServicePrincipalNameW(context, pszTargetName) < 0)
sspi_CopyAuthIdentity(&context->identity, &credentials->identity); return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NTLM_PACKAGE_NAME); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NTLM_PACKAGE_NAME);
@ -554,20 +592,39 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti
SECURITY_STATUS status; SECURITY_STATUS status;
SEC_WCHAR* pszTargetNameW = NULL; SEC_WCHAR* pszTargetNameW = NULL;
if (pszTargetName != NULL) if (pszTargetName)
{ {
ConvertToUnicode(CP_UTF8, 0, pszTargetName, -1, &pszTargetNameW, 0); if (ConvertToUnicode(CP_UTF8, 0, pszTargetName, -1, &pszTargetNameW, 0) <= 0)
return SEC_E_INTERNAL_ERROR;
} }
status = ntlm_InitializeSecurityContextW(phCredential, phContext, pszTargetNameW, fContextReq, status = ntlm_InitializeSecurityContextW(phCredential, phContext, pszTargetNameW, fContextReq,
Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
if (pszTargetNameW != NULL) if (pszTargetNameW)
free(pszTargetNameW); free(pszTargetNameW);
return status; return status;
} }
SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
{
NTLM_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
return SEC_E_INVALID_HANDLE;
if (context->server)
{
status = ntlm_server_AuthenticateComplete(context);
}
return status;
}
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375354 */ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375354 */
SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext) SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
@ -588,12 +645,16 @@ SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{ {
NTLM_CONTEXT* context;
if (!phContext) if (!phContext)
return SEC_E_INVALID_HANDLE; return SEC_E_INVALID_HANDLE;
if (!pBuffer) if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY; return SEC_E_INSUFFICIENT_MEMORY;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (ulAttribute == SECPKG_ATTR_SIZES) if (ulAttribute == SECPKG_ATTR_SIZES)
{ {
SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer; SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer;
@ -605,6 +666,35 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, UL
return SEC_E_OK; return SEC_E_OK;
} }
else if (ulAttribute == SECPKG_ATTR_AUTH_IDENTITY)
{
int status;
char* UserA = NULL;
char* DomainA = NULL;
SSPI_CREDENTIALS* credentials;
SecPkgContext_AuthIdentity* AuthIdentity = (SecPkgContext_AuthIdentity*) pBuffer;
credentials = context->credentials;
ZeroMemory(AuthIdentity, sizeof(SecPkgContext_AuthIdentity));
UserA = AuthIdentity->User;
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) credentials->identity.User,
credentials->identity.UserLength,
&UserA, 256, NULL, NULL);
if (status <= 0)
return SEC_E_INTERNAL_ERROR;
DomainA = AuthIdentity->Domain;
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) credentials->identity.Domain,
credentials->identity.DomainLength,
&DomainA, 256, NULL, NULL);
if (status <= 0)
return SEC_E_INTERNAL_ERROR;
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION; return SEC_E_UNSUPPORTED_FUNCTION;
} }
@ -614,6 +704,38 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, UL
return ntlm_QueryContextAttributesW(phContext, ulAttribute, pBuffer); return ntlm_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
} }
SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
NTLM_CONTEXT* context;
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INVALID_PARAMETER;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_HASH)
{
SecPkgContext_AuthNtlmHash* AuthNtlmHash = (SecPkgContext_AuthNtlmHash*) pBuffer;
if (cbBuffer < sizeof(SecPkgContext_AuthNtlmHash))
return SEC_E_INVALID_PARAMETER;
CopyMemory(context->NtlmHash, AuthNtlmHash->NtlmHash, 16);
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
return ntlm_SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
}
SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext) SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext)
{ {
return SEC_E_OK; return SEC_E_OK;
@ -654,20 +776,24 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
/* Copy original data buffer */ /* Copy original data buffer */
length = data_buffer->cbBuffer; length = data_buffer->cbBuffer;
data = malloc(length); data = malloc(length);
if (!data)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(data, data_buffer->pvBuffer, length); CopyMemory(data, data_buffer->pvBuffer, length);
/* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */ /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */
HMAC_CTX_init(&hmac); HMAC_CTX_init(&hmac);
HMAC_Init_ex(&hmac, context->SendSigningKey, 16, EVP_md5(), NULL); HMAC_Init_ex(&hmac, context->SendSigningKey, 16, EVP_md5(), NULL);
HMAC_Update(&hmac, (void*) &(SeqNo), 4); HMAC_Update(&hmac, (void*) &(SeqNo), 4);
HMAC_Update(&hmac, data, length); HMAC_Update(&hmac, (void*) data, length);
HMAC_Final(&hmac, digest, NULL); HMAC_Final(&hmac, digest, NULL);
HMAC_CTX_cleanup(&hmac); HMAC_CTX_cleanup(&hmac);
/* Encrypt message using with RC4, result overwrites original buffer */ /* Encrypt message using with RC4, result overwrites original buffer */
if (context->confidentiality) if (context->confidentiality)
RC4(&context->SendRc4Seal, length, data, data_buffer->pvBuffer); RC4(&context->SendRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer);
else else
CopyMemory(data_buffer->pvBuffer, data, length); CopyMemory(data_buffer->pvBuffer, data, length);
@ -719,7 +845,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
PSecBuffer signature_buffer = NULL; PSecBuffer signature_buffer = NULL;
SeqNo = (UINT32) MessageSeqNo; SeqNo = (UINT32) MessageSeqNo;
context = sspi_SecureHandleGetLowerPointer(phContext); context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
for (index = 0; index < (int) pMessage->cBuffers; index++) for (index = 0; index < (int) pMessage->cBuffers; index++)
{ {
@ -738,12 +864,16 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
/* Copy original data buffer */ /* Copy original data buffer */
length = data_buffer->cbBuffer; length = data_buffer->cbBuffer;
data = malloc(length); data = malloc(length);
if (!data)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(data, data_buffer->pvBuffer, length); CopyMemory(data, data_buffer->pvBuffer, length);
/* Decrypt message using with RC4, result overwrites original buffer */ /* Decrypt message using with RC4, result overwrites original buffer */
if (context->confidentiality) if (context->confidentiality)
RC4(&context->RecvRc4Seal, length, data, data_buffer->pvBuffer); RC4(&context->RecvRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer);
else else
CopyMemory(data_buffer->pvBuffer, data, length); CopyMemory(data_buffer->pvBuffer, data, length);
@ -751,7 +881,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
HMAC_CTX_init(&hmac); HMAC_CTX_init(&hmac);
HMAC_Init_ex(&hmac, context->RecvSigningKey, 16, EVP_md5(), NULL); HMAC_Init_ex(&hmac, context->RecvSigningKey, 16, EVP_md5(), NULL);
HMAC_Update(&hmac, (void*) &(SeqNo), 4); HMAC_Update(&hmac, (void*) &(SeqNo), 4);
HMAC_Update(&hmac, data_buffer->pvBuffer, data_buffer->cbBuffer); HMAC_Update(&hmac, (void*) data_buffer->pvBuffer, data_buffer->cbBuffer);
HMAC_Final(&hmac, digest, NULL); HMAC_Final(&hmac, digest, NULL);
HMAC_CTX_cleanup(&hmac); HMAC_CTX_cleanup(&hmac);
@ -784,7 +914,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
fprintf(stderr, "Expected Signature:\n"); fprintf(stderr, "Expected Signature:\n");
winpr_HexDump(expected_signature, 16); winpr_HexDump(expected_signature, 16);
fprintf(stderr, "Actual Signature:\n"); fprintf(stderr, "Actual Signature:\n");
winpr_HexDump(signature_buffer->pvBuffer, 16); winpr_HexDump((BYTE*) signature_buffer->pvBuffer, 16);
return SEC_E_MESSAGE_ALTERED; return SEC_E_MESSAGE_ALTERED;
} }
@ -794,12 +924,12 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{ {
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
{ {
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
const SecurityFunctionTableA NTLM_SecurityFunctionTableA = const SecurityFunctionTableA NTLM_SecurityFunctionTableA =
@ -812,7 +942,7 @@ const SecurityFunctionTableA NTLM_SecurityFunctionTableA =
NULL, /* Reserved2 */ NULL, /* Reserved2 */
ntlm_InitializeSecurityContextA, /* InitializeSecurityContext */ ntlm_InitializeSecurityContextA, /* InitializeSecurityContext */
ntlm_AcceptSecurityContext, /* AcceptSecurityContext */ ntlm_AcceptSecurityContext, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */ ntlm_CompleteAuthToken, /* CompleteAuthToken */
ntlm_DeleteSecurityContext, /* DeleteSecurityContext */ ntlm_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */ NULL, /* ApplyControlToken */
ntlm_QueryContextAttributesA, /* QueryContextAttributes */ ntlm_QueryContextAttributesA, /* QueryContextAttributes */
@ -831,7 +961,7 @@ const SecurityFunctionTableA NTLM_SecurityFunctionTableA =
NULL, /* QuerySecurityContextToken */ NULL, /* QuerySecurityContextToken */
ntlm_EncryptMessage, /* EncryptMessage */ ntlm_EncryptMessage, /* EncryptMessage */
ntlm_DecryptMessage, /* DecryptMessage */ ntlm_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */ ntlm_SetContextAttributesA, /* SetContextAttributes */
}; };
const SecurityFunctionTableW NTLM_SecurityFunctionTableW = const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
@ -844,7 +974,7 @@ const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
NULL, /* Reserved2 */ NULL, /* Reserved2 */
ntlm_InitializeSecurityContextW, /* InitializeSecurityContext */ ntlm_InitializeSecurityContextW, /* InitializeSecurityContext */
ntlm_AcceptSecurityContext, /* AcceptSecurityContext */ ntlm_AcceptSecurityContext, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */ ntlm_CompleteAuthToken, /* CompleteAuthToken */
ntlm_DeleteSecurityContext, /* DeleteSecurityContext */ ntlm_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */ NULL, /* ApplyControlToken */
ntlm_QueryContextAttributesW, /* QueryContextAttributes */ ntlm_QueryContextAttributesW, /* QueryContextAttributes */
@ -863,7 +993,7 @@ const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
NULL, /* QuerySecurityContextToken */ NULL, /* QuerySecurityContextToken */
ntlm_EncryptMessage, /* EncryptMessage */ ntlm_EncryptMessage, /* EncryptMessage */
ntlm_DecryptMessage, /* DecryptMessage */ ntlm_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */ ntlm_SetContextAttributesA, /* SetContextAttributes */
}; };
const SecPkgInfoA NTLM_SecPkgInfoA = const SecPkgInfoA NTLM_SecPkgInfoA =

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* NTLM Security Package * NTLM Security Package
* *
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,6 +23,8 @@
#include <winpr/sspi.h> #include <winpr/sspi.h>
#include <winpr/windows.h> #include <winpr/windows.h>
#include <winpr/nt.h>
#include <time.h> #include <time.h>
#include <openssl/des.h> #include <openssl/des.h>
#include <openssl/md4.h> #include <openssl/md4.h>
@ -78,6 +80,7 @@ enum _NTLM_STATE
NTLM_STATE_NEGOTIATE, NTLM_STATE_NEGOTIATE,
NTLM_STATE_CHALLENGE, NTLM_STATE_CHALLENGE,
NTLM_STATE_AUTHENTICATE, NTLM_STATE_AUTHENTICATE,
NTLM_STATE_COMPLETION,
NTLM_STATE_FINAL NTLM_STATE_FINAL
}; };
typedef enum _NTLM_STATE NTLM_STATE; typedef enum _NTLM_STATE NTLM_STATE;
@ -226,6 +229,8 @@ struct _NTLM_CONTEXT
NTLM_STATE state; NTLM_STATE state;
int SendSeqNum; int SendSeqNum;
int RecvSeqNum; int RecvSeqNum;
BYTE NtlmHash[16];
BYTE NtlmV2Hash[16];
BYTE MachineID[32]; BYTE MachineID[32];
BOOL SendVersionInfo; BOOL SendVersionInfo;
BOOL confidentiality; BOOL confidentiality;
@ -241,7 +246,7 @@ struct _NTLM_CONTEXT
BOOL SendWorkstationName; BOOL SendWorkstationName;
UNICODE_STRING Workstation; UNICODE_STRING Workstation;
UNICODE_STRING ServicePrincipalName; UNICODE_STRING ServicePrincipalName;
SEC_WINNT_AUTH_IDENTITY identity; SSPI_CREDENTIALS* credentials;
BYTE* ChannelBindingToken; BYTE* ChannelBindingToken;
BYTE ChannelBindingsHash[16]; BYTE ChannelBindingsHash[16];
SecPkgContext_Bindings Bindings; SecPkgContext_Bindings Bindings;
@ -258,6 +263,7 @@ struct _NTLM_CONTEXT
SecBuffer TargetName; SecBuffer TargetName;
SecBuffer NtChallengeResponse; SecBuffer NtChallengeResponse;
SecBuffer LmChallengeResponse; SecBuffer LmChallengeResponse;
NTLMv2_RESPONSE NTLMv2Response;
BYTE Timestamp[8]; BYTE Timestamp[8];
BYTE ChallengeTimestamp[8]; BYTE ChallengeTimestamp[8];
BYTE ServerChallenge[8]; BYTE ServerChallenge[8];
@ -272,6 +278,7 @@ struct _NTLM_CONTEXT
BYTE ServerSigningKey[16]; BYTE ServerSigningKey[16];
BYTE ServerSealingKey[16]; BYTE ServerSealingKey[16];
BYTE MessageIntegrityCheck[16]; BYTE MessageIntegrityCheck[16];
UINT32 MessageIntegrityCheckOffset;
}; };
typedef struct _NTLM_CONTEXT NTLM_CONTEXT; typedef struct _NTLM_CONTEXT NTLM_CONTEXT;

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* NTLM Security Package (AV_PAIRs) * NTLM Security Package (AV_PAIRs)
* *
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -173,34 +173,45 @@ NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, NTLM_AV_PAIR* pAv
return pAvPairCopy; return pAvPairCopy;
} }
void ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type) int ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
{ {
char* name; char* name;
int length; int status;
DWORD nSize = 0; DWORD nSize = 0;
GetComputerNameExA(type, NULL, &nSize); GetComputerNameExA(type, NULL, &nSize);
name = malloc(nSize);
GetComputerNameExA(type, name, &nSize); name = (char*) malloc(nSize);
if (!name)
return -1;
if (!GetComputerNameExA(type, name, &nSize))
return -1;
if (type == ComputerNameNetBIOS) if (type == ComputerNameNetBIOS)
CharUpperA(name); CharUpperA(name);
length = ConvertToUnicode(CP_UTF8, 0, name, -1, &pName->Buffer, 0); status = ConvertToUnicode(CP_UTF8, 0, name, -1, &pName->Buffer, 0);
pName->Length = (length - 1) * 2; if (status <= 0)
return status;
pName->Length = (USHORT) ((status - 1) * 2);
pName->MaximumLength = pName->Length; pName->MaximumLength = pName->Length;
free(name); free(name);
return 1;
} }
void ntlm_free_unicode_string(PUNICODE_STRING string) void ntlm_free_unicode_string(PUNICODE_STRING string)
{ {
if (string != NULL) if (string)
{ {
if (string->Length > 0) if (string->Length > 0)
{ {
if (string->Buffer != NULL) if (string->Buffer)
free(string->Buffer); free(string->Buffer);
string->Buffer = NULL; string->Buffer = NULL;
@ -297,7 +308,7 @@ void ntlm_compute_single_host_data(NTLM_CONTEXT* context)
FillMemory(context->SingleHostData.MachineID, 32, 0xAA); FillMemory(context->SingleHostData.MachineID, 32, 0xAA);
} }
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context) int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
{ {
int length; int length;
ULONG AvPairsCount; ULONG AvPairsCount;
@ -310,23 +321,33 @@ void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
UNICODE_STRING DnsComputerName; UNICODE_STRING DnsComputerName;
NbDomainName.Buffer = NULL; NbDomainName.Buffer = NULL;
ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS);
if (ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS) < 0)
return -1;
NbComputerName.Buffer = NULL; NbComputerName.Buffer = NULL;
ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS);
if (ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS) < 0)
return -1;
DnsDomainName.Buffer = NULL; DnsDomainName.Buffer = NULL;
ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain);
if (ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain) < 0)
return -1;
DnsComputerName.Buffer = NULL; DnsComputerName.Buffer = NULL;
ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname);
if (ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname) < 0)
return -1;
AvPairsCount = 5; AvPairsCount = 5;
AvPairsLength = NbDomainName.Length + NbComputerName.Length + AvPairsLength = NbDomainName.Length + NbComputerName.Length +
DnsDomainName.Length + DnsComputerName.Length + 8; DnsDomainName.Length + DnsComputerName.Length + 8;
length = ntlm_av_pair_list_size(AvPairsCount, AvPairsLength); length = ntlm_av_pair_list_size(AvPairsCount, AvPairsLength);
sspi_SecBufferAlloc(&context->ChallengeTargetInfo, length);
if (!sspi_SecBufferAlloc(&context->ChallengeTargetInfo, length))
return -1;
pAvPairList = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer; pAvPairList = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
AvPairListSize = (ULONG) context->ChallengeTargetInfo.cbBuffer; AvPairListSize = (ULONG) context->ChallengeTargetInfo.cbBuffer;
@ -342,9 +363,11 @@ void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
ntlm_free_unicode_string(&NbComputerName); ntlm_free_unicode_string(&NbComputerName);
ntlm_free_unicode_string(&DnsDomainName); ntlm_free_unicode_string(&DnsDomainName);
ntlm_free_unicode_string(&DnsComputerName); ntlm_free_unicode_string(&DnsComputerName);
return 1;
} }
void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context) int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
{ {
ULONG size; ULONG size;
ULONG AvPairsCount; ULONG AvPairsCount;
@ -369,31 +392,31 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
AvDnsTreeName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsTreeName); AvDnsTreeName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsTreeName);
AvTimestamp = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvTimestamp); AvTimestamp = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvTimestamp);
if (AvNbDomainName != NULL) if (AvNbDomainName)
{ {
AvPairsCount++; /* MsvAvNbDomainName */ AvPairsCount++; /* MsvAvNbDomainName */
AvPairsValueLength += AvNbDomainName->AvLen; AvPairsValueLength += AvNbDomainName->AvLen;
} }
if (AvNbComputerName != NULL) if (AvNbComputerName)
{ {
AvPairsCount++; /* MsvAvNbComputerName */ AvPairsCount++; /* MsvAvNbComputerName */
AvPairsValueLength += AvNbComputerName->AvLen; AvPairsValueLength += AvNbComputerName->AvLen;
} }
if (AvDnsDomainName != NULL) if (AvDnsDomainName)
{ {
AvPairsCount++; /* MsvAvDnsDomainName */ AvPairsCount++; /* MsvAvDnsDomainName */
AvPairsValueLength += AvDnsDomainName->AvLen; AvPairsValueLength += AvDnsDomainName->AvLen;
} }
if (AvDnsComputerName != NULL) if (AvDnsComputerName)
{ {
AvPairsCount++; /* MsvAvDnsComputerName */ AvPairsCount++; /* MsvAvDnsComputerName */
AvPairsValueLength += AvDnsComputerName->AvLen; AvPairsValueLength += AvDnsComputerName->AvLen;
} }
if (AvDnsTreeName != NULL) if (AvDnsTreeName)
{ {
AvPairsCount++; /* MsvAvDnsTreeName */ AvPairsCount++; /* MsvAvDnsTreeName */
AvPairsValueLength += AvDnsTreeName->AvLen; AvPairsValueLength += AvDnsTreeName->AvLen;
@ -448,22 +471,22 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
ntlm_av_pair_list_init(AuthenticateTargetInfo); ntlm_av_pair_list_init(AuthenticateTargetInfo);
if (AvNbDomainName != NULL) if (AvNbDomainName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbDomainName); ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbDomainName);
if (AvNbComputerName != NULL) if (AvNbComputerName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbComputerName); ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbComputerName);
if (AvDnsDomainName != NULL) if (AvDnsDomainName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsDomainName); ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsDomainName);
if (AvDnsComputerName != NULL) if (AvDnsComputerName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsComputerName); ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsComputerName);
if (AvDnsTreeName != NULL) if (AvDnsTreeName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsTreeName); ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsTreeName);
if (AvTimestamp != NULL) if (AvTimestamp)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvTimestamp); ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvTimestamp);
if (context->UseMIC) if (context->UseMIC)
@ -497,4 +520,6 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvEOL); AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvEOL);
ZeroMemory((void*) AvEOL, 4); ZeroMemory((void*) AvEOL, 4);
} }
return 1;
} }

View File

@ -35,7 +35,7 @@ NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId);
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId, PBYTE Value, UINT16 AvLen); NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId, PBYTE Value, UINT16 AvLen);
NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, NTLM_AV_PAIR* pAvPair); NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, NTLM_AV_PAIR* pAvPair);
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context); int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context);
void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context); int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context);
#endif /* WINPR_SSPI_NTLM_AV_PAIRS_H */ #endif /* WINPR_SSPI_NTLM_AV_PAIRS_H */

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* NTLM Security Package (Compute) * NTLM Security Package (Compute)
* *
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -32,12 +32,15 @@
#include "ntlm_compute.h" #include "ntlm_compute.h"
const char lm_magic[] = "KGS!@#$%"; const char LM_MAGIC[] = "KGS!@#$%";
static const char client_sign_magic[] = "session key to client-to-server signing key magic constant"; static const char NTLM_CLIENT_SIGN_MAGIC[] = "session key to client-to-server signing key magic constant";
static const char server_sign_magic[] = "session key to server-to-client signing key magic constant"; static const char NTLM_SERVER_SIGN_MAGIC[] = "session key to server-to-client signing key magic constant";
static const char client_seal_magic[] = "session key to client-to-server sealing key magic constant"; static const char NTLM_CLIENT_SEAL_MAGIC[] = "session key to client-to-server sealing key magic constant";
static const char server_seal_magic[] = "session key to server-to-client sealing key magic constant"; static const char NTLM_SERVER_SEAL_MAGIC[] = "session key to server-to-client sealing key magic constant";
static const BYTE NTLM_NULL_HASH[16] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/** /**
* Populate VERSION structure.\n * Populate VERSION structure.\n
@ -66,13 +69,18 @@ void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo)
* @param s * @param s
*/ */
void ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo) int ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo)
{ {
if (Stream_GetRemainingLength(s) < 8)
return -1;
Stream_Read_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */ Stream_Read_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */
Stream_Read_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */ Stream_Read_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */
Stream_Read_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */ Stream_Read_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */
Stream_Read(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */ Stream_Read(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */
Stream_Read_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */ Stream_Read_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */
return 1;
} }
/** /**
@ -107,7 +115,7 @@ void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo)
fprintf(stderr, "\tNTLMRevisionCurrent: 0x%02X\n", versionInfo->NTLMRevisionCurrent); fprintf(stderr, "\tNTLMRevisionCurrent: 0x%02X\n", versionInfo->NTLMRevisionCurrent);
} }
void ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge) int ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
{ {
size_t size; size_t size;
@ -121,10 +129,16 @@ void ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* cha
size = Stream_Length(s) - Stream_GetPosition(s); size = Stream_Length(s) - Stream_GetPosition(s);
challenge->AvPairs = (NTLM_AV_PAIR*) malloc(size); challenge->AvPairs = (NTLM_AV_PAIR*) malloc(size);
if (!challenge->AvPairs)
return -1;
Stream_Read(s, challenge->AvPairs, size); Stream_Read(s, challenge->AvPairs, size);
return 1;
} }
void ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge) int ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
{ {
ULONG length; ULONG length;
@ -138,57 +152,22 @@ void ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* ch
length = ntlm_av_pair_list_length(challenge->AvPairs); length = ntlm_av_pair_list_length(challenge->AvPairs);
Stream_Write(s, challenge->AvPairs, length); Stream_Write(s, challenge->AvPairs, length);
return 1;
} }
void ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response) int ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
{ {
Stream_Read(s, response->Response, 16); Stream_Read(s, response->Response, 16);
ntlm_read_ntlm_v2_client_challenge(s, &(response->Challenge)); return ntlm_read_ntlm_v2_client_challenge(s, &(response->Challenge));
} }
void ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response) int ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
{ {
Stream_Write(s, response->Response, 16); Stream_Write(s, response->Response, 16);
ntlm_write_ntlm_v2_client_challenge(s, &(response->Challenge)); return ntlm_write_ntlm_v2_client_challenge(s, &(response->Challenge));
} }
#if 0
/**
* Output Restriction_Encoding.\n
* Restriction_Encoding @msdn{cc236647}
* @param NTLM context
*/
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context)
{
wStream* s;
AV_PAIR* restrictions = &context->av_pairs->Restrictions;
BYTE machineID[32] =
"\x3A\x15\x8E\xA6\x75\x82\xD8\xF7\x3E\x06\xFA\x7A\xB4\xDF\xFD\x43"
"\x84\x6C\x02\x3A\xFD\x5A\x94\xFE\xCF\x97\x0F\x3D\x19\x2C\x38\x20";
restrictions->value = malloc(48);
restrictions->length = 48;
s = PStreamAllocAttach(restrictions->value, restrictions->length);
Stream_Write_UINT32(s, 48); /* Size */
Stream_Zero(s, 4); /* Z4 (set to zero) */
/* IntegrityLevel (bit 31 set to 1) */
Stream_Write_UINT8(s, 1);
Stream_Zero(s, 3);
Stream_Write_UINT32(s, 0x00002000); /* SubjectIntegrityLevel */
Stream_Write(s, machineID, 32); /* MachineID */
PStreamFreeDetach(s);
}
#endif
/** /**
* Get current time, in tenths of microseconds since midnight of January 1, 1601. * Get current time, in tenths of microseconds since midnight of January 1, 1601.
* @param[out] timestamp 64-bit little-endian timestamp * @param[out] timestamp 64-bit little-endian timestamp
@ -224,20 +203,22 @@ void ntlm_generate_timestamp(NTLM_CONTEXT* context)
ntlm_current_time(context->Timestamp); ntlm_current_time(context->Timestamp);
} }
void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
{ {
WINPR_SAM* sam; WINPR_SAM* sam;
WINPR_SAM_ENTRY* entry; WINPR_SAM_ENTRY* entry;
SSPI_CREDENTIALS* credentials = context->credentials;
sam = SamOpen(1); sam = SamOpen(TRUE);
if (sam == NULL)
return; if (!sam)
return -1;
entry = SamLookupUserW(sam, entry = SamLookupUserW(sam,
(LPWSTR) context->identity.User, context->identity.UserLength * 2, (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2); (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2);
if (entry != NULL) if (entry)
{ {
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
fprintf(stderr, "NTLM Hash:\n"); fprintf(stderr, "NTLM Hash:\n");
@ -245,20 +226,20 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
#endif #endif
NTOWFv2FromHashW(entry->NtHash, NTOWFv2FromHashW(entry->NtHash,
(LPWSTR) context->identity.User, context->identity.UserLength * 2, (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2, (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash); (BYTE*) hash);
SamFreeEntry(sam, entry); SamFreeEntry(sam, entry);
SamClose(sam); SamClose(sam);
return; return 1;
} }
entry = SamLookupUserW(sam, entry = SamLookupUserW(sam,
(LPWSTR) context->identity.User, context->identity.UserLength * 2, NULL, 0); (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2, NULL, 0);
if (entry != NULL) if (entry)
{ {
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
fprintf(stderr, "NTLM Hash:\n"); fprintf(stderr, "NTLM Hash:\n");
@ -266,32 +247,44 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
#endif #endif
NTOWFv2FromHashW(entry->NtHash, NTOWFv2FromHashW(entry->NtHash,
(LPWSTR) context->identity.User, context->identity.UserLength * 2, (LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2, (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash); (BYTE*) hash);
SamFreeEntry(sam, entry); SamFreeEntry(sam, entry);
SamClose(sam); SamClose(sam);
return; return 1;
} }
else else
{ {
fprintf(stderr, "Error: Could not find user in SAM database\n"); fprintf(stderr, "Error: Could not find user in SAM database\n");
} return 0;
SamClose(sam);
} }
void ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash) SamClose(sam);
return 1;
}
int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
{ {
int status;
int i, hn, ln; int i, hn, ln;
char* PasswordHash = NULL; char* PasswordHash = NULL;
UINT32 PasswordHashLength = 0; UINT32 PasswordHashLength = 0;
SSPI_CREDENTIALS* credentials = context->credentials;
/* Password contains a password hash of length (PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR) */ /* Password contains a password hash of length (PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR) */
PasswordHashLength = context->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR; PasswordHashLength = credentials->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
ConvertFromUnicode(CP_UTF8, 0, context->identity.Password, PasswordHashLength, &PasswordHash, 0, NULL, NULL);
status = ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR) credentials->identity.Password,
PasswordHashLength, &PasswordHash, 0, NULL, NULL);
if (status <= 0)
return -1;
CharUpperBuffA(PasswordHash, PasswordHashLength); CharUpperBuffA(PasswordHash, PasswordHashLength);
for (i = 0; i < 32; i += 2) for (i = 0; i < 32; i += 2)
@ -302,62 +295,83 @@ void ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
} }
free(PasswordHash); free(PasswordHash);
return 1;
} }
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
{ {
if (context->identity.PasswordLength > 256) SSPI_CREDENTIALS* credentials = context->credentials;
if (memcmp(context->NtlmHash, NTLM_NULL_HASH, 16) != 0)
{ {
BYTE PasswordHash[16]; NTOWFv2FromHashW(context->NtlmHash,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
/* Special case for WinPR: password hash */ (LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
ntlm_convert_password_hash(context, PasswordHash);
NTOWFv2FromHashW(PasswordHash,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2,
(BYTE*) hash); (BYTE*) hash);
} }
else if (context->identity.PasswordLength > 0) else if (credentials->identity.PasswordLength > 256)
{ {
NTOWFv2W((LPWSTR) context->identity.Password, context->identity.PasswordLength * 2, /* Special case for WinPR: password hash */
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2, (BYTE*) hash); if (ntlm_convert_password_hash(context, context->NtlmHash) < 0)
return -1;
NTOWFv2FromHashW(context->NtlmHash,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash);
}
else if (credentials->identity.PasswordLength > 0)
{
NTOWFv2W((LPWSTR) credentials->identity.Password, credentials->identity.PasswordLength * 2,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2, (BYTE*) hash);
} }
else else
{ {
ntlm_fetch_ntlm_v2_hash(context, hash); ntlm_fetch_ntlm_v2_hash(context, hash);
} }
return 1;
} }
void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
{ {
char* response; BYTE* response;
char value[16]; BYTE value[16];
char ntlm_v2_hash[16];
if (context->LmCompatibilityLevel < 2) if (context->LmCompatibilityLevel < 2)
{ {
sspi_SecBufferAlloc(&context->LmChallengeResponse, 24); if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24))
return -1;
ZeroMemory(context->LmChallengeResponse.pvBuffer, 24); ZeroMemory(context->LmChallengeResponse.pvBuffer, 24);
return;
return 1;
} }
/* Compute the NTLMv2 hash */ /* Compute the NTLMv2 hash */
ntlm_compute_ntlm_v2_hash(context, ntlm_v2_hash);
if (ntlm_compute_ntlm_v2_hash(context, context->NtlmV2Hash) < 0)
return -1;
/* Concatenate the server and client challenges */ /* Concatenate the server and client challenges */
CopyMemory(value, context->ServerChallenge, 8); CopyMemory(value, context->ServerChallenge, 8);
CopyMemory(&value[8], context->ClientChallenge, 8); CopyMemory(&value[8], context->ClientChallenge, 8);
sspi_SecBufferAlloc(&context->LmChallengeResponse, 24); if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24))
response = (char*) context->LmChallengeResponse.pvBuffer; return -1;
response = (BYTE*) context->LmChallengeResponse.pvBuffer;
/* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */ /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */
HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) value, 16, (void*) response, NULL); HMAC(EVP_md5(), (void*) context->NtlmV2Hash, 16, (BYTE*) value, 16, (BYTE*) response, NULL);
/* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */ /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */
CopyMemory(&response[16], context->ClientChallenge, 8); CopyMemory(&response[16], context->ClientChallenge, 8);
return 1;
} }
/** /**
@ -367,10 +381,9 @@ void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
* @param NTLM context * @param NTLM context
*/ */
void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
{ {
BYTE* blob; BYTE* blob;
BYTE ntlm_v2_hash[16];
BYTE nt_proof_str[16]; BYTE nt_proof_str[16];
SecBuffer ntlm_v2_temp; SecBuffer ntlm_v2_temp;
SecBuffer ntlm_v2_temp_chal; SecBuffer ntlm_v2_temp_chal;
@ -378,13 +391,16 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
TargetInfo = &context->ChallengeTargetInfo; TargetInfo = &context->ChallengeTargetInfo;
sspi_SecBufferAlloc(&ntlm_v2_temp, TargetInfo->cbBuffer + 28); if (!sspi_SecBufferAlloc(&ntlm_v2_temp, TargetInfo->cbBuffer + 28))
return -1;
ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
blob = (BYTE*) ntlm_v2_temp.pvBuffer; blob = (BYTE*) ntlm_v2_temp.pvBuffer;
/* Compute the NTLMv2 hash */ /* Compute the NTLMv2 hash */
ntlm_compute_ntlm_v2_hash(context, (char*) ntlm_v2_hash);
if (ntlm_compute_ntlm_v2_hash(context, (BYTE*) context->NtlmV2Hash) < 0)
return -1;
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
fprintf(stderr, "Password (length = %d)\n", context->identity.PasswordLength * 2); fprintf(stderr, "Password (length = %d)\n", context->identity.PasswordLength * 2);
@ -404,7 +420,7 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "NTOWFv2, NTLMv2 Hash\n"); fprintf(stderr, "NTOWFv2, NTLMv2 Hash\n");
winpr_HexDump(ntlm_v2_hash, 16); winpr_HexDump(context->NtlmV2Hash, 16);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
#endif #endif
@ -425,25 +441,33 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
#endif #endif
/* Concatenate server challenge with temp */ /* Concatenate server challenge with temp */
sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8);
if (!sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8))
return -1;
blob = (BYTE*) ntlm_v2_temp_chal.pvBuffer; blob = (BYTE*) ntlm_v2_temp_chal.pvBuffer;
CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(blob, context->ServerChallenge, 8);
CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, ntlm_v2_temp_chal.pvBuffer, HMAC(EVP_md5(), (BYTE*) context->NtlmV2Hash, 16, (BYTE*) ntlm_v2_temp_chal.pvBuffer,
ntlm_v2_temp_chal.cbBuffer, (void*) nt_proof_str, NULL); ntlm_v2_temp_chal.cbBuffer, (BYTE*) nt_proof_str, NULL);
/* NtChallengeResponse, Concatenate NTProofStr with temp */ /* NtChallengeResponse, Concatenate NTProofStr with temp */
sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16);
if (!sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16))
return -1;
blob = (BYTE*) context->NtChallengeResponse.pvBuffer; blob = (BYTE*) context->NtChallengeResponse.pvBuffer;
CopyMemory(blob, nt_proof_str, 16); CopyMemory(blob, nt_proof_str, 16);
CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
/* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */
HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) nt_proof_str, 16, (void*) context->SessionBaseKey, NULL); HMAC(EVP_md5(), (BYTE*) context->NtlmV2Hash, 16, (BYTE*) nt_proof_str, 16, (BYTE*) context->SessionBaseKey, NULL);
sspi_SecBufferFree(&ntlm_v2_temp); sspi_SecBufferFree(&ntlm_v2_temp);
sspi_SecBufferFree(&ntlm_v2_temp_chal); sspi_SecBufferFree(&ntlm_v2_temp_chal);
return 1;
} }
/** /**
@ -548,7 +572,7 @@ void ntlm_decrypt_random_session_key(NTLM_CONTEXT* context)
* @param signing_key Destination signing key * @param signing_key Destination signing key
*/ */
void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic, BYTE* signing_key) int ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic, BYTE* signing_key)
{ {
int length; int length;
BYTE* value; BYTE* value;
@ -557,6 +581,9 @@ void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic
length = 16 + sign_magic->cbBuffer; length = 16 + sign_magic->cbBuffer;
value = (BYTE*) malloc(length); value = (BYTE*) malloc(length);
if (!value)
return -1;
/* Concatenate ExportedSessionKey with sign magic */ /* Concatenate ExportedSessionKey with sign magic */
CopyMemory(value, exported_session_key, 16); CopyMemory(value, exported_session_key, 16);
CopyMemory(&value[16], sign_magic->pvBuffer, sign_magic->cbBuffer); CopyMemory(&value[16], sign_magic->pvBuffer, sign_magic->cbBuffer);
@ -566,6 +593,8 @@ void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic
MD5_Final(signing_key, &md5); MD5_Final(signing_key, &md5);
free(value); free(value);
return 1;
} }
/** /**
@ -576,10 +605,12 @@ void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic
void ntlm_generate_client_signing_key(NTLM_CONTEXT* context) void ntlm_generate_client_signing_key(NTLM_CONTEXT* context)
{ {
SecBuffer sign_magic; SecBuffer signMagic;
sign_magic.pvBuffer = (void*) client_sign_magic;
sign_magic.cbBuffer = sizeof(client_sign_magic); signMagic.pvBuffer = (void*) NTLM_CLIENT_SIGN_MAGIC;
ntlm_generate_signing_key(context->ExportedSessionKey, &sign_magic, context->ClientSigningKey); signMagic.cbBuffer = sizeof(NTLM_CLIENT_SIGN_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &signMagic, context->ClientSigningKey);
} }
/** /**
@ -590,10 +621,12 @@ void ntlm_generate_client_signing_key(NTLM_CONTEXT* context)
void ntlm_generate_server_signing_key(NTLM_CONTEXT* context) void ntlm_generate_server_signing_key(NTLM_CONTEXT* context)
{ {
SecBuffer sign_magic; SecBuffer signMagic;
sign_magic.pvBuffer = (void*) server_sign_magic;
sign_magic.cbBuffer = sizeof(server_sign_magic); signMagic.pvBuffer = (void*) NTLM_SERVER_SIGN_MAGIC;
ntlm_generate_signing_key(context->ExportedSessionKey, &sign_magic, context->ServerSigningKey); signMagic.cbBuffer = sizeof(NTLM_SERVER_SIGN_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &signMagic, context->ServerSigningKey);
} }
/** /**
@ -604,13 +637,15 @@ void ntlm_generate_server_signing_key(NTLM_CONTEXT* context)
* @param sealing_key Destination sealing key * @param sealing_key Destination sealing key
*/ */
void ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, BYTE* sealing_key) int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, BYTE* sealing_key)
{ {
BYTE* p; BYTE* p;
MD5_CTX md5; MD5_CTX md5;
SecBuffer buffer; SecBuffer buffer;
sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer); if (!sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer))
return -1;
p = (BYTE*) buffer.pvBuffer; p = (BYTE*) buffer.pvBuffer;
/* Concatenate ExportedSessionKey with seal magic */ /* Concatenate ExportedSessionKey with seal magic */
@ -622,6 +657,8 @@ void ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic
MD5_Final(sealing_key, &md5); MD5_Final(sealing_key, &md5);
sspi_SecBufferFree(&buffer); sspi_SecBufferFree(&buffer);
return 1;
} }
/** /**
@ -632,10 +669,12 @@ void ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic
void ntlm_generate_client_sealing_key(NTLM_CONTEXT* context) void ntlm_generate_client_sealing_key(NTLM_CONTEXT* context)
{ {
SecBuffer seal_magic; SecBuffer sealMagic;
seal_magic.pvBuffer = (void*) client_seal_magic;
seal_magic.cbBuffer = sizeof(client_seal_magic); sealMagic.pvBuffer = (void*) NTLM_CLIENT_SEAL_MAGIC;
ntlm_generate_signing_key(context->ExportedSessionKey, &seal_magic, context->ClientSealingKey); sealMagic.cbBuffer = sizeof(NTLM_CLIENT_SEAL_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &sealMagic, context->ClientSealingKey);
} }
/** /**
@ -646,10 +685,12 @@ void ntlm_generate_client_sealing_key(NTLM_CONTEXT* context)
void ntlm_generate_server_sealing_key(NTLM_CONTEXT* context) void ntlm_generate_server_sealing_key(NTLM_CONTEXT* context)
{ {
SecBuffer seal_magic; SecBuffer sealMagic;
seal_magic.pvBuffer = (void*) server_seal_magic;
seal_magic.cbBuffer = sizeof(server_seal_magic); sealMagic.pvBuffer = (void*) NTLM_SERVER_SEAL_MAGIC;
ntlm_generate_signing_key(context->ExportedSessionKey, &seal_magic, context->ServerSealingKey); sealMagic.cbBuffer = sizeof(NTLM_SERVER_SEAL_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &sealMagic, context->ServerSealingKey);
} }
/** /**
@ -690,9 +731,9 @@ void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context)
HMAC_CTX_init(&hmac_ctx); HMAC_CTX_init(&hmac_ctx);
HMAC_Init_ex(&hmac_ctx, context->ExportedSessionKey, 16, EVP_md5(), NULL); HMAC_Init_ex(&hmac_ctx, context->ExportedSessionKey, 16, EVP_md5(), NULL);
HMAC_Update(&hmac_ctx, context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer); HMAC_Update(&hmac_ctx, (BYTE*) context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer);
HMAC_Update(&hmac_ctx, context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer); HMAC_Update(&hmac_ctx, (BYTE*) context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
HMAC_Update(&hmac_ctx, context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer); HMAC_Update(&hmac_ctx, (BYTE*) context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer);
HMAC_Final(&hmac_ctx, context->MessageIntegrityCheck, NULL); HMAC_Final(&hmac_ctx, context->MessageIntegrityCheck, NULL);
HMAC_CTX_cleanup(&hmac_ctx); HMAC_CTX_cleanup(&hmac_ctx);
} }

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* NTLM Security Package (Compute) * NTLM Security Package (Compute)
* *
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -25,24 +25,22 @@
#include "ntlm_av_pairs.h" #include "ntlm_av_pairs.h"
void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo); void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo);
void ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo); int ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo);
void ntlm_write_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo); void ntlm_write_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo);
void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo); void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo);
void ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response); int ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
void ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response); int ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context);
void ntlm_output_target_name(NTLM_CONTEXT* context); void ntlm_output_target_name(NTLM_CONTEXT* context);
void ntlm_output_channel_bindings(NTLM_CONTEXT* context); void ntlm_output_channel_bindings(NTLM_CONTEXT* context);
void ntlm_current_time(BYTE* timestamp); void ntlm_current_time(BYTE* timestamp);
void ntlm_generate_timestamp(NTLM_CONTEXT* context); void ntlm_generate_timestamp(NTLM_CONTEXT* context);
void ntlm_compute_ntlm_hash(UINT16* password, UINT32 length, char* hash); int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash);
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash); int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context);
void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context); int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context);
void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context);
void ntlm_rc4k(BYTE* key, int length, BYTE* plaintext, BYTE* ciphertext); void ntlm_rc4k(BYTE* key, int length, BYTE* plaintext, BYTE* ciphertext);
void ntlm_generate_client_challenge(NTLM_CONTEXT* context); void ntlm_generate_client_challenge(NTLM_CONTEXT* context);

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* NTLM Security Package (Message) * NTLM Security Package (Message)
* *
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,4 +29,6 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer);
SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer); SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer);
SECURITY_STATUS ntlm_server_AuthenticateComplete(NTLM_CONTEXT* context);
#endif /* WINPR_SSPI_NTLM_MESSAGE_H */ #endif /* WINPR_SSPI_NTLM_MESSAGE_H */

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* Negotiate Security Package * Negotiate Security Package
* *
* Copyright 2011-2012 Jiten Pathy * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,67 +28,27 @@
#include "../sspi.h" #include "../sspi.h"
extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA;
extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW;
char* NEGOTIATE_PACKAGE_NAME = "Negotiate"; char* NEGOTIATE_PACKAGE_NAME = "Negotiate";
SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext,
SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
NEGOTIATE_CONTEXT* context;
CREDENTIALS* credentials;
PSecBuffer output_SecBuffer;
context = sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = negotiate_ContextNew();
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
sspi_CopyAuthIdentity(&context->identity, &credentials->identity);
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
}
if ((!pInput) && (context->state == NEGOTIATE_STATE_INITIAL))
{
if (!pOutput)
return SEC_E_INVALID_TOKEN;
if (pOutput->cBuffers < 1)
return SEC_E_INVALID_TOKEN;
output_SecBuffer = &pOutput->pBuffers[0];
if (output_SecBuffer->cbBuffer < 1)
return SEC_E_INSUFFICIENT_MEMORY;
}
return SEC_E_OK;
}
NEGOTIATE_CONTEXT* negotiate_ContextNew() NEGOTIATE_CONTEXT* negotiate_ContextNew()
{ {
NEGOTIATE_CONTEXT* context; NEGOTIATE_CONTEXT* context;
context = (NEGOTIATE_CONTEXT*) calloc(1, sizeof(NEGOTIATE_CONTEXT)); context = (NEGOTIATE_CONTEXT*) calloc(1, sizeof(NEGOTIATE_CONTEXT));
if (context != NULL) if (!context)
{ return NULL;
context->NegotiateFlags = 0; context->NegotiateFlags = 0;
context->state = NEGOTIATE_STATE_INITIAL; context->state = NEGOTIATE_STATE_INITIAL;
}
SecInvalidateHandle(&(context->SubContext));
context->sspiA = (SecurityFunctionTableA*) &NTLM_SecurityFunctionTableA;
context->sspiW = (SecurityFunctionTableW*) &NTLM_SecurityFunctionTableW;
return context; return context;
} }
@ -101,37 +61,258 @@ void negotiate_ContextFree(NEGOTIATE_CONTEXT* context)
free(context); free(context);
} }
SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext,
SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{ {
SECURITY_STATUS status;
NEGOTIATE_CONTEXT* context;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = negotiate_ContextNew();
if (!context)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
}
status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext),
pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext),
pOutput, pfContextAttr, ptsExpiry);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
SECURITY_STATUS status;
NEGOTIATE_CONTEXT* context;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = negotiate_ContextNew();
if (!context)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
}
status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext),
pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext),
pOutput, pfContextAttr, ptsExpiry);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext,
PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
{
SECURITY_STATUS status;
NEGOTIATE_CONTEXT* context;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
context = negotiate_ContextNew();
if (!context)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
}
status = context->sspiA->AcceptSecurityContext(phCredential, &(context->SubContext),
pInput, fContextReq, TargetDataRep, &(context->SubContext),
pOutput, pfContextAttr, ptsTimeStamp);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
return SEC_E_INVALID_HANDLE;
if (context->sspiW->CompleteAuthToken)
status = context->sspiW->CompleteAuthToken(phContext, pToken);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle phContext)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
return SEC_E_INVALID_HANDLE;
if (context->sspiW->DeleteSecurityContext)
status = context->sspiW->DeleteSecurityContext(&(context->SubContext));
negotiate_ContextFree(context);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_ImpersonateSecurityContext(PCtxtHandle phContext)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (context->sspiW->ImpersonateSecurityContext)
status = context->sspiW->ImpersonateSecurityContext(&(context->SubContext));
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_RevertSecurityContext(PCtxtHandle phContext)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (context->sspiW->RevertSecurityContext)
status = context->sspiW->RevertSecurityContext(&(context->SubContext));
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext) if (!phContext)
return SEC_E_INVALID_HANDLE; return SEC_E_INVALID_HANDLE;
if (!pBuffer) if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY; return SEC_E_INSUFFICIENT_MEMORY;
return SEC_E_UNSUPPORTED_FUNCTION; if (context->sspiW->QueryContextAttributesW)
status = context->sspiW->QueryContextAttributesW(&(context->SubContext), ulAttribute, pBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (context->sspiA->QueryContextAttributesA)
status = context->sspiA->QueryContextAttributesA(&(context->SubContext), ulAttribute, pBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (context->sspiW->SetContextAttributesW)
status = context->sspiW->SetContextAttributesW(&(context->SubContext), ulAttribute, pBuffer, cbBuffer);
return status;
}
SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
if (context->sspiA->SetContextAttributesA)
status = context->sspiA->SetContextAttributesA(&(context->SubContext), ulAttribute, pBuffer, cbBuffer);
return status;
} }
SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{ {
return SEC_E_OK; SSPI_CREDENTIALS* credentials;
}
SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity; SEC_WINNT_AUTH_IDENTITY* identity;
if (fCredentialUse == SECPKG_CRED_OUTBOUND) if ((fCredentialUse != SECPKG_CRED_OUTBOUND) &&
(fCredentialUse != SECPKG_CRED_INBOUND) &&
(fCredentialUse != SECPKG_CRED_BOTH))
{ {
return SEC_E_INVALID_PARAMETER;
}
credentials = sspi_CredentialsNew(); credentials = sspi_CredentialsNew();
if (!credentials)
return SEC_E_INTERNAL_ERROR;
credentials->fCredentialUse = fCredentialUse;
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
memcpy(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); if (identity)
sspi_CopyAuthIdentity(&(credentials->identity), identity);
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME);
@ -139,36 +320,58 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrinc
return SEC_E_OK; return SEC_E_OK;
} }
SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity;
if ((fCredentialUse != SECPKG_CRED_OUTBOUND) &&
(fCredentialUse != SECPKG_CRED_INBOUND) &&
(fCredentialUse != SECPKG_CRED_BOTH))
{
return SEC_E_INVALID_PARAMETER;
}
credentials = sspi_CredentialsNew();
if (!credentials)
return SEC_E_INTERNAL_ERROR;
credentials->fCredentialUse = fCredentialUse;
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity)
sspi_CopyAuthIdentity(&(credentials->identity), identity);
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME);
return SEC_E_OK; return SEC_E_OK;
} }
SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{ {
return SEC_E_OK; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
{ {
if (ulAttribute == SECPKG_CRED_ATTR_NAMES)
{
CREDENTIALS* credentials;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION; return SEC_E_UNSUPPORTED_FUNCTION;
} }
SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredential) SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredential)
{ {
CREDENTIALS* credentials; SSPI_CREDENTIALS* credentials;
if (!phCredential) if (!phCredential)
return SEC_E_INVALID_HANDLE; return SEC_E_INVALID_HANDLE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials) if (!credentials)
return SEC_E_INVALID_HANDLE; return SEC_E_INVALID_HANDLE;
@ -180,22 +383,54 @@ SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredenti
SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{ {
return SEC_E_OK; NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (context->sspiW->EncryptMessage)
status = context->sspiW->EncryptMessage(&(context->SubContext), fQOP, pMessage, MessageSeqNo);
return status;
} }
SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
{ {
return SEC_E_OK; NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (context->sspiW->DecryptMessage)
status = context->sspiW->DecryptMessage(&(context->SubContext), pMessage, MessageSeqNo, pfQOP);
return status;
} }
SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{ {
return SEC_E_OK; NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (context->sspiW->MakeSignature)
status = context->sspiW->MakeSignature(&(context->SubContext), fQOP, pMessage, MessageSeqNo);
return status;
} }
SECURITY_STATUS SEC_ENTRY negotiate_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) SECURITY_STATUS SEC_ENTRY negotiate_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
{ {
return SEC_E_OK; NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (context->sspiW->VerifySignature)
status = context->sspiW->VerifySignature(&(context->SubContext), pMessage, MessageSeqNo, pfQOP);
return status;
} }
const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA = const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA =
@ -207,13 +442,13 @@ const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA =
negotiate_FreeCredentialsHandle, /* FreeCredentialsHandle */ negotiate_FreeCredentialsHandle, /* FreeCredentialsHandle */
NULL, /* Reserved2 */ NULL, /* Reserved2 */
negotiate_InitializeSecurityContextA, /* InitializeSecurityContext */ negotiate_InitializeSecurityContextA, /* InitializeSecurityContext */
NULL, /* AcceptSecurityContext */ negotiate_AcceptSecurityContext, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */ negotiate_CompleteAuthToken, /* CompleteAuthToken */
NULL, /* DeleteSecurityContext */ negotiate_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */ NULL, /* ApplyControlToken */
negotiate_QueryContextAttributes, /* QueryContextAttributes */ negotiate_QueryContextAttributesA, /* QueryContextAttributes */
NULL, /* ImpersonateSecurityContext */ negotiate_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
NULL, /* RevertSecurityContext */ negotiate_RevertSecurityContext, /* RevertSecurityContext */
negotiate_MakeSignature, /* MakeSignature */ negotiate_MakeSignature, /* MakeSignature */
negotiate_VerifySignature, /* VerifySignature */ negotiate_VerifySignature, /* VerifySignature */
NULL, /* FreeContextBuffer */ NULL, /* FreeContextBuffer */
@ -227,7 +462,7 @@ const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA =
NULL, /* QuerySecurityContextToken */ NULL, /* QuerySecurityContextToken */
negotiate_EncryptMessage, /* EncryptMessage */ negotiate_EncryptMessage, /* EncryptMessage */
negotiate_DecryptMessage, /* DecryptMessage */ negotiate_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */ negotiate_SetContextAttributesA, /* SetContextAttributes */
}; };
const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW = const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
@ -239,13 +474,13 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
negotiate_FreeCredentialsHandle, /* FreeCredentialsHandle */ negotiate_FreeCredentialsHandle, /* FreeCredentialsHandle */
NULL, /* Reserved2 */ NULL, /* Reserved2 */
negotiate_InitializeSecurityContextW, /* InitializeSecurityContext */ negotiate_InitializeSecurityContextW, /* InitializeSecurityContext */
NULL, /* AcceptSecurityContext */ negotiate_AcceptSecurityContext, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */ negotiate_CompleteAuthToken, /* CompleteAuthToken */
NULL, /* DeleteSecurityContext */ negotiate_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */ NULL, /* ApplyControlToken */
negotiate_QueryContextAttributes, /* QueryContextAttributes */ negotiate_QueryContextAttributesW, /* QueryContextAttributes */
NULL, /* ImpersonateSecurityContext */ negotiate_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
NULL, /* RevertSecurityContext */ negotiate_RevertSecurityContext, /* RevertSecurityContext */
negotiate_MakeSignature, /* MakeSignature */ negotiate_MakeSignature, /* MakeSignature */
negotiate_VerifySignature, /* VerifySignature */ negotiate_VerifySignature, /* VerifySignature */
NULL, /* FreeContextBuffer */ NULL, /* FreeContextBuffer */
@ -259,7 +494,7 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
NULL, /* QuerySecurityContextToken */ NULL, /* QuerySecurityContextToken */
negotiate_EncryptMessage, /* EncryptMessage */ negotiate_EncryptMessage, /* EncryptMessage */
negotiate_DecryptMessage, /* DecryptMessage */ negotiate_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */ negotiate_SetContextAttributesW, /* SetContextAttributes */
}; };
const SecPkgInfoA NEGOTIATE_SecPkgInfoA = const SecPkgInfoA NEGOTIATE_SecPkgInfoA =

View File

@ -40,8 +40,12 @@ struct _NEGOTIATE_CONTEXT
NEGOTIATE_STATE state; NEGOTIATE_STATE state;
UINT32 NegotiateFlags; UINT32 NegotiateFlags;
PCtxtHandle auth_ctx; PCtxtHandle auth_ctx;
SEC_WINNT_AUTH_IDENTITY identity;
SecBuffer NegoInitMessage; SecBuffer NegoInitMessage;
CtxtHandle SubContext;
SecurityFunctionTableA* sspiA;
SecurityFunctionTableW* sspiW;
}; };
typedef struct _NEGOTIATE_CONTEXT NEGOTIATE_CONTEXT; typedef struct _NEGOTIATE_CONTEXT NEGOTIATE_CONTEXT;

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* Schannel Security Package * Schannel Security Package
* *
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* Schannel Security Package (OpenSSL) * Schannel Security Package (OpenSSL)
* *
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -280,7 +280,7 @@ SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context
if (status > 0) if (status > 0)
{ {
if (pBuffer->cbBuffer < status) if (pBuffer->cbBuffer < (unsigned long) status)
return SEC_E_INSUFFICIENT_MEMORY; return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status); CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
@ -339,7 +339,7 @@ SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context
if (status > 0) if (status > 0)
{ {
if (pBuffer->cbBuffer < status) if (pBuffer->cbBuffer < (unsigned long) status)
return SEC_E_INSUFFICIENT_MEMORY; return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status); CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
@ -387,17 +387,17 @@ SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSec
if (status > 0) if (status > 0)
{ {
offset = 0; offset = 0;
length = (pStreamHeaderBuffer->cbBuffer > status) ? status : pStreamHeaderBuffer->cbBuffer; length = (pStreamHeaderBuffer->cbBuffer > (unsigned long) status) ? status : pStreamHeaderBuffer->cbBuffer;
CopyMemory(pStreamHeaderBuffer->pvBuffer, &context->ReadBuffer[offset], length); CopyMemory(pStreamHeaderBuffer->pvBuffer, &context->ReadBuffer[offset], length);
status -= length; status -= length;
offset += length; offset += length;
length = (pStreamBodyBuffer->cbBuffer > status) ? status : pStreamBodyBuffer->cbBuffer; length = (pStreamBodyBuffer->cbBuffer > (unsigned long) status) ? status : pStreamBodyBuffer->cbBuffer;
CopyMemory(pStreamBodyBuffer->pvBuffer, &context->ReadBuffer[offset], length); CopyMemory(pStreamBodyBuffer->pvBuffer, &context->ReadBuffer[offset], length);
status -= length; status -= length;
offset += length; offset += length;
length = (pStreamTrailerBuffer->cbBuffer > status) ? status : pStreamTrailerBuffer->cbBuffer; length = (pStreamTrailerBuffer->cbBuffer > (unsigned long) status) ? status : pStreamTrailerBuffer->cbBuffer;
CopyMemory(pStreamTrailerBuffer->pvBuffer, &context->ReadBuffer[offset], length); CopyMemory(pStreamTrailerBuffer->pvBuffer, &context->ReadBuffer[offset], length);
status -= length; status -= length;
} }

View File

@ -1,3 +1,34 @@
LIBRARY "libwinpr-sspi" LIBRARY "libwinpr-sspi"
EXPORTS EXPORTS
AcceptSecurityContext
AcquireCredentialsHandleA
AcquireCredentialsHandleW
ApplyControlToken
CompleteAuthToken
DecryptMessage
DeleteSecurityContext
EncryptMessage
EnumerateSecurityPackagesA
EnumerateSecurityPackagesW
ExportSecurityContext
FreeContextBuffer
FreeCredentialsHandle
ImpersonateSecurityContext
ImportSecurityContextA
ImportSecurityContextW
InitSecurityInterfaceA
InitSecurityInterfaceW
InitializeSecurityContextA
InitializeSecurityContextW
MakeSignature
QueryContextAttributesA
QueryContextAttributesW
QueryCredentialsAttributesA
QueryCredentialsAttributesW
QuerySecurityContextToken
QuerySecurityPackageInfoA
QuerySecurityPackageInfoW
RevertSecurityContext
VerifySignature
InitSecurityInterfaceExA
InitSecurityInterfaceExW

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* Security Support Provider Interface (SSPI) * Security Support Provider Interface (SSPI)
* *
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,20 +28,22 @@
#define SSPI_CREDENTIALS_HASH_LENGTH_FACTOR 64 #define SSPI_CREDENTIALS_HASH_LENGTH_FACTOR 64
struct _CREDENTIALS struct _SSPI_CREDENTIALS
{ {
DWORD flags; DWORD flags;
ULONG fCredentialUse;
SEC_GET_KEY_FN pGetKeyFn;
void* pvGetKeyArgument;
SEC_WINNT_AUTH_IDENTITY identity; SEC_WINNT_AUTH_IDENTITY identity;
}; };
typedef struct _CREDENTIALS CREDENTIALS; typedef struct _SSPI_CREDENTIALS SSPI_CREDENTIALS;
CREDENTIALS* sspi_CredentialsNew(void); SSPI_CREDENTIALS* sspi_CredentialsNew(void);
void sspi_CredentialsFree(CREDENTIALS* credentials); void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials);
PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType); PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType);
SecHandle* sspi_SecureHandleAlloc(void); SecHandle* sspi_SecureHandleAlloc(void);
void sspi_SecureHandleInit(SecHandle* handle);
void sspi_SecureHandleInvalidate(SecHandle* handle); void sspi_SecureHandleInvalidate(SecHandle* handle);
void* sspi_SecureHandleGetLowerPointer(SecHandle* handle); void* sspi_SecureHandleGetLowerPointer(SecHandle* handle);
void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer); void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer);
@ -81,4 +83,6 @@ enum SecurityFunctionTableIndex
SetContextAttributesIndex = 28 SetContextAttributesIndex = 28
}; };
#include "sspi_winpr.h"
#endif /* WINPR_SSPI_PRIVATE_H */ #endif /* WINPR_SSPI_PRIVATE_H */

View File

@ -0,0 +1,289 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Security Support Provider Interface (SSPI)
*
* Copyright 2012-2014 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef _WIN32
#define SEC_ENTRY __stdcall
#define SSPI_EXPORT __declspec(dllexport)
#else
#define SEC_ENTRY
#define SSPI_EXPORT
#endif
typedef long LONG;
typedef unsigned long ULONG;
typedef LONG SECURITY_STATUS;
/**
* Standard SSPI API
*/
/* Package Management */
extern SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesW(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesW(void* pcPackages, void* ppPackageInfo)
{
return sspi_EnumerateSecurityPackagesW(pcPackages, ppPackageInfo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesA(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesA(void* pcPackages, void* ppPackageInfo)
{
return sspi_EnumerateSecurityPackagesA(pcPackages, ppPackageInfo);
}
extern void* SEC_ENTRY sspi_InitSecurityInterfaceW(void);
SSPI_EXPORT void* SEC_ENTRY InitSecurityInterfaceW(void)
{
return sspi_InitSecurityInterfaceW();
}
extern void* SEC_ENTRY sspi_InitSecurityInterfaceA(void);
SSPI_EXPORT void* SEC_ENTRY InitSecurityInterfaceA(void)
{
return sspi_InitSecurityInterfaceA();
}
extern SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoW(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoW(void* pszPackageName, void* ppPackageInfo)
{
return sspi_QuerySecurityPackageInfoW(pszPackageName, ppPackageInfo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoA(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoA(void* pszPackageName, void* ppPackageInfo)
{
return sspi_QuerySecurityPackageInfoA(pszPackageName, ppPackageInfo);
}
/* Credential Management */
extern SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleW(void*, void*, ULONG, void*, void*, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleW(void* pszPrincipal, void* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, void* pGetKeyFn,
void* pvGetKeyArgument, void* phCredential, void* ptsExpiry)
{
return sspi_AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse,
pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleA(void*, void*, ULONG, void*, void*, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleA(void* pszPrincipal, void* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, void* pGetKeyFn,
void* pvGetKeyArgument, void* phCredential, void* ptsExpiry)
{
return sspi_AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse,
pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ExportSecurityContext(void*, ULONG, void*, void**);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ExportSecurityContext(void* phContext, ULONG fFlags, void* pPackedContext, void** pToken)
{
return sspi_ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
}
extern SECURITY_STATUS SEC_ENTRY sspi_FreeCredentialsHandle(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY FreeCredentialsHandle(void* phCredential)
{
return sspi_FreeCredentialsHandle(phCredential);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextW(void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ImportSecurityContextW(void* pszPackage, void* pPackedContext, void* pToken, void* phContext)
{
return sspi_ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextA(void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ImportSecurityContextA(void* pszPackage, void* pPackedContext, void* pToken, void* phContext)
{
return sspi_ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesW(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesW(void* phCredential, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesA(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesA(void* phCredential, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
}
/* Context Management */
extern SECURITY_STATUS SEC_ENTRY sspi_AcceptSecurityContext(void*, void*, void*, ULONG, ULONG, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY AcceptSecurityContext(void* phCredential, void* phContext,
void* pInput, ULONG fContextReq, ULONG TargetDataRep, void* phNewContext,
void* pOutput, void* pfContextAttr, void* ptsTimeStamp)
{
return sspi_AcceptSecurityContext(phCredential, phContext, pInput, fContextReq,
TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ApplyControlToken(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ApplyControlToken(void* phContext, void* pInput)
{
return sspi_ApplyControlToken(phContext, pInput);
}
extern SECURITY_STATUS SEC_ENTRY sspi_CompleteAuthToken(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY CompleteAuthToken(void* phContext, void* pToken)
{
return sspi_CompleteAuthToken(phContext, pToken);
}
extern SECURITY_STATUS SEC_ENTRY sspi_DeleteSecurityContext(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY DeleteSecurityContext(void* phContext)
{
return sspi_DeleteSecurityContext(phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_FreeContextBuffer(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY FreeContextBuffer(void* pvContextBuffer)
{
return sspi_FreeContextBuffer(pvContextBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ImpersonateSecurityContext(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ImpersonateSecurityContext(void* phContext)
{
return sspi_ImpersonateSecurityContext(phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextW(void*, void*, void*, ULONG, ULONG, ULONG,
void*, ULONG, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY InitializeSecurityContextW(void* phCredential, void* phContext,
void* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
void* pInput, ULONG Reserved2, void* phNewContext,
void* pOutput, void* pfContextAttr, void* ptsExpiry)
{
return sspi_InitializeSecurityContextW(phCredential, phContext, pszTargetName, fContextReq, Reserved1,
TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextA(void*, void*, void*, ULONG, ULONG, ULONG,
void*, ULONG, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY InitializeSecurityContextA(void* phCredential, void* phContext,
void* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
void* pInput, ULONG Reserved2, void* phNewContext,
void* pOutput, void* pfContextAttr, void* ptsExpiry)
{
return sspi_InitializeSecurityContextA(phCredential, phContext, pszTargetName, fContextReq, Reserved1,
TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesW(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryContextAttributesW(void* phContext, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesA(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryContextAttributesA(void* phContext, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryContextAttributesA(phContext, ulAttribute, pBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityContextToken(void*, void**);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QuerySecurityContextToken(void* phContext, void** phToken)
{
return sspi_QuerySecurityContextToken(phContext, phToken);
}
extern SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesW(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY SetContextAttributesW(void* phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
return sspi_SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesA(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY SetContextAttributesA(void* phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
return sspi_SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_RevertSecurityContext(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY RevertSecurityContext(void* phContext)
{
return sspi_RevertSecurityContext(phContext);
}
/* Message Support */
extern SECURITY_STATUS SEC_ENTRY sspi_DecryptMessage(void*, void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY DecryptMessage(void* phContext, void* pMessage, ULONG MessageSeqNo, void* pfQOP)
{
return sspi_DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
}
extern SECURITY_STATUS SEC_ENTRY sspi_EncryptMessage(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY EncryptMessage(void* phContext, ULONG fQOP, void* pMessage, ULONG MessageSeqNo)
{
return sspi_EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_MakeSignature(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY MakeSignature(void* phContext, ULONG fQOP, void* pMessage, ULONG MessageSeqNo)
{
return sspi_MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_VerifySignature(void*, void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY VerifySignature(void* phContext, void* pMessage, ULONG MessageSeqNo, void* pfQOP)
{
return sspi_VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/** /**
* WinPR: Windows Portable Runtime * WinPR: Windows Portable Runtime
* config.h definitions for installable headers * Security Support Provider Interface (SSPI)
* *
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,16 +17,12 @@
* limitations under the License. * limitations under the License.
*/ */
#ifndef WINPR_CONFIG_H #ifndef WINPR_SSPI_WINPR_H
#define WINPR_CONFIG_H #define WINPR_SSPI_WINPR_H
/* #include <winpr/sspi.h>
* This generated config.h header is meant for installation, which is why
* all definitions MUST be prefixed to avoid conflicting with third-party
* libraries. Only add configurable definitions which really must be used
* from installable headers, such as the base type definition types.
*/
#cmakedefine WITH_NATIVE_SSPI SecurityFunctionTableW* SEC_ENTRY winpr_InitSecurityInterfaceW(void);
SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void);
#endif /* WINPR_CONFIG_H */ #endif /* WINPR_SSPI_WINPR_H */

View File

@ -9,8 +9,9 @@ set(${MODULE_PREFIX}_TESTS
TestEnumerateSecurityPackages.c TestEnumerateSecurityPackages.c
TestInitializeSecurityContext.c TestInitializeSecurityContext.c
TestAcquireCredentialsHandle.c TestAcquireCredentialsHandle.c
TestNTLM.c TestCredSSP.c
) TestSchannel.c
TestNTLM.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_DRIVER}

View File

@ -0,0 +1,8 @@
#include <winpr/crt.h>
#include <winpr/sspi.h>
int TestCredSSP(int argc, char* argv[])
{
return 0;
}

View File

@ -1,59 +1,546 @@
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/sspi.h> #include <winpr/sspi.h>
#include <winpr/print.h>
BYTE test_Certificate[] = #define TEST_SSPI_INTERFACE SSPI_INTERFACE_WINPR
"\x30\x82\x02\x09\x30\x82\x01\x76\xa0\x03\x02\x01\x02\x02\x10\xcb"
"\x69\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30"
"\x09\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x30\x16\x31\x14\x30\x12"
"\x06\x03\x55\x04\x03\x13\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38"
"\x52\x32\x30\x1e\x17\x0d\x31\x32\x31\x31\x31\x37\x30\x30\x35\x39"
"\x32\x31\x5a\x17\x0d\x33\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35"
"\x39\x5a\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x44"
"\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x30\x81\x9f\x30\x0d\x06"
"\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00"
"\x30\x81\x89\x02\x81\x81\x00\x9b\x00\xf8\x1a\x2d\x37\xc6\x8d\xa1"
"\x39\x91\x46\xf3\x6a\x1b\xf9\x60\x6c\xb3\x6c\xa0\xac\xed\x85\xe0"
"\x3f\xdc\x92\x86\x36\xbd\x64\xbf\x36\x51\xdb\x57\x3a\x8a\x82\x6b"
"\xd8\x94\x17\x7b\xd3\x91\x11\x98\xef\x19\x06\x52\x30\x03\x73\x67"
"\xc8\xed\x8e\xfa\x0b\x3d\x4c\xc9\x10\x63\x9f\xcf\xb4\xcf\x39\xd8"
"\xfe\x99\xeb\x5b\x11\xf2\xfc\xfa\x86\x24\xd9\xff\xd9\x19\xf5\x69"
"\xb4\xdf\x5a\x5a\xc4\x94\xb4\xb0\x07\x25\x97\x13\xad\x7e\x38\x14"
"\xfb\xd6\x33\x65\x6f\xe6\xf7\x48\x4b\x2d\xb3\x51\x2e\x6d\xc7\xea"
"\x11\x76\x9a\x2b\xf0\x00\x4d\x02\x03\x01\x00\x01\xa3\x60\x30\x5e"
"\x30\x13\x06\x03\x55\x1d\x25\x04\x0c\x30\x0a\x06\x08\x2b\x06\x01"
"\x05\x05\x07\x03\x01\x30\x47\x06\x03\x55\x1d\x01\x04\x40\x30\x3e"
"\x80\x10\xeb\x65\x26\x03\x95\x4b\xd6\xc0\x54\x75\x78\x7c\xb6\x2a"
"\xa1\xbb\xa1\x18\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13"
"\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x82\x10\xcb\x69"
"\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30\x09"
"\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x03\x81\x81\x00\x7b\xfa\xfe"
"\xee\x74\x05\xac\xbb\x79\xe9\xda\xca\x00\x44\x96\x94\x71\x92\xb1"
"\xdb\xc9\x9b\x71\x29\xc0\xe4\x28\x5e\x6a\x50\x99\xcd\xa8\x17\xe4"
"\x56\xb9\xef\x7f\x02\x7d\x96\xa3\x48\x14\x72\x75\x2f\xb0\xb5\x87"
"\xee\x55\xe9\x6a\x6d\x28\x3c\xc1\xfd\x00\xe4\x76\xe3\x80\x88\x78"
"\x26\x0d\x6c\x8c\xb8\x64\x61\x63\xb7\x13\x3a\xab\xc7\xdd\x1d\x0a"
"\xd7\x15\x45\xa1\xd6\xd9\x34\xc7\x21\x48\xfb\x43\x87\x38\xda\x1f"
"\x50\x47\xb1\xa5\x5c\x47\xed\x04\x44\x97\xd3\xac\x74\x2d\xeb\x09"
"\x77\x59\xbf\xa3\x54\x5b\xde\x42\xd5\x23\x5a\x71\x9f";
BYTE test_Certificate_SHA256Hash[] = static const char* TEST_NTLM_USER = "Username";
"\xea\x05\xfe\xfe\xcc\x6b\x0b\xd5\x71\xdb\xbc\x5b\xaa\x3e\xd4\x53" static const char* TEST_NTLM_DOMAIN = "Domain";
"\x86\xd0\x44\x68\x35\xf7\xb7\x4c\x85\x62\x1b\x99\x83\x47\x5f\x95"; static const char* TEST_NTLM_PASSWORD = "P4ss123!";
BYTE test_ChannelBindings_MD5Hash[] = //static const char* TEST_NTLM_HASH_STRING = "d5922a65c4d5c082ca444af1be0001db";
"\x65\x86\xE9\x9D\x81\xC2\xFC\x98\x4E\x47\x17\x2F\xD4\xDD\x03\x10";
int test_ntlm_channel_binding_token() static const BYTE TEST_NTLM_HASH[16] =
{ 0xd5, 0x92, 0x2a, 0x65, 0xc4, 0xd5, 0xc0, 0x82, 0xca, 0x44, 0x4a, 0xf1, 0xbe, 0x00, 0x01, 0xdb };
//#define NTLM_PACKAGE_NAME NEGOSSP_NAME
#define NTLM_PACKAGE_NAME NTLMSP_NAME
struct _TEST_NTLM_CLIENT
{ {
CtxtHandle context;
ULONG cbMaxToken;
ULONG fContextReq;
ULONG pfContextAttr;
TimeStamp expiration;
PSecBuffer pBuffer;
SecBuffer inputBuffer[2];
SecBuffer outputBuffer[2];
BOOL haveContext;
BOOL haveInputBuffer;
LPTSTR ServicePrincipalName;
SecBufferDesc inputBufferDesc;
SecBufferDesc outputBufferDesc;
CredHandle credentials;
BOOL confidentiality;
SecPkgInfo* pPackageInfo;
SecurityFunctionTable* table;
SEC_WINNT_AUTH_IDENTITY identity;
};
typedef struct _TEST_NTLM_CLIENT TEST_NTLM_CLIENT;
return 0; int test_ntlm_client_init(TEST_NTLM_CLIENT* ntlm, const char* user, const char* domain, const char* password)
{
SECURITY_STATUS status;
SecInvalidateHandle(&(ntlm->context));
ntlm->table = InitSecurityInterfaceEx(TEST_SSPI_INTERFACE);
sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password);
status = ntlm->table->QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &ntlm->pPackageInfo);
if (status != SEC_E_OK)
{
fprintf(stderr, "QuerySecurityPackageInfo status: %s (0x%04X)\n",
GetSecurityStatusString(status), status);
return -1;
}
ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
status = ntlm->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME,
SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration);
if (status != SEC_E_OK)
{
fprintf(stderr, "AcquireCredentialsHandle status: %s (0x%04X)\n",
GetSecurityStatusString(status), status);
return -1;
}
ntlm->haveContext = FALSE;
ntlm->haveInputBuffer = FALSE;
ZeroMemory(&ntlm->inputBuffer, sizeof(SecBuffer));
ZeroMemory(&ntlm->outputBuffer, sizeof(SecBuffer));
ntlm->fContextReq = 0;
#if 0
/* HTTP authentication flags */
ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY;
#endif
/* NLA authentication flags */
ntlm->fContextReq |= ISC_REQ_MUTUAL_AUTH;
ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY;
ntlm->fContextReq |= ISC_REQ_USE_SESSION_KEY;
return 1;
}
void test_ntlm_client_uninit(TEST_NTLM_CLIENT* ntlm)
{
if (!ntlm)
return;
if (ntlm->outputBuffer[0].pvBuffer)
{
free(ntlm->outputBuffer[0].pvBuffer);
ntlm->outputBuffer[0].pvBuffer = NULL;
}
free(ntlm->identity.User);
free(ntlm->identity.Domain);
free(ntlm->identity.Password);
free(ntlm->ServicePrincipalName);
if (ntlm->table)
{
ntlm->table->FreeCredentialsHandle(&ntlm->credentials);
ntlm->table->FreeContextBuffer(ntlm->pPackageInfo);
ntlm->table->DeleteSecurityContext(&ntlm->context);
}
}
/**
* SSPI Client Ceremony
*
* --------------
* ( Client Begin )
* --------------
* |
* |
* \|/
* -----------+--------------
* | AcquireCredentialsHandle |
* --------------------------
* |
* |
* \|/
* -------------+--------------
* +---------------> / InitializeSecurityContext /
* | ----------------------------
* | |
* | |
* | \|/
* --------------------------- ---------+------------- ----------------------
* / Receive blob from server / < Received security blob? > --Yes-> / Send blob to server /
* -------------+------------- ----------------------- ----------------------
* /|\ | |
* | No |
* Yes \|/ |
* | ------------+----------- |
* +---------------- < Received Continue Needed > <-----------------+
* ------------------------
* |
* No
* \|/
* ------+-------
* ( Client End )
* --------------
*/
int test_ntlm_client_authenticate(TEST_NTLM_CLIENT* ntlm)
{
SECURITY_STATUS status;
if (ntlm->outputBuffer[0].pvBuffer)
{
free(ntlm->outputBuffer[0].pvBuffer);
ntlm->outputBuffer[0].pvBuffer = NULL;
}
ntlm->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->outputBufferDesc.cBuffers = 1;
ntlm->outputBufferDesc.pBuffers = ntlm->outputBuffer;
ntlm->outputBuffer[0].BufferType = SECBUFFER_TOKEN;
ntlm->outputBuffer[0].cbBuffer = ntlm->cbMaxToken;
ntlm->outputBuffer[0].pvBuffer = malloc(ntlm->outputBuffer[0].cbBuffer);
if (!ntlm->outputBuffer[0].pvBuffer)
return -1;
if (ntlm->haveInputBuffer)
{
ntlm->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->inputBufferDesc.cBuffers = 1;
ntlm->inputBufferDesc.pBuffers = ntlm->inputBuffer;
ntlm->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
}
if ((!ntlm) || (!ntlm->table))
{
fprintf(stderr, "ntlm_authenticate: invalid ntlm context\n");
return -1;
}
status = ntlm->table->InitializeSecurityContext(&ntlm->credentials,
(ntlm->haveContext) ? &ntlm->context : NULL,
(ntlm->ServicePrincipalName) ? ntlm->ServicePrincipalName : NULL,
ntlm->fContextReq, 0, SECURITY_NATIVE_DREP,
(ntlm->haveInputBuffer) ? &ntlm->inputBufferDesc : NULL,
0, &ntlm->context, &ntlm->outputBufferDesc,
&ntlm->pfContextAttr, &ntlm->expiration);
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
{
if (ntlm->table->CompleteAuthToken)
ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
else if (status == SEC_I_COMPLETE_AND_CONTINUE)
status = SEC_I_CONTINUE_NEEDED;
}
if (ntlm->haveInputBuffer)
{
free(ntlm->inputBuffer[0].pvBuffer);
}
ntlm->haveInputBuffer = TRUE;
ntlm->haveContext = TRUE;
return (status == SEC_I_CONTINUE_NEEDED) ? 1 : 0;
}
TEST_NTLM_CLIENT* test_ntlm_client_new()
{
TEST_NTLM_CLIENT* ntlm;
ntlm = (TEST_NTLM_CLIENT*) calloc(1, sizeof(TEST_NTLM_CLIENT));
if (!ntlm)
return NULL;
return ntlm;
}
void test_ntlm_client_free(TEST_NTLM_CLIENT* ntlm)
{
if (!ntlm)
return;
test_ntlm_client_uninit(ntlm);
free(ntlm);
}
struct _TEST_NTLM_SERVER
{
CtxtHandle context;
ULONG cbMaxToken;
ULONG fContextReq;
ULONG pfContextAttr;
TimeStamp expiration;
PSecBuffer pBuffer;
SecBuffer inputBuffer[2];
SecBuffer outputBuffer[2];
BOOL haveContext;
BOOL haveInputBuffer;
LPTSTR ServicePrincipalName;
SecBufferDesc inputBufferDesc;
SecBufferDesc outputBufferDesc;
CredHandle credentials;
BOOL confidentiality;
SecPkgInfo* pPackageInfo;
SecurityFunctionTable* table;
SEC_WINNT_AUTH_IDENTITY identity;
};
typedef struct _TEST_NTLM_SERVER TEST_NTLM_SERVER;
int test_ntlm_server_init(TEST_NTLM_SERVER* ntlm)
{
SECURITY_STATUS status;
SecInvalidateHandle(&(ntlm->context));
ntlm->table = InitSecurityInterfaceEx(TEST_SSPI_INTERFACE);
status = ntlm->table->QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &ntlm->pPackageInfo);
if (status != SEC_E_OK)
{
fprintf(stderr, "QuerySecurityPackageInfo status: %s (0x%04X)\n",
GetSecurityStatusString(status), status);
return -1;
}
ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
status = ntlm->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME,
SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL,
&ntlm->credentials, &ntlm->expiration);
if (status != SEC_E_OK)
{
fprintf(stderr, "AcquireCredentialsHandle status: %s (0x%04X)\n",
GetSecurityStatusString(status), status);
return -1;
}
ntlm->haveContext = FALSE;
ntlm->haveInputBuffer = FALSE;
ZeroMemory(&ntlm->inputBuffer, sizeof(SecBuffer));
ZeroMemory(&ntlm->outputBuffer, sizeof(SecBuffer));
ntlm->fContextReq = 0;
/* NLA authentication flags */
ntlm->fContextReq |= ASC_REQ_MUTUAL_AUTH;
ntlm->fContextReq |= ASC_REQ_CONFIDENTIALITY;
ntlm->fContextReq |= ASC_REQ_CONNECTION;
ntlm->fContextReq |= ASC_REQ_USE_SESSION_KEY;
ntlm->fContextReq |= ASC_REQ_REPLAY_DETECT;
ntlm->fContextReq |= ASC_REQ_SEQUENCE_DETECT;
ntlm->fContextReq |= ASC_REQ_EXTENDED_ERROR;
return 1;
}
void test_ntlm_server_uninit(TEST_NTLM_SERVER* ntlm)
{
if (!ntlm)
return;
if (ntlm->outputBuffer[0].pvBuffer)
{
free(ntlm->outputBuffer[0].pvBuffer);
ntlm->outputBuffer[0].pvBuffer = NULL;
}
free(ntlm->identity.User);
free(ntlm->identity.Domain);
free(ntlm->identity.Password);
free(ntlm->ServicePrincipalName);
if (ntlm->table)
{
ntlm->table->FreeCredentialsHandle(&ntlm->credentials);
ntlm->table->FreeContextBuffer(ntlm->pPackageInfo);
ntlm->table->DeleteSecurityContext(&ntlm->context);
}
}
int test_ntlm_server_authenticate(TEST_NTLM_SERVER* ntlm)
{
SECURITY_STATUS status;
ntlm->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->inputBufferDesc.cBuffers = 1;
ntlm->inputBufferDesc.pBuffers = ntlm->inputBuffer;
ntlm->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
ntlm->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->outputBufferDesc.cBuffers = 1;
ntlm->outputBufferDesc.pBuffers = &ntlm->outputBuffer[0];
ntlm->outputBuffer[0].BufferType = SECBUFFER_TOKEN;
ntlm->outputBuffer[0].cbBuffer = ntlm->cbMaxToken;
ntlm->outputBuffer[0].pvBuffer = malloc(ntlm->outputBuffer[0].cbBuffer);
status = ntlm->table->AcceptSecurityContext(&ntlm->credentials,
ntlm->haveContext? &ntlm->context: NULL,
&ntlm->inputBufferDesc, ntlm->fContextReq, SECURITY_NATIVE_DREP, &ntlm->context,
&ntlm->outputBufferDesc, &ntlm->pfContextAttr, &ntlm->expiration);
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
{
SecPkgContext_AuthIdentity AuthIdentity;
SecPkgContext_AuthNtlmHash AuthNtlmHash;
ZeroMemory(&AuthIdentity, sizeof(SecPkgContext_AuthIdentity));
ZeroMemory(&AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash));
status = ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_AUTH_IDENTITY, &AuthIdentity);
if (status == SEC_E_OK)
{
if (strcmp(AuthIdentity.User, TEST_NTLM_USER) == 0)
{
CopyMemory(AuthNtlmHash.NtlmHash, TEST_NTLM_HASH, 16);
status = ntlm->table->SetContextAttributes(&ntlm->context,
SECPKG_ATTR_AUTH_NTLM_HASH, &AuthNtlmHash, sizeof(SecPkgContext_AuthNtlmHash));
}
}
if (ntlm->table->CompleteAuthToken)
status = ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc);
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
else if (status == SEC_I_COMPLETE_AND_CONTINUE)
status = SEC_I_CONTINUE_NEEDED;
}
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED))
{
fprintf(stderr, "AcceptSecurityContext status: %s (0x%04X)\n",
GetSecurityStatusString(status), status);
return -1; /* Access Denied */
}
ntlm->haveContext = TRUE;
return (status == SEC_I_CONTINUE_NEEDED) ? 1 : 0;
}
TEST_NTLM_SERVER* test_ntlm_server_new()
{
TEST_NTLM_SERVER* ntlm;
ntlm = (TEST_NTLM_SERVER*) calloc(1, sizeof(TEST_NTLM_SERVER));
if (!ntlm)
return NULL;
return ntlm;
}
void test_ntlm_server_free(TEST_NTLM_SERVER* ntlm)
{
if (!ntlm)
return;
test_ntlm_server_uninit(ntlm);
free(ntlm);
} }
int TestNTLM(int argc, char* argv[]) int TestNTLM(int argc, char* argv[])
{ {
if (test_ntlm_channel_binding_token() < 0) int status;
PSecBuffer pSecBuffer;
TEST_NTLM_CLIENT* client;
TEST_NTLM_SERVER* server;
/**
* Client Initialization
*/
client = test_ntlm_client_new();
status = test_ntlm_client_init(client, TEST_NTLM_USER, TEST_NTLM_DOMAIN, TEST_NTLM_PASSWORD);
if (status < 0)
{
printf("test_ntlm_client_init failure\n");
return -1; return -1;
}
/**
* Server Initialization
*/
server = test_ntlm_server_new();
status = test_ntlm_server_init(server);
if (status < 0)
{
printf("test_ntlm_server_init failure\n");
return -1;
}
/**
* Client -> Negotiate Message
*/
status = test_ntlm_client_authenticate(client);
if (status < 0)
{
printf("test_ntlm_client_authenticate failure\n");
return -1;
}
pSecBuffer = &(client->outputBuffer[0]);
fprintf(stderr, "NTLM_NEGOTIATE (length = %d):\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
/**
* Server <- Negotiate Message
* Server -> Challenge Message
*/
server->haveInputBuffer = TRUE;
server->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
server->inputBuffer[0].pvBuffer = pSecBuffer->pvBuffer;
server->inputBuffer[0].cbBuffer = pSecBuffer->cbBuffer;
status = test_ntlm_server_authenticate(server);
if (status < 0)
{
printf("test_ntlm_server_authenticate failure\n");
return -1;
}
pSecBuffer = &(server->outputBuffer[0]);
fprintf(stderr, "NTLM_CHALLENGE (length = %d):\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
/**
* Client <- Challenge Message
* Client -> Authenticate Message
*/
client->haveInputBuffer = TRUE;
client->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
client->inputBuffer[0].pvBuffer = pSecBuffer->pvBuffer;
client->inputBuffer[0].cbBuffer = pSecBuffer->cbBuffer;
status = test_ntlm_client_authenticate(client);
if (status < 0)
{
printf("test_ntlm_client_authenticate failure\n");
return -1;
}
pSecBuffer = &(client->outputBuffer[0]);
fprintf(stderr, "NTLM_AUTHENTICATE (length = %d):\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
/**
* Server <- Authenticate Message
*/
server->haveInputBuffer = TRUE;
server->inputBuffer[0].BufferType = SECBUFFER_TOKEN;
server->inputBuffer[0].pvBuffer = pSecBuffer->pvBuffer;
server->inputBuffer[0].cbBuffer = pSecBuffer->cbBuffer;
status = test_ntlm_server_authenticate(server);
if (status < 0)
{
printf("test_ntlm_server_authenticate failure\n");
return -1;
}
/**
* Cleanup & Termination
*/
test_ntlm_client_free(client);
test_ntlm_server_free(server);
return 0; return 0;
} }

View File

@ -273,7 +273,7 @@ int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
printf("EncryptMessage status: 0x%08X\n", status); printf("EncryptMessage status: 0x%08X\n", status);
printf("EncryptMessage output: cBuffers: %ld [0]: %lu / %lu [1]: %lu / %lu [2]: %lu / %lu [3]: %lu / %lu\n", Message.cBuffers, printf("EncryptMessage output: cBuffers: %d [0]: %u / %u [1]: %u / %u [2]: %u / %u [3]: %u / %u\n", Message.cBuffers,
Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType, Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType,
Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType, Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType,
Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType, Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType,
@ -342,7 +342,7 @@ int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
printf("DecryptMessage status: 0x%08X\n", status); printf("DecryptMessage status: 0x%08X\n", status);
printf("DecryptMessage output: cBuffers: %ld [0]: %lu / %lu [1]: %lu / %lu [2]: %lu / %lu [3]: %lu / %lu\n", Message.cBuffers, printf("DecryptMessage output: cBuffers: %d [0]: %u / %u [1]: %u / %u [2]: %u / %u [3]: %u / %u\n", Message.cBuffers,
Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType, Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType,
Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType, Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType,
Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType, Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType,
@ -351,7 +351,7 @@ int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
if (status != SEC_E_OK) if (status != SEC_E_OK)
return -1; return -1;
printf("Decrypted Message (%ld)\n", Message.pBuffers[1].cbBuffer); printf("Decrypted Message (%d)\n", Message.pBuffers[1].cbBuffer);
winpr_HexDump((BYTE*) Message.pBuffers[1].pvBuffer, Message.pBuffers[1].cbBuffer); winpr_HexDump((BYTE*) Message.pBuffers[1].pvBuffer, Message.pBuffers[1].cbBuffer);
if (memcmp(Message.pBuffers[1].pvBuffer, test_LastDummyMessage, sizeof(test_LastDummyMessage)) == 0) if (memcmp(Message.pBuffers[1].pvBuffer, test_LastDummyMessage, sizeof(test_LastDummyMessage)) == 0)
@ -522,9 +522,9 @@ static void* schannel_test_server_thread(void* arg)
else if (status == SEC_E_INCOMPLETE_MESSAGE) else if (status == SEC_E_INCOMPLETE_MESSAGE)
printf("AcceptSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n"); printf("AcceptSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
printf("Server cBuffers: %lu pBuffers[0]: %lu type: %lu\n", printf("Server cBuffers: %u pBuffers[0]: %u type: %u\n",
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType); SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType);
printf("Server Input cBuffers: %ld pBuffers[0]: %lu type: %lu pBuffers[1]: %lu type: %lu\n", SecBufferDesc_in.cBuffers, printf("Server Input cBuffers: %d pBuffers[0]: %u type: %u pBuffers[1]: %u type: %u\n", SecBufferDesc_in.cBuffers,
SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType, SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType,
SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
@ -543,7 +543,7 @@ static void* schannel_test_server_thread(void* arg)
if (pSecBuffer->cbBuffer > 0) if (pSecBuffer->cbBuffer > 0)
{ {
printf("Server > Client (%ld)\n", pSecBuffer->cbBuffer); printf("Server > Client (%d)\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))
@ -615,7 +615,7 @@ int dump_test_certificate_files()
int TestSchannel(int argc, char* argv[]) int TestSchannel(int argc, char* argv[])
{ {
int count; int count;
int index; DWORD index;
ALG_ID algId; ALG_ID algId;
HANDLE thread; HANDLE thread;
BYTE* lpTokenIn; BYTE* lpTokenIn;
@ -641,6 +641,8 @@ int TestSchannel(int argc, char* argv[])
SecPkgCred_CipherStrengths CipherStrengths; SecPkgCred_CipherStrengths CipherStrengths;
SecPkgCred_SupportedProtocols SupportedProtocols; SecPkgCred_SupportedProtocols SupportedProtocols;
return 0; /* disable by default - causes crash */
sspi_GlobalInit(); sspi_GlobalInit();
dump_test_certificate_files(); dump_test_certificate_files();
@ -713,7 +715,7 @@ int TestSchannel(int argc, char* argv[])
* 0x800C 0x800D 0x800E 0x2400 0xAA02 0xAE06 0x2200 0x2203 * 0x800C 0x800D 0x800E 0x2400 0xAA02 0xAE06 0x2200 0x2203
*/ */
printf("SupportedAlgs: %ld\n", SupportedAlgs.cSupportedAlgs); printf("SupportedAlgs: %d\n", SupportedAlgs.cSupportedAlgs);
for (index = 0; index < SupportedAlgs.cSupportedAlgs; index++) for (index = 0; index < SupportedAlgs.cSupportedAlgs; index++)
{ {
@ -734,7 +736,7 @@ int TestSchannel(int argc, char* argv[])
/* CipherStrengths: Minimum: 40 Maximum: 256 */ /* CipherStrengths: Minimum: 40 Maximum: 256 */
printf("CipherStrengths: Minimum: %ld Maximum: %ld\n", printf("CipherStrengths: Minimum: %d Maximum: %d\n",
CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength); CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength);
ZeroMemory(&SupportedProtocols, sizeof(SecPkgCred_SupportedProtocols)); ZeroMemory(&SupportedProtocols, sizeof(SecPkgCred_SupportedProtocols));
@ -748,7 +750,7 @@ int TestSchannel(int argc, char* argv[])
/* SupportedProtocols: 0x208A0 */ /* SupportedProtocols: 0x208A0 */
printf("SupportedProtocols: 0x%04lX\n", SupportedProtocols.grbitProtocol); printf("SupportedProtocols: 0x%04X\n", SupportedProtocols.grbitProtocol);
fContextReq = ISC_REQ_STREAM | fContextReq = ISC_REQ_STREAM |
ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
@ -781,7 +783,7 @@ int TestSchannel(int argc, char* argv[])
} }
g_ClientWait = TRUE; g_ClientWait = TRUE;
printf("NumberOfBytesRead: %ld\n", NumberOfBytesRead); printf("NumberOfBytesRead: %d\n", NumberOfBytesRead);
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
SecBuffer_in[0].pvBuffer = lpTokenIn; SecBuffer_in[0].pvBuffer = lpTokenIn;
@ -821,9 +823,9 @@ int TestSchannel(int argc, char* argv[])
else if (status == SEC_E_INCOMPLETE_MESSAGE) else if (status == SEC_E_INCOMPLETE_MESSAGE)
printf("InitializeSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n"); printf("InitializeSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
printf("Client Output cBuffers: %ld pBuffers[0]: %ld type: %ld\n", printf("Client Output cBuffers: %d pBuffers[0]: %d type: %d\n",
SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType); SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType);
printf("Client Input cBuffers: %ld pBuffers[0]: %ld type: %ld pBuffers[1]: %ld type: %ld\n", SecBufferDesc_in.cBuffers, printf("Client Input cBuffers: %d pBuffers[0]: %d type: %d pBuffers[1]: %d type: %d\n", SecBufferDesc_in.cBuffers,
SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType, SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType,
SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
@ -833,7 +835,7 @@ int TestSchannel(int argc, char* argv[])
if (pSecBuffer->cbBuffer > 0) if (pSecBuffer->cbBuffer > 0)
{ {
printf("Client > Server (%ld)\n", pSecBuffer->cbBuffer); printf("Client > Server (%d)\n", pSecBuffer->cbBuffer);
winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer);
if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))

View File

@ -59,7 +59,11 @@ BOOL TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformati
#endif #endif
#if !defined(_WIN32) || (defined(_WIN32) && (_WIN32_WINNT < 0x0600)) /* Windows Vista */ /*
* GetDynamicTimeZoneInformation is provided by the SDK if _WIN32_WINNT >= 0x0600 in SDKs above 7.1A
* and incorrectly if _WIN32_WINNT >= 0x0501 in older SDKs
*/
#if !defined(_WIN32) || (defined(_WIN32) && (defined(NTDDI_WIN8) && _WIN32_WINNT < 0x0600 || !defined(NTDDI_WIN8) && _WIN32_WINNT < 0x0501)) /* Windows Vista */
DWORD GetDynamicTimeZoneInformation(PDYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation) DWORD GetDynamicTimeZoneInformation(PDYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation)
{ {

View File

@ -285,7 +285,11 @@ BOOL ArrayList_Remove(wArrayList* arrayList, void* obj)
} }
if (found) if (found)
{
if (arrayList->object.fnObjectFree)
arrayList->object.fnObjectFree(arrayList->array[index]);
ret = ArrayList_Shift(arrayList, index, -1); ret = ArrayList_Shift(arrayList, index, -1);
}
if (arrayList->synchronized) if (arrayList->synchronized)
LeaveCriticalSection(&arrayList->lock); LeaveCriticalSection(&arrayList->lock);
@ -305,6 +309,8 @@ BOOL ArrayList_RemoveAt(wArrayList* arrayList, int index)
if ((index >= 0) && (index < arrayList->size)) if ((index >= 0) && (index < arrayList->size))
{ {
if (arrayList->object.fnObjectFree)
arrayList->object.fnObjectFree(arrayList->array[index]);
ret = ArrayList_Shift(arrayList, index, -1); ret = ArrayList_Shift(arrayList, index, -1);
} }

View File

@ -319,7 +319,7 @@ int WLog_ParseFilters()
{ {
char* p; char* p;
char* env; char* env;
int count; DWORD count;
DWORD nSize; DWORD nSize;
int status; int status;
char** strs; char** strs;