Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
26
third_party/FreeRDP/client/common/test/CMakeLists.txt
vendored
Normal file
26
third_party/FreeRDP/client/common/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
set(MODULE_NAME "TestClient")
|
||||
set(MODULE_PREFIX "TEST_CLIENT")
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS TestClientRdpFile.c TestClientChannels.c TestClientCmdLine.c)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
target_compile_definitions(${MODULE_NAME} PRIVATE TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client freerdp)
|
||||
|
||||
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/Client/Test")
|
||||
87
third_party/FreeRDP/client/common/test/TestClientChannels.c
vendored
Normal file
87
third_party/FreeRDP/client/common/test/TestClientChannels.c
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/channels/rdpsnd.h>
|
||||
|
||||
int TestClientChannels(int argc, char* argv[])
|
||||
{
|
||||
DWORD dwFlags = 0;
|
||||
FREERDP_ADDIN** ppAddins = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
dwFlags = FREERDP_ADDIN_DYNAMIC;
|
||||
|
||||
printf("Enumerate all\n");
|
||||
ppAddins = freerdp_channels_list_addins(nullptr, nullptr, nullptr, dwFlags);
|
||||
|
||||
for (size_t index = 0; ppAddins[index] != nullptr; index++)
|
||||
{
|
||||
FREERDP_ADDIN* pAddin = ppAddins[index];
|
||||
|
||||
printf("Addin: Name: %s Subsystem: %s Type: %s\n", pAddin->cName, pAddin->cSubsystem,
|
||||
pAddin->cType);
|
||||
}
|
||||
|
||||
freerdp_channels_addin_list_free(ppAddins);
|
||||
|
||||
printf("Enumerate rdpsnd\n");
|
||||
ppAddins = freerdp_channels_list_addins(RDPSND_CHANNEL_NAME, nullptr, nullptr, dwFlags);
|
||||
|
||||
for (size_t index = 0; ppAddins[index] != nullptr; index++)
|
||||
{
|
||||
FREERDP_ADDIN* pAddin = ppAddins[index];
|
||||
|
||||
printf("Addin: Name: %s Subsystem: %s Type: %s\n", pAddin->cName, pAddin->cSubsystem,
|
||||
pAddin->cType);
|
||||
}
|
||||
|
||||
freerdp_channels_addin_list_free(ppAddins);
|
||||
|
||||
#if defined(CHANNEL_TSMF_CLIENT)
|
||||
printf("Enumerate tsmf video\n");
|
||||
ppAddins = freerdp_channels_list_addins("tsmf", nullptr, "video", dwFlags);
|
||||
|
||||
for (size_t index = 0; ppAddins[index] != nullptr; index++)
|
||||
{
|
||||
FREERDP_ADDIN* pAddin = ppAddins[index];
|
||||
|
||||
printf("Addin: Name: %s Subsystem: %s Type: %s\n", pAddin->cName, pAddin->cSubsystem,
|
||||
pAddin->cType);
|
||||
}
|
||||
|
||||
freerdp_channels_addin_list_free(ppAddins);
|
||||
#endif
|
||||
|
||||
ppAddins = freerdp_channels_list_addins("unknown", nullptr, nullptr, dwFlags);
|
||||
|
||||
for (size_t index = 0; ppAddins[index] != nullptr; index++)
|
||||
{
|
||||
FREERDP_ADDIN* pAddin = ppAddins[index];
|
||||
|
||||
printf("Addin: Name: %s Subsystem: %s Type: %s\n", pAddin->cName, pAddin->cSubsystem,
|
||||
pAddin->cType);
|
||||
}
|
||||
|
||||
freerdp_channels_addin_list_free(ppAddins);
|
||||
|
||||
printf("Enumerate static addins\n");
|
||||
|
||||
dwFlags = FREERDP_ADDIN_STATIC;
|
||||
ppAddins = freerdp_channels_list_addins(nullptr, nullptr, nullptr, dwFlags);
|
||||
|
||||
for (size_t index = 0; ppAddins[index] != nullptr; index++)
|
||||
{
|
||||
FREERDP_ADDIN* pAddin = ppAddins[index];
|
||||
|
||||
printf("Addin: Name: %s Subsystem: %s Type: %s\n", pAddin->cName, pAddin->cSubsystem,
|
||||
pAddin->cType);
|
||||
}
|
||||
|
||||
freerdp_channels_addin_list_free(ppAddins);
|
||||
|
||||
return 0;
|
||||
}
|
||||
263
third_party/FreeRDP/client/common/test/TestClientCmdLine.c
vendored
Normal file
263
third_party/FreeRDP/client/common/test/TestClientCmdLine.c
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
#include <freerdp/client.h>
|
||||
#include <freerdp/client/cmdline.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <winpr/cmdline.h>
|
||||
#include <winpr/spec.h>
|
||||
#include <winpr/strlst.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
typedef BOOL (*validate_settings_pr)(rdpSettings* settings);
|
||||
|
||||
#define printref() printf("%s:%d: in function %-40s:", __FILE__, __LINE__, __func__)
|
||||
|
||||
#define TEST_ERROR(format, ...) \
|
||||
do \
|
||||
{ \
|
||||
(void)fprintf(stderr, format, ##__VA_ARGS__); \
|
||||
printref(); \
|
||||
(void)printf(format, ##__VA_ARGS__); \
|
||||
(void)fflush(stdout); \
|
||||
} while (0)
|
||||
|
||||
#define TEST_FAILURE(format, ...) \
|
||||
do \
|
||||
{ \
|
||||
printref(); \
|
||||
(void)printf(" FAILURE "); \
|
||||
(void)printf(format, ##__VA_ARGS__); \
|
||||
(void)fflush(stdout); \
|
||||
} while (0)
|
||||
|
||||
static void print_test_title(int argc, char** argv)
|
||||
{
|
||||
printf("Running test:");
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
printf(" %s", argv[i]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static inline BOOL testcase(const char* name, char** argv, size_t argc, int expected_return,
|
||||
validate_settings_pr validate_settings)
|
||||
{
|
||||
int status = 0;
|
||||
BOOL valid_settings = TRUE;
|
||||
rdpSettings* settings = freerdp_settings_new(0);
|
||||
|
||||
WINPR_ASSERT(argc <= INT_MAX);
|
||||
|
||||
print_test_title((int)argc, argv);
|
||||
|
||||
if (!settings)
|
||||
{
|
||||
TEST_ERROR("Test %s could not allocate settings!\n", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = freerdp_client_settings_parse_command_line(settings, (int)argc, argv, FALSE);
|
||||
|
||||
if (validate_settings)
|
||||
{
|
||||
valid_settings = validate_settings(settings);
|
||||
}
|
||||
|
||||
freerdp_settings_free(settings);
|
||||
|
||||
if (status == expected_return)
|
||||
{
|
||||
if (!valid_settings)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_FAILURE("Expected status %d, got status %d\n", expected_return, status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define DRIVE_REDIRECT_PATH "c:\\Windows"
|
||||
#else
|
||||
#define DRIVE_REDIRECT_PATH "/tmp"
|
||||
#endif
|
||||
|
||||
static BOOL check_settings_smartcard_no_redirection(rdpSettings* settings)
|
||||
{
|
||||
BOOL result = TRUE;
|
||||
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_RedirectSmartCards))
|
||||
{
|
||||
TEST_FAILURE("Expected RedirectSmartCards = FALSE, but RedirectSmartCards = TRUE!\n");
|
||||
result = FALSE;
|
||||
}
|
||||
|
||||
if (freerdp_device_collection_find_type(settings, RDPDR_DTYP_SMARTCARD))
|
||||
{
|
||||
TEST_FAILURE("Expected no SMARTCARD device, but found at least one!\n");
|
||||
result = FALSE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int expected_status;
|
||||
validate_settings_pr validate_settings;
|
||||
const char* command_line[128];
|
||||
struct
|
||||
{
|
||||
int index;
|
||||
const char* expected_value;
|
||||
} modified_arguments[8];
|
||||
} test;
|
||||
|
||||
// NOLINTBEGIN(bugprone-suspicious-missing-comma)
|
||||
static const test tests[] = {
|
||||
{ COMMAND_LINE_STATUS_PRINT_HELP,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "--help", nullptr },
|
||||
{ { 0 } } },
|
||||
{ COMMAND_LINE_STATUS_PRINT_HELP,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/help", nullptr },
|
||||
{ { 0 } } },
|
||||
{ COMMAND_LINE_STATUS_PRINT_HELP,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "-help", nullptr },
|
||||
{ { 0 } } },
|
||||
{ COMMAND_LINE_STATUS_PRINT_VERSION,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "--version", nullptr },
|
||||
{ { 0 } } },
|
||||
{ COMMAND_LINE_STATUS_PRINT_VERSION,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/version", nullptr },
|
||||
{ { 0 } } },
|
||||
{ COMMAND_LINE_STATUS_PRINT_VERSION,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "-version", nullptr },
|
||||
{ { 0 } } },
|
||||
{ 0,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "-v", "test.freerdp.com", nullptr },
|
||||
{ { 0 } } },
|
||||
{ 0,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "--v", "test.freerdp.com", nullptr },
|
||||
{ { 0 } } },
|
||||
{ 0,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/v:test.freerdp.com", nullptr },
|
||||
{ { 0 } } },
|
||||
{ 0,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/sound", "/drive:media," DRIVE_REDIRECT_PATH, "/v:test.freerdp.com",
|
||||
nullptr },
|
||||
{ { 0 } } },
|
||||
{ 0,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "-u", "test", "-p", "test", "-v", "test.freerdp.com", nullptr },
|
||||
{ { 4, "****" }, { 0 } } },
|
||||
{ 0,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/u:test", "/p:test", "/v:test.freerdp.com", nullptr },
|
||||
{ { 2, "/p:****" }, { 0 } } },
|
||||
{ COMMAND_LINE_ERROR_NO_KEYWORD,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "-invalid", nullptr },
|
||||
{ { 0 } } },
|
||||
{ COMMAND_LINE_ERROR_NO_KEYWORD,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "--invalid", nullptr },
|
||||
{ { 0 } } },
|
||||
#if defined(WITH_FREERDP_DEPRECATED_CMDLINE)
|
||||
{ COMMAND_LINE_STATUS_PRINT,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/kbd-list", 0 },
|
||||
{ { 0 } } },
|
||||
{ COMMAND_LINE_STATUS_PRINT,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/monitor-list", 0 },
|
||||
{ { 0 } } },
|
||||
#endif
|
||||
{ COMMAND_LINE_STATUS_PRINT,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/list:kbd", nullptr },
|
||||
{ { 0 } } },
|
||||
{ COMMAND_LINE_STATUS_PRINT,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/list:monitor", nullptr },
|
||||
{ { 0 } } },
|
||||
{ 0,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/sound", "/drive:media:" DRIVE_REDIRECT_PATH, "/v:test.freerdp.com",
|
||||
nullptr },
|
||||
{ { 0 } } },
|
||||
{ 0,
|
||||
check_settings_smartcard_no_redirection,
|
||||
{ "testfreerdp", "/sound", "/drive:media,/foo/bar/blabla", "/v:test.freerdp.com", nullptr },
|
||||
{ { 0 } } },
|
||||
};
|
||||
// NOLINTEND(bugprone-suspicious-missing-comma)
|
||||
|
||||
static void check_modified_arguments(const test* test, char** command_line, int* rc)
|
||||
{
|
||||
const char* expected_argument = nullptr;
|
||||
|
||||
for (int k = 0; (expected_argument = test->modified_arguments[k].expected_value); k++)
|
||||
{
|
||||
int index = test->modified_arguments[k].index;
|
||||
char* actual_argument = command_line[index];
|
||||
|
||||
if (0 != strcmp(actual_argument, expected_argument))
|
||||
{
|
||||
printref();
|
||||
printf("Failure: overridden argument %d is %s but it should be %s\n", index,
|
||||
actual_argument, expected_argument);
|
||||
(void)fflush(stdout);
|
||||
*rc = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int TestClientCmdLine(int argc, char* argv[])
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
for (size_t i = 0; i < ARRAYSIZE(tests); i++)
|
||||
{
|
||||
const test* current = &tests[i];
|
||||
int failure = 0;
|
||||
char** command_line = string_list_copy(current->command_line);
|
||||
|
||||
const int len = string_list_length((const char* const*)command_line);
|
||||
if (!testcase(__func__, command_line, WINPR_ASSERTING_INT_CAST(size_t, len),
|
||||
current->expected_status, current->validate_settings))
|
||||
{
|
||||
TEST_FAILURE("parsing arguments.\n");
|
||||
failure = 1;
|
||||
}
|
||||
|
||||
check_modified_arguments(current, command_line, &failure);
|
||||
|
||||
if (failure)
|
||||
{
|
||||
string_list_print(stdout, (const char* const*)command_line);
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
string_list_free(command_line);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
838
third_party/FreeRDP/client/common/test/TestClientRdpFile.c
vendored
Normal file
838
third_party/FreeRDP/client/common/test/TestClientRdpFile.c
vendored
Normal file
@@ -0,0 +1,838 @@
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/windows.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#include <freerdp/client/file.h>
|
||||
#include <freerdp/channels/rdpecam.h>
|
||||
|
||||
static const BYTE testRdpFileUTF16[] = {
|
||||
0xff, 0xfe, 0x73, 0x00, 0x63, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00,
|
||||
0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x00, 0x69, 0x00, 0x64, 0x00, 0x3a, 0x00,
|
||||
0x69, 0x00, 0x3a, 0x00, 0x32, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00,
|
||||
0x20, 0x00, 0x6d, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x6f, 0x00,
|
||||
0x6e, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x64, 0x00,
|
||||
0x65, 0x00, 0x73, 0x00, 0x6b, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x77, 0x00, 0x69, 0x00,
|
||||
0x64, 0x00, 0x74, 0x00, 0x68, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x39, 0x00,
|
||||
0x32, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x64, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6b, 0x00,
|
||||
0x74, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x68, 0x00, 0x65, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00,
|
||||
0x74, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x30, 0x00, 0x38, 0x00, 0x30, 0x00,
|
||||
0x0d, 0x00, 0x0a, 0x00, 0x73, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00,
|
||||
0x6e, 0x00, 0x20, 0x00, 0x62, 0x00, 0x70, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00,
|
||||
0x33, 0x00, 0x32, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x70, 0x00,
|
||||
0x6f, 0x00, 0x73, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x3a, 0x00, 0x73, 0x00, 0x3a, 0x00,
|
||||
0x30, 0x00, 0x2c, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x35, 0x00, 0x35, 0x00, 0x33, 0x00, 0x2c, 0x00,
|
||||
0x32, 0x00, 0x31, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x31, 0x00, 0x33, 0x00, 0x35, 0x00, 0x33, 0x00,
|
||||
0x2c, 0x00, 0x38, 0x00, 0x31, 0x00, 0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x63, 0x00, 0x6f, 0x00,
|
||||
0x6d, 0x00, 0x70, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00,
|
||||
0x6e, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x6b, 0x00,
|
||||
0x65, 0x00, 0x79, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x68, 0x00,
|
||||
0x6f, 0x00, 0x6f, 0x00, 0x6b, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x32, 0x00, 0x0d, 0x00,
|
||||
0x0a, 0x00, 0x61, 0x00, 0x75, 0x00, 0x64, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00,
|
||||
0x70, 0x00, 0x74, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00,
|
||||
0x65, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x76, 0x00,
|
||||
0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
|
||||
0x62, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x65, 0x00,
|
||||
0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x63, 0x00, 0x6f, 0x00,
|
||||
0x6e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00,
|
||||
0x20, 0x00, 0x74, 0x00, 0x79, 0x00, 0x70, 0x00, 0x65, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00,
|
||||
0x37, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x74, 0x00, 0x77, 0x00, 0x6f, 0x00,
|
||||
0x72, 0x00, 0x6b, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x65, 0x00,
|
||||
0x74, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00,
|
||||
0x0d, 0x00, 0x0a, 0x00, 0x62, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x77, 0x00, 0x69, 0x00,
|
||||
0x64, 0x00, 0x74, 0x00, 0x68, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x64, 0x00,
|
||||
0x65, 0x00, 0x74, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00,
|
||||
0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x70, 0x00, 0x6c, 0x00,
|
||||
0x61, 0x00, 0x79, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x63, 0x00,
|
||||
0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x72, 0x00, 0x3a, 0x00,
|
||||
0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x61, 0x00,
|
||||
0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6b, 0x00, 0x73, 0x00,
|
||||
0x70, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x6f, 0x00,
|
||||
0x6e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00,
|
||||
0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x61, 0x00, 0x62, 0x00,
|
||||
0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x77, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x70, 0x00,
|
||||
0x61, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x30, 0x00,
|
||||
0x0d, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x20, 0x00,
|
||||
0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6d, 0x00, 0x6f, 0x00,
|
||||
0x6f, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x3a, 0x00, 0x69, 0x00,
|
||||
0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00,
|
||||
0x77, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6b, 0x00, 0x74, 0x00, 0x6f, 0x00,
|
||||
0x70, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x73, 0x00,
|
||||
0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00,
|
||||
0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x61, 0x00, 0x62, 0x00,
|
||||
0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x66, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00,
|
||||
0x77, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x20, 0x00, 0x64, 0x00,
|
||||
0x72, 0x00, 0x61, 0x00, 0x67, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00,
|
||||
0x0a, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00,
|
||||
0x20, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00,
|
||||
0x69, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00,
|
||||
0x0a, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00,
|
||||
0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x3a, 0x00,
|
||||
0x69, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00,
|
||||
0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x63, 0x00, 0x75, 0x00, 0x72, 0x00,
|
||||
0x73, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x73, 0x00, 0x65, 0x00, 0x74, 0x00, 0x74, 0x00,
|
||||
0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00,
|
||||
0x0a, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x70, 0x00, 0x63, 0x00,
|
||||
0x61, 0x00, 0x63, 0x00, 0x68, 0x00, 0x65, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00,
|
||||
0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00,
|
||||
0x65, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x66, 0x00,
|
||||
0x75, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x64, 0x00, 0x64, 0x00, 0x72, 0x00,
|
||||
0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x4c, 0x00, 0x41, 0x00,
|
||||
0x42, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x57, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x44, 0x00, 0x4d, 0x00,
|
||||
0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x62, 0x00, 0x31, 0x00,
|
||||
0x2e, 0x00, 0x61, 0x00, 0x77, 0x00, 0x61, 0x00, 0x6b, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x6c, 0x00,
|
||||
0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x75, 0x00,
|
||||
0x64, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x65, 0x00, 0x3a, 0x00,
|
||||
0x69, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00,
|
||||
0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x70, 0x00, 0x72, 0x00, 0x69, 0x00,
|
||||
0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00,
|
||||
0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00,
|
||||
0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x6f, 0x00,
|
||||
0x72, 0x00, 0x74, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00,
|
||||
0x0a, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00,
|
||||
0x74, 0x00, 0x73, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x63, 0x00, 0x61, 0x00,
|
||||
0x72, 0x00, 0x64, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00,
|
||||
0x0a, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00,
|
||||
0x74, 0x00, 0x63, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x70, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x61, 0x00,
|
||||
0x72, 0x00, 0x64, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00,
|
||||
0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00,
|
||||
0x70, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x64, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00,
|
||||
0x65, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00,
|
||||
0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x6f, 0x00,
|
||||
0x6e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00,
|
||||
0x20, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x64, 0x00,
|
||||
0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x75, 0x00,
|
||||
0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00,
|
||||
0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x76, 0x00,
|
||||
0x65, 0x00, 0x6c, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x32, 0x00, 0x0d, 0x00, 0x0a, 0x00,
|
||||
0x70, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x74, 0x00, 0x20, 0x00, 0x66, 0x00,
|
||||
0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x63, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x65, 0x00,
|
||||
0x6e, 0x00, 0x74, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x69, 0x00,
|
||||
0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x67, 0x00, 0x6f, 0x00,
|
||||
0x74, 0x00, 0x69, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x65, 0x00,
|
||||
0x63, 0x00, 0x75, 0x00, 0x72, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6c, 0x00,
|
||||
0x61, 0x00, 0x79, 0x00, 0x65, 0x00, 0x72, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00,
|
||||
0x0d, 0x00, 0x0a, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x65, 0x00,
|
||||
0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00,
|
||||
0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x65, 0x00, 0x3a, 0x00,
|
||||
0x69, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x74, 0x00,
|
||||
0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00,
|
||||
0x68, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x3a, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x0d, 0x00,
|
||||
0x0a, 0x00, 0x73, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x77, 0x00,
|
||||
0x6f, 0x00, 0x72, 0x00, 0x6b, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x64, 0x00,
|
||||
0x69, 0x00, 0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x79, 0x00,
|
||||
0x3a, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x61, 0x00, 0x74, 0x00,
|
||||
0x65, 0x00, 0x77, 0x00, 0x61, 0x00, 0x79, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x74, 0x00,
|
||||
0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x3a, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x4c, 0x00,
|
||||
0x41, 0x00, 0x42, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x57, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x38, 0x00,
|
||||
0x52, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x47, 0x00, 0x57, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x61, 0x00,
|
||||
0x62, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x77, 0x00, 0x61, 0x00, 0x6b, 0x00, 0x65, 0x00,
|
||||
0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x0d, 0x00, 0x0a, 0x00,
|
||||
0x67, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x77, 0x00, 0x61, 0x00, 0x79, 0x00, 0x75, 0x00,
|
||||
0x73, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x74, 0x00, 0x68, 0x00,
|
||||
0x6f, 0x00, 0x64, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00,
|
||||
0x67, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x77, 0x00, 0x61, 0x00, 0x79, 0x00, 0x63, 0x00,
|
||||
0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x69, 0x00, 0x61, 0x00,
|
||||
0x6c, 0x00, 0x73, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00,
|
||||
0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x61, 0x00,
|
||||
0x74, 0x00, 0x65, 0x00, 0x77, 0x00, 0x61, 0x00, 0x79, 0x00, 0x70, 0x00, 0x72, 0x00, 0x6f, 0x00,
|
||||
0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x75, 0x00, 0x73, 0x00, 0x61, 0x00, 0x67, 0x00,
|
||||
0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x3a, 0x00,
|
||||
0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x72, 0x00, 0x6f, 0x00,
|
||||
0x6d, 0x00, 0x70, 0x00, 0x74, 0x00, 0x63, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x65, 0x00,
|
||||
0x6e, 0x00, 0x74, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x63, 0x00,
|
||||
0x65, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x31, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x75, 0x00,
|
||||
0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00,
|
||||
0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x73, 0x00,
|
||||
0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00,
|
||||
0x6d, 0x00, 0x65, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00, 0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00,
|
||||
0x72, 0x00, 0x64, 0x00, 0x67, 0x00, 0x69, 0x00, 0x73, 0x00, 0x6b, 0x00, 0x64, 0x00, 0x63, 0x00,
|
||||
0x70, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x78, 0x00, 0x79, 0x00, 0x3a, 0x00, 0x69, 0x00, 0x3a, 0x00,
|
||||
0x30, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x6b, 0x00, 0x64, 0x00, 0x63, 0x00, 0x70, 0x00, 0x72, 0x00,
|
||||
0x6f, 0x00, 0x78, 0x00, 0x79, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x3a, 0x00,
|
||||
0x73, 0x00, 0x3a, 0x00, 0x0d, 0x00, 0x0a, 0x00, 0x64, 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x00,
|
||||
0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00,
|
||||
0x72, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x3a, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x2a, 0x00,
|
||||
0x0d, 0x00, 0x0a, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x61, 0x00,
|
||||
0x6d, 0x00, 0x65, 0x00, 0x3a, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x4c, 0x00, 0x41, 0x00, 0x42, 0x00,
|
||||
0x31, 0x00, 0x5c, 0x00, 0x4a, 0x00, 0x6f, 0x00, 0x68, 0x00, 0x6e, 0x00, 0x44, 0x00, 0x6f, 0x00,
|
||||
0x65, 0x00, 0x0d, 0x00, 0x0a, 0x00
|
||||
};
|
||||
|
||||
#if defined(CHANNEL_RDPECAM_CLIENT)
|
||||
static const char* camera_args[] = { RDPECAM_DVC_CHANNEL_NAME,
|
||||
"device:*",
|
||||
"device:\\?\\usb#vid_0bda&pid_58b0&mi",
|
||||
"device:-\\?\\usb#vid_0bdc&pid_58b1&mi",
|
||||
"encode:1",
|
||||
"quality:2" };
|
||||
#endif
|
||||
|
||||
#if defined(CHANNEL_URBDRC_CLIENT)
|
||||
static const char* urbdrc_args[] = { "urbdrc", "device:*", "device:USBInstanceID:someid",
|
||||
"device:{72631e54-78a4-11d0-bcf7-00aa00b7b32a}" };
|
||||
#endif
|
||||
|
||||
static char testRdpFileUTF8[] =
|
||||
"screen mode id:i:2\n"
|
||||
"use multimon:i:0\n"
|
||||
"desktopwidth:i:1920\n"
|
||||
"desktopheight:i:1080\n"
|
||||
"dynamic resolution:i:1080\n"
|
||||
"desktopscalefactor:i:1080\n"
|
||||
"redirected video capture encoding quality:i:2\n"
|
||||
"encode redirected video capture:i:1\n"
|
||||
"camerastoredirect:s:*,\\?\\usb#vid_0bda&pid_58b0&mi,-\\?\\usb#vid_0bdc&pid_58b1&mi\n"
|
||||
"usbdevicestoredirect:s:*,USBInstanceID:someid,{72631e54-78a4-11d0-bcf7-00aa00b7b32a}\n"
|
||||
"selectedmonitors:s:3,2,42,23"
|
||||
"session bpp:i:32\n"
|
||||
"winposstr:s:0,1,553,211,1353,811\n"
|
||||
"compression:i:1\n"
|
||||
"keyboardhook:i:2\n"
|
||||
"audiocapturemode:i:0\n"
|
||||
"videoplaybackmode:i:2\n"
|
||||
"connection type:i:7\n"
|
||||
"networkautodetect:i:1\n"
|
||||
"bandwidthautodetect:i:1\n"
|
||||
"displayconnectionbar:i:1\n"
|
||||
"enableworkspacereconnect:i:0\n"
|
||||
"disable wallpaper:i:0\n"
|
||||
"allow font smoothing:i:0\n"
|
||||
"allow desktop composition:i:0\n"
|
||||
"disable full window drag:i:1\n"
|
||||
"disable menu anims:i:1\n"
|
||||
"disable themes:i:0\n"
|
||||
"disable cursor setting:i:0\n"
|
||||
"bitmapcachepersistenable:i:1\n"
|
||||
"full address:s:LAB1-W7-DM-01.lab1.awake.local\n"
|
||||
"alternate full address:s:LAB1-W7-DM-01.lab1.awake.global\n"
|
||||
"audiomode:i:0\n"
|
||||
"redirectprinters:i:1\n"
|
||||
"redirectcomports:i:0\n"
|
||||
"redirectsmartcards:i:1\n"
|
||||
"redirectclipboard:i:1\n"
|
||||
"redirectposdevices:i:0\n"
|
||||
"autoreconnection enabled:i:1\n"
|
||||
"authentication level:i:2\n"
|
||||
"prompt for credentials:i:0\n"
|
||||
"negotiate security layer:i:1\n"
|
||||
"remoteapplicationmode:i:0\n"
|
||||
"alternate shell:s:\n"
|
||||
"shell working directory:s:\n"
|
||||
"gatewayhostname:s:LAB1-W2K8R2-GW.lab1.awake.local\n"
|
||||
"gatewayusagemethod:i:1\n"
|
||||
"gatewaycredentialssource:i:0\n"
|
||||
"gatewayprofileusagemethod:i:1\n"
|
||||
"promptcredentialonce:i:1\n"
|
||||
"use redirection server name:i:0\n"
|
||||
"rdgiskdcproxy:i:0\n"
|
||||
"kdcproxyname:s:\n"
|
||||
"drivestoredirect:s:*\n"
|
||||
"username:s:LAB1\\JohnDoe\n"
|
||||
"vendor integer:i:123\n"
|
||||
"vendor string:s:microsoft\n";
|
||||
|
||||
static char* append(const char* fmt, ...)
|
||||
{
|
||||
int rc = 0;
|
||||
char* dst = nullptr;
|
||||
va_list ap = WINPR_C_ARRAY_INIT;
|
||||
|
||||
va_start(ap, fmt);
|
||||
rc = vsnprintf(nullptr, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
if (rc < 0)
|
||||
return nullptr;
|
||||
dst = malloc((size_t)rc + 1);
|
||||
if (!dst)
|
||||
return nullptr;
|
||||
|
||||
va_start(ap, fmt);
|
||||
rc = vsnprintf(dst, (size_t)rc + 1, fmt, ap);
|
||||
va_end(ap);
|
||||
if (rc < 0)
|
||||
{
|
||||
free(dst);
|
||||
return nullptr;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static FILE* test_fopen(const char* name, const char* mode)
|
||||
{
|
||||
#ifndef TEST_SOURCE_DIR
|
||||
#error "TEST_SOURCE_DIR must be defined to the test source directory"
|
||||
#endif
|
||||
|
||||
char* path = GetCombinedPath(TEST_SOURCE_DIR, name);
|
||||
FILE* fp = winpr_fopen(path, mode);
|
||||
free(path);
|
||||
return fp;
|
||||
}
|
||||
|
||||
static void* read_rdp_data(const char* name, size_t* plen)
|
||||
{
|
||||
BOOL success = FALSE;
|
||||
char* json = nullptr;
|
||||
FILE* fp = test_fopen(name, "r");
|
||||
if (!fp)
|
||||
goto fail;
|
||||
|
||||
if (fseek(fp, 0, SEEK_END) != 0)
|
||||
goto fail;
|
||||
|
||||
const INT64 pos = _ftelli64(fp);
|
||||
if (pos < 0)
|
||||
goto fail;
|
||||
|
||||
if (fseek(fp, 0, SEEK_SET) != 0)
|
||||
goto fail;
|
||||
|
||||
const size_t upos = WINPR_CXX_COMPAT_CAST(size_t, pos);
|
||||
json = calloc(1ULL + upos, sizeof(char));
|
||||
if (!json)
|
||||
goto fail;
|
||||
if (fread(json, 1, pos, fp) != pos)
|
||||
goto fail;
|
||||
|
||||
*plen = upos;
|
||||
success = TRUE;
|
||||
fail:
|
||||
if (!success)
|
||||
{
|
||||
char buffer[128] = WINPR_C_ARRAY_INIT;
|
||||
WLog_ERR(__func__, "failed to read data from '%s': %s", name,
|
||||
winpr_strerror(errno, buffer, sizeof(buffer)));
|
||||
free(json);
|
||||
json = nullptr;
|
||||
}
|
||||
|
||||
if (fp)
|
||||
(void)fclose(fp);
|
||||
return json;
|
||||
}
|
||||
|
||||
static bool save_settings(const rdpSettings* settings, const char* name)
|
||||
{
|
||||
bool rc = false;
|
||||
size_t datalen = 0;
|
||||
char* data = freerdp_settings_serialize(settings, TRUE, &datalen);
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
FILE* fp = test_fopen(name, "w");
|
||||
if (fp)
|
||||
{
|
||||
const size_t res = fwrite(data, 1, datalen, fp);
|
||||
(void)fclose(fp);
|
||||
rc = res == datalen;
|
||||
}
|
||||
|
||||
free(data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static char* get_json_name(const char* base, bool unchecked)
|
||||
{
|
||||
size_t namelen = 0;
|
||||
char* name = nullptr;
|
||||
winpr_asprintf(&name, &namelen, "%s%s.json", base, unchecked ? ".unchecked" : "");
|
||||
return name;
|
||||
}
|
||||
|
||||
static rdpSettings* read_json(const char* name)
|
||||
{
|
||||
size_t datalen = 0;
|
||||
void* data = read_rdp_data(name, &datalen);
|
||||
rdpSettings* settings = freerdp_settings_deserialize(data, datalen);
|
||||
fail:
|
||||
free(data);
|
||||
return settings;
|
||||
}
|
||||
|
||||
static rdpSettings* load_from(const void* data, size_t len, bool unchecked)
|
||||
{
|
||||
BOOL rc = false;
|
||||
rdpFile* file = freerdp_client_rdp_file_new();
|
||||
rdpSettings* settings = read_json("default-settings.json");
|
||||
if (!settings)
|
||||
{
|
||||
settings = freerdp_settings_new(0);
|
||||
if (settings)
|
||||
{
|
||||
save_settings(settings, "default-settings.json");
|
||||
}
|
||||
}
|
||||
if (!file || !settings)
|
||||
goto fail;
|
||||
|
||||
if (!freerdp_client_parse_rdp_file_buffer(file, data, len))
|
||||
goto fail;
|
||||
|
||||
if (unchecked)
|
||||
{
|
||||
if (!freerdp_client_populate_settings_from_rdp_file_unchecked(file, settings))
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!freerdp_client_populate_settings_from_rdp_file(file, settings))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = true;
|
||||
fail:
|
||||
freerdp_client_rdp_file_free(file);
|
||||
if (!rc)
|
||||
{
|
||||
freerdp_settings_free(settings);
|
||||
return nullptr;
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
static rdpSettings* load_from_file(const char* name, bool unchecked)
|
||||
{
|
||||
size_t datalen = 0;
|
||||
void* data = read_rdp_data(name, &datalen);
|
||||
if (!data)
|
||||
return nullptr;
|
||||
rdpSettings* settings = load_from(data, datalen, unchecked);
|
||||
free(data);
|
||||
return settings;
|
||||
}
|
||||
|
||||
static bool test_data(const char* json, const void* data, size_t len, bool unchecked)
|
||||
{
|
||||
bool rc = false;
|
||||
|
||||
rdpSettings* settings = load_from(data, len, unchecked);
|
||||
rdpSettings* expect = read_json(json);
|
||||
if (!settings || !expect)
|
||||
goto fail;
|
||||
|
||||
#ifndef WITH_GFX_H264
|
||||
if (!freerdp_settings_set_bool(expect, FreeRDP_GfxH264, FALSE) ||
|
||||
!freerdp_settings_set_bool(expect, FreeRDP_GfxAVC444, FALSE) ||
|
||||
!freerdp_settings_set_bool(expect, FreeRDP_GfxAVC444v2, FALSE))
|
||||
goto fail;
|
||||
#endif
|
||||
wLog* log = WLog_Get(__func__);
|
||||
WLog_Print(log, WLOG_INFO, "Test cast '%s'", json);
|
||||
if (freerdp_settings_print_diff(log, WLOG_ERROR, expect, settings))
|
||||
goto fail;
|
||||
rc = true;
|
||||
fail:
|
||||
freerdp_settings_free(settings);
|
||||
freerdp_settings_free(expect);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static HANDLE FindFirstFileUTF8(LPCSTR pszSearchPath, WIN32_FIND_DATAW* FindData)
|
||||
{
|
||||
HANDLE hdl = INVALID_HANDLE_VALUE;
|
||||
if (!pszSearchPath)
|
||||
return hdl;
|
||||
WCHAR* wpath = ConvertUtf8ToWCharAlloc(pszSearchPath, nullptr);
|
||||
if (!wpath)
|
||||
return hdl;
|
||||
|
||||
hdl = FindFirstFileW(wpath, FindData);
|
||||
free(wpath);
|
||||
|
||||
return hdl;
|
||||
}
|
||||
|
||||
static bool test_rdp_file(const char* base, bool allowCreate, bool unchecked)
|
||||
{
|
||||
bool rc = false;
|
||||
|
||||
size_t rdplen = 0;
|
||||
char* rdp = nullptr;
|
||||
winpr_asprintf(&rdp, &rdplen, "%s.rdp", base);
|
||||
char* json = get_json_name(base, unchecked);
|
||||
size_t datalen = 0;
|
||||
void* data = read_rdp_data(rdp, &datalen);
|
||||
|
||||
if (!data)
|
||||
goto fail;
|
||||
|
||||
rc = test_data(json, data, datalen, unchecked);
|
||||
if (!rc && allowCreate)
|
||||
{
|
||||
rdpSettings* expect = read_json(json);
|
||||
if (expect)
|
||||
{
|
||||
freerdp_settings_free(expect);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rdpSettings* settings = load_from_file(rdp, unchecked);
|
||||
if (!settings)
|
||||
goto fail;
|
||||
|
||||
rc = save_settings(settings, json);
|
||||
}
|
||||
fail:
|
||||
free(data);
|
||||
free(json);
|
||||
free(rdp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool test_rdp_files(bool allowCreate)
|
||||
{
|
||||
bool rc = false;
|
||||
/* Load RDP files from directory, compare to JSON in same directory.
|
||||
* If JSON does not exist, create it.
|
||||
*/
|
||||
#ifndef TEST_SOURCE_DIR
|
||||
#error "TEST_SOURCE_DIR must be defined to the test source directory"
|
||||
#endif
|
||||
|
||||
HANDLE hdl = INVALID_HANDLE_VALUE;
|
||||
char* path = GetCombinedPath(TEST_SOURCE_DIR, "rdp-testcases/*.rdp");
|
||||
if (!path)
|
||||
goto fail;
|
||||
|
||||
WIN32_FIND_DATAW FindData = WINPR_C_ARRAY_INIT;
|
||||
hdl = FindFirstFileUTF8(path, &FindData);
|
||||
|
||||
if (hdl == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WLog_INFO(
|
||||
__func__,
|
||||
"no RDP files found in %s. Add RDP files to generate settings JSON for comparison.",
|
||||
path);
|
||||
rc = true;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if ((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
{
|
||||
char cFileName[6 * MAX_PATH] = WINPR_C_ARRAY_INIT;
|
||||
char rdp[6 * MAX_PATH] = WINPR_C_ARRAY_INIT;
|
||||
ConvertWCharToUtf8(FindData.cFileName, cFileName, sizeof(cFileName));
|
||||
const size_t len = strnlen(cFileName, sizeof(cFileName));
|
||||
if (len < 4)
|
||||
continue;
|
||||
strcpy(rdp, "rdp-testcases/");
|
||||
strncpy(&rdp[14], cFileName, len - 4);
|
||||
|
||||
if (!test_rdp_file(rdp, allowCreate, false))
|
||||
goto fail;
|
||||
if (!test_rdp_file(rdp, allowCreate, true))
|
||||
goto fail;
|
||||
}
|
||||
} while (FindNextFileW(hdl, &FindData));
|
||||
|
||||
rc = true;
|
||||
|
||||
fail:
|
||||
FindClose(hdl);
|
||||
free(path);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestClientRdpFile(int argc, char* argv[])
|
||||
{
|
||||
int rc = -1;
|
||||
int iValue = 0;
|
||||
UINT32 uValue = 0;
|
||||
const UINT32* puValue = nullptr;
|
||||
const char* sValue = nullptr;
|
||||
char* utfname = nullptr;
|
||||
char* uniname = nullptr;
|
||||
char* base = nullptr;
|
||||
char* tmp = nullptr;
|
||||
UINT64 id = 0;
|
||||
rdpFile* file = nullptr;
|
||||
rdpSettings* settings = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
if (winpr_RAND(&id, sizeof(id)) < 0)
|
||||
return -1;
|
||||
|
||||
/* UTF8 */
|
||||
#if defined(CHANNEL_URBDRC_CLIENT) && defined(CHANNEL_RDPECAM_CLIENT)
|
||||
if (!test_data("testRdpFileUTF8.json", testRdpFileUTF8, sizeof(testRdpFileUTF8), false))
|
||||
return -1;
|
||||
if (!test_data("testRdpFileUTF8.unchecked.json", testRdpFileUTF8, sizeof(testRdpFileUTF8),
|
||||
true))
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
/* Unicode */
|
||||
#if defined(CHANNEL_URBDRC_CLIENT)
|
||||
if (!test_data("testRdpFileUTF16.json", testRdpFileUTF16, sizeof(testRdpFileUTF16), false))
|
||||
return -1;
|
||||
if (!test_data("testRdpFileUTF16.unchecked.json", testRdpFileUTF16, sizeof(testRdpFileUTF16),
|
||||
true))
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#if defined(CHANNEL_URBDRC_CLIENT) && defined(CHANNEL_RDPECAM_CLIENT)
|
||||
if (!test_rdp_files(argc > 1))
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
/* Ascii */
|
||||
file = freerdp_client_rdp_file_new();
|
||||
settings = freerdp_settings_new(0);
|
||||
if (!file || !settings)
|
||||
{
|
||||
printf("rdp_file_new failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!freerdp_client_parse_rdp_file_buffer(file, (BYTE*)testRdpFileUTF8,
|
||||
sizeof(testRdpFileUTF8)))
|
||||
goto fail;
|
||||
|
||||
if (!freerdp_client_populate_settings_from_rdp_file(file, settings))
|
||||
goto fail;
|
||||
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_UseMultimon))
|
||||
{
|
||||
printf("UseMultiMon mismatch: Actual: %" PRIu32 ", Expected: 0\n",
|
||||
freerdp_settings_get_bool(settings, FreeRDP_UseMultimon));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!freerdp_settings_get_bool(settings, FreeRDP_Fullscreen))
|
||||
{
|
||||
printf("ScreenModeId mismatch: Actual: %" PRIu32 ", Expected: TRUE\n",
|
||||
freerdp_settings_get_bool(settings, FreeRDP_Fullscreen));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(freerdp_settings_get_string(settings, FreeRDP_ServerHostname),
|
||||
"LAB1-W7-DM-01.lab1.awake.global") != 0)
|
||||
{
|
||||
printf("ServerHostname mismatch: Actual: %s, Expected: %s\n",
|
||||
freerdp_settings_get_string(settings, FreeRDP_ServerHostname),
|
||||
"LAB1-W7-DM-01.lab1.awake.global");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (strcmp(freerdp_settings_get_string(settings, FreeRDP_GatewayHostname),
|
||||
"LAB1-W2K8R2-GW.lab1.awake.local") != 0)
|
||||
{
|
||||
printf("GatewayHostname mismatch: Actual: %s, Expected: %s\n",
|
||||
freerdp_settings_get_string(settings, FreeRDP_GatewayHostname),
|
||||
"LAB1-W2K8R2-GW.lab1.awake.local");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
iValue = freerdp_client_rdp_file_get_integer_option(file, "dynamic resolution");
|
||||
if (iValue != 1080)
|
||||
{
|
||||
printf("dynamic resolution uses invalid default value %d", iValue);
|
||||
goto fail;
|
||||
}
|
||||
if (!freerdp_settings_get_bool(settings, FreeRDP_DynamicResolutionUpdate))
|
||||
{
|
||||
printf("FreeRDP_DynamicResolutionUpdate has invalid value");
|
||||
goto fail;
|
||||
}
|
||||
iValue = freerdp_client_rdp_file_get_integer_option(file, "desktopscalefactor");
|
||||
if (iValue != 1080)
|
||||
{
|
||||
printf("desktopscalefactor uses invalid default value %d", iValue);
|
||||
goto fail;
|
||||
}
|
||||
if ((INT64)freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor) != iValue)
|
||||
{
|
||||
printf("FreeRDP_DesktopScaleFactor has invalid value");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check [MS-RDPECAM] related options */
|
||||
#if defined(CHANNEL_RDPECAM_CLIENT)
|
||||
{
|
||||
ADDIN_ARGV* args = nullptr;
|
||||
iValue =
|
||||
freerdp_client_rdp_file_get_integer_option(file, "encode redirected video capture");
|
||||
if (iValue != 1)
|
||||
{
|
||||
printf("encode redirected video capture uses invalid default value %d", iValue);
|
||||
goto fail;
|
||||
}
|
||||
iValue = freerdp_client_rdp_file_get_integer_option(
|
||||
file, "redirected video capture encoding quality");
|
||||
if (iValue != 2)
|
||||
{
|
||||
printf("redirected video capture encoding quality uses invalid default value %d",
|
||||
iValue);
|
||||
goto fail;
|
||||
}
|
||||
args = freerdp_dynamic_channel_collection_find(settings, RDPECAM_DVC_CHANNEL_NAME);
|
||||
if (!args)
|
||||
{
|
||||
printf("rdpecam channel was not loaded");
|
||||
goto fail;
|
||||
}
|
||||
if (args->argc != 6)
|
||||
{
|
||||
printf("rdpecam channel was not loaded");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (int x = 0; x < args->argc; x++)
|
||||
{
|
||||
if (strcmp(args->argv[x], camera_args[x]) != 0)
|
||||
{
|
||||
printf("rdpecam invalid argument argv[%d]: %s", x, args->argv[x]);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check [URBDRC] related options */
|
||||
#if defined(CHANNEL_URBDRC_CLIENT)
|
||||
{
|
||||
ADDIN_ARGV* args = freerdp_dynamic_channel_collection_find(settings, "urbdrc");
|
||||
if (!args)
|
||||
{
|
||||
printf("urbdrc channel was not loaded");
|
||||
goto fail;
|
||||
}
|
||||
if (args->argc != 4)
|
||||
{
|
||||
printf("urbdrc channel was not loaded");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (int x = 0; x < args->argc; x++)
|
||||
{
|
||||
if (strcmp(args->argv[x], urbdrc_args[x]) != 0)
|
||||
{
|
||||
printf("urbdrc invalid argument argv[%d]: %s", x, args->argv[x]);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Validate selectedmonitors:s:3,2,42,23 */
|
||||
uValue = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
|
||||
if (uValue != 4)
|
||||
{
|
||||
printf("FreeRDP_NumMonitorIds has invalid value %" PRIu32, uValue);
|
||||
goto fail;
|
||||
}
|
||||
puValue = (const UINT32*)freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, 0);
|
||||
if (!puValue)
|
||||
{
|
||||
printf("FreeRDP_MonitorIds has invalid value %p", (const void*)puValue);
|
||||
goto fail;
|
||||
}
|
||||
if ((puValue[0] != 3) || (puValue[1] != 2) || (puValue[2] != 42) || (puValue[3] != 23))
|
||||
{
|
||||
printf("FreeRDP_MonitorIds has invalid values: [%" PRIu32 ",%" PRIu32 ",%" PRIu32
|
||||
",%" PRIu32 "]",
|
||||
puValue[0], puValue[1], puValue[2], puValue[3]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
iValue = freerdp_client_rdp_file_get_integer_option(file, "videoplaybackmode");
|
||||
if (iValue != 2)
|
||||
{
|
||||
printf("videoplaybackmode uses invalid default value %d", iValue);
|
||||
goto fail;
|
||||
}
|
||||
if (!freerdp_settings_get_bool(settings, FreeRDP_SupportVideoOptimized))
|
||||
{
|
||||
printf("FreeRDP_SupportVideoOptimized has invalid value");
|
||||
goto fail;
|
||||
}
|
||||
if (!freerdp_settings_get_bool(settings, FreeRDP_SupportGeometryTracking))
|
||||
{
|
||||
printf("FreeRDP_SupportGeometryTracking has invalid value");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
iValue = freerdp_client_rdp_file_get_integer_option(file, "vendor integer");
|
||||
if (iValue != 123)
|
||||
goto fail;
|
||||
|
||||
if (freerdp_client_rdp_file_set_integer_option(file, "vendor integer", 456) == -1)
|
||||
{
|
||||
printf("failed to set integer: vendor integer");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
iValue = freerdp_client_rdp_file_get_integer_option(file, "vendor integer");
|
||||
if (iValue != 456)
|
||||
return -1;
|
||||
|
||||
const char microsoft[] = "microsoft";
|
||||
sValue = freerdp_client_rdp_file_get_string_option(file, "vendor string");
|
||||
if (strncmp(sValue, microsoft, sizeof(microsoft)) != 0)
|
||||
goto fail;
|
||||
|
||||
const char apple[] = "apple";
|
||||
freerdp_client_rdp_file_set_string_option(file, "vendor string", "apple");
|
||||
sValue = freerdp_client_rdp_file_get_string_option(file, "vendor string");
|
||||
if (strncmp(sValue, apple, sizeof(apple)) != 0)
|
||||
goto fail;
|
||||
|
||||
freerdp_client_rdp_file_set_string_option(file, "fruits", "banana,oranges");
|
||||
|
||||
if (freerdp_client_rdp_file_set_integer_option(file, "numbers", 123456789) == -1)
|
||||
{
|
||||
printf("failed to set integer: numbers");
|
||||
return -1;
|
||||
}
|
||||
|
||||
freerdp_client_rdp_file_free(file);
|
||||
|
||||
tmp = GetKnownPath(KNOWN_PATH_TEMP);
|
||||
if (!tmp)
|
||||
goto fail;
|
||||
|
||||
base = append("%s/rdp-file-test-%" PRIx64, tmp, id);
|
||||
if (!base)
|
||||
goto fail;
|
||||
if (!CreateDirectoryA(base, nullptr))
|
||||
goto fail;
|
||||
utfname = append("%s/utfname", base);
|
||||
uniname = append("%s/uniname", base);
|
||||
file = freerdp_client_rdp_file_new();
|
||||
if (!file || !utfname || !uniname)
|
||||
goto fail;
|
||||
|
||||
if (!freerdp_client_populate_rdp_file_from_settings(file, settings))
|
||||
goto fail;
|
||||
|
||||
if (!freerdp_client_write_rdp_file(file, utfname, FALSE))
|
||||
goto fail;
|
||||
|
||||
if (!freerdp_client_write_rdp_file(file, uniname, TRUE))
|
||||
goto fail;
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
if (utfname)
|
||||
winpr_DeleteFile(utfname);
|
||||
if (uniname)
|
||||
winpr_DeleteFile(uniname);
|
||||
if (base)
|
||||
winpr_RemoveDirectory(base);
|
||||
free(utfname);
|
||||
free(uniname);
|
||||
free(base);
|
||||
free(tmp);
|
||||
freerdp_client_rdp_file_free(file);
|
||||
freerdp_settings_free(settings);
|
||||
return rc;
|
||||
}
|
||||
1377
third_party/FreeRDP/client/common/test/default-settings.json
vendored
Normal file
1377
third_party/FreeRDP/client/common/test/default-settings.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
third_party/FreeRDP/client/common/test/rdp-testcases/README.txt
vendored
Normal file
8
third_party/FreeRDP/client/common/test/rdp-testcases/README.txt
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
This directory should contain RDP files that are checked by TestClientRdpFile
|
||||
|
||||
Adding new test works like this:
|
||||
|
||||
1. place a .rdp file in this folder
|
||||
2. run TestClient TestClientRdpFile generate to generate a settings JSON from the RDP file
|
||||
3. git add .rdp .json && git commit .
|
||||
4. now the unit test is run and the result is compared
|
||||
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test1.json
vendored
Normal file
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test1.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
38
third_party/FreeRDP/client/common/test/rdp-testcases/test1.rdp
vendored
Normal file
38
third_party/FreeRDP/client/common/test/rdp-testcases/test1.rdp
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
gatewayusagemethod:i:1
|
||||
gatewayprofileusagemethod:i:1
|
||||
authentication level:i:1
|
||||
gatewaybrokeringtype:i:1
|
||||
wvd endpoint pool:s:11112222-0815-1234-abcd-123456789abc
|
||||
geo:s:EU
|
||||
armpath:s:/subscriptions/584e4430-82fd-41aa-b87a-efc8b62f890c/resourcegroups/f6cfbbf2-efed-4756-a9c8-3c547bc4eb50/providers/Microsoft.DesktopVirtualization/hostpools/3367af18e772425b82d958c4f06d8023
|
||||
aadtenantid:s:77064fd5-2634-4a0d-b310-2fa3c1d0472d
|
||||
full address:s:rdgateway-r1.wvd.microsoft.com
|
||||
alternate full address:s:rdgateway-r1.wvd.microsoft.com
|
||||
diagnosticserviceurl:s:https://rdweb-g-eu-r1.wvd.microsoft.com/api/arm/DiagnosticEvents/v1
|
||||
hubdiscoverygeourl:s:https://rdweb-g-eu-r1.wvd.microsoft.com/api/arm/hubdiscovery?resourceId=16e1fb18-0f41-4e0c-acf8-5046124affe9
|
||||
resourceprovider:s:arm
|
||||
gatewayhostname:s:afdfp-rdgateway-r1.wvd.microsoft.com:443
|
||||
loadbalanceinfo:s:mth://localhost/b47b47c1-b81e-4dfa-ac1b-a8a195d43f26/16e1fb18-0f41-4e0c-acf8-5046124affe9
|
||||
workspace id:s:cd2471f8-135b-405b-ac04-c2e1564ef354
|
||||
activityhint:s:ms-wvd-ep:16e1fb18-0f41-4e0c-acf8-5046124affe9?ScaleUnitPath={"Geo"%3a"EU"%2c"Ring"%3a1%2c"Region"%3a"westeurope"%2c"ScaleUnit"%3a100}
|
||||
promptcredentialonce:i:1
|
||||
gatewaycredentialssource:i:0
|
||||
remoteapplicationprogram:s:||40d51148-8d2c-4222-aeb3-7ad10be11650
|
||||
remotedesktopname:s:Cloud PC Enterprise 8vCPU/32GB/512GB
|
||||
remoteapplicationmode:i:0
|
||||
audiomode:i:0
|
||||
redirectclipboard:i:1
|
||||
redirectprinters:i:1
|
||||
redirectsmartcards:i:1
|
||||
dynamic resolution:i:1
|
||||
audiocapturemode:i:1
|
||||
camerastoredirect:s:*
|
||||
devicestoredirect:s:*
|
||||
redirectcomports:i:1
|
||||
drivestoredirect:s:*
|
||||
usbdevicestoredirect:s:*
|
||||
singlemoninwindowedmode:i:1
|
||||
redirectlocation:i:1
|
||||
targetisaadjoined:i:1
|
||||
enablerdsaadauth:i:0
|
||||
clientrejectinjectedinput:i:0
|
||||
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test1.unchecked.json
vendored
Normal file
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test1.unchecked.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test2.json
vendored
Normal file
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test2.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
39
third_party/FreeRDP/client/common/test/rdp-testcases/test2.rdp
vendored
Normal file
39
third_party/FreeRDP/client/common/test/rdp-testcases/test2.rdp
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
gatewayusagemethod:i:1
|
||||
gatewayprofileusagemethod:i:1
|
||||
authentication level:i:1
|
||||
gatewaybrokeringtype:i:1
|
||||
wvd endpoint pool:s:11112222-0815-1234-abcd-123456789abc
|
||||
geo:s:EU
|
||||
armpath:s:/subscriptions/584e4430-82fd-41aa-b87a-efc8b62f890c/resourcegroups/f6cfbbf2-efed-4756-a9c8-3c547bc4eb50/providers/Microsoft.DesktopVirtualization/hostpools/3367af18e772425b82d958c4f06d8023
|
||||
aadtenantid:s:77064fd5-2634-4a0d-b310-2fa3c1d0472d
|
||||
full address:s:rdgateway-r1.wvd.microsoft.com
|
||||
rdgiskdcproxy:i:1
|
||||
alternate full address:s:rdgateway-r1.wvd.microsoft.com
|
||||
diagnosticserviceurl:s:https://rdweb-g-eu-r1.wvd.microsoft.com/api/arm/DiagnosticEvents/v1
|
||||
hubdiscoverygeourl:s:https://rdweb-g-eu-r1.wvd.microsoft.com/api/arm/hubdiscovery?resourceId=16e1fb18-0f41-4e0c-acf8-5046124affe9
|
||||
resourceprovider:s:arm
|
||||
gatewayhostname:s:afdfp-rdgateway-r1.wvd.microsoft.com:443
|
||||
loadbalanceinfo:s:mth://localhost/b47b47c1-b81e-4dfa-ac1b-a8a195d43f26/16e1fb18-0f41-4e0c-acf8-5046124affe9
|
||||
workspace id:s:cd2471f8-135b-405b-ac04-c2e1564ef354
|
||||
activityhint:s:ms-wvd-ep:16e1fb18-0f41-4e0c-acf8-5046124affe9?ScaleUnitPath={"Geo"%3a"EU"%2c"Ring"%3a1%2c"Region"%3a"westeurope"%2c"ScaleUnit"%3a100}
|
||||
promptcredentialonce:i:1
|
||||
gatewaycredentialssource:i:0
|
||||
remoteapplicationprogram:s:||40d51148-8d2c-4222-aeb3-7ad10be11650
|
||||
remotedesktopname:s:Cloud PC Enterprise 8vCPU/32GB/512GB
|
||||
remoteapplicationmode:i:0
|
||||
audiomode:i:0
|
||||
redirectclipboard:i:1
|
||||
redirectprinters:i:1
|
||||
redirectsmartcards:i:1
|
||||
dynamic resolution:i:1
|
||||
audiocapturemode:i:1
|
||||
camerastoredirect:s:*
|
||||
devicestoredirect:s:*
|
||||
redirectcomports:i:1
|
||||
drivestoredirect:s:*
|
||||
usbdevicestoredirect:s:*
|
||||
singlemoninwindowedmode:i:1
|
||||
redirectlocation:i:1
|
||||
targetisaadjoined:i:1
|
||||
enablerdsaadauth:i:0
|
||||
clientrejectinjectedinput:i:0
|
||||
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test2.unchecked.json
vendored
Normal file
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test2.unchecked.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test3.json
vendored
Normal file
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test3.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
39
third_party/FreeRDP/client/common/test/rdp-testcases/test3.rdp
vendored
Normal file
39
third_party/FreeRDP/client/common/test/rdp-testcases/test3.rdp
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
gatewayusagemethod:i:1
|
||||
gatewayprofileusagemethod:i:1
|
||||
authentication level:i:1
|
||||
gatewaybrokeringtype:i:1
|
||||
wvd endpoint pool:s:11112222-0815-1234-abcd-123456789abc
|
||||
geo:s:EU
|
||||
armpath:s:/subscriptions/584e4430-82fd-41aa-b87a-efc8b62f890c/resourcegroups/f6cfbbf2-efed-4756-a9c8-3c547bc4eb50/providers/Microsoft.DesktopVirtualization/hostpools/3367af18e772425b82d958c4f06d8023
|
||||
aadtenantid:s:77064fd5-2634-4a0d-b310-2fa3c1d0472d
|
||||
full address:s:rdgateway-r1.wvd.microsoft.com
|
||||
rdgiskdcproxy:i:0
|
||||
alternate full address:s:rdgateway-r1.wvd.microsoft.com
|
||||
diagnosticserviceurl:s:https://rdweb-g-eu-r1.wvd.microsoft.com/api/arm/DiagnosticEvents/v1
|
||||
hubdiscoverygeourl:s:https://rdweb-g-eu-r1.wvd.microsoft.com/api/arm/hubdiscovery?resourceId=16e1fb18-0f41-4e0c-acf8-5046124affe9
|
||||
resourceprovider:s:arm
|
||||
gatewayhostname:s:afdfp-rdgateway-r1.wvd.microsoft.com:443
|
||||
loadbalanceinfo:s:mth://localhost/b47b47c1-b81e-4dfa-ac1b-a8a195d43f26/16e1fb18-0f41-4e0c-acf8-5046124affe9
|
||||
workspace id:s:cd2471f8-135b-405b-ac04-c2e1564ef354
|
||||
activityhint:s:ms-wvd-ep:16e1fb18-0f41-4e0c-acf8-5046124affe9?ScaleUnitPath={"Geo"%3a"EU"%2c"Ring"%3a1%2c"Region"%3a"westeurope"%2c"ScaleUnit"%3a100}
|
||||
promptcredentialonce:i:1
|
||||
gatewaycredentialssource:i:0
|
||||
remoteapplicationprogram:s:||40d51148-8d2c-4222-aeb3-7ad10be11650
|
||||
remotedesktopname:s:Cloud PC Enterprise 8vCPU/32GB/512GB
|
||||
remoteapplicationmode:i:0
|
||||
audiomode:i:0
|
||||
redirectclipboard:i:1
|
||||
redirectprinters:i:1
|
||||
redirectsmartcards:i:1
|
||||
dynamic resolution:i:1
|
||||
audiocapturemode:i:1
|
||||
camerastoredirect:s:*
|
||||
devicestoredirect:s:*
|
||||
redirectcomports:i:1
|
||||
drivestoredirect:s:*
|
||||
usbdevicestoredirect:s:*
|
||||
singlemoninwindowedmode:i:1
|
||||
redirectlocation:i:1
|
||||
targetisaadjoined:i:1
|
||||
enablerdsaadauth:i:0
|
||||
clientrejectinjectedinput:i:0
|
||||
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test3.unchecked.json
vendored
Normal file
1521
third_party/FreeRDP/client/common/test/rdp-testcases/test3.unchecked.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1377
third_party/FreeRDP/client/common/test/testRdpFileUTF16.json
vendored
Normal file
1377
third_party/FreeRDP/client/common/test/testRdpFileUTF16.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1377
third_party/FreeRDP/client/common/test/testRdpFileUTF16.unchecked.json
vendored
Normal file
1377
third_party/FreeRDP/client/common/test/testRdpFileUTF16.unchecked.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1433
third_party/FreeRDP/client/common/test/testRdpFileUTF8.json
vendored
Normal file
1433
third_party/FreeRDP/client/common/test/testRdpFileUTF8.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1433
third_party/FreeRDP/client/common/test/testRdpFileUTF8.unchecked.json
vendored
Normal file
1433
third_party/FreeRDP/client/common/test/testRdpFileUTF8.unchecked.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user