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

This commit is contained in:
Benoit LeBlanc 2014-06-16 14:59:26 -04:00
commit 9b269d93b5
85 changed files with 8479 additions and 6111 deletions

View File

@ -417,9 +417,13 @@ set(FFMPEG_FEATURE_TYPE "RECOMMENDED")
set(FFMPEG_FEATURE_PURPOSE "multimedia")
set(FFMPEG_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
set(GSTREAMER_FEATURE_TYPE "RECOMMENDED")
set(GSTREAMER_FEATURE_PURPOSE "multimedia")
set(GSTREAMER_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL")
set(GSTREAMER_0_10_FEATURE_PURPOSE "multimedia")
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_PURPOSE "performance")
@ -442,14 +446,15 @@ if(WIN32)
set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_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")
endif()
if(APPLE)
set(DIRECTFB_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
set(GSTREAMER_FEATURE_TYPE "OPTIONAL")
set(GSTREAMER_1_0_FEATURE_TYPE "OPTIONAL")
set(X11_FEATURE_TYPE "OPTIONAL")
if(IOS)
set(X11_FEATURE_TYPE "DISABLED")
@ -457,7 +462,8 @@ if(APPLE)
set(PULSE_FEATURE_TYPE "DISABLED")
set(CUPS_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()
set(OPENSLES_FEATURE_TYPE "DISABLED")
endif()
@ -470,7 +476,8 @@ if(ANDROID)
set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_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")
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(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(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})

View File

@ -77,9 +77,11 @@ static void audin_server_select_format(audin_server_context* context, int client
static void audin_server_send_version(audin_server* audin, wStream* s)
{
ULONG written;
Stream_Write_UINT8(s, MSG_SNDIN_VERSION);
Stream_Write_UINT32(s, 1); /* Version (4 bytes) */
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
}
static BOOL audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length)
@ -101,6 +103,7 @@ static void audin_server_send_formats(audin_server* audin, wStream* s)
{
int i;
UINT32 nAvgBytesPerSec;
ULONG written;
Stream_SetPosition(s, 0);
Stream_Write_UINT8(s, MSG_SNDIN_FORMATS);
@ -131,7 +134,7 @@ static void audin_server_send_formats(audin_server* audin, wStream* s)
}
}
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
}
static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length)
@ -181,6 +184,8 @@ static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 le
static void audin_server_send_open(audin_server* audin, wStream* s)
{
ULONG written;
if (audin->context.selected_client_format < 0)
return;
@ -203,7 +208,7 @@ static void audin_server_send_open(audin_server* audin, wStream* s)
Stream_Write_UINT16(s, 16); /* wBitsPerSample */
Stream_Write_UINT16(s, 0); /* cbSize */
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
}
static BOOL audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length)

View File

@ -68,6 +68,7 @@ static int cliprdr_server_send_capabilities(CliprdrServerContext* context)
BOOL status;
UINT32 generalFlags;
CLIPRDR_HEADER header;
ULONG written;
printf("CliprdrServerSendCapabilities\n");
@ -96,7 +97,7 @@ static int cliprdr_server_send_capabilities(CliprdrServerContext* context)
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);
@ -108,6 +109,7 @@ static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context)
wStream* s;
BOOL status;
CLIPRDR_HEADER header;
ULONG written;
printf("CliprdrServerSendMonitorReady\n");
@ -123,7 +125,7 @@ static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context)
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);
@ -135,6 +137,7 @@ static int cliprdr_server_send_format_list_response(CliprdrServerContext* contex
wStream* s;
BOOL status;
CLIPRDR_HEADER header;
ULONG written;
printf("CliprdrServerSendFormatListResponse\n");
@ -150,7 +153,7 @@ static int cliprdr_server_send_format_list_response(CliprdrServerContext* contex
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);

View File

@ -3,6 +3,8 @@
* Dynamic Virtual Channel Manager
*
* Copyright 2010-2011 Vic Lee
* Copyright 2014 Thincast Technologies GmbH
* 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.
@ -21,6 +23,9 @@
#include "config.h"
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -28,45 +33,61 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <freerdp/addin.h>
#include "drdynvc_types.h"
#include "dvcman.h"
static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag)
static wListDictionary *cb_dict = NULL;
struct cb_value
{
void *fkt;
void *context;
};
static int dvcman_get_configuration(IWTSListener *pListener, void **ppPropertyBag)
{
if (!ppPropertyBag)
{
DEBUG_WARN("ppPropertyBag=%p", ppPropertyBag);
return 0;
}
*ppPropertyBag = NULL;
return 1;
}
static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
const char* pszChannelName, UINT32 ulFlags,
IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener)
static int dvcman_create_listener(IWTSVirtualChannelManager *pChannelMgr,
const char *pszChannelName, UINT32 ulFlags,
IWTSListenerCallback *pListenerCallback, IWTSListener **ppListener)
{
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
DVCMAN_LISTENER* listener;
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
DVCMAN_LISTENER *listener;
assert(dvcman);
if (dvcman->num_listeners < MAX_PLUGINS)
{
DEBUG_DVC("%d.%s.", dvcman->num_listeners, pszChannelName);
listener = (DVCMAN_LISTENER *) calloc(1, sizeof(DVCMAN_LISTENER));
listener = (DVCMAN_LISTENER*) malloc(sizeof(DVCMAN_LISTENER));
ZeroMemory(listener, sizeof(DVCMAN_LISTENER));
if (!listener)
{
DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
return 2;
}
listener->iface.GetConfiguration = dvcman_get_configuration;
listener->iface.pInterface = NULL;
listener->dvcman = dvcman;
listener->channel_name = _strdup(pszChannelName);
listener->flags = ulFlags;
listener->listener_callback = pListenerCallback;
if (ppListener)
*ppListener = (IWTSListener*) listener;
*ppListener = (IWTSListener *) listener;
dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*) listener;
dvcman->listeners[dvcman->num_listeners++] = (IWTSListener *) listener;
return 0;
}
else
@ -76,11 +97,11 @@ static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
}
}
static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, wMessage* pEvent)
static int dvcman_push_event(IWTSVirtualChannelManager *pChannelMgr, wMessage *pEvent)
{
int status;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
assert(dvcman);
status = drdynvc_push_event(dvcman->drdynvc, pEvent);
if (status == 0)
@ -95,9 +116,11 @@ static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, wMessage* p
return status;
}
static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, IWTSPlugin* pPlugin)
static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const char *name, IWTSPlugin *pPlugin)
{
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
DVCMAN *dvcman = ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->dvcman;
assert(pEntryPoints);
assert(dvcman);
if (dvcman->num_plugins < MAX_PLUGINS)
{
@ -113,15 +136,17 @@ static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const cha
}
}
IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name)
IWTSPlugin *dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const char *name)
{
int i;
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
DVCMAN *dvcman = ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->dvcman;
assert(pEntryPoints);
assert(dvcman);
for (i = 0; i < dvcman->num_plugins; i++)
{
if (dvcman->plugin_names[i] == name ||
strcmp(dvcman->plugin_names[i], name) == 0)
strcmp(dvcman->plugin_names[i], name) == 0)
{
return dvcman->plugins[i];
}
@ -130,27 +155,28 @@ IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* n
return NULL;
}
ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
ADDIN_ARGV *dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS *pEntryPoints)
{
return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->args;
assert(pEntryPoints);
return ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->args;
}
UINT32 dvcman_get_channel_id(IWTSVirtualChannel * channel)
UINT32 dvcman_get_channel_id(IWTSVirtualChannel *channel)
{
return ((DVCMAN_CHANNEL*) channel)->channel_id;
assert(channel);
return ((DVCMAN_CHANNEL *) channel)->channel_id;
}
IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
IWTSVirtualChannel *dvcman_find_channel_by_id(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId)
{
int index;
BOOL found = FALSE;
DVCMAN_CHANNEL* channel;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
DVCMAN_CHANNEL *channel;
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
assert(dvcman);
ArrayList_Lock(dvcman->channels);
index = 0;
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++);
channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, index++);
while (channel)
{
@ -160,25 +186,26 @@ IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChanne
break;
}
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++);
channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, index++);
}
ArrayList_Unlock(dvcman->channels);
return (found) ? ((IWTSVirtualChannel*) channel) : NULL;
return (found) ? ((IWTSVirtualChannel *) channel) : NULL;
}
void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName)
void *dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager *pChannelMgr, const char *ChannelName)
{
int i;
BOOL found = FALSE;
void* pInterface = NULL;
DVCMAN_LISTENER* listener;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
void *pInterface = NULL;
DVCMAN_LISTENER *listener;
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
assert(dvcman);
for (i = 0; i < dvcman->num_listeners; i++)
{
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
listener = (DVCMAN_LISTENER *) dvcman->listeners[i];
assert(listener);
if (strcmp(listener->channel_name, ChannelName) == 0)
{
@ -191,12 +218,16 @@ void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMg
return (found) ? pInterface : NULL;
}
IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
IWTSVirtualChannelManager *dvcman_new(drdynvcPlugin *plugin)
{
DVCMAN* dvcman;
DVCMAN *dvcman;
dvcman = (DVCMAN *) calloc(1,sizeof(DVCMAN));
dvcman = (DVCMAN*) malloc(sizeof(DVCMAN));
ZeroMemory(dvcman, sizeof(DVCMAN));
if (!dvcman)
{
DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
return NULL;
}
dvcman->iface.CreateListener = dvcman_create_listener;
dvcman->iface.PushEvent = dvcman_push_event;
@ -204,68 +235,68 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
dvcman->iface.GetChannelId = dvcman_get_channel_id;
dvcman->drdynvc = plugin;
dvcman->channels = ArrayList_New(TRUE);
return (IWTSVirtualChannelManager*) dvcman;
return (IWTSVirtualChannelManager *) dvcman;
}
int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args)
int dvcman_load_addin(IWTSVirtualChannelManager *pChannelMgr, ADDIN_ARGV *args)
{
DVCMAN_ENTRY_POINTS entryPoints;
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
assert(args);
fprintf(stderr, "Loading Dynamic Virtual Channel %s\n", args->argv[0]);
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(args->argv[0],
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
if (pDVCPluginEntry)
{
entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
entryPoints.iface.GetPlugin = dvcman_get_plugin;
entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
entryPoints.dvcman = (DVCMAN*) pChannelMgr;
entryPoints.dvcman = (DVCMAN *) pChannelMgr;
entryPoints.args = args;
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS *) &entryPoints);
}
return 0;
}
static void dvcman_channel_free(DVCMAN_CHANNEL* channel)
static void dvcman_channel_free(DVCMAN_CHANNEL *channel)
{
assert(channel);
if (channel->channel_callback)
channel->channel_callback->OnClose(channel->channel_callback);
if (channel->channel_name)
free(channel->channel_name);
free(channel);
}
void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
void dvcman_free(IWTSVirtualChannelManager *pChannelMgr)
{
int i;
int count;
IWTSPlugin* pPlugin;
DVCMAN_LISTENER* listener;
DVCMAN_CHANNEL* channel;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
IWTSPlugin *pPlugin;
DVCMAN_LISTENER *listener;
DVCMAN_CHANNEL *channel;
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
assert(dvcman);
ArrayList_Lock(dvcman->channels);
count = ArrayList_Count(dvcman->channels);
for (i = 0; i < count; i++)
{
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, i);
channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, i);
dvcman_channel_free(channel);
}
ArrayList_Unlock(dvcman->channels);
ArrayList_Free(dvcman->channels);
for (i = 0; i < dvcman->num_listeners; i++)
{
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
listener = (DVCMAN_LISTENER *) dvcman->listeners[i];
free(listener->channel_name);
free(listener);
}
@ -281,11 +312,12 @@ void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
free(dvcman);
}
int dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
int dvcman_init(IWTSVirtualChannelManager *pChannelMgr)
{
int i;
IWTSPlugin* pPlugin;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
IWTSPlugin *pPlugin;
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
assert(dvcman);
for (i = 0; i < dvcman->num_plugins; i++)
{
@ -298,83 +330,83 @@ int dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
return 0;
}
static int dvcman_write_channel(IWTSVirtualChannel* pChannel, UINT32 cbSize, BYTE* pBuffer, void* pReserved)
static int dvcman_write_channel(IWTSVirtualChannel *pChannel, UINT32 cbSize, BYTE *pBuffer, void *pReserved)
{
int status;
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
DVCMAN_CHANNEL *channel = (DVCMAN_CHANNEL *) pChannel;
assert(channel);
WaitForSingleObject(channel->dvc_chan_mutex, INFINITE);
status = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
ReleaseMutex(channel->dvc_chan_mutex);
return status;
}
static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
static int dvcman_close_channel_iface(IWTSVirtualChannel *pChannel)
{
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
DVCMAN* dvcman = channel->dvcman;
DVCMAN_CHANNEL *channel = (DVCMAN_CHANNEL *) pChannel;
DVCMAN *dvcman = channel->dvcman;
assert(channel);
assert(dvcman);
DEBUG_DVC("id=%d", channel->channel_id);
ArrayList_Remove(dvcman->channels, channel);
dvcman_channel_free(channel);
return 1;
}
int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName)
int dvcman_create_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, const char *ChannelName)
{
int i;
int bAccept;
DVCMAN_LISTENER* listener;
DVCMAN_CHANNEL* channel;
DrdynvcClientContext* context;
IWTSVirtualChannelCallback* pCallback;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
DVCMAN_LISTENER *listener;
DVCMAN_CHANNEL *channel;
DrdynvcClientContext *context;
IWTSVirtualChannelCallback *pCallback;
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
channel = (DVCMAN_CHANNEL *) calloc(1, sizeof(DVCMAN_CHANNEL));
if (!channel)
{
DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
return -1;
}
channel = (DVCMAN_CHANNEL*) malloc(sizeof(DVCMAN_CHANNEL));
ZeroMemory(channel, sizeof(DVCMAN_CHANNEL));
channel->dvcman = dvcman;
channel->channel_id = ChannelId;
channel->channel_name = _strdup(ChannelName);
for (i = 0; i < dvcman->num_listeners; i++)
{
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
listener = (DVCMAN_LISTENER *) dvcman->listeners[i];
assert(listener);
if (strcmp(listener->channel_name, ChannelName) == 0)
{
channel->iface.Write = dvcman_write_channel;
channel->iface.Close = dvcman_close_channel_iface;
channel->dvc_chan_mutex = CreateMutex(NULL, FALSE, NULL);
bAccept = 1;
pCallback = NULL;
assert(listener->listener_callback);
assert(listener->listener_callback->OnNewChannelConnection);
if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback,
(IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1)
(IWTSVirtualChannel *) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1)
{
DEBUG_DVC("listener %s created new channel %d",
listener->channel_name, channel->channel_id);
listener->channel_name, channel->channel_id);
channel->status = 0;
channel->channel_callback = pCallback;
channel->pInterface = listener->iface.pInterface;
assert(dvcman->drdynvc);
ArrayList_Add(dvcman->channels, channel);
context = dvcman->drdynvc->context;
IFCALL(context->OnChannelConnected, context, ChannelName, listener->iface.pInterface);
return 0;
}
else
{
DEBUG_WARN("channel rejected by plugin");
free(channel);
return 1;
}
@ -385,14 +417,14 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
return 1;
}
int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
int dvcman_close_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId)
{
DVCMAN_CHANNEL* channel;
IWTSVirtualChannel* ichannel;
DrdynvcClientContext* context;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
DVCMAN_CHANNEL *channel;
IWTSVirtualChannel *ichannel;
DrdynvcClientContext *context;
DVCMAN *dvcman = (DVCMAN *) pChannelMgr;
assert(dvcman);
channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
@ -408,25 +440,21 @@ int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelI
if (channel->status == 0)
{
assert(dvcman->drdynvc);
context = dvcman->drdynvc->context;
IFCALL(context->OnChannelDisconnected, context, channel->channel_name, channel->pInterface);
free(channel->channel_name);
DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId);
ichannel = (IWTSVirtualChannel*) channel;
ichannel = (IWTSVirtualChannel *) channel;
ichannel->Close(ichannel);
}
return 0;
}
int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length)
int dvcman_receive_channel_data_first(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, UINT32 length)
{
DVCMAN_CHANNEL* channel;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
DVCMAN_CHANNEL *channel;
channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
@ -438,16 +466,14 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UI
Stream_Free(channel->dvc_data, TRUE);
channel->dvc_data = Stream_New(NULL, length);
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, BYTE *data, UINT32 data_size)
{
int error = 0;
DVCMAN_CHANNEL* channel;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
DVCMAN_CHANNEL *channel;
channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
@ -471,15 +497,122 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 C
if (((size_t) Stream_GetPosition(channel->dvc_data)) >= Stream_Capacity(channel->dvc_data))
{
error = channel->channel_callback->OnDataReceived(channel->channel_callback,
Stream_Capacity(channel->dvc_data), Stream_Buffer(channel->dvc_data));
Stream_Capacity(channel->dvc_data), Stream_Buffer(channel->dvc_data));
Stream_Free(channel->dvc_data, TRUE);
channel->dvc_data = NULL;
}
}
else
{
assert(channel->channel_callback);
assert(channel->channel_callback->OnDataReceived);
error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data);
}
return error;
}
static void dump_callbacks(void)
{
wListDictionaryItem *cur;
DEBUG_DVC("Dumping all currently registered callbacks");
if (!cb_dict)
{
DEBUG_DVC("cb_dict=NULL");
return;
}
cur = cb_dict->head;
while (cur)
{
DEBUG_DVC("cb_dict %s:%p", cur->key, cur->value);
cur = cur->next;
}
}
void *get_callback_by_name(const char *name, void **context)
{
struct cb_value *rc;
if (!cb_dict)
{
DEBUG_WARN("'%s' not found, function list does not exist.",
name);
return NULL;
}
if (!ListDictionary_Contains(cb_dict, (void *)name))
{
DEBUG_WARN("'%s' not found", name);
return NULL;
}
rc = ListDictionary_GetItemValue(cb_dict, (void *)name);
DEBUG_DVC("'%s'=%p found", name, rc);
if (context)
*context = rc->context;
return rc->fkt;
}
static BOOL callback_key_cmp(void *a, void *b)
{
return strcmp(a, b) ? FALSE : TRUE;
}
void add_callback_by_name(const char *name, void *fkt, void *context)
{
struct cb_value *value = calloc(1, sizeof(struct cb_value));
if (!value)
{
DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno);
assert(FALSE);
return;
}
if (!cb_dict)
{
DEBUG_DVC("Function list is empty, allocating new.");
cb_dict = ListDictionary_New(TRUE);
ListDictionary_KeyObject(cb_dict)->fnObjectEquals = callback_key_cmp;
}
value->fkt = fkt;
value->context = context;
DEBUG_DVC("Adding '%s'=%p to function list.", name, fkt);
ListDictionary_Add(cb_dict, (void *)name, value);
dump_callbacks();
}
void remove_callback_by_name(const char *name, void *context)
{
if (!cb_dict)
{
DEBUG_WARN("trying to remove '%s', but function list does not exist.",
name);
return;
}
if (!ListDictionary_Contains(cb_dict, (void *)name))
{
DEBUG_WARN("trying to remove '%s', which is not in function list.",
name);
return;
}
DEBUG_DVC("Removing '%s' from function list.", name);
ListDictionary_Remove(cb_dict, (void *)name);
if (ListDictionary_Count(cb_dict) < 1)
{
DEBUG_DVC("Function list is empty, freeing resources.");
ListDictionary_Free(cb_dict);
cb_dict = NULL;
}
dump_callbacks();
}

View File

@ -34,6 +34,7 @@ static int rdpdr_server_send_announce_request(RdpdrServerContext* context)
wStream* s;
BOOL status;
RDPDR_HEADER header;
ULONG written;
printf("RdpdrServerSendAnnounceRequest\n");
@ -51,7 +52,7 @@ static int rdpdr_server_send_announce_request(RdpdrServerContext* context)
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);
@ -295,6 +296,7 @@ static int rdpdr_server_send_core_capability_request(RdpdrServerContext* context
BOOL status;
RDPDR_HEADER header;
UINT16 numCapabilities;
ULONG written;
printf("RdpdrServerSendCoreCapabilityRequest\n");
@ -319,7 +321,7 @@ static int rdpdr_server_send_core_capability_request(RdpdrServerContext* context
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);
@ -376,6 +378,7 @@ static int rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
wStream* s;
BOOL status;
RDPDR_HEADER header;
ULONG written;
printf("RdpdrServerSendClientIdConfirm\n");
@ -393,7 +396,7 @@ static int rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);
@ -457,6 +460,7 @@ static int rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
wStream* s;
BOOL status;
RDPDR_HEADER header;
ULONG written;
printf("%s\n", __FUNCTION__);
@ -470,7 +474,7 @@ static int rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), &written);
Stream_Free(s, TRUE);

View File

@ -36,6 +36,7 @@ static BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
int pos;
UINT16 i;
BOOL status;
ULONG written;
Stream_Write_UINT8(s, SNDC_FORMATS);
Stream_Write_UINT8(s, 0);
@ -74,7 +75,7 @@ static BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0);
return status;
@ -361,6 +362,7 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
BOOL status;
AUDIO_FORMAT* format;
int tbytes_per_frame;
ULONG written;
wStream* s = context->priv->rdpsnd_pdu;
format = &context->client_formats[context->selected_client_format];
@ -422,7 +424,7 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
Stream_Seek(s, 3); /* bPad */
Stream_Write(s, src, 4);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
if (!status)
goto out;
Stream_SetPosition(s, 0);
@ -435,7 +437,7 @@ static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
if (fill_size > 0)
Stream_Zero(s, fill_size);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
out:
Stream_SetPosition(s, 0);
@ -476,6 +478,7 @@ static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int
{
int pos;
BOOL status;
ULONG written;
wStream* s = context->priv->rdpsnd_pdu;
Stream_Write_UINT8(s, SNDC_SETVOLUME);
@ -489,7 +492,7 @@ static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0);
return status;
@ -499,6 +502,7 @@ static BOOL rdpsnd_server_close(RdpsndServerContext* context)
{
int pos;
BOOL status;
ULONG written;
wStream* s = context->priv->rdpsnd_pdu;
if (context->selected_client_format < 0)
@ -520,7 +524,7 @@ static BOOL rdpsnd_server_close(RdpsndServerContext* context)
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_SetPosition(s, 0);
return status;

View File

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

View File

@ -24,7 +24,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <winpr/crt.h>
@ -41,225 +40,194 @@ typedef struct _TSMFALSAAudioDevice
ITSMFAudioDevice iface;
char device[32];
snd_pcm_t* out_handle;
snd_pcm_t *out_handle;
UINT32 source_rate;
UINT32 actual_rate;
UINT32 source_channels;
UINT32 actual_channels;
UINT32 bytes_per_sample;
FREERDP_DSP_CONTEXT* dsp_context;
FREERDP_DSP_CONTEXT *dsp_context;
} TSMFAlsaAudioDevice;
static BOOL tsmf_alsa_open_device(TSMFAlsaAudioDevice* alsa)
static BOOL tsmf_alsa_open_device(TSMFAlsaAudioDevice *alsa)
{
int error;
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);
return FALSE;
}
DEBUG_DVC("open device %s", alsa->device);
DEBUG_TSMF("open device %s", alsa->device);
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;
if (!device)
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
if(!device)
{
if (!alsa->device[0])
if(!alsa->device[0])
strncpy(alsa->device, "default", sizeof(alsa->device));
}
else
{
strncpy(alsa->device, device, sizeof(alsa->device));
}
return tsmf_alsa_open_device(alsa);
}
static BOOL tsmf_alsa_set_format(ITSMFAudioDevice* audio,
UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample)
static BOOL tsmf_alsa_set_format(ITSMFAudioDevice *audio,
UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample)
{
int error;
snd_pcm_uframes_t frames;
snd_pcm_hw_params_t* hw_params;
snd_pcm_sw_params_t* sw_params;
TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
if (!alsa->out_handle)
snd_pcm_hw_params_t *hw_params;
snd_pcm_sw_params_t *sw_params;
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
if(!alsa->out_handle)
return FALSE;
snd_pcm_drop(alsa->out_handle);
alsa->actual_rate = alsa->source_rate = sample_rate;
alsa->actual_channels = alsa->source_channels = channels;
alsa->bytes_per_sample = bits_per_sample / 8;
error = snd_pcm_hw_params_malloc(&hw_params);
if (error < 0)
if(error < 0)
{
DEBUG_WARN("snd_pcm_hw_params_malloc failed");
return FALSE;
}
snd_pcm_hw_params_any(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);
snd_pcm_hw_params_set_format(alsa->out_handle, hw_params,
SND_PCM_FORMAT_S16_LE);
SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params,
&alsa->actual_rate, NULL);
&alsa->actual_rate, NULL);
snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params,
&alsa->actual_channels);
&alsa->actual_channels);
frames = sample_rate;
snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params,
&frames);
&frames);
snd_pcm_hw_params(alsa->out_handle, hw_params);
snd_pcm_hw_params_free(hw_params);
error = snd_pcm_sw_params_malloc(&sw_params);
if (error < 0)
if(error < 0)
{
DEBUG_WARN("snd_pcm_sw_params_malloc");
return FALSE;
}
snd_pcm_sw_params_current(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_free(sw_params);
snd_pcm_prepare(alsa->out_handle);
DEBUG_DVC("sample_rate %d channels %d bits_per_sample %d",
sample_rate, channels, bits_per_sample);
DEBUG_DVC("hardware buffer %d frames", (int)frames);
if ((alsa->actual_rate != alsa->source_rate) ||
(alsa->actual_channels != alsa->source_channels))
DEBUG_TSMF("sample_rate %d channels %d bits_per_sample %d",
sample_rate, channels, bits_per_sample);
DEBUG_TSMF("hardware buffer %d frames", (int)frames);
if((alsa->actual_rate != alsa->source_rate) ||
(alsa->actual_channels != alsa->source_channels))
{
DEBUG_DVC("actual rate %d / channel %d is different "
"from source rate %d / channel %d, resampling required.",
alsa->actual_rate, alsa->actual_channels,
alsa->source_rate, alsa->source_channels);
DEBUG_TSMF("actual rate %d / channel %d is different "
"from source rate %d / channel %d, resampling required.",
alsa->actual_rate, alsa->actual_channels,
alsa->source_rate, alsa->source_channels);
}
return TRUE;
}
static BOOL tsmf_alsa_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size)
static BOOL tsmf_alsa_play(ITSMFAudioDevice *audio, BYTE *data, UINT32 data_size)
{
int len;
int error;
int frames;
BYTE* end;
BYTE* src;
BYTE* pindex;
BYTE *end;
BYTE *src;
BYTE *pindex;
int rbytes_per_frame;
int sbytes_per_frame;
TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
DEBUG_DVC("data_size %d", data_size);
if (alsa->out_handle)
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
DEBUG_TSMF("data_size %d", data_size);
if(alsa->out_handle)
{
sbytes_per_frame = alsa->source_channels * alsa->bytes_per_sample;
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_sample;
if ((alsa->source_rate == alsa->actual_rate) &&
(alsa->source_channels == alsa->actual_channels))
if((alsa->source_rate == alsa->actual_rate) &&
(alsa->source_channels == alsa->actual_channels))
{
src = data;
}
else
{
alsa->dsp_context->resample(alsa->dsp_context, data, alsa->bytes_per_sample,
alsa->source_channels, alsa->source_rate, data_size / sbytes_per_frame,
alsa->actual_channels, alsa->actual_rate);
alsa->source_channels, alsa->source_rate, data_size / sbytes_per_frame,
alsa->actual_channels, alsa->actual_rate);
frames = alsa->dsp_context->resampled_frames;
DEBUG_DVC("resampled %d frames at %d to %d frames at %d",
data_size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate);
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 = frames * rbytes_per_frame;
src = alsa->dsp_context->resampled_buffer;
}
pindex = src;
end = pindex + data_size;
while (pindex < end)
while(pindex < end)
{
len = end - pindex;
frames = len / rbytes_per_frame;
error = snd_pcm_writei(alsa->out_handle, pindex, frames);
if (error == -EPIPE)
if(error == -EPIPE)
{
snd_pcm_recover(alsa->out_handle, error, 0);
error = 0;
}
else if (error < 0)
{
DEBUG_DVC("error len %d", error);
snd_pcm_close(alsa->out_handle);
alsa->out_handle = 0;
tsmf_alsa_open_device(alsa);
else
if(error < 0)
{
DEBUG_TSMF("error len %d", error);
snd_pcm_close(alsa->out_handle);
alsa->out_handle = 0;
tsmf_alsa_open_device(alsa);
break;
}
DEBUG_TSMF("%d frames played.", error);
if(error == 0)
break;
}
DEBUG_DVC("%d frames played.", error);
if (error == 0)
break;
pindex += error * rbytes_per_frame;
}
}
free(data);
return TRUE;
}
static UINT64 tsmf_alsa_get_latency(ITSMFAudioDevice* audio)
static UINT64 tsmf_alsa_get_latency(ITSMFAudioDevice *audio)
{
UINT64 latency = 0;
snd_pcm_sframes_t frames = 0;
TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
if (alsa->out_handle && alsa->actual_rate > 0 &&
snd_pcm_delay(alsa->out_handle, &frames) == 0 &&
frames > 0)
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
if(alsa->out_handle && alsa->actual_rate > 0 &&
snd_pcm_delay(alsa->out_handle, &frames) == 0 &&
frames > 0)
{
latency = ((UINT64)frames) * 10000000LL / (UINT64) alsa->actual_rate;
}
return latency;
}
static void tsmf_alsa_flush(ITSMFAudioDevice* audio)
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;
DEBUG_DVC("");
if (alsa->out_handle)
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
DEBUG_TSMF("");
if(alsa->out_handle)
{
snd_pcm_drain(alsa->out_handle);
snd_pcm_close(alsa->out_handle);
}
freerdp_dsp_context_free(alsa->dsp_context);
free(alsa);
}
@ -268,21 +236,17 @@ static void tsmf_alsa_free(ITSMFAudioDevice* audio)
#define freerdp_tsmf_client_audio_subsystem_entry alsa_freerdp_tsmf_client_audio_subsystem_entry
#endif
ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)
ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)
{
TSMFAlsaAudioDevice* alsa;
alsa = (TSMFAlsaAudioDevice*) malloc(sizeof(TSMFAlsaAudioDevice));
TSMFAlsaAudioDevice *alsa;
alsa = (TSMFAlsaAudioDevice *) malloc(sizeof(TSMFAlsaAudioDevice));
ZeroMemory(alsa, sizeof(TSMFAlsaAudioDevice));
alsa->iface.Open = tsmf_alsa_open;
alsa->iface.SetFormat = tsmf_alsa_set_format;
alsa->iface.Play = tsmf_alsa_play;
alsa->iface.GetLatency = tsmf_alsa_get_latency;
alsa->iface.Flush = tsmf_alsa_flush;
alsa->iface.Free = tsmf_alsa_free;
alsa->dsp_context = freerdp_dsp_context_new();
return (ITSMFAudioDevice*) alsa;
return (ITSMFAudioDevice *) alsa;
}

View File

@ -32,8 +32,6 @@
#include <libavcodec/avcodec.h>
#include <pthread.h>
#include "tsmf_constants.h"
#include "tsmf_decoder.h"
@ -59,55 +57,47 @@ typedef struct _TSMFFFmpegDecoder
#else
enum AVCodecID codec_id;
#endif
AVCodecContext* codec_context;
AVCodec* codec;
AVFrame* frame;
AVCodecContext *codec_context;
AVCodec *codec;
AVFrame *frame;
int prepared;
BYTE* decoded_data;
BYTE *decoded_data;
UINT32 decoded_size;
UINT32 decoded_size_max;
} 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);
if (!mdecoder->codec_context)
if(!mdecoder->codec_context)
{
DEBUG_WARN("avcodec_alloc_context failed.");
return FALSE;
}
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->height = media_type->Height;
mdecoder->codec_context->bit_rate = media_type->BitRate;
mdecoder->codec_context->time_base.den = media_type->SamplesPerSecond.Numerator;
mdecoder->codec_context->time_base.num = media_type->SamplesPerSecond.Denominator;
mdecoder->frame = avcodec_alloc_frame();
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->bit_rate = media_type->BitRate;
mdecoder->codec_context->channels = media_type->Channels;
mdecoder->codec_context->block_align = media_type->BlockAlign;
#if LIBAVCODEC_VERSION_MAJOR < 55
#ifdef AV_CPU_FLAG_SSE2
mdecoder->codec_context->dsp_mask = AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2;
@ -125,43 +115,38 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED
av_set_cpu_flags_mask(FF_MM_SSE2 | FF_MM_MMX2);
#endif
#endif /* LIBAVCODEC_VERSION_MAJOR < 55 */
return TRUE;
}
static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type)
{
BYTE* p;
BYTE *p;
UINT32 size;
const BYTE* s;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
const BYTE *s;
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id);
if (!mdecoder->codec)
if(!mdecoder->codec)
{
DEBUG_WARN("avcodec_find_decoder failed.");
return FALSE;
}
mdecoder->codec_context->codec_id = mdecoder->codec_id;
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;
}
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))
return FALSE;
}
if(media_type->ExtraData)
{
if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type))
return FALSE;
}
if (media_type->ExtraData)
{
if (media_type->SubType == TSMF_SUB_TYPE_AVC1 &&
media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO)
if(media_type->SubType == TSMF_SUB_TYPE_AVC1 &&
media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO)
{
/* The extradata format that FFmpeg uses is following CodecPrivate in Matroska.
See http://haali.su/mkv/codecs.pdf */
@ -194,33 +179,27 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
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;
return TRUE;
}
static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder* decoder)
static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder *decoder)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
if (avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0)
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0)
{
DEBUG_WARN("avcodec_open2 failed.");
return FALSE;
}
mdecoder->prepared = 1;
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;
switch (media_type->MajorType)
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
switch(media_type->MajorType)
{
case TSMF_MAJOR_TYPE_VIDEO:
mdecoder->media_type = AVMEDIA_TYPE_VIDEO;
@ -231,7 +210,7 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* medi
default:
return FALSE;
}
switch (media_type->SubType)
switch(media_type->SubType)
{
case TSMF_SUB_TYPE_WVC1:
mdecoder->codec_id = CODEC_ID_VC1;
@ -259,7 +238,7 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* medi
/* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data
is at the end of it. See
http://msdn.microsoft.com/en-us/library/dd757806.aspx */
if (media_type->ExtraData)
if(media_type->ExtraData)
{
media_type->ExtraData += 12;
media_type->ExtraDataSize -= 12;
@ -275,118 +254,108 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* medi
default:
return FALSE;
}
if (!tsmf_ffmpeg_init_context(decoder))
if(!tsmf_ffmpeg_init_context(decoder))
return FALSE;
if (!tsmf_ffmpeg_init_stream(decoder, media_type))
if(!tsmf_ffmpeg_init_stream(decoder, media_type))
return FALSE;
if (!tsmf_ffmpeg_prepare(decoder))
if(!tsmf_ffmpeg_prepare(decoder))
return FALSE;
return TRUE;
}
static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size, UINT32 extensions)
static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
int decoded;
int len;
AVFrame* frame;
AVFrame *frame;
BOOL ret = TRUE;
#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);
#else
{
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = (BYTE*) data;
pkt.data = (BYTE *) data;
pkt.size = data_size;
if (extensions & TSMM_SAMPLE_EXT_CLEANPOINT)
if(extensions & TSMM_SAMPLE_EXT_CLEANPOINT)
pkt.flags |= AV_PKT_FLAG_KEY;
len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt);
}
#endif
if (len < 0)
if(len < 0)
{
DEBUG_WARN("data_size %d, avcodec_decode_video failed (%d)", data_size, len);
ret = FALSE;
}
else if (!decoded)
{
DEBUG_WARN("data_size %d, no frame is decoded.", data_size);
ret = FALSE;
}
else
{
DEBUG_DVC("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d "
"pix_fmt %d width %d height %d",
mdecoder->frame->linesize[0], mdecoder->frame->linesize[1],
mdecoder->frame->linesize[2], mdecoder->frame->linesize[3],
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->decoded_data = malloc(mdecoder->decoded_size);
ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size);
frame = avcodec_alloc_frame();
avpicture_fill((AVPicture*) frame, mdecoder->decoded_data,
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
av_picture_copy((AVPicture*) frame, (AVPicture*) mdecoder->frame,
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
av_free(frame);
}
if(!decoded)
{
DEBUG_WARN("data_size %d, no frame is decoded.", data_size);
ret = FALSE;
}
else
{
DEBUG_TSMF("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d "
"pix_fmt %d width %d height %d",
mdecoder->frame->linesize[0], mdecoder->frame->linesize[1],
mdecoder->frame->linesize[2], mdecoder->frame->linesize[3],
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->decoded_data = malloc(mdecoder->decoded_size);
ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size);
frame = avcodec_alloc_frame();
avpicture_fill((AVPicture *) frame, mdecoder->decoded_data,
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
av_picture_copy((AVPicture *) frame, (AVPicture *) mdecoder->frame,
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
av_free(frame);
}
return ret;
}
static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size, UINT32 extensions)
static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
int len;
int frame_size;
UINT32 src_size;
const BYTE* src;
BYTE* dst;
const BYTE *src;
BYTE *dst;
int dst_offset;
#if 0
LLOGLN(0, ("tsmf_ffmpeg_decode_audio: data_size %d", data_size));
int i;
for (i = 0; i < data_size; i++)
for(i = 0; i < data_size; i++)
{
LLOG(0, ("%02X ", data[i]));
if (i % 16 == 15)
if(i % 16 == 15)
LLOG(0, ("\n"));
}
LLOG(0, ("\n"));
#endif
if (mdecoder->decoded_size_max == 0)
if(mdecoder->decoded_size_max == 0)
mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16;
mdecoder->decoded_data = malloc(mdecoder->decoded_size_max);
ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size_max);
/* align the memory for SSE2 needs */
dst = (BYTE*) (((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F);
dst = (BYTE *)(((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F);
dst_offset = dst - mdecoder->decoded_data;
src = data;
src_size = data_size;
while (src_size > 0)
while(src_size > 0)
{
/* Ensure enough space for decoding */
if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE)
if(mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE)
{
mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16;
mdecoder->decoded_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max);
dst = (BYTE*) (((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
if (dst - mdecoder->decoded_data != dst_offset)
dst = (BYTE *)(((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
if(dst - mdecoder->decoded_data != dst_offset)
{
/* re-align the memory if the alignment has changed after realloc */
memmove(dst, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
@ -394,72 +363,64 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
}
dst += 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)
len = avcodec_decode_audio2(mdecoder->codec_context,
(int16_t*) dst, &frame_size, src, src_size);
(int16_t *) dst, &frame_size, src, src_size);
#else
{
AVFrame* decoded_frame = avcodec_alloc_frame();
AVFrame *decoded_frame = avcodec_alloc_frame();
int got_frame = 0;
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = (BYTE*) src;
pkt.data = (BYTE *) src;
pkt.size = src_size;
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,
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);
}
av_free(decoded_frame);
}
#endif
if (len <= 0 || frame_size <= 0)
if(len <= 0 || frame_size <= 0)
{
DEBUG_WARN("error decoding");
break;
}
src += len;
src_size -= len;
mdecoder->decoded_size += frame_size;
dst += frame_size;
}
if (mdecoder->decoded_size == 0)
if(mdecoder->decoded_size == 0)
{
free(mdecoder->decoded_data);
mdecoder->decoded_data = NULL;
}
else if (dst_offset)
{
/* move the aligned decoded data to original place */
memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
}
DEBUG_DVC("data_size %d decoded_size %d",
data_size, mdecoder->decoded_size);
else
if(dst_offset)
{
/* move the aligned decoded data to original place */
memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
}
DEBUG_TSMF("data_size %d decoded_size %d",
data_size, mdecoder->decoded_size);
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;
if (mdecoder->decoded_data)
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(mdecoder->decoded_data)
{
free(mdecoder->decoded_data);
mdecoder->decoded_data = NULL;
}
mdecoder->decoded_size = 0;
switch (mdecoder->media_type)
switch(mdecoder->media_type)
{
case AVMEDIA_TYPE_VIDEO:
return tsmf_ffmpeg_decode_video(decoder, data, data_size, extensions);
@ -471,40 +432,35 @@ static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE* data, UINT32 d
}
}
static BYTE* tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32* size)
static BYTE *tsmf_ffmpeg_get_decoded_data(ITSMFDecoder *decoder, UINT32 *size)
{
BYTE* buf;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
BYTE *buf;
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
*size = mdecoder->decoded_size;
buf = mdecoder->decoded_data;
mdecoder->decoded_data = NULL;
mdecoder->decoded_size = 0;
return buf;
}
static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder* decoder)
static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder *decoder)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
switch (mdecoder->codec_context->pix_fmt)
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
switch(mdecoder->codec_context->pix_fmt)
{
case PIX_FMT_YUV420P:
return RDP_PIXFMT_I420;
default:
DEBUG_WARN("unsupported pixel format %u",
mdecoder->codec_context->pix_fmt);
mdecoder->codec_context->pix_fmt);
return (UINT32) -1;
}
}
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;
if (mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0)
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0)
{
*width = mdecoder->codec_context->width;
*height = mdecoder->codec_context->height;
@ -516,25 +472,21 @@ 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;
if (mdecoder->frame)
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(mdecoder->frame)
av_free(mdecoder->frame);
if (mdecoder->decoded_data)
if(mdecoder->decoded_data)
free(mdecoder->decoded_data);
if (mdecoder->codec_context)
if(mdecoder->codec_context)
{
if (mdecoder->prepared)
if(mdecoder->prepared)
avcodec_close(mdecoder->codec_context);
if (mdecoder->codec_context->extradata)
if(mdecoder->codec_context->extradata)
free(mdecoder->codec_context->extradata);
av_free(mdecoder->codec_context);
}
free(decoder);
}
@ -544,27 +496,22 @@ static BOOL initialized = FALSE;
#define freerdp_tsmf_client_decoder_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry
#endif
ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
ITSMFDecoder *freerdp_tsmf_client_decoder_subsystem_entry(void)
{
TSMFFFmpegDecoder* decoder;
if (!initialized)
TSMFFFmpegDecoder *decoder;
if(!initialized)
{
avcodec_register_all();
initialized = TRUE;
}
fprintf(stderr, "TSMFDecoderEntry FFMPEG\n");
decoder = (TSMFFFmpegDecoder*) malloc(sizeof(TSMFFFmpegDecoder));
decoder = (TSMFFFmpegDecoder *) malloc(sizeof(TSMFFFmpegDecoder));
ZeroMemory(decoder, sizeof(TSMFFFmpegDecoder));
decoder->iface.SetFormat = tsmf_ffmpeg_set_format;
decoder->iface.Decode = tsmf_ffmpeg_decode;
decoder->iface.GetDecodedData = tsmf_ffmpeg_get_decoded_data;
decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format;
decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension;
decoder->iface.Free = tsmf_ffmpeg_free;
return (ITSMFDecoder*) decoder;
return (ITSMFDecoder *) decoder;
}

View File

@ -7,7 +7,7 @@
# 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
# 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,
@ -17,26 +17,60 @@
define_channel_client_subsystem("tsmf" "gstreamer" "decoder")
set(${MODULE_PREFIX}_SRCS
tsmf_gstreamer.c)
if(NOT GSTREAMER_0_10_FOUND AND NOT GSTREAMER_1_0_FOUND)
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(${GSTREAMER_INCLUDE_DIRS})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-utils)
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-utils)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
${GSTREAMER_LIBRARIES}
gstapp-0.10
gstinterfaces-0.10
Xrandr X11 Xext)
${LIBS})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})

View File

@ -0,0 +1,316 @@
/*
* FreeRDP: A Remote Desktop Protocol Implementation
* Video Redirection Virtual Channel - GStreamer Decoder X11 specifics
*
* (C) Copyright 2014 Thincast Technologies GmbH
* (C) Copyright 2014 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <assert.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <fcntl.h>
#include <winpr/thread.h>
#include <gst/gst.h>
#if GST_VERSION_MAJOR > 0
#include <gst/video/videooverlay.h>
#else
#include <gst/interfaces/xoverlay.h>
#endif
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/shape.h>
#include <freerdp/channels/tsmf.h>
#include "tsmf_platform.h"
#include "tsmf_constants.h"
#include "tsmf_decoder.h"
#if !defined(WITH_XEXT)
#warning "Building TSMF without shape extension support"
#endif
struct X11Handle
{
int shmid;
int *xfwin;
#if defined(WITH_XEXT)
BOOL has_shape;
#endif
Display *disp;
Window subwin;
};
static const char *get_shm_id()
{
static char shm_id[64];
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId());
return shm_id;
}
const char *tsmf_platform_get_video_sink(void)
{
return "xvimagesink";
}
const char *tsmf_platform_get_audio_sink(void)
{
return "autoaudiosink";
}
int tsmf_platform_create(TSMFGstreamerDecoder *decoder)
{
struct X11Handle *hdl;
assert(decoder);
assert(!decoder->platform);
hdl = malloc(sizeof(struct X11Handle));
if (!hdl)
{
DEBUG_WARN("%s: Could not allocate handle.", __func__);
return -1;
}
memset(hdl, 0, sizeof(struct X11Handle));
decoder->platform = hdl;
hdl->shmid = shm_open(get_shm_id(), O_RDWR, PROT_READ | PROT_WRITE);;
if (hdl->shmid < 0)
{
DEBUG_WARN("%s: failed to get access to shared memory - shmget()",
__func__);
return -2;
}
else
hdl->xfwin = mmap(0, sizeof(void *), PROT_READ | PROT_WRITE, MAP_SHARED, hdl->shmid, 0);
if (hdl->xfwin == (int *)-1)
{
DEBUG_WARN("%s: shmat failed!", __func__);
return -3;
}
hdl->disp = XOpenDisplay(NULL);
if (!hdl->disp)
{
DEBUG_WARN("Failed to open display");
return -4;
}
return 0;
}
int tsmf_platform_set_format(TSMFGstreamerDecoder *decoder)
{
assert(decoder);
if (decoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
{
}
return 0;
}
int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder)
{
assert(decoder);
assert(decoder->pipe);
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(decoder->pipe));
if (!bus)
{
DEBUG_WARN("gst_pipeline_get_bus failed!");
return 1;
}
return 0;
}
int tsmf_platform_free(TSMFGstreamerDecoder *decoder)
{
struct X11Handle *hdl = decoder->platform;
if (!hdl)
return -1;
if (hdl->disp)
XCloseDisplay(hdl->disp);
if (hdl->xfwin)
munmap(0, sizeof(void *));
if (hdl->shmid >= 0)
close(hdl->shmid);
free(hdl);
decoder->platform = NULL;
return 0;
}
int tsmf_window_create(TSMFGstreamerDecoder *decoder)
{
if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
{
decoder->ready = TRUE;
return -3;
}
else
{
#if GST_VERSION_MAJOR > 0
GstVideoOverlay *overlay = GST_VIDEO_OVERLAY(decoder->outsink);
#else
GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink);
#endif
struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
assert(decoder);
assert(hdl);
if (!hdl->subwin)
{
int event, error;
hdl->subwin = XCreateSimpleWindow(hdl->disp, *(int *)hdl->xfwin, 0, 0, 1, 1, 0, 0, 0);
if (!hdl->subwin)
{
DEBUG_WARN("Could not create subwindow!");
}
XMapWindow(hdl->disp, hdl->subwin);
XSync(hdl->disp, FALSE);
#if GST_VERSION_MAJOR > 0
gst_video_overlay_set_window_handle(overlay, hdl->subwin);
#else
gst_x_overlay_set_window_handle(overlay, hdl->subwin);
#endif
decoder->ready = TRUE;
#if defined(WITH_XEXT)
hdl->has_shape = XShapeQueryExtension(hdl->disp, &event, &error);
#endif
}
#if GST_VERSION_MAJOR > 0
gst_video_overlay_handle_events(overlay, TRUE);
#else
gst_x_overlay_handle_events(overlay, TRUE);
#endif
return 0;
}
}
int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y, int width,
int height, int nr_rects, RDP_RECT *rects)
{
if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
return -3;
else
{
#if GST_VERSION_MAJOR > 0
GstVideoOverlay *overlay = GST_VIDEO_OVERLAY(decoder->outsink);
#else
GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink);
#endif
struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
DEBUG_TSMF("resize: x=%d, y=%d, w=%d, h=%d", x, y, width, height);
assert(decoder);
assert(hdl);
#if GST_VERSION_MAJOR > 0
if (!gst_video_overlay_set_render_rectangle(overlay, 0, 0, width, height))
{
DEBUG_WARN("Could not resize overlay!");
}
gst_video_overlay_expose(overlay);
#else
if (!gst_x_overlay_set_render_rectangle(overlay, 0, 0, width, height))
{
DEBUG_WARN("Could not resize overlay!");
}
gst_x_overlay_expose(overlay);
#endif
if (hdl->subwin)
{
XMoveResizeWindow(hdl->disp, hdl->subwin, x, y, width, height);
#if defined(WITH_XEXT)
if (hdl->has_shape)
{
int i;
XRectangle *xrects = calloc(nr_rects, sizeof(XRectangle));
for (i=0; i<nr_rects; i++)
{
xrects[i].x = rects[i].x - x;
xrects[i].y = rects[i].y - y;
xrects[i].width = rects[i].width;
xrects[i].height = rects[i].height;
}
XShapeCombineRectangles(hdl->disp, hdl->subwin, ShapeBounding, x, y, xrects, nr_rects, ShapeSet, 0);
free(xrects);
}
#endif
XSync(hdl->disp, FALSE);
}
return 0;
}
}
int tsmf_window_pause(TSMFGstreamerDecoder *decoder)
{
assert(decoder);
return 0;
}
int tsmf_window_resume(TSMFGstreamerDecoder *decoder)
{
assert(decoder);
return 0;
}
int tsmf_window_destroy(TSMFGstreamerDecoder *decoder)
{
struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
decoder->ready = FALSE;
if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
return -3;
assert(decoder);
assert(hdl);
if (hdl->subwin)
{
XDestroyWindow(hdl->disp, hdl->subwin);
XSync(hdl->disp, FALSE);
}
hdl->subwin = 0;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
/*
* FreeRDP: A Remote Desktop Protocol Implementation
* Video Redirection Virtual Channel - GStreamer Decoder
* platform specific functions
*
* (C) Copyright 2014 Thincast Technologies GmbH
* (C) Copyright 2014 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _TSMF_PLATFORM_H_
#define _TSMF_PLATFORM_H_
#include <gst/gst.h>
#include <tsmf_decoder.h>
typedef struct _TSMFGstreamerDecoder
{
ITSMFDecoder iface;
int media_type; /* TSMF_MAJOR_TYPE_AUDIO or TSMF_MAJOR_TYPE_VIDEO */
gint64 duration;
GstState state;
GstCaps *gst_caps;
GstElement *pipe;
GstElement *src;
GstElement *outsink;
GstElement *volume;
BOOL ready;
BOOL paused;
UINT64 last_sample_end_time;
double gstVolume;
BOOL gstMuted;
int pipeline_start_time_valid; /* We've set the start time and have not reset the pipeline */
int shutdown; /* The decoder stream is shutting down */
void *platform;
BOOL (*ack_cb)(void *,BOOL);
void (*sync_cb)(void *);
void *stream;
} TSMFGstreamerDecoder;
const char *get_type(TSMFGstreamerDecoder *mdecoder);
const char *tsmf_platform_get_video_sink(void);
const char *tsmf_platform_get_audio_sink(void);
int tsmf_platform_create(TSMFGstreamerDecoder *decoder);
int tsmf_platform_set_format(TSMFGstreamerDecoder *decoder);
int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder);
int tsmf_platform_free(TSMFGstreamerDecoder *decoder);
int tsmf_window_create(TSMFGstreamerDecoder *decoder);
int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y,
int width, int height, int nr_rect, RDP_RECT *visible);
int tsmf_window_destroy(TSMFGstreamerDecoder *decoder);
int tsmf_window_pause(TSMFGstreamerDecoder *decoder);
int tsmf_window_resume(TSMFGstreamerDecoder *decoder);
BOOL tsmf_gstreamer_add_pad(TSMFGstreamerDecoder *mdecoder);
void tsmf_gstreamer_remove_pad(TSMFGstreamerDecoder *mdecoder);
#endif

View File

@ -37,75 +37,70 @@ typedef struct _TSMFPulseAudioDevice
ITSMFAudioDevice iface;
char device[32];
pa_threaded_mainloop* mainloop;
pa_context* context;
pa_threaded_mainloop *mainloop;
pa_context *context;
pa_sample_spec sample_spec;
pa_stream* stream;
pa_stream *stream;
} TSMFPulseAudioDevice;
static void tsmf_pulse_context_state_callback(pa_context* context, void* userdata)
static void tsmf_pulse_context_state_callback(pa_context *context, void *userdata)
{
TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) userdata;
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata;
pa_context_state_t state;
state = pa_context_get_state(context);
switch (state)
switch(state)
{
case PA_CONTEXT_READY:
DEBUG_DVC("PA_CONTEXT_READY");
DEBUG_TSMF("PA_CONTEXT_READY");
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
DEBUG_DVC("state %d", (int)state);
DEBUG_TSMF("state %d", (int)state);
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
default:
DEBUG_DVC("state %d", (int)state);
DEBUG_TSMF("state %d", (int)state);
break;
}
}
static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice* pulse)
static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice *pulse)
{
pa_context_state_t state;
if (!pulse->context)
if(!pulse->context)
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)",
pa_context_errno(pulse->context));
pa_context_errno(pulse->context));
return FALSE;
}
pa_threaded_mainloop_lock(pulse->mainloop);
if (pa_threaded_mainloop_start(pulse->mainloop) < 0)
if(pa_threaded_mainloop_start(pulse->mainloop) < 0)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
DEBUG_WARN("pa_threaded_mainloop_start failed (%d)",
pa_context_errno(pulse->context));
pa_context_errno(pulse->context));
return FALSE;
}
for (;;)
for(;;)
{
state = pa_context_get_state(pulse->context);
if (state == PA_CONTEXT_READY)
if(state == PA_CONTEXT_READY)
break;
if (!PA_CONTEXT_IS_GOOD(state))
if(!PA_CONTEXT_IS_GOOD(state))
{
DEBUG_DVC("bad context state (%d)",
pa_context_errno(pulse->context));
DEBUG_TSMF("bad context state (%d)",
pa_context_errno(pulse->context));
break;
}
pa_threaded_mainloop_wait(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;
}
else
@ -115,166 +110,150 @@ 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;
if (device)
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
if(device)
{
strcpy(pulse->device, device);
}
pulse->mainloop = pa_threaded_mainloop_new();
if (!pulse->mainloop)
if(!pulse->mainloop)
{
DEBUG_WARN("pa_threaded_mainloop_new failed");
return FALSE;
}
pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp");
if (!pulse->context)
if(!pulse->context)
{
DEBUG_WARN("pa_context_new failed");
return FALSE;
}
pa_context_set_state_callback(pulse->context, tsmf_pulse_context_state_callback, pulse);
if (tsmf_pulse_connect(pulse))
if(tsmf_pulse_connect(pulse))
{
DEBUG_WARN("tsmf_pulse_connect failed");
return FALSE;
}
DEBUG_DVC("open device %s", pulse->device);
DEBUG_TSMF("open device %s", pulse->device);
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);
}
static void tsmf_pulse_wait_for_operation(TSMFPulseAudioDevice* pulse, pa_operation* operation)
static void tsmf_pulse_wait_for_operation(TSMFPulseAudioDevice *pulse, pa_operation *operation)
{
if (operation == NULL)
if(operation == NULL)
return;
while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
while(pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
{
pa_threaded_mainloop_wait(pulse->mainloop);
}
pa_operation_unref(operation);
}
static void tsmf_pulse_stream_state_callback(pa_stream* stream, void* userdata)
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;
state = pa_stream_get_state(stream);
switch (state)
switch(state)
{
case PA_STREAM_READY:
DEBUG_DVC("PA_STREAM_READY");
pa_threaded_mainloop_signal (pulse->mainloop, 0);
DEBUG_TSMF("PA_STREAM_READY");
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
DEBUG_DVC("state %d", (int)state);
pa_threaded_mainloop_signal (pulse->mainloop, 0);
DEBUG_TSMF("state %d", (int)state);
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
default:
DEBUG_DVC("state %d", (int)state);
DEBUG_TSMF("state %d", (int)state);
break;
}
}
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;
DEBUG_DVC("%d", (int) length);
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) userdata;
DEBUG_TSMF("%d", (int) length);
pa_threaded_mainloop_signal(pulse->mainloop, 0);
}
static BOOL tsmf_pulse_close_stream(TSMFPulseAudioDevice* pulse)
static BOOL tsmf_pulse_close_stream(TSMFPulseAudioDevice *pulse)
{
if (!pulse->context || !pulse->stream)
if(!pulse->context || !pulse->stream)
return FALSE;
DEBUG_DVC("");
DEBUG_TSMF("");
pa_threaded_mainloop_lock(pulse->mainloop);
pa_stream_set_write_callback(pulse->stream, NULL, NULL);
tsmf_pulse_wait_for_operation(pulse,
pa_stream_drain(pulse->stream, tsmf_pulse_stream_success_callback, pulse));
pa_stream_drain(pulse->stream, tsmf_pulse_stream_success_callback, pulse));
pa_stream_disconnect(pulse->stream);
pa_stream_unref(pulse->stream);
pulse->stream = NULL;
pa_threaded_mainloop_unlock(pulse->mainloop);
return TRUE;
}
static BOOL tsmf_pulse_open_stream(TSMFPulseAudioDevice* pulse)
static BOOL tsmf_pulse_open_stream(TSMFPulseAudioDevice *pulse)
{
pa_stream_state_t state;
pa_buffer_attr buffer_attr = { 0 };
if (!pulse->context)
if(!pulse->context)
return FALSE;
DEBUG_DVC("");
DEBUG_TSMF("");
pa_threaded_mainloop_lock(pulse->mainloop);
pulse->stream = pa_stream_new(pulse->context, "freerdp",
&pulse->sample_spec, NULL);
if (!pulse->stream)
&pulse->sample_spec, NULL);
if(!pulse->stream)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
DEBUG_WARN("pa_stream_new failed (%d)",
pa_context_errno(pulse->context));
pa_context_errno(pulse->context));
return FALSE;
}
pa_stream_set_state_callback(pulse->stream,
tsmf_pulse_stream_state_callback, pulse);
tsmf_pulse_stream_state_callback, pulse);
pa_stream_set_write_callback(pulse->stream,
tsmf_pulse_stream_request_callback, pulse);
tsmf_pulse_stream_request_callback, pulse);
buffer_attr.maxlength = pa_usec_to_bytes(500000, &pulse->sample_spec);
buffer_attr.tlength = pa_usec_to_bytes(250000, &pulse->sample_spec);
buffer_attr.prebuf = (UINT32) -1;
buffer_attr.minreq = (UINT32) -1;
buffer_attr.fragsize = (UINT32) -1;
if (pa_stream_connect_playback(pulse->stream,
pulse->device[0] ? pulse->device : NULL, &buffer_attr,
PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE,
NULL, NULL) < 0)
if(pa_stream_connect_playback(pulse->stream,
pulse->device[0] ? pulse->device : NULL, &buffer_attr,
PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE,
NULL, NULL) < 0)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
DEBUG_WARN("pa_stream_connect_playback failed (%d)",
pa_context_errno(pulse->context));
pa_context_errno(pulse->context));
return FALSE;
}
for (;;)
for(;;)
{
state = pa_stream_get_state(pulse->stream);
if (state == PA_STREAM_READY)
if(state == PA_STREAM_READY)
break;
if (!PA_STREAM_IS_GOOD(state))
if(!PA_STREAM_IS_GOOD(state))
{
DEBUG_WARN("bad stream state (%d)",
pa_context_errno(pulse->context));
pa_context_errno(pulse->context));
break;
}
pa_threaded_mainloop_wait(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;
}
else
@ -284,105 +263,93 @@ static BOOL tsmf_pulse_open_stream(TSMFPulseAudioDevice* pulse)
}
}
static BOOL tsmf_pulse_set_format(ITSMFAudioDevice* audio,
UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample)
static BOOL tsmf_pulse_set_format(ITSMFAudioDevice *audio,
UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample)
{
TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio;
DEBUG_DVC("sample_rate %d channels %d bits_per_sample %d",
sample_rate, channels, bits_per_sample);
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
DEBUG_TSMF("sample_rate %d channels %d bits_per_sample %d",
sample_rate, channels, bits_per_sample);
pulse->sample_spec.rate = sample_rate;
pulse->sample_spec.channels = channels;
pulse->sample_spec.format = PA_SAMPLE_S16LE;
return tsmf_pulse_open_stream(pulse);
}
static BOOL tsmf_pulse_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size)
static BOOL tsmf_pulse_play(ITSMFAudioDevice *audio, BYTE *data, UINT32 data_size)
{
TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio;
BYTE* src;
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
BYTE *src;
int len;
int ret;
DEBUG_DVC("data_size %d", data_size);
if (pulse->stream)
DEBUG_TSMF("data_size %d", data_size);
if(pulse->stream)
{
pa_threaded_mainloop_lock(pulse->mainloop);
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);
}
if (len < 0)
if(len < 0)
break;
if (len > data_size)
if(len > data_size)
len = data_size;
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)",
pa_context_errno(pulse->context));
DEBUG_TSMF("pa_stream_write failed (%d)",
pa_context_errno(pulse->context));
break;
}
src += len;
data_size -= len;
}
pa_threaded_mainloop_unlock(pulse->mainloop);
}
free(data);
return TRUE;
}
static UINT64 tsmf_pulse_get_latency(ITSMFAudioDevice* audio)
static UINT64 tsmf_pulse_get_latency(ITSMFAudioDevice *audio)
{
pa_usec_t usec;
UINT64 latency = 0;
TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio;
if (pulse->stream && pa_stream_get_latency(pulse->stream, &usec, NULL) == 0)
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
if(pulse->stream && pa_stream_get_latency(pulse->stream, &usec, NULL) == 0)
{
latency = ((UINT64)usec) * 10LL;
}
return latency;
}
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);
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));
pa_threaded_mainloop_unlock(pulse->mainloop);
}
static void tsmf_pulse_free(ITSMFAudioDevice* audio)
static void tsmf_pulse_free(ITSMFAudioDevice *audio)
{
TSMFPulseAudioDevice* pulse = (TSMFPulseAudioDevice*) audio;
DEBUG_DVC("");
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
DEBUG_TSMF("");
tsmf_pulse_close_stream(pulse);
if (pulse->mainloop)
if(pulse->mainloop)
{
pa_threaded_mainloop_stop(pulse->mainloop);
}
if (pulse->context)
if(pulse->context)
{
pa_context_disconnect(pulse->context);
pa_context_unref(pulse->context);
pulse->context = NULL;
}
if (pulse->mainloop)
if(pulse->mainloop)
{
pa_threaded_mainloop_free(pulse->mainloop);
pulse->mainloop = NULL;
@ -394,20 +361,17 @@ static void tsmf_pulse_free(ITSMFAudioDevice* audio)
#define freerdp_tsmf_client_audio_subsystem_entry pulse_freerdp_tsmf_client_audio_subsystem_entry
#endif
ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)
ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)
{
TSMFPulseAudioDevice* pulse;
pulse = (TSMFPulseAudioDevice*) malloc(sizeof(TSMFPulseAudioDevice));
TSMFPulseAudioDevice *pulse;
pulse = (TSMFPulseAudioDevice *) malloc(sizeof(TSMFPulseAudioDevice));
ZeroMemory(pulse, sizeof(TSMFPulseAudioDevice));
pulse->iface.Open = tsmf_pulse_open;
pulse->iface.SetFormat = tsmf_pulse_set_format;
pulse->iface.Play = tsmf_pulse_play;
pulse->iface.GetLatency = tsmf_pulse_get_latency;
pulse->iface.Flush = tsmf_pulse_flush;
pulse->iface.Free = tsmf_pulse_free;
return (ITSMFAudioDevice*) pulse;
return (ITSMFAudioDevice *) pulse;
}

View File

@ -37,7 +37,7 @@
typedef struct _TSMFMediaTypeMap
{
BYTE guid[16];
const char* name;
const char *name;
int type;
} TSMFMediaTypeMap;
@ -259,24 +259,23 @@ 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;
for (i = 3; i >= 0; i--)
for(i = 3; i >= 0; i--)
fprintf(stderr, "%02X", guid[i]);
fprintf(stderr, "-");
for (i = 5; i >= 4; i--)
for(i = 5; i >= 4; i--)
fprintf(stderr, "%02X", guid[i]);
fprintf(stderr, "-");
for (i = 7; i >= 6; i--)
for(i = 7; i >= 6; i--)
fprintf(stderr, "%02X", guid[i]);
fprintf(stderr, "-");
for (i = 8; i < 16; i++)
for(i = 8; i < 16; i++)
{
fprintf(stderr, "%02X", guid[i]);
if (i == 9)
if(i == 9)
fprintf(stderr, "-");
}
fprintf(stderr, "\n");
@ -284,34 +283,29 @@ static void tsmf_print_guid(const BYTE* guid)
}
/* http://msdn.microsoft.com/en-us/library/dd318229.aspx */
static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStream* s, BOOL bypass)
static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE *mediatype, wStream *s, BOOL bypass)
{
UINT32 biSize;
UINT32 biWidth;
UINT32 biHeight;
Stream_Read_UINT32(s, biSize);
Stream_Read_UINT32(s, biWidth);
Stream_Read_UINT32(s, biHeight);
Stream_Seek(s, 28);
if (mediatype->Width == 0)
if(mediatype->Width == 0)
mediatype->Width = biWidth;
if (mediatype->Height == 0)
if(mediatype->Height == 0)
mediatype->Height = biHeight;
/* Assume there will be no color table for video? */
if (bypass && biSize > 40)
if(bypass && biSize > 40)
Stream_Seek(s, biSize - 40);
return (bypass ? biSize : 40);
}
/* http://msdn.microsoft.com/en-us/library/dd407326.aspx */
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;
/* VIDEOINFOHEADER2.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
Stream_Seek_UINT32(s);
Stream_Seek_UINT32(s);
@ -329,25 +323,23 @@ static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, wSt
mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL);
/* Remaining fields before bmiHeader */
Stream_Seek(s, 24);
return 72;
}
/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
static UINT32 tsmf_codec_parse_VIDEOINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
static UINT32 tsmf_codec_parse_VIDEOINFOHEADER(TS_AM_MEDIA_TYPE *mediatype, wStream *s)
{
/*
typedef struct tagVIDEOINFOHEADER {
RECT rcSource; //16
RECT rcTarget; //16 32
DWORD dwBitRate; //4 36
DWORD dwBitErrorRate; //4 40
REFERENCE_TIME AvgTimePerFrame; //8 48
BITMAPINFOHEADER bmiHeader;
} VIDEOINFOHEADER;
*/
/*
typedef struct tagVIDEOINFOHEADER {
RECT rcSource; //16
RECT rcTarget; //16 32
DWORD dwBitRate; //4 36
DWORD dwBitErrorRate; //4 40
REFERENCE_TIME AvgTimePerFrame; //8 48
BITMAPINFOHEADER bmiHeader;
} VIDEOINFOHEADER;
*/
UINT64 AvgTimePerFrame;
/* VIDEOINFOHEADER.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
Stream_Seek_UINT32(s);
Stream_Seek_UINT32(s);
@ -363,76 +355,66 @@ typedef struct tagVIDEOINFOHEADER {
Stream_Read_UINT64(s, AvgTimePerFrame);
mediatype->SamplesPerSecond.Numerator = 1000000;
mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL);
return 48;
}
BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE *mediatype, wStream *s)
{
int i;
UINT32 cbFormat;
BOOL ret = TRUE;
memset(mediatype, 0, sizeof(TS_AM_MEDIA_TYPE));
/* MajorType */
DEBUG_DVC("MajorType:");
DEBUG_TSMF("MajorType:");
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++)
{
if (memcmp(tsmf_major_type_map[i].guid, Stream_Pointer(s), 16) == 0)
if(memcmp(tsmf_major_type_map[i].guid, Stream_Pointer(s), 16) == 0)
break;
}
mediatype->MajorType = tsmf_major_type_map[i].type;
if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
if(mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
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);
/* SubType */
DEBUG_DVC("SubType:");
DEBUG_TSMF("SubType:");
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++)
{
if (memcmp(tsmf_sub_type_map[i].guid, Stream_Pointer(s), 16) == 0)
if(memcmp(tsmf_sub_type_map[i].guid, Stream_Pointer(s), 16) == 0)
break;
}
mediatype->SubType = tsmf_sub_type_map[i].type;
if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
if(mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
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);
/* bFixedSizeSamples, bTemporalCompression, SampleSize */
Stream_Seek(s, 12);
/* FormatType */
DEBUG_DVC("FormatType:");
DEBUG_TSMF("FormatType:");
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++)
{
if (memcmp(tsmf_format_type_map[i].guid, Stream_Pointer(s), 16) == 0)
if(memcmp(tsmf_format_type_map[i].guid, Stream_Pointer(s), 16) == 0)
break;
}
mediatype->FormatType = tsmf_format_type_map[i].type;
if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
if(mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
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);
/* cbFormat */
Stream_Read_UINT32(s, cbFormat);
DEBUG_DVC("cbFormat %d", cbFormat);
#ifdef WITH_DEBUG_DVC
DEBUG_TSMF("cbFormat %d", cbFormat);
#ifdef WITH_DEBUG_TSMF
winpr_HexDump(Stream_Pointer(s), cbFormat);
#endif
switch (mediatype->FormatType)
switch(mediatype->FormatType)
{
case TSMF_FORMAT_TYPE_MFVIDEOFORMAT:
/* http://msdn.microsoft.com/en-us/library/aa473808.aspx */
Stream_Seek(s, 8); /* dwSize and ? */
Stream_Read_UINT32(s, mediatype->Width); /* videoInfo.dwWidth */
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_Read_UINT32(s, mediatype->BitRate); /* compressedInfo.AvgBitrate */
Stream_Seek(s, 36);
if (cbFormat > 176)
if(cbFormat > 176)
{
mediatype->ExtraDataSize = cbFormat - 176;
mediatype->ExtraData = Stream_Pointer(s);
}
break;
case TSMF_FORMAT_TYPE_WAVEFORMATEX:
/* http://msdn.microsoft.com/en-us/library/dd757720.aspx */
Stream_Seek_UINT16(s);
Stream_Read_UINT16(s, mediatype->Channels);
Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator);
@ -463,66 +442,55 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
Stream_Read_UINT16(s, mediatype->BlockAlign);
Stream_Read_UINT16(s, mediatype->BitsPerSample);
Stream_Read_UINT16(s, mediatype->ExtraDataSize);
if (mediatype->ExtraDataSize > 0)
if(mediatype->ExtraDataSize > 0)
mediatype->ExtraData = Stream_Pointer(s);
break;
case TSMF_FORMAT_TYPE_MPEG1VIDEOINFO:
/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
i = tsmf_codec_parse_VIDEOINFOHEADER(mediatype, s);
i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
if (cbFormat > i)
if(cbFormat > i)
{
mediatype->ExtraDataSize = cbFormat - i;
mediatype->ExtraData = Stream_Pointer(s);
}
break;
case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO:
/* http://msdn.microsoft.com/en-us/library/dd390707.aspx */
i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
if (cbFormat > i)
if(cbFormat > i)
{
mediatype->ExtraDataSize = cbFormat - i;
mediatype->ExtraData = Stream_Pointer(s);
}
break;
case TSMF_FORMAT_TYPE_VIDEOINFO2:
i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, FALSE);
if (cbFormat > i)
if(cbFormat > i)
{
mediatype->ExtraDataSize = cbFormat - i;
mediatype->ExtraData = Stream_Pointer(s);
}
break;
default:
break;
}
if (mediatype->SamplesPerSecond.Numerator == 0)
if(mediatype->SamplesPerSecond.Numerator == 0)
mediatype->SamplesPerSecond.Numerator = 1;
if (mediatype->SamplesPerSecond.Denominator == 0)
if(mediatype->SamplesPerSecond.Denominator == 0)
mediatype->SamplesPerSecond.Denominator = 1;
return ret;
}
BOOL tsmf_codec_check_media_type(wStream* s)
BOOL tsmf_codec_check_media_type(wStream *s)
{
BYTE* m;
BYTE *m;
BOOL ret;
TS_AM_MEDIA_TYPE mediatype;
Stream_GetPointer(s, m);
ret = tsmf_codec_parse_media_type(&mediatype, s);
Stream_SetPointer(s, m);
return ret;
}

View File

@ -32,45 +32,41 @@
#include "tsmf_constants.h"
#include "tsmf_decoder.h"
static ITSMFDecoder* tsmf_load_decoder_by_name(const char* name, TS_AM_MEDIA_TYPE* media_type)
static ITSMFDecoder *tsmf_load_decoder_by_name(const char *name, TS_AM_MEDIA_TYPE *media_type)
{
ITSMFDecoder* decoder;
ITSMFDecoder *decoder;
TSMF_DECODER_ENTRY entry;
entry = (TSMF_DECODER_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "decoder", 0);
if (entry == NULL)
if(entry == NULL)
return NULL;
decoder = entry();
if (decoder == NULL)
if(decoder == NULL)
{
DEBUG_WARN("failed to call export function in %s", name);
return NULL;
}
if (!decoder->SetFormat(decoder, media_type))
if(!decoder->SetFormat(decoder, media_type))
{
decoder->Free(decoder);
decoder = NULL;
}
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;
if (name)
ITSMFDecoder *decoder = NULL;
if(name)
{
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);
}
#endif
return decoder;
}

View File

@ -26,9 +26,8 @@
typedef enum _ITSMFControlMsg
{
Control_Pause,
Control_Restart,
Control_Flush,
Control_EndOfStream
Control_Resume,
Control_Stop
} ITSMFControlMsg;
typedef struct _ITSMFDecoder ITSMFDecoder;
@ -36,36 +35,40 @@ typedef struct _ITSMFDecoder ITSMFDecoder;
struct _ITSMFDecoder
{
/* Set the decoder format. Return true if supported. */
BOOL (*SetFormat) (ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type);
BOOL (*SetFormat)(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *media_type);
/* Decode a sample. */
BOOL (*Decode) (ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size, UINT32 extensions);
BOOL (*Decode)(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions);
/* Get the decoded data */
BYTE* (*GetDecodedData) (ITSMFDecoder* decoder, UINT32* size);
BYTE *(*GetDecodedData)(ITSMFDecoder *decoder, UINT32 *size);
/* Get the pixel format of decoded video frame */
UINT32 (*GetDecodedFormat) (ITSMFDecoder* decoder);
UINT32(*GetDecodedFormat)(ITSMFDecoder *decoder);
/* Get the width and height of decoded video frame */
BOOL (*GetDecodedDimension) (ITSMFDecoder* decoder, UINT32* width, UINT32* height);
BOOL (*GetDecodedDimension)(ITSMFDecoder *decoder, UINT32 *width, UINT32 *height);
/* Free the decoder */
void (*Free) (ITSMFDecoder * decoder);
void (*Free)(ITSMFDecoder *decoder);
/* Optional Contol function */
void (*Control) (ITSMFDecoder * decoder, ITSMFControlMsg control_msg, UINT32 *arg);
void (*Control)(ITSMFDecoder *decoder, ITSMFControlMsg control_msg, UINT32 *arg);
/* Decode a sample with extended interface. */
int (*DecodeEx) (ITSMFDecoder * decoder, const BYTE * data, UINT32 data_size, UINT32 extensions,
UINT64 start_time, UINT64 end_time, UINT64 duration);
int (*DecodeEx)(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions,
UINT64 start_time, UINT64 end_time, UINT64 duration);
/* Get current play time */
UINT64 (*GetRunningTime) (ITSMFDecoder * decoder);
UINT64(*GetRunningTime)(ITSMFDecoder *decoder);
/* Update Gstreamer Rendering Area */
void (*UpdateRenderingArea) (ITSMFDecoder * decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles);
void (*UpdateRenderingArea)(ITSMFDecoder *decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles);
/* Change Gstreamer Audio Volume */
void (*ChangeVolume) (ITSMFDecoder * decoder, UINT32 newVolume, UINT32 muted);
void (*ChangeVolume)(ITSMFDecoder *decoder, UINT32 newVolume, UINT32 muted);
/* 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"
typedef ITSMFDecoder* (*TSMF_DECODER_ENTRY) (void);
typedef ITSMFDecoder *(*TSMF_DECODER_ENTRY)(void);
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);
#endif

View File

@ -37,21 +37,18 @@
#include "tsmf_ifman.h"
int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman)
int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN *ifman)
{
UINT32 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_Write_UINT32(ifman->output, 1); /* CapabilityValue */
Stream_Write_UINT32(ifman->output, 0); /* Result */
return 0;
}
int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
int tsmf_ifman_exchange_capability_request(TSMF_IFMAN *ifman)
{
UINT32 i;
UINT32 v;
@ -59,32 +56,28 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
UINT32 CapabilityType;
UINT32 cbCapabilityLength;
UINT32 numHostCapabilities;
pos = Stream_GetPosition(ifman->output);
Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4);
Stream_Copy(ifman->output, ifman->input, ifman->input_size);
Stream_SetPosition(ifman->output, pos);
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, cbCapabilityLength);
pos = Stream_GetPosition(ifman->output);
switch (CapabilityType)
switch(CapabilityType)
{
case 1: /* Protocol version request */
Stream_Read_UINT32(ifman->output, v);
DEBUG_DVC("server protocol version %d", v);
DEBUG_TSMF("server protocol version %d", v);
break;
case 2: /* Supported platform */
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. */
Stream_Write_UINT32(ifman->output,
MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW);
MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW);
break;
default:
DEBUG_WARN("unknown capability type %d", CapabilityType);
@ -93,81 +86,62 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
Stream_SetPosition(ifman->output, pos + cbCapabilityLength);
}
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0;
}
int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
int tsmf_ifman_check_format_support_request(TSMF_IFMAN *ifman)
{
UINT32 numMediaType;
UINT32 PlatformCookie;
UINT32 FormatSupported = 1;
Stream_Read_UINT32(ifman->input, PlatformCookie);
Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */
Stream_Read_UINT32(ifman->input, numMediaType);
DEBUG_DVC("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType);
if (!tsmf_codec_check_media_type(ifman->input))
DEBUG_TSMF("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType);
if(!tsmf_codec_check_media_type(ifman->input))
FormatSupported = 0;
if (FormatSupported)
DEBUG_DVC("format ok.");
if(FormatSupported)
DEBUG_TSMF("format ok.");
Stream_EnsureRemainingCapacity(ifman->output, 12);
Stream_Write_UINT32(ifman->output, FormatSupported);
Stream_Write_UINT32(ifman->output, PlatformCookie);
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0;
}
int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
int tsmf_ifman_on_new_presentation(TSMF_IFMAN *ifman)
{
int status = 0;
TSMF_PRESENTATION* presentation;
DEBUG_DVC("");
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
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;
return 0;
}
presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback);
if (presentation == NULL)
if(presentation == NULL)
status = 1;
else
tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device);
ifman->output_pending = TRUE;
return status;
}
int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
int tsmf_ifman_add_stream(TSMF_IFMAN *ifman)
{
UINT32 StreamId;
int status = 0;
TSMF_STREAM* stream;
TSMF_PRESENTATION* presentation;
DEBUG_DVC("");
TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
if (presentation == NULL)
if(presentation == NULL)
{
status = 1;
}
@ -176,41 +150,33 @@ int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
Stream_Read_UINT32(ifman->input, StreamId);
Stream_Seek_UINT32(ifman->input); /* numMediaType */
stream = tsmf_stream_new(presentation, StreamId);
if (stream)
if(stream)
tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input);
}
ifman->output_pending = TRUE;
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_Write_UINT32(ifman->output, 1); /* TopologyReady */
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0;
}
int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
int tsmf_ifman_remove_stream(TSMF_IFMAN *ifman)
{
int status = 0;
UINT32 StreamId;
TSMF_STREAM* stream;
TSMF_PRESENTATION* presentation;
DEBUG_DVC("");
TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
if (presentation == NULL)
if(presentation == NULL)
{
status = 1;
}
@ -218,41 +184,34 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
{
Stream_Read_UINT32(ifman->input, StreamId);
stream = tsmf_stream_find_by_id(presentation, StreamId);
if (stream)
if(stream)
tsmf_stream_free(stream);
else
status = 1;
}
ifman->output_pending = TRUE;
return status;
}
float tsmf_stream_read_float(wStream* s)
float tsmf_stream_read_float(wStream *s)
{
float fValue;
UINT32 iValue;
Stream_Read_UINT32(s, iValue);
CopyMemory(&fValue, &iValue, 4);
return fValue;
}
int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman)
int tsmf_ifman_set_source_video_rect(TSMF_IFMAN *ifman)
{
int status = 0;
float Left, Top;
float Right, Bottom;
TSMF_PRESENTATION* presentation;
DEBUG_DVC("");
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
if (!presentation)
if(!presentation)
{
status = 1;
}
@ -262,144 +221,117 @@ int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman)
Top = tsmf_stream_read_float(ifman->input); /* Top (4 bytes) */
Right = tsmf_stream_read_float(ifman->input); /* Right (4 bytes) */
Bottom = tsmf_stream_read_float(ifman->input); /* Bottom (4 bytes) */
DEBUG_DVC("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f",
Left, Top, Right, Bottom);
DEBUG_TSMF("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f",
Left, Top, Right, Bottom);
}
ifman->output_pending = TRUE;
return status;
}
int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
int tsmf_ifman_shutdown_presentation(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION* presentation;
DEBUG_DVC("");
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if (presentation)
if(presentation)
tsmf_presentation_free(presentation);
else
DEBUG_WARN("unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 4);
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0;
}
int tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman)
int tsmf_ifman_on_stream_volume(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION* presentation;
DEBUG_DVC("on stream volume");
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("on stream volume");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if (presentation)
if(presentation)
{
UINT32 newVolume;
UINT32 muted;
Stream_Seek(ifman->input, 16);
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);
DEBUG_DVC("on stream volume: muted=[%d]", muted);
DEBUG_TSMF("on stream volume: muted=[%d]", muted);
tsmf_presentation_volume_changed(presentation, newVolume, muted);
}
else
{
DEBUG_WARN("unknown presentation id");
}
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman)
int tsmf_ifman_on_channel_volume(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION* presentation;
DEBUG_DVC("on channel volume");
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("on channel volume");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if (presentation)
if(presentation)
{
UINT32 channelVolume;
UINT32 changedChannel;
Stream_Seek(ifman->input, 16);
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);
DEBUG_DVC("on stream volume: changed channel=[%d]", changedChannel);
DEBUG_TSMF("on stream volume: changed channel=[%d]", changedChannel);
}
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_set_video_window(TSMF_IFMAN* ifman)
{
DEBUG_DVC("");
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
int tsmf_ifman_set_video_window(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_update_geometry_info(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION *presentation;
UINT32 numGeometryInfo;
UINT32 Left;
UINT32 Top;
UINT32 Width;
UINT32 Height;
UINT32 cbVisibleRect;
RDP_RECT* rects = NULL;
RDP_RECT *rects = NULL;
int num_rects = 0;
int error = 0;
int i;
int pos;
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, numGeometryInfo);
pos = Stream_GetPosition(ifman->input);
Stream_Seek(ifman->input, 12); /* VideoWindowId (8 bytes), VideoWindowState (4 bytes) */
Stream_Read_UINT32(ifman->input, Width);
Stream_Read_UINT32(ifman->input, Height);
Stream_Read_UINT32(ifman->input, Left);
Stream_Read_UINT32(ifman->input, Top);
Stream_SetPosition(ifman->input, pos + numGeometryInfo);
Stream_Read_UINT32(ifman->input, cbVisibleRect);
num_rects = cbVisibleRect / 16;
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);
if (presentation == NULL)
DEBUG_TSMF("numGeometryInfo %d Width %d Height %d Left %d Top %d cbVisibleRect %d num_rects %d",
numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);
if(presentation == NULL)
{
error = 1;
}
else
{
if (num_rects > 0)
if(num_rects > 0)
{
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);
for (i = 0; i < num_rects; i++)
for(i = 0; i < num_rects; i++)
{
Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */
Stream_Seek_UINT16(ifman->input);
@ -411,44 +343,40 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
Stream_Seek_UINT16(ifman->input);
rects[i].width -= rects[i].x;
rects[i].height -= rects[i].y;
DEBUG_DVC("rect %d: %d %d %d %d", i,
rects[i].x, rects[i].y, rects[i].width, rects[i].height);
DEBUG_TSMF("rect %d: %d %d %d %d", i,
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);
}
ifman->output_pending = TRUE;
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;
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;
return 0;
}
int tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
int tsmf_ifman_on_sample(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION* presentation;
TSMF_STREAM* stream;
TSMF_PRESENTATION *presentation;
TSMF_STREAM *stream;
UINT32 StreamId;
UINT64 SampleStartTime;
UINT64 SampleEndTime;
UINT64 ThrottleDuration;
UINT32 SampleExtensions;
UINT32 cbData;
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId);
Stream_Seek_UINT32(ifman->input); /* numSample */
@ -458,183 +386,144 @@ int tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
Stream_Seek_UINT32(ifman->input); /* SampleFlags */
Stream_Read_UINT32(ifman->input, SampleExtensions);
Stream_Read_UINT32(ifman->input, cbData);
DEBUG_DVC("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d "
"ThrottleDuration %d SampleExtensions %d cbData %d",
ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime,
(int)ThrottleDuration, SampleExtensions, cbData);
DEBUG_TSMF("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d "
"ThrottleDuration %d SampleExtensions %d cbData %d",
ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime,
(int)ThrottleDuration, SampleExtensions, cbData);
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
if (presentation == NULL)
if(presentation == NULL)
{
DEBUG_WARN("unknown presentation id");
return 1;
}
stream = tsmf_stream_find_by_id(presentation, StreamId);
if (stream == NULL)
if(stream == NULL)
{
DEBUG_WARN("unknown stream id");
return 1;
}
tsmf_stream_push_sample(stream, ifman->channel_callback,
ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions,
cbData, Stream_Pointer(ifman->input));
ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions,
cbData, Stream_Pointer(ifman->input));
tsmf_presentation_sync(presentation);
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
int tsmf_ifman_on_flush(TSMF_IFMAN *ifman)
{
UINT32 StreamId;
TSMF_PRESENTATION* presentation;
TSMF_PRESENTATION *presentation;
Stream_Seek(ifman->input, 16);
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);
if (presentation == NULL)
if(presentation == NULL)
{
DEBUG_WARN("unknown presentation id");
return 1;
}
tsmf_presentation_flush(presentation);
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman)
int tsmf_ifman_on_end_of_stream(TSMF_IFMAN *ifman)
{
UINT32 StreamId;
TSMF_STREAM* stream;
TSMF_PRESENTATION* presentation;
TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation;
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId);
if (presentation)
if(presentation)
{
stream = tsmf_stream_find_by_id(presentation, StreamId);
if (stream)
if(stream)
tsmf_stream_end(stream);
}
DEBUG_DVC("StreamId %d", StreamId);
DEBUG_TSMF("StreamId %d", StreamId);
Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, StreamId); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_ENDOFSTREAM); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
return 0;
}
int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman)
int tsmf_ifman_on_playback_started(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION* presentation;
DEBUG_DVC("");
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if (presentation)
if(presentation)
tsmf_presentation_start(presentation);
else
DEBUG_WARN("unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, 0); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_START_COMPLETED); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
return 0;
}
int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman)
int tsmf_ifman_on_playback_paused(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION* presentation;
DEBUG_DVC("");
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
ifman->output_pending = TRUE;
/* Added pause control so gstreamer pipeline can be paused accordingly */
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if (presentation)
if(presentation)
tsmf_presentation_paused(presentation);
else
DEBUG_WARN("unknown presentation id");
return 0;
}
int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman)
int tsmf_ifman_on_playback_restarted(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION* presentation;
DEBUG_DVC("");
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
ifman->output_pending = TRUE;
/* Added restart control so gstreamer pipeline can be resumed accordingly */
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if (presentation)
if(presentation)
tsmf_presentation_restarted(presentation);
else
DEBUG_WARN("unknown presentation id");
return 0;
}
int tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman)
int tsmf_ifman_on_playback_stopped(TSMF_IFMAN *ifman)
{
TSMF_PRESENTATION* presentation;
DEBUG_DVC("");
TSMF_PRESENTATION *presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if (presentation)
if(presentation)
tsmf_presentation_stop(presentation);
else
DEBUG_WARN("unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, 0); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_STOP_COMPLETED); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
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_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, 0); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_MONITORCHANGED); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
return 0;
}

View File

@ -47,19 +47,19 @@ struct _TSMF_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
IWTSPlugin *plugin;
IWTSVirtualChannelManager *channel_mgr;
};
struct _TSMF_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
IWTSVirtualChannel* channel;
IWTSPlugin *plugin;
IWTSVirtualChannelManager *channel_mgr;
IWTSVirtualChannel *channel;
BYTE presentation_id[16];
BYTE presentation_id[GUID_SIZE];
UINT32 stream_id;
};
@ -67,20 +67,19 @@ struct _TSMF_PLUGIN
{
IWTSPlugin iface;
TSMF_LISTENER_CALLBACK* listener_callback;
TSMF_LISTENER_CALLBACK *listener_callback;
const char* decoder_name;
const char* audio_name;
const char* audio_device;
const char *decoder_name;
const char *audio_name;
const char *audio_device;
};
void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
UINT32 message_id, UINT64 duration, UINT32 data_size)
void tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback,
UINT32 message_id, UINT64 duration, UINT32 data_size)
{
wStream* s;
int status;
TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
wStream *s;
int status = -1;
TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
s = Stream_New(NULL, 32);
Stream_Write_UINT32(s, TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY);
Stream_Write_UINT32(s, message_id);
@ -88,71 +87,66 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
Stream_Write_UINT32(s, callback->stream_id); /* StreamId */
Stream_Write_UINT64(s, duration); /* DataDuration */
Stream_Write_UINT64(s, data_size); /* cbData */
DEBUG_DVC("response size %d", (int) Stream_GetPosition(s));
status = callback->channel->Write(callback->channel, Stream_GetPosition(s), Stream_Buffer(s), NULL);
if (status)
DEBUG_TSMF("response size %d", (int) Stream_GetPosition(s));
if(!callback || !callback->channel || !callback->channel->Write)
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)
{
DEBUG_WARN("response error %d", status);
}
Stream_Free(s, TRUE);
}
BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, wMessage* event)
BOOL tsmf_push_event(IWTSVirtualChannelCallback *pChannelCallback, wMessage *event)
{
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);
if (status)
if(status)
{
DEBUG_WARN("response error %d", status);
return FALSE;
}
return TRUE;
}
static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
UINT32 cbSize,
BYTE* pBuffer)
static int tsmf_on_data_received(IWTSVirtualChannelCallback *pChannelCallback,
UINT32 cbSize,
BYTE *pBuffer)
{
int length;
wStream* input;
wStream* output;
wStream *input;
wStream *output;
int status = -1;
TSMF_IFMAN ifman;
UINT32 MessageId;
UINT32 FunctionId;
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) */
if (cbSize < 12)
if(cbSize < 12)
{
DEBUG_WARN("invalid size. cbSize=%d", cbSize);
return 1;
}
input = Stream_New((BYTE*) pBuffer, cbSize);
input = Stream_New((BYTE *) pBuffer, cbSize);
output = Stream_New(NULL, 256);
Stream_Seek(output, 8);
Stream_Read_UINT32(input, InterfaceId);
Stream_Read_UINT32(input, MessageId);
Stream_Read_UINT32(input, FunctionId);
DEBUG_DVC("cbSize=%d InterfaceId=0x%X MessageId=0x%X FunctionId=0x%X",
cbSize, InterfaceId, MessageId, FunctionId);
DEBUG_TSMF("cbSize=%d InterfaceId=0x%X MessageId=0x%X FunctionId=0x%X",
cbSize, InterfaceId, MessageId, FunctionId);
memset(&ifman, 0, sizeof(TSMF_IFMAN));
ifman.channel_callback = pChannelCallback;
ifman.decoder_name = ((TSMF_PLUGIN*) callback->plugin)->decoder_name;
ifman.audio_name = ((TSMF_PLUGIN*) callback->plugin)->audio_name;
ifman.audio_device = ((TSMF_PLUGIN*) callback->plugin)->audio_device;
memcpy(ifman.presentation_id, callback->presentation_id, 16);
ifman.decoder_name = ((TSMF_PLUGIN *) callback->plugin)->decoder_name;
ifman.audio_name = ((TSMF_PLUGIN *) callback->plugin)->audio_name;
ifman.audio_device = ((TSMF_PLUGIN *) callback->plugin)->audio_device;
memcpy(ifman.presentation_id, callback->presentation_id, GUID_SIZE);
ifman.stream_id = callback->stream_id;
ifman.message_id = MessageId;
ifman.input = input;
@ -160,139 +154,108 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
ifman.output = output;
ifman.output_pending = FALSE;
ifman.output_interface_id = InterfaceId;
switch (InterfaceId)
switch(InterfaceId)
{
case TSMF_INTERFACE_CAPABILITIES | STREAM_ID_NONE:
switch (FunctionId)
switch(FunctionId)
{
case RIM_EXCHANGE_CAPABILITY_REQUEST:
status = tsmf_ifman_rim_exchange_capability_request(&ifman);
break;
default:
break;
}
break;
case TSMF_INTERFACE_DEFAULT | STREAM_ID_PROXY:
switch (FunctionId)
switch(FunctionId)
{
case SET_CHANNEL_PARAMS:
memcpy(callback->presentation_id, Stream_Pointer(input), 16);
Stream_Seek(input, 16);
memcpy(callback->presentation_id, Stream_Pointer(input), GUID_SIZE);
Stream_Seek(input, GUID_SIZE);
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;
status = 0;
break;
case EXCHANGE_CAPABILITIES_REQ:
status = tsmf_ifman_exchange_capability_request(&ifman);
break;
case CHECK_FORMAT_SUPPORT_REQ:
status = tsmf_ifman_check_format_support_request(&ifman);
break;
case ON_NEW_PRESENTATION:
status = tsmf_ifman_on_new_presentation(&ifman);
break;
case ADD_STREAM:
status = tsmf_ifman_add_stream(&ifman);
break;
case SET_TOPOLOGY_REQ:
status = tsmf_ifman_set_topology_request(&ifman);
break;
case REMOVE_STREAM:
status = tsmf_ifman_remove_stream(&ifman);
break;
case SET_SOURCE_VIDEO_RECT:
status = tsmf_ifman_set_source_video_rect(&ifman);
break;
case SHUTDOWN_PRESENTATION_REQ:
status = tsmf_ifman_shutdown_presentation(&ifman);
break;
case ON_STREAM_VOLUME:
status = tsmf_ifman_on_stream_volume(&ifman);
break;
case ON_CHANNEL_VOLUME:
status = tsmf_ifman_on_channel_volume(&ifman);
break;
case SET_VIDEO_WINDOW:
status = tsmf_ifman_set_video_window(&ifman);
break;
case UPDATE_GEOMETRY_INFO:
status = tsmf_ifman_update_geometry_info(&ifman);
break;
case SET_ALLOCATOR:
status = tsmf_ifman_set_allocator(&ifman);
break;
case NOTIFY_PREROLL:
status = tsmf_ifman_notify_preroll(&ifman);
break;
case ON_SAMPLE:
status = tsmf_ifman_on_sample(&ifman);
break;
case ON_FLUSH:
status = tsmf_ifman_on_flush(&ifman);
break;
case ON_END_OF_STREAM:
status = tsmf_ifman_on_end_of_stream(&ifman);
break;
case ON_PLAYBACK_STARTED:
status = tsmf_ifman_on_playback_started(&ifman);
break;
case ON_PLAYBACK_PAUSED:
status = tsmf_ifman_on_playback_paused(&ifman);
break;
case ON_PLAYBACK_RESTARTED:
status = tsmf_ifman_on_playback_restarted(&ifman);
break;
case ON_PLAYBACK_STOPPED:
status = tsmf_ifman_on_playback_stopped(&ifman);
break;
case ON_PLAYBACK_RATE_CHANGED:
status = tsmf_ifman_on_playback_rate_changed(&ifman);
break;
default:
break;
}
break;
default:
break;
}
Stream_Free(input, FALSE);
input = NULL;
ifman.input = NULL;
if (status == -1)
if(status == -1)
{
switch (FunctionId)
switch(FunctionId)
{
case RIMCALL_RELEASE:
/* [MS-RDPEXPS] 2.2.2.2 Interface Release (IFACE_RELEASE)
@ -300,121 +263,98 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
status = 0;
ifman.output_pending = 1;
break;
case RIMCALL_QUERYINTERFACE:
/* [MS-RDPEXPS] 2.2.2.1.2 Query Interface Response (QI_RSP)
This message is not supported in this channel. */
status = 0;
break;
}
if (status == -1)
if(status == -1)
{
DEBUG_WARN("InterfaceId 0x%X FunctionId 0x%X not processed.",
InterfaceId, FunctionId);
InterfaceId, FunctionId);
/* When a request is not implemented we return empty response indicating error */
}
status = 0;
}
if (status == 0 && !ifman.output_pending)
if(status == 0 && !ifman.output_pending)
{
/* Response packet does not have FunctionId */
length = Stream_GetPosition(output);
Stream_SetPosition(output, 0);
Stream_Write_UINT32(output, ifman.output_interface_id);
Stream_Write_UINT32(output, MessageId);
DEBUG_DVC("response size %d", length);
DEBUG_TSMF("response size %d", length);
status = callback->channel->Write(callback->channel, length, Stream_Buffer(output), NULL);
if (status)
if(status)
{
DEBUG_WARN("response error %d", status);
}
}
Stream_Free(output, TRUE);
return status;
}
static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback)
static int tsmf_on_close(IWTSVirtualChannelCallback *pChannelCallback)
{
TSMF_STREAM* stream;
TSMF_PRESENTATION* presentation;
TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
DEBUG_DVC("");
if (callback->stream_id)
TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation;
TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
DEBUG_TSMF("");
if(callback->stream_id)
{
presentation = tsmf_presentation_find_by_id(callback->presentation_id);
if (presentation)
if(presentation)
{
stream = tsmf_stream_find_by_id(presentation, callback->stream_id);
if (stream)
if(stream)
tsmf_stream_free(stream);
}
}
free(pChannelCallback);
return 0;
}
static int tsmf_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
IWTSVirtualChannel* pChannel,
BYTE* Data,
int* pbAccept,
IWTSVirtualChannelCallback** ppCallback)
static int tsmf_on_new_channel_connection(IWTSListenerCallback *pListenerCallback,
IWTSVirtualChannel *pChannel,
BYTE *Data,
int *pbAccept,
IWTSVirtualChannelCallback **ppCallback)
{
TSMF_CHANNEL_CALLBACK* callback;
TSMF_LISTENER_CALLBACK* listener_callback = (TSMF_LISTENER_CALLBACK*) pListenerCallback;
DEBUG_DVC("");
callback = (TSMF_CHANNEL_CALLBACK*) malloc(sizeof(TSMF_CHANNEL_CALLBACK));
TSMF_CHANNEL_CALLBACK *callback;
TSMF_LISTENER_CALLBACK *listener_callback = (TSMF_LISTENER_CALLBACK *) pListenerCallback;
DEBUG_TSMF("");
callback = (TSMF_CHANNEL_CALLBACK *) malloc(sizeof(TSMF_CHANNEL_CALLBACK));
ZeroMemory(callback, sizeof(TSMF_CHANNEL_CALLBACK));
callback->iface.OnDataReceived = tsmf_on_data_received;
callback->iface.OnClose = tsmf_on_close;
callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel;
*ppCallback = (IWTSVirtualChannelCallback*) callback;
*ppCallback = (IWTSVirtualChannelCallback *) callback;
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;
DEBUG_DVC("");
tsmf->listener_callback = (TSMF_LISTENER_CALLBACK*) malloc(sizeof(TSMF_LISTENER_CALLBACK));
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
DEBUG_TSMF("");
tsmf->listener_callback = (TSMF_LISTENER_CALLBACK *) malloc(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->plugin = pPlugin;
tsmf->listener_callback->channel_mgr = pChannelMgr;
return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0,
(IWTSListenerCallback*) tsmf->listener_callback, NULL);
(IWTSListenerCallback *) tsmf->listener_callback, NULL);
}
static int tsmf_plugin_terminated(IWTSPlugin* pPlugin)
static int tsmf_plugin_terminated(IWTSPlugin *pPlugin)
{
TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
DEBUG_DVC("");
if (tsmf->listener_callback)
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
DEBUG_TSMF("");
if(tsmf->listener_callback)
free(tsmf->listener_callback);
free(tsmf);
return 0;
}
@ -426,27 +366,21 @@ COMMAND_LINE_ARGUMENT_A tsmf_args[] =
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
static void tsmf_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args)
{
int status;
DWORD flags;
COMMAND_LINE_ARGUMENT_A* arg;
TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
COMMAND_LINE_ARGUMENT_A *arg;
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
tsmf_args, flags, tsmf, NULL, NULL);
status = CommandLineParseArgumentsA(args->argc, (const char **) args->argv,
tsmf_args, flags, tsmf, NULL, NULL);
arg = tsmf_args;
do
{
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
if(!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
continue;
CommandLineSwitchStart(arg)
CommandLineSwitchCase(arg, "audio")
{
tsmf->audio_name = _strdup(arg->Value);
@ -461,43 +395,35 @@ static void tsmf_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
}
CommandLineSwitchDefault(arg)
{
}
CommandLineSwitchEnd(arg)
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
while((arg = CommandLineFindNextArgumentA(arg)) != NULL);
}
#ifdef STATIC_CHANNELS
#define DVCPluginEntry tsmf_DVCPluginEntry
#endif
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS *pEntryPoints)
{
int status = 0;
TSMF_PLUGIN* tsmf;
tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
if (tsmf == NULL)
TSMF_PLUGIN *tsmf;
tsmf = (TSMF_PLUGIN *) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
if(tsmf == NULL)
{
tsmf = (TSMF_PLUGIN*) malloc(sizeof(TSMF_PLUGIN));
tsmf = (TSMF_PLUGIN *) malloc(sizeof(TSMF_PLUGIN));
ZeroMemory(tsmf, sizeof(TSMF_PLUGIN));
tsmf->iface.Initialize = tsmf_plugin_initialize;
tsmf->iface.Connected = NULL;
tsmf->iface.Disconnected = NULL;
tsmf->iface.Terminated = tsmf_plugin_terminated;
status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf);
status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin *) tsmf);
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;
}

File diff suppressed because it is too large Load Diff

View File

@ -32,30 +32,31 @@ typedef struct _TSMF_STREAM TSMF_STREAM;
typedef struct _TSMF_SAMPLE TSMF_SAMPLE;
TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCallback* pChannelCallback);
TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE* guid);
void tsmf_presentation_start(TSMF_PRESENTATION* presentation);
void tsmf_presentation_stop(TSMF_PRESENTATION* presentation);
void tsmf_presentation_paused(TSMF_PRESENTATION* presentation);
void tsmf_presentation_restarted(TSMF_PRESENTATION* presentation);
void tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 newVolume, UINT32 muted);
void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation,
UINT32 x, UINT32 y, UINT32 width, UINT32 height,
int num_rects, RDP_RECT* rects);
void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation,
const char* name, const char* device);
void tsmf_presentation_flush(TSMF_PRESENTATION* presentation);
void tsmf_presentation_free(TSMF_PRESENTATION* presentation);
TSMF_PRESENTATION *tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback);
TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid);
void tsmf_presentation_start(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_restarted(TSMF_PRESENTATION *presentation);
void tsmf_presentation_volume_changed(TSMF_PRESENTATION *presentation, UINT32 newVolume, UINT32 muted);
void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation,
UINT32 x, UINT32 y, UINT32 width, UINT32 height,
int num_rects, RDP_RECT *rects);
void tsmf_presentation_set_audio_device(TSMF_PRESENTATION *presentation,
const char *name, const char *device);
void tsmf_presentation_flush(TSMF_PRESENTATION *presentation);
void tsmf_presentation_free(TSMF_PRESENTATION *presentation);
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id);
TSMF_STREAM* tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, UINT32 stream_id);
void tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, wStream* s);
void tsmf_stream_end(TSMF_STREAM* stream);
void tsmf_stream_free(TSMF_STREAM* stream);
TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id);
TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION *presentation, UINT32 stream_id);
void tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s);
void tsmf_stream_end(TSMF_STREAM *stream);
void tsmf_stream_free(TSMF_STREAM *stream);
void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pChannelCallback,
UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions,
UINT32 data_size, BYTE* data);
void tsmf_stream_push_sample(TSMF_STREAM *stream, IWTSVirtualChannelCallback *pChannelCallback,
UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions,
UINT32 data_size, BYTE *data);
void tsmf_media_init(void);

View File

@ -28,10 +28,10 @@
#include <freerdp/types.h>
#include <freerdp/utils/debug.h>
#ifdef WITH_DEBUG_DVC
#define DEBUG_DVC(fmt, ...) DEBUG_CLASS(DVC, fmt, ## __VA_ARGS__)
#ifdef WITH_DEBUG_TSMF
#define DEBUG_TSMF(fmt, ...) DEBUG_CLASS(TSMF, fmt, ## __VA_ARGS__)
#else
#define DEBUG_DVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#define DEBUG_TSMF(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
typedef struct _TS_AM_MEDIA_TYPE
@ -41,7 +41,7 @@ typedef struct _TS_AM_MEDIA_TYPE
int FormatType;
UINT32 Width;
UINT32 Height;
UINT32 Height;
UINT32 BitRate;
struct
{
@ -51,7 +51,7 @@ typedef struct _TS_AM_MEDIA_TYPE
UINT32 Channels;
UINT32 BitsPerSample;
UINT32 BlockAlign;
const BYTE* ExtraData;
const BYTE *ExtraData;
UINT32 ExtraDataSize;
} TS_AM_MEDIA_TYPE;

View File

@ -9,33 +9,28 @@
* the argument struct. */
#include "../common/cmdline.c"
LPSTR tmp = NULL;
LPSTR tr_esc_str(LPCSTR arg)
{
LPSTR tmp = NULL;
size_t cs = 0, x, ds;
size_t s;
if( NULL == arg )
if(NULL == arg)
return NULL;
s = strlen(arg);
/* Find trailing whitespaces */
while( (s > 0) && isspace(arg[s-1]))
while((s > 0) && isspace(arg[s-1]))
s--;
/* Prepare a initial buffer with the size of the result string. */
if (s)
tmp = (LPSTR)malloc(s * sizeof(CHAR));
if( NULL == tmp )
ds = s + 1;
if(s)
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if(NULL == tmp)
{
fprintf(stderr, "Could not allocate string buffer.");
exit(-2);
}
/* 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++)
{
switch(arg[x])
@ -43,7 +38,7 @@ LPSTR tr_esc_str(LPCSTR arg)
case '<':
ds += 3;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if( NULL == tmp )
if(NULL == tmp)
{
fprintf(stderr, "Could not reallocate string buffer.");
exit(-3);
@ -56,7 +51,7 @@ LPSTR tr_esc_str(LPCSTR arg)
case '>':
ds += 3;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if( NULL == tmp )
if(NULL == tmp)
{
fprintf(stderr, "Could not reallocate string buffer.");
exit(-4);
@ -69,7 +64,7 @@ LPSTR tr_esc_str(LPCSTR arg)
case '\'':
ds += 5;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if( NULL == tmp )
if(NULL == tmp)
{
fprintf(stderr, "Could not reallocate string buffer.");
exit(-5);
@ -84,7 +79,7 @@ LPSTR tr_esc_str(LPCSTR arg)
case '"':
ds += 5;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if( NULL == tmp )
if(NULL == tmp)
{
fprintf(stderr, "Could not reallocate string buffer.");
exit(-6);
@ -99,7 +94,7 @@ LPSTR tr_esc_str(LPCSTR arg)
case '&':
ds += 4;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if( NULL == tmp )
if(NULL == tmp)
{
fprintf(stderr, "Could not reallocate string buffer.");
exit(-7);
@ -114,11 +109,9 @@ LPSTR tr_esc_str(LPCSTR arg)
tmp[cs++] = arg[x];
break;
}
/* Assure, the string is '\0' terminated. */
tmp[ds-1] = '\0';
}
return tmp;
}
@ -128,51 +121,46 @@ int main(int argc, char *argv[])
size_t x;
const char *fname = "xfreerdp-argument.1.xml";
FILE *fp = NULL;
/* Open output file for writing, truncate if existing. */
fp = fopen(fname, "w");
if( NULL == fp )
if(NULL == fp)
{
fprintf(stderr, "Could not open '%s' for writing.", fname);
return -1;
}
/* The tag used as header in the manpage */
fprintf(fp, "<refsect1>\n");
fprintf(fp, "\t<title>Options</title>\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 */
if( elements < 2 )
if(elements < 2)
{
fprintf(stderr, "The argument array 'args' is empty, writing an empty file.");
elements = 1;
}
for(x=0; x<elements - 1; 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");
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) );
if(COMMAND_LINE_VALUE_REQUIRED == arg->Flags)
fprintf(fp, "\t\t\t\t<term><option>/%s</option> <replaceable>%s</replaceable></term>\n", name, format);
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\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</varlistentry>\n");
free(name);
free(format);
free(text);
}
fprintf(fp, "\t\t</variablelist>\n");
fprintf(fp, "\t</refsect1>\n");
fclose(fp);
if(NULL != tmp)
free(tmp);
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -71,10 +71,12 @@ struct xf_window
int bottom;
int width;
int height;
int shmid;
Window handle;
Window *xfwin;
BOOL fullscreen;
BOOL decorations;
rdpWindow* window;
rdpWindow *window;
BOOL is_mapped;
BOOL is_transient;
xfLocalMove local_move;
@ -82,39 +84,39 @@ struct xf_window
BOOL rail_ignore_configure;
};
void xf_ewmhints_init(xfContext* xfc);
void xf_ewmhints_init(xfContext *xfc);
BOOL xf_GetCurrentDesktop(xfContext* xfc);
BOOL xf_GetWorkArea(xfContext* xfc);
BOOL xf_GetCurrentDesktop(xfContext *xfc);
BOOL xf_GetWorkArea(xfContext *xfc);
void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen);
void xf_SetWindowDecorations(xfContext* xfc, xfWindow* window, BOOL show);
void xf_SetWindowUnlisted(xfContext* xfc, xfWindow* window);
void xf_SetWindowFullscreen(xfContext *xfc, xfWindow *window, BOOL fullscreen);
void xf_SetWindowDecorations(xfContext *xfc, xfWindow *window, BOOL show);
void xf_SetWindowUnlisted(xfContext *xfc, xfWindow *window);
xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height, BOOL decorations);
void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int height);
xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations);
void xf_ResizeDesktopWindow(xfContext *xfc, xfWindow *window, int width, int height);
xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int width, int height, UINT32 id);
void xf_SetWindowText(xfContext* xfc, xfWindow* window, char *name);
void xf_MoveWindow(xfContext* xfc, xfWindow* window, int x, int y, int width, int height);
void xf_ShowWindow(xfContext* xfc, xfWindow* window, BYTE state);
void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon);
void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects);
void xf_SetWindowVisibilityRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects);
void xf_SetWindowStyle(xfContext* xfc, xfWindow* window, UINT32 style, UINT32 ex_style);
void xf_UpdateWindowArea(xfContext* xfc, xfWindow* window, int x, int y, int width, int height);
BOOL xf_IsWindowBorder(xfContext* xfc, xfWindow* xfw, int x, int y);
void xf_DestroyWindow(xfContext* xfc, xfWindow* window);
rdpWindow* xf_rdpWindowFromWindow(xfContext* xfc, Window wnd);
xfWindow *xf_CreateWindow(xfContext *xfc, rdpWindow *wnd, int x, int y, int width, int height, UINT32 id);
void xf_SetWindowText(xfContext *xfc, xfWindow *window, char *name);
void xf_MoveWindow(xfContext *xfc, xfWindow *window, int x, int y, int width, int height);
void xf_ShowWindow(xfContext *xfc, xfWindow *window, BYTE state);
void xf_SetWindowIcon(xfContext *xfc, xfWindow *window, rdpIcon *icon);
void xf_SetWindowRects(xfContext *xfc, xfWindow *window, RECTANGLE_16 *rects, int nrects);
void xf_SetWindowVisibilityRects(xfContext *xfc, xfWindow *window, RECTANGLE_16 *rects, int nrects);
void xf_SetWindowStyle(xfContext *xfc, xfWindow *window, UINT32 style, UINT32 ex_style);
void xf_UpdateWindowArea(xfContext *xfc, xfWindow *window, int x, int y, int width, int height);
BOOL xf_IsWindowBorder(xfContext *xfc, xfWindow *xfw, int x, int y);
void xf_DestroyWindow(xfContext *xfc, xfWindow *window);
rdpWindow *xf_rdpWindowFromWindow(xfContext *xfc, Window wnd);
BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int length,
unsigned long* nitems, unsigned long* bytes, BYTE** prop);
BOOL xf_GetWindowProperty(xfContext *xfc, Window window, Atom property, int length,
unsigned long *nitems, unsigned long *bytes, BYTE **prop);
void xf_SetWindowMinMaxInfo(xfContext* xfc, xfWindow* window, int maxWidth, int maxHeight,
int maxPosX, int maxPosY, int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight);
void xf_SetWindowMinMaxInfo(xfContext *xfc, xfWindow *window, int maxWidth, int maxHeight,
int maxPosX, int maxPosY, int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight);
void xf_StartLocalMoveSize(xfContext* xfc, xfWindow* window, int direction, int x, int y);
void xf_EndLocalMoveSize(xfContext* xfc, xfWindow *window);
void xf_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs, ...);
void xf_StartLocalMoveSize(xfContext *xfc, xfWindow *window, int direction, int x, int y);
void xf_EndLocalMoveSize(xfContext *xfc, xfWindow *window);
void xf_SendClientEvent(xfContext *xfc, xfWindow *window, Atom atom, unsigned int numArgs, ...);
#endif /* __XF_WINDOW_H */

View File

@ -814,6 +814,38 @@ int freerdp_parse_username(char* username, char** user, char** domain)
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)
{
settings->ConnectionType = type;

View File

@ -767,10 +767,23 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
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)
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)
freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, file->DesktopWidth);
@ -802,12 +815,12 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
*
* Values:
*
* 0: The remote session will appear in a window.
* 1: The remote session will appear full screen.
* 1: The remote session will appear in a window.
* 2: The remote session will appear full screen.
*/
freerdp_set_param_bool(settings, FreeRDP_Fullscreen,
(file->ScreenModeId == 1) ? TRUE : FALSE);
(file->ScreenModeId == 2) ? TRUE : FALSE);
}
if (~((size_t) file->SmartSizing))
@ -867,7 +880,19 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
freerdp_set_param_bool(settings, FreeRDP_CompressionEnabled, file->Compression);
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)
freerdp_set_gateway_usage_method(settings, file->GatewayUsageMethod);

View File

@ -100,6 +100,7 @@ option(WITH_DEBUG_CAPABILITIES "Print capability negotiation debug messages." ${
option(WITH_DEBUG_CHANNELS "Print channel manager debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_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_TSMF "Print TSMF virtual channel 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_LICENSE "Print license debug messages." ${DEFAULT_DEBUG_OPTION})

View File

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

View File

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

43
cmake/FindGlib.cmake Normal file
View File

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

View File

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

116
cmake/LibFindMacros.cmake Normal file
View File

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

View File

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

View File

@ -0,0 +1,63 @@
/*
* FreeRDP: A Remote Desktop Protocol Implementation
* Video Redirection Virtual Channel - Callback interface
*
* (C) Copyright 2014 Thincast Technologies GmbH
* (C) Copyright 2014 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _TSMF_H_
#define _TSMF_H_
#include <freerdp/types.h>
/* Callback function setup order:
*
* When the channel is loaded, it calls TSMF_REGISTER to register the
* decoder handle with the client.
* The client then stores the handle and calls TSMF_REGISTER_INSTANCE
* to give the channel the current handle to the session necessary
* to call other functions.
* After this initial setup the other functions can be used.
*/
/* Functions called from client -> registered by channel */
#define TSMF_GET_INSTANCE "tsmf_get_instance"
typedef void (*tsmf_get_instance)(void *instance, void *decoder);
#define TSMF_ADD_WINDOW_HANDLE "tsmf_add_window_handle"
typedef void (*tsmf_add_window_handle)(void *instance, void *decoder, void *window);
#define TSMF_DEL_WINDOW_HANDLE "tsmf_del_window_handle"
typedef void (*tsmf_del_window_handle)(void *instance, void *decoder);
/* Functions called from channel -> registered by client */
#define TSMF_REGISTER "tsmf_register"
typedef void (*tsmf_register)(void *instance, void *decoder);
#define TSMF_DESTROY "tsmf_destroy"
typedef void (*tsmf_destroy)(void *instance, void *decoder);
#define TSMF_PLAY "tsmf_play"
typedef void (*tsmf_play)(void *instance, void *decoder);
#define TSMF_PAUSE "tsmf_pause"
typedef void (*tsmf_pause)(void *instance, void *decoder);
#define TSMF_RESIZE_WINDOW "tsmf_resize_window"
typedef void (*tsmf_resize_window)(void *instance, void *decoder, int x, int y, int width,
int height, int nr_rect, RDP_RECT *visible);
#endif

View File

@ -35,6 +35,7 @@ FREERDP_API int freerdp_client_print_version(void);
FREERDP_API int freerdp_client_print_command_line_help(int argc, char** argv);
FREERDP_API int freerdp_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_client_add_device_channel(rdpSettings* settings, int count, char** params);

View File

@ -72,7 +72,6 @@ struct rdp_tls
void* tsg;
SSL_CTX* ctx;
BYTE* PublicKey;
BIO_METHOD* methods;
DWORD PublicKeyLength;
rdpSettings* settings;
SecPkgContext_Bindings* Bindings;

View File

@ -65,96 +65,100 @@ typedef struct _IWTSVirtualChannelCallback IWTSVirtualChannelCallback;
struct _IWTSListener
{
/* Retrieves the listener-specific configuration. */
int (*GetConfiguration) (IWTSListener* pListener,
void** ppPropertyBag);
int (*GetConfiguration)(IWTSListener *pListener,
void **ppPropertyBag);
void* pInterface;
void *pInterface;
};
struct _IWTSVirtualChannel
{
/* Starts a write request on the channel. */
int (*Write) (IWTSVirtualChannel* pChannel,
UINT32 cbSize,
BYTE* pBuffer,
void* pReserved);
int (*Write)(IWTSVirtualChannel *pChannel,
UINT32 cbSize,
BYTE *pBuffer,
void *pReserved);
/* Closes the channel. */
int (*Close) (IWTSVirtualChannel* pChannel);
int (*Close)(IWTSVirtualChannel *pChannel);
};
struct _IWTSVirtualChannelManager
{
/* Returns an instance of a listener object that listens on a specific
endpoint, or creates a static channel. */
int (*CreateListener) (IWTSVirtualChannelManager* pChannelMgr,
const char* pszChannelName,
UINT32 ulFlags,
IWTSListenerCallback* pListenerCallback,
IWTSListener** ppListener);
int (*CreateListener)(IWTSVirtualChannelManager *pChannelMgr,
const char *pszChannelName,
UINT32 ulFlags,
IWTSListenerCallback *pListenerCallback,
IWTSListener **ppListener);
/* Push a virtual channel event.
This is a FreeRDP extension to standard MS API. */
int (*PushEvent) (IWTSVirtualChannelManager* pChannelMgr,
wMessage* pEvent);
int (*PushEvent)(IWTSVirtualChannelManager *pChannelMgr,
wMessage *pEvent);
/* Find the channel or ID to send data to a specific endpoint. */
UINT32 (*GetChannelId) (IWTSVirtualChannel * channel);
IWTSVirtualChannel* (*FindChannelById) (IWTSVirtualChannelManager* pChannelMgr,
UINT32 ChannelId);
UINT32(*GetChannelId)(IWTSVirtualChannel *channel);
IWTSVirtualChannel *(*FindChannelById)(IWTSVirtualChannelManager *pChannelMgr,
UINT32 ChannelId);
};
struct _IWTSPlugin
{
/* Used for the first call that is made from the client to the plug-in. */
int (*Initialize) (IWTSPlugin* pPlugin,
IWTSVirtualChannelManager* pChannelMgr);
int (*Initialize)(IWTSPlugin *pPlugin,
IWTSVirtualChannelManager *pChannelMgr);
/* Notifies the plug-in that the Remote Desktop Connection (RDC) client
has successfully connected to the Remote Desktop Session Host (RD
Session Host) server. */
int (*Connected) (IWTSPlugin* pPlugin);
int (*Connected)(IWTSPlugin *pPlugin);
/* Notifies the plug-in that the Remote Desktop Connection (RDC) client
has disconnected from the RD Session Host server. */
int (*Disconnected) (IWTSPlugin* pPlugin,
UINT32 dwDisconnectCode);
int (*Disconnected)(IWTSPlugin *pPlugin,
UINT32 dwDisconnectCode);
/* Notifies the plug-in that the Remote Desktop Connection (RDC) client
has terminated. */
int (*Terminated) (IWTSPlugin* pPlugin);
int (*Terminated)(IWTSPlugin *pPlugin);
/* Extended */
void* pInterface;
void *pInterface;
};
struct _IWTSListenerCallback
{
/* Accepts or denies a connection request for an incoming connection to
the associated listener. */
int (*OnNewChannelConnection) (IWTSListenerCallback* pListenerCallback,
IWTSVirtualChannel* pChannel,
BYTE* Data,
int* pbAccept,
IWTSVirtualChannelCallback** ppCallback);
int (*OnNewChannelConnection)(IWTSListenerCallback *pListenerCallback,
IWTSVirtualChannel *pChannel,
BYTE *Data,
int *pbAccept,
IWTSVirtualChannelCallback **ppCallback);
};
struct _IWTSVirtualChannelCallback
{
/* Notifies the user about data that is being received. */
int (*OnDataReceived) (IWTSVirtualChannelCallback* pChannelCallback,
UINT32 cbSize,
BYTE* pBuffer);
int (*OnDataReceived)(IWTSVirtualChannelCallback *pChannelCallback,
UINT32 cbSize,
BYTE *pBuffer);
/* Notifies the user that the channel has been closed. */
int (*OnClose) (IWTSVirtualChannelCallback* pChannelCallback);
int (*OnClose)(IWTSVirtualChannelCallback *pChannelCallback);
};
/* The DVC Plugin entry points */
typedef struct _IDRDYNVC_ENTRY_POINTS IDRDYNVC_ENTRY_POINTS;
struct _IDRDYNVC_ENTRY_POINTS
{
int (*RegisterPlugin) (IDRDYNVC_ENTRY_POINTS* pEntryPoints,
const char* name, IWTSPlugin* pPlugin);
IWTSPlugin* (*GetPlugin) (IDRDYNVC_ENTRY_POINTS* pEntryPoints,
const char* name);
ADDIN_ARGV* (*GetPluginData) (IDRDYNVC_ENTRY_POINTS* pEntryPoints);
int (*RegisterPlugin)(IDRDYNVC_ENTRY_POINTS *pEntryPoints,
const char *name, IWTSPlugin *pPlugin);
IWTSPlugin *(*GetPlugin)(IDRDYNVC_ENTRY_POINTS *pEntryPoints,
const char *name);
ADDIN_ARGV *(*GetPluginData)(IDRDYNVC_ENTRY_POINTS *pEntryPoints);
};
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 */

View File

@ -85,11 +85,7 @@
#define WITH_DEBUG_CREDSSP
#endif
#ifdef WITH_NATIVE_SSPI
#define NLA_PKG_NAME NTLMSP_NAME
#else
#define NLA_PKG_NAME NTLMSP_NAME
#endif
#define NLA_PKG_NAME NEGOSSP_NAME
#define TERMSRV_SPN_PREFIX "TERMSRV/"
@ -267,24 +263,7 @@ int credssp_client_authenticate(rdpCredssp* credssp)
if (credssp_ntlm_client_init(credssp) == 0)
return 0;
#ifdef WITH_NATIVE_SSPI
{
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
credssp->table = InitSecurityInterfaceEx(0);
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,
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);
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);
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;
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);
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 */
@ -469,11 +451,6 @@ int credssp_server_authenticate(rdpCredssp* credssp)
if (credssp_ntlm_server_init(credssp) == 0)
return 0;
#ifdef WITH_NATIVE_SSPI
if (!credssp->SspiModule)
credssp->SspiModule = _tcsdup(_T("secur32.dll"));
#endif
if (credssp->SspiModule)
{
HMODULE hSSPI;
@ -493,14 +470,12 @@ int credssp_server_authenticate(rdpCredssp* credssp)
pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA");
#endif
credssp->table = (*pInitSecurityInterface)();
credssp->table = pInitSecurityInterface();
}
#ifndef WITH_NATIVE_SSPI
else
{
credssp->table = InitSecurityInterface();
credssp->table = InitSecurityInterfaceEx(0);
}
#endif
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 (credssp->table->CompleteAuthToken != NULL)
if (credssp->table->CompleteAuthToken)
credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc);
if (status == SEC_I_COMPLETE_NEEDED)
@ -1385,7 +1360,7 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings*
{
rdpCredssp* credssp;
credssp = (rdpCredssp*) malloc(sizeof(rdpCredssp));
credssp = (rdpCredssp*) calloc(1, sizeof(rdpCredssp));
if (credssp)
{
@ -1394,8 +1369,6 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings*
DWORD dwType;
DWORD dwSize;
ZeroMemory(credssp, sizeof(rdpCredssp));
credssp->instance = instance;
credssp->settings = settings;
credssp->server = settings->ServerMode;

View File

@ -431,8 +431,7 @@ void freerdp_peer_context_new(freerdp_peer* client)
{
rdpRdp* rdp;
client->context = (rdpContext*) malloc(client->ContextSize);
ZeroMemory(client->context, client->ContextSize);
client->context = (rdpContext *)calloc(1, client->ContextSize);
client->context->ServerMode = TRUE;
@ -470,6 +469,8 @@ void freerdp_peer_context_new(freerdp_peer* client)
void freerdp_peer_context_free(freerdp_peer* client)
{
IFCALL(client->ContextFree, client, client->context);
metrics_free(client->context->metrics);
}
freerdp_peer* freerdp_peer_new(int sockfd)

View File

@ -427,9 +427,11 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer)
if (channel)
{
ULONG written;
vcm->drdynvc_channel = channel;
dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */
WTSVirtualChannelWrite(channel, (PCHAR) &dynvc_caps, sizeof(dynvc_caps), NULL);
WTSVirtualChannelWrite(channel, (PCHAR) &dynvc_caps, sizeof(dynvc_caps), &written);
}
}
@ -916,6 +918,7 @@ HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualNam
BOOL joined = FALSE;
freerdp_peer* client;
rdpPeerChannel* channel;
ULONG written;
WTSVirtualChannelManager* vcm;
if (SessionId == WTS_CURRENT_SESSION)
@ -968,7 +971,7 @@ HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualNam
s = Stream_New(NULL, 64);
wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName);
WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_Free(s, TRUE);
return channel;
@ -997,9 +1000,11 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle)
if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED)
{
ULONG written;
s = Stream_New(NULL, 8);
wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channelId);
WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
Stream_Free(s, TRUE);
}
}

View File

@ -1112,7 +1112,7 @@ int transport_check_fds(rdpTransport* transport)
return status;
if ((pos = Stream_GetPosition(transport->ReceiveBuffer)) < 2)
return status;
return 0;
Stream_SetPosition(transport->ReceiveBuffer, 0);
length = 0;

View File

@ -480,7 +480,7 @@ static CryptoCert tls_get_certificate(rdpTls* tls, BOOL peer)
if (peer)
remote_cert = SSL_get_peer_certificate(tls->ssl);
else
remote_cert = SSL_get_certificate(tls->ssl);
remote_cert = X509_dup( SSL_get_certificate(tls->ssl) );
if (!remote_cert)
{
@ -624,9 +624,6 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
}
while (TRUE);
if (!clientMode)
return 1;
cert = tls_get_certificate(tls, clientMode);
if (!cert)
{
@ -638,26 +635,34 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
if (!tls->Bindings)
{
fprintf(stderr, "%s: unable to retrieve bindings\n", __FUNCTION__);
return -1;
verify_status = -1;
goto out;
}
if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
{
fprintf(stderr, "%s: crypto_cert_get_public_key failed to return the server public key.\n", __FUNCTION__);
tls_free_certificate(cert);
return -1;
verify_status = -1;
goto out;
}
verify_status = tls_verify_certificate(tls, cert, tls->hostname, tls->port);
if (verify_status < 1)
/* Note: server-side NLA needs public keys (keys from us, the server) but no
* certificate verify
*/
verify_status = 1;
if (clientMode)
{
fprintf(stderr, "%s: certificate not trusted, aborting.\n", __FUNCTION__);
tls_disconnect(tls);
tls_free_certificate(cert);
return 0;
verify_status = tls_verify_certificate(tls, cert, tls->hostname, tls->port);
if (verify_status < 1)
{
fprintf(stderr, "%s: certificate not trusted, aborting.\n", __FUNCTION__);
tls_disconnect(tls);
verify_status = 0;
}
}
out:
tls_free_certificate(cert);
return verify_status;

23
scripts/format_code.sh Executable file
View File

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

View File

@ -405,6 +405,7 @@ static void* tf_debug_channel_thread_func(void* arg)
wStream* s;
void* buffer;
DWORD BytesReturned = 0;
ULONG written;
testPeerContext* context = (testPeerContext*) arg;
if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &BytesReturned) == TRUE)
@ -417,7 +418,7 @@ static void* tf_debug_channel_thread_func(void* arg)
s = Stream_New(NULL, 4096);
WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test1", 5, NULL);
WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test1", 5, &written);
while (1)
{
@ -583,7 +584,8 @@ void tf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{
if (context->debug_channel)
{
WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test2", 5, NULL);
ULONG written;
WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test2", 5, &written);
}
}
else if ((flags & 0x4000) && code == 0x2D) /* 'x' key */

View File

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

View File

@ -67,9 +67,6 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINPR_EXPORTS")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${CMAKE_CURRENT_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(libwinpr)

View File

@ -29,7 +29,22 @@
#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 */
@ -60,7 +75,6 @@ typedef ULONG_PTR NCRYPT_SECRET_HANDLE;
#define ALG_TYPE_STREAM (4 << 9)
#define ALG_TYPE_DH (5 << 9)
#define ALG_TYPE_SECURECHANNEL (6 << 9)
#define ALG_TYPE_RESERVED7 (7 << 9)
#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_DMS 2
#define ALG_SID_ECDSA 3
#define ALG_SID_DES 1
#define ALG_SID_3DES 3
#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_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
{
@ -594,5 +605,10 @@ BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, L
#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 */

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* you may not use this file except in compliance with the License.
@ -20,37 +20,23 @@
#ifndef WINPR_SSPI_H
#define WINPR_SSPI_H
#include <winpr/config.h>
#include <wchar.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/windows.h>
#include <winpr/security.h>
#define _NO_KSECDD_IMPORT_ 1
#ifdef _WIN32
#include <tchar.h>
#include <winerror.h>
#ifdef WITH_NATIVE_SSPI
#define SECURITY_WIN32
#include <sspi.h>
#include <security.h>
#else
#define WINPR_SSPI
#define SEC_ENTRY __stdcall
#endif
#else
#define WINPR_SSPI
#endif
#ifdef WINPR_SSPI
#ifndef _WIN32
#ifndef SEC_ENTRY
#define SEC_ENTRY
@ -266,7 +252,7 @@ typedef SecPkgInfoW* PSecPkgInfoW;
#define SECPKG_ATTR_NEGO_STATUS 32
#define SECPKG_ATTR_CONTEXT_DELETED 33
#ifdef WINPR_SSPI
#ifndef _WIN32
struct _SecPkgContext_AccessToken
{
@ -593,7 +579,7 @@ typedef SecPkgCredentials_NamesW* PSecPkgCredentials_NamesW;
#define SEC_WINNT_AUTH_IDENTITY_ANSI 0x1
#define SEC_WINNT_AUTH_IDENTITY_UNICODE 0x2
#ifdef WINPR_SSPI
#ifndef _WIN32
typedef struct _SEC_WINNT_AUTH_IDENTITY_W
{
@ -679,7 +665,7 @@ typedef CtxtHandle* PCtxtHandle;
#define SECBUFFER_READONLY_WITH_CHECKSUM 0x10000000
#define SECBUFFER_RESERVED 0x60000000
#ifdef WINPR_SSPI
#ifndef _WIN32
struct _SecBuffer
{
@ -1000,8 +986,7 @@ WINPR_API SECURITY_STATUS SEC_ENTRY VerifySignature(PCtxtHandle phContext, PSecB
}
#endif
#endif // WINPR_SSPI
#endif
#ifdef __cplusplus
extern "C" {
@ -1009,14 +994,56 @@ extern "C" {
/* 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_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_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, char* user, char* domain, char* password);
WINPR_API void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDENTITY* srcIdentity);
WINPR_API int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain, const char* password);
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
}

View File

@ -62,7 +62,11 @@ WINPR_API BOOL TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZon
#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 BOOL SetDynamicTimeZoneInformation(const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation);

View File

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

View File

@ -361,8 +361,6 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
{
io_status = nNumberOfBytesToRead;
if (pipe->clientfd == -1)
return FALSE;
@ -374,9 +372,9 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
{
case ECONNRESET:
SetLastError(ERROR_BROKEN_PIPE);
io_status = 0;
break;
}
status = FALSE;
}
else if (io_status < 0)
{

View File

@ -165,35 +165,24 @@ BOOL CloseHandle(HANDLE hObject)
}
else if (Type == HANDLE_TYPE_NAMED_PIPE)
{
WINPR_NAMED_PIPE* pipe;
WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*) Object;
pipe = (WINPR_NAMED_PIPE*) Object;
if (pipe->ServerMode)
{
assert(pipe->dwRefCount);
if (--pipe->dwRefCount == 0)
{
pipe->pfnRemoveBaseNamedPipeFromList(pipe);
if (pipe->pBaseNamedPipe)
{
CloseHandle((HANDLE) pipe->pBaseNamedPipe);
}
}
if (pNamedPipe->clientfd != -1) {
//fprintf(stderr, "%s: closing clientfd %d\n", __FUNCTION__, pNamedPipe->clientfd);
close(pNamedPipe->clientfd);
}
if (pNamedPipe->serverfd != -1) {
//fprintf(stderr, "%s: closing serverfd %d\n", __FUNCTION__, pNamedPipe->serverfd);
close(pNamedPipe->serverfd);
}
if (pipe->clientfd != -1)
close(pipe->clientfd);
if (pNamedPipe->pfnUnrefNamedPipe)
pNamedPipe->pfnUnrefNamedPipe(pNamedPipe);
if (pipe->serverfd != -1)
close(pipe->serverfd);
free((char *)pipe->lpFileName);
free((char *)pipe->lpFilePath);
free((char *)pipe->name);
free(pipe);
free((void*)pNamedPipe->lpFileName);
free((void*)pNamedPipe->lpFilePath);
free((void*)pNamedPipe->name);
free(pNamedPipe);
return TRUE;
}

View File

@ -21,6 +21,7 @@
#define WINPR_HANDLE_PRIVATE_H
#include <winpr/handle.h>
#include <winpr/file.h>
#define HANDLE_TYPE_NONE 0
#define HANDLE_TYPE_PROCESS 1
@ -52,7 +53,7 @@ static inline BOOL winpr_Handle_GetInfo(HANDLE handle, ULONG* pType, PVOID* pObj
{
WINPR_HANDLE* wHandle;
if (handle == NULL)
if (handle == NULL || handle == INVALID_HANDLE_VALUE)
return FALSE;
wHandle = (WINPR_HANDLE*) handle;

View File

@ -41,6 +41,7 @@
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <assert.h>
#include "pipe.h"
@ -48,34 +49,32 @@
* Since the WinPR implementation of named pipes makes use of UNIX domain
* sockets, it is not possible to bind the same name more than once (i.e.,
* SO_REUSEADDR does not work with UNIX domain sockets). As a result, the
* first call to CreateNamedPipe must create the UNIX domain socket and
* subsequent calls to CreateNamedPipe will reference the first named pipe
* handle and duplicate the socket descriptor.
* first call to CreateNamedPipe with name n creates a "shared" UNIX domain
* socket descriptor that gets duplicated via dup() for the first and all
* subsequent calls to CreateNamedPipe with name n.
*
* The following array keeps track of the named pipe handles for the first
* instance. If multiple instances are created, subsequent instances store
* a pointer to the first instance and a reference count is maintained. When
* the last instance is closed, the named pipe handle is removed from the list.
* The following array keeps track of the references to the shared socked
* descriptors. If an entry's reference count is zero the base socket
* descriptor gets closed and the entry is removed from the list.
*/
static wArrayList* g_BaseNamedPipeList = NULL;
static wArrayList* g_NamedPipeServerSockets = NULL;
static BOOL g_Initialized = FALSE;
typedef struct _NamedPipeServerSocketEntry
{
char* name;
int serverfd;
int references;
} NamedPipeServerSocketEntry;
static void InitWinPRPipeModule()
{
if (g_Initialized)
if (g_NamedPipeServerSockets)
return;
g_BaseNamedPipeList = ArrayList_New(TRUE);
g_Initialized = TRUE;
g_NamedPipeServerSockets = ArrayList_New(FALSE);
}
void WinPR_RemoveBaseNamedPipeFromList(WINPR_NAMED_PIPE* pNamedPipe)
{
ArrayList_Remove(g_BaseNamedPipeList, pNamedPipe);
}
/*
* Unnamed pipe
@ -126,48 +125,70 @@ BOOL CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpP
* Named pipe
*/
static void winpr_unref_named_pipe(WINPR_NAMED_PIPE* pNamedPipe)
{
int index;
NamedPipeServerSocketEntry *baseSocket;
if (!pNamedPipe)
return;
assert(pNamedPipe->name);
assert(g_NamedPipeServerSockets);
//fprintf(stderr, "%s: %p (%s)\n", __FUNCTION__, pNamedPipe, pNamedPipe->name);
ArrayList_Lock(g_NamedPipeServerSockets);
for (index = 0; index < ArrayList_Count(g_NamedPipeServerSockets); index++)
{
baseSocket = (NamedPipeServerSocketEntry*) ArrayList_GetItem(
g_NamedPipeServerSockets, index);
assert(baseSocket->name);
if (!strcmp(baseSocket->name, pNamedPipe->name))
{
assert(baseSocket->references > 0);
assert(baseSocket->serverfd != -1);
if (--baseSocket->references == 0)
{
//fprintf(stderr, "%s: removing shared server socked resource\n", __FUNCTION__);
//fprintf(stderr, "%s: closing shared serverfd %d\n", __FUNCTION__, baseSocket->serverfd);
ArrayList_Remove(g_NamedPipeServerSockets, baseSocket);
close(baseSocket->serverfd);
free(baseSocket->name);
free(baseSocket);
}
break;
}
}
ArrayList_Unlock(g_NamedPipeServerSockets);
}
HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances,
DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
int index;
int status;
HANDLE hNamedPipe;
HANDLE hNamedPipe = INVALID_HANDLE_VALUE;
char* lpPipePath;
struct sockaddr_un s;
WINPR_NAMED_PIPE* pNamedPipe;
WINPR_NAMED_PIPE* pBaseNamedPipe;
WINPR_NAMED_PIPE* pNamedPipe = NULL;
int serverfd = -1;
NamedPipeServerSocketEntry *baseSocket = NULL;
if (!lpName)
return INVALID_HANDLE_VALUE;
InitWinPRPipeModule();
/* Find the base named pipe instance (i.e., the first instance). */
pBaseNamedPipe = NULL;
ArrayList_Lock(g_BaseNamedPipeList);
for (index = 0; index < ArrayList_Count(g_BaseNamedPipeList); index++)
{
WINPR_NAMED_PIPE* p = (WINPR_NAMED_PIPE*) ArrayList_GetItem(g_BaseNamedPipeList, index);
if (strcmp(p->name, lpName) == 0)
{
pBaseNamedPipe = p;
break;
}
}
ArrayList_Unlock(g_BaseNamedPipeList);
pNamedPipe = (WINPR_NAMED_PIPE*) malloc(sizeof(WINPR_NAMED_PIPE));
hNamedPipe = (HANDLE) pNamedPipe;
pNamedPipe = (WINPR_NAMED_PIPE*) calloc(1, sizeof(WINPR_NAMED_PIPE));
WINPR_HANDLE_SET_TYPE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE);
pNamedPipe->pfnRemoveBaseNamedPipeFromList = WinPR_RemoveBaseNamedPipeFromList;
pNamedPipe->name = _strdup(lpName);
if (!(pNamedPipe->name = _strdup(lpName)))
goto out;
if (!(pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpName)))
goto out;
if (!(pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpName)))
goto out;
pNamedPipe->dwOpenMode = dwOpenMode;
pNamedPipe->dwPipeMode = dwPipeMode;
pNamedPipe->nMaxInstances = nMaxInstances;
@ -176,20 +197,29 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD
pNamedPipe->nDefaultTimeOut = nDefaultTimeOut;
pNamedPipe->dwFlagsAndAttributes = dwOpenMode;
pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpName);
pNamedPipe->clientfd = -1;
pNamedPipe->ServerMode = TRUE;
pNamedPipe->pBaseNamedPipe = pBaseNamedPipe;
pNamedPipe->dwRefCount = 1;
ArrayList_Lock(g_NamedPipeServerSockets);
for (index = 0; index < ArrayList_Count(g_NamedPipeServerSockets); index++)
{
baseSocket = (NamedPipeServerSocketEntry*) ArrayList_GetItem(
g_NamedPipeServerSockets, index);
if (!strcmp(baseSocket->name, lpName))
{
serverfd = baseSocket->serverfd;
//fprintf(stderr, "using shared socked resource for pipe %p (%s)\n", pNamedPipe, lpName);
break;
}
}
/* If this is the first instance of the named pipe... */
if (pBaseNamedPipe == NULL)
if (serverfd == -1)
{
/* Create the UNIX domain socket and start listening. */
lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
if (!(lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA()))
goto out;
if (!PathFileExistsA(lpPipePath))
{
@ -204,48 +234,49 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD
DeleteFileA(pNamedPipe->lpFilePath);
}
pNamedPipe->serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (pNamedPipe->serverfd == -1)
if ((serverfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "CreateNamedPipeA: socket error, %s\n", strerror(errno));
goto err_out;
goto out;
}
ZeroMemory(&s, sizeof(struct sockaddr_un));
s.sun_family = AF_UNIX;
strcpy(s.sun_path, pNamedPipe->lpFilePath);
status = bind(pNamedPipe->serverfd, (struct sockaddr*) &s, sizeof(struct sockaddr_un));
if (status != 0)
if (bind(serverfd, (struct sockaddr*) &s, sizeof(struct sockaddr_un)) == -1)
{
fprintf(stderr, "CreateNamedPipeA: bind error, %s\n", strerror(errno));
goto err_out;
goto out;
}
status = listen(pNamedPipe->serverfd, 2);
if (status != 0)
if (listen(serverfd, 2) == -1)
{
fprintf(stderr, "CreateNamedPipeA: listen error, %s\n", strerror(errno));
goto err_out;
goto out;
}
UnixChangeFileMode(pNamedPipe->lpFilePath, 0xFFFF);
/* Add the named pipe to the list of base named pipe instances. */
ArrayList_Add(g_BaseNamedPipeList, pNamedPipe);
}
else
{
/* Duplicate the file handle for the UNIX domain socket in the first instance. */
pNamedPipe->serverfd = dup(pBaseNamedPipe->serverfd);
if (!(baseSocket = (NamedPipeServerSocketEntry *) malloc(sizeof(NamedPipeServerSocketEntry))))
goto out;
if (!(baseSocket->name = _strdup(lpName)))
{
free(baseSocket);
goto out;
}
baseSocket->serverfd = serverfd;
baseSocket->references = 0;
ArrayList_Add(g_NamedPipeServerSockets, baseSocket);
//fprintf(stderr, "created shared socked resource for pipe %p (%s). base serverfd = %d\n", pNamedPipe, lpName, serverfd);
/* Update the reference count in the base named pipe instance. */
pBaseNamedPipe->dwRefCount++;
}
pNamedPipe->serverfd = dup(baseSocket->serverfd);
//fprintf(stderr, "using serverfd %d (duplicated from %d)\n", pNamedPipe->serverfd, baseSocket->serverfd);
pNamedPipe->pfnUnrefNamedPipe = winpr_unref_named_pipe;
baseSocket->references++;
if (dwOpenMode & FILE_FLAG_OVERLAPPED)
{
#if 0
@ -256,15 +287,23 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD
#endif
}
return hNamedPipe;
hNamedPipe = (HANDLE) pNamedPipe;
err_out:
if (pNamedPipe) {
if (pNamedPipe->serverfd != -1)
close(pNamedPipe->serverfd);
free(pNamedPipe);
out:
if (hNamedPipe == INVALID_HANDLE_VALUE)
{
if (pNamedPipe)
{
free((void*)pNamedPipe->name);
free((void*)pNamedPipe->lpFileName);
free((void*)pNamedPipe->lpFilePath);
free(pNamedPipe);
}
if (serverfd != -1)
close(serverfd);
}
return INVALID_HANDLE_VALUE;
ArrayList_Unlock(g_NamedPipeServerSockets);
return hNamedPipe;
}
HANDLE CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances,

View File

@ -27,6 +27,7 @@
#include "../handle/handle.h"
struct winpr_pipe
{
WINPR_HANDLE_DEF();
@ -37,7 +38,7 @@ typedef struct winpr_pipe WINPR_PIPE;
typedef struct winpr_named_pipe WINPR_NAMED_PIPE;
typedef void ( * fnRemoveBaseNamedPipeFromList)(WINPR_NAMED_PIPE* pNamedPipe);
typedef void(*fnUnrefNamedPipe)(WINPR_NAMED_PIPE* pNamedPipe);
struct winpr_named_pipe
{
@ -60,13 +61,11 @@ struct winpr_named_pipe
DWORD dwFlagsAndAttributes;
LPOVERLAPPED lpOverlapped;
fnRemoveBaseNamedPipeFromList pfnRemoveBaseNamedPipeFromList;
WINPR_NAMED_PIPE* pBaseNamedPipe;
DWORD dwRefCount;
fnUnrefNamedPipe pfnUnrefNamedPipe;
};
BOOL winpr_destroy_named_pipe(WINPR_NAMED_PIPE* pNamedPipe);
#endif
#endif /* WINPR_PIPE_PRIVATE_H */

View File

@ -8,18 +8,25 @@
#include <winpr/print.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#ifndef _WIN32
#include <signal.h>
#endif
#include "../pipe.h"
#define PIPE_BUFFER_SIZE 32
static HANDLE ReadyEvent;
static LPTSTR lpszPipeName = _T("\\\\.\\pipe\\winpr_test_pipe");
static LPTSTR lpszPipeNameMt = _T("\\\\.\\pipe\\winpr_test_pipe_mt");
static LPTSTR lpszPipeNameSt = _T("\\\\.\\pipe\\winpr_test_pipe_st");
BOOL testFailed = FALSE;
static void* named_pipe_client_thread(void* arg)
{
HANDLE hNamedPipe;
BYTE* lpReadBuffer;
BYTE* lpWriteBuffer;
HANDLE hNamedPipe = NULL;
BYTE* lpReadBuffer = NULL;
BYTE* lpWriteBuffer = NULL;
BOOL fSuccess = FALSE;
DWORD nNumberOfBytesToRead;
DWORD nNumberOfBytesToWrite;
@ -28,39 +35,42 @@ static void* named_pipe_client_thread(void* arg)
WaitForSingleObject(ReadyEvent, INFINITE);
hNamedPipe = CreateFile(lpszPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
hNamedPipe = CreateFile(lpszPipeNameMt, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (!hNamedPipe)
{
printf("Named Pipe CreateFile failure: NULL handle\n");
return NULL;
printf("%s:Named Pipe CreateFile failure: NULL handle\n", __FUNCTION__);
goto out;
}
if (hNamedPipe == INVALID_HANDLE_VALUE)
{
printf("Named Pipe CreateFile failure: INVALID_HANDLE_VALUE\n");
return NULL;
printf("%s: Named Pipe CreateFile failure: INVALID_HANDLE_VALUE\n", __FUNCTION__);
goto out;
}
lpReadBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE);
lpWriteBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE);
if (!(lpReadBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE)))
{
printf("%s: Error allocating read buffer\n", __FUNCTION__);
goto out;
}
if (!(lpWriteBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE)))
{
printf("%s: Error allocating write buffer\n", __FUNCTION__);
goto out;
}
lpNumberOfBytesWritten = 0;
nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
FillMemory(lpWriteBuffer, PIPE_BUFFER_SIZE, 0x59);
fSuccess = WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten, NULL);
if (!fSuccess || (lpNumberOfBytesWritten == 0))
if (!WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten, NULL) ||
lpNumberOfBytesWritten != nNumberOfBytesToWrite)
{
printf("Client NamedPipe WriteFile failure\n");
free(lpReadBuffer);
free(lpWriteBuffer);
CloseHandle(hNamedPipe);
return NULL;
printf("%s: Client NamedPipe WriteFile failure\n", __FUNCTION__);
goto out;
}
lpNumberOfBytesRead = 0;
@ -68,34 +78,31 @@ static void* named_pipe_client_thread(void* arg)
ZeroMemory(lpReadBuffer, PIPE_BUFFER_SIZE);
fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, NULL);
if (!fSuccess || (lpNumberOfBytesRead == 0))
if (!ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, NULL) ||
lpNumberOfBytesRead != nNumberOfBytesToRead)
{
printf("Client NamedPipe ReadFile failure\n");
free(lpReadBuffer);
free(lpWriteBuffer);
CloseHandle(hNamedPipe);
return NULL;
printf("%s: Client NamedPipe ReadFile failure\n", __FUNCTION__);
goto out;
}
printf("Client ReadFile (%d):\n", lpNumberOfBytesRead);
winpr_HexDump(lpReadBuffer, lpNumberOfBytesRead);
fSuccess = TRUE;
out:
free(lpReadBuffer);
free(lpWriteBuffer);
CloseHandle(hNamedPipe);
if (!fSuccess)
testFailed = TRUE;
return NULL;
}
static void* named_pipe_server_thread(void* arg)
{
HANDLE hNamedPipe;
BYTE* lpReadBuffer;
BYTE* lpWriteBuffer;
HANDLE hNamedPipe = NULL;
BYTE* lpReadBuffer = NULL;
BYTE* lpWriteBuffer = NULL;
BOOL fSuccess = FALSE;
BOOL fConnected = FALSE;
DWORD nNumberOfBytesToRead;
@ -103,20 +110,20 @@ static void* named_pipe_server_thread(void* arg)
DWORD lpNumberOfBytesRead;
DWORD lpNumberOfBytesWritten;
hNamedPipe = CreateNamedPipe(lpszPipeName,
hNamedPipe = CreateNamedPipe(lpszPipeNameMt,
PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, NULL);
if (!hNamedPipe)
{
printf("CreateNamedPipe failure: NULL handle\n");
return NULL;
printf("%s: CreateNamedPipe failure: NULL handle\n", __FUNCTION__);
goto out;
}
if (hNamedPipe == INVALID_HANDLE_VALUE)
{
printf("CreateNamedPipe failure: INVALID_HANDLE_VALUE\n");
return NULL;
printf("%s: CreateNamedPipe failure: INVALID_HANDLE_VALUE\n", __FUNCTION__);
goto out;
}
SetEvent(ReadyEvent);
@ -128,30 +135,32 @@ static void* named_pipe_server_thread(void* arg)
if (!fConnected)
{
printf("ConnectNamedPipe failure\n");
CloseHandle(hNamedPipe);
return NULL;
printf("%s: ConnectNamedPipe failure\n", __FUNCTION__);
goto out;
}
lpReadBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE);
lpWriteBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE);
if (!(lpReadBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE)))
{
printf("%s: Error allocating read buffer\n", __FUNCTION__);
goto out;
}
if (!(lpWriteBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE)))
{
printf("%s: Error allocating write buffer\n", __FUNCTION__);
goto out;
}
lpNumberOfBytesRead = 0;
nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
ZeroMemory(lpReadBuffer, PIPE_BUFFER_SIZE);
fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, NULL);
if (!fSuccess || (lpNumberOfBytesRead == 0))
if (!ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, NULL) ||
lpNumberOfBytesRead != nNumberOfBytesToRead)
{
printf("Server NamedPipe ReadFile failure\n");
free(lpReadBuffer);
free(lpWriteBuffer);
CloseHandle(hNamedPipe);
return NULL;
printf("%s: Server NamedPipe ReadFile failure\n", __FUNCTION__);
goto out;
}
printf("Server ReadFile (%d):\n", lpNumberOfBytesRead);
@ -162,42 +171,307 @@ static void* named_pipe_server_thread(void* arg)
FillMemory(lpWriteBuffer, PIPE_BUFFER_SIZE, 0x45);
fSuccess = WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten, NULL);
if (!fSuccess || (lpNumberOfBytesWritten == 0))
if (!WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten, NULL) ||
lpNumberOfBytesWritten != nNumberOfBytesToWrite)
{
printf("Server NamedPipe WriteFile failure\n");
free(lpReadBuffer);
free(lpWriteBuffer);
CloseHandle(hNamedPipe);
return NULL;
printf("%s: Server NamedPipe WriteFile failure\n", __FUNCTION__);
goto out;
}
fSuccess = TRUE;
out:
free(lpReadBuffer);
free(lpWriteBuffer);
CloseHandle(hNamedPipe);
if (!fSuccess)
testFailed = TRUE;
return NULL;
}
#define TESTNUMPIPESST 16
static void* named_pipe_single_thread(void* arg)
{
HANDLE servers[TESTNUMPIPESST];
HANDLE clients[TESTNUMPIPESST];
char sndbuf[PIPE_BUFFER_SIZE];
char rcvbuf[PIPE_BUFFER_SIZE];
DWORD dwRead;
DWORD dwWritten;
int i;
int numPipes;
BOOL bSuccess = FALSE;
#ifndef _WIN32
WINPR_NAMED_PIPE* p;
#endif
numPipes = TESTNUMPIPESST;
memset(servers, 0, sizeof(servers));
memset(clients, 0, sizeof(clients));
WaitForSingleObject(ReadyEvent, INFINITE);
for (i = 0; i < numPipes; i++)
{
if (!(servers[i] = CreateNamedPipe(lpszPipeNameSt,
PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, NULL)))
{
printf("%s: CreateNamedPipe #%d failed\n", __FUNCTION__, i);
goto out;
}
}
#ifndef _WIN32
for (i = 0; i < numPipes; i++)
{
p = (WINPR_NAMED_PIPE*)servers[i];
if (strcmp(lpszPipeNameSt, p->name))
{
printf("%s: Pipe name mismatch for pipe #%d ([%s] instead of [%s])\n",
__FUNCTION__, i, p->name, lpszPipeNameSt);
goto out;
}
if (p->clientfd != -1)
{
printf("%s: Unexpected client fd value for pipe #%d (%d instead of -1)\n",
__FUNCTION__, i, p->clientfd);
goto out;
}
if (p->serverfd < 1)
{
printf("%s: Unexpected server fd value for pipe #%d (%d is not > 0)\n",
__FUNCTION__, i, p->serverfd);
goto out;
}
if (p->ServerMode == FALSE)
{
printf("%s: Unexpected ServerMode value for pipe #%d (0 instead of 1)\n",
__FUNCTION__, i);
goto out;
}
}
#endif
for (i = 0; i < numPipes; i++)
{
if (!(clients[i] = CreateFile(lpszPipeNameSt, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL)))
{
printf("%s: CreateFile #%d failed\n", __FUNCTION__, i);
goto out;
}
if (!ConnectNamedPipe(servers[i], NULL))
{
printf("%s: ConnectNamedPipe #%d failed\n", __FUNCTION__, i);
goto out;
}
}
#ifndef _WIN32
for (i = 0; i < numPipes; i++)
{
p = servers[i];
if (p->clientfd < 1)
{
printf("%s: Unexpected client fd value for pipe #%d (%d is not > 0)\n",
__FUNCTION__, i, p->clientfd);
goto out;
}
if (p->ServerMode)
{
printf("%s: Unexpected ServerMode value for pipe #%d (1 instead of 0)\n",
__FUNCTION__, i);
goto out;
}
}
for (i = 0; i < numPipes; i++)
{
/* Test writing from clients to servers */
ZeroMemory(sndbuf, sizeof(sndbuf));
ZeroMemory(rcvbuf, sizeof(rcvbuf));
sprintf_s(sndbuf, sizeof(sndbuf), "CLIENT->SERVER ON PIPE #%05d", i);
p = servers[i];
if (!WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL) ||
dwWritten != sizeof(sndbuf))
{
printf("%s: Error writing to client end of pipe #%d\n", __FUNCTION__, i);
goto out;
}
if (!ReadFile(servers[i], rcvbuf, dwWritten, &dwRead, NULL) ||
dwRead != dwWritten)
{
printf("%s: Error reading on server end of pipe #%d\n", __FUNCTION__, i);
goto out;
}
if (memcmp(sndbuf, rcvbuf, sizeof(sndbuf)))
{
printf("%s: Error data read on server end of pipe #%d is corrupted\n",
__FUNCTION__, i);
goto out;
}
/* Test writing from servers to clients */
ZeroMemory(sndbuf, sizeof(sndbuf));
ZeroMemory(rcvbuf, sizeof(rcvbuf));
sprintf_s(sndbuf, sizeof(sndbuf), "SERVER->CLIENT ON PIPE #%05d", i);
p = servers[i];
if (!WriteFile(servers[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL) ||
dwWritten != sizeof(sndbuf))
{
printf("%s: Error writing to server end of pipe #%d\n", __FUNCTION__, i);
goto out;
}
if (!ReadFile(clients[i], rcvbuf, dwWritten, &dwRead, NULL) ||
dwRead != dwWritten)
{
printf("%s: Error reading on client end of pipe #%d\n", __FUNCTION__, i);
goto out;
}
if (memcmp(sndbuf, rcvbuf, sizeof(sndbuf)))
{
printf("%s: Error data read on client end of pipe #%d is corrupted\n",
__FUNCTION__, i);
goto out;
}
}
#endif
/**
* After DisconnectNamedPipe on server end
* ReadFile/WriteFile must fail on client end
*/
i = numPipes - 1;
DisconnectNamedPipe(servers[i]);
if (ReadFile(clients[i], rcvbuf, sizeof(rcvbuf), &dwRead, NULL))
{
printf("%s: Error ReadFile on client should have failed after DisconnectNamedPipe on server\n", __FUNCTION__);
goto out;
}
if (WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL))
{
printf("%s: Error WriteFile on client end should have failed after DisconnectNamedPipe on server\n", __FUNCTION__);
goto out;
}
CloseHandle(servers[i]);
CloseHandle(clients[i]);
numPipes--;
/**
* After CloseHandle (without calling DisconnectNamedPipe first) on server end
* ReadFile/WriteFile must fail on client end
*/
i = numPipes - 1;
CloseHandle(servers[i]);
if (ReadFile(clients[i], rcvbuf, sizeof(rcvbuf), &dwRead, NULL))
{
printf("%s: Error ReadFile on client end should have failed after CloseHandle on server\n", __FUNCTION__);
goto out;
}
if (WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL))
{
printf("%s: Error WriteFile on client end should have failed after CloseHandle on server\n", __FUNCTION__);
goto out;
}
CloseHandle(clients[i]);
numPipes--;
/**
* After CloseHandle on client end
* ReadFile/WriteFile must fail on server end
*/
i = numPipes - 1;
CloseHandle(clients[i]);
if (ReadFile(servers[i], rcvbuf, sizeof(rcvbuf), &dwRead, NULL))
{
printf("%s: Error ReadFile on server end should have failed after CloseHandle on client\n", __FUNCTION__);
goto out;
}
if (WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL))
{
printf("%s: Error WriteFile on server end should have failed after CloseHandle on client\n", __FUNCTION__);
goto out;
}
DisconnectNamedPipe(servers[i]);
CloseHandle(servers[i]);
numPipes--;
/* Close all remaining pipes */
for (i = 0; i < numPipes; i++)
{
DisconnectNamedPipe(servers[i]);
CloseHandle(servers[i]);
CloseHandle(clients[i]);
}
numPipes = 0;
bSuccess = TRUE;
out:
if (!bSuccess)
testFailed = TRUE;
return NULL;
}
int TestPipeCreateNamedPipe(int argc, char* argv[])
{
HANDLE SingleThread;
HANDLE ClientThread;
HANDLE ServerThread;
#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
ReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
SingleThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_single_thread, NULL, 0, NULL);
ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_client_thread, NULL, 0, NULL);
ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_server_thread, NULL, 0, NULL);
WaitForSingleObject(SingleThread, INFINITE);
WaitForSingleObject(ClientThread, INFINITE);
WaitForSingleObject(ServerThread, INFINITE);
CloseHandle(SingleThread);
CloseHandle(ClientThread);
CloseHandle(ServerThread);
return 0;
return testFailed;
}

View File

@ -43,20 +43,21 @@ set(${MODULE_PREFIX}_CREDSSP_SRCS
set(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_CREDSSP_SRCS}
sspi_winpr.c
sspi_winpr.h
sspi_export.c
sspi.c
sspi.h)
if(NOT WITH_NATIVE_SSPI)
set(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_NTLM_SRCS}
${${MODULE_PREFIX}_KERBEROS_SRCS}
${${MODULE_PREFIX}_NEGOTIATE_SRCS}
${${MODULE_PREFIX}_SCHANNEL_SRCS}
${${MODULE_PREFIX}_SRCS})
endif()
set(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_NTLM_SRCS}
${${MODULE_PREFIX}_KERBEROS_SRCS}
${${MODULE_PREFIX}_NEGOTIATE_SRCS}
${${MODULE_PREFIX}_SCHANNEL_SRCS}
${${MODULE_PREFIX}_SRCS})
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()
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
@ -80,7 +81,7 @@ endif()
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL
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)
set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* 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 pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
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)
{
CREDSSP_CONTEXT* context;
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
context = sspi_SecureHandleGetLowerPointer(phContext);
context = (CREDSSP_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
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_SecureHandleSetUpperPointer(phNewContext, (void*) CREDSSP_PACKAGE_NAME);
}
return SEC_E_OK;
}
CREDSSP_CONTEXT* credssp_ContextNew()
@ -68,10 +70,8 @@ CREDSSP_CONTEXT* credssp_ContextNew()
context = (CREDSSP_CONTEXT*) calloc(1, sizeof(CREDSSP_CONTEXT));
if (context != NULL)
{
}
if (!context)
return NULL;
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,
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,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
SEC_WINNT_AUTH_IDENTITY* identity;
if (fCredentialUse == SECPKG_CRED_OUTBOUND)
{
credentials = sspi_CredentialsNew();
if (!credentials)
return SEC_E_INSUFFICIENT_MEMORY;
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
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_UNSUPPORTED_FUNCTION;
}
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)
{
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;
}
@ -146,12 +150,12 @@ SECURITY_STATUS SEC_ENTRY credssp_QueryCredentialsAttributesA(PCredHandle phCred
SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle phCredential)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
if (!phCredential)
return SEC_E_INVALID_HANDLE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials)
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)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
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)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
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 =

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* you may not use this file except in compliance with the License.
@ -41,145 +41,195 @@
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;
char* ws = Workstation;
if (!Workstation)
{
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,
ws, -1, &context->Workstation.Buffer, 0) - 1;
context->Workstation.Buffer = NULL;
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;
if (!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)
{
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);
if (!context->ServicePrincipalName.Buffer)
return -1;
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,
ServicePrincipalName, -1, &context->ServicePrincipalName.Buffer, 0) - 1;
context->ServicePrincipalName.Length *= 2;
int status;
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;
char* name = TargetName;
if (!TargetName)
{
GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize);
name = malloc(nSize);
GetComputerNameExA(ComputerNameDnsHostname, name, &nSize);
if (!GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize))
return -1;
name = (char*) malloc(nSize);
if (!name)
return -1;
if (!GetComputerNameExA(ComputerNameDnsHostname, name, &nSize))
return -1;
CharUpperA(TargetName);
}
context->TargetName.cbBuffer = ConvertToUnicode(CP_UTF8, 0,
name, -1, (LPWSTR*) &context->TargetName.pvBuffer, 0) - 1;
context->TargetName.cbBuffer *= 2;
context->TargetName.pvBuffer = NULL;
status = ConvertToUnicode(CP_UTF8, 0, name, -1, (LPWSTR*) &context->TargetName.pvBuffer, 0);
if (status <= 0)
return -1;
context->TargetName.cbBuffer = (USHORT) ((status - 1) * 2);
if (!TargetName)
free(name);
return 1;
}
NTLM_CONTEXT* ntlm_ContextNew()
{
HKEY hKey;
LONG status;
DWORD dwType;
DWORD dwSize;
DWORD dwValue;
NTLM_CONTEXT* context;
context = (NTLM_CONTEXT*) malloc(sizeof(NTLM_CONTEXT));
ZeroMemory(context, sizeof(NTLM_CONTEXT));
context = (NTLM_CONTEXT*) calloc(1, sizeof(NTLM_CONTEXT));
if (context != NULL)
if (!context)
return NULL;
context->NTLMv2 = TRUE;
context->UseMIC = FALSE;
context->SendVersionInfo = TRUE;
context->SendSingleHostData = FALSE;
context->SendWorkstationName = TRUE;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\WinPR\\NTLM"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
HKEY hKey;
LONG status;
DWORD dwType;
DWORD dwSize;
DWORD dwValue;
if (RegQueryValueEx(hKey, _T("NTLMv2"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->NTLMv2 = dwValue ? 1 : 0;
context->NTLMv2 = TRUE;
context->UseMIC = FALSE;
context->SendVersionInfo = TRUE;
context->SendSingleHostData = FALSE;
context->SendWorkstationName = TRUE;
if (RegQueryValueEx(hKey, _T("UseMIC"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->UseMIC = dwValue ? 1 : 0;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\WinPR\\NTLM"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (RegQueryValueEx(hKey, _T("SendVersionInfo"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendVersionInfo = dwValue ? 1 : 0;
if (status == ERROR_SUCCESS)
if (RegQueryValueEx(hKey, _T("SendSingleHostData"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendSingleHostData = dwValue ? 1 : 0;
if (RegQueryValueEx(hKey, _T("SendWorkstationName"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendWorkstationName = dwValue ? 1 : 0;
if (RegQueryValueEx(hKey, _T("WorkstationName"), NULL, &dwType, NULL, &dwSize) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("NTLMv2"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->NTLMv2 = dwValue ? 1 : 0;
char* workstation = (char*) malloc(dwSize + 1);
if (RegQueryValueEx(hKey, _T("UseMIC"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->UseMIC = dwValue ? 1 : 0;
if (!workstation)
return NULL;
if (RegQueryValueEx(hKey, _T("SendVersionInfo"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendVersionInfo = dwValue ? 1 : 0;
status = RegQueryValueExA(hKey, "WorkstationName", NULL, &dwType, (BYTE*) workstation, &dwSize);
workstation[dwSize] = '\0';
if (RegQueryValueEx(hKey, _T("SendSingleHostData"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendSingleHostData = dwValue ? 1 : 0;
if (ntlm_SetContextWorkstation(context, workstation) < 0)
return NULL;
if (RegQueryValueEx(hKey, _T("SendWorkstationName"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SendWorkstationName = dwValue ? 1 : 0;
if (RegQueryValueEx(hKey, _T("WorkstationName"), NULL, &dwType, NULL, &dwSize) == ERROR_SUCCESS)
{
char* workstation = (char*) malloc(dwSize + 1);
status = RegQueryValueExA(hKey, "WorkstationName", NULL, &dwType, (BYTE*) workstation, &dwSize);
workstation[dwSize] = '\0';
ntlm_SetContextWorkstation(context, workstation);
free(workstation);
}
RegCloseKey(hKey);
free(workstation);
}
/*
* Extended Protection is enabled by default in Windows 7,
* but enabling it in WinPR breaks TS Gateway at this point
*/
context->SuppressExtendedProtection = FALSE;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\LSA"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("SuppressExtendedProtection"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SuppressExtendedProtection = dwValue ? 1 : 0;
RegCloseKey(hKey);
}
context->NegotiateFlags = 0;
context->LmCompatibilityLevel = 3;
context->state = NTLM_STATE_INITIAL;
memset(context->MachineID, 0xAA, sizeof(context->MachineID));
if (context->NTLMv2)
context->UseMIC = TRUE;
RegCloseKey(hKey);
}
/*
* Extended Protection is enabled by default in Windows 7,
* but enabling it in WinPR breaks TS Gateway at this point
*/
context->SuppressExtendedProtection = FALSE;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\LSA"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("SuppressExtendedProtection"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->SuppressExtendedProtection = dwValue ? 1 : 0;
RegCloseKey(hKey);
}
context->NegotiateFlags = 0;
context->LmCompatibilityLevel = 3;
context->state = NTLM_STATE_INITIAL;
FillMemory(context->MachineID, sizeof(context->MachineID), 0xAA);
if (context->NTLMv2)
context->UseMIC = TRUE;
return context;
}
@ -197,10 +247,6 @@ void ntlm_ContextFree(NTLM_CONTEXT* context)
sspi_SecBufferFree(&context->LmChallengeResponse);
free(context->ServicePrincipalName.Buffer);
free(context->identity.User);
free(context->identity.Password);
free(context->identity.Domain);
free(context->Workstation.Buffer);
free(context);
}
@ -209,39 +255,32 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
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();
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_INVALID_PARAMETER;
}
else if (fCredentialUse == SECPKG_CRED_INBOUND)
{
credentials = sspi_CredentialsNew();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
credentials = sspi_CredentialsNew();
if (identity)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
else
ZeroMemory(&(credentials->identity), sizeof(SEC_WINNT_AUTH_IDENTITY));
if (!credentials)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
credentials->fCredentialUse = fCredentialUse;
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
return SEC_E_OK;
}
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity)
sspi_CopyAuthIdentity(&(credentials->identity), identity);
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
return SEC_E_OK;
}
@ -250,49 +289,44 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
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();
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_INVALID_PARAMETER;
}
else if (fCredentialUse == SECPKG_CRED_INBOUND)
{
credentials = sspi_CredentialsNew();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
credentials = sspi_CredentialsNew();
if (identity != NULL)
CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
if (!credentials)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
credentials->fCredentialUse = fCredentialUse;
credentials->pGetKeyFn = pGetKeyFn;
credentials->pvGetKeyArgument = pvGetKeyArgument;
return SEC_E_OK;
}
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
if (identity)
sspi_CopyAuthIdentity(&(credentials->identity), identity);
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NTLM_PACKAGE_NAME);
return SEC_E_OK;
}
SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
if (!phCredential)
return SEC_E_INVALID_HANDLE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials)
return SEC_E_INVALID_HANDLE;
@ -326,7 +360,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
{
NTLM_CONTEXT* context;
SECURITY_STATUS status;
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
PSecBuffer input_buffer;
PSecBuffer output_buffer;
@ -339,13 +373,13 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
if (!context)
return SEC_E_INSUFFICIENT_MEMORY;
context->server = 1;
context->server = TRUE;
if (fContextReq & ASC_REQ_CONFIDENTIALITY)
context->confidentiality = 1;
context->confidentiality = TRUE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
sspi_CopyAuthIdentity(&context->identity, &credentials->identity);
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
context->credentials = credentials;
ntlm_SetContextTargetName(context, NULL);
@ -414,7 +448,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P
if (pOutput)
{
int i;
ULONG i;
for (i = 0; i < pOutput->cBuffers; i++)
{
@ -441,7 +475,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
{
NTLM_CONTEXT* context;
SECURITY_STATUS status;
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
PSecBuffer input_buffer = NULL;
PSecBuffer output_buffer = NULL;
PSecBuffer channel_bindings = NULL;
@ -456,15 +490,19 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti
return SEC_E_INSUFFICIENT_MEMORY;
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)
ntlm_SetContextWorkstation(context, NULL);
{
if (ntlm_SetContextWorkstation(context, NULL) < 0)
return SEC_E_INTERNAL_ERROR;
}
ntlm_SetContextServicePrincipalNameW(context, pszTargetName);
sspi_CopyAuthIdentity(&context->identity, &credentials->identity);
if (ntlm_SetContextServicePrincipalNameW(context, pszTargetName) < 0)
return SEC_E_INTERNAL_ERROR;
sspi_SecureHandleSetLowerPointer(phNewContext, context);
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NTLM_PACKAGE_NAME);
@ -554,20 +592,39 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti
SECURITY_STATUS status;
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,
Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
if (pszTargetNameW != NULL)
if (pszTargetNameW)
free(pszTargetNameW);
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 */
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)
{
NTLM_CONTEXT* context;
if (!phContext)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
return SEC_E_INSUFFICIENT_MEMORY;
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (ulAttribute == SECPKG_ATTR_SIZES)
{
SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer;
@ -605,6 +666,35 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, UL
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;
}
@ -614,6 +704,38 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, UL
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)
{
return SEC_E_OK;
@ -654,20 +776,24 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
/* Copy original data buffer */
length = data_buffer->cbBuffer;
data = malloc(length);
if (!data)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(data, data_buffer->pvBuffer, length);
/* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */
HMAC_CTX_init(&hmac);
HMAC_Init_ex(&hmac, context->SendSigningKey, 16, EVP_md5(), NULL);
HMAC_Update(&hmac, (void*) &(SeqNo), 4);
HMAC_Update(&hmac, data, length);
HMAC_Update(&hmac, (void*) data, length);
HMAC_Final(&hmac, digest, NULL);
HMAC_CTX_cleanup(&hmac);
/* Encrypt message using with RC4, result overwrites original buffer */
if (context->confidentiality)
RC4(&context->SendRc4Seal, length, data, data_buffer->pvBuffer);
RC4(&context->SendRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer);
else
CopyMemory(data_buffer->pvBuffer, data, length);
@ -719,7 +845,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
PSecBuffer signature_buffer = NULL;
SeqNo = (UINT32) MessageSeqNo;
context = sspi_SecureHandleGetLowerPointer(phContext);
context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
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 */
length = data_buffer->cbBuffer;
data = malloc(length);
if (!data)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(data, data_buffer->pvBuffer, length);
/* Decrypt message using with RC4, result overwrites original buffer */
if (context->confidentiality)
RC4(&context->RecvRc4Seal, length, data, data_buffer->pvBuffer);
RC4(&context->RecvRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer);
else
CopyMemory(data_buffer->pvBuffer, data, length);
@ -751,7 +881,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
HMAC_CTX_init(&hmac);
HMAC_Init_ex(&hmac, context->RecvSigningKey, 16, EVP_md5(), NULL);
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_CTX_cleanup(&hmac);
@ -784,7 +914,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
fprintf(stderr, "Expected Signature:\n");
winpr_HexDump(expected_signature, 16);
fprintf(stderr, "Actual Signature:\n");
winpr_HexDump(signature_buffer->pvBuffer, 16);
winpr_HexDump((BYTE*) signature_buffer->pvBuffer, 16);
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)
{
return SEC_E_OK;
return SEC_E_UNSUPPORTED_FUNCTION;
}
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 =
@ -812,7 +942,7 @@ const SecurityFunctionTableA NTLM_SecurityFunctionTableA =
NULL, /* Reserved2 */
ntlm_InitializeSecurityContextA, /* InitializeSecurityContext */
ntlm_AcceptSecurityContext, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */
ntlm_CompleteAuthToken, /* CompleteAuthToken */
ntlm_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */
ntlm_QueryContextAttributesA, /* QueryContextAttributes */
@ -831,7 +961,7 @@ const SecurityFunctionTableA NTLM_SecurityFunctionTableA =
NULL, /* QuerySecurityContextToken */
ntlm_EncryptMessage, /* EncryptMessage */
ntlm_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
ntlm_SetContextAttributesA, /* SetContextAttributes */
};
const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
@ -844,7 +974,7 @@ const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
NULL, /* Reserved2 */
ntlm_InitializeSecurityContextW, /* InitializeSecurityContext */
ntlm_AcceptSecurityContext, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */
ntlm_CompleteAuthToken, /* CompleteAuthToken */
ntlm_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */
ntlm_QueryContextAttributesW, /* QueryContextAttributes */
@ -863,7 +993,7 @@ const SecurityFunctionTableW NTLM_SecurityFunctionTableW =
NULL, /* QuerySecurityContextToken */
ntlm_EncryptMessage, /* EncryptMessage */
ntlm_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
ntlm_SetContextAttributesA, /* SetContextAttributes */
};
const SecPkgInfoA NTLM_SecPkgInfoA =

View File

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

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* 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;
}
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;
int length;
int status;
DWORD nSize = 0;
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)
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;
free(name);
return 1;
}
void ntlm_free_unicode_string(PUNICODE_STRING string)
{
if (string != NULL)
if (string)
{
if (string->Length > 0)
{
if (string->Buffer != NULL)
if (string->Buffer)
free(string->Buffer);
string->Buffer = NULL;
@ -297,7 +308,7 @@ void ntlm_compute_single_host_data(NTLM_CONTEXT* context)
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;
ULONG AvPairsCount;
@ -310,23 +321,33 @@ void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
UNICODE_STRING DnsComputerName;
NbDomainName.Buffer = NULL;
ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS);
if (ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS) < 0)
return -1;
NbComputerName.Buffer = NULL;
ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS);
if (ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS) < 0)
return -1;
DnsDomainName.Buffer = NULL;
ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain);
if (ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain) < 0)
return -1;
DnsComputerName.Buffer = NULL;
ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname);
if (ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname) < 0)
return -1;
AvPairsCount = 5;
AvPairsLength = NbDomainName.Length + NbComputerName.Length +
DnsDomainName.Length + DnsComputerName.Length + 8;
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;
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(&DnsDomainName);
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 AvPairsCount;
@ -369,31 +392,31 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
AvDnsTreeName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsTreeName);
AvTimestamp = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvTimestamp);
if (AvNbDomainName != NULL)
if (AvNbDomainName)
{
AvPairsCount++; /* MsvAvNbDomainName */
AvPairsValueLength += AvNbDomainName->AvLen;
}
if (AvNbComputerName != NULL)
if (AvNbComputerName)
{
AvPairsCount++; /* MsvAvNbComputerName */
AvPairsValueLength += AvNbComputerName->AvLen;
}
if (AvDnsDomainName != NULL)
if (AvDnsDomainName)
{
AvPairsCount++; /* MsvAvDnsDomainName */
AvPairsValueLength += AvDnsDomainName->AvLen;
}
if (AvDnsComputerName != NULL)
if (AvDnsComputerName)
{
AvPairsCount++; /* MsvAvDnsComputerName */
AvPairsValueLength += AvDnsComputerName->AvLen;
}
if (AvDnsTreeName != NULL)
if (AvDnsTreeName)
{
AvPairsCount++; /* MsvAvDnsTreeName */
AvPairsValueLength += AvDnsTreeName->AvLen;
@ -448,22 +471,22 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
ntlm_av_pair_list_init(AuthenticateTargetInfo);
if (AvNbDomainName != NULL)
if (AvNbDomainName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbDomainName);
if (AvNbComputerName != NULL)
if (AvNbComputerName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbComputerName);
if (AvDnsDomainName != NULL)
if (AvDnsDomainName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsDomainName);
if (AvDnsComputerName != NULL)
if (AvDnsComputerName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsComputerName);
if (AvDnsTreeName != NULL)
if (AvDnsTreeName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsTreeName);
if (AvTimestamp != NULL)
if (AvTimestamp)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvTimestamp);
if (context->UseMIC)
@ -497,4 +520,6 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvEOL);
ZeroMemory((void*) AvEOL, 4);
}
return 1;
}

View File

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

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* you may not use this file except in compliance with the License.
@ -32,12 +32,15 @@
#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 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 server_seal_magic[] = "session key to server-to-client sealing key magic constant";
static const char NTLM_CLIENT_SIGN_MAGIC[] = "session key to client-to-server signing key magic constant";
static const char NTLM_SERVER_SIGN_MAGIC[] = "session key to server-to-client signing key magic constant";
static const char NTLM_CLIENT_SEAL_MAGIC[] = "session key to client-to-server 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
@ -66,13 +69,18 @@ void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo)
* @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->ProductMinorVersion); /* ProductMinorVersion (1 byte) */
Stream_Read_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */
Stream_Read(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */
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);
}
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;
@ -121,10 +129,16 @@ void ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* cha
size = Stream_Length(s) - Stream_GetPosition(s);
challenge->AvPairs = (NTLM_AV_PAIR*) malloc(size);
if (!challenge->AvPairs)
return -1;
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;
@ -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);
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);
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);
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.
* @param[out] timestamp 64-bit little-endian timestamp
@ -224,20 +203,22 @@ void ntlm_generate_timestamp(NTLM_CONTEXT* context)
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_ENTRY* entry;
SSPI_CREDENTIALS* credentials = context->credentials;
sam = SamOpen(1);
if (sam == NULL)
return;
sam = SamOpen(TRUE);
if (!sam)
return -1;
entry = SamLookupUserW(sam,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2);
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2);
if (entry != NULL)
if (entry)
{
#ifdef WITH_DEBUG_NTLM
fprintf(stderr, "NTLM Hash:\n");
@ -245,20 +226,20 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
#endif
NTOWFv2FromHashW(entry->NtHash,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash);
SamFreeEntry(sam, entry);
SamClose(sam);
return;
return 1;
}
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
fprintf(stderr, "NTLM Hash:\n");
@ -266,32 +247,44 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
#endif
NTOWFv2FromHashW(entry->NtHash,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash);
SamFreeEntry(sam, entry);
SamClose(sam);
return;
return 1;
}
else
{
fprintf(stderr, "Error: Could not find user in SAM database\n");
return 0;
}
SamClose(sam);
return 1;
}
void ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
{
int status;
int i, hn, ln;
char* PasswordHash = NULL;
UINT32 PasswordHashLength = 0;
SSPI_CREDENTIALS* credentials = context->credentials;
/* Password contains a password hash of length (PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR) */
PasswordHashLength = context->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
ConvertFromUnicode(CP_UTF8, 0, context->identity.Password, PasswordHashLength, &PasswordHash, 0, NULL, NULL);
PasswordHashLength = credentials->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
status = ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR) credentials->identity.Password,
PasswordHashLength, &PasswordHash, 0, NULL, NULL);
if (status <= 0)
return -1;
CharUpperBuffA(PasswordHash, PasswordHashLength);
for (i = 0; i < 32; i += 2)
@ -302,62 +295,83 @@ void ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
}
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];
/* Special case for WinPR: password hash */
ntlm_convert_password_hash(context, PasswordHash);
NTOWFv2FromHashW(PasswordHash,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2,
NTOWFv2FromHashW(context->NtlmHash,
(LPWSTR) credentials->identity.User, credentials->identity.UserLength * 2,
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash);
}
else if (context->identity.PasswordLength > 0)
else if (credentials->identity.PasswordLength > 256)
{
NTOWFv2W((LPWSTR) context->identity.Password, context->identity.PasswordLength * 2,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2, (BYTE*) hash);
/* Special case for WinPR: password 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
{
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;
char value[16];
char ntlm_v2_hash[16];
BYTE* response;
BYTE value[16];
if (context->LmCompatibilityLevel < 2)
{
sspi_SecBufferAlloc(&context->LmChallengeResponse, 24);
if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24))
return -1;
ZeroMemory(context->LmChallengeResponse.pvBuffer, 24);
return;
return 1;
}
/* 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 */
CopyMemory(value, context->ServerChallenge, 8);
CopyMemory(&value[8], context->ClientChallenge, 8);
sspi_SecBufferAlloc(&context->LmChallengeResponse, 24);
response = (char*) context->LmChallengeResponse.pvBuffer;
if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24))
return -1;
response = (BYTE*) context->LmChallengeResponse.pvBuffer;
/* 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) */
CopyMemory(&response[16], context->ClientChallenge, 8);
return 1;
}
/**
@ -367,10 +381,9 @@ void ntlm_compute_lm_v2_response(NTLM_CONTEXT* 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 ntlm_v2_hash[16];
BYTE nt_proof_str[16];
SecBuffer ntlm_v2_temp;
SecBuffer ntlm_v2_temp_chal;
@ -378,13 +391,16 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
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);
blob = (BYTE*) ntlm_v2_temp.pvBuffer;
/* 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
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, "NTOWFv2, NTLMv2 Hash\n");
winpr_HexDump(ntlm_v2_hash, 16);
winpr_HexDump(context->NtlmV2Hash, 16);
fprintf(stderr, "\n");
#endif
@ -425,25 +441,33 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
#endif
/* 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;
CopyMemory(blob, context->ServerChallenge, 8);
CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, ntlm_v2_temp_chal.pvBuffer,
ntlm_v2_temp_chal.cbBuffer, (void*) nt_proof_str, NULL);
HMAC(EVP_md5(), (BYTE*) context->NtlmV2Hash, 16, (BYTE*) ntlm_v2_temp_chal.pvBuffer,
ntlm_v2_temp_chal.cbBuffer, (BYTE*) nt_proof_str, NULL);
/* 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;
CopyMemory(blob, nt_proof_str, 16);
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 */
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_chal);
return 1;
}
/**
@ -548,7 +572,7 @@ void ntlm_decrypt_random_session_key(NTLM_CONTEXT* context)
* @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;
BYTE* value;
@ -557,6 +581,9 @@ void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic
length = 16 + sign_magic->cbBuffer;
value = (BYTE*) malloc(length);
if (!value)
return -1;
/* Concatenate ExportedSessionKey with sign magic */
CopyMemory(value, exported_session_key, 16);
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);
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)
{
SecBuffer sign_magic;
sign_magic.pvBuffer = (void*) client_sign_magic;
sign_magic.cbBuffer = sizeof(client_sign_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &sign_magic, context->ClientSigningKey);
SecBuffer signMagic;
signMagic.pvBuffer = (void*) NTLM_CLIENT_SIGN_MAGIC;
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)
{
SecBuffer sign_magic;
sign_magic.pvBuffer = (void*) server_sign_magic;
sign_magic.cbBuffer = sizeof(server_sign_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &sign_magic, context->ServerSigningKey);
SecBuffer signMagic;
signMagic.pvBuffer = (void*) NTLM_SERVER_SIGN_MAGIC;
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
*/
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;
MD5_CTX md5;
SecBuffer buffer;
sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer);
if (!sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer))
return -1;
p = (BYTE*) buffer.pvBuffer;
/* 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);
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)
{
SecBuffer seal_magic;
seal_magic.pvBuffer = (void*) client_seal_magic;
seal_magic.cbBuffer = sizeof(client_seal_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &seal_magic, context->ClientSealingKey);
SecBuffer sealMagic;
sealMagic.pvBuffer = (void*) NTLM_CLIENT_SEAL_MAGIC;
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)
{
SecBuffer seal_magic;
seal_magic.pvBuffer = (void*) server_seal_magic;
seal_magic.cbBuffer = sizeof(server_seal_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &seal_magic, context->ServerSealingKey);
SecBuffer sealMagic;
sealMagic.pvBuffer = (void*) NTLM_SERVER_SEAL_MAGIC;
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_Init_ex(&hmac_ctx, context->ExportedSessionKey, 16, EVP_md5(), NULL);
HMAC_Update(&hmac_ctx, context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer);
HMAC_Update(&hmac_ctx, context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
HMAC_Update(&hmac_ctx, context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer);
HMAC_Update(&hmac_ctx, (BYTE*) context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer);
HMAC_Update(&hmac_ctx, (BYTE*) context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
HMAC_Update(&hmac_ctx, (BYTE*) context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer);
HMAC_Final(&hmac_ctx, context->MessageIntegrityCheck, NULL);
HMAC_CTX_cleanup(&hmac_ctx);
}

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* you may not use this file except in compliance with the License.
@ -25,24 +25,22 @@
#include "ntlm_av_pairs.h"
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_print_version_info(NTLM_VERSION_INFO* versionInfo);
void ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
void ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
int ntlm_read_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_channel_bindings(NTLM_CONTEXT* context);
void ntlm_current_time(BYTE* timestamp);
void ntlm_generate_timestamp(NTLM_CONTEXT* context);
void ntlm_compute_ntlm_hash(UINT16* password, UINT32 length, char* hash);
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash);
void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context);
void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context);
int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash);
int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context);
int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context);
void ntlm_rc4k(BYTE* key, int length, BYTE* plaintext, BYTE* ciphertext);
void ntlm_generate_client_challenge(NTLM_CONTEXT* context);

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* 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_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer);
SECURITY_STATUS ntlm_server_AuthenticateComplete(NTLM_CONTEXT* context);
#endif /* WINPR_SSPI_NTLM_MESSAGE_H */

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* you may not use this file except in compliance with the License.
@ -28,67 +28,27 @@
#include "../sspi.h"
extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA;
extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW;
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* context;
context = (NEGOTIATE_CONTEXT*) calloc(1, sizeof(NEGOTIATE_CONTEXT));
if (context != NULL)
{
context->NegotiateFlags = 0;
context->state = NEGOTIATE_STATE_INITIAL;
}
if (!context)
return NULL;
context->NegotiateFlags = 0;
context->state = NEGOTIATE_STATE_INITIAL;
SecInvalidateHandle(&(context->SubContext));
context->sspiA = (SecurityFunctionTableA*) &NTLM_SecurityFunctionTableA;
context->sspiW = (SecurityFunctionTableW*) &NTLM_SecurityFunctionTableW;
return context;
}
@ -101,21 +61,262 @@ void negotiate_ContextFree(NEGOTIATE_CONTEXT* 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)
return SEC_E_INVALID_HANDLE;
if (!pBuffer)
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,
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;
}
@ -123,52 +324,54 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrinc
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
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();
identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
memcpy(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY));
sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME);
return SEC_E_OK;
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;
}
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)
{
if (ulAttribute == SECPKG_CRED_ATTR_NAMES)
{
CREDENTIALS* credentials;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
return SEC_E_OK;
}
return SEC_E_UNSUPPORTED_FUNCTION;
}
SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredential)
{
CREDENTIALS* credentials;
SSPI_CREDENTIALS* credentials;
if (!phCredential)
return SEC_E_INVALID_HANDLE;
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
if (!credentials)
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)
{
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)
{
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)
{
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)
{
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 =
@ -207,13 +442,13 @@ const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA =
negotiate_FreeCredentialsHandle, /* FreeCredentialsHandle */
NULL, /* Reserved2 */
negotiate_InitializeSecurityContextA, /* InitializeSecurityContext */
NULL, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */
NULL, /* DeleteSecurityContext */
negotiate_AcceptSecurityContext, /* AcceptSecurityContext */
negotiate_CompleteAuthToken, /* CompleteAuthToken */
negotiate_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */
negotiate_QueryContextAttributes, /* QueryContextAttributes */
NULL, /* ImpersonateSecurityContext */
NULL, /* RevertSecurityContext */
negotiate_QueryContextAttributesA, /* QueryContextAttributes */
negotiate_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
negotiate_RevertSecurityContext, /* RevertSecurityContext */
negotiate_MakeSignature, /* MakeSignature */
negotiate_VerifySignature, /* VerifySignature */
NULL, /* FreeContextBuffer */
@ -227,7 +462,7 @@ const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA =
NULL, /* QuerySecurityContextToken */
negotiate_EncryptMessage, /* EncryptMessage */
negotiate_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
negotiate_SetContextAttributesA, /* SetContextAttributes */
};
const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
@ -239,13 +474,13 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
negotiate_FreeCredentialsHandle, /* FreeCredentialsHandle */
NULL, /* Reserved2 */
negotiate_InitializeSecurityContextW, /* InitializeSecurityContext */
NULL, /* AcceptSecurityContext */
NULL, /* CompleteAuthToken */
NULL, /* DeleteSecurityContext */
negotiate_AcceptSecurityContext, /* AcceptSecurityContext */
negotiate_CompleteAuthToken, /* CompleteAuthToken */
negotiate_DeleteSecurityContext, /* DeleteSecurityContext */
NULL, /* ApplyControlToken */
negotiate_QueryContextAttributes, /* QueryContextAttributes */
NULL, /* ImpersonateSecurityContext */
NULL, /* RevertSecurityContext */
negotiate_QueryContextAttributesW, /* QueryContextAttributes */
negotiate_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
negotiate_RevertSecurityContext, /* RevertSecurityContext */
negotiate_MakeSignature, /* MakeSignature */
negotiate_VerifySignature, /* VerifySignature */
NULL, /* FreeContextBuffer */
@ -259,7 +494,7 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW =
NULL, /* QuerySecurityContextToken */
negotiate_EncryptMessage, /* EncryptMessage */
negotiate_DecryptMessage, /* DecryptMessage */
NULL, /* SetContextAttributes */
negotiate_SetContextAttributesW, /* SetContextAttributes */
};
const SecPkgInfoA NEGOTIATE_SecPkgInfoA =

View File

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

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* you may not use this file except in compliance with the License.

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* 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 (pBuffer->cbBuffer < status)
if (pBuffer->cbBuffer < (unsigned long) status)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
@ -339,7 +339,7 @@ SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context
if (status > 0)
{
if (pBuffer->cbBuffer < status)
if (pBuffer->cbBuffer < (unsigned long) status)
return SEC_E_INSUFFICIENT_MEMORY;
CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
@ -387,17 +387,17 @@ SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSec
if (status > 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);
status -= 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);
status -= 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);
status -= length;
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* 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");
* you may not use this file except in compliance with the License.
@ -28,20 +28,22 @@
#define SSPI_CREDENTIALS_HASH_LENGTH_FACTOR 64
struct _CREDENTIALS
struct _SSPI_CREDENTIALS
{
DWORD flags;
ULONG fCredentialUse;
SEC_GET_KEY_FN pGetKeyFn;
void* pvGetKeyArgument;
SEC_WINNT_AUTH_IDENTITY identity;
};
typedef struct _CREDENTIALS CREDENTIALS;
typedef struct _SSPI_CREDENTIALS SSPI_CREDENTIALS;
CREDENTIALS* sspi_CredentialsNew(void);
void sspi_CredentialsFree(CREDENTIALS* credentials);
SSPI_CREDENTIALS* sspi_CredentialsNew(void);
void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials);
PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType);
SecHandle* sspi_SecureHandleAlloc(void);
void sspi_SecureHandleInit(SecHandle* handle);
void sspi_SecureHandleInvalidate(SecHandle* handle);
void* sspi_SecureHandleGetLowerPointer(SecHandle* handle);
void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer);
@ -81,4 +83,6 @@ enum SecurityFunctionTableIndex
SetContextAttributesIndex = 28
};
#include "sspi_winpr.h"
#endif /* WINPR_SSPI_PRIVATE_H */

View File

@ -0,0 +1,289 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Security Support Provider Interface (SSPI)
*
* Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef _WIN32
#define SEC_ENTRY __stdcall
#define SSPI_EXPORT __declspec(dllexport)
#else
#define SEC_ENTRY
#define SSPI_EXPORT
#endif
typedef long LONG;
typedef unsigned long ULONG;
typedef LONG SECURITY_STATUS;
/**
* Standard SSPI API
*/
/* Package Management */
extern SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesW(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesW(void* pcPackages, void* ppPackageInfo)
{
return sspi_EnumerateSecurityPackagesW(pcPackages, ppPackageInfo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesA(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY EnumerateSecurityPackagesA(void* pcPackages, void* ppPackageInfo)
{
return sspi_EnumerateSecurityPackagesA(pcPackages, ppPackageInfo);
}
extern void* SEC_ENTRY sspi_InitSecurityInterfaceW(void);
SSPI_EXPORT void* SEC_ENTRY InitSecurityInterfaceW(void)
{
return sspi_InitSecurityInterfaceW();
}
extern void* SEC_ENTRY sspi_InitSecurityInterfaceA(void);
SSPI_EXPORT void* SEC_ENTRY InitSecurityInterfaceA(void)
{
return sspi_InitSecurityInterfaceA();
}
extern SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoW(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoW(void* pszPackageName, void* ppPackageInfo)
{
return sspi_QuerySecurityPackageInfoW(pszPackageName, ppPackageInfo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoA(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoA(void* pszPackageName, void* ppPackageInfo)
{
return sspi_QuerySecurityPackageInfoA(pszPackageName, ppPackageInfo);
}
/* Credential Management */
extern SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleW(void*, void*, ULONG, void*, void*, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleW(void* pszPrincipal, void* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, void* pGetKeyFn,
void* pvGetKeyArgument, void* phCredential, void* ptsExpiry)
{
return sspi_AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse,
pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleA(void*, void*, ULONG, void*, void*, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleA(void* pszPrincipal, void* pszPackage,
ULONG fCredentialUse, void* pvLogonID, void* pAuthData, void* pGetKeyFn,
void* pvGetKeyArgument, void* phCredential, void* ptsExpiry)
{
return sspi_AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse,
pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ExportSecurityContext(void*, ULONG, void*, void**);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ExportSecurityContext(void* phContext, ULONG fFlags, void* pPackedContext, void** pToken)
{
return sspi_ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
}
extern SECURITY_STATUS SEC_ENTRY sspi_FreeCredentialsHandle(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY FreeCredentialsHandle(void* phCredential)
{
return sspi_FreeCredentialsHandle(phCredential);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextW(void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ImportSecurityContextW(void* pszPackage, void* pPackedContext, void* pToken, void* phContext)
{
return sspi_ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextA(void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ImportSecurityContextA(void* pszPackage, void* pPackedContext, void* pToken, void* phContext)
{
return sspi_ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesW(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesW(void* phCredential, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesA(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryCredentialsAttributesA(void* phCredential, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
}
/* Context Management */
extern SECURITY_STATUS SEC_ENTRY sspi_AcceptSecurityContext(void*, void*, void*, ULONG, ULONG, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY AcceptSecurityContext(void* phCredential, void* phContext,
void* pInput, ULONG fContextReq, ULONG TargetDataRep, void* phNewContext,
void* pOutput, void* pfContextAttr, void* ptsTimeStamp)
{
return sspi_AcceptSecurityContext(phCredential, phContext, pInput, fContextReq,
TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ApplyControlToken(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ApplyControlToken(void* phContext, void* pInput)
{
return sspi_ApplyControlToken(phContext, pInput);
}
extern SECURITY_STATUS SEC_ENTRY sspi_CompleteAuthToken(void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY CompleteAuthToken(void* phContext, void* pToken)
{
return sspi_CompleteAuthToken(phContext, pToken);
}
extern SECURITY_STATUS SEC_ENTRY sspi_DeleteSecurityContext(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY DeleteSecurityContext(void* phContext)
{
return sspi_DeleteSecurityContext(phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_FreeContextBuffer(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY FreeContextBuffer(void* pvContextBuffer)
{
return sspi_FreeContextBuffer(pvContextBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_ImpersonateSecurityContext(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY ImpersonateSecurityContext(void* phContext)
{
return sspi_ImpersonateSecurityContext(phContext);
}
extern SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextW(void*, void*, void*, ULONG, ULONG, ULONG,
void*, ULONG, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY InitializeSecurityContextW(void* phCredential, void* phContext,
void* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
void* pInput, ULONG Reserved2, void* phNewContext,
void* pOutput, void* pfContextAttr, void* ptsExpiry)
{
return sspi_InitializeSecurityContextW(phCredential, phContext, pszTargetName, fContextReq, Reserved1,
TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextA(void*, void*, void*, ULONG, ULONG, ULONG,
void*, ULONG, void*, void*, void*, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY InitializeSecurityContextA(void* phCredential, void* phContext,
void* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
void* pInput, ULONG Reserved2, void* phNewContext,
void* pOutput, void* pfContextAttr, void* ptsExpiry)
{
return sspi_InitializeSecurityContextA(phCredential, phContext, pszTargetName, fContextReq, Reserved1,
TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesW(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryContextAttributesW(void* phContext, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesA(void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QueryContextAttributesA(void* phContext, ULONG ulAttribute, void* pBuffer)
{
return sspi_QueryContextAttributesA(phContext, ulAttribute, pBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityContextToken(void*, void**);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY QuerySecurityContextToken(void* phContext, void** phToken)
{
return sspi_QuerySecurityContextToken(phContext, phToken);
}
extern SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesW(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY SetContextAttributesW(void* phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
return sspi_SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesA(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY SetContextAttributesA(void* phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
{
return sspi_SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
}
extern SECURITY_STATUS SEC_ENTRY sspi_RevertSecurityContext(void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY RevertSecurityContext(void* phContext)
{
return sspi_RevertSecurityContext(phContext);
}
/* Message Support */
extern SECURITY_STATUS SEC_ENTRY sspi_DecryptMessage(void*, void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY DecryptMessage(void* phContext, void* pMessage, ULONG MessageSeqNo, void* pfQOP)
{
return sspi_DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
}
extern SECURITY_STATUS SEC_ENTRY sspi_EncryptMessage(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY EncryptMessage(void* phContext, ULONG fQOP, void* pMessage, ULONG MessageSeqNo)
{
return sspi_EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_MakeSignature(void*, ULONG, void*, ULONG);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY MakeSignature(void* phContext, ULONG fQOP, void* pMessage, ULONG MessageSeqNo)
{
return sspi_MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
}
extern SECURITY_STATUS SEC_ENTRY sspi_VerifySignature(void*, void*, ULONG, void*);
SSPI_EXPORT SECURITY_STATUS SEC_ENTRY VerifySignature(void* phContext, void* pMessage, ULONG MessageSeqNo, void* pfQOP)
{
return sspi_VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/**
* WinPR: Windows Portable Runtime
* 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");
* you may not use this file except in compliance with the License.
@ -17,16 +17,12 @@
* limitations under the License.
*/
#ifndef WINPR_CONFIG_H
#define WINPR_CONFIG_H
#ifndef WINPR_SSPI_WINPR_H
#define WINPR_SSPI_WINPR_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.
*/
#include <winpr/sspi.h>
#cmakedefine WITH_NATIVE_SSPI
SecurityFunctionTableW* SEC_ENTRY winpr_InitSecurityInterfaceW(void);
SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void);
#endif /* WINPR_CONFIG_H */
#endif /* WINPR_SSPI_WINPR_H */

View File

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

View File

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

View File

@ -1,59 +1,546 @@
#include <winpr/crt.h>
#include <winpr/sspi.h>
#include <winpr/print.h>
BYTE test_Certificate[] =
"\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";
#define TEST_SSPI_INTERFACE SSPI_INTERFACE_WINPR
BYTE test_Certificate_SHA256Hash[] =
"\xea\x05\xfe\xfe\xcc\x6b\x0b\xd5\x71\xdb\xbc\x5b\xaa\x3e\xd4\x53"
"\x86\xd0\x44\x68\x35\xf7\xb7\x4c\x85\x62\x1b\x99\x83\x47\x5f\x95";
static const char* TEST_NTLM_USER = "Username";
static const char* TEST_NTLM_DOMAIN = "Domain";
static const char* TEST_NTLM_PASSWORD = "P4ss123!";
BYTE test_ChannelBindings_MD5Hash[] =
"\x65\x86\xE9\x9D\x81\xC2\xFC\x98\x4E\x47\x17\x2F\xD4\xDD\x03\x10";
//static const char* TEST_NTLM_HASH_STRING = "d5922a65c4d5c082ca444af1be0001db";
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[])
{
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;
}
/**
* 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;
}

View File

@ -273,7 +273,7 @@ int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phCont
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[1].cbBuffer, Message.pBuffers[1].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 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[1].cbBuffer, Message.pBuffers[1].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)
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);
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)
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);
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[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
@ -543,7 +543,7 @@ static void* schannel_test_server_thread(void* arg)
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);
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 count;
int index;
DWORD index;
ALG_ID algId;
HANDLE thread;
BYTE* lpTokenIn;
@ -641,6 +641,8 @@ int TestSchannel(int argc, char* argv[])
SecPkgCred_CipherStrengths CipherStrengths;
SecPkgCred_SupportedProtocols SupportedProtocols;
return 0; /* disable by default - causes crash */
sspi_GlobalInit();
dump_test_certificate_files();
@ -713,7 +715,7 @@ int TestSchannel(int argc, char* argv[])
* 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++)
{
@ -734,7 +736,7 @@ int TestSchannel(int argc, char* argv[])
/* CipherStrengths: Minimum: 40 Maximum: 256 */
printf("CipherStrengths: Minimum: %ld Maximum: %ld\n",
printf("CipherStrengths: Minimum: %d Maximum: %d\n",
CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength);
ZeroMemory(&SupportedProtocols, sizeof(SecPkgCred_SupportedProtocols));
@ -748,7 +750,7 @@ int TestSchannel(int argc, char* argv[])
/* SupportedProtocols: 0x208A0 */
printf("SupportedProtocols: 0x%04lX\n", SupportedProtocols.grbitProtocol);
printf("SupportedProtocols: 0x%04X\n", SupportedProtocols.grbitProtocol);
fContextReq = ISC_REQ_STREAM |
ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
@ -781,7 +783,7 @@ int TestSchannel(int argc, char* argv[])
}
g_ClientWait = TRUE;
printf("NumberOfBytesRead: %ld\n", NumberOfBytesRead);
printf("NumberOfBytesRead: %d\n", NumberOfBytesRead);
SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
SecBuffer_in[0].pvBuffer = lpTokenIn;
@ -821,9 +823,9 @@ int TestSchannel(int argc, char* argv[])
else if (status == SEC_E_INCOMPLETE_MESSAGE)
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);
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[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType);
@ -833,7 +835,7 @@ int TestSchannel(int argc, char* argv[])
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);
if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL))

View File

@ -59,7 +59,11 @@ BOOL TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformati
#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)
{

View File

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

View File

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