mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2025-06-03 00:00:20 +00:00
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:
commit
6f9a256c5c
@ -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})
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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})
|
||||||
|
|
||||||
|
316
channels/tsmf/client/gstreamer/tsmf_X11.c
Normal file
316
channels/tsmf/client/gstreamer/tsmf_X11.c
Normal 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
83
channels/tsmf/client/gstreamer/tsmf_platform.h
Normal file
83
channels/tsmf/client/gstreamer/tsmf_platform.h
Normal 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
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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})
|
||||||
|
118
cmake/FindGStreamer_0_10.cmake
Normal file
118
cmake/FindGStreamer_0_10.cmake
Normal 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)
|
||||||
|
|
153
cmake/FindGStreamer_1_0.cmake
Normal file
153
cmake/FindGStreamer_1_0.cmake
Normal 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
43
cmake/FindGlib.cmake
Normal 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)
|
||||||
|
|
@ -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
116
cmake/LibFindMacros.cmake
Normal 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)
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
63
include/freerdp/channels/tsmf.h
Normal file
63
include/freerdp/channels/tsmf.h
Normal 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
|
||||||
|
|
@ -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);
|
||||||
|
@ -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 */
|
||||||
|
@ -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
23
scripts/format_code.sh
Executable 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 $?
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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 =
|
||||||
|
@ -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 =
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
@ -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 */
|
||||||
|
@ -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 =
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
@ -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 */
|
||||||
|
289
winpr/libwinpr/sspi/sspi_export.c
Normal file
289
winpr/libwinpr/sspi/sspi_export.c
Normal 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);
|
||||||
|
}
|
1442
winpr/libwinpr/sspi/sspi_winpr.c
Normal file
1442
winpr/libwinpr/sspi/sspi_winpr.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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 */
|
@ -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}
|
||||||
|
8
winpr/libwinpr/sspi/test/TestCredSSP.c
Normal file
8
winpr/libwinpr/sspi/test/TestCredSSP.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/sspi.h>
|
||||||
|
|
||||||
|
int TestCredSSP(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user