#include "cliprdr_main.h"
#include "cliprdr_format.h"
-const char* const CB_MSG_TYPE_STRINGS[] =
+static const char* const CB_MSG_TYPE_STRINGS[] =
{
"",
"CB_MONITOR_READY",
"CB_UNLOCK_CLIPDATA"
};
+static WINPR_TLS cliprdrPlugin* s_TLSPluginContext = NULL;
+
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr)
{
CliprdrClientContext* pInterface;
+
if (!cliprdr)
return NULL;
+
pInterface = (CliprdrClientContext*) cliprdr->channelEntryPoints.pInterface;
return pInterface;
}
-wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen)
+static wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags,
+ UINT32 dataLen)
{
wStream* s;
-
s = Stream_New(NULL, dataLen + 8);
if (!s)
Stream_Write_UINT16(s, msgType);
Stream_Write_UINT16(s, msgFlags);
-
/* Write actual length after the entire packet has been constructed. */
Stream_Seek(s, 4);
-
return s;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s)
+static UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s)
{
UINT32 pos;
UINT32 dataLen;
UINT status = CHANNEL_RC_OK;
-
pos = Stream_GetPosition(s);
-
dataLen = pos - 8;
-
Stream_SetPosition(s, 4);
Stream_Write_UINT32(s, dataLen);
Stream_SetPosition(s, pos);
-
#ifdef WITH_DEBUG_CLIPRDR
WLog_DBG(TAG, "Cliprdr Sending (%d bytes)", dataLen + 8);
winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8);
else
{
status = cliprdr->channelEntryPoints.pVirtualChannelWrite(cliprdr->OpenHandle,
- Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
+ Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
}
if (status != CHANNEL_RC_OK)
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
- WTSErrorToString(status), status);
+ WTSErrorToString(status), status);
return status;
}
-void cliprdr_print_general_capability_flags(UINT32 flags)
+static void cliprdr_print_general_capability_flags(UINT32 flags)
{
WLog_INFO(TAG, "generalFlags (0x%08X) {", flags);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* s)
+static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr,
+ wStream* s)
{
UINT32 version;
UINT32 generalFlags;
Stream_Read_UINT32(s, version); /* version (4 bytes) */
Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
-
DEBUG_CLIPRDR("Version: %d", version);
#ifdef WITH_DEBUG_CLIPRDR
cliprdr_print_general_capability_flags(generalFlags);
#endif
if (cliprdr->useLongFormatNames)
- cliprdr->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE : FALSE;
+ cliprdr->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE :
+ FALSE;
if (cliprdr->streamFileClipEnabled)
- cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED) ? TRUE : FALSE;
+ cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED) ?
+ TRUE : FALSE;
if (cliprdr->fileClipNoFilePaths)
- cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS) ? TRUE : FALSE;
+ cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS) ?
+ TRUE : FALSE;
if (cliprdr->canLockClipData)
cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE;
}
capabilities.cCapabilitiesSets = 1;
- capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet);
+ capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &
+ (generalCapabilitySet);
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
generalCapabilitySet.capabilitySetLength = 12;
generalCapabilitySet.version = version;
generalCapabilitySet.generalFlags = generalFlags;
-
-
IFCALLRET(context->ServerCapabilities, error, context, &capabilities);
+
if (error)
WLog_ERR(TAG, "ServerCapabilities failed with error %lu!", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
+static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s,
+ UINT16 length, UINT16 flags)
{
UINT16 index;
UINT16 lengthCapability;
UINT16 cCapabilitiesSets;
UINT16 capabilitySetType;
UINT error = CHANNEL_RC_OK;
-
Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */
Stream_Seek_UINT16(s); /* pad1 (2 bytes) */
-
WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerCapabilities");
for (index = 0; index < cCapabilitiesSets; index++)
case CB_CAPSTYPE_GENERAL:
if ((error = cliprdr_process_general_capability(cliprdr, s)))
{
- WLog_ERR(TAG, "cliprdr_process_general_capability failed with error %lu!", error);
+ WLog_ERR(TAG, "cliprdr_process_general_capability failed with error %lu!",
+ error);
return error;
}
+
break;
default:
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
+static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s,
+ UINT16 length, UINT16 flags)
{
CLIPRDR_MONITOR_READY monitorReady;
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
UINT error = CHANNEL_RC_OK;
-
WLog_Print(cliprdr->log, WLOG_DEBUG, "MonitorReady");
if (!context->custom)
* When the server capabilities pdu is not used, default capabilities
* corresponding to a generalFlags field set to zero are assumed.
*/
-
cliprdr->useLongFormatNames = FALSE;
cliprdr->streamFileClipEnabled = FALSE;
cliprdr->fileClipNoFilePaths = TRUE;
monitorReady.msgType = CB_MONITOR_READY;
monitorReady.msgFlags = flags;
monitorReady.dataLen = length;
-
IFCALLRET(context->MonitorReady, error, context, &monitorReady);
+
if (error)
WLog_ERR(TAG, "MonitorReady failed with error %lu!", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags)
+static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr,
+ wStream* s, UINT32 length, UINT16 flags)
{
CLIPRDR_FILE_CONTENTS_REQUEST request;
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
UINT error = CHANNEL_RC_OK;
-
WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsRequest");
if (!context->custom)
request.msgType = CB_FILECONTENTS_REQUEST;
request.msgFlags = flags;
request.dataLen = length;
-
Stream_Read_UINT32(s, request.streamId); /* streamId (4 bytes) */
Stream_Read_UINT32(s, request.listIndex); /* listIndex (4 bytes) */
Stream_Read_UINT32(s, request.dwFlags); /* dwFlags (4 bytes) */
Stream_Read_UINT32(s, request.nPositionLow); /* nPositionLow (4 bytes) */
Stream_Read_UINT32(s, request.nPositionHigh); /* nPositionHigh (4 bytes) */
Stream_Read_UINT32(s, request.cbRequested); /* cbRequested (4 bytes) */
+
if (Stream_GetRemainingLength(s) >= 4)
Stream_Read_UINT32(s, request.clipDataId); /* clipDataId (4 bytes) */
else
request.clipDataId = 0;
-
IFCALLRET(context->ServerFileContentsRequest, error, context, &request);
+
if (error)
WLog_ERR(TAG, "ServerFileContentsRequest failed with error %lu!", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags)
+static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr,
+ wStream* s, UINT32 length, UINT16 flags)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
UINT error = CHANNEL_RC_OK;
-
WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsResponse");
if (!context->custom)
response.msgType = CB_FILECONTENTS_RESPONSE;
response.msgFlags = flags;
response.dataLen = length;
-
Stream_Read_UINT32(s, response.streamId); /* streamId (4 bytes) */
-
response.cbRequested = length - 4;
response.requestedData = Stream_Pointer(s); /* requestedFileContentsData */
-
-
IFCALLRET(context->ServerFileContentsResponse, error, context, &response);
+
if (error)
WLog_ERR(TAG, "ServerFileContentsResponse failed with error %lu!", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags)
+static UINT cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s,
+ UINT32 length, UINT16 flags)
{
CLIPRDR_LOCK_CLIPBOARD_DATA lockClipboardData;
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
UINT error = CHANNEL_RC_OK;
-
WLog_Print(cliprdr->log, WLOG_DEBUG, "LockClipData");
if (!context->custom)
lockClipboardData.msgType = CB_LOCK_CLIPDATA;
lockClipboardData.msgFlags = flags;
lockClipboardData.dataLen = length;
-
Stream_Read_UINT32(s, lockClipboardData.clipDataId); /* clipDataId (4 bytes) */
-
IFCALLRET(context->ServerLockClipboardData, error, context, &lockClipboardData);
+
if (error)
WLog_ERR(TAG, "ServerLockClipboardData failed with error %lu!", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags)
+static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s,
+ UINT32 length, UINT16 flags)
{
CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData;
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
UINT error = CHANNEL_RC_OK;
-
WLog_Print(cliprdr->log, WLOG_DEBUG, "UnlockClipData");
if (!context->custom)
unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA;
unlockClipboardData.msgFlags = flags;
unlockClipboardData.dataLen = length;
+ Stream_Read_UINT32(s,
+ unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */
+ IFCALLRET(context->ServerUnlockClipboardData, error, context,
+ &unlockClipboardData);
- Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */
-
-
- IFCALLRET(context->ServerUnlockClipboardData, error, context, &unlockClipboardData);
if (error)
WLog_ERR(TAG, "ServerUnlockClipboardData failed with error %lu!", error);
UINT16 msgFlags;
UINT32 dataLen;
UINT error;
-
Stream_Read_UINT16(s, msgType); /* msgType (2 bytes) */
Stream_Read_UINT16(s, msgFlags); /* msgFlags (2 bytes) */
Stream_Read_UINT32(s, dataLen); /* dataLen (4 bytes) */
-
#ifdef WITH_DEBUG_CLIPRDR
WLog_DBG(TAG, "msgType: %s (%d), msgFlags: %d dataLen: %d",
- CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen);
+ CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen);
winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8);
#endif
case CB_CLIP_CAPS:
if ((error = cliprdr_process_clip_caps(cliprdr, s, dataLen, msgFlags)))
WLog_ERR(TAG, "cliprdr_process_clip_caps failed with error %lu!", error);
+
break;
case CB_MONITOR_READY:
if ((error = cliprdr_process_monitor_ready(cliprdr, s, dataLen, msgFlags)))
WLog_ERR(TAG, "cliprdr_process_monitor_ready failed with error %lu!", error);
+
break;
case CB_FORMAT_LIST:
if ((error = cliprdr_process_format_list(cliprdr, s, dataLen, msgFlags)))
WLog_ERR(TAG, "cliprdr_process_format_list failed with error %lu!", error);
+
break;
case CB_FORMAT_LIST_RESPONSE:
- if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen, msgFlags)))
- WLog_ERR(TAG, "cliprdr_process_format_list_response failed with error %lu!", error);
+ if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen,
+ msgFlags)))
+ WLog_ERR(TAG, "cliprdr_process_format_list_response failed with error %lu!",
+ error);
+
break;
case CB_FORMAT_DATA_REQUEST:
- if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen, msgFlags)))
- WLog_ERR(TAG, "cliprdr_process_format_data_request failed with error %lu!", error);
+ if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen,
+ msgFlags)))
+ WLog_ERR(TAG, "cliprdr_process_format_data_request failed with error %lu!",
+ error);
+
break;
case CB_FORMAT_DATA_RESPONSE:
- if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen, msgFlags)))
- WLog_ERR(TAG, "cliprdr_process_format_data_response failed with error %lu!", error);
+ if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen,
+ msgFlags)))
+ WLog_ERR(TAG, "cliprdr_process_format_data_response failed with error %lu!",
+ error);
+
break;
case CB_FILECONTENTS_REQUEST:
- if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen, msgFlags)))
- WLog_ERR(TAG, "cliprdr_process_filecontents_request failed with error %lu!", error);
+ if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen,
+ msgFlags)))
+ WLog_ERR(TAG, "cliprdr_process_filecontents_request failed with error %lu!",
+ error);
+
break;
case CB_FILECONTENTS_RESPONSE:
- if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen, msgFlags)))
- WLog_ERR(TAG, "cliprdr_process_filecontents_response failed with error %lu!", error);
+ if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen,
+ msgFlags)))
+ WLog_ERR(TAG, "cliprdr_process_filecontents_response failed with error %lu!",
+ error);
+
break;
case CB_LOCK_CLIPDATA:
if ((error = cliprdr_process_lock_clipdata(cliprdr, s, dataLen, msgFlags)))
WLog_ERR(TAG, "cliprdr_process_lock_clipdata failed with error %lu!", error);
+
break;
case CB_UNLOCK_CLIPDATA:
if ((error = cliprdr_process_unlock_clipdata(cliprdr, s, dataLen, msgFlags)))
WLog_ERR(TAG, "cliprdr_process_lock_clipdata failed with error %lu!", error);
+
break;
default:
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_client_capabilities(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities)
+static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
+ CLIPRDR_CAPABILITIES* capabilities)
{
wStream* s;
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
-
s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
if (!s)
Stream_Write_UINT16(s, 1); /* cCapabilitiesSets */
Stream_Write_UINT16(s, 0); /* pad1 */
-
- generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*) capabilities->capabilitySets;
- Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetType); /* capabilitySetType */
- Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetLength); /* lengthCapability */
+ generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*)
+ capabilities->capabilitySets;
+ Stream_Write_UINT16(s,
+ generalCapabilitySet->capabilitySetType); /* capabilitySetType */
+ Stream_Write_UINT16(s,
+ generalCapabilitySet->capabilitySetLength); /* lengthCapability */
Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */
Stream_Write_UINT32(s, generalCapabilitySet->generalFlags); /* generalFlags */
-
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientCapabilities");
return cliprdr_packet_send(cliprdr, s);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_temp_directory(CliprdrClientContext* context, CLIPRDR_TEMP_DIRECTORY* tempDirectory)
+static UINT cliprdr_temp_directory(CliprdrClientContext* context,
+ CLIPRDR_TEMP_DIRECTORY* tempDirectory)
{
int length;
wStream* s;
WCHAR* wszTempDir = NULL;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
-
s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, 520 * 2);
if (!s)
return ERROR_INTERNAL_ERROR;
}
- length = ConvertToUnicode(CP_UTF8, 0, tempDirectory->szTempDir, -1, &wszTempDir, 0);
+ length = ConvertToUnicode(CP_UTF8, 0, tempDirectory->szTempDir, -1, &wszTempDir,
+ 0);
if (length < 0)
return ERROR_INTERNAL_ERROR;
Stream_Write(s, wszTempDir, length * 2);
Stream_Zero(s, (520 - length) * 2);
-
free(wszTempDir);
-
WLog_Print(cliprdr->log, WLOG_DEBUG, "TempDirectory: %s",
- tempDirectory->szTempDir);
-
+ tempDirectory->szTempDir);
return cliprdr_packet_send(cliprdr, s);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList)
+static UINT cliprdr_client_format_list(CliprdrClientContext* context,
+ CLIPRDR_FORMAT_LIST* formatList)
{
wStream* s;
UINT32 index;
if (!cliprdr->useLongFormatNames)
{
length = formatList->numFormats * 36;
-
s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length);
if (!s)
for (index = 0; index < formatList->numFormats; index++)
{
- format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
-
+ format = (CLIPRDR_FORMAT*) & (formatList->formats[index]);
Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */
-
formatNameSize = 0;
formatNameLength = 0;
-
szFormatName = format->formatName;
if (asciiNames)
wszFormatName = NULL;
if (szFormatName)
- formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName, 0);
+ formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName,
+ 0);
if (formatNameSize > 15)
formatNameSize = 15;
Stream_Write(s, wszFormatName, formatNameSize * 2);
Stream_Zero(s, 32 - (formatNameSize * 2));
-
free(wszFormatName);
}
}
{
for (index = 0; index < formatList->numFormats; index++)
{
- format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
+ format = (CLIPRDR_FORMAT*) & (formatList->formats[index]);
length += 4;
formatNameSize = 2;
if (format->formatName)
- formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, 0) * 2;
+ formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL,
+ 0) * 2;
length += formatNameSize;
}
for (index = 0; index < formatList->numFormats; index++)
{
- format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
+ format = (CLIPRDR_FORMAT*) & (formatList->formats[index]);
Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */
if (format->formatName)
lpWideCharStr = (LPWSTR) Stream_Pointer(s);
cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2;
formatNameSize = MultiByteToWideChar(CP_UTF8, 0,
- format->formatName, -1, lpWideCharStr, cchWideChar) * 2;
+ format->formatName, -1, lpWideCharStr, cchWideChar) * 2;
Stream_Seek(s, formatNameSize);
}
else
}
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatList: numFormats: %d",
- formatList->numFormats);
-
+ formatList->numFormats);
return cliprdr_packet_send(cliprdr, s);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_client_format_list_response(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
+static UINT cliprdr_client_format_list_response(CliprdrClientContext* context,
+ CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
-
formatListResponse->msgType = CB_FORMAT_LIST_RESPONSE;
formatListResponse->dataLen = 0;
-
- s = cliprdr_packet_new(formatListResponse->msgType, formatListResponse->msgFlags, formatListResponse->dataLen);
+ s = cliprdr_packet_new(formatListResponse->msgType,
+ formatListResponse->msgFlags, formatListResponse->dataLen);
if (!s)
{
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
+static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
+ CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
-
s = cliprdr_packet_new(CB_LOCK_CLIPDATA, 0, 4);
if (!s)
return ERROR_INTERNAL_ERROR;
}
- Stream_Write_UINT32(s, lockClipboardData->clipDataId); /* clipDataId (4 bytes) */
-
- WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientLockClipboardData: clipDataId: 0x%04X",
- lockClipboardData->clipDataId);
-
+ Stream_Write_UINT32(s,
+ lockClipboardData->clipDataId); /* clipDataId (4 bytes) */
+ WLog_Print(cliprdr->log, WLOG_DEBUG,
+ "ClientLockClipboardData: clipDataId: 0x%04X",
+ lockClipboardData->clipDataId);
return cliprdr_packet_send(cliprdr, s);;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
+static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
+ CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
-
s = cliprdr_packet_new(CB_UNLOCK_CLIPDATA, 0, 4);
- if (!s) {
+ if (!s)
+ {
WLog_ERR(TAG, "cliprdr_packet_new failed!");
return ERROR_INTERNAL_ERROR;
}
- Stream_Write_UINT32(s, unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */
-
- WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientUnlockClipboardData: clipDataId: 0x%04X",
- unlockClipboardData->clipDataId);
-
+ Stream_Write_UINT32(s,
+ unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */
+ WLog_Print(cliprdr->log, WLOG_DEBUG,
+ "ClientUnlockClipboardData: clipDataId: 0x%04X",
+ unlockClipboardData->clipDataId);
return cliprdr_packet_send(cliprdr, s);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_client_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
+static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
+ CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
-
formatDataRequest->msgType = CB_FORMAT_DATA_REQUEST;
formatDataRequest->msgFlags = 0;
formatDataRequest->dataLen = 4;
-
- s = cliprdr_packet_new(formatDataRequest->msgType, formatDataRequest->msgFlags, formatDataRequest->dataLen);
+ s = cliprdr_packet_new(formatDataRequest->msgType, formatDataRequest->msgFlags,
+ formatDataRequest->dataLen);
if (!s)
{
return ERROR_INTERNAL_ERROR;
}
- Stream_Write_UINT32(s, formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */
-
+ Stream_Write_UINT32(s,
+ formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataRequest");
return cliprdr_packet_send(cliprdr, s);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_client_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
+static UINT cliprdr_client_format_data_response(CliprdrClientContext* context,
+ CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
-
formatDataResponse->msgType = CB_FORMAT_DATA_RESPONSE;
-
- s = cliprdr_packet_new(formatDataResponse->msgType, formatDataResponse->msgFlags, formatDataResponse->dataLen);
+ s = cliprdr_packet_new(formatDataResponse->msgType,
+ formatDataResponse->msgFlags, formatDataResponse->dataLen);
if (!s)
{
return ERROR_INTERNAL_ERROR;
}
- Stream_Write(s, formatDataResponse->requestedFormatData, formatDataResponse->dataLen);
-
+ Stream_Write(s, formatDataResponse->requestedFormatData,
+ formatDataResponse->dataLen);
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataResponse");
return cliprdr_packet_send(cliprdr, s);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_client_file_contents_request(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
+static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context,
+ CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
-
s = cliprdr_packet_new(CB_FILECONTENTS_REQUEST, 0, 28);
if (!s)
}
Stream_Write_UINT32(s, fileContentsRequest->streamId); /* streamId (4 bytes) */
- Stream_Write_UINT32(s, fileContentsRequest->listIndex); /* listIndex (4 bytes) */
+ Stream_Write_UINT32(s,
+ fileContentsRequest->listIndex); /* listIndex (4 bytes) */
Stream_Write_UINT32(s, fileContentsRequest->dwFlags); /* dwFlags (4 bytes) */
- Stream_Write_UINT32(s, fileContentsRequest->nPositionLow); /* nPositionLow (4 bytes) */
- Stream_Write_UINT32(s, fileContentsRequest->nPositionHigh); /* nPositionHigh (4 bytes) */
- Stream_Write_UINT32(s, fileContentsRequest->cbRequested); /* cbRequested (4 bytes) */
- Stream_Write_UINT32(s, fileContentsRequest->clipDataId); /* clipDataId (4 bytes) */
-
- WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFileContentsRequest: streamId: 0x%04X",
- fileContentsRequest->streamId);
-
+ Stream_Write_UINT32(s,
+ fileContentsRequest->nPositionLow); /* nPositionLow (4 bytes) */
+ Stream_Write_UINT32(s,
+ fileContentsRequest->nPositionHigh); /* nPositionHigh (4 bytes) */
+ Stream_Write_UINT32(s,
+ fileContentsRequest->cbRequested); /* cbRequested (4 bytes) */
+ Stream_Write_UINT32(s,
+ fileContentsRequest->clipDataId); /* clipDataId (4 bytes) */
+ WLog_Print(cliprdr->log, WLOG_DEBUG,
+ "ClientFileContentsRequest: streamId: 0x%04X",
+ fileContentsRequest->streamId);
return cliprdr_packet_send(cliprdr, s);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT cliprdr_client_file_contents_response(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
+static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context,
+ CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
fileContentsResponse->cbRequested = sizeof(UINT64);
s = cliprdr_packet_new(CB_FILECONTENTS_RESPONSE, fileContentsResponse->msgFlags,
- 4 + fileContentsResponse->cbRequested);
+ 4 + fileContentsResponse->cbRequested);
if (!s)
{
}
Stream_Write_UINT32(s, fileContentsResponse->streamId); /* streamId (4 bytes) */
-
/**
* requestedFileContentsData:
* FILECONTENTS_SIZE: file size as UINT64
* FILECONTENTS_RANGE: file data from requested range
*/
-
- Stream_Write(s, fileContentsResponse->requestedData, fileContentsResponse->cbRequested);
-
- WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFileContentsResponse: streamId: 0x%04X",
- fileContentsResponse->streamId);
-
+ Stream_Write(s, fileContentsResponse->requestedData,
+ fileContentsResponse->cbRequested);
+ WLog_Print(cliprdr->log, WLOG_DEBUG,
+ "ClientFileContentsResponse: streamId: 0x%04X",
+ fileContentsResponse->streamId);
return cliprdr_packet_send(cliprdr, s);
}
-/****************************************************************************************/
-
-static wListDictionary* g_InitHandles = NULL;
-static wListDictionary* g_OpenHandles = NULL;
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-UINT cliprdr_add_init_handle_data(void* pInitHandle, void* pUserData)
-{
- if (!g_InitHandles)
- g_InitHandles = ListDictionary_New(TRUE);
- if (!g_InitHandles)
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return ERROR_NOT_ENOUGH_MEMORY;
- }
-
- if (!ListDictionary_Add(g_InitHandles, pInitHandle, pUserData))
- {
- WLog_ERR(TAG, "ListDictionary_Add failed!");
- return ERROR_INTERNAL_ERROR;
- }
- return CHANNEL_RC_OK;
-}
-
-void* cliprdr_get_init_handle_data(void* pInitHandle)
-{
- void* pUserData = NULL;
- pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
- return pUserData;
-}
-
-void cliprdr_remove_init_handle_data(void* pInitHandle)
-{
- ListDictionary_Remove(g_InitHandles, pInitHandle);
- if (ListDictionary_Count(g_InitHandles) < 1)
- {
- ListDictionary_Free(g_InitHandles);
- g_InitHandles = NULL;
- }
-}
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-UINT cliprdr_add_open_handle_data(DWORD openHandle, void* pUserData)
-{
- void* pOpenHandle = (void*) (size_t) openHandle;
-
- if (!g_OpenHandles)
- g_OpenHandles = ListDictionary_New(TRUE);
-
- if (!g_OpenHandles)
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return ERROR_NOT_ENOUGH_MEMORY;
- }
-
- if (!ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData))
- {
- WLog_ERR(TAG, "ListDictionary_Add failed!");
- return ERROR_INTERNAL_ERROR;
- }
-
- return CHANNEL_RC_OK;
-}
-
-void* cliprdr_get_open_handle_data(DWORD openHandle)
-{
- void* pUserData = NULL;
- void* pOpenHandle = (void*) (size_t) openHandle;
- pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
- return pUserData;
-}
-
-void cliprdr_remove_open_handle_data(DWORD openHandle)
-{
- void* pOpenHandle = (void*) (size_t) openHandle;
- ListDictionary_Remove(g_OpenHandles, pOpenHandle);
-
- if (ListDictionary_Count(g_OpenHandles) < 1)
- {
- ListDictionary_Free(g_OpenHandles);
- g_OpenHandles = NULL;
- }
-}
-
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr,
- void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
+ void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
wStream* data_in;
return CHANNEL_RC_NO_MEMORY;
}
-
if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength))
{
Stream_Free(cliprdr->data_in, TRUE);
return ERROR_INTERNAL_ERROR;
}
}
+
return CHANNEL_RC_OK;
}
-static VOID VCAPITYPE cliprdr_virtual_channel_open_event(DWORD openHandle, UINT event,
- LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
+static VOID VCAPITYPE cliprdr_virtual_channel_open_event(DWORD openHandle,
+ UINT event,
+ LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
- cliprdrPlugin* cliprdr;
+ cliprdrPlugin* cliprdr = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- cliprdr = (cliprdrPlugin*) cliprdr_get_open_handle_data(openHandle);
-
- if (!cliprdr)
+ if (!cliprdr || (cliprdr->OpenHandle != openHandle))
{
WLog_ERR(TAG, "cliprdr_virtual_channel_open_event: error no match");
return;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
- error = cliprdr_virtual_channel_event_data_received(cliprdr, pData, dataLength, totalLength, dataFlags);
+ error = cliprdr_virtual_channel_event_data_received(cliprdr, pData, dataLength,
+ totalLength, dataFlags);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
}
if (error && cliprdr->context->rdpcontext)
- setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_open_event reported an error");
-
+ setChannelError(cliprdr->context->rdpcontext, error,
+ "cliprdr_virtual_channel_open_event reported an error");
}
static void* cliprdr_virtual_channel_client_thread(void* arg)
error = ERROR_INTERNAL_ERROR;
break;
}
+
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
{
data = (wStream*) message.wParam;
+
if ((error = cliprdr_order_recv(cliprdr, data)))
{
WLog_ERR(TAG, "cliprdr_order_recv failed with error %lu!", error);
}
if (error && cliprdr->context->rdpcontext)
- setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_client_thread reported an error");
+ setChannelError(cliprdr->context->rdpcontext, error,
+ "cliprdr_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr, LPVOID pData, UINT32 dataLength)
+static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr,
+ LPVOID pData, UINT32 dataLength)
{
UINT32 status;
- UINT error;
-
status = cliprdr->channelEntryPoints.pVirtualChannelOpen(cliprdr->InitHandle,
- &cliprdr->OpenHandle, cliprdr->channelDef.name, cliprdr_virtual_channel_open_event);
+ &cliprdr->OpenHandle, cliprdr->channelDef.name,
+ cliprdr_virtual_channel_open_event);
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
- WTSErrorToString(status), status);
+ WTSErrorToString(status), status);
return status;
}
- if ((error = cliprdr_add_open_handle_data(cliprdr->OpenHandle, cliprdr)))
- {
- WLog_ERR(TAG, "cliprdr_add_open_handle_data failed with error %lu", error);
- return error;
- }
-
cliprdr->queue = MessageQueue_New(NULL);
+
if (!cliprdr->queue)
{
WLog_ERR(TAG, "MessageQueue_New failed!");
}
if (!(cliprdr->thread = CreateThread(NULL, 0,
- (LPTHREAD_START_ROUTINE) cliprdr_virtual_channel_client_thread, (void*) cliprdr, 0, NULL)))
+ (LPTHREAD_START_ROUTINE) cliprdr_virtual_channel_client_thread, (void*) cliprdr,
+ 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
MessageQueue_Free(cliprdr->queue);
cliprdr->queue = NULL;
return ERROR_INTERNAL_ERROR;
}
+
return CHANNEL_RC_OK;
}
{
UINT rc;
- if (MessageQueue_PostQuit(cliprdr->queue, 0) && (WaitForSingleObject(cliprdr->thread, INFINITE) == WAIT_FAILED))
- {
- rc = GetLastError();
- WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
- return rc;
- }
+ if (MessageQueue_PostQuit(cliprdr->queue, 0)
+ && (WaitForSingleObject(cliprdr->thread, INFINITE) == WAIT_FAILED))
+ {
+ rc = GetLastError();
+ WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
+ return rc;
+ }
MessageQueue_Free(cliprdr->queue);
CloseHandle(cliprdr->thread);
-
rc = cliprdr->channelEntryPoints.pVirtualChannelClose(cliprdr->OpenHandle);
+
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
- WTSErrorToString(rc), rc);
+ WTSErrorToString(rc), rc);
return rc;
}
+ cliprdr->OpenHandle = 0;
+
if (cliprdr->data_in)
{
Stream_Free(cliprdr->data_in, TRUE);
cliprdr->data_in = NULL;
}
- cliprdr_remove_open_handle_data(cliprdr->OpenHandle);
return CHANNEL_RC_OK;
}
*/
static UINT cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprdr)
{
- cliprdr_remove_init_handle_data(cliprdr->InitHandle);
-
free(cliprdr);
return CHANNEL_RC_OK;
}
static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle,
- UINT event, LPVOID pData,
- UINT dataLength)
+ UINT event, LPVOID pData,
+ UINT dataLength)
{
- cliprdrPlugin* cliprdr;
+ cliprdrPlugin* cliprdr = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- cliprdr = (cliprdrPlugin*) cliprdr_get_init_handle_data(pInitHandle);
-
- if (!cliprdr)
+ if (!cliprdr || (cliprdr->InitHandle != pInitHandle))
{
WLog_ERR(TAG, "error no match");
return;
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
- if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData, dataLength)))
- WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %lu!", error);
+ if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData,
+ dataLength)))
+ WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %lu!",
+ error);
+
break;
case CHANNEL_EVENT_DISCONNECTED:
if ((error = cliprdr_virtual_channel_event_disconnected(cliprdr)))
- WLog_ERR(TAG, "cliprdr_virtual_channel_event_disconnected failed with error %lu!", error);
+ WLog_ERR(TAG,
+ "cliprdr_virtual_channel_event_disconnected failed with error %lu!", error);
+
break;
case CHANNEL_EVENT_TERMINATED:
if ((error = cliprdr_virtual_channel_event_terminated(cliprdr)))
- WLog_ERR(TAG, "cliprdr_virtual_channel_event_terminated failed with error %lu!", error);
+ WLog_ERR(TAG, "cliprdr_virtual_channel_event_terminated failed with error %lu!",
+ error);
+
break;
}
+
if (error && cliprdr->context->rdpcontext)
- setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_init_event reported an error");
+ setChannelError(cliprdr->context->rdpcontext, error,
+ "cliprdr_virtual_channel_init_event reported an error");
}
/* cliprdr is always built-in */
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
- int error;
-
cliprdrPlugin* cliprdr;
CliprdrClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
-
cliprdr = (cliprdrPlugin*) calloc(1, sizeof(cliprdrPlugin));
+
if (!cliprdr)
{
WLog_ERR(TAG, "calloc failed!");
}
cliprdr->channelDef.options =
- CHANNEL_OPTION_INITIALIZED |
- CHANNEL_OPTION_ENCRYPT_RDP |
- CHANNEL_OPTION_COMPRESS_RDP |
- CHANNEL_OPTION_SHOW_PROTOCOL;
-
+ CHANNEL_OPTION_INITIALIZED |
+ CHANNEL_OPTION_ENCRYPT_RDP |
+ CHANNEL_OPTION_COMPRESS_RDP |
+ CHANNEL_OPTION_SHOW_PROTOCOL;
strcpy(cliprdr->channelDef.name, "cliprdr");
-
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
- (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
+ (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
context = (CliprdrClientContext*) calloc(1, sizeof(CliprdrClientContext));
+
if (!context)
{
free(cliprdr);
context->handle = (void*) cliprdr;
context->custom = NULL;
-
context->ClientCapabilities = cliprdr_client_capabilities;
context->TempDirectory = cliprdr_temp_directory;
context->ClientFormatList = cliprdr_client_format_list;
context->ClientFormatDataResponse = cliprdr_client_format_data_response;
context->ClientFileContentsRequest = cliprdr_client_file_contents_request;
context->ClientFileContentsResponse = cliprdr_client_file_contents_response;
-
*(pEntryPointsEx->ppInterface) = (void*) context;
cliprdr->context = context;
context->rdpcontext = pEntryPointsEx->context;
}
cliprdr->log = WLog_Get("com.freerdp.channels.cliprdr.client");
-
cliprdr->useLongFormatNames = TRUE;
cliprdr->streamFileClipEnabled = FALSE;
cliprdr->fileClipNoFilePaths = TRUE;
cliprdr->canLockClipData = FALSE;
-
WLog_Print(cliprdr->log, WLOG_DEBUG, "VirtualChannelEntry");
-
- CopyMemory(&(cliprdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
-
+ CopyMemory(&(cliprdr->channelEntryPoints), pEntryPoints,
+ sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
rc = cliprdr->channelEntryPoints.pVirtualChannelInit(&cliprdr->InitHandle,
- &cliprdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, cliprdr_virtual_channel_init_event);
+ &cliprdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
+ cliprdr_virtual_channel_init_event);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
- WTSErrorToString(rc), rc);
- free(cliprdr->context);
- free(cliprdr);
- return FALSE;
- }
-
- cliprdr->channelEntryPoints.pInterface = *(cliprdr->channelEntryPoints.ppInterface);
- cliprdr->channelEntryPoints.ppInterface = &(cliprdr->channelEntryPoints.pInterface);
-
- if ((error = cliprdr_add_init_handle_data(cliprdr->InitHandle, (void*) cliprdr)))
- {
- WLog_ERR(TAG, "cliprdr_add_init_handle_data failed with error %lu", error);
+ WTSErrorToString(rc), rc);
free(cliprdr->context);
free(cliprdr);
return FALSE;
}
+ cliprdr->channelEntryPoints.pInterface = *
+ (cliprdr->channelEntryPoints.ppInterface);
+ cliprdr->channelEntryPoints.ppInterface = &
+ (cliprdr->channelEntryPoints.pInterface);
+ s_TLSPluginContext = cliprdr;
return TRUE;
}
};
typedef struct cliprdr_plugin cliprdrPlugin;
-wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen);
-UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* data_out);
-
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr);
#ifdef WITH_DEBUG_CLIPRDR
#define TAG CHANNELS_TAG("drdynvc.client")
+static WINPR_TLS drdynvcPlugin* s_TLSPluginContext = NULL;
+
static void dvcman_channel_free(void* channel);
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId,
const BYTE* data, UINT32 dataSize);
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
- UINT32 ChannelId, const char* ChannelName)
+static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
+ UINT32 ChannelId, const char* ChannelName)
{
int i;
BOOL bAccept;
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId,
- const BYTE* data, UINT32 dataSize)
+static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId,
+ const BYTE* data, UINT32 dataSize)
{
wStream* data_out;
unsigned long pos;
}
}
-/****************************************************************************************/
-
-static wListDictionary* g_InitHandles = NULL;
-static wListDictionary* g_OpenHandles = NULL;
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-static UINT drdynvc_add_init_handle_data(void* pInitHandle, void* pUserData)
-{
- if (!g_InitHandles)
- g_InitHandles = ListDictionary_New(TRUE);
-
- if (!g_InitHandles)
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
-
- if (!ListDictionary_Add(g_InitHandles, pInitHandle, pUserData))
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return ERROR_INTERNAL_ERROR;
- }
-
- return CHANNEL_RC_OK;
-}
-
-static void* drdynvc_get_init_handle_data(void* pInitHandle)
-{
- void* pUserData = NULL;
- pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
- return pUserData;
-}
-
-static void drdynvc_remove_init_handle_data(void* pInitHandle)
-{
- ListDictionary_Remove(g_InitHandles, pInitHandle);
-
- if (ListDictionary_Count(g_InitHandles) < 1)
- {
- ListDictionary_Free(g_InitHandles);
- g_InitHandles = NULL;
- }
-}
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-static UINT drdynvc_add_open_handle_data(DWORD openHandle, void* pUserData)
-{
- void* pOpenHandle = (void*)(size_t) openHandle;
-
- if (!g_OpenHandles)
- g_OpenHandles = ListDictionary_New(TRUE);
-
- if (!g_OpenHandles)
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
-
- if (!ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData))
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return ERROR_INTERNAL_ERROR;
- }
-
- return CHANNEL_RC_OK;
-}
-
-static void* drdynvc_get_open_handle_data(DWORD openHandle)
-{
- void* pUserData = NULL;
- void* pOpenHandle = (void*)(size_t) openHandle;
- pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
- return pUserData;
-}
-
-static void drdynvc_remove_open_handle_data(DWORD openHandle)
-{
- void* pOpenHandle = (void*)(size_t) openHandle;
-
- if (!g_OpenHandles)
- return;
-
- ListDictionary_Remove(g_OpenHandles, pOpenHandle);
-
- if (ListDictionary_Count(g_OpenHandles) < 1)
- {
- ListDictionary_Free(g_OpenHandles);
- g_OpenHandles = NULL;
- }
-}
-
/**
* Function description
*
UINT event,
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
- drdynvcPlugin* drdynvc;
+ drdynvcPlugin* drdynvc = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- drdynvc = (drdynvcPlugin*) drdynvc_get_open_handle_data(openHandle);
- if (!drdynvc)
+ if (!drdynvc || (drdynvc->OpenHandle != openHandle))
{
WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match");
return;
wMessage message;
drdynvcPlugin* drdynvc = (drdynvcPlugin*) arg;
UINT error = CHANNEL_RC_OK;
+ freerdp_channel_init_thread_context(drdynvc->rdpcontext);
while (1)
{
return status;
}
- if ((error = drdynvc_add_open_handle_data(drdynvc->OpenHandle, drdynvc)))
- {
- WLog_ERR(TAG, "drdynvc_add_open_handle_data failed with error %lu!", error);
- return error;
- }
-
drdynvc->queue = MessageQueue_New(NULL);
if (!drdynvc->queue)
goto error;
}
- return CHANNEL_RC_OK;
error:
- drdynvc_remove_open_handle_data(drdynvc->OpenHandle);
return error;
}
WTSErrorToString(status), status);
}
+ drdynvc->OpenHandle = 0;
+
if (drdynvc->data_in)
{
Stream_Free(drdynvc->data_in, TRUE);
drdynvc->channel_mgr = NULL;
}
- drdynvc_remove_open_handle_data(drdynvc->OpenHandle);
return status;
}
*/
static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
{
- drdynvc_remove_init_handle_data(drdynvc->InitHandle);
+ drdynvc->InitHandle = 0;
free(drdynvc);
return CHANNEL_RC_OK;
}
UINT event, LPVOID pData,
UINT dataLength)
{
- drdynvcPlugin* drdynvc;
+ drdynvcPlugin* drdynvc = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- drdynvc = (drdynvcPlugin*) drdynvc_get_init_handle_data(pInitHandle);
- if (!drdynvc)
+ if (!drdynvc || (drdynvc->InitHandle != pInitHandle))
{
WLog_ERR(TAG, "drdynvc_virtual_channel_init_event: error no match");
return;
drdynvcPlugin* drdynvc;
DrdynvcClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
- UINT error;
drdynvc = (drdynvcPlugin*) calloc(1, sizeof(drdynvcPlugin));
if (!drdynvc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
WTSErrorToString(rc), rc);
+ free(drdynvc->context);
free(drdynvc);
- free(*(pEntryPointsEx->ppInterface));
- *(pEntryPointsEx->ppInterface) = NULL;
return FALSE;
}
(drdynvc->channelEntryPoints.ppInterface);
drdynvc->channelEntryPoints.ppInterface = &
(drdynvc->channelEntryPoints.pInterface);
-
- if ((error = drdynvc_add_init_handle_data(drdynvc->InitHandle,
- (void*) drdynvc)))
- {
- WLog_ERR(TAG, "drdynvc_add_init_handle_data failed with error %lu!", error);
- free(drdynvc);
- free(*(pEntryPointsEx->ppInterface));
- *(pEntryPointsEx->ppInterface) = NULL;
- return FALSE;
- }
-
+ s_TLSPluginContext = drdynvc;
return TRUE;
}
#include "encomsp_main.h"
+static WINPR_TLS encomspPlugin* s_TLSPluginContext = NULL;
+
/**
* Function description
*
Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */
Stream_Read_UINT16(s, header->Length); /* Length (2 bytes) */
-
return CHANNEL_RC_OK;
}
{
Stream_Write_UINT16(s, header->Type); /* Type (2 bytes) */
Stream_Write_UINT16(s, header->Length); /* Length (2 bytes) */
-
return CHANNEL_RC_OK;
}
return ERROR_INVALID_DATA;
}
- if (Stream_GetRemainingLength(s) < (size_t) (str->cchString * 2))
+ if (Stream_GetRemainingLength(s) < (size_t)(str->cchString * 2))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
Stream_Read(s, &(str->wString), (str->cchString * 2)); /* String (variable) */
-
return CHANNEL_RC_OK;
}
-EncomspClientContext* encomsp_get_client_interface(encomspPlugin* encomsp)
+static EncomspClientContext* encomsp_get_client_interface(
+ encomspPlugin* encomsp)
{
EncomspClientContext* pInterface;
pInterface = (EncomspClientContext*) encomsp->channelEntryPoints.pInterface;
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s)
+static UINT encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s)
{
UINT status;
WLog_INFO(TAG, "EncomspWrite (%d)", Stream_Length(s));
winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
#endif
-
status = encomsp->channelEntryPoints.pVirtualChannelWrite(encomsp->OpenHandle,
- Stream_Buffer(s), (UINT32) Stream_Length(s), s);
+ Stream_Buffer(s), (UINT32) Stream_Length(s), s);
if (status != CHANNEL_RC_OK)
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
- WTSErrorToString(status), status);
+ WTSErrorToString(status), status);
return status;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s,
+ ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_FILTER_UPDATED_PDU pdu;
UINT error = CHANNEL_RC_OK;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 1)
}
Stream_Read_UINT8(s, pdu.Flags); /* Flags (1 byte) */
-
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->FilterUpdated, error, context, &pdu);
+
if (error)
WLog_ERR(TAG, "context->FilterUpdated failed with error %lu", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp,
+ wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_APPLICATION_CREATED_PDU pdu;
UINT error;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 6)
Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */
- if ((error = encomsp_read_unicode_string(s, &(pdu.Name)) ))
+ if ((error = encomsp_read_unicode_string(s, &(pdu.Name))))
{
WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %lu", error);
return error;
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->ApplicationCreated, error, context, &pdu);
+
if (error)
WLog_ERR(TAG, "context->ApplicationCreated failed with error %lu", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp,
+ wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_APPLICATION_REMOVED_PDU pdu;
UINT error = CHANNEL_RC_OK;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 4)
}
Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */
-
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->ApplicationRemoved, error, context, &pdu);
+
if (error)
WLog_ERR(TAG, "context->ApplicationRemoved failed with error %lu", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s,
+ ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_WINDOW_CREATED_PDU pdu;
UINT error;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 10)
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->WindowCreated, error, context, &pdu);
+
if (error)
WLog_ERR(TAG, "context->WindowCreated failed with error %lu", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s,
+ ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_WINDOW_REMOVED_PDU pdu;
UINT error = CHANNEL_RC_OK;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 4)
}
Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */
-
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->WindowRemoved, error, context, &pdu);
+
if (error)
WLog_ERR(TAG, "context->WindowRemoved failed with error %lu", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s,
+ ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_SHOW_WINDOW_PDU pdu;
UINT error = CHANNEL_RC_OK;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 4)
}
Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */
-
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->ShowWindow, error, context, &pdu);
+
if (error)
WLog_ERR(TAG, "context->ShowWindow failed with error %lu", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp,
+ wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_PARTICIPANT_CREATED_PDU pdu;
UINT error;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 10)
Stream_Read_UINT32(s, pdu.GroupId); /* GroupId (4 bytes) */
Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
-
if ((error = encomsp_read_unicode_string(s, &(pdu.FriendlyName))))
{
WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %lu", error);
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->ParticipantCreated, error, context, &pdu);
+
if (error)
WLog_ERR(TAG, "context->ParticipantCreated failed with error %lu", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp,
+ wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_PARTICIPANT_REMOVED_PDU pdu;
UINT error = CHANNEL_RC_OK;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 12)
Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */
Stream_Read_UINT32(s, pdu.DiscType); /* DiscType (4 bytes) */
Stream_Read_UINT32(s, pdu.DiscCode); /* DiscCode (4 bytes) */
-
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->ParticipantRemoved, error, context, &pdu);
+
if (error)
WLog_ERR(TAG, "context->ParticipantRemoved failed with error %lu", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_change_participant_control_level_pdu(
+ encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu;
UINT error = CHANNEL_RC_OK;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 6)
Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */
-
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu);
+
if (error)
- WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %lu", error);
+ WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %lu",
+ error);
return error;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_send_change_participant_control_level_pdu(EncomspClientContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* pdu)
+static UINT encomsp_send_change_participant_control_level_pdu(
+ EncomspClientContext* context,
+ ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* pdu)
{
wStream* s;
encomspPlugin* encomsp;
UINT error;
-
encomsp = (encomspPlugin*) context->handle;
-
pdu->Type = ODTYPE_PARTICIPANT_CTRL_CHANGED;
pdu->Length = ENCOMSP_ORDER_HEADER_SIZE + 6;
-
s = Stream_New(NULL, pdu->Length);
+
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
Stream_Write_UINT16(s, pdu->Flags); /* Flags (2 bytes) */
Stream_Write_UINT32(s, pdu->ParticipantId); /* ParticipantId (4 bytes) */
-
Stream_SealLength(s);
-
return encomsp_virtual_channel_write(encomsp, s);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp,
+ wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU pdu;
UINT error = CHANNEL_RC_OK;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
-
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->GraphicsStreamPaused, error, context, &pdu);
+
if (error)
WLog_ERR(TAG, "context->GraphicsStreamPaused failed with error %lu", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
+static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp,
+ wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU pdu;
UINT error = CHANNEL_RC_OK;
-
context = encomsp_get_client_interface(encomsp);
if (!context)
return ERROR_INVALID_HANDLE;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
-
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
-
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
if ((beg + header->Length) > end)
{
- if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
+ if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end))
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
IFCALLRET(context->GraphicsStreamResumed, error, context, &pdu);
+
if (error)
WLog_ERR(TAG, "context->GraphicsStreamResumed failed with error %lu", error);
WLog_ERR(TAG, "encomsp_recv_filter_updated_pdu failed with error %lu!", error);
return error;
}
+
break;
case ODTYPE_APP_REMOVED:
if ((error = encomsp_recv_application_removed_pdu(encomsp, s, &header)))
{
- WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %lu!", error);
+ WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %lu!",
+ error);
return error;
}
+
break;
case ODTYPE_APP_CREATED:
if ((error = encomsp_recv_application_created_pdu(encomsp, s, &header)))
{
- WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %lu!", error);
+ WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %lu!",
+ error);
return error;
}
+
break;
case ODTYPE_WND_REMOVED:
WLog_ERR(TAG, "encomsp_recv_window_removed_pdu failed with error %lu!", error);
return error;
}
+
break;
case ODTYPE_WND_CREATED:
WLog_ERR(TAG, "encomsp_recv_window_created_pdu failed with error %lu!", error);
return error;
}
+
break;
case ODTYPE_WND_SHOW:
WLog_ERR(TAG, "encomsp_recv_show_window_pdu failed with error %lu!", error);
return error;
}
+
break;
case ODTYPE_PARTICIPANT_REMOVED:
if ((error = encomsp_recv_participant_removed_pdu(encomsp, s, &header)))
{
- WLog_ERR(TAG, "encomsp_recv_participant_removed_pdu failed with error %lu!", error);
+ WLog_ERR(TAG, "encomsp_recv_participant_removed_pdu failed with error %lu!",
+ error);
return error;
}
+
break;
case ODTYPE_PARTICIPANT_CREATED:
if ((error = encomsp_recv_participant_created_pdu(encomsp, s, &header)))
{
- WLog_ERR(TAG, "encomsp_recv_participant_created_pdu failed with error %lu!", error);
+ WLog_ERR(TAG, "encomsp_recv_participant_created_pdu failed with error %lu!",
+ error);
return error;
}
+
break;
case ODTYPE_PARTICIPANT_CTRL_CHANGED:
- if ((error = encomsp_recv_change_participant_control_level_pdu(encomsp, s, &header)))
+ if ((error = encomsp_recv_change_participant_control_level_pdu(encomsp, s,
+ &header)))
{
- WLog_ERR(TAG, "encomsp_recv_change_participant_control_level_pdu failed with error %lu!", error);
+ WLog_ERR(TAG,
+ "encomsp_recv_change_participant_control_level_pdu failed with error %lu!",
+ error);
return error;
}
+
break;
case ODTYPE_GRAPHICS_STREAM_PAUSED:
if ((error = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header)))
{
- WLog_ERR(TAG, "encomsp_recv_graphics_stream_paused_pdu failed with error %lu!", error);
+ WLog_ERR(TAG, "encomsp_recv_graphics_stream_paused_pdu failed with error %lu!",
+ error);
return error;
}
+
break;
case ODTYPE_GRAPHICS_STREAM_RESUMED:
if ((error = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header)))
{
- WLog_ERR(TAG, "encomsp_recv_graphics_stream_resumed_pdu failed with error %lu!", error);
+ WLog_ERR(TAG, "encomsp_recv_graphics_stream_resumed_pdu failed with error %lu!",
+ error);
return error;
}
+
break;
default:
return ERROR_INVALID_DATA;
break;
}
-
}
+
return error;
}
static void encomsp_process_connect(encomspPlugin* encomsp)
{
-
}
-/****************************************************************************************/
-
-static wListDictionary* g_InitHandles = NULL;
-static wListDictionary* g_OpenHandles = NULL;
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-UINT encomsp_add_init_handle_data(void* pInitHandle, void* pUserData)
-{
- if (!g_InitHandles)
- {
- g_InitHandles = ListDictionary_New(TRUE);
- }
- if (!g_InitHandles)
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
-
- if (!ListDictionary_Add(g_InitHandles, pInitHandle, pUserData))
- {
- WLog_ERR(TAG, "ListDictionary_Add failed!");
- return ERROR_INTERNAL_ERROR;
- }
- return CHANNEL_RC_OK;
-}
-
-void* encomsp_get_init_handle_data(void* pInitHandle)
-{
- void* pUserData = NULL;
- pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
- return pUserData;
-}
-
-void encomsp_remove_init_handle_data(void* pInitHandle)
-{
- ListDictionary_Remove(g_InitHandles, pInitHandle);
- if (ListDictionary_Count(g_InitHandles) < 1)
- {
- ListDictionary_Free(g_InitHandles);
- g_InitHandles = NULL;
- }
-}
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-UINT encomsp_add_open_handle_data(DWORD openHandle, void* pUserData)
-{
- void* pOpenHandle = (void*) (size_t) openHandle;
-
- if (!g_OpenHandles)
- {
- g_OpenHandles = ListDictionary_New(TRUE);
- }
-
- if (!g_OpenHandles)
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
-
- if (!ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData))
- {
- WLog_ERR(TAG, "ListDictionary_Add failed!");
- return ERROR_INTERNAL_ERROR;
- }
- return CHANNEL_RC_OK;
-}
-
-void* encomsp_get_open_handle_data(DWORD openHandle)
-{
- void* pUserData = NULL;
- void* pOpenHandle = (void*) (size_t) openHandle;
- pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
- return pUserData;
-}
-
-void encomsp_remove_open_handle_data(DWORD openHandle)
-{
- void* pOpenHandle = (void*) (size_t) openHandle;
- ListDictionary_Remove(g_OpenHandles, pOpenHandle);
- if (ListDictionary_Count(g_OpenHandles) < 1)
- {
- ListDictionary_Free(g_OpenHandles);
- g_OpenHandles = NULL;
- }
-}
-
-int encomsp_send(encomspPlugin* encomsp, wStream* s)
+static int encomsp_send(encomspPlugin* encomsp, wStream* s)
{
UINT32 status = 0;
encomspPlugin* plugin = (encomspPlugin*) encomsp;
else
{
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
- Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
+ Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
}
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
- WTSErrorToString(status), status);
+ WTSErrorToString(status), status);
}
return status;
* @return 0 on success, otherwise a Win32 error code
*/
static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp,
- void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
+ void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
wStream* data_in;
Stream_Free(encomsp->data_in, TRUE);
encomsp->data_in = Stream_New(NULL, totalLength);
+
if (!encomsp->data_in)
{
WLog_ERR(TAG, "Stream_New failed!");
}
data_in = encomsp->data_in;
+
if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return ERROR_INTERNAL_ERROR;
}
+
Stream_Write(data_in, pData, dataLength);
if (dataFlags & CHANNEL_FLAG_LAST)
return ERROR_INTERNAL_ERROR;
}
}
+
return CHANNEL_RC_OK;
}
-static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle, UINT event,
- LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
+static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle,
+ UINT event,
+ LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
- encomspPlugin* encomsp;
+ encomspPlugin* encomsp = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- encomsp = (encomspPlugin*) encomsp_get_open_handle_data(openHandle);
-
- if (!encomsp)
+ if (!encomsp || (encomsp->OpenHandle != openHandle))
{
WLog_ERR(TAG, "encomsp_virtual_channel_open_event: error no match");
return;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
- if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength, totalLength, dataFlags)))
- WLog_ERR(TAG, "encomsp_virtual_channel_event_data_received failed with error %lu", error);
+ if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData,
+ dataLength, totalLength, dataFlags)))
+ WLog_ERR(TAG,
+ "encomsp_virtual_channel_event_data_received failed with error %lu", error);
+
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
case CHANNEL_EVENT_USER:
break;
}
+
if (error && encomsp->rdpcontext)
- setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_open_event reported an error");
+ setChannelError(encomsp->rdpcontext, error,
+ "encomsp_virtual_channel_open_event reported an error");
return;
}
wMessage message;
encomspPlugin* encomsp = (encomspPlugin*) arg;
UINT error = CHANNEL_RC_OK;
-
encomsp_process_connect(encomsp);
while (1)
if (message.id == 0)
{
data = (wStream*) message.wParam;
+
if ((error = encomsp_process_receive(encomsp, data)))
{
WLog_ERR(TAG, "encomsp_process_receive failed with error %lu!", error);
}
if (error && encomsp->rdpcontext)
- setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_client_thread reported an error");
+ setChannelError(encomsp->rdpcontext, error,
+ "encomsp_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp, LPVOID pData, UINT32 dataLength)
+static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp,
+ LPVOID pData, UINT32 dataLength)
{
UINT32 status;
- UINT error;
-
status = encomsp->channelEntryPoints.pVirtualChannelOpen(encomsp->InitHandle,
- &encomsp->OpenHandle, encomsp->channelDef.name, encomsp_virtual_channel_open_event);
+ &encomsp->OpenHandle, encomsp->channelDef.name,
+ encomsp_virtual_channel_open_event);
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
- WTSErrorToString(status), status);
- return status;
- }
-
- if ((error = encomsp_add_open_handle_data(encomsp->OpenHandle, encomsp)))
- {
- WLog_ERR(TAG, "encomsp_process_receive failed with error %lu!", error);
+ WTSErrorToString(status), status);
return status;
}
encomsp->queue = MessageQueue_New(NULL);
+
if (!encomsp->queue)
{
WLog_ERR(TAG, "MessageQueue_New failed!");
}
if (!(encomsp->thread = CreateThread(NULL, 0,
- (LPTHREAD_START_ROUTINE) encomsp_virtual_channel_client_thread, (void*) encomsp, 0, NULL)))
+ (LPTHREAD_START_ROUTINE) encomsp_virtual_channel_client_thread, (void*) encomsp,
+ 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
MessageQueue_Free(encomsp->queue);
return ERROR_INTERNAL_ERROR;
}
+
return CHANNEL_RC_OK;
}
{
UINT rc;
- if (MessageQueue_PostQuit(encomsp->queue, 0) && (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED))
- {
- rc = GetLastError();
- WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
- return rc;
- }
+ if (MessageQueue_PostQuit(encomsp->queue, 0)
+ && (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED))
+ {
+ rc = GetLastError();
+ WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
+ return rc;
+ }
MessageQueue_Free(encomsp->queue);
CloseHandle(encomsp->thread);
-
encomsp->queue = NULL;
encomsp->thread = NULL;
-
rc = encomsp->channelEntryPoints.pVirtualChannelClose(encomsp->OpenHandle);
+
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
- WTSErrorToString(rc), rc);
+ WTSErrorToString(rc), rc);
return rc;
}
+ encomsp->OpenHandle = 0;
+
if (encomsp->data_in)
{
Stream_Free(encomsp->data_in, TRUE);
encomsp->data_in = NULL;
}
- encomsp_remove_open_handle_data(encomsp->OpenHandle);
return CHANNEL_RC_OK;
}
*/
static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
{
- encomsp_remove_init_handle_data(encomsp->InitHandle);
+ encomsp->InitHandle = 0;
free(encomsp);
return CHANNEL_RC_OK;
}
static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle,
- UINT event, LPVOID pData,
- UINT dataLength)
+ UINT event, LPVOID pData,
+ UINT dataLength)
{
- encomspPlugin* encomsp;
+ encomspPlugin* encomsp = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- encomsp = (encomspPlugin*) encomsp_get_init_handle_data(pInitHandle);
-
- if (!encomsp)
+ if (!encomsp || (encomsp->InitHandle != pInitHandle))
{
WLog_ERR(TAG, "encomsp_virtual_channel_init_event: error no match");
return;
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
- if ((error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength)))
- WLog_ERR(TAG, "encomsp_virtual_channel_event_connected failed with error %lu", error);
+ if ((error = encomsp_virtual_channel_event_connected(encomsp, pData,
+ dataLength)))
+ WLog_ERR(TAG, "encomsp_virtual_channel_event_connected failed with error %lu",
+ error);
+
break;
case CHANNEL_EVENT_DISCONNECTED:
if ((error = encomsp_virtual_channel_event_disconnected(encomsp)))
- WLog_ERR(TAG, "encomsp_virtual_channel_event_disconnected failed with error %lu", error);
+ WLog_ERR(TAG,
+ "encomsp_virtual_channel_event_disconnected failed with error %lu", error);
+
break;
case CHANNEL_EVENT_TERMINATED:
encomsp_virtual_channel_event_terminated(encomsp);
break;
+
default:
WLog_ERR(TAG, "Unhandled event type %d", event);
}
if (error && encomsp->rdpcontext)
- setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_init_event reported an error");
+ setChannelError(encomsp->rdpcontext, error,
+ "encomsp_virtual_channel_init_event reported an error");
}
/* encomsp is always built-in */
EncomspClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
BOOL isFreerdp = FALSE;
- UINT error;
-
encomsp = (encomspPlugin*) calloc(1, sizeof(encomspPlugin));
+
if (!encomsp)
{
WLog_ERR(TAG, "calloc failed!");
}
encomsp->channelDef.options =
- CHANNEL_OPTION_INITIALIZED |
- CHANNEL_OPTION_ENCRYPT_RDP |
- CHANNEL_OPTION_COMPRESS_RDP |
- CHANNEL_OPTION_SHOW_PROTOCOL;
-
+ CHANNEL_OPTION_INITIALIZED |
+ CHANNEL_OPTION_ENCRYPT_RDP |
+ CHANNEL_OPTION_COMPRESS_RDP |
+ CHANNEL_OPTION_SHOW_PROTOCOL;
strcpy(encomsp->channelDef.name, "encomsp");
-
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
- (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
+ (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
context = (EncomspClientContext*) calloc(1, sizeof(EncomspClientContext));
+
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
}
context->handle = (void*) encomsp;
-
context->FilterUpdated = NULL;
context->ApplicationCreated = NULL;
context->ApplicationRemoved = NULL;
context->ShowWindow = NULL;
context->ParticipantCreated = NULL;
context->ParticipantRemoved = NULL;
- context->ChangeParticipantControlLevel = encomsp_send_change_participant_control_level_pdu;
+ context->ChangeParticipantControlLevel =
+ encomsp_send_change_participant_control_level_pdu;
context->GraphicsStreamPaused = NULL;
context->GraphicsStreamResumed = NULL;
-
*(pEntryPointsEx->ppInterface) = (void*) context;
encomsp->context = context;
encomsp->rdpcontext = pEntryPointsEx->context;
isFreerdp = TRUE;
}
- CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
-
+ CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints,
+ sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
rc = encomsp->channelEntryPoints.pVirtualChannelInit(&encomsp->InitHandle,
- &encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, encomsp_virtual_channel_init_event);
+ &encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
+ encomsp_virtual_channel_init_event);
+
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
- WTSErrorToString(rc), rc);
- goto error_out;
- }
-
- encomsp->channelEntryPoints.pInterface = *(encomsp->channelEntryPoints.ppInterface);
- encomsp->channelEntryPoints.ppInterface = &(encomsp->channelEntryPoints.pInterface);
-
- if ((error = encomsp_add_init_handle_data(encomsp->InitHandle, (void*) encomsp)))
- {
- WLog_ERR(TAG, "encomsp_add_init_handle_data failed with error %lu!", error);
+ WTSErrorToString(rc), rc);
goto error_out;
}
+ encomsp->channelEntryPoints.pInterface = *
+ (encomsp->channelEntryPoints.ppInterface);
+ encomsp->channelEntryPoints.ppInterface = &
+ (encomsp->channelEntryPoints.pInterface);
+ s_TLSPluginContext = encomsp;
return TRUE;
error_out:
+
if (isFreerdp)
free(encomsp->context);
+
free(encomsp);
return FALSE;
}
#include "rail_orders.h"
#include "rail_main.h"
+static WINPR_TLS railPlugin* s_TLSPluginContext = NULL;
+
RailClientContext* rail_get_client_interface(railPlugin* rail)
{
RailClientContext* pInterface;
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_send(railPlugin* rail, wStream* s)
+static UINT rail_send(railPlugin* rail, wStream* s)
{
UINT status;
else
{
status = rail->channelEntryPoints.pVirtualChannelWrite(rail->OpenHandle,
- Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
+ Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
}
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
- WTSErrorToString(status), status);
+ WTSErrorToString(status), status);
}
return status;
UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length)
{
wStream* s = NULL;
-
s = Stream_New(NULL, length);
+
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
- Stream_Write(s, data, length);
+ Stream_Write(s, data, length);
return rail_send(rail, s);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_execute(RailClientContext* context, RAIL_EXEC_ORDER* exec)
+static UINT rail_client_execute(RailClientContext* context,
+ RAIL_EXEC_ORDER* exec)
{
char* exeOrFile;
railPlugin* rail = (railPlugin*) context->handle;
-
exeOrFile = exec->RemoteApplicationProgram;
if (!exeOrFile)
exec->flags |= RAIL_EXEC_FLAG_FILE;
}
- rail_string_to_unicode_string(exec->RemoteApplicationProgram, &exec->exeOrFile); /* RemoteApplicationProgram */
- rail_string_to_unicode_string(exec->RemoteApplicationWorkingDir, &exec->workingDir); /* ShellWorkingDirectory */
- rail_string_to_unicode_string(exec->RemoteApplicationArguments, &exec->arguments); /* RemoteApplicationCmdLine */
-
+ rail_string_to_unicode_string(exec->RemoteApplicationProgram,
+ &exec->exeOrFile); /* RemoteApplicationProgram */
+ rail_string_to_unicode_string(exec->RemoteApplicationWorkingDir,
+ &exec->workingDir); /* ShellWorkingDirectory */
+ rail_string_to_unicode_string(exec->RemoteApplicationArguments,
+ &exec->arguments); /* RemoteApplicationCmdLine */
return rail_send_client_exec_order(rail, exec);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_activate(RailClientContext* context, RAIL_ACTIVATE_ORDER* activate)
+static UINT rail_client_activate(RailClientContext* context,
+ RAIL_ACTIVATE_ORDER* activate)
{
railPlugin* rail = (railPlugin*) context->handle;
-
return rail_send_client_activate_order(rail, activate);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_send_client_sysparam(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam)
+static UINT rail_send_client_sysparam(RailClientContext* context,
+ RAIL_SYSPARAM_ORDER* sysparam)
{
wStream* s;
int length;
railPlugin* rail = (railPlugin*) context->handle;
UINT error;
-
length = RAIL_SYSPARAM_ORDER_LENGTH;
switch (sysparam->param)
}
s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH + 8);
+
if (!s)
{
WLog_ERR(TAG, "rail_pdu_init failed!");
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam)
+static UINT rail_client_system_param(RailClientContext* context,
+ RAIL_SYSPARAM_ORDER* sysparam)
{
UINT error = CHANNEL_RC_OK;
if (sysparam->params & SPI_MASK_SET_HIGH_CONTRAST)
{
sysparam->param = SPI_SET_HIGH_CONTRAST;
+
if ((error = rail_send_client_sysparam(context, sysparam)))
{
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
if (sysparam->params & SPI_MASK_TASKBAR_POS)
{
sysparam->param = SPI_TASKBAR_POS;
+
if ((error = rail_send_client_sysparam(context, sysparam)))
{
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
if (sysparam->params & SPI_MASK_SET_MOUSE_BUTTON_SWAP)
{
sysparam->param = SPI_SET_MOUSE_BUTTON_SWAP;
+
if ((error = rail_send_client_sysparam(context, sysparam)))
{
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
if (sysparam->params & SPI_MASK_SET_KEYBOARD_PREF)
{
sysparam->param = SPI_SET_KEYBOARD_PREF;
+
if ((error = rail_send_client_sysparam(context, sysparam)))
{
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
if (sysparam->params & SPI_MASK_SET_DRAG_FULL_WINDOWS)
{
sysparam->param = SPI_SET_DRAG_FULL_WINDOWS;
+
if ((error = rail_send_client_sysparam(context, sysparam)))
{
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
if (sysparam->params & SPI_MASK_SET_KEYBOARD_CUES)
{
sysparam->param = SPI_SET_KEYBOARD_CUES;
+
if ((error = rail_send_client_sysparam(context, sysparam)))
{
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
if (sysparam->params & SPI_MASK_SET_WORK_AREA)
{
sysparam->param = SPI_SET_WORK_AREA;
+
if ((error = rail_send_client_sysparam(context, sysparam)))
{
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_server_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam)
+static UINT rail_server_system_param(RailClientContext* context,
+ RAIL_SYSPARAM_ORDER* sysparam)
{
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_system_command(RailClientContext* context, RAIL_SYSCOMMAND_ORDER* syscommand)
+static UINT rail_client_system_command(RailClientContext* context,
+ RAIL_SYSCOMMAND_ORDER* syscommand)
{
railPlugin* rail = (railPlugin*) context->handle;
-
return rail_send_client_syscommand_order(rail, syscommand);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* handshake)
+static UINT rail_client_handshake(RailClientContext* context,
+ RAIL_HANDSHAKE_ORDER* handshake)
{
railPlugin* rail = (railPlugin*) context->handle;
-
return rail_send_handshake_order(rail, handshake);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_server_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* handshake)
+static UINT rail_server_handshake(RailClientContext* context,
+ RAIL_HANDSHAKE_ORDER* handshake)
{
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
+static UINT rail_client_handshake_ex(RailClientContext* context,
+ RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
railPlugin* rail = (railPlugin*) context->handle;
-
return rail_send_handshake_ex_order(rail, handshakeEx);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_server_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
+static UINT rail_server_handshake_ex(RailClientContext* context,
+ RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_notify_event(RailClientContext* context, RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
+static UINT rail_client_notify_event(RailClientContext* context,
+ RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
{
railPlugin* rail = (railPlugin*) context->handle;
-
return rail_send_client_notify_event_order(rail, notifyEvent);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_window_move(RailClientContext* context, RAIL_WINDOW_MOVE_ORDER* windowMove)
+static UINT rail_client_window_move(RailClientContext* context,
+ RAIL_WINDOW_MOVE_ORDER* windowMove)
{
railPlugin* rail = (railPlugin*) context->handle;
-
return rail_send_client_window_move_order(rail, windowMove);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_server_local_move_size(RailClientContext* context, RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
+static UINT rail_server_local_move_size(RailClientContext* context,
+ RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
{
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_server_min_max_info(RailClientContext* context, RAIL_MINMAXINFO_ORDER* minMaxInfo)
+static UINT rail_server_min_max_info(RailClientContext* context,
+ RAIL_MINMAXINFO_ORDER* minMaxInfo)
{
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_information(RailClientContext* context, RAIL_CLIENT_STATUS_ORDER* clientStatus)
+static UINT rail_client_information(RailClientContext* context,
+ RAIL_CLIENT_STATUS_ORDER* clientStatus)
{
railPlugin* rail = (railPlugin*) context->handle;
-
return rail_send_client_status_order(rail, clientStatus);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_system_menu(RailClientContext* context, RAIL_SYSMENU_ORDER* sysmenu)
+static UINT rail_client_system_menu(RailClientContext* context,
+ RAIL_SYSMENU_ORDER* sysmenu)
{
railPlugin* rail = (railPlugin*) context->handle;
-
return rail_send_client_sysmenu_order(rail, sysmenu);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO_ORDER* langBarInfo)
+static UINT rail_client_language_bar_info(RailClientContext* context,
+ RAIL_LANGBAR_INFO_ORDER* langBarInfo)
{
railPlugin* rail = (railPlugin*) context->handle;
-
return rail_send_client_langbar_info_order(rail, langBarInfo);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_server_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO_ORDER* langBarInfo)
+static UINT rail_server_language_bar_info(RailClientContext* context,
+ RAIL_LANGBAR_INFO_ORDER* langBarInfo)
{
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_server_execute_result(RailClientContext* context, RAIL_EXEC_RESULT_ORDER* execResult)
+static UINT rail_server_execute_result(RailClientContext* context,
+ RAIL_EXEC_RESULT_ORDER* execResult)
{
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_client_get_appid_request(RailClientContext* context, RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
+static UINT rail_client_get_appid_request(RailClientContext* context,
+ RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
{
railPlugin* rail = (railPlugin*) context->handle;
-
return rail_send_client_get_appid_req_order(rail, getAppIdReq);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rail_server_get_appid_response(RailClientContext* context, RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
+static UINT rail_server_get_appid_response(RailClientContext* context,
+ RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
{
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
-/****************************************************************************************/
-
-static wListDictionary* g_InitHandles = NULL;
-static wListDictionary* g_OpenHandles = NULL;
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-UINT rail_add_init_handle_data(void* pInitHandle, void* pUserData)
-{
- if (!g_InitHandles)
- {
- g_InitHandles = ListDictionary_New(TRUE);
- }
- if (!g_InitHandles)
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
-
- if (!ListDictionary_Add(g_InitHandles, pInitHandle, pUserData))
- {
- WLog_ERR(TAG, "ListDictionary_Add failed!");
- return ERROR_INTERNAL_ERROR;
- }
- return CHANNEL_RC_OK;
-}
-
-void* rail_get_init_handle_data(void* pInitHandle)
-{
- void* pUserData = NULL;
- pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
- return pUserData;
-}
-
-void rail_remove_init_handle_data(void* pInitHandle)
-{
- ListDictionary_Remove(g_InitHandles, pInitHandle);
- if (ListDictionary_Count(g_InitHandles) < 1)
- {
- ListDictionary_Free(g_InitHandles);
- g_InitHandles = NULL;
- }
-}
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-UINT rail_add_open_handle_data(DWORD openHandle, void* pUserData)
-{
- void* pOpenHandle = (void*) (size_t) openHandle;
-
- if (!g_OpenHandles)
- {
- g_OpenHandles = ListDictionary_New(TRUE);
- }
- if (!g_OpenHandles)
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
-
- if (!ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData))
- {
- WLog_ERR(TAG, "ListDictionary_Add failed!");
- return ERROR_INTERNAL_ERROR;
- }
- return CHANNEL_RC_OK;
-}
-
-void* rail_get_open_handle_data(DWORD openHandle)
-{
- void* pUserData = NULL;
- void* pOpenHandle = (void*) (size_t) openHandle;
- pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
- return pUserData;
-}
-
-void rail_remove_open_handle_data(DWORD openHandle)
-{
- void* pOpenHandle = (void*) (size_t) openHandle;
- ListDictionary_Remove(g_OpenHandles, pOpenHandle);
- if (ListDictionary_Count(g_OpenHandles) < 1)
- {
- ListDictionary_Free(g_OpenHandles);
- g_OpenHandles = NULL;
- }
-}
-
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rail_virtual_channel_event_data_received(railPlugin* rail,
- void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
+ void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
wStream* data_in;
Stream_Free(rail->data_in, TRUE);
rail->data_in = Stream_New(NULL, totalLength);
+
if (!rail->data_in)
{
WLog_ERR(TAG, "Stream_New failed!");
}
data_in = rail->data_in;
+
if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
+
Stream_Write(data_in, pData, dataLength);
if (dataFlags & CHANNEL_FLAG_LAST)
return ERROR_INTERNAL_ERROR;
}
}
+
return CHANNEL_RC_OK;
}
-static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle, UINT event,
- LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
+static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle,
+ UINT event,
+ LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
- railPlugin* rail;
+ railPlugin* rail = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- rail = (railPlugin*) rail_get_open_handle_data(openHandle);
-
- if (!rail)
+ if (!rail || (rail->OpenHandle != openHandle))
{
WLog_ERR(TAG, "rail_virtual_channel_open_event: error no match");
return;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
- if ((error = rail_virtual_channel_event_data_received(rail, pData, dataLength, totalLength, dataFlags)))
- WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %lu!", error);
+ if ((error = rail_virtual_channel_event_data_received(rail, pData, dataLength,
+ totalLength, dataFlags)))
+ WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %lu!",
+ error);
+
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
}
if (error && rail->rdpcontext)
- setChannelError(rail->rdpcontext, error, "rail_virtual_channel_open_event reported an error");
+ setChannelError(rail->rdpcontext, error,
+ "rail_virtual_channel_open_event reported an error");
return;
}
error = ERROR_INTERNAL_ERROR;
break;
}
+
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
{
data = (wStream*) message.wParam;
+
if ((error = rail_order_recv(rail, data)))
{
WLog_ERR(TAG, "rail_order_recv failed with error %d!", error);
}
if (error && rail->rdpcontext)
- setChannelError(rail->rdpcontext, error, "rail_virtual_channel_client_thread reported an error");
+ setChannelError(rail->rdpcontext, error,
+ "rail_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData, UINT32 dataLength)
+static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData,
+ UINT32 dataLength)
{
UINT status;
-
status = rail->channelEntryPoints.pVirtualChannelOpen(rail->InitHandle,
- &rail->OpenHandle, rail->channelDef.name, rail_virtual_channel_open_event);
+ &rail->OpenHandle, rail->channelDef.name, rail_virtual_channel_open_event);
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
- WTSErrorToString(status), status);
- return status;
- }
-
- if ((status = rail_add_open_handle_data(rail->OpenHandle, rail)))
- {
- WLog_ERR(TAG, "rail_add_open_handle_data failed with error %lu!", status);
+ WTSErrorToString(status), status);
return status;
}
rail->queue = MessageQueue_New(NULL);
+
if (!rail->queue)
{
WLog_ERR(TAG, "MessageQueue_New failed!");
}
if (!(rail->thread = CreateThread(NULL, 0,
- (LPTHREAD_START_ROUTINE) rail_virtual_channel_client_thread, (void*) rail, 0, NULL)))
+ (LPTHREAD_START_ROUTINE) rail_virtual_channel_client_thread, (void*) rail, 0,
+ NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
MessageQueue_Free(rail->queue);
rail->queue = NULL;
return ERROR_INTERNAL_ERROR;
}
+
return CHANNEL_RC_OK;
}
static UINT rail_virtual_channel_event_disconnected(railPlugin* rail)
{
UINT rc;
- if (MessageQueue_PostQuit(rail->queue, 0) && (WaitForSingleObject(rail->thread, INFINITE) == WAIT_FAILED))
- {
- rc = GetLastError();
- WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
- return rc;
- }
+
+ if (MessageQueue_PostQuit(rail->queue, 0)
+ && (WaitForSingleObject(rail->thread, INFINITE) == WAIT_FAILED))
+ {
+ rc = GetLastError();
+ WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
+ return rc;
+ }
MessageQueue_Free(rail->queue);
CloseHandle(rail->thread);
-
rail->queue = NULL;
rail->thread = NULL;
-
rc = rail->channelEntryPoints.pVirtualChannelClose(rail->OpenHandle);
+
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
- WTSErrorToString(rc), rc);
- return rc;
+ WTSErrorToString(rc), rc);
+ return rc;
}
+ rail->OpenHandle = 0;
+
if (rail->data_in)
{
Stream_Free(rail->data_in, TRUE);
rail->data_in = NULL;
}
- rail_remove_open_handle_data(rail->OpenHandle);
- return CHANNEL_RC_OK;
+ return CHANNEL_RC_OK;
}
static void rail_virtual_channel_event_terminated(railPlugin* rail)
{
- rail_remove_init_handle_data(rail->InitHandle);
+ rail->InitHandle = 0;
free(rail);
}
-static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
+static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle,
+ UINT event, LPVOID pData, UINT dataLength)
{
- railPlugin* rail;
+ railPlugin* rail = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- rail = (railPlugin*) rail_get_init_handle_data(pInitHandle);
-
- if (!rail)
+ if (!rail || (rail->InitHandle != pInitHandle))
{
WLog_ERR(TAG, "rail_virtual_channel_init_event: error no match");
return;
{
case CHANNEL_EVENT_CONNECTED:
if ((error = rail_virtual_channel_event_connected(rail, pData, dataLength)))
- WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %lu!", error);
+ WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %lu!",
+ error);
+
break;
case CHANNEL_EVENT_DISCONNECTED:
if ((error = rail_virtual_channel_event_disconnected(rail)))
- WLog_ERR(TAG, "rail_virtual_channel_event_disconnected failed with error %lu!", error);
+ WLog_ERR(TAG, "rail_virtual_channel_event_disconnected failed with error %lu!",
+ error);
+
break;
case CHANNEL_EVENT_TERMINATED:
break;
}
- if(error && rail->rdpcontext)
- setChannelError(rail->rdpcontext, error, "rail_virtual_channel_init_event reported an error");
+ if (error && rail->rdpcontext)
+ setChannelError(rail->rdpcontext, error,
+ "rail_virtual_channel_init_event reported an error");
}
/* rail is always built-in */
RailClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
BOOL isFreerdp = FALSE;
- UINT error;
-
rail = (railPlugin*) calloc(1, sizeof(railPlugin));
+
if (!rail)
{
WLog_ERR(TAG, "calloc failed!");
}
rail->channelDef.options =
- CHANNEL_OPTION_INITIALIZED |
- CHANNEL_OPTION_ENCRYPT_RDP |
- CHANNEL_OPTION_COMPRESS_RDP |
- CHANNEL_OPTION_SHOW_PROTOCOL;
-
+ CHANNEL_OPTION_INITIALIZED |
+ CHANNEL_OPTION_ENCRYPT_RDP |
+ CHANNEL_OPTION_COMPRESS_RDP |
+ CHANNEL_OPTION_SHOW_PROTOCOL;
strcpy(rail->channelDef.name, "rail");
-
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
- (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
+ (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
context = (RailClientContext*) calloc(1, sizeof(RailClientContext));
+
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
context->handle = (void*) rail;
context->custom = NULL;
-
context->ClientExecute = rail_client_execute;
context->ClientActivate = rail_client_activate;
context->ClientSystemParam = rail_client_system_param;
context->ClientGetAppIdRequest = rail_client_get_appid_request;
context->ServerGetAppIdResponse = rail_server_get_appid_response;
rail->rdpcontext = pEntryPointsEx->context;
-
*(pEntryPointsEx->ppInterface) = (void*) context;
rail->context = context;
isFreerdp = TRUE;
WLog_Init();
rail->log = WLog_Get("com.freerdp.channels.rail.client");
-
WLog_Print(rail->log, WLOG_DEBUG, "VirtualChannelEntry");
-
- CopyMemory(&(rail->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
-
+ CopyMemory(&(rail->channelEntryPoints), pEntryPoints,
+ sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
rc = rail->channelEntryPoints.pVirtualChannelInit(&rail->InitHandle,
- &rail->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rail_virtual_channel_init_event);
+ &rail->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
+ rail_virtual_channel_init_event);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
- WTSErrorToString(rc), rc);
+ WTSErrorToString(rc), rc);
goto error_out;
}
rail->channelEntryPoints.pInterface = *(rail->channelEntryPoints.ppInterface);
rail->channelEntryPoints.ppInterface = &(rail->channelEntryPoints.pInterface);
-
- if ((error = rail_add_init_handle_data(rail->InitHandle, (void*) rail)))
- {
- WLog_ERR(TAG, "rail_add_init_handle_data failed with error %lu!", error);
- goto error_out;
- }
-
+ s_TLSPluginContext = rail;
return TRUE;
error_out:
+
if (isFreerdp)
free(rail->context);
+
free(rail);
return FALSE;
}
char* path;
};
+static WINPR_TLS rdpdrPlugin* s_TLSPluginContext = NULL;
+
/**
* Function description
*
return error;
}
-void first_hotplug(rdpdrPlugin* rdpdr)
+static void first_hotplug(rdpdrPlugin* rdpdr)
{
UINT error;
return CHANNEL_RC_OK;
}
-
-/****************************************************************************************/
-
-
-static wListDictionary* g_InitHandles = NULL;
-static wListDictionary* g_OpenHandles = NULL;
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-UINT rdpdr_add_init_handle_data(void* pInitHandle, void* pUserData)
-{
- if (!g_InitHandles)
- {
- g_InitHandles = ListDictionary_New(TRUE);
- }
-
- if (!g_InitHandles)
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
-
- if (!ListDictionary_Add(g_InitHandles, pInitHandle, pUserData))
- {
- WLog_ERR(TAG, "ListDictionary_Add failed!");
- return ERROR_INTERNAL_ERROR;
- }
-
- return CHANNEL_RC_OK;
-}
-
-void* rdpdr_get_init_handle_data(void* pInitHandle)
-{
- void* pUserData = NULL;
- pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
- return pUserData;
-}
-
-void rdpdr_remove_init_handle_data(void* pInitHandle)
-{
- ListDictionary_Remove(g_InitHandles, pInitHandle);
-
- if (ListDictionary_Count(g_InitHandles) < 1)
- {
- ListDictionary_Free(g_InitHandles);
- g_InitHandles = NULL;
- }
-}
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-UINT rdpdr_add_open_handle_data(DWORD openHandle, void* pUserData)
-{
- void* pOpenHandle = (void*)(size_t) openHandle;
-
- if (!g_OpenHandles)
- {
- g_OpenHandles = ListDictionary_New(TRUE);
- }
-
- if (!g_OpenHandles)
- {
- WLog_ERR(TAG, "ListDictionary_New failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
-
- if (!ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData))
- {
- WLog_ERR(TAG, "ListDictionary_Add failed!");
- return ERROR_INTERNAL_ERROR;
- }
-
- return CHANNEL_RC_OK;
-}
-
-void* rdpdr_get_open_handle_data(DWORD openHandle)
-{
- void* pUserData = NULL;
- void* pOpenHandle = (void*)(size_t) openHandle;
- pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
- return pUserData;
-}
-
-void rdpdr_remove_open_handle_data(DWORD openHandle)
-{
- void* pOpenHandle = (void*)(size_t) openHandle;
- ListDictionary_Remove(g_OpenHandles, pOpenHandle);
-
- if (ListDictionary_Count(g_OpenHandles) < 1)
- {
- ListDictionary_Free(g_OpenHandles);
- g_OpenHandles = NULL;
- }
-}
-
/**
* Function description
*
UINT event,
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
- rdpdrPlugin* rdpdr;
+ rdpdrPlugin* rdpdr = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- rdpdr = (rdpdrPlugin*) rdpdr_get_open_handle_data(openHandle);
- if (!rdpdr || !pData)
+ if (!rdpdr || !pData || (rdpdr->OpenHandle != openHandle))
{
WLog_ERR(TAG, "rdpdr_virtual_channel_open_event: error no match");
return;
LPVOID pData, UINT32 dataLength)
{
UINT32 status;
- UINT error;
status = rdpdr->channelEntryPoints.pVirtualChannelOpen(rdpdr->InitHandle,
&rdpdr->OpenHandle, rdpdr->channelDef.name, rdpdr_virtual_channel_open_event);
return status;
}
- if ((error = rdpdr_add_open_handle_data(rdpdr->OpenHandle, rdpdr)))
- {
- WLog_ERR(TAG, "rdpdr_add_open_handle_data failed with error %lu!", error);
- return error;
- }
-
rdpdr->queue = MessageQueue_New(NULL);
if (!rdpdr->queue)
WTSErrorToString(error), error);
}
+ rdpdr->OpenHandle = 0;
+
if (rdpdr->data_in)
{
Stream_Free(rdpdr->data_in, TRUE);
rdpdr->devman = NULL;
}
- rdpdr_remove_open_handle_data(rdpdr->OpenHandle);
return error;
}
static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
{
- rdpdr_remove_init_handle_data(rdpdr->InitHandle);
free(rdpdr);
}
UINT event,
LPVOID pData, UINT dataLength)
{
- rdpdrPlugin* rdpdr;
+ rdpdrPlugin* rdpdr = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- rdpdr = (rdpdrPlugin*) rdpdr_get_init_handle_data(pInitHandle);
- if (!rdpdr)
+ if (!rdpdr || (rdpdr->InitHandle != pInitHandle))
{
WLog_ERR(TAG, "error no match");
return;
return FALSE;
}
- if ((rc = rdpdr_add_init_handle_data(rdpdr->InitHandle, (void*) rdpdr)))
- {
- WLog_ERR(TAG, "rdpdr_add_init_handle_data failed with error %lu!", rc);
- free(rdpdr);
- return FALSE;
- }
-
+ s_TLSPluginContext = rdpdr;
return TRUE;
}
rdpContext* rdpcontext;
};
+static WINPR_TLS rdpsndPlugin* s_TLSPluginContext = NULL;
+
/**
* Function description
*
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg;
HANDLE events[2];
UINT error = CHANNEL_RC_OK;
- DWORD status;
-
+ DWORD status;
events[0] = MessageQueue_Event(rdpsnd->MsgPipe->Out);
events[1] = rdpsnd->stopEvent;
while (1)
{
- status = WaitForMultipleObjects(2, events, FALSE, INFINITE);
+ status = WaitForMultipleObjects(2, events, FALSE, INFINITE);
- if (status == WAIT_FAILED)
- {
- error = GetLastError();
- WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
- break;
- }
-
- status = WaitForSingleObject(rdpsnd->stopEvent, 0);
-
- if (status == WAIT_FAILED)
- {
- error = GetLastError();
- WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
- break;
- }
+ if (status == WAIT_FAILED)
+ {
+ error = GetLastError();
+ WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
+ break;
+ }
- if (status == WAIT_OBJECT_0)
- break;
+ status = WaitForSingleObject(rdpsnd->stopEvent, 0);
+ if (status == WAIT_FAILED)
+ {
+ error = GetLastError();
+ WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
+ break;
+ }
- status = WaitForSingleObject(events[0], 0);
+ if (status == WAIT_OBJECT_0)
+ break;
- if (status == WAIT_FAILED)
- {
- error = GetLastError();
- WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
- break;
- }
+ status = WaitForSingleObject(events[0], 0);
+ if (status == WAIT_FAILED)
+ {
+ error = GetLastError();
+ WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
+ break;
+ }
- if (!MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, TRUE))
+ if (!MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
}
if (error && rdpsnd->rdpcontext)
- setChannelError(rdpsnd->rdpcontext, error, "rdpsnd_schedule_thread reported an error");
+ setChannelError(rdpsnd->rdpcontext, error,
+ "rdpsnd_schedule_thread reported an error");
ExitThread((DWORD)error);
return NULL;
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
+static UINT rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
{
wStream* pdu;
-
pdu = Stream_New(NULL, 8);
+
if (!pdu)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
+
Stream_Write_UINT8(pdu, SNDC_QUALITYMODE); /* msgType */
Stream_Write_UINT8(pdu, 0); /* bPad */
Stream_Write_UINT16(pdu, 4); /* BodySize */
Stream_Write_UINT16(pdu, rdpsnd->wQualityMode); /* wQualityMode */
Stream_Write_UINT16(pdu, 0); /* Reserved */
-
WLog_Print(rdpsnd->log, WLOG_DEBUG, "QualityMode: %d", rdpsnd->wQualityMode);
-
return rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
int index;
AUDIO_FORMAT* serverFormat;
AUDIO_FORMAT* clientFormat;
-
rdpsnd_free_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats);
rdpsnd->NumberOfClientFormats = 0;
rdpsnd->ClientFormats = NULL;
if (!rdpsnd->NumberOfServerFormats)
return;
- rdpsnd->ClientFormats = (AUDIO_FORMAT*) malloc(sizeof(AUDIO_FORMAT) * rdpsnd->NumberOfServerFormats);
+ rdpsnd->ClientFormats = (AUDIO_FORMAT*) malloc(sizeof(AUDIO_FORMAT) *
+ rdpsnd->NumberOfServerFormats);
+
for (index = 0; index < (int) rdpsnd->NumberOfServerFormats; index++)
{
serverFormat = &rdpsnd->ServerFormats[index];
- if (rdpsnd->fixedFormat > 0 && (rdpsnd->fixedFormat != serverFormat->wFormatTag))
+ if (rdpsnd->fixedFormat > 0
+ && (rdpsnd->fixedFormat != serverFormat->wFormatTag))
continue;
- if (rdpsnd->fixedChannel > 0 && (rdpsnd->fixedChannel != serverFormat->nChannels))
+ if (rdpsnd->fixedChannel > 0
+ && (rdpsnd->fixedChannel != serverFormat->nChannels))
continue;
- if (rdpsnd->fixedRate > 0 && (rdpsnd->fixedRate != serverFormat->nSamplesPerSec))
+ if (rdpsnd->fixedRate > 0
+ && (rdpsnd->fixedRate != serverFormat->nSamplesPerSec))
continue;
- if (rdpsnd->device && rdpsnd->device->FormatSupported(rdpsnd->device, serverFormat))
+ if (rdpsnd->device
+ && rdpsnd->device->FormatSupported(rdpsnd->device, serverFormat))
{
clientFormat = &rdpsnd->ClientFormats[rdpsnd->NumberOfClientFormats++];
-
CopyMemory(clientFormat, serverFormat, sizeof(AUDIO_FORMAT));
clientFormat->cbSize = 0;
#if 0
WLog_ERR(TAG, "Server ");
- rdpsnd_print_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats);
+ rdpsnd_print_audio_formats(rdpsnd->ServerFormats,
+ rdpsnd->NumberOfServerFormats);
WLog_ERR(TAG, "");
WLog_ERR(TAG, "Client ");
- rdpsnd_print_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats);
+ rdpsnd_print_audio_formats(rdpsnd->ClientFormats,
+ rdpsnd->NumberOfClientFormats);
WLog_ERR(TAG, "");
#endif
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
+static UINT rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
{
int index;
wStream* pdu;
UINT16 dwVolumeRight;
UINT16 wNumberOfFormats;
AUDIO_FORMAT* clientFormat;
-
dwVolumeLeft = ((50 * 0xFFFF) / 100); /* 50% */
dwVolumeRight = ((50 * 0xFFFF) / 100); /* 50% */
dwVolume = (dwVolumeLeft << 16) | dwVolumeRight;
}
wNumberOfFormats = rdpsnd->NumberOfClientFormats;
-
length = 4 + 20;
for (index = 0; index < (int) wNumberOfFormats; index++)
length += (18 + rdpsnd->ClientFormats[index].cbSize);
pdu = Stream_New(NULL, length);
+
if (!pdu)
{
WLog_ERR(TAG, "Stream_New failed!");
Stream_Write_UINT8(pdu, SNDC_FORMATS); /* msgType */
Stream_Write_UINT8(pdu, 0); /* bPad */
Stream_Write_UINT16(pdu, length - 4); /* BodySize */
-
Stream_Write_UINT32(pdu, TSSNDCAPS_ALIVE | TSSNDCAPS_VOLUME); /* dwFlags */
Stream_Write_UINT32(pdu, dwVolume); /* dwVolume */
Stream_Write_UINT32(pdu, 0); /* dwPitch */
for (index = 0; index < (int) wNumberOfFormats; index++)
{
clientFormat = &rdpsnd->ClientFormats[index];
-
Stream_Write_UINT16(pdu, clientFormat->wFormatTag);
Stream_Write_UINT16(pdu, clientFormat->nChannels);
Stream_Write_UINT32(pdu, clientFormat->nSamplesPerSec);
}
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Client Audio Formats");
-
return rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
+static UINT rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd,
+ wStream* s)
{
int index;
UINT16 wVersion;
AUDIO_FORMAT* format;
UINT16 wNumberOfFormats;
UINT ret = ERROR_BAD_LENGTH;
-
rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats);
rdpsnd->NumberOfServerFormats = 0;
rdpsnd->ServerFormats = NULL;
Stream_Read_UINT8(s, rdpsnd->cBlockNo); /* cLastBlockConfirmed */
Stream_Read_UINT16(s, wVersion); /* wVersion */
Stream_Seek_UINT8(s); /* bPad */
-
rdpsnd->NumberOfServerFormats = wNumberOfFormats;
+
if (Stream_GetRemainingLength(s) / 14 < wNumberOfFormats)
return ERROR_BAD_LENGTH;
- rdpsnd->ServerFormats = (AUDIO_FORMAT*) calloc(wNumberOfFormats, sizeof(AUDIO_FORMAT));
+ rdpsnd->ServerFormats = (AUDIO_FORMAT*) calloc(wNumberOfFormats,
+ sizeof(AUDIO_FORMAT));
+
if (!rdpsnd->ServerFormats)
return CHANNEL_RC_NO_MEMORY;
if (Stream_GetRemainingLength(s) < 14)
goto out_fail;
+
Stream_Read_UINT16(s, format->wFormatTag); /* wFormatTag */
Stream_Read_UINT16(s, format->nChannels); /* nChannels */
Stream_Read_UINT32(s, format->nSamplesPerSec); /* nSamplesPerSec */
goto out_fail;
format->data = (BYTE*) malloc(format->cbSize);
+
if (!format->data)
{
ret = CHANNEL_RC_NO_MEMORY;
goto out_fail;
}
+
Stream_Read(s, format->data, format->cbSize);
}
}
rdpsnd_select_supported_audio_formats(rdpsnd);
-
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Server Audio Formats");
-
ret = rdpsnd_send_client_audio_formats(rdpsnd);
+
if (ret == CHANNEL_RC_OK)
{
if (wVersion >= 6)
}
return ret;
-
out_fail:
+
for (index = 0; index < (int) wNumberOfFormats; index++)
free(format->data);
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, UINT16 wPackSize)
+static UINT rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd,
+ UINT16 wTimeStamp, UINT16 wPackSize)
{
wStream* pdu;
-
pdu = Stream_New(NULL, 8);
+
if (!pdu)
{
WLog_ERR(TAG, "Stream_New failed!");
Stream_Write_UINT16(pdu, 4); /* BodySize */
Stream_Write_UINT16(pdu, wTimeStamp);
Stream_Write_UINT16(pdu, wPackSize);
-
- WLog_Print(rdpsnd->log, WLOG_DEBUG, "Training Response: wTimeStamp: %d wPackSize: %d",
- wTimeStamp, wPackSize);
-
+ WLog_Print(rdpsnd->log, WLOG_DEBUG,
+ "Training Response: wTimeStamp: %d wPackSize: %d",
+ wTimeStamp, wPackSize);
return rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
Stream_Read_UINT16(s, wTimeStamp);
Stream_Read_UINT16(s, wPackSize);
-
- WLog_Print(rdpsnd->log, WLOG_DEBUG, "Training Request: wTimeStamp: %d wPackSize: %d",
- wTimeStamp, wPackSize);
-
+ WLog_Print(rdpsnd->log, WLOG_DEBUG,
+ "Training Request: wTimeStamp: %d wPackSize: %d",
+ wTimeStamp, wPackSize);
return rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s, UINT16 BodySize)
+static UINT rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s,
+ UINT16 BodySize)
{
UINT16 wFormatNo;
AUDIO_FORMAT* format;
-
rdpsnd->expectingWave = TRUE;
if (Stream_GetRemainingLength(s) < 12)
Stream_Read_UINT8(s, rdpsnd->cBlockNo);
Stream_Seek(s, 3); /* bPad */
Stream_Read(s, rdpsnd->waveData, 4);
-
rdpsnd->waveDataSize = BodySize - 8;
-
format = &rdpsnd->ClientFormats[wFormatNo];
-
WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveInfo: cBlockNo: %d wFormatNo: %d",
- rdpsnd->cBlockNo, wFormatNo);
+ rdpsnd->cBlockNo, wFormatNo);
if (!rdpsnd->isOpen)
{
//rdpsnd_print_audio_format(format);
if (rdpsnd->device && rdpsnd->device->Open &&
- !rdpsnd->device->Open(rdpsnd->device, format, rdpsnd->latency))
+ !rdpsnd->device->Open(rdpsnd->device, format, rdpsnd->latency))
{
- return CHANNEL_RC_INITIALIZATION_ERROR;
+ return CHANNEL_RC_INITIALIZATION_ERROR;
}
}
else if (wFormatNo != rdpsnd->wCurrentFormatNo)
if (rdpsnd->device)
{
- if(rdpsnd->device->SetFormat && !rdpsnd->device->SetFormat(rdpsnd->device, format, rdpsnd->latency))
- return CHANNEL_RC_INITIALIZATION_ERROR;
+ if (rdpsnd->device->SetFormat
+ && !rdpsnd->device->SetFormat(rdpsnd->device, format, rdpsnd->latency))
+ return CHANNEL_RC_INITIALIZATION_ERROR;
}
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE cConfirmedBlockNo)
+static UINT rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd,
+ UINT16 wTimeStamp, BYTE cConfirmedBlockNo)
{
wStream* pdu;
-
pdu = Stream_New(NULL, 8);
+
if (!pdu)
{
WLog_ERR(TAG, "Stream_New failed!");
Stream_Write_UINT16(pdu, wTimeStamp);
Stream_Write_UINT8(pdu, cConfirmedBlockNo); /* cConfirmedBlockNo */
Stream_Write_UINT8(pdu, 0); /* bPad */
-
return rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave)
+static UINT rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave)
{
- WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveConfirm: cBlockNo: %d wTimeStamp: %d wTimeDiff: %d",
- wave->cBlockNo, wave->wTimeStampB, wave->wTimeStampB - wave->wTimeStampA);
-
+ WLog_Print(rdpsnd->log, WLOG_DEBUG,
+ "WaveConfirm: cBlockNo: %d wTimeStamp: %d wTimeDiff: %d",
+ wave->cBlockNo, wave->wTimeStampB, wave->wTimeStampB - wave->wTimeStampA);
return rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
+static UINT rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device,
+ RDPSND_WAVE* wave)
{
if (device->DisableConfirmThread)
return rdpsnd_confirm_wave(device->rdpsnd, wave);
- if (!MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave, NULL))
+ if (!MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave,
+ NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
-
}
/**
RDPSND_WAVE* wave;
AUDIO_FORMAT* format;
UINT status;
-
rdpsnd->expectingWave = FALSE;
-
/**
* The Wave PDU is a special case: it is always sent after a Wave Info PDU,
* and we do not process its header. Instead, the header is pad that needs
* to be filled with the first four bytes of the audio sample data sent as
* part of the preceding Wave Info PDU.
*/
-
CopyMemory(Stream_Buffer(s), rdpsnd->waveData, 4);
-
data = Stream_Buffer(s);
size = (int) Stream_Capacity(s);
-
wave = (RDPSND_WAVE*) calloc(1, sizeof(RDPSND_WAVE));
+
if (!wave)
{
WLog_ERR(TAG, "calloc failed!");
wave->wTimeStampA = rdpsnd->wTimeStamp;
wave->wFormatNo = rdpsnd->wCurrentFormatNo;
wave->cBlockNo = rdpsnd->cBlockNo;
-
wave->data = data;
wave->length = size;
wave->AutoConfirm = TRUE;
-
format = &rdpsnd->ClientFormats[rdpsnd->wCurrentFormatNo];
wave->wAudioLength = rdpsnd_compute_audio_time_length(format, size);
-
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Wave: cBlockNo: %d wTimeStamp: %d",
- wave->cBlockNo, wave->wTimeStampA);
+ wave->cBlockNo, wave->wTimeStampA);
if (!rdpsnd->device)
{
return status;
}
- if (rdpsnd->device->WaveDecode && !rdpsnd->device->WaveDecode(rdpsnd->device, wave))
+ if (rdpsnd->device->WaveDecode
+ && !rdpsnd->device->WaveDecode(rdpsnd->device, wave))
{
free(wave);
return CHANNEL_RC_NO_MEMORY;
}
status = CHANNEL_RC_OK;
+
if (wave->AutoConfirm)
status = rdpsnd->device->WaveConfirm(rdpsnd->device, wave);
+
return status;
}
return ERROR_BAD_LENGTH;
Stream_Read_UINT32(s, dwVolume);
-
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Volume: 0x%04X", dwVolume);
if (rdpsnd->device && rdpsnd->device->SetVolume &&
- !rdpsnd->device->SetVolume(rdpsnd->device, dwVolume))
+ !rdpsnd->device->SetVolume(rdpsnd->device, dwVolume))
{
WLog_ERR(TAG, "error setting volume");
return CHANNEL_RC_INITIALIZATION_ERROR;
}
+
return CHANNEL_RC_OK;
}
return status;
}
-static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd, rdpsndDevicePlugin* device)
+static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd,
+ rdpsndDevicePlugin* device)
{
if (rdpsnd->device)
{
rdpsnd->device = device;
device->rdpsnd = rdpsnd;
-
device->WaveConfirm = rdpsnd_device_send_wave_confirm_pdu;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, ADDIN_ARGV* args)
+static UINT rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name,
+ ADDIN_ARGV* args)
{
PFREERDP_RDPSND_DEVICE_ENTRY entry;
- FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;\
+ FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;
+ \
UINT error;
-
- entry = (PFREERDP_RDPSND_DEVICE_ENTRY) freerdp_load_channel_addin_entry("rdpsnd", (LPSTR) name, NULL, 0);
+ entry = (PFREERDP_RDPSND_DEVICE_ENTRY)
+ freerdp_load_channel_addin_entry("rdpsnd", (LPSTR) name, NULL, 0);
if (!entry)
return ERROR_INTERNAL_ERROR;
return error;
}
-BOOL rdpsnd_set_subsystem(rdpsndPlugin* rdpsnd, const char* subsystem)
+static BOOL rdpsnd_set_subsystem(rdpsndPlugin* rdpsnd, const char* subsystem)
{
free(rdpsnd->subsystem);
rdpsnd->subsystem = _strdup(subsystem);
int status;
DWORD flags;
COMMAND_LINE_ARGUMENT_A* arg;
-
rdpsnd->wQualityMode = HIGH_QUALITY; /* default quality mode */
-
if (args->argc > 1)
{
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
- status = CommandLineParseArgumentsA(args->argc, (const char **) args->argv,
- rdpsnd_args, flags, rdpsnd, NULL, NULL);
+ status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
+ rdpsnd_args, flags, rdpsnd, NULL, NULL);
if (status < 0)
return CHANNEL_RC_INITIALIZATION_ERROR;
continue;
CommandLineSwitchStart(arg)
-
CommandLineSwitchCase(arg, "sys")
{
if (!rdpsnd_set_subsystem(rdpsnd, arg->Value))
}
CommandLineSwitchDefault(arg)
{
-
}
-
CommandLineSwitchEnd(arg)
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
{
ADDIN_ARGV* args;
UINT status = ERROR_INTERNAL_ERROR;
- char *subsystem_name = NULL, *device_name = NULL;
-
+ char* subsystem_name = NULL, *device_name = NULL;
rdpsnd->latency = -1;
-
args = (ADDIN_ARGV*) rdpsnd->channelEntryPoints.pExtendedData;
+
if (args)
{
status = rdpsnd_process_addin_args(rdpsnd, args);
+
if (status != CHANNEL_RC_OK)
return status;
}
if ((status = rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args)))
{
- WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", rdpsnd->subsystem, status);
+ WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
+ rdpsnd->subsystem, status);
return status;
}
}
else
{
#if defined(WITH_IOSAUDIO)
+
if (!rdpsnd->device)
{
subsystem_name = "ios";
device_name = "";
+
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
- WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", subsystem_name, status);
+ WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
+ subsystem_name, status);
}
-#endif
+#endif
#if defined(WITH_OPENSLES)
+
if (!rdpsnd->device)
{
subsystem_name = "opensles";
device_name = "";
+
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
- WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", subsystem_name, status);
+ WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
+ subsystem_name, status);
}
-#endif
+#endif
#if defined(WITH_PULSE)
+
if (!rdpsnd->device)
{
subsystem_name = "pulse";
device_name = "";
+
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
- WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", subsystem_name, status);
+ WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
+ subsystem_name, status);
}
-#endif
+#endif
#if defined(WITH_ALSA)
+
if (!rdpsnd->device)
{
subsystem_name = "alsa";
device_name = "default";
+
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
- WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", subsystem_name, status);
+ WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
+ subsystem_name, status);
}
-#endif
+#endif
#if defined(WITH_OSS)
+
if (!rdpsnd->device)
{
subsystem_name = "oss";
device_name = "";
+
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
- WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", subsystem_name, status);
+ WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
+ subsystem_name, status);
}
-#endif
-
+#endif
#if defined(WITH_MACAUDIO)
+
if (!rdpsnd->device)
{
subsystem_name = "mac";
device_name = "default";
+
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
- WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", subsystem_name, status);
+ WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
+ subsystem_name, status);
}
-#endif
+#endif
#if defined(WITH_WINMM)
+
if (!rdpsnd->device)
{
subsystem_name = "winmm";
device_name = "";
+
if ((status = rdpsnd_load_device_plugin(rdpsnd, subsystem_name, args)))
- WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu", subsystem_name, status);
+ WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %lu",
+ subsystem_name, status);
}
+
#endif
+
if (status)
return status;
if (rdpsnd->device)
{
- if (!rdpsnd_set_subsystem(rdpsnd, subsystem_name) || !rdpsnd_set_device_name(rdpsnd, device_name))
+ if (!rdpsnd_set_subsystem(rdpsnd, subsystem_name)
+ || !rdpsnd_set_device_name(rdpsnd, device_name))
return CHANNEL_RC_NO_MEMORY;
}
}
return CHANNEL_RC_INITIALIZATION_ERROR;
}
-
if (!rdpsnd->device->DisableConfirmThread)
{
rdpsnd->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
if (!rdpsnd->stopEvent)
{
WLog_ERR(TAG, "CreateEvent failed!");
}
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
- (LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
- (void*) rdpsnd, 0, NULL);
+ (LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
+ (void*) rdpsnd, 0, NULL);
+
if (!rdpsnd->ScheduleThread)
{
WLog_ERR(TAG, "CreateThread failed!");
if (rdpsnd->ScheduleThread)
{
SetEvent(rdpsnd->stopEvent);
+
if (WaitForSingleObject(rdpsnd->ScheduleThread, INFINITE) == WAIT_FAILED)
- {
- WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError());
- return;
- }
+ {
+ WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError());
+ return;
+ }
+
CloseHandle(rdpsnd->ScheduleThread);
CloseHandle(rdpsnd->stopEvent);
}
}
-/****************************************************************************************/
-
-
-static wListDictionary* g_InitHandles = NULL;
-static wListDictionary* g_OpenHandles = NULL;
-
-BOOL rdpsnd_add_init_handle_data(void* pInitHandle, void* pUserData)
-{
- if (!g_InitHandles)
- {
- g_InitHandles = ListDictionary_New(TRUE);
- if (!g_InitHandles)
- return FALSE;
- }
-
- return ListDictionary_Add(g_InitHandles, pInitHandle, pUserData);
-}
-
-void* rdpsnd_get_init_handle_data(void* pInitHandle)
-{
- void* pUserData = NULL;
- pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
- return pUserData;
-}
-
-void rdpsnd_remove_init_handle_data(void* pInitHandle)
-{
- ListDictionary_Remove(g_InitHandles, pInitHandle);
- if (ListDictionary_Count(g_InitHandles) < 1)
- {
- ListDictionary_Free(g_InitHandles);
- g_InitHandles = NULL;
- }
-}
-
-BOOL rdpsnd_add_open_handle_data(DWORD openHandle, void* pUserData)
-{
- void* pOpenHandle = (void*) (size_t) openHandle;
-
- if (!g_OpenHandles)
- {
- g_OpenHandles = ListDictionary_New(TRUE);
- if (!g_OpenHandles)
- return FALSE;
- }
-
- return ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData);
-}
-
-void* rdpsnd_get_open_handle_data(DWORD openHandle)
-{
- void* pUserData = NULL;
- void* pOpenHandle = (void*) (size_t) openHandle;
- pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
- return pUserData;
-}
-
-void rdpsnd_remove_open_handle_data(DWORD openHandle)
-{
- void* pOpenHandle = (void*) (size_t) openHandle;
- ListDictionary_Remove(g_OpenHandles, pOpenHandle);
- if (ListDictionary_Count(g_OpenHandles) < 1)
- {
- ListDictionary_Free(g_OpenHandles);
- g_OpenHandles = NULL;
- }
-}
-
/**
* Function description
*
else
{
status = rdpsnd->channelEntryPoints.pVirtualChannelWrite(rdpsnd->OpenHandle,
- Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
+ Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
}
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
- WTSErrorToString(status), status);
+ WTSErrorToString(status), status);
}
return status;
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
- void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
+ void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
wStream* s;
Stream_Free(plugin->data_in, TRUE);
plugin->data_in = Stream_New(NULL, totalLength);
+
if (!plugin->data_in)
{
WLog_ERR(TAG, "Stream_New failed!");
return ERROR_INTERNAL_ERROR;
}
}
+
return CHANNEL_RC_OK;
}
-static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle, UINT event,
- LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
+static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle,
+ UINT event,
+ LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
- rdpsndPlugin* rdpsnd;
+ rdpsndPlugin* rdpsnd = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- rdpsnd = (rdpsndPlugin*) rdpsnd_get_open_handle_data(openHandle);
-
- if (!rdpsnd)
+ if (!rdpsnd || (rdpsnd->OpenHandle != openHandle))
{
WLog_ERR(TAG, "rdpsnd_virtual_channel_open_event: error no match");
return;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
- if ((error = rdpsnd_virtual_channel_event_data_received(rdpsnd, pData, dataLength, totalLength, dataFlags)))
- WLog_ERR(TAG, "rdpsnd_virtual_channel_event_data_received failed with error %lu", error);
+ if ((error = rdpsnd_virtual_channel_event_data_received(rdpsnd, pData,
+ dataLength, totalLength, dataFlags)))
+ WLog_ERR(TAG,
+ "rdpsnd_virtual_channel_event_data_received failed with error %lu", error);
+
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
case CHANNEL_EVENT_USER:
break;
}
- if (error && rdpsnd->rdpcontext)
- setChannelError(rdpsnd->rdpcontext, error, "rdpsnd_virtual_channel_open_event reported an error");
+ if (error && rdpsnd->rdpcontext)
+ setChannelError(rdpsnd->rdpcontext, error,
+ "rdpsnd_virtual_channel_open_event reported an error");
}
static void* rdpsnd_virtual_channel_client_thread(void* arg)
if (message.id == 0)
{
data = (wStream*) message.wParam;
+
if ((error = rdpsnd_recv_pdu(rdpsnd, data)))
{
WLog_ERR(TAG, "error treating sound channel message");
}
out:
+
if (error && rdpsnd->rdpcontext)
- setChannelError(rdpsnd->rdpcontext, error, "rdpsnd_virtual_channel_client_thread reported an error");
+ setChannelError(rdpsnd->rdpcontext, error,
+ "rdpsnd_virtual_channel_client_thread reported an error");
rdpsnd_process_disconnect(rdpsnd);
-
ExitThread((DWORD)error);
return NULL;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, LPVOID pData, UINT32 dataLength)
+static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin,
+ LPVOID pData, UINT32 dataLength)
{
UINT32 status;
-
status = plugin->channelEntryPoints.pVirtualChannelOpen(plugin->InitHandle,
- &plugin->OpenHandle, plugin->channelDef.name, rdpsnd_virtual_channel_open_event);
+ &plugin->OpenHandle, plugin->channelDef.name,
+ rdpsnd_virtual_channel_open_event);
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
- WTSErrorToString(status), status);
+ WTSErrorToString(status), status);
return status;
}
- if (!rdpsnd_add_open_handle_data(plugin->OpenHandle, plugin))
- {
- WLog_ERR(TAG, "unable to register opened handle");
- return ERROR_INTERNAL_ERROR;
- }
-
plugin->MsgPipe = MessagePipe_New();
+
if (!plugin->MsgPipe)
{
WLog_ERR(TAG, "unable to create message pipe");
}
plugin->thread = CreateThread(NULL, 0,
- (LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) plugin, 0, NULL);
+ (LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) plugin,
+ 0, NULL);
+
if (!plugin->thread)
{
WLog_ERR(TAG, "unable to create thread");
static UINT rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd)
{
UINT error;
-
MessagePipe_PostQuit(rdpsnd->MsgPipe, 0);
+
if (WaitForSingleObject(rdpsnd->thread, INFINITE) == WAIT_FAILED)
- {
- error = GetLastError();
- WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
- return error;
- }
+ {
+ error = GetLastError();
+ WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
+ return error;
+ }
CloseHandle(rdpsnd->thread);
rdpsnd->thread = NULL;
-
error = rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle);
+
if (CHANNEL_RC_OK != error)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
- WTSErrorToString(error), error);
+ WTSErrorToString(error), error);
return error;
}
+ rdpsnd->OpenHandle = 0;
+
if (rdpsnd->data_in)
{
Stream_Free(rdpsnd->data_in, TRUE);
MessagePipe_Free(rdpsnd->MsgPipe);
rdpsnd->MsgPipe = NULL;
-
rdpsnd_free_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats);
rdpsnd->NumberOfClientFormats = 0;
rdpsnd->ClientFormats = NULL;
-
rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats);
rdpsnd->NumberOfServerFormats = 0;
rdpsnd->ServerFormats = NULL;
rdpsnd->device_name = NULL;
}
- rdpsnd_remove_open_handle_data(rdpsnd->OpenHandle);
-
return CHANNEL_RC_OK;
}
static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
{
- rdpsnd_remove_init_handle_data(rdpsnd->InitHandle);
-
+ rdpsnd->InitHandle = 0;
free(rdpsnd);
}
-static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
+static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle,
+ UINT event, LPVOID pData, UINT dataLength)
{
- rdpsndPlugin* plugin;
+ rdpsndPlugin* plugin = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- plugin = (rdpsndPlugin*) rdpsnd_get_init_handle_data(pInitHandle);
-
- if (!plugin)
+ if (!plugin || (plugin->InitHandle != pInitHandle))
{
WLog_ERR(TAG, "rdpsnd_virtual_channel_init_event: error no match");
return;
{
case CHANNEL_EVENT_CONNECTED:
if ((error = rdpsnd_virtual_channel_event_connected(plugin, pData, dataLength)))
- WLog_ERR(TAG, "rdpsnd_virtual_channel_event_connected failed with error %lu!", error);
+ WLog_ERR(TAG, "rdpsnd_virtual_channel_event_connected failed with error %lu!",
+ error);
+
break;
case CHANNEL_EVENT_DISCONNECTED:
if ((error = rdpsnd_virtual_channel_event_disconnected(plugin)))
- WLog_ERR(TAG, "rdpsnd_virtual_channel_event_disconnected failed with error %lu!", error);
+ WLog_ERR(TAG,
+ "rdpsnd_virtual_channel_event_disconnected failed with error %lu!", error);
+
break;
case CHANNEL_EVENT_TERMINATED:
rdpsnd_virtual_channel_event_terminated(plugin);
break;
}
+
if (error && plugin->rdpcontext)
- setChannelError(plugin->rdpcontext, error, "rdpsnd_virtual_channel_init_event reported an error");
+ setChannelError(plugin->rdpcontext, error,
+ "rdpsnd_virtual_channel_init_event reported an error");
}
/* rdpsnd is always built-in */
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
-
rdpsndPlugin* rdpsnd;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
-
-
rdpsnd = (rdpsndPlugin*) calloc(1, sizeof(rdpsndPlugin));
+
if (!rdpsnd)
{
WLog_ERR(TAG, "calloc failed!");
pthread_sigmask(SIG_BLOCK, &mask, NULL);
}
#endif
-
rdpsnd->channelDef.options =
- CHANNEL_OPTION_INITIALIZED |
- CHANNEL_OPTION_ENCRYPT_RDP;
-
+ CHANNEL_OPTION_INITIALIZED |
+ CHANNEL_OPTION_ENCRYPT_RDP;
strcpy(rdpsnd->channelDef.name, "rdpsnd");
-
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
- (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
+ (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
rdpsnd->rdpcontext = pEntryPointsEx->context;
}
- CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
-
+ CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints,
+ sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");
-
rc = rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
- &rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpsnd_virtual_channel_init_event);
+ &rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
+ rdpsnd_virtual_channel_init_event);
+
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
- WTSErrorToString(rc), rc);
+ WTSErrorToString(rc), rc);
free(rdpsnd);
return FALSE;
}
- return rdpsnd_add_init_handle_data(rdpsnd->InitHandle, (void*) rdpsnd);
+ s_TLSPluginContext = rdpsnd;
+ return TRUE;
}
#include "remdesk_main.h"
-RemdeskClientContext* remdesk_get_client_interface(remdeskPlugin* remdesk)
+static WINPR_TLS remdeskPlugin* s_TLSPluginContext = NULL;
+
+static RemdeskClientContext* remdesk_get_client_interface(
+ remdeskPlugin* remdesk)
{
RemdeskClientContext* pInterface;
pInterface = (RemdeskClientContext*) remdesk->channelEntryPoints.pInterface;
}
status = remdesk->channelEntryPoints.pVirtualChannelWrite(remdesk->OpenHandle,
- Stream_Buffer(s), (UINT32) Stream_Length(s), s);
+ Stream_Buffer(s), (UINT32) Stream_Length(s), s);
if (status != CHANNEL_RC_OK)
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
- WTSErrorToString(status), status);
+ WTSErrorToString(status), status);
return status;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk)
+static UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk)
{
char* name;
char* pass;
name = "Expert";
remdesk->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(password,
- settings->RemoteAssistancePassStub, &(remdesk->EncryptedPassStubSize));
+ settings->RemoteAssistancePassStub, &(remdesk->EncryptedPassStubSize));
if (!remdesk->EncryptedPassStub)
{
return ERROR_INTERNAL_ERROR;
}
- pass = freerdp_assistance_bin_to_hex_string(remdesk->EncryptedPassStub, remdesk->EncryptedPassStubSize);
+ pass = freerdp_assistance_bin_to_hex_string(remdesk->EncryptedPassStub,
+ remdesk->EncryptedPassStubSize);
if (!pass)
{
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header)
+static UINT remdesk_read_channel_header(wStream* s,
+ REMDESK_CHANNEL_HEADER* header)
{
int status;
UINT32 ChannelNameLen;
}
ZeroMemory(header->ChannelName, sizeof(header->ChannelName));
-
pChannelName = (char*) header->ChannelName;
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
- ChannelNameLen / 2, &pChannelName, 32, NULL, NULL);
-
+ ChannelNameLen / 2, &pChannelName, 32, NULL, NULL);
Stream_Seek(s, ChannelNameLen);
if (status <= 0)
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header)
+static UINT remdesk_write_channel_header(wStream* s,
+ REMDESK_CHANNEL_HEADER* header)
{
int index;
UINT32 ChannelNameLen;
WCHAR ChannelNameW[32];
-
ZeroMemory(ChannelNameW, sizeof(ChannelNameW));
for (index = 0; index < 32; index++)
}
ChannelNameLen = (strlen(header->ChannelName) + 1) * 2;
-
Stream_Write_UINT32(s, ChannelNameLen); /* ChannelNameLen (4 bytes) */
Stream_Write_UINT32(s, header->DataLength); /* DataLen (4 bytes) */
-
Stream_Write(s, ChannelNameW, ChannelNameLen); /* ChannelName (variable) */
-
return CHANNEL_RC_OK;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msgType, UINT32 msgSize)
+static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader,
+ UINT32 msgType, UINT32 msgSize)
{
ctlHeader->msgType = msgType;
strcpy(ctlHeader->ChannelName, REMDESK_CHANNEL_CTL_NAME);
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
+static UINT remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk,
+ wStream* s, REMDESK_CHANNEL_HEADER* header)
{
return CHANNEL_RC_OK;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
+static UINT remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk,
+ wStream* s, REMDESK_CHANNEL_HEADER* header)
{
UINT32 versionMajor;
UINT32 versionMinor;
Stream_Read_UINT32(s, versionMajor); /* versionMajor (4 bytes) */
Stream_Read_UINT32(s, versionMinor); /* versionMinor (4 bytes) */
-
remdesk->Version = versionMajor;
-
return CHANNEL_RC_OK;
}
wStream* s;
REMDESK_CTL_VERSION_INFO_PDU pdu;
UINT error;
-
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERSIONINFO, 8);
-
pdu.versionMajor = 1;
pdu.versionMinor = 2;
-
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
+
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
}
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
-
Stream_Write_UINT32(s, pdu.versionMajor); /* versionMajor (4 bytes) */
Stream_Write_UINT32(s, pdu.versionMinor); /* versionMinor (4 bytes) */
-
Stream_SealLength(s);
if ((error = remdesk_virtual_channel_write(remdesk, s)))
if (error != CHANNEL_RC_OK)
Stream_Free(s, TRUE);
+
return error;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT remdesk_recv_ctl_result_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header, UINT32 *pResult)
+static UINT remdesk_recv_ctl_result_pdu(remdeskPlugin* remdesk, wStream* s,
+ REMDESK_CHANNEL_HEADER* header, UINT32* pResult)
{
UINT32 result;
}
Stream_Read_UINT32(s, result); /* result (4 bytes) */
-
*pResult = result;
//WLog_DBG(TAG, "RemdeskRecvResult: 0x%04X", result);
return CHANNEL_RC_OK;
pdu.expertBlob = remdesk->ExpertBlob;
pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;
-
- status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1, &raConnectionStringW, 0);
+ status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1,
+ &raConnectionStringW, 0);
if (status <= 0)
{
}
cbRaConnectionStringW = status * 2;
-
status = ConvertToUnicode(CP_UTF8, 0, pdu.expertBlob, -1, &expertBlobW, 0);
if (status <= 0)
}
cbExpertBlobW = status * 2;
-
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_AUTHENTICATE,
- cbRaConnectionStringW + cbExpertBlobW);
-
+ cbRaConnectionStringW + cbExpertBlobW);
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
+
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
}
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
-
Stream_Write(s, (BYTE*) raConnectionStringW, cbRaConnectionStringW);
Stream_Write(s, (BYTE*) expertBlobW, cbExpertBlobW);
-
Stream_SealLength(s);
if ((error = remdesk_virtual_channel_write(remdesk, s)))
out:
free(raConnectionStringW);
free(expertBlobW);
+
if (error != CHANNEL_RC_OK)
Stream_Free(s, TRUE);
int cbRaConnectionStringW = 0;
WCHAR* raConnectionStringW = NULL;
REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU pdu;
-
pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;
-
- status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1, &raConnectionStringW, 0);
+ status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1,
+ &raConnectionStringW, 0);
if (status <= 0)
{
}
cbRaConnectionStringW = status * 2;
-
- remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_REMOTE_CONTROL_DESKTOP, cbRaConnectionStringW);
-
+ remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_REMOTE_CONTROL_DESKTOP,
+ cbRaConnectionStringW);
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
+
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
}
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
-
Stream_Write(s, (BYTE*) raConnectionStringW, cbRaConnectionStringW);
-
Stream_SealLength(s);
if ((error = remdesk_virtual_channel_write(remdesk, s)))
out:
free(raConnectionStringW);
+
if (error != CHANNEL_RC_OK)
Stream_Free(s, TRUE);
}
pdu.expertBlob = remdesk->ExpertBlob;
-
status = ConvertToUnicode(CP_UTF8, 0, pdu.expertBlob, -1, &expertBlobW, 0);
if (status <= 0)
}
cbExpertBlobW = status * 2;
-
- remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERIFY_PASSWORD, cbExpertBlobW);
-
+ remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERIFY_PASSWORD,
+ cbExpertBlobW);
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
+
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
}
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
-
Stream_Write(s, (BYTE*) expertBlobW, cbExpertBlobW);
-
Stream_SealLength(s);
if ((error = remdesk_virtual_channel_write(remdesk, s)))
out:
free(expertBlobW);
+
if (error != CHANNEL_RC_OK)
Stream_Free(s, TRUE);
pdu.EncryptedPasswordLength = remdesk->EncryptedPassStubSize;
pdu.EncryptedPassword = remdesk->EncryptedPassStub;
-
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_EXPERT_ON_VISTA,
- pdu.EncryptedPasswordLength);
-
+ pdu.EncryptedPasswordLength);
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
+
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
}
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
-
Stream_Write(s, pdu.EncryptedPassword, pdu.EncryptedPasswordLength);
-
Stream_SealLength(s);
-
return remdesk_virtual_channel_write(remdesk, s);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
+static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s,
+ REMDESK_CHANNEL_HEADER* header)
{
UINT error = CHANNEL_RC_OK;
UINT32 msgType = 0;
case REMDESK_CTL_RESULT:
if ((error = remdesk_recv_ctl_result_pdu(remdesk, s, header, &result)))
WLog_ERR(TAG, "remdesk_recv_ctl_result_pdu failed with error %lu", error);
+
break;
case REMDESK_CTL_AUTHENTICATE:
case REMDESK_CTL_SERVER_ANNOUNCE:
if ((error = remdesk_recv_ctl_server_announce_pdu(remdesk, s, header)))
- WLog_ERR(TAG, "remdesk_recv_ctl_server_announce_pdu failed with error %lu", error);
+ WLog_ERR(TAG, "remdesk_recv_ctl_server_announce_pdu failed with error %lu",
+ error);
+
break;
case REMDESK_CTL_DISCONNECT:
if ((error = remdesk_send_ctl_remote_control_desktop_pdu(remdesk)))
{
- WLog_ERR(TAG, "remdesk_send_ctl_remote_control_desktop_pdu failed with error %lu", error);
+ WLog_ERR(TAG,
+ "remdesk_send_ctl_remote_control_desktop_pdu failed with error %lu", error);
break;
}
}
{
if ((error = remdesk_send_ctl_expert_on_vista_pdu(remdesk)))
{
- WLog_ERR(TAG, "remdesk_send_ctl_expert_on_vista_pdu failed with error %lu", error);
+ WLog_ERR(TAG, "remdesk_send_ctl_expert_on_vista_pdu failed with error %lu",
+ error);
break;
}
if ((error = remdesk_send_ctl_verify_password_pdu(remdesk)))
{
- WLog_ERR(TAG, "remdesk_send_ctl_verify_password_pdu failed with error %lu", error);
+ WLog_ERR(TAG, "remdesk_send_ctl_verify_password_pdu failed with error %lu",
+ error);
break;
}
}
{
UINT status;
REMDESK_CHANNEL_HEADER header;
-
#if 0
WLog_DBG(TAG, "RemdeskReceive: %d", Stream_GetRemainingLength(s));
winpr_HexDump(Stream_Pointer(s), Stream_GetRemainingLength(s));
}
else if (strcmp(header.ChannelName, "70") == 0)
{
-
}
else if (strcmp(header.ChannelName, "71") == 0)
{
-
}
else if (strcmp(header.ChannelName, ".") == 0)
{
-
}
else if (strcmp(header.ChannelName, "1000.") == 0)
{
-
}
else if (strcmp(header.ChannelName, "RA_FX") == 0)
{
-
}
else
{
-
}
return status;
remdesk->settings = (rdpSettings*) remdesk->channelEntryPoints.pExtendedData;
}
-/****************************************************************************************/
-
-static wListDictionary* g_InitHandles = NULL;
-static wListDictionary* g_OpenHandles = NULL;
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-UINT remdesk_add_init_handle_data(void* pInitHandle, void* pUserData)
-{
- if (!g_InitHandles)
- {
- g_InitHandles = ListDictionary_New(TRUE);
- if (!g_InitHandles)
- return CHANNEL_RC_NO_MEMORY;
- }
-
- return ListDictionary_Add(g_InitHandles, pInitHandle, pUserData) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
-}
-
-void* remdesk_get_init_handle_data(void* pInitHandle)
-{
- void* pUserData = NULL;
- pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
- return pUserData;
-}
-
-void remdesk_remove_init_handle_data(void* pInitHandle)
-{
- ListDictionary_Remove(g_InitHandles, pInitHandle);
- if (ListDictionary_Count(g_InitHandles) < 1)
- {
- ListDictionary_Free(g_InitHandles);
- g_InitHandles = NULL;
- }
-}
-
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT remdesk_add_open_handle_data(DWORD openHandle, void* pUserData)
-{
- void* pOpenHandle = (void*) (size_t) openHandle;
-
- if (!g_OpenHandles)
- {
- g_OpenHandles = ListDictionary_New(TRUE);
- if (!g_OpenHandles)
- return CHANNEL_RC_NO_MEMORY;
- }
-
- return ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
-}
-
-void* remdesk_get_open_handle_data(DWORD openHandle)
-{
- void* pUserData = NULL;
- void* pOpenHandle = (void*) (size_t) openHandle;
- pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
- return pUserData;
-}
-
-void remdesk_remove_open_handle_data(DWORD openHandle)
-{
- void* pOpenHandle = (void*) (size_t) openHandle;
- ListDictionary_Remove(g_OpenHandles, pOpenHandle);
- if (ListDictionary_Count(g_OpenHandles) < 1)
- {
- ListDictionary_Free(g_OpenHandles);
- g_OpenHandles = NULL;
- }
-}
-
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-UINT remdesk_send(remdeskPlugin* remdesk, wStream* s)
+static UINT remdesk_send(remdeskPlugin* remdesk, wStream* s)
{
UINT status = 0;
remdeskPlugin* plugin = (remdeskPlugin*) remdesk;
else
{
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
- Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
+ Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
}
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
- WTSErrorToString(status), status);
+ WTSErrorToString(status), status);
}
return status;
* @return 0 on success, otherwise a Win32 error code
*/
static UINT remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk,
- void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
+ void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
wStream* data_in;
Stream_Free(remdesk->data_in, TRUE);
remdesk->data_in = Stream_New(NULL, totalLength);
+
if (!remdesk->data_in)
{
WLog_ERR(TAG, "Stream_New failed!");
}
data_in = remdesk->data_in;
+
if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
+
Stream_Write(data_in, pData, dataLength);
if (dataFlags & CHANNEL_FLAG_LAST)
return ERROR_INTERNAL_ERROR;
}
}
+
return CHANNEL_RC_OK;
}
-static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT event,
- LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
+static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle,
+ UINT event,
+ LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
- remdeskPlugin* remdesk;
+ remdeskPlugin* remdesk = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- remdesk = (remdeskPlugin*) remdesk_get_open_handle_data(openHandle);
-
- if (!remdesk)
+ if (!remdesk || (remdesk->OpenHandle != openHandle))
{
WLog_ERR(TAG, "error no match");
return;
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
- if ((error = remdesk_virtual_channel_event_data_received(remdesk, pData, dataLength, totalLength, dataFlags)))
- WLog_ERR(TAG, "remdesk_virtual_channel_event_data_received failed with error %lu!", error);
+ if ((error = remdesk_virtual_channel_event_data_received(remdesk, pData,
+ dataLength, totalLength, dataFlags)))
+ WLog_ERR(TAG,
+ "remdesk_virtual_channel_event_data_received failed with error %lu!", error);
+
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
default:
WLog_ERR(TAG, "unhandled event %lu!", event);
error = ERROR_INTERNAL_ERROR;
-
}
- if (error && remdesk->rdpcontext)
- setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_open_event reported an error");
+ if (error && remdesk->rdpcontext)
+ setChannelError(remdesk->rdpcontext, error,
+ "remdesk_virtual_channel_open_event reported an error");
}
static void* remdesk_virtual_channel_client_thread(void* arg)
wMessage message;
remdeskPlugin* remdesk = (remdeskPlugin*) arg;
UINT error = CHANNEL_RC_OK;
-
remdesk_process_connect(remdesk);
while (1)
break;
}
- if (!MessageQueue_Peek(remdesk->queue, &message, TRUE)) {
+ if (!MessageQueue_Peek(remdesk->queue, &message, TRUE))
+ {
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
+
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
{
data = (wStream*) message.wParam;
+
if ((error = remdesk_process_receive(remdesk, data)))
{
WLog_ERR(TAG, "remdesk_process_receive failed with error %lu!", error);
}
if (error && remdesk->rdpcontext)
- setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_client_thread reported an error");
+ setChannelError(remdesk->rdpcontext, error,
+ "remdesk_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk, LPVOID pData, UINT32 dataLength)
+static UINT remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk,
+ LPVOID pData, UINT32 dataLength)
{
UINT32 status;
UINT error;
-
status = remdesk->channelEntryPoints.pVirtualChannelOpen(remdesk->InitHandle,
- &remdesk->OpenHandle, remdesk->channelDef.name, remdesk_virtual_channel_open_event);
+ &remdesk->OpenHandle, remdesk->channelDef.name,
+ remdesk_virtual_channel_open_event);
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
- WTSErrorToString(status), status);
+ WTSErrorToString(status), status);
return status;
}
- if ((error = remdesk_add_open_handle_data(remdesk->OpenHandle, remdesk)))
- {
- WLog_ERR(TAG, "remdesk_add_open_handle_data failed with error %lu", error);
- return error;
- }
-
remdesk->queue = MessageQueue_New(NULL);
+
if (!remdesk->queue)
{
WLog_ERR(TAG, "MessageQueue_New failed!");
}
remdesk->thread = CreateThread(NULL, 0,
- (LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk, 0, NULL);
+ (LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk,
+ 0, NULL);
+
if (!remdesk->thread)
{
WLog_ERR(TAG, "CreateThread failed");
error = ERROR_INTERNAL_ERROR;
goto error_out;
}
+
return CHANNEL_RC_OK;
error_out:
- remdesk_remove_open_handle_data(remdesk->OpenHandle);
MessageQueue_Free(remdesk->queue);
remdesk->queue = NULL;
return error;
{
UINT rc;
- if (MessageQueue_PostQuit(remdesk->queue, 0) && (WaitForSingleObject(remdesk->thread, INFINITE) == WAIT_FAILED))
+ if (MessageQueue_PostQuit(remdesk->queue, 0)
+ && (WaitForSingleObject(remdesk->thread, INFINITE) == WAIT_FAILED))
{
rc = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
MessageQueue_Free(remdesk->queue);
CloseHandle(remdesk->thread);
-
remdesk->queue = NULL;
remdesk->thread = NULL;
-
rc = remdesk->channelEntryPoints.pVirtualChannelClose(remdesk->OpenHandle);
+
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
- WTSErrorToString(rc), rc);
+ WTSErrorToString(rc), rc);
}
+ remdesk->OpenHandle = 0;
+
if (remdesk->data_in)
{
Stream_Free(remdesk->data_in, TRUE);
remdesk->data_in = NULL;
}
- remdesk_remove_open_handle_data(remdesk->OpenHandle);
return rc;
}
static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk)
{
- remdesk_remove_init_handle_data(remdesk->InitHandle);
-
+ remdesk->InitHandle = 0;
free(remdesk);
}
static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle,
- UINT event, LPVOID pData,
- UINT dataLength)
+ UINT event, LPVOID pData,
+ UINT dataLength)
{
- remdeskPlugin* remdesk;
+ remdeskPlugin* remdesk = s_TLSPluginContext;
UINT error = CHANNEL_RC_OK;
- remdesk = (remdeskPlugin*) remdesk_get_init_handle_data(pInitHandle);
-
- if (!remdesk)
+ if (!remdesk || (remdesk->InitHandle != pInitHandle))
{
WLog_ERR(TAG, "error no match");
return;
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
- if ((error = remdesk_virtual_channel_event_connected(remdesk, pData, dataLength)))
- WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %lu", error);
+ if ((error = remdesk_virtual_channel_event_connected(remdesk, pData,
+ dataLength)))
+ WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %lu",
+ error);
+
break;
case CHANNEL_EVENT_DISCONNECTED:
if ((error = remdesk_virtual_channel_event_disconnected(remdesk)))
- WLog_ERR(TAG, "remdesk_virtual_channel_event_disconnected failed with error %lu", error);
+ WLog_ERR(TAG,
+ "remdesk_virtual_channel_event_disconnected failed with error %lu", error);
+
break;
case CHANNEL_EVENT_TERMINATED:
remdesk_virtual_channel_event_terminated(remdesk);
break;
}
+
if (error && remdesk->rdpcontext)
- setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_init_event reported an error");
+ setChannelError(remdesk->rdpcontext, error,
+ "remdesk_virtual_channel_init_event reported an error");
}
/* remdesk is always built-in */
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
- UINT error;
-
remdeskPlugin* remdesk;
RemdeskClientContext* context = NULL;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
-
remdesk = (remdeskPlugin*) calloc(1, sizeof(remdeskPlugin));
if (!remdesk)
}
remdesk->channelDef.options =
- CHANNEL_OPTION_INITIALIZED |
- CHANNEL_OPTION_ENCRYPT_RDP |
- CHANNEL_OPTION_COMPRESS_RDP |
- CHANNEL_OPTION_SHOW_PROTOCOL;
-
+ CHANNEL_OPTION_INITIALIZED |
+ CHANNEL_OPTION_ENCRYPT_RDP |
+ CHANNEL_OPTION_COMPRESS_RDP |
+ CHANNEL_OPTION_SHOW_PROTOCOL;
strcpy(remdesk->channelDef.name, "remdesk");
-
remdesk->Version = 2;
-
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
- (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
+ (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
context = (RemdeskClientContext*) calloc(1, sizeof(RemdeskClientContext));
+
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
}
context->handle = (void*) remdesk;
-
*(pEntryPointsEx->ppInterface) = (void*) context;
remdesk->context = context;
remdesk->rdpcontext = pEntryPointsEx->context;
}
- CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
-
+ CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints,
+ sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
rc = remdesk->channelEntryPoints.pVirtualChannelInit(&remdesk->InitHandle,
- &remdesk->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, remdesk_virtual_channel_init_event);
+ &remdesk->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
+ remdesk_virtual_channel_init_event);
+
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
- WTSErrorToString(rc), rc);
+ WTSErrorToString(rc), rc);
goto error_out;
}
- remdesk->channelEntryPoints.pInterface = *(remdesk->channelEntryPoints.ppInterface);
- remdesk->channelEntryPoints.ppInterface = &(remdesk->channelEntryPoints.pInterface);
-
- if ((error = remdesk_add_init_handle_data(remdesk->InitHandle, (void*) remdesk)))
- {
- WLog_ERR(TAG, "remdesk_add_init_handle_data failed with error %lu!", error);
- goto error_out;
- }
+ remdesk->channelEntryPoints.pInterface = *
+ (remdesk->channelEntryPoints.ppInterface);
+ remdesk->channelEntryPoints.ppInterface = &
+ (remdesk->channelEntryPoints.pInterface);
+ s_TLSPluginContext = remdesk;
return TRUE;
error_out:
free(remdesk);
if (!instance || !context)
return FALSE;
- if (!(context->channels = freerdp_channels_new()))
+ if (!(context->channels = freerdp_channels_new(instance)))
return FALSE;
if (!android_event_queue_init(instance))
BOOL df_context_new(freerdp* instance, rdpContext* context)
{
- if (!(context->channels = freerdp_channels_new()))
+ if (!(context->channels = freerdp_channels_new(instance)))
return FALSE;
return TRUE;
{
rdpGdi* gdi;
dfInfo* dfi;
-
gdi = context->gdi;
dfi = ((dfContext*) context)->dfi;
dfi->update_rect.w = gdi->width;
dfi->update_rect.h = gdi->height;
#endif
-
- dfi->primary->Blit(dfi->primary, dfi->surface, &(dfi->update_rect), dfi->update_rect.x, dfi->update_rect.y);
+ dfi->primary->Blit(dfi->primary, dfi->surface, &(dfi->update_rect),
+ dfi->update_rect.x, dfi->update_rect.y);
}
-BOOL df_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
+BOOL df_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds,
+ int* wcount)
{
dfInfo* dfi;
-
dfi = ((dfContext*) instance->context)->dfi;
-
rfds[*rcount] = (void*)(long)(dfi->read_fds);
(*rcount)++;
-
return TRUE;
}
BOOL df_check_fds(freerdp* instance, fd_set* set)
{
dfInfo* dfi;
-
dfi = ((dfContext*) instance->context)->dfi;
if (!FD_ISSET(dfi->read_fds, set))
BOOL bitmap_cache;
dfContext* context;
rdpSettings* settings;
-
dfi = (dfInfo*) malloc(sizeof(dfInfo));
ZeroMemory(dfi, sizeof(dfInfo));
-
context = ((dfContext*) instance->context);
context->dfi = dfi;
-
settings = instance->settings;
bitmap_cache = settings->BitmapCacheEnabled;
-
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
-
dfi->clrconv = (CLRCONV*) malloc(sizeof(CLRCONV));
ZeroMemory(dfi->clrconv, sizeof(CLRCONV));
-
dfi->clrconv->alpha = 1;
dfi->clrconv->invert = 0;
dfi->clrconv->rgb555 = 0;
-
dfi->clrconv->palette = (rdpPalette*) malloc(sizeof(rdpPalette));
ZeroMemory(dfi->clrconv->palette, sizeof(rdpPalette));
- if (freerdp_channels_pre_connect(instance->context->channels, instance) != CHANNEL_RC_OK)
+ if (freerdp_channels_pre_connect(instance->context->channels,
+ instance) != CHANNEL_RC_OK)
return FALSE;
return (instance->context->cache = cache_new(instance->settings)) != NULL;
rdpGdi* gdi;
dfInfo* dfi;
dfContext* context;
-
context = ((dfContext*) instance->context);
dfi = context->dfi;
- if (!gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_16BPP | CLRBUF_32BPP, NULL))
+ if (!gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_16BPP |
+ CLRBUF_32BPP, NULL))
return FALSE;
gdi = instance->context->gdi;
-
dfi->err = DirectFBCreate(&(dfi->dfb));
-
dfi->dsc.flags = DSDESC_CAPS;
dfi->dsc.caps = DSCAPS_PRIMARY;
dfi->err = dfi->dfb->CreateSurface(dfi->dfb, &(dfi->dsc), &(dfi->primary));
dfi->err = dfi->primary->GetSize(dfi->primary, &(gdi->width), &(gdi->height));
dfi->dfb->SetVideoMode(dfi->dfb, gdi->width, gdi->height, gdi->dstBpp);
- dfi->dfb->CreateInputEventBuffer(dfi->dfb, DICAPS_ALL, DFB_TRUE, &(dfi->event_buffer));
+ dfi->dfb->CreateInputEventBuffer(dfi->dfb, DICAPS_ALL, DFB_TRUE,
+ &(dfi->event_buffer));
dfi->event_buffer->CreateFileDescriptor(dfi->event_buffer, &(dfi->read_fds));
-
dfi->dfb->GetDisplayLayer(dfi->dfb, 0, &(dfi->layer));
dfi->layer->EnableCursor(dfi->layer, 1);
-
- dfi->dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PREALLOCATED | DSDESC_PIXELFORMAT;
+ dfi->dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT |
+ DSDESC_PREALLOCATED | DSDESC_PIXELFORMAT;
dfi->dsc.caps = DSCAPS_SYSTEMONLY;
dfi->dsc.width = gdi->width;
dfi->dsc.height = gdi->height;
dfi->dsc.preallocated[0].data = gdi->primary_buffer;
dfi->dsc.preallocated[0].pitch = gdi->width * gdi->bytesPerPixel;
dfi->dfb->CreateSurface(dfi->dfb, &(dfi->dsc), &(dfi->surface));
-
instance->update->BeginPaint = df_begin_paint;
instance->update->EndPaint = df_end_paint;
-
df_keyboard_init();
-
pointer_cache_register_callbacks(instance->update);
df_register_graphics(instance->context->graphics);
-
- return freerdp_channels_post_connect(instance->context->channels, instance) == CHANNEL_RC_OK;
+ return freerdp_channels_post_connect(instance->context->channels,
+ instance) == CHANNEL_RC_OK;
}
-BOOL df_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint)
+BOOL df_verify_certificate(freerdp* instance, char* subject, char* issuer,
+ char* fingerprint)
{
char answer;
WLog_INFO(TAG, "Certificate details:");
WLog_INFO(TAG, "\tSubject: %s", subject);
WLog_INFO(TAG, "\tIssuer: %s", issuer);
WLog_INFO(TAG, "\tThumbprint: %s", fingerprint);
- WLog_INFO(TAG, "The above X.509 certificate could not be verified, possibly because you do not have "
- "the CA certificate in your certificate store, or the certificate has expired. "
- "Please look at the documentation on how to create local certificate store for a private CA.");
+ WLog_INFO(TAG,
+ "The above X.509 certificate could not be verified, possibly because you do not have "
+ "the CA certificate in your certificate store, or the certificate has expired. "
+ "Please look at the documentation on how to create local certificate store for a private CA.");
while (1)
{
return FALSE;
}
-static int df_receive_channel_data(freerdp* instance, UINT16 channelId, BYTE* data, int size, int flags, int total_size)
+static int df_receive_channel_data(freerdp* instance, UINT16 channelId,
+ BYTE* data, int size, int flags, int total_size)
{
- return freerdp_channels_data(instance, channelId, data, size, flags, total_size);
+ return freerdp_channels_data(instance, channelId, data, size, flags,
+ total_size);
}
-static void df_process_cb_monitor_ready_event(rdpChannels* channels, freerdp* instance)
+static void df_process_cb_monitor_ready_event(rdpChannels* channels,
+ freerdp* instance)
{
wMessage* event;
RDP_CB_FORMAT_LIST_EVENT* format_list_event;
-
- event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL);
-
+ event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL,
+ NULL);
format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event;
format_list_event->num_formats = 0;
-
freerdp_channels_send_event(channels, event);
}
static void df_process_channel_event(rdpChannels* channels, freerdp* instance)
{
wMessage* event;
-
event = freerdp_channels_pop_event(channels);
if (event)
break;
default:
- WLog_ERR(TAG, "df_process_channel_event: unknown event type %d", GetMessageType(event->id));
+ WLog_ERR(TAG, "df_process_channel_event: unknown event type %d",
+ GetMessageType(event->id));
break;
}
dfInfo* dfi;
dfContext* context;
rdpChannels* channels;
-
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
return 0;
context = (dfContext*) instance->context;
-
dfi = context->dfi;
channels = instance->context->channels;
WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
break;
}
- if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
+
+ if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds,
+ &wcount) != TRUE)
{
WLog_ERR(TAG, "Failed to get channel manager file descriptor");
break;
}
+
if (df_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
WLog_ERR(TAG, "Failed to get dfreerdp file descriptor");
{
/* these are not really errors */
if (!((errno == EAGAIN) ||
- (errno == EWOULDBLOCK) ||
- (errno == EINPROGRESS) ||
- (errno == EINTR))) /* signal occurred */
+ (errno == EWOULDBLOCK) ||
+ (errno == EINPROGRESS) ||
+ (errno == EINTR))) /* signal occurred */
{
WLog_ERR(TAG, "dfreerdp_run: select failed");
break;
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
break;
}
+
if (df_check_fds(instance, &rfds_set) != TRUE)
{
WLog_ERR(TAG, "Failed to check dfreerdp file descriptor");
break;
}
+
if (freerdp_channels_check_fds(channels, instance) != TRUE)
{
WLog_ERR(TAG, "Failed to check channel manager file descriptor");
break;
}
+
df_process_channel_event(channels, instance);
}
freerdp_channels_disconnect(channels, instance);
freerdp_disconnect(instance);
-
freerdp_channels_close(channels, instance);
freerdp_channels_free(channels);
df_free(dfi);
gdi_free(instance);
freerdp_disconnect(instance);
freerdp_free(instance);
-
return 0;
}
{
struct thread_data* data;
data = (struct thread_data*) param;
-
dfreerdp_run(data->instance);
-
free(data);
-
pthread_detach(pthread_self());
-
g_thread_count--;
- if (g_thread_count < 1)
- ReleaseSemaphore(g_sem, 1, NULL);
+ if (g_thread_count < 1)
+ ReleaseSemaphore(g_sem, 1, NULL);
return NULL;
}
dfContext* context;
rdpChannels* channels;
struct thread_data* data;
-
setlocale(LC_ALL, "");
if (!(g_sem = CreateSemaphore(NULL, 0, 1, NULL)))
instance->PostConnect = df_post_connect;
instance->VerifyCertificate = df_verify_certificate;
instance->ReceiveChannelData = df_receive_channel_data;
-
instance->ContextSize = sizeof(dfContext);
instance->ContextNew = df_context_new;
instance->ContextFree = df_context_free;
context = (dfContext*) instance->context;
channels = instance->context->channels;
-
DirectFBInit(&argc, &argv);
-
instance->context->argc = argc;
instance->context->argv = argv;
-
- status = freerdp_client_settings_parse_command_line(instance->settings, argc, argv, FALSE);
+ status = freerdp_client_settings_parse_command_line(instance->settings, argc,
+ argv, FALSE);
if (status < 0)
exit(0);
- if (!freerdp_client_load_addins(instance->context->channels, instance->settings))
+ if (!freerdp_client_load_addins(instance->context->channels,
+ instance->settings))
exit(-1);
data = (struct thread_data*) malloc(sizeof(struct thread_data));
ZeroMemory(data, sizeof(sizeof(struct thread_data)));
-
data->instance = instance;
-
g_thread_count++;
pthread_create(&thread, 0, thread_func, data);
context->instance->PreConnect = mac_pre_connect;
context->instance->PostConnect = mac_post_connect;
context->instance->Authenticate = mac_authenticate;
- context->channels = freerdp_channels_new();
+ context->channels = freerdp_channels_new(instance);
settings = instance->settings;
settings->AsyncTransport = TRUE;
settings->AsyncUpdate = TRUE;
static BOOL tf_context_new(freerdp* instance, rdpContext* context)
{
- if (!(context->channels = freerdp_channels_new()))
+ if (!(context->channels = freerdp_channels_new(instance)))
return FALSE;
return TRUE;
{
rdpGdi* gdi = context->gdi;
gdi->primary->hdc->hwnd->invalid->null = 1;
- return TRUE;
+ return TRUE;
}
static BOOL tf_end_paint(rdpContext* context)
if (gdi->primary->hdc->hwnd->invalid->null)
return TRUE;
+
return TRUE;
}
static BOOL tf_pre_connect(freerdp* instance)
{
rdpSettings* settings;
-
-
settings = instance->settings;
-
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = TRUE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = TRUE;
- if (freerdp_channels_pre_connect(instance->context->channels, instance) != CHANNEL_RC_OK)
+ if (freerdp_channels_pre_connect(instance->context->channels,
+ instance) != CHANNEL_RC_OK)
return FALSE;
return TRUE;
instance->update->BeginPaint = tf_begin_paint;
instance->update->EndPaint = tf_end_paint;
-
- return (freerdp_channels_post_connect(instance->context->channels, instance) == CHANNEL_RC_OK);
+ return (freerdp_channels_post_connect(instance->context->channels,
+ instance) == CHANNEL_RC_OK);
}
static void* tf_client_thread_proc(freerdp* instance)
if (nCount == 0)
{
- WLog_ERR(TAG, "%s: freerdp_get_event_handles failed", __FUNCTION__);
- break;
+ WLog_ERR(TAG, "%s: freerdp_get_event_handles failed", __FUNCTION__);
+ break;
}
status = WaitForMultipleObjects(nCount, handles, FALSE, 100);
if (status == WAIT_FAILED)
{
- WLog_ERR(TAG, "%s: WaitForMultipleObjects failed with %lu", __FUNCTION__, status);
- break;
+ WLog_ERR(TAG, "%s: WaitForMultipleObjects failed with %lu", __FUNCTION__,
+ status);
+ break;
}
if (!freerdp_check_event_handles(instance->context))
}
freerdp_disconnect(instance);
-
ExitThread(0);
return NULL;
}
int status;
HANDLE thread;
freerdp* instance;
-
instance = freerdp_new();
+
if (!instance)
{
WLog_ERR(TAG, "Couldn't create instance");
exit(1);
}
+
instance->PreConnect = tf_pre_connect;
instance->PostConnect = tf_post_connect;
-
instance->ContextSize = sizeof(tfContext);
instance->ContextNew = tf_context_new;
instance->ContextFree = tf_context_free;
exit(1);
}
- status = freerdp_client_settings_parse_command_line(instance->settings, argc, argv, FALSE);
+ status = freerdp_client_settings_parse_command_line(instance->settings, argc,
+ argv, FALSE);
if (status < 0)
{
exit(0);
}
- if (!freerdp_client_load_addins(instance->context->channels, instance->settings))
- exit (-1);
+ if (!freerdp_client_load_addins(instance->context->channels,
+ instance->settings))
+ exit(-1);
if (!(thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
- tf_client_thread_proc, instance, 0, NULL)))
+ tf_client_thread_proc, instance, 0, NULL)))
{
WLog_ERR(TAG, "Failed to create client thread");
}
freerdp_context_free(instance);
freerdp_free(instance);
-
return 0;
}
if (!instance || !context)
return FALSE;
- if (!(context->channels = freerdp_channels_new()))
+ if (!(context->channels = freerdp_channels_new(instance)))
return FALSE;
instance->PreConnect = wl_pre_connect;
{
wf_image_free(wfc->primary);
wfc->primary = wf_image_new(wfc, settings->DesktopWidth,
- settings->DesktopHeight, wfc->context.gdi->dstFormat, NULL);
+ settings->DesktopHeight, wfc->context.gdi->dstFormat, NULL);
}
return TRUE;
same = (wfc->primary == wfc->drawing) ? TRUE : FALSE;
wf_image_free(wfc->primary);
wfc->primary = wf_image_new(wfc, settings->DesktopWidth,
- settings->DesktopHeight, wfc->context.gdi->dstFormat, NULL);
+ settings->DesktopHeight, wfc->context.gdi->dstFormat, NULL);
if (same)
wfc->drawing = wfc->primary;
{
if (wfc->hwnd)
SetWindowPos(wfc->hwnd, HWND_TOP, -1, -1, settings->DesktopWidth + wfc->diff.x,
- settings->DesktopHeight + wfc->diff.y, SWP_NOMOVE);
+ settings->DesktopHeight + wfc->diff.y, SWP_NOMOVE);
}
else
{
}
if ((settings->DesktopWidth < 64) || (settings->DesktopHeight < 64) ||
- (settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096))
+ (settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096))
{
WLog_ERR(TAG, "invalid dimensions %d %d", settings->DesktopWidth,
- settings->DesktopHeight);
+ settings->DesktopHeight);
return FALSE;
}
freerdp_set_param_uint32(settings, FreeRDP_KeyboardLayout,
- (int) GetKeyboardLayout(0) & 0x0000FFFF);
+ (int) GetKeyboardLayout(0) & 0x0000FFFF);
PubSub_SubscribeChannelConnected(instance->context->pubSub,
- (pChannelConnectedEventHandler) wf_OnChannelConnectedEventHandler);
+ (pChannelConnectedEventHandler) wf_OnChannelConnectedEventHandler);
PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
- (pChannelDisconnectedEventHandler) wf_OnChannelDisconnectedEventHandler);
+ (pChannelDisconnectedEventHandler) wf_OnChannelDisconnectedEventHandler);
if (freerdp_channels_pre_connect(instance->context->channels,
- instance) != CHANNEL_RC_OK)
+ instance) != CHANNEL_RC_OK)
return FALSE;
return TRUE;
MENUITEMINFO item_info;
ZeroMemory(&item_info, sizeof(MENUITEMINFO));
item_info.fMask = MIIM_CHECKMARKS | MIIM_FTYPE | MIIM_ID | MIIM_STRING |
- MIIM_DATA;
+ MIIM_DATA;
item_info.cbSize = sizeof(MENUITEMINFO);
item_info.wID = SYSCOMMAND_ID_SMARTSIZING;
item_info.fType = MFT_STRING;
rdpSettings* settings;
EmbedWindowEventArgs e;
const UINT32 format = PIXEL_FORMAT_BGRX32;
-
settings = instance->settings;
context = instance->context;
wfc = (wfContext*) instance->context;
cache = instance->context->cache;
wfc->primary = wf_image_new(wfc, settings->DesktopWidth,
- settings->DesktopHeight, format, NULL);
+ settings->DesktopHeight, format, NULL);
if (!gdi_init_ex(instance, format, 0, wfc->primary->pdata, wf_image_free))
return FALSE;
_snwprintf(lpWindowName, ARRAYSIZE(lpWindowName), L"%S", settings->WindowTitle);
else if (settings->ServerPort == 3389)
_snwprintf(lpWindowName, ARRAYSIZE(lpWindowName), L"FreeRDP: %S",
- settings->ServerHostname);
+ settings->ServerHostname);
else
_snwprintf(lpWindowName, ARRAYSIZE(lpWindowName), L"FreeRDP: %S:%d",
- settings->ServerHostname, settings->ServerPort);
+ settings->ServerHostname, settings->ServerPort);
if (settings->EmbeddedWindow)
settings->Decorations = FALSE;
dwStyle = WS_CHILD | WS_BORDER;
else
dwStyle = WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX
- | WS_MAXIMIZEBOX;
+ | WS_MAXIMIZEBOX;
if (!wfc->hwnd)
{
wfc->hwnd = CreateWindowEx((DWORD) NULL, wfc->wndClassName, lpWindowName,
- dwStyle,
- 0, 0, 0, 0, wfc->hWndParent, NULL, wfc->hInstance, NULL);
+ dwStyle,
+ 0, 0, 0, 0, wfc->hWndParent, NULL, wfc->hInstance, NULL);
SetWindowLongPtr(wfc->hwnd, GWLP_USERDATA, (LONG_PTR) wfc);
}
wf_resize_window(wfc);
wf_add_system_menu(wfc);
BitBlt(wfc->primary->hdc, 0, 0, settings->DesktopWidth, settings->DesktopHeight,
- NULL, 0, 0, BLACKNESS);
+ NULL, 0, 0, BLACKNESS);
wfc->drawing = wfc->primary;
EventArgsInit(&e, "wfreerdp");
e.embed = FALSE;
};
static BOOL wf_authenticate_raw(freerdp* instance, const char* title,
- char** username, char** password, char** domain)
+ char** username, char** password, char** domain)
{
BOOL fSave;
DWORD status;
ZeroMemory(Password, sizeof(Password));
dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES;
status = CredUIPromptForCredentialsA(&wfUiInfo, title, NULL, 0,
- UserName, CREDUI_MAX_USERNAME_LENGTH + 1,
- Password, CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags);
+ UserName, CREDUI_MAX_USERNAME_LENGTH + 1,
+ Password, CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags);
if (status != NO_ERROR)
{
ZeroMemory(User, sizeof(User));
ZeroMemory(Domain, sizeof(Domain));
status = CredUIParseUserNameA(UserName, User, sizeof(User), Domain,
- sizeof(Domain));
+ sizeof(Domain));
//WLog_ERR(TAG, "User: %s Domain: %s Password: %s", User, Domain, Password);
*username = _strdup(User);
}
static BOOL wf_authenticate(freerdp* instance,
- char** username, char** password, char** domain)
+ char** username, char** password, char** domain)
{
return wf_authenticate_raw(instance, instance->settings->ServerHostname,
- username, password, domain);
+ username, password, domain);
}
static BOOL wf_gw_authenticate(freerdp* instance,
- char** username, char** password, char** domain)
+ char** username, char** password, char** domain)
{
char tmp[MAX_PATH];
sprintf_s(tmp, sizeof(tmp), "Gateway %s", instance->settings->GatewayHostname);
}
static DWORD wf_verify_certificate(freerdp* instance,
- const char* common_name,
- const char* subject,
- const char* issuer,
- const char* fingerprint,
- BOOL host_mismatch)
+ const char* common_name,
+ const char* subject,
+ const char* issuer,
+ const char* fingerprint,
+ BOOL host_mismatch)
{
#if 0
DWORD mode;
WLog_INFO(TAG, "\tThumbprint: %s", fingerprint);
WLog_INFO(TAG, "\tHostMismatch: %s", host_mismatch ? "Yes" : "No");
WLog_INFO(TAG,
- "The above X.509 certificate could not be verified, possibly because you do not have "
- "the CA certificate in your certificate store, or the certificate has expired. "
- "Please look at the documentation on how to create local certificate store for a private CA.");
+ "The above X.509 certificate could not be verified, possibly because you do not have "
+ "the CA certificate in your certificate store, or the certificate has expired. "
+ "Please look at the documentation on how to create local certificate store for a private CA.");
/* TODO: ask for user validation */
#if 0
input_handle = GetStdHandle(STD_INPUT_HANDLE);
}
static DWORD wf_verify_changed_certificate(freerdp* instance,
- const char* common_name,
- const char* subject, const char* issuer,
- const char* fingerprint,
- const char* old_subject, const char* old_issuer,
- const char* old_fingerprint)
+ const char* common_name,
+ const char* subject, const char* issuer,
+ const char* fingerprint,
+ const char* old_subject, const char* old_issuer,
+ const char* old_fingerprint)
{
WLog_ERR(TAG, "!!! Certificate has changed !!!");
WLog_ERR(TAG, "New Certificate details:");
WLog_ERR(TAG, "\tIssuer: %s", old_issuer);
WLog_ERR(TAG, "\tThumbprint: %s", old_fingerprint);
WLog_ERR(TAG,
- "The above X.509 certificate does not match the certificate used for previous connections. "
- "This may indicate that the certificate has been tampered with."
- "Please contact the administrator of the RDP server and clarify.");
+ "The above X.509 certificate does not match the certificate used for previous connections. "
+ "This may indicate that the certificate has been tampered with."
+ "Please contact the administrator of the RDP server and clarify.");
return 0;
}
while (MessageQueue_Peek(queue, &message, TRUE))
{
status = freerdp_message_queue_process_message(instance,
- FREERDP_INPUT_MESSAGE_QUEUE, &message);
+ FREERDP_INPUT_MESSAGE_QUEUE, &message);
if (!status)
break;
if (async_input)
{
if (!(input_thread = CreateThread(NULL, 0,
- (LPTHREAD_START_ROUTINE) wf_input_thread,
- instance, 0, NULL)))
+ (LPTHREAD_START_ROUTINE) wf_input_thread,
+ instance, 0, NULL)))
{
WLog_ERR(TAG, "Failed to create async input thread.");
goto disconnect;
}
if (MsgWaitForMultipleObjects(nCount, handles, FALSE, 1000,
- QS_ALLINPUT) == WAIT_FAILED)
+ QS_ALLINPUT) == WAIT_FAILED)
{
WLog_ERR(TAG, "wfreerdp_run: WaitForMultipleObjects failed: 0x%04X",
- GetLastError());
+ GetLastError());
break;
}
wfc = (wfContext*) lpParam;
assert(NULL != wfc);
hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, wf_ll_kbd_proc, wfc->hInstance,
- 0);
+ 0);
if (hook_handle)
{
if ((width != wfc->client_width) || (height != wfc->client_height))
{
PostThreadMessage(wfc->mainThreadId, WM_SIZE, SIZE_RESTORED,
- ((UINT) height << 16) | (UINT) width);
+ ((UINT) height << 16) | (UINT) width);
}
return 0;
}
void wf_size_scrollbars(wfContext* wfc, UINT32 client_width,
- UINT32 client_height)
+ UINT32 client_height)
{
if (wfc->disablewindowtracking)
return;
horiz = TRUE;
}
else if (horiz
- && client_width >=
- wfc->context.settings->DesktopWidth/* - GetSystemMetrics(SM_CXVSCROLL)*/)
+ && client_width >=
+ wfc->context.settings->DesktopWidth/* - GetSystemMetrics(SM_CXVSCROLL)*/)
{
horiz = FALSE;
}
vert = TRUE;
}
else if (vert
- && client_height >=
- wfc->context.settings->DesktopHeight/* - GetSystemMetrics(SM_CYHSCROLL)*/)
+ && client_height >=
+ wfc->context.settings->DesktopHeight/* - GetSystemMetrics(SM_CYHSCROLL)*/)
{
vert = FALSE;
}
if (horiz == vert && (horiz != wfc->xScrollVisible
- && vert != wfc->yScrollVisible))
+ && vert != wfc->yScrollVisible))
{
if (ShowScrollBar(wfc->hwnd, SB_BOTH, horiz))
{
// (bitmap_height) - (client_height). The current vertical
// scroll value remains within the vertical scrolling range.
wfc->yMaxScroll = MAX(wfc->context.settings->DesktopHeight - client_height,
- 0);
+ 0);
wfc->yCurrentScroll = MIN(wfc->yCurrentScroll, wfc->yMaxScroll);
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
if (!(wfreerdp_client_global_init()))
return FALSE;
- if (!(context->channels = freerdp_channels_new()))
+ if (!(context->channels = freerdp_channels_new(instance)))
return FALSE;
instance->PreConnect = wf_pre_connect;
instance->GatewayAuthenticate = wf_gw_authenticate;
instance->VerifyCertificate = wf_verify_certificate;
instance->VerifyChangedCertificate = wf_verify_changed_certificate;
-
return TRUE;
}
wfc->wndClass.hIconSm = wfc->icon;
RegisterClassEx(&(wfc->wndClass));
wfc->keyboardThread = CreateThread(NULL, 0, wf_keyboard_thread, (void*) wfc, 0,
- &wfc->keyboardThreadId);
+ &wfc->keyboardThreadId);
if (!wfc->keyboardThread)
return -1;
return -1;
wfc->thread = CreateThread(NULL, 0, wf_client_thread, (void*) instance, 0,
- &wfc->mainThreadId);
+ &wfc->mainThreadId);
if (!wfc->thread)
return -1;
assert(!xfc->mutex);
assert(!xfc->x11event);
- if (!(context->channels = freerdp_channels_new()))
+ if (!(context->channels = freerdp_channels_new(instance)))
goto fail_channels_new;
instance->PreConnect = xf_pre_connect;
if (!instance || !context)
return FALSE;
- if (!(context->channels = freerdp_channels_new()))
+ if (!(context->channels = freerdp_channels_new(instance)))
return FALSE;
if ((ctx->mfi = calloc(1, sizeof(mfInfo))) == NULL)
extern "C" {
#endif
-FREERDP_API rdpChannels* freerdp_channels_new(void);
+FREERDP_API rdpChannels* freerdp_channels_new(freerdp* instance);
FREERDP_API void freerdp_channels_free(rdpChannels* channels);
-FREERDP_API int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings,
- PVIRTUALCHANNELENTRY entry, void* data);
-FREERDP_API int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings,
- const char* name, void* data);
-FREERDP_API UINT freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance);
-FREERDP_API UINT freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance);
-FREERDP_API UINT freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance);
-FREERDP_API BOOL freerdp_channels_get_fds(rdpChannels* channels, freerdp* instance, void** read_fds,
- int* read_count, void** write_fds, int* write_count);
-FREERDP_API BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance);
-FREERDP_API void freerdp_channels_close(rdpChannels* channels, freerdp* instance);
-
-FREERDP_API void* freerdp_channels_get_static_channel_interface(rdpChannels* channels, const char* name);
+FREERDP_API int freerdp_channels_client_load(rdpChannels* channels,
+ rdpSettings* settings,
+ PVIRTUALCHANNELENTRY entry, void* data);
+FREERDP_API int freerdp_channels_load_plugin(rdpChannels* channels,
+ rdpSettings* settings,
+ const char* name, void* data);
+FREERDP_API UINT freerdp_channels_pre_connect(rdpChannels* channels,
+ freerdp* instance);
+FREERDP_API UINT freerdp_channels_post_connect(rdpChannels* channels,
+ freerdp* instance);
+FREERDP_API UINT freerdp_channels_disconnect(rdpChannels* channels,
+ freerdp* instance);
+FREERDP_API BOOL freerdp_channels_get_fds(rdpChannels* channels,
+ freerdp* instance, void** read_fds,
+ int* read_count, void** write_fds, int* write_count);
+FREERDP_API BOOL freerdp_channels_check_fds(rdpChannels* channels,
+ freerdp* instance);
+FREERDP_API void freerdp_channels_close(rdpChannels* channels,
+ freerdp* instance);
+
+FREERDP_API void* freerdp_channels_get_static_channel_interface(
+ rdpChannels* channels, const char* name);
FREERDP_API HANDLE freerdp_channels_get_event_handle(freerdp* instance);
FREERDP_API int freerdp_channels_process_pending_messages(freerdp* instance);
FREERDP_API int freerdp_channels_data(freerdp* instance,
- UINT16 channelId, BYTE* data, int dataSize, int flags, int totalSize);
+ UINT16 channelId, BYTE* data, int dataSize, int flags, int totalSize);
FREERDP_API PWtsApiFunctionTable FreeRDP_InitWtsApi(void);
typedef BOOL (*pPostConnect)(freerdp* instance);
typedef void (*pPostDisconnect)(freerdp* instance);
typedef BOOL (*pAuthenticate)(freerdp* instance, char** username,
- char** password, char** domain);
+ char** password, char** domain);
/** @brief Callback used if user interaction is required to accept
* an unknown certificate.
* a certificate only for this session, 0 otherwise.
*/
typedef DWORD (*pVerifyCertificate)(freerdp* instance,
- const char* common_name,
- const char* subject,
- const char* issuer,
- const char* fingerprint,
- BOOL host_mismatch);
+ const char* common_name,
+ const char* subject,
+ const char* issuer,
+ const char* fingerprint,
+ BOOL host_mismatch);
/** @brief Callback used if user interaction is required to accept
* a changed certificate.
*/
typedef DWORD (*pVerifyChangedCertificate)(freerdp* instance,
- const char* common_name,
- const char* subject,
- const char* issuer,
- const char* new_fingerprint,
- const char* old_subject,
- const char* old_issuer,
- const char* old_fingerprint);
+ const char* common_name,
+ const char* subject,
+ const char* issuer,
+ const char* new_fingerprint,
+ const char* old_subject,
+ const char* old_issuer,
+ const char* old_fingerprint);
typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data,
- int length, const char* hostname,
- int port, DWORD flags);
+ int length, const char* hostname,
+ int port, DWORD flags);
typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);
-typedef int (*pSendChannelData)(freerdp* instance, UINT16 channelId, BYTE* data, int size);
-typedef int (*pReceiveChannelData)(freerdp* instance, UINT16 channelId, BYTE* data, int size, int flags, int totalSize);
+typedef int (*pSendChannelData)(freerdp* instance, UINT16 channelId, BYTE* data,
+ int size);
+typedef int (*pReceiveChannelData)(freerdp* instance, UINT16 channelId,
+ BYTE* data, int size, int flags, int totalSize);
/**
* Defines the context for a given instance of RDP connection.
Used when a certificate differs from stored fingerprint.
If returns TRUE, the new fingerprint will be trusted and old thrown out. */
- ALIGN64 pVerifyX509Certificate VerifyX509Certificate; /**< (offset 53) Callback for X509 certificate verification (PEM format) */
+ ALIGN64 pVerifyX509Certificate
+ VerifyX509Certificate; /**< (offset 53) Callback for X509 certificate verification (PEM format) */
- ALIGN64 pLogonErrorInfo LogonErrorInfo; /**< (offset 54) Callback for logon error info, important for logon system messages with RemoteApp */
+ ALIGN64 pLogonErrorInfo
+ LogonErrorInfo; /**< (offset 54) Callback for logon error info, important for logon system messages with RemoteApp */
ALIGN64 pPostDisconnect PostDisconnect; /**< (offset 55)
Callback for cleaning up resources allocated
FREERDP_API BOOL freerdp_disconnect(freerdp* instance);
FREERDP_API BOOL freerdp_reconnect(freerdp* instance);
-FREERDP_API BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount);
+FREERDP_API void freerdp_channel_init_thread_context(rdpContext* context);
+FREERDP_API freerdp* freerdp_channel_get_instance(void);
+FREERDP_API rdpContext* freerdp_channel_get_context(void);
+FREERDP_API rdpChannels* freerdp_channel_get_channels_context(void);
+
+FREERDP_API BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount,
+ void** wfds, int* wcount);
FREERDP_API BOOL freerdp_check_fds(freerdp* instance);
-FREERDP_API DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count);
+FREERDP_API DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events,
+ DWORD count);
FREERDP_API BOOL freerdp_check_event_handles(rdpContext* context);
-FREERDP_API wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD id);
-FREERDP_API HANDLE freerdp_get_message_queue_event_handle(freerdp* instance, DWORD id);
-FREERDP_API int freerdp_message_queue_process_message(freerdp* instance, DWORD id, wMessage* message);
-FREERDP_API int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD id);
+FREERDP_API wMessageQueue* freerdp_get_message_queue(freerdp* instance,
+ DWORD id);
+FREERDP_API HANDLE freerdp_get_message_queue_event_handle(freerdp* instance,
+ DWORD id);
+FREERDP_API int freerdp_message_queue_process_message(freerdp* instance,
+ DWORD id, wMessage* message);
+FREERDP_API int freerdp_message_queue_process_pending_messages(
+ freerdp* instance, DWORD id);
FREERDP_API UINT32 freerdp_error_info(freerdp* instance);
FREERDP_API void freerdp_set_error_info(rdpRdp* rdp, UINT32 error);
FREERDP_API const char* freerdp_get_last_error_string(UINT32 error);
FREERDP_API void freerdp_set_last_error(rdpContext* context, UINT32 lastError);
-FREERDP_API ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount);
+FREERDP_API ULONG freerdp_get_transport_sent(rdpContext* context,
+ BOOL resetCount);
FREERDP_API void clearChannelError(rdpContext* context);
FREERDP_API HANDLE getChannelErrorEventHandle(rdpContext* context);
FREERDP_API UINT getChannelError(rdpContext* context);
FREERDP_API const char* getChannelErrorDescription(rdpContext* context);
-FREERDP_API void setChannelError(rdpContext* context, UINT errorNum, char* description);
+FREERDP_API void setChannelError(rdpContext* context, UINT errorNum,
+ char* description);
FREERDP_API BOOL checkChannelErrorEvent(rdpContext* context);
#ifdef __cplusplus
#define TAG FREERDP_TAG("core.client")
-static void* g_pInterface = NULL;
-static CHANNEL_INIT_DATA g_ChannelInitData;
+static WINPR_TLS void* g_pInterface = NULL;
-static wHashTable* g_OpenHandles = NULL;
-
-/* To generate unique sequence for all open handles */
-int g_open_handle_sequence = 1;
-
-/* For locking the global resources */
-static CRITICAL_SECTION g_channels_lock;
-
-CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(
+static CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(
rdpChannels* channels, const char* name)
{
int index;
}
/* returns rdpChannel for the channel name passed in */
-rdpMcsChannel* freerdp_channels_find_channel_by_name(rdpRdp* rdp,
+static rdpMcsChannel* freerdp_channels_find_channel_by_name(rdpRdp* rdp,
const char* name)
{
UINT32 index;
return NULL;
}
-rdpChannels* freerdp_channels_new(void)
+rdpChannels* freerdp_channels_new(freerdp* instance)
{
rdpChannels* channels;
channels = (rdpChannels*) calloc(1, sizeof(rdpChannels));
if (!channels)
return NULL;
+ if (!InitializeCriticalSectionAndSpinCount(&channels->channelsLock, 4000))
+ goto error;
+
+ channels->instance = instance;
+ channels->openHandleSeq = 1;
channels->queue = MessageQueue_New(NULL);
if (!channels->queue)
- goto error_queue;
-
- if (!g_OpenHandles)
- {
- g_OpenHandles = HashTable_New(TRUE);
+ goto error;
- if (!g_OpenHandles)
- goto error_open_handles;
+ channels->openHandles = HashTable_New(TRUE);
- if (!InitializeCriticalSectionAndSpinCount(&g_channels_lock, 4000))
- goto error_open_handles;
- }
+ if (!channels->openHandles)
+ goto error;
return channels;
-error_open_handles:
- MessageQueue_Free(channels->queue);
-error_queue:
- free(channels);
+error:
+ freerdp_channels_free(channels);
return NULL;
}
void freerdp_channels_free(rdpChannels* channels)
{
int index;
- int nkeys;
- ULONG_PTR* pKeys = NULL;
CHANNEL_OPEN_DATA* pChannelOpenData;
if (!channels)
return;
+ DeleteCriticalSection(&channels->channelsLock);
+
if (channels->queue)
{
MessageQueue_Free(channels->queue);
pChannelOpenData->pInterface = NULL;
}
- HashTable_Remove(g_OpenHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle);
+ if (channels->openHandles)
+ HashTable_Remove(channels->openHandles,
+ (void*)(UINT_PTR)pChannelOpenData->OpenHandle);
}
- if (g_OpenHandles)
- {
- nkeys = HashTable_GetKeys(g_OpenHandles, &pKeys);
-
- if (nkeys == 0)
- {
- HashTable_Free(g_OpenHandles);
- DeleteCriticalSection(&g_channels_lock);
- g_OpenHandles = NULL;
- }
-
- free(pKeys);
- }
+ if (channels->openHandles)
+ HashTable_Free(channels->openHandles);
free(channels);
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context,
+static UINT freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context,
const char* name, void* pInterface)
{
UINT status = CHANNEL_RC_OK;
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext* context,
+static UINT freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext*
+ context,
const char* name, void* pInterface)
{
UINT status = CHANNEL_RC_OK;
UINT error = CHANNEL_RC_OK;
int index;
CHANNEL_CLIENT_DATA* pChannelClientData;
- channels->instance = instance;
for (index = 0; index < channels->clientDataCount; index++)
{
MessageQueue_PostQuit(channels->queue, 0);
}
-UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle,
+static UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle,
PCHANNEL_DEF pChannel,
INT channelCount, ULONG versionRequested,
PCHANNEL_INIT_EVENT_FN pChannelInitEventProc)
void* pInterface;
DWORD OpenHandle;
CHANNEL_DEF* channel;
- rdpChannels* channels;
+ rdpChannels* channels = freerdp_channel_get_channels_context();
rdpSettings* settings;
PCHANNEL_DEF pChannelDef;
CHANNEL_INIT_DATA* pChannelInitData;
CHANNEL_OPEN_DATA* pChannelOpenData;
CHANNEL_CLIENT_DATA* pChannelClientData;
- if (!ppInitHandle)
+ if (!ppInitHandle || !channels)
return CHANNEL_RC_BAD_INIT_HANDLE;
if (!pChannel || (channelCount <= 0) || !pChannelInitEventProc)
return CHANNEL_RC_INITIALIZATION_ERROR;
- channels = g_ChannelInitData.channels;
pInterface = g_pInterface;
pChannelInitData = &(channels->initDataList[channels->initDataCount]);
*ppInitHandle = pChannelInitData;
pChannelClientData->pChannelInitEventProc = pChannelInitEventProc;
pChannelClientData->pInitHandle = *ppInitHandle;
channels->clientDataCount++;
- settings = channels->settings;
+ settings = channels->instance->context->settings;
for (index = 0; index < channelCount; index++)
{
pChannelDef = &pChannel[index];
pChannelOpenData = &channels->openDataList[channels->openDataCount];
- OpenHandle = g_open_handle_sequence++;
+ OpenHandle = channels->openHandleSeq++;
pChannelOpenData->OpenHandle = OpenHandle;
pChannelOpenData->channels = channels;
- HashTable_Add(g_OpenHandles, (void*)(UINT_PTR) OpenHandle,
+ HashTable_Add(channels->openHandles, (void*)(UINT_PTR) OpenHandle,
(void*) pChannelOpenData);
pChannelOpenData->flags = 1; /* init */
strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN);
channel = &settings->ChannelDefArray[settings->ChannelCount];
strncpy(channel->name, pChannelDef->name, 7);
channel->options = pChannelDef->options;
- channels->settings->ChannelCount++;
+ settings->ChannelCount++;
}
channels->openDataCount++;
return CHANNEL_RC_OK;
}
-UINT VCAPITYPE FreeRDP_VirtualChannelOpen(LPVOID pInitHandle,
+static UINT VCAPITYPE FreeRDP_VirtualChannelOpen(LPVOID pInitHandle,
LPDWORD pOpenHandle,
PCHAR pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc)
{
return CHANNEL_RC_OK;
}
-UINT VCAPITYPE FreeRDP_VirtualChannelClose(DWORD openHandle)
+static UINT VCAPITYPE FreeRDP_VirtualChannelClose(DWORD openHandle)
{
+ rdpChannels* channels = freerdp_channel_get_channels_context();
CHANNEL_OPEN_DATA* pChannelOpenData;
- pChannelOpenData = HashTable_GetItemValue(g_OpenHandles,
+
+ if (!channels)
+ return CHANNEL_RC_BAD_CHANNEL_HANDLE;
+
+ pChannelOpenData = HashTable_GetItemValue(channels->openHandles,
(void*)(UINT_PTR) openHandle);
if (!pChannelOpenData)
return CHANNEL_RC_OK;
}
-UINT VCAPITYPE FreeRDP_VirtualChannelWrite(DWORD openHandle, LPVOID pData,
+static UINT VCAPITYPE FreeRDP_VirtualChannelWrite(DWORD openHandle,
+ LPVOID pData,
ULONG dataLength, LPVOID pUserData)
{
- rdpChannels* channels;
+ rdpChannels* channels = freerdp_channel_get_channels_context();
CHANNEL_OPEN_DATA* pChannelOpenData;
CHANNEL_OPEN_EVENT* pChannelOpenEvent;
- pChannelOpenData = HashTable_GetItemValue(g_OpenHandles,
- (void*)(UINT_PTR) openHandle);
- if (!pChannelOpenData)
+ if (!channels)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
- channels = pChannelOpenData->channels;
+ pChannelOpenData = HashTable_GetItemValue(channels->openHandles,
+ (void*)(UINT_PTR) openHandle);
- if (!channels)
+ if (!pChannelOpenData)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
if (!channels->connected)
EntryPoints.context = ((freerdp*)settings->instance)->context;
/* enable VirtualChannelInit */
channels->can_call_init = TRUE;
- channels->settings = settings;
- EnterCriticalSection(&g_channels_lock);
+ EnterCriticalSection(&channels->channelsLock);
g_pInterface = NULL;
- g_ChannelInitData.channels = channels;
status = pChannelClientData->entry((PCHANNEL_ENTRY_POINTS) &EntryPoints);
- LeaveCriticalSection(&g_channels_lock);
+ LeaveCriticalSection(&channels->channelsLock);
/* disable MyVirtualChannelInit */
- channels->settings = NULL;
channels->can_call_init = FALSE;
if (!status)
/* control for entry into MyVirtualChannelInit */
int can_call_init;
- rdpSettings* settings;
/* true once freerdp_channels_post_connect is called */
BOOL connected;
wMessageQueue* queue;
DrdynvcClientContext* drdynvc;
+ UINT64 openHandleSeq;
+ CRITICAL_SECTION channelsLock;
+ wHashTable* openHandles;
};
#endif /* FREERDP_CORE_CLIENT_H */
/* connectErrorCode is 'extern' in error.h. See comment there.*/
+/* Thread local storage variables.
+ * They need to be initialized in every thread that
+ * has to use them. */
+static WINPR_TLS rdpContext* s_TLSContext = NULL;
+
+void freerdp_channel_init_thread_context(rdpContext* context)
+{
+ s_TLSContext = context;
+}
+
+freerdp* freerdp_channel_get_instance(void)
+{
+ if (!s_TLSContext)
+ return NULL;
+
+ return s_TLSContext->instance;
+}
+
+rdpContext* freerdp_channel_get_context(void)
+{
+ return s_TLSContext;
+}
+
+rdpChannels* freerdp_channel_get_channels_context(void)
+{
+ if (!s_TLSContext)
+ return NULL;
+
+ return s_TLSContext->channels;
+}
+
/** Creates a new connection based on the settings found in the "instance" parameter
* It will use the callbacks registered on the structure to process the pre/post connect operations
* that the caller requires.
rdpSettings* settings;
ConnectionResultEventArgs e;
+ if (!instance)
+ return FALSE;
+
+ freerdp_channel_init_thread_context(instance->context);
/* We always set the return code to 0 before we start the connect sequence*/
connectErrorCode = 0;
freerdp_set_last_error(instance->context, FREERDP_ERROR_SUCCESS);
clearChannelError(instance->context);
ResetEvent(instance->context->abortEvent);
-
rdp = instance->context->rdp;
settings = instance->settings;
-
instance->context->codecs = codecs_new(instance->context);
IFCALLRET(instance->PreConnect, status, instance);
{
if (instance->settings->DumpRemoteFx)
{
- instance->update->pcap_rfx = pcap_open(instance->settings->DumpRemoteFxFile, TRUE);
+ instance->update->pcap_rfx = pcap_open(instance->settings->DumpRemoteFxFile,
+ TRUE);
+
if (instance->update->pcap_rfx)
instance->update->dump_rfx = TRUE;
}
wStream* s;
rdpUpdate* update;
pcap_record record;
-
update = instance->update;
-
update->pcap_rfx = pcap_open(settings->PlayRemoteFxFile, FALSE);
if (!update->pcap_rfx)
while (pcap_has_next_record(update->pcap_rfx))
{
-
pcap_get_next_record_header(update->pcap_rfx, &record);
if (!(s = StreamPool_Take(rdp->transport->ReceivePool, record.length)))
break;
record.data = Stream_Buffer(s);
-
pcap_get_next_record_content(update->pcap_rfx, &record);
- Stream_SetLength(s,record.length);
+ Stream_SetLength(s, record.length);
Stream_SetPosition(s, 0);
-
update->BeginPaint(update->context);
update_recv_surfcmds(update, Stream_Length(s) , s);
update->EndPaint(update->context);
}
if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
- freerdp_set_last_error(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
+ freerdp_set_last_error(instance->context,
+ FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
SetEvent(rdp->transport->connectedEvent);
freerdp_connect_finally:
EventArgsInit(&e, "freerdp");
e.result = status ? 0 : -1;
PubSub_OnConnectionResult(instance->context->pubSub, instance->context, &e);
-
return status;
}
return SetEvent(instance->context->abortEvent);
}
-BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
+BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds,
+ int* wcount)
{
rdpRdp* rdp = instance->context->rdp;
transport_get_fds(rdp->transport, rfds, rcount);
return FALSE;
rdp = instance->context->rdp;
-
status = rdp_check_fds(rdp);
if (status < 0)
{
TerminateEventArgs e;
rdpContext* context = instance->context;
-
WLog_DBG(TAG, "rdp_check_fds() - %i", status);
EventArgsInit(&e, "freerdp");
e.code = 0;
PubSub_OnTerminate(context->pubSub, context, &e);
-
return FALSE;
}
return TRUE;
}
-DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count)
+DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events,
+ DWORD count)
{
DWORD nCount = 0;
-
nCount += transport_get_event_handles(context->rdp->transport, events, count);
if (nCount == 0)
BOOL freerdp_check_event_handles(rdpContext* context)
{
BOOL status;
-
status = freerdp_check_fds(context->instance);
if (!status)
}
status = freerdp_channels_check_fds(context->channels, context->instance);
+
if (!status)
{
WLog_ERR(TAG, "freerdp_channels_check_fds() failed - %i", status);
return FALSE;
status = checkChannelErrorEvent(context);
-
return status;
}
{
HANDLE event = NULL;
wMessageQueue* queue = NULL;
-
queue = freerdp_get_message_queue(instance, id);
if (queue)
return event;
}
-int freerdp_message_queue_process_message(freerdp* instance, DWORD id, wMessage* message)
+int freerdp_message_queue_process_message(freerdp* instance, DWORD id,
+ wMessage* message)
{
int status = -1;
return status;
}
-static int freerdp_send_channel_data(freerdp* instance, UINT16 channelId, BYTE* data, int size)
+static int freerdp_send_channel_data(freerdp* instance, UINT16 channelId,
+ BYTE* data, int size)
{
return rdp_send_channel_data(instance->context->rdp, channelId, data, size);
}
BOOL freerdp_disconnect(freerdp* instance)
{
rdpRdp* rdp;
-
rdp = instance->context->rdp;
-
rdp_client_disconnect(rdp);
update_post_disconnect(instance->update);
-
IFCALL(instance->PostDisconnect, instance);
if (instance->update->pcap_rfx)
{
BOOL status;
rdpRdp* rdp = instance->context->rdp;
-
ResetEvent(instance->context->abortEvent);
status = rdp_client_reconnect(rdp);
-
return status;
}
{
if (!instance || !instance->context)
return FALSE;
+
if (WaitForSingleObject(instance->context->abortEvent, 0) != WAIT_OBJECT_0)
return FALSE;
+
return TRUE;
}
{
rdpRdp* rdp;
BOOL bRetCode = FALSE;
-
rdp = instance->context->rdp;
if (rdp->resendFocus)
void freerdp_set_focus(freerdp* instance)
{
rdpRdp* rdp;
-
rdp = instance->context->rdp;
rdp->resendFocus = TRUE;
}
const char* freerdp_get_build_date(void)
{
static char build_date[] = __DATE__ " " __TIME__;
-
return build_date;
}
const char* freerdp_get_build_config(void)
{
static const char build_config[] =
- "Build configuration: " BUILD_CONFIG "\n"
- "Build type: " BUILD_TYPE "\n"
- "CFLAGS: " CFLAGS "\n"
- "Compiler: " COMPILER_ID ", " COMPILER_VERSION "\n"
- "Target architecture: " TARGET_ARCH "\n";
-
+ "Build configuration: " BUILD_CONFIG "\n"
+ "Build type: " BUILD_TYPE "\n"
+ "CFLAGS: " CFLAGS "\n"
+ "Compiler: " COMPILER_ID ", " COMPILER_VERSION "\n"
+ "Target architecture: " TARGET_ARCH "\n";
return build_config;
}
rdpRdp* rdp;
rdpContext* context;
BOOL ret = TRUE;
-
instance->context = (rdpContext*) calloc(1, instance->ContextSize);
+
if (!instance->context)
return FALSE;
context = instance->context;
context->instance = instance;
-
context->ServerMode = FALSE;
context->settings = instance->settings;
-
context->pubSub = PubSub_New(TRUE);
- if(!context->pubSub)
+
+ if (!context->pubSub)
goto out_error_pubsub;
- PubSub_AddEventTypes(context->pubSub, FreeRDP_Events, sizeof(FreeRDP_Events) / sizeof(wEventType));
+ PubSub_AddEventTypes(context->pubSub, FreeRDP_Events,
+ sizeof(FreeRDP_Events) / sizeof(wEventType));
context->metrics = metrics_new(context);
+
if (!context->metrics)
goto out_error_metrics_new;
rdp = rdp_new(context);
+
if (!rdp)
goto out_error_rdp_new;
instance->update = rdp->update;
instance->settings = rdp->settings;
instance->autodetect = rdp->autodetect;
-
context->graphics = graphics_new(context);
- if(!context->graphics)
+
+ if (!context->graphics)
goto out_error_graphics_new;
context->rdp = rdp;
-
context->input = instance->input;
context->update = instance->update;
context->settings = instance->settings;
context->autodetect = instance->autodetect;
-
instance->update->context = instance->context;
instance->update->pointer->context = instance->context;
instance->update->primary->context = instance->context;
instance->update->secondary->context = instance->context;
instance->update->altsec->context = instance->context;
-
instance->input->context = context;
-
instance->autodetect->context = context;
if (!(context->errorDescription = calloc(1, 500)))
}
update_register_client_callbacks(rdp->update);
-
instance->context->abortEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
if (!instance->context->abortEvent)
goto out_error_abort_event;
return;
IFCALL(instance->ContextFree, instance, instance->context);
-
rdp_free(instance->context->rdp);
instance->context->rdp = NULL;
-
graphics_free(instance->context->graphics);
instance->context->graphics = NULL;
-
PubSub_Free(instance->context->pubSub);
-
metrics_free(instance->context->metrics);
-
CloseHandle(instance->context->channelErrorEvent);
free(instance->context->errorDescription);
-
CloseHandle(instance->context->abortEvent);
instance->context->abortEvent = NULL;
-
free(instance->context);
instance->context = NULL;
-
}
UINT32 freerdp_error_info(freerdp* instance)
const char* freerdp_get_last_error_name(UINT32 code)
{
- const char *name = NULL;
+ const char* name = NULL;
const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
- switch(cls)
+ switch (cls)
{
case FREERDP_ERROR_ERRBASE_CLASS:
name = freerdp_get_error_base_name(type);
break;
+
case FREERDP_ERROR_ERRINFO_CLASS:
name = freerdp_get_error_info_name(type);
break;
+
case FREERDP_ERROR_CONNECT_CLASS:
name = freerdp_get_error_connect_name(type);
break;
+
default:
name = "Unknown error class";
break;
const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
- switch(cls)
+ switch (cls)
{
case FREERDP_ERROR_ERRBASE_CLASS:
string = freerdp_get_error_base_string(type);
break;
+
case FREERDP_ERROR_ERRINFO_CLASS:
string = freerdp_get_error_info_string(type);
break;
+
case FREERDP_ERROR_CONNECT_CLASS:
string = freerdp_get_error_connect_string(type);
break;
+
default:
string = "Unknown error class";
break;
{
if (lastError)
WLog_ERR(TAG, "freerdp_set_last_error %s [0x%04X]",
- freerdp_get_last_error_name(lastError), lastError);
+ freerdp_get_last_error_name(lastError), lastError);
context->LastError = lastError;
freerdp* freerdp_new()
{
freerdp* instance;
-
instance = (freerdp*) calloc(1, sizeof(freerdp));
if (!instance)
instance->ContextSize = sizeof(rdpContext);
instance->SendChannelData = freerdp_send_channel_data;
instance->ReceiveChannelData = freerdp_channels_data;
-
return instance;
}
free(instance);
}
-ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount) {
+ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount)
+{
ULONG written = context->rdp->transport->written;
+
if (resetCount)
context->rdp->transport->written = 0;
+
return written;
}
BOOL checkChannelErrorEvent(rdpContext* context)
{
- if (WaitForSingleObject( context->channelErrorEvent, 0) == WAIT_OBJECT_0)
+ if (WaitForSingleObject(context->channelErrorEvent, 0) == WAIT_OBJECT_0)
{
- WLog_ERR(TAG, "%s. Error was %lu", context->errorDescription, context->channelErrorNum);
+ WLog_ERR(TAG, "%s. Error was %lu", context->errorDescription,
+ context->channelErrorNum);
return FALSE;
}
+
return TRUE;
}
#define WINPR_H
#if defined _WIN32 || defined __CYGWIN__
- #ifdef WINPR_EXPORTS
- #ifdef __GNUC__
- #define WINPR_API __attribute__((dllexport))
- #else
- #define WINPR_API __declspec(dllexport)
- #endif
- #else
- #ifdef __GNUC__
- #define WINPR_API __attribute__((dllimport))
- #else
- #define WINPR_API __declspec(dllimport)
- #endif
- #endif
-#else
- #if __GNUC__ >= 4
- #define WINPR_API __attribute__ ((visibility("default")))
- #else
- #define WINPR_API
- #endif
+#ifdef WINPR_EXPORTS
+#ifdef __GNUC__
+#define WINPR_API __attribute__((dllexport))
+#else
+#define WINPR_API __declspec(dllexport)
+#endif
+#else
+#ifdef __GNUC__
+#define WINPR_API __attribute__((dllimport))
+#else
+#define WINPR_API __declspec(dllimport)
+#endif
+#endif
+#else
+#if __GNUC__ >= 4
+#define WINPR_API __attribute__ ((visibility("default")))
+#else
+#define WINPR_API
#endif
+#endif
+
+/* Thread local storage keyword define */
+#if defined _WIN32 || defined __CYGWIN__
+#ifdef __GNUC__
+#define WINPR_TLS __thread
+#else
+#define WINPR_TLS __declspec(thread)
+#endif
+#else
+#define WINPR_TLS __thread
+#endif
+
#ifdef _WIN32
#define INLINE __inline