Merge pull request #1679 from awakecoding/master
Robustness, WinPR, Codecs, CMake
This commit is contained in:
commit
19ab10d819
2
.gitignore
vendored
2
.gitignore
vendored
@ -5,7 +5,7 @@ CMakeCache.txt
|
|||||||
config.h
|
config.h
|
||||||
install_manifest*.txt
|
install_manifest*.txt
|
||||||
CTestTestfile.cmake
|
CTestTestfile.cmake
|
||||||
freerdp.pc
|
*.pc
|
||||||
Makefile
|
Makefile
|
||||||
Testing
|
Testing
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
|
@ -144,6 +144,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
|||||||
CHECK_C_COMPILER_FLAG(-Wno-deprecated-declarations Wno-deprecated-declarations)
|
CHECK_C_COMPILER_FLAG(-Wno-deprecated-declarations Wno-deprecated-declarations)
|
||||||
if(Wno-deprecated-declarations)
|
if(Wno-deprecated-declarations)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
|
||||||
endif()
|
endif()
|
||||||
if(NOT EXPORT_ALL_SYMBOLS)
|
if(NOT EXPORT_ALL_SYMBOLS)
|
||||||
message(STATUS "GCC default symbol visibility: hidden")
|
message(STATUS "GCC default symbol visibility: hidden")
|
||||||
@ -176,6 +177,7 @@ if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
|||||||
CHECK_C_COMPILER_FLAG(-Wno-deprecated-declarations Wno-deprecated-declarations)
|
CHECK_C_COMPILER_FLAG(-Wno-deprecated-declarations Wno-deprecated-declarations)
|
||||||
if(Wno-deprecated-declarations)
|
if(Wno-deprecated-declarations)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -212,8 +214,8 @@ if(IOS)
|
|||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -isysroot ${CMAKE_IOS_SDK_ROOT} -g")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -isysroot ${CMAKE_IOS_SDK_ROOT} -g")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINPR_EXPORTS")
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFREERDP_EXPORTS")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFREERDP_EXPORTS")
|
||||||
|
|
||||||
# Include files
|
# Include files
|
||||||
if(NOT IOS)
|
if(NOT IOS)
|
||||||
check_include_files(fcntl.h HAVE_FCNTL_H)
|
check_include_files(fcntl.h HAVE_FCNTL_H)
|
||||||
@ -313,10 +315,11 @@ if(NOT IOS AND NOT ANDROID)
|
|||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT WIN32)
|
||||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
||||||
check_library_exists(pthread pthread_tryjoin_np "" HAVE_PTHREAD_GNU_EXT)
|
check_library_exists(pthread pthread_tryjoin_np "" HAVE_PTHREAD_GNU_EXT)
|
||||||
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(UNIX OR CYGWIN)
|
if(UNIX OR CYGWIN)
|
||||||
check_include_files(sys/eventfd.h HAVE_AIO_H)
|
check_include_files(sys/eventfd.h HAVE_AIO_H)
|
||||||
@ -382,6 +385,10 @@ set(JPEG_FEATURE_TYPE "OPTIONAL")
|
|||||||
set(JPEG_FEATURE_PURPOSE "codec")
|
set(JPEG_FEATURE_PURPOSE "codec")
|
||||||
set(JPEG_FEATURE_DESCRIPTION "use JPEG library")
|
set(JPEG_FEATURE_DESCRIPTION "use JPEG library")
|
||||||
|
|
||||||
|
set(GSM_FEATURE_TYPE "OPTIONAL")
|
||||||
|
set(GSM_FEATURE_PURPOSE "codec")
|
||||||
|
set(GSM_FEATURE_DESCRIPTION "GSM audio codec library")
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(X11_FEATURE_TYPE "DISABLED")
|
set(X11_FEATURE_TYPE "DISABLED")
|
||||||
set(ZLIB_FEATURE_TYPE "DISABLED")
|
set(ZLIB_FEATURE_TYPE "DISABLED")
|
||||||
@ -427,9 +434,7 @@ endif()
|
|||||||
find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION})
|
find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION})
|
||||||
find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION})
|
find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION})
|
||||||
if (${WITH_DIRECTFB})
|
if (${WITH_DIRECTFB})
|
||||||
message(WARNING "
|
message(WARNING "DIRECTFB is orphaned and not maintained see docs/README.directfb for details")
|
||||||
DIRECTFB is orphaned and not maintained see docs/README.directfb for details
|
|
||||||
")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_feature(ZLIB ${ZLIB_FEATURE_TYPE} ${ZLIB_FEATURE_PURPOSE} ${ZLIB_FEATURE_DESCRIPTION})
|
find_feature(ZLIB ${ZLIB_FEATURE_TYPE} ${ZLIB_FEATURE_PURPOSE} ${ZLIB_FEATURE_DESCRIPTION})
|
||||||
@ -446,6 +451,7 @@ find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FE
|
|||||||
find_feature(Gstreamer ${GSTREAMER_FEATURE_TYPE} ${GSTREAMER_FEATURE_PURPOSE} ${GSTREAMER_FEATURE_DESCRIPTION})
|
find_feature(Gstreamer ${GSTREAMER_FEATURE_TYPE} ${GSTREAMER_FEATURE_PURPOSE} ${GSTREAMER_FEATURE_DESCRIPTION})
|
||||||
|
|
||||||
find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION})
|
find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION})
|
||||||
|
find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})
|
||||||
|
|
||||||
if(TARGET_ARCH MATCHES "x86|x64")
|
if(TARGET_ARCH MATCHES "x86|x64")
|
||||||
if (NOT APPLE)
|
if (NOT APPLE)
|
||||||
@ -456,7 +462,7 @@ if(TARGET_ARCH MATCHES "x86|x64")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Installation Paths
|
# Installation Paths
|
||||||
if(WIN32)
|
if(WIN32 AND NOT FREERDP_SDK)
|
||||||
set(CMAKE_INSTALL_BINDIR ".")
|
set(CMAKE_INSTALL_BINDIR ".")
|
||||||
set(CMAKE_INSTALL_LIBDIR ".")
|
set(CMAKE_INSTALL_LIBDIR ".")
|
||||||
endif()
|
endif()
|
||||||
@ -521,12 +527,6 @@ include_directories("${CMAKE_BINARY_DIR}/winpr/include")
|
|||||||
|
|
||||||
add_subdirectory(winpr)
|
add_subdirectory(winpr)
|
||||||
|
|
||||||
# Generate pkg-config
|
|
||||||
if(NOT MSVC)
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc @ONLY)
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_CUNIT)
|
if(WITH_CUNIT)
|
||||||
message(FATAL_ERROR "cunit (WITH_CUNIT) is deprecated please use BUILD_TESTING to build ctest tests.
|
message(FATAL_ERROR "cunit (WITH_CUNIT) is deprecated please use BUILD_TESTING to build ctest tests.
|
||||||
The cunit directory contains the old tests and is kept until all tests are converted.")
|
The cunit directory contains the old tests and is kept until all tests are converted.")
|
||||||
|
@ -212,6 +212,74 @@ void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, wStream* s, UINT3
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
||||||
|
{
|
||||||
|
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||||
|
|
||||||
|
if (context->custom)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
int formatNameLength;
|
||||||
|
CLIPRDR_FORMAT* formats;
|
||||||
|
CLIPRDR_FORMAT_LIST formatList;
|
||||||
|
|
||||||
|
formatList.msgType = CB_FORMAT_LIST;
|
||||||
|
formatList.msgFlags = msgFlags;
|
||||||
|
formatList.dataLen = dataLen;
|
||||||
|
|
||||||
|
formatList.cFormats = 0;
|
||||||
|
|
||||||
|
while (dataLen)
|
||||||
|
{
|
||||||
|
Stream_Seek(s, 4); /* formatId */
|
||||||
|
dataLen -= 4;
|
||||||
|
|
||||||
|
formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s));
|
||||||
|
Stream_Seek(s, (formatNameLength + 1) * 2);
|
||||||
|
dataLen -= ((formatNameLength + 1) * 2);
|
||||||
|
formatList.cFormats++;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
dataLen = formatList.dataLen;
|
||||||
|
Stream_Rewind(s, dataLen);
|
||||||
|
|
||||||
|
formats = (CLIPRDR_FORMAT*) malloc(sizeof(CLIPRDR_FORMAT) * formatList.cFormats);
|
||||||
|
formatList.formats = formats;
|
||||||
|
|
||||||
|
while (dataLen)
|
||||||
|
{
|
||||||
|
Stream_Read_UINT32(s, formats[index].formatId); /* formatId */
|
||||||
|
dataLen -= 4;
|
||||||
|
|
||||||
|
formats[index].formatName = NULL;
|
||||||
|
formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s));
|
||||||
|
|
||||||
|
if (formatNameLength)
|
||||||
|
{
|
||||||
|
formatNameLength = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
|
||||||
|
-1, &(formats[index].formatName), 0, NULL, NULL);
|
||||||
|
|
||||||
|
Stream_Seek(s, formatNameLength * 2);
|
||||||
|
dataLen -= (formatNameLength * 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Stream_Seek(s, 2);
|
||||||
|
dataLen -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->ServerFormatList)
|
||||||
|
context->ServerFormatList(context, &formatList);
|
||||||
|
|
||||||
|
for (index = 0; index < formatList.cFormats; index++)
|
||||||
|
free(formats[index].formatName);
|
||||||
|
|
||||||
|
free(formats);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
UINT32 format;
|
UINT32 format;
|
||||||
@ -303,22 +371,56 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
|
|||||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
||||||
cliprdr_send_format_list_response(cliprdr);
|
cliprdr_send_format_list_response(cliprdr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
||||||
{
|
{
|
||||||
/* http://msdn.microsoft.com/en-us/library/hh872154.aspx */
|
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||||
wMessage* event;
|
|
||||||
|
|
||||||
|
/* http://msdn.microsoft.com/en-us/library/hh872154.aspx */
|
||||||
|
|
||||||
|
if (context->custom)
|
||||||
|
{
|
||||||
|
CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse;
|
||||||
|
|
||||||
|
formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE;
|
||||||
|
formatListResponse.msgFlags = msgFlags;
|
||||||
|
formatListResponse.dataLen = dataLen;
|
||||||
|
|
||||||
|
if (context->ServerFormatListResponse)
|
||||||
|
context->ServerFormatListResponse(context, &formatListResponse);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if ((msgFlags & CB_RESPONSE_FAIL) != 0)
|
if ((msgFlags & CB_RESPONSE_FAIL) != 0)
|
||||||
{
|
{
|
||||||
/* In case of an error the clipboard will not be synchronized with the server.
|
/* In case of an error the clipboard will not be synchronized with the server.
|
||||||
* Post this event to restart format negociation and data transfer. */
|
* Post this event to restart format negotiation and data transfer. */
|
||||||
event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
|
|
||||||
|
wMessage* event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
|
||||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event);
|
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
||||||
|
{
|
||||||
|
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||||
|
|
||||||
|
if (context->custom)
|
||||||
|
{
|
||||||
|
CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest;
|
||||||
|
|
||||||
|
formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST;
|
||||||
|
formatDataRequest.msgFlags = msgFlags;
|
||||||
|
formatDataRequest.dataLen = dataLen;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */
|
||||||
|
|
||||||
|
if (context->ServerFormatDataRequest)
|
||||||
|
context->ServerFormatDataRequest(context, &formatDataRequest);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
RDP_CB_DATA_REQUEST_EVENT* cb_event;
|
RDP_CB_DATA_REQUEST_EVENT* cb_event;
|
||||||
|
|
||||||
@ -328,6 +430,7 @@ void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UIN
|
|||||||
Stream_Read_UINT32(s, cb_event->format);
|
Stream_Read_UINT32(s, cb_event->format);
|
||||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_RESPONSE_EVENT* cb_event)
|
void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_RESPONSE_EVENT* cb_event)
|
||||||
{
|
{
|
||||||
@ -360,6 +463,30 @@ void cliprdr_process_format_data_request_event(cliprdrPlugin* cliprdr, RDP_CB_DA
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
||||||
|
{
|
||||||
|
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||||
|
|
||||||
|
if (context->custom)
|
||||||
|
{
|
||||||
|
CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse;
|
||||||
|
|
||||||
|
formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE;
|
||||||
|
formatDataResponse.msgFlags = msgFlags;
|
||||||
|
formatDataResponse.dataLen = dataLen;
|
||||||
|
formatDataResponse.requestedFormatData = NULL;
|
||||||
|
|
||||||
|
if (dataLen)
|
||||||
|
{
|
||||||
|
formatDataResponse.requestedFormatData = (BYTE*) malloc(dataLen);
|
||||||
|
Stream_Read(s, formatDataResponse.requestedFormatData, dataLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->ClientFormatDataResponse)
|
||||||
|
context->ClientFormatDataResponse(context, &formatDataResponse);
|
||||||
|
|
||||||
|
free(formatDataResponse.requestedFormatData);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
RDP_CB_DATA_RESPONSE_EVENT* cb_event;
|
RDP_CB_DATA_RESPONSE_EVENT* cb_event;
|
||||||
|
|
||||||
@ -375,3 +502,4 @@ void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UI
|
|||||||
|
|
||||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -53,6 +53,14 @@ static const char* const CB_MSG_TYPE_STRINGS[] =
|
|||||||
"CB_UNLOCK_CLIPDATA"
|
"CB_UNLOCK_CLIPDATA"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr)
|
||||||
|
{
|
||||||
|
CliprdrClientContext* pInterface;
|
||||||
|
rdpSvcPlugin* plugin = (rdpSvcPlugin*) cliprdr;
|
||||||
|
pInterface = (CliprdrClientContext*) plugin->channel_entry_points.pInterface;
|
||||||
|
return pInterface;
|
||||||
|
}
|
||||||
|
|
||||||
wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen)
|
wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen)
|
||||||
{
|
{
|
||||||
wStream* s;
|
wStream* s;
|
||||||
@ -110,7 +118,9 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
|
|||||||
{
|
{
|
||||||
UINT32 version;
|
UINT32 version;
|
||||||
UINT32 generalFlags;
|
UINT32 generalFlags;
|
||||||
RDP_CB_CLIP_CAPS *caps_event;
|
CliprdrClientContext* context;
|
||||||
|
|
||||||
|
context = cliprdr_get_client_interface(cliprdr);
|
||||||
|
|
||||||
Stream_Read_UINT32(s, version); /* version (4 bytes) */
|
Stream_Read_UINT32(s, version); /* version (4 bytes) */
|
||||||
Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
|
Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
|
||||||
@ -121,9 +131,6 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
|
|||||||
cliprdr_print_general_capability_flags(generalFlags);
|
cliprdr_print_general_capability_flags(generalFlags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
caps_event = (RDP_CB_CLIP_CAPS *)freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_ClipCaps, NULL, NULL);
|
|
||||||
caps_event->capabilities = generalFlags;
|
|
||||||
|
|
||||||
if (generalFlags & CB_USE_LONG_FORMAT_NAMES)
|
if (generalFlags & CB_USE_LONG_FORMAT_NAMES)
|
||||||
cliprdr->use_long_format_names = TRUE;
|
cliprdr->use_long_format_names = TRUE;
|
||||||
|
|
||||||
@ -138,8 +145,32 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
|
|||||||
|
|
||||||
cliprdr->received_caps = TRUE;
|
cliprdr->received_caps = TRUE;
|
||||||
|
|
||||||
svc_plugin_send_event((rdpSvcPlugin *)cliprdr, (wMessage *)caps_event);
|
if (context->custom)
|
||||||
|
{
|
||||||
|
CLIPRDR_CAPABILITIES capabilities;
|
||||||
|
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
|
||||||
|
|
||||||
|
capabilities.cCapabilitiesSets = 1;
|
||||||
|
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet);
|
||||||
|
|
||||||
|
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
|
||||||
|
generalCapabilitySet.capabilitySetLength = 12;
|
||||||
|
|
||||||
|
generalCapabilitySet.version = version;
|
||||||
|
generalCapabilitySet.generalFlags = generalFlags;
|
||||||
|
|
||||||
|
if (context->ServerCapabilities)
|
||||||
|
context->ServerCapabilities(context, &capabilities);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RDP_CB_CLIP_CAPS* caps_event;
|
||||||
|
|
||||||
|
caps_event = (RDP_CB_CLIP_CAPS*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_ClipCaps, NULL, NULL);
|
||||||
|
caps_event->capabilities = generalFlags;
|
||||||
|
|
||||||
|
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) caps_event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
|
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
|
||||||
@ -194,6 +225,21 @@ static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
|
static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
|
||||||
|
{
|
||||||
|
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||||
|
|
||||||
|
if (context->custom)
|
||||||
|
{
|
||||||
|
CLIPRDR_MONITOR_READY monitorReady;
|
||||||
|
|
||||||
|
monitorReady.msgType = CB_MONITOR_READY;
|
||||||
|
monitorReady.msgFlags = flags;
|
||||||
|
monitorReady.dataLen = length;
|
||||||
|
|
||||||
|
if (context->MonitorReady)
|
||||||
|
context->MonitorReady(context, &monitorReady);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
RDP_CB_MONITOR_READY_EVENT* event;
|
RDP_CB_MONITOR_READY_EVENT* event;
|
||||||
|
|
||||||
@ -204,6 +250,7 @@ static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UI
|
|||||||
|
|
||||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) event);
|
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
|
static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
|
||||||
{
|
{
|
||||||
@ -290,23 +337,127 @@ static void cliprdr_process_terminate(rdpSvcPlugin* plugin)
|
|||||||
* Callback Interface
|
* Callback Interface
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int cliprdr_monitor_ready(CliprdrClientContext* context)
|
int 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);
|
||||||
|
|
||||||
|
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 */
|
||||||
|
Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */
|
||||||
|
Stream_Write_UINT32(s, generalCapabilitySet->generalFlags); /* generalFlags */
|
||||||
|
|
||||||
|
cliprdr_packet_send(cliprdr, s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cliprdr_format_list(CliprdrClientContext* context)
|
int cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList)
|
||||||
{
|
{
|
||||||
|
int index;
|
||||||
|
wStream* s;
|
||||||
|
int length = 0;
|
||||||
|
int formatNameSize;
|
||||||
|
CLIPRDR_FORMAT* format;
|
||||||
|
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||||
|
|
||||||
|
for (index = 0; index < formatList->cFormats; 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;
|
||||||
|
|
||||||
|
length += formatNameSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length);
|
||||||
|
|
||||||
|
for (index = 0; index < formatList->cFormats; index++)
|
||||||
|
{
|
||||||
|
format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
|
||||||
|
|
||||||
|
Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */
|
||||||
|
|
||||||
|
if (format->formatName)
|
||||||
|
{
|
||||||
|
int cchWideChar;
|
||||||
|
LPWSTR lpWideCharStr;
|
||||||
|
|
||||||
|
lpWideCharStr = (LPWSTR) Stream_Pointer(s);
|
||||||
|
cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2;
|
||||||
|
|
||||||
|
formatNameSize = MultiByteToWideChar(CP_UTF8, 0,
|
||||||
|
format->formatName, -1, lpWideCharStr, cchWideChar) * 2;
|
||||||
|
|
||||||
|
Stream_Seek(s, formatNameSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Stream_Write_UINT16(s, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cliprdr_packet_send(cliprdr, s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cliprdr_data_request(CliprdrClientContext* context)
|
int 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);
|
||||||
|
cliprdr_packet_send(cliprdr, s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cliprdr_data_response(CliprdrClientContext* context)
|
int 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);
|
||||||
|
Stream_Write_UINT32(s, formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */
|
||||||
|
|
||||||
|
cliprdr_packet_send(cliprdr, s);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int 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);
|
||||||
|
Stream_Write(s, formatDataResponse->requestedFormatData, formatDataResponse->dataLen);
|
||||||
|
|
||||||
|
cliprdr_packet_send(cliprdr, s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,25 +466,25 @@ int cliprdr_data_response(CliprdrClientContext* context)
|
|||||||
|
|
||||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||||
{
|
{
|
||||||
cliprdrPlugin* _p;
|
cliprdrPlugin* cliprdr;
|
||||||
CliprdrClientContext* context;
|
CliprdrClientContext* context;
|
||||||
CHANNEL_ENTRY_POINTS_EX* pEntryPointsEx;
|
CHANNEL_ENTRY_POINTS_EX* pEntryPointsEx;
|
||||||
|
|
||||||
_p = (cliprdrPlugin*) malloc(sizeof(cliprdrPlugin));
|
cliprdr = (cliprdrPlugin*) malloc(sizeof(cliprdrPlugin));
|
||||||
ZeroMemory(_p, sizeof(cliprdrPlugin));
|
ZeroMemory(cliprdr, sizeof(cliprdrPlugin));
|
||||||
|
|
||||||
_p->plugin.channel_def.options =
|
cliprdr->plugin.channel_def.options =
|
||||||
CHANNEL_OPTION_INITIALIZED |
|
CHANNEL_OPTION_INITIALIZED |
|
||||||
CHANNEL_OPTION_ENCRYPT_RDP |
|
CHANNEL_OPTION_ENCRYPT_RDP |
|
||||||
CHANNEL_OPTION_COMPRESS_RDP |
|
CHANNEL_OPTION_COMPRESS_RDP |
|
||||||
CHANNEL_OPTION_SHOW_PROTOCOL;
|
CHANNEL_OPTION_SHOW_PROTOCOL;
|
||||||
|
|
||||||
strcpy(_p->plugin.channel_def.name, "cliprdr");
|
strcpy(cliprdr->plugin.channel_def.name, "cliprdr");
|
||||||
|
|
||||||
_p->plugin.connect_callback = cliprdr_process_connect;
|
cliprdr->plugin.connect_callback = cliprdr_process_connect;
|
||||||
_p->plugin.receive_callback = cliprdr_process_receive;
|
cliprdr->plugin.receive_callback = cliprdr_process_receive;
|
||||||
_p->plugin.event_callback = cliprdr_process_event;
|
cliprdr->plugin.event_callback = cliprdr_process_event;
|
||||||
_p->plugin.terminate_callback = cliprdr_process_terminate;
|
cliprdr->plugin.terminate_callback = cliprdr_process_terminate;
|
||||||
|
|
||||||
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_EX*) pEntryPoints;
|
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_EX*) pEntryPoints;
|
||||||
|
|
||||||
@ -341,16 +492,20 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
|
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
|
||||||
{
|
{
|
||||||
context = (CliprdrClientContext*) malloc(sizeof(CliprdrClientContext));
|
context = (CliprdrClientContext*) malloc(sizeof(CliprdrClientContext));
|
||||||
|
ZeroMemory(context, sizeof(CliprdrClientContext));
|
||||||
|
|
||||||
context->MonitorReady = cliprdr_monitor_ready;
|
context->handle = (void*) cliprdr;
|
||||||
context->FormatList = cliprdr_format_list;
|
|
||||||
context->DataRequest = cliprdr_data_request;
|
context->ClientCapabilities = cliprdr_client_capabilities;
|
||||||
context->DataResponse = cliprdr_data_response;
|
context->ClientFormatList = cliprdr_client_format_list;
|
||||||
|
context->ClientFormatListResponse = cliprdr_client_format_list_response;
|
||||||
|
context->ClientFormatDataRequest = cliprdr_client_format_data_request;
|
||||||
|
context->ClientFormatDataResponse = cliprdr_client_format_data_response;
|
||||||
|
|
||||||
*(pEntryPointsEx->ppInterface) = (void*) context;
|
*(pEntryPointsEx->ppInterface) = (void*) context;
|
||||||
}
|
}
|
||||||
|
|
||||||
svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints);
|
svc_plugin_init((rdpSvcPlugin*) cliprdr, pEntryPoints);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,8 @@ typedef struct cliprdr_plugin cliprdrPlugin;
|
|||||||
wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen);
|
wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen);
|
||||||
void cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* data_out);
|
void cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* data_out);
|
||||||
|
|
||||||
|
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr);
|
||||||
|
|
||||||
#ifdef WITH_DEBUG_CLIPRDR
|
#ifdef WITH_DEBUG_CLIPRDR
|
||||||
#define DEBUG_CLIPRDR(fmt, ...) DEBUG_CLASS(CLIPRDR, fmt, ## __VA_ARGS__)
|
#define DEBUG_CLIPRDR(fmt, ...) DEBUG_CLASS(CLIPRDR, fmt, ## __VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
|
@ -28,14 +28,6 @@
|
|||||||
|
|
||||||
#define CLIPRDR_HEADER_LENGTH 8
|
#define CLIPRDR_HEADER_LENGTH 8
|
||||||
|
|
||||||
struct _CLIPRDR_HEADER
|
|
||||||
{
|
|
||||||
UINT16 msgType;
|
|
||||||
UINT16 msgFlags;
|
|
||||||
UINT32 dataLen;
|
|
||||||
};
|
|
||||||
typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER;
|
|
||||||
|
|
||||||
struct _cliprdr_server_private
|
struct _cliprdr_server_private
|
||||||
{
|
{
|
||||||
HANDLE Thread;
|
HANDLE Thread;
|
||||||
|
@ -42,7 +42,7 @@ RailClientContext* rail_get_client_interface(void* railObject)
|
|||||||
{
|
{
|
||||||
RailClientContext* pInterface;
|
RailClientContext* pInterface;
|
||||||
rdpSvcPlugin* plugin = (rdpSvcPlugin*) railObject;
|
rdpSvcPlugin* plugin = (rdpSvcPlugin*) railObject;
|
||||||
pInterface = (RailClientContext*) *(plugin->channel_entry_points.ppInterface);
|
pInterface = (RailClientContext*) plugin->channel_entry_points.pInterface;
|
||||||
return pInterface;
|
return pInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,25 +503,25 @@ int rail_server_get_appid_response(RailClientContext* context, RAIL_GET_APPID_RE
|
|||||||
|
|
||||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||||
{
|
{
|
||||||
railPlugin* _p;
|
railPlugin* rail;
|
||||||
RailClientContext* context;
|
RailClientContext* context;
|
||||||
CHANNEL_ENTRY_POINTS_EX* pEntryPointsEx;
|
CHANNEL_ENTRY_POINTS_EX* pEntryPointsEx;
|
||||||
|
|
||||||
_p = (railPlugin*) malloc(sizeof(railPlugin));
|
rail = (railPlugin*) malloc(sizeof(railPlugin));
|
||||||
ZeroMemory(_p, sizeof(railPlugin));
|
ZeroMemory(rail, sizeof(railPlugin));
|
||||||
|
|
||||||
_p->plugin.channel_def.options =
|
rail->plugin.channel_def.options =
|
||||||
CHANNEL_OPTION_INITIALIZED |
|
CHANNEL_OPTION_INITIALIZED |
|
||||||
CHANNEL_OPTION_ENCRYPT_RDP |
|
CHANNEL_OPTION_ENCRYPT_RDP |
|
||||||
CHANNEL_OPTION_COMPRESS_RDP |
|
CHANNEL_OPTION_COMPRESS_RDP |
|
||||||
CHANNEL_OPTION_SHOW_PROTOCOL;
|
CHANNEL_OPTION_SHOW_PROTOCOL;
|
||||||
|
|
||||||
strcpy(_p->plugin.channel_def.name, "rail");
|
strcpy(rail->plugin.channel_def.name, "rail");
|
||||||
|
|
||||||
_p->plugin.connect_callback = rail_process_connect;
|
rail->plugin.connect_callback = rail_process_connect;
|
||||||
_p->plugin.receive_callback = rail_process_receive;
|
rail->plugin.receive_callback = rail_process_receive;
|
||||||
_p->plugin.event_callback = rail_process_event;
|
rail->plugin.event_callback = rail_process_event;
|
||||||
_p->plugin.terminate_callback = rail_process_terminate;
|
rail->plugin.terminate_callback = rail_process_terminate;
|
||||||
|
|
||||||
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_EX*) pEntryPoints;
|
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_EX*) pEntryPoints;
|
||||||
|
|
||||||
@ -530,7 +530,7 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
{
|
{
|
||||||
context = (RailClientContext*) malloc(sizeof(RailClientContext));
|
context = (RailClientContext*) malloc(sizeof(RailClientContext));
|
||||||
|
|
||||||
context->handle = (void*) _p;
|
context->handle = (void*) rail;
|
||||||
|
|
||||||
context->ClientExecute = rail_client_execute;
|
context->ClientExecute = rail_client_execute;
|
||||||
context->ClientActivate = rail_client_activate;
|
context->ClientActivate = rail_client_activate;
|
||||||
@ -557,11 +557,11 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
}
|
}
|
||||||
|
|
||||||
WLog_Init();
|
WLog_Init();
|
||||||
_p->log = WLog_Get("com.freerdp.channels.rail.client");
|
rail->log = WLog_Get("com.freerdp.channels.rail.client");
|
||||||
|
|
||||||
WLog_Print(_p->log, WLOG_DEBUG, "VirtualChannelEntry");
|
WLog_Print(rail->log, WLOG_DEBUG, "VirtualChannelEntry");
|
||||||
|
|
||||||
svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints);
|
svc_plugin_init((rdpSvcPlugin*) rail, pEntryPoints);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Use AudioQueue to implement audio redirection
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
@ -40,163 +36,242 @@
|
|||||||
|
|
||||||
#include "rdpsnd_main.h"
|
#include "rdpsnd_main.h"
|
||||||
|
|
||||||
#define AQ_NUM_BUFFERS 10
|
#define MAC_AUDIO_QUEUE_NUM_BUFFERS 10
|
||||||
#define AQ_BUF_SIZE (32 * 1024)
|
#define MAC_AUDIO_QUEUE_BUFFER_SIZE 32768
|
||||||
|
|
||||||
static void aq_playback_cb(void *user_data,
|
struct rdpsnd_mac_plugin
|
||||||
AudioQueueRef aq_ref,
|
|
||||||
AudioQueueBufferRef aq_buf_ref
|
|
||||||
);
|
|
||||||
|
|
||||||
struct rdpsnd_audio_q_plugin
|
|
||||||
{
|
{
|
||||||
rdpsndDevicePlugin device;
|
rdpsndDevicePlugin device;
|
||||||
|
|
||||||
/* audio queue player state */
|
BOOL isOpen;
|
||||||
int is_open; // true when audio_q has been inited
|
BOOL isPlaying;
|
||||||
char * device_name;
|
|
||||||
int is_playing;
|
|
||||||
int buf_index;
|
|
||||||
|
|
||||||
AudioStreamBasicDescription data_format;
|
UINT32 latency;
|
||||||
AudioQueueRef aq_ref;
|
AUDIO_FORMAT format;
|
||||||
AudioQueueBufferRef buffers[AQ_NUM_BUFFERS];
|
int audioBufferIndex;
|
||||||
|
|
||||||
|
AudioQueueRef audioQueue;
|
||||||
|
AudioStreamBasicDescription audioFormat;
|
||||||
|
AudioQueueBufferRef audioBuffers[MAC_AUDIO_QUEUE_NUM_BUFFERS];
|
||||||
};
|
};
|
||||||
typedef struct rdpsnd_audio_q_plugin rdpsndAudioQPlugin;
|
typedef struct rdpsnd_mac_plugin rdpsndMacPlugin;
|
||||||
|
|
||||||
static void rdpsnd_audio_close(rdpsndDevicePlugin* device)
|
static void mac_audio_queue_output_cb(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
|
||||||
{
|
{
|
||||||
rdpsndAudioQPlugin* aq_plugin_p = (rdpsndAudioQPlugin*) device;
|
|
||||||
|
|
||||||
AudioQueueStop(aq_plugin_p->aq_ref, 0);
|
|
||||||
aq_plugin_p->is_open = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rdpsnd_audio_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
|
static void rdpsnd_mac_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
|
||||||
{
|
{
|
||||||
int rv;
|
rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device;
|
||||||
int i;
|
|
||||||
|
|
||||||
rdpsndAudioQPlugin* aq_plugin_p = (rdpsndAudioQPlugin *) device;
|
mac->latency = (UINT32) latency;
|
||||||
if (aq_plugin_p->is_open) {
|
CopyMemory(&(mac->format), format, sizeof(AUDIO_FORMAT));
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
aq_plugin_p->buf_index = 0;
|
|
||||||
|
|
||||||
// setup AudioStreamBasicDescription
|
|
||||||
aq_plugin_p->data_format.mSampleRate = 44100;
|
|
||||||
aq_plugin_p->data_format.mFormatID = kAudioFormatLinearPCM;
|
|
||||||
aq_plugin_p->data_format.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
|
|
||||||
|
|
||||||
// until we know better, assume that one packet = one frame
|
|
||||||
// one frame = bytes_per_sample x number_of_channels
|
|
||||||
aq_plugin_p->data_format.mBytesPerPacket = 4;
|
|
||||||
aq_plugin_p->data_format.mFramesPerPacket = 1;
|
|
||||||
aq_plugin_p->data_format.mBytesPerFrame = 4;
|
|
||||||
aq_plugin_p->data_format.mChannelsPerFrame = 2;
|
|
||||||
aq_plugin_p->data_format.mBitsPerChannel = 16;
|
|
||||||
|
|
||||||
rv = AudioQueueNewOutput(
|
|
||||||
&aq_plugin_p->data_format, // audio stream basic desc
|
|
||||||
aq_playback_cb, // callback when more data is required
|
|
||||||
aq_plugin_p, // data to pass to callback
|
|
||||||
CFRunLoopGetCurrent(), // The current run loop, and the one on
|
|
||||||
// which the audio queue playback callback
|
|
||||||
// will be invoked
|
|
||||||
kCFRunLoopCommonModes, // run loop modes in which callbacks can
|
|
||||||
// be invoked
|
|
||||||
0, // flags - reserved
|
|
||||||
&aq_plugin_p->aq_ref
|
|
||||||
);
|
|
||||||
if (rv != 0) {
|
|
||||||
fprintf(stderr, "rdpsnd_audio_open: AudioQueueNewOutput() failed with error %d\n", rv);
|
|
||||||
aq_plugin_p->is_open = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < AQ_NUM_BUFFERS; i++)
|
|
||||||
{
|
|
||||||
rv = AudioQueueAllocateBuffer(aq_plugin_p->aq_ref, AQ_BUF_SIZE, &aq_plugin_p->buffers[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
aq_plugin_p->is_open = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rdpsnd_audio_free(rdpsndDevicePlugin* device)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL rdpsnd_audio_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format)
|
|
||||||
{
|
|
||||||
switch (format->wFormatTag)
|
switch (format->wFormatTag)
|
||||||
{
|
{
|
||||||
case 1: /* PCM */
|
case WAVE_FORMAT_ALAW:
|
||||||
if (format->cbSize == 0 &&
|
mac->audioFormat.mFormatID = kAudioFormatALaw;
|
||||||
(format->nSamplesPerSec <= 48000) &&
|
break;
|
||||||
(format->wBitsPerSample == 8 || format->wBitsPerSample == 16) &&
|
|
||||||
(format->nChannels == 1 || format->nChannels == 2))
|
case WAVE_FORMAT_MULAW:
|
||||||
{
|
mac->audioFormat.mFormatID = kAudioFormatULaw;
|
||||||
return 1;
|
break;
|
||||||
}
|
|
||||||
|
case WAVE_FORMAT_PCM:
|
||||||
|
mac->audioFormat.mFormatID = kAudioFormatLinearPCM;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WAVE_FORMAT_GSM610:
|
||||||
|
mac->audioFormat.mFormatID = kAudioFormatMicrosoftGSM;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
mac->audioFormat.mSampleRate = format->nSamplesPerSec;
|
||||||
|
mac->audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||||
|
mac->audioFormat.mFramesPerPacket = 1;
|
||||||
|
mac->audioFormat.mChannelsPerFrame = format->nChannels;
|
||||||
|
mac->audioFormat.mBitsPerChannel = format->wBitsPerSample;
|
||||||
|
mac->audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8;
|
||||||
|
mac->audioFormat.mBytesPerPacket = format->nBlockAlign;
|
||||||
|
mac->audioFormat.mReserved = 0;
|
||||||
|
|
||||||
|
rdpsnd_print_audio_format(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rdpsnd_audio_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
|
static void rdpsnd_mac_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
|
||||||
{
|
{
|
||||||
}
|
int index;
|
||||||
|
OSStatus status;
|
||||||
|
|
||||||
static void rdpsnd_audio_set_volume(rdpsndDevicePlugin* device, UINT32 value)
|
rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device;
|
||||||
|
|
||||||
|
if (mac->isOpen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mac->audioBufferIndex = 0;
|
||||||
|
|
||||||
|
device->SetFormat(device, format, 0);
|
||||||
|
|
||||||
|
status = AudioQueueNewOutput(&(mac->audioFormat),
|
||||||
|
mac_audio_queue_output_cb, mac,
|
||||||
|
NULL, NULL, 0, &(mac->audioQueue));
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
{
|
{
|
||||||
}
|
fprintf(stderr, "AudioQueueNewOutput failure\n");
|
||||||
|
|
||||||
static void rdpsnd_audio_play(rdpsndDevicePlugin* device, BYTE* data, int size)
|
|
||||||
{
|
|
||||||
rdpsndAudioQPlugin* aq_plugin_p = (rdpsndAudioQPlugin *) device;
|
|
||||||
AudioQueueBufferRef aq_buf_ref;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (!aq_plugin_p->is_open) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get next empty buffer */
|
UInt32 DecodeBufferSizeFrames;
|
||||||
aq_buf_ref = aq_plugin_p->buffers[aq_plugin_p->buf_index];
|
UInt32 propertySize = sizeof(DecodeBufferSizeFrames);
|
||||||
|
|
||||||
// fill aq_buf_ref with audio data
|
AudioQueueGetProperty(mac->audioQueue,
|
||||||
len = size > AQ_BUF_SIZE ? AQ_BUF_SIZE : size;
|
kAudioQueueProperty_DecodeBufferSizeFrames,
|
||||||
|
&DecodeBufferSizeFrames,
|
||||||
|
&propertySize);
|
||||||
|
|
||||||
memcpy(aq_buf_ref->mAudioData, (char *) data, len);
|
if (status != 0)
|
||||||
aq_buf_ref->mAudioDataByteSize = len;
|
|
||||||
|
|
||||||
// add buffer to audioqueue
|
|
||||||
AudioQueueEnqueueBuffer(aq_plugin_p->aq_ref, aq_buf_ref, 0, 0);
|
|
||||||
|
|
||||||
// update buf_index
|
|
||||||
aq_plugin_p->buf_index++;
|
|
||||||
if (aq_plugin_p->buf_index >= AQ_NUM_BUFFERS) {
|
|
||||||
aq_plugin_p->buf_index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rdpsnd_audio_start(rdpsndDevicePlugin* device)
|
|
||||||
{
|
{
|
||||||
rdpsndAudioQPlugin* aq_plugin_p = (rdpsndAudioQPlugin *) device;
|
printf("AudioQueueGetProperty failure: kAudioQueueProperty_DecodeBufferSizeFrames\n");
|
||||||
|
|
||||||
AudioQueueStart(aq_plugin_p->aq_ref, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
for (index = 0; index < MAC_AUDIO_QUEUE_NUM_BUFFERS; index++)
|
||||||
* AudioQueue Playback callback
|
|
||||||
*
|
|
||||||
* our job here is to fill aq_buf_ref with audio data and enqueue it
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void aq_playback_cb(void* user_data, AudioQueueRef aq_ref, AudioQueueBufferRef aq_buf_ref)
|
|
||||||
{
|
{
|
||||||
|
status = AudioQueueAllocateBuffer(mac->audioQueue, MAC_AUDIO_QUEUE_BUFFER_SIZE, &mac->audioBuffers[index]);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "AudioQueueAllocateBuffer failed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mac->isOpen = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rdpsnd_mac_close(rdpsndDevicePlugin* device)
|
||||||
|
{
|
||||||
|
rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device;
|
||||||
|
|
||||||
|
if (mac->isOpen)
|
||||||
|
{
|
||||||
|
mac->isOpen = FALSE;
|
||||||
|
|
||||||
|
AudioQueueStop(mac->audioQueue, true);
|
||||||
|
|
||||||
|
AudioQueueDispose(mac->audioQueue, true);
|
||||||
|
mac->audioQueue = NULL;
|
||||||
|
|
||||||
|
mac->isPlaying = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rdpsnd_mac_free(rdpsndDevicePlugin* device)
|
||||||
|
{
|
||||||
|
rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device;
|
||||||
|
|
||||||
|
device->Close(device);
|
||||||
|
|
||||||
|
free(mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL rdpsnd_mac_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format)
|
||||||
|
{
|
||||||
|
if (format->wFormatTag == WAVE_FORMAT_PCM)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (format->wFormatTag == WAVE_FORMAT_ALAW)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (format->wFormatTag == WAVE_FORMAT_MULAW)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (format->wFormatTag == WAVE_FORMAT_GSM610)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rdpsnd_mac_set_volume(rdpsndDevicePlugin* device, UINT32 value)
|
||||||
|
{
|
||||||
|
OSStatus status;
|
||||||
|
Float32 fVolume;
|
||||||
|
UINT16 volumeLeft;
|
||||||
|
UINT16 volumeRight;
|
||||||
|
rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device;
|
||||||
|
|
||||||
|
if (!mac->audioQueue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
volumeLeft = (value & 0xFFFF);
|
||||||
|
volumeRight = ((value >> 16) & 0xFFFF);
|
||||||
|
|
||||||
|
fVolume = ((float) volumeLeft) / 65535.0;
|
||||||
|
|
||||||
|
status = AudioQueueSetParameter(mac->audioQueue, kAudioQueueParam_Volume, fVolume);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "AudioQueueSetParameter kAudioQueueParam_Volume failed: %f\n", fVolume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rdpsnd_mac_start(rdpsndDevicePlugin* device)
|
||||||
|
{
|
||||||
|
rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device;
|
||||||
|
|
||||||
|
if (!mac->isPlaying)
|
||||||
|
{
|
||||||
|
OSStatus status;
|
||||||
|
|
||||||
|
if (!mac->audioQueue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
status = AudioQueueStart(mac->audioQueue, NULL);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "AudioQueueStart failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
mac->isPlaying = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rdpsnd_mac_play(rdpsndDevicePlugin* device, BYTE* data, int size)
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
AudioQueueBufferRef audioBuffer;
|
||||||
|
rdpsndMacPlugin* mac = (rdpsndMacPlugin*) device;
|
||||||
|
|
||||||
|
if (!mac->isOpen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
audioBuffer = mac->audioBuffers[mac->audioBufferIndex];
|
||||||
|
|
||||||
|
length = size > audioBuffer->mAudioDataBytesCapacity ? audioBuffer->mAudioDataBytesCapacity : size;
|
||||||
|
|
||||||
|
CopyMemory(audioBuffer->mAudioData, data, length);
|
||||||
|
audioBuffer->mAudioDataByteSize = length;
|
||||||
|
|
||||||
|
AudioQueueEnqueueBuffer(mac->audioQueue, audioBuffer, 0, 0);
|
||||||
|
|
||||||
|
mac->audioBufferIndex++;
|
||||||
|
|
||||||
|
if (mac->audioBufferIndex >= MAC_AUDIO_QUEUE_NUM_BUFFERS)
|
||||||
|
{
|
||||||
|
mac->audioBufferIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
device->Start(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef STATIC_CHANNELS
|
#ifdef STATIC_CHANNELS
|
||||||
@ -205,31 +280,25 @@ static void aq_playback_cb(void* user_data, AudioQueueRef aq_ref, AudioQueueBuff
|
|||||||
|
|
||||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "freerdp_rdpsnd_client_subsystem_entry()\n\n");
|
rdpsndMacPlugin* mac;
|
||||||
|
|
||||||
ADDIN_ARGV* args;
|
mac = (rdpsndMacPlugin*) malloc(sizeof(rdpsndMacPlugin));
|
||||||
rdpsndAudioQPlugin* aqPlugin;
|
|
||||||
|
|
||||||
aqPlugin = (rdpsndAudioQPlugin*) malloc(sizeof(rdpsndAudioQPlugin));
|
if (mac)
|
||||||
ZeroMemory(aqPlugin, sizeof(rdpsndAudioQPlugin));
|
|
||||||
|
|
||||||
aqPlugin->device.Open = rdpsnd_audio_open;
|
|
||||||
aqPlugin->device.FormatSupported = rdpsnd_audio_format_supported;
|
|
||||||
aqPlugin->device.SetFormat = rdpsnd_audio_set_format;
|
|
||||||
aqPlugin->device.SetVolume = rdpsnd_audio_set_volume;
|
|
||||||
aqPlugin->device.Play = rdpsnd_audio_play;
|
|
||||||
aqPlugin->device.Start = rdpsnd_audio_start;
|
|
||||||
aqPlugin->device.Close = rdpsnd_audio_close;
|
|
||||||
aqPlugin->device.Free = rdpsnd_audio_free;
|
|
||||||
|
|
||||||
args = pEntryPoints->args;
|
|
||||||
|
|
||||||
if (args->argc > 2)
|
|
||||||
{
|
{
|
||||||
/* TODO: parse device name */
|
ZeroMemory(mac, sizeof(rdpsndMacPlugin));
|
||||||
}
|
|
||||||
|
|
||||||
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) aqPlugin);
|
mac->device.Open = rdpsnd_mac_open;
|
||||||
|
mac->device.FormatSupported = rdpsnd_mac_format_supported;
|
||||||
|
mac->device.SetFormat = rdpsnd_mac_set_format;
|
||||||
|
mac->device.SetVolume = rdpsnd_mac_set_volume;
|
||||||
|
mac->device.Play = rdpsnd_mac_play;
|
||||||
|
mac->device.Start = rdpsnd_mac_start;
|
||||||
|
mac->device.Close = rdpsnd_mac_close;
|
||||||
|
mac->device.Free = rdpsnd_mac_free;
|
||||||
|
|
||||||
|
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,11 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
|||||||
MODULE freerdp
|
MODULE freerdp
|
||||||
MODULES freerdp-codec freerdp-utils)
|
MODULES freerdp-codec freerdp-utils)
|
||||||
|
|
||||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
|
list(APPEND ${MODULE_PREFIX}_LIBS ${PULSE_LIBRARY})
|
||||||
|
|
||||||
|
if(GSM_FOUND)
|
||||||
|
list(APPEND ${MODULE_PREFIX}_LIBS ${GSM_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||||
|
|
||||||
|
@ -26,10 +26,15 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/stream.h>
|
||||||
#include <winpr/cmdline.h>
|
#include <winpr/cmdline.h>
|
||||||
|
|
||||||
#include <pulse/pulseaudio.h>
|
#include <pulse/pulseaudio.h>
|
||||||
|
|
||||||
|
#ifdef WITH_GSM
|
||||||
|
#include <gsm/gsm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <freerdp/types.h>
|
#include <freerdp/types.h>
|
||||||
#include <freerdp/codec/dsp.h>
|
#include <freerdp/codec/dsp.h>
|
||||||
#include <freerdp/utils/svc_plugin.h>
|
#include <freerdp/utils/svc_plugin.h>
|
||||||
@ -52,6 +57,11 @@ struct rdpsnd_pulse_plugin
|
|||||||
int latency;
|
int latency;
|
||||||
|
|
||||||
FREERDP_DSP_CONTEXT* dsp_context;
|
FREERDP_DSP_CONTEXT* dsp_context;
|
||||||
|
|
||||||
|
#ifdef WITH_GSM
|
||||||
|
gsm gsm_context;
|
||||||
|
wStream* gsmBuffer;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static void rdpsnd_pulse_context_state_callback(pa_context* context, void* userdata)
|
static void rdpsnd_pulse_context_state_callback(pa_context* context, void* userdata)
|
||||||
@ -241,6 +251,7 @@ static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, AUDIO_FORMAT*
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WAVE_FORMAT_GSM610:
|
case WAVE_FORMAT_GSM610:
|
||||||
|
sample_spec.format = PA_SAMPLE_S16LE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,6 +342,14 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
|
|||||||
if (state == PA_STREAM_READY)
|
if (state == PA_STREAM_READY)
|
||||||
{
|
{
|
||||||
freerdp_dsp_context_reset_adpcm(pulse->dsp_context);
|
freerdp_dsp_context_reset_adpcm(pulse->dsp_context);
|
||||||
|
|
||||||
|
#ifdef WITH_GSM
|
||||||
|
if (pulse->gsm_context)
|
||||||
|
gsm_destroy(pulse->gsm_context);
|
||||||
|
|
||||||
|
pulse->gsm_context = gsm_create();
|
||||||
|
#endif
|
||||||
|
|
||||||
DEBUG_SVC("connected");
|
DEBUG_SVC("connected");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -410,7 +429,18 @@ static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, AUDIO_FORM
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef WITH_GSM
|
||||||
|
case WAVE_FORMAT_GSM610:
|
||||||
|
if ((format->nSamplesPerSec <= PA_RATE_MAX) &&
|
||||||
|
(format->nBlockAlign == 65) && (format->nChannels == 1))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,63 +489,108 @@ static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, UINT32 value)
|
|||||||
pa_threaded_mainloop_unlock(pulse->mainloop);
|
pa_threaded_mainloop_unlock(pulse->mainloop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BYTE* rdpsnd_pulse_convert_audio(rdpsndDevicePlugin* device, BYTE* data, int* size)
|
||||||
|
{
|
||||||
|
BYTE* pcmData = NULL;
|
||||||
|
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
|
||||||
|
|
||||||
|
if (pulse->format == WAVE_FORMAT_ADPCM)
|
||||||
|
{
|
||||||
|
pulse->dsp_context->decode_ms_adpcm(pulse->dsp_context,
|
||||||
|
data, *size, pulse->sample_spec.channels, pulse->block_size);
|
||||||
|
|
||||||
|
*size = pulse->dsp_context->adpcm_size;
|
||||||
|
pcmData = pulse->dsp_context->adpcm_buffer;
|
||||||
|
}
|
||||||
|
else if (pulse->format == WAVE_FORMAT_DVI_ADPCM)
|
||||||
|
{
|
||||||
|
pulse->dsp_context->decode_ima_adpcm(pulse->dsp_context,
|
||||||
|
data, *size, pulse->sample_spec.channels, pulse->block_size);
|
||||||
|
|
||||||
|
*size = pulse->dsp_context->adpcm_size;
|
||||||
|
pcmData = pulse->dsp_context->adpcm_buffer;
|
||||||
|
}
|
||||||
|
#ifdef WITH_GSM
|
||||||
|
else if (pulse->format == WAVE_FORMAT_GSM610)
|
||||||
|
{
|
||||||
|
int inPos = 0;
|
||||||
|
int inSize = *size;
|
||||||
|
UINT16 gsmBlockBuffer[160];
|
||||||
|
|
||||||
|
Stream_SetPosition(pulse->gsmBuffer, 0);
|
||||||
|
|
||||||
|
while (inSize)
|
||||||
|
{
|
||||||
|
ZeroMemory(gsmBlockBuffer, sizeof(gsmBlockBuffer));
|
||||||
|
gsm_decode(pulse->gsm_context, (gsm_byte*) &data[inPos], (gsm_signal*) gsmBlockBuffer);
|
||||||
|
|
||||||
|
if ((inPos % 65) == 0)
|
||||||
|
{
|
||||||
|
inPos += 33;
|
||||||
|
inSize -= 33;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inPos += 32;
|
||||||
|
inSize -= 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream_EnsureRemainingCapacity(pulse->gsmBuffer, 160 * 2);
|
||||||
|
Stream_Write(pulse->gsmBuffer, (void*) gsmBlockBuffer, 160 * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream_SealLength(pulse->gsmBuffer);
|
||||||
|
|
||||||
|
pcmData = Stream_Buffer(pulse->gsmBuffer);
|
||||||
|
*size = Stream_Length(pulse->gsmBuffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pcmData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pcmData;
|
||||||
|
}
|
||||||
|
|
||||||
static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, BYTE* data, int size)
|
static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, BYTE* data, int size)
|
||||||
{
|
{
|
||||||
int len;
|
int length;
|
||||||
int ret;
|
int status;
|
||||||
BYTE* src;
|
BYTE* pcmData;
|
||||||
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
|
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
|
||||||
|
|
||||||
if (!pulse->stream)
|
if (!pulse->stream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pulse->format == WAVE_FORMAT_ADPCM)
|
pcmData = rdpsnd_pulse_convert_audio(device, data, &size);
|
||||||
{
|
|
||||||
pulse->dsp_context->decode_ms_adpcm(pulse->dsp_context,
|
|
||||||
data, size, pulse->sample_spec.channels, pulse->block_size);
|
|
||||||
|
|
||||||
size = pulse->dsp_context->adpcm_size;
|
|
||||||
src = pulse->dsp_context->adpcm_buffer;
|
|
||||||
}
|
|
||||||
else if (pulse->format == WAVE_FORMAT_DVI_ADPCM)
|
|
||||||
{
|
|
||||||
pulse->dsp_context->decode_ima_adpcm(pulse->dsp_context,
|
|
||||||
data, size, pulse->sample_spec.channels, pulse->block_size);
|
|
||||||
|
|
||||||
size = pulse->dsp_context->adpcm_size;
|
|
||||||
src = pulse->dsp_context->adpcm_buffer;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
src = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
pa_threaded_mainloop_lock(pulse->mainloop);
|
pa_threaded_mainloop_lock(pulse->mainloop);
|
||||||
|
|
||||||
while (size > 0)
|
while (size > 0)
|
||||||
{
|
{
|
||||||
while ((len = pa_stream_writable_size(pulse->stream)) == 0)
|
while ((length = pa_stream_writable_size(pulse->stream)) == 0)
|
||||||
{
|
{
|
||||||
pa_threaded_mainloop_wait(pulse->mainloop);
|
pa_threaded_mainloop_wait(pulse->mainloop);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len < 0)
|
if (length < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (len > size)
|
if (length > size)
|
||||||
len = size;
|
length = size;
|
||||||
|
|
||||||
ret = pa_stream_write(pulse->stream, src, len, NULL, 0LL, PA_SEEK_RELATIVE);
|
status = pa_stream_write(pulse->stream, pcmData, length, NULL, 0LL, PA_SEEK_RELATIVE);
|
||||||
|
|
||||||
if (ret < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
DEBUG_WARN("pa_stream_write failed (%d)",
|
DEBUG_WARN("pa_stream_write failed (%d)",
|
||||||
pa_context_errno(pulse->context));
|
pa_context_errno(pulse->context));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
src += len;
|
pcmData += length;
|
||||||
size -= len;
|
size -= length;
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_threaded_mainloop_unlock(pulse->mainloop);
|
pa_threaded_mainloop_unlock(pulse->mainloop);
|
||||||
@ -595,6 +670,10 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
|
|||||||
|
|
||||||
pulse->dsp_context = freerdp_dsp_context_new();
|
pulse->dsp_context = freerdp_dsp_context_new();
|
||||||
|
|
||||||
|
#ifdef WITH_GSM
|
||||||
|
pulse->gsmBuffer = Stream_New(NULL, 4096);
|
||||||
|
#endif
|
||||||
|
|
||||||
pulse->mainloop = pa_threaded_mainloop_new();
|
pulse->mainloop = pa_threaded_mainloop_new();
|
||||||
|
|
||||||
if (!pulse->mainloop)
|
if (!pulse->mainloop)
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/wlog.h>
|
||||||
#include <winpr/synch.h>
|
#include <winpr/synch.h>
|
||||||
#include <winpr/print.h>
|
#include <winpr/print.h>
|
||||||
#include <winpr/thread.h>
|
#include <winpr/thread.h>
|
||||||
@ -62,9 +63,11 @@ struct rdpsnd_plugin
|
|||||||
UINT32 OpenHandle;
|
UINT32 OpenHandle;
|
||||||
wMessagePipe* MsgPipe;
|
wMessagePipe* MsgPipe;
|
||||||
|
|
||||||
|
wLog* log;
|
||||||
HANDLE ScheduleThread;
|
HANDLE ScheduleThread;
|
||||||
|
|
||||||
BYTE cBlockNo;
|
BYTE cBlockNo;
|
||||||
|
UINT16 wQualityMode;
|
||||||
int wCurrentFormatNo;
|
int wCurrentFormatNo;
|
||||||
|
|
||||||
AUDIO_FORMAT* ServerFormats;
|
AUDIO_FORMAT* ServerFormats;
|
||||||
@ -91,7 +94,7 @@ struct rdpsnd_plugin
|
|||||||
rdpsndDevicePlugin* device;
|
rdpsndDevicePlugin* device;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE cConfirmedBlockNo);
|
static void rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave);
|
||||||
|
|
||||||
static void* rdpsnd_schedule_thread(void* arg)
|
static void* rdpsnd_schedule_thread(void* arg)
|
||||||
{
|
{
|
||||||
@ -123,9 +126,10 @@ static void* rdpsnd_schedule_thread(void* arg)
|
|||||||
Sleep(wTimeDiff);
|
Sleep(wTimeDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo);
|
rdpsnd_confirm_wave(rdpsnd, wave);
|
||||||
free(wave);
|
|
||||||
message.wParam = NULL;
|
message.wParam = NULL;
|
||||||
|
free(wave);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -139,9 +143,11 @@ void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
|
|||||||
Stream_Write_UINT8(pdu, SNDC_QUALITYMODE); /* msgType */
|
Stream_Write_UINT8(pdu, SNDC_QUALITYMODE); /* msgType */
|
||||||
Stream_Write_UINT8(pdu, 0); /* bPad */
|
Stream_Write_UINT8(pdu, 0); /* bPad */
|
||||||
Stream_Write_UINT16(pdu, 4); /* BodySize */
|
Stream_Write_UINT16(pdu, 4); /* BodySize */
|
||||||
Stream_Write_UINT16(pdu, HIGH_QUALITY); /* wQualityMode */
|
Stream_Write_UINT16(pdu, rdpsnd->wQualityMode); /* wQualityMode */
|
||||||
Stream_Write_UINT16(pdu, 0); /* Reserved */
|
Stream_Write_UINT16(pdu, 0); /* Reserved */
|
||||||
|
|
||||||
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "QualityMode: %d", rdpsnd->wQualityMode);
|
||||||
|
|
||||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,6 +264,8 @@ void rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
|
|||||||
Stream_Write(pdu, clientFormat->data, clientFormat->cbSize);
|
Stream_Write(pdu, clientFormat->data, clientFormat->cbSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Client Audio Formats");
|
||||||
|
|
||||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,6 +318,8 @@ void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
|||||||
|
|
||||||
rdpsnd_select_supported_audio_formats(rdpsnd);
|
rdpsnd_select_supported_audio_formats(rdpsnd);
|
||||||
|
|
||||||
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Server Audio Formats");
|
||||||
|
|
||||||
rdpsnd_send_client_audio_formats(rdpsnd);
|
rdpsnd_send_client_audio_formats(rdpsnd);
|
||||||
|
|
||||||
if (wVersion >= 6)
|
if (wVersion >= 6)
|
||||||
@ -330,6 +340,9 @@ void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, U
|
|||||||
Stream_Write_UINT16(pdu, wTimeStamp);
|
Stream_Write_UINT16(pdu, wTimeStamp);
|
||||||
Stream_Write_UINT16(pdu, wPackSize);
|
Stream_Write_UINT16(pdu, wPackSize);
|
||||||
|
|
||||||
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Training Response: wTimeStamp: %d wPackSize: %d",
|
||||||
|
wTimeStamp, wPackSize);
|
||||||
|
|
||||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,6 +354,9 @@ static void rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
|||||||
Stream_Read_UINT16(s, wTimeStamp);
|
Stream_Read_UINT16(s, wTimeStamp);
|
||||||
Stream_Read_UINT16(s, wPackSize);
|
Stream_Read_UINT16(s, wPackSize);
|
||||||
|
|
||||||
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Training Request: wTimeStamp: %d wPackSize: %d",
|
||||||
|
wTimeStamp, wPackSize);
|
||||||
|
|
||||||
rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize);
|
rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,6 +377,9 @@ static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s, UINT16 B
|
|||||||
|
|
||||||
format = &rdpsnd->ClientFormats[wFormatNo];
|
format = &rdpsnd->ClientFormats[wFormatNo];
|
||||||
|
|
||||||
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveInfo: cBlockNo: %d wFormatNo: %d",
|
||||||
|
rdpsnd->cBlockNo, wFormatNo);
|
||||||
|
|
||||||
if (!rdpsnd->isOpen)
|
if (!rdpsnd->isOpen)
|
||||||
{
|
{
|
||||||
rdpsnd->isOpen = TRUE;
|
rdpsnd->isOpen = TRUE;
|
||||||
@ -399,8 +418,19 @@ void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE
|
|||||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void 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);
|
||||||
|
|
||||||
|
rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo);
|
||||||
|
}
|
||||||
|
|
||||||
static void rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
static void rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
||||||
{
|
{
|
||||||
|
if (device->DisableConfirmThread)
|
||||||
|
rdpsnd_confirm_wave(device->rdpsnd, wave);
|
||||||
|
else
|
||||||
MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave, NULL);
|
MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,12 +464,19 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
|||||||
|
|
||||||
wave->data = data;
|
wave->data = data;
|
||||||
wave->length = size;
|
wave->length = size;
|
||||||
|
wave->AutoConfirm = TRUE;
|
||||||
|
|
||||||
format = &rdpsnd->ClientFormats[rdpsnd->wCurrentFormatNo];
|
format = &rdpsnd->ClientFormats[rdpsnd->wCurrentFormatNo];
|
||||||
wave->wAudioLength = rdpsnd_compute_audio_time_length(format, size);
|
wave->wAudioLength = rdpsnd_compute_audio_time_length(format, size);
|
||||||
|
|
||||||
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Wave: cBlockNo: %d wTimeStamp: %d",
|
||||||
|
wave->cBlockNo, wave->wTimeStampA);
|
||||||
|
|
||||||
if (!rdpsnd->device)
|
if (!rdpsnd->device)
|
||||||
{
|
{
|
||||||
|
wave->wLocalTimeB = wave->wLocalTimeA;
|
||||||
|
wave->wTimeStampB = wave->wTimeStampA;
|
||||||
|
rdpsnd_confirm_wave(rdpsnd, wave);
|
||||||
free(wave);
|
free(wave);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -463,11 +500,15 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
|||||||
wave->wTimeStampB = rdpsnd->wTimeStamp + wave->wAudioLength + TIME_DELAY_MS;
|
wave->wTimeStampB = rdpsnd->wTimeStamp + wave->wAudioLength + TIME_DELAY_MS;
|
||||||
wave->wLocalTimeB = wave->wLocalTimeA + wave->wAudioLength + TIME_DELAY_MS;
|
wave->wLocalTimeB = wave->wLocalTimeA + wave->wAudioLength + TIME_DELAY_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wave->AutoConfirm)
|
||||||
rdpsnd->device->WaveConfirm(rdpsnd->device, wave);
|
rdpsnd->device->WaveConfirm(rdpsnd->device, wave);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd)
|
static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd)
|
||||||
{
|
{
|
||||||
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Close");
|
||||||
|
|
||||||
if (rdpsnd->device)
|
if (rdpsnd->device)
|
||||||
{
|
{
|
||||||
IFCALL(rdpsnd->device->Close, rdpsnd->device);
|
IFCALL(rdpsnd->device->Close, rdpsnd->device);
|
||||||
@ -482,6 +523,8 @@ static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
|||||||
|
|
||||||
Stream_Read_UINT32(s, dwVolume);
|
Stream_Read_UINT32(s, dwVolume);
|
||||||
|
|
||||||
|
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Volume: 0x%04X", dwVolume);
|
||||||
|
|
||||||
if (rdpsnd->device)
|
if (rdpsnd->device)
|
||||||
{
|
{
|
||||||
IFCALL(rdpsnd->device->SetVolume, rdpsnd->device, dwVolume);
|
IFCALL(rdpsnd->device->SetVolume, rdpsnd->device, dwVolume);
|
||||||
@ -597,6 +640,7 @@ COMMAND_LINE_ARGUMENT_A rdpsnd_args[] =
|
|||||||
{ "rate", COMMAND_LINE_VALUE_REQUIRED, "<rate>", NULL, NULL, -1, NULL, "rate" },
|
{ "rate", COMMAND_LINE_VALUE_REQUIRED, "<rate>", NULL, NULL, -1, NULL, "rate" },
|
||||||
{ "channel", COMMAND_LINE_VALUE_REQUIRED, "<channel>", NULL, NULL, -1, NULL, "channel" },
|
{ "channel", COMMAND_LINE_VALUE_REQUIRED, "<channel>", NULL, NULL, -1, NULL, "channel" },
|
||||||
{ "latency", COMMAND_LINE_VALUE_REQUIRED, "<latency>", NULL, NULL, -1, NULL, "latency" },
|
{ "latency", COMMAND_LINE_VALUE_REQUIRED, "<latency>", NULL, NULL, -1, NULL, "latency" },
|
||||||
|
{ "quality", COMMAND_LINE_VALUE_REQUIRED, "<quality mode>", NULL, NULL, -1, NULL, "quality mode" },
|
||||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -606,10 +650,13 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
|
|||||||
DWORD flags;
|
DWORD flags;
|
||||||
COMMAND_LINE_ARGUMENT_A* arg;
|
COMMAND_LINE_ARGUMENT_A* arg;
|
||||||
|
|
||||||
|
rdpsnd->wQualityMode = HIGH_QUALITY; /* default quality mode */
|
||||||
|
|
||||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||||
|
|
||||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||||
rdpsnd_args, flags, rdpsnd, NULL, NULL);
|
rdpsnd_args, flags, rdpsnd, NULL, NULL);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -646,6 +693,24 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
|
|||||||
{
|
{
|
||||||
rdpsnd->latency = atoi(arg->Value);
|
rdpsnd->latency = atoi(arg->Value);
|
||||||
}
|
}
|
||||||
|
CommandLineSwitchCase(arg, "quality")
|
||||||
|
{
|
||||||
|
int wQualityMode = DYNAMIC_QUALITY;
|
||||||
|
|
||||||
|
if (_stricmp(arg->Value, "dynamic") == 0)
|
||||||
|
wQualityMode = DYNAMIC_QUALITY;
|
||||||
|
else if (_stricmp(arg->Value, "medium") == 0)
|
||||||
|
wQualityMode = MEDIUM_QUALITY;
|
||||||
|
else if (_stricmp(arg->Value, "high") == 0)
|
||||||
|
wQualityMode = HIGH_QUALITY;
|
||||||
|
else
|
||||||
|
wQualityMode = atoi(arg->Value);
|
||||||
|
|
||||||
|
if ((wQualityMode < 0) || (wQualityMode > 2))
|
||||||
|
wQualityMode = DYNAMIC_QUALITY;
|
||||||
|
|
||||||
|
rdpsnd->wQualityMode = (UINT16) wQualityMode;
|
||||||
|
}
|
||||||
CommandLineSwitchDefault(arg)
|
CommandLineSwitchDefault(arg)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -662,10 +727,6 @@ static void rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
|
|
||||||
rdpsnd->latency = -1;
|
rdpsnd->latency = -1;
|
||||||
|
|
||||||
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
|
|
||||||
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
|
|
||||||
(void*) rdpsnd, 0, NULL);
|
|
||||||
|
|
||||||
args = (ADDIN_ARGV*) rdpsnd->channelEntryPoints.pExtendedData;
|
args = (ADDIN_ARGV*) rdpsnd->channelEntryPoints.pExtendedData;
|
||||||
|
|
||||||
if (args)
|
if (args)
|
||||||
@ -674,7 +735,9 @@ static void rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
if (rdpsnd->subsystem)
|
if (rdpsnd->subsystem)
|
||||||
{
|
{
|
||||||
if (strcmp(rdpsnd->subsystem, "fake") == 0)
|
if (strcmp(rdpsnd->subsystem, "fake") == 0)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||||
}
|
}
|
||||||
@ -718,7 +781,7 @@ static void rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
#if defined(WITH_MACAUDIO)
|
#if defined(WITH_MACAUDIO)
|
||||||
if (!rdpsnd->device)
|
if (!rdpsnd->device)
|
||||||
{
|
{
|
||||||
rdpsnd_set_subsystem(rdpsnd, "macaudio");
|
rdpsnd_set_subsystem(rdpsnd, "mac");
|
||||||
rdpsnd_set_device_name(rdpsnd, "default");
|
rdpsnd_set_device_name(rdpsnd, "default");
|
||||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||||
}
|
}
|
||||||
@ -738,6 +801,13 @@ static void rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
|||||||
DEBUG_WARN("no sound device.");
|
DEBUG_WARN("no sound device.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!rdpsnd->device->DisableConfirmThread)
|
||||||
|
{
|
||||||
|
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
|
||||||
|
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
|
||||||
|
(void*) rdpsnd, 0, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1018,6 +1088,10 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||||||
|
|
||||||
CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, pEntryPoints->cbSize);
|
CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, pEntryPoints->cbSize);
|
||||||
|
|
||||||
|
rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");
|
||||||
|
|
||||||
|
WLog_SetLogLevel(rdpsnd->log, WLOG_TRACE);
|
||||||
|
|
||||||
rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
|
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);
|
||||||
|
|
||||||
|
@ -38,28 +38,16 @@
|
|||||||
|
|
||||||
#include "rdpsnd_main.h"
|
#include "rdpsnd_main.h"
|
||||||
|
|
||||||
typedef struct rdpsnd_winmm_datablock rdpsndWinmmDatablock;
|
|
||||||
|
|
||||||
struct rdpsnd_winmm_datablock
|
|
||||||
{
|
|
||||||
WAVEHDR header;
|
|
||||||
rdpsndWinmmDatablock* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct rdpsnd_winmm_plugin rdpsndWinmmPlugin;
|
typedef struct rdpsnd_winmm_plugin rdpsndWinmmPlugin;
|
||||||
|
|
||||||
struct rdpsnd_winmm_plugin
|
struct rdpsnd_winmm_plugin
|
||||||
{
|
{
|
||||||
rdpsndDevicePlugin device;
|
rdpsndDevicePlugin device;
|
||||||
|
|
||||||
HWAVEOUT out_handle;
|
HWAVEOUT hWaveOut;
|
||||||
WAVEFORMATEX format;
|
WAVEFORMATEX format;
|
||||||
int wformat;
|
int wformat;
|
||||||
int block_size;
|
int block_size;
|
||||||
int latency;
|
|
||||||
HANDLE event;
|
|
||||||
rdpsndWinmmDatablock* datablock_head;
|
|
||||||
|
|
||||||
FREERDP_DSP_CONTEXT* dsp_context;
|
FREERDP_DSP_CONTEXT* dsp_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,25 +80,6 @@ static BOOL rdpsnd_winmm_convert_format(const AUDIO_FORMAT* in, WAVEFORMATEX* ou
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rdpsnd_winmm_clear_datablocks(rdpsndWinmmPlugin* winmm, BOOL drain)
|
|
||||||
{
|
|
||||||
rdpsndWinmmDatablock* datablock;
|
|
||||||
|
|
||||||
while ((datablock = winmm->datablock_head) != NULL)
|
|
||||||
{
|
|
||||||
if (!drain && (datablock->header.dwFlags & WHDR_DONE) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
while ((datablock->header.dwFlags & WHDR_DONE) == 0)
|
|
||||||
WaitForSingleObject(winmm->event, INFINITE);
|
|
||||||
|
|
||||||
winmm->datablock_head = datablock->next;
|
|
||||||
|
|
||||||
free(datablock->header.lpData);
|
|
||||||
free(datablock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rdpsnd_winmm_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
|
static void rdpsnd_winmm_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
|
||||||
{
|
{
|
||||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||||
@ -122,46 +91,93 @@ static void rdpsnd_winmm_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* fo
|
|||||||
winmm->wformat = format->wFormatTag;
|
winmm->wformat = format->wFormatTag;
|
||||||
winmm->block_size = format->nBlockAlign;
|
winmm->block_size = format->nBlockAlign;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
winmm->latency = latency;
|
static void CALLBACK rdpsnd_winmm_callback_function(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
|
||||||
|
{
|
||||||
|
MMRESULT mmResult;
|
||||||
|
RDPSND_WAVE* wave;
|
||||||
|
LPWAVEHDR lpWaveHdr;
|
||||||
|
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) dwInstance;
|
||||||
|
|
||||||
|
switch (uMsg)
|
||||||
|
{
|
||||||
|
case MM_WOM_OPEN:
|
||||||
|
fprintf(stderr, "MM_WOM_OPEN\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MM_WOM_CLOSE:
|
||||||
|
fprintf(stderr, "MM_WOM_CLOSE\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MM_WOM_DONE:
|
||||||
|
{
|
||||||
|
UINT32 wTimeDelta;
|
||||||
|
lpWaveHdr = (LPWAVEHDR) dwParam1;
|
||||||
|
|
||||||
|
if (!lpWaveHdr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wave = (RDPSND_WAVE*) lpWaveHdr->dwUser;
|
||||||
|
|
||||||
|
if (!wave)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fprintf(stderr, "MM_WOM_DONE: dwBufferLength: %d cBlockNo: %d\n",
|
||||||
|
lpWaveHdr->dwBufferLength, wave->cBlockNo);
|
||||||
|
|
||||||
|
wave->wLocalTimeB = GetTickCount();
|
||||||
|
wTimeDelta = wave->wLocalTimeB - wave->wLocalTimeA;
|
||||||
|
wave->wTimeStampB = wave->wTimeStampA + wTimeDelta;
|
||||||
|
|
||||||
|
winmm->device.WaveConfirm(&(winmm->device), wave);
|
||||||
|
|
||||||
|
if (lpWaveHdr->lpData)
|
||||||
|
free(lpWaveHdr->lpData);
|
||||||
|
|
||||||
|
free(wave);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rdpsnd_winmm_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
|
static void rdpsnd_winmm_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
|
||||||
{
|
{
|
||||||
MMRESULT result;
|
MMRESULT mmResult;
|
||||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||||
|
|
||||||
if (winmm->out_handle != NULL)
|
if (winmm->hWaveOut)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DEBUG_SVC("opening");
|
|
||||||
|
|
||||||
rdpsnd_winmm_set_format(device, format, latency);
|
rdpsnd_winmm_set_format(device, format, latency);
|
||||||
freerdp_dsp_context_reset_adpcm(winmm->dsp_context);
|
freerdp_dsp_context_reset_adpcm(winmm->dsp_context);
|
||||||
|
|
||||||
result = waveOutOpen(&winmm->out_handle, WAVE_MAPPER, &winmm->format, (DWORD_PTR) winmm->event, 0, CALLBACK_EVENT);
|
mmResult = waveOutOpen(&winmm->hWaveOut, WAVE_MAPPER, &winmm->format,
|
||||||
|
(DWORD_PTR) rdpsnd_winmm_callback_function, (DWORD_PTR) winmm, CALLBACK_FUNCTION);
|
||||||
|
|
||||||
if (result != MMSYSERR_NOERROR)
|
if (mmResult != MMSYSERR_NOERROR)
|
||||||
{
|
{
|
||||||
DEBUG_WARN("waveOutOpen failed: %d", result);
|
fprintf(stderr, "waveOutOpen failed: %d\n", mmResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rdpsnd_winmm_close(rdpsndDevicePlugin* device)
|
static void rdpsnd_winmm_close(rdpsndDevicePlugin* device)
|
||||||
{
|
{
|
||||||
|
MMRESULT mmResult;
|
||||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||||
|
|
||||||
if (winmm->out_handle)
|
if (winmm->hWaveOut)
|
||||||
{
|
{
|
||||||
DEBUG_SVC("close");
|
mmResult = waveOutReset(winmm->hWaveOut);
|
||||||
rdpsnd_winmm_clear_datablocks(winmm, TRUE);
|
|
||||||
|
|
||||||
if (waveOutClose(winmm->out_handle) != MMSYSERR_NOERROR)
|
mmResult = waveOutClose(winmm->hWaveOut);
|
||||||
|
|
||||||
|
if (mmResult != MMSYSERR_NOERROR)
|
||||||
{
|
{
|
||||||
DEBUG_WARN("waveOutClose error");
|
fprintf(stderr, "waveOutClose failure: %d\n", mmResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
winmm->out_handle = NULL;
|
winmm->hWaveOut = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,11 +185,15 @@ static void rdpsnd_winmm_free(rdpsndDevicePlugin* device)
|
|||||||
{
|
{
|
||||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||||
|
|
||||||
|
if (winmm)
|
||||||
|
{
|
||||||
rdpsnd_winmm_close(device);
|
rdpsnd_winmm_close(device);
|
||||||
|
|
||||||
freerdp_dsp_context_free(winmm->dsp_context);
|
freerdp_dsp_context_free(winmm->dsp_context);
|
||||||
CloseHandle(winmm->event);
|
|
||||||
free(winmm);
|
free(winmm);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL rdpsnd_winmm_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format)
|
static BOOL rdpsnd_winmm_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format)
|
||||||
{
|
{
|
||||||
@ -203,10 +223,10 @@ static UINT32 rdpsnd_winmm_get_volume(rdpsndDevicePlugin* device)
|
|||||||
dwVolumeRight = ((50 * 0xFFFF) / 100); /* 50% */
|
dwVolumeRight = ((50 * 0xFFFF) / 100); /* 50% */
|
||||||
dwVolume = (dwVolumeLeft << 16) | dwVolumeRight;
|
dwVolume = (dwVolumeLeft << 16) | dwVolumeRight;
|
||||||
|
|
||||||
if (!winmm->out_handle)
|
if (!winmm->hWaveOut)
|
||||||
return dwVolume;
|
return dwVolume;
|
||||||
|
|
||||||
waveOutGetVolume(winmm->out_handle, &dwVolume);
|
waveOutGetVolume(winmm->hWaveOut, &dwVolume);
|
||||||
|
|
||||||
return dwVolume;
|
return dwVolume;
|
||||||
}
|
}
|
||||||
@ -215,82 +235,94 @@ static void rdpsnd_winmm_set_volume(rdpsndDevicePlugin* device, UINT32 value)
|
|||||||
{
|
{
|
||||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||||
|
|
||||||
if (!winmm->out_handle)
|
if (!winmm->hWaveOut)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
waveOutSetVolume(winmm->out_handle, value);
|
waveOutSetVolume(winmm->hWaveOut, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rdpsnd_winmm_play(rdpsndDevicePlugin* device, BYTE* data, int size)
|
static void rdpsnd_winmm_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
||||||
{
|
{
|
||||||
BYTE* src;
|
int length;
|
||||||
MMRESULT result;
|
BYTE* data;
|
||||||
rdpsndWinmmDatablock* last;
|
|
||||||
rdpsndWinmmDatablock* datablock;
|
|
||||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||||
|
|
||||||
if (!winmm->out_handle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (winmm->wformat == WAVE_FORMAT_ADPCM)
|
if (winmm->wformat == WAVE_FORMAT_ADPCM)
|
||||||
{
|
{
|
||||||
winmm->dsp_context->decode_ms_adpcm(winmm->dsp_context,
|
winmm->dsp_context->decode_ms_adpcm(winmm->dsp_context,
|
||||||
data, size, winmm->format.nChannels, winmm->block_size);
|
wave->data, wave->length, winmm->format.nChannels, winmm->block_size);
|
||||||
size = winmm->dsp_context->adpcm_size;
|
length = winmm->dsp_context->adpcm_size;
|
||||||
src = winmm->dsp_context->adpcm_buffer;
|
data = winmm->dsp_context->adpcm_buffer;
|
||||||
}
|
}
|
||||||
else if (winmm->wformat == WAVE_FORMAT_DVI_ADPCM)
|
else if (winmm->wformat == WAVE_FORMAT_DVI_ADPCM)
|
||||||
{
|
{
|
||||||
winmm->dsp_context->decode_ima_adpcm(winmm->dsp_context,
|
winmm->dsp_context->decode_ima_adpcm(winmm->dsp_context,
|
||||||
data, size, winmm->format.nChannels, winmm->block_size);
|
wave->data, wave->length, winmm->format.nChannels, winmm->block_size);
|
||||||
size = winmm->dsp_context->adpcm_size;
|
length = winmm->dsp_context->adpcm_size;
|
||||||
src = winmm->dsp_context->adpcm_buffer;
|
data = winmm->dsp_context->adpcm_buffer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
src = data;
|
length = wave->length;
|
||||||
|
data = wave->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdpsnd_winmm_clear_datablocks(winmm, FALSE);
|
wave->data = (BYTE*) malloc(length);
|
||||||
|
CopyMemory(wave->data, data, length);
|
||||||
for (last = winmm->datablock_head; last && last->next; last = last->next)
|
wave->length = length;
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
datablock = (rdpsndWinmmDatablock*) malloc(sizeof(rdpsndWinmmDatablock));
|
void rdpsnd_winmm_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
||||||
ZeroMemory(datablock, sizeof(rdpsndWinmmDatablock));
|
|
||||||
|
|
||||||
if (last)
|
|
||||||
last->next = datablock;
|
|
||||||
else
|
|
||||||
winmm->datablock_head = datablock;
|
|
||||||
|
|
||||||
datablock->header.dwBufferLength = size;
|
|
||||||
datablock->header.lpData = (LPSTR) malloc(size);
|
|
||||||
CopyMemory(datablock->header.lpData, src, size);
|
|
||||||
|
|
||||||
result = waveOutPrepareHeader(winmm->out_handle, &datablock->header, sizeof(datablock->header));
|
|
||||||
|
|
||||||
if (result != MMSYSERR_NOERROR)
|
|
||||||
{
|
{
|
||||||
DEBUG_WARN("waveOutPrepareHeader: %d", result);
|
MMRESULT mmResult;
|
||||||
|
LPWAVEHDR lpWaveHdr;
|
||||||
|
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||||
|
|
||||||
|
if (!winmm->hWaveOut)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wave->AutoConfirm = FALSE;
|
||||||
|
|
||||||
|
lpWaveHdr = (LPWAVEHDR) malloc(sizeof(WAVEHDR));
|
||||||
|
|
||||||
|
if (!lpWaveHdr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ZeroMemory(lpWaveHdr, sizeof(WAVEHDR));
|
||||||
|
|
||||||
|
lpWaveHdr->dwFlags = 0;
|
||||||
|
lpWaveHdr->dwLoops = 0;
|
||||||
|
lpWaveHdr->lpData = (LPSTR) wave->data;
|
||||||
|
lpWaveHdr->dwBufferLength = wave->length;
|
||||||
|
lpWaveHdr->dwUser = (DWORD_PTR) wave;
|
||||||
|
lpWaveHdr->lpNext = NULL;
|
||||||
|
|
||||||
|
mmResult = waveOutPrepareHeader(winmm->hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
|
||||||
|
|
||||||
|
if (mmResult != MMSYSERR_NOERROR)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "waveOutPrepareHeader failure: %d\n", mmResult);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetEvent(winmm->event);
|
mmResult = waveOutWrite(winmm->hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
|
||||||
waveOutWrite(winmm->out_handle, &datablock->header, sizeof(datablock->header));
|
|
||||||
|
if (mmResult != MMSYSERR_NOERROR)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "waveOutWrite failure: %d\n", mmResult);
|
||||||
|
waveOutUnprepareHeader(winmm->hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rdpsnd_winmm_start(rdpsndDevicePlugin* device)
|
static void rdpsnd_winmm_start(rdpsndDevicePlugin* device)
|
||||||
{
|
{
|
||||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
//rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||||
|
|
||||||
rdpsnd_winmm_clear_datablocks(winmm, FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rdpsnd_winmm_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
|
static void rdpsnd_winmm_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef STATIC_CHANNELS
|
#ifdef STATIC_CHANNELS
|
||||||
@ -305,12 +337,15 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
|
|||||||
winmm = (rdpsndWinmmPlugin*) malloc(sizeof(rdpsndWinmmPlugin));
|
winmm = (rdpsndWinmmPlugin*) malloc(sizeof(rdpsndWinmmPlugin));
|
||||||
ZeroMemory(winmm, sizeof(rdpsndWinmmPlugin));
|
ZeroMemory(winmm, sizeof(rdpsndWinmmPlugin));
|
||||||
|
|
||||||
|
winmm->device.DisableConfirmThread = TRUE;
|
||||||
|
|
||||||
winmm->device.Open = rdpsnd_winmm_open;
|
winmm->device.Open = rdpsnd_winmm_open;
|
||||||
winmm->device.FormatSupported = rdpsnd_winmm_format_supported;
|
winmm->device.FormatSupported = rdpsnd_winmm_format_supported;
|
||||||
winmm->device.SetFormat = rdpsnd_winmm_set_format;
|
winmm->device.SetFormat = rdpsnd_winmm_set_format;
|
||||||
winmm->device.GetVolume = rdpsnd_winmm_get_volume;
|
winmm->device.GetVolume = rdpsnd_winmm_get_volume;
|
||||||
winmm->device.SetVolume = rdpsnd_winmm_set_volume;
|
winmm->device.SetVolume = rdpsnd_winmm_set_volume;
|
||||||
winmm->device.Play = rdpsnd_winmm_play;
|
winmm->device.WaveDecode = rdpsnd_winmm_wave_decode;
|
||||||
|
winmm->device.WavePlay = rdpsnd_winmm_wave_play;
|
||||||
winmm->device.Start = rdpsnd_winmm_start;
|
winmm->device.Start = rdpsnd_winmm_start;
|
||||||
winmm->device.Close = rdpsnd_winmm_close;
|
winmm->device.Close = rdpsnd_winmm_close;
|
||||||
winmm->device.Free = rdpsnd_winmm_free;
|
winmm->device.Free = rdpsnd_winmm_free;
|
||||||
@ -319,7 +354,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
|
|||||||
rdpsnd_winmm_parse_addin_args((rdpsndDevicePlugin*) winmm, args);
|
rdpsnd_winmm_parse_addin_args((rdpsndDevicePlugin*) winmm, args);
|
||||||
|
|
||||||
winmm->dsp_context = freerdp_dsp_context_new();
|
winmm->dsp_context = freerdp_dsp_context_new();
|
||||||
winmm->event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
||||||
|
|
||||||
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) winmm);
|
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) winmm);
|
||||||
|
|
||||||
|
4
client/Android/.gitignore
vendored
4
client/Android/.gitignore
vendored
@ -8,3 +8,7 @@ libs/armeabi*
|
|||||||
AndroidManifest.xml
|
AndroidManifest.xml
|
||||||
local.properties
|
local.properties
|
||||||
!.project
|
!.project
|
||||||
|
|
||||||
|
FreeRDPCore/project.properties
|
||||||
|
FreeRDPCore/src/com/freerdp/freerdpcore/utils/BuildConfiguration.java
|
||||||
|
aFreeRDP/project.properties
|
||||||
|
4
client/Android/FreeRDPCore/.gitignore
vendored
Normal file
4
client/Android/FreeRDPCore/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ant.properties
|
||||||
|
build.xml
|
||||||
|
jni/Android.mk
|
||||||
|
jni/Application.mk
|
4
client/Android/aFreeRDP/.gitignore
vendored
Normal file
4
client/Android/aFreeRDP/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ant.properties
|
||||||
|
build.xml
|
||||||
|
jni/Android.mk
|
||||||
|
jni/Application.mk
|
@ -1,3 +1,6 @@
|
|||||||
|
#ifndef MRDPVIEW_H
|
||||||
|
#define MRDPVIEW_H
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
* MacFreeRDP
|
* MacFreeRDP
|
||||||
@ -97,3 +100,5 @@ BOOL mac_post_connect(freerdp* instance);
|
|||||||
BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain);
|
BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain);
|
||||||
int mac_receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size);
|
int mac_receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size);
|
||||||
DWORD mac_client_thread(void* param);
|
DWORD mac_client_thread(void* param);
|
||||||
|
|
||||||
|
#endif // MRDPVIEW_H
|
||||||
|
@ -59,6 +59,8 @@
|
|||||||
#import "freerdp/types.h"
|
#import "freerdp/types.h"
|
||||||
#import "freerdp/channels/channels.h"
|
#import "freerdp/channels/channels.h"
|
||||||
#import "freerdp/gdi/gdi.h"
|
#import "freerdp/gdi/gdi.h"
|
||||||
|
#import "freerdp/gdi/dc.h"
|
||||||
|
#import "freerdp/gdi/region.h"
|
||||||
#import "freerdp/graphics.h"
|
#import "freerdp/graphics.h"
|
||||||
#import "freerdp/utils/event.h"
|
#import "freerdp/utils/event.h"
|
||||||
#import "freerdp/client/cliprdr.h"
|
#import "freerdp/client/cliprdr.h"
|
||||||
@ -496,32 +498,84 @@ DWORD mac_client_thread(void* param)
|
|||||||
mf_scale_mouse_event(context, instance->input, PTR_FLAGS_MOVE, x, y);
|
mf_scale_mouse_event(context, instance->input, PTR_FLAGS_MOVE, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD fixKeyCode(DWORD keyCode, unichar keyChar)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* In 99% of cases, the given key code is truly keyboard independent.
|
||||||
|
* This function handles the remaining 1% of edge cases.
|
||||||
|
*
|
||||||
|
* Hungarian Keyboard: This is 'QWERTZ' and not 'QWERTY'.
|
||||||
|
* The '0' key is on the left of the '1' key, where '~' is on a US keyboard.
|
||||||
|
* A special 'i' letter key with acute is found on the right of the left shift key.
|
||||||
|
* On the hungarian keyboard, the 'i' key is at the left of the 'Y' key
|
||||||
|
* Some international keyboards have a corresponding key which would be at
|
||||||
|
* the left of the 'Z' key when using a QWERTY layout.
|
||||||
|
*
|
||||||
|
* The Apple Hungarian keyboard sends inverted key codes for the '0' and 'i' keys.
|
||||||
|
* When using the US keyboard layout, key codes are left as-is (inverted).
|
||||||
|
* When using the Hungarian keyboard layout, key codes are swapped (non-inverted).
|
||||||
|
* This means that when using the Hungarian keyboard layout with a US keyboard,
|
||||||
|
* the keys corresponding to '0' and 'i' will effectively be inverted.
|
||||||
|
*
|
||||||
|
* To fix the '0' and 'i' key inversion, we use the corresponding output character
|
||||||
|
* provided by OS X and check for a character to key code mismatch: for instance,
|
||||||
|
* when the output character is '0' for the key code corresponding to the 'i' key.
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch (keyChar)
|
||||||
|
{
|
||||||
|
case '0':
|
||||||
|
case 0x00A7: /* section sign */
|
||||||
|
if (keyCode == APPLE_VK_ISO_Section)
|
||||||
|
keyCode = APPLE_VK_ANSI_Grave;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x00ED: /* latin small letter i with acute */
|
||||||
|
case 0x00CD: /* latin capital letter i with acute */
|
||||||
|
if (keyCode == APPLE_VK_ANSI_Grave)
|
||||||
|
keyCode = APPLE_VK_ISO_Section;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyCode;
|
||||||
|
}
|
||||||
|
|
||||||
/** *********************************************************************
|
/** *********************************************************************
|
||||||
* called when a key is pressed
|
* called when a key is pressed
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
- (void) keyDown:(NSEvent *) event
|
- (void) keyDown:(NSEvent *) event
|
||||||
{
|
{
|
||||||
int key;
|
DWORD keyCode;
|
||||||
DWORD keyFlags;
|
DWORD keyFlags;
|
||||||
DWORD vkcode;
|
DWORD vkcode;
|
||||||
DWORD scancode;
|
DWORD scancode;
|
||||||
|
unichar keyChar;
|
||||||
|
NSString* characters;
|
||||||
|
|
||||||
if (!is_connected)
|
if (!is_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
keyFlags = KBD_FLAGS_DOWN;
|
keyFlags = KBD_FLAGS_DOWN;
|
||||||
key = [event keyCode] + 8;
|
keyCode = [event keyCode];
|
||||||
|
|
||||||
vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE);
|
characters = [event charactersIgnoringModifiers];
|
||||||
|
|
||||||
|
if ([characters length] > 0)
|
||||||
|
{
|
||||||
|
keyChar = [characters characterAtIndex:0];
|
||||||
|
keyCode = fixKeyCode(keyCode, keyChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
vkcode = GetVirtualKeyCodeFromKeycode(keyCode + 8, KEYCODE_TYPE_APPLE);
|
||||||
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
|
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
|
||||||
keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
|
keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
|
||||||
scancode &= 0xFF;
|
scancode &= 0xFF;
|
||||||
vkcode &= 0xFF;
|
vkcode &= 0xFF;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
fprintf(stderr, "keyDown: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s\n",
|
fprintf(stderr, "keyDown: keyCode: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s\n",
|
||||||
key - 8, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
|
keyCode, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
freerdp_input_send_keyboard_event(instance->input, keyFlags, scancode);
|
freerdp_input_send_keyboard_event(instance->input, keyFlags, scancode);
|
||||||
@ -533,18 +587,28 @@ DWORD mac_client_thread(void* param)
|
|||||||
|
|
||||||
- (void) keyUp:(NSEvent *) event
|
- (void) keyUp:(NSEvent *) event
|
||||||
{
|
{
|
||||||
int key;
|
DWORD keyCode;
|
||||||
DWORD keyFlags;
|
DWORD keyFlags;
|
||||||
DWORD vkcode;
|
DWORD vkcode;
|
||||||
DWORD scancode;
|
DWORD scancode;
|
||||||
|
unichar keyChar;
|
||||||
|
NSString* characters;
|
||||||
|
|
||||||
if (!is_connected)
|
if (!is_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
key = [event keyCode] + 8;
|
|
||||||
keyFlags = KBD_FLAGS_RELEASE;
|
keyFlags = KBD_FLAGS_RELEASE;
|
||||||
|
keyCode = [event keyCode];
|
||||||
|
|
||||||
vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE);
|
characters = [event charactersIgnoringModifiers];
|
||||||
|
|
||||||
|
if ([characters length] > 0)
|
||||||
|
{
|
||||||
|
keyChar = [characters characterAtIndex:0];
|
||||||
|
keyCode = fixKeyCode(keyCode, keyChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
vkcode = GetVirtualKeyCodeFromKeycode(keyCode + 8, KEYCODE_TYPE_APPLE);
|
||||||
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
|
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
|
||||||
keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
|
keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
|
||||||
scancode &= 0xFF;
|
scancode &= 0xFF;
|
||||||
@ -552,7 +616,7 @@ DWORD mac_client_thread(void* param)
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
fprintf(stderr, "keyUp: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s\n",
|
fprintf(stderr, "keyUp: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s\n",
|
||||||
key - 8, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
|
keyCode, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
freerdp_input_send_keyboard_event(instance->input, keyFlags, scancode);
|
freerdp_input_send_keyboard_event(instance->input, keyFlags, scancode);
|
||||||
@ -660,6 +724,8 @@ DWORD mac_client_thread(void* param)
|
|||||||
if (!is_connected)
|
if (!is_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
gdi_free(context->instance);
|
||||||
|
|
||||||
freerdp_channels_global_uninit();
|
freerdp_channels_global_uninit();
|
||||||
|
|
||||||
if (pixel_data)
|
if (pixel_data)
|
||||||
@ -743,7 +809,6 @@ DWORD mac_client_thread(void* param)
|
|||||||
BOOL mac_pre_connect(freerdp* instance)
|
BOOL mac_pre_connect(freerdp* instance)
|
||||||
{
|
{
|
||||||
rdpSettings* settings;
|
rdpSettings* settings;
|
||||||
BOOL bitmap_cache;
|
|
||||||
|
|
||||||
// setup callbacks
|
// setup callbacks
|
||||||
instance->update->BeginPaint = mac_begin_paint;
|
instance->update->BeginPaint = mac_begin_paint;
|
||||||
@ -760,17 +825,13 @@ BOOL mac_pre_connect(freerdp* instance)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
freerdp_client_load_addins(instance->context->channels, instance->settings);
|
settings->ColorDepth = 32;
|
||||||
|
settings->SoftwareGdi = TRUE;
|
||||||
|
|
||||||
settings = instance->settings;
|
settings->OsMajorType = OSMAJORTYPE_MACINTOSH;
|
||||||
bitmap_cache = settings->BitmapCacheEnabled;
|
settings->OsMinorType = OSMINORTYPE_MACINTOSH;
|
||||||
|
|
||||||
instance->settings->ColorDepth = 32;
|
|
||||||
instance->settings->SoftwareGdi = TRUE;
|
|
||||||
|
|
||||||
settings->OsMajorType = OSMAJORTYPE_UNIX;
|
|
||||||
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
|
|
||||||
|
|
||||||
|
ZeroMemory(settings->OrderSupport, 32);
|
||||||
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
|
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
|
||||||
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
|
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
|
||||||
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
|
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
|
||||||
@ -783,23 +844,21 @@ BOOL mac_pre_connect(freerdp* instance)
|
|||||||
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
|
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
|
||||||
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
|
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
|
||||||
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
|
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
|
||||||
settings->OrderSupport[NEG_MEMBLT_INDEX] = bitmap_cache;
|
settings->OrderSupport[NEG_MEMBLT_INDEX] = settings->BitmapCacheEnabled;
|
||||||
|
|
||||||
settings->OrderSupport[NEG_MEM3BLT_INDEX] = (settings->SoftwareGdi) ? TRUE : FALSE;
|
settings->OrderSupport[NEG_MEM3BLT_INDEX] = (settings->SoftwareGdi) ? TRUE : FALSE;
|
||||||
|
settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = settings->BitmapCacheEnabled;
|
||||||
settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = bitmap_cache;
|
|
||||||
settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
|
settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
|
||||||
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
|
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
|
||||||
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
|
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
|
||||||
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
|
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
|
||||||
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
|
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
|
||||||
|
|
||||||
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
|
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
|
||||||
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
|
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
|
||||||
|
|
||||||
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
|
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
|
||||||
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
|
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
|
||||||
|
|
||||||
|
freerdp_client_load_addins(instance->context->channels, instance->settings);
|
||||||
|
|
||||||
freerdp_channels_pre_connect(instance->context->channels, instance);
|
freerdp_channels_pre_connect(instance->context->channels, instance);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -855,7 +914,6 @@ BOOL mac_post_connect(freerdp* instance)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain)
|
BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain)
|
||||||
{
|
{
|
||||||
PasswordDialog* dialog = [PasswordDialog new];
|
PasswordDialog* dialog = [PasswordDialog new];
|
||||||
@ -921,9 +979,6 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer)
|
|||||||
freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData,
|
freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData,
|
||||||
pointer->width, pointer->height, pointer->xorBpp, context->gdi->clrconv);
|
pointer->width, pointer->height, pointer->xorBpp, context->gdi->clrconv);
|
||||||
|
|
||||||
// TODO if xorBpp is > 24 need to call freerdp_image_swap_color_order
|
|
||||||
// see file df_graphics.c
|
|
||||||
|
|
||||||
/* store cursor bitmap image in representation - required by NSImage */
|
/* store cursor bitmap image in representation - required by NSImage */
|
||||||
bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &cursor_data
|
bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &cursor_data
|
||||||
pixelsWide:rect.size.width
|
pixelsWide:rect.size.width
|
||||||
@ -1049,6 +1104,10 @@ void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap)
|
|||||||
void mac_begin_paint(rdpContext* context)
|
void mac_begin_paint(rdpContext* context)
|
||||||
{
|
{
|
||||||
rdpGdi* gdi = context->gdi;
|
rdpGdi* gdi = context->gdi;
|
||||||
|
|
||||||
|
if (!gdi)
|
||||||
|
return;
|
||||||
|
|
||||||
gdi->primary->hdc->hwnd->invalid->null = 1;
|
gdi->primary->hdc->hwnd->invalid->null = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1058,20 +1117,24 @@ void mac_begin_paint(rdpContext* context)
|
|||||||
|
|
||||||
void mac_end_paint(rdpContext* context)
|
void mac_end_paint(rdpContext* context)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
rdpGdi* gdi;
|
rdpGdi* gdi;
|
||||||
NSRect drawRect;
|
HGDI_RGN invalid;
|
||||||
|
NSRect newDrawRect;
|
||||||
|
int ww, wh, dw, dh;
|
||||||
mfContext* mfc = (mfContext*) context;
|
mfContext* mfc = (mfContext*) context;
|
||||||
MRDPView* view = (MRDPView*) mfc->view;
|
MRDPView* view = (MRDPView*) mfc->view;
|
||||||
|
|
||||||
int ww, wh, dw, dh;
|
gdi = context->gdi;
|
||||||
|
|
||||||
|
if (!gdi)
|
||||||
|
return;
|
||||||
|
|
||||||
ww = mfc->client_width;
|
ww = mfc->client_width;
|
||||||
wh = mfc->client_height;
|
wh = mfc->client_height;
|
||||||
dw = mfc->context.settings->DesktopWidth;
|
dw = mfc->context.settings->DesktopWidth;
|
||||||
dh = mfc->context.settings->DesktopHeight;
|
dh = mfc->context.settings->DesktopHeight;
|
||||||
|
|
||||||
if ((context == 0) || (context->gdi == 0))
|
if ((!context) || (!context->gdi))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (context->gdi->primary->hdc->hwnd->invalid->null)
|
if (context->gdi->primary->hdc->hwnd->invalid->null)
|
||||||
@ -1080,37 +1143,31 @@ void mac_end_paint(rdpContext* context)
|
|||||||
if (context->gdi->drawing != context->gdi->primary)
|
if (context->gdi->drawing != context->gdi->primary)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gdi = context->gdi;
|
invalid = gdi->primary->hdc->hwnd->invalid;
|
||||||
|
|
||||||
for (i = 0; i < gdi->primary->hdc->hwnd->ninvalid; i++)
|
newDrawRect.origin.x = invalid->x;
|
||||||
{
|
newDrawRect.origin.y = invalid->y;
|
||||||
drawRect.origin.x = gdi->primary->hdc->hwnd->cinvalid[i].x;
|
newDrawRect.size.width = invalid->w;
|
||||||
drawRect.origin.y = gdi->primary->hdc->hwnd->cinvalid[i].y;
|
newDrawRect.size.height = invalid->h;
|
||||||
drawRect.size.width = gdi->primary->hdc->hwnd->cinvalid[i].w;
|
|
||||||
drawRect.size.height = gdi->primary->hdc->hwnd->cinvalid[i].h;
|
|
||||||
|
|
||||||
if (mfc->context.settings->SmartSizing && (ww != dw || wh != dh))
|
if (mfc->context.settings->SmartSizing && (ww != dw || wh != dh))
|
||||||
{
|
{
|
||||||
drawRect.origin.y = drawRect.origin.y * wh / dh - 1;
|
newDrawRect.origin.y = newDrawRect.origin.y * wh / dh - 1;
|
||||||
drawRect.size.height = drawRect.size.height * wh / dh + 1;
|
newDrawRect.size.height = newDrawRect.size.height * wh / dh + 1;
|
||||||
drawRect.origin.x = drawRect.origin.x * ww / dw - 1;
|
newDrawRect.origin.x = newDrawRect.origin.x * ww / dw - 1;
|
||||||
drawRect.size.width = drawRect.size.width * ww / dw + 1;
|
newDrawRect.size.width = newDrawRect.size.width * ww / dw + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
drawRect.origin.y = drawRect.origin.y - 1;
|
newDrawRect.origin.y = newDrawRect.origin.y - 1;
|
||||||
drawRect.size.height = drawRect.size.height + 1;
|
newDrawRect.size.height = newDrawRect.size.height + 1;
|
||||||
drawRect.origin.x = drawRect.origin.x - 1;
|
newDrawRect.origin.x = newDrawRect.origin.x - 1;
|
||||||
drawRect.size.width = drawRect.size.width + 1;
|
newDrawRect.size.width = newDrawRect.size.width + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
windows_to_apple_cords(mfc->view, &drawRect);
|
windows_to_apple_cords(mfc->view, &newDrawRect);
|
||||||
|
|
||||||
// Note: The xCurrentScroll and yCurrentScroll values do not need to be taken into account
|
[view setNeedsDisplayInRect:newDrawRect];
|
||||||
// because the current frame is always at full size, since the scrolling is handled by the external container.
|
|
||||||
|
|
||||||
[view setNeedsDisplayInRect:drawRect];
|
|
||||||
}
|
|
||||||
|
|
||||||
gdi->primary->hdc->hwnd->ninvalid = 0;
|
gdi->primary->hdc->hwnd->ninvalid = 0;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ static AppDelegate* _singleDelegate = nil;
|
|||||||
void AppDelegate_EmbedWindowEventHandler(void* context, EmbedWindowEventArgs* e);
|
void AppDelegate_EmbedWindowEventHandler(void* context, EmbedWindowEventArgs* e);
|
||||||
void AppDelegate_ConnectionResultEventHandler(void* context, ConnectionResultEventArgs* e);
|
void AppDelegate_ConnectionResultEventHandler(void* context, ConnectionResultEventArgs* e);
|
||||||
void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e);
|
void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e);
|
||||||
int mac_client_start(rdpContext* context);
|
|
||||||
void mac_set_view_size(rdpContext* context, MRDPView* view);
|
void mac_set_view_size(rdpContext* context, MRDPView* view);
|
||||||
|
|
||||||
@implementation AppDelegate
|
@implementation AppDelegate
|
||||||
@ -94,7 +93,13 @@ void mac_set_view_size(rdpContext* context, MRDPView* view);
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = freerdp_client_settings_parse_command_line(context->settings, argc, argv);
|
status = freerdp_client_settings_parse_command_line(context->settings, argc, argv);
|
||||||
|
|
||||||
|
if (context->argc && context->argv)
|
||||||
status = freerdp_client_settings_command_line_status_print(context->settings, status, context->argc, context->argv);
|
status = freerdp_client_settings_command_line_status_print(context->settings, status, context->argc, context->argv);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
freerdp_client_print_command_line_help(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -109,8 +114,6 @@ void mac_set_view_size(rdpContext* context, MRDPView* view);
|
|||||||
|
|
||||||
RdpClientEntry(&clientEntryPoints);
|
RdpClientEntry(&clientEntryPoints);
|
||||||
|
|
||||||
clientEntryPoints.ClientStart = mac_client_start;
|
|
||||||
|
|
||||||
context = freerdp_client_context_new(&clientEntryPoints);
|
context = freerdp_client_context_new(&clientEntryPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +177,6 @@ void AppDelegate_EmbedWindowEventHandler(void* ctx, EmbedWindowEventArgs* e)
|
|||||||
[[_singleDelegate->window contentView] addSubview:mfc->view];
|
[[_singleDelegate->window contentView] addSubview:mfc->view];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mac_set_view_size(context, mfc->view);
|
mac_set_view_size(context, mfc->view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,13 +195,12 @@ void AppDelegate_ConnectionResultEventHandler(void* ctx, ConnectionResultEventAr
|
|||||||
NSString* message = nil;
|
NSString* message = nil;
|
||||||
if (connectErrorCode == AUTHENTICATIONERROR)
|
if (connectErrorCode == AUTHENTICATIONERROR)
|
||||||
{
|
{
|
||||||
message = [NSString stringWithFormat:@"%@:\n%@", message, @"Authentication failure, check credentials."];
|
message = [NSString stringWithFormat:@"%@", @"Authentication failure, check credentials."];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Making sure this should be invoked on the main UI thread.
|
// Making sure this should be invoked on the main UI thread.
|
||||||
[_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:) withObject:message waitUntilDone:FALSE];
|
[_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:) withObject:message waitUntilDone:FALSE];
|
||||||
[message release];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,7 +224,6 @@ void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void mac_set_view_size(rdpContext* context, MRDPView* view)
|
void mac_set_view_size(rdpContext* context, MRDPView* view)
|
||||||
{
|
{
|
||||||
// set client area to specified dimensions
|
// set client area to specified dimensions
|
||||||
@ -244,22 +244,6 @@ void mac_set_view_size(rdpContext* context, MRDPView* view)
|
|||||||
// set window to given area
|
// set window to given area
|
||||||
[[view window] setFrame:outerRect display:YES];
|
[[view window] setFrame:outerRect display:YES];
|
||||||
|
|
||||||
|
|
||||||
if (context->settings->Fullscreen)
|
if (context->settings->Fullscreen)
|
||||||
[[view window] toggleFullScreen:nil];
|
[[view window] toggleFullScreen:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
int mac_client_start(rdpContext* context)
|
|
||||||
{
|
|
||||||
mfContext* mfc;
|
|
||||||
MRDPView* view;
|
|
||||||
|
|
||||||
mfc = (mfContext*) context;
|
|
||||||
view = [[MRDPView alloc] initWithFrame : NSMakeRect(0, 0, context->settings->DesktopWidth, context->settings->DesktopHeight)];
|
|
||||||
mfc->view = view;
|
|
||||||
|
|
||||||
[view rdpStart:context];
|
|
||||||
mac_set_view_size(context, view);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -105,38 +105,6 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context)
|
|||||||
settings->AsyncChannels = TRUE;
|
settings->AsyncChannels = TRUE;
|
||||||
settings->AsyncTransport = TRUE;
|
settings->AsyncTransport = TRUE;
|
||||||
|
|
||||||
settings->OsMajorType = OSMAJORTYPE_MACINTOSH;
|
|
||||||
settings->OsMinorType = OSMINORTYPE_MACINTOSH;
|
|
||||||
|
|
||||||
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_MEMBLT_INDEX] = settings->BitmapCacheEnabled;
|
|
||||||
|
|
||||||
settings->OrderSupport[NEG_MEM3BLT_INDEX] = (settings->SoftwareGdi) ? TRUE : FALSE;
|
|
||||||
|
|
||||||
settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = settings->BitmapCacheEnabled;
|
|
||||||
settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
|
|
||||||
|
|
||||||
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
|
|
||||||
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
|
|
||||||
|
|
||||||
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
|||||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||||
|
|
||||||
if(WITH_CLIENT_INTERFACE)
|
if(WITH_CLIENT_INTERFACE)
|
||||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT WinPRTargets)
|
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT FreeRDPTargets)
|
||||||
add_subdirectory(cli)
|
add_subdirectory(cli)
|
||||||
else()
|
else()
|
||||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
|
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
|
||||||
|
@ -54,7 +54,7 @@ static UINT32 get_local_format_id_by_name(cliprdrContext *cliprdr, void *format_
|
|||||||
for (i = 0; i < cliprdr->map_size; i++)
|
for (i = 0; i < cliprdr->map_size; i++)
|
||||||
{
|
{
|
||||||
map = &cliprdr->format_mappings[i];
|
map = &cliprdr->format_mappings[i];
|
||||||
if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0)
|
if ((cliprdr->capabilities & CB_USE_LONG_FORMAT_NAMES) != 0)
|
||||||
{
|
{
|
||||||
if (map->name)
|
if (map->name)
|
||||||
{
|
{
|
||||||
@ -144,7 +144,7 @@ static void cliprdr_send_format_list(cliprdrContext *cliprdr)
|
|||||||
{
|
{
|
||||||
Write_UINT32(format_data + len, format);
|
Write_UINT32(format_data + len, format);
|
||||||
len += 4;
|
len += 4;
|
||||||
if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0)
|
if ((cliprdr->capabilities & CB_USE_LONG_FORMAT_NAMES) != 0)
|
||||||
{
|
{
|
||||||
if (format >= CF_MAX)
|
if (format >= CF_MAX)
|
||||||
{
|
{
|
||||||
@ -518,7 +518,7 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA
|
|||||||
|
|
||||||
clear_format_map(cliprdr);
|
clear_format_map(cliprdr);
|
||||||
|
|
||||||
if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0)
|
if ((cliprdr->capabilities & CB_USE_LONG_FORMAT_NAMES) != 0)
|
||||||
{
|
{
|
||||||
while (left_size >= 6)
|
while (left_size >= 6)
|
||||||
{
|
{
|
||||||
|
@ -798,39 +798,6 @@ int freerdp_client_set_window_size(wfContext* wfc, int width, int height)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wf_ParamChangeEventHandler(rdpContext* context, ParamChangeEventArgs* e)
|
|
||||||
{
|
|
||||||
RECT rect;
|
|
||||||
HMENU hMenu;
|
|
||||||
wfContext* wfc = (wfContext*) context;
|
|
||||||
|
|
||||||
// specific processing here
|
|
||||||
switch (e->id)
|
|
||||||
{
|
|
||||||
case FreeRDP_SmartSizing:
|
|
||||||
fprintf(stderr, "SmartSizing changed.\n");
|
|
||||||
|
|
||||||
if (!context->settings->SmartSizing && (wfc->client_width > context->settings->DesktopWidth || wfc->client_height > context->settings->DesktopHeight))
|
|
||||||
{
|
|
||||||
GetWindowRect(wfc->hwnd, &rect);
|
|
||||||
SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0, MIN(wfc->client_width + wfc->offset_x, rect.right - rect.left), MIN(wfc->client_height + wfc->offset_y, rect.bottom - rect.top), SWP_NOMOVE | SWP_FRAMECHANGED);
|
|
||||||
wf_update_canvas_diff(wfc);
|
|
||||||
}
|
|
||||||
|
|
||||||
hMenu = GetSystemMenu(wfc->hwnd, FALSE);
|
|
||||||
CheckMenuItem(hMenu, SYSCOMMAND_ID_SMARTSIZING, context->settings->SmartSizing);
|
|
||||||
wf_size_scrollbars(wfc, wfc->client_width, wfc->client_height);
|
|
||||||
GetClientRect(wfc->hwnd, &rect);
|
|
||||||
InvalidateRect(wfc->hwnd, &rect, TRUE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FreeRDP_ConnectionType:
|
|
||||||
fprintf(stderr, "ConnectionType changed.\n");
|
|
||||||
freerdp_set_connection_type(wfc->instance->settings, wfc->instance->settings->ConnectionType);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Some of that code is a duplicate of wf_pre_connect. Refactor?
|
// TODO: Some of that code is a duplicate of wf_pre_connect. Refactor?
|
||||||
int freerdp_client_load_settings_from_rdp_file(wfContext* wfc, char* filename)
|
int freerdp_client_load_settings_from_rdp_file(wfContext* wfc, char* filename)
|
||||||
{
|
{
|
||||||
@ -862,37 +829,6 @@ int freerdp_client_load_settings_from_rdp_file(wfContext* wfc, char* filename)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int freerdp_client_save_settings_to_rdp_file(wfContext* wfc, char* filename)
|
|
||||||
{
|
|
||||||
if (!filename)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (wfc->instance->settings->ConnectionFile)
|
|
||||||
{
|
|
||||||
free(wfc->instance->settings->ConnectionFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
wfc->instance->settings->ConnectionFile = _strdup(filename);
|
|
||||||
|
|
||||||
// Reuse existing rdpFile structure if available, to preserve unsupported settings when saving to disk.
|
|
||||||
if (wfc->connectionRdpFile == NULL)
|
|
||||||
{
|
|
||||||
wfc->connectionRdpFile = freerdp_client_rdp_file_new();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!freerdp_client_populate_rdp_file_from_settings(wfc->connectionRdpFile, wfc->instance->settings))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!freerdp_client_write_rdp_file(wfc->connectionRdpFile, filename, UNICODE));
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wf_size_scrollbars(wfContext* wfc, int client_width, int client_height)
|
void wf_size_scrollbars(wfContext* wfc, int client_width, int client_height)
|
||||||
{
|
{
|
||||||
BOOL rc;
|
BOOL rc;
|
||||||
@ -1048,8 +984,6 @@ int wfreerdp_client_new(freerdp* instance, rdpContext* context)
|
|||||||
wfc->instance = instance;
|
wfc->instance = instance;
|
||||||
context->channels = freerdp_channels_new();
|
context->channels = freerdp_channels_new();
|
||||||
|
|
||||||
PubSub_SubscribeParamChange(context->pubSub, wf_ParamChangeEventHandler);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
LPSTR tmp = NULL;
|
LPSTR tmp = NULL;
|
||||||
|
|
||||||
LPSTR tr_esc_str(LPSTR arg)
|
LPSTR tr_esc_str(LPCSTR arg)
|
||||||
{
|
{
|
||||||
size_t cs = 0, x, ds;
|
size_t cs = 0, x, ds;
|
||||||
size_t s;
|
size_t s;
|
||||||
|
@ -762,6 +762,35 @@ BOOL xf_pre_connect(freerdp* instance)
|
|||||||
settings = instance->settings;
|
settings = instance->settings;
|
||||||
channels = instance->context->channels;
|
channels = instance->context->channels;
|
||||||
|
|
||||||
|
settings->OsMajorType = OSMAJORTYPE_UNIX;
|
||||||
|
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
|
||||||
|
|
||||||
|
ZeroMemory(settings->OrderSupport, 32);
|
||||||
|
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
|
||||||
|
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
|
||||||
|
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
|
||||||
|
settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
|
||||||
|
settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
|
||||||
|
settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
|
||||||
|
settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
|
||||||
|
settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
|
||||||
|
settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
|
||||||
|
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
|
||||||
|
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
|
||||||
|
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
|
||||||
|
settings->OrderSupport[NEG_MEMBLT_INDEX] = settings->BitmapCacheEnabled;
|
||||||
|
settings->OrderSupport[NEG_MEM3BLT_INDEX] = (settings->SoftwareGdi) ? TRUE : FALSE;
|
||||||
|
settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = settings->BitmapCacheEnabled;
|
||||||
|
settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
|
||||||
|
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
|
||||||
|
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
|
||||||
|
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
|
||||||
|
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
|
||||||
|
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
|
||||||
|
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
|
||||||
|
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
|
||||||
|
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
|
||||||
|
|
||||||
xfc->UseXThreads = TRUE;
|
xfc->UseXThreads = TRUE;
|
||||||
|
|
||||||
if (xfc->UseXThreads)
|
if (xfc->UseXThreads)
|
||||||
@ -1728,37 +1757,6 @@ void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void xf_ParamChangeEventHandler(rdpContext* context, ParamChangeEventArgs* e)
|
|
||||||
{
|
|
||||||
|
|
||||||
xfContext* xfc = (xfContext*) context;
|
|
||||||
|
|
||||||
switch (e->id)
|
|
||||||
{
|
|
||||||
case FreeRDP_ScalingFactor:
|
|
||||||
|
|
||||||
xfc->currentWidth = xfc->originalWidth * xfc->settings->ScalingFactor;
|
|
||||||
xfc->currentHeight = xfc->originalHeight * xfc->settings->ScalingFactor;
|
|
||||||
|
|
||||||
xf_transform_window(xfc);
|
|
||||||
|
|
||||||
{
|
|
||||||
ResizeWindowEventArgs e;
|
|
||||||
|
|
||||||
EventArgsInit(&e, "xfreerdp");
|
|
||||||
e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
|
|
||||||
e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
|
|
||||||
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
|
|
||||||
}
|
|
||||||
xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChangeEventArgs* e)
|
static void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChangeEventArgs* e)
|
||||||
{
|
{
|
||||||
xfContext* xfc = (xfContext*) context;
|
xfContext* xfc = (xfContext*) context;
|
||||||
@ -1870,36 +1868,7 @@ static int xfreerdp_client_new(freerdp* instance, rdpContext* context)
|
|||||||
settings = instance->settings;
|
settings = instance->settings;
|
||||||
xfc->settings = instance->context->settings;
|
xfc->settings = instance->context->settings;
|
||||||
|
|
||||||
settings->OsMajorType = OSMAJORTYPE_UNIX;
|
|
||||||
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
|
|
||||||
|
|
||||||
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_MEMBLT_INDEX] = settings->BitmapCacheEnabled;
|
|
||||||
settings->OrderSupport[NEG_MEM3BLT_INDEX] = (settings->SoftwareGdi) ? TRUE : FALSE;
|
|
||||||
settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = settings->BitmapCacheEnabled;
|
|
||||||
settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
|
|
||||||
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
|
|
||||||
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE;
|
|
||||||
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
|
|
||||||
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
|
|
||||||
|
|
||||||
PubSub_SubscribeTerminate(context->pubSub, (pTerminateEventHandler) xf_TerminateEventHandler);
|
PubSub_SubscribeTerminate(context->pubSub, (pTerminateEventHandler) xf_TerminateEventHandler);
|
||||||
PubSub_SubscribeParamChange(context->pubSub, (pParamChangeEventHandler) xf_ParamChangeEventHandler);
|
|
||||||
PubSub_SubscribeScalingFactorChange(context->pubSub, (pScalingFactorChangeEventHandler) xf_ScalingFactorChangeEventHandler);
|
PubSub_SubscribeScalingFactorChange(context->pubSub, (pScalingFactorChangeEventHandler) xf_ScalingFactorChangeEventHandler);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -830,11 +830,11 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
|
|||||||
|
|
||||||
switch (polygon_cb->fillMode)
|
switch (polygon_cb->fillMode)
|
||||||
{
|
{
|
||||||
case 1: /* alternate */
|
case GDI_FILL_ALTERNATE: /* alternate */
|
||||||
XSetFillRule(xfc->display, xfc->gc, EvenOddRule);
|
XSetFillRule(xfc->display, xfc->gc, EvenOddRule);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /* winding */
|
case GDI_FILL_WINDING: /* winding */
|
||||||
XSetFillRule(xfc->display, xfc->gc, WindingRule);
|
XSetFillRule(xfc->display, xfc->gc, WindingRule);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
|||||||
{
|
{
|
||||||
status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
|
status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
|
||||||
|
|
||||||
if (status == FALSE)
|
if (!status)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "xf_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
fprintf(stderr, "xf_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,6 @@
|
|||||||
set(MODULE_NAME "freerdp-client")
|
set(MODULE_NAME "freerdp-client")
|
||||||
set(MODULE_PREFIX "FREERDP_CLIENT")
|
set(MODULE_PREFIX "FREERDP_CLIENT")
|
||||||
|
|
||||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
|
||||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
|
||||||
|
|
||||||
set(${MODULE_PREFIX}_SRCS
|
set(${MODULE_PREFIX}_SRCS
|
||||||
client.c
|
client.c
|
||||||
cmdline.c
|
cmdline.c
|
||||||
@ -40,6 +37,9 @@ endif()
|
|||||||
|
|
||||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||||
|
|
||||||
|
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||||
|
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||||
|
|
||||||
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION} PREFIX "lib")
|
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION} PREFIX "lib")
|
||||||
|
|
||||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
||||||
@ -53,7 +53,10 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHI
|
|||||||
MODULE winpr
|
MODULE winpr
|
||||||
MODULES winpr-crt winpr-utils)
|
MODULES winpr-crt winpr-utils)
|
||||||
|
|
||||||
|
if(NOT WIN32)
|
||||||
set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "")
|
set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "")
|
||||||
|
set_target_properties(${MODULE_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES "")
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ int freerdp_client_settings_parse_connection_file(rdpSettings* settings, const c
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int freerdp_client_settings_parse_connection_file_buffer(rdpSettings* settings, BYTE* buffer, size_t size)
|
int freerdp_client_settings_parse_connection_file_buffer(rdpSettings* settings, const BYTE* buffer, size_t size)
|
||||||
{
|
{
|
||||||
rdpFile* file;
|
rdpFile* file;
|
||||||
int status = -1;
|
int status = -1;
|
||||||
@ -151,22 +151,19 @@ int freerdp_client_settings_parse_connection_file_buffer(rdpSettings* settings,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int freerdp_client_settings_write_connection_file(rdpSettings* settings, const char* filename, BOOL unicode)
|
int freerdp_client_settings_write_connection_file(const rdpSettings* settings, const char* filename, BOOL unicode)
|
||||||
{
|
{
|
||||||
rdpFile* file;
|
rdpFile* file;
|
||||||
int status = -1;
|
|
||||||
|
|
||||||
file = freerdp_client_rdp_file_new();
|
file = freerdp_client_rdp_file_new();
|
||||||
|
|
||||||
if (freerdp_client_populate_rdp_file_from_settings(file, settings))
|
if (!freerdp_client_populate_rdp_file_from_settings(file, settings))
|
||||||
{
|
return -1;
|
||||||
if (freerdp_client_write_rdp_file(file, filename, unicode))
|
|
||||||
{
|
if (!freerdp_client_write_rdp_file(file, filename, unicode))
|
||||||
status = 0;
|
return -1;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
freerdp_client_rdp_file_free(file);
|
freerdp_client_rdp_file_free(file);
|
||||||
|
|
||||||
return status;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -148,6 +148,8 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
|||||||
{ "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Authenticate only." },
|
{ "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Authenticate only." },
|
||||||
{ "reconnect-cookie", COMMAND_LINE_VALUE_REQUIRED, "<base64 cookie>", NULL, NULL, -1, NULL, "Pass base64 reconnect cookie to the connection" },
|
{ "reconnect-cookie", COMMAND_LINE_VALUE_REQUIRED, "<base64 cookie>", NULL, NULL, -1, NULL, "Pass base64 reconnect cookie to the connection" },
|
||||||
{ "print-reconnect-cookie", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Print base64 reconnect cookie after connecting" },
|
{ "print-reconnect-cookie", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Print base64 reconnect cookie after connecting" },
|
||||||
|
{ "heartbeat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support heartbeat PDUs" },
|
||||||
|
{ "multitransport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support multitransport protocol" },
|
||||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -719,6 +721,15 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT
|
|||||||
freerdp_client_add_dynamic_channel(settings, count, p);
|
freerdp_client_add_dynamic_channel(settings, count, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CommandLineSwitchCase(arg, "heartbeat")
|
||||||
|
{
|
||||||
|
settings->SupportHeartbeatPdu = TRUE;
|
||||||
|
}
|
||||||
|
CommandLineSwitchCase(arg, "multitransport")
|
||||||
|
{
|
||||||
|
settings->SupportMultitransport = TRUE;
|
||||||
|
settings->MultitransportFlags = (TRANSPORT_TYPE_UDP_FECR | TRANSPORT_TYPE_UDP_FECL | TRANSPORT_TYPE_UDP_PREFERRED);
|
||||||
|
}
|
||||||
|
|
||||||
CommandLineSwitchEnd(arg)
|
CommandLineSwitchEnd(arg)
|
||||||
|
|
||||||
@ -990,7 +1001,7 @@ BOOL freerdp_client_detect_command_line(int argc, char** argv, DWORD* flags)
|
|||||||
*flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
|
*flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
|
||||||
*flags |= COMMAND_LINE_SIGIL_ENABLE_DISABLE;
|
*flags |= COMMAND_LINE_SIGIL_ENABLE_DISABLE;
|
||||||
|
|
||||||
if (windows_cli_count > posix_cli_count)
|
if (windows_cli_count >= posix_cli_count)
|
||||||
{
|
{
|
||||||
*flags = COMMAND_LINE_SEPARATOR_COLON;
|
*flags = COMMAND_LINE_SEPARATOR_COLON;
|
||||||
*flags |= COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SIGIL_PLUS_MINUS;
|
*flags |= COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SIGIL_PLUS_MINUS;
|
||||||
@ -1099,7 +1110,6 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
arg = CommandLineFindArgumentA(args, "v");
|
arg = CommandLineFindArgumentA(args, "v");
|
||||||
|
|
||||||
arg = args;
|
arg = args;
|
||||||
@ -1139,10 +1149,6 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
|||||||
settings->PreconnectionBlob = _strdup(arg->Value);
|
settings->PreconnectionBlob = _strdup(arg->Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CommandLineSwitchCase(arg, "port")
|
|
||||||
{
|
|
||||||
settings->ServerPort = atoi(arg->Value);
|
|
||||||
}
|
|
||||||
CommandLineSwitchCase(arg, "w")
|
CommandLineSwitchCase(arg, "w")
|
||||||
{
|
{
|
||||||
settings->DesktopWidth = atoi(arg->Value);
|
settings->DesktopWidth = atoi(arg->Value);
|
||||||
@ -1484,9 +1490,9 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
|||||||
}
|
}
|
||||||
CommandLineSwitchCase(arg, "gdi")
|
CommandLineSwitchCase(arg, "gdi")
|
||||||
{
|
{
|
||||||
if (strcmp(arg->Value, "sw") == 0)
|
if (_stricmp(arg->Value, "sw") == 0)
|
||||||
settings->SoftwareGdi = TRUE;
|
settings->SoftwareGdi = TRUE;
|
||||||
else if (strcmp(arg->Value, "hw") == 0)
|
else if (_stricmp(arg->Value, "hw") == 0)
|
||||||
settings->SoftwareGdi = FALSE;
|
settings->SoftwareGdi = FALSE;
|
||||||
}
|
}
|
||||||
CommandLineSwitchCase(arg, "gfx")
|
CommandLineSwitchCase(arg, "gfx")
|
||||||
@ -1745,6 +1751,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arg = CommandLineFindArgumentA(args, "port");
|
||||||
|
|
||||||
|
if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
|
||||||
|
{
|
||||||
|
settings->ServerPort = atoi(arg->Value);
|
||||||
|
}
|
||||||
|
|
||||||
arg = CommandLineFindArgumentA(args, "p");
|
arg = CommandLineFindArgumentA(args, "p");
|
||||||
|
|
||||||
if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
|
if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
|
||||||
@ -1797,6 +1810,13 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
|
|||||||
settings->AudioCapture = TRUE;
|
settings->AudioCapture = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings->NetworkAutoDetect ||
|
||||||
|
settings->SupportHeartbeatPdu ||
|
||||||
|
settings->SupportMultitransport)
|
||||||
|
{
|
||||||
|
settings->DeviceRedirection = TRUE; /* these RDP 8 features require rdpdr to be registered */
|
||||||
|
}
|
||||||
|
|
||||||
if (settings->RedirectDrives)
|
if (settings->RedirectDrives)
|
||||||
{
|
{
|
||||||
settings->DeviceRedirection = TRUE;
|
settings->DeviceRedirection = TRUE;
|
||||||
|
@ -199,7 +199,12 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
|
|||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
freerdp_client_old_parse_hostname((char*) argv[index], &settings->ServerHostname, &settings->ServerPort);
|
|
||||||
|
if (settings)
|
||||||
|
{
|
||||||
|
freerdp_client_old_parse_hostname((char*) argv[index],
|
||||||
|
&settings->ServerHostname, &settings->ServerPort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -280,12 +285,17 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
|
|||||||
index++;
|
index++;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (settings)
|
||||||
|
{
|
||||||
if (settings->instance)
|
if (settings->instance)
|
||||||
{
|
{
|
||||||
freerdp_client_old_process_plugin(settings, args);
|
freerdp_client_old_process_plugin(settings, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < args->argc; i++)
|
for (i = 0; i < args->argc; i++)
|
||||||
free(args->argv[i]);
|
free(args->argv[i]);
|
||||||
|
@ -49,8 +49,10 @@ static WCHAR CR_LF_STR_W[] = { '\r', '\n', '\0' };
|
|||||||
|
|
||||||
#define INVALID_INTEGER_VALUE 0xFFFFFFFF
|
#define INVALID_INTEGER_VALUE 0xFFFFFFFF
|
||||||
|
|
||||||
BOOL freerdp_client_rdp_file_set_integer(rdpFile* file, char* name, int value)
|
BOOL freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, int value, int index)
|
||||||
{
|
{
|
||||||
|
BOOL bStandard = TRUE;
|
||||||
|
|
||||||
#ifdef DEBUG_CLIENT_FILE
|
#ifdef DEBUG_CLIENT_FILE
|
||||||
fprintf(stderr, "%s:i:%d\n", name, value);
|
fprintf(stderr, "%s:i:%d\n", name, value);
|
||||||
#endif
|
#endif
|
||||||
@ -184,12 +186,26 @@ BOOL freerdp_client_rdp_file_set_integer(rdpFile* file, char* name, int value)
|
|||||||
else if (_stricmp(name, "rdgiskdcproxy") == 0)
|
else if (_stricmp(name, "rdgiskdcproxy") == 0)
|
||||||
file->RdgIsKdcProxy = value;
|
file->RdgIsKdcProxy = value;
|
||||||
else
|
else
|
||||||
return FALSE;
|
bStandard = FALSE;
|
||||||
|
|
||||||
return TRUE;
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
file->lines[index].name = _strdup(name);
|
||||||
|
file->lines[index].iValue = (DWORD) value;
|
||||||
|
|
||||||
|
file->lines[index].flags = RDP_FILE_LINE_FLAG_FORMATTED;
|
||||||
|
file->lines[index].flags |= RDP_FILE_LINE_FLAG_TYPE_INTEGER;
|
||||||
|
|
||||||
|
if (bStandard)
|
||||||
|
file->lines[index].flags |= RDP_FILE_LINE_FLAG_STANDARD;
|
||||||
|
|
||||||
|
file->lines[index].valueLength = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freerdp_client_parse_rdp_file_integer_unicode(rdpFile* file, WCHAR* name, WCHAR* value)
|
return bStandard;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freerdp_client_parse_rdp_file_integer_unicode(rdpFile* file, WCHAR* name, WCHAR* value, int index)
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
int ivalue;
|
int ivalue;
|
||||||
@ -207,20 +223,22 @@ void freerdp_client_parse_rdp_file_integer_unicode(rdpFile* file, WCHAR* name, W
|
|||||||
valueA[length] = '\0';
|
valueA[length] = '\0';
|
||||||
|
|
||||||
ivalue = atoi(valueA);
|
ivalue = atoi(valueA);
|
||||||
freerdp_client_rdp_file_set_integer(file, nameA, ivalue);
|
freerdp_client_rdp_file_set_integer(file, nameA, ivalue, index);
|
||||||
|
|
||||||
free(nameA);
|
free(nameA);
|
||||||
free(valueA);
|
free(valueA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freerdp_client_parse_rdp_file_integer_ascii(rdpFile* file, char* name, char* value)
|
void freerdp_client_parse_rdp_file_integer_ascii(rdpFile* file, const char* name, const char* value, int index)
|
||||||
{
|
{
|
||||||
int ivalue = atoi(value);
|
int ivalue = atoi(value);
|
||||||
freerdp_client_rdp_file_set_integer(file, name, ivalue);
|
freerdp_client_rdp_file_set_integer(file, name, ivalue, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL freerdp_client_rdp_file_set_string(rdpFile* file, char* name, char* value)
|
BOOL freerdp_client_rdp_file_set_string(rdpFile* file, const char* name, const char* value, int index)
|
||||||
{
|
{
|
||||||
|
BOOL bStandard = TRUE;
|
||||||
|
|
||||||
#ifdef DEBUG_CLIENT_FILE
|
#ifdef DEBUG_CLIENT_FILE
|
||||||
fprintf(stderr, "%s:s:%s\n", name, value);
|
fprintf(stderr, "%s:s:%s\n", name, value);
|
||||||
#endif
|
#endif
|
||||||
@ -264,9 +282,23 @@ BOOL freerdp_client_rdp_file_set_string(rdpFile* file, char* name, char* value)
|
|||||||
else if (_stricmp(name, "winposstr") == 0)
|
else if (_stricmp(name, "winposstr") == 0)
|
||||||
file->WinPosStr = _strdup(value);
|
file->WinPosStr = _strdup(value);
|
||||||
else
|
else
|
||||||
return FALSE;
|
bStandard = FALSE;
|
||||||
|
|
||||||
return TRUE;
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
file->lines[index].name = _strdup(name);
|
||||||
|
file->lines[index].sValue = _strdup(value);
|
||||||
|
|
||||||
|
file->lines[index].flags = RDP_FILE_LINE_FLAG_FORMATTED;
|
||||||
|
file->lines[index].flags |= RDP_FILE_LINE_FLAG_TYPE_STRING;
|
||||||
|
|
||||||
|
if (bStandard)
|
||||||
|
file->lines[index].flags |= RDP_FILE_LINE_FLAG_STANDARD;
|
||||||
|
|
||||||
|
file->lines[index].valueLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bStandard;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freerdp_client_add_option(rdpFile* file, char* option)
|
void freerdp_client_add_option(rdpFile* file, char* option)
|
||||||
@ -281,7 +313,41 @@ void freerdp_client_add_option(rdpFile* file, char* option)
|
|||||||
(file->argc)++;
|
(file->argc)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, WCHAR* name, WCHAR* value)
|
int freerdp_client_parse_rdp_file_add_line(rdpFile* file, char* line, int index)
|
||||||
|
{
|
||||||
|
if (index < 0)
|
||||||
|
index = file->lineCount;
|
||||||
|
|
||||||
|
while ((file->lineCount + 1) > file->lineSize)
|
||||||
|
{
|
||||||
|
file->lineSize *= 2;
|
||||||
|
file->lines = (rdpFileLine*) realloc(file->lines, file->lineSize * sizeof(rdpFileLine));
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(&(file->lines[file->lineCount]), sizeof(rdpFileLine));
|
||||||
|
file->lines[file->lineCount].text = _strdup(line);
|
||||||
|
file->lines[file->lineCount].index = index;
|
||||||
|
(file->lineCount)++;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freerdp_client_parse_rdp_file_add_line_unicode(rdpFile* file, WCHAR* line, int index)
|
||||||
|
{
|
||||||
|
char* lineA = NULL;
|
||||||
|
|
||||||
|
ConvertFromUnicode(CP_UTF8, 0, line, -1, &lineA, 0, NULL, NULL);
|
||||||
|
freerdp_client_parse_rdp_file_add_line(file, lineA, index);
|
||||||
|
|
||||||
|
free(lineA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void freerdp_client_parse_rdp_file_add_line_ascii(rdpFile* file, char* line, int index)
|
||||||
|
{
|
||||||
|
freerdp_client_parse_rdp_file_add_line(file, line, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, WCHAR* name, WCHAR* value, int index)
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
char* nameA;
|
char* nameA;
|
||||||
@ -297,18 +363,20 @@ void freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, WCHAR* name, WC
|
|||||||
WideCharToMultiByte(CP_UTF8, 0, value, length, valueA, length, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, value, length, valueA, length, NULL, NULL);
|
||||||
valueA[length] = '\0';
|
valueA[length] = '\0';
|
||||||
|
|
||||||
freerdp_client_rdp_file_set_string(file, nameA, valueA);
|
freerdp_client_rdp_file_set_string(file, nameA, valueA, index);
|
||||||
|
|
||||||
free(nameA);
|
free(nameA);
|
||||||
free(valueA);
|
free(valueA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freerdp_client_parse_rdp_file_string_ascii(rdpFile* file, char* name, char* value)
|
void freerdp_client_parse_rdp_file_string_ascii(rdpFile* file, char* name, char* value, int index)
|
||||||
{
|
{
|
||||||
freerdp_client_rdp_file_set_string(file, name, value);
|
char* valueA = _strdup(value);
|
||||||
|
freerdp_client_rdp_file_set_string(file, name, valueA, index);
|
||||||
|
free(valueA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freerdp_client_parse_rdp_file_option_unicode(rdpFile* file, WCHAR* option)
|
void freerdp_client_parse_rdp_file_option_unicode(rdpFile* file, WCHAR* option, int index)
|
||||||
{
|
{
|
||||||
char* optionA = NULL;
|
char* optionA = NULL;
|
||||||
|
|
||||||
@ -318,13 +386,14 @@ void freerdp_client_parse_rdp_file_option_unicode(rdpFile* file, WCHAR* option)
|
|||||||
free(optionA);
|
free(optionA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freerdp_client_parse_rdp_file_option_ascii(rdpFile* file, char* option)
|
void freerdp_client_parse_rdp_file_option_ascii(rdpFile* file, char* option, int index)
|
||||||
{
|
{
|
||||||
freerdp_client_add_option(file, option);
|
freerdp_client_add_option(file, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, BYTE* buffer, size_t size)
|
BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, const BYTE* buffer, size_t size)
|
||||||
{
|
{
|
||||||
|
int index;
|
||||||
int length;
|
int length;
|
||||||
char* line;
|
char* line;
|
||||||
char* type;
|
char* type;
|
||||||
@ -333,6 +402,7 @@ BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, BYTE* buffer, siz
|
|||||||
char *beg, *end;
|
char *beg, *end;
|
||||||
char *name, *value;
|
char *name, *value;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
line = strtok_s((char*) buffer, "\r\n", &context);
|
line = strtok_s((char*) buffer, "\r\n", &context);
|
||||||
|
|
||||||
while (line)
|
while (line)
|
||||||
@ -344,9 +414,11 @@ BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, BYTE* buffer, siz
|
|||||||
beg = line;
|
beg = line;
|
||||||
end = &line[length - 1];
|
end = &line[length - 1];
|
||||||
|
|
||||||
|
freerdp_client_parse_rdp_file_add_line_ascii(file, line, index);
|
||||||
|
|
||||||
if (beg[0] == '/')
|
if (beg[0] == '/')
|
||||||
{
|
{
|
||||||
freerdp_client_parse_rdp_file_option_ascii(file, line);
|
freerdp_client_parse_rdp_file_option_ascii(file, line, index);
|
||||||
goto next_line; /* FreeRDP option */
|
goto next_line; /* FreeRDP option */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,8 +436,6 @@ BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, BYTE* buffer, siz
|
|||||||
if ((d2 - d1) != 2)
|
if ((d2 - d1) != 2)
|
||||||
goto next_line; /* improper type length */
|
goto next_line; /* improper type length */
|
||||||
|
|
||||||
if (d2 == end)
|
|
||||||
goto next_line; /* no value */
|
|
||||||
|
|
||||||
*d1 = 0;
|
*d1 = 0;
|
||||||
*d2 = 0;
|
*d2 = 0;
|
||||||
@ -375,12 +445,12 @@ BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, BYTE* buffer, siz
|
|||||||
if (*type == 'i')
|
if (*type == 'i')
|
||||||
{
|
{
|
||||||
/* integer type */
|
/* integer type */
|
||||||
freerdp_client_parse_rdp_file_integer_ascii(file, name, value);
|
freerdp_client_parse_rdp_file_integer_ascii(file, name, value, index);
|
||||||
}
|
}
|
||||||
else if (*type == 's')
|
else if (*type == 's')
|
||||||
{
|
{
|
||||||
/* string type */
|
/* string type */
|
||||||
freerdp_client_parse_rdp_file_string_ascii(file, name, value);
|
freerdp_client_parse_rdp_file_string_ascii(file, name, value, index);
|
||||||
}
|
}
|
||||||
else if (*type == 'b')
|
else if (*type == 'b')
|
||||||
{
|
{
|
||||||
@ -390,13 +460,15 @@ BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, BYTE* buffer, siz
|
|||||||
|
|
||||||
next_line:
|
next_line:
|
||||||
line = strtok_s(NULL, "\r\n", &context);
|
line = strtok_s(NULL, "\r\n", &context);
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, BYTE* buffer, size_t size)
|
BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, const BYTE* buffer, size_t size)
|
||||||
{
|
{
|
||||||
|
int index;
|
||||||
int length;
|
int length;
|
||||||
WCHAR* line;
|
WCHAR* line;
|
||||||
WCHAR* type;
|
WCHAR* type;
|
||||||
@ -405,6 +477,7 @@ BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, BYTE* buffer, s
|
|||||||
WCHAR *beg, *end;
|
WCHAR *beg, *end;
|
||||||
WCHAR *name, *value;
|
WCHAR *name, *value;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
line = wcstok_s((WCHAR*) buffer, CR_LF_STR_W, &context);
|
line = wcstok_s((WCHAR*) buffer, CR_LF_STR_W, &context);
|
||||||
|
|
||||||
while (line != NULL)
|
while (line != NULL)
|
||||||
@ -416,10 +489,12 @@ BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, BYTE* buffer, s
|
|||||||
beg = line;
|
beg = line;
|
||||||
end = &line[length - 1];
|
end = &line[length - 1];
|
||||||
|
|
||||||
|
freerdp_client_parse_rdp_file_add_line_unicode(file, line, index);
|
||||||
|
|
||||||
if (beg[0] == '/')
|
if (beg[0] == '/')
|
||||||
{
|
{
|
||||||
/* FreeRDP option */
|
/* FreeRDP option */
|
||||||
freerdp_client_parse_rdp_file_option_unicode(file, line);
|
freerdp_client_parse_rdp_file_option_unicode(file, line, index);
|
||||||
goto next_line;
|
goto next_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,8 +512,6 @@ BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, BYTE* buffer, s
|
|||||||
if ((d2 - d1) != 2)
|
if ((d2 - d1) != 2)
|
||||||
goto next_line; /* improper type length */
|
goto next_line; /* improper type length */
|
||||||
|
|
||||||
if (d2 == end)
|
|
||||||
goto next_line; /* no value */
|
|
||||||
|
|
||||||
*d1 = 0;
|
*d1 = 0;
|
||||||
*d2 = 0;
|
*d2 = 0;
|
||||||
@ -448,12 +521,12 @@ BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, BYTE* buffer, s
|
|||||||
if (*type == 'i')
|
if (*type == 'i')
|
||||||
{
|
{
|
||||||
/* integer type */
|
/* integer type */
|
||||||
freerdp_client_parse_rdp_file_integer_unicode(file, name, value);
|
freerdp_client_parse_rdp_file_integer_unicode(file, name, value, index);
|
||||||
}
|
}
|
||||||
else if (*type == 's')
|
else if (*type == 's')
|
||||||
{
|
{
|
||||||
/* string type */
|
/* string type */
|
||||||
freerdp_client_parse_rdp_file_string_unicode(file, name, value);
|
freerdp_client_parse_rdp_file_string_unicode(file, name, value, index);
|
||||||
}
|
}
|
||||||
else if (*type == 'b')
|
else if (*type == 'b')
|
||||||
{
|
{
|
||||||
@ -463,12 +536,13 @@ BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, BYTE* buffer, s
|
|||||||
|
|
||||||
next_line:
|
next_line:
|
||||||
line = wcstok_s(NULL, CR_LF_STR_W, &context);
|
line = wcstok_s(NULL, CR_LF_STR_W, &context);
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, BYTE* buffer, size_t size)
|
BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, const BYTE* buffer, size_t size)
|
||||||
{
|
{
|
||||||
if (size < 2)
|
if (size < 2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -532,13 +606,14 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name)
|
|||||||
#define WRITE_ALL_SETTINGS TRUE
|
#define WRITE_ALL_SETTINGS TRUE
|
||||||
#define SETTING_MODIFIED(_settings, _field) (WRITE_ALL_SETTINGS || _settings->SettingsModified[FreeRDP_##_field])
|
#define SETTING_MODIFIED(_settings, _field) (WRITE_ALL_SETTINGS || _settings->SettingsModified[FreeRDP_##_field])
|
||||||
#define SETTING_MODIFIED_SET(_target, _settings, _field) if SETTING_MODIFIED(_settings, _field) _target = _settings->_field
|
#define SETTING_MODIFIED_SET(_target, _settings, _field) if SETTING_MODIFIED(_settings, _field) _target = _settings->_field
|
||||||
|
#define SETTING_MODIFIED_SET_STRING(_target, _settings, _field) if SETTING_MODIFIED(_settings, _field) _target = _strdup(_settings->_field)
|
||||||
|
|
||||||
BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings* settings)
|
BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSettings* settings)
|
||||||
{
|
{
|
||||||
SETTING_MODIFIED_SET(file->Domain, settings, Domain);
|
SETTING_MODIFIED_SET_STRING(file->Domain, settings, Domain);
|
||||||
SETTING_MODIFIED_SET(file->Username, settings, Username);
|
SETTING_MODIFIED_SET_STRING(file->Username, settings, Username);
|
||||||
SETTING_MODIFIED_SET(file->ServerPort, settings, ServerPort);
|
SETTING_MODIFIED_SET(file->ServerPort, settings, ServerPort);
|
||||||
SETTING_MODIFIED_SET(file->FullAddress, settings, ServerHostname);
|
SETTING_MODIFIED_SET_STRING(file->FullAddress, settings, ServerHostname);
|
||||||
SETTING_MODIFIED_SET(file->DesktopWidth, settings, DesktopWidth);
|
SETTING_MODIFIED_SET(file->DesktopWidth, settings, DesktopWidth);
|
||||||
SETTING_MODIFIED_SET(file->DesktopHeight, settings, DesktopHeight);
|
SETTING_MODIFIED_SET(file->DesktopHeight, settings, DesktopHeight);
|
||||||
SETTING_MODIFIED_SET(file->SessionBpp, settings, ColorDepth);
|
SETTING_MODIFIED_SET(file->SessionBpp, settings, ColorDepth);
|
||||||
@ -546,8 +621,8 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings*
|
|||||||
SETTING_MODIFIED_SET(file->AdministrativeSession, settings, ConsoleSession);
|
SETTING_MODIFIED_SET(file->AdministrativeSession, settings, ConsoleSession);
|
||||||
SETTING_MODIFIED_SET(file->NegotiateSecurityLayer, settings, NegotiateSecurityLayer);
|
SETTING_MODIFIED_SET(file->NegotiateSecurityLayer, settings, NegotiateSecurityLayer);
|
||||||
SETTING_MODIFIED_SET(file->EnableCredSSPSupport, settings, NlaSecurity);
|
SETTING_MODIFIED_SET(file->EnableCredSSPSupport, settings, NlaSecurity);
|
||||||
SETTING_MODIFIED_SET(file->AlternateShell, settings, AlternateShell);
|
SETTING_MODIFIED_SET_STRING(file->AlternateShell, settings, AlternateShell);
|
||||||
SETTING_MODIFIED_SET(file->ShellWorkingDirectory, settings, ShellWorkingDirectory);
|
SETTING_MODIFIED_SET_STRING(file->ShellWorkingDirectory, settings, ShellWorkingDirectory);
|
||||||
SETTING_MODIFIED_SET(file->ConnectionType, settings, ConnectionType);
|
SETTING_MODIFIED_SET(file->ConnectionType, settings, ConnectionType);
|
||||||
|
|
||||||
if (SETTING_MODIFIED(settings, AudioPlayback) || SETTING_MODIFIED(settings, RemoteConsoleAudio))
|
if (SETTING_MODIFIED(settings, AudioPlayback) || SETTING_MODIFIED(settings, RemoteConsoleAudio))
|
||||||
@ -560,17 +635,17 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings*
|
|||||||
file->AudioMode = AUDIO_MODE_NONE;
|
file->AudioMode = AUDIO_MODE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SETTING_MODIFIED_SET(file->GatewayHostname, settings, GatewayHostname);
|
SETTING_MODIFIED_SET_STRING(file->GatewayHostname, settings, GatewayHostname);
|
||||||
SETTING_MODIFIED_SET(file->GatewayUsageMethod, settings, GatewayUsageMethod);
|
SETTING_MODIFIED_SET(file->GatewayUsageMethod, settings, GatewayUsageMethod);
|
||||||
SETTING_MODIFIED_SET(file->PromptCredentialOnce, settings, GatewayUseSameCredentials);
|
SETTING_MODIFIED_SET(file->PromptCredentialOnce, settings, GatewayUseSameCredentials);
|
||||||
|
|
||||||
SETTING_MODIFIED_SET(file->RemoteApplicationMode, settings, RemoteApplicationMode);
|
SETTING_MODIFIED_SET(file->RemoteApplicationMode, settings, RemoteApplicationMode);
|
||||||
SETTING_MODIFIED_SET(file->RemoteApplicationProgram, settings, RemoteApplicationProgram);
|
SETTING_MODIFIED_SET_STRING(file->RemoteApplicationProgram, settings, RemoteApplicationProgram);
|
||||||
SETTING_MODIFIED_SET(file->RemoteApplicationName, settings, RemoteApplicationName);
|
SETTING_MODIFIED_SET_STRING(file->RemoteApplicationName, settings, RemoteApplicationName);
|
||||||
SETTING_MODIFIED_SET(file->RemoteApplicationIcon, settings, RemoteApplicationIcon);
|
SETTING_MODIFIED_SET_STRING(file->RemoteApplicationIcon, settings, RemoteApplicationIcon);
|
||||||
SETTING_MODIFIED_SET(file->RemoteApplicationFile, settings, RemoteApplicationFile);
|
SETTING_MODIFIED_SET_STRING(file->RemoteApplicationFile, settings, RemoteApplicationFile);
|
||||||
SETTING_MODIFIED_SET(file->RemoteApplicationGuid, settings, RemoteApplicationGuid);
|
SETTING_MODIFIED_SET_STRING(file->RemoteApplicationGuid, settings, RemoteApplicationGuid);
|
||||||
SETTING_MODIFIED_SET(file->RemoteApplicationCmdLine, settings, RemoteApplicationCmdLine);
|
SETTING_MODIFIED_SET_STRING(file->RemoteApplicationCmdLine, settings, RemoteApplicationCmdLine);
|
||||||
|
|
||||||
SETTING_MODIFIED_SET(file->SpanMonitors, settings, SpanMonitors);
|
SETTING_MODIFIED_SET(file->SpanMonitors, settings, SpanMonitors);
|
||||||
SETTING_MODIFIED_SET(file->UseMultiMon, settings, UseMultimon);
|
SETTING_MODIFIED_SET(file->UseMultiMon, settings, UseMultimon);
|
||||||
@ -578,138 +653,94 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings*
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL freerdp_client_write_rdp_file(rdpFile* file, const char* name, BOOL unicode)
|
BOOL freerdp_client_write_rdp_file(const rdpFile* file, const char* name, BOOL unicode)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
FILE* fp;
|
||||||
|
int length;
|
||||||
char* buffer;
|
char* buffer;
|
||||||
int len, len2;
|
int status = 0;
|
||||||
FILE* fp = NULL;
|
|
||||||
WCHAR* unicodestr = NULL;
|
WCHAR* unicodestr = NULL;
|
||||||
|
|
||||||
len = freerdp_client_write_rdp_file_buffer(file, NULL, 0);
|
length = freerdp_client_write_rdp_file_buffer(file, NULL, 0);
|
||||||
|
|
||||||
if (len <= 0)
|
if (length < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "freerdp_client_write_rdp_file: Error determining buffer size.\n");
|
fprintf(stderr, "freerdp_client_write_rdp_file: error determining buffer size.\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = (char*) malloc((len + 1) * sizeof(char));
|
buffer = (char*) malloc((length + 1) * sizeof(char));
|
||||||
len2 = freerdp_client_write_rdp_file_buffer(file, buffer, len + 1);
|
|
||||||
|
|
||||||
if (len2 == len)
|
if (freerdp_client_write_rdp_file_buffer(file, buffer, length + 1) != length)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "freerdp_client_write_rdp_file: error writing to output buffer\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
fp = fopen(name, "w+b");
|
fp = fopen(name, "w+b");
|
||||||
|
|
||||||
if (fp != NULL)
|
if (fp)
|
||||||
{
|
{
|
||||||
if (unicode)
|
if (unicode)
|
||||||
{
|
{
|
||||||
ConvertToUnicode(CP_UTF8, 0, buffer, len, &unicodestr, 0);
|
ConvertToUnicode(CP_UTF8, 0, buffer, length, &unicodestr, 0);
|
||||||
|
|
||||||
// Write multi-byte header
|
/* Write multi-byte header */
|
||||||
fwrite(BOM_UTF16_LE, sizeof(BYTE), 2, fp);
|
fwrite(BOM_UTF16_LE, sizeof(BYTE), 2, fp);
|
||||||
fwrite(unicodestr, 2, len, fp);
|
fwrite(unicodestr, 2, length, fp);
|
||||||
|
|
||||||
free(unicodestr);
|
free(unicodestr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fwrite(buffer, 1, len, fp);
|
fwrite(buffer, 1, length, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = fflush(fp);
|
status = fflush(fp);
|
||||||
rc = fclose(fp);
|
status = fclose(fp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer != NULL)
|
if (buffer)
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
return (rc == 0);
|
return (status == 0) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WRITE_RDP_FILE_DECLARE(_file, _buffer, _size) \
|
size_t freerdp_client_write_rdp_file_buffer(const rdpFile* file, char* buffer, size_t size)
|
||||||
rdpFile* __rdpFile = file; \
|
|
||||||
char* __buffer = _buffer; \
|
|
||||||
size_t __size = _size; \
|
|
||||||
size_t __required_size = 0; \
|
|
||||||
int __current = 0; \
|
|
||||||
int __count = 0;
|
|
||||||
|
|
||||||
#define WRITE_RDP_FILE_VALUE_INTEGER(_format, _field) \
|
|
||||||
if (~__rdpFile->_field) \
|
|
||||||
{ \
|
|
||||||
__count = sprintf_s(__buffer == NULL ? NULL : __buffer + __current, __buffer == NULL ? 0 : __size - __required_size, _format, (int) __rdpFile->_field); \
|
|
||||||
__required_size += __count; \
|
|
||||||
__current += __count; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define WRITE_RDP_FILE_VALUE_STRING(_format, _field) \
|
|
||||||
if (~((size_t) __rdpFile->_field) && __rdpFile->_field != NULL) \
|
|
||||||
{ \
|
|
||||||
__count = sprintf_s(__buffer == NULL ? NULL : __buffer + __current, __buffer == NULL ? 0 : __size - __required_size, _format, __rdpFile->_field); \
|
|
||||||
__required_size += __count; \
|
|
||||||
__current += __count; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define WRITE_RDP_FILE_VALUE_RETURN \
|
|
||||||
return __required_size;
|
|
||||||
|
|
||||||
size_t freerdp_client_write_rdp_file_buffer(rdpFile* file, char* buffer, size_t size)
|
|
||||||
{
|
{
|
||||||
WRITE_RDP_FILE_DECLARE(file, buffer, size)
|
int index;
|
||||||
|
int length;
|
||||||
|
char* output;
|
||||||
|
rdpFileLine* line;
|
||||||
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("screen mode id:i:%d\n", ScreenModeId);
|
if (!buffer)
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("use multimon:i:%d\n", UseMultiMon);
|
size = 0;
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("desktopwidth:i:%d\n", DesktopWidth);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("desktopheight:i:%d\n", DesktopHeight);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("session bpp:i:%d\n", SessionBpp);
|
|
||||||
WRITE_RDP_FILE_VALUE_STRING("winposstr:s:%s\n", WinPosStr);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("compression:i:%d\n", Compression);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("keyboardhook:i:%d\n", KeyboardHook);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("audiocapturemode:i:%d\n", AudioCaptureMode);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("videoplaybackmode:i:%d\n", VideoPlaybackMode);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("connection type:i:%d\n", ConnectionType);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("networkautodetect:i:%d\n", NetworkAutoDetect);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("bandwidthautodetect:i:%d\n", BandwidthAutoDetect);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("displayconnectionbar:i:%d\n", DisplayConnectionBar);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("enableworkspacereconnect:i:%d\n", EnableWorkspaceReconnect);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("disable wallpaper:i:%d\n", DisableWallpaper);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("allow font smoothing:i:%d\n", AllowFontSmoothing);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("allow desktop composition:i:%d\n", AllowDesktopComposition);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("disable full window drag:i:%d\n", DisableFullWindowDrag);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("disable menu anims:i:%d\n", DisableMenuAnims);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("disable themes:i:%d\n", DisableThemes);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("disable cursor setting:i:%d\n", DisableCursorSetting);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("bitmapcachepersistenable:i:%d\n", BitmapCachePersistEnable);
|
|
||||||
WRITE_RDP_FILE_VALUE_STRING("full address:s:%s\n", FullAddress);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("audiomode:i:%d\n", AudioMode);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("redirectprinters:i:%d\n", RedirectPrinters);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("redirectcomports:i:%d\n", RedirectComPorts);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("redirectsmartcards:i:%d\n", RedirectSmartCards);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("redirectclipboard:i:%d\n", RedirectClipboard);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("redirectposdevices:i:%d\n", RedirectPosDevices);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("autoreconnection enabled:i:%d\n", AutoReconnectionEnabled);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("authentication level:i:%d\n", AuthenticationLevel);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("prompt for credentials:i:%d\n", PromptForCredentials);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("negotiate security layer:i:%d\n", NegotiateSecurityLayer);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("remoteapplicationmode:i:%d\n", RemoteApplicationMode);
|
|
||||||
WRITE_RDP_FILE_VALUE_STRING("alternate shell:s:%s\n", AlternateShell);
|
|
||||||
WRITE_RDP_FILE_VALUE_STRING("shell working directory:s:%s\n", ShellWorkingDirectory);
|
|
||||||
WRITE_RDP_FILE_VALUE_STRING("gatewayhostname:s:%s\n", GatewayHostname);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("gatewayusagemethod:i:%d\n", GatewayUsageMethod);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("gatewaycredentialssource:i:%d\n", GatewayCredentialsSource);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("gatewayprofileusagemethod:i:%d\n", GatewayProfileUsageMethod);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("promptcredentialonce:i:%d\n", PromptCredentialOnce);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("use redirection server name:i:%d\n", UseRedirectionServerName);
|
|
||||||
WRITE_RDP_FILE_VALUE_INTEGER("rdgiskdcproxy:i:%d\n", RdgIsKdcProxy);
|
|
||||||
WRITE_RDP_FILE_VALUE_STRING("kdcproxyname:s:%s\n", KdcProxyName);
|
|
||||||
WRITE_RDP_FILE_VALUE_STRING("drivestoredirect:s:%s\n", DrivesToRedirect);
|
|
||||||
WRITE_RDP_FILE_VALUE_STRING("username:s:%s\n", Username);
|
|
||||||
WRITE_RDP_FILE_VALUE_STRING("domain:s:%s\n", Domain);
|
|
||||||
|
|
||||||
WRITE_RDP_FILE_VALUE_RETURN
|
output = buffer;
|
||||||
|
|
||||||
|
for (index = 0; index < file->lineCount; index++)
|
||||||
|
{
|
||||||
|
line = &(file->lines[index]);
|
||||||
|
|
||||||
|
length = strlen(line->text);
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
{
|
||||||
|
size += length + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyMemory(output, line->text, length);
|
||||||
|
output += length;
|
||||||
|
*output = '\n';
|
||||||
|
output++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
size = (output - buffer);
|
||||||
|
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* settings)
|
BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* settings)
|
||||||
@ -846,7 +877,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (~file->PromptCredentialOnce)
|
if (~file->PromptCredentialOnce)
|
||||||
freerdp_set_param_bool(settings, FreeRDP_GatewayUseSameCredentials, TRUE);
|
freerdp_set_param_bool(settings, FreeRDP_GatewayUseSameCredentials, file->PromptCredentialOnce);
|
||||||
|
|
||||||
if (~file->RemoteApplicationMode)
|
if (~file->RemoteApplicationMode)
|
||||||
freerdp_set_param_bool(settings, FreeRDP_RemoteApplicationMode, file->RemoteApplicationMode);
|
freerdp_set_param_bool(settings, FreeRDP_RemoteApplicationMode, file->RemoteApplicationMode);
|
||||||
@ -858,8 +889,6 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
|
|||||||
freerdp_set_param_string(settings, FreeRDP_RemoteApplicationIcon, file->RemoteApplicationIcon);
|
freerdp_set_param_string(settings, FreeRDP_RemoteApplicationIcon, file->RemoteApplicationIcon);
|
||||||
if (~((size_t) file->RemoteApplicationFile))
|
if (~((size_t) file->RemoteApplicationFile))
|
||||||
freerdp_set_param_string(settings, FreeRDP_RemoteApplicationGuid, file->RemoteApplicationGuid);
|
freerdp_set_param_string(settings, FreeRDP_RemoteApplicationGuid, file->RemoteApplicationGuid);
|
||||||
if (~((size_t) file->RemoteApplicationGuid))
|
|
||||||
freerdp_set_param_string(settings, FreeRDP_RemoteApplicationGuid, file->RemoteApplicationGuid);
|
|
||||||
if (~((size_t) file->RemoteApplicationCmdLine))
|
if (~((size_t) file->RemoteApplicationCmdLine))
|
||||||
freerdp_set_param_string(settings, FreeRDP_RemoteApplicationCmdLine, file->RemoteApplicationCmdLine);
|
freerdp_set_param_string(settings, FreeRDP_RemoteApplicationCmdLine, file->RemoteApplicationCmdLine);
|
||||||
|
|
||||||
@ -879,7 +908,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
|
|||||||
if (~file->DisableThemes)
|
if (~file->DisableThemes)
|
||||||
freerdp_set_param_bool(settings, FreeRDP_DisableThemes, file->DisableThemes);
|
freerdp_set_param_bool(settings, FreeRDP_DisableThemes, file->DisableThemes);
|
||||||
if (~file->AllowDesktopComposition)
|
if (~file->AllowDesktopComposition)
|
||||||
freerdp_set_param_bool(settings, FreeRDP_DisableCursorShadow, file->AllowDesktopComposition);
|
freerdp_set_param_bool(settings, FreeRDP_AllowDesktopComposition, file->AllowDesktopComposition);
|
||||||
|
|
||||||
if (~file->BitmapCachePersistEnable)
|
if (~file->BitmapCachePersistEnable)
|
||||||
freerdp_set_param_bool(settings, FreeRDP_BitmapCachePersistEnabled, file->BitmapCachePersistEnable);
|
freerdp_set_param_bool(settings, FreeRDP_BitmapCachePersistEnabled, file->BitmapCachePersistEnable);
|
||||||
@ -965,12 +994,147 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
|
|||||||
|
|
||||||
if (file->argc > 1)
|
if (file->argc > 1)
|
||||||
{
|
{
|
||||||
|
char* ConnectionFile = settings->ConnectionFile;
|
||||||
|
|
||||||
|
settings->ConnectionFile = NULL;
|
||||||
freerdp_client_settings_parse_command_line(settings, file->argc, file->argv);
|
freerdp_client_settings_parse_command_line(settings, file->argc, file->argv);
|
||||||
|
settings->ConnectionFile = ConnectionFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rdpFileLine* freerdp_client_rdp_file_find_line_index(rdpFile* file, int index)
|
||||||
|
{
|
||||||
|
rdpFileLine* line;
|
||||||
|
|
||||||
|
line = &(file->lines[index]);
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdpFileLine* freerdp_client_rdp_file_find_line_by_name(rdpFile* file, const char* name)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
BOOL bFound = FALSE;
|
||||||
|
rdpFileLine* line = NULL;
|
||||||
|
|
||||||
|
for (index = 0; index < file->lineCount; index++)
|
||||||
|
{
|
||||||
|
line = &(file->lines[index]);
|
||||||
|
|
||||||
|
if (line->flags & RDP_FILE_LINE_FLAG_FORMATTED)
|
||||||
|
{
|
||||||
|
if (strcmp(name, line->name) == 0)
|
||||||
|
{
|
||||||
|
bFound = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bFound) ? line : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_client_rdp_file_set_string_option(rdpFile* file, const char* name, const char* value)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
int length;
|
||||||
|
char* text;
|
||||||
|
rdpFileLine* line;
|
||||||
|
|
||||||
|
line = freerdp_client_rdp_file_find_line_by_name(file, name);
|
||||||
|
|
||||||
|
length = _scprintf("%s:s:%s", name, value);
|
||||||
|
text = (char*) malloc(length + 1);
|
||||||
|
sprintf_s(text, length + 1, "%s:s:%s", name, value ? value : "");
|
||||||
|
text[length] = '\0';
|
||||||
|
|
||||||
|
if (line)
|
||||||
|
{
|
||||||
|
free(line->sValue);
|
||||||
|
line->sValue = _strdup(value);
|
||||||
|
|
||||||
|
free(line->text);
|
||||||
|
line->text = text;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = freerdp_client_parse_rdp_file_add_line(file, text, -1);
|
||||||
|
line = freerdp_client_rdp_file_find_line_index(file, index);
|
||||||
|
|
||||||
|
freerdp_client_rdp_file_set_string(file, name, value, index);
|
||||||
|
|
||||||
|
free(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* freerdp_client_rdp_file_get_string_option(rdpFile* file, const char* name)
|
||||||
|
{
|
||||||
|
rdpFileLine* line;
|
||||||
|
|
||||||
|
line = freerdp_client_rdp_file_find_line_by_name(file, name);
|
||||||
|
|
||||||
|
if (!line)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!(line->flags & RDP_FILE_LINE_FLAG_TYPE_STRING))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return line->sValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_client_rdp_file_set_integer_option(rdpFile* file, const char* name, int value)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
int length;
|
||||||
|
char* text;
|
||||||
|
rdpFileLine* line;
|
||||||
|
|
||||||
|
line = freerdp_client_rdp_file_find_line_by_name(file, name);
|
||||||
|
|
||||||
|
length = _scprintf("%s:i:%d", name, value);
|
||||||
|
text = (char*) malloc(length + 1);
|
||||||
|
sprintf_s(text, length + 1, "%s:i:%d", name, value);
|
||||||
|
text[length] = '\0';
|
||||||
|
|
||||||
|
if (line)
|
||||||
|
{
|
||||||
|
line->iValue = value;
|
||||||
|
|
||||||
|
free(line->text);
|
||||||
|
line->text = text;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = freerdp_client_parse_rdp_file_add_line(file, text, -1);
|
||||||
|
line = freerdp_client_rdp_file_find_line_index(file, index);
|
||||||
|
|
||||||
|
freerdp_client_rdp_file_set_integer(file, (char*) name, value, index);
|
||||||
|
|
||||||
|
free(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_client_rdp_file_get_integer_option(rdpFile* file, const char* name)
|
||||||
|
{
|
||||||
|
rdpFileLine* line;
|
||||||
|
|
||||||
|
line = freerdp_client_rdp_file_find_line_by_name(file, name);
|
||||||
|
|
||||||
|
if (!line)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!(line->flags & RDP_FILE_LINE_FLAG_TYPE_INTEGER))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return line->iValue;
|
||||||
|
}
|
||||||
|
|
||||||
void freerdp_client_file_string_check_free(LPSTR str)
|
void freerdp_client_file_string_check_free(LPSTR str)
|
||||||
{
|
{
|
||||||
if (~((size_t) str))
|
if (~((size_t) str))
|
||||||
@ -987,6 +1151,10 @@ rdpFile* freerdp_client_rdp_file_new()
|
|||||||
{
|
{
|
||||||
FillMemory(file, sizeof(rdpFile), 0xFF);
|
FillMemory(file, sizeof(rdpFile), 0xFF);
|
||||||
|
|
||||||
|
file->lineCount = 0;
|
||||||
|
file->lineSize = 32;
|
||||||
|
file->lines = (rdpFileLine*) malloc(file->lineSize * sizeof(rdpFileLine));
|
||||||
|
|
||||||
file->argc = 0;
|
file->argc = 0;
|
||||||
file->argSize = 32;
|
file->argSize = 32;
|
||||||
file->argv = (char**) malloc(file->argSize * sizeof(char*));
|
file->argv = (char**) malloc(file->argSize * sizeof(char*));
|
||||||
@ -1003,6 +1171,18 @@ void freerdp_client_rdp_file_free(rdpFile* file)
|
|||||||
|
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
|
if (file->lineCount)
|
||||||
|
{
|
||||||
|
for (i = 0; i < file->lineCount; i++)
|
||||||
|
{
|
||||||
|
free(file->lines[i].text);
|
||||||
|
free(file->lines[i].name);
|
||||||
|
free(file->lines[i].sValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(file->lines);
|
||||||
|
}
|
||||||
|
|
||||||
if (file->argv)
|
if (file->argv)
|
||||||
{
|
{
|
||||||
for (i = 0; i < file->argc; i++)
|
for (i = 0; i < file->argc; i++)
|
||||||
|
@ -256,11 +256,17 @@ static char testRdpFileUTF8[] =
|
|||||||
"rdgiskdcproxy:i:0\n"
|
"rdgiskdcproxy:i:0\n"
|
||||||
"kdcproxyname:s:\n"
|
"kdcproxyname:s:\n"
|
||||||
"drivestoredirect:s:*\n"
|
"drivestoredirect:s:*\n"
|
||||||
"username:s:LAB1\\JohnDoe\n";
|
"username:s:LAB1\\JohnDoe\n"
|
||||||
|
"vendor integer:i:123\n"
|
||||||
|
"vendor string:s:microsoft\n";
|
||||||
|
|
||||||
int TestClientRdpFile(int argc, char* argv[])
|
int TestClientRdpFile(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
int index;
|
||||||
|
int iValue;
|
||||||
|
char* sValue;
|
||||||
rdpFile* file;
|
rdpFile* file;
|
||||||
|
rdpFileLine* line;
|
||||||
|
|
||||||
/* Unicode */
|
/* Unicode */
|
||||||
|
|
||||||
@ -324,6 +330,38 @@ int TestClientRdpFile(int argc, char* argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iValue = freerdp_client_rdp_file_get_integer_option(file, "vendor integer");
|
||||||
|
freerdp_client_rdp_file_set_integer_option(file, "vendor integer", 456);
|
||||||
|
iValue = freerdp_client_rdp_file_get_integer_option(file, "vendor integer");
|
||||||
|
|
||||||
|
sValue = (char*) freerdp_client_rdp_file_get_string_option(file, "vendor string");
|
||||||
|
freerdp_client_rdp_file_set_string_option(file, "vendor string", "apple");
|
||||||
|
sValue = (char*) freerdp_client_rdp_file_get_string_option(file, "vendor string");
|
||||||
|
|
||||||
|
freerdp_client_rdp_file_set_string_option(file, "fruits", "banana,oranges");
|
||||||
|
freerdp_client_rdp_file_set_integer_option(file, "numbers", 123456789);
|
||||||
|
|
||||||
|
for (index = 0; index < file->lineCount; index++)
|
||||||
|
{
|
||||||
|
line = &(file->lines[index]);
|
||||||
|
|
||||||
|
if (line->flags & RDP_FILE_LINE_FLAG_FORMATTED)
|
||||||
|
{
|
||||||
|
if (line->flags & RDP_FILE_LINE_FLAG_TYPE_STRING)
|
||||||
|
{
|
||||||
|
printf("line %02d: name: %s value: %s, %s\n",
|
||||||
|
line->index, line->name, line->sValue,
|
||||||
|
(line->flags & RDP_FILE_LINE_FLAG_STANDARD) ? "standard" : "non-standard");
|
||||||
|
}
|
||||||
|
else if (line->flags & RDP_FILE_LINE_FLAG_TYPE_INTEGER)
|
||||||
|
{
|
||||||
|
printf("line %02d: name: %s value: %d, %s\n",
|
||||||
|
line->index, line->name, line->iValue,
|
||||||
|
(line->flags & RDP_FILE_LINE_FLAG_STANDARD) ? "standard" : "non-standard");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
freerdp_client_rdp_file_free(file);
|
freerdp_client_rdp_file_free(file);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
2
client/iOS/.gitignore
vendored
2
client/iOS/.gitignore
vendored
@ -6,3 +6,5 @@ bin/
|
|||||||
build/
|
build/
|
||||||
project.pbxproj
|
project.pbxproj
|
||||||
!iFreeRDP.xcodeproj/
|
!iFreeRDP.xcodeproj/
|
||||||
|
iFreeRDP.app/
|
||||||
|
|
||||||
|
@ -470,6 +470,7 @@ if( ANDROID_FORBID_SYGWIN )
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# FIXME: properly detect 64-bit host, currently reported as 32-bit
|
||||||
|
|
||||||
# detect current host platform
|
# detect current host platform
|
||||||
if( NOT DEFINED ANDROID_NDK_HOST_X64 AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64")
|
if( NOT DEFINED ANDROID_NDK_HOST_X64 AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64")
|
||||||
@ -493,7 +494,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if( NOT ANDROID_NDK_HOST_X64 )
|
if( NOT ANDROID_NDK_HOST_X64 )
|
||||||
set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} )
|
#set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# see if we have path to Android NDK
|
# see if we have path to Android NDK
|
||||||
|
13
cmake/FindGSM.cmake
Normal file
13
cmake/FindGSM.cmake
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
find_path(GSM_INCLUDE_DIR gsm/gsm.h)
|
||||||
|
|
||||||
|
find_library(GSM_LIBRARY gsm)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(GSM DEFAULT_MSG GSM_INCLUDE_DIR GSM_LIBRARY)
|
||||||
|
|
||||||
|
if(GSM_FOUND)
|
||||||
|
set(GSM_LIBRARIES ${GSM_LIBRARY})
|
||||||
|
set(GSM_INCLUDE_DIRS ${GSM_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(GSM_INCLUDE_DIR GSM_LIBRARY)
|
@ -143,14 +143,10 @@ IF(WIN32 AND NOT CYGWIN)
|
|||||||
"lib/VC"
|
"lib/VC"
|
||||||
)
|
)
|
||||||
|
|
||||||
if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
|
set( OPENSSL_DEBUG_LIBRARIES ${SSL_EAY_DEBUG} ${LIB_EAY_DEBUG} )
|
||||||
set( OPENSSL_LIBRARIES
|
set( OPENSSL_RELEASE_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} )
|
||||||
optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG}
|
set( OPENSSL_LIBRARIES ${OPENSSL_RELEASE_LIBRARIES} )
|
||||||
optimized ${LIB_EAY_RELEASE} debug ${LIB_EAY_DEBUG}
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
set( OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} )
|
|
||||||
endif()
|
|
||||||
MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE)
|
MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE)
|
||||||
MARK_AS_ADVANCED(LIB_EAY_DEBUG LIB_EAY_RELEASE)
|
MARK_AS_ADVANCED(LIB_EAY_DEBUG LIB_EAY_RELEASE)
|
||||||
ELSEIF(MINGW)
|
ELSEIF(MINGW)
|
||||||
@ -322,4 +318,4 @@ else (OPENSSL_VERSION)
|
|||||||
)
|
)
|
||||||
endif (OPENSSL_VERSION)
|
endif (OPENSSL_VERSION)
|
||||||
|
|
||||||
MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)
|
MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES OPENSSL_DEBUG_LIBRARIES OPENSSL_RELEASE_LIBRARIES)
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#cmakedefine WITH_PULSE
|
#cmakedefine WITH_PULSE
|
||||||
#cmakedefine WITH_IOSAUDIO
|
#cmakedefine WITH_IOSAUDIO
|
||||||
#cmakedefine WITH_OPENSLES
|
#cmakedefine WITH_OPENSLES
|
||||||
|
#cmakedefine WITH_GSM
|
||||||
|
|
||||||
/* Plugins */
|
/* Plugins */
|
||||||
#cmakedefine STATIC_CHANNELS
|
#cmakedefine STATIC_CHANNELS
|
||||||
|
83
docs/valgrind.supp
Normal file
83
docs/valgrind.supp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
|
||||||
|
{
|
||||||
|
ignore glibc getaddrinfo
|
||||||
|
Memcheck:Param
|
||||||
|
sendmsg(mmsg[0].msg_hdr)
|
||||||
|
fun:sendmmsg
|
||||||
|
fun:__libc_res_nsend
|
||||||
|
fun:__libc_res_nquery
|
||||||
|
fun:__libc_res_nsearch
|
||||||
|
fun:_nss_dns_gethostbyname4_r
|
||||||
|
fun:gaih_inet
|
||||||
|
fun:getaddrinfo
|
||||||
|
fun:freerdp_tcp_connect
|
||||||
|
fun:tcp_connect
|
||||||
|
fun:transport_connect
|
||||||
|
fun:nego_tcp_connect
|
||||||
|
fun:nego_transport_connect
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore openssl malloc
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:CRYPTO_malloc
|
||||||
|
...
|
||||||
|
obj:*libcrypto*
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore openssl realloc
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:realloc
|
||||||
|
fun:CRYPTO_realloc
|
||||||
|
...
|
||||||
|
obj:*libcrypto*
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore libssl cond
|
||||||
|
Memcheck:Cond
|
||||||
|
obj:*libssl*
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore libssl value
|
||||||
|
Memcheck:Value4
|
||||||
|
obj:*libssl*
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore ssl3_read_bytes tls1_enc
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:tls1_enc
|
||||||
|
fun:ssl3_read_bytes
|
||||||
|
obj:*libssl*
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore ssl3_read_bytes memcpy
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:memcpy@@GLIBC_2.14
|
||||||
|
fun:ssl3_read_bytes
|
||||||
|
obj:*libssl*
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore ssl3_read_bytes value8
|
||||||
|
Memcheck:Value8
|
||||||
|
fun:memcpy@@GLIBC_2.14
|
||||||
|
fun:ssl3_read_bytes
|
||||||
|
obj:*libssl*
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore write buf BIO_write
|
||||||
|
Memcheck:Param
|
||||||
|
write(buf)
|
||||||
|
obj:*libpthread*
|
||||||
|
obj:*libcrypto*
|
||||||
|
fun:BIO_write
|
||||||
|
fun:ssl3_write_pending
|
||||||
|
fun:ssl3_write_bytes
|
||||||
|
}
|
177
include/freerdp/channels/cliprdr.h
Normal file
177
include/freerdp/channels/cliprdr.h
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Clipboard Virtual Channel Extension
|
||||||
|
*
|
||||||
|
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREERDP_CHANNEL_CLIPRDR_H
|
||||||
|
#define FREERDP_CHANNEL_CLIPRDR_H
|
||||||
|
|
||||||
|
#include <freerdp/api.h>
|
||||||
|
#include <freerdp/types.h>
|
||||||
|
|
||||||
|
#define CLIPRDR_SVC_CHANNEL_NAME "cliprdr"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clipboard Formats
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CLIPRDR_FORMAT_RAW 0
|
||||||
|
#define CLIPRDR_FORMAT_TEXT 1 /* "Plain Text" */
|
||||||
|
#define CLIPRDR_FORMAT_BITMAP 2 /* "Bitmap" */
|
||||||
|
#define CLIPRDR_FORMAT_METAFILEPICT 3 /* "Windows Metafile" */
|
||||||
|
#define CLIPRDR_FORMAT_SYLK 4
|
||||||
|
#define CLIPRDR_FORMAT_DIF 5
|
||||||
|
#define CLIPRDR_FORMAT_TIFF 6
|
||||||
|
#define CLIPRDR_FORMAT_OEMTEXT 7 /* "OEM Text" */
|
||||||
|
#define CLIPRDR_FORMAT_DIB 8 /* "Device Independent Bitmap (DIB)" */
|
||||||
|
#define CLIPRDR_FORMAT_PALETTE 9
|
||||||
|
#define CLIPRDR_FORMAT_PENDATA 10
|
||||||
|
#define CLIPRDR_FORMAT_RIFF 11
|
||||||
|
#define CLIPRDR_FORMAT_WAVE 12
|
||||||
|
#define CLIPRDR_FORMAT_UNICODETEXT 13 /* "Unicode Text" */
|
||||||
|
#define CLIPRDR_FORMAT_ENHMETAFILE 14 /* "Enhanced Metafile" */
|
||||||
|
#define CLIPRDR_FORMAT_HDROP 15 /* "File List" */
|
||||||
|
#define CLIPRDR_FORMAT_LOCALE 16 /* "Locale Identifier" */
|
||||||
|
#define CLIPRDR_FORMAT_DIBV5 17
|
||||||
|
#define CLIPRDR_FORMAT_MAX 18
|
||||||
|
|
||||||
|
#define CB_FORMAT_RAW 0x0000
|
||||||
|
#define CB_FORMAT_TEXT 0x0001
|
||||||
|
#define CB_FORMAT_DIB 0x0008
|
||||||
|
#define CB_FORMAT_UNICODETEXT 0x000D
|
||||||
|
#define CB_FORMAT_HTML 0xD010
|
||||||
|
#define CB_FORMAT_PNG 0xD011
|
||||||
|
#define CB_FORMAT_JPEG 0xD012
|
||||||
|
#define CB_FORMAT_GIF 0xD013
|
||||||
|
|
||||||
|
/* CLIPRDR_HEADER.msgType */
|
||||||
|
#define CB_MONITOR_READY 0x0001
|
||||||
|
#define CB_FORMAT_LIST 0x0002
|
||||||
|
#define CB_FORMAT_LIST_RESPONSE 0x0003
|
||||||
|
#define CB_FORMAT_DATA_REQUEST 0x0004
|
||||||
|
#define CB_FORMAT_DATA_RESPONSE 0x0005
|
||||||
|
#define CB_TEMP_DIRECTORY 0x0006
|
||||||
|
#define CB_CLIP_CAPS 0x0007
|
||||||
|
#define CB_FILECONTENTS_REQUEST 0x0008
|
||||||
|
#define CB_FILECONTENTS_RESPONSE 0x0009
|
||||||
|
#define CB_LOCK_CLIPDATA 0x000A
|
||||||
|
#define CB_UNLOCK_CLIPDATA 0x000B
|
||||||
|
|
||||||
|
/* CLIPRDR_HEADER.msgFlags */
|
||||||
|
#define CB_RESPONSE_OK 0x0001
|
||||||
|
#define CB_RESPONSE_FAIL 0x0002
|
||||||
|
#define CB_ASCII_NAMES 0x0004
|
||||||
|
|
||||||
|
/* CLIPRDR_CAPS_SET.capabilitySetType */
|
||||||
|
#define CB_CAPSTYPE_GENERAL 0x0001
|
||||||
|
|
||||||
|
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
|
||||||
|
#define CB_CAPSTYPE_GENERAL_LEN 12
|
||||||
|
|
||||||
|
/* CLIPRDR_GENERAL_CAPABILITY.version */
|
||||||
|
#define CB_CAPS_VERSION_1 0x00000001
|
||||||
|
#define CB_CAPS_VERSION_2 0x00000002
|
||||||
|
|
||||||
|
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
|
||||||
|
#define CB_USE_LONG_FORMAT_NAMES 0x00000002
|
||||||
|
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
|
||||||
|
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
|
||||||
|
#define CB_CAN_LOCK_CLIPDATA 0x00000010
|
||||||
|
|
||||||
|
#define DEFINE_CLIPRDR_HEADER_COMMON() \
|
||||||
|
UINT16 msgType; \
|
||||||
|
UINT16 msgFlags; \
|
||||||
|
UINT32 dataLen
|
||||||
|
|
||||||
|
struct _CLIPRDR_HEADER
|
||||||
|
{
|
||||||
|
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||||
|
};
|
||||||
|
typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER;
|
||||||
|
|
||||||
|
struct _CLIPRDR_CAPABILITY_SET
|
||||||
|
{
|
||||||
|
UINT16 capabilitySetType;
|
||||||
|
UINT16 capabilitySetLength;
|
||||||
|
};
|
||||||
|
typedef struct _CLIPRDR_CAPABILITY_SET CLIPRDR_CAPABILITY_SET;
|
||||||
|
|
||||||
|
struct _CLIPRDR_GENERAL_CAPABILITY_SET
|
||||||
|
{
|
||||||
|
UINT16 capabilitySetType;
|
||||||
|
UINT16 capabilitySetLength;
|
||||||
|
|
||||||
|
UINT32 version;
|
||||||
|
UINT32 generalFlags;
|
||||||
|
};
|
||||||
|
typedef struct _CLIPRDR_GENERAL_CAPABILITY_SET CLIPRDR_GENERAL_CAPABILITY_SET;
|
||||||
|
|
||||||
|
struct _CLIPRDR_CAPABILITIES
|
||||||
|
{
|
||||||
|
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||||
|
|
||||||
|
UINT32 cCapabilitiesSets;
|
||||||
|
CLIPRDR_CAPABILITY_SET* capabilitySets;
|
||||||
|
};
|
||||||
|
typedef struct _CLIPRDR_CAPABILITIES CLIPRDR_CAPABILITIES;
|
||||||
|
|
||||||
|
struct _CLIPRDR_MONITOR_READY
|
||||||
|
{
|
||||||
|
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||||
|
};
|
||||||
|
typedef struct _CLIPRDR_MONITOR_READY CLIPRDR_MONITOR_READY;
|
||||||
|
|
||||||
|
struct _CLIPRDR_FORMAT
|
||||||
|
{
|
||||||
|
UINT32 formatId;
|
||||||
|
char* formatName;
|
||||||
|
};
|
||||||
|
typedef struct _CLIPRDR_FORMAT CLIPRDR_FORMAT;
|
||||||
|
|
||||||
|
struct _CLIPRDR_FORMAT_LIST
|
||||||
|
{
|
||||||
|
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||||
|
|
||||||
|
UINT32 cFormats;
|
||||||
|
CLIPRDR_FORMAT* formats;
|
||||||
|
};
|
||||||
|
typedef struct _CLIPRDR_FORMAT_LIST CLIPRDR_FORMAT_LIST;
|
||||||
|
|
||||||
|
struct _CLIPRDR_FORMAT_LIST_RESPONSE
|
||||||
|
{
|
||||||
|
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||||
|
};
|
||||||
|
typedef struct _CLIPRDR_FORMAT_LIST_RESPONSE CLIPRDR_FORMAT_LIST_RESPONSE;
|
||||||
|
|
||||||
|
struct _CLIPRDR_FORMAT_DATA_REQUEST
|
||||||
|
{
|
||||||
|
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||||
|
|
||||||
|
UINT32 requestedFormatId;
|
||||||
|
};
|
||||||
|
typedef struct _CLIPRDR_FORMAT_DATA_REQUEST CLIPRDR_FORMAT_DATA_REQUEST;
|
||||||
|
|
||||||
|
struct _CLIPRDR_FORMAT_DATA_RESPONSE
|
||||||
|
{
|
||||||
|
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||||
|
|
||||||
|
BYTE* requestedFormatData;
|
||||||
|
};
|
||||||
|
typedef struct _CLIPRDR_FORMAT_DATA_RESPONSE CLIPRDR_FORMAT_DATA_RESPONSE;
|
||||||
|
|
||||||
|
#endif /* FREERDP_CHANNEL_CLIPRDR_H */
|
||||||
|
|
@ -87,8 +87,8 @@ FREERDP_API HANDLE freerdp_client_get_thread(rdpContext* context);
|
|||||||
|
|
||||||
FREERDP_API int freerdp_client_settings_parse_command_line(rdpSettings* settings, int argc, char** argv);
|
FREERDP_API int freerdp_client_settings_parse_command_line(rdpSettings* settings, int argc, char** argv);
|
||||||
FREERDP_API int freerdp_client_settings_parse_connection_file(rdpSettings* settings, const char* filename);
|
FREERDP_API int freerdp_client_settings_parse_connection_file(rdpSettings* settings, const char* filename);
|
||||||
FREERDP_API int freerdp_client_settings_parse_connection_file_buffer(rdpSettings* settings, BYTE* buffer, size_t size);
|
FREERDP_API int freerdp_client_settings_parse_connection_file_buffer(rdpSettings* settings, const BYTE* buffer, size_t size);
|
||||||
FREERDP_API int freerdp_client_settings_write_connection_file(rdpSettings* settings, const char* filename, BOOL unicode);
|
FREERDP_API int freerdp_client_settings_write_connection_file(const rdpSettings* settings, const char* filename, BOOL unicode);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
* Clipboard Virtual Channel Types
|
* Clipboard Virtual Channel Extension
|
||||||
*
|
*
|
||||||
* Copyright 2011 Vic Lee
|
* Copyright 2011 Vic Lee
|
||||||
*
|
*
|
||||||
@ -22,72 +22,45 @@
|
|||||||
|
|
||||||
#include <freerdp/types.h>
|
#include <freerdp/types.h>
|
||||||
|
|
||||||
|
#include <freerdp/message.h>
|
||||||
|
#include <freerdp/channels/cliprdr.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client Interface
|
* Client Interface
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct _cliprdr_client_context CliprdrClientContext;
|
typedef struct _cliprdr_client_context CliprdrClientContext;
|
||||||
|
|
||||||
typedef int (*pcCliprdrMonitorReady)(CliprdrClientContext* context);
|
typedef int (*pcCliprdrServerCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities);
|
||||||
typedef int (*pcCliprdrFormatList)(CliprdrClientContext* context);
|
typedef int (*pcCliprdrClientCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities);
|
||||||
typedef int (*pcCliprdrDataRequest)(CliprdrClientContext* context);
|
typedef int (*pcCliprdrMonitorReady)(CliprdrClientContext* context, CLIPRDR_MONITOR_READY* monitorReady);
|
||||||
typedef int (*pcCliprdrDataResponse)(CliprdrClientContext* context);
|
typedef int (*pcCliprdrClientFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList);
|
||||||
|
typedef int (*pcCliprdrServerFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList);
|
||||||
|
typedef int (*pcCliprdrClientFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
|
||||||
|
typedef int (*pcCliprdrServerFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
|
||||||
|
typedef int (*pcCliprdrClientFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
|
||||||
|
typedef int (*pcCliprdrServerFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
|
||||||
|
typedef int (*pcCliprdrClientFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
|
||||||
|
typedef int (*pcCliprdrServerFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
|
||||||
|
|
||||||
struct _cliprdr_client_context
|
struct _cliprdr_client_context
|
||||||
{
|
{
|
||||||
|
void* handle;
|
||||||
|
void* custom;
|
||||||
|
|
||||||
|
pcCliprdrServerCapabilities ServerCapabilities;
|
||||||
|
pcCliprdrClientCapabilities ClientCapabilities;
|
||||||
pcCliprdrMonitorReady MonitorReady;
|
pcCliprdrMonitorReady MonitorReady;
|
||||||
pcCliprdrFormatList FormatList;
|
pcCliprdrClientFormatList ClientFormatList;
|
||||||
pcCliprdrDataRequest DataRequest;
|
pcCliprdrServerFormatList ServerFormatList;
|
||||||
pcCliprdrDataResponse DataResponse;
|
pcCliprdrClientFormatListResponse ClientFormatListResponse;
|
||||||
|
pcCliprdrServerFormatListResponse ServerFormatListResponse;
|
||||||
|
pcCliprdrClientFormatDataRequest ClientFormatDataRequest;
|
||||||
|
pcCliprdrServerFormatDataRequest ServerFormatDataRequest;
|
||||||
|
pcCliprdrClientFormatDataResponse ClientFormatDataResponse;
|
||||||
|
pcCliprdrServerFormatDataResponse ServerFormatDataResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Clipboard Formats
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define CB_FORMAT_RAW 0x0000
|
|
||||||
#define CB_FORMAT_TEXT 0x0001
|
|
||||||
#define CB_FORMAT_DIB 0x0008
|
|
||||||
#define CB_FORMAT_UNICODETEXT 0x000D
|
|
||||||
#define CB_FORMAT_HTML 0xD010
|
|
||||||
#define CB_FORMAT_PNG 0xD011
|
|
||||||
#define CB_FORMAT_JPEG 0xD012
|
|
||||||
#define CB_FORMAT_GIF 0xD013
|
|
||||||
|
|
||||||
/* CLIPRDR_HEADER.msgType */
|
|
||||||
#define CB_MONITOR_READY 0x0001
|
|
||||||
#define CB_FORMAT_LIST 0x0002
|
|
||||||
#define CB_FORMAT_LIST_RESPONSE 0x0003
|
|
||||||
#define CB_FORMAT_DATA_REQUEST 0x0004
|
|
||||||
#define CB_FORMAT_DATA_RESPONSE 0x0005
|
|
||||||
#define CB_TEMP_DIRECTORY 0x0006
|
|
||||||
#define CB_CLIP_CAPS 0x0007
|
|
||||||
#define CB_FILECONTENTS_REQUEST 0x0008
|
|
||||||
#define CB_FILECONTENTS_RESPONSE 0x0009
|
|
||||||
#define CB_LOCK_CLIPDATA 0x000A
|
|
||||||
#define CB_UNLOCK_CLIPDATA 0x000B
|
|
||||||
|
|
||||||
/* CLIPRDR_HEADER.msgFlags */
|
|
||||||
#define CB_RESPONSE_OK 0x0001
|
|
||||||
#define CB_RESPONSE_FAIL 0x0002
|
|
||||||
#define CB_ASCII_NAMES 0x0004
|
|
||||||
|
|
||||||
/* CLIPRDR_CAPS_SET.capabilitySetType */
|
|
||||||
#define CB_CAPSTYPE_GENERAL 0x0001
|
|
||||||
|
|
||||||
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
|
|
||||||
#define CB_CAPSTYPE_GENERAL_LEN 12
|
|
||||||
|
|
||||||
/* CLIPRDR_GENERAL_CAPABILITY.version */
|
|
||||||
#define CB_CAPS_VERSION_1 0x00000001
|
|
||||||
#define CB_CAPS_VERSION_2 0x00000002
|
|
||||||
|
|
||||||
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
|
|
||||||
#define CB_USE_LONG_FORMAT_NAMES 0x00000002
|
|
||||||
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
|
|
||||||
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
|
|
||||||
#define CB_CAN_LOCK_CLIPDATA 0x00000010
|
|
||||||
|
|
||||||
struct _CLIPRDR_FORMAT_NAME
|
struct _CLIPRDR_FORMAT_NAME
|
||||||
{
|
{
|
||||||
UINT32 id;
|
UINT32 id;
|
||||||
@ -99,10 +72,6 @@ typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME;
|
|||||||
/**
|
/**
|
||||||
* Clipboard Events
|
* Clipboard Events
|
||||||
*/
|
*/
|
||||||
#define CAPS_USE_LONG_FORMAT_NAMES 0x00000002
|
|
||||||
#define CAPS_STREAM_FILECLIP_ENABLED 0x00000004
|
|
||||||
#define CAPS_FILECLIP_NO_FILE_PATH 0x00000008
|
|
||||||
#define CAPS_CAN_LOCK_CLIPDATA 0x00000010
|
|
||||||
|
|
||||||
struct _RDP_CB_CLIP_CAPS
|
struct _RDP_CB_CLIP_CAPS
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,25 @@
|
|||||||
#include <freerdp/api.h>
|
#include <freerdp/api.h>
|
||||||
#include <freerdp/freerdp.h>
|
#include <freerdp/freerdp.h>
|
||||||
|
|
||||||
|
#define RDP_FILE_LINE_FLAG_FORMATTED 0x00000001
|
||||||
|
#define RDP_FILE_LINE_FLAG_STANDARD 0x00000002
|
||||||
|
#define RDP_FILE_LINE_FLAG_TYPE_STRING 0x00000010
|
||||||
|
#define RDP_FILE_LINE_FLAG_TYPE_INTEGER 0x00000020
|
||||||
|
#define RDP_FILE_LINE_FLAG_TYPE_BINARY 0x00000040
|
||||||
|
|
||||||
|
struct rdp_file_line
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
char* text;
|
||||||
|
DWORD flags;
|
||||||
|
char* name;
|
||||||
|
LPSTR sValue;
|
||||||
|
DWORD iValue;
|
||||||
|
PBYTE bValue;
|
||||||
|
int valueLength;
|
||||||
|
};
|
||||||
|
typedef struct rdp_file_line rdpFileLine;
|
||||||
|
|
||||||
struct rdp_file
|
struct rdp_file
|
||||||
{
|
{
|
||||||
DWORD UseMultiMon; /* use multimon */
|
DWORD UseMultiMon; /* use multimon */
|
||||||
@ -130,6 +149,10 @@ struct rdp_file
|
|||||||
LPSTR DevicesToRedirect; /* devicestoredirect */
|
LPSTR DevicesToRedirect; /* devicestoredirect */
|
||||||
LPSTR WinPosStr; /* winposstr */
|
LPSTR WinPosStr; /* winposstr */
|
||||||
|
|
||||||
|
int lineCount;
|
||||||
|
int lineSize;
|
||||||
|
rdpFileLine* lines;
|
||||||
|
|
||||||
int argc;
|
int argc;
|
||||||
char** argv;
|
char** argv;
|
||||||
int argSize;
|
int argSize;
|
||||||
@ -142,12 +165,18 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
FREERDP_API BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name);
|
FREERDP_API BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name);
|
||||||
FREERDP_API BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, BYTE* buffer, size_t size);
|
FREERDP_API BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, const BYTE* buffer, size_t size);
|
||||||
FREERDP_API BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* settings);
|
FREERDP_API BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* settings);
|
||||||
|
|
||||||
FREERDP_API BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings* settings);
|
FREERDP_API BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSettings* settings);
|
||||||
FREERDP_API BOOL freerdp_client_write_rdp_file(rdpFile* file, const char* name, BOOL unicode);
|
FREERDP_API BOOL freerdp_client_write_rdp_file(const rdpFile* file, const char* name, BOOL unicode);
|
||||||
FREERDP_API size_t freerdp_client_write_rdp_file_buffer(rdpFile* file, char* buffer, size_t size);
|
FREERDP_API size_t freerdp_client_write_rdp_file_buffer(const rdpFile* file, char* buffer, size_t size);
|
||||||
|
|
||||||
|
FREERDP_API int freerdp_client_rdp_file_set_string_option(rdpFile* file, const char* name, const char* value);
|
||||||
|
FREERDP_API const char* freerdp_client_rdp_file_get_string_option(rdpFile* file, const char* name);
|
||||||
|
|
||||||
|
FREERDP_API int freerdp_client_rdp_file_set_integer_option(rdpFile* file, const char* name, int value);
|
||||||
|
FREERDP_API int freerdp_client_rdp_file_get_integer_option(rdpFile* file, const char* name);
|
||||||
|
|
||||||
FREERDP_API rdpFile* freerdp_client_rdp_file_new(void);
|
FREERDP_API rdpFile* freerdp_client_rdp_file_new(void);
|
||||||
FREERDP_API void freerdp_client_rdp_file_free(rdpFile* file);
|
FREERDP_API void freerdp_client_rdp_file_free(rdpFile* file);
|
||||||
|
@ -43,6 +43,8 @@ struct _RDPSND_WAVE
|
|||||||
|
|
||||||
UINT32 wLocalTimeA;
|
UINT32 wLocalTimeA;
|
||||||
UINT32 wLocalTimeB;
|
UINT32 wLocalTimeB;
|
||||||
|
|
||||||
|
BOOL AutoConfirm;
|
||||||
};
|
};
|
||||||
typedef struct _RDPSND_WAVE RDPSND_WAVE;
|
typedef struct _RDPSND_WAVE RDPSND_WAVE;
|
||||||
|
|
||||||
@ -81,6 +83,8 @@ struct rdpsnd_device_plugin
|
|||||||
pcWaveDecode WaveDecode;
|
pcWaveDecode WaveDecode;
|
||||||
pcWavePlay WavePlay;
|
pcWavePlay WavePlay;
|
||||||
pcWaveConfirm WaveConfirm;
|
pcWaveConfirm WaveConfirm;
|
||||||
|
|
||||||
|
BOOL DisableConfirmThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RDPSND_DEVICE_EXPORT_FUNC_NAME "freerdp_rdpsnd_client_subsystem_entry"
|
#define RDPSND_DEVICE_EXPORT_FUNC_NAME "freerdp_rdpsnd_client_subsystem_entry"
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include <freerdp/api.h>
|
#include <freerdp/api.h>
|
||||||
#include <freerdp/types.h>
|
#include <freerdp/types.h>
|
||||||
|
|
||||||
|
#include <freerdp/codec/color.h>
|
||||||
|
|
||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
@ -31,4 +33,17 @@ FREERDP_API BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int
|
|||||||
FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height,
|
FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height,
|
||||||
wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e);
|
wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e);
|
||||||
|
|
||||||
|
#define PLANAR_FORMAT_HEADER_CS (1 << 3)
|
||||||
|
#define PLANAR_FORMAT_HEADER_RLE (1 << 4)
|
||||||
|
#define PLANAR_FORMAT_HEADER_NA (1 << 5)
|
||||||
|
#define PLANAR_FORMAT_HEADER_CLL_MASK 0x07
|
||||||
|
|
||||||
|
typedef struct _BITMAP_PLANAR_CONTEXT BITMAP_PLANAR_CONTEXT;
|
||||||
|
|
||||||
|
FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
|
||||||
|
int width, int height, int scanline, BYTE* dstData, int* dstSize);
|
||||||
|
|
||||||
|
FREERDP_API BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight);
|
||||||
|
FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context);
|
||||||
|
|
||||||
#endif /* FREERDP_CODEC_BITMAP_H */
|
#endif /* FREERDP_CODEC_BITMAP_H */
|
||||||
|
@ -23,6 +23,20 @@
|
|||||||
#include <freerdp/api.h>
|
#include <freerdp/api.h>
|
||||||
#include <freerdp/freerdp.h>
|
#include <freerdp/freerdp.h>
|
||||||
|
|
||||||
|
#define FREERDP_PIXEL_FORMAT_TYPE_ARGB 1
|
||||||
|
#define FREERDP_PIXEL_FORMAT_TYPE_ABGR 2
|
||||||
|
|
||||||
|
#define FREERDP_PIXEL_FLIP_NONE 0
|
||||||
|
#define FREERDP_PIXEL_FLIP_VERTICAL 1
|
||||||
|
#define FREERDP_PIXEL_FLIP_HORIZONTAL 2
|
||||||
|
|
||||||
|
#define FREERDP_PIXEL_FORMAT(_bpp, _type, _flip) \
|
||||||
|
((_bpp << 24) | (_type << 16) | (_flip << 8))
|
||||||
|
|
||||||
|
#define FREERDP_PIXEL_FORMAT_BPP(_format) (((_format) >> 24) & 0xFF)
|
||||||
|
#define FREERDP_PIXEL_FORMAT_TYPE(_format) (((_format) >> 16) & 0xFF)
|
||||||
|
#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 8) & 0xFF)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -50,6 +50,7 @@ FREERDP_API int decompress_rdp_4(struct rdp_mppc_dec* dec, BYTE* cbuf, int len,
|
|||||||
FREERDP_API int decompress_rdp_5(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen);
|
FREERDP_API int decompress_rdp_5(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen);
|
||||||
FREERDP_API int decompress_rdp_6(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen);
|
FREERDP_API int decompress_rdp_6(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen);
|
||||||
FREERDP_API int decompress_rdp_61(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen);
|
FREERDP_API int decompress_rdp_61(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen);
|
||||||
|
|
||||||
FREERDP_API struct rdp_mppc_dec* mppc_dec_new(void);
|
FREERDP_API struct rdp_mppc_dec* mppc_dec_new(void);
|
||||||
FREERDP_API void mppc_dec_free(struct rdp_mppc_dec* dec);
|
FREERDP_API void mppc_dec_free(struct rdp_mppc_dec* dec);
|
||||||
|
|
||||||
|
@ -34,6 +34,35 @@
|
|||||||
|
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
|
#define TLS_ALERT_LEVEL_WARNING 1
|
||||||
|
#define TLS_ALERT_LEVEL_FATAL 2
|
||||||
|
|
||||||
|
#define TLS_ALERT_DESCRIPTION_CLOSE_NOTIFY 0
|
||||||
|
#define TLS_ALERT_DESCRIPTION_UNEXPECTED_MESSAGE 10
|
||||||
|
#define TLS_ALERT_DESCRIPTION_BAD_RECORD_MAC 20
|
||||||
|
#define TLS_ALERT_DESCRIPTION_DECRYPTION_FAILED 21
|
||||||
|
#define TLS_ALERT_DESCRIPTION_RECORD_OVERFLOW 22
|
||||||
|
#define TLS_ALERT_DESCRIPTION_DECOMPRESSION_FAILURE 30
|
||||||
|
#define TLS_ALERT_DESCRIPTION_HANSHAKE_FAILURE 40
|
||||||
|
#define TLS_ALERT_DESCRIPTION_NO_CERTIFICATE 41
|
||||||
|
#define TLS_ALERT_DESCRIPTION_BAD_CERTIFICATE 42
|
||||||
|
#define TLS_ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE 43
|
||||||
|
#define TLS_ALERT_DESCRIPTION_CERTIFICATE_REVOKED 44
|
||||||
|
#define TLS_ALERT_DESCRIPTION_CERTIFICATE_EXPIRED 45
|
||||||
|
#define TLS_ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN 46
|
||||||
|
#define TLS_ALERT_DESCRIPTION_ILLEGAL_PARAMETER 47
|
||||||
|
#define TLS_ALERT_DESCRIPTION_UNKNOWN_CA 48
|
||||||
|
#define TLS_ALERT_DESCRIPTION_ACCESS_DENIED 49
|
||||||
|
#define TLS_ALERT_DESCRIPTION_DECODE_ERROR 50
|
||||||
|
#define TLS_ALERT_DESCRIPTION_DECRYPT_ERROR 51
|
||||||
|
#define TLS_ALERT_DESCRIPTION_EXPORT_RESTRICTION 60
|
||||||
|
#define TLS_ALERT_DESCRIPTION_PROTOCOL_VERSION 70
|
||||||
|
#define TLS_ALERT_DESCRIPTION_INSUFFICIENT_SECURITY 71
|
||||||
|
#define TLS_ALERT_DESCRIPTION_INTERNAL_ERROR 80
|
||||||
|
#define TLS_ALERT_DESCRIPTION_USER_CANCELED 90
|
||||||
|
#define TLS_ALERT_DESCRIPTION_NO_RENEGOTIATION 100
|
||||||
|
#define TLS_ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION 110
|
||||||
|
|
||||||
typedef struct rdp_tls rdpTls;
|
typedef struct rdp_tls rdpTls;
|
||||||
|
|
||||||
struct rdp_tls
|
struct rdp_tls
|
||||||
@ -49,6 +78,10 @@ struct rdp_tls
|
|||||||
rdpSettings* settings;
|
rdpSettings* settings;
|
||||||
SecPkgContext_Bindings* Bindings;
|
SecPkgContext_Bindings* Bindings;
|
||||||
rdpCertificateStore* certificate_store;
|
rdpCertificateStore* certificate_store;
|
||||||
|
char* hostname;
|
||||||
|
int port;
|
||||||
|
int alertLevel;
|
||||||
|
int alertDescription;
|
||||||
};
|
};
|
||||||
|
|
||||||
FREERDP_API BOOL tls_connect(rdpTls* tls);
|
FREERDP_API BOOL tls_connect(rdpTls* tls);
|
||||||
@ -63,8 +96,10 @@ FREERDP_API int tls_write_all(rdpTls* tls, BYTE* data, int length);
|
|||||||
FREERDP_API int tls_wait_read(rdpTls* tls);
|
FREERDP_API int tls_wait_read(rdpTls* tls);
|
||||||
FREERDP_API int tls_wait_write(rdpTls* tls);
|
FREERDP_API int tls_wait_write(rdpTls* tls);
|
||||||
|
|
||||||
|
FREERDP_API int tls_set_alert_code(rdpTls* tls, int level, int description);
|
||||||
|
|
||||||
FREERDP_API BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname);
|
FREERDP_API BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname);
|
||||||
FREERDP_API BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname);
|
FREERDP_API BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port);
|
||||||
FREERDP_API void tls_print_certificate_error(char* hostname, char* fingerprint, char* hosts_file);
|
FREERDP_API void tls_print_certificate_error(char* hostname, char* fingerprint, char* hosts_file);
|
||||||
FREERDP_API void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count);
|
FREERDP_API void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count);
|
||||||
|
|
||||||
|
@ -45,6 +45,19 @@ extern "C" {
|
|||||||
#define ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER 0x0000000B
|
#define ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER 0x0000000B
|
||||||
#define ERRINFO_LOGOFF_BY_USER 0x0000000C
|
#define ERRINFO_LOGOFF_BY_USER 0x0000000C
|
||||||
|
|
||||||
|
/* Protocol-independent codes generated by the Connection Broker */
|
||||||
|
#define ERRINFO_CB_DESTINATION_NOT_FOUND 0x0000400
|
||||||
|
#define ERRINFO_CB_LOADING_DESTINATION 0x0000402
|
||||||
|
#define ERRINFO_CB_REDIRECTING_TO_DESTINATION 0x0000404
|
||||||
|
#define ERRINFO_CB_SESSION_ONLINE_VM_WAKE 0x0000405
|
||||||
|
#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT 0x0000406
|
||||||
|
#define ERRINFO_CB_SESSION_ONLINE_VM_NO_DNS 0x0000407
|
||||||
|
#define ERRINFO_CB_DESTINATION_POOL_NOT_FREE 0x0000408
|
||||||
|
#define ERRINFO_CB_CONNECTION_CANCELLED 0x0000409
|
||||||
|
#define ERRINFO_CB_CONNECTION_ERROR_INVALID_SETTINGS 0x0000410
|
||||||
|
#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT_TIMEOUT 0x0000411
|
||||||
|
#define ERRINFO_CB_SESSION_ONLINE_VM_SESSMON_FAILED 0x0000412
|
||||||
|
|
||||||
/* Protocol-independent licensing codes */
|
/* Protocol-independent licensing codes */
|
||||||
#define ERRINFO_LICENSE_INTERNAL 0x00000100
|
#define ERRINFO_LICENSE_INTERNAL 0x00000100
|
||||||
#define ERRINFO_LICENSE_NO_LICENSE_SERVER 0x00000101
|
#define ERRINFO_LICENSE_NO_LICENSE_SERVER 0x00000101
|
||||||
@ -123,6 +136,11 @@ extern "C" {
|
|||||||
#define ERRINFO_VC_DATA_TOO_LONG 0x0000112B
|
#define ERRINFO_VC_DATA_TOO_LONG 0x0000112B
|
||||||
#define ERRINFO_GRAPHICS_MODE_NOT_SUPPORTED 0x0000112D
|
#define ERRINFO_GRAPHICS_MODE_NOT_SUPPORTED 0x0000112D
|
||||||
#define ERRINFO_GRAPHICS_SUBSYSTEM_RESET_FAILED 0x0000112E
|
#define ERRINFO_GRAPHICS_SUBSYSTEM_RESET_FAILED 0x0000112E
|
||||||
|
#define ERRINFO_GRAPHICS_SUBSYSTEM_FAILED 0x0000112F
|
||||||
|
#define ERRINFO_TIMEZONE_KEY_NAME_LENGTH_TOO_SHORT 0x00001130
|
||||||
|
#define ERRINFO_TIMEZONE_KEY_NAME_LENGTH_TOO_LONG 0x00001131
|
||||||
|
#define ERRINFO_DYNAMIC_DST_DISABLED_FIELD_MISSING 0x00001132
|
||||||
|
#define ERRINFO_VC_DECODING_ERROR 0x00001133
|
||||||
#define ERRINFO_UPDATE_SESSION_KEY_FAILED 0x00001191
|
#define ERRINFO_UPDATE_SESSION_KEY_FAILED 0x00001191
|
||||||
#define ERRINFO_DECRYPT_FAILED 0x00001192
|
#define ERRINFO_DECRYPT_FAILED 0x00001192
|
||||||
#define ERRINFO_ENCRYPT_FAILED 0x00001193
|
#define ERRINFO_ENCRYPT_FAILED 0x00001193
|
||||||
@ -155,6 +173,7 @@ FREERDP_API extern int connectErrorCode;
|
|||||||
#define TLSCONNECTERROR ERRORSTART + 8
|
#define TLSCONNECTERROR ERRORSTART + 8
|
||||||
#define AUTHENTICATIONERROR ERRORSTART + 9
|
#define AUTHENTICATIONERROR ERRORSTART + 9
|
||||||
#define INSUFFICIENTPRIVILEGESERROR ERRORSTART + 10
|
#define INSUFFICIENTPRIVILEGESERROR ERRORSTART + 10
|
||||||
|
#define CANCELEDBYUSER ERRORSTART + 11
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -65,10 +65,6 @@ DEFINE_EVENT_BEGIN(ErrorInfo)
|
|||||||
UINT32 code;
|
UINT32 code;
|
||||||
DEFINE_EVENT_END(ErrorInfo)
|
DEFINE_EVENT_END(ErrorInfo)
|
||||||
|
|
||||||
DEFINE_EVENT_BEGIN(ParamChange)
|
|
||||||
int id;
|
|
||||||
DEFINE_EVENT_END(ParamChange)
|
|
||||||
|
|
||||||
DEFINE_EVENT_BEGIN(Terminate)
|
DEFINE_EVENT_BEGIN(Terminate)
|
||||||
int code;
|
int code;
|
||||||
DEFINE_EVENT_END(Terminate)
|
DEFINE_EVENT_END(Terminate)
|
||||||
|
@ -61,6 +61,7 @@ typedef void (*pPostDisconnect)(freerdp* instance);
|
|||||||
typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain);
|
typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain);
|
||||||
typedef BOOL (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint);
|
typedef BOOL (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint);
|
||||||
typedef BOOL (*pVerifyChangedCertificate)(freerdp* instance, char* subject, char* issuer, char* new_fingerprint, char* old_fingerprint);
|
typedef BOOL (*pVerifyChangedCertificate)(freerdp* instance, char* subject, char* issuer, char* new_fingerprint, char* old_fingerprint);
|
||||||
|
typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, int length, const char* hostname, int port, DWORD flags);
|
||||||
|
|
||||||
typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);
|
typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);
|
||||||
|
|
||||||
@ -195,13 +196,19 @@ struct rdp_freerdp
|
|||||||
Used when a certificate differs from stored fingerprint.
|
Used when a certificate differs from stored fingerprint.
|
||||||
If returns TRUE, the new fingerprint will be trusted and old thrown out. */
|
If returns TRUE, the new fingerprint will be trusted and old thrown out. */
|
||||||
|
|
||||||
ALIGN64 pLogonErrorInfo LogonErrorInfo; /**< (offset 53) Callback for logon error info, important for logon system messages with RemoteApp */
|
ALIGN64 pVerifyX509Certificate VerifyX509Certificate; /**< (offset 53) Callback for X509 certificate verification (PEM format) */
|
||||||
|
|
||||||
ALIGN64 pPostDisconnect PostDisconnect; /**< (offset 54)
|
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
|
Callback for cleaning up resources allocated
|
||||||
by connect callbacks. */
|
by connect callbacks. */
|
||||||
|
|
||||||
UINT64 paddingD[64 - 55]; /* 55 */
|
ALIGN64 pAuthenticate GatewayAuthenticate; /**< (offset 56)
|
||||||
|
Callback for gateway authentication.
|
||||||
|
It is used to get the username/password when it was not provided at connection time. */
|
||||||
|
|
||||||
|
UINT64 paddingD[64 - 57]; /* 57 */
|
||||||
|
|
||||||
ALIGN64 pSendChannelData SendChannelData; /* (offset 64)
|
ALIGN64 pSendChannelData SendChannelData; /* (offset 64)
|
||||||
Callback for sending data to a channel.
|
Callback for sending data to a channel.
|
||||||
|
@ -113,6 +113,10 @@
|
|||||||
#define GDI_OPAQUE 0x00000001
|
#define GDI_OPAQUE 0x00000001
|
||||||
#define GDI_TRANSPARENT 0x00000002
|
#define GDI_TRANSPARENT 0x00000002
|
||||||
|
|
||||||
|
/* Fill Modes */
|
||||||
|
#define GDI_FILL_ALTERNATE 0x01
|
||||||
|
#define GDI_FILL_WINDING 0x02
|
||||||
|
|
||||||
/* GDI Object Types */
|
/* GDI Object Types */
|
||||||
#define GDIOBJECT_BITMAP 0x00
|
#define GDIOBJECT_BITMAP 0x00
|
||||||
#define GDIOBJECT_PEN 0x01
|
#define GDIOBJECT_PEN 0x01
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include <freerdp/api.h>
|
#include <freerdp/api.h>
|
||||||
#include <freerdp/types.h>
|
#include <freerdp/types.h>
|
||||||
#include <freerdp/channels/wtsvc.h>
|
#include <freerdp/channels/wtsvc.h>
|
||||||
|
|
||||||
|
#include <freerdp/channels/cliprdr.h>
|
||||||
#include <freerdp/client/cliprdr.h>
|
#include <freerdp/client/cliprdr.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,13 +51,15 @@
|
|||||||
#define CS_CLUSTER 0xC004
|
#define CS_CLUSTER 0xC004
|
||||||
#define CS_MONITOR 0xC005
|
#define CS_MONITOR 0xC005
|
||||||
#define CS_MCS_MSGCHANNEL 0xC006
|
#define CS_MCS_MSGCHANNEL 0xC006
|
||||||
#define CS_MULTITRANSPORT 0xC008
|
#define CS_MONITOR_EX 0xC008
|
||||||
|
#define CS_MULTITRANSPORT 0xC00A
|
||||||
|
|
||||||
/* Server to Client (SC) data blocks */
|
/* Server to Client (SC) data blocks */
|
||||||
#define SC_CORE 0x0C01
|
#define SC_CORE 0x0C01
|
||||||
#define SC_SECURITY 0x0C02
|
#define SC_SECURITY 0x0C02
|
||||||
#define SC_NET 0x0C03
|
#define SC_NET 0x0C03
|
||||||
#define SC_MULTITRANSPORT 0x0C06
|
#define SC_MCS_MSGCHANNEL 0x0C04
|
||||||
|
#define SC_MULTITRANSPORT 0x0C08
|
||||||
|
|
||||||
/* RDP version */
|
/* RDP version */
|
||||||
#define RDP_VERSION_4 0x00080001
|
#define RDP_VERSION_4 0x00080001
|
||||||
@ -240,6 +242,15 @@ typedef struct _TARGET_NET_ADDRESS TARGET_NET_ADDRESS;
|
|||||||
#define LOGON_FAILED_OTHER 0x00000002
|
#define LOGON_FAILED_OTHER 0x00000002
|
||||||
#define LOGON_WARNING 0x00000003
|
#define LOGON_WARNING 0x00000003
|
||||||
|
|
||||||
|
/* Server Status Info */
|
||||||
|
#define STATUS_FINDING_DESTINATION 0x00000401
|
||||||
|
#define STATUS_LOADING_DESTINATION 0x00000402
|
||||||
|
#define STATUS_BRINGING_SESSION_ONLINE 0x00000403
|
||||||
|
#define STATUS_REDIRECTING_TO_DESTINATION 0x00000404
|
||||||
|
#define STATUS_VM_LOADING 0x00000501
|
||||||
|
#define STATUS_VM_WAKING 0x00000502
|
||||||
|
#define STATUS_VM_BOOTING 0x00000503
|
||||||
|
|
||||||
/* SYSTEM_TIME */
|
/* SYSTEM_TIME */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -389,6 +400,26 @@ struct rdp_monitor
|
|||||||
};
|
};
|
||||||
typedef struct rdp_monitor rdpMonitor;
|
typedef struct rdp_monitor rdpMonitor;
|
||||||
|
|
||||||
|
struct _MONITOR_DEF
|
||||||
|
{
|
||||||
|
INT32 left;
|
||||||
|
INT32 top;
|
||||||
|
INT32 right;
|
||||||
|
INT32 bottom;
|
||||||
|
UINT32 flags;
|
||||||
|
};
|
||||||
|
typedef struct _MONITOR_DEF MONITOR_DEF;
|
||||||
|
|
||||||
|
struct _MONITOR_ATTRIBUTES
|
||||||
|
{
|
||||||
|
UINT32 physicalWidth;
|
||||||
|
UINT32 physicalHeight;
|
||||||
|
UINT32 orientation;
|
||||||
|
UINT32 desktopScaleFactor;
|
||||||
|
UINT32 deviceScaleFactor;
|
||||||
|
};
|
||||||
|
typedef struct _MONITOR_ATTRIBUTES MONITOR_ATTRIBUTES;
|
||||||
|
|
||||||
/* Device Redirection */
|
/* Device Redirection */
|
||||||
|
|
||||||
#define RDPDR_DTYP_SERIAL 0x00000001
|
#define RDPDR_DTYP_SERIAL 0x00000001
|
||||||
@ -493,6 +524,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
|
|||||||
#define FreeRDP_SupportMonitorLayoutPdu 141
|
#define FreeRDP_SupportMonitorLayoutPdu 141
|
||||||
#define FreeRDP_SupportGraphicsPipeline 142
|
#define FreeRDP_SupportGraphicsPipeline 142
|
||||||
#define FreeRDP_SupportDynamicTimeZone 143
|
#define FreeRDP_SupportDynamicTimeZone 143
|
||||||
|
#define FreeRDP_SupportHeartbeatPdu 144
|
||||||
#define FreeRDP_DisableEncryption 192
|
#define FreeRDP_DisableEncryption 192
|
||||||
#define FreeRDP_EncryptionMethods 193
|
#define FreeRDP_EncryptionMethods 193
|
||||||
#define FreeRDP_ExtEncryptionMethods 194
|
#define FreeRDP_ExtEncryptionMethods 194
|
||||||
@ -516,6 +548,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
|
|||||||
#define FreeRDP_DesktopPosX 390
|
#define FreeRDP_DesktopPosX 390
|
||||||
#define FreeRDP_DesktopPosY 391
|
#define FreeRDP_DesktopPosY 391
|
||||||
#define FreeRDP_MultitransportFlags 512
|
#define FreeRDP_MultitransportFlags 512
|
||||||
|
#define FreeRDP_SupportMultitransport 513
|
||||||
#define FreeRDP_AlternateShell 640
|
#define FreeRDP_AlternateShell 640
|
||||||
#define FreeRDP_ShellWorkingDirectory 641
|
#define FreeRDP_ShellWorkingDirectory 641
|
||||||
#define FreeRDP_AutoLogonEnabled 704
|
#define FreeRDP_AutoLogonEnabled 704
|
||||||
@ -594,6 +627,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
|
|||||||
#define FreeRDP_RdpKeyFile 1412
|
#define FreeRDP_RdpKeyFile 1412
|
||||||
#define FreeRDP_RdpServerRsaKey 1413
|
#define FreeRDP_RdpServerRsaKey 1413
|
||||||
#define FreeRDP_RdpServerCertificate 1414
|
#define FreeRDP_RdpServerCertificate 1414
|
||||||
|
#define FreeRDP_ExternalCertificateManagement 1415
|
||||||
#define FreeRDP_Workarea 1536
|
#define FreeRDP_Workarea 1536
|
||||||
#define FreeRDP_Fullscreen 1537
|
#define FreeRDP_Fullscreen 1537
|
||||||
#define FreeRDP_PercentScreen 1538
|
#define FreeRDP_PercentScreen 1538
|
||||||
@ -698,6 +732,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
|
|||||||
#define FreeRDP_CompDeskSupportLevel 3456
|
#define FreeRDP_CompDeskSupportLevel 3456
|
||||||
#define FreeRDP_SurfaceCommandsEnabled 3520
|
#define FreeRDP_SurfaceCommandsEnabled 3520
|
||||||
#define FreeRDP_FrameMarkerCommandEnabled 3521
|
#define FreeRDP_FrameMarkerCommandEnabled 3521
|
||||||
|
#define FreeRDP_SurfaceFrameMarkerEnabled 3522
|
||||||
#define FreeRDP_RemoteFxOnly 3648
|
#define FreeRDP_RemoteFxOnly 3648
|
||||||
#define FreeRDP_RemoteFxCodec 3649
|
#define FreeRDP_RemoteFxCodec 3649
|
||||||
#define FreeRDP_RemoteFxCodecId 3650
|
#define FreeRDP_RemoteFxCodecId 3650
|
||||||
@ -786,7 +821,8 @@ struct rdp_settings
|
|||||||
ALIGN64 BOOL SupportMonitorLayoutPdu; /* 141 */
|
ALIGN64 BOOL SupportMonitorLayoutPdu; /* 141 */
|
||||||
ALIGN64 BOOL SupportGraphicsPipeline; /* 142 */
|
ALIGN64 BOOL SupportGraphicsPipeline; /* 142 */
|
||||||
ALIGN64 BOOL SupportDynamicTimeZone; /* 143 */
|
ALIGN64 BOOL SupportDynamicTimeZone; /* 143 */
|
||||||
UINT64 padding0192[192 - 143]; /* 143 */
|
ALIGN64 BOOL SupportHeartbeatPdu; /* 144 */
|
||||||
|
UINT64 padding0192[192 - 145]; /* 145 */
|
||||||
|
|
||||||
/* Client/Server Security Data */
|
/* Client/Server Security Data */
|
||||||
ALIGN64 BOOL DisableEncryption; /* 192 */
|
ALIGN64 BOOL DisableEncryption; /* 192 */
|
||||||
@ -831,7 +867,8 @@ struct rdp_settings
|
|||||||
|
|
||||||
/* Client Multitransport Channel Data */
|
/* Client Multitransport Channel Data */
|
||||||
ALIGN64 UINT32 MultitransportFlags; /* 512 */
|
ALIGN64 UINT32 MultitransportFlags; /* 512 */
|
||||||
UINT64 padding0576[576 - 513]; /* 513 */
|
ALIGN64 BOOL SupportMultitransport; /* 513 */
|
||||||
|
UINT64 padding0576[576 - 514]; /* 514 */
|
||||||
UINT64 padding0640[640 - 576]; /* 576 */
|
UINT64 padding0640[640 - 576]; /* 576 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -960,7 +997,8 @@ struct rdp_settings
|
|||||||
ALIGN64 char* RdpKeyFile; /* 1412 */
|
ALIGN64 char* RdpKeyFile; /* 1412 */
|
||||||
ALIGN64 rdpRsaKey* RdpServerRsaKey; /* 1413 */
|
ALIGN64 rdpRsaKey* RdpServerRsaKey; /* 1413 */
|
||||||
ALIGN64 rdpCertificate* RdpServerCertificate; /* 1414 */
|
ALIGN64 rdpCertificate* RdpServerCertificate; /* 1414 */
|
||||||
UINT64 padding1472[1472 - 1350]; /* 1415 */
|
ALIGN64 BOOL ExternalCertificateManagement; /* 1415 */
|
||||||
|
UINT64 padding1472[1472 - 1416]; /* 1416 */
|
||||||
UINT64 padding1536[1536 - 1472]; /* 1472 */
|
UINT64 padding1536[1536 - 1472]; /* 1472 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1173,7 +1211,8 @@ struct rdp_settings
|
|||||||
/* Surface Commands Capabilities */
|
/* Surface Commands Capabilities */
|
||||||
ALIGN64 BOOL SurfaceCommandsEnabled; /* 3520 */
|
ALIGN64 BOOL SurfaceCommandsEnabled; /* 3520 */
|
||||||
ALIGN64 BOOL FrameMarkerCommandEnabled; /* 3521 */
|
ALIGN64 BOOL FrameMarkerCommandEnabled; /* 3521 */
|
||||||
UINT64 padding3584[3584 - 3522]; /* 3522 */
|
ALIGN64 BOOL SurfaceFrameMarkerEnabled; /* 3522 */
|
||||||
|
UINT64 padding3584[3584 - 3523]; /* 3523 */
|
||||||
UINT64 padding3648[3648 - 3584]; /* 3584 */
|
UINT64 padding3648[3648 - 3584]; /* 3584 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -109,7 +109,8 @@ struct _CHANNEL_ENTRY_POINTS_EX
|
|||||||
/* Extended Fields */
|
/* Extended Fields */
|
||||||
UINT32 MagicNumber; /* identifies FreeRDP */
|
UINT32 MagicNumber; /* identifies FreeRDP */
|
||||||
void* pExtendedData; /* extended initial data */
|
void* pExtendedData; /* extended initial data */
|
||||||
void** ppInterface; /* channel callback interface */
|
void* pInterface; /* channel callback interface, use after initialization */
|
||||||
|
void** ppInterface; /* channel callback interface, use for initialization */
|
||||||
PVIRTUALCHANNELEVENTPUSH pVirtualChannelEventPush;
|
PVIRTUALCHANNELEVENTPUSH pVirtualChannelEventPush;
|
||||||
};
|
};
|
||||||
typedef struct _CHANNEL_ENTRY_POINTS_EX CHANNEL_ENTRY_POINTS_EX;
|
typedef struct _CHANNEL_ENTRY_POINTS_EX CHANNEL_ENTRY_POINTS_EX;
|
||||||
|
@ -50,8 +50,8 @@ struct rdp_svc_plugin
|
|||||||
|
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
wStream* data_in;
|
wStream* data_in;
|
||||||
void* init_handle;
|
void* InitHandle;
|
||||||
UINT32 open_handle;
|
UINT32 OpenHandle;
|
||||||
wMessagePipe* MsgPipe;
|
wMessagePipe* MsgPipe;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,3 +65,7 @@ if(MONOLITHIC_BUILD)
|
|||||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(FREERDP_PC_LIBS "-lfreerdp -lwinpr")
|
||||||
|
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc @ONLY)
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||||
|
@ -22,6 +22,8 @@ set(${MODULE_PREFIX}_SRCS
|
|||||||
dsp.c
|
dsp.c
|
||||||
color.c
|
color.c
|
||||||
audio.c
|
audio.c
|
||||||
|
planar.c
|
||||||
|
planar.h
|
||||||
bitmap_decode.c
|
bitmap_decode.c
|
||||||
bitmap_encode.c
|
bitmap_encode.c
|
||||||
rfx_bitstream.h
|
rfx_bitstream.h
|
||||||
@ -106,3 +108,8 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
|
||||||
|
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
add_subdirectory(test)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
@ -35,8 +35,36 @@ UINT32 rdpsnd_compute_audio_time_length(AUDIO_FORMAT* format, int size)
|
|||||||
* http://msdn.microsoft.com/en-us/library/ms713497.aspx
|
* http://msdn.microsoft.com/en-us/library/ms713497.aspx
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (format->wBitsPerSample)
|
||||||
|
{
|
||||||
wSamples = (size * 8) / format->wBitsPerSample;
|
wSamples = (size * 8) / format->wBitsPerSample;
|
||||||
mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
|
mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mstime = 0;
|
||||||
|
|
||||||
|
if (format->wFormatTag == WAVE_FORMAT_GSM610)
|
||||||
|
{
|
||||||
|
UINT16 nSamplesPerBlock;
|
||||||
|
|
||||||
|
if ((format->cbSize == 2) && (format->data))
|
||||||
|
{
|
||||||
|
nSamplesPerBlock = *((UINT16*) format->data);
|
||||||
|
|
||||||
|
wSamples = (size / format->nBlockAlign) * nSamplesPerBlock;
|
||||||
|
mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "rdpsnd_compute_audio_time_length: invalid WAVE_FORMAT_GSM610 format\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "rdpsnd_compute_audio_time_length: unknown format %d\n", format->wFormatTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return mstime;
|
return mstime;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,11 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
|
#include "planar.h"
|
||||||
|
|
||||||
#include <freerdp/codec/color.h>
|
#include <freerdp/codec/color.h>
|
||||||
|
|
||||||
#include <freerdp/codec/bitmap.h>
|
#include <freerdp/codec/bitmap.h>
|
||||||
@ -251,190 +255,6 @@ static UINT32 ExtractRunLength(UINT32 code, BYTE* pbOrderHdr, UINT32* advance)
|
|||||||
#define RLEEXTRA
|
#define RLEEXTRA
|
||||||
#include "include/bitmap.c"
|
#include "include/bitmap.c"
|
||||||
|
|
||||||
#define IN_UINT8_MV(_p) (*((_p)++))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* decompress an RLE color plane
|
|
||||||
* RDP6_BITMAP_STREAM
|
|
||||||
*/
|
|
||||||
static int process_rle_plane(BYTE* in, int width, int height, BYTE* out, int size)
|
|
||||||
{
|
|
||||||
int indexw;
|
|
||||||
int indexh;
|
|
||||||
int code;
|
|
||||||
int collen;
|
|
||||||
int replen;
|
|
||||||
int color;
|
|
||||||
int x;
|
|
||||||
int revcode;
|
|
||||||
BYTE* last_line;
|
|
||||||
BYTE* this_line;
|
|
||||||
BYTE* org_in;
|
|
||||||
BYTE* org_out;
|
|
||||||
|
|
||||||
org_in = in;
|
|
||||||
org_out = out;
|
|
||||||
last_line = 0;
|
|
||||||
indexh = 0;
|
|
||||||
while (indexh < height)
|
|
||||||
{
|
|
||||||
out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
|
|
||||||
color = 0;
|
|
||||||
this_line = out;
|
|
||||||
indexw = 0;
|
|
||||||
if (last_line == 0)
|
|
||||||
{
|
|
||||||
while (indexw < width)
|
|
||||||
{
|
|
||||||
code = IN_UINT8_MV(in);
|
|
||||||
replen = code & 0xf;
|
|
||||||
collen = (code >> 4) & 0xf;
|
|
||||||
revcode = (replen << 4) | collen;
|
|
||||||
if ((revcode <= 47) && (revcode >= 16))
|
|
||||||
{
|
|
||||||
replen = revcode;
|
|
||||||
collen = 0;
|
|
||||||
}
|
|
||||||
while (collen > 0)
|
|
||||||
{
|
|
||||||
color = IN_UINT8_MV(in);
|
|
||||||
*out = color;
|
|
||||||
out += 4;
|
|
||||||
indexw++;
|
|
||||||
collen--;
|
|
||||||
}
|
|
||||||
while (replen > 0)
|
|
||||||
{
|
|
||||||
*out = color;
|
|
||||||
out += 4;
|
|
||||||
indexw++;
|
|
||||||
replen--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (indexw < width)
|
|
||||||
{
|
|
||||||
code = IN_UINT8_MV(in);
|
|
||||||
replen = code & 0xf;
|
|
||||||
collen = (code >> 4) & 0xf;
|
|
||||||
revcode = (replen << 4) | collen;
|
|
||||||
if ((revcode <= 47) && (revcode >= 16))
|
|
||||||
{
|
|
||||||
replen = revcode;
|
|
||||||
collen = 0;
|
|
||||||
}
|
|
||||||
while (collen > 0)
|
|
||||||
{
|
|
||||||
x = IN_UINT8_MV(in);
|
|
||||||
if (x & 1)
|
|
||||||
{
|
|
||||||
x = x >> 1;
|
|
||||||
x = x + 1;
|
|
||||||
color = -x;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = x >> 1;
|
|
||||||
color = x;
|
|
||||||
}
|
|
||||||
x = last_line[indexw * 4] + color;
|
|
||||||
*out = x;
|
|
||||||
out += 4;
|
|
||||||
indexw++;
|
|
||||||
collen--;
|
|
||||||
}
|
|
||||||
while (replen > 0)
|
|
||||||
{
|
|
||||||
x = last_line[indexw * 4] + color;
|
|
||||||
*out = x;
|
|
||||||
out += 4;
|
|
||||||
indexw++;
|
|
||||||
replen--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
indexh++;
|
|
||||||
last_line = this_line;
|
|
||||||
}
|
|
||||||
return (int) (in - org_in);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* process a raw color plane
|
|
||||||
*/
|
|
||||||
static int process_raw_plane(BYTE* srcData, int width, int height, BYTE* dstData, int size)
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
for (x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (width * height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 4 byte bitmap decompress
|
|
||||||
* RDP6_BITMAP_STREAM
|
|
||||||
*/
|
|
||||||
static BOOL bitmap_decompress4(BYTE* srcData, BYTE* dstData, int width, int height, int size)
|
|
||||||
{
|
|
||||||
int RLE;
|
|
||||||
int code;
|
|
||||||
int NoAlpha;
|
|
||||||
int bytes_processed;
|
|
||||||
int total_processed;
|
|
||||||
|
|
||||||
code = IN_UINT8_MV(srcData);
|
|
||||||
RLE = code & 0x10;
|
|
||||||
|
|
||||||
total_processed = 1;
|
|
||||||
NoAlpha = code & 0x20;
|
|
||||||
|
|
||||||
if (NoAlpha == 0)
|
|
||||||
{
|
|
||||||
bytes_processed = process_rle_plane(srcData, width, height, dstData + 3, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
srcData += bytes_processed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RLE != 0)
|
|
||||||
{
|
|
||||||
bytes_processed = process_rle_plane(srcData, width, height, dstData + 2, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
srcData += bytes_processed;
|
|
||||||
|
|
||||||
bytes_processed = process_rle_plane(srcData, width, height, dstData + 1, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
srcData += bytes_processed;
|
|
||||||
|
|
||||||
bytes_processed = process_rle_plane(srcData, width, height, dstData + 0, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bytes_processed = process_raw_plane(srcData, width, height, dstData + 2, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
srcData += bytes_processed;
|
|
||||||
|
|
||||||
bytes_processed = process_raw_plane(srcData, width, height, dstData + 1, size - total_processed);
|
|
||||||
total_processed += bytes_processed;
|
|
||||||
srcData += bytes_processed;
|
|
||||||
|
|
||||||
bytes_processed = process_raw_plane(srcData, width, height, dstData + 0, size - total_processed);
|
|
||||||
total_processed += bytes_processed + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (size == total_processed) ? TRUE : FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bitmap decompression routine
|
* bitmap decompression routine
|
||||||
*/
|
*/
|
||||||
@ -451,7 +271,7 @@ BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int
|
|||||||
}
|
}
|
||||||
else if (srcBpp == 32 && dstBpp == 32)
|
else if (srcBpp == 32 && dstBpp == 32)
|
||||||
{
|
{
|
||||||
if (!bitmap_decompress4(srcData, dstData, width, height, size))
|
if (freerdp_bitmap_planar_decompress(srcData, dstData, width, height, size) < 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else if (srcBpp == 15 && dstBpp == 15)
|
else if (srcBpp == 15 && dstBpp == 15)
|
||||||
|
@ -23,27 +23,9 @@
|
|||||||
|
|
||||||
#include <freerdp/codec/bitmap.h>
|
#include <freerdp/codec/bitmap.h>
|
||||||
|
|
||||||
#define GETPIXEL8(d, x, y, w) (*(((unsigned char*)d) + ((y) * (w) + (x))))
|
|
||||||
#define GETPIXEL16(d, x, y, w) (*(((unsigned short*)d) + ((y) * (w) + (x))))
|
#define GETPIXEL16(d, x, y, w) (*(((unsigned short*)d) + ((y) * (w) + (x))))
|
||||||
#define GETPIXEL32(d, x, y, w) (*(((unsigned int*)d) + ((y) * (w) + (x))))
|
#define GETPIXEL32(d, x, y, w) (*(((unsigned int*)d) + ((y) * (w) + (x))))
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
#define IN_PIXEL8(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
|
|
||||||
{ \
|
|
||||||
if (in_ptr == 0) \
|
|
||||||
{ \
|
|
||||||
in_pixel = 0; \
|
|
||||||
} \
|
|
||||||
else if (in_x < in_w) \
|
|
||||||
{ \
|
|
||||||
in_pixel = GETPIXEL8(in_ptr, in_x, in_y, in_w); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
in_pixel = in_last_pixel; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
#define IN_PIXEL16(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
|
#define IN_PIXEL16(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
|
||||||
{ \
|
{ \
|
||||||
@ -78,35 +60,6 @@
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* color */
|
|
||||||
#define OUT_COLOR_COUNT1(in_count, in_s, in_data) \
|
|
||||||
{ \
|
|
||||||
if (in_count > 0) \
|
|
||||||
{ \
|
|
||||||
if (in_count < 32) \
|
|
||||||
{ \
|
|
||||||
temp = (0x3 << 5) | in_count; \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
Stream_Write_UINT8(in_s, in_data); \
|
|
||||||
} \
|
|
||||||
else if (in_count < 256 + 32) \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0x60); \
|
|
||||||
temp = in_count - 32; \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
Stream_Write_UINT8(in_s, in_data); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0xf3); \
|
|
||||||
Stream_Write_UINT16(in_s, in_count); \
|
|
||||||
Stream_Write_UINT8(in_s, in_data); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
in_count = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* color */
|
/* color */
|
||||||
#define OUT_COLOR_COUNT2(in_count, in_s, in_data) \
|
#define OUT_COLOR_COUNT2(in_count, in_s, in_data) \
|
||||||
@ -171,36 +124,6 @@
|
|||||||
in_count = 0; \
|
in_count = 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* copy */
|
|
||||||
#define OUT_COPY_COUNT1(in_count, in_s, in_data) \
|
|
||||||
{ \
|
|
||||||
if (in_count > 0) \
|
|
||||||
{ \
|
|
||||||
if (in_count < 32) \
|
|
||||||
{ \
|
|
||||||
temp = (0x4 << 5) | in_count; \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
Stream_Write(in_s, Stream_Buffer(in_data), in_count); \
|
|
||||||
} \
|
|
||||||
else if (in_count < 256 + 32) \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0x80); \
|
|
||||||
temp = in_count - 32; \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
Stream_Write(in_s, Stream_Buffer(in_data), in_count); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0xf4); \
|
|
||||||
Stream_Write_UINT16(in_s, in_count); \
|
|
||||||
Stream_Write(in_s, Stream_Buffer(in_data), in_count); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
in_count = 0; \
|
|
||||||
Stream_SetPosition(in_data, 0); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* copy */
|
/* copy */
|
||||||
#define OUT_COPY_COUNT2(in_count, in_s, in_data) \
|
#define OUT_COPY_COUNT2(in_count, in_s, in_data) \
|
||||||
@ -267,39 +190,6 @@
|
|||||||
Stream_SetPosition(in_data, 0); \
|
Stream_SetPosition(in_data, 0); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* bicolor */
|
|
||||||
#define OUT_BICOLOR_COUNT1(in_count, in_s, in_color1, in_color2) \
|
|
||||||
{ \
|
|
||||||
if (in_count > 0) \
|
|
||||||
{ \
|
|
||||||
if (in_count / 2 < 16) \
|
|
||||||
{ \
|
|
||||||
temp = (0xe << 4) | (in_count / 2); \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
Stream_Write_UINT8(in_s, in_color1); \
|
|
||||||
Stream_Write_UINT8(in_s, in_color2); \
|
|
||||||
} \
|
|
||||||
else if (in_count / 2 < 256 + 16) \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0xe0); \
|
|
||||||
temp = in_count / 2 - 16; \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
Stream_Write_UINT8(in_s, in_color1); \
|
|
||||||
Stream_Write_UINT8(in_s, in_color2); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0xf8); \
|
|
||||||
temp = in_count / 2; \
|
|
||||||
Stream_Write_UINT16(in_s, temp); \
|
|
||||||
Stream_Write_UINT8(in_s, in_color1); \
|
|
||||||
Stream_Write_UINT8(in_s, in_color2); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
in_count = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* bicolor */
|
/* bicolor */
|
||||||
#define OUT_BICOLOR_COUNT2(in_count, in_s, in_color1, in_color2) \
|
#define OUT_BICOLOR_COUNT2(in_count, in_s, in_color1, in_color2) \
|
||||||
@ -378,31 +268,6 @@
|
|||||||
in_count = 0; \
|
in_count = 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* fill */
|
|
||||||
#define OUT_FILL_COUNT1(in_count, in_s) \
|
|
||||||
{ \
|
|
||||||
if (in_count > 0) \
|
|
||||||
{ \
|
|
||||||
if (in_count < 32) \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, in_count); \
|
|
||||||
} \
|
|
||||||
else if (in_count < 256 + 32) \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0x0); \
|
|
||||||
temp = in_count - 32; \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0xf0); \
|
|
||||||
Stream_Write_UINT16(in_s, in_count); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
in_count = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* fill */
|
/* fill */
|
||||||
#define OUT_FILL_COUNT2(in_count, in_s) \
|
#define OUT_FILL_COUNT2(in_count, in_s) \
|
||||||
@ -453,32 +318,6 @@
|
|||||||
in_count = 0; \
|
in_count = 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* mix */
|
|
||||||
#define OUT_MIX_COUNT1(in_count, in_s) \
|
|
||||||
{ \
|
|
||||||
if (in_count > 0) \
|
|
||||||
{ \
|
|
||||||
if (in_count < 32) \
|
|
||||||
{ \
|
|
||||||
temp = (0x1 << 5) | in_count; \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
} \
|
|
||||||
else if (in_count < 256 + 32) \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0x20); \
|
|
||||||
temp = in_count - 32; \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0xf1); \
|
|
||||||
Stream_Write_UINT16(in_s, in_count); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
in_count = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* mix */
|
/* mix */
|
||||||
#define OUT_MIX_COUNT2(in_count, in_s) \
|
#define OUT_MIX_COUNT2(in_count, in_s) \
|
||||||
@ -531,35 +370,6 @@
|
|||||||
in_count = 0; \
|
in_count = 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* fom */
|
|
||||||
#define OUT_FOM_COUNT1(in_count, in_s, in_mask, in_mask_len) \
|
|
||||||
{ \
|
|
||||||
if (in_count > 0) \
|
|
||||||
{ \
|
|
||||||
if ((in_count % 8) == 0 && in_count < 249) \
|
|
||||||
{ \
|
|
||||||
temp = (0x2 << 5) | (in_count / 8); \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
Stream_Write(in_s, in_mask, in_mask_len); \
|
|
||||||
} \
|
|
||||||
else if (in_count < 256) \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0x40); \
|
|
||||||
temp = in_count - 1; \
|
|
||||||
Stream_Write_UINT8(in_s, temp); \
|
|
||||||
Stream_Write(in_s, in_mask, in_mask_len); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
Stream_Write_UINT8(in_s, 0xf2); \
|
|
||||||
Stream_Write_UINT16(in_s, in_count); \
|
|
||||||
Stream_Write(in_s, in_mask, in_mask_len); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
in_count = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* fom */
|
/* fom */
|
||||||
#define OUT_FOM_COUNT2(in_count, in_s, in_mask, in_mask_len) \
|
#define OUT_FOM_COUNT2(in_count, in_s, in_mask, in_mask_len) \
|
||||||
@ -618,7 +428,6 @@
|
|||||||
in_count = 0; \
|
in_count = 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
#define TEST_FILL \
|
#define TEST_FILL \
|
||||||
((last_line == 0 && pixel == 0) || \
|
((last_line == 0 && pixel == 0) || \
|
||||||
(last_line != 0 && pixel == ypixel))
|
(last_line != 0 && pixel == ypixel))
|
||||||
@ -646,8 +455,7 @@
|
|||||||
bicolor_spin = 0; \
|
bicolor_spin = 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
int freerdp_bitmap_compress(char* srcData, int width, int height,
|
||||||
int freerdp_bitmap_compress(char* in_data, int width, int height,
|
|
||||||
wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e)
|
wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e)
|
||||||
{
|
{
|
||||||
char *line;
|
char *line;
|
||||||
@ -691,303 +499,11 @@ int freerdp_bitmap_compress(char* in_data, int width, int height,
|
|||||||
mix_count = 0;
|
mix_count = 0;
|
||||||
fom_count = 0;
|
fom_count = 0;
|
||||||
|
|
||||||
if (bpp == 8)
|
if ((bpp == 15) || (bpp == 16))
|
||||||
{
|
|
||||||
mix = 0xFF;
|
|
||||||
out_count = end;
|
|
||||||
line = in_data + width * start_line;
|
|
||||||
|
|
||||||
while (start_line >= 0 && out_count < 32768)
|
|
||||||
{
|
|
||||||
i = Stream_GetPosition(s) + count;
|
|
||||||
|
|
||||||
if (i - color_count >= byte_limit &&
|
|
||||||
i - bicolor_count >= byte_limit &&
|
|
||||||
i - fill_count >= byte_limit &&
|
|
||||||
i - mix_count >= byte_limit &&
|
|
||||||
i - fom_count >= byte_limit)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_count += end;
|
|
||||||
|
|
||||||
for (i = 0; i < end; i++)
|
|
||||||
{
|
|
||||||
/* read next pixel */
|
|
||||||
IN_PIXEL8(line, i, 0, width, last_pixel, pixel);
|
|
||||||
IN_PIXEL8(last_line, i, 0, width, last_ypixel, ypixel);
|
|
||||||
|
|
||||||
if (!TEST_FILL)
|
|
||||||
{
|
|
||||||
if (fill_count > 3 &&
|
|
||||||
fill_count >= color_count &&
|
|
||||||
fill_count >= bicolor_count &&
|
|
||||||
fill_count >= mix_count &&
|
|
||||||
fill_count >= fom_count)
|
|
||||||
{
|
|
||||||
count -= fill_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_FILL_COUNT1(fill_count, s);
|
|
||||||
RESET_COUNTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
fill_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TEST_MIX)
|
|
||||||
{
|
|
||||||
if (mix_count > 3 &&
|
|
||||||
mix_count >= fill_count &&
|
|
||||||
mix_count >= bicolor_count &&
|
|
||||||
mix_count >= color_count &&
|
|
||||||
mix_count >= fom_count)
|
|
||||||
{
|
|
||||||
count -= mix_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_MIX_COUNT1(mix_count, s);
|
|
||||||
RESET_COUNTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
mix_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TEST_COLOR)
|
|
||||||
{
|
|
||||||
if (color_count > 3 &&
|
|
||||||
color_count >= fill_count &&
|
|
||||||
color_count >= bicolor_count &&
|
|
||||||
color_count >= mix_count &&
|
|
||||||
color_count >= fom_count)
|
|
||||||
{
|
|
||||||
count -= color_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_COLOR_COUNT1(color_count, s, last_pixel);
|
|
||||||
RESET_COUNTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
color_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TEST_BICOLOR)
|
|
||||||
{
|
|
||||||
if (bicolor_count > 3 &&
|
|
||||||
bicolor_count >= fill_count &&
|
|
||||||
bicolor_count >= color_count &&
|
|
||||||
bicolor_count >= mix_count &&
|
|
||||||
bicolor_count >= fom_count)
|
|
||||||
{
|
|
||||||
if ((bicolor_count % 2) == 0)
|
|
||||||
{
|
|
||||||
count -= bicolor_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bicolor_count--;
|
|
||||||
count -= bicolor_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor2, bicolor1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RESET_COUNTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
bicolor_count = 0;
|
|
||||||
bicolor1 = last_pixel;
|
|
||||||
bicolor2 = pixel;
|
|
||||||
bicolor_spin = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TEST_FOM)
|
|
||||||
{
|
|
||||||
if (fom_count > 3 &&
|
|
||||||
fom_count >= fill_count &&
|
|
||||||
fom_count >= color_count &&
|
|
||||||
fom_count >= mix_count &&
|
|
||||||
fom_count >= bicolor_count)
|
|
||||||
{
|
|
||||||
count -= fom_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
|
|
||||||
RESET_COUNTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
fom_count = 0;
|
|
||||||
fom_mask_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_FILL)
|
|
||||||
{
|
|
||||||
fill_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_MIX)
|
|
||||||
{
|
|
||||||
mix_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_COLOR)
|
|
||||||
{
|
|
||||||
color_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_BICOLOR)
|
|
||||||
{
|
|
||||||
bicolor_spin = !bicolor_spin;
|
|
||||||
bicolor_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_FOM)
|
|
||||||
{
|
|
||||||
if ((fom_count % 8) == 0)
|
|
||||||
{
|
|
||||||
fom_mask[fom_mask_len] = 0;
|
|
||||||
fom_mask_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pixel == (ypixel ^ mix))
|
|
||||||
{
|
|
||||||
fom_mask[fom_mask_len - 1] |= (1 << (fom_count % 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
fom_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream_Write_UINT8(temp_s, pixel);
|
|
||||||
count++;
|
|
||||||
last_pixel = pixel;
|
|
||||||
last_ypixel = ypixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* can't take fix, mix, or fom past first line */
|
|
||||||
if (last_line == 0)
|
|
||||||
{
|
|
||||||
if (fill_count > 3 &&
|
|
||||||
fill_count >= color_count &&
|
|
||||||
fill_count >= bicolor_count &&
|
|
||||||
fill_count >= mix_count &&
|
|
||||||
fill_count >= fom_count)
|
|
||||||
{
|
|
||||||
count -= fill_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_FILL_COUNT1(fill_count, s);
|
|
||||||
RESET_COUNTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
fill_count = 0;
|
|
||||||
|
|
||||||
if (mix_count > 3 &&
|
|
||||||
mix_count >= fill_count &&
|
|
||||||
mix_count >= bicolor_count &&
|
|
||||||
mix_count >= color_count &&
|
|
||||||
mix_count >= fom_count)
|
|
||||||
{
|
|
||||||
count -= mix_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_MIX_COUNT1(mix_count, s);
|
|
||||||
RESET_COUNTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
mix_count = 0;
|
|
||||||
|
|
||||||
if (fom_count > 3 &&
|
|
||||||
fom_count >= fill_count &&
|
|
||||||
fom_count >= color_count &&
|
|
||||||
fom_count >= mix_count &&
|
|
||||||
fom_count >= bicolor_count)
|
|
||||||
{
|
|
||||||
count -= fom_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
|
|
||||||
RESET_COUNTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
fom_count = 0;
|
|
||||||
fom_mask_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
last_line = line;
|
|
||||||
line = line - width;
|
|
||||||
start_line--;
|
|
||||||
lines_sent++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fill_count > 3 &&
|
|
||||||
fill_count >= color_count &&
|
|
||||||
fill_count >= bicolor_count &&
|
|
||||||
fill_count >= mix_count &&
|
|
||||||
fill_count >= fom_count)
|
|
||||||
{
|
|
||||||
count -= fill_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_FILL_COUNT1(fill_count, s);
|
|
||||||
}
|
|
||||||
else if (mix_count > 3 &&
|
|
||||||
mix_count >= color_count &&
|
|
||||||
mix_count >= bicolor_count &&
|
|
||||||
mix_count >= fill_count &&
|
|
||||||
mix_count >= fom_count)
|
|
||||||
{
|
|
||||||
count -= mix_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_MIX_COUNT1(mix_count, s);
|
|
||||||
}
|
|
||||||
else if (color_count > 3 &&
|
|
||||||
color_count >= mix_count &&
|
|
||||||
color_count >= bicolor_count &&
|
|
||||||
color_count >= fill_count &&
|
|
||||||
color_count >= fom_count)
|
|
||||||
{
|
|
||||||
count -= color_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_COLOR_COUNT1(color_count, s, last_pixel);
|
|
||||||
}
|
|
||||||
else if (bicolor_count > 3 &&
|
|
||||||
bicolor_count >= mix_count &&
|
|
||||||
bicolor_count >= color_count &&
|
|
||||||
bicolor_count >= fill_count &&
|
|
||||||
bicolor_count >= fom_count)
|
|
||||||
{
|
|
||||||
if ((bicolor_count % 2) == 0)
|
|
||||||
{
|
|
||||||
count -= bicolor_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bicolor_count--;
|
|
||||||
count -= bicolor_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor2, bicolor1);
|
|
||||||
}
|
|
||||||
|
|
||||||
count -= bicolor_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
|
|
||||||
}
|
|
||||||
else if (fom_count > 3 &&
|
|
||||||
fom_count >= mix_count &&
|
|
||||||
fom_count >= color_count &&
|
|
||||||
fom_count >= fill_count &&
|
|
||||||
fom_count >= bicolor_count)
|
|
||||||
{
|
|
||||||
count -= fom_count;
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OUT_COPY_COUNT1(count, s, temp_s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((bpp == 15) || (bpp == 16))
|
|
||||||
{
|
{
|
||||||
mix = (bpp == 15) ? 0xBA1F : 0xFFFF;
|
mix = (bpp == 15) ? 0xBA1F : 0xFFFF;
|
||||||
out_count = end * 2;
|
out_count = end * 2;
|
||||||
line = in_data + width * start_line * 2;
|
line = srcData + width * start_line * 2;
|
||||||
|
|
||||||
while (start_line >= 0 && out_count < 32768)
|
while (start_line >= 0 && out_count < 32768)
|
||||||
{
|
{
|
||||||
@ -1279,7 +795,7 @@ int freerdp_bitmap_compress(char* in_data, int width, int height,
|
|||||||
{
|
{
|
||||||
mix = 0xFFFFFF;
|
mix = 0xFFFFFF;
|
||||||
out_count = end * 3;
|
out_count = end * 3;
|
||||||
line = in_data + width * start_line * 4;
|
line = srcData + width * start_line * 4;
|
||||||
|
|
||||||
while (start_line >= 0 && out_count < 32768)
|
while (start_line >= 0 && out_count < 32768)
|
||||||
{
|
{
|
||||||
@ -1572,153 +1088,3 @@ int freerdp_bitmap_compress(char* in_data, int width, int height,
|
|||||||
|
|
||||||
return lines_sent;
|
return lines_sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* RDP6 Bitmap Test Case ([MS-RDPEGDI])
|
|
||||||
*/
|
|
||||||
|
|
||||||
const BYTE TEST_RDP6_COMPRESSED_BITMAP[220] =
|
|
||||||
"\x85\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x06\x8B\x99\xD6\x99"
|
|
||||||
"\xD6\x99\xD6\x10\x84\x08\x42\x08\x42\x10\x84\x99\xD6\x99\xD6\x99"
|
|
||||||
"\xD6\x99\xD6\x06\x84\x99\xD6\x99\xD6\x99\xD6\xFF\xFF\x16\x69\x99"
|
|
||||||
"\xD6\x06\x69\x99\xD6\x04\xCC\x89\x52\x03\x6E\xFF\xFF\x02\x6E\x08"
|
|
||||||
"\x42\x01\x70\x08\x42\x71\xFF\xFF\xCE\x18\xC6\x01\x81\x08\x42\xCE"
|
|
||||||
"\x66\x29\x02\xCD\x89\x52\x03\x88\x10\x84\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x00\x00\xD8\x99\xD6\x03\xF8\x01\x00\x00"
|
|
||||||
"\x00\x00\xF0\x66\x99\xD6\x05\x6A\x99\xD6\x00\xC4\xCC\x89\x52\x03"
|
|
||||||
"\x6E\xFF\xFF\x02\x6E\x08\x42\x01\x70\x08\x42\x71\xFF\xFF\xCE\x18"
|
|
||||||
"\xC6\x01\x81\x08\x42\xCE\x66\x29\x02\xCD\x89\x52\x03\x00\x04\xD6"
|
|
||||||
"\x99\xD6\xC3\x80\x61\x00\xA5\x80\x40\xEC\x52\x00\x5A\x00\x2D\x00"
|
|
||||||
"\x24\x00\x12\x00\x24\x00\x12\x00\x5A\x00\x2D\x00\xA5\x80\x52\x00"
|
|
||||||
"\xC3\x80\x61\x00\x00\x00\x00\x00\xCC\x89\x52\x03\x6E\xFF\xFF\x02"
|
|
||||||
"\xCB\x18\xC6\x84\x08\x42\x08\x42\x08\x42\xFF\xFF";
|
|
||||||
|
|
||||||
const BYTE TEST_RDP6_UNCOMPRESSED_BITMAP[2048] =
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
|
|
||||||
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
|
|
||||||
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
|
|
||||||
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
|
|
||||||
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
|
|
||||||
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
|
|
||||||
"\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
|
|
||||||
"\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
|
|
||||||
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
|
|
||||||
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
|
|
||||||
"\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
|
|
||||||
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
|
|
||||||
"\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
|
|
||||||
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
|
||||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
|
|
||||||
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF";
|
|
||||||
|
860
libfreerdp/codec/planar.c
Normal file
860
libfreerdp/codec/planar.c
Normal file
@ -0,0 +1,860 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* RDP6 Planar Codec
|
||||||
|
*
|
||||||
|
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/print.h>
|
||||||
|
|
||||||
|
#include <freerdp/codec/bitmap.h>
|
||||||
|
|
||||||
|
#include "planar.h"
|
||||||
|
|
||||||
|
static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int srcSize)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
int x, y;
|
||||||
|
BYTE* srcp;
|
||||||
|
BYTE* dstp;
|
||||||
|
UINT32 pixel;
|
||||||
|
int scanline;
|
||||||
|
int cRawBytes;
|
||||||
|
int nRunLength;
|
||||||
|
int deltaValue;
|
||||||
|
BYTE controlByte;
|
||||||
|
BYTE* currentScanline;
|
||||||
|
BYTE* previousScanline;
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
|
||||||
|
srcp = inPlane;
|
||||||
|
dstp = outPlane;
|
||||||
|
scanline = width * 4;
|
||||||
|
previousScanline = NULL;
|
||||||
|
|
||||||
|
y = 0;
|
||||||
|
|
||||||
|
while (y < height)
|
||||||
|
{
|
||||||
|
pixel = 0;
|
||||||
|
dstp = (outPlane + height * scanline) - ((y + 1) * scanline);
|
||||||
|
currentScanline = dstp;
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
|
||||||
|
while (x < width)
|
||||||
|
{
|
||||||
|
controlByte = *srcp;
|
||||||
|
srcp++;
|
||||||
|
|
||||||
|
if ((srcp - inPlane) > srcSize)
|
||||||
|
{
|
||||||
|
printf("freerdp_bitmap_planar_decompress_plane_rle: error reading input buffer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nRunLength = PLANAR_CONTROL_BYTE_RUN_LENGTH(controlByte);
|
||||||
|
cRawBytes = PLANAR_CONTROL_BYTE_RAW_BYTES(controlByte);
|
||||||
|
|
||||||
|
//printf("CONTROL(%d, %d)\n", cRawBytes, nRunLength);
|
||||||
|
|
||||||
|
if (nRunLength == 1)
|
||||||
|
{
|
||||||
|
nRunLength = cRawBytes + 16;
|
||||||
|
cRawBytes = 0;
|
||||||
|
}
|
||||||
|
else if (nRunLength == 2)
|
||||||
|
{
|
||||||
|
nRunLength = cRawBytes + 32;
|
||||||
|
cRawBytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf("y: %d cRawBytes: %d nRunLength: %d\n", y, cRawBytes, nRunLength);
|
||||||
|
|
||||||
|
printf("RAW[");
|
||||||
|
|
||||||
|
for (k = 0; k < cRawBytes; k++)
|
||||||
|
{
|
||||||
|
printf("0x%02X%s", srcp[k],
|
||||||
|
((k + 1) == cRawBytes) ? "" : ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("] RUN[%d]\n", nRunLength);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > width * 4)
|
||||||
|
{
|
||||||
|
printf("freerdp_bitmap_planar_decompress_plane_rle: too many pixels in scanline\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!previousScanline)
|
||||||
|
{
|
||||||
|
/* first scanline, absolute values */
|
||||||
|
|
||||||
|
while (cRawBytes > 0)
|
||||||
|
{
|
||||||
|
pixel = *srcp;
|
||||||
|
srcp++;
|
||||||
|
|
||||||
|
*dstp = pixel;
|
||||||
|
dstp += 4;
|
||||||
|
x++;
|
||||||
|
cRawBytes--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (nRunLength > 0)
|
||||||
|
{
|
||||||
|
*dstp = pixel;
|
||||||
|
dstp += 4;
|
||||||
|
x++;
|
||||||
|
nRunLength--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* delta values relative to previous scanline */
|
||||||
|
|
||||||
|
while (cRawBytes > 0)
|
||||||
|
{
|
||||||
|
deltaValue = *srcp;
|
||||||
|
srcp++;
|
||||||
|
|
||||||
|
if (deltaValue & 1)
|
||||||
|
{
|
||||||
|
deltaValue = deltaValue >> 1;
|
||||||
|
deltaValue = deltaValue + 1;
|
||||||
|
pixel = -deltaValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deltaValue = deltaValue >> 1;
|
||||||
|
pixel = deltaValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
deltaValue = previousScanline[x * 4] + pixel;
|
||||||
|
*dstp = deltaValue;
|
||||||
|
dstp += 4;
|
||||||
|
x++;
|
||||||
|
cRawBytes--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (nRunLength > 0)
|
||||||
|
{
|
||||||
|
deltaValue = previousScanline[x * 4] + pixel;
|
||||||
|
*dstp = deltaValue;
|
||||||
|
dstp += 4;
|
||||||
|
x++;
|
||||||
|
nRunLength--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previousScanline = currentScanline;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) (srcp - inPlane);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int freerdp_bitmap_planar_decompress_plane_raw(BYTE* srcData, int width, int height, BYTE* dstData, int size)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (width * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size)
|
||||||
|
{
|
||||||
|
BYTE* srcp;
|
||||||
|
int dstSize;
|
||||||
|
BYTE FormatHeader;
|
||||||
|
|
||||||
|
srcp = srcData;
|
||||||
|
|
||||||
|
FormatHeader = *srcp;
|
||||||
|
srcp++;
|
||||||
|
|
||||||
|
/* AlphaPlane */
|
||||||
|
|
||||||
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
|
||||||
|
{
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 3, size - (srcp - srcData));
|
||||||
|
|
||||||
|
if (dstSize < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
srcp += dstSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 3, size - (srcp - srcData));
|
||||||
|
srcp += dstSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
/* LumaOrRedPlane */
|
||||||
|
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 2, size - (srcp - srcData));
|
||||||
|
|
||||||
|
if (dstSize < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
srcp += dstSize;
|
||||||
|
|
||||||
|
/* OrangeChromaOrGreenPlane */
|
||||||
|
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 1, size - (srcp - srcData));
|
||||||
|
|
||||||
|
if (dstSize < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
srcp += dstSize;
|
||||||
|
|
||||||
|
/* GreenChromeOrBluePlane */
|
||||||
|
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 0, size - (srcp - srcData));
|
||||||
|
|
||||||
|
if (dstSize < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
srcp += dstSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* LumaOrRedPlane */
|
||||||
|
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 2, size - (srcp - srcData));
|
||||||
|
srcp += dstSize;
|
||||||
|
|
||||||
|
/* OrangeChromaOrGreenPlane */
|
||||||
|
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 1, size - (srcp - srcData));
|
||||||
|
srcp += dstSize;
|
||||||
|
|
||||||
|
/* GreenChromeOrBluePlane */
|
||||||
|
|
||||||
|
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 0, size - (srcp - srcData));
|
||||||
|
srcp += dstSize;
|
||||||
|
srcp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (size == (srcp - srcData)) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4])
|
||||||
|
{
|
||||||
|
int bpp;
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
bpp = FREERDP_PIXEL_FORMAT_BPP(format);
|
||||||
|
|
||||||
|
if (bpp == 32)
|
||||||
|
{
|
||||||
|
UINT32* pixel;
|
||||||
|
|
||||||
|
for (i = height - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
pixel = (UINT32*) &data[scanline * i];
|
||||||
|
|
||||||
|
for (j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
GetARGB32(planes[0][k], planes[1][k], planes[2][k], planes[3][k], *pixel);
|
||||||
|
pixel++;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bpp == 24)
|
||||||
|
{
|
||||||
|
UINT32* pixel;
|
||||||
|
|
||||||
|
for (i = height - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
pixel = (UINT32*) &data[scanline * i];
|
||||||
|
|
||||||
|
for (j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
GetRGB32(planes[1][k], planes[2][k], planes[3][k], *pixel);
|
||||||
|
planes[0][k] = 0xFF; /* A */
|
||||||
|
pixel++;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_write_rle_bytes(BYTE* pInBuffer, int cRawBytes, int nRunLength, BYTE* pOutBuffer, int outBufferSize)
|
||||||
|
{
|
||||||
|
BYTE* pInput;
|
||||||
|
BYTE* pOutput;
|
||||||
|
BYTE controlByte;
|
||||||
|
int nBytesToWrite;
|
||||||
|
|
||||||
|
pInput = pInBuffer;
|
||||||
|
pOutput = pOutBuffer;
|
||||||
|
|
||||||
|
if (!cRawBytes && !nRunLength)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (nRunLength < 3)
|
||||||
|
{
|
||||||
|
cRawBytes += nRunLength;
|
||||||
|
nRunLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cRawBytes)
|
||||||
|
{
|
||||||
|
if (cRawBytes < 16)
|
||||||
|
{
|
||||||
|
if (nRunLength > 15)
|
||||||
|
{
|
||||||
|
if (nRunLength < 18)
|
||||||
|
{
|
||||||
|
controlByte = PLANAR_CONTROL_BYTE(13, cRawBytes);
|
||||||
|
nRunLength -= 13;
|
||||||
|
cRawBytes = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controlByte = PLANAR_CONTROL_BYTE(15, cRawBytes);
|
||||||
|
nRunLength -= 15;
|
||||||
|
cRawBytes = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controlByte = PLANAR_CONTROL_BYTE(nRunLength, cRawBytes);
|
||||||
|
nRunLength = 0;
|
||||||
|
cRawBytes = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controlByte = PLANAR_CONTROL_BYTE(0, 15);
|
||||||
|
cRawBytes -= 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outBufferSize < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
outBufferSize--;
|
||||||
|
|
||||||
|
*pOutput = controlByte;
|
||||||
|
pOutput++;
|
||||||
|
|
||||||
|
nBytesToWrite = (int) (controlByte >> 4);
|
||||||
|
|
||||||
|
if (nBytesToWrite)
|
||||||
|
{
|
||||||
|
if (outBufferSize < nBytesToWrite)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
outBufferSize -= nBytesToWrite;
|
||||||
|
CopyMemory(pOutput, pInput, nBytesToWrite);
|
||||||
|
pOutput += nBytesToWrite;
|
||||||
|
pInput += nBytesToWrite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (nRunLength)
|
||||||
|
{
|
||||||
|
if (nRunLength > 47)
|
||||||
|
{
|
||||||
|
if (nRunLength < 50)
|
||||||
|
{
|
||||||
|
controlByte = PLANAR_CONTROL_BYTE(2, 13);
|
||||||
|
nRunLength -= 45;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controlByte = PLANAR_CONTROL_BYTE(2, 15);
|
||||||
|
nRunLength -= 47;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (nRunLength > 31)
|
||||||
|
{
|
||||||
|
controlByte = PLANAR_CONTROL_BYTE(2, (nRunLength - 32));
|
||||||
|
nRunLength = 0;
|
||||||
|
}
|
||||||
|
else if (nRunLength > 15)
|
||||||
|
{
|
||||||
|
controlByte = PLANAR_CONTROL_BYTE(1, (nRunLength - 16));
|
||||||
|
nRunLength = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controlByte = PLANAR_CONTROL_BYTE(nRunLength, 0);
|
||||||
|
nRunLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outBufferSize < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
--outBufferSize;
|
||||||
|
*pOutput = controlByte;
|
||||||
|
pOutput++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pOutput - pOutBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_encode_rle_bytes(BYTE* pInBuffer, int inBufferSize, BYTE* pOutBuffer, int outBufferSize)
|
||||||
|
{
|
||||||
|
BYTE symbol;
|
||||||
|
BYTE* pInput;
|
||||||
|
BYTE* pOutput;
|
||||||
|
BYTE* pBytes;
|
||||||
|
int cRawBytes;
|
||||||
|
int nRunLength;
|
||||||
|
int bSymbolMatch;
|
||||||
|
int nBytesWritten;
|
||||||
|
int nTotalBytesWritten;
|
||||||
|
|
||||||
|
symbol = 0;
|
||||||
|
cRawBytes = 0;
|
||||||
|
nRunLength = 0;
|
||||||
|
pInput = pInBuffer;
|
||||||
|
pOutput = pOutBuffer;
|
||||||
|
nTotalBytesWritten = 0;
|
||||||
|
|
||||||
|
if (!outBufferSize)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!inBufferSize)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bSymbolMatch = (symbol == *pInput) ? TRUE : FALSE;
|
||||||
|
symbol = *pInput;
|
||||||
|
pInput++;
|
||||||
|
inBufferSize--;
|
||||||
|
|
||||||
|
if (nRunLength && !bSymbolMatch)
|
||||||
|
{
|
||||||
|
if (nRunLength < 3)
|
||||||
|
{
|
||||||
|
cRawBytes += nRunLength;
|
||||||
|
nRunLength = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pBytes = pInput - (cRawBytes + nRunLength + 1);
|
||||||
|
|
||||||
|
nBytesWritten = freerdp_bitmap_planar_write_rle_bytes(pBytes,
|
||||||
|
cRawBytes, nRunLength, pOutput, outBufferSize);
|
||||||
|
|
||||||
|
nRunLength = 0;
|
||||||
|
|
||||||
|
if (!nBytesWritten || (nBytesWritten > outBufferSize))
|
||||||
|
return nRunLength;
|
||||||
|
|
||||||
|
nTotalBytesWritten += nBytesWritten;
|
||||||
|
outBufferSize -= nBytesWritten;
|
||||||
|
pOutput += nBytesWritten;
|
||||||
|
cRawBytes = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nRunLength += bSymbolMatch;
|
||||||
|
cRawBytes += (!bSymbolMatch) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
while (outBufferSize);
|
||||||
|
|
||||||
|
if (cRawBytes || nRunLength)
|
||||||
|
{
|
||||||
|
pBytes = pInput - (cRawBytes + nRunLength);
|
||||||
|
|
||||||
|
nBytesWritten = freerdp_bitmap_planar_write_rle_bytes(pBytes,
|
||||||
|
cRawBytes, nRunLength, pOutput, outBufferSize);
|
||||||
|
|
||||||
|
if (!nBytesWritten)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nTotalBytesWritten += nBytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inBufferSize)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return nTotalBytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int* dstSize)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
BYTE* pInput;
|
||||||
|
BYTE* pOutput;
|
||||||
|
int outBufferSize;
|
||||||
|
int nBytesWritten;
|
||||||
|
int nTotalBytesWritten;
|
||||||
|
|
||||||
|
if (!outPlane)
|
||||||
|
{
|
||||||
|
outBufferSize = width * height;
|
||||||
|
outPlane = malloc(outBufferSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outBufferSize = *dstSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
pInput = inPlane;
|
||||||
|
pOutput = outPlane;
|
||||||
|
nTotalBytesWritten = 0;
|
||||||
|
|
||||||
|
while (outBufferSize)
|
||||||
|
{
|
||||||
|
nBytesWritten = freerdp_bitmap_planar_encode_rle_bytes(pInput, width, pOutput, outBufferSize);
|
||||||
|
|
||||||
|
if ((!nBytesWritten) || (nBytesWritten > outBufferSize))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
outBufferSize -= nBytesWritten;
|
||||||
|
nTotalBytesWritten += nBytesWritten;
|
||||||
|
pOutput += nBytesWritten;
|
||||||
|
pInput += width;
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= height)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dstSize = nTotalBytesWritten;
|
||||||
|
|
||||||
|
return outPlane;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_compress_planes_rle(BYTE* inPlanes[4], int width, int height, BYTE* outPlanes, int* dstSizes, BOOL skipAlpha)
|
||||||
|
{
|
||||||
|
int outPlanesSize = width * height * 4;
|
||||||
|
|
||||||
|
/* AlphaPlane */
|
||||||
|
|
||||||
|
if (skipAlpha)
|
||||||
|
{
|
||||||
|
dstSizes[0] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstSizes[0] = outPlanesSize;
|
||||||
|
|
||||||
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[0], width, height, outPlanes, &dstSizes[0]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
outPlanes += dstSizes[0];
|
||||||
|
outPlanesSize -= dstSizes[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LumaOrRedPlane */
|
||||||
|
|
||||||
|
dstSizes[1] = outPlanesSize;
|
||||||
|
|
||||||
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[1], width, height, outPlanes, &dstSizes[1]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
outPlanes += dstSizes[1];
|
||||||
|
outPlanesSize -= dstSizes[1];
|
||||||
|
|
||||||
|
/* OrangeChromaOrGreenPlane */
|
||||||
|
|
||||||
|
dstSizes[2] = outPlanesSize;
|
||||||
|
|
||||||
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[2], width, height, outPlanes, &dstSizes[2]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
outPlanes += dstSizes[2];
|
||||||
|
outPlanesSize -= dstSizes[2];
|
||||||
|
|
||||||
|
/* GreenChromeOrBluePlane */
|
||||||
|
|
||||||
|
dstSizes[3] = outPlanesSize;
|
||||||
|
|
||||||
|
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[3], width, height, outPlanes, &dstSizes[3]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
outPlanes += dstSizes[3];
|
||||||
|
outPlanesSize -= dstSizes[3];
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane)
|
||||||
|
{
|
||||||
|
char s2c;
|
||||||
|
int delta;
|
||||||
|
int y, x;
|
||||||
|
BYTE *outPtr, *srcPtr, *prevLinePtr;
|
||||||
|
|
||||||
|
if (!outPlane)
|
||||||
|
outPlane = (BYTE*) malloc(width * height);
|
||||||
|
|
||||||
|
// first line is copied as is
|
||||||
|
CopyMemory(outPlane, inPlane, width);
|
||||||
|
|
||||||
|
outPtr = outPlane + width;
|
||||||
|
srcPtr = inPlane + width;
|
||||||
|
prevLinePtr = inPlane;
|
||||||
|
|
||||||
|
for (y = 1; y < height; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < width; x++, outPtr++, srcPtr++, prevLinePtr++)
|
||||||
|
{
|
||||||
|
delta = *srcPtr - *prevLinePtr;
|
||||||
|
|
||||||
|
s2c = (delta >= 0) ? (char) delta : (char) (~((BYTE) (-delta)) + 1);
|
||||||
|
|
||||||
|
s2c = (s2c >= 0) ? (s2c << 1) : (char) (((~((BYTE) s2c) + 1) << 1) - 1);
|
||||||
|
|
||||||
|
*outPtr = (BYTE)s2c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outPlane;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[4], int width, int height, BYTE* outPlanes[4])
|
||||||
|
{
|
||||||
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[0], width, height, outPlanes[0]);
|
||||||
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[1], width, height, outPlanes[1]);
|
||||||
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[2], width, height, outPlanes[2]);
|
||||||
|
freerdp_bitmap_planar_delta_encode_plane(inPlanes[3], width, height, outPlanes[3]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
|
||||||
|
int width, int height, int scanline, BYTE* dstData, int* dstSize)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
BYTE* dstp;
|
||||||
|
int planeSize;
|
||||||
|
int dstSizes[4];
|
||||||
|
BYTE FormatHeader = 0;
|
||||||
|
|
||||||
|
if (context->AllowSkipAlpha)
|
||||||
|
FormatHeader |= PLANAR_FORMAT_HEADER_NA;
|
||||||
|
|
||||||
|
planeSize = width * height;
|
||||||
|
|
||||||
|
freerdp_split_color_planes(data, format, width, height, scanline, context->planes);
|
||||||
|
|
||||||
|
if (context->AllowRunLengthEncoding)
|
||||||
|
{
|
||||||
|
freerdp_bitmap_planar_delta_encode_planes(context->planes, width, height, context->deltaPlanes);
|
||||||
|
|
||||||
|
if (freerdp_bitmap_planar_compress_planes_rle(context->deltaPlanes, width, height,
|
||||||
|
context->rlePlanesBuffer, (int*) &dstSizes, context->AllowSkipAlpha) > 0)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
FormatHeader |= PLANAR_FORMAT_HEADER_RLE;
|
||||||
|
|
||||||
|
context->rlePlanes[0] = &context->rlePlanesBuffer[offset];
|
||||||
|
offset += dstSizes[0];
|
||||||
|
|
||||||
|
context->rlePlanes[1] = &context->rlePlanesBuffer[offset];
|
||||||
|
offset += dstSizes[1];
|
||||||
|
|
||||||
|
context->rlePlanes[2] = &context->rlePlanesBuffer[offset];
|
||||||
|
offset += dstSizes[2];
|
||||||
|
|
||||||
|
context->rlePlanes[3] = &context->rlePlanesBuffer[offset];
|
||||||
|
offset += dstSizes[3];
|
||||||
|
|
||||||
|
//printf("R: [%d/%d] G: [%d/%d] B: [%d/%d]\n",
|
||||||
|
// dstSizes[1], planeSize, dstSizes[2], planeSize, dstSizes[3], planeSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dstData)
|
||||||
|
{
|
||||||
|
size = 1;
|
||||||
|
|
||||||
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
|
||||||
|
{
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
size += dstSizes[0];
|
||||||
|
else
|
||||||
|
size += planeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
size += (dstSizes[1] + dstSizes[2] + dstSizes[3]);
|
||||||
|
else
|
||||||
|
size += (planeSize * 3);
|
||||||
|
|
||||||
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_RLE))
|
||||||
|
size++;
|
||||||
|
|
||||||
|
dstData = malloc(size);
|
||||||
|
*dstSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
dstp = dstData;
|
||||||
|
|
||||||
|
*dstp = FormatHeader; /* FormatHeader */
|
||||||
|
dstp++;
|
||||||
|
|
||||||
|
/* AlphaPlane */
|
||||||
|
|
||||||
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
|
||||||
|
{
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, context->rlePlanes[0], dstSizes[0]); /* Alpha */
|
||||||
|
dstp += dstSizes[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, context->planes[0], planeSize); /* Alpha */
|
||||||
|
dstp += planeSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LumaOrRedPlane */
|
||||||
|
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, context->rlePlanes[1], dstSizes[1]); /* Red */
|
||||||
|
dstp += dstSizes[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, context->planes[1], planeSize); /* Red */
|
||||||
|
dstp += planeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OrangeChromaOrGreenPlane */
|
||||||
|
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, context->rlePlanes[2], dstSizes[2]); /* Green */
|
||||||
|
dstp += dstSizes[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, context->planes[2], planeSize); /* Green */
|
||||||
|
dstp += planeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GreenChromeOrBluePlane */
|
||||||
|
|
||||||
|
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, context->rlePlanes[3], dstSizes[3]); /* Blue */
|
||||||
|
dstp += dstSizes[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyMemory(dstp, context->planes[3], planeSize); /* Blue */
|
||||||
|
dstp += planeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pad1 (1 byte) */
|
||||||
|
|
||||||
|
if (!(FormatHeader & PLANAR_FORMAT_HEADER_RLE))
|
||||||
|
{
|
||||||
|
*dstp = 0;
|
||||||
|
dstp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = (dstp - dstData);
|
||||||
|
*dstSize = size;
|
||||||
|
|
||||||
|
return dstData;
|
||||||
|
}
|
||||||
|
|
||||||
|
BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight)
|
||||||
|
{
|
||||||
|
BITMAP_PLANAR_CONTEXT* context;
|
||||||
|
|
||||||
|
context = (BITMAP_PLANAR_CONTEXT*) malloc(sizeof(BITMAP_PLANAR_CONTEXT));
|
||||||
|
|
||||||
|
if (!context)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ZeroMemory(context, sizeof(BITMAP_PLANAR_CONTEXT));
|
||||||
|
|
||||||
|
if (flags & PLANAR_FORMAT_HEADER_NA)
|
||||||
|
context->AllowSkipAlpha = TRUE;
|
||||||
|
|
||||||
|
if (flags & PLANAR_FORMAT_HEADER_RLE)
|
||||||
|
context->AllowRunLengthEncoding = TRUE;
|
||||||
|
|
||||||
|
if (flags & PLANAR_FORMAT_HEADER_CS)
|
||||||
|
context->AllowColorSubsampling = TRUE;
|
||||||
|
|
||||||
|
context->ColorLossLevel = flags & PLANAR_FORMAT_HEADER_CLL_MASK;
|
||||||
|
|
||||||
|
if (context->ColorLossLevel)
|
||||||
|
context->AllowDynamicColorFidelity = TRUE;
|
||||||
|
|
||||||
|
context->maxWidth = maxWidth;
|
||||||
|
context->maxHeight = maxHeight;
|
||||||
|
context->maxPlaneSize = context->maxWidth * context->maxHeight;
|
||||||
|
|
||||||
|
context->planesBuffer = malloc(context->maxPlaneSize * 4);
|
||||||
|
context->planes[0] = &context->planesBuffer[context->maxPlaneSize * 0];
|
||||||
|
context->planes[1] = &context->planesBuffer[context->maxPlaneSize * 1];
|
||||||
|
context->planes[2] = &context->planesBuffer[context->maxPlaneSize * 2];
|
||||||
|
context->planes[3] = &context->planesBuffer[context->maxPlaneSize * 3];
|
||||||
|
|
||||||
|
context->deltaPlanesBuffer = malloc(context->maxPlaneSize * 4);
|
||||||
|
context->deltaPlanes[0] = &context->deltaPlanesBuffer[context->maxPlaneSize * 0];
|
||||||
|
context->deltaPlanes[1] = &context->deltaPlanesBuffer[context->maxPlaneSize * 1];
|
||||||
|
context->deltaPlanes[2] = &context->deltaPlanesBuffer[context->maxPlaneSize * 2];
|
||||||
|
context->deltaPlanes[3] = &context->deltaPlanesBuffer[context->maxPlaneSize * 3];
|
||||||
|
|
||||||
|
context->rlePlanesBuffer = malloc(context->maxPlaneSize * 4);
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context)
|
||||||
|
{
|
||||||
|
if (!context)
|
||||||
|
return;
|
||||||
|
|
||||||
|
free(context->planesBuffer);
|
||||||
|
free(context->deltaPlanesBuffer);
|
||||||
|
free(context->rlePlanesBuffer);
|
||||||
|
|
||||||
|
free(context);
|
||||||
|
}
|
97
libfreerdp/codec/planar.h
Normal file
97
libfreerdp/codec/planar.h
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* RDP6 Planar Codec
|
||||||
|
*
|
||||||
|
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREERDP_CODEC_PLANAR_PRIVATE_H
|
||||||
|
#define FREERDP_CODEC_PLANAR_PRIVATE_H
|
||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
|
|
||||||
|
#include <freerdp/codec/color.h>
|
||||||
|
#include <freerdp/codec/bitmap.h>
|
||||||
|
|
||||||
|
#define PLANAR_CONTROL_BYTE(_nRunLength, _cRawBytes) \
|
||||||
|
(_nRunLength & 0x0F) | ((_cRawBytes & 0x0F) << 4)
|
||||||
|
|
||||||
|
#define PLANAR_CONTROL_BYTE_RUN_LENGTH(_controlByte) (_controlByte & 0x0F)
|
||||||
|
#define PLANAR_CONTROL_BYTE_RAW_BYTES(_controlByte) ((_controlByte >> 4) & 0x0F)
|
||||||
|
|
||||||
|
struct _RDP6_RLE_SEGMENT
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* controlByte:
|
||||||
|
* [0-3]: nRunLength
|
||||||
|
* [4-7]: cRawBytes
|
||||||
|
*/
|
||||||
|
BYTE controlByte;
|
||||||
|
BYTE* rawValues;
|
||||||
|
};
|
||||||
|
typedef struct _RDP6_RLE_SEGMENT RDP6_RLE_SEGMENT;
|
||||||
|
|
||||||
|
struct _RDP6_RLE_SEGMENTS
|
||||||
|
{
|
||||||
|
UINT32 cSegments;
|
||||||
|
RDP6_RLE_SEGMENT* segments;
|
||||||
|
};
|
||||||
|
typedef struct _RDP6_RLE_SEGMENTS RDP6_RLE_SEGMENTS;
|
||||||
|
|
||||||
|
struct _RDP6_BITMAP_STREAM
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* formatHeader:
|
||||||
|
* [0-2]: Color Loss Level (CLL)
|
||||||
|
* [3] : Chroma Subsampling (CS)
|
||||||
|
* [4] : Run Length Encoding (RLE)
|
||||||
|
* [5] : No Alpha (NA)
|
||||||
|
* [6-7]: Reserved
|
||||||
|
*/
|
||||||
|
BYTE formatHeader;
|
||||||
|
};
|
||||||
|
typedef struct _RDP6_BITMAP_STREAM RDP6_BITMAP_STREAM;
|
||||||
|
|
||||||
|
struct _BITMAP_PLANAR_CONTEXT
|
||||||
|
{
|
||||||
|
int maxWidth;
|
||||||
|
int maxHeight;
|
||||||
|
int maxPlaneSize;
|
||||||
|
|
||||||
|
BOOL AllowSkipAlpha;
|
||||||
|
BOOL AllowRunLengthEncoding;
|
||||||
|
BOOL AllowColorSubsampling;
|
||||||
|
BOOL AllowDynamicColorFidelity;
|
||||||
|
|
||||||
|
int ColorLossLevel;
|
||||||
|
|
||||||
|
BYTE* planes[4];
|
||||||
|
BYTE* planesBuffer;
|
||||||
|
|
||||||
|
BYTE* deltaPlanes[4];
|
||||||
|
BYTE* deltaPlanesBuffer;
|
||||||
|
|
||||||
|
BYTE* rlePlanes[4];
|
||||||
|
BYTE* rlePlanesBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size);
|
||||||
|
|
||||||
|
int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4]);
|
||||||
|
BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* plane, int width, int height, BYTE* outPlane, int* dstSize);
|
||||||
|
BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane);
|
||||||
|
int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[4], int width, int height, BYTE* outPlanes[4]);
|
||||||
|
|
||||||
|
#endif /* FREERDP_CODEC_PLANAR_PRIVATE_H */
|
3
libfreerdp/codec/test/.gitignore
vendored
Normal file
3
libfreerdp/codec/test/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
TestFreeRDPCodec
|
||||||
|
TestFreeRDPCodec.c
|
||||||
|
|
32
libfreerdp/codec/test/CMakeLists.txt
Normal file
32
libfreerdp/codec/test/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
set(MODULE_NAME "TestFreeRDPCodec")
|
||||||
|
set(MODULE_PREFIX "TEST_FREERDP_CODEC")
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_TESTS
|
||||||
|
TestFreeRDPCodecMppc.c
|
||||||
|
TestFreeRDPCodecPlanar.c)
|
||||||
|
|
||||||
|
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||||
|
${${MODULE_PREFIX}_DRIVER}
|
||||||
|
${${MODULE_PREFIX}_TESTS})
|
||||||
|
|
||||||
|
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||||
|
|
||||||
|
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||||
|
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||||
|
MODULE freerdp
|
||||||
|
MODULES freerdp-codec)
|
||||||
|
|
||||||
|
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||||
|
|
||||||
|
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||||
|
|
||||||
|
foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||||
|
get_filename_component(TestName ${test} NAME_WE)
|
||||||
|
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Test")
|
||||||
|
|
684
libfreerdp/codec/test/TestFreeRDPCodecMppc.c
Normal file
684
libfreerdp/codec/test/TestFreeRDPCodecMppc.c
Normal file
@ -0,0 +1,684 @@
|
|||||||
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/print.h>
|
||||||
|
|
||||||
|
#include <freerdp/freerdp.h>
|
||||||
|
#include <freerdp/codec/mppc_dec.h>
|
||||||
|
#include <freerdp/codec/mppc_enc.h>
|
||||||
|
|
||||||
|
static BYTE TEST_RDP5_COMPRESSED_DATA[] =
|
||||||
|
{
|
||||||
|
0x24, 0x02, 0x03, 0x09, 0x00, 0x20, 0x0c, 0x05, 0x10, 0x01, 0x40, 0x0a, 0xbf, 0xdf, 0xc3, 0x20,
|
||||||
|
0x80, 0x00, 0x1f, 0x0a, 0x00, 0x00, 0x07, 0x43, 0x4e, 0x00, 0x68, 0x02, 0x00, 0x22, 0x00, 0x34,
|
||||||
|
0xcb, 0xfb, 0xf8, 0x18, 0x40, 0x01, 0x00, 0x27, 0xe2, 0x90, 0x0f, 0xc3, 0x91, 0xa8, 0x00, 0x08,
|
||||||
|
0x00, 0x00, 0x68, 0x50, 0x60, 0x65, 0xfc, 0x0e, 0xfe, 0x04, 0x00, 0x08, 0x00, 0x06, 0x0c, 0x00,
|
||||||
|
0x01, 0x00, 0xf8, 0x40, 0x20, 0x00, 0x00, 0x90, 0x00, 0xcf, 0x95, 0x1f, 0x44, 0x90, 0x00, 0x6e,
|
||||||
|
0x03, 0xf4, 0x40, 0x21, 0x9f, 0x26, 0x01, 0xbf, 0x88, 0x10, 0x90, 0x00, 0x08, 0x04, 0x00, 0x04,
|
||||||
|
0x30, 0x03, 0xe4, 0xc7, 0xea, 0x05, 0x1e, 0x87, 0xf8, 0x20, 0x1c, 0x00, 0x10, 0x84, 0x22, 0x1f,
|
||||||
|
0x71, 0x0d, 0x0e, 0xb9, 0x88, 0x9f, 0x5c, 0xee, 0x41, 0x97, 0xfb, 0xf8, 0x88, 0x68, 0x08, 0x6d,
|
||||||
|
0xd0, 0x44, 0xfc, 0x34, 0x06, 0xe6, 0x16, 0x21, 0x04, 0x11, 0x0f, 0xb9, 0x85, 0x86, 0x5d, 0x44,
|
||||||
|
0x4f, 0xae, 0xb7, 0x40, 0xa8, 0xcd, 0x5b, 0xed, 0x02, 0xee, 0xc2, 0x21, 0x40, 0x21, 0x21, 0x23,
|
||||||
|
0x17, 0xb7, 0x00, 0x60, 0x00, 0x3b, 0xfd, 0xfc, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x34, 0x00, 0x33,
|
||||||
|
0xc7, 0xe0, 0xc0, 0x0f, 0x07, 0x12, 0x42, 0x01, 0xe8, 0x6c, 0xc7, 0x83, 0x07, 0x8c, 0xd4, 0x30,
|
||||||
|
0x07, 0x20, 0x01, 0x90, 0xa3, 0xf1, 0xdb, 0xf5, 0xd4, 0x13, 0xc2, 0x4f, 0x0f, 0xe5, 0xe2, 0xc7,
|
||||||
|
0x87, 0xf2, 0xf0, 0x93, 0xc3, 0xf9, 0x78, 0xb0, 0x1a, 0x03, 0xe1, 0xf1, 0xd0, 0x08, 0x4c, 0x66,
|
||||||
|
0xac, 0x32, 0x31, 0x70, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0xf0, 0x36, 0x1f, 0xe5, 0xe0,
|
||||||
|
0x6c, 0xbc, 0x26, 0xf0, 0x36, 0x5f, 0xe5, 0xe0, 0x6c, 0xbc, 0x26, 0xf0, 0x34, 0xf9, 0x94, 0x32,
|
||||||
|
0x31, 0x74, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xbf, 0x87, 0xdf, 0xef, 0xfe, 0x4b, 0xbf, 0x02, 0xfa,
|
||||||
|
0xde, 0xa7, 0x79, 0x32, 0x44, 0x7c, 0x20, 0x82, 0x00, 0x5f, 0xef, 0xff, 0x09, 0xe1, 0x05, 0x74,
|
||||||
|
0x32, 0xea, 0x09, 0xe1, 0x0f, 0x55, 0x83, 0x85, 0x2a, 0xa0, 0x1d, 0x50, 0x0e, 0x0e, 0x0b, 0x01,
|
||||||
|
0x01, 0x43, 0x06, 0x02, 0xbe, 0x5f, 0x00, 0x00, 0x0c, 0x3d, 0x4d, 0x87, 0xa6, 0x5e, 0xa6, 0xcb,
|
||||||
|
0xc3, 0xcf, 0x53, 0x65, 0xe9, 0x97, 0xa9, 0xb2, 0xf5, 0x9b, 0xd4, 0xd3, 0xee, 0xcd, 0xc0, 0x7c,
|
||||||
|
0xae, 0xe0, 0x65, 0x1f, 0xe5, 0xe0, 0x6c, 0xbc, 0x26, 0xf0, 0x36, 0x5f, 0xe5, 0xe0, 0x6c, 0xbc,
|
||||||
|
0x26, 0xf0, 0x34, 0xfb, 0xb3, 0xf2, 0x41, 0x30, 0x20, 0x04, 0xa0, 0x80, 0x93, 0xf3, 0xf2, 0x1b,
|
||||||
|
0xed, 0xf6, 0x0f, 0x04, 0x82, 0x7b, 0xcc, 0x00, 0x65, 0xef, 0x4f, 0x86, 0x02, 0xf7, 0xa7, 0xe0,
|
||||||
|
0x0a, 0x88, 0x1c, 0x34, 0x02, 0x02, 0x02, 0x60, 0x60, 0x49, 0x40, 0xc1, 0x2f, 0x14, 0xca, 0x60,
|
||||||
|
0xc1, 0x81, 0x80, 0x07, 0xc3, 0x00, 0x00, 0x39, 0xfa, 0x86, 0x38, 0x93, 0x47, 0x08, 0x27, 0x08,
|
||||||
|
0xfc, 0xb8, 0x4e, 0x38, 0x47, 0xe5, 0xc2, 0x09, 0xc2, 0x3f, 0x2e, 0x13, 0x8e, 0x11, 0xf3, 0xc3,
|
||||||
|
0x57, 0x1a, 0x88, 0x7d, 0x44, 0x3c, 0x3c, 0x04, 0x0f, 0xd4, 0x3f, 0x83, 0x8d, 0x82, 0x00, 0x25,
|
||||||
|
0x04, 0x84, 0xdf, 0xe0, 0x17, 0xf8, 0x04, 0x03, 0xe1, 0x47, 0xc4, 0xaf, 0x9c, 0x00, 0x00, 0x31,
|
||||||
|
0xf5, 0x4c, 0x71, 0x78, 0x8f, 0x54, 0xfb, 0x1c, 0x97, 0xa4, 0x04, 0x13, 0xd5, 0x2f, 0x77, 0xc7,
|
||||||
|
0xb8, 0x9e, 0xef, 0xcb, 0xc2, 0x6f, 0x77, 0xe5, 0xee, 0x27, 0xbb, 0xf2, 0xf7, 0xe3, 0xdd, 0xf3,
|
||||||
|
0xc6, 0xfb, 0x2a, 0x78, 0x6d, 0x3c, 0x34, 0x37, 0xc0, 0xaf, 0x25, 0xc7, 0x81, 0x7d, 0x6e, 0x5d,
|
||||||
|
0x5c, 0xd6, 0xe3, 0x43, 0xc0, 0x82, 0xd0, 0x95, 0x90, 0xd8, 0xbd, 0xfc, 0x00, 0x09, 0xc0, 0x34,
|
||||||
|
0x39, 0x46, 0x84, 0x20, 0x40, 0x38, 0xa3, 0x42, 0x12, 0xb0, 0x55, 0xbe, 0x28, 0xc0, 0x70, 0x64,
|
||||||
|
0x28, 0xc8, 0x48, 0x42, 0x08, 0xb2, 0x1b, 0x46, 0xa6, 0x09, 0x54, 0x2e, 0x5f, 0x73, 0x84, 0xfc,
|
||||||
|
0x28, 0x4a, 0x73, 0x79, 0xf2, 0x6c, 0x5d, 0x82, 0x82, 0x6e, 0xc2, 0x27, 0xd7, 0x6b, 0xb8, 0x4f,
|
||||||
|
0xa4, 0xa4, 0x22, 0xee, 0x22, 0x7e, 0x10, 0x03, 0x78, 0x08, 0xf4, 0x94, 0x5e, 0x02, 0x01, 0xef,
|
||||||
|
0x02, 0x27, 0xd7, 0x8b, 0xc8, 0x3f, 0xa4, 0xa4, 0x1a, 0xf3, 0xd1, 0x84, 0x0c, 0x32, 0x31, 0x75,
|
||||||
|
0x60, 0x05, 0xe2, 0x30, 0xb7, 0xad, 0x5b, 0x15, 0xd5, 0xc3, 0xc0, 0x00, 0x11, 0x81, 0x81, 0x69,
|
||||||
|
0x8f, 0x06, 0x0f, 0x14, 0xcf, 0xa6, 0xe8, 0xb1, 0x22, 0x77, 0xeb, 0xd7, 0x45, 0x89, 0xf0, 0xb6,
|
||||||
|
0x3e, 0x23, 0x06, 0x80, 0xf8, 0x5b, 0x0f, 0x04, 0x83, 0xfc, 0x2d, 0x8f, 0x88, 0xc1, 0xa0, 0x3e,
|
||||||
|
0x16, 0x1d, 0x00, 0x83, 0x74, 0x58, 0xa0, 0xc0, 0x10, 0xce, 0x8b, 0x17, 0xe0, 0x68, 0xff, 0x20,
|
||||||
|
0xff, 0x03, 0x63, 0xe5, 0xcf, 0x1f, 0xa0, 0x40, 0x00, 0x00, 0x2a, 0xff, 0xd6, 0xd1, 0xc0, 0xb9,
|
||||||
|
0xe0, 0x5f, 0x6b, 0x81, 0x73, 0xc9, 0x93, 0xd1, 0x63, 0x50, 0xf0, 0x9b, 0xf0, 0x48, 0x4f, 0xaf,
|
||||||
|
0xe0, 0x1b, 0xef, 0x82, 0x6f, 0xc2, 0x40, 0xe0, 0xe4, 0x60, 0xa0, 0x69, 0xa1, 0xa1, 0xbe, 0xba,
|
||||||
|
0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x42, 0x00, 0x44, 0x00, 0x88, 0x01, 0x10, 0x02,
|
||||||
|
0x21, 0x02, 0x22, 0x04, 0x44, 0x08, 0x9c, 0x8f, 0xcd, 0xe0, 0x02, 0x20, 0x88, 0x02, 0x10, 0x40,
|
||||||
|
0x01, 0xf0, 0x60, 0x44, 0xc0, 0xce, 0xb1, 0x8f, 0xd0, 0x30, 0x00, 0x60, 0x00, 0xa0, 0x00, 0xc4,
|
||||||
|
0x00, 0xcc, 0x01, 0x98, 0x03, 0x28, 0x03, 0x31, 0x03, 0x33, 0x06, 0x66, 0x07, 0x0e, 0x2c, 0xe3,
|
||||||
|
0x7b, 0x18, 0x85, 0xc7, 0xd6, 0x51, 0x71, 0x0f, 0x0e, 0xb8, 0x88, 0x9f, 0x5c, 0x6e, 0x41, 0xde,
|
||||||
|
0xeb, 0x71, 0x20, 0x5c, 0xba, 0xf7, 0xc8, 0x6f, 0xba, 0xc1, 0xf7, 0x30, 0xd0, 0xce, 0xc1, 0x31,
|
||||||
|
0x74, 0xec, 0x13, 0x41, 0x77, 0x41, 0x13, 0xa0, 0x10, 0xbf, 0x7c, 0x45, 0xd3, 0xa5, 0xbc, 0x55,
|
||||||
|
0x84, 0xaa, 0x41, 0xc1, 0xc1, 0xe0, 0xe0, 0x29, 0x01, 0x20, 0x81, 0x00, 0x03, 0x80, 0x07, 0xc0,
|
||||||
|
0x0f, 0xe0, 0x06, 0xbe, 0x16, 0x75, 0xe7, 0x9f, 0xfb, 0x1e, 0x17, 0x90, 0xef, 0x0b, 0xbb, 0x15,
|
||||||
|
0x03, 0x7c, 0x2b, 0x7e, 0x22, 0x78, 0x56, 0x83, 0xae, 0x77, 0x40, 0xcf, 0xb0, 0xf0, 0x98, 0x28,
|
||||||
|
0x04, 0x2f, 0xaf, 0x0e, 0x40, 0xfc, 0x01, 0x1c, 0x5c, 0xb1, 0xf2, 0xbf, 0xa5, 0xd7, 0x8f, 0x97,
|
||||||
|
0xc0, 0xfe, 0x9f, 0x02, 0xe7, 0x24, 0x79, 0xe0, 0x9b, 0xa9, 0xfd, 0x74, 0x3b, 0xaf, 0x2d, 0xf8,
|
||||||
|
0x4b, 0xd2, 0xf7, 0x84, 0x54, 0x04, 0x2a, 0x02, 0x02, 0x01, 0xe1, 0x1e, 0xf0, 0x87, 0xff, 0x77,
|
||||||
|
0x07, 0x00, 0x02, 0x00, 0x0d, 0xbd, 0xe1, 0xf0, 0x01, 0x1e, 0xf0, 0xfd, 0x80, 0x4c, 0x24, 0x11,
|
||||||
|
0x2c, 0x10, 0x24, 0x02, 0x01, 0x40, 0xb0, 0x5c, 0x2c, 0x14, 0x08, 0x07, 0x1b, 0x80, 0x01, 0xa7,
|
||||||
|
0xbd, 0x3e, 0x00, 0x27, 0xde, 0x9f, 0xb0, 0x85, 0x01, 0xfb, 0xd2, 0x04, 0x0c, 0x1c, 0x2e, 0x0e,
|
||||||
|
0x06, 0x18, 0x03, 0xd4, 0x00, 0x00, 0x67, 0xef, 0x4f, 0x80, 0x0a, 0xf7, 0xa7, 0xe3, 0x94, 0xe0,
|
||||||
|
0xe0, 0x10, 0x1b, 0xfd, 0xfc, 0x74, 0x62, 0xe8, 0xc0, 0x1d, 0x62, 0x00, 0x0b, 0x00, 0xb7, 0x70,
|
||||||
|
0xe6, 0x8a, 0x68, 0x75, 0x38, 0x3c, 0x3c, 0x4c, 0x2f, 0x87, 0xef, 0x01, 0xc7, 0xb2, 0x40, 0x21,
|
||||||
|
0xa3, 0x23, 0x0a, 0x08, 0x01, 0xa1, 0xa1, 0xe1, 0x80, 0x69, 0x40, 0xe1, 0x00, 0x00, 0x40, 0xd0,
|
||||||
|
0xea, 0xe5, 0xe1, 0xc0, 0x81, 0x87, 0xed, 0x68, 0x1a, 0x08, 0x94, 0x0c, 0x0c, 0xf1, 0x7c, 0xbe,
|
||||||
|
0x5f, 0x2f, 0x8f, 0x00, 0x00, 0x0d, 0x1f, 0x68, 0x7a, 0x1a, 0x04, 0x05, 0xce, 0xe6, 0x2a, 0x0c,
|
||||||
|
0x01, 0xc2, 0x00, 0x40, 0x42, 0x61, 0xc0, 0x49, 0x41, 0x60, 0xa0, 0x80, 0x01, 0xc0, 0x03, 0xe0,
|
||||||
|
0x07, 0xf0, 0x07, 0xfa, 0x00, 0x07, 0x3b, 0x99, 0x01, 0x0f, 0x19, 0x18, 0x54, 0x40, 0xe0, 0x60,
|
||||||
|
0xee, 0xd0, 0x0e, 0x19, 0x0a, 0x03, 0xa5, 0x7d, 0x05, 0xd0, 0x83, 0x98, 0x5a, 0x96, 0x21, 0x4b,
|
||||||
|
0x10, 0x10, 0xe6, 0x17, 0xaf, 0xeb, 0xaf, 0x34, 0x3c, 0xc8, 0x0f, 0xf0, 0x64, 0x3f, 0xd0, 0x0f,
|
||||||
|
0xe0, 0x03, 0xfe, 0x10, 0x02, 0x7d, 0x47, 0x2d, 0x58, 0xfc, 0x35, 0xe0, 0xca, 0x0f, 0x19, 0x0a,
|
||||||
|
0xf9, 0xf1, 0xe0, 0xb9, 0xc0, 0x81, 0x10, 0x03, 0xe0, 0xbd, 0x4f, 0xea, 0x61, 0xf7, 0xeb, 0xf6,
|
||||||
|
0x02, 0xd4, 0x7a, 0xf9, 0xff, 0x15, 0x30, 0xfa, 0x88, 0x68, 0x68, 0xd8, 0x80, 0x12, 0x60, 0x50,
|
||||||
|
0x50, 0xf0, 0x03, 0xfc, 0x01, 0xfe, 0x01, 0x7f, 0xa0, 0x7c, 0x28, 0xbf, 0xd0, 0x3e, 0x64, 0x0f,
|
||||||
|
0x00, 0x37, 0x00, 0x08, 0x80, 0x20, 0x0b, 0x88, 0x81, 0xa5, 0x04, 0x84, 0x60, 0x40, 0x36, 0x04,
|
||||||
|
0x1b, 0x8f, 0x88, 0x01, 0x00, 0xa1, 0x80, 0x1e, 0x00, 0x36, 0xfd, 0xb9, 0x12, 0x02, 0x4c, 0x09,
|
||||||
|
0x08, 0x1e, 0x00, 0x61, 0x80, 0x20, 0x60, 0x44, 0x17, 0xdc, 0x7c, 0x62, 0x00, 0x03, 0x67, 0xdb,
|
||||||
|
0x81, 0xb1, 0x30, 0x34, 0xb0, 0xa0, 0xaf, 0xa0, 0x80, 0x75, 0x35, 0x20, 0x7c, 0x49, 0xfc, 0x0f,
|
||||||
|
0xf5, 0x0d, 0x7f, 0x7e, 0x45, 0x00, 0x53, 0x42, 0x82, 0x83, 0xc0, 0x0c, 0x28, 0x1f, 0x72, 0x3e,
|
||||||
|
0xd3, 0xf5, 0x62, 0xd4, 0x00, 0x22, 0xa8, 0x81, 0xec, 0x67, 0x96, 0x02, 0xa0, 0x49, 0x7d, 0xfd,
|
||||||
|
0x6b, 0xbf, 0xcc, 0x7c, 0x4a, 0xf8, 0xd0, 0x00, 0x00, 0xcf, 0xd5, 0xd2, 0x23, 0x35, 0x60, 0x01,
|
||||||
|
0xf1, 0x60, 0x14, 0xc0, 0xb0, 0xbe, 0xb3, 0x02, 0x0f, 0x89, 0x5f, 0x1b, 0x00, 0x02, 0x0b, 0xfd,
|
||||||
|
0x80, 0x00, 0x01, 0x9b, 0xf3, 0x40, 0x42, 0x10, 0x00, 0xd8, 0xb8, 0x0f, 0xa8, 0x17, 0xfe, 0x59,
|
||||||
|
0xef, 0x14, 0x61, 0xf2, 0x30, 0x65, 0xfc, 0x51, 0xe2, 0xc1, 0x18, 0xc0, 0x07, 0x5e, 0x68, 0x08,
|
||||||
|
0xe8, 0x46, 0xf8, 0x95, 0xf1, 0xb0, 0xf9, 0x13, 0x7f, 0xbc, 0x00, 0x00, 0x32, 0x7e, 0xa8, 0xeb,
|
||||||
|
0xcd, 0x03, 0x20, 0x09, 0xa1, 0x81, 0x97, 0xfb, 0x87, 0x80, 0xb0, 0xf9, 0x19, 0x7c, 0xa8, 0x63,
|
||||||
|
0xf3, 0xe6, 0x20, 0x22, 0xbd, 0x85, 0x9e, 0x62, 0x00, 0x8b, 0x7c, 0x87, 0x91, 0x00, 0x22, 0xff,
|
||||||
|
0x21, 0xe2, 0xa0, 0x08, 0xc7, 0xc8, 0x78, 0x20, 0x02, 0x33, 0xf2, 0x1c, 0x10, 0x41, 0xe3, 0x40,
|
||||||
|
0x69, 0x7c, 0x45, 0x72, 0x62, 0xf0, 0x04, 0x7f, 0x60, 0x68, 0x6f, 0x80, 0x00, 0x08, 0x1f, 0xf7,
|
||||||
|
0xad, 0x51, 0x03, 0xf3, 0xf8, 0xa0, 0x9d, 0xa8, 0x40, 0x00, 0x23, 0x42, 0x37, 0x46, 0x0f, 0xde,
|
||||||
|
0xa6, 0x06, 0xd3, 0x3c, 0x33, 0xe1, 0x78, 0xd8, 0x34, 0x32, 0x14, 0x67, 0xdb, 0xd2, 0x38, 0xaf,
|
||||||
|
0xc7, 0x9c, 0xdf, 0xd0, 0x21, 0xe6, 0xd7, 0x80, 0x40, 0x22, 0x3f, 0x21, 0xe8, 0xd8, 0x12, 0xf9,
|
||||||
|
0x0f, 0xb4, 0x01, 0x13, 0xf9, 0x0f, 0x46, 0xc0, 0xa7, 0x13, 0x37, 0x1e, 0x67, 0x07, 0x8b, 0x01,
|
||||||
|
0xfd, 0xfe, 0x0f, 0xf7, 0x7a, 0xf0, 0x16, 0x36, 0x0a, 0x92, 0x08, 0x08, 0xc1, 0x70, 0xb8, 0x30,
|
||||||
|
0x34, 0xf1, 0xf3, 0x72, 0x27, 0x8f, 0x4b, 0x60, 0x21, 0xc4, 0xdd, 0xe2, 0xdf, 0x0b, 0xca, 0x4f,
|
||||||
|
0x2e, 0x4f, 0x9c, 0xde, 0x59, 0xe9, 0xf1, 0x55, 0x00, 0x8d, 0xf2, 0x20, 0x53, 0x3c, 0xc4, 0xf6,
|
||||||
|
0x46, 0x7e, 0x24, 0xee, 0xf2, 0x0c, 0x0d, 0x81, 0x83, 0xf9, 0x98, 0x0e, 0x00, 0x02, 0x10, 0x11,
|
||||||
|
0x01, 0x08, 0x95, 0x2a, 0xfc, 0x28, 0x95, 0x2a, 0x84, 0x80, 0xbf, 0x81, 0x06, 0x80, 0x0d, 0x00,
|
||||||
|
0x86, 0xe0, 0x6b, 0xa5, 0xc3, 0xd8, 0x8f, 0x22, 0xa0, 0x3e, 0xe9, 0x8f, 0x90, 0xf2, 0x6b, 0x85,
|
||||||
|
0x77, 0x57, 0x99, 0x43, 0x5c, 0x66, 0x5f, 0x9e, 0x85, 0x7c, 0x3f, 0x1f, 0xb3, 0xce, 0xc0, 0x0e,
|
||||||
|
0x64, 0x20, 0x0e, 0x20, 0xdc, 0x7e, 0x18, 0x81, 0x90, 0xa3, 0x13, 0x4e, 0x52, 0x71, 0x81, 0x03,
|
||||||
|
0xa4, 0x30, 0x30, 0x6c, 0x73, 0x8f, 0xc4, 0x50, 0x60, 0x16, 0x38, 0x03, 0xbf, 0x6f, 0x89, 0x3e,
|
||||||
|
0x00, 0x77, 0x00, 0xb1, 0xc0, 0x28, 0x3d, 0x73, 0x98, 0x06, 0xfe, 0x00, 0xe9, 0x81, 0xa3, 0xb8,
|
||||||
|
0x1c, 0x85, 0x20, 0x45, 0x45, 0xe1, 0xa1, 0x23, 0x63, 0xa0, 0x29, 0x61, 0x41, 0x27, 0xf4, 0x03,
|
||||||
|
0xfa, 0x01, 0x02, 0x05, 0xff, 0xe1, 0x20, 0x34, 0x08, 0x08, 0x04, 0x04, 0x02, 0xff, 0xeb, 0x96,
|
||||||
|
0x05, 0x24, 0x8e, 0x0a, 0xb1, 0xce, 0xf2, 0x06, 0xc7, 0xb9, 0x01, 0xd7, 0x20, 0x52, 0x04, 0x03,
|
||||||
|
0xe1, 0x47, 0xc4, 0xa4, 0x0b, 0xfd, 0x03, 0x01, 0xc0, 0x47, 0xe6, 0xc0, 0x2c, 0x7c, 0x09, 0x10,
|
||||||
|
0x1c, 0x0a, 0xfd, 0x7e, 0xc0, 0xd2, 0x94, 0x7a, 0x1a, 0x06, 0x07, 0xcf, 0x12, 0x2a, 0x8c, 0x1e,
|
||||||
|
0xe7, 0x07, 0x08, 0x81, 0x81, 0x91, 0x90, 0x72, 0x26, 0x9e, 0x55, 0x44, 0x0e, 0x4d, 0x21, 0x00,
|
||||||
|
0x08, 0x40, 0x02, 0x20, 0x01, 0x17, 0x2c, 0xd4, 0x22, 0x00, 0x88, 0x80, 0x44, 0x40, 0x23, 0xcd,
|
||||||
|
0xf8, 0xf1, 0xc8, 0x9b, 0x02, 0x10, 0x0c, 0x02, 0x99, 0x30, 0x00, 0x0a, 0x06, 0x01, 0x4b, 0x18,
|
||||||
|
0x00, 0x46, 0x00, 0x29, 0x9c, 0xa3, 0x86, 0x60, 0x11, 0x98, 0x05, 0x32, 0x80, 0xcc, 0xc0, 0xf3,
|
||||||
|
0xc3, 0xb8, 0x7a, 0x21, 0x7d, 0xbe, 0xfa, 0xce, 0x2a, 0x9d, 0xfa, 0xa0, 0x3c, 0x32, 0xfb, 0x7d,
|
||||||
|
0x13, 0x22, 0x05, 0xeb, 0x0b, 0xbb, 0xb8, 0x00, 0x15, 0xfe, 0xfe, 0x1a, 0x14, 0x7e, 0x1c, 0x00,
|
||||||
|
0x01, 0x82, 0x3a, 0xa7, 0xd2, 0x6c, 0x11, 0xdd, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x18, 0x23, 0x5a,
|
||||||
|
0x00, 0x80, 0xb0, 0x47, 0x84, 0x7c, 0xa8, 0x03, 0xa7, 0x82, 0x48, 0x83, 0x01, 0x50, 0x11, 0x2a,
|
||||||
|
0x37, 0xfb, 0xfc, 0x03, 0x03, 0xd1, 0xa3, 0x35, 0x68, 0xcd, 0x58, 0x40, 0x03, 0xe3, 0x47, 0xc4,
|
||||||
|
0xaf, 0x8d, 0x1f, 0x42, 0x84, 0x20, 0x81, 0x08, 0x57, 0xfb, 0xff, 0xd0, 0x98, 0x27, 0xc8, 0xaf,
|
||||||
|
0x99, 0x1f, 0x12, 0x04, 0x3e, 0x84, 0xfe, 0x08, 0x1c, 0xc1, 0x31, 0x58, 0x80, 0x3a, 0xd1, 0x99,
|
||||||
|
0x8a, 0x40, 0x02, 0x5a, 0x04, 0x00, 0x02, 0x1a, 0x38, 0xf3, 0x08, 0x00, 0x01, 0xda, 0xe3, 0x35,
|
||||||
|
0x60, 0x5f, 0x88, 0x00, 0x03, 0x6e, 0xbf, 0xdf, 0xc0, 0xbe, 0x20, 0x00, 0x42, 0x80, 0x01, 0x77,
|
||||||
|
0x9e, 0x80, 0xd0, 0x30, 0x4a, 0x32, 0x81, 0xe3, 0x94, 0x04, 0x21, 0x0a, 0x9c, 0xcc, 0x52, 0x03,
|
||||||
|
0x7d, 0xa7, 0x0c, 0x51, 0x80, 0x6f, 0xa5, 0xc0, 0x3f, 0x3e, 0x80, 0xa0, 0x22, 0x10, 0x40, 0x68,
|
||||||
|
0x17, 0x9f, 0x60, 0x1e, 0x9b, 0x09, 0x52, 0x03, 0x2d, 0x03, 0x81, 0x88, 0x41, 0x3c, 0x65, 0x14,
|
||||||
|
0x98, 0xcd, 0x58, 0x6a, 0x04, 0x21, 0x80, 0x9b, 0x81, 0x45, 0x21, 0x24, 0xe1, 0x8c, 0xf1, 0x9a,
|
||||||
|
0xb0, 0xa9, 0x38, 0xef, 0xe7, 0x90, 0xdf, 0x98, 0x00, 0x19, 0xa8, 0x18, 0x42, 0x6a, 0xc0, 0x7f,
|
||||||
|
0xda, 0x00, 0x00, 0x2b, 0x1e, 0x36, 0x7c, 0xaa, 0xa0, 0x00, 0xc0, 0xf8, 0xa0, 0xbe, 0x60, 0x2e,
|
||||||
|
0xb1, 0x09, 0xab, 0x60, 0x3e, 0x38, 0xf9, 0x6f, 0xa9, 0x3e, 0x08, 0x81, 0xa6, 0x8c, 0x13, 0xae,
|
||||||
|
0x83, 0x7e, 0x0a, 0xfb, 0x0f, 0x60, 0x86, 0x3e, 0x90, 0x6d, 0xa2, 0x33, 0x56, 0x06, 0xfa, 0xcf,
|
||||||
|
0xc5, 0x1f, 0x12, 0x38, 0x49, 0x3d, 0x04, 0x03, 0xa6, 0x42, 0x54, 0x82, 0x3e, 0xd3, 0xd1, 0xd0,
|
||||||
|
0x08, 0x58, 0x06, 0xdc, 0x10, 0x85, 0xe8, 0xf8, 0xf8, 0x94, 0x10, 0x84, 0x21, 0xe7, 0xa3, 0x85,
|
||||||
|
0xfe, 0xfe, 0xc1, 0xe9, 0x77, 0xa3, 0x27, 0xe7, 0xbd, 0x31, 0x98, 0x17, 0xa1, 0xe2, 0x13, 0xe8,
|
||||||
|
0x5a, 0xf1, 0x44, 0x7c, 0x4a, 0x00, 0x00, 0x07, 0x2d, 0x03, 0x2d, 0x05, 0xa3, 0x46, 0x6a, 0xc1,
|
||||||
|
0x9e, 0x9f, 0x9f, 0x51, 0xc0, 0x55, 0x1a, 0x13, 0x56, 0x0e, 0xf4, 0xa4, 0x85, 0xfd, 0x4c, 0x47,
|
||||||
|
0x10, 0x0d, 0x70, 0x24, 0x9b, 0xfa, 0x45, 0x41, 0x3a, 0x33, 0xea, 0x28, 0x60, 0x00, 0x80, 0x00,
|
||||||
|
0xbc, 0x00, 0x80, 0x7b, 0x2e, 0x43, 0x10, 0x0b, 0x00, 0xec, 0x1e, 0x98, 0x8a, 0xb4, 0x26, 0xac,
|
||||||
|
0x5f, 0xf9, 0x20, 0x03, 0xf2, 0xc1, 0xdf, 0xca, 0x14, 0x40, 0x07, 0x40, 0x1e, 0x00, 0x3d, 0x10,
|
||||||
|
0xe1, 0x37, 0x90, 0x64, 0x17, 0xec, 0x3d, 0x4c, 0xf5, 0x94, 0x20, 0x15, 0x80, 0xdc, 0x3e, 0x74,
|
||||||
|
0x7f, 0x87, 0x87, 0xa9, 0xa6, 0x33, 0x56, 0x16, 0xfd, 0xcf, 0xa9, 0x1f, 0x12, 0x23, 0x35, 0x60,
|
||||||
|
0xaf, 0xa4, 0x04, 0xf5, 0xb0, 0x1f, 0xe4, 0x3d, 0x75, 0x1c, 0x20, 0xeb, 0xd7, 0x19, 0x00, 0xb8,
|
||||||
|
0x04, 0x21, 0x7a, 0xd3, 0xbe, 0x15, 0xeb, 0x4a, 0xf1, 0x84, 0x78, 0x52, 0x3e, 0x25, 0x03, 0x16,
|
||||||
|
0x81, 0xc3, 0x7d, 0x59, 0x1f, 0x12, 0x30, 0x50, 0xe3, 0xe1, 0xcf, 0xc5, 0x8f, 0xa1, 0x1c, 0x0e,
|
||||||
|
0x9e, 0xd0, 0x0d, 0x7b, 0x18, 0x14, 0xcc, 0x21, 0x04, 0x1b, 0x6a, 0x8c, 0xd5, 0x86, 0xe0, 0x31,
|
||||||
|
0x9a, 0xb0, 0x4f, 0xc8, 0x0b, 0x7c, 0x40, 0x37, 0xc4, 0x5c, 0x22, 0x80, 0x3e, 0x54, 0x71, 0x10,
|
||||||
|
0xbf, 0x26, 0xf9, 0xa2, 0x1c, 0x0b, 0x82, 0xf0, 0x8f, 0x22, 0x47, 0x8a, 0xab, 0xca, 0xd4, 0x31,
|
||||||
|
0x08, 0xf1, 0xe6, 0x51, 0x9a, 0xb7, 0xcc, 0x80, 0x7f, 0xc9, 0xc2, 0x13, 0x08, 0xfd, 0x95, 0xfe,
|
||||||
|
0x23, 0xc0, 0x14, 0x0f, 0x08, 0xe1, 0xb5, 0x5f, 0x4a, 0x38, 0x10, 0x47, 0x1b, 0x17, 0x0a, 0x07,
|
||||||
|
0x1d, 0x38, 0xe3, 0xcb, 0x42, 0x10, 0x4f, 0x5d, 0x40, 0x3f, 0xf8, 0xe1, 0x0a, 0xe0, 0x45, 0xa8,
|
||||||
|
0x47, 0xe0, 0x78, 0x23, 0x0f, 0x91, 0x5f, 0x4a, 0x7f, 0xe3, 0xc9, 0x11, 0xe0, 0x4a, 0x09, 0xfe,
|
||||||
|
0x5a, 0xf0, 0xea, 0x8f, 0x21, 0x57, 0x82, 0xa3, 0xfa, 0x47, 0xc4, 0x8e, 0x0d, 0x8f, 0xcc, 0xfe,
|
||||||
|
0x11, 0xf1, 0x22, 0x33, 0x56, 0xe1, 0xf9, 0x1f, 0x9a, 0x83, 0x79, 0x2d, 0xe3, 0xf5, 0x23, 0xf6,
|
||||||
|
0x50, 0x64, 0x17, 0xce, 0x4f, 0x12, 0x58, 0x5f, 0xe0, 0xc4, 0x32, 0x0d, 0xfc, 0xab, 0xd5, 0x54,
|
||||||
|
0x15, 0x04, 0xfd, 0x91, 0xf1, 0x20, 0x32, 0x0d, 0xe1, 0x48, 0xf8, 0x91, 0xe5, 0x48, 0x09, 0xfc,
|
||||||
|
0xdb, 0x7b, 0xab, 0x84, 0x22, 0x0d, 0xfd, 0x23, 0xda, 0xd1, 0xf2, 0x20, 0x2a, 0x11, 0xfe, 0x23,
|
||||||
|
0xe7, 0x4f, 0x8c, 0x2f, 0x80, 0xe7, 0x1f, 0x09, 0x40, 0x2f, 0x00, 0xee, 0x7f, 0xf5, 0x1f, 0x12,
|
||||||
|
0x3c, 0x0d, 0x40, 0xff, 0xa9, 0xc3, 0x1b, 0x01, 0x42, 0xce, 0x18, 0x5b, 0x52, 0xd9, 0x8a, 0x79,
|
||||||
|
0xa7, 0xbc, 0xc5, 0x01, 0x08, 0x41, 0x21, 0xb5, 0xfc, 0x1b, 0x93, 0x1e, 0x8f, 0x60, 0x02, 0x98,
|
||||||
|
0xf8, 0xe0, 0x0c, 0x1c, 0x2e, 0x15, 0x00, 0xe7, 0x61, 0x08, 0x02, 0xfd, 0x16, 0x5c, 0xdb, 0xf2,
|
||||||
|
0xb8, 0x4f, 0x03, 0xfd, 0x81, 0x8a, 0x88, 0x52, 0x05, 0x20, 0x0e, 0xe9, 0xf9, 0xaa, 0xed, 0x7f,
|
||||||
|
0xbf, 0xd0, 0x0b, 0x0b, 0x42, 0x60, 0x85, 0xa1, 0x3f, 0x0a, 0x0b, 0x42, 0x40, 0x08, 0xa8, 0x02,
|
||||||
|
0x04, 0xa9, 0x60, 0x46, 0x00, 0x45, 0x40, 0x5c, 0xa7, 0xa6, 0xfa, 0x5c, 0x07, 0xf0, 0xe0, 0xa4,
|
||||||
|
0x0f, 0x94, 0xc4, 0x16, 0x82, 0x96, 0x82, 0x94, 0x83, 0x71, 0x76, 0x04, 0x94, 0x8f, 0xa1, 0xf3,
|
||||||
|
0x40, 0x00, 0x93, 0x85, 0xa2, 0x50, 0xc0, 0x00, 0x28, 0x1c, 0xbb, 0x03, 0x09, 0x12, 0x5e, 0x91,
|
||||||
|
0xaf, 0x21, 0x42, 0x05, 0x09, 0x6b, 0xe5, 0x59, 0x27, 0xcf, 0x8f, 0x88, 0x24, 0x00, 0x90, 0x7c,
|
||||||
|
0x60, 0x00, 0x00, 0x17, 0x1a, 0x02, 0x40, 0x2c, 0x03, 0x94, 0x1a, 0xf8, 0x02, 0xa0, 0x80, 0xd2,
|
||||||
|
0x15, 0xf5, 0x64, 0x00, 0xc0, 0x32, 0x01, 0x83, 0xa4, 0xc0, 0x5e, 0xb2, 0x0e, 0x70, 0x9a, 0x7b,
|
||||||
|
0x12, 0x23, 0x35, 0x6f, 0x26, 0x43, 0x7f, 0x40, 0x6a, 0x04, 0xe8, 0x14, 0x04, 0xa4, 0xb3, 0x14,
|
||||||
|
0x81, 0x30, 0x2f, 0x16, 0x84, 0xd0, 0x0c, 0x0b, 0x42, 0x6e, 0x14, 0x00, 0x9a, 0x00, 0x87, 0x76,
|
||||||
|
0x80, 0x07, 0x98, 0x2c, 0x03, 0x99, 0x9c, 0xf3, 0xbb, 0x7f, 0xb8, 0xa4, 0xdb, 0xde, 0xfc, 0x4a,
|
||||||
|
0x00, 0x05, 0xa4, 0xc2, 0x6a, 0xc0, 0xed, 0x3d, 0x15, 0xc1, 0x04, 0xe1, 0x30, 0x2e, 0x2c, 0xf1,
|
||||||
|
0x50, 0x69, 0x84, 0xa9, 0x0f, 0xf8, 0xc2, 0xbe, 0x35, 0xa8, 0x87, 0x50, 0x10, 0x0e, 0x00, 0xe5,
|
||||||
|
0x1e, 0xc6, 0xa9, 0x55, 0xfe, 0xff, 0x48, 0xf5, 0xe0, 0x53, 0xdc, 0x78, 0x80, 0x10, 0x51, 0x89,
|
||||||
|
0x52, 0xc0, 0x06, 0xab, 0x03, 0x14, 0x6f, 0xed, 0x85, 0xde, 0x80, 0x03, 0x09, 0x52, 0xe5, 0xff,
|
||||||
|
0x5e, 0x02, 0xbf, 0x8f, 0x8f, 0xc9, 0xcf, 0xe5, 0xeb, 0xf3, 0x72, 0xbb, 0x80, 0x00, 0xc6, 0x6a,
|
||||||
|
0xd8, 0x08, 0x95, 0xf4, 0xb2, 0xf9, 0x4f, 0xa1, 0xc1, 0xc2, 0x5a, 0xef, 0xf7, 0xfa, 0x81, 0xdd,
|
||||||
|
0xbd, 0xef, 0xee, 0xe0, 0xd1, 0xe5, 0x72, 0xc5, 0xcd, 0xf0, 0x2c, 0x00, 0x03, 0xcb, 0x98, 0xf0,
|
||||||
|
0x7f, 0x52, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
static BYTE TEST_RDP5_UNCOMPRESSED_DATA[] =
|
||||||
|
{
|
||||||
|
0x24, 0x02, 0x03, 0x09, 0x00, 0x20, 0x0c, 0x05, 0x10, 0x01, 0x40, 0x0a, 0xff, 0xff, 0x0c, 0x84,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x0d, 0x38, 0x01, 0xc0, 0x10, 0x01, 0x10,
|
||||||
|
0x01, 0xcc, 0xff, 0x7f, 0x03, 0x08, 0x00, 0x20, 0x04, 0x05, 0x10, 0x01, 0x40, 0x0a, 0x00, 0x0c,
|
||||||
|
0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x01, 0x00, 0x00, 0x0d, 0x0a,
|
||||||
|
0x0c, 0x0c, 0xff, 0x03, 0xff, 0x02, 0x00, 0x04, 0x00, 0x03, 0x06, 0x00, 0x00, 0x80, 0x00, 0x80,
|
||||||
|
0x00, 0x02, 0x00, 0x00, 0x09, 0x00, 0x0c, 0x80, 0x00, 0x80, 0x00, 0x06, 0x00, 0x00, 0x48, 0x00,
|
||||||
|
0x37, 0x01, 0x02, 0x00, 0x00, 0x01, 0x0c, 0x48, 0x00, 0x37, 0x01, 0x06, 0x01, 0x00, 0x00, 0x04,
|
||||||
|
0x24, 0x00, 0x02, 0x01, 0x00, 0x01, 0x0c, 0x00, 0x04, 0x24, 0x00, 0x02, 0x00, 0x00, 0x09, 0x0a,
|
||||||
|
0x3d, 0x0f, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11,
|
||||||
|
0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3,
|
||||||
|
0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6,
|
||||||
|
0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x09, 0x18, 0xfb, 0x70, 0x06, 0x00, 0x03,
|
||||||
|
0xff, 0xff, 0x00, 0x03, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x00, 0x80, 0x0c, 0x00, 0x0f,
|
||||||
|
0x00, 0x01, 0x49, 0x08, 0x07, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x72, 0x00, 0x19,
|
||||||
|
0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e,
|
||||||
|
0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b,
|
||||||
|
0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11,
|
||||||
|
0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01,
|
||||||
|
0x11, 0x01, 0x01, 0x01, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f,
|
||||||
|
0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4,
|
||||||
|
0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e,
|
||||||
|
0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18,
|
||||||
|
0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5,
|
||||||
|
0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff,
|
||||||
|
0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3,
|
||||||
|
0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11,
|
||||||
|
0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11,
|
||||||
|
0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0c, 0xf5,
|
||||||
|
0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff,
|
||||||
|
0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3,
|
||||||
|
0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11,
|
||||||
|
0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x0e, 0xd0, 0x0e, 0x0e, 0x0b,
|
||||||
|
0x01, 0x01, 0x43, 0x06, 0x02, 0xfc, 0xfc, 0x00, 0x00, 0x30, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe,
|
||||||
|
0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0x08,
|
||||||
|
0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x99, 0xd6, 0x11, 0x0f,
|
||||||
|
0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x0b, 0xf6,
|
||||||
|
0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01,
|
||||||
|
0x01, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3,
|
||||||
|
0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01,
|
||||||
|
0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99,
|
||||||
|
0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00,
|
||||||
|
0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11,
|
||||||
|
0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d,
|
||||||
|
0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11,
|
||||||
|
0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19,
|
||||||
|
0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84,
|
||||||
|
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0c, 0xf5, 0x04, 0x08, 0x42, 0x11,
|
||||||
|
0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d,
|
||||||
|
0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11,
|
||||||
|
0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19,
|
||||||
|
0x18, 0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x0e, 0xd0, 0x0e, 0x0e, 0x13, 0x02, 0x00, 0x4a, 0x08,
|
||||||
|
0x09, 0x3f, 0x3f, 0x21, 0xfd, 0xfd, 0x87, 0x84, 0x84, 0xfc, 0x00, 0x00, 0x00, 0x32, 0x00, 0x19,
|
||||||
|
0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e,
|
||||||
|
0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b,
|
||||||
|
0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11,
|
||||||
|
0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01,
|
||||||
|
0x11, 0x01, 0x01, 0x01, 0x02, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f,
|
||||||
|
0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4,
|
||||||
|
0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e,
|
||||||
|
0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18,
|
||||||
|
0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5,
|
||||||
|
0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff,
|
||||||
|
0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3,
|
||||||
|
0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11,
|
||||||
|
0x0a, 0x01, 0x09, 0x19, 0x18, 0x54, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x13, 0x03, 0x02, 0x4a,
|
||||||
|
0x06, 0x09, 0x78, 0xcc, 0xcc, 0x18, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x73, 0x00,
|
||||||
|
0x19, 0x0a, 0x3f, 0xdd, 0x0c, 0xf5, 0x04, 0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11,
|
||||||
|
0x3e, 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3,
|
||||||
|
0x0b, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84,
|
||||||
|
0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a, 0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0xd1,
|
||||||
|
0x0f, 0xd1, 0x0f, 0x0f, 0x01, 0x03, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11,
|
||||||
|
0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d,
|
||||||
|
0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11,
|
||||||
|
0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19,
|
||||||
|
0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe,
|
||||||
|
0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff,
|
||||||
|
0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f,
|
||||||
|
0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6,
|
||||||
|
0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0x54, 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1b, 0x04, 0x00,
|
||||||
|
0x4a, 0x09, 0x09, 0xff, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0xff, 0x80, 0x00, 0x00, 0x31, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04,
|
||||||
|
0xff, 0xff, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0x08, 0x42, 0x11,
|
||||||
|
0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0b,
|
||||||
|
0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x3a,
|
||||||
|
0x01, 0x09, 0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x04, 0x19,
|
||||||
|
0x0a, 0x3f, 0xdd, 0x0c, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0d, 0x0e, 0xf3, 0x11, 0x3e,
|
||||||
|
0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0b,
|
||||||
|
0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5, 0xf4, 0x0a, 0x99, 0xd6, 0x11,
|
||||||
|
0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0xcf,
|
||||||
|
0x0d, 0xcf, 0x0d, 0x0d, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1,
|
||||||
|
0x0d, 0x0e, 0xf3, 0x11, 0x3e, 0xf3, 0xf2, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0d, 0xf4, 0x11,
|
||||||
|
0x3f, 0x0d, 0x01, 0xf3, 0x0b, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0b, 0x0c, 0xf5, 0x11, 0x3e, 0xf5,
|
||||||
|
0xf4, 0x0a, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0b, 0xf6, 0x11, 0x0a, 0x01, 0x09, 0x19, 0x18, 0xf4,
|
||||||
|
0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xee, 0x34, 0x3c, 0x08, 0x2d, 0x09, 0x59, 0x0d, 0x97,
|
||||||
|
0xff, 0x00, 0x02, 0x70, 0x0d, 0x0e, 0x51, 0xc2, 0x10, 0x20, 0x1c, 0x51, 0xc2, 0x12, 0xe0, 0xd6,
|
||||||
|
0x51, 0xc2, 0x12, 0x30, 0x1c, 0x19, 0x0a, 0x32, 0x12, 0x10, 0x84, 0x59, 0x0d, 0xc6, 0xcc, 0x12,
|
||||||
|
0xd0, 0xf2, 0x51, 0xc2, 0x10, 0x20, 0x1c, 0x51, 0xc2, 0x12, 0xe0, 0xd6, 0x51, 0xc2, 0x12, 0x30,
|
||||||
|
0x1c, 0x19, 0x0a, 0x3f, 0x0a, 0x12, 0xb9, 0xf9, 0x08, 0x42, 0x11, 0x0f, 0xf6, 0x0a, 0x09, 0xf6,
|
||||||
|
0x11, 0x3e, 0xf6, 0xf7, 0x09, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x08, 0xf7, 0x11, 0x3f, 0x08, 0x01,
|
||||||
|
0xf8, 0x08, 0x10, 0x84, 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, 0x11, 0x3e, 0xf8, 0xf9, 0x07, 0x99,
|
||||||
|
0xd6, 0x11, 0x0d, 0x01, 0x06, 0xf9, 0x11, 0x0a, 0x01, 0x06, 0x19, 0x18, 0xf5, 0x60, 0x05, 0x00,
|
||||||
|
0x00, 0x00, 0xef, 0x5a, 0xec, 0x57, 0x57, 0x0f, 0x00, 0x00, 0x46, 0x06, 0x05, 0xcc, 0x78, 0x30,
|
||||||
|
0x78, 0xcc, 0x00, 0x00, 0x00, 0x72, 0x00, 0x19, 0x0a, 0x3f, 0x13, 0xfe, 0xfa, 0x04, 0xff, 0xff,
|
||||||
|
0x11, 0x0f, 0xf6, 0x0a, 0x09, 0xf6, 0x11, 0x3e, 0xf6, 0xf7, 0x09, 0x08, 0x42, 0x11, 0x0d, 0x01,
|
||||||
|
0x08, 0xf7, 0x11, 0x3f, 0x08, 0x01, 0xf8, 0x08, 0x99, 0xd6, 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8,
|
||||||
|
0x11, 0x3e, 0xf8, 0xf9, 0x07, 0x10, 0x84, 0x11, 0x0d, 0x01, 0x06, 0xf9, 0x11, 0x3a, 0x01, 0x06,
|
||||||
|
0x99, 0xd6, 0x19, 0x18, 0xf0, 0x60, 0x0c, 0x01, 0x0c, 0x01, 0x01, 0x01, 0x00, 0x19, 0x0a, 0x3f,
|
||||||
|
0x13, 0xfe, 0xfa, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf6, 0x0a, 0x09, 0xf6, 0x11, 0x3e, 0xf6, 0xf7,
|
||||||
|
0x09, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x08, 0xf7, 0x11, 0x3f, 0x08, 0x01, 0xf8, 0x08, 0x10, 0x84,
|
||||||
|
0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, 0x11, 0x3e, 0xf8, 0xf9, 0x07, 0x99, 0xd6, 0x11, 0x0d, 0x01,
|
||||||
|
0x06, 0xf9, 0x11, 0x0a, 0x01, 0x06, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0a, 0xff, 0x0a,
|
||||||
|
0xff, 0xff, 0x19, 0x0a, 0x3f, 0x13, 0xfe, 0xfa, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf6, 0x0a, 0x09,
|
||||||
|
0xf6, 0x11, 0x3e, 0xf6, 0xf7, 0x09, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x08, 0xf7, 0x11, 0x3f, 0x08,
|
||||||
|
0x01, 0xf8, 0x08, 0x10, 0x84, 0x11, 0x0f, 0xf8, 0x08, 0x07, 0xf8, 0x11, 0x3e, 0xf8, 0xf9, 0x07,
|
||||||
|
0x99, 0xd6, 0x11, 0x0d, 0x01, 0x06, 0xf9, 0x11, 0x0a, 0x01, 0x06, 0x19, 0x18, 0xf4, 0x20, 0xff,
|
||||||
|
0xff, 0x00, 0x0c, 0x01, 0x0c, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0x19, 0x0a, 0x0f, 0x09, 0xfe, 0x09, 0x09, 0x19, 0x18, 0xf5, 0x60, 0x06, 0xff, 0xff,
|
||||||
|
0x00, 0x09, 0xfe, 0x12, 0x07, 0x07, 0x23, 0x05, 0x03, 0x4d, 0x0d, 0x0d, 0x00, 0x00, 0x00, 0x08,
|
||||||
|
0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x88, 0x01, 0x10, 0x02, 0x20, 0x04, 0x40, 0x08, 0x88,
|
||||||
|
0x11, 0x10, 0x22, 0x20, 0x44, 0x40, 0x00, 0x00, 0x6f, 0x00, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00,
|
||||||
|
0x1f, 0x06, 0x04, 0x4c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0,
|
||||||
|
0x01, 0x90, 0x03, 0x30, 0x06, 0x60, 0x0c, 0xc0, 0x19, 0x90, 0x33, 0x30, 0x66, 0x60, 0x70, 0x00,
|
||||||
|
0x19, 0x0a, 0x37, 0xe3, 0x10, 0xf1, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e,
|
||||||
|
0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d,
|
||||||
|
0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11,
|
||||||
|
0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00,
|
||||||
|
0x00, 0xd6, 0x12, 0xd2, 0x0e, 0x0e, 0x0f, 0x07, 0x01, 0x48, 0x09, 0x04, 0x08, 0x00, 0x1c, 0x00,
|
||||||
|
0x3e, 0x00, 0x7f, 0x00, 0x35, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x10, 0x84, 0x11,
|
||||||
|
0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, 0xf2, 0x0e, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11,
|
||||||
|
0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x0e, 0xf3,
|
||||||
|
0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x0a, 0x01, 0x0b, 0x19, 0x18, 0xf0, 0x60, 0x11,
|
||||||
|
0x01, 0x11, 0x01, 0x01, 0x01, 0x07, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11,
|
||||||
|
0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d,
|
||||||
|
0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11,
|
||||||
|
0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99,
|
||||||
|
0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f,
|
||||||
|
0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2,
|
||||||
|
0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84,
|
||||||
|
0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01,
|
||||||
|
0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11,
|
||||||
|
0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19,
|
||||||
|
0x0a, 0x3f, 0xdd, 0x0e, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e,
|
||||||
|
0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d,
|
||||||
|
0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11,
|
||||||
|
0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00,
|
||||||
|
0x00, 0xd0, 0x10, 0xd0, 0x10, 0x10, 0x0f, 0x08, 0x01, 0x48, 0x09, 0x04, 0x7f, 0x00, 0x3e, 0x00,
|
||||||
|
0x1c, 0x00, 0x08, 0x00, 0x36, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x10, 0x84, 0x11,
|
||||||
|
0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, 0xf2, 0x0e, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11,
|
||||||
|
0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x0e, 0xf3,
|
||||||
|
0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x0a, 0x01, 0x0b, 0x19, 0x18, 0xf0, 0x60, 0x11,
|
||||||
|
0x01, 0x11, 0x01, 0x01, 0x01, 0x08, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11,
|
||||||
|
0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d,
|
||||||
|
0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11,
|
||||||
|
0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99,
|
||||||
|
0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f,
|
||||||
|
0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2,
|
||||||
|
0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84,
|
||||||
|
0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01,
|
||||||
|
0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11,
|
||||||
|
0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19,
|
||||||
|
0x0a, 0x3f, 0xdd, 0x0e, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e,
|
||||||
|
0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d,
|
||||||
|
0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11,
|
||||||
|
0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x60, 0x00, 0x00,
|
||||||
|
0x00, 0xd0, 0x10, 0xd0, 0x10, 0x10, 0x13, 0x09, 0x04, 0x4b, 0x04, 0x09, 0x00, 0x80, 0xc0, 0xe0,
|
||||||
|
0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5,
|
||||||
|
0x04, 0x10, 0x84, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1, 0xf2, 0x0e, 0x11, 0x0d,
|
||||||
|
0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11, 0x0f, 0xf3, 0x0d, 0x0c,
|
||||||
|
0xf3, 0x11, 0x0e, 0xf3, 0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x0a, 0x01, 0x0b, 0x19,
|
||||||
|
0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x09, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5,
|
||||||
|
0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6,
|
||||||
|
0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3,
|
||||||
|
0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11,
|
||||||
|
0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff,
|
||||||
|
0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1,
|
||||||
|
0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01,
|
||||||
|
0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff,
|
||||||
|
0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20,
|
||||||
|
0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xdd, 0x0e, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f,
|
||||||
|
0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f,
|
||||||
|
0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4,
|
||||||
|
0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18,
|
||||||
|
0xf4, 0x60, 0x00, 0x00, 0x00, 0xd0, 0x10, 0xd0, 0x10, 0x10, 0x13, 0x0a, 0x03, 0x4b, 0x04, 0x09,
|
||||||
|
0x00, 0x10, 0x30, 0x70, 0xf0, 0x70, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x19, 0x0a,
|
||||||
|
0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x10, 0x84, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x0e, 0xf1,
|
||||||
|
0xf2, 0x0e, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x99, 0xd6, 0x11,
|
||||||
|
0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x0e, 0xf3, 0xf4, 0x0c, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11,
|
||||||
|
0x0a, 0x01, 0x0b, 0x19, 0x18, 0xf0, 0x60, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x0a, 0x19, 0x0a,
|
||||||
|
0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f, 0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1,
|
||||||
|
0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2, 0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10,
|
||||||
|
0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e, 0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d,
|
||||||
|
0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6, 0x19, 0x18, 0xf4, 0x20, 0x10, 0x00, 0x00,
|
||||||
|
0x0f, 0xff, 0x0f, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0x1d, 0xfe, 0xf5, 0x04, 0x08, 0x42, 0x11, 0x0f,
|
||||||
|
0xf1, 0x0f, 0x0e, 0xf1, 0x11, 0x3e, 0xf1, 0xf2, 0x0e, 0x99, 0xd6, 0x11, 0x0d, 0x01, 0x0d, 0xf2,
|
||||||
|
0x11, 0x3f, 0x0d, 0x01, 0xf3, 0x0d, 0x10, 0x84, 0x11, 0x0f, 0xf3, 0x0d, 0x0c, 0xf3, 0x11, 0x3e,
|
||||||
|
0xf3, 0xf4, 0x0c, 0xff, 0xff, 0x11, 0x0d, 0x01, 0x0b, 0xf4, 0x11, 0x3a, 0x01, 0x0b, 0x99, 0xd6,
|
||||||
|
0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10,
|
||||||
|
0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xce, 0x0e, 0x01, 0x01, 0xff, 0xff,
|
||||||
|
0x1d, 0x18, 0xf4, 0x60, 0x0e, 0xe2, 0x00, 0x0b, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x0e,
|
||||||
|
0xce, 0x0f, 0x0f, 0x13, 0x0b, 0x04, 0x4b, 0x04, 0x09, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xe0, 0xc0,
|
||||||
|
0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, 0x40, 0x0d,
|
||||||
|
0x0d, 0x0f, 0x0c, 0x03, 0x4a, 0x07, 0x08, 0x00, 0x02, 0x06, 0x8e, 0xdc, 0xf8, 0x70, 0x20, 0x61,
|
||||||
|
0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, 0x40, 0x0d, 0x0d, 0x0f, 0x0d, 0x04, 0x4a, 0x06,
|
||||||
|
0x06, 0x78, 0xfc, 0xfc, 0xfc, 0xfc, 0x78, 0x00, 0x00, 0x68, 0x00, 0x19, 0x0a, 0x3d, 0x0d, 0x02,
|
||||||
|
0x02, 0x99, 0xd6, 0x19, 0x18, 0xd0, 0x60, 0x0e, 0x10, 0x02, 0x02, 0x13, 0x0e, 0x02, 0x4a, 0x0b,
|
||||||
|
0x05, 0x04, 0x00, 0x0e, 0x00, 0x1f, 0x00, 0x3f, 0x80, 0x7f, 0xc0, 0x00, 0x00, 0x35, 0x00, 0x19,
|
||||||
|
0x0a, 0x01, 0x0f, 0x19, 0x18, 0x54, 0x40, 0x10, 0x00, 0x00, 0x0f, 0x0f, 0x01, 0x0e, 0x19, 0x0a,
|
||||||
|
0x03, 0xca, 0x0f, 0x19, 0x18, 0xf4, 0x20, 0xff, 0xff, 0x00, 0xcb, 0x10, 0xcb, 0x10, 0x10, 0x11,
|
||||||
|
0xf4, 0x20, 0x10, 0x84, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x01, 0x0f, 0x19, 0x18,
|
||||||
|
0x54, 0x40, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x13, 0x0f, 0x02, 0x4a, 0x0b, 0x05, 0x7f, 0xc0, 0x3f,
|
||||||
|
0x80, 0x1f, 0x00, 0x0e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x36, 0x00, 0x19, 0x0a, 0x01, 0x0f, 0x19,
|
||||||
|
0x18, 0x54, 0x40, 0x10, 0x00, 0x00, 0x0f, 0x0f, 0x01, 0x0f, 0x19, 0x0a, 0x01, 0x0f, 0x19, 0x18,
|
||||||
|
0xf4, 0x20, 0xff, 0xff, 0x00, 0x10, 0x01, 0x10, 0x01, 0x01, 0x11, 0xf4, 0x20, 0x10, 0x84, 0x00,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0a, 0x3f, 0xd3, 0x0f, 0xfe, 0xfe, 0xff, 0xff, 0x19, 0x18,
|
||||||
|
0xf4, 0x60, 0x00, 0x00, 0x00, 0xd3, 0x0f, 0xd1, 0x0d, 0x0d, 0x1b, 0x10, 0x02, 0x4c, 0x0a, 0x0a,
|
||||||
|
0x1e, 0x00, 0x7f, 0x80, 0x7f, 0x80, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0x7f, 0x80,
|
||||||
|
0x7f, 0x80, 0x1e, 0x00, 0x6e, 0x00, 0x11, 0x00, 0x40, 0x17, 0x11, 0x03, 0x4a, 0x09, 0x08, 0x01,
|
||||||
|
0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0xc3, 0x00, 0x3c, 0x00, 0x6d,
|
||||||
|
0x00, 0x11, 0x00, 0x40, 0x17, 0x12, 0x02, 0x4c, 0x09, 0x08, 0x1e, 0x00, 0x61, 0x80, 0x40, 0x00,
|
||||||
|
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x11, 0x00, 0x40, 0x1b,
|
||||||
|
0x13, 0x03, 0x4b, 0x0a, 0x0a, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00,
|
||||||
|
0x40, 0x00, 0x80, 0x00, 0x80, 0xc3, 0x00, 0x3c, 0x00, 0x6b, 0x00, 0x11, 0x00, 0x40, 0x1b, 0x14,
|
||||||
|
0x01, 0x4d, 0x0a, 0x0a, 0x0f, 0x00, 0x30, 0xc0, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x00,
|
||||||
|
0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x6a, 0x00, 0x11, 0x54, 0x40, 0xff, 0xff, 0x00,
|
||||||
|
0x0d, 0x0d, 0x1b, 0x15, 0x02, 0x4b, 0x09, 0x09, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80,
|
||||||
|
0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0x00, 0x00, 0x67, 0x00, 0x11, 0x04,
|
||||||
|
0x40, 0x99, 0xd6, 0x00, 0x1f, 0x16, 0x01, 0x4c, 0x0b, 0x0b, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
|
||||||
|
0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0xff, 0xe0,
|
||||||
|
0x00, 0x00, 0x66, 0x00, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x1b, 0x17, 0x01, 0x4c, 0x0a, 0x0a,
|
||||||
|
0xff, 0xc0, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
|
||||||
|
0x80, 0x00, 0x80, 0x00, 0x65, 0x00, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x23, 0x18, 0x00, 0x4d,
|
||||||
|
0x0d, 0x0d, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
|
||||||
|
0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xff, 0xf8, 0x00, 0x00, 0x64, 0x00,
|
||||||
|
0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x1f, 0x19, 0x00, 0x4d, 0x0c, 0x0c, 0xff, 0xf0, 0x80, 0x00,
|
||||||
|
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
|
||||||
|
0x80, 0x00, 0x80, 0x00, 0x63, 0x00, 0x11, 0x54, 0x40, 0xff, 0xff, 0x00, 0x0d, 0x0d, 0x01, 0x15,
|
||||||
|
0x11, 0x04, 0x40, 0x99, 0xd6, 0x00, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17,
|
||||||
|
0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19,
|
||||||
|
0x11, 0x04, 0x40, 0x00, 0x00, 0x00, 0x0f, 0x1a, 0x03, 0x4b, 0x07, 0x08, 0x00, 0x02, 0x06, 0x8e,
|
||||||
|
0xdc, 0xf8, 0x70, 0x20, 0x62, 0x00, 0x11, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15,
|
||||||
|
0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40,
|
||||||
|
0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x54, 0x40,
|
||||||
|
0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08,
|
||||||
|
0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10,
|
||||||
|
0x84, 0x00, 0x01, 0x19, 0x11, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x1a, 0x11, 0xf4, 0x60, 0x99,
|
||||||
|
0xd6, 0x00, 0xcc, 0x0d, 0xcc, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04,
|
||||||
|
0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04,
|
||||||
|
0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, 0x40, 0x01, 0x1a, 0x19, 0x0a, 0x33, 0x0d, 0x0d,
|
||||||
|
0x00, 0x00, 0x19, 0x18, 0x54, 0x40, 0xff, 0xff, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x04, 0x40,
|
||||||
|
0x99, 0xd6, 0x00, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40,
|
||||||
|
0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x19, 0x0a, 0x01,
|
||||||
|
0x0d, 0x19, 0x18, 0x54, 0x40, 0xff, 0xff, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x04, 0x40, 0x99,
|
||||||
|
0xd6, 0x00, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff,
|
||||||
|
0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x11, 0x04, 0x40, 0x00,
|
||||||
|
0x00, 0x00, 0x0b, 0x1b, 0x05, 0x49, 0x04, 0x04, 0x60, 0xf0, 0xf0, 0x60, 0x69, 0x00, 0x19, 0x0a,
|
||||||
|
0x01, 0x0d, 0x19, 0x18, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x00, 0x40,
|
||||||
|
0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00,
|
||||||
|
0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18,
|
||||||
|
0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x10, 0x11, 0x00, 0x40, 0x01, 0x11, 0x11, 0x04,
|
||||||
|
0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04,
|
||||||
|
0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x11, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x19, 0x0a,
|
||||||
|
0x03, 0xcc, 0x0d, 0x19, 0x18, 0xf4, 0x60, 0x99, 0xd6, 0x00, 0xcc, 0x0d, 0xcc, 0x0d, 0x0d, 0x01,
|
||||||
|
0x10, 0x11, 0x00, 0x40, 0x01, 0x11, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x12, 0x11, 0x04,
|
||||||
|
0x40, 0xff, 0xff, 0x00, 0x01, 0x13, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x14, 0x11, 0x00,
|
||||||
|
0x40, 0x01, 0x1b, 0x03, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x08, 0x08, 0x81, 0x08, 0xaa,
|
||||||
|
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0x09, 0x01, 0x7f, 0x02, 0x0d, 0x00, 0x1a, 0x01, 0x0d,
|
||||||
|
0x00, 0x0d, 0x00, 0xf0, 0xff, 0xff, 0x00, 0x99, 0xd6, 0x00, 0x81, 0x19, 0x18, 0x54, 0x40, 0x99,
|
||||||
|
0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04,
|
||||||
|
0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00,
|
||||||
|
0x40, 0x01, 0x1a, 0x11, 0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40,
|
||||||
|
0x01, 0x16, 0x11, 0x04, 0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00,
|
||||||
|
0x01, 0x18, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, 0x40, 0x01, 0x1a, 0x11,
|
||||||
|
0x54, 0x40, 0x99, 0xd6, 0x00, 0x0d, 0x0d, 0x01, 0x15, 0x11, 0x00, 0x40, 0x01, 0x16, 0x11, 0x04,
|
||||||
|
0x40, 0x08, 0x42, 0x00, 0x01, 0x17, 0x11, 0x04, 0x40, 0xff, 0xff, 0x00, 0x01, 0x18, 0x11, 0x04,
|
||||||
|
0x40, 0x10, 0x84, 0x00, 0x01, 0x19, 0x11, 0x00, 0x40, 0x01, 0x1a, 0x19, 0x0a, 0x31, 0x34, 0xff,
|
||||||
|
0xff, 0x19, 0x18, 0x54, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x1b, 0x1c, 0x02, 0x4b, 0x09, 0x09,
|
||||||
|
0xc1, 0x80, 0xe3, 0x80, 0x77, 0x00, 0x3e, 0x00, 0x1c, 0x00, 0x3e, 0x00, 0x77, 0x00, 0xe3, 0x80,
|
||||||
|
0xc1, 0x80, 0x00, 0x00, 0x72, 0x00, 0x19, 0x0a, 0x03, 0xcc, 0x0d, 0x1d, 0x18, 0xf0, 0x60, 0xa0,
|
||||||
|
0x45, 0x45, 0xcc, 0x0d, 0xcc, 0x0d, 0x0d, 0x1b, 0x1d, 0x01, 0x4b, 0x0a, 0x09, 0x3f, 0xc0, 0x3f,
|
||||||
|
0xc0, 0x20, 0x40, 0xff, 0x40, 0xff, 0x40, 0x81, 0xc0, 0x81, 0x00, 0x81, 0x00, 0xff, 0x00, 0x00,
|
||||||
|
0x00, 0x32, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50, 0x40, 0x0d, 0x0d, 0x1b, 0x1e, 0x01,
|
||||||
|
0x4c, 0x0a, 0x0a, 0xff, 0xc0, 0xff, 0xc0, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80,
|
||||||
|
0x40, 0x80, 0x40, 0x80, 0x40, 0xff, 0xc0, 0x31, 0x00, 0x19, 0x0a, 0x01, 0x0d, 0x19, 0x18, 0x50,
|
||||||
|
0x40, 0x0d, 0x0d, 0x0b, 0x1f, 0x02, 0x44, 0x07, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x30, 0x00, 0x19,
|
||||||
|
0x0a, 0x3d, 0x0d, 0x03, 0x03, 0x99, 0xd6, 0x19, 0x18, 0xd4, 0x60, 0xff, 0xff, 0x00, 0x0e, 0x11,
|
||||||
|
0x03, 0x03, 0x23, 0x20, 0x00, 0x4d, 0x0d, 0x0d, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00,
|
||||||
|
0x10, 0x00, 0x88, 0x00, 0x44, 0x00, 0x22, 0x00, 0x11, 0x00, 0x88, 0x80, 0x44, 0x40, 0x22, 0x20,
|
||||||
|
0x11, 0x10, 0x00, 0x00, 0x78, 0x00, 0x11, 0x04, 0x40, 0x10, 0x84, 0x00, 0x1f, 0x21, 0x00, 0x4c,
|
||||||
|
0x0c, 0x0c, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x98, 0x00, 0xcc, 0x00,
|
||||||
|
0x66, 0x00, 0x33, 0x00, 0x99, 0x80, 0xcc, 0xc0, 0x66, 0x60, 0x79, 0x00, 0x19, 0x0a, 0x3d, 0x10,
|
||||||
|
0xfd, 0xfd, 0xff, 0xff, 0x19, 0x18, 0xd4, 0x60, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0xfd, 0xfd, 0x13,
|
||||||
|
0x22, 0x05, 0x4b, 0x04, 0x09, 0x00, 0x10, 0x30, 0x70, 0xf0, 0x70, 0x30, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x77, 0x00, 0x02, 0xff, 0xff, 0x0d, 0x0a, 0x3f, 0x0e, 0x00, 0x00, 0xff, 0x03, 0xff, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x48, 0x00, 0x37,
|
||||||
|
0x01, 0x02, 0x02, 0x00, 0x09, 0x00, 0x0c, 0x48, 0x00, 0x37, 0x01, 0x03, 0xcf, 0x04, 0xa2, 0x0c,
|
||||||
|
0x05, 0x40, 0x44, 0xd1, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00,
|
||||||
|
0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00,
|
||||||
|
0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x08, 0x42, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84,
|
||||||
|
0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84,
|
||||||
|
0xff, 0xff, 0x99, 0xd6, 0x10, 0x84, 0x08, 0x42, 0x1c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x75, 0xc6, 0x66, 0x29, 0x00, 0x09, 0x68, 0x10, 0x00, 0x08, 0x68, 0x10, 0x84,
|
||||||
|
0x00, 0x20, 0x00, 0x07, 0x6b, 0x99, 0xd6, 0x05, 0x6b, 0x99, 0xd6, 0x00, 0x03, 0x6e, 0xff, 0xff,
|
||||||
|
0x02, 0x6e, 0xff, 0xff, 0x00, 0x10, 0xc0, 0x00, 0xf7, 0xbd, 0x01, 0xc0, 0x00, 0x08, 0x42, 0xc0,
|
||||||
|
0x00, 0xff, 0xff, 0x81, 0x08, 0x42, 0xce, 0x66, 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd,
|
||||||
|
0x2e, 0x01, 0x81, 0x08, 0x42, 0xce, 0x66, 0x29, 0x02, 0x81, 0x10, 0x84, 0x06, 0x82, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x07, 0xcd, 0x89, 0x52, 0x03, 0x2d, 0x03, 0x83, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6,
|
||||||
|
0xc9, 0x99, 0xd6, 0x1a, 0x82, 0x10, 0x00, 0x10, 0x00, 0x0a, 0x29, 0x09, 0x27, 0x0c, 0x67, 0x99,
|
||||||
|
0xd6, 0x15, 0x27, 0x1d, 0x82, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x67, 0x99, 0xd6, 0x00, 0x19, 0xd0,
|
||||||
|
0x30, 0x89, 0xd6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x99, 0xd6, 0x05, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x83, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xd8, 0x89,
|
||||||
|
0xd6, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x83, 0x99, 0xd6, 0x10, 0x00, 0x10,
|
||||||
|
0x00, 0x1a, 0x68, 0x00, 0x00, 0x09, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x99, 0xd6, 0x18, 0x68, 0x00, 0x00, 0x1b, 0x68, 0x99, 0xd6, 0x06, 0x86, 0x99, 0xd6, 0x10,
|
||||||
|
0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x19, 0x6b, 0x99, 0xd6, 0x03, 0xcc, 0x89,
|
||||||
|
0x52, 0x08, 0x68, 0x99, 0xd6, 0x05, 0x6b, 0x99, 0xd6, 0x04, 0x2c, 0x03, 0x6e, 0x08, 0x42, 0x02,
|
||||||
|
0x6e, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0x08, 0x42, 0x10, 0x81, 0x08, 0x42, 0x70,
|
||||||
|
0xff, 0xff, 0x60, 0x00, 0x08, 0x42, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0x81, 0x08, 0x42, 0xce, 0x66,
|
||||||
|
0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x02, 0xcd, 0x89, 0x52, 0x03, 0x89, 0x10,
|
||||||
|
0x84, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x07, 0x2d, 0x03, 0x2d, 0x05, 0xc6, 0x99, 0xd6, 0x0c, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x99,
|
||||||
|
0xd6, 0x99, 0xd6, 0x0a, 0xc6, 0x89, 0xd6, 0x0e, 0x82, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x84, 0x99,
|
||||||
|
0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x1c, 0x40, 0x35, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xd0, 0x4e, 0x99, 0xd6, 0x03, 0x00, 0x00, 0x60, 0x00, 0x80, 0x01, 0x78, 0x01, 0x00, 0x82,
|
||||||
|
0x10, 0x00, 0x10, 0x00, 0x0c, 0x40, 0x2c, 0x03, 0xe0, 0x05, 0x00, 0x00, 0x00, 0xd6, 0x89, 0xd6,
|
||||||
|
0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x4e, 0x99, 0xd6, 0x3b, 0x00, 0x00, 0x00, 0x28, 0x80,
|
||||||
|
0x1d, 0x00, 0x78, 0x00, 0x86, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99,
|
||||||
|
0xd6, 0x0c, 0x85, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x40, 0x2b, 0x01,
|
||||||
|
0xf0, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x89, 0xd6, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x99,
|
||||||
|
0xd6, 0x16, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x0a,
|
||||||
|
0x69, 0x99, 0xd6, 0x04, 0xcc, 0x89, 0x52, 0x07, 0x69, 0x99, 0xd6, 0x08, 0x68, 0x99, 0xd6, 0x03,
|
||||||
|
0x6e, 0xff, 0xff, 0x02, 0x6e, 0x08, 0x42, 0x02, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x01,
|
||||||
|
0x70, 0x08, 0x42, 0x70, 0xff, 0xff, 0x60, 0x00, 0x08, 0x42, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0x81,
|
||||||
|
0x08, 0x42, 0xce, 0x66, 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x02, 0xcd, 0x89,
|
||||||
|
0x52, 0x03, 0x8a, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x2d, 0x03, 0x8d, 0x99, 0xd6, 0x99, 0xd6, 0x99,
|
||||||
|
0xd6, 0x99, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x99,
|
||||||
|
0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x06, 0xc6, 0x99, 0xd6, 0x1a, 0xc6, 0x89, 0xd6, 0x0a, 0x66, 0x10,
|
||||||
|
0x84, 0x1b, 0x6a, 0x99, 0xd6, 0x1b, 0x81, 0x99, 0xd6, 0x09, 0x6a, 0x99, 0xd6, 0x16, 0x6a, 0x99,
|
||||||
|
0xd6, 0x06, 0x6a, 0x99, 0xd6, 0xf0, 0x94, 0x01, 0xcc, 0x89, 0x52, 0x00, 0x03, 0x6e, 0xff, 0xff,
|
||||||
|
0x02, 0x6e, 0x08, 0x42, 0x02, 0x6e, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x01, 0x70, 0x08, 0x42,
|
||||||
|
0x70, 0xff, 0xff, 0x60, 0x00, 0x08, 0x42, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0x81, 0x08, 0x42, 0xce,
|
||||||
|
0x66, 0x29, 0x01, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x02, 0xcd, 0x89, 0x52, 0x03, 0x10,
|
||||||
|
0x2d, 0x03, 0x2d, 0x17, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99,
|
||||||
|
0xd6, 0x00, 0x00, 0x00, 0x00, 0x18, 0x88, 0xff, 0xff, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x99,
|
||||||
|
0xd6, 0x99, 0xd6, 0xff, 0xff, 0xff, 0xff, 0x07, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99,
|
||||||
|
0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x09, 0x88, 0x99, 0xd6, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x07, 0x88, 0x10, 0x00, 0x10,
|
||||||
|
0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x08, 0x89, 0x10,
|
||||||
|
0x84, 0x10, 0x84, 0xff, 0xff, 0xff, 0xff, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0x99,
|
||||||
|
0xd6, 0x07, 0x88, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x99, 0xd6, 0x0a, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99,
|
||||||
|
0xd6, 0x08, 0x88, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10,
|
||||||
|
0x00, 0x99, 0xd6, 0x08, 0x88, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0xff, 0xff, 0xff, 0xff, 0x10,
|
||||||
|
0x84, 0x10, 0x84, 0x99, 0xd6, 0x09, 0x86, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x99, 0xd6, 0x0c, 0x84, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x0a, 0x86, 0x99,
|
||||||
|
0xd6, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x0a, 0x86, 0x99, 0xd6, 0x10,
|
||||||
|
0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x0b, 0x84, 0x99, 0xd6, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x99, 0xd6, 0x0d, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x84, 0x99,
|
||||||
|
0xd6, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x0c, 0x85, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0x0b, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x86, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x84, 0x10, 0x00, 0x10,
|
||||||
|
0x00, 0x10, 0x00, 0x10, 0x00, 0x0c, 0x86, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0x09, 0x86, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x0a, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x08, 0x86, 0x10, 0x00, 0x10, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10,
|
||||||
|
0x00, 0x0a, 0x88, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0x07, 0x88, 0x00, 0x00, 0x00, 0x00, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99,
|
||||||
|
0xd6, 0x00, 0x00, 0x00, 0x00, 0x09, 0x6a, 0x99, 0xd6, 0x05, 0x88, 0x10, 0x00, 0x10, 0x00, 0x99,
|
||||||
|
0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x00, 0x10, 0x00, 0x08, 0x89, 0x10, 0x84, 0x10,
|
||||||
|
0x84, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x10, 0x84, 0x10, 0x84, 0x99, 0xd6, 0x07,
|
||||||
|
0x6a, 0x99, 0xd6, 0x16, 0x6a, 0x99, 0xd6, 0x06, 0x6a, 0x99, 0xd6, 0x14, 0x2c, 0x00, 0x03, 0x6e,
|
||||||
|
0xff, 0xff, 0x02, 0x6e, 0x08, 0x42, 0x02, 0x6e, 0xff, 0xff, 0x02, 0xcb, 0x66, 0x29, 0x84, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x42, 0x09, 0x0d, 0xdf, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x03, 0x15, 0x00, 0xa2, 0x0c,
|
||||||
|
0x05, 0x40, 0x40, 0x17, 0xff, 0xff, 0x00, 0x1c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xf0, 0xbc, 0x0f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x0a, 0x40,
|
||||||
|
0xc8, 0x03, 0xf4, 0x00, 0xa2, 0x0c, 0x05, 0x40, 0x40, 0xf6, 0xff, 0xff, 0xc0, 0x2c, 0x2d, 0x09,
|
||||||
|
0x84, 0x2d, 0x09, 0x2d, 0x09, 0x2d, 0x09, 0x2d, 0x09, 0x00, 0x22, 0xc0, 0x10, 0x25, 0x4b, 0x02,
|
||||||
|
0x30, 0x02, 0x2a, 0x02, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x03, 0xfd, 0x2e, 0x03, 0xfd,
|
||||||
|
0x29, 0x03, 0xcd, 0x89, 0x52, 0x03, 0x2d, 0x05, 0x2d, 0x05, 0x29, 0x06, 0xc6, 0x99, 0xd6, 0x09,
|
||||||
|
0x29, 0x1f, 0x43, 0x03, 0x00, 0x00, 0x01, 0x27, 0x0b, 0x44, 0xc3, 0x00, 0x00, 0xc0, 0x68, 0x99,
|
||||||
|
0xd6, 0x18, 0x48, 0xa5, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc2, 0x5a, 0x00, 0x60,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xa0,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x81, 0x99, 0xd6, 0x48, 0x05, 0x80, 0x05, 0x00, 0x00, 0xfc,
|
||||||
|
0x01, 0x50, 0x40, 0x69, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x80, 0x06, 0x00,
|
||||||
|
0x00, 0x02, 0x6a, 0x99, 0xd6, 0x1c, 0x86, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0x2d,
|
||||||
|
0x09, 0x2d, 0x09, 0x6f, 0xff, 0xff, 0x02, 0x6e, 0xff, 0xff, 0x04, 0x6e, 0xff, 0xff, 0x04, 0xc9,
|
||||||
|
0x66, 0x29, 0x02, 0x60, 0x5e, 0x2d, 0x09, 0xc0, 0x30, 0x2d, 0x09, 0xf0, 0xc0, 0x09, 0xc0, 0x10,
|
||||||
|
0x08, 0x42, 0x00, 0x00, 0xfd, 0xce, 0x18, 0xc6, 0x01, 0xfd, 0x2e, 0x00, 0x02, 0xcd, 0x89, 0x52,
|
||||||
|
0x03, 0x83, 0x99, 0xd6, 0x99, 0xd6, 0x99, 0xd6, 0xc9, 0xef, 0x7b, 0x81, 0x99, 0xd6, 0x00, 0x05,
|
||||||
|
0xc9, 0x89, 0xd6, 0x07, 0x69, 0x10, 0x84, 0x00, 0x08, 0x27, 0x09, 0x82, 0xff, 0xff, 0x99, 0xd6,
|
||||||
|
0xd0, 0x69, 0x89, 0x52, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x51, 0x0e, 0xc0, 0x40, 0x38, 0x03, 0xa8, 0x00, 0xa2, 0x0c, 0x05, 0x40, 0x40, 0xaa,
|
||||||
|
0xff, 0xff, 0xc8, 0x2d, 0x09, 0x00, 0x14, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x20, 0xc6, 0x25, 0x4b, 0x00, 0x1a, 0xd8, 0x18, 0xc6, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xf7, 0xc0, 0x01, 0x89, 0x52, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7,
|
||||||
|
0x00, 0x01, 0x99, 0xd6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x3b, 0xef,
|
||||||
|
0x7b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x2d, 0x09, 0x00, 0x58, 0xf3, 0x7c,
|
||||||
|
0x0b, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x0a, 0x40, 0xc8,
|
||||||
|
};
|
||||||
|
|
||||||
|
int TestFreeRDPCodecMppc(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
BOOL status;
|
||||||
|
UINT32 roff;
|
||||||
|
UINT32 rlen;
|
||||||
|
struct rdp_mppc_enc* enc;
|
||||||
|
struct rdp_mppc_dec* rmppc;
|
||||||
|
|
||||||
|
/* Decompression */
|
||||||
|
|
||||||
|
rmppc = mppc_dec_new();
|
||||||
|
|
||||||
|
status = decompress_rdp_5(rmppc, TEST_RDP5_COMPRESSED_DATA,
|
||||||
|
sizeof(TEST_RDP5_COMPRESSED_DATA), PACKET_COMPRESSED, &roff, &rlen);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
printf("RDP5 decompression failure: %d\n", status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(TEST_RDP5_UNCOMPRESSED_DATA, rmppc->history_buf, sizeof(TEST_RDP5_UNCOMPRESSED_DATA)) != 0)
|
||||||
|
{
|
||||||
|
printf("RDP5 decompression failure\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mppc_dec_free(rmppc);
|
||||||
|
rmppc = mppc_dec_new();
|
||||||
|
|
||||||
|
/* Compression */
|
||||||
|
|
||||||
|
enc = mppc_enc_new(PROTO_RDP_50);
|
||||||
|
|
||||||
|
status = compress_rdp(enc, TEST_RDP5_UNCOMPRESSED_DATA, sizeof(TEST_RDP5_UNCOMPRESSED_DATA));
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
printf("RDP5 decompression failure: %d\n", status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enc->flags & PACKET_COMPRESSED)
|
||||||
|
{
|
||||||
|
status = decompress_rdp_5(rmppc, (BYTE*) enc->outputBuffer,
|
||||||
|
enc->bytes_in_opb, enc->flags, &roff, &rlen);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
printf("RDP5 compression/decompression failure: %d\n", status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rlen != sizeof(TEST_RDP5_UNCOMPRESSED_DATA))
|
||||||
|
{
|
||||||
|
printf("RDP5 compression/decompression failure: size mismatch: Actual: %d, Expected: %d\n",
|
||||||
|
rlen, sizeof(TEST_RDP5_UNCOMPRESSED_DATA));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(TEST_RDP5_UNCOMPRESSED_DATA, &rmppc->history_buf[roff], rlen) != 0)
|
||||||
|
{
|
||||||
|
printf("RDP5 compression/decompression failure\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enc->bytes_in_opb != sizeof(TEST_RDP5_UNCOMPRESSED_DATA))
|
||||||
|
{
|
||||||
|
printf("RDP5 decompression failure: size mismatch: Actual: %d, Expected: %d\n",
|
||||||
|
enc->bytes_in_opb, sizeof(TEST_RDP5_UNCOMPRESSED_DATA));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(TEST_RDP5_COMPRESSED_DATA, enc->outputBuffer, sizeof(TEST_RDP5_COMPRESSED_DATA)) != 0)
|
||||||
|
{
|
||||||
|
printf("RDP5 decompression failure\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mppc_enc_free(enc);
|
||||||
|
mppc_dec_free(rmppc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
3396
libfreerdp/codec/test/TestFreeRDPCodecPlanar.c
Normal file
3396
libfreerdp/codec/test/TestFreeRDPCodecPlanar.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
libfreerdp/codec/test/test01.bmp
Normal file
BIN
libfreerdp/codec/test/test01.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
@ -665,6 +665,10 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
|
|||||||
return settings->IgnoreCertificate;
|
return settings->IgnoreCertificate;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FreeRDP_ExternalCertificateManagement:
|
||||||
|
return settings->ExternalCertificateManagement;
|
||||||
|
break;
|
||||||
|
|
||||||
case FreeRDP_Workarea:
|
case FreeRDP_Workarea:
|
||||||
return settings->Workarea;
|
return settings->Workarea;
|
||||||
break;
|
break;
|
||||||
@ -1129,6 +1133,10 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
|
|||||||
settings->IgnoreCertificate = param;
|
settings->IgnoreCertificate = param;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FreeRDP_ExternalCertificateManagement:
|
||||||
|
settings->ExternalCertificateManagement = param;
|
||||||
|
break;
|
||||||
|
|
||||||
case FreeRDP_Workarea:
|
case FreeRDP_Workarea:
|
||||||
settings->Workarea = param;
|
settings->Workarea = param;
|
||||||
break;
|
break;
|
||||||
|
@ -83,6 +83,12 @@ set(${MODULE_PREFIX}_SRCS
|
|||||||
connection.h
|
connection.h
|
||||||
redirection.c
|
redirection.c
|
||||||
redirection.h
|
redirection.h
|
||||||
|
autodetect.c
|
||||||
|
autodetect.h
|
||||||
|
heartbeat.c
|
||||||
|
heartbeat.h
|
||||||
|
multitransport.c
|
||||||
|
multitransport.h
|
||||||
timezone.c
|
timezone.c
|
||||||
timezone.h
|
timezone.h
|
||||||
rdp.c
|
rdp.c
|
||||||
|
@ -368,7 +368,8 @@ BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
if (!rdp_send_server_font_map_pdu(rdp))
|
if (!rdp_send_server_font_map_pdu(rdp))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE);
|
if (rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE) < 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
288
libfreerdp/core/autodetect.c
Normal file
288
libfreerdp/core/autodetect.c
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Auto-Detect PDUs
|
||||||
|
*
|
||||||
|
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#define WITH_DEBUG_AUTODETECT
|
||||||
|
|
||||||
|
#include "autodetect.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT8 headerLength;
|
||||||
|
UINT8 headerTypeId;
|
||||||
|
UINT16 sequenceNumber;
|
||||||
|
UINT16 requestType;
|
||||||
|
} AUTODETECT_REQ_PDU;
|
||||||
|
|
||||||
|
static BOOL autodetect_send_rtt_measure_response(rdpRdp* rdp, UINT16 sequenceNumber)
|
||||||
|
{
|
||||||
|
wStream* s;
|
||||||
|
|
||||||
|
/* Send the response PDU to the server */
|
||||||
|
s = rdp_message_channel_pdu_init(rdp);
|
||||||
|
if (s == NULL) return FALSE;
|
||||||
|
|
||||||
|
DEBUG_AUTODETECT("sending RTT Measure Response PDU");
|
||||||
|
|
||||||
|
Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
|
||||||
|
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
|
||||||
|
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||||
|
Stream_Write_UINT16(s, 0x0000); /* responseType (1 byte) */
|
||||||
|
|
||||||
|
return rdp_send_message_channel_pdu(rdp, s, SEC_AUTODETECT_RSP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL autodetect_send_bandwidth_measure_results(rdpRdp* rdp, UINT16 responseType, UINT16 sequenceNumber)
|
||||||
|
{
|
||||||
|
UINT32 timeDelta;
|
||||||
|
wStream* s;
|
||||||
|
|
||||||
|
/* Compute the total time */
|
||||||
|
timeDelta = GetTickCount() - rdp->autodetect->bandwidthMeasureStartTime;
|
||||||
|
|
||||||
|
/* Send the result PDU to the server */
|
||||||
|
s = rdp_message_channel_pdu_init(rdp);
|
||||||
|
if (s == NULL) return FALSE;
|
||||||
|
|
||||||
|
DEBUG_AUTODETECT("sending Bandwidth Measure Results PDU -> timeDelta=%u, byteCount=%u", timeDelta, rdp->autodetect->bandwidthMeasureByteCount);
|
||||||
|
|
||||||
|
Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
|
||||||
|
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
|
||||||
|
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||||
|
Stream_Write_UINT16(s, responseType); /* responseType (1 byte) */
|
||||||
|
Stream_Write_UINT32(s, timeDelta); /* timeDelta (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, rdp->autodetect->bandwidthMeasureByteCount); /* byteCount (4 bytes) */
|
||||||
|
|
||||||
|
return rdp_send_message_channel_pdu(rdp, s, SEC_AUTODETECT_RSP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL autodetect_send_netchar_sync(rdpRdp* rdp, UINT16 sequenceNumber)
|
||||||
|
{
|
||||||
|
wStream* s;
|
||||||
|
|
||||||
|
/* Send the response PDU to the server */
|
||||||
|
s = rdp_message_channel_pdu_init(rdp);
|
||||||
|
if (s == NULL) return FALSE;
|
||||||
|
|
||||||
|
DEBUG_AUTODETECT("sending Network Characteristics Sync PDU -> bandwidth=%u, rtt=%u", rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT);
|
||||||
|
|
||||||
|
Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
|
||||||
|
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
|
||||||
|
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||||
|
Stream_Write_UINT16(s, 0x0018); /* responseType (1 byte) */
|
||||||
|
Stream_Write_UINT32(s, rdp->autodetect->netCharBandwidth); /* bandwidth (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, rdp->autodetect->netCharAverageRTT); /* rtt (4 bytes) */
|
||||||
|
|
||||||
|
return rdp_send_message_channel_pdu(rdp, s, SEC_AUTODETECT_RSP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL autodetect_recv_rtt_measure_request(rdpRdp* rdp, wStream* s, AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||||
|
{
|
||||||
|
if (autodetectReqPdu->headerLength != 0x06)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
DEBUG_AUTODETECT("received RTT Measure Request PDU");
|
||||||
|
|
||||||
|
/* Send a response to the server */
|
||||||
|
return autodetect_send_rtt_measure_response(rdp, autodetectReqPdu->sequenceNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL autodetect_recv_bandwidth_measure_start(rdpRdp* rdp, wStream* s, AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||||
|
{
|
||||||
|
if (autodetectReqPdu->headerLength != 0x06)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
DEBUG_AUTODETECT("received Bandwidth Measure Start PDU - time=%lu", GetTickCount());
|
||||||
|
|
||||||
|
/* Initialize bandwidth measurement parameters */
|
||||||
|
rdp->autodetect->bandwidthMeasureStartTime = GetTickCount();
|
||||||
|
rdp->autodetect->bandwidthMeasureByteCount = 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL autodetect_recv_bandwidth_measure_payload(rdpRdp* rdp, wStream* s, AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||||
|
{
|
||||||
|
UINT16 payloadLength;
|
||||||
|
|
||||||
|
if (autodetectReqPdu->headerLength != 0x08)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 2)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
|
||||||
|
|
||||||
|
DEBUG_AUTODETECT("received Bandwidth Measure Payload PDU -> payloadLength=%u", payloadLength);
|
||||||
|
|
||||||
|
/* Add the payload length to the bandwidth measurement parameters */
|
||||||
|
rdp->autodetect->bandwidthMeasureByteCount += payloadLength;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL autodetect_recv_bandwidth_measure_stop(rdpRdp* rdp, wStream* s, AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||||
|
{
|
||||||
|
UINT16 payloadLength;
|
||||||
|
UINT16 responseType;
|
||||||
|
|
||||||
|
if (autodetectReqPdu->requestType == 0x002B)
|
||||||
|
{
|
||||||
|
if (autodetectReqPdu->headerLength != 0x08)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 2)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (autodetectReqPdu->headerLength != 0x06)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
payloadLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_AUTODETECT("received Bandwidth Measure Stop PDU -> payloadLength=%u", payloadLength);
|
||||||
|
|
||||||
|
/* Add the payload length to the bandwidth measurement parameters */
|
||||||
|
rdp->autodetect->bandwidthMeasureByteCount += payloadLength;
|
||||||
|
|
||||||
|
/* Send a response the server */
|
||||||
|
responseType = autodetectReqPdu->requestType == 0x002B ? 0x0003 : 0x000B;
|
||||||
|
|
||||||
|
return autodetect_send_bandwidth_measure_results(rdp, responseType, autodetectReqPdu->sequenceNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL autodetect_recv_netchar_result(rdpRdp* rdp, wStream* s, AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||||
|
{
|
||||||
|
switch (autodetectReqPdu->requestType)
|
||||||
|
{
|
||||||
|
case 0x0840:
|
||||||
|
/* baseRTT and averageRTT fields are present (bandwidth field is not) */
|
||||||
|
if ((autodetectReqPdu->headerLength != 0x0E) || (Stream_GetRemainingLength(s) < 8))
|
||||||
|
return FALSE;
|
||||||
|
Stream_Read_UINT32(s, rdp->autodetect->netCharBaseRTT); /* baseRTT (4 bytes) */
|
||||||
|
Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0880:
|
||||||
|
/* bandwidth and averageRTT fields are present (baseRTT field is not) */
|
||||||
|
if ((autodetectReqPdu->headerLength != 0x0E) || (Stream_GetRemainingLength(s) < 8))
|
||||||
|
return FALSE;
|
||||||
|
Stream_Read_UINT32(s, rdp->autodetect->netCharBandwidth); /* bandwidth (4 bytes) */
|
||||||
|
Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x08C0:
|
||||||
|
/* baseRTT, bandwidth, and averageRTT fields are present */
|
||||||
|
if ((autodetectReqPdu->headerLength != 0x12) || (Stream_GetRemainingLength(s) < 12))
|
||||||
|
return FALSE;
|
||||||
|
Stream_Read_UINT32(s, rdp->autodetect->netCharBaseRTT); /* baseRTT (4 bytes) */
|
||||||
|
Stream_Read_UINT32(s, rdp->autodetect->netCharBandwidth); /* bandwidth (4 bytes) */
|
||||||
|
Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_AUTODETECT("received Network Characteristics Result PDU -> baseRTT=%u, bandwidth=%u, averageRTT=%u", rdp->autodetect->netCharBaseRTT, rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rdp_recv_autodetect_packet(rdpRdp* rdp, wStream* s)
|
||||||
|
{
|
||||||
|
AUTODETECT_REQ_PDU autodetectReqPdu;
|
||||||
|
BOOL success = FALSE;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 6)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
Stream_Read_UINT8(s, autodetectReqPdu.headerLength); /* headerLength (1 byte) */
|
||||||
|
Stream_Read_UINT8(s, autodetectReqPdu.headerTypeId); /* headerTypeId (1 byte) */
|
||||||
|
Stream_Read_UINT16(s, autodetectReqPdu.sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||||
|
Stream_Read_UINT16(s, autodetectReqPdu.requestType); /* requestType (2 bytes) */
|
||||||
|
|
||||||
|
DEBUG_AUTODETECT(
|
||||||
|
"rdp_recv_autodetect_packet: headerLength=%u, headerTypeId=%u, sequenceNumber=%u, requestType=%04x",
|
||||||
|
autodetectReqPdu.headerLength, autodetectReqPdu.headerTypeId,
|
||||||
|
autodetectReqPdu.sequenceNumber, autodetectReqPdu.requestType);
|
||||||
|
|
||||||
|
if (autodetectReqPdu.headerTypeId != TYPE_ID_AUTODETECT_REQUEST)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch (autodetectReqPdu.requestType)
|
||||||
|
{
|
||||||
|
case 0x0001:
|
||||||
|
case 0x1001:
|
||||||
|
/* RTT Measure Request (RDP_RTT_REQUEST) - MS-RDPBCGR 2.2.14.1.1 */
|
||||||
|
success = autodetect_recv_rtt_measure_request(rdp, s, &autodetectReqPdu);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0014:
|
||||||
|
case 0x0114:
|
||||||
|
case 0x1014:
|
||||||
|
/* Bandwidth Measure Start (RDP_BW_START) - MS-RDPBCGR 2.2.14.1.2 */
|
||||||
|
success = autodetect_recv_bandwidth_measure_start(rdp, s, &autodetectReqPdu);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0002:
|
||||||
|
/* Bandwidth Measure Payload (RDP_BW_PAYLOAD) - MS-RDPBCGR 2.2.14.1.3 */
|
||||||
|
success = autodetect_recv_bandwidth_measure_payload(rdp, s, &autodetectReqPdu);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x002B:
|
||||||
|
case 0x0429:
|
||||||
|
case 0x0629:
|
||||||
|
/* Bandwidth Measure Stop (RDP_BW_STOP) - MS-RDPBCGR 2.2.14.1.4 */
|
||||||
|
success = autodetect_recv_bandwidth_measure_stop(rdp, s, &autodetectReqPdu);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0840:
|
||||||
|
case 0x0880:
|
||||||
|
case 0x08C0:
|
||||||
|
/* Network Characteristics Result (RDP_NETCHAR_RESULT) - MS-RDPBCGR 2.2.14.1.5 */
|
||||||
|
success = autodetect_recv_netchar_result(rdp, s, &autodetectReqPdu);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdpAutoDetect* autodetect_new(void)
|
||||||
|
{
|
||||||
|
rdpAutoDetect* autodetect = (rdpAutoDetect*)malloc(sizeof(rdpAutoDetect));
|
||||||
|
if (autodetect)
|
||||||
|
{
|
||||||
|
memset(autodetect, 0, sizeof(rdpAutoDetect));
|
||||||
|
}
|
||||||
|
|
||||||
|
return autodetect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void autodetect_free(rdpAutoDetect* autodetect)
|
||||||
|
{
|
||||||
|
free(autodetect);
|
||||||
|
}
|
58
libfreerdp/core/autodetect.h
Normal file
58
libfreerdp/core/autodetect.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Auto-Detect PDUs
|
||||||
|
*
|
||||||
|
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AUTODETECT_H
|
||||||
|
#define __AUTODETECT_H
|
||||||
|
|
||||||
|
typedef struct rdp_autodetect rdpAutoDetect;
|
||||||
|
|
||||||
|
#include "rdp.h"
|
||||||
|
|
||||||
|
#include <freerdp/freerdp.h>
|
||||||
|
|
||||||
|
#include <winpr/stream.h>
|
||||||
|
#include <winpr/sysinfo.h>
|
||||||
|
|
||||||
|
#define TYPE_ID_AUTODETECT_REQUEST 0x00
|
||||||
|
#define TYPE_ID_AUTODETECT_RESPONSE 0x01
|
||||||
|
|
||||||
|
struct rdp_autodetect
|
||||||
|
{
|
||||||
|
/* Bandwidth measurement */
|
||||||
|
UINT32 bandwidthMeasureStartTime;
|
||||||
|
UINT32 bandwidthMeasureByteCount;
|
||||||
|
|
||||||
|
/* Network characteristics (as reported by server) */
|
||||||
|
UINT32 netCharBandwidth;
|
||||||
|
UINT32 netCharBaseRTT;
|
||||||
|
UINT32 netCharAverageRTT;
|
||||||
|
};
|
||||||
|
|
||||||
|
int rdp_recv_autodetect_packet(rdpRdp* rdp, wStream* s);
|
||||||
|
|
||||||
|
rdpAutoDetect* autodetect_new(void);
|
||||||
|
void autodetect_free(rdpAutoDetect* autodetect);
|
||||||
|
|
||||||
|
#ifdef WITH_DEBUG_AUTODETECT
|
||||||
|
#define DEBUG_AUTODETECT(fmt, ...) DEBUG_CLASS(AUTODETECT, fmt, ## __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DEBUG_AUTODETECT(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __AUTODETECT_H */
|
@ -2387,13 +2387,15 @@ BOOL rdp_print_large_pointer_capability_set(wStream* s, UINT16 length)
|
|||||||
|
|
||||||
BOOL rdp_read_surface_commands_capability_set(wStream* s, UINT16 length, rdpSettings* settings)
|
BOOL rdp_read_surface_commands_capability_set(wStream* s, UINT16 length, rdpSettings* settings)
|
||||||
{
|
{
|
||||||
|
UINT32 cmdFlags;
|
||||||
if (length < 12)
|
if (length < 12)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Seek_UINT32(s); /* cmdFlags (4 bytes) */
|
Stream_Read_UINT32(s, cmdFlags); /* cmdFlags (4 bytes) */
|
||||||
Stream_Seek_UINT32(s); /* reserved (4 bytes) */
|
Stream_Seek_UINT32(s); /* reserved (4 bytes) */
|
||||||
|
|
||||||
settings->SurfaceCommandsEnabled = TRUE;
|
settings->SurfaceCommandsEnabled = TRUE;
|
||||||
|
settings->SurfaceFrameMarkerEnabled = (cmdFlags & SURFCMDS_FRAME_MARKER);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -2414,9 +2416,10 @@ void rdp_write_surface_commands_capability_set(wStream* s, rdpSettings* settings
|
|||||||
|
|
||||||
header = rdp_capability_set_start(s);
|
header = rdp_capability_set_start(s);
|
||||||
|
|
||||||
cmdFlags = SURFCMDS_FRAME_MARKER |
|
cmdFlags = SURFCMDS_SET_SURFACE_BITS |
|
||||||
SURFCMDS_SET_SURFACE_BITS |
|
|
||||||
SURFCMDS_STREAM_SURFACE_BITS;
|
SURFCMDS_STREAM_SURFACE_BITS;
|
||||||
|
if (settings->SurfaceFrameMarkerEnabled)
|
||||||
|
cmdFlags |= SURFCMDS_FRAME_MARKER;
|
||||||
|
|
||||||
Stream_Write_UINT32(s, cmdFlags); /* cmdFlags (4 bytes) */
|
Stream_Write_UINT32(s, cmdFlags); /* cmdFlags (4 bytes) */
|
||||||
Stream_Write_UINT32(s, 0); /* reserved (4 bytes) */
|
Stream_Write_UINT32(s, 0); /* reserved (4 bytes) */
|
||||||
@ -3386,9 +3389,14 @@ BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId)
|
|||||||
|
|
||||||
if (*pChannelId != MCS_GLOBAL_CHANNEL_ID)
|
if (*pChannelId != MCS_GLOBAL_CHANNEL_ID)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "expected MCS_GLOBAL_CHANNEL_ID %04x, got %04x\n", MCS_GLOBAL_CHANNEL_ID, *pChannelId);
|
UINT16 mcsMessageChannelId = rdp->mcs->message_channel_id;
|
||||||
|
|
||||||
|
if ((mcsMessageChannelId == 0) || (*pChannelId != mcsMessageChannelId))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "unexpected MCS channel id %04x received\n", *pChannelId);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -581,6 +581,31 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
|||||||
|
|
||||||
rdp->mcs->global_channel_joined = TRUE;
|
rdp->mcs->global_channel_joined = TRUE;
|
||||||
|
|
||||||
|
if (rdp->mcs->message_channel_id != 0)
|
||||||
|
{
|
||||||
|
if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->message_channel_id))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
all_joined = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (rdp->settings->ChannelCount > 0)
|
||||||
|
{
|
||||||
|
if (!mcs_send_channel_join_request(rdp->mcs, rdp->settings->ChannelDefArray[0].ChannelId))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
all_joined = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((rdp->mcs->message_channel_id != 0) && !rdp->mcs->message_channel_joined)
|
||||||
|
{
|
||||||
|
if (channel_id != rdp->mcs->message_channel_id)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
rdp->mcs->message_channel_joined = TRUE;
|
||||||
|
|
||||||
if (rdp->settings->ChannelCount > 0)
|
if (rdp->settings->ChannelCount > 0)
|
||||||
{
|
{
|
||||||
if (!mcs_send_channel_join_request(rdp->mcs, rdp->settings->ChannelDefArray[0].ChannelId))
|
if (!mcs_send_channel_join_request(rdp->mcs, rdp->settings->ChannelDefArray[0].ChannelId))
|
||||||
@ -626,6 +651,33 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream *s)
|
||||||
|
{
|
||||||
|
BYTE* mark;
|
||||||
|
UINT16 length;
|
||||||
|
UINT16 channelId;
|
||||||
|
|
||||||
|
/* If the MCS message channel has been joined... */
|
||||||
|
if (rdp->mcs->message_channel_id != 0)
|
||||||
|
{
|
||||||
|
/* Process any MCS message channel PDUs. */
|
||||||
|
Stream_GetPointer(s, mark);
|
||||||
|
|
||||||
|
if (rdp_read_header(rdp, s, &length, &channelId))
|
||||||
|
{
|
||||||
|
if (channelId == rdp->mcs->message_channel_id)
|
||||||
|
{
|
||||||
|
if (rdp_recv_message_channel_pdu(rdp, s) == 0)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream_SetPointer(s, mark);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
int rdp_client_connect_license(rdpRdp* rdp, wStream* s)
|
int rdp_client_connect_license(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
@ -53,6 +53,7 @@ BOOL rdp_client_reconnect(rdpRdp* rdp);
|
|||||||
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s);
|
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s);
|
||||||
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s);
|
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s);
|
||||||
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s);
|
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s);
|
||||||
|
BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s);
|
||||||
int rdp_client_connect_license(rdpRdp* rdp, wStream* s);
|
int rdp_client_connect_license(rdpRdp* rdp, wStream* s);
|
||||||
int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s);
|
int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s);
|
||||||
int rdp_client_connect_finalize(rdpRdp* rdp);
|
int rdp_client_connect_finalize(rdpRdp* rdp);
|
||||||
|
@ -62,6 +62,41 @@ int connectErrorCode;
|
|||||||
#define ERRINFO_LOGOFF_BY_USER_STRING \
|
#define ERRINFO_LOGOFF_BY_USER_STRING \
|
||||||
"The disconnection was initiated by the user logging off his or her session on the server."
|
"The disconnection was initiated by the user logging off his or her session on the server."
|
||||||
|
|
||||||
|
/* Protocol-independent codes generated by the Connection Broker */
|
||||||
|
|
||||||
|
#define ERRINFO_CB_DESTINATION_NOT_FOUND_STRING \
|
||||||
|
"The target endpoint could not be found."
|
||||||
|
|
||||||
|
#define ERRINFO_CB_LOADING_DESTINATION_STRING \
|
||||||
|
"The target endpoint to which the client is being redirected is disconnecting from the Connection Broker."
|
||||||
|
|
||||||
|
#define ERRINFO_CB_REDIRECTING_TO_DESTINATION_STRING \
|
||||||
|
"An error occurred while the connection was being redirected to the target endpoint."
|
||||||
|
|
||||||
|
#define ERRINFO_CB_SESSION_ONLINE_VM_WAKE_STRING \
|
||||||
|
"An error occurred while the target endpoint (a virtual machine) was being awakened."
|
||||||
|
|
||||||
|
#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT_STRING \
|
||||||
|
"An error occurred while the target endpoint (a virtual machine) was being started."
|
||||||
|
|
||||||
|
#define ERRINFO_CB_SESSION_ONLINE_VM_NO_DNS_STRING \
|
||||||
|
"The IP address of the target endpoint (a virtual machine) cannot be determined."
|
||||||
|
|
||||||
|
#define ERRINFO_CB_DESTINATION_POOL_NOT_FREE_STRING \
|
||||||
|
"There are no available endpoints in the pool managed by the Connection Broker."
|
||||||
|
|
||||||
|
#define ERRINFO_CB_CONNECTION_CANCELLED_STRING \
|
||||||
|
"Processing of the connection has been cancelled."
|
||||||
|
|
||||||
|
#define ERRINFO_CB_CONNECTION_ERROR_INVALID_SETTINGS_STRING \
|
||||||
|
"The settings contained in the routingToken field of the X.224 Connection Request PDU (section 2.2.1.1) cannot be validated."
|
||||||
|
|
||||||
|
#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT_TIMEOUT_STRING \
|
||||||
|
"A time-out occurred while the target endpoint (a virtual machine) was being started."
|
||||||
|
|
||||||
|
#define ERRINFO_CB_SESSION_ONLINE_VM_SESSMON_FAILED_STRING \
|
||||||
|
"A session monitoring error occurred while the target endpoint (a virtual machine) was being started."
|
||||||
|
|
||||||
/* Protocol-independent licensing codes */
|
/* Protocol-independent licensing codes */
|
||||||
|
|
||||||
#define ERRINFO_LICENSE_INTERNAL_STRING \
|
#define ERRINFO_LICENSE_INTERNAL_STRING \
|
||||||
@ -319,6 +354,21 @@ int connectErrorCode;
|
|||||||
#define ERRINFO_GRAPHICS_SUBSYSTEM_RESET_FAILED_STRING \
|
#define ERRINFO_GRAPHICS_SUBSYSTEM_RESET_FAILED_STRING \
|
||||||
"The server-side graphics subsystem failed to reset."
|
"The server-side graphics subsystem failed to reset."
|
||||||
|
|
||||||
|
#define ERRINFO_GRAPHICS_SUBSYSTEM_FAILED_STRING \
|
||||||
|
"The server-side graphics subsystem is in an error state and unable to continue graphics encoding."
|
||||||
|
|
||||||
|
#define ERRINFO_TIMEZONE_KEY_NAME_LENGTH_TOO_SHORT_STRING \
|
||||||
|
"There is not enough data to read the cbDynamicDSTTimeZoneKeyName field in the Extended Info Packet (section 2.2.1.11.1.1.1)."
|
||||||
|
|
||||||
|
#define ERRINFO_TIMEZONE_KEY_NAME_LENGTH_TOO_LONG_STRING \
|
||||||
|
"The length reported in the cbDynamicDSTTimeZoneKeyName field of the Extended Info Packet (section 2.2.1.11.1.1.1) is too long."
|
||||||
|
|
||||||
|
#define ERRINFO_DYNAMIC_DST_DISABLED_FIELD_MISSING_STRING \
|
||||||
|
"The dynamicDaylightTimeDisabled field is not present in the Extended Info Packet (section 2.2.1.11.1.1.1)."
|
||||||
|
|
||||||
|
#define ERRINFO_VC_DECODING_ERROR_STRING \
|
||||||
|
"An error occurred when processing dynamic virtual channel data ([MS-RDPEDYC] section 3.3.5)."
|
||||||
|
|
||||||
#define ERRINFO_UPDATE_SESSION_KEY_FAILED_STRING \
|
#define ERRINFO_UPDATE_SESSION_KEY_FAILED_STRING \
|
||||||
"An attempt to update the session keys while using Standard RDP Security mechanisms (section 5.3.7) failed."
|
"An attempt to update the session keys while using Standard RDP Security mechanisms (section 5.3.7) failed."
|
||||||
|
|
||||||
@ -356,6 +406,19 @@ static const ERRINFO ERRINFO_CODES[] =
|
|||||||
ERRINFO_DEFINE(RPC_INITIATED_DISCONNECT_BY_USER),
|
ERRINFO_DEFINE(RPC_INITIATED_DISCONNECT_BY_USER),
|
||||||
ERRINFO_DEFINE(LOGOFF_BY_USER),
|
ERRINFO_DEFINE(LOGOFF_BY_USER),
|
||||||
|
|
||||||
|
/* Protocol-independent codes generated by the Connection Broker */
|
||||||
|
ERRINFO_DEFINE(CB_DESTINATION_NOT_FOUND),
|
||||||
|
ERRINFO_DEFINE(CB_LOADING_DESTINATION),
|
||||||
|
ERRINFO_DEFINE(CB_REDIRECTING_TO_DESTINATION),
|
||||||
|
ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_WAKE),
|
||||||
|
ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_BOOT),
|
||||||
|
ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_NO_DNS),
|
||||||
|
ERRINFO_DEFINE(CB_DESTINATION_POOL_NOT_FREE),
|
||||||
|
ERRINFO_DEFINE(CB_CONNECTION_CANCELLED),
|
||||||
|
ERRINFO_DEFINE(CB_CONNECTION_ERROR_INVALID_SETTINGS),
|
||||||
|
ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_BOOT_TIMEOUT),
|
||||||
|
ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_SESSMON_FAILED),
|
||||||
|
|
||||||
/* Protocol-independent licensing codes */
|
/* Protocol-independent licensing codes */
|
||||||
ERRINFO_DEFINE(LICENSE_INTERNAL),
|
ERRINFO_DEFINE(LICENSE_INTERNAL),
|
||||||
ERRINFO_DEFINE(LICENSE_NO_LICENSE_SERVER),
|
ERRINFO_DEFINE(LICENSE_NO_LICENSE_SERVER),
|
||||||
@ -434,6 +497,11 @@ static const ERRINFO ERRINFO_CODES[] =
|
|||||||
ERRINFO_DEFINE(VC_DATA_TOO_LONG),
|
ERRINFO_DEFINE(VC_DATA_TOO_LONG),
|
||||||
ERRINFO_DEFINE(GRAPHICS_MODE_NOT_SUPPORTED),
|
ERRINFO_DEFINE(GRAPHICS_MODE_NOT_SUPPORTED),
|
||||||
ERRINFO_DEFINE(GRAPHICS_SUBSYSTEM_RESET_FAILED),
|
ERRINFO_DEFINE(GRAPHICS_SUBSYSTEM_RESET_FAILED),
|
||||||
|
ERRINFO_DEFINE(GRAPHICS_SUBSYSTEM_FAILED),
|
||||||
|
ERRINFO_DEFINE(TIMEZONE_KEY_NAME_LENGTH_TOO_SHORT),
|
||||||
|
ERRINFO_DEFINE(TIMEZONE_KEY_NAME_LENGTH_TOO_LONG),
|
||||||
|
ERRINFO_DEFINE(DYNAMIC_DST_DISABLED_FIELD_MISSING),
|
||||||
|
ERRINFO_DEFINE(VC_DECODING_ERROR),
|
||||||
ERRINFO_DEFINE(UPDATE_SESSION_KEY_FAILED),
|
ERRINFO_DEFINE(UPDATE_SESSION_KEY_FAILED),
|
||||||
ERRINFO_DEFINE(DECRYPT_FAILED),
|
ERRINFO_DEFINE(DECRYPT_FAILED),
|
||||||
ERRINFO_DEFINE(ENCRYPT_FAILED),
|
ERRINFO_DEFINE(ENCRYPT_FAILED),
|
||||||
@ -500,4 +568,3 @@ void rdp_print_errinfo(UINT32 code)
|
|||||||
|
|
||||||
fprintf(stderr, "ERRINFO_UNKNOWN 0x%08X: Unknown error.\n", code);
|
fprintf(stderr, "ERRINFO_UNKNOWN 0x%08X: Unknown error.\n", code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +369,6 @@ static wEventType FreeRDP_Events[] =
|
|||||||
DEFINE_EVENT_ENTRY(PanningChange)
|
DEFINE_EVENT_ENTRY(PanningChange)
|
||||||
DEFINE_EVENT_ENTRY(ScalingFactorChange)
|
DEFINE_EVENT_ENTRY(ScalingFactorChange)
|
||||||
DEFINE_EVENT_ENTRY(ErrorInfo)
|
DEFINE_EVENT_ENTRY(ErrorInfo)
|
||||||
DEFINE_EVENT_ENTRY(ParamChange)
|
|
||||||
DEFINE_EVENT_ENTRY(Terminate)
|
DEFINE_EVENT_ENTRY(Terminate)
|
||||||
DEFINE_EVENT_ENTRY(ConnectionResult)
|
DEFINE_EVENT_ENTRY(ConnectionResult)
|
||||||
DEFINE_EVENT_ENTRY(ChannelConnected)
|
DEFINE_EVENT_ENTRY(ChannelConnected)
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <winpr/tchar.h>
|
#include <winpr/tchar.h>
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
#include <winpr/dsparse.h>
|
#include <winpr/dsparse.h>
|
||||||
|
#include <winpr/winhttp.h>
|
||||||
|
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
@ -98,12 +99,15 @@ int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc)
|
|||||||
|
|
||||||
http_response = http_response_recv(rpc->TlsIn);
|
http_response = http_response_recv(rpc->TlsIn);
|
||||||
|
|
||||||
|
if (http_response->AuthParam)
|
||||||
|
{
|
||||||
ntlm_token_data = NULL;
|
ntlm_token_data = NULL;
|
||||||
crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam),
|
crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam),
|
||||||
&ntlm_token_data, &ntlm_token_length);
|
&ntlm_token_data, &ntlm_token_length);
|
||||||
|
|
||||||
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
|
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
|
||||||
ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
|
ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
|
||||||
|
}
|
||||||
|
|
||||||
http_response_free(http_response);
|
http_response_free(http_response);
|
||||||
|
|
||||||
@ -113,30 +117,67 @@ int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc)
|
|||||||
int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
|
int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
|
||||||
{
|
{
|
||||||
rdpNtlm* ntlm = NULL;
|
rdpNtlm* ntlm = NULL;
|
||||||
rdpSettings* settings;
|
rdpSettings* settings = rpc->settings;
|
||||||
|
freerdp* instance = (freerdp*) rpc->settings->instance;
|
||||||
settings = rpc->settings;
|
BOOL promptPassword = FALSE;
|
||||||
|
|
||||||
if (channel == TSG_CHANNEL_IN)
|
if (channel == TSG_CHANNEL_IN)
|
||||||
ntlm = rpc->NtlmHttpIn->ntlm;
|
ntlm = rpc->NtlmHttpIn->ntlm;
|
||||||
else if (channel == TSG_CHANNEL_OUT)
|
else if (channel == TSG_CHANNEL_OUT)
|
||||||
ntlm = rpc->NtlmHttpOut->ntlm;
|
ntlm = rpc->NtlmHttpOut->ntlm;
|
||||||
|
|
||||||
ntlm_client_init(ntlm, TRUE, settings->GatewayUsername,
|
if ((!settings->GatewayPassword) || (!settings->GatewayUsername)
|
||||||
|
|| (!strlen(settings->GatewayPassword)) || (!strlen(settings->GatewayUsername)))
|
||||||
|
{
|
||||||
|
promptPassword = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (promptPassword)
|
||||||
|
{
|
||||||
|
if (instance->GatewayAuthenticate)
|
||||||
|
{
|
||||||
|
BOOL proceed = instance->GatewayAuthenticate(instance,
|
||||||
|
&settings->GatewayUsername, &settings->GatewayPassword, &settings->GatewayDomain);
|
||||||
|
|
||||||
|
if (!proceed)
|
||||||
|
{
|
||||||
|
connectErrorCode = CANCELEDBYUSER;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->GatewayUseSameCredentials)
|
||||||
|
{
|
||||||
|
settings->Username = _strdup(settings->GatewayUsername);
|
||||||
|
settings->Domain = _strdup(settings->GatewayDomain);
|
||||||
|
settings->Password = _strdup(settings->GatewayPassword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ntlm_client_init(ntlm, TRUE, settings->GatewayUsername,
|
||||||
settings->GatewayDomain, settings->GatewayPassword,
|
settings->GatewayDomain, settings->GatewayPassword,
|
||||||
rpc->TlsIn->Bindings);
|
rpc->TlsIn->Bindings))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//ntlm_client_make_spn(ntlm, NULL, settings->GatewayHostname);
|
//ntlm_client_make_spn(ntlm, NULL, settings->GatewayHostname);
|
||||||
ntlm_client_make_spn(ntlm, _T("HTTP"), settings->GatewayHostname);
|
if (!ntlm_client_make_spn(ntlm, _T("HTTP"), settings->GatewayHostname))
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc)
|
BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc)
|
||||||
{
|
{
|
||||||
rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm;
|
rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm;
|
||||||
|
BOOL success = FALSE;
|
||||||
|
|
||||||
rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_IN);
|
if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_IN) == 1)
|
||||||
|
{
|
||||||
|
success = TRUE;
|
||||||
|
|
||||||
/* Send IN Channel Request */
|
/* Send IN Channel Request */
|
||||||
|
|
||||||
@ -151,11 +192,13 @@ BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc)
|
|||||||
rpc_ncacn_http_send_in_channel_request(rpc);
|
rpc_ncacn_http_send_in_channel_request(rpc);
|
||||||
|
|
||||||
ntlm_client_uninit(ntlm);
|
ntlm_client_uninit(ntlm);
|
||||||
|
}
|
||||||
|
|
||||||
ntlm_free(ntlm);
|
ntlm_free(ntlm);
|
||||||
|
|
||||||
rpc->NtlmHttpIn->ntlm = NULL;
|
rpc->NtlmHttpIn->ntlm = NULL;
|
||||||
|
|
||||||
return TRUE;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
|
int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
|
||||||
@ -180,7 +223,7 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
|
|||||||
|
|
||||||
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
|
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
|
||||||
{
|
{
|
||||||
int ntlm_token_length;
|
int ntlm_token_length = 0;
|
||||||
BYTE* ntlm_token_data;
|
BYTE* ntlm_token_data;
|
||||||
HttpResponse* http_response;
|
HttpResponse* http_response;
|
||||||
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
|
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
|
||||||
@ -188,8 +231,11 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
|
|||||||
http_response = http_response_recv(rpc->TlsOut);
|
http_response = http_response_recv(rpc->TlsOut);
|
||||||
|
|
||||||
ntlm_token_data = NULL;
|
ntlm_token_data = NULL;
|
||||||
|
if (http_response && http_response->AuthParam)
|
||||||
|
{
|
||||||
crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam),
|
crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam),
|
||||||
&ntlm_token_data, &ntlm_token_length);
|
&ntlm_token_data, &ntlm_token_length);
|
||||||
|
}
|
||||||
|
|
||||||
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
|
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
|
||||||
ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
|
ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
|
||||||
@ -202,8 +248,11 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
|
|||||||
BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc)
|
BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc)
|
||||||
{
|
{
|
||||||
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
|
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
|
||||||
|
BOOL success = FALSE;
|
||||||
|
|
||||||
rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_OUT);
|
if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_OUT) == 1)
|
||||||
|
{
|
||||||
|
success = TRUE;
|
||||||
|
|
||||||
/* Send OUT Channel Request */
|
/* Send OUT Channel Request */
|
||||||
|
|
||||||
@ -218,9 +267,13 @@ BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc)
|
|||||||
rpc_ncacn_http_send_out_channel_request(rpc);
|
rpc_ncacn_http_send_out_channel_request(rpc);
|
||||||
|
|
||||||
ntlm_client_uninit(ntlm);
|
ntlm_client_uninit(ntlm);
|
||||||
|
}
|
||||||
|
|
||||||
ntlm_free(ntlm);
|
ntlm_free(ntlm);
|
||||||
|
|
||||||
return TRUE;
|
rpc->NtlmHttpOut->ntlm = NULL;
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpc_ntlm_http_init_channel(rdpRpc* rpc, rdpNtlmHttp* ntlm_http, TSG_CHANNEL channel)
|
void rpc_ntlm_http_init_channel(rdpRpc* rpc, rdpNtlmHttp* ntlm_http, TSG_CHANNEL channel)
|
||||||
|
@ -151,7 +151,7 @@ BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, char* hostname)
|
|||||||
status = DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName);
|
status = DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName);
|
||||||
|
|
||||||
if (status != ERROR_SUCCESS)
|
if (status != ERROR_SUCCESS)
|
||||||
return -1;
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -227,6 +227,12 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((!ntlm) || (!ntlm->table))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ntlm_authenticate: invalid ntlm context\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
status = ntlm->table->InitializeSecurityContext(&ntlm->credentials,
|
status = ntlm->table->InitializeSecurityContext(&ntlm->credentials,
|
||||||
(ntlm->haveContext) ? &ntlm->context : NULL,
|
(ntlm->haveContext) ? &ntlm->context : NULL,
|
||||||
(ntlm->ServicePrincipalName) ? ntlm->ServicePrincipalName : NULL,
|
(ntlm->ServicePrincipalName) ? ntlm->ServicePrincipalName : NULL,
|
||||||
@ -270,10 +276,13 @@ void ntlm_client_uninit(rdpNtlm* ntlm)
|
|||||||
free(ntlm->identity.Password);
|
free(ntlm->identity.Password);
|
||||||
free(ntlm->ServicePrincipalName);
|
free(ntlm->ServicePrincipalName);
|
||||||
|
|
||||||
|
if (ntlm->table)
|
||||||
|
{
|
||||||
ntlm->table->FreeCredentialsHandle(&ntlm->credentials);
|
ntlm->table->FreeCredentialsHandle(&ntlm->credentials);
|
||||||
ntlm->table->FreeContextBuffer(ntlm->pPackageInfo);
|
ntlm->table->FreeContextBuffer(ntlm->pPackageInfo);
|
||||||
ntlm->table->DeleteSecurityContext(&ntlm->context);
|
ntlm->table->DeleteSecurityContext(&ntlm->context);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rdpNtlm* ntlm_new()
|
rdpNtlm* ntlm_new()
|
||||||
{
|
{
|
||||||
|
@ -360,6 +360,12 @@ int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
|
|||||||
|
|
||||||
ntlm = rpc->ntlm;
|
ntlm = rpc->ntlm;
|
||||||
|
|
||||||
|
if ((!ntlm) || (!ntlm->table))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "rpc_write: invalid ntlm context\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes) != SEC_E_OK)
|
if (ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes) != SEC_E_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "QueryContextAttributes SECPKG_ATTR_SIZES failure\n");
|
fprintf(stderr, "QueryContextAttributes SECPKG_ATTR_SIZES failure\n");
|
||||||
|
@ -97,11 +97,41 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
|||||||
p_cont_elem_t* p_cont_elem;
|
p_cont_elem_t* p_cont_elem;
|
||||||
rpcconn_bind_hdr_t* bind_pdu;
|
rpcconn_bind_hdr_t* bind_pdu;
|
||||||
rdpSettings* settings = rpc->settings;
|
rdpSettings* settings = rpc->settings;
|
||||||
|
BOOL promptPassword = FALSE;
|
||||||
|
freerdp* instance = (freerdp*) settings->instance;
|
||||||
|
|
||||||
DEBUG_RPC("Sending bind PDU");
|
DEBUG_RPC("Sending bind PDU");
|
||||||
|
|
||||||
rpc->ntlm = ntlm_new();
|
rpc->ntlm = ntlm_new();
|
||||||
|
|
||||||
|
if ((!settings->GatewayPassword) || (!settings->GatewayUsername)
|
||||||
|
|| (!strlen(settings->GatewayPassword)) || (!strlen(settings->GatewayUsername)))
|
||||||
|
{
|
||||||
|
promptPassword = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (promptPassword)
|
||||||
|
{
|
||||||
|
if (instance->GatewayAuthenticate)
|
||||||
|
{
|
||||||
|
BOOL proceed = instance->GatewayAuthenticate(instance,
|
||||||
|
&settings->GatewayUsername, &settings->GatewayPassword, &settings->GatewayDomain);
|
||||||
|
|
||||||
|
if (!proceed)
|
||||||
|
{
|
||||||
|
connectErrorCode = CANCELEDBYUSER;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->GatewayUseSameCredentials)
|
||||||
|
{
|
||||||
|
settings->Username = _strdup(settings->GatewayUsername);
|
||||||
|
settings->Domain = _strdup(settings->GatewayDomain);
|
||||||
|
settings->Password = _strdup(settings->GatewayPassword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ntlm_client_init(rpc->ntlm, FALSE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword, NULL);
|
ntlm_client_init(rpc->ntlm, FALSE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword, NULL);
|
||||||
ntlm_client_make_spn(rpc->ntlm, NULL, settings->GatewayHostname);
|
ntlm_client_make_spn(rpc->ntlm, NULL, settings->GatewayHostname);
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/winhttp.h>
|
||||||
|
|
||||||
#include "ncacn_http.h"
|
#include "ncacn_http.h"
|
||||||
#include "rpc_client.h"
|
#include "rpc_client.h"
|
||||||
@ -147,11 +148,17 @@ BOOL rts_connect(rdpRpc* rpc)
|
|||||||
|
|
||||||
http_response = http_response_recv(rpc->TlsOut);
|
http_response = http_response_recv(rpc->TlsOut);
|
||||||
|
|
||||||
if (http_response->StatusCode != 200)
|
if (http_response->StatusCode != HTTP_STATUS_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "rts_connect error! Status Code: %d\n", http_response->StatusCode);
|
fprintf(stderr, "rts_connect error! Status Code: %d\n", http_response->StatusCode);
|
||||||
http_response_print(http_response);
|
http_response_print(http_response);
|
||||||
http_response_free(http_response);
|
http_response_free(http_response);
|
||||||
|
|
||||||
|
if (!connectErrorCode && http_response->StatusCode == HTTP_STATUS_DENIED)
|
||||||
|
{
|
||||||
|
connectErrorCode = AUTHENTICATIONERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1367,6 +1367,9 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port)
|
|||||||
|
|
||||||
pdu = rpc_recv_dequeue_pdu(rpc);
|
pdu = rpc_recv_dequeue_pdu(rpc);
|
||||||
|
|
||||||
|
if (!pdu)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
call = rpc_client_call_find_by_id(rpc, pdu->CallId);
|
call = rpc_client_call_find_by_id(rpc, pdu->CallId);
|
||||||
|
|
||||||
if (call->OpNum == TsProxyMakeTunnelCallOpnum)
|
if (call->OpNum == TsProxyMakeTunnelCallOpnum)
|
||||||
@ -1409,6 +1412,9 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port)
|
|||||||
#if 0
|
#if 0
|
||||||
pdu = rpc_recv_dequeue_pdu(rpc);
|
pdu = rpc_recv_dequeue_pdu(rpc);
|
||||||
|
|
||||||
|
if (!pdu)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (!TsProxySetupReceivePipeReadResponse(tsg, pdu))
|
if (!TsProxySetupReceivePipeReadResponse(tsg, pdu))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "TsProxySetupReceivePipe: error reading response\n");
|
fprintf(stderr, "TsProxySetupReceivePipe: error reading response\n");
|
||||||
|
@ -232,36 +232,46 @@ BOOL gcc_read_conference_create_response(wStream* s, rdpSettings* settings)
|
|||||||
BYTE number;
|
BYTE number;
|
||||||
|
|
||||||
/* ConnectData */
|
/* ConnectData */
|
||||||
per_read_choice(s, &choice);
|
if (!per_read_choice(s, &choice) ||
|
||||||
per_read_object_identifier(s, t124_02_98_oid);
|
!per_read_object_identifier(s, t124_02_98_oid))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* ConnectData::connectPDU (OCTET_STRING) */
|
/* ConnectData::connectPDU (OCTET_STRING) */
|
||||||
per_read_length(s, &length);
|
if (!per_read_length(s, &length))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* ConnectGCCPDU */
|
/* ConnectGCCPDU */
|
||||||
per_read_choice(s, &choice);
|
if (!per_read_choice(s, &choice))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* ConferenceCreateResponse::nodeID (UserID) */
|
/* ConferenceCreateResponse::nodeID (UserID) */
|
||||||
per_read_integer16(s, &nodeID, 1001);
|
if (!per_read_integer16(s, &nodeID, 1001))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* ConferenceCreateResponse::tag (INTEGER) */
|
/* ConferenceCreateResponse::tag (INTEGER) */
|
||||||
per_read_integer(s, &tag);
|
if (!per_read_integer(s, &tag))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* ConferenceCreateResponse::result (ENUMERATED) */
|
/* ConferenceCreateResponse::result (ENUMERATED) */
|
||||||
per_read_enumerated(s, &result, MCS_Result_enum_length);
|
if (!per_read_enumerated(s, &result, MCS_Result_enum_length))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* number of UserData sets */
|
/* number of UserData sets */
|
||||||
per_read_number_of_sets(s, &number);
|
if (!per_read_number_of_sets(s, &number))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* UserData::value present + select h221NonStandard (1) */
|
/* UserData::value present + select h221NonStandard (1) */
|
||||||
per_read_choice(s, &choice);
|
if (!per_read_choice(s, &choice))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* h221NonStandard */
|
/* h221NonStandard */
|
||||||
if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
|
if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* userData (OCTET_STRING) */
|
/* userData (OCTET_STRING) */
|
||||||
per_read_length(s, &length);
|
if (!per_read_length(s, &length))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (!gcc_read_server_data_blocks(s, settings, length))
|
if (!gcc_read_server_data_blocks(s, settings, length))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n");
|
fprintf(stderr, "gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n");
|
||||||
@ -309,14 +319,18 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length)
|
|||||||
{
|
{
|
||||||
UINT16 type;
|
UINT16 type;
|
||||||
UINT16 blockLength;
|
UINT16 blockLength;
|
||||||
int pos;
|
int begPos, endPos;
|
||||||
|
|
||||||
while (length > 0)
|
while (length > 0)
|
||||||
{
|
{
|
||||||
pos = Stream_GetPosition(s);
|
begPos = Stream_GetPosition(s);
|
||||||
|
|
||||||
if (!gcc_read_user_data_header(s, &type, &blockLength))
|
if (!gcc_read_user_data_header(s, &type, &blockLength))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < (blockLength - 4))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case CS_CORE:
|
case CS_CORE:
|
||||||
@ -344,12 +358,37 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpSettings* settings, int length)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CS_MCS_MSGCHANNEL:
|
||||||
|
if (!gcc_read_client_message_channel_data(s, settings, blockLength - 4))
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CS_MONITOR_EX:
|
||||||
|
if (!gcc_read_client_monitor_extended_data(s, settings, blockLength - 4))
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CS_MULTITRANSPORT:
|
||||||
|
if (!gcc_read_client_multitransport_channel_data(s, settings, blockLength - 4))
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
fprintf(stderr, "Unknown GCC client data block: 0x%04X\n", type);
|
||||||
|
Stream_Seek(s, blockLength - 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endPos = Stream_GetPosition(s);
|
||||||
|
|
||||||
|
if (endPos != (begPos + blockLength))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error parsing GCC client data block 0x%04X: Actual Offset: %d Expected Offset: %d\n",
|
||||||
|
type, endPos, begPos + blockLength);
|
||||||
|
}
|
||||||
|
|
||||||
length -= blockLength;
|
length -= blockLength;
|
||||||
Stream_SetPosition(s, pos + blockLength);
|
Stream_SetPosition(s, begPos + blockLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -366,10 +405,12 @@ void gcc_write_client_data_blocks(wStream* s, rdpSettings* settings)
|
|||||||
|
|
||||||
if (settings->NegotiationFlags & EXTENDED_CLIENT_DATA_SUPPORTED)
|
if (settings->NegotiationFlags & EXTENDED_CLIENT_DATA_SUPPORTED)
|
||||||
{
|
{
|
||||||
if (!settings->SpanMonitors)
|
if (settings->SpanMonitors)
|
||||||
{
|
{
|
||||||
gcc_write_client_monitor_data(s, settings);
|
gcc_write_client_monitor_data(s, settings);
|
||||||
}
|
}
|
||||||
|
gcc_write_client_message_channel_data(s, settings);
|
||||||
|
gcc_write_client_multitransport_channel_data(s, settings);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -433,6 +474,22 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SC_MCS_MSGCHANNEL:
|
||||||
|
if (!gcc_read_server_message_channel_data(s, settings))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SC_MULTITRANSPORT:
|
||||||
|
if (!gcc_read_server_multitransport_channel_data(s, settings))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "gcc_read_server_data_blocks: gcc_read_server_multitransport_channel_data failed\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "gcc_read_server_data_blocks: ignoring type=%hu\n", type);
|
fprintf(stderr, "gcc_read_server_data_blocks: ignoring type=%hu\n", type);
|
||||||
break;
|
break;
|
||||||
@ -446,9 +503,13 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpSettings* settings, int length)
|
|||||||
|
|
||||||
void gcc_write_server_data_blocks(wStream* s, rdpSettings* settings)
|
void gcc_write_server_data_blocks(wStream* s, rdpSettings* settings)
|
||||||
{
|
{
|
||||||
gcc_write_server_core_data(s, settings);
|
gcc_write_server_core_data(s, settings); /* serverCoreData */
|
||||||
gcc_write_server_network_data(s, settings);
|
gcc_write_server_network_data(s, settings); /* serverNetworkData */
|
||||||
gcc_write_server_security_data(s, settings);
|
gcc_write_server_security_data(s, settings); /* serverSecurityData */
|
||||||
|
|
||||||
|
/* TODO: Send these GCC data blocks only when the client sent them */
|
||||||
|
//gcc_write_server_message_channel_data(s, settings); /* serverMessageChannelData */
|
||||||
|
//gcc_write_server_multitransport_channel_data(s, settings); /* serverMultitransportChannelData */
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length)
|
BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length)
|
||||||
@ -496,20 +557,25 @@ BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLe
|
|||||||
UINT16 highColorDepth = 0;
|
UINT16 highColorDepth = 0;
|
||||||
UINT16 supportedColorDepths = 0;
|
UINT16 supportedColorDepths = 0;
|
||||||
UINT32 serverSelectedProtocol = 0;
|
UINT32 serverSelectedProtocol = 0;
|
||||||
|
UINT32 desktopPhysicalWidth = 0;
|
||||||
|
UINT32 desktopPhysicalHeight = 0;
|
||||||
|
UINT16 desktopOrientation = 0;
|
||||||
|
UINT32 desktopScaleFactor = 0;
|
||||||
|
UINT32 deviceScaleFactor = 0;
|
||||||
|
|
||||||
/* Length of all required fields, until imeFileName */
|
/* Length of all required fields, until imeFileName */
|
||||||
if (blockLength < 128)
|
if (blockLength < 128)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT32(s, version); /* version */
|
Stream_Read_UINT32(s, version); /* version (4 bytes) */
|
||||||
settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7);
|
settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7);
|
||||||
|
|
||||||
Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth */
|
Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth (2 bytes) */
|
||||||
Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight */
|
Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight (2 bytes) */
|
||||||
Stream_Read_UINT16(s, colorDepth); /* ColorDepth */
|
Stream_Read_UINT16(s, colorDepth); /* ColorDepth (2 bytes) */
|
||||||
Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) */
|
Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) (2 bytes) */
|
||||||
Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout */
|
Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout (4 bytes) */
|
||||||
Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild */
|
Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild (4 bytes) */
|
||||||
|
|
||||||
/* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
|
/* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
|
||||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL);
|
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL);
|
||||||
@ -519,11 +585,11 @@ BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLe
|
|||||||
free(str);
|
free(str);
|
||||||
str = NULL;
|
str = NULL;
|
||||||
|
|
||||||
Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType */
|
Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType (4 bytes) */
|
||||||
Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */
|
Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType (4 bytes) */
|
||||||
Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey */
|
Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey (4 bytes) */
|
||||||
|
|
||||||
Stream_Seek(s, 64); /* imeFileName */
|
Stream_Seek(s, 64); /* imeFileName (64 bytes) */
|
||||||
|
|
||||||
blockLength -= 128;
|
blockLength -= 128;
|
||||||
|
|
||||||
@ -538,56 +604,81 @@ BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLe
|
|||||||
{
|
{
|
||||||
if (blockLength < 2)
|
if (blockLength < 2)
|
||||||
break;
|
break;
|
||||||
Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */
|
Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth (2 bytes) */
|
||||||
blockLength -= 2;
|
blockLength -= 2;
|
||||||
|
|
||||||
if (blockLength < 2)
|
if (blockLength < 2)
|
||||||
break;
|
break;
|
||||||
Stream_Seek_UINT16(s); /* clientProductID */
|
Stream_Seek_UINT16(s); /* clientProductID (2 bytes) */
|
||||||
blockLength -= 2;
|
blockLength -= 2;
|
||||||
|
|
||||||
if (blockLength < 4)
|
if (blockLength < 4)
|
||||||
break;
|
break;
|
||||||
Stream_Seek_UINT32(s); /* serialNumber */
|
Stream_Seek_UINT32(s); /* serialNumber (4 bytes) */
|
||||||
blockLength -= 4;
|
blockLength -= 4;
|
||||||
|
|
||||||
if (blockLength < 2)
|
if (blockLength < 2)
|
||||||
break;
|
break;
|
||||||
Stream_Read_UINT16(s, highColorDepth); /* highColorDepth */
|
Stream_Read_UINT16(s, highColorDepth); /* highColorDepth (2 bytes) */
|
||||||
blockLength -= 2;
|
blockLength -= 2;
|
||||||
|
|
||||||
if (blockLength < 2)
|
if (blockLength < 2)
|
||||||
break;
|
break;
|
||||||
Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths */
|
Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths (2 bytes) */
|
||||||
blockLength -= 2;
|
blockLength -= 2;
|
||||||
|
|
||||||
if (blockLength < 2)
|
if (blockLength < 2)
|
||||||
break;
|
break;
|
||||||
Stream_Read_UINT16(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags */
|
Stream_Read_UINT16(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
|
||||||
blockLength -= 2;
|
blockLength -= 2;
|
||||||
|
|
||||||
if (blockLength < 64)
|
if (blockLength < 64)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL);
|
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL);
|
||||||
Stream_Seek(s, 64);
|
Stream_Seek(s, 64); /* clientDigProductId (64 bytes) */
|
||||||
sprintf_s(settings->ClientProductId, 32, "%s", str);
|
sprintf_s(settings->ClientProductId, 32, "%s", str);
|
||||||
free(str);
|
free(str);
|
||||||
blockLength -= 64;
|
blockLength -= 64;
|
||||||
|
|
||||||
if (blockLength < 1)
|
if (blockLength < 1)
|
||||||
break;
|
break;
|
||||||
Stream_Read_UINT8(s, settings->PerformanceFlags); /* connectionType */
|
Stream_Read_UINT8(s, settings->PerformanceFlags); /* connectionType (1 byte) */
|
||||||
blockLength -= 1;
|
blockLength -= 1;
|
||||||
|
|
||||||
if (blockLength < 1)
|
if (blockLength < 1)
|
||||||
break;
|
break;
|
||||||
Stream_Seek_UINT8(s); /* pad1octet */
|
Stream_Seek_UINT8(s); /* pad1octet (1 byte) */
|
||||||
blockLength -= 1;
|
blockLength -= 1;
|
||||||
|
|
||||||
if (blockLength < 4)
|
if (blockLength < 4)
|
||||||
break;
|
break;
|
||||||
Stream_Read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol */
|
Stream_Read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol (4 bytes) */
|
||||||
|
blockLength -= 4;
|
||||||
|
|
||||||
|
if (blockLength < 4)
|
||||||
|
break;
|
||||||
|
Stream_Read_UINT32(s, desktopPhysicalWidth); /* desktopPhysicalWidth (4 bytes) */
|
||||||
|
blockLength -= 4;
|
||||||
|
|
||||||
|
if (blockLength < 4)
|
||||||
|
break;
|
||||||
|
Stream_Read_UINT32(s, desktopPhysicalHeight); /* desktopPhysicalHeight (4 bytes) */
|
||||||
|
blockLength -= 4;
|
||||||
|
|
||||||
|
if (blockLength < 2)
|
||||||
|
break;
|
||||||
|
Stream_Read_UINT16(s, desktopOrientation); /* desktopOrientation (2 bytes) */
|
||||||
|
blockLength -= 2;
|
||||||
|
|
||||||
|
if (blockLength < 4)
|
||||||
|
break;
|
||||||
|
Stream_Read_UINT32(s, desktopScaleFactor); /* desktopScaleFactor (4 bytes) */
|
||||||
|
blockLength -= 4;
|
||||||
|
|
||||||
|
if (blockLength < 4)
|
||||||
|
break;
|
||||||
|
Stream_Read_UINT32(s, deviceScaleFactor); /* deviceScaleFactor (4 bytes) */
|
||||||
blockLength -= 4;
|
blockLength -= 4;
|
||||||
|
|
||||||
if (settings->SelectedProtocol != serverSelectedProtocol)
|
if (settings->SelectedProtocol != serverSelectedProtocol)
|
||||||
@ -730,6 +821,9 @@ void gcc_write_client_core_data(wStream* s, rdpSettings* settings)
|
|||||||
if (settings->NetworkAutoDetect)
|
if (settings->NetworkAutoDetect)
|
||||||
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT;
|
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT;
|
||||||
|
|
||||||
|
if (settings->SupportHeartbeatPdu)
|
||||||
|
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_HEARTBEAT_PDU;
|
||||||
|
|
||||||
if (settings->SupportGraphicsPipeline)
|
if (settings->SupportGraphicsPipeline)
|
||||||
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL;
|
earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL;
|
||||||
|
|
||||||
@ -761,26 +855,38 @@ BOOL gcc_read_server_core_data(wStream* s, rdpSettings* settings)
|
|||||||
{
|
{
|
||||||
UINT32 version;
|
UINT32 version;
|
||||||
UINT32 clientRequestedProtocols;
|
UINT32 clientRequestedProtocols;
|
||||||
|
UINT32 earlyCapabilityFlags;
|
||||||
|
|
||||||
if(Stream_GetRemainingLength(s) < 8)
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT32(s, version); /* version */
|
Stream_Read_UINT32(s, version); /* version */
|
||||||
Stream_Read_UINT32(s, clientRequestedProtocols); /* clientRequestedProtocols */
|
|
||||||
|
|
||||||
if (version == RDP_VERSION_4 && settings->RdpVersion > 4)
|
if (version == RDP_VERSION_4 && settings->RdpVersion > 4)
|
||||||
settings->RdpVersion = 4;
|
settings->RdpVersion = 4;
|
||||||
else if (version == RDP_VERSION_5_PLUS && settings->RdpVersion < 5)
|
else if (version == RDP_VERSION_5_PLUS && settings->RdpVersion < 5)
|
||||||
settings->RdpVersion = 7;
|
settings->RdpVersion = 7;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) >= 4)
|
||||||
|
{
|
||||||
|
Stream_Read_UINT32(s, clientRequestedProtocols); /* clientRequestedProtocols */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) >= 4)
|
||||||
|
{
|
||||||
|
Stream_Read_UINT32(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gcc_write_server_core_data(wStream* s, rdpSettings* settings)
|
void gcc_write_server_core_data(wStream* s, rdpSettings* settings)
|
||||||
{
|
{
|
||||||
gcc_write_user_data_header(s, SC_CORE, 12);
|
gcc_write_user_data_header(s, SC_CORE, 16);
|
||||||
|
|
||||||
Stream_Write_UINT32(s, settings->RdpVersion == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS);
|
Stream_Write_UINT32(s, settings->RdpVersion == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS);
|
||||||
Stream_Write_UINT32(s, settings->RequestedProtocols); /* clientRequestedProtocols */
|
Stream_Write_UINT32(s, settings->RequestedProtocols); /* clientRequestedProtocols */
|
||||||
|
Stream_Write_UINT32(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1125,24 +1231,31 @@ BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
UINT16 MCSChannelId;
|
UINT16 MCSChannelId;
|
||||||
UINT16 channelCount;
|
UINT16 channelCount, channelsToTreat;
|
||||||
UINT16 channelId;
|
UINT16 channelId;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < 4)
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
|
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
|
||||||
Stream_Read_UINT16(s, channelCount); /* channelCount */
|
Stream_Read_UINT16(s, channelCount); /* channelCount */
|
||||||
|
|
||||||
|
channelsToTreat = channelCount;
|
||||||
|
|
||||||
if (channelCount != settings->ChannelCount)
|
if (channelCount != settings->ChannelCount)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "requested %d channels, got %d instead\n",
|
fprintf(stderr, "requested %d channels, got %d instead\n",
|
||||||
settings->ChannelCount, channelCount);
|
settings->ChannelCount, channelCount);
|
||||||
|
|
||||||
|
/* we ensure that the response is not bigger than the request */
|
||||||
|
if (channelCount > settings->ChannelCount)
|
||||||
|
channelsToTreat = settings->ChannelCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < channelCount * 2)
|
if (Stream_GetRemainingLength(s) < channelCount * 2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
for (i = 0; i < channelCount; i++)
|
for (i = 0; i < channelsToTreat; i++)
|
||||||
{
|
{
|
||||||
Stream_Read_UINT16(s, channelId); /* channelId */
|
Stream_Read_UINT16(s, channelId); /* channelId */
|
||||||
settings->ChannelDefArray[i].ChannelId = channelId;
|
settings->ChannelDefArray[i].ChannelId = channelId;
|
||||||
@ -1182,18 +1295,16 @@ void gcc_write_server_network_data(wStream* s, rdpSettings* settings)
|
|||||||
BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
|
BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
|
||||||
{
|
{
|
||||||
UINT32 flags;
|
UINT32 flags;
|
||||||
|
UINT32 redirectedSessionId;
|
||||||
|
|
||||||
if (blockLength < 4)
|
if (blockLength < 8)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT32(s, flags); /* flags */
|
Stream_Read_UINT32(s, flags); /* flags */
|
||||||
|
Stream_Read_UINT32(s, redirectedSessionId); /* redirectedSessionId */
|
||||||
|
|
||||||
if ((flags & REDIRECTED_SESSIONID_FIELD_VALID))
|
if (flags & REDIRECTED_SESSIONID_FIELD_VALID)
|
||||||
{
|
settings->RedirectedSessionId = redirectedSessionId;
|
||||||
if(blockLength < 8)
|
|
||||||
return FALSE;
|
|
||||||
Stream_Read_UINT32(s, settings->RedirectedSessionId); /* redirectedSessionID */
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -1229,7 +1340,34 @@ void gcc_write_client_cluster_data(wStream* s, rdpSettings* settings)
|
|||||||
|
|
||||||
BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
|
BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "CS_MONITOR\n");
|
UINT32 index;
|
||||||
|
UINT32 flags;
|
||||||
|
UINT32 monitorCount;
|
||||||
|
MONITOR_DEF* monitorDefArray;
|
||||||
|
|
||||||
|
if (blockLength < 8)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, flags); /* flags */
|
||||||
|
Stream_Read_UINT32(s, monitorCount); /* monitorCount */
|
||||||
|
|
||||||
|
if (blockLength < (8 + (monitorCount * 20)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
monitorDefArray = (MONITOR_DEF*) malloc(sizeof(MONITOR_DEF) * monitorCount);
|
||||||
|
ZeroMemory(monitorDefArray, sizeof(MONITOR_DEF) * monitorCount);
|
||||||
|
|
||||||
|
for (index = 0; index < monitorCount; index++)
|
||||||
|
{
|
||||||
|
Stream_Read_UINT32(s, monitorDefArray[index].left); /* left */
|
||||||
|
Stream_Read_UINT32(s, monitorDefArray[index].top); /* top */
|
||||||
|
Stream_Read_UINT32(s, monitorDefArray[index].right); /* right */
|
||||||
|
Stream_Read_UINT32(s, monitorDefArray[index].bottom); /* bottom */
|
||||||
|
Stream_Read_UINT32(s, monitorDefArray[index].flags); /* flags */
|
||||||
|
}
|
||||||
|
|
||||||
|
free(monitorDefArray);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1270,3 +1408,167 @@ void gcc_write_client_monitor_data(wStream* s, rdpSettings* settings)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
|
||||||
|
{
|
||||||
|
UINT32 index;
|
||||||
|
UINT32 flags;
|
||||||
|
UINT32 monitorCount;
|
||||||
|
UINT32 monitorAttributeSize;
|
||||||
|
MONITOR_ATTRIBUTES* monitorAttributesArray;
|
||||||
|
|
||||||
|
if (blockLength < 8)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, flags); /* flags */
|
||||||
|
Stream_Read_UINT32(s, monitorAttributeSize); /* monitorAttributeSize */
|
||||||
|
Stream_Read_UINT32(s, monitorCount); /* monitorCount */
|
||||||
|
|
||||||
|
if (monitorAttributeSize != 20)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (blockLength < (12 + (monitorCount * monitorAttributeSize)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
monitorAttributesArray = (MONITOR_ATTRIBUTES*) malloc(sizeof(MONITOR_ATTRIBUTES) * monitorCount);
|
||||||
|
ZeroMemory(monitorAttributesArray, sizeof(MONITOR_ATTRIBUTES) * monitorCount);
|
||||||
|
|
||||||
|
for (index = 0; index < monitorCount; index++)
|
||||||
|
{
|
||||||
|
Stream_Read_UINT32(s, monitorAttributesArray[index].physicalWidth); /* physicalWidth */
|
||||||
|
Stream_Read_UINT32(s, monitorAttributesArray[index].physicalHeight); /* physicalHeight */
|
||||||
|
Stream_Read_UINT32(s, monitorAttributesArray[index].orientation); /* orientation */
|
||||||
|
Stream_Read_UINT32(s, monitorAttributesArray[index].desktopScaleFactor); /* desktopScaleFactor */
|
||||||
|
Stream_Read_UINT32(s, monitorAttributesArray[index].deviceScaleFactor); /* deviceScaleFactor */
|
||||||
|
}
|
||||||
|
|
||||||
|
free(monitorAttributesArray);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gcc_write_client_monitor_extended_data(wStream* s, rdpSettings* settings)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a client message channel data block (TS_UD_CS_MCS_MSGCHANNEL).\n
|
||||||
|
* @msdn{jj217627}
|
||||||
|
* @param s stream
|
||||||
|
* @param settings rdp settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL gcc_read_client_message_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
|
||||||
|
{
|
||||||
|
UINT32 flags;
|
||||||
|
|
||||||
|
if (blockLength < 4)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, flags);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a client message channel data block (TS_UD_CS_MCS_MSGCHANNEL).\n
|
||||||
|
* @msdn{jj217627}
|
||||||
|
* @param s stream
|
||||||
|
* @param settings rdp settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
void gcc_write_client_message_channel_data(wStream* s, rdpSettings* settings)
|
||||||
|
{
|
||||||
|
if (settings->NetworkAutoDetect ||
|
||||||
|
settings->SupportHeartbeatPdu ||
|
||||||
|
settings->SupportMultitransport)
|
||||||
|
{
|
||||||
|
gcc_write_user_data_header(s, CS_MCS_MSGCHANNEL, 8);
|
||||||
|
|
||||||
|
Stream_Write_UINT32(s, 0); /* flags */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL gcc_read_server_message_channel_data(wStream* s, rdpSettings* settings)
|
||||||
|
{
|
||||||
|
freerdp* instance;
|
||||||
|
UINT16 MCSChannelId;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 2)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
|
||||||
|
|
||||||
|
/* Save the MCS message channel id */
|
||||||
|
instance = (freerdp*) settings->instance;
|
||||||
|
instance->context->rdp->mcs->message_channel_id = MCSChannelId;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gcc_write_server_message_channel_data(wStream* s, rdpSettings* settings)
|
||||||
|
{
|
||||||
|
UINT16 mcsChannelId = 0;
|
||||||
|
|
||||||
|
gcc_write_user_data_header(s, SC_MCS_MSGCHANNEL, 6);
|
||||||
|
|
||||||
|
Stream_Write_UINT16(s, mcsChannelId); /* mcsChannelId (2 bytes) */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a client multitransport channel data block (TS_UD_CS_MULTITRANSPORT).\n
|
||||||
|
* @msdn{jj217498}
|
||||||
|
* @param s stream
|
||||||
|
* @param settings rdp settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
|
||||||
|
{
|
||||||
|
UINT32 flags;
|
||||||
|
|
||||||
|
if (blockLength < 4)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, flags);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a client multitransport channel data block (TS_UD_CS_MULTITRANSPORT).\n
|
||||||
|
* @msdn{jj217498}
|
||||||
|
* @param s stream
|
||||||
|
* @param settings rdp settings
|
||||||
|
*/
|
||||||
|
|
||||||
|
void gcc_write_client_multitransport_channel_data(wStream* s, rdpSettings* settings)
|
||||||
|
{
|
||||||
|
if (settings->MultitransportFlags != 0)
|
||||||
|
{
|
||||||
|
gcc_write_user_data_header(s, CS_MULTITRANSPORT, 8);
|
||||||
|
|
||||||
|
Stream_Write_UINT32(s, settings->MultitransportFlags); /* flags */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpSettings* settings)
|
||||||
|
{
|
||||||
|
UINT32 flags;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, flags); /* flags */
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gcc_write_server_multitransport_channel_data(wStream* s, rdpSettings* settings)
|
||||||
|
{
|
||||||
|
UINT32 flags = 0;
|
||||||
|
|
||||||
|
gcc_write_user_data_header(s, SC_MULTITRANSPORT, 8);
|
||||||
|
|
||||||
|
Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
|
||||||
|
}
|
||||||
|
@ -55,5 +55,15 @@ BOOL gcc_read_client_cluster_data(wStream* s, rdpSettings *settings, UINT16 bloc
|
|||||||
void gcc_write_client_cluster_data(wStream* s, rdpSettings* settings);
|
void gcc_write_client_cluster_data(wStream* s, rdpSettings* settings);
|
||||||
BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
|
BOOL gcc_read_client_monitor_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
|
||||||
void gcc_write_client_monitor_data(wStream* s, rdpSettings* settings);
|
void gcc_write_client_monitor_data(wStream* s, rdpSettings* settings);
|
||||||
|
BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
|
||||||
|
void gcc_write_client_monitor_extended_data(wStream* s, rdpSettings* settings);
|
||||||
|
BOOL gcc_read_client_message_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
|
||||||
|
void gcc_write_client_message_channel_data(wStream* s, rdpSettings* settings);
|
||||||
|
BOOL gcc_read_server_message_channel_data(wStream* s, rdpSettings* settings);
|
||||||
|
void gcc_write_server_message_channel_data(wStream* s, rdpSettings* settings);
|
||||||
|
BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpSettings* settings, UINT16 blockLength);
|
||||||
|
void gcc_write_client_multitransport_channel_data(wStream* s, rdpSettings* settings);
|
||||||
|
BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpSettings* settings);
|
||||||
|
void gcc_write_server_multitransport_channel_data(wStream* s, rdpSettings* settings);
|
||||||
|
|
||||||
#endif /* FREERDP_CORE_GCC_H */
|
#endif /* FREERDP_CORE_GCC_H */
|
||||||
|
62
libfreerdp/core/heartbeat.c
Normal file
62
libfreerdp/core/heartbeat.c
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Heartbeat PDUs
|
||||||
|
*
|
||||||
|
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WITH_DEBUG_HEARTBEAT
|
||||||
|
|
||||||
|
#include "heartbeat.h"
|
||||||
|
|
||||||
|
int rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s)
|
||||||
|
{
|
||||||
|
BYTE reserved;
|
||||||
|
BYTE period;
|
||||||
|
BYTE count1;
|
||||||
|
BYTE count2;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
Stream_Read_UINT8(s, reserved); /* reserved (1 byte) */
|
||||||
|
Stream_Read_UINT8(s, period); /* period (1 byte) */
|
||||||
|
Stream_Read_UINT8(s, count1); /* count1 (1 byte) */
|
||||||
|
Stream_Read_UINT8(s, count2); /* count2 (1 byte) */
|
||||||
|
|
||||||
|
DEBUG_HEARTBEAT("received Heartbeat PDU -> period=%u, count1=%u, count2=%u", period, count1, count2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdpHeartbeat* heartbeat_new(void)
|
||||||
|
{
|
||||||
|
rdpHeartbeat* heartbeat = (rdpHeartbeat*)malloc(sizeof(rdpHeartbeat));
|
||||||
|
if (heartbeat)
|
||||||
|
{
|
||||||
|
ZeroMemory(heartbeat, sizeof(rdpHeartbeat));
|
||||||
|
}
|
||||||
|
|
||||||
|
return heartbeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void heartbeat_free(rdpHeartbeat* heartbeat)
|
||||||
|
{
|
||||||
|
free(heartbeat);
|
||||||
|
}
|
47
libfreerdp/core/heartbeat.h
Normal file
47
libfreerdp/core/heartbeat.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Heartbeat PDUs
|
||||||
|
*
|
||||||
|
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HEARTBEAT_H
|
||||||
|
#define __HEARTBEAT_H
|
||||||
|
|
||||||
|
typedef struct rdp_heartbeat rdpHeartbeat;
|
||||||
|
|
||||||
|
#include "rdp.h"
|
||||||
|
|
||||||
|
#include <freerdp/freerdp.h>
|
||||||
|
|
||||||
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
|
struct rdp_heartbeat
|
||||||
|
{
|
||||||
|
UINT32 placeholder;
|
||||||
|
};
|
||||||
|
|
||||||
|
int rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s);
|
||||||
|
|
||||||
|
rdpHeartbeat* heartbeat_new(void);
|
||||||
|
void heartbeat_free(rdpHeartbeat* heartbeat);
|
||||||
|
|
||||||
|
#ifdef WITH_DEBUG_HEARTBEAT
|
||||||
|
#define DEBUG_HEARTBEAT(fmt, ...) DEBUG_CLASS(HEARTBEAT, fmt, ## __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DEBUG_HEARTBEAT(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __HEARTBEAT_H */
|
@ -464,7 +464,7 @@ BOOL mcs_send_connect_initial(rdpMcs* mcs)
|
|||||||
client_data = Stream_New(NULL, 512);
|
client_data = Stream_New(NULL, 512);
|
||||||
gcc_write_client_data_blocks(client_data, mcs->transport->settings);
|
gcc_write_client_data_blocks(client_data, mcs->transport->settings);
|
||||||
|
|
||||||
gcc_CCrq = Stream_New(NULL, 512);
|
gcc_CCrq = Stream_New(NULL, 1024);
|
||||||
gcc_write_conference_create_request(gcc_CCrq, client_data);
|
gcc_write_conference_create_request(gcc_CCrq, client_data);
|
||||||
length = Stream_GetPosition(gcc_CCrq) + 7;
|
length = Stream_GetPosition(gcc_CCrq) + 7;
|
||||||
|
|
||||||
@ -584,11 +584,22 @@ BOOL mcs_send_connect_response(rdpMcs* mcs)
|
|||||||
BOOL mcs_recv_erect_domain_request(rdpMcs* mcs, wStream* s)
|
BOOL mcs_recv_erect_domain_request(rdpMcs* mcs, wStream* s)
|
||||||
{
|
{
|
||||||
UINT16 length;
|
UINT16 length;
|
||||||
|
UINT32 subHeight;
|
||||||
|
UINT32 subInterval;
|
||||||
enum DomainMCSPDU MCSPDU;
|
enum DomainMCSPDU MCSPDU;
|
||||||
|
|
||||||
MCSPDU = DomainMCSPDU_ErectDomainRequest;
|
MCSPDU = DomainMCSPDU_ErectDomainRequest;
|
||||||
|
|
||||||
return mcs_read_domain_mcspdu_header(s, &MCSPDU, &length);
|
if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!per_read_integer(s, &subHeight)) /* subHeight (INTEGER) */
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!per_read_integer(s, &subInterval)) /* subInterval (INTEGER) */
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -818,6 +829,54 @@ BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channel_id)
|
|||||||
return (status < 0) ? FALSE : TRUE;
|
return (status < 0) ? FALSE : TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive MCS Disconnect Provider Ultimatum PDU.\n
|
||||||
|
* @param mcs mcs module
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL mcs_recv_disconnect_provider_ultimatum(rdpMcs* mcs, wStream* s, int* reason)
|
||||||
|
{
|
||||||
|
BYTE b1, b2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* http://msdn.microsoft.com/en-us/library/cc240872.aspx:
|
||||||
|
*
|
||||||
|
* PER encoded (ALIGNED variant of BASIC-PER) PDU contents:
|
||||||
|
* 21 80
|
||||||
|
*
|
||||||
|
* 0x21:
|
||||||
|
* 0 - --\
|
||||||
|
* 0 - |
|
||||||
|
* 1 - | CHOICE: From DomainMCSPDU select disconnectProviderUltimatum (8)
|
||||||
|
* 0 - | of type DisconnectProviderUltimatum
|
||||||
|
* 0 - |
|
||||||
|
* 0 - --/
|
||||||
|
* 0 - --\
|
||||||
|
* 1 - |
|
||||||
|
* | DisconnectProviderUltimatum::reason = rn-user-requested (3)
|
||||||
|
* 0x80: |
|
||||||
|
* 1 - --/
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Rewind_UINT8(s);
|
||||||
|
Stream_Read_UINT8(s, b1);
|
||||||
|
Stream_Read_UINT8(s, b2);
|
||||||
|
|
||||||
|
*reason = ((b1 & 0x01) << 1) | (b2 >> 7);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send MCS Disconnect Provider Ultimatum PDU.\n
|
* Send MCS Disconnect Provider Ultimatum PDU.\n
|
||||||
* @param mcs mcs module
|
* @param mcs mcs module
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#ifndef __MCS_H
|
#ifndef __MCS_H
|
||||||
#define __MCS_H
|
#define __MCS_H
|
||||||
|
|
||||||
|
typedef struct rdp_mcs rdpMcs;
|
||||||
|
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
|
|
||||||
#include <freerdp/crypto/ber.h>
|
#include <freerdp/crypto/ber.h>
|
||||||
@ -52,6 +54,15 @@ enum MCS_Result
|
|||||||
MCS_Result_enum_length = 16
|
MCS_Result_enum_length = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum MCS_Reason
|
||||||
|
{
|
||||||
|
MCS_Reason_domain_disconnected = 0,
|
||||||
|
MCS_Reason_provider_initiated = 1,
|
||||||
|
MCS_Reason_token_purged = 2,
|
||||||
|
MCS_Reason_user_requested = 3,
|
||||||
|
MCS_Reason_channel_purged = 4
|
||||||
|
};
|
||||||
|
|
||||||
enum DomainMCSPDU
|
enum DomainMCSPDU
|
||||||
{
|
{
|
||||||
DomainMCSPDU_PlumbDomainIndication = 0,
|
DomainMCSPDU_PlumbDomainIndication = 0,
|
||||||
@ -114,8 +125,11 @@ typedef struct
|
|||||||
|
|
||||||
struct rdp_mcs
|
struct rdp_mcs
|
||||||
{
|
{
|
||||||
|
rdpTransport* transport;
|
||||||
|
|
||||||
UINT16 user_id;
|
UINT16 user_id;
|
||||||
struct rdp_transport* transport;
|
UINT16 message_channel_id;
|
||||||
|
|
||||||
DomainParameters domainParameters;
|
DomainParameters domainParameters;
|
||||||
DomainParameters targetParameters;
|
DomainParameters targetParameters;
|
||||||
DomainParameters minimumParameters;
|
DomainParameters minimumParameters;
|
||||||
@ -123,8 +137,8 @@ struct rdp_mcs
|
|||||||
|
|
||||||
BOOL user_channel_joined;
|
BOOL user_channel_joined;
|
||||||
BOOL global_channel_joined;
|
BOOL global_channel_joined;
|
||||||
|
BOOL message_channel_joined;
|
||||||
};
|
};
|
||||||
typedef struct rdp_mcs rdpMcs;
|
|
||||||
|
|
||||||
#define MCS_SEND_DATA_HEADER_MAX_LENGTH 8
|
#define MCS_SEND_DATA_HEADER_MAX_LENGTH 8
|
||||||
|
|
||||||
@ -148,6 +162,7 @@ BOOL mcs_recv_channel_join_request(rdpMcs* mcs, wStream* s, UINT16* channel_id);
|
|||||||
BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channel_id);
|
BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channel_id);
|
||||||
BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channel_id);
|
BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channel_id);
|
||||||
BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channel_id);
|
BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channel_id);
|
||||||
|
BOOL mcs_recv_disconnect_provider_ultimatum(rdpMcs* mcs, wStream* s, int* reason);
|
||||||
BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs);
|
BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs);
|
||||||
BOOL mcs_read_domain_mcspdu_header(wStream* s, enum DomainMCSPDU* domainMCSPDU, UINT16* length);
|
BOOL mcs_read_domain_mcspdu_header(wStream* s, enum DomainMCSPDU* domainMCSPDU, UINT16* length);
|
||||||
void mcs_write_domain_mcspdu_header(wStream* s, enum DomainMCSPDU domainMCSPDU, UINT16 length, BYTE options);
|
void mcs_write_domain_mcspdu_header(wStream* s, enum DomainMCSPDU domainMCSPDU, UINT16 length, BYTE options);
|
||||||
|
58
libfreerdp/core/multitransport.c
Normal file
58
libfreerdp/core/multitransport.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* MULTITRANSPORT PDUs
|
||||||
|
*
|
||||||
|
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "multitransport.h"
|
||||||
|
|
||||||
|
int rdp_recv_multitransport_packet(rdpRdp* rdp, wStream* s)
|
||||||
|
{
|
||||||
|
UINT32 requestId;
|
||||||
|
UINT16 requestedProtocol;
|
||||||
|
UINT16 reserved;
|
||||||
|
BYTE securityCookie[16];
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 24)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, requestId); /* requestId (4 bytes) */
|
||||||
|
Stream_Read_UINT16(s, requestedProtocol); /* requestedProtocol (2 bytes) */
|
||||||
|
Stream_Read_UINT16(s, reserved); /* reserved (2 bytes) */
|
||||||
|
Stream_Read(s, securityCookie, 16); /* securityCookie (16 bytes) */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdpMultitransport* multitransport_new(void)
|
||||||
|
{
|
||||||
|
rdpMultitransport* multitransport = (rdpMultitransport*)malloc(sizeof(rdpMultitransport));
|
||||||
|
if (multitransport)
|
||||||
|
{
|
||||||
|
memset(multitransport, 0, sizeof(rdpMultitransport));
|
||||||
|
}
|
||||||
|
|
||||||
|
return multitransport;
|
||||||
|
}
|
||||||
|
|
||||||
|
void multitransport_free(rdpMultitransport* multitransport)
|
||||||
|
{
|
||||||
|
free(multitransport);
|
||||||
|
}
|
41
libfreerdp/core/multitransport.h
Normal file
41
libfreerdp/core/multitransport.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Multitransport PDUs
|
||||||
|
*
|
||||||
|
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MULTITRANSPORT_H
|
||||||
|
#define __MULTITRANSPORT_H
|
||||||
|
|
||||||
|
typedef struct rdp_multitransport rdpMultitransport;
|
||||||
|
|
||||||
|
#include "rdp.h"
|
||||||
|
|
||||||
|
#include <freerdp/freerdp.h>
|
||||||
|
|
||||||
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
|
struct rdp_multitransport
|
||||||
|
{
|
||||||
|
UINT32 placeholder;
|
||||||
|
};
|
||||||
|
|
||||||
|
int rdp_recv_multitransport_packet(rdpRdp* rdp, wStream* s);
|
||||||
|
|
||||||
|
rdpMultitransport* multitransport_new(void);
|
||||||
|
void multitransport_free(rdpMultitransport* multitransport);
|
||||||
|
|
||||||
|
#endif /* __MULTITRANSPORT_H */
|
@ -491,6 +491,7 @@ BOOL nego_recv_response(rdpNego* nego)
|
|||||||
status = nego_recv(nego->transport, s, nego);
|
status = nego_recv(nego->transport, s, nego);
|
||||||
|
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -147,8 +147,12 @@ int credssp_ntlm_client_init(rdpCredssp* credssp)
|
|||||||
&settings->Username, &settings->Password, &settings->Domain);
|
&settings->Username, &settings->Password, &settings->Domain);
|
||||||
|
|
||||||
if (!proceed)
|
if (!proceed)
|
||||||
|
{
|
||||||
|
connectErrorCode = CANCELEDBYUSER;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sspi_SetAuthIdentity(&(credssp->identity), settings->Username, settings->Domain, settings->Password);
|
sspi_SetAuthIdentity(&(credssp->identity), settings->Username, settings->Domain, settings->Password);
|
||||||
@ -623,7 +627,7 @@ int credssp_server_authenticate(rdpCredssp* credssp)
|
|||||||
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED))
|
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "AcceptSecurityContext status: 0x%08X\n", status);
|
fprintf(stderr, "AcceptSecurityContext status: 0x%08X\n", status);
|
||||||
return -1;
|
return -1; /* Access Denied */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send authentication token */
|
/* send authentication token */
|
||||||
|
@ -229,6 +229,34 @@ wStream* rdp_data_pdu_init(rdpRdp* rdp)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo)
|
||||||
|
{
|
||||||
|
rdp->errorInfo = errorInfo;
|
||||||
|
|
||||||
|
if (rdp->errorInfo != ERRINFO_SUCCESS)
|
||||||
|
{
|
||||||
|
ErrorInfoEventArgs e;
|
||||||
|
rdpContext* context = rdp->instance->context;
|
||||||
|
|
||||||
|
rdp_print_errinfo(rdp->errorInfo);
|
||||||
|
|
||||||
|
EventArgsInit(&e, "freerdp");
|
||||||
|
e.code = rdp->errorInfo;
|
||||||
|
PubSub_OnErrorInfo(context->pubSub, context, &e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
wStream* rdp_message_channel_pdu_init(rdpRdp* rdp)
|
||||||
|
{
|
||||||
|
wStream* s;
|
||||||
|
s = transport_send_stream_init(rdp->transport, 2048);
|
||||||
|
Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH);
|
||||||
|
rdp_security_stream_init(rdp, s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read an RDP packet header.\n
|
* Read an RDP packet header.\n
|
||||||
* @param rdp rdp module
|
* @param rdp rdp module
|
||||||
@ -256,12 +284,30 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
|
|||||||
|
|
||||||
if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum)
|
if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum)
|
||||||
{
|
{
|
||||||
BYTE reason;
|
int reason = 0;
|
||||||
TerminateEventArgs e;
|
TerminateEventArgs e;
|
||||||
rdpContext* context = rdp->instance->context;
|
rdpContext* context = rdp->instance->context;
|
||||||
|
|
||||||
(void) per_read_enumerated(s, &reason, 0);
|
if (!mcs_recv_disconnect_provider_ultimatum(rdp->mcs, s, &reason))
|
||||||
DEBUG_RDP("DisconnectProviderUltimatum from server, reason code 0x%02x\n", reason);
|
return FALSE;
|
||||||
|
|
||||||
|
if (rdp->errorInfo == ERRINFO_SUCCESS)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Some servers like Windows Server 2008 R2 do not send the error info pdu
|
||||||
|
* when the user logs off like they should. Map DisconnectProviderUltimatum
|
||||||
|
* to a ERRINFO_LOGOFF_BY_USER when the errinfo code is ERRINFO_SUCCESS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (reason == MCS_Reason_provider_initiated)
|
||||||
|
rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
|
||||||
|
else if (reason == MCS_Reason_user_requested)
|
||||||
|
rdp_set_error_info(rdp, ERRINFO_LOGOFF_BY_USER);
|
||||||
|
else
|
||||||
|
rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "DisconnectProviderUltimatum: reason: %d\n", reason);
|
||||||
|
|
||||||
rdp->disconnect = TRUE;
|
rdp->disconnect = TRUE;
|
||||||
|
|
||||||
@ -328,13 +374,12 @@ void rdp_write_header(rdpRdp* rdp, wStream* s, UINT16 length, UINT16 channelId)
|
|||||||
Stream_Write_UINT16_BE(s, length); /* userData (OCTET_STRING) */
|
Stream_Write_UINT16_BE(s, length); /* userData (OCTET_STRING) */
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT32 rdp_security_stream_out(rdpRdp* rdp, wStream* s, int length)
|
static UINT32 rdp_security_stream_out(rdpRdp* rdp, wStream* s, int length, UINT32 sec_flags)
|
||||||
{
|
{
|
||||||
BYTE* data;
|
BYTE* data;
|
||||||
UINT32 sec_flags;
|
|
||||||
UINT32 pad = 0;
|
UINT32 pad = 0;
|
||||||
|
|
||||||
sec_flags = rdp->sec_flags;
|
sec_flags |= rdp->sec_flags;
|
||||||
|
|
||||||
if (sec_flags != 0)
|
if (sec_flags != 0)
|
||||||
{
|
{
|
||||||
@ -431,7 +476,7 @@ BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channel_id)
|
|||||||
Stream_Seek(s, sec_bytes);
|
Stream_Seek(s, sec_bytes);
|
||||||
|
|
||||||
Stream_SetPosition(s, secm);
|
Stream_SetPosition(s, secm);
|
||||||
length += rdp_security_stream_out(rdp, s, length);
|
length += rdp_security_stream_out(rdp, s, length, 0);
|
||||||
|
|
||||||
Stream_SetPosition(s, length);
|
Stream_SetPosition(s, length);
|
||||||
Stream_SealLength(s);
|
Stream_SealLength(s);
|
||||||
@ -460,7 +505,7 @@ BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id)
|
|||||||
rdp_write_share_control_header(s, length - sec_bytes, type, channel_id);
|
rdp_write_share_control_header(s, length - sec_bytes, type, channel_id);
|
||||||
|
|
||||||
Stream_SetPosition(s, sec_hold);
|
Stream_SetPosition(s, sec_hold);
|
||||||
length += rdp_security_stream_out(rdp, s, length);
|
length += rdp_security_stream_out(rdp, s, length, 0);
|
||||||
|
|
||||||
Stream_SetPosition(s, length);
|
Stream_SetPosition(s, length);
|
||||||
Stream_SealLength(s);
|
Stream_SealLength(s);
|
||||||
@ -490,7 +535,7 @@ BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id)
|
|||||||
rdp_write_share_data_header(s, length - sec_bytes, type, rdp->settings->ShareId);
|
rdp_write_share_data_header(s, length - sec_bytes, type, rdp->settings->ShareId);
|
||||||
|
|
||||||
Stream_SetPosition(s, sec_hold);
|
Stream_SetPosition(s, sec_hold);
|
||||||
length += rdp_security_stream_out(rdp, s, length);
|
length += rdp_security_stream_out(rdp, s, length, 0);
|
||||||
|
|
||||||
Stream_SetPosition(s, length);
|
Stream_SetPosition(s, length);
|
||||||
Stream_SealLength(s);
|
Stream_SealLength(s);
|
||||||
@ -501,23 +546,158 @@ BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, wStream* s)
|
BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags)
|
||||||
{
|
{
|
||||||
|
UINT16 length;
|
||||||
|
UINT32 sec_bytes;
|
||||||
|
int sec_hold;
|
||||||
|
|
||||||
|
length = Stream_GetPosition(s);
|
||||||
|
Stream_SetPosition(s, 0);
|
||||||
|
|
||||||
|
rdp_write_header(rdp, s, length, rdp->mcs->message_channel_id);
|
||||||
|
|
||||||
|
sec_bytes = rdp_get_sec_bytes(rdp);
|
||||||
|
sec_hold = Stream_GetPosition(s);
|
||||||
|
Stream_Seek(s, sec_bytes);
|
||||||
|
|
||||||
|
Stream_SetPosition(s, sec_hold);
|
||||||
|
length += rdp_security_stream_out(rdp, s, length, sec_flags);
|
||||||
|
|
||||||
|
Stream_SetPosition(s, length);
|
||||||
|
Stream_SealLength(s);
|
||||||
|
|
||||||
|
if (transport_write(rdp->transport, s) < 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL rdp_recv_server_shutdown_denied_pdu(rdpRdp* rdp, wStream* s)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL rdp_recv_server_set_keyboard_indicators_pdu(rdpRdp* rdp, wStream* s)
|
||||||
|
{
|
||||||
|
UINT16 unitId;
|
||||||
|
UINT16 ledFlags;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < 4)
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT32(s, rdp->errorInfo); /* errorInfo (4 bytes) */
|
Stream_Read_UINT16(s, unitId); /* unitId (2 bytes) */
|
||||||
|
Stream_Read_UINT16(s, ledFlags); /* ledFlags (2 bytes) */
|
||||||
|
|
||||||
if (rdp->errorInfo != ERRINFO_SUCCESS)
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL rdp_recv_server_set_keyboard_ime_status_pdu(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
ErrorInfoEventArgs e;
|
UINT16 unitId;
|
||||||
rdpContext* context = rdp->instance->context;
|
UINT32 imeState;
|
||||||
|
UINT32 imeConvMode;
|
||||||
|
|
||||||
rdp_print_errinfo(rdp->errorInfo);
|
if (Stream_GetRemainingLength(s) < 10)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
EventArgsInit(&e, "freerdp");
|
Stream_Read_UINT16(s, unitId); /* unitId (2 bytes) */
|
||||||
e.code = rdp->errorInfo;
|
Stream_Read_UINT32(s, imeState); /* imeState (4 bytes) */
|
||||||
PubSub_OnErrorInfo(context->pubSub, context, &e);
|
Stream_Read_UINT32(s, imeConvMode); /* imeConvMode (4 bytes) */
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, wStream* s)
|
||||||
|
{
|
||||||
|
UINT32 errorInfo;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, errorInfo); /* errorInfo (4 bytes) */
|
||||||
|
|
||||||
|
rdp_set_error_info(rdp, errorInfo);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL rdp_recv_server_auto_reconnect_status_pdu(rdpRdp* rdp, wStream* s)
|
||||||
|
{
|
||||||
|
UINT32 arcStatus;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, arcStatus); /* arcStatus (4 bytes) */
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL rdp_recv_server_status_info_pdu(rdpRdp* rdp, wStream* s)
|
||||||
|
{
|
||||||
|
UINT32 statusCode;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, statusCode); /* statusCode (4 bytes) */
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
UINT32 monitorCount;
|
||||||
|
MONITOR_DEF* monitor;
|
||||||
|
MONITOR_DEF* monitorDefArray;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, monitorCount); /* monitorCount (4 bytes) */
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < (monitorCount * 20))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
monitorDefArray = (MONITOR_DEF*) malloc(sizeof(MONITOR_DEF) * monitorCount);
|
||||||
|
ZeroMemory(monitorDefArray, sizeof(MONITOR_DEF) * monitorCount);
|
||||||
|
|
||||||
|
for (index = 0; index < monitorCount; index++)
|
||||||
|
{
|
||||||
|
monitor = &(monitorDefArray[index]);
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, monitor->left); /* left (4 bytes) */
|
||||||
|
Stream_Read_UINT32(s, monitor->top); /* top (4 bytes) */
|
||||||
|
Stream_Read_UINT32(s, monitor->right); /* right (4 bytes) */
|
||||||
|
Stream_Read_UINT32(s, monitor->bottom); /* bottom (4 bytes) */
|
||||||
|
Stream_Read_UINT32(s, monitor->flags); /* flags (4 bytes) */
|
||||||
|
}
|
||||||
|
|
||||||
|
free(monitorDefArray);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL rdp_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount, MONITOR_DEF* monitorDefArray)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
MONITOR_DEF* monitor;
|
||||||
|
|
||||||
|
Stream_EnsureRemainingCapacity(s, 4 + (monitorCount * 20));
|
||||||
|
|
||||||
|
Stream_Write_UINT32(s, monitorCount); /* monitorCount (4 bytes) */
|
||||||
|
|
||||||
|
for (index = 0; index < monitorCount; index++)
|
||||||
|
{
|
||||||
|
monitor = &(monitorDefArray[index]);
|
||||||
|
|
||||||
|
Stream_Write_UINT32(s, monitor->left); /* left (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, monitor->top); /* top (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, monitor->right); /* right (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, monitor->bottom); /* bottom (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, monitor->flags); /* flags (4 bytes) */
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -589,29 +769,19 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_INPUT:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DATA_PDU_TYPE_SYNCHRONIZE:
|
case DATA_PDU_TYPE_SYNCHRONIZE:
|
||||||
if (!rdp_recv_synchronize_pdu(rdp, cs))
|
if (!rdp_recv_synchronize_pdu(rdp, cs))
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_REFRESH_RECT:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DATA_PDU_TYPE_PLAY_SOUND:
|
case DATA_PDU_TYPE_PLAY_SOUND:
|
||||||
if (!update_recv_play_sound(rdp->update, cs))
|
if (!update_recv_play_sound(rdp->update, cs))
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_SUPPRESS_OUTPUT:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DATA_PDU_TYPE_SHUTDOWN_REQUEST:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DATA_PDU_TYPE_SHUTDOWN_DENIED:
|
case DATA_PDU_TYPE_SHUTDOWN_DENIED:
|
||||||
|
if (!rdp_recv_server_shutdown_denied_pdu(rdp, cs))
|
||||||
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_SAVE_SESSION_INFO:
|
case DATA_PDU_TYPE_SAVE_SESSION_INFO:
|
||||||
@ -619,27 +789,19 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_FONT_LIST:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DATA_PDU_TYPE_FONT_MAP:
|
case DATA_PDU_TYPE_FONT_MAP:
|
||||||
if (!rdp_recv_font_map_pdu(rdp, cs))
|
if (!rdp_recv_font_map_pdu(rdp, cs))
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS:
|
case DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS:
|
||||||
break;
|
if (!rdp_recv_server_set_keyboard_indicators_pdu(rdp, cs))
|
||||||
|
return -1;
|
||||||
case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DATA_PDU_TYPE_BITMAP_CACHE_ERROR:
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS:
|
case DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS:
|
||||||
break;
|
if (!rdp_recv_server_set_keyboard_ime_status_pdu(rdp, cs))
|
||||||
|
return -1;
|
||||||
case DATA_PDU_TYPE_OFFSCREEN_CACHE_ERROR:
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_SET_ERROR_INFO:
|
case DATA_PDU_TYPE_SET_ERROR_INFO:
|
||||||
@ -647,19 +809,19 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_DRAW_NINEGRID_ERROR:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DATA_PDU_TYPE_DRAW_GDIPLUS_ERROR:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DATA_PDU_TYPE_ARC_STATUS:
|
case DATA_PDU_TYPE_ARC_STATUS:
|
||||||
|
if (!rdp_recv_server_auto_reconnect_status_pdu(rdp, cs))
|
||||||
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_STATUS_INFO:
|
case DATA_PDU_TYPE_STATUS_INFO:
|
||||||
|
if (!rdp_recv_server_status_info_pdu(rdp, cs))
|
||||||
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_PDU_TYPE_MONITOR_LAYOUT:
|
case DATA_PDU_TYPE_MONITOR_LAYOUT:
|
||||||
|
if (!rdp_recv_monitor_layout_pdu(rdp, cs))
|
||||||
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -672,6 +834,34 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s)
|
||||||
|
{
|
||||||
|
UINT16 securityFlags;
|
||||||
|
|
||||||
|
if (!rdp_read_security_header(s, &securityFlags))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (securityFlags & SEC_AUTODETECT_REQ)
|
||||||
|
{
|
||||||
|
/* Server Auto-Detect Request PDU */
|
||||||
|
return rdp_recv_autodetect_packet(rdp, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (securityFlags & SEC_HEARTBEAT)
|
||||||
|
{
|
||||||
|
/* Heartbeat PDU */
|
||||||
|
return rdp_recv_heartbeat_packet(rdp, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (securityFlags & SEC_TRANSPORT_REQ)
|
||||||
|
{
|
||||||
|
/* Initiate Multitransport Request PDU */
|
||||||
|
return rdp_recv_multitransport_packet(rdp, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
|
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
UINT16 type;
|
UINT16 type;
|
||||||
@ -820,12 +1010,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channelId != MCS_GLOBAL_CHANNEL_ID)
|
if (channelId == MCS_GLOBAL_CHANNEL_ID)
|
||||||
{
|
|
||||||
if (!freerdp_channel_process(rdp->instance, s, channelId))
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
while (Stream_GetRemainingLength(s) > 3)
|
while (Stream_GetRemainingLength(s) > 3)
|
||||||
{
|
{
|
||||||
@ -865,6 +1050,15 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
Stream_SetPosition(s, nextPosition);
|
Stream_SetPosition(s, nextPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (channelId == rdp->mcs->message_channel_id)
|
||||||
|
{
|
||||||
|
return rdp_recv_message_channel_pdu(rdp, s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!freerdp_channel_process(rdp->instance, s, channelId))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -909,6 +1103,19 @@ static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
|||||||
int status = 0;
|
int status = 0;
|
||||||
rdpRdp* rdp = (rdpRdp*) extra;
|
rdpRdp* rdp = (rdpRdp*) extra;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At any point in the connection sequence between when all
|
||||||
|
* MCS channels have been joined and when the RDP connection
|
||||||
|
* enters the active state, an auto-detect PDU can be received
|
||||||
|
* on the MCS message channel.
|
||||||
|
*/
|
||||||
|
if ((rdp->state > CONNECTION_STATE_MCS_CHANNEL_JOIN) &&
|
||||||
|
(rdp->state < CONNECTION_STATE_ACTIVE))
|
||||||
|
{
|
||||||
|
if (rdp_client_connect_auto_detect(rdp, s))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (rdp->state)
|
switch (rdp->state)
|
||||||
{
|
{
|
||||||
case CONNECTION_STATE_NEGO:
|
case CONNECTION_STATE_NEGO:
|
||||||
@ -1020,6 +1227,9 @@ rdpRdp* rdp_new(rdpContext* context)
|
|||||||
rdp->nego = nego_new(rdp->transport);
|
rdp->nego = nego_new(rdp->transport);
|
||||||
rdp->mcs = mcs_new(rdp->transport);
|
rdp->mcs = mcs_new(rdp->transport);
|
||||||
rdp->redirection = redirection_new();
|
rdp->redirection = redirection_new();
|
||||||
|
rdp->autodetect = autodetect_new();
|
||||||
|
rdp->heartbeat = heartbeat_new();
|
||||||
|
rdp->multitransport = multitransport_new();
|
||||||
rdp->mppc_dec = mppc_dec_new();
|
rdp->mppc_dec = mppc_dec_new();
|
||||||
rdp->mppc_enc = mppc_enc_new(PROTO_RDP_50);
|
rdp->mppc_enc = mppc_enc_new(PROTO_RDP_50);
|
||||||
}
|
}
|
||||||
@ -1092,6 +1302,9 @@ void rdp_free(rdpRdp* rdp)
|
|||||||
nego_free(rdp->nego);
|
nego_free(rdp->nego);
|
||||||
mcs_free(rdp->mcs);
|
mcs_free(rdp->mcs);
|
||||||
redirection_free(rdp->redirection);
|
redirection_free(rdp->redirection);
|
||||||
|
autodetect_free(rdp->autodetect);
|
||||||
|
heartbeat_free(rdp->heartbeat);
|
||||||
|
multitransport_free(rdp->multitransport);
|
||||||
mppc_dec_free(rdp->mppc_dec);
|
mppc_dec_free(rdp->mppc_dec);
|
||||||
mppc_enc_free(rdp->mppc_enc);
|
mppc_enc_free(rdp->mppc_enc);
|
||||||
free(rdp);
|
free(rdp);
|
||||||
|
@ -34,6 +34,9 @@
|
|||||||
#include "license.h"
|
#include "license.h"
|
||||||
#include "errinfo.h"
|
#include "errinfo.h"
|
||||||
#include "extension.h"
|
#include "extension.h"
|
||||||
|
#include "autodetect.h"
|
||||||
|
#include "heartbeat.h"
|
||||||
|
#include "multitransport.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
@ -51,6 +54,8 @@
|
|||||||
|
|
||||||
/* Security Header Flags */
|
/* Security Header Flags */
|
||||||
#define SEC_EXCHANGE_PKT 0x0001
|
#define SEC_EXCHANGE_PKT 0x0001
|
||||||
|
#define SEC_TRANSPORT_REQ 0x0002
|
||||||
|
#define SEC_TRANSPORT_RSP 0x0004
|
||||||
#define SEC_ENCRYPT 0x0008
|
#define SEC_ENCRYPT 0x0008
|
||||||
#define SEC_RESET_SEQNO 0x0010
|
#define SEC_RESET_SEQNO 0x0010
|
||||||
#define SEC_IGNORE_SEQNO 0x0020
|
#define SEC_IGNORE_SEQNO 0x0020
|
||||||
@ -60,6 +65,9 @@
|
|||||||
#define SEC_LICENSE_ENCRYPT_SC 0x0200
|
#define SEC_LICENSE_ENCRYPT_SC 0x0200
|
||||||
#define SEC_REDIRECTION_PKT 0x0400
|
#define SEC_REDIRECTION_PKT 0x0400
|
||||||
#define SEC_SECURE_CHECKSUM 0x0800
|
#define SEC_SECURE_CHECKSUM 0x0800
|
||||||
|
#define SEC_AUTODETECT_REQ 0x1000
|
||||||
|
#define SEC_AUTODETECT_RSP 0x2000
|
||||||
|
#define SEC_HEARTBEAT 0x4000
|
||||||
#define SEC_FLAGSHI_VALID 0x8000
|
#define SEC_FLAGSHI_VALID 0x8000
|
||||||
|
|
||||||
#define SEC_PKT_CS_MASK (SEC_EXCHANGE_PKT | SEC_INFO_PKT)
|
#define SEC_PKT_CS_MASK (SEC_EXCHANGE_PKT | SEC_INFO_PKT)
|
||||||
@ -131,6 +139,9 @@ struct rdp_rdp
|
|||||||
rdpSettings* settings;
|
rdpSettings* settings;
|
||||||
rdpTransport* transport;
|
rdpTransport* transport;
|
||||||
rdpExtension* extension;
|
rdpExtension* extension;
|
||||||
|
rdpAutoDetect* autodetect;
|
||||||
|
rdpHeartbeat* heartbeat;
|
||||||
|
rdpMultitransport* multitransport;
|
||||||
struct rdp_mppc_dec* mppc_dec;
|
struct rdp_mppc_dec* mppc_dec;
|
||||||
struct rdp_mppc_enc* mppc_enc;
|
struct rdp_mppc_enc* mppc_enc;
|
||||||
struct crypto_rc4_struct* rc4_decrypt_key;
|
struct crypto_rc4_struct* rc4_decrypt_key;
|
||||||
@ -191,6 +202,10 @@ BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channel_id);
|
|||||||
|
|
||||||
int rdp_send_channel_data(rdpRdp* rdp, int channel_id, BYTE* data, int size);
|
int rdp_send_channel_data(rdpRdp* rdp, int channel_id, BYTE* data, int size);
|
||||||
|
|
||||||
|
wStream* rdp_message_channel_pdu_init(rdpRdp* rdp);
|
||||||
|
BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags);
|
||||||
|
int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s);
|
||||||
|
|
||||||
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
|
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
|
||||||
|
|
||||||
void rdp_set_blocking_mode(rdpRdp* rdp, BOOL blocking);
|
void rdp_set_blocking_mode(rdpRdp* rdp, BOOL blocking);
|
||||||
|
@ -234,6 +234,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
|||||||
settings->DisableEncryption = FALSE;
|
settings->DisableEncryption = FALSE;
|
||||||
settings->SaltedChecksum = TRUE;
|
settings->SaltedChecksum = TRUE;
|
||||||
settings->ServerPort = 3389;
|
settings->ServerPort = 3389;
|
||||||
|
settings->GatewayPort = 443;
|
||||||
settings->DesktopResize = TRUE;
|
settings->DesktopResize = TRUE;
|
||||||
settings->ToggleFullscreen = TRUE;
|
settings->ToggleFullscreen = TRUE;
|
||||||
settings->DesktopPosX = 0;
|
settings->DesktopPosX = 0;
|
||||||
@ -248,8 +249,6 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
|||||||
settings->DisableThemes = FALSE;
|
settings->DisableThemes = FALSE;
|
||||||
settings->ConnectionType = CONNECTION_TYPE_LAN;
|
settings->ConnectionType = CONNECTION_TYPE_LAN;
|
||||||
|
|
||||||
settings->AutoReconnectionEnabled = TRUE;
|
|
||||||
|
|
||||||
settings->EncryptionMethods = ENCRYPTION_METHOD_NONE;
|
settings->EncryptionMethods = ENCRYPTION_METHOD_NONE;
|
||||||
settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
|
settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
|
||||||
|
|
||||||
@ -313,6 +312,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
|||||||
settings->DrawGdiPlusEnabled = FALSE;
|
settings->DrawGdiPlusEnabled = FALSE;
|
||||||
|
|
||||||
settings->FrameMarkerCommandEnabled = FALSE;
|
settings->FrameMarkerCommandEnabled = FALSE;
|
||||||
|
settings->SurfaceFrameMarkerEnabled = TRUE;
|
||||||
settings->BitmapCacheV3Enabled = FALSE;
|
settings->BitmapCacheV3Enabled = FALSE;
|
||||||
|
|
||||||
settings->BitmapCacheEnabled = TRUE;
|
settings->BitmapCacheEnabled = TRUE;
|
||||||
@ -379,7 +379,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
|||||||
|
|
||||||
settings->MultifragMaxRequestSize = 0xFFFF;
|
settings->MultifragMaxRequestSize = 0xFFFF;
|
||||||
|
|
||||||
settings->GatewayUseSameCredentials = TRUE;
|
settings->GatewayUseSameCredentials = FALSE;
|
||||||
|
|
||||||
settings->FastPathInput = TRUE;
|
settings->FastPathInput = TRUE;
|
||||||
settings->FastPathOutput = TRUE;
|
settings->FastPathOutput = TRUE;
|
||||||
@ -620,6 +620,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
|||||||
_settings->MstscCookieMode = settings->MstscCookieMode; /* 1152 */
|
_settings->MstscCookieMode = settings->MstscCookieMode; /* 1152 */
|
||||||
_settings->SendPreconnectionPdu = settings->SendPreconnectionPdu; /* 1156 */
|
_settings->SendPreconnectionPdu = settings->SendPreconnectionPdu; /* 1156 */
|
||||||
_settings->IgnoreCertificate = settings->IgnoreCertificate; /* 1408 */
|
_settings->IgnoreCertificate = settings->IgnoreCertificate; /* 1408 */
|
||||||
|
_settings->ExternalCertificateManagement = settings->ExternalCertificateManagement; /* 1415 */
|
||||||
_settings->Workarea = settings->Workarea; /* 1536 */
|
_settings->Workarea = settings->Workarea; /* 1536 */
|
||||||
_settings->Fullscreen = settings->Fullscreen; /* 1537 */
|
_settings->Fullscreen = settings->Fullscreen; /* 1537 */
|
||||||
_settings->GrabKeyboard = settings->GrabKeyboard; /* 1539 */
|
_settings->GrabKeyboard = settings->GrabKeyboard; /* 1539 */
|
||||||
@ -667,6 +668,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
|||||||
_settings->SoundBeepsEnabled = settings->SoundBeepsEnabled; /* 2944 */
|
_settings->SoundBeepsEnabled = settings->SoundBeepsEnabled; /* 2944 */
|
||||||
_settings->SurfaceCommandsEnabled = settings->SurfaceCommandsEnabled; /* 3520 */
|
_settings->SurfaceCommandsEnabled = settings->SurfaceCommandsEnabled; /* 3520 */
|
||||||
_settings->FrameMarkerCommandEnabled = settings->FrameMarkerCommandEnabled; /* 3521 */
|
_settings->FrameMarkerCommandEnabled = settings->FrameMarkerCommandEnabled; /* 3521 */
|
||||||
|
_settings->SurfaceFrameMarkerEnabled = settings->SurfaceFrameMarkerEnabled; /* 3522 */
|
||||||
_settings->RemoteFxOnly = settings->RemoteFxOnly; /* 3648 */
|
_settings->RemoteFxOnly = settings->RemoteFxOnly; /* 3648 */
|
||||||
_settings->RemoteFxCodec = settings->RemoteFxCodec; /* 3649 */
|
_settings->RemoteFxCodec = settings->RemoteFxCodec; /* 3649 */
|
||||||
_settings->RemoteFxImageCodec = settings->RemoteFxImageCodec; /* 3652 */
|
_settings->RemoteFxImageCodec = settings->RemoteFxImageCodec; /* 3652 */
|
||||||
|
@ -67,6 +67,7 @@ void tcp_get_ip_address(rdpTcp * tcp)
|
|||||||
struct sockaddr_in sockaddr;
|
struct sockaddr_in sockaddr;
|
||||||
|
|
||||||
length = sizeof(sockaddr);
|
length = sizeof(sockaddr);
|
||||||
|
ZeroMemory(&sockaddr, length);
|
||||||
|
|
||||||
if (getsockname(tcp->sockfd, (struct sockaddr*) &sockaddr, &length) == 0)
|
if (getsockname(tcp->sockfd, (struct sockaddr*) &sockaddr, &length) == 0)
|
||||||
{
|
{
|
||||||
@ -76,19 +77,12 @@ void tcp_get_ip_address(rdpTcp * tcp)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strncpy(tcp->ip_address, "127.0.0.1", sizeof(tcp->ip_address));
|
strcpy(tcp->ip_address, "127.0.0.1");
|
||||||
}
|
}
|
||||||
|
|
||||||
tcp->ip_address[sizeof(tcp->ip_address) - 1] = 0;
|
|
||||||
|
|
||||||
tcp->settings->IPv6Enabled = 0;
|
tcp->settings->IPv6Enabled = 0;
|
||||||
|
|
||||||
if (tcp->settings->ClientAddress)
|
|
||||||
{
|
|
||||||
free(tcp->settings->ClientAddress);
|
free(tcp->settings->ClientAddress);
|
||||||
tcp->settings->ClientAddress = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tcp->settings->ClientAddress = _strdup(tcp->ip_address);
|
tcp->settings->ClientAddress = _strdup(tcp->ip_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +119,7 @@ void tcp_get_mac_address(rdpTcp * tcp)
|
|||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); */
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); */
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL tcp_connect(rdpTcp* tcp, const char* hostname, UINT16 port)
|
BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port)
|
||||||
{
|
{
|
||||||
UINT32 option_value;
|
UINT32 option_value;
|
||||||
socklen_t option_len;
|
socklen_t option_len;
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
#include <winpr/synch.h>
|
#include <winpr/synch.h>
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
#include <winpr/winsock.h>
|
||||||
|
|
||||||
#ifndef MSG_NOSIGNAL
|
#ifndef MSG_NOSIGNAL
|
||||||
#define MSG_NOSIGNAL 0
|
#define MSG_NOSIGNAL 0
|
||||||
@ -41,14 +42,14 @@ struct rdp_tcp
|
|||||||
int sockfd;
|
int sockfd;
|
||||||
char ip_address[32];
|
char ip_address[32];
|
||||||
BYTE mac_address[6];
|
BYTE mac_address[6];
|
||||||
struct rdp_settings* settings;
|
rdpSettings* settings;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSAEVENT wsa_event;
|
WSAEVENT wsa_event;
|
||||||
#endif
|
#endif
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOL tcp_connect(rdpTcp* tcp, const char* hostname, UINT16 port);
|
BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port);
|
||||||
BOOL tcp_disconnect(rdpTcp* tcp);
|
BOOL tcp_disconnect(rdpTcp* tcp);
|
||||||
int tcp_read(rdpTcp* tcp, BYTE* data, int length);
|
int tcp_read(rdpTcp* tcp, BYTE* data, int length);
|
||||||
int tcp_write(rdpTcp* tcp, BYTE* data, int length);
|
int tcp_write(rdpTcp* tcp, BYTE* data, int length);
|
||||||
|
@ -29,10 +29,10 @@
|
|||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
#include <winpr/synch.h>
|
#include <winpr/synch.h>
|
||||||
#include <winpr/print.h>
|
#include <winpr/print.h>
|
||||||
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
#include <freerdp/error.h>
|
#include <freerdp/error.h>
|
||||||
#include <freerdp/utils/tcp.h>
|
#include <freerdp/utils/tcp.h>
|
||||||
#include <winpr/stream.h>
|
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -80,7 +80,7 @@ BOOL transport_disconnect(rdpTransport* transport)
|
|||||||
if (transport->layer == TRANSPORT_LAYER_TLS)
|
if (transport->layer == TRANSPORT_LAYER_TLS)
|
||||||
status &= tls_disconnect(transport->TlsIn);
|
status &= tls_disconnect(transport->TlsIn);
|
||||||
|
|
||||||
if (transport->layer == TRANSPORT_LAYER_TSG || transport->layer == TRANSPORT_LAYER_TSG_TLS)
|
if ((transport->layer == TRANSPORT_LAYER_TSG) || (transport->layer == TRANSPORT_LAYER_TSG_TLS))
|
||||||
{
|
{
|
||||||
tsg_disconnect(transport->tsg);
|
tsg_disconnect(transport->tsg);
|
||||||
}
|
}
|
||||||
@ -222,7 +222,13 @@ BOOL transport_connect_tls(rdpTransport* transport)
|
|||||||
|
|
||||||
transport->layer = TRANSPORT_LAYER_TSG_TLS;
|
transport->layer = TRANSPORT_LAYER_TSG_TLS;
|
||||||
|
|
||||||
if (tls_connect(transport->TsgTls) != TRUE)
|
transport->TsgTls->hostname = transport->settings->ServerHostname;
|
||||||
|
transport->TsgTls->port = transport->settings->ServerPort;
|
||||||
|
|
||||||
|
if (transport->TsgTls->port == 0)
|
||||||
|
transport->TsgTls->port = 3389;
|
||||||
|
|
||||||
|
if (!tls_connect(transport->TsgTls))
|
||||||
{
|
{
|
||||||
if (!connectErrorCode)
|
if (!connectErrorCode)
|
||||||
connectErrorCode = TLSCONNECTERROR;
|
connectErrorCode = TLSCONNECTERROR;
|
||||||
@ -236,16 +242,22 @@ BOOL transport_connect_tls(rdpTransport* transport)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transport->TlsIn == NULL)
|
if (!transport->TlsIn)
|
||||||
transport->TlsIn = tls_new(transport->settings);
|
transport->TlsIn = tls_new(transport->settings);
|
||||||
|
|
||||||
if (transport->TlsOut == NULL)
|
if (!transport->TlsOut)
|
||||||
transport->TlsOut = transport->TlsIn;
|
transport->TlsOut = transport->TlsIn;
|
||||||
|
|
||||||
transport->layer = TRANSPORT_LAYER_TLS;
|
transport->layer = TRANSPORT_LAYER_TLS;
|
||||||
transport->TlsIn->sockfd = transport->TcpIn->sockfd;
|
transport->TlsIn->sockfd = transport->TcpIn->sockfd;
|
||||||
|
|
||||||
if (tls_connect(transport->TlsIn) != TRUE)
|
transport->TlsIn->hostname = transport->settings->ServerHostname;
|
||||||
|
transport->TlsIn->port = transport->settings->ServerPort;
|
||||||
|
|
||||||
|
if (transport->TlsIn->port == 0)
|
||||||
|
transport->TlsIn->port = 3389;
|
||||||
|
|
||||||
|
if (!tls_connect(transport->TlsIn))
|
||||||
{
|
{
|
||||||
if (!connectErrorCode)
|
if (!connectErrorCode)
|
||||||
connectErrorCode = TLSCONNECTERROR;
|
connectErrorCode = TLSCONNECTERROR;
|
||||||
@ -268,18 +280,18 @@ BOOL transport_connect_nla(rdpTransport* transport)
|
|||||||
freerdp* instance;
|
freerdp* instance;
|
||||||
rdpSettings* settings;
|
rdpSettings* settings;
|
||||||
|
|
||||||
|
settings = transport->settings;
|
||||||
|
instance = (freerdp*) settings->instance;
|
||||||
|
|
||||||
if (!transport_connect_tls(transport))
|
if (!transport_connect_tls(transport))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Network Level Authentication */
|
/* Network Level Authentication */
|
||||||
|
|
||||||
if (transport->settings->Authentication != TRUE)
|
if (!settings->Authentication)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
settings = transport->settings;
|
if (!transport->credssp)
|
||||||
instance = (freerdp*) settings->instance;
|
|
||||||
|
|
||||||
if (transport->credssp == NULL)
|
|
||||||
transport->credssp = credssp_new(instance, transport, settings);
|
transport->credssp = credssp_new(instance, transport, settings);
|
||||||
|
|
||||||
if (credssp_authenticate(transport->credssp) < 0)
|
if (credssp_authenticate(transport->credssp) < 0)
|
||||||
@ -296,6 +308,7 @@ BOOL transport_connect_nla(rdpTransport* transport)
|
|||||||
}
|
}
|
||||||
|
|
||||||
credssp_free(transport->credssp);
|
credssp_free(transport->credssp);
|
||||||
|
transport->credssp = NULL;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -308,20 +321,30 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
|
|||||||
transport->tsg = tsg;
|
transport->tsg = tsg;
|
||||||
transport->SplitInputOutput = TRUE;
|
transport->SplitInputOutput = TRUE;
|
||||||
|
|
||||||
if (transport->TlsIn == NULL)
|
if (!transport->TlsIn)
|
||||||
transport->TlsIn = tls_new(transport->settings);
|
transport->TlsIn = tls_new(transport->settings);
|
||||||
|
|
||||||
transport->TlsIn->sockfd = transport->TcpIn->sockfd;
|
transport->TlsIn->sockfd = transport->TcpIn->sockfd;
|
||||||
|
transport->TlsIn->hostname = transport->settings->GatewayHostname;
|
||||||
|
transport->TlsIn->port = transport->settings->GatewayPort;
|
||||||
|
|
||||||
if (transport->TlsOut == NULL)
|
if (transport->TlsIn->port == 0)
|
||||||
|
transport->TlsIn->port = 443;
|
||||||
|
|
||||||
|
if (!transport->TlsOut)
|
||||||
transport->TlsOut = tls_new(transport->settings);
|
transport->TlsOut = tls_new(transport->settings);
|
||||||
|
|
||||||
transport->TlsOut->sockfd = transport->TcpOut->sockfd;
|
transport->TlsOut->sockfd = transport->TcpOut->sockfd;
|
||||||
|
transport->TlsOut->hostname = transport->settings->GatewayHostname;
|
||||||
|
transport->TlsOut->port = transport->settings->GatewayPort;
|
||||||
|
|
||||||
if (tls_connect(transport->TlsIn) != TRUE)
|
if (transport->TlsOut->port == 0)
|
||||||
|
transport->TlsOut->port = 443;
|
||||||
|
|
||||||
|
if (!tls_connect(transport->TlsIn))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (tls_connect(transport->TlsOut) != TRUE)
|
if (!tls_connect(transport->TlsOut))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!tsg_connect(tsg, hostname, port))
|
if (!tsg_connect(tsg, hostname, port))
|
||||||
@ -342,10 +365,10 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
|
|||||||
transport->layer = TRANSPORT_LAYER_TSG;
|
transport->layer = TRANSPORT_LAYER_TSG;
|
||||||
transport->TcpOut = tcp_new(settings);
|
transport->TcpOut = tcp_new(settings);
|
||||||
|
|
||||||
status = tcp_connect(transport->TcpIn, settings->GatewayHostname, 443);
|
status = tcp_connect(transport->TcpIn, settings->GatewayHostname, settings->GatewayPort);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
status = tcp_connect(transport->TcpOut, settings->GatewayHostname, 443);
|
status = tcp_connect(transport->TcpOut, settings->GatewayHostname, settings->GatewayPort);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
status = transport_tsg_connect(transport, hostname, port);
|
status = transport_tsg_connect(transport, hostname, port);
|
||||||
@ -381,16 +404,16 @@ BOOL transport_accept_rdp(rdpTransport* transport)
|
|||||||
|
|
||||||
BOOL transport_accept_tls(rdpTransport* transport)
|
BOOL transport_accept_tls(rdpTransport* transport)
|
||||||
{
|
{
|
||||||
if (transport->TlsIn == NULL)
|
if (!transport->TlsIn)
|
||||||
transport->TlsIn = tls_new(transport->settings);
|
transport->TlsIn = tls_new(transport->settings);
|
||||||
|
|
||||||
if (transport->TlsOut == NULL)
|
if (!transport->TlsOut)
|
||||||
transport->TlsOut = transport->TlsIn;
|
transport->TlsOut = transport->TlsIn;
|
||||||
|
|
||||||
transport->layer = TRANSPORT_LAYER_TLS;
|
transport->layer = TRANSPORT_LAYER_TLS;
|
||||||
transport->TlsIn->sockfd = transport->TcpIn->sockfd;
|
transport->TlsIn->sockfd = transport->TcpIn->sockfd;
|
||||||
|
|
||||||
if (tls_accept(transport->TlsIn, transport->settings->CertificateFile, transport->settings->PrivateKeyFile) != TRUE)
|
if (!tls_accept(transport->TlsIn, transport->settings->CertificateFile, transport->settings->PrivateKeyFile))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -401,27 +424,27 @@ BOOL transport_accept_nla(rdpTransport* transport)
|
|||||||
freerdp* instance;
|
freerdp* instance;
|
||||||
rdpSettings* settings;
|
rdpSettings* settings;
|
||||||
|
|
||||||
if (transport->TlsIn == NULL)
|
settings = transport->settings;
|
||||||
|
instance = (freerdp*) settings->instance;
|
||||||
|
|
||||||
|
if (!transport->TlsIn)
|
||||||
transport->TlsIn = tls_new(transport->settings);
|
transport->TlsIn = tls_new(transport->settings);
|
||||||
|
|
||||||
if (transport->TlsOut == NULL)
|
if (!transport->TlsOut)
|
||||||
transport->TlsOut = transport->TlsIn;
|
transport->TlsOut = transport->TlsIn;
|
||||||
|
|
||||||
transport->layer = TRANSPORT_LAYER_TLS;
|
transport->layer = TRANSPORT_LAYER_TLS;
|
||||||
transport->TlsIn->sockfd = transport->TcpIn->sockfd;
|
transport->TlsIn->sockfd = transport->TcpIn->sockfd;
|
||||||
|
|
||||||
if (tls_accept(transport->TlsIn, transport->settings->CertificateFile, transport->settings->PrivateKeyFile) != TRUE)
|
if (!tls_accept(transport->TlsIn, transport->settings->CertificateFile, transport->settings->PrivateKeyFile))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Network Level Authentication */
|
/* Network Level Authentication */
|
||||||
|
|
||||||
if (transport->settings->Authentication != TRUE)
|
if (!settings->Authentication)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
settings = transport->settings;
|
if (!transport->credssp)
|
||||||
instance = (freerdp*) settings->instance;
|
|
||||||
|
|
||||||
if (transport->credssp == NULL)
|
|
||||||
transport->credssp = credssp_new(instance, transport, settings);
|
transport->credssp = credssp_new(instance, transport, settings);
|
||||||
|
|
||||||
if (credssp_authenticate(transport->credssp) < 0)
|
if (credssp_authenticate(transport->credssp) < 0)
|
||||||
@ -429,6 +452,9 @@ BOOL transport_accept_nla(rdpTransport* transport)
|
|||||||
fprintf(stderr, "client authentication failure\n");
|
fprintf(stderr, "client authentication failure\n");
|
||||||
credssp_free(transport->credssp);
|
credssp_free(transport->credssp);
|
||||||
transport->credssp = NULL;
|
transport->credssp = NULL;
|
||||||
|
|
||||||
|
tls_set_alert_code(transport->TlsIn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +465,7 @@ BOOL transport_accept_nla(rdpTransport* transport)
|
|||||||
|
|
||||||
BOOL nla_verify_header(wStream* s)
|
BOOL nla_verify_header(wStream* s)
|
||||||
{
|
{
|
||||||
if ((s->pointer[0] == 0x30) && (s->pointer[1] & 0x80))
|
if ((Stream_Pointer(s)[0] == 0x30) && (Stream_Pointer(s)[1] & 0x80))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -449,17 +475,17 @@ UINT32 nla_read_header(wStream* s)
|
|||||||
{
|
{
|
||||||
UINT32 length = 0;
|
UINT32 length = 0;
|
||||||
|
|
||||||
if (s->pointer[1] & 0x80)
|
if (Stream_Pointer(s)[1] & 0x80)
|
||||||
{
|
{
|
||||||
if ((s->pointer[1] & ~(0x80)) == 1)
|
if ((Stream_Pointer(s)[1] & ~(0x80)) == 1)
|
||||||
{
|
{
|
||||||
length = s->pointer[2];
|
length = Stream_Pointer(s)[2];
|
||||||
length += 3;
|
length += 3;
|
||||||
Stream_Seek(s, 3);
|
Stream_Seek(s, 3);
|
||||||
}
|
}
|
||||||
else if ((s->pointer[1] & ~(0x80)) == 2)
|
else if ((Stream_Pointer(s)[1] & ~(0x80)) == 2)
|
||||||
{
|
{
|
||||||
length = (s->pointer[2] << 8) | s->pointer[3];
|
length = (Stream_Pointer(s)[2] << 8) | Stream_Pointer(s)[3];
|
||||||
length += 4;
|
length += 4;
|
||||||
Stream_Seek(s, 4);
|
Stream_Seek(s, 4);
|
||||||
}
|
}
|
||||||
@ -470,7 +496,7 @@ UINT32 nla_read_header(wStream* s)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
length = s->pointer[1];
|
length = Stream_Pointer(s)[1];
|
||||||
length += 2;
|
length += 2;
|
||||||
Stream_Seek(s, 2);
|
Stream_Seek(s, 2);
|
||||||
}
|
}
|
||||||
@ -482,11 +508,11 @@ UINT32 nla_header_length(wStream* s)
|
|||||||
{
|
{
|
||||||
UINT32 length = 0;
|
UINT32 length = 0;
|
||||||
|
|
||||||
if (s->pointer[1] & 0x80)
|
if (Stream_Pointer(s)[1] & 0x80)
|
||||||
{
|
{
|
||||||
if ((s->pointer[1] & ~(0x80)) == 1)
|
if ((Stream_Pointer(s)[1] & ~(0x80)) == 1)
|
||||||
length = 3;
|
length = 3;
|
||||||
else if ((s->pointer[1] & ~(0x80)) == 2)
|
else if ((Stream_Pointer(s)[1] & ~(0x80)) == 2)
|
||||||
length = 4;
|
length = 4;
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Error reading TSRequest!\n");
|
fprintf(stderr, "Error reading TSRequest!\n");
|
||||||
@ -499,7 +525,7 @@ UINT32 nla_header_length(wStream* s)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int transport_read_layer(rdpTransport* transport, UINT8* data, int bytes)
|
int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)
|
||||||
{
|
{
|
||||||
int read = 0;
|
int read = 0;
|
||||||
int status = -1;
|
int status = -1;
|
||||||
@ -542,10 +568,12 @@ int transport_read_layer(rdpTransport* transport, UINT8* data, int bytes)
|
|||||||
int transport_read(rdpTransport* transport, wStream* s)
|
int transport_read(rdpTransport* transport, wStream* s)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
int position;
|
||||||
int pduLength;
|
int pduLength;
|
||||||
int streamPosition;
|
BYTE header[4];
|
||||||
int transport_status;
|
int transport_status;
|
||||||
|
|
||||||
|
position = 0;
|
||||||
pduLength = 0;
|
pduLength = 0;
|
||||||
transport_status = 0;
|
transport_status = 0;
|
||||||
|
|
||||||
@ -556,54 +584,57 @@ int transport_read(rdpTransport* transport, wStream* s)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* first check if we have header */
|
/* first check if we have header */
|
||||||
streamPosition = Stream_GetPosition(s);
|
position = Stream_GetPosition(s);
|
||||||
|
|
||||||
if (streamPosition < 4)
|
if (position < 4)
|
||||||
{
|
{
|
||||||
status = transport_read_layer(transport, Stream_Buffer(s) + streamPosition, 4 - streamPosition);
|
status = transport_read_layer(transport, Stream_Buffer(s) + position, 4 - position);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
transport_status += status;
|
transport_status += status;
|
||||||
|
|
||||||
if ((status + streamPosition) < 4)
|
if ((status + position) < 4)
|
||||||
return transport_status;
|
return transport_status;
|
||||||
|
|
||||||
streamPosition += status;
|
position += status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CopyMemory(header, Stream_Buffer(s), 4); /* peek at first 4 bytes */
|
||||||
|
|
||||||
/* if header is present, read in exactly one PDU */
|
/* if header is present, read in exactly one PDU */
|
||||||
if (s->buffer[0] == 0x03)
|
if (header[0] == 0x03)
|
||||||
{
|
{
|
||||||
/* TPKT header */
|
/* TPKT header */
|
||||||
|
|
||||||
pduLength = (s->buffer[2] << 8) | s->buffer[3];
|
pduLength = (header[2] << 8) | header[3];
|
||||||
}
|
}
|
||||||
else if (s->buffer[0] == 0x30)
|
else if (header[0] == 0x30)
|
||||||
{
|
{
|
||||||
/* TSRequest (NLA) */
|
/* TSRequest (NLA) */
|
||||||
|
|
||||||
if (s->buffer[1] & 0x80)
|
if (header[1] & 0x80)
|
||||||
{
|
{
|
||||||
if ((s->buffer[1] & ~(0x80)) == 1)
|
if ((header[1] & ~(0x80)) == 1)
|
||||||
{
|
{
|
||||||
pduLength = s->buffer[2];
|
pduLength = header[2];
|
||||||
pduLength += 3;
|
pduLength += 3;
|
||||||
}
|
}
|
||||||
else if ((s->buffer[1] & ~(0x80)) == 2)
|
else if ((header[1] & ~(0x80)) == 2)
|
||||||
{
|
{
|
||||||
pduLength = (s->buffer[2] << 8) | s->buffer[3];
|
pduLength = (header[2] << 8) | header[3];
|
||||||
pduLength += 4;
|
pduLength += 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error reading TSRequest!\n");
|
fprintf(stderr, "Error reading TSRequest!\n");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pduLength = s->buffer[1];
|
pduLength = header[1];
|
||||||
pduLength += 2;
|
pduLength += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -611,13 +642,13 @@ int transport_read(rdpTransport* transport, wStream* s)
|
|||||||
{
|
{
|
||||||
/* Fast-Path Header */
|
/* Fast-Path Header */
|
||||||
|
|
||||||
if (s->buffer[1] & 0x80)
|
if (header[1] & 0x80)
|
||||||
pduLength = ((s->buffer[1] & 0x7F) << 8) | s->buffer[2];
|
pduLength = ((header[1] & 0x7F) << 8) | header[2];
|
||||||
else
|
else
|
||||||
pduLength = s->buffer[1];
|
pduLength = header[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
status = transport_read_layer(transport, Stream_Buffer(s) + streamPosition, pduLength - streamPosition);
|
status = transport_read_layer(transport, Stream_Buffer(s) + position, pduLength - position);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
@ -626,14 +657,14 @@ int transport_read(rdpTransport* transport, wStream* s)
|
|||||||
|
|
||||||
#ifdef WITH_DEBUG_TRANSPORT
|
#ifdef WITH_DEBUG_TRANSPORT
|
||||||
/* dump when whole PDU is read */
|
/* dump when whole PDU is read */
|
||||||
if (streamPosition + status >= pduLength)
|
if (position + status >= pduLength)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Local < Remote\n");
|
fprintf(stderr, "Local < Remote\n");
|
||||||
winpr_HexDump(Stream_Buffer(s), pduLength);
|
winpr_HexDump(Stream_Buffer(s), pduLength);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (streamPosition + status >= pduLength)
|
if (position + status >= pduLength)
|
||||||
{
|
{
|
||||||
WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);
|
WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);
|
||||||
}
|
}
|
||||||
@ -660,7 +691,7 @@ int transport_write(rdpTransport* transport, wStream* s)
|
|||||||
int length;
|
int length;
|
||||||
int status = -1;
|
int status = -1;
|
||||||
|
|
||||||
WaitForSingleObject(transport->WriteMutex, INFINITE);
|
EnterCriticalSection(&(transport->WriteLock));
|
||||||
|
|
||||||
length = Stream_GetPosition(s);
|
length = Stream_GetPosition(s);
|
||||||
Stream_SetPosition(s, 0);
|
Stream_SetPosition(s, 0);
|
||||||
@ -725,7 +756,7 @@ int transport_write(rdpTransport* transport, wStream* s)
|
|||||||
if (s->pool)
|
if (s->pool)
|
||||||
Stream_Release(s);
|
Stream_Release(s);
|
||||||
|
|
||||||
ReleaseMutex(transport->WriteMutex);
|
LeaveCriticalSection(&(transport->WriteLock));
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -802,7 +833,7 @@ int transport_check_fds(rdpTransport* transport)
|
|||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
int status;
|
int status;
|
||||||
UINT16 length;
|
int length;
|
||||||
int recv_status;
|
int recv_status;
|
||||||
wStream* received;
|
wStream* received;
|
||||||
|
|
||||||
@ -1041,8 +1072,8 @@ rdpTransport* transport_new(rdpSettings* settings)
|
|||||||
|
|
||||||
transport->blocking = TRUE;
|
transport->blocking = TRUE;
|
||||||
|
|
||||||
transport->ReadMutex = CreateMutex(NULL, FALSE, NULL);
|
InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000);
|
||||||
transport->WriteMutex = CreateMutex(NULL, FALSE, NULL);
|
InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000);
|
||||||
|
|
||||||
transport->layer = TRANSPORT_LAYER_TCP;
|
transport->layer = TRANSPORT_LAYER_TCP;
|
||||||
}
|
}
|
||||||
@ -1056,8 +1087,17 @@ void transport_free(rdpTransport* transport)
|
|||||||
{
|
{
|
||||||
if (transport->async)
|
if (transport->async)
|
||||||
{
|
{
|
||||||
assert(!transport->thread);
|
if (transport->stopEvent)
|
||||||
assert(!transport->stopEvent);
|
{
|
||||||
|
SetEvent(transport->stopEvent);
|
||||||
|
WaitForSingleObject(transport->thread, INFINITE);
|
||||||
|
|
||||||
|
CloseHandle(transport->thread);
|
||||||
|
CloseHandle(transport->stopEvent);
|
||||||
|
|
||||||
|
transport->thread = NULL;
|
||||||
|
transport->stopEvent = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transport->ReceiveBuffer)
|
if (transport->ReceiveBuffer)
|
||||||
@ -1089,8 +1129,8 @@ void transport_free(rdpTransport* transport)
|
|||||||
tsg_free(transport->tsg);
|
tsg_free(transport->tsg);
|
||||||
transport->tsg = NULL;
|
transport->tsg = NULL;
|
||||||
|
|
||||||
CloseHandle(transport->ReadMutex);
|
DeleteCriticalSection(&(transport->ReadLock));
|
||||||
CloseHandle(transport->WriteMutex);
|
DeleteCriticalSection(&(transport->WriteLock));
|
||||||
|
|
||||||
free(transport);
|
free(transport);
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,8 @@ struct rdp_transport
|
|||||||
HANDLE stopEvent;
|
HANDLE stopEvent;
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
BOOL async;
|
BOOL async;
|
||||||
HANDLE ReadMutex;
|
CRITICAL_SECTION ReadLock;
|
||||||
HANDLE WriteMutex;
|
CRITICAL_SECTION WriteLock;
|
||||||
wLog* log;
|
wLog* log;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user