Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
268
third_party/FreeRDP/winpr/libwinpr/CMakeLists.txt
vendored
Normal file
268
third_party/FreeRDP/winpr/libwinpr/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# winpr cmake build script
|
||||
#
|
||||
# Copyright 2012 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.
|
||||
|
||||
include(CheckFunctionExists)
|
||||
include(JsonDetect)
|
||||
|
||||
set(WINPR_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(WINPR_SRCS "")
|
||||
set(WINPR_LIBS_PRIVATE "")
|
||||
set(WINPR_LIBS_PUBLIC "")
|
||||
set(WINPR_INCLUDES "")
|
||||
set(WINPR_SYSTEM_INCLUDES "")
|
||||
set(WINPR_DEFINITIONS "")
|
||||
set(WINPR_COMPILE_OPTIONS "")
|
||||
set(WINPR_LINK_OPTIONS "")
|
||||
set(WINPR_LINK_DIRS "")
|
||||
|
||||
macro(winpr_module_add)
|
||||
file(RELATIVE_PATH _relPath "${WINPR_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
foreach(_src ${ARGN})
|
||||
if(_relPath)
|
||||
list(APPEND WINPR_SRCS "${_relPath}/${_src}")
|
||||
else()
|
||||
list(APPEND WINPR_SRCS "${_src}")
|
||||
endif()
|
||||
endforeach()
|
||||
if(_relPath)
|
||||
set(WINPR_SRCS ${WINPR_SRCS} PARENT_SCOPE)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(winpr_include_directory_add)
|
||||
file(RELATIVE_PATH _relPath "${WINPR_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
foreach(_inc ${ARGN})
|
||||
if(IS_ABSOLUTE ${_inc})
|
||||
list(APPEND WINPR_INCLUDES "${_inc}")
|
||||
else()
|
||||
if(_relPath)
|
||||
list(APPEND WINPR_INCLUDES "${_relPath}/${_inc}")
|
||||
else()
|
||||
list(APPEND WINPR_INCLUDES "${_inc}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
if(_relPath)
|
||||
set(WINPR_INCLUDES ${WINPR_INCLUDES} PARENT_SCOPE)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(winpr_system_include_directory_add)
|
||||
file(RELATIVE_PATH _relPath "${WINPR_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
foreach(_inc ${ARGN})
|
||||
if(IS_ABSOLUTE ${_inc})
|
||||
list(APPEND WINPR_SYSTEM_INCLUDES "${_inc}")
|
||||
else()
|
||||
if(_relPath)
|
||||
list(APPEND WINPR_SYSTEM_INCLUDES "${_relPath}/${_inc}")
|
||||
else()
|
||||
list(APPEND WINPR_SYSTEM_INCLUDES "${_inc}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
if(_relPath)
|
||||
set(WINPR_SYSTEM_INCLUDES ${WINPR_SYSTEM_INCLUDES} PARENT_SCOPE)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(winpr_library_add_private)
|
||||
foreach(_lib ${ARGN})
|
||||
list(APPEND WINPR_LIBS_PRIVATE "${_lib}")
|
||||
endforeach()
|
||||
set(WINPR_LIBS_PRIVATE ${WINPR_LIBS_PRIVATE} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
macro(winpr_library_add_public)
|
||||
foreach(_lib ${ARGN})
|
||||
list(APPEND WINPR_LIBS_PUBLIC "${_lib}")
|
||||
endforeach()
|
||||
set(WINPR_LIBS_PUBLIC ${WINPR_LIBS_PUBLIC} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
macro(winpr_definition_add)
|
||||
foreach(_define ${ARGN})
|
||||
list(APPEND WINPR_DEFINITIONS "${_define}")
|
||||
endforeach()
|
||||
set(WINPR_DEFINITIONS ${WINPR_DEFINITIONS} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
macro(winpr_library_add_compile_options)
|
||||
foreach(_define ${ARGN})
|
||||
list(APPEND WINPR_COMPILE_OPTIONS "${_define}")
|
||||
endforeach()
|
||||
set(WINPR_COMPILE_OPTIONS ${WINPR_COMPILE_OPTIONS} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
macro(winpr_library_add_link_options)
|
||||
foreach(_define ${ARGN})
|
||||
list(APPEND WINPR_LINK_OPTIONS "${_define}")
|
||||
endforeach()
|
||||
set(WINPR_LINK_OPTIONS ${WINPR_LINK_OPTIONS} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
macro(winpr_library_add_link_directory)
|
||||
foreach(_define ${ARGN})
|
||||
list(APPEND WINPR_LINK_DIRS "${_define}")
|
||||
endforeach()
|
||||
set(WINPR_LINK_DIRS ${WINPR_LINK_DIRS} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES rt)
|
||||
|
||||
find_package(uriparser)
|
||||
option(WITH_URIPARSER "use uriparser library to handle URIs" ${uriparser_FOUND})
|
||||
if(WITH_URIPARSER)
|
||||
find_package(uriparser CONFIG COMPONENTS char)
|
||||
if(uriparser_FOUND)
|
||||
winpr_library_add_private(uriparser::uriparser)
|
||||
else()
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(uriparser REQUIRED liburiparser)
|
||||
winpr_system_include_directory_add(${uriparser_INCLUDEDIR})
|
||||
winpr_system_include_directory_add(${uriparser_INCLUDE_DIRS})
|
||||
winpr_library_add_private(${uriparser_LIBRARIES})
|
||||
endif()
|
||||
add_compile_definitions("WITH_URIPARSER")
|
||||
winpr_pc_add_requires_private("liburiparser")
|
||||
endif()
|
||||
|
||||
if(NOT IOS)
|
||||
check_function_exists(timer_create TIMER_CREATE)
|
||||
check_function_exists(timer_delete TIMER_DELETE)
|
||||
check_function_exists(timer_settime TIMER_SETTIME)
|
||||
check_function_exists(timer_gettime TIMER_GETTIME)
|
||||
if(TIMER_CREATE AND TIMER_DELETE AND TIMER_SETTIME AND TIMER_GETTIME)
|
||||
add_compile_definitions(WITH_POSIX_TIMER)
|
||||
winpr_library_add_private(rt)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_function_exists(pthread_setschedprio PTHREAD_SETSCHEDPRIO)
|
||||
if(PTHREAD_SETSCHEDPRIO)
|
||||
winpr_definition_add(PTHREAD_SETSCHEDPRIO)
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
winpr_library_add_private(log)
|
||||
endif()
|
||||
|
||||
# Level "1" API as defined for MinCore.lib
|
||||
set(WINPR_CORE
|
||||
synch
|
||||
library
|
||||
file
|
||||
comm
|
||||
credentials
|
||||
pipe
|
||||
interlocked
|
||||
security
|
||||
environment
|
||||
crypto
|
||||
registry
|
||||
path
|
||||
io
|
||||
memory
|
||||
ncrypt
|
||||
input
|
||||
shell
|
||||
utils
|
||||
error
|
||||
timezone
|
||||
sysinfo
|
||||
pool
|
||||
handle
|
||||
thread
|
||||
)
|
||||
|
||||
foreach(DIR ${WINPR_CORE})
|
||||
add_subdirectory(${DIR})
|
||||
source_group("${DIR}" REGULAR_EXPRESSION "${DIR}/.*\\.[ch]")
|
||||
endforeach()
|
||||
|
||||
set(WINPR_LEVEL2
|
||||
winsock
|
||||
sspi
|
||||
sspicli
|
||||
crt
|
||||
bcrypt
|
||||
rpc
|
||||
wtsapi
|
||||
dsparse
|
||||
smartcard
|
||||
nt
|
||||
clipboard
|
||||
)
|
||||
|
||||
foreach(DIR ${WINPR_LEVEL2})
|
||||
add_subdirectory(${DIR})
|
||||
source_group("${DIR}" REGULAR_EXPRESSION "${DIR}/.*\\.[ch]")
|
||||
endforeach()
|
||||
|
||||
set(MODULE_NAME winpr)
|
||||
list(REMOVE_DUPLICATES WINPR_DEFINITIONS)
|
||||
list(REMOVE_DUPLICATES WINPR_COMPILE_OPTIONS)
|
||||
list(REMOVE_DUPLICATES WINPR_LINK_OPTIONS)
|
||||
list(REMOVE_DUPLICATES WINPR_LINK_DIRS)
|
||||
list(REMOVE_DUPLICATES WINPR_INCLUDES)
|
||||
list(REMOVE_DUPLICATES WINPR_SYSTEM_INCLUDES)
|
||||
|
||||
addtargetwithresourcefile(${MODULE_NAME} FALSE "${WINPR_VERSION}" WINPR_SRCS)
|
||||
|
||||
if(WITH_RESOURCE_VERSIONING)
|
||||
target_compile_definitions(${MODULE_NAME} PRIVATE WITH_RESOURCE_VERSIONING)
|
||||
endif()
|
||||
if(WINPR_USE_VENDOR_PRODUCT_CONFIG_DIR)
|
||||
target_compile_definitions(${MODULE_NAME} PRIVATE WINPR_USE_VENDOR_PRODUCT_CONFIG_DIR)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION FALSE)
|
||||
endif()
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
set(LINK_OPTS_MODE PUBLIC)
|
||||
else()
|
||||
set(LINK_OPTS_MODE PRIVATE)
|
||||
endif()
|
||||
target_link_options(${MODULE_NAME} ${LINK_OPTS_MODE} ${WINPR_LINK_OPTIONS})
|
||||
target_include_directories(${MODULE_NAME} PRIVATE ${WINPR_INCLUDES})
|
||||
target_include_directories(${MODULE_NAME} SYSTEM PRIVATE ${WINPR_SYSTEM_INCLUDES})
|
||||
target_include_directories(${MODULE_NAME} INTERFACE $<INSTALL_INTERFACE:include/winpr${WINPR_VERSION_MAJOR}>)
|
||||
target_link_directories(${MODULE_NAME} PRIVATE ${WINPR_LINK_DIRS})
|
||||
target_compile_options(${MODULE_NAME} PRIVATE ${WINPR_COMPILE_OPTIONS})
|
||||
target_compile_definitions(${MODULE_NAME} PRIVATE ${WINPR_DEFINITIONS})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} PRIVATE ${WINPR_LIBS_PRIVATE} PUBLIC ${WINPR_LIBS_PUBLIC})
|
||||
installwithrpath(
|
||||
TARGETS
|
||||
${MODULE_NAME}
|
||||
COMPONENT
|
||||
libraries
|
||||
EXPORT
|
||||
WinPRTargets
|
||||
ARCHIVE
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/libwinpr")
|
||||
22
third_party/FreeRDP/winpr/libwinpr/bcrypt/CMakeLists.txt
vendored
Normal file
22
third_party/FreeRDP/winpr/libwinpr/bcrypt/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-bcrypt cmake build script
|
||||
#
|
||||
# Copyright 2012 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.
|
||||
|
||||
winpr_module_add(bcrypt.c)
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
7
third_party/FreeRDP/winpr/libwinpr/bcrypt/ModuleOptions.cmake
vendored
Normal file
7
third_party/FreeRDP/winpr/libwinpr/bcrypt/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
set(MINWIN_LAYER "0")
|
||||
set(MINWIN_GROUP "none")
|
||||
set(MINWIN_MAJOR_VERSION "0")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "bcrypt")
|
||||
set(MINWIN_LONG_NAME "Cryptography API: Next Generation (CNG)")
|
||||
set(MODULE_LIBRARY_NAME "${MINWIN_SHORT_NAME}")
|
||||
154
third_party/FreeRDP/winpr/libwinpr/bcrypt/bcrypt.c
vendored
Normal file
154
third_party/FreeRDP/winpr/libwinpr/bcrypt/bcrypt.c
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Cryptography API: Next Generation
|
||||
*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <winpr/bcrypt.h>
|
||||
|
||||
/**
|
||||
* Cryptography API: Next Generation:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa376210/
|
||||
*/
|
||||
|
||||
NTSTATUS BCryptOpenAlgorithmProvider(WINPR_ATTR_UNUSED BCRYPT_ALG_HANDLE* phAlgorithm,
|
||||
WINPR_ATTR_UNUSED LPCWSTR pszAlgId,
|
||||
WINPR_ATTR_UNUSED LPCWSTR pszImplementation,
|
||||
WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptCloseAlgorithmProvider(WINPR_ATTR_UNUSED BCRYPT_ALG_HANDLE hAlgorithm,
|
||||
WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptGetProperty(WINPR_ATTR_UNUSED BCRYPT_HANDLE hObject,
|
||||
WINPR_ATTR_UNUSED LPCWSTR pszProperty, WINPR_ATTR_UNUSED PUCHAR pbOutput,
|
||||
WINPR_ATTR_UNUSED ULONG cbOutput, WINPR_ATTR_UNUSED ULONG* pcbResult,
|
||||
WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptCreateHash(WINPR_ATTR_UNUSED BCRYPT_ALG_HANDLE hAlgorithm,
|
||||
WINPR_ATTR_UNUSED BCRYPT_HASH_HANDLE* phHash,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbHashObject,
|
||||
WINPR_ATTR_UNUSED ULONG cbHashObject, WINPR_ATTR_UNUSED PUCHAR pbSecret,
|
||||
WINPR_ATTR_UNUSED ULONG cbSecret, WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptDestroyHash(WINPR_ATTR_UNUSED BCRYPT_HASH_HANDLE hHash)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptHashData(WINPR_ATTR_UNUSED BCRYPT_HASH_HANDLE hHash,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbInput, WINPR_ATTR_UNUSED ULONG cbInput,
|
||||
WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptFinishHash(WINPR_ATTR_UNUSED BCRYPT_HASH_HANDLE hHash,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbOutput, WINPR_ATTR_UNUSED ULONG cbOutput,
|
||||
WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptGenRandom(WINPR_ATTR_UNUSED BCRYPT_ALG_HANDLE hAlgorithm,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbBuffer, WINPR_ATTR_UNUSED ULONG cbBuffer,
|
||||
WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptGenerateSymmetricKey(WINPR_ATTR_UNUSED BCRYPT_ALG_HANDLE hAlgorithm,
|
||||
WINPR_ATTR_UNUSED BCRYPT_KEY_HANDLE* phKey,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbKeyObject,
|
||||
WINPR_ATTR_UNUSED ULONG cbKeyObject,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbSecret,
|
||||
WINPR_ATTR_UNUSED ULONG cbSecret,
|
||||
WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptGenerateKeyPair(WINPR_ATTR_UNUSED BCRYPT_ALG_HANDLE hAlgorithm,
|
||||
WINPR_ATTR_UNUSED BCRYPT_KEY_HANDLE* phKey,
|
||||
WINPR_ATTR_UNUSED ULONG dwLength, WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptImportKey(WINPR_ATTR_UNUSED BCRYPT_ALG_HANDLE hAlgorithm,
|
||||
WINPR_ATTR_UNUSED BCRYPT_KEY_HANDLE hImportKey,
|
||||
WINPR_ATTR_UNUSED LPCWSTR pszBlobType,
|
||||
WINPR_ATTR_UNUSED BCRYPT_KEY_HANDLE* phKey,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbKeyObject, WINPR_ATTR_UNUSED ULONG cbKeyObject,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbInput, WINPR_ATTR_UNUSED ULONG cbInput,
|
||||
WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptDestroyKey(WINPR_ATTR_UNUSED BCRYPT_KEY_HANDLE hKey)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptEncrypt(WINPR_ATTR_UNUSED BCRYPT_KEY_HANDLE hKey, WINPR_ATTR_UNUSED PUCHAR pbInput,
|
||||
WINPR_ATTR_UNUSED ULONG cbInput, WINPR_ATTR_UNUSED VOID* pPaddingInfo,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbIV, WINPR_ATTR_UNUSED ULONG cbIV,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbOutput, WINPR_ATTR_UNUSED ULONG cbOutput,
|
||||
WINPR_ATTR_UNUSED ULONG* pcbResult, WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS BCryptDecrypt(WINPR_ATTR_UNUSED BCRYPT_KEY_HANDLE hKey, WINPR_ATTR_UNUSED PUCHAR pbInput,
|
||||
WINPR_ATTR_UNUSED ULONG cbInput, WINPR_ATTR_UNUSED VOID* pPaddingInfo,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbIV, WINPR_ATTR_UNUSED ULONG cbIV,
|
||||
WINPR_ATTR_UNUSED PUCHAR pbOutput, WINPR_ATTR_UNUSED ULONG cbOutput,
|
||||
WINPR_ATTR_UNUSED ULONG* pcbResult, WINPR_ATTR_UNUSED ULONG dwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
21
third_party/FreeRDP/winpr/libwinpr/bcrypt/test/CMakeLists.txt
vendored
Normal file
21
third_party/FreeRDP/winpr/libwinpr/bcrypt/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
set(MODULE_NAME "TestBCrypt")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(TESTS TestBCryptDefine.c)
|
||||
|
||||
create_test_sourcelist(SRCS ${DRIVER} ${TESTS})
|
||||
add_executable(${MODULE_NAME} ${SRCS})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
foreach(test ${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 "WinPR/Test")
|
||||
129
third_party/FreeRDP/winpr/libwinpr/bcrypt/test/TestBCryptDefine.c
vendored
Normal file
129
third_party/FreeRDP/winpr/libwinpr/bcrypt/test/TestBCryptDefine.c
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/bcrypt.h>
|
||||
|
||||
#define STR(x) #x
|
||||
|
||||
static BOOL test_wchar_len(void)
|
||||
{
|
||||
struct test_case
|
||||
{
|
||||
size_t bytelen;
|
||||
const char* name;
|
||||
const WCHAR* value;
|
||||
};
|
||||
|
||||
const struct test_case test_cases[] = {
|
||||
{ sizeof(BCRYPT_RSA_ALGORITHM), STR(BCRYPT_RSA_ALGORITHM), BCRYPT_RSA_ALGORITHM },
|
||||
{ sizeof(BCRYPT_RSA_SIGN_ALGORITHM), STR(BCRYPT_RSA_SIGN_ALGORITHM),
|
||||
BCRYPT_RSA_SIGN_ALGORITHM },
|
||||
{ sizeof(BCRYPT_DH_ALGORITHM), STR(BCRYPT_DH_ALGORITHM), BCRYPT_DH_ALGORITHM },
|
||||
{ sizeof(BCRYPT_DSA_ALGORITHM), STR(BCRYPT_DSA_ALGORITHM), BCRYPT_DSA_ALGORITHM },
|
||||
{ sizeof(BCRYPT_RC2_ALGORITHM), STR(BCRYPT_RC2_ALGORITHM), BCRYPT_RC2_ALGORITHM },
|
||||
{ sizeof(BCRYPT_RC4_ALGORITHM), STR(BCRYPT_RC4_ALGORITHM), BCRYPT_RC4_ALGORITHM },
|
||||
{ sizeof(BCRYPT_AES_ALGORITHM), STR(BCRYPT_AES_ALGORITHM), BCRYPT_AES_ALGORITHM },
|
||||
{ sizeof(BCRYPT_DES_ALGORITHM), STR(BCRYPT_DES_ALGORITHM), BCRYPT_DES_ALGORITHM },
|
||||
{ sizeof(BCRYPT_DESX_ALGORITHM), STR(BCRYPT_DESX_ALGORITHM), BCRYPT_DESX_ALGORITHM },
|
||||
{ sizeof(BCRYPT_3DES_ALGORITHM), STR(BCRYPT_3DES_ALGORITHM), BCRYPT_3DES_ALGORITHM },
|
||||
{ sizeof(BCRYPT_3DES_112_ALGORITHM), STR(BCRYPT_3DES_112_ALGORITHM),
|
||||
BCRYPT_3DES_112_ALGORITHM },
|
||||
{ sizeof(BCRYPT_MD2_ALGORITHM), STR(BCRYPT_MD2_ALGORITHM), BCRYPT_MD2_ALGORITHM },
|
||||
{ sizeof(BCRYPT_MD4_ALGORITHM), STR(BCRYPT_MD4_ALGORITHM), BCRYPT_MD4_ALGORITHM },
|
||||
{ sizeof(BCRYPT_MD5_ALGORITHM), STR(BCRYPT_MD5_ALGORITHM), BCRYPT_MD5_ALGORITHM },
|
||||
{ sizeof(BCRYPT_SHA1_ALGORITHM), STR(BCRYPT_SHA1_ALGORITHM), BCRYPT_SHA1_ALGORITHM },
|
||||
{ sizeof(BCRYPT_SHA256_ALGORITHM), STR(BCRYPT_SHA256_ALGORITHM), BCRYPT_SHA256_ALGORITHM },
|
||||
{ sizeof(BCRYPT_SHA384_ALGORITHM), STR(BCRYPT_SHA384_ALGORITHM), BCRYPT_SHA384_ALGORITHM },
|
||||
{ sizeof(BCRYPT_SHA512_ALGORITHM), STR(BCRYPT_SHA512_ALGORITHM), BCRYPT_SHA512_ALGORITHM },
|
||||
{ sizeof(BCRYPT_AES_GMAC_ALGORITHM), STR(BCRYPT_AES_GMAC_ALGORITHM),
|
||||
BCRYPT_AES_GMAC_ALGORITHM },
|
||||
{ sizeof(BCRYPT_AES_CMAC_ALGORITHM), STR(BCRYPT_AES_CMAC_ALGORITHM),
|
||||
BCRYPT_AES_CMAC_ALGORITHM },
|
||||
{ sizeof(BCRYPT_ECDSA_P256_ALGORITHM), STR(BCRYPT_ECDSA_P256_ALGORITHM),
|
||||
BCRYPT_ECDSA_P256_ALGORITHM },
|
||||
{ sizeof(BCRYPT_ECDSA_P384_ALGORITHM), STR(BCRYPT_ECDSA_P384_ALGORITHM),
|
||||
BCRYPT_ECDSA_P384_ALGORITHM },
|
||||
{ sizeof(BCRYPT_ECDSA_P521_ALGORITHM), STR(BCRYPT_ECDSA_P521_ALGORITHM),
|
||||
BCRYPT_ECDSA_P521_ALGORITHM },
|
||||
{ sizeof(BCRYPT_ECDH_P256_ALGORITHM), STR(BCRYPT_ECDH_P256_ALGORITHM),
|
||||
BCRYPT_ECDH_P256_ALGORITHM },
|
||||
{ sizeof(BCRYPT_ECDH_P384_ALGORITHM), STR(BCRYPT_ECDH_P384_ALGORITHM),
|
||||
BCRYPT_ECDH_P384_ALGORITHM },
|
||||
{ sizeof(BCRYPT_ECDH_P521_ALGORITHM), STR(BCRYPT_ECDH_P521_ALGORITHM),
|
||||
BCRYPT_ECDH_P521_ALGORITHM },
|
||||
{ sizeof(BCRYPT_RNG_ALGORITHM), STR(BCRYPT_RNG_ALGORITHM), BCRYPT_RNG_ALGORITHM },
|
||||
{ sizeof(BCRYPT_RNG_FIPS186_DSA_ALGORITHM), STR(BCRYPT_RNG_FIPS186_DSA_ALGORITHM),
|
||||
BCRYPT_RNG_FIPS186_DSA_ALGORITHM },
|
||||
{ sizeof(BCRYPT_RNG_DUAL_EC_ALGORITHM), STR(BCRYPT_RNG_DUAL_EC_ALGORITHM),
|
||||
BCRYPT_RNG_DUAL_EC_ALGORITHM },
|
||||
// The following algorithms are only supported on windows 10 onward.
|
||||
#if !defined(_WIN32) || _WIN32_WINNT >= 0x0A00
|
||||
{ sizeof(BCRYPT_ECDSA_ALGORITHM), STR(BCRYPT_ECDSA_ALGORITHM), BCRYPT_ECDSA_ALGORITHM },
|
||||
{ sizeof(BCRYPT_ECDH_ALGORITHM), STR(BCRYPT_ECDH_ALGORITHM), BCRYPT_ECDH_ALGORITHM },
|
||||
{ sizeof(BCRYPT_XTS_AES_ALGORITHM), STR(BCRYPT_XTS_AES_ALGORITHM),
|
||||
BCRYPT_XTS_AES_ALGORITHM },
|
||||
#endif
|
||||
|
||||
{ sizeof(MS_PRIMITIVE_PROVIDER), STR(MS_PRIMITIVE_PROVIDER), MS_PRIMITIVE_PROVIDER },
|
||||
{ sizeof(MS_PLATFORM_CRYPTO_PROVIDER), STR(MS_PLATFORM_CRYPTO_PROVIDER),
|
||||
MS_PLATFORM_CRYPTO_PROVIDER },
|
||||
{ sizeof(BCRYPT_OBJECT_LENGTH), STR(BCRYPT_OBJECT_LENGTH), BCRYPT_OBJECT_LENGTH },
|
||||
{ sizeof(BCRYPT_ALGORITHM_NAME), STR(BCRYPT_ALGORITHM_NAME), BCRYPT_ALGORITHM_NAME },
|
||||
{ sizeof(BCRYPT_PROVIDER_HANDLE), STR(BCRYPT_PROVIDER_HANDLE), BCRYPT_PROVIDER_HANDLE },
|
||||
{ sizeof(BCRYPT_CHAINING_MODE), STR(BCRYPT_CHAINING_MODE), BCRYPT_CHAINING_MODE },
|
||||
{ sizeof(BCRYPT_BLOCK_LENGTH), STR(BCRYPT_BLOCK_LENGTH), BCRYPT_BLOCK_LENGTH },
|
||||
{ sizeof(BCRYPT_KEY_LENGTH), STR(BCRYPT_KEY_LENGTH), BCRYPT_KEY_LENGTH },
|
||||
{ sizeof(BCRYPT_KEY_OBJECT_LENGTH), STR(BCRYPT_KEY_OBJECT_LENGTH),
|
||||
BCRYPT_KEY_OBJECT_LENGTH },
|
||||
{ sizeof(BCRYPT_KEY_STRENGTH), STR(BCRYPT_KEY_STRENGTH), BCRYPT_KEY_STRENGTH },
|
||||
{ sizeof(BCRYPT_KEY_LENGTHS), STR(BCRYPT_KEY_LENGTHS), BCRYPT_KEY_LENGTHS },
|
||||
{ sizeof(BCRYPT_BLOCK_SIZE_LIST), STR(BCRYPT_BLOCK_SIZE_LIST), BCRYPT_BLOCK_SIZE_LIST },
|
||||
{ sizeof(BCRYPT_EFFECTIVE_KEY_LENGTH), STR(BCRYPT_EFFECTIVE_KEY_LENGTH),
|
||||
BCRYPT_EFFECTIVE_KEY_LENGTH },
|
||||
{ sizeof(BCRYPT_HASH_LENGTH), STR(BCRYPT_HASH_LENGTH), BCRYPT_HASH_LENGTH },
|
||||
{ sizeof(BCRYPT_HASH_OID_LIST), STR(BCRYPT_HASH_OID_LIST), BCRYPT_HASH_OID_LIST },
|
||||
{ sizeof(BCRYPT_PADDING_SCHEMES), STR(BCRYPT_PADDING_SCHEMES), BCRYPT_PADDING_SCHEMES },
|
||||
{ sizeof(BCRYPT_SIGNATURE_LENGTH), STR(BCRYPT_SIGNATURE_LENGTH), BCRYPT_SIGNATURE_LENGTH },
|
||||
{ sizeof(BCRYPT_HASH_BLOCK_LENGTH), STR(BCRYPT_HASH_BLOCK_LENGTH),
|
||||
BCRYPT_HASH_BLOCK_LENGTH },
|
||||
{ sizeof(BCRYPT_AUTH_TAG_LENGTH), STR(BCRYPT_AUTH_TAG_LENGTH), BCRYPT_AUTH_TAG_LENGTH },
|
||||
{ sizeof(BCRYPT_PRIMITIVE_TYPE), STR(BCRYPT_PRIMITIVE_TYPE), BCRYPT_PRIMITIVE_TYPE },
|
||||
{ sizeof(BCRYPT_IS_KEYED_HASH), STR(BCRYPT_IS_KEYED_HASH), BCRYPT_IS_KEYED_HASH },
|
||||
{ sizeof(BCRYPT_KEY_DATA_BLOB), STR(BCRYPT_KEY_DATA_BLOB), BCRYPT_KEY_DATA_BLOB }
|
||||
};
|
||||
|
||||
BOOL rc = TRUE;
|
||||
for (size_t x = 0; x < ARRAYSIZE(test_cases); x++)
|
||||
{
|
||||
const struct test_case* cur = &test_cases[x];
|
||||
|
||||
// sizeof(WCHAR) == 2, so all strings must have even byte length
|
||||
if (cur->bytelen % 2 != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "[%s] invalid bytelength %" PRIuz, cur->name, cur->bytelen);
|
||||
rc = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
// each string must be '\0' terminated
|
||||
const size_t len = _wcsnlen(cur->value, cur->bytelen / sizeof(WCHAR));
|
||||
if (len == cur->bytelen / sizeof(WCHAR))
|
||||
{
|
||||
(void)fprintf(stderr, "[%s] missing '\0' termination", cur->name);
|
||||
rc = FALSE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestBCryptDefine(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (!test_wchar_len())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
22
third_party/FreeRDP/winpr/libwinpr/clipboard/CMakeLists.txt
vendored
Normal file
22
third_party/FreeRDP/winpr/libwinpr/clipboard/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-clipboard cmake build script
|
||||
#
|
||||
# Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
winpr_module_add(synthetic.c clipboard.c clipboard.h synthetic_file.h synthetic_file.c)
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
7
third_party/FreeRDP/winpr/libwinpr/clipboard/ModuleOptions.cmake
vendored
Normal file
7
third_party/FreeRDP/winpr/libwinpr/clipboard/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
set(MINWIN_LAYER "0")
|
||||
set(MINWIN_GROUP "none")
|
||||
set(MINWIN_MAJOR_VERSION "0")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "clipboard")
|
||||
set(MINWIN_LONG_NAME "Clipboard Functions")
|
||||
set(MODULE_LIBRARY_NAME "clipboard")
|
||||
771
third_party/FreeRDP/winpr/libwinpr/clipboard/clipboard.c
vendored
Normal file
771
third_party/FreeRDP/winpr/libwinpr/clipboard/clipboard.c
vendored
Normal file
@@ -0,0 +1,771 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Clipboard Functions
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/collections.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#include <winpr/clipboard.h>
|
||||
|
||||
#include "clipboard.h"
|
||||
|
||||
#include "synthetic_file.h"
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("clipboard")
|
||||
|
||||
const char* const mime_text_plain = "text/plain";
|
||||
|
||||
/**
|
||||
* Clipboard (Windows):
|
||||
* msdn.microsoft.com/en-us/library/windows/desktop/ms648709/
|
||||
*
|
||||
* W3C Clipboard API and events:
|
||||
* http://www.w3.org/TR/clipboard-apis/
|
||||
*/
|
||||
|
||||
static const char* CF_STANDARD_STRINGS[] = {
|
||||
"CF_RAW", /* 0 */
|
||||
"CF_TEXT", /* 1 */
|
||||
"CF_BITMAP", /* 2 */
|
||||
"CF_METAFILEPICT", /* 3 */
|
||||
"CF_SYLK", /* 4 */
|
||||
"CF_DIF", /* 5 */
|
||||
"CF_TIFF", /* 6 */
|
||||
"CF_OEMTEXT", /* 7 */
|
||||
"CF_DIB", /* 8 */
|
||||
"CF_PALETTE", /* 9 */
|
||||
"CF_PENDATA", /* 10 */
|
||||
"CF_RIFF", /* 11 */
|
||||
"CF_WAVE", /* 12 */
|
||||
"CF_UNICODETEXT", /* 13 */
|
||||
"CF_ENHMETAFILE", /* 14 */
|
||||
"CF_HDROP", /* 15 */
|
||||
"CF_LOCALE", /* 16 */
|
||||
"CF_DIBV5" /* 17 */
|
||||
};
|
||||
|
||||
const char* ClipboardGetFormatIdString(UINT32 formatId)
|
||||
{
|
||||
if (formatId < ARRAYSIZE(CF_STANDARD_STRINGS))
|
||||
return CF_STANDARD_STRINGS[formatId];
|
||||
return "CF_REGISTERED_FORMAT";
|
||||
}
|
||||
|
||||
static wClipboardFormat* ClipboardFindFormat(wClipboard* clipboard, UINT32 formatId,
|
||||
const char* name)
|
||||
{
|
||||
wClipboardFormat* format = nullptr;
|
||||
|
||||
if (!clipboard)
|
||||
return nullptr;
|
||||
|
||||
if (formatId)
|
||||
{
|
||||
for (UINT32 index = 0; index < clipboard->numFormats; index++)
|
||||
{
|
||||
wClipboardFormat* cformat = &clipboard->formats[index];
|
||||
if (formatId == cformat->formatId)
|
||||
{
|
||||
format = cformat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (name)
|
||||
{
|
||||
for (UINT32 index = 0; index < clipboard->numFormats; index++)
|
||||
{
|
||||
wClipboardFormat* cformat = &clipboard->formats[index];
|
||||
if (!cformat->formatName)
|
||||
continue;
|
||||
|
||||
if (strcmp(name, cformat->formatName) == 0)
|
||||
{
|
||||
format = cformat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* special "CF_RAW" case */
|
||||
if (clipboard->numFormats > 0)
|
||||
{
|
||||
format = &clipboard->formats[0];
|
||||
|
||||
if (format->formatId)
|
||||
return nullptr;
|
||||
|
||||
if (!format->formatName || (strcmp(format->formatName, CF_STANDARD_STRINGS[0]) == 0))
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static wClipboardSynthesizer* ClipboardFindSynthesizer(wClipboardFormat* format, UINT32 formatId)
|
||||
{
|
||||
if (!format)
|
||||
return nullptr;
|
||||
|
||||
for (UINT32 index = 0; index < format->numSynthesizers; index++)
|
||||
{
|
||||
wClipboardSynthesizer* synthesizer = &(format->synthesizers[index]);
|
||||
|
||||
if (formatId == synthesizer->syntheticId)
|
||||
return synthesizer;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ClipboardLock(wClipboard* clipboard)
|
||||
{
|
||||
if (!clipboard)
|
||||
return;
|
||||
|
||||
EnterCriticalSection(&(clipboard->lock));
|
||||
}
|
||||
|
||||
void ClipboardUnlock(wClipboard* clipboard)
|
||||
{
|
||||
if (!clipboard)
|
||||
return;
|
||||
|
||||
LeaveCriticalSection(&(clipboard->lock));
|
||||
}
|
||||
|
||||
BOOL ClipboardEmpty(wClipboard* clipboard)
|
||||
{
|
||||
if (!clipboard)
|
||||
return FALSE;
|
||||
|
||||
if (clipboard->data)
|
||||
{
|
||||
free(clipboard->data);
|
||||
clipboard->data = nullptr;
|
||||
}
|
||||
|
||||
clipboard->size = 0;
|
||||
clipboard->formatId = 0;
|
||||
clipboard->sequenceNumber++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UINT32 ClipboardCountRegisteredFormats(wClipboard* clipboard)
|
||||
{
|
||||
if (!clipboard)
|
||||
return 0;
|
||||
|
||||
return clipboard->numFormats;
|
||||
}
|
||||
|
||||
UINT32 ClipboardGetRegisteredFormatIds(wClipboard* clipboard, UINT32** ppFormatIds)
|
||||
{
|
||||
UINT32* pFormatIds = nullptr;
|
||||
wClipboardFormat* format = nullptr;
|
||||
|
||||
if (!clipboard)
|
||||
return 0;
|
||||
|
||||
if (!ppFormatIds)
|
||||
return 0;
|
||||
|
||||
pFormatIds = *ppFormatIds;
|
||||
|
||||
if (!pFormatIds)
|
||||
{
|
||||
pFormatIds = calloc(clipboard->numFormats, sizeof(UINT32));
|
||||
|
||||
if (!pFormatIds)
|
||||
return 0;
|
||||
|
||||
*ppFormatIds = pFormatIds;
|
||||
}
|
||||
|
||||
for (UINT32 index = 0; index < clipboard->numFormats; index++)
|
||||
{
|
||||
format = &(clipboard->formats[index]);
|
||||
pFormatIds[index] = format->formatId;
|
||||
}
|
||||
|
||||
return clipboard->numFormats;
|
||||
}
|
||||
|
||||
UINT32 ClipboardRegisterFormat(wClipboard* clipboard, const char* name)
|
||||
{
|
||||
wClipboardFormat* format = nullptr;
|
||||
|
||||
if (!clipboard)
|
||||
return 0;
|
||||
|
||||
format = ClipboardFindFormat(clipboard, 0, name);
|
||||
|
||||
if (format)
|
||||
return format->formatId;
|
||||
|
||||
if ((clipboard->numFormats + 1) >= clipboard->maxFormats)
|
||||
{
|
||||
UINT32 numFormats = clipboard->maxFormats * 2;
|
||||
wClipboardFormat* tmpFormat = nullptr;
|
||||
tmpFormat =
|
||||
(wClipboardFormat*)realloc(clipboard->formats, numFormats * sizeof(wClipboardFormat));
|
||||
|
||||
if (!tmpFormat)
|
||||
return 0;
|
||||
|
||||
clipboard->formats = tmpFormat;
|
||||
clipboard->maxFormats = numFormats;
|
||||
}
|
||||
|
||||
format = &(clipboard->formats[clipboard->numFormats]);
|
||||
ZeroMemory(format, sizeof(wClipboardFormat));
|
||||
|
||||
if (name)
|
||||
{
|
||||
format->formatName = _strdup(name);
|
||||
|
||||
if (!format->formatName)
|
||||
return 0;
|
||||
}
|
||||
|
||||
format->formatId = clipboard->nextFormatId++;
|
||||
clipboard->numFormats++;
|
||||
return format->formatId;
|
||||
}
|
||||
|
||||
BOOL ClipboardRegisterSynthesizer(wClipboard* clipboard, UINT32 formatId, UINT32 syntheticId,
|
||||
CLIPBOARD_SYNTHESIZE_FN pfnSynthesize)
|
||||
{
|
||||
UINT32 index = 0;
|
||||
wClipboardFormat* format = nullptr;
|
||||
wClipboardSynthesizer* synthesizer = nullptr;
|
||||
|
||||
if (!clipboard)
|
||||
return FALSE;
|
||||
|
||||
format = ClipboardFindFormat(clipboard, formatId, nullptr);
|
||||
|
||||
if (!format)
|
||||
return FALSE;
|
||||
|
||||
if (format->formatId == syntheticId)
|
||||
return FALSE;
|
||||
|
||||
synthesizer = ClipboardFindSynthesizer(format, formatId);
|
||||
|
||||
if (!synthesizer)
|
||||
{
|
||||
wClipboardSynthesizer* tmpSynthesizer = nullptr;
|
||||
UINT32 numSynthesizers = format->numSynthesizers + 1;
|
||||
tmpSynthesizer = (wClipboardSynthesizer*)realloc(
|
||||
format->synthesizers, numSynthesizers * sizeof(wClipboardSynthesizer));
|
||||
|
||||
if (!tmpSynthesizer)
|
||||
return FALSE;
|
||||
|
||||
format->synthesizers = tmpSynthesizer;
|
||||
format->numSynthesizers = numSynthesizers;
|
||||
index = numSynthesizers - 1;
|
||||
synthesizer = &(format->synthesizers[index]);
|
||||
}
|
||||
|
||||
synthesizer->syntheticId = syntheticId;
|
||||
synthesizer->pfnSynthesize = pfnSynthesize;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UINT32 ClipboardCountFormats(wClipboard* clipboard)
|
||||
{
|
||||
UINT32 count = 0;
|
||||
wClipboardFormat* format = nullptr;
|
||||
|
||||
if (!clipboard)
|
||||
return 0;
|
||||
|
||||
format = ClipboardFindFormat(clipboard, clipboard->formatId, nullptr);
|
||||
|
||||
if (!format)
|
||||
return 0;
|
||||
|
||||
count = 1 + format->numSynthesizers;
|
||||
return count;
|
||||
}
|
||||
|
||||
UINT32 ClipboardGetFormatIds(wClipboard* clipboard, UINT32** ppFormatIds)
|
||||
{
|
||||
UINT32 count = 0;
|
||||
UINT32* pFormatIds = nullptr;
|
||||
wClipboardFormat* format = nullptr;
|
||||
wClipboardSynthesizer* synthesizer = nullptr;
|
||||
|
||||
if (!clipboard)
|
||||
return 0;
|
||||
|
||||
format = ClipboardFindFormat(clipboard, clipboard->formatId, nullptr);
|
||||
|
||||
if (!format)
|
||||
return 0;
|
||||
|
||||
count = 1 + format->numSynthesizers;
|
||||
|
||||
if (!ppFormatIds)
|
||||
return 0;
|
||||
|
||||
pFormatIds = *ppFormatIds;
|
||||
|
||||
if (!pFormatIds)
|
||||
{
|
||||
pFormatIds = calloc(count, sizeof(UINT32));
|
||||
|
||||
if (!pFormatIds)
|
||||
return 0;
|
||||
|
||||
*ppFormatIds = pFormatIds;
|
||||
}
|
||||
|
||||
pFormatIds[0] = format->formatId;
|
||||
|
||||
for (UINT32 index = 1; index < count; index++)
|
||||
{
|
||||
synthesizer = &(format->synthesizers[index - 1]);
|
||||
pFormatIds[index] = synthesizer->syntheticId;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void ClipboardUninitFormats(wClipboard* clipboard)
|
||||
{
|
||||
WINPR_ASSERT(clipboard);
|
||||
for (UINT32 formatId = 0; formatId < clipboard->numFormats; formatId++)
|
||||
{
|
||||
wClipboardFormat* format = &clipboard->formats[formatId];
|
||||
free(format->formatName);
|
||||
free(format->synthesizers);
|
||||
format->formatName = nullptr;
|
||||
format->synthesizers = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL ClipboardInitFormats(wClipboard* clipboard)
|
||||
{
|
||||
UINT32 formatId = 0;
|
||||
wClipboardFormat* format = nullptr;
|
||||
|
||||
if (!clipboard)
|
||||
return FALSE;
|
||||
|
||||
for (formatId = 0; formatId < CF_MAX; formatId++, clipboard->numFormats++)
|
||||
{
|
||||
format = &(clipboard->formats[clipboard->numFormats]);
|
||||
ZeroMemory(format, sizeof(wClipboardFormat));
|
||||
format->formatId = formatId;
|
||||
format->formatName = _strdup(CF_STANDARD_STRINGS[formatId]);
|
||||
|
||||
if (!format->formatName)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!ClipboardInitSynthesizers(clipboard))
|
||||
goto error;
|
||||
|
||||
return TRUE;
|
||||
error:
|
||||
|
||||
ClipboardUninitFormats(clipboard);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UINT32 ClipboardGetFormatId(wClipboard* clipboard, const char* name)
|
||||
{
|
||||
wClipboardFormat* format = nullptr;
|
||||
|
||||
if (!clipboard)
|
||||
return 0;
|
||||
|
||||
format = ClipboardFindFormat(clipboard, 0, name);
|
||||
|
||||
if (!format)
|
||||
return 0;
|
||||
|
||||
return format->formatId;
|
||||
}
|
||||
|
||||
const char* ClipboardGetFormatName(wClipboard* clipboard, UINT32 formatId)
|
||||
{
|
||||
wClipboardFormat* format = nullptr;
|
||||
|
||||
if (!clipboard)
|
||||
return nullptr;
|
||||
|
||||
format = ClipboardFindFormat(clipboard, formatId, nullptr);
|
||||
|
||||
if (!format)
|
||||
return nullptr;
|
||||
|
||||
return format->formatName;
|
||||
}
|
||||
|
||||
void* ClipboardGetData(wClipboard* clipboard, UINT32 formatId, UINT32* pSize)
|
||||
{
|
||||
UINT32 SrcSize = 0;
|
||||
UINT32 DstSize = 0;
|
||||
void* pSrcData = nullptr;
|
||||
void* pDstData = nullptr;
|
||||
wClipboardFormat* format = nullptr;
|
||||
wClipboardSynthesizer* synthesizer = nullptr;
|
||||
|
||||
if (!clipboard || !pSize)
|
||||
{
|
||||
WLog_ERR(TAG, "Invalid parameters clipboard=%p, pSize=%p",
|
||||
WINPR_CXX_COMPAT_CAST(const void*, clipboard),
|
||||
WINPR_CXX_COMPAT_CAST(const void*, pSize));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*pSize = 0;
|
||||
format = ClipboardFindFormat(clipboard, clipboard->formatId, nullptr);
|
||||
|
||||
if (!format)
|
||||
{
|
||||
WLog_ERR(TAG, "Format [0x%08" PRIx32 "] not found", clipboard->formatId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SrcSize = clipboard->size;
|
||||
pSrcData = clipboard->data;
|
||||
|
||||
if (formatId == format->formatId)
|
||||
{
|
||||
DstSize = SrcSize;
|
||||
pDstData = malloc(DstSize);
|
||||
|
||||
if (!pDstData)
|
||||
return nullptr;
|
||||
|
||||
CopyMemory(pDstData, pSrcData, SrcSize);
|
||||
*pSize = DstSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
synthesizer = ClipboardFindSynthesizer(format, formatId);
|
||||
|
||||
if (!synthesizer || !synthesizer->pfnSynthesize)
|
||||
{
|
||||
WLog_ERR(TAG, "No synthesizer for format %s [0x%08" PRIx32 "] --> %s [0x%08" PRIx32 "]",
|
||||
ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId,
|
||||
ClipboardGetFormatName(clipboard, formatId), formatId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DstSize = SrcSize;
|
||||
pDstData = synthesizer->pfnSynthesize(clipboard, format->formatId, pSrcData, &DstSize);
|
||||
if (pDstData)
|
||||
*pSize = DstSize;
|
||||
}
|
||||
|
||||
WLog_DBG(TAG, "getting formatId=%s [0x%08" PRIx32 "] data=%p, size=%" PRIu32,
|
||||
ClipboardGetFormatName(clipboard, formatId), formatId, pDstData, *pSize);
|
||||
return pDstData;
|
||||
}
|
||||
|
||||
BOOL ClipboardSetData(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32 size)
|
||||
{
|
||||
wClipboardFormat* format = nullptr;
|
||||
|
||||
WLog_DBG(TAG, "setting formatId=%s [0x%08" PRIx32 "], size=%" PRIu32,
|
||||
ClipboardGetFormatName(clipboard, formatId), formatId, size);
|
||||
if (!clipboard)
|
||||
return FALSE;
|
||||
|
||||
format = ClipboardFindFormat(clipboard, formatId, nullptr);
|
||||
|
||||
if (!format)
|
||||
return FALSE;
|
||||
|
||||
free(clipboard->data);
|
||||
|
||||
clipboard->data = calloc(size + sizeof(WCHAR), sizeof(char));
|
||||
|
||||
if (!clipboard->data)
|
||||
return FALSE;
|
||||
|
||||
memcpy(clipboard->data, data, size);
|
||||
|
||||
/* For string values we don´t know if they are '\0' terminated.
|
||||
* so set the size to the full length in bytes (e.g. string length + 1)
|
||||
*/
|
||||
switch (formatId)
|
||||
{
|
||||
case CF_TEXT:
|
||||
case CF_OEMTEXT:
|
||||
clipboard->size = (UINT32)(strnlen(clipboard->data, size) + 1UL);
|
||||
break;
|
||||
case CF_UNICODETEXT:
|
||||
clipboard->size =
|
||||
(UINT32)((_wcsnlen(clipboard->data, size / sizeof(WCHAR)) + 1UL) * sizeof(WCHAR));
|
||||
break;
|
||||
default:
|
||||
clipboard->size = size;
|
||||
break;
|
||||
}
|
||||
|
||||
clipboard->formatId = formatId;
|
||||
clipboard->sequenceNumber++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UINT64 ClipboardGetOwner(wClipboard* clipboard)
|
||||
{
|
||||
if (!clipboard)
|
||||
return 0;
|
||||
|
||||
return clipboard->ownerId;
|
||||
}
|
||||
|
||||
void ClipboardSetOwner(wClipboard* clipboard, UINT64 ownerId)
|
||||
{
|
||||
if (!clipboard)
|
||||
return;
|
||||
|
||||
clipboard->ownerId = ownerId;
|
||||
}
|
||||
|
||||
wClipboardDelegate* ClipboardGetDelegate(wClipboard* clipboard)
|
||||
{
|
||||
if (!clipboard)
|
||||
return nullptr;
|
||||
|
||||
return &clipboard->delegate;
|
||||
}
|
||||
|
||||
static void ClipboardInitLocalFileSubsystem(wClipboard* clipboard)
|
||||
{
|
||||
/*
|
||||
* There can be only one local file subsystem active.
|
||||
* Return as soon as initialization succeeds.
|
||||
*/
|
||||
if (ClipboardInitSyntheticFileSubsystem(clipboard))
|
||||
{
|
||||
WLog_DBG(TAG, "initialized synthetic local file subsystem");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_WARN(TAG, "failed to initialize synthetic local file subsystem");
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "failed to initialize local file subsystem, file transfer not available");
|
||||
}
|
||||
|
||||
wClipboard* ClipboardCreate(void)
|
||||
{
|
||||
wClipboard* clipboard = (wClipboard*)calloc(1, sizeof(wClipboard));
|
||||
|
||||
if (!clipboard)
|
||||
return nullptr;
|
||||
|
||||
clipboard->nextFormatId = 0xC000;
|
||||
clipboard->sequenceNumber = 0;
|
||||
|
||||
if (!InitializeCriticalSectionAndSpinCount(&(clipboard->lock), 4000))
|
||||
goto fail;
|
||||
|
||||
clipboard->numFormats = 0;
|
||||
clipboard->maxFormats = 64;
|
||||
clipboard->formats = (wClipboardFormat*)calloc(clipboard->maxFormats, sizeof(wClipboardFormat));
|
||||
|
||||
if (!clipboard->formats)
|
||||
goto fail;
|
||||
|
||||
if (!ClipboardInitFormats(clipboard))
|
||||
goto fail;
|
||||
|
||||
clipboard->delegate.clipboard = clipboard;
|
||||
ClipboardInitLocalFileSubsystem(clipboard);
|
||||
return clipboard;
|
||||
fail:
|
||||
ClipboardDestroy(clipboard);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ClipboardDestroy(wClipboard* clipboard)
|
||||
{
|
||||
if (!clipboard)
|
||||
return;
|
||||
|
||||
ArrayList_Free(clipboard->localFiles);
|
||||
clipboard->localFiles = nullptr;
|
||||
|
||||
ClipboardUninitFormats(clipboard);
|
||||
|
||||
free(clipboard->data);
|
||||
clipboard->data = nullptr;
|
||||
clipboard->size = 0;
|
||||
clipboard->numFormats = 0;
|
||||
free(clipboard->formats);
|
||||
DeleteCriticalSection(&(clipboard->lock));
|
||||
free(clipboard);
|
||||
}
|
||||
|
||||
static BOOL is_dos_drive(const char* path, size_t len)
|
||||
{
|
||||
if (len < 2)
|
||||
return FALSE;
|
||||
|
||||
WINPR_ASSERT(path);
|
||||
if (path[1] == ':' || path[1] == '|')
|
||||
{
|
||||
if (((path[0] >= 'A') && (path[0] <= 'Z')) || ((path[0] >= 'a') && (path[0] <= 'z')))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char* parse_uri_to_local_file(const char* uri, size_t uri_len)
|
||||
{
|
||||
// URI is specified by RFC 8089: https://datatracker.ietf.org/doc/html/rfc8089
|
||||
const char prefix[] = "file:";
|
||||
const char prefixTraditional[] = "file://";
|
||||
const char* localName = nullptr;
|
||||
size_t localLen = 0;
|
||||
char* buffer = nullptr;
|
||||
const size_t prefixLen = strnlen(prefix, sizeof(prefix));
|
||||
const size_t prefixTraditionalLen = strnlen(prefixTraditional, sizeof(prefixTraditional));
|
||||
|
||||
WINPR_ASSERT(uri || (uri_len == 0));
|
||||
|
||||
WLog_VRB(TAG, "processing URI: %.*s", WINPR_ASSERTING_INT_CAST(int, uri_len), uri);
|
||||
|
||||
if ((uri_len <= prefixLen) || strncmp(uri, prefix, prefixLen) != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "non-'file:' URI schemes are not supported");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* https://datatracker.ietf.org/doc/html/rfc8089#appendix-F
|
||||
* - The minimal representation of a local file in a DOS- or Windows-
|
||||
* based environment with no authority field and an absolute path
|
||||
* that begins with a drive letter.
|
||||
*
|
||||
* "file:c:/path/to/file"
|
||||
*
|
||||
* - Regular DOS or Windows file URIs with vertical line characters in
|
||||
* the drive letter construct.
|
||||
*
|
||||
* "file:c|/path/to/file"
|
||||
*
|
||||
*/
|
||||
if (uri[prefixLen] != '/')
|
||||
{
|
||||
|
||||
if (is_dos_drive(&uri[prefixLen], uri_len - prefixLen))
|
||||
{
|
||||
// Dos and Windows file URI
|
||||
localName = &uri[prefixLen];
|
||||
localLen = uri_len - prefixLen;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "URI format are not supported: %s", uri);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* - The minimal representation of a local file with no authority field
|
||||
* and an absolute path that begins with a slash "/". For example:
|
||||
*
|
||||
* "file:/path/to/file"
|
||||
*
|
||||
*/
|
||||
else if ((uri_len > prefixLen + 1) && (uri[prefixLen + 1] != '/'))
|
||||
{
|
||||
if (is_dos_drive(&uri[prefixLen + 1], uri_len - prefixLen - 1))
|
||||
{
|
||||
// Dos and Windows file URI
|
||||
localName = (uri + prefixLen + 1);
|
||||
localLen = uri_len - prefixLen - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
localName = &uri[prefixLen];
|
||||
localLen = uri_len - prefixLen;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* - A traditional file URI for a local file with an empty authority.
|
||||
*
|
||||
* "file:///path/to/file"
|
||||
*/
|
||||
if ((uri_len < prefixTraditionalLen) ||
|
||||
strncmp(uri, prefixTraditional, prefixTraditionalLen) != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "non-'file:' URI schemes are not supported");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
localName = &uri[prefixTraditionalLen];
|
||||
localLen = uri_len - prefixTraditionalLen;
|
||||
|
||||
if (localLen < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "empty 'file:' URI schemes are not supported");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* "file:///c:/path/to/file"
|
||||
* "file:///c|/path/to/file"
|
||||
*/
|
||||
if (localName[0] != '/')
|
||||
{
|
||||
WLog_ERR(TAG, "URI format are not supported: %s", uri);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (is_dos_drive(&localName[1], localLen - 1))
|
||||
{
|
||||
localName++;
|
||||
localLen--;
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
buffer = winpr_str_url_decode(localName, localLen);
|
||||
if (buffer)
|
||||
{
|
||||
if (buffer[1] == '|' &&
|
||||
((buffer[0] >= 'A' && buffer[0] <= 'Z') || (buffer[0] >= 'a' && buffer[0] <= 'z')))
|
||||
buffer[1] = ':';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
77
third_party/FreeRDP/winpr/libwinpr/clipboard/clipboard.h
vendored
Normal file
77
third_party/FreeRDP/winpr/libwinpr/clipboard/clipboard.h
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Clipboard Functions
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WINPR_CLIPBOARD_PRIVATE_H
|
||||
#define WINPR_CLIPBOARD_PRIVATE_H
|
||||
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/clipboard.h>
|
||||
|
||||
#include <winpr/collections.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 syntheticId;
|
||||
CLIPBOARD_SYNTHESIZE_FN pfnSynthesize;
|
||||
} wClipboardSynthesizer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 formatId;
|
||||
char* formatName;
|
||||
|
||||
UINT32 numSynthesizers;
|
||||
wClipboardSynthesizer* synthesizers;
|
||||
} wClipboardFormat;
|
||||
|
||||
struct s_wClipboard
|
||||
{
|
||||
UINT64 ownerId;
|
||||
|
||||
/* clipboard formats */
|
||||
|
||||
UINT32 numFormats;
|
||||
UINT32 maxFormats;
|
||||
UINT32 nextFormatId;
|
||||
wClipboardFormat* formats;
|
||||
|
||||
/* clipboard data */
|
||||
|
||||
UINT32 size;
|
||||
void* data;
|
||||
UINT32 formatId;
|
||||
UINT32 sequenceNumber;
|
||||
|
||||
/* clipboard file handling */
|
||||
|
||||
wArrayList* localFiles;
|
||||
UINT32 fileListSequenceNumber;
|
||||
|
||||
wClipboardDelegate delegate;
|
||||
|
||||
CRITICAL_SECTION lock;
|
||||
};
|
||||
|
||||
WINPR_LOCAL BOOL ClipboardInitSynthesizers(wClipboard* clipboard);
|
||||
|
||||
WINPR_LOCAL char* parse_uri_to_local_file(const char* uri, size_t uri_len);
|
||||
|
||||
extern const char* const mime_text_plain;
|
||||
|
||||
#endif /* WINPR_CLIPBOARD_PRIVATE_H */
|
||||
1205
third_party/FreeRDP/winpr/libwinpr/clipboard/synthetic.c
vendored
Normal file
1205
third_party/FreeRDP/winpr/libwinpr/clipboard/synthetic.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1248
third_party/FreeRDP/winpr/libwinpr/clipboard/synthetic_file.c
vendored
Normal file
1248
third_party/FreeRDP/winpr/libwinpr/clipboard/synthetic_file.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
27
third_party/FreeRDP/winpr/libwinpr/clipboard/synthetic_file.h
vendored
Normal file
27
third_party/FreeRDP/winpr/libwinpr/clipboard/synthetic_file.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Clipboard Functions: POSIX file handling
|
||||
*
|
||||
* Copyright 2017 Alexei Lozovsky <a.lozovsky@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 WINPR_CLIPBOARD_POSIX_H
|
||||
#define WINPR_CLIPBOARD_POSIX_H
|
||||
|
||||
#include <winpr/clipboard.h>
|
||||
|
||||
BOOL ClipboardInitSyntheticFileSubsystem(wClipboard* clipboard);
|
||||
|
||||
#endif /* WINPR_CLIPBOARD_POSIX_H */
|
||||
40
third_party/FreeRDP/winpr/libwinpr/clipboard/test/CMakeLists.txt
vendored
Normal file
40
third_party/FreeRDP/winpr/libwinpr/clipboard/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
set(MODULE_NAME "TestClipboard")
|
||||
set(MODULE_PREFIX "TEST_CLIPBOARD")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(TESTS TestClipboardFormats.c)
|
||||
|
||||
if(BUILD_TESTING_INTERNAL)
|
||||
list(APPEND TESTS TestUri.c)
|
||||
endif()
|
||||
|
||||
set(TEST_CLIP_PNG "${CMAKE_SOURCE_DIR}/resources/FreeRDP_Icon.png")
|
||||
file(TO_NATIVE_PATH "${TEST_CLIP_PNG}" TEST_CLIP_PNG)
|
||||
|
||||
set(TEST_CLIP_BMP "${CMAKE_SOURCE_DIR}/resources/FreeRDP_Install.bmp")
|
||||
file(TO_NATIVE_PATH "${TEST_CLIP_BMP}" TEST_CLIP_BMP)
|
||||
|
||||
if(WIN32)
|
||||
string(REPLACE "\\" "\\\\" TEST_CLIP_PNG "${TEST_CLIP_PNG}")
|
||||
string(REPLACE "\\" "\\\\" TEST_CLIP_BMP "${TEST_CLIP_BMP}")
|
||||
endif()
|
||||
|
||||
add_compile_definitions(TEST_CLIP_BMP="${TEST_CLIP_BMP}")
|
||||
add_compile_definitions(TEST_CLIP_PNG="${TEST_CLIP_PNG}")
|
||||
|
||||
create_test_sourcelist(SRCS ${DRIVER} ${TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${SRCS})
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
foreach(test ${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 "WinPR/Test")
|
||||
243
third_party/FreeRDP/winpr/libwinpr/clipboard/test/TestClipboardFormats.c
vendored
Normal file
243
third_party/FreeRDP/winpr/libwinpr/clipboard/test/TestClipboardFormats.c
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/image.h>
|
||||
#include <winpr/clipboard.h>
|
||||
|
||||
int TestClipboardFormats(int argc, char* argv[])
|
||||
{
|
||||
int rc = -1;
|
||||
UINT32 count = 0;
|
||||
UINT32* pFormatIds = nullptr;
|
||||
const char* formatName = nullptr;
|
||||
wClipboard* clipboard = nullptr;
|
||||
UINT32 utf8StringFormatId = 0;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
clipboard = ClipboardCreate();
|
||||
if (!clipboard)
|
||||
return -1;
|
||||
|
||||
const char* mime_types[] = { "text/html", "text/html", "image/bmp",
|
||||
"image/png", "image/webp", "image/jpeg" };
|
||||
for (size_t x = 0; x < ARRAYSIZE(mime_types); x++)
|
||||
{
|
||||
const char* mime = mime_types[x];
|
||||
UINT32 id = ClipboardRegisterFormat(clipboard, mime);
|
||||
(void)fprintf(stderr, "ClipboardRegisterFormat(%s) -> 0x%08" PRIx32 "\n", mime, id);
|
||||
if (id == 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
utf8StringFormatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING");
|
||||
pFormatIds = nullptr;
|
||||
count = ClipboardGetRegisteredFormatIds(clipboard, &pFormatIds);
|
||||
|
||||
for (UINT32 index = 0; index < count; index++)
|
||||
{
|
||||
UINT32 formatId = pFormatIds[index];
|
||||
formatName = ClipboardGetFormatName(clipboard, formatId);
|
||||
(void)fprintf(stderr, "Format: 0x%08" PRIX32 " %s\n", formatId, formatName);
|
||||
}
|
||||
|
||||
free(pFormatIds);
|
||||
|
||||
if (1)
|
||||
{
|
||||
BOOL bSuccess = 0;
|
||||
UINT32 SrcSize = 0;
|
||||
UINT32 DstSize = 0;
|
||||
const char pSrcData[] = "this is a test string";
|
||||
char* pDstData = nullptr;
|
||||
|
||||
SrcSize = (UINT32)(strnlen(pSrcData, ARRAYSIZE(pSrcData)) + 1);
|
||||
bSuccess = ClipboardSetData(clipboard, utf8StringFormatId, pSrcData, SrcSize);
|
||||
(void)fprintf(stderr, "ClipboardSetData: %" PRId32 "\n", bSuccess);
|
||||
DstSize = 0;
|
||||
pDstData = (char*)ClipboardGetData(clipboard, utf8StringFormatId, &DstSize);
|
||||
(void)fprintf(stderr, "ClipboardGetData: %s\n", pDstData);
|
||||
free(pDstData);
|
||||
}
|
||||
|
||||
if (1)
|
||||
{
|
||||
UINT32 DstSize = 0;
|
||||
char* pSrcData = nullptr;
|
||||
WCHAR* pDstData = nullptr;
|
||||
DstSize = 0;
|
||||
pDstData = (WCHAR*)ClipboardGetData(clipboard, CF_UNICODETEXT, &DstSize);
|
||||
pSrcData = ConvertWCharNToUtf8Alloc(pDstData, DstSize / sizeof(WCHAR), nullptr);
|
||||
|
||||
(void)fprintf(stderr, "ClipboardGetData (synthetic): %s\n", pSrcData);
|
||||
free(pDstData);
|
||||
free(pSrcData);
|
||||
}
|
||||
|
||||
pFormatIds = nullptr;
|
||||
count = ClipboardGetFormatIds(clipboard, &pFormatIds);
|
||||
|
||||
for (UINT32 index = 0; index < count; index++)
|
||||
{
|
||||
UINT32 formatId = pFormatIds[index];
|
||||
formatName = ClipboardGetFormatName(clipboard, formatId);
|
||||
(void)fprintf(stderr, "Format: 0x%08" PRIX32 " %s\n", formatId, formatName);
|
||||
}
|
||||
|
||||
if (1)
|
||||
{
|
||||
const char* name = TEST_CLIP_BMP;
|
||||
BOOL bSuccess = FALSE;
|
||||
UINT32 idBmp = ClipboardRegisterFormat(clipboard, "image/bmp");
|
||||
|
||||
wImage* img = winpr_image_new();
|
||||
if (!img)
|
||||
goto fail;
|
||||
|
||||
if (winpr_image_read(img, name) <= 0)
|
||||
{
|
||||
winpr_image_free(img, TRUE);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
size_t bmpsize = 0;
|
||||
void* data = winpr_image_write_buffer(img, WINPR_IMAGE_BITMAP, &bmpsize);
|
||||
bSuccess = ClipboardSetData(clipboard, idBmp, data, bmpsize);
|
||||
(void)fprintf(stderr, "ClipboardSetData: %" PRId32 "\n", bSuccess);
|
||||
|
||||
free(data);
|
||||
winpr_image_free(img, TRUE);
|
||||
if (!bSuccess)
|
||||
goto fail;
|
||||
|
||||
{
|
||||
UINT32 id = CF_DIB;
|
||||
|
||||
UINT32 DstSize = 0;
|
||||
void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
|
||||
(void)fprintf(stderr, "ClipboardGetData: [CF_DIB] %p [%" PRIu32 "]\n", pDstData,
|
||||
DstSize);
|
||||
if (!pDstData)
|
||||
goto fail;
|
||||
bSuccess = ClipboardSetData(clipboard, id, pDstData, DstSize);
|
||||
free(pDstData);
|
||||
if (!bSuccess)
|
||||
goto fail;
|
||||
}
|
||||
{
|
||||
const uint32_t id = ClipboardGetFormatId(clipboard, "HTML Format");
|
||||
UINT32 DstSize = 0;
|
||||
void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
|
||||
if (!pDstData)
|
||||
goto fail;
|
||||
{
|
||||
FILE* fp = fopen("test.html", "w");
|
||||
if (fp)
|
||||
{
|
||||
(void)fwrite(pDstData, 1, DstSize, fp);
|
||||
(void)fclose(fp);
|
||||
}
|
||||
}
|
||||
free(pDstData);
|
||||
}
|
||||
{
|
||||
UINT32 id = ClipboardRegisterFormat(clipboard, "image/bmp");
|
||||
|
||||
UINT32 DstSize = 0;
|
||||
void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
|
||||
(void)fprintf(stderr, "ClipboardGetData: [image/bmp] %p [%" PRIu32 "]\n", pDstData,
|
||||
DstSize);
|
||||
if (!pDstData)
|
||||
goto fail;
|
||||
free(pDstData);
|
||||
if (DstSize != bmpsize)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(WINPR_UTILS_IMAGE_PNG)
|
||||
{
|
||||
UINT32 id = ClipboardRegisterFormat(clipboard, "image/png");
|
||||
|
||||
UINT32 DstSize = 0;
|
||||
void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
|
||||
(void)fprintf(stderr, "ClipboardGetData: [image/png] %p\n", pDstData);
|
||||
if (!pDstData)
|
||||
goto fail;
|
||||
free(pDstData);
|
||||
}
|
||||
{
|
||||
const char* name = TEST_CLIP_PNG;
|
||||
BOOL bSuccess = FALSE;
|
||||
UINT32 idBmp = ClipboardRegisterFormat(clipboard, "image/png");
|
||||
|
||||
wImage* img = winpr_image_new();
|
||||
if (!img)
|
||||
goto fail;
|
||||
|
||||
if (winpr_image_read(img, name) <= 0)
|
||||
{
|
||||
winpr_image_free(img, TRUE);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
size_t bmpsize = 0;
|
||||
void* data = winpr_image_write_buffer(img, WINPR_IMAGE_PNG, &bmpsize);
|
||||
bSuccess = ClipboardSetData(clipboard, idBmp, data, bmpsize);
|
||||
(void)fprintf(stderr, "ClipboardSetData: %" PRId32 "\n", bSuccess);
|
||||
|
||||
free(data);
|
||||
winpr_image_free(img, TRUE);
|
||||
if (!bSuccess)
|
||||
goto fail;
|
||||
}
|
||||
{
|
||||
UINT32 id = CF_DIB;
|
||||
|
||||
UINT32 DstSize = 0;
|
||||
void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
|
||||
(void)fprintf(stderr, "ClipboardGetData: [CF_DIB] %p [%" PRIu32 "]\n", pDstData,
|
||||
DstSize);
|
||||
if (!pDstData)
|
||||
goto fail;
|
||||
bSuccess = ClipboardSetData(clipboard, id, pDstData, DstSize);
|
||||
free(pDstData);
|
||||
if (!bSuccess)
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WINPR_UTILS_IMAGE_WEBP)
|
||||
{
|
||||
UINT32 id = ClipboardRegisterFormat(clipboard, "image/webp");
|
||||
|
||||
UINT32 DstSize = 0;
|
||||
void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
|
||||
(void)fprintf(stderr, "ClipboardGetData: [image/webp] %p\n", pDstData);
|
||||
if (!pDstData)
|
||||
goto fail;
|
||||
free(pDstData);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WINPR_UTILS_IMAGE_JPEG)
|
||||
{
|
||||
UINT32 id = ClipboardRegisterFormat(clipboard, "image/jpeg");
|
||||
|
||||
UINT32 DstSize = 0;
|
||||
void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
|
||||
(void)fprintf(stderr, "ClipboardGetData: [image/jpeg] %p\n", pDstData);
|
||||
if (!pDstData)
|
||||
goto fail;
|
||||
free(pDstData);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
fail:
|
||||
free(pFormatIds);
|
||||
ClipboardDestroy(clipboard);
|
||||
return rc;
|
||||
}
|
||||
69
third_party/FreeRDP/winpr/libwinpr/clipboard/test/TestUri.c
vendored
Normal file
69
third_party/FreeRDP/winpr/libwinpr/clipboard/test/TestUri.c
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include <winpr/winpr.h>
|
||||
#include "winpr/wlog.h"
|
||||
|
||||
#include "../clipboard.h"
|
||||
|
||||
#define WINPR_TAG(tag) "com.winpr." tag
|
||||
#define TAG WINPR_TAG("clipboard.posix")
|
||||
|
||||
int TestUri(int argc, char* argv[])
|
||||
{
|
||||
int nRet = 0;
|
||||
const char* input[] = { /*uri, file or nullptr*/
|
||||
"file://root/a.txt",
|
||||
nullptr,
|
||||
"file:a.txt",
|
||||
nullptr,
|
||||
"file:///c:/windows/a.txt",
|
||||
"c:/windows/a.txt",
|
||||
"file:c:/windows/a.txt",
|
||||
"c:/windows/a.txt",
|
||||
"file:c|/windows/a.txt",
|
||||
"c:/windows/a.txt",
|
||||
"file:///root/a.txt",
|
||||
"/root/a.txt",
|
||||
"file:/root/a.txt",
|
||||
"/root/a.txt"
|
||||
};
|
||||
|
||||
const size_t nLen = ARRAYSIZE(input);
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
printf("input length:%" PRIuz "\n", nLen / 2);
|
||||
|
||||
for (size_t i = 0; i < nLen; i += 2)
|
||||
{
|
||||
const char* in = input[i];
|
||||
const char* cmp = input[i + 1];
|
||||
int bTest = 0;
|
||||
char* name = parse_uri_to_local_file(in, strlen(in));
|
||||
if (name && cmp)
|
||||
{
|
||||
bTest = !strcmp(name, cmp);
|
||||
if (!bTest)
|
||||
{
|
||||
printf("Test error: input: %s; Expected value: %s; output: %s\n", in, cmp, name);
|
||||
nRet++;
|
||||
}
|
||||
free(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cmp)
|
||||
{
|
||||
printf("Test error: input: %s; Expected value: %s; output: %s\n", in, cmp, name);
|
||||
nRet++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("TestUri return value: %d\n", nRet);
|
||||
return nRet;
|
||||
}
|
||||
49
third_party/FreeRDP/winpr/libwinpr/comm/CMakeLists.txt
vendored
Normal file
49
third_party/FreeRDP/winpr/libwinpr/comm/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-comm cmake build script
|
||||
#
|
||||
# Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(MODULE_NAME "winpr-comm")
|
||||
set(MODULE_PREFIX "WINPR_COMM")
|
||||
|
||||
if(NOT WIN32)
|
||||
set(${MODULE_PREFIX}_SRCS comm.c comm.h)
|
||||
if(NOT EMSCRIPTEN AND NOT APPLE)
|
||||
winpr_definition_add(WINPR_HAVE_SERIAL_SUPPORT)
|
||||
list(
|
||||
APPEND
|
||||
${MODULE_PREFIX}_SRCS
|
||||
comm_io.c
|
||||
comm_ioctl.c
|
||||
comm_ioctl.h
|
||||
comm_serial_sys.c
|
||||
comm_serial_sys.h
|
||||
comm_sercx_sys.c
|
||||
comm_sercx_sys.h
|
||||
comm_sercx2_sys.c
|
||||
comm_sercx2_sys.h
|
||||
)
|
||||
else()
|
||||
list(APPEND ${MODULE_PREFIX}_SRCS comm_ioctl_dummy.c comm_ioctl.h)
|
||||
endif()
|
||||
|
||||
winpr_module_add(${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
if(NOT EMSCRIPTEN)
|
||||
if(BUILD_TESTING_INTERNAL AND BUILD_COMM_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
9
third_party/FreeRDP/winpr/libwinpr/comm/ModuleOptions.cmake
vendored
Normal file
9
third_party/FreeRDP/winpr/libwinpr/comm/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
set(MINWIN_LAYER "1")
|
||||
set(MINWIN_GROUP "core")
|
||||
set(MINWIN_MAJOR_VERSION "1")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "comm")
|
||||
set(MINWIN_LONG_NAME "Serial Communication API")
|
||||
set(MODULE_LIBRARY_NAME
|
||||
"api-ms-win-${MINWIN_GROUP}-${MINWIN_SHORT_NAME}-l${MINWIN_LAYER}-${MINWIN_MAJOR_VERSION}-${MINWIN_MINOR_VERSION}"
|
||||
)
|
||||
1920
third_party/FreeRDP/winpr/libwinpr/comm/comm.c
vendored
Normal file
1920
third_party/FreeRDP/winpr/libwinpr/comm/comm.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
134
third_party/FreeRDP/winpr/libwinpr/comm/comm.h
vendored
Normal file
134
third_party/FreeRDP/winpr/libwinpr/comm/comm.h
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* 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 WINPR_COMM_PRIVATE_H
|
||||
#define WINPR_COMM_PRIVATE_H
|
||||
|
||||
#if defined(__linux__)
|
||||
#define WINPR_HAVE_COMM_COUNTERS
|
||||
#include <linux/serial.h>
|
||||
#endif
|
||||
|
||||
#include <winpr/comm.h>
|
||||
|
||||
#include "../handle/handle.h"
|
||||
#include <winpr/config.h>
|
||||
|
||||
#if defined(WINPR_HAVE_SYS_EVENTFD_H)
|
||||
#include <sys/eventfd.h>
|
||||
#endif
|
||||
|
||||
struct winpr_comm
|
||||
{
|
||||
WINPR_HANDLE common;
|
||||
|
||||
int fd;
|
||||
|
||||
int fd_read;
|
||||
int fd_read_event; /* as of today, only used by _purge() */
|
||||
CRITICAL_SECTION ReadLock;
|
||||
|
||||
int fd_write;
|
||||
int fd_write_event; /* as of today, only used by _purge() */
|
||||
CRITICAL_SECTION WriteLock;
|
||||
|
||||
/* permissive mode on errors. If TRUE (default is FALSE)
|
||||
* CommDeviceIoControl always return TRUE.
|
||||
*
|
||||
* Not all features are supported yet and an error is then returned when
|
||||
* an application turns them on (e.g: i/o buffers > 4096). It appeared
|
||||
* though that devices and applications can be still functional on such
|
||||
* errors.
|
||||
*
|
||||
* see also: comm_ioctl.c
|
||||
*
|
||||
* FIXME: getting rid of this flag once all features supported.
|
||||
*/
|
||||
BOOL permissive;
|
||||
|
||||
SERIAL_DRIVER_ID serverSerialDriverId;
|
||||
|
||||
COMMTIMEOUTS timeouts;
|
||||
|
||||
CRITICAL_SECTION
|
||||
EventsLock; /* protects counters, WaitEventMask and PendingEvents */
|
||||
#if defined(WINPR_HAVE_COMM_COUNTERS)
|
||||
struct serial_icounter_struct counters;
|
||||
#endif
|
||||
ULONG WaitEventMask;
|
||||
ULONG PendingEvents;
|
||||
|
||||
BYTE eventChar;
|
||||
/* NB: CloseHandle() has to free resources */
|
||||
ULONG XOnLimit;
|
||||
ULONG XOffLimit;
|
||||
|
||||
#if defined(WINPR_HAVE_COMM_COUNTERS)
|
||||
BOOL TIOCGICOUNTSupported;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct winpr_comm WINPR_COMM;
|
||||
|
||||
#define SERIAL_EV_RXCHAR 0x0001
|
||||
#define SERIAL_EV_RXFLAG 0x0002
|
||||
#define SERIAL_EV_TXEMPTY 0x0004
|
||||
#define SERIAL_EV_CTS 0x0008
|
||||
#define SERIAL_EV_DSR 0x0010
|
||||
#define SERIAL_EV_RLSD 0x0020
|
||||
#define SERIAL_EV_BREAK 0x0040
|
||||
#define SERIAL_EV_ERR 0x0080
|
||||
#define SERIAL_EV_RING 0x0100
|
||||
#define SERIAL_EV_PERR 0x0200
|
||||
#define SERIAL_EV_RX80FULL 0x0400
|
||||
#define SERIAL_EV_EVENT1 0x0800
|
||||
#define SERIAL_EV_EVENT2 0x1000
|
||||
#define SERIAL_EV_WINPR_WAITING 0x4000 /* bit today unused by other SERIAL_EV_* */
|
||||
#define SERIAL_EV_WINPR_STOP 0x8000 /* bit today unused by other SERIAL_EV_* */
|
||||
|
||||
#define WINPR_PURGE_TXABORT 0x00000001 /* abort pending transmission */
|
||||
#define WINPR_PURGE_RXABORT 0x00000002 /* abort pending reception */
|
||||
|
||||
#define CommLog_Print(level, ...) CommLog_PrintEx(level, __FILE__, __LINE__, __func__, __VA_ARGS__)
|
||||
WINPR_ATTR_FORMAT_ARG(5, 6)
|
||||
void CommLog_PrintEx(DWORD level, const char* file, size_t line, const char* fkt,
|
||||
WINPR_FORMAT_ARG const char* fmt, ...);
|
||||
|
||||
BOOL CommIsHandled(HANDLE handle);
|
||||
BOOL CommIsHandleValid(HANDLE handle);
|
||||
BOOL CommCloseHandle(HANDLE handle);
|
||||
const HANDLE_CREATOR* GetCommHandleCreator(void);
|
||||
|
||||
#define CommIoCtl(pComm, ctl, data) \
|
||||
CommIoCtl_int((pComm), (ctl), (data), __FILE__, __func__, __LINE__)
|
||||
BOOL CommIoCtl_int(WINPR_COMM* pComm, unsigned long int ctl, void* data, const char* file,
|
||||
const char* fkt, size_t line);
|
||||
BOOL CommUpdateIOCount(HANDLE handle, BOOL checkSupportStatus);
|
||||
|
||||
const char* CommSerialEvString(ULONG status, char* buffer, size_t size);
|
||||
|
||||
#if defined(WINPR_HAVE_SYS_EVENTFD_H)
|
||||
#ifndef WITH_EVENTFD_READ_WRITE
|
||||
int eventfd_read(int fd, eventfd_t* value);
|
||||
int eventfd_write(int fd, eventfd_t value);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_COMM_PRIVATE_H */
|
||||
567
third_party/FreeRDP/winpr/libwinpr/comm/comm_io.c
vendored
Normal file
567
third_party/FreeRDP/winpr/libwinpr/comm/comm_io.c
vendored
Normal file
@@ -0,0 +1,567 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <errno.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <winpr/io.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include "comm.h"
|
||||
|
||||
BOOL _comm_set_permissive(HANDLE hDevice, BOOL permissive)
|
||||
{
|
||||
WINPR_COMM* pComm = (WINPR_COMM*)hDevice;
|
||||
|
||||
if (!CommIsHandled(hDevice))
|
||||
return FALSE;
|
||||
|
||||
pComm->permissive = permissive;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Computes VTIME in deciseconds from Ti in milliseconds */
|
||||
static UCHAR svtime(ULONG Ti)
|
||||
{
|
||||
/* FIXME: look for an equivalent math function otherwise let
|
||||
* do the compiler do the optimization */
|
||||
if (Ti == 0)
|
||||
return 0;
|
||||
else if (Ti < 100)
|
||||
return 1;
|
||||
else if (Ti > 25500)
|
||||
return 255; /* 0xFF */
|
||||
else
|
||||
return (UCHAR)(Ti / 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* ERRORS:
|
||||
* ERROR_INVALID_HANDLE
|
||||
* ERROR_NOT_SUPPORTED
|
||||
* ERROR_INVALID_PARAMETER
|
||||
* ERROR_TIMEOUT
|
||||
* ERROR_IO_DEVICE
|
||||
* ERROR_BAD_DEVICE
|
||||
*/
|
||||
BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
WINPR_COMM* pComm = (WINPR_COMM*)hDevice;
|
||||
int biggestFd = -1;
|
||||
fd_set read_set;
|
||||
int nbFds = 0;
|
||||
COMMTIMEOUTS* pTimeouts = nullptr;
|
||||
UCHAR vmin = 0;
|
||||
UCHAR vtime = 0;
|
||||
LONGLONG Tmax = 0;
|
||||
struct timeval tmaxTimeout;
|
||||
struct timeval* pTmaxTimeout = nullptr;
|
||||
struct termios currentTermios;
|
||||
EnterCriticalSection(&pComm->ReadLock); /* KISSer by the function's beginning */
|
||||
|
||||
if (!CommIsHandled(hDevice))
|
||||
goto return_false;
|
||||
|
||||
if (lpOverlapped != nullptr)
|
||||
{
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
if (lpNumberOfBytesRead == nullptr)
|
||||
{
|
||||
SetLastError(
|
||||
ERROR_INVALID_PARAMETER); /* since we doesn't support lpOverlapped != nullptr */
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
*lpNumberOfBytesRead = 0; /* will be adjusted if required ... */
|
||||
|
||||
if (nNumberOfBytesToRead <= 0) /* N */
|
||||
{
|
||||
goto return_true; /* FIXME: or FALSE? */
|
||||
}
|
||||
|
||||
if (tcgetattr(pComm->fd, ¤tTermios) < 0)
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
if (currentTermios.c_lflag & ICANON)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "Canonical mode not supported"); /* the timeout could not be set */
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
/* http://msdn.microsoft.com/en-us/library/hh439614%28v=vs.85%29.aspx
|
||||
* http://msdn.microsoft.com/en-us/library/windows/hardware/hh439614%28v=vs.85%29.aspx
|
||||
*
|
||||
* ReadIntervalTimeout | ReadTotalTimeoutMultiplier | ReadTotalTimeoutConstant | VMIN | VTIME |
|
||||
* TMAX | 0 | 0 | 0 | N | 0 |
|
||||
* INDEF | Blocks for N bytes available. 0< Ti <MAXULONG | 0 | 0 |
|
||||
* N | Ti | INDEF | Blocks on first byte, then use Ti between bytes. MAXULONG | 0 | 0
|
||||
* | 0 | 0 | 0 | Returns immediately with bytes available (don't block) MAXULONG |
|
||||
* MAXULONG | 0< Tc <MAXULONG | N | 0 | Tc | Blocks on first byte
|
||||
* during Tc or returns immediately with bytes available MAXULONG | m |
|
||||
* MAXULONG | | Invalid 0 | m | 0< Tc
|
||||
* <MAXULONG | N | 0 | Tmax | Blocks on first byte during Tmax or returns
|
||||
* immediately with bytes available 0< Ti <MAXULONG | m | 0<
|
||||
* Tc <MAXULONG | N | Ti | Tmax | Blocks on first byte, then use Ti between bytes.
|
||||
* Tmax is used for the whole system call.
|
||||
*/
|
||||
/* NB: timeouts are in milliseconds, VTIME are in deciseconds and is an unsigned char */
|
||||
/* FIXME: double check whether open(pComm->fd_read_event, O_NONBLOCK) doesn't conflict with
|
||||
* above use cases */
|
||||
pTimeouts = &(pComm->timeouts);
|
||||
|
||||
if ((pTimeouts->ReadIntervalTimeout == MAXULONG) &&
|
||||
(pTimeouts->ReadTotalTimeoutConstant == MAXULONG))
|
||||
{
|
||||
CommLog_Print(
|
||||
WLOG_WARN,
|
||||
"ReadIntervalTimeout and ReadTotalTimeoutConstant cannot be both set to MAXULONG");
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
/* VMIN */
|
||||
|
||||
if ((pTimeouts->ReadIntervalTimeout == MAXULONG) &&
|
||||
(pTimeouts->ReadTotalTimeoutMultiplier == 0) && (pTimeouts->ReadTotalTimeoutConstant == 0))
|
||||
{
|
||||
vmin = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* N */
|
||||
/* vmin = nNumberOfBytesToRead < 256 ? nNumberOfBytesToRead : 255;*/ /* 0xFF */
|
||||
/* NB: we might wait endlessly with vmin=N, prefer to
|
||||
* force vmin=1 and return with bytes
|
||||
* available. FIXME: is a feature disarded here? */
|
||||
vmin = 1;
|
||||
}
|
||||
|
||||
/* VTIME */
|
||||
|
||||
if ((pTimeouts->ReadIntervalTimeout > 0) && (pTimeouts->ReadIntervalTimeout < MAXULONG))
|
||||
{
|
||||
/* Ti */
|
||||
vtime = svtime(pTimeouts->ReadIntervalTimeout);
|
||||
}
|
||||
|
||||
/* TMAX */
|
||||
pTmaxTimeout = &tmaxTimeout;
|
||||
|
||||
if ((pTimeouts->ReadIntervalTimeout == MAXULONG) &&
|
||||
(pTimeouts->ReadTotalTimeoutMultiplier == MAXULONG))
|
||||
{
|
||||
/* Tc */
|
||||
Tmax = pTimeouts->ReadTotalTimeoutConstant;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Tmax */
|
||||
Tmax = 1ll * nNumberOfBytesToRead * pTimeouts->ReadTotalTimeoutMultiplier +
|
||||
1ll * pTimeouts->ReadTotalTimeoutConstant;
|
||||
|
||||
/* INDEFinitely */
|
||||
if ((Tmax == 0) && (pTimeouts->ReadIntervalTimeout < MAXULONG) &&
|
||||
(pTimeouts->ReadTotalTimeoutMultiplier == 0))
|
||||
pTmaxTimeout = nullptr;
|
||||
}
|
||||
|
||||
if ((currentTermios.c_cc[VMIN] != vmin) || (currentTermios.c_cc[VTIME] != vtime))
|
||||
{
|
||||
currentTermios.c_cc[VMIN] = vmin;
|
||||
currentTermios.c_cc[VTIME] = vtime;
|
||||
|
||||
if (tcsetattr(pComm->fd, TCSANOW, ¤tTermios) < 0)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"CommReadFile failure, could not apply new timeout values: VMIN=%" PRIu8
|
||||
", VTIME=%" PRIu8 "",
|
||||
vmin, vtime);
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
goto return_false;
|
||||
}
|
||||
}
|
||||
|
||||
/* wait indefinitely if pTmaxTimeout is nullptr */
|
||||
|
||||
if (pTmaxTimeout != nullptr)
|
||||
{
|
||||
ZeroMemory(pTmaxTimeout, sizeof(struct timeval));
|
||||
|
||||
if (Tmax > 0) /* return immdiately if Tmax == 0 */
|
||||
{
|
||||
pTmaxTimeout->tv_sec = Tmax / 1000; /* s */
|
||||
pTmaxTimeout->tv_usec = (Tmax % 1000) * 1000; /* us */
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: had expected eventfd_write() to return EAGAIN when
|
||||
* there is no eventfd_read() but this not the case. */
|
||||
/* discard a possible and no more relevant event */
|
||||
#if defined(WINPR_HAVE_SYS_EVENTFD_H)
|
||||
{
|
||||
eventfd_t val = 0;
|
||||
(void)eventfd_read(pComm->fd_read_event, &val);
|
||||
}
|
||||
#endif
|
||||
biggestFd = pComm->fd_read;
|
||||
|
||||
if (pComm->fd_read_event > biggestFd)
|
||||
biggestFd = pComm->fd_read_event;
|
||||
|
||||
FD_ZERO(&read_set);
|
||||
WINPR_ASSERT(pComm->fd_read_event < FD_SETSIZE);
|
||||
WINPR_ASSERT(pComm->fd_read < FD_SETSIZE);
|
||||
FD_SET(pComm->fd_read_event, &read_set);
|
||||
FD_SET(pComm->fd_read, &read_set);
|
||||
nbFds = select(biggestFd + 1, &read_set, nullptr, nullptr, pTmaxTimeout);
|
||||
|
||||
if (nbFds < 0)
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
CommLog_Print(WLOG_WARN, "select() failure, errno=[%d] %s\n", errno,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
if (nbFds == 0)
|
||||
{
|
||||
/* timeout */
|
||||
SetLastError(ERROR_TIMEOUT);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
/* read_set */
|
||||
|
||||
if (FD_ISSET(pComm->fd_read_event, &read_set))
|
||||
{
|
||||
#if defined(WINPR_HAVE_SYS_EVENTFD_H)
|
||||
eventfd_t event = 0;
|
||||
|
||||
if (eventfd_read(pComm->fd_read_event, &event) < 0)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
WINPR_ASSERT(FALSE); /* not quite sure this should ever happen */
|
||||
/* keep on */
|
||||
}
|
||||
else
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"unexpected error on reading fd_read_event, errno=[%d] %s\n", errno,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
/* FIXME: goto return_false ? */
|
||||
}
|
||||
|
||||
WINPR_ASSERT(errno == EAGAIN);
|
||||
}
|
||||
|
||||
if (event == WINPR_PURGE_RXABORT)
|
||||
{
|
||||
SetLastError(ERROR_CANCELLED);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(event == WINPR_PURGE_RXABORT); /* no other expected event so far */
|
||||
#endif
|
||||
}
|
||||
|
||||
if (FD_ISSET(pComm->fd_read, &read_set))
|
||||
{
|
||||
ssize_t nbRead = read(pComm->fd_read, lpBuffer, nNumberOfBytesToRead);
|
||||
|
||||
if ((nbRead < 0) || (nbRead > nNumberOfBytesToRead))
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"CommReadFile failed, ReadIntervalTimeout=%" PRIu32
|
||||
", ReadTotalTimeoutMultiplier=%" PRIu32
|
||||
", ReadTotalTimeoutConstant=%" PRIu32 " VMIN=%u, VTIME=%u",
|
||||
pTimeouts->ReadIntervalTimeout, pTimeouts->ReadTotalTimeoutMultiplier,
|
||||
pTimeouts->ReadTotalTimeoutConstant, currentTermios.c_cc[VMIN],
|
||||
currentTermios.c_cc[VTIME]);
|
||||
CommLog_Print(
|
||||
WLOG_WARN, "CommReadFile failed, nNumberOfBytesToRead=%" PRIu32 ", errno=[%d] %s",
|
||||
nNumberOfBytesToRead, errno, winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
/* keep on */
|
||||
goto return_true; /* expect a read-loop to be implemented on the server side */
|
||||
}
|
||||
else if (errno == EBADF)
|
||||
{
|
||||
SetLastError(ERROR_BAD_DEVICE); /* STATUS_INVALID_DEVICE_REQUEST */
|
||||
goto return_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
WINPR_ASSERT(FALSE);
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
goto return_false;
|
||||
}
|
||||
}
|
||||
|
||||
if (nbRead == 0)
|
||||
{
|
||||
/* termios timeout */
|
||||
SetLastError(ERROR_TIMEOUT);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
*lpNumberOfBytesRead = WINPR_ASSERTING_INT_CAST(UINT32, nbRead);
|
||||
|
||||
EnterCriticalSection(&pComm->EventsLock);
|
||||
if (pComm->PendingEvents & SERIAL_EV_WINPR_WAITING)
|
||||
{
|
||||
if (pComm->eventChar != '\0' &&
|
||||
memchr(lpBuffer, pComm->eventChar, WINPR_ASSERTING_INT_CAST(size_t, nbRead)))
|
||||
pComm->PendingEvents |= SERIAL_EV_RXCHAR;
|
||||
}
|
||||
LeaveCriticalSection(&pComm->EventsLock);
|
||||
goto return_true;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(FALSE);
|
||||
*lpNumberOfBytesRead = 0;
|
||||
return_false:
|
||||
LeaveCriticalSection(&pComm->ReadLock);
|
||||
return FALSE;
|
||||
return_true:
|
||||
LeaveCriticalSection(&pComm->ReadLock);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ERRORS:
|
||||
* ERROR_INVALID_HANDLE
|
||||
* ERROR_NOT_SUPPORTED
|
||||
* ERROR_INVALID_PARAMETER
|
||||
* ERROR_BAD_DEVICE
|
||||
*/
|
||||
BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
WINPR_COMM* pComm = (WINPR_COMM*)hDevice;
|
||||
struct timeval tmaxTimeout;
|
||||
struct timeval* pTmaxTimeout = nullptr;
|
||||
EnterCriticalSection(&pComm->WriteLock); /* KISSer by the function's beginning */
|
||||
|
||||
if (!CommIsHandled(hDevice))
|
||||
goto return_false;
|
||||
|
||||
if (lpOverlapped != nullptr)
|
||||
{
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
if (lpNumberOfBytesWritten == nullptr)
|
||||
{
|
||||
SetLastError(
|
||||
ERROR_INVALID_PARAMETER); /* since we doesn't support lpOverlapped != nullptr */
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
*lpNumberOfBytesWritten = 0; /* will be adjusted if required ... */
|
||||
|
||||
if (nNumberOfBytesToWrite <= 0)
|
||||
{
|
||||
goto return_true; /* FIXME: or FALSE? */
|
||||
}
|
||||
|
||||
/* FIXME: had expected eventfd_write() to return EAGAIN when
|
||||
* there is no eventfd_read() but this not the case. */
|
||||
/* discard a possible and no more relevant event */
|
||||
|
||||
#if defined(WINPR_HAVE_SYS_EVENTFD_H)
|
||||
{
|
||||
eventfd_t val = 0;
|
||||
(void)eventfd_read(pComm->fd_write_event, &val);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
/* ms */
|
||||
const LONGLONG Tmax =
|
||||
1ll * nNumberOfBytesToWrite * pComm->timeouts.WriteTotalTimeoutMultiplier +
|
||||
1ll * pComm->timeouts.WriteTotalTimeoutConstant;
|
||||
/* NB: select() may update the timeout argument to indicate
|
||||
* how much time was left. Keep the timeout variable out of
|
||||
* the while() */
|
||||
pTmaxTimeout = &tmaxTimeout;
|
||||
ZeroMemory(pTmaxTimeout, sizeof(struct timeval));
|
||||
|
||||
if (Tmax > 0)
|
||||
{
|
||||
pTmaxTimeout->tv_sec = Tmax / 1000; /* s */
|
||||
pTmaxTimeout->tv_usec = (Tmax % 1000) * 1000; /* us */
|
||||
}
|
||||
else if ((pComm->timeouts.WriteTotalTimeoutMultiplier == 0) &&
|
||||
(pComm->timeouts.WriteTotalTimeoutConstant == 0))
|
||||
{
|
||||
pTmaxTimeout = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* else return immdiately */
|
||||
|
||||
while (*lpNumberOfBytesWritten < nNumberOfBytesToWrite)
|
||||
{
|
||||
int biggestFd = -1;
|
||||
fd_set event_set;
|
||||
fd_set write_set;
|
||||
int nbFds = 0;
|
||||
biggestFd = pComm->fd_write;
|
||||
|
||||
if (pComm->fd_write_event > biggestFd)
|
||||
biggestFd = pComm->fd_write_event;
|
||||
|
||||
FD_ZERO(&event_set);
|
||||
FD_ZERO(&write_set);
|
||||
WINPR_ASSERT(pComm->fd_write_event < FD_SETSIZE);
|
||||
WINPR_ASSERT(pComm->fd_write < FD_SETSIZE);
|
||||
FD_SET(pComm->fd_write_event, &event_set);
|
||||
FD_SET(pComm->fd_write, &write_set);
|
||||
nbFds = select(biggestFd + 1, &event_set, &write_set, nullptr, pTmaxTimeout);
|
||||
|
||||
if (nbFds < 0)
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
CommLog_Print(WLOG_WARN, "select() failure, errno=[%d] %s\n", errno,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
if (nbFds == 0)
|
||||
{
|
||||
/* timeout */
|
||||
SetLastError(ERROR_TIMEOUT);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
/* event_set */
|
||||
|
||||
if (FD_ISSET(pComm->fd_write_event, &event_set))
|
||||
{
|
||||
#if defined(WINPR_HAVE_SYS_EVENTFD_H)
|
||||
eventfd_t event = 0;
|
||||
|
||||
if (eventfd_read(pComm->fd_write_event, &event) < 0)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
WINPR_ASSERT(FALSE); /* not quite sure this should ever happen */
|
||||
/* keep on */
|
||||
}
|
||||
else
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"unexpected error on reading fd_write_event, errno=[%d] %s\n",
|
||||
errno, winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
/* FIXME: goto return_false ? */
|
||||
}
|
||||
|
||||
WINPR_ASSERT(errno == EAGAIN);
|
||||
}
|
||||
|
||||
if (event == WINPR_PURGE_TXABORT)
|
||||
{
|
||||
SetLastError(ERROR_CANCELLED);
|
||||
goto return_false;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(event == WINPR_PURGE_TXABORT); /* no other expected event so far */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* write_set */
|
||||
|
||||
if (FD_ISSET(pComm->fd_write, &write_set))
|
||||
{
|
||||
ssize_t nbWritten = 0;
|
||||
const BYTE* ptr = lpBuffer;
|
||||
nbWritten = write(pComm->fd_write, &ptr[*lpNumberOfBytesWritten],
|
||||
nNumberOfBytesToWrite - (*lpNumberOfBytesWritten));
|
||||
|
||||
if (nbWritten < 0)
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"CommWriteFile failed after %" PRIu32
|
||||
" bytes written, errno=[%d] %s\n",
|
||||
*lpNumberOfBytesWritten, errno,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
/* keep on */
|
||||
continue;
|
||||
}
|
||||
else if (errno == EBADF)
|
||||
{
|
||||
SetLastError(ERROR_BAD_DEVICE); /* STATUS_INVALID_DEVICE_REQUEST */
|
||||
goto return_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
WINPR_ASSERT(FALSE);
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
goto return_false;
|
||||
}
|
||||
}
|
||||
|
||||
*lpNumberOfBytesWritten += nbWritten;
|
||||
}
|
||||
} /* while */
|
||||
|
||||
/* FIXME: this call to tcdrain() doesn't look correct and
|
||||
* might hide a bug but was required while testing a serial
|
||||
* printer. Its driver was expecting the modem line status
|
||||
* SERIAL_MSR_DSR true after the sending which was never
|
||||
* happening otherwise. A purge was also done before each
|
||||
* Write operation. The serial port was opened with:
|
||||
* DesiredAccess=0x0012019F. The printer worked fine with
|
||||
* mstsc. */
|
||||
tcdrain(pComm->fd_write);
|
||||
|
||||
return_true:
|
||||
LeaveCriticalSection(&pComm->WriteLock);
|
||||
return TRUE;
|
||||
|
||||
return_false:
|
||||
LeaveCriticalSection(&pComm->WriteLock);
|
||||
return FALSE;
|
||||
}
|
||||
759
third_party/FreeRDP/winpr/libwinpr/comm/comm_ioctl.c
vendored
Normal file
759
third_party/FreeRDP/winpr/libwinpr/comm/comm_ioctl.c
vendored
Normal file
@@ -0,0 +1,759 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2011 O.S. Systems Software Ltda.
|
||||
* Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#include "comm.h"
|
||||
#include "comm_ioctl.h"
|
||||
#include "comm_serial_sys.h"
|
||||
#include "comm_sercx_sys.h"
|
||||
#include "comm_sercx2_sys.h"
|
||||
|
||||
static const char* comm_ioctl_modem_status_string(ULONG status, char* buffer, size_t size);
|
||||
|
||||
/* NB: MS-RDPESP's recommendation:
|
||||
*
|
||||
* <2> Section 3.2.5.1.6: Windows Implementations use IOCTL constants
|
||||
* for IoControlCode values. The content and values of the IOCTLs are
|
||||
* opaque to the protocol. On the server side, the data contained in
|
||||
* an IOCTL is simply packaged and sent to the client side. For
|
||||
* maximum compatibility between the different versions of the Windows
|
||||
* operating system, the client implementation only singles out
|
||||
* critical IOCTLs and invokes the applicable Win32 port API. The
|
||||
* other IOCTLS are passed directly to the client-side driver, and the
|
||||
* processing of this value depends on the drivers installed on the
|
||||
* client side. The values and parameters for these IOCTLS can be
|
||||
* found in [MSFT-W2KDDK] Volume 2, Part 2—Serial and Parallel
|
||||
* Drivers, and in [MSDN-PORTS].
|
||||
*/
|
||||
static BOOL s_CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
char buffer[128] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_COMM* pComm = (WINPR_COMM*)hDevice;
|
||||
const SERIAL_DRIVER* pServerSerialDriver = nullptr;
|
||||
|
||||
if (!CommIsHandleValid(hDevice))
|
||||
return FALSE;
|
||||
|
||||
if (lpOverlapped)
|
||||
{
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (lpBytesReturned == nullptr)
|
||||
{
|
||||
SetLastError(
|
||||
ERROR_INVALID_PARAMETER); /* since we doesn't support lpOverlapped != nullptr */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* clear any previous last error */
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
|
||||
*lpBytesReturned = 0; /* will be adjusted if required ... */
|
||||
|
||||
CommLog_Print(WLOG_DEBUG, "CommDeviceIoControl: IoControlCode: %s [0x%08" PRIx32 "]",
|
||||
_comm_serial_ioctl_name(dwIoControlCode), dwIoControlCode);
|
||||
|
||||
/* remoteSerialDriver to be use ...
|
||||
*
|
||||
* FIXME: might prefer to use an automatic rather than static structure
|
||||
*/
|
||||
switch (pComm->serverSerialDriverId)
|
||||
{
|
||||
case SerialDriverSerialSys:
|
||||
pServerSerialDriver = SerialSys_s();
|
||||
break;
|
||||
|
||||
case SerialDriverSerCxSys:
|
||||
pServerSerialDriver = SerCxSys_s();
|
||||
break;
|
||||
|
||||
case SerialDriverSerCx2Sys:
|
||||
pServerSerialDriver = SerCx2Sys_s();
|
||||
break;
|
||||
|
||||
case SerialDriverUnknown:
|
||||
default:
|
||||
CommLog_Print(WLOG_DEBUG, "Unknown remote serial driver (%u), using SerCx2.sys",
|
||||
pComm->serverSerialDriverId);
|
||||
pServerSerialDriver = SerCx2Sys_s();
|
||||
break;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(pServerSerialDriver != nullptr);
|
||||
|
||||
switch (dwIoControlCode)
|
||||
{
|
||||
case IOCTL_USBPRINT_GET_1284_ID:
|
||||
{
|
||||
/* FIXME:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff551803(v=vs.85).aspx */
|
||||
*lpBytesReturned = nOutBufferSize; /* an empty OutputBuffer will be returned */
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_BAUD_RATE:
|
||||
{
|
||||
if (pServerSerialDriver->set_baud_rate)
|
||||
{
|
||||
SERIAL_BAUD_RATE* pBaudRate = (SERIAL_BAUD_RATE*)lpInBuffer;
|
||||
|
||||
WINPR_ASSERT(nInBufferSize >= sizeof(SERIAL_BAUD_RATE));
|
||||
if (nInBufferSize < sizeof(SERIAL_BAUD_RATE))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pServerSerialDriver->set_baud_rate(pComm, pBaudRate);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_GET_BAUD_RATE:
|
||||
{
|
||||
if (pServerSerialDriver->get_baud_rate)
|
||||
{
|
||||
SERIAL_BAUD_RATE* pBaudRate = (SERIAL_BAUD_RATE*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(SERIAL_BAUD_RATE));
|
||||
if (nOutBufferSize < sizeof(SERIAL_BAUD_RATE))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->get_baud_rate(pComm, pBaudRate))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(SERIAL_BAUD_RATE);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_GET_PROPERTIES:
|
||||
{
|
||||
if (pServerSerialDriver->get_properties)
|
||||
{
|
||||
COMMPROP* pProperties = (COMMPROP*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(COMMPROP));
|
||||
if (nOutBufferSize < sizeof(COMMPROP))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->get_properties(pComm, pProperties))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(COMMPROP);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_CHARS:
|
||||
{
|
||||
if (pServerSerialDriver->set_serial_chars)
|
||||
{
|
||||
SERIAL_CHARS* pSerialChars = (SERIAL_CHARS*)lpInBuffer;
|
||||
|
||||
WINPR_ASSERT(nInBufferSize >= sizeof(SERIAL_CHARS));
|
||||
if (nInBufferSize < sizeof(SERIAL_CHARS))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pServerSerialDriver->set_serial_chars(pComm, pSerialChars);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_GET_CHARS:
|
||||
{
|
||||
if (pServerSerialDriver->get_serial_chars)
|
||||
{
|
||||
SERIAL_CHARS* pSerialChars = (SERIAL_CHARS*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(SERIAL_CHARS));
|
||||
if (nOutBufferSize < sizeof(SERIAL_CHARS))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->get_serial_chars(pComm, pSerialChars))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(SERIAL_CHARS);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_LINE_CONTROL:
|
||||
{
|
||||
if (pServerSerialDriver->set_line_control)
|
||||
{
|
||||
SERIAL_LINE_CONTROL* pLineControl = (SERIAL_LINE_CONTROL*)lpInBuffer;
|
||||
|
||||
WINPR_ASSERT(nInBufferSize >= sizeof(SERIAL_LINE_CONTROL));
|
||||
if (nInBufferSize < sizeof(SERIAL_LINE_CONTROL))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pServerSerialDriver->set_line_control(pComm, pLineControl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_GET_LINE_CONTROL:
|
||||
{
|
||||
if (pServerSerialDriver->get_line_control)
|
||||
{
|
||||
SERIAL_LINE_CONTROL* pLineControl = (SERIAL_LINE_CONTROL*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(SERIAL_LINE_CONTROL));
|
||||
if (nOutBufferSize < sizeof(SERIAL_LINE_CONTROL))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->get_line_control(pComm, pLineControl))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(SERIAL_LINE_CONTROL);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_HANDFLOW:
|
||||
{
|
||||
if (pServerSerialDriver->set_handflow)
|
||||
{
|
||||
SERIAL_HANDFLOW* pHandflow = (SERIAL_HANDFLOW*)lpInBuffer;
|
||||
|
||||
WINPR_ASSERT(nInBufferSize >= sizeof(SERIAL_HANDFLOW));
|
||||
if (nInBufferSize < sizeof(SERIAL_HANDFLOW))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pServerSerialDriver->set_handflow(pComm, pHandflow);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_GET_HANDFLOW:
|
||||
{
|
||||
if (pServerSerialDriver->get_handflow)
|
||||
{
|
||||
SERIAL_HANDFLOW* pHandflow = (SERIAL_HANDFLOW*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(SERIAL_HANDFLOW));
|
||||
if (nOutBufferSize < sizeof(SERIAL_HANDFLOW))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->get_handflow(pComm, pHandflow))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(SERIAL_HANDFLOW);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_TIMEOUTS:
|
||||
{
|
||||
if (pServerSerialDriver->set_timeouts)
|
||||
{
|
||||
SERIAL_TIMEOUTS* pHandflow = (SERIAL_TIMEOUTS*)lpInBuffer;
|
||||
|
||||
WINPR_ASSERT(nInBufferSize >= sizeof(SERIAL_TIMEOUTS));
|
||||
if (nInBufferSize < sizeof(SERIAL_TIMEOUTS))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pServerSerialDriver->set_timeouts(pComm, pHandflow);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_GET_TIMEOUTS:
|
||||
{
|
||||
if (pServerSerialDriver->get_timeouts)
|
||||
{
|
||||
SERIAL_TIMEOUTS* pHandflow = (SERIAL_TIMEOUTS*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(SERIAL_TIMEOUTS));
|
||||
if (nOutBufferSize < sizeof(SERIAL_TIMEOUTS))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->get_timeouts(pComm, pHandflow))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(SERIAL_TIMEOUTS);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_DTR:
|
||||
{
|
||||
if (pServerSerialDriver->set_dtr)
|
||||
{
|
||||
return pServerSerialDriver->set_dtr(pComm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_CLR_DTR:
|
||||
{
|
||||
if (pServerSerialDriver->clear_dtr)
|
||||
{
|
||||
return pServerSerialDriver->clear_dtr(pComm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_RTS:
|
||||
{
|
||||
if (pServerSerialDriver->set_rts)
|
||||
{
|
||||
return pServerSerialDriver->set_rts(pComm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_CLR_RTS:
|
||||
{
|
||||
if (pServerSerialDriver->clear_rts)
|
||||
{
|
||||
return pServerSerialDriver->clear_rts(pComm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_GET_MODEMSTATUS:
|
||||
{
|
||||
if (pServerSerialDriver->get_modemstatus)
|
||||
{
|
||||
ULONG* pRegister = (ULONG*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(ULONG));
|
||||
if (nOutBufferSize < sizeof(ULONG))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->get_modemstatus(pComm, pRegister))
|
||||
return FALSE;
|
||||
|
||||
CommLog_Print(WLOG_DEBUG, "modem status %s" PRIx32,
|
||||
comm_ioctl_modem_status_string(*pRegister, buffer, sizeof(buffer)));
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_WAIT_MASK:
|
||||
{
|
||||
if (pServerSerialDriver->set_wait_mask)
|
||||
{
|
||||
ULONG* pWaitMask = (ULONG*)lpInBuffer;
|
||||
|
||||
WINPR_ASSERT(nInBufferSize >= sizeof(ULONG));
|
||||
if (nInBufferSize < sizeof(ULONG))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const BOOL rc = pServerSerialDriver->set_wait_mask(pComm, pWaitMask);
|
||||
CommLog_Print(WLOG_DEBUG, "set_wait_mask %s -> %d",
|
||||
CommSerialEvString(*pWaitMask, buffer, sizeof(buffer)), rc);
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_GET_WAIT_MASK:
|
||||
{
|
||||
if (pServerSerialDriver->get_wait_mask)
|
||||
{
|
||||
ULONG* pWaitMask = (ULONG*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(ULONG));
|
||||
if (nOutBufferSize < sizeof(ULONG))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->get_wait_mask(pComm, pWaitMask))
|
||||
return FALSE;
|
||||
|
||||
CommLog_Print(WLOG_DEBUG, "get_wait_mask %s",
|
||||
CommSerialEvString(*pWaitMask, buffer, sizeof(buffer)));
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_WAIT_ON_MASK:
|
||||
{
|
||||
if (pServerSerialDriver->wait_on_mask)
|
||||
{
|
||||
ULONG* pOutputMask = (ULONG*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(ULONG));
|
||||
if (nOutBufferSize < sizeof(ULONG))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const BOOL rc = pServerSerialDriver->wait_on_mask(pComm, pOutputMask);
|
||||
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
CommLog_Print(WLOG_DEBUG, "wait_on_mask %s -> %d",
|
||||
CommSerialEvString(*pOutputMask, buffer, sizeof(buffer)), rc);
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_QUEUE_SIZE:
|
||||
{
|
||||
if (pServerSerialDriver->set_queue_size)
|
||||
{
|
||||
SERIAL_QUEUE_SIZE* pQueueSize = (SERIAL_QUEUE_SIZE*)lpInBuffer;
|
||||
|
||||
WINPR_ASSERT(nInBufferSize >= sizeof(SERIAL_QUEUE_SIZE));
|
||||
if (nInBufferSize < sizeof(SERIAL_QUEUE_SIZE))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pServerSerialDriver->set_queue_size(pComm, pQueueSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_PURGE:
|
||||
{
|
||||
if (pServerSerialDriver->purge)
|
||||
{
|
||||
ULONG* pPurgeMask = (ULONG*)lpInBuffer;
|
||||
|
||||
WINPR_ASSERT(nInBufferSize >= sizeof(ULONG));
|
||||
if (nInBufferSize < sizeof(ULONG))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pServerSerialDriver->purge(pComm, pPurgeMask);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_GET_COMMSTATUS:
|
||||
{
|
||||
if (pServerSerialDriver->get_commstatus)
|
||||
{
|
||||
SERIAL_STATUS* pCommstatus = (SERIAL_STATUS*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(SERIAL_STATUS));
|
||||
if (nOutBufferSize < sizeof(SERIAL_STATUS))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->get_commstatus(pComm, pCommstatus))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(SERIAL_STATUS);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_BREAK_ON:
|
||||
{
|
||||
if (pServerSerialDriver->set_break_on)
|
||||
{
|
||||
return pServerSerialDriver->set_break_on(pComm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_BREAK_OFF:
|
||||
{
|
||||
if (pServerSerialDriver->set_break_off)
|
||||
{
|
||||
return pServerSerialDriver->set_break_off(pComm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_XOFF:
|
||||
{
|
||||
if (pServerSerialDriver->set_xoff)
|
||||
{
|
||||
return pServerSerialDriver->set_xoff(pComm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_SET_XON:
|
||||
{
|
||||
if (pServerSerialDriver->set_xon)
|
||||
{
|
||||
return pServerSerialDriver->set_xon(pComm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_GET_DTRRTS:
|
||||
{
|
||||
if (pServerSerialDriver->get_dtrrts)
|
||||
{
|
||||
ULONG* pMask = (ULONG*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(ULONG));
|
||||
if (nOutBufferSize < sizeof(ULONG))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->get_dtrrts(pComm, pMask))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_CONFIG_SIZE:
|
||||
{
|
||||
if (pServerSerialDriver->config_size)
|
||||
{
|
||||
ULONG* pSize = (ULONG*)lpOutBuffer;
|
||||
|
||||
WINPR_ASSERT(nOutBufferSize >= sizeof(ULONG));
|
||||
if (nOutBufferSize < sizeof(ULONG))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->config_size(pComm, pSize))
|
||||
return FALSE;
|
||||
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_IMMEDIATE_CHAR:
|
||||
{
|
||||
if (pServerSerialDriver->immediate_char)
|
||||
{
|
||||
UCHAR* pChar = (UCHAR*)lpInBuffer;
|
||||
|
||||
WINPR_ASSERT(nInBufferSize >= sizeof(UCHAR));
|
||||
if (nInBufferSize < sizeof(UCHAR))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pServerSerialDriver->immediate_char(pComm, pChar);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_SERIAL_RESET_DEVICE:
|
||||
{
|
||||
if (pServerSerialDriver->reset_device)
|
||||
{
|
||||
return pServerSerialDriver->reset_device(pComm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
CommLog_Print(
|
||||
WLOG_WARN, _T("unsupported IoControlCode=[0x%08" PRIX32 "] %s (remote serial driver: %s)"),
|
||||
dwIoControlCode, _comm_serial_ioctl_name(dwIoControlCode), pServerSerialDriver->name);
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); /* => STATUS_NOT_IMPLEMENTED */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME: to be used through winpr-io's DeviceIoControl
|
||||
*
|
||||
* Any previous error as returned by GetLastError is cleared.
|
||||
*
|
||||
* ERRORS:
|
||||
* ERROR_INVALID_HANDLE
|
||||
* ERROR_INVALID_PARAMETER
|
||||
* ERROR_NOT_SUPPORTED lpOverlapped is not supported
|
||||
* ERROR_INSUFFICIENT_BUFFER
|
||||
* ERROR_CALL_NOT_IMPLEMENTED unimplemented ioctl
|
||||
*/
|
||||
BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
WINPR_COMM* pComm = (WINPR_COMM*)hDevice;
|
||||
BOOL result = 0;
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!CommIsHandled(hDevice))
|
||||
return FALSE;
|
||||
|
||||
if (!pComm->fd)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
result = s_CommDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer,
|
||||
nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
|
||||
if (lpBytesReturned && *lpBytesReturned != nOutBufferSize)
|
||||
{
|
||||
/* This might be a hint for a bug, especially when result==TRUE */
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"IoControlCode=[0x%08" PRIX32 "] %s: lpBytesReturned=%" PRIu32
|
||||
" and nOutBufferSize=%" PRIu32 " are different!",
|
||||
dwIoControlCode, _comm_serial_ioctl_name(dwIoControlCode), *lpBytesReturned,
|
||||
nOutBufferSize);
|
||||
}
|
||||
|
||||
if (pComm->permissive)
|
||||
{
|
||||
if (!result)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"[permissive]: IoControlCode=[0x%08" PRIX32 "] %s failed, ignoring",
|
||||
dwIoControlCode, _comm_serial_ioctl_name(dwIoControlCode));
|
||||
}
|
||||
|
||||
return TRUE; /* always! */
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios* termios_p)
|
||||
{
|
||||
struct termios currentState = WINPR_C_ARRAY_INIT;
|
||||
size_t count = 0;
|
||||
do
|
||||
{
|
||||
const int src = tcsetattr(fd, optional_actions, termios_p);
|
||||
if (src < 0)
|
||||
{
|
||||
char buffer[64] = WINPR_C_ARRAY_INIT;
|
||||
CommLog_Print(WLOG_WARN, "[%" PRIuz "] tcsetattr failure, errno: %s [%d]", count,
|
||||
winpr_strerror(errno, buffer, sizeof(buffer)), errno);
|
||||
return src;
|
||||
}
|
||||
|
||||
/* NB: tcsetattr() can succeed even if not all changes have been applied. */
|
||||
const int rrc = tcgetattr(fd, ¤tState);
|
||||
if (rrc < 0)
|
||||
{
|
||||
char buffer[64] = WINPR_C_ARRAY_INIT;
|
||||
CommLog_Print(WLOG_WARN, "[%" PRIuz "] tcgetattr failure, errno: %s [%d]", count,
|
||||
winpr_strerror(errno, buffer, sizeof(buffer)), errno);
|
||||
return rrc;
|
||||
}
|
||||
// NOLINTNEXTLINE(bugprone-suspicious-memory-comparison,cert-exp42-c,cert-flp37-c)
|
||||
} while ((memcmp(¤tState, termios_p, sizeof(struct termios)) != 0) && (count++ < 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* comm_ioctl_modem_flag_str(ULONG flag)
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
case SERIAL_MSR_DCTS:
|
||||
return "SERIAL_MSR_DCTS";
|
||||
case SERIAL_MSR_DDSR:
|
||||
return "SERIAL_MSR_DDSR";
|
||||
case SERIAL_MSR_TERI:
|
||||
return "SERIAL_MSR_TERI";
|
||||
case SERIAL_MSR_DDCD:
|
||||
return "SERIAL_MSR_DDCD";
|
||||
case SERIAL_MSR_CTS:
|
||||
return "SERIAL_MSR_CTS";
|
||||
case SERIAL_MSR_DSR:
|
||||
return "SERIAL_MSR_DSR";
|
||||
case SERIAL_MSR_RI:
|
||||
return "SERIAL_MSR_RI";
|
||||
case SERIAL_MSR_DCD:
|
||||
return "SERIAL_MSR_DCD";
|
||||
default:
|
||||
return "SERIAL_MSR_UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
const char* comm_ioctl_modem_status_string(ULONG status, char* buffer, size_t size)
|
||||
{
|
||||
const ULONG flags[] = { SERIAL_MSR_DCTS, SERIAL_MSR_DDSR, SERIAL_MSR_TERI, SERIAL_MSR_DDCD,
|
||||
SERIAL_MSR_CTS, SERIAL_MSR_DSR, SERIAL_MSR_RI, SERIAL_MSR_DCD
|
||||
|
||||
};
|
||||
winpr_str_append("{", buffer, size, "");
|
||||
|
||||
const char* sep = "";
|
||||
for (size_t x = 0; x < ARRAYSIZE(flags); x++)
|
||||
{
|
||||
const ULONG flag = flags[x];
|
||||
if (status & flag)
|
||||
{
|
||||
winpr_str_append(comm_ioctl_modem_flag_str(flag), buffer, size, sep);
|
||||
sep = "|";
|
||||
}
|
||||
}
|
||||
|
||||
char number[32] = WINPR_C_ARRAY_INIT;
|
||||
(void)_snprintf(number, sizeof(number), "}[0x%08" PRIx32 "]", status);
|
||||
winpr_str_append(number, buffer, size, "");
|
||||
return buffer;
|
||||
}
|
||||
232
third_party/FreeRDP/winpr/libwinpr/comm/comm_ioctl.h
vendored
Normal file
232
third_party/FreeRDP/winpr/libwinpr/comm/comm_ioctl.h
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2011 O.S. Systems Software Ltda.
|
||||
* Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* 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 WINPR_COMM_IOCTL_H_
|
||||
#define WINPR_COMM_IOCTL_H_
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#include <winpr/io.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include "comm.h"
|
||||
|
||||
/* Serial I/O Request Interface: http://msdn.microsoft.com/en-us/library/dn265347%28v=vs.85%29.aspx
|
||||
* Ntddser.h http://msdn.microsoft.com/en-us/cc308432.aspx
|
||||
* Ntddpar.h http://msdn.microsoft.com/en-us/cc308431.aspx
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* TODO: defines and types below are very similar to those in comm.h, keep only
|
||||
* those that differ more than the names */
|
||||
|
||||
#define STOP_BIT_1 0
|
||||
#define STOP_BITS_1_5 1
|
||||
#define STOP_BITS_2 2
|
||||
|
||||
#define NO_PARITY 0
|
||||
#define ODD_PARITY 1
|
||||
#define EVEN_PARITY 2
|
||||
#define MARK_PARITY 3
|
||||
#define SPACE_PARITY 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG BaudRate;
|
||||
} SERIAL_BAUD_RATE, *PSERIAL_BAUD_RATE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UCHAR EofChar;
|
||||
UCHAR ErrorChar;
|
||||
UCHAR BreakChar;
|
||||
UCHAR EventChar;
|
||||
UCHAR XonChar;
|
||||
UCHAR XoffChar;
|
||||
} SERIAL_CHARS, *PSERIAL_CHARS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UCHAR StopBits;
|
||||
UCHAR Parity;
|
||||
UCHAR WordLength;
|
||||
} SERIAL_LINE_CONTROL, *PSERIAL_LINE_CONTROL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG ControlHandShake;
|
||||
ULONG FlowReplace;
|
||||
ULONG XonLimit;
|
||||
ULONG XoffLimit;
|
||||
} SERIAL_HANDFLOW, *PSERIAL_HANDFLOW;
|
||||
|
||||
#define SERIAL_DTR_MASK ((ULONG)0x03)
|
||||
#define SERIAL_DTR_CONTROL ((ULONG)0x01)
|
||||
#define SERIAL_DTR_HANDSHAKE ((ULONG)0x02)
|
||||
#define SERIAL_CTS_HANDSHAKE ((ULONG)0x08)
|
||||
#define SERIAL_DSR_HANDSHAKE ((ULONG)0x10)
|
||||
#define SERIAL_DCD_HANDSHAKE ((ULONG)0x20)
|
||||
#define SERIAL_OUT_HANDSHAKEMASK ((ULONG)0x38)
|
||||
#define SERIAL_DSR_SENSITIVITY ((ULONG)0x40)
|
||||
#define SERIAL_ERROR_ABORT ((ULONG)0x80000000)
|
||||
#define SERIAL_CONTROL_INVALID ((ULONG)0x7fffff84)
|
||||
#define SERIAL_AUTO_TRANSMIT ((ULONG)0x01)
|
||||
#define SERIAL_AUTO_RECEIVE ((ULONG)0x02)
|
||||
#define SERIAL_ERROR_CHAR ((ULONG)0x04)
|
||||
#define SERIAL_NULL_STRIPPING ((ULONG)0x08)
|
||||
#define SERIAL_BREAK_CHAR ((ULONG)0x10)
|
||||
#define SERIAL_RTS_MASK ((ULONG)0xc0)
|
||||
#define SERIAL_RTS_CONTROL ((ULONG)0x40)
|
||||
#define SERIAL_RTS_HANDSHAKE ((ULONG)0x80)
|
||||
#define SERIAL_TRANSMIT_TOGGLE ((ULONG)0xc0)
|
||||
#define SERIAL_XOFF_CONTINUE ((ULONG)0x80000000)
|
||||
#define SERIAL_FLOW_INVALID ((ULONG)0x7fffff20)
|
||||
|
||||
#define SERIAL_SP_SERIALCOMM ((ULONG)0x00000001)
|
||||
|
||||
#define SERIAL_SP_UNSPECIFIED ((ULONG)0x00000000)
|
||||
#define SERIAL_SP_RS232 ((ULONG)0x00000001)
|
||||
#define SERIAL_SP_PARALLEL ((ULONG)0x00000002)
|
||||
#define SERIAL_SP_RS422 ((ULONG)0x00000003)
|
||||
#define SERIAL_SP_RS423 ((ULONG)0x00000004)
|
||||
#define SERIAL_SP_RS449 ((ULONG)0x00000005)
|
||||
#define SERIAL_SP_MODEM ((ULONG)0x00000006)
|
||||
#define SERIAL_SP_FAX ((ULONG)0x00000021)
|
||||
#define SERIAL_SP_SCANNER ((ULONG)0x00000022)
|
||||
#define SERIAL_SP_BRIDGE ((ULONG)0x00000100)
|
||||
#define SERIAL_SP_LAT ((ULONG)0x00000101)
|
||||
#define SERIAL_SP_TELNET ((ULONG)0x00000102)
|
||||
#define SERIAL_SP_X25 ((ULONG)0x00000103)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG ReadIntervalTimeout;
|
||||
ULONG ReadTotalTimeoutMultiplier;
|
||||
ULONG ReadTotalTimeoutConstant;
|
||||
ULONG WriteTotalTimeoutMultiplier;
|
||||
ULONG WriteTotalTimeoutConstant;
|
||||
} SERIAL_TIMEOUTS, *PSERIAL_TIMEOUTS;
|
||||
|
||||
#define SERIAL_MSR_DCTS 0x01
|
||||
#define SERIAL_MSR_DDSR 0x02
|
||||
#define SERIAL_MSR_TERI 0x04
|
||||
#define SERIAL_MSR_DDCD 0x08
|
||||
#define SERIAL_MSR_CTS 0x10
|
||||
#define SERIAL_MSR_DSR 0x20
|
||||
#define SERIAL_MSR_RI 0x40
|
||||
#define SERIAL_MSR_DCD 0x80
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG InSize;
|
||||
ULONG OutSize;
|
||||
} SERIAL_QUEUE_SIZE, *PSERIAL_QUEUE_SIZE;
|
||||
|
||||
#define SERIAL_PURGE_TXABORT 0x00000001
|
||||
#define SERIAL_PURGE_RXABORT 0x00000002
|
||||
#define SERIAL_PURGE_TXCLEAR 0x00000004
|
||||
#define SERIAL_PURGE_RXCLEAR 0x00000008
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG Errors;
|
||||
ULONG HoldReasons;
|
||||
ULONG AmountInInQueue;
|
||||
ULONG AmountInOutQueue;
|
||||
BOOLEAN EofReceived;
|
||||
BOOLEAN WaitForImmediate;
|
||||
} SERIAL_STATUS, *PSERIAL_STATUS;
|
||||
|
||||
#define SERIAL_TX_WAITING_FOR_CTS ((ULONG)0x00000001)
|
||||
#define SERIAL_TX_WAITING_FOR_DSR ((ULONG)0x00000002)
|
||||
#define SERIAL_TX_WAITING_FOR_DCD ((ULONG)0x00000004)
|
||||
#define SERIAL_TX_WAITING_FOR_XON ((ULONG)0x00000008)
|
||||
#define SERIAL_TX_WAITING_XOFF_SENT ((ULONG)0x00000010)
|
||||
#define SERIAL_TX_WAITING_ON_BREAK ((ULONG)0x00000020)
|
||||
#define SERIAL_RX_WAITING_FOR_DSR ((ULONG)0x00000040)
|
||||
|
||||
#define SERIAL_ERROR_BREAK ((ULONG)0x00000001)
|
||||
#define SERIAL_ERROR_FRAMING ((ULONG)0x00000002)
|
||||
#define SERIAL_ERROR_OVERRUN ((ULONG)0x00000004)
|
||||
#define SERIAL_ERROR_QUEUEOVERRUN ((ULONG)0x00000008)
|
||||
#define SERIAL_ERROR_PARITY ((ULONG)0x00000010)
|
||||
|
||||
#define SERIAL_DTR_STATE ((ULONG)0x00000001)
|
||||
#define SERIAL_RTS_STATE ((ULONG)0x00000002)
|
||||
#define SERIAL_CTS_STATE ((ULONG)0x00000010)
|
||||
#define SERIAL_DSR_STATE ((ULONG)0x00000020)
|
||||
#define SERIAL_RI_STATE ((ULONG)0x00000040)
|
||||
#define SERIAL_DCD_STATE ((ULONG)0x00000080)
|
||||
|
||||
/**
|
||||
* A function might be nullptr if not supported by the underlying driver.
|
||||
*
|
||||
* FIXME: better have to use input and output buffers for all functions?
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
SERIAL_DRIVER_ID id;
|
||||
TCHAR* name;
|
||||
BOOL (*set_baud_rate)(WINPR_COMM* pComm, const SERIAL_BAUD_RATE* pBaudRate);
|
||||
BOOL (*get_baud_rate)(WINPR_COMM* pComm, SERIAL_BAUD_RATE* pBaudRate);
|
||||
BOOL (*get_properties)(WINPR_COMM* pComm, COMMPROP* pProperties);
|
||||
BOOL (*set_serial_chars)(WINPR_COMM* pComm, const SERIAL_CHARS* pSerialChars);
|
||||
BOOL (*get_serial_chars)(WINPR_COMM* pComm, SERIAL_CHARS* pSerialChars);
|
||||
BOOL (*set_line_control)(WINPR_COMM* pComm, const SERIAL_LINE_CONTROL* pLineControl);
|
||||
BOOL (*get_line_control)(WINPR_COMM* pComm, SERIAL_LINE_CONTROL* pLineControl);
|
||||
BOOL (*set_handflow)(WINPR_COMM* pComm, const SERIAL_HANDFLOW* pHandflow);
|
||||
BOOL (*get_handflow)(WINPR_COMM* pComm, SERIAL_HANDFLOW* pHandflow);
|
||||
BOOL (*set_timeouts)(WINPR_COMM* pComm, const SERIAL_TIMEOUTS* pTimeouts);
|
||||
BOOL (*get_timeouts)(WINPR_COMM* pComm, SERIAL_TIMEOUTS* pTimeouts);
|
||||
BOOL (*set_dtr)(WINPR_COMM* pComm);
|
||||
BOOL (*clear_dtr)(WINPR_COMM* pComm);
|
||||
BOOL (*set_rts)(WINPR_COMM* pComm);
|
||||
BOOL (*clear_rts)(WINPR_COMM* pComm);
|
||||
BOOL (*get_modemstatus)(WINPR_COMM* pComm, ULONG* pRegister);
|
||||
BOOL (*set_wait_mask)(WINPR_COMM* pComm, const ULONG* pWaitMask);
|
||||
BOOL (*get_wait_mask)(WINPR_COMM* pComm, ULONG* pWaitMask);
|
||||
BOOL (*wait_on_mask)(WINPR_COMM* pComm, ULONG* pOutputMask);
|
||||
BOOL (*set_queue_size)(WINPR_COMM* pComm, const SERIAL_QUEUE_SIZE* pQueueSize);
|
||||
BOOL (*purge)(WINPR_COMM* pComm, const ULONG* pPurgeMask);
|
||||
BOOL (*get_commstatus)(WINPR_COMM* pComm, SERIAL_STATUS* pCommstatus);
|
||||
BOOL (*set_break_on)(WINPR_COMM* pComm);
|
||||
BOOL (*set_break_off)(WINPR_COMM* pComm);
|
||||
BOOL (*set_xoff)(WINPR_COMM* pComm);
|
||||
BOOL (*set_xon)(WINPR_COMM* pComm);
|
||||
BOOL (*get_dtrrts)(WINPR_COMM* pComm, ULONG* pMask);
|
||||
BOOL (*config_size)(WINPR_COMM* pComm, ULONG* pSize);
|
||||
BOOL (*immediate_char)(WINPR_COMM* pComm, const UCHAR* pChar);
|
||||
BOOL (*reset_device)(WINPR_COMM* pComm);
|
||||
|
||||
} SERIAL_DRIVER;
|
||||
|
||||
int comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios* termios_p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_COMM_IOCTL_H_ */
|
||||
87
third_party/FreeRDP/winpr/libwinpr/comm/comm_ioctl_dummy.c
vendored
Normal file
87
third_party/FreeRDP/winpr/libwinpr/comm/comm_ioctl_dummy.c
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API - Dummy implementation
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <winpr/comm.h>
|
||||
|
||||
#include "comm_ioctl.h"
|
||||
#include <../log.h>
|
||||
|
||||
#define TAG WINPR_TAG("comm")
|
||||
|
||||
BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
WINPR_UNUSED(hDevice);
|
||||
WINPR_UNUSED(dwIoControlCode);
|
||||
WINPR_UNUSED(lpInBuffer);
|
||||
WINPR_UNUSED(nInBufferSize);
|
||||
WINPR_UNUSED(lpOutBuffer);
|
||||
WINPR_UNUSED(nOutBufferSize);
|
||||
WINPR_UNUSED(lpBytesReturned);
|
||||
WINPR_UNUSED(lpOverlapped);
|
||||
|
||||
WLog_ERR(TAG, "TODO: Function not implemented for this platform");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios* termios_p)
|
||||
{
|
||||
WINPR_UNUSED(fd);
|
||||
WINPR_UNUSED(optional_actions);
|
||||
WINPR_UNUSED(termios_p);
|
||||
|
||||
WLog_ERR(TAG, "TODO: Function not implemented for this platform");
|
||||
return -1;
|
||||
}
|
||||
|
||||
BOOL _comm_set_permissive(HANDLE hDevice, BOOL permissive)
|
||||
{
|
||||
WINPR_UNUSED(hDevice);
|
||||
WINPR_UNUSED(permissive);
|
||||
|
||||
WLog_ERR(TAG, "TODO: Function not implemented for this platform");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
WINPR_UNUSED(hDevice);
|
||||
WINPR_UNUSED(lpBuffer);
|
||||
WINPR_UNUSED(nNumberOfBytesToRead);
|
||||
WINPR_UNUSED(lpNumberOfBytesRead);
|
||||
WINPR_UNUSED(lpOverlapped);
|
||||
|
||||
WLog_ERR(TAG, "TODO: Function not implemented for this platform");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
WINPR_UNUSED(hDevice);
|
||||
WINPR_UNUSED(lpBuffer);
|
||||
WINPR_UNUSED(nNumberOfBytesToWrite);
|
||||
WINPR_UNUSED(lpNumberOfBytesWritten);
|
||||
WINPR_UNUSED(lpOverlapped);
|
||||
|
||||
WLog_ERR(TAG, "TODO: Function not implemented for this platform");
|
||||
return FALSE;
|
||||
}
|
||||
210
third_party/FreeRDP/winpr/libwinpr/comm/comm_sercx2_sys.c
vendored
Normal file
210
third_party/FreeRDP/winpr/libwinpr/comm/comm_sercx2_sys.c
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2011 O.S. Systems Software Ltda.
|
||||
* Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#include "comm_serial_sys.h"
|
||||
#include "comm_sercx_sys.h"
|
||||
|
||||
#include "comm_sercx2_sys.h"
|
||||
|
||||
/* http://msdn.microsoft.com/en-us/library/dn265347%28v=vs.85%29.aspx
|
||||
*
|
||||
* SerCx2 does not support special characters. SerCx2 always completes
|
||||
* an IOCTL_SERIAL_SET_CHARS request with a STATUS_SUCCESS status
|
||||
* code, but does not set any special characters or perform any other
|
||||
* operation in response to this request. For an
|
||||
* IOCTL_SERIAL_GET_CHARS request, SerCx2 sets all the character
|
||||
* values in the SERIAL_CHARS structure to null, and completes the
|
||||
* request with a STATUS_SUCCESS status code.
|
||||
*/
|
||||
|
||||
static BOOL set_serial_chars(WINPR_ATTR_UNUSED WINPR_COMM* pComm,
|
||||
WINPR_ATTR_UNUSED const SERIAL_CHARS* pSerialChars)
|
||||
{
|
||||
WINPR_ASSERT(pComm);
|
||||
WINPR_ASSERT(pSerialChars);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL get_serial_chars(WINPR_ATTR_UNUSED WINPR_COMM* pComm, SERIAL_CHARS* pSerialChars)
|
||||
{
|
||||
WINPR_ASSERT(pComm);
|
||||
WINPR_ASSERT(pSerialChars);
|
||||
|
||||
ZeroMemory(pSerialChars, sizeof(SERIAL_CHARS));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* http://msdn.microsoft.com/en-us/library/windows/hardware/hh439605%28v=vs.85%29.aspx */
|
||||
/* FIXME: only using the Serial.sys' events, complete the support of the remaining events */
|
||||
static const ULONG SERCX2_SYS_SUPPORTED_EV_MASK =
|
||||
SERIAL_EV_RXCHAR | SERIAL_EV_RXFLAG | SERIAL_EV_TXEMPTY | SERIAL_EV_CTS | SERIAL_EV_DSR |
|
||||
SERIAL_EV_RLSD | SERIAL_EV_BREAK | SERIAL_EV_ERR | SERIAL_EV_RING |
|
||||
/* SERIAL_EV_PERR | */
|
||||
SERIAL_EV_RX80FULL /*|
|
||||
SERIAL_EV_EVENT1 |
|
||||
SERIAL_EV_EVENT2*/
|
||||
;
|
||||
|
||||
/* use Serial.sys for basis (not SerCx.sys) */
|
||||
static BOOL set_wait_mask(WINPR_COMM* pComm, const ULONG* pWaitMask)
|
||||
{
|
||||
const SERIAL_DRIVER* pSerialSys = SerialSys_s();
|
||||
|
||||
WINPR_ASSERT(pComm);
|
||||
WINPR_ASSERT(pWaitMask);
|
||||
WINPR_ASSERT(pSerialSys);
|
||||
|
||||
const ULONG possibleMask = *pWaitMask & SERCX2_SYS_SUPPORTED_EV_MASK;
|
||||
|
||||
if (possibleMask != *pWaitMask)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"Not all wait events supported (SerCx2.sys), requested events= 0x%08" PRIX32
|
||||
", possible events= 0x%08" PRIX32 "",
|
||||
*pWaitMask, possibleMask);
|
||||
|
||||
/* FIXME: shall we really set the possibleMask and return FALSE? */
|
||||
pComm->WaitEventMask = possibleMask;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* NB: All events that are supported by SerCx.sys are supported by Serial.sys*/
|
||||
return pSerialSys->set_wait_mask(pComm, pWaitMask);
|
||||
}
|
||||
|
||||
static BOOL purge(WINPR_COMM* pComm, const ULONG* pPurgeMask)
|
||||
{
|
||||
const SERIAL_DRIVER* pSerialSys = SerialSys_s();
|
||||
|
||||
WINPR_ASSERT(pComm);
|
||||
WINPR_ASSERT(pPurgeMask);
|
||||
WINPR_ASSERT(pSerialSys);
|
||||
|
||||
/* http://msdn.microsoft.com/en-us/library/windows/hardware/ff546655%28v=vs.85%29.aspx */
|
||||
|
||||
if ((*pPurgeMask & SERIAL_PURGE_RXCLEAR) && !(*pPurgeMask & SERIAL_PURGE_RXABORT))
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"Expecting SERIAL_PURGE_RXABORT since SERIAL_PURGE_RXCLEAR is set");
|
||||
SetLastError(ERROR_INVALID_DEVICE_OBJECT_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((*pPurgeMask & SERIAL_PURGE_TXCLEAR) && !(*pPurgeMask & SERIAL_PURGE_TXABORT))
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"Expecting SERIAL_PURGE_TXABORT since SERIAL_PURGE_TXCLEAR is set");
|
||||
SetLastError(ERROR_INVALID_DEVICE_OBJECT_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pSerialSys->purge(pComm, pPurgeMask);
|
||||
}
|
||||
|
||||
/* specific functions only */
|
||||
static SERIAL_DRIVER SerCx2Sys = {
|
||||
.id = SerialDriverSerCx2Sys,
|
||||
.name = _T("SerCx2.sys"),
|
||||
.set_baud_rate = nullptr,
|
||||
.get_baud_rate = nullptr,
|
||||
.get_properties = nullptr,
|
||||
.set_serial_chars = set_serial_chars,
|
||||
.get_serial_chars = get_serial_chars,
|
||||
.set_line_control = nullptr,
|
||||
.get_line_control = nullptr,
|
||||
.set_handflow = nullptr,
|
||||
.get_handflow = nullptr,
|
||||
.set_timeouts = nullptr,
|
||||
.get_timeouts = nullptr,
|
||||
.set_dtr = nullptr,
|
||||
.clear_dtr = nullptr,
|
||||
.set_rts = nullptr,
|
||||
.clear_rts = nullptr,
|
||||
.get_modemstatus = nullptr,
|
||||
.set_wait_mask = set_wait_mask,
|
||||
.get_wait_mask = nullptr,
|
||||
.wait_on_mask = nullptr,
|
||||
.set_queue_size = nullptr,
|
||||
.purge = purge,
|
||||
.get_commstatus = nullptr,
|
||||
.set_break_on = nullptr,
|
||||
.set_break_off = nullptr,
|
||||
.set_xoff = nullptr, /* not supported by SerCx2.sys */
|
||||
.set_xon = nullptr, /* not supported by SerCx2.sys */
|
||||
.get_dtrrts = nullptr,
|
||||
.config_size = nullptr, /* not supported by SerCx2.sys */
|
||||
.immediate_char = nullptr, /* not supported by SerCx2.sys */
|
||||
.reset_device = nullptr, /* not supported by SerCx2.sys */
|
||||
};
|
||||
|
||||
const SERIAL_DRIVER* SerCx2Sys_s(void)
|
||||
{
|
||||
/* SerCx2Sys completed with inherited functions from SerialSys or SerCxSys */
|
||||
const SERIAL_DRIVER* pSerialSys = SerialSys_s();
|
||||
const SERIAL_DRIVER* pSerCxSys = SerCxSys_s();
|
||||
if (!pSerialSys || !pSerCxSys)
|
||||
return nullptr;
|
||||
|
||||
SerCx2Sys.set_baud_rate = pSerialSys->set_baud_rate;
|
||||
SerCx2Sys.get_baud_rate = pSerialSys->get_baud_rate;
|
||||
|
||||
SerCx2Sys.get_properties = pSerialSys->get_properties;
|
||||
|
||||
SerCx2Sys.set_line_control = pSerCxSys->set_line_control;
|
||||
SerCx2Sys.get_line_control = pSerCxSys->get_line_control;
|
||||
|
||||
/* Only SERIAL_CTS_HANDSHAKE, SERIAL_RTS_CONTROL and SERIAL_RTS_HANDSHAKE flags are really
|
||||
* required by SerCx2.sys http://msdn.microsoft.com/en-us/library/jj680685%28v=vs.85%29.aspx
|
||||
*/
|
||||
SerCx2Sys.set_handflow = pSerialSys->set_handflow;
|
||||
SerCx2Sys.get_handflow = pSerialSys->get_handflow;
|
||||
|
||||
SerCx2Sys.set_timeouts = pSerialSys->set_timeouts;
|
||||
SerCx2Sys.get_timeouts = pSerialSys->get_timeouts;
|
||||
|
||||
SerCx2Sys.set_dtr = pSerialSys->set_dtr;
|
||||
SerCx2Sys.clear_dtr = pSerialSys->clear_dtr;
|
||||
|
||||
SerCx2Sys.set_rts = pSerialSys->set_rts;
|
||||
SerCx2Sys.clear_rts = pSerialSys->clear_rts;
|
||||
|
||||
SerCx2Sys.get_modemstatus = pSerialSys->get_modemstatus;
|
||||
|
||||
SerCx2Sys.set_wait_mask = pSerialSys->set_wait_mask;
|
||||
SerCx2Sys.get_wait_mask = pSerialSys->get_wait_mask;
|
||||
SerCx2Sys.wait_on_mask = pSerialSys->wait_on_mask;
|
||||
|
||||
SerCx2Sys.set_queue_size = pSerialSys->set_queue_size;
|
||||
|
||||
SerCx2Sys.get_commstatus = pSerialSys->get_commstatus;
|
||||
|
||||
SerCx2Sys.set_break_on = pSerialSys->set_break_on;
|
||||
SerCx2Sys.set_break_off = pSerialSys->set_break_off;
|
||||
|
||||
SerCx2Sys.get_dtrrts = pSerialSys->get_dtrrts;
|
||||
|
||||
return &SerCx2Sys;
|
||||
}
|
||||
36
third_party/FreeRDP/winpr/libwinpr/comm/comm_sercx2_sys.h
vendored
Normal file
36
third_party/FreeRDP/winpr/libwinpr/comm/comm_sercx2_sys.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* 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 COMM_SERCX2_SYS_H
|
||||
#define COMM_SERCX2_SYS_H
|
||||
|
||||
#include "comm_ioctl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
const SERIAL_DRIVER* SerCx2Sys_s(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMM_SERCX2_SYS_H */
|
||||
261
third_party/FreeRDP/winpr/libwinpr/comm/comm_sercx_sys.c
vendored
Normal file
261
third_party/FreeRDP/winpr/libwinpr/comm/comm_sercx_sys.c
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2011 O.S. Systems Software Ltda.
|
||||
* Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#include "comm_serial_sys.h"
|
||||
#include "comm_sercx_sys.h"
|
||||
|
||||
static BOOL set_handflow(WINPR_COMM* pComm, const SERIAL_HANDFLOW* pHandflow)
|
||||
{
|
||||
SERIAL_HANDFLOW SerCxHandflow;
|
||||
BOOL result = TRUE;
|
||||
const SERIAL_DRIVER* pSerialSys = SerialSys_s();
|
||||
|
||||
memcpy(&SerCxHandflow, pHandflow, sizeof(SERIAL_HANDFLOW));
|
||||
|
||||
/* filter out unsupported bits by SerCx.sys
|
||||
*
|
||||
* http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx
|
||||
*/
|
||||
|
||||
SerCxHandflow.ControlHandShake =
|
||||
pHandflow->ControlHandShake &
|
||||
(SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE);
|
||||
SerCxHandflow.FlowReplace =
|
||||
pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE);
|
||||
|
||||
if (SerCxHandflow.ControlHandShake != pHandflow->ControlHandShake)
|
||||
{
|
||||
if (pHandflow->ControlHandShake & SERIAL_DCD_HANDSHAKE)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"SERIAL_DCD_HANDSHAKE not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_DSR_SENSITIVITY)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"SERIAL_DSR_SENSITIVITY not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_ERROR_ABORT)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"SERIAL_ERROR_ABORT not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE;
|
||||
}
|
||||
|
||||
if (SerCxHandflow.FlowReplace != pHandflow->FlowReplace)
|
||||
{
|
||||
if (pHandflow->ControlHandShake & SERIAL_AUTO_TRANSMIT)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"SERIAL_AUTO_TRANSMIT not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_AUTO_RECEIVE)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"SERIAL_AUTO_RECEIVE not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_ERROR_CHAR)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"SERIAL_ERROR_CHAR not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_NULL_STRIPPING)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"SERIAL_NULL_STRIPPING not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_BREAK_CHAR)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"SERIAL_BREAK_CHAR not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_XOFF_CONTINUE)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"SERIAL_XOFF_CONTINUE not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE;
|
||||
}
|
||||
|
||||
if (!pSerialSys->set_handflow(pComm, &SerCxHandflow))
|
||||
return FALSE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL get_handflow(WINPR_COMM* pComm, SERIAL_HANDFLOW* pHandflow)
|
||||
{
|
||||
const SERIAL_DRIVER* pSerialSys = SerialSys_s();
|
||||
|
||||
BOOL result = pSerialSys->get_handflow(pComm, pHandflow);
|
||||
|
||||
/* filter out unsupported bits by SerCx.sys
|
||||
*
|
||||
* http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx
|
||||
*/
|
||||
|
||||
pHandflow->ControlHandShake =
|
||||
pHandflow->ControlHandShake &
|
||||
(SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE);
|
||||
pHandflow->FlowReplace = pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* http://msdn.microsoft.com/en-us/library/windows/hardware/hh439605%28v=vs.85%29.aspx */
|
||||
static const ULONG SERCX_SYS_SUPPORTED_EV_MASK = SERIAL_EV_RXCHAR |
|
||||
/* SERIAL_EV_RXFLAG | */
|
||||
SERIAL_EV_TXEMPTY | SERIAL_EV_CTS | SERIAL_EV_DSR |
|
||||
SERIAL_EV_RLSD | SERIAL_EV_BREAK | SERIAL_EV_ERR |
|
||||
SERIAL_EV_RING /* |
|
||||
SERIAL_EV_PERR |
|
||||
SERIAL_EV_RX80FULL |
|
||||
SERIAL_EV_EVENT1 |
|
||||
SERIAL_EV_EVENT2*/
|
||||
;
|
||||
|
||||
static BOOL set_wait_mask(WINPR_COMM* pComm, const ULONG* pWaitMask)
|
||||
{
|
||||
const SERIAL_DRIVER* pSerialSys = SerialSys_s();
|
||||
WINPR_ASSERT(pWaitMask);
|
||||
|
||||
const ULONG possibleMask = *pWaitMask & SERCX_SYS_SUPPORTED_EV_MASK;
|
||||
|
||||
if (possibleMask != *pWaitMask)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"Not all wait events supported (SerCx.sys), requested events= 0x%08" PRIX32
|
||||
", possible events= 0x%08" PRIX32 "",
|
||||
*pWaitMask, possibleMask);
|
||||
|
||||
/* FIXME: shall we really set the possibleMask and return FALSE? */
|
||||
pComm->WaitEventMask = possibleMask;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* NB: All events that are supported by SerCx.sys are supported by Serial.sys*/
|
||||
return pSerialSys->set_wait_mask(pComm, pWaitMask);
|
||||
}
|
||||
|
||||
/* specific functions only */
|
||||
static SERIAL_DRIVER SerCxSys = {
|
||||
.id = SerialDriverSerCxSys,
|
||||
.name = _T("SerCx.sys"),
|
||||
.set_baud_rate = nullptr,
|
||||
.get_baud_rate = nullptr,
|
||||
.get_properties = nullptr,
|
||||
.set_serial_chars = nullptr,
|
||||
.get_serial_chars = nullptr,
|
||||
.set_line_control = nullptr,
|
||||
.get_line_control = nullptr,
|
||||
.set_handflow = set_handflow,
|
||||
.get_handflow = get_handflow,
|
||||
.set_timeouts = nullptr,
|
||||
.get_timeouts = nullptr,
|
||||
.set_dtr = nullptr,
|
||||
.clear_dtr = nullptr,
|
||||
.set_rts = nullptr,
|
||||
.clear_rts = nullptr,
|
||||
.get_modemstatus = nullptr,
|
||||
.set_wait_mask = set_wait_mask,
|
||||
.get_wait_mask = nullptr,
|
||||
.wait_on_mask = nullptr,
|
||||
.set_queue_size = nullptr,
|
||||
.purge = nullptr,
|
||||
.get_commstatus = nullptr,
|
||||
.set_break_on = nullptr,
|
||||
.set_break_off = nullptr,
|
||||
.set_xoff = nullptr,
|
||||
.set_xon = nullptr,
|
||||
.get_dtrrts = nullptr,
|
||||
.config_size = nullptr, /* not supported by SerCx.sys */
|
||||
.immediate_char = nullptr,
|
||||
.reset_device = nullptr, /* not supported by SerCx.sys */
|
||||
};
|
||||
|
||||
const SERIAL_DRIVER* SerCxSys_s(void)
|
||||
{
|
||||
/* _SerCxSys completed with inherited functions from SerialSys */
|
||||
const SERIAL_DRIVER* pSerialSys = SerialSys_s();
|
||||
if (!pSerialSys)
|
||||
return nullptr;
|
||||
|
||||
SerCxSys.set_baud_rate = pSerialSys->set_baud_rate;
|
||||
SerCxSys.get_baud_rate = pSerialSys->get_baud_rate;
|
||||
|
||||
SerCxSys.get_properties = pSerialSys->get_properties;
|
||||
|
||||
SerCxSys.set_serial_chars = pSerialSys->set_serial_chars;
|
||||
SerCxSys.get_serial_chars = pSerialSys->get_serial_chars;
|
||||
SerCxSys.set_line_control = pSerialSys->set_line_control;
|
||||
SerCxSys.get_line_control = pSerialSys->get_line_control;
|
||||
|
||||
SerCxSys.set_timeouts = pSerialSys->set_timeouts;
|
||||
SerCxSys.get_timeouts = pSerialSys->get_timeouts;
|
||||
|
||||
SerCxSys.set_dtr = pSerialSys->set_dtr;
|
||||
SerCxSys.clear_dtr = pSerialSys->clear_dtr;
|
||||
|
||||
SerCxSys.set_rts = pSerialSys->set_rts;
|
||||
SerCxSys.clear_rts = pSerialSys->clear_rts;
|
||||
|
||||
SerCxSys.get_modemstatus = pSerialSys->get_modemstatus;
|
||||
|
||||
SerCxSys.set_wait_mask = pSerialSys->set_wait_mask;
|
||||
SerCxSys.get_wait_mask = pSerialSys->get_wait_mask;
|
||||
SerCxSys.wait_on_mask = pSerialSys->wait_on_mask;
|
||||
|
||||
SerCxSys.set_queue_size = pSerialSys->set_queue_size;
|
||||
|
||||
SerCxSys.purge = pSerialSys->purge;
|
||||
|
||||
SerCxSys.get_commstatus = pSerialSys->get_commstatus;
|
||||
|
||||
SerCxSys.set_break_on = pSerialSys->set_break_on;
|
||||
SerCxSys.set_break_off = pSerialSys->set_break_off;
|
||||
|
||||
SerCxSys.set_xoff = pSerialSys->set_xoff;
|
||||
SerCxSys.set_xon = pSerialSys->set_xon;
|
||||
|
||||
SerCxSys.get_dtrrts = pSerialSys->get_dtrrts;
|
||||
|
||||
SerCxSys.immediate_char = pSerialSys->immediate_char;
|
||||
|
||||
return &SerCxSys;
|
||||
}
|
||||
36
third_party/FreeRDP/winpr/libwinpr/comm/comm_sercx_sys.h
vendored
Normal file
36
third_party/FreeRDP/winpr/libwinpr/comm/comm_sercx_sys.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* 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 COMM_SERCX_SYS_H
|
||||
#define COMM_SERCX_SYS_H
|
||||
|
||||
#include "comm_ioctl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
const SERIAL_DRIVER* SerCxSys_s(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMM_SERCX_SYS_H */
|
||||
1666
third_party/FreeRDP/winpr/libwinpr/comm/comm_serial_sys.c
vendored
Normal file
1666
third_party/FreeRDP/winpr/libwinpr/comm/comm_serial_sys.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
36
third_party/FreeRDP/winpr/libwinpr/comm/comm_serial_sys.h
vendored
Normal file
36
third_party/FreeRDP/winpr/libwinpr/comm/comm_serial_sys.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* 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 COMM_SERIAL_SYS_H
|
||||
#define COMM_SERIAL_SYS_H
|
||||
|
||||
#include "comm_ioctl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
const SERIAL_DRIVER* SerialSys_s(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMM_SERIAL_SYS_H */
|
||||
34
third_party/FreeRDP/winpr/libwinpr/comm/test/CMakeLists.txt
vendored
Normal file
34
third_party/FreeRDP/winpr/libwinpr/comm/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
set(MODULE_NAME "TestComm")
|
||||
set(MODULE_PREFIX "TEST_COMM")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestCommDevice.c
|
||||
TestCommConfig.c
|
||||
TestGetCommState.c
|
||||
TestSetCommState.c
|
||||
TestSerialChars.c
|
||||
TestControlSettings.c
|
||||
TestHandflow.c
|
||||
TestTimeouts.c
|
||||
TestCommMonitor.c
|
||||
)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
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})
|
||||
set_tests_properties(${TestName} PROPERTIES LABELS "comm")
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
|
||||
151
third_party/FreeRDP/winpr/libwinpr/comm/test/TestCommConfig.c
vendored
Normal file
151
third_party/FreeRDP/winpr/libwinpr/comm/test/TestCommConfig.c
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/comm.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/handle.h>
|
||||
|
||||
int TestCommConfig(int argc, char* argv[])
|
||||
{
|
||||
DCB dcb = WINPR_C_ARRAY_INIT;
|
||||
BOOL success = FALSE;
|
||||
LPCSTR lpFileName = "\\\\.\\COM1";
|
||||
COMMPROP commProp = WINPR_C_ARRAY_INIT;
|
||||
struct stat statbuf = WINPR_C_ARRAY_INIT;
|
||||
|
||||
HANDLE hComm = CreateFileA(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING,
|
||||
0, nullptr);
|
||||
|
||||
if (hComm && (hComm != INVALID_HANDLE_VALUE))
|
||||
{
|
||||
(void)fprintf(
|
||||
stderr, "CreateFileA failure: could create a handle on a not yet defined device: %s\n",
|
||||
lpFileName);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (stat("/dev/ttyS0", &statbuf) < 0)
|
||||
{
|
||||
(void)fprintf(stderr, "/dev/ttyS0 not available, making the test to succeed though\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
success = DefineCommDevice(lpFileName, "/dev/ttyS0");
|
||||
if (!success)
|
||||
{
|
||||
(void)fprintf(stderr, "DefineCommDevice failure: %s\n", lpFileName);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
hComm = CreateFileA(lpFileName, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE, /* invalid parameter */
|
||||
nullptr, CREATE_NEW, /* invalid parameter */
|
||||
0, (HANDLE)1234); /* invalid parameter */
|
||||
if (hComm != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void)fprintf(
|
||||
stderr, "CreateFileA failure: could create a handle with some invalid parameters %s\n",
|
||||
lpFileName);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
hComm = CreateFileA(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0,
|
||||
nullptr);
|
||||
|
||||
if (!hComm || (hComm == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
(void)fprintf(stderr, "CreateFileA failure: %s GetLastError() = 0x%08x\n", lpFileName,
|
||||
GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* TODO: a second call to CreateFileA should failed and
|
||||
* GetLastError should return ERROR_SHARING_VIOLATION */
|
||||
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
success = GetCommState(hComm, &dcb);
|
||||
if (!success)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: GetLastError() = Ox%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
(void)fprintf(stderr,
|
||||
"BaudRate: %" PRIu32 " ByteSize: %" PRIu8 " Parity: %" PRIu8 " StopBits: %" PRIu8
|
||||
"\n",
|
||||
dcb.BaudRate, dcb.ByteSize, dcb.Parity, dcb.StopBits);
|
||||
|
||||
if (!GetCommProperties(hComm, &commProp))
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommProperties failure: GetLastError(): 0x%08x\n",
|
||||
GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if ((commProp.dwSettableBaud & BAUD_57600) <= 0)
|
||||
{
|
||||
(void)fprintf(stderr, "BAUD_57600 unsupported!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if ((commProp.dwSettableBaud & BAUD_14400) > 0)
|
||||
{
|
||||
(void)fprintf(stderr, "BAUD_14400 supported!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
dcb.BaudRate = CBR_57600;
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
|
||||
success = SetCommState(hComm, &dcb);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure: GetLastError() = 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
success = GetCommState(hComm, &dcb);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: GetLastError() = 0x%x\n", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((dcb.BaudRate != CBR_57600) || (dcb.ByteSize != 8) || (dcb.Parity != NOPARITY) ||
|
||||
(dcb.StopBits != ONESTOPBIT))
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"Got an unexpected value among: BaudRate: %" PRIu32 " ByteSize: %" PRIu8
|
||||
" Parity: %" PRIu8 " StopBits: %" PRIu8 "\n",
|
||||
dcb.BaudRate, dcb.ByteSize, dcb.Parity, dcb.StopBits);
|
||||
}
|
||||
|
||||
(void)CloseHandle(hComm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
115
third_party/FreeRDP/winpr/libwinpr/comm/test/TestCommDevice.c
vendored
Normal file
115
third_party/FreeRDP/winpr/libwinpr/comm/test/TestCommDevice.c
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <winpr/comm.h>
|
||||
#include <winpr/tchar.h>
|
||||
|
||||
static int test_CommDevice(LPCTSTR lpDeviceName, BOOL expectedResult)
|
||||
{
|
||||
TCHAR lpTargetPath[MAX_PATH] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
BOOL result = DefineCommDevice(lpDeviceName, _T("/dev/test"));
|
||||
if ((!expectedResult && result) || (expectedResult && !result)) /* logical XOR */
|
||||
{
|
||||
_tprintf(_T("DefineCommDevice failure: device name: %s, expected result: %s, result: %s\n"),
|
||||
lpDeviceName, (expectedResult ? "TRUE" : "FALSE"), (result ? "TRUE" : "FALSE"));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
result = IsCommDevice(lpDeviceName);
|
||||
if ((!expectedResult && result) || (expectedResult && !result)) /* logical XOR */
|
||||
{
|
||||
_tprintf(_T("IsCommDevice failure: device name: %s, expected result: %s, result: %s\n"),
|
||||
lpDeviceName, (expectedResult ? "TRUE" : "FALSE"), (result ? "TRUE" : "FALSE"));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const size_t tclen = QueryCommDevice(lpDeviceName, lpTargetPath, MAX_PATH);
|
||||
if (expectedResult)
|
||||
{
|
||||
const size_t tlen = _tcsnlen(lpTargetPath, ARRAYSIZE(lpTargetPath) - 1);
|
||||
if (tclen <= tlen) /* at least 2 more TCHAR are expected */
|
||||
{
|
||||
_tprintf(_T("QueryCommDevice failure: didn't find the device name: %s\n"),
|
||||
lpDeviceName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_tcsncmp(_T("/dev/test"), lpTargetPath, ARRAYSIZE(lpTargetPath)) != 0)
|
||||
{
|
||||
_tprintf(
|
||||
_T("QueryCommDevice failure: device name: %s, expected result: %s, result: %s\n"),
|
||||
lpDeviceName, _T("/dev/test"), lpTargetPath);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((tlen >= (ARRAYSIZE(lpTargetPath) - 1)) || (lpTargetPath[tlen + 1] != 0))
|
||||
{
|
||||
_tprintf(
|
||||
_T("QueryCommDevice failure: device name: %s, the second nullptr character is ")
|
||||
_T("missing at the end of the buffer\n"),
|
||||
lpDeviceName);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tclen > 0)
|
||||
{
|
||||
_tprintf(_T("QueryCommDevice failure: device name: %s, expected result: <none>, ")
|
||||
_T("result: %") _T(PRIuz) _T(" %s\n"),
|
||||
lpDeviceName, tclen, lpTargetPath);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TestCommDevice(int argc, char* argv[])
|
||||
{
|
||||
if (!test_CommDevice(_T("COM0"), FALSE))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!test_CommDevice(_T("COM1"), TRUE))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!test_CommDevice(_T("COM1"), TRUE))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!test_CommDevice(_T("COM10"), FALSE))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!test_CommDevice(_T("\\\\.\\COM5"), TRUE))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!test_CommDevice(_T("\\\\.\\COM10"), TRUE))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!test_CommDevice(_T("\\\\.COM10"), FALSE))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
70
third_party/FreeRDP/winpr/libwinpr/comm/test/TestCommMonitor.c
vendored
Normal file
70
third_party/FreeRDP/winpr/libwinpr/comm/test/TestCommMonitor.c
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/comm.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/handle.h>
|
||||
|
||||
int TestCommMonitor(int argc, char* argv[])
|
||||
{
|
||||
HANDLE hComm = nullptr;
|
||||
DWORD dwError = 0;
|
||||
BOOL fSuccess = 0;
|
||||
DWORD dwEvtMask = 0;
|
||||
OVERLAPPED overlapped = WINPR_C_ARRAY_INIT;
|
||||
LPCSTR lpFileName = "\\\\.\\COM1";
|
||||
|
||||
hComm = CreateFileA(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED, nullptr);
|
||||
|
||||
if (!hComm || (hComm == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
printf("CreateFileA failure: %s\n", lpFileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fSuccess = SetCommMask(hComm, EV_CTS | EV_DSR);
|
||||
|
||||
if (!fSuccess)
|
||||
{
|
||||
printf("SetCommMask failure: GetLastError() = %" PRIu32 "\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(overlapped.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
|
||||
{
|
||||
printf("CreateEvent failed: GetLastError() = %" PRIu32 "\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (WaitCommEvent(hComm, &dwEvtMask, &overlapped))
|
||||
{
|
||||
if (dwEvtMask & EV_DSR)
|
||||
{
|
||||
printf("EV_DSR\n");
|
||||
}
|
||||
|
||||
if (dwEvtMask & EV_CTS)
|
||||
{
|
||||
printf("EV_CTS\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dwError = GetLastError();
|
||||
|
||||
if (dwError == ERROR_IO_PENDING)
|
||||
{
|
||||
printf("ERROR_IO_PENDING\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("WaitCommEvent failure: GetLastError() = %" PRIu32 "\n", dwError);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
(void)CloseHandle(hComm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
123
third_party/FreeRDP/winpr/libwinpr/comm/test/TestControlSettings.c
vendored
Normal file
123
third_party/FreeRDP/winpr/libwinpr/comm/test/TestControlSettings.c
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <winpr/comm.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include "../comm.h"
|
||||
|
||||
int TestControlSettings(int argc, char* argv[])
|
||||
{
|
||||
struct stat statbuf = WINPR_C_ARRAY_INIT;
|
||||
BOOL result = 0;
|
||||
HANDLE hComm = nullptr;
|
||||
DCB dcb = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (stat("/dev/ttyS0", &statbuf) < 0)
|
||||
{
|
||||
(void)fprintf(stderr, "/dev/ttyS0 not available, making the test to succeed though\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
result = DefineCommDevice("COM1", "/dev/ttyS0");
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "DefineCommDevice failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (hComm == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void)fprintf(stderr, "CreateFileA failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
ZeroMemory(&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!GetCommState(hComm, &dcb))
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure; GetLastError(): %08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Test 1 */
|
||||
|
||||
dcb.ByteSize = 5;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
dcb.Parity = MARKPARITY;
|
||||
|
||||
if (!SetCommState(hComm, &dcb))
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure; GetLastError(): %08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!GetCommState(hComm, &dcb))
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure; GetLastError(): %08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((dcb.ByteSize != 5) || (dcb.StopBits != ONESTOPBIT) || (dcb.Parity != MARKPARITY))
|
||||
{
|
||||
(void)fprintf(stderr, "test1 failed.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Test 2 */
|
||||
|
||||
dcb.ByteSize = 8;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
dcb.Parity = NOPARITY;
|
||||
|
||||
if (!SetCommState(hComm, &dcb))
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure; GetLastError(): %08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!GetCommState(hComm, &dcb))
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure; GetLastError(): %08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((dcb.ByteSize != 8) || (dcb.StopBits != ONESTOPBIT) || (dcb.Parity != NOPARITY))
|
||||
{
|
||||
(void)fprintf(stderr, "test2 failed.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!CloseHandle(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "CloseHandle failure, GetLastError()=%08x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
140
third_party/FreeRDP/winpr/libwinpr/comm/test/TestGetCommState.c
vendored
Normal file
140
third_party/FreeRDP/winpr/libwinpr/comm/test/TestGetCommState.c
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <winpr/comm.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include "../comm.h"
|
||||
|
||||
static BOOL test_generic(HANDLE hComm)
|
||||
{
|
||||
DCB dcb = WINPR_C_ARRAY_INIT;
|
||||
DCB* pDcb = nullptr;
|
||||
BOOL result = 0;
|
||||
|
||||
ZeroMemory(&dcb, sizeof(DCB));
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (result)
|
||||
{
|
||||
printf("GetCommState failure, should have returned false because dcb.DCBlength has been "
|
||||
"let uninitialized\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB) / 2; /* improper value */
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (result)
|
||||
{
|
||||
printf("GetCommState failure, should have return false because dcb.DCBlength was not "
|
||||
"correctly initialized\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
printf("GetCommState failure: Ox%x, with adjusted DCBlength\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pDcb = (DCB*)calloc(2, sizeof(DCB));
|
||||
if (!pDcb)
|
||||
return FALSE;
|
||||
pDcb->DCBlength = sizeof(DCB) * 2;
|
||||
result = GetCommState(hComm, pDcb);
|
||||
result = result && (pDcb->DCBlength == sizeof(DCB) * 2);
|
||||
free(pDcb);
|
||||
if (!result)
|
||||
{
|
||||
printf("GetCommState failure: 0x%x, with bigger DCBlength\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TestGetCommState(int argc, char* argv[])
|
||||
{
|
||||
struct stat statbuf = WINPR_C_ARRAY_INIT;
|
||||
BOOL result = 0;
|
||||
HANDLE hComm = nullptr;
|
||||
|
||||
if (stat("/dev/ttyS0", &statbuf) < 0)
|
||||
{
|
||||
(void)fprintf(stderr, "/dev/ttyS0 not available, making the test to succeed though\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
result = DefineCommDevice("COM1", "/dev/ttyS0");
|
||||
if (!result)
|
||||
{
|
||||
printf("DefineCommDevice failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
hComm =
|
||||
CreateFileA("COM1", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
|
||||
if (hComm == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("CreateFileA failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
printf("test_generic failure (SerialDriverUnknown)\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerialSys);
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
printf("test_generic failure (SerialDriverSerialSys)\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerCxSys);
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
printf("test_generic failure (SerialDriverSerCxSys)\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerCx2Sys);
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
printf("test_generic failure (SerialDriverSerCx2Sys)\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!CloseHandle(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "CloseHandle failure, GetLastError()=%08x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
92
third_party/FreeRDP/winpr/libwinpr/comm/test/TestHandflow.c
vendored
Normal file
92
third_party/FreeRDP/winpr/libwinpr/comm/test/TestHandflow.c
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <termios.h>
|
||||
#endif
|
||||
|
||||
#include <winpr/comm.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include "../comm.h"
|
||||
|
||||
static BOOL test_SerialSys(HANDLE hComm)
|
||||
{
|
||||
// TMP: TODO:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TestHandflow(int argc, char* argv[])
|
||||
{
|
||||
struct stat statbuf = WINPR_C_ARRAY_INIT;
|
||||
BOOL result = 0;
|
||||
HANDLE hComm = nullptr;
|
||||
|
||||
if (stat("/dev/ttyS0", &statbuf) < 0)
|
||||
{
|
||||
(void)fprintf(stderr, "/dev/ttyS0 not available, making the test to succeed though\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
result = DefineCommDevice("COM1", "/dev/ttyS0");
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "DefineCommDevice failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (hComm == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void)fprintf(stderr, "CreateFileA failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerialSys);
|
||||
if (!test_SerialSys(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCxSys failure\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* _comm_setServerSerialDriver(hComm, SerialDriverSerCxSys); */
|
||||
/* if (!test_SerCxSys(hComm)) */
|
||||
/* { */
|
||||
/* (void)fprintf(stderr, "test_SerCxSys failure\n"); */
|
||||
/* return EXIT_FAILURE; */
|
||||
/* } */
|
||||
|
||||
/* _comm_setServerSerialDriver(hComm, SerialDriverSerCx2Sys); */
|
||||
/* if (!test_SerCx2Sys(hComm)) */
|
||||
/* { */
|
||||
/* (void)fprintf(stderr, "test_SerCxSys failure\n"); */
|
||||
/* return EXIT_FAILURE; */
|
||||
/* } */
|
||||
|
||||
if (!CloseHandle(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "CloseHandle failure, GetLastError()=%08x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
180
third_party/FreeRDP/winpr/libwinpr/comm/test/TestSerialChars.c
vendored
Normal file
180
third_party/FreeRDP/winpr/libwinpr/comm/test/TestSerialChars.c
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <termios.h>
|
||||
#endif
|
||||
|
||||
#include <winpr/comm.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include "../comm.h"
|
||||
|
||||
static BOOL test_SerCxSys(HANDLE hComm)
|
||||
{
|
||||
DCB dcb = WINPR_C_ARRAY_INIT;
|
||||
UCHAR XonChar = 0;
|
||||
UCHAR XoffChar = 0;
|
||||
|
||||
struct termios currentTermios = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (tcgetattr(((WINPR_COMM*)hComm)->fd, ¤tTermios) < 0)
|
||||
{
|
||||
(void)fprintf(stderr, "tcgetattr failure.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!GetCommState(hComm, &dcb))
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure, GetLastError(): 0x%08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((dcb.XonChar == '\0') || (dcb.XoffChar == '\0'))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCxSys failure, expected XonChar and XoffChar to be set\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* retrieve Xon/Xoff chars */
|
||||
if ((dcb.XonChar != currentTermios.c_cc[VSTART]) ||
|
||||
(dcb.XoffChar != currentTermios.c_cc[VSTOP]))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCxSys failure, could not retrieve XonChar and XoffChar\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* swap XonChar/XoffChar */
|
||||
|
||||
XonChar = dcb.XonChar;
|
||||
XoffChar = dcb.XoffChar;
|
||||
dcb.XonChar = XoffChar;
|
||||
dcb.XoffChar = XonChar;
|
||||
if (!SetCommState(hComm, &dcb))
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure, GetLastError(): 0x%08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!GetCommState(hComm, &dcb))
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure, GetLastError(): 0x%08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((dcb.XonChar != XoffChar) || (dcb.XoffChar != XonChar))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCxSys, expected XonChar and XoffChar to be swapped\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* same XonChar / XoffChar */
|
||||
dcb.XonChar = dcb.XoffChar;
|
||||
if (SetCommState(hComm, &dcb))
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"test_SerCxSys failure, SetCommState() was supposed to failed because "
|
||||
"XonChar and XoffChar are the same\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (GetLastError() != ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCxSys failure, SetCommState() was supposed to failed with "
|
||||
"GetLastError()=ERROR_INVALID_PARAMETER\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL test_SerCx2Sys(HANDLE hComm)
|
||||
{
|
||||
DCB dcb = WINPR_C_ARRAY_INIT;
|
||||
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!GetCommState(hComm, &dcb))
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure; GetLastError(): %08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((dcb.ErrorChar != '\0') || (dcb.EofChar != '\0') || (dcb.EvtChar != '\0') ||
|
||||
(dcb.XonChar != '\0') || (dcb.XoffChar != '\0'))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCx2Sys failure, expected all characters to be: '\\0'\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TestSerialChars(int argc, char* argv[])
|
||||
{
|
||||
struct stat statbuf = WINPR_C_ARRAY_INIT;
|
||||
BOOL result = 0;
|
||||
HANDLE hComm = nullptr;
|
||||
|
||||
if (stat("/dev/ttyS0", &statbuf) < 0)
|
||||
{
|
||||
(void)fprintf(stderr, "/dev/ttyS0 not available, making the test to succeed though\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
result = DefineCommDevice("COM1", "/dev/ttyS0");
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "DefineCommDevice failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (hComm == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void)fprintf(stderr, "CreateFileA failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerCxSys);
|
||||
if (!test_SerCxSys(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCxSys failure\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerCx2Sys);
|
||||
if (!test_SerCx2Sys(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCxSys failure\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!CloseHandle(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "CloseHandle failure, GetLastError()=%08x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
335
third_party/FreeRDP/winpr/libwinpr/comm/test/TestSetCommState.c
vendored
Normal file
335
third_party/FreeRDP/winpr/libwinpr/comm/test/TestSetCommState.c
vendored
Normal file
@@ -0,0 +1,335 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <winpr/comm.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include "../comm.h"
|
||||
|
||||
static void init_empty_dcb(DCB* pDcb)
|
||||
{
|
||||
WINPR_ASSERT(pDcb);
|
||||
|
||||
ZeroMemory(pDcb, sizeof(DCB));
|
||||
pDcb->DCBlength = sizeof(DCB);
|
||||
pDcb->XonChar = 1;
|
||||
pDcb->XoffChar = 2;
|
||||
}
|
||||
|
||||
static BOOL test_fParity(HANDLE hComm)
|
||||
{
|
||||
DCB dcb = WINPR_C_ARRAY_INIT;
|
||||
BOOL result = 0;
|
||||
|
||||
init_empty_dcb(&dcb);
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: 0x%08" PRIx32 "\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* test 1 */
|
||||
dcb.fParity = TRUE;
|
||||
result = SetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure: 0x%08" PRIx32 "\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
init_empty_dcb(&dcb);
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: 0x%08" PRIx32 "\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!dcb.fParity)
|
||||
{
|
||||
(void)fprintf(stderr, "unexpected fParity: %" PRIu32 " instead of TRUE\n", dcb.fParity);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* test 2 */
|
||||
dcb.fParity = FALSE;
|
||||
result = SetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure: 0x%08" PRIx32 "\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
init_empty_dcb(&dcb);
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: 0x%08" PRIx32 "\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dcb.fParity)
|
||||
{
|
||||
(void)fprintf(stderr, "unexpected fParity: %" PRIu32 " instead of FALSE\n", dcb.fParity);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* test 3 (redo test 1) */
|
||||
dcb.fParity = TRUE;
|
||||
result = SetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure: 0x%08" PRIx32 "\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
init_empty_dcb(&dcb);
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: 0x%08" PRIx32 "\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!dcb.fParity)
|
||||
{
|
||||
(void)fprintf(stderr, "unexpected fParity: %" PRIu32 " instead of TRUE\n", dcb.fParity);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL test_SerialSys(HANDLE hComm)
|
||||
{
|
||||
DCB dcb = WINPR_C_ARRAY_INIT;
|
||||
BOOL result = 0;
|
||||
|
||||
init_empty_dcb(&dcb);
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: 0x%x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Test 1 */
|
||||
dcb.BaudRate = CBR_115200;
|
||||
result = SetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure: 0x%08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
init_empty_dcb(&dcb);
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: 0x%x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
if (dcb.BaudRate != CBR_115200)
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure: could not set BaudRate=%d (CBR_115200)\n",
|
||||
CBR_115200);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Test 2 using a different baud rate */
|
||||
|
||||
dcb.BaudRate = CBR_57600;
|
||||
result = SetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure: 0x%x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
init_empty_dcb(&dcb);
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: 0x%x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
if (dcb.BaudRate != CBR_57600)
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure: could not set BaudRate=%d (CBR_57600)\n",
|
||||
CBR_57600);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Test 3 using an unsupported baud rate on Linux */
|
||||
dcb.BaudRate = CBR_128000;
|
||||
result = SetCommState(hComm, &dcb);
|
||||
if (result)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"SetCommState failure: unexpected support of BaudRate=%d (CBR_128000)\n",
|
||||
CBR_128000);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL test_SerCxSys(HANDLE hComm)
|
||||
{
|
||||
/* as of today there is no difference */
|
||||
return test_SerialSys(hComm);
|
||||
}
|
||||
|
||||
static BOOL test_SerCx2Sys(HANDLE hComm)
|
||||
{
|
||||
/* as of today there is no difference */
|
||||
return test_SerialSys(hComm);
|
||||
}
|
||||
|
||||
static BOOL test_generic(HANDLE hComm)
|
||||
{
|
||||
DCB dcb = WINPR_C_ARRAY_INIT;
|
||||
DCB dcb2 = WINPR_C_ARRAY_INIT;
|
||||
BOOL result = 0;
|
||||
|
||||
init_empty_dcb(&dcb);
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: 0x%x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Checks whether we get the same information before and after SetCommState */
|
||||
memcpy(&dcb2, &dcb, sizeof(DCB));
|
||||
result = SetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommState failure: 0x%08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
result = GetCommState(hComm, &dcb);
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommState failure: 0x%x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (memcmp(&dcb, &dcb2, sizeof(DCB)) != 0)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"DCB is different after SetCommState() whereas it should have not changed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// TODO: a more complete and generic test using GetCommProperties()
|
||||
|
||||
/* TMP: TODO: fBinary tests */
|
||||
|
||||
/* fParity tests */
|
||||
if (!test_fParity(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_fParity failure\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TestSetCommState(int argc, char* argv[])
|
||||
{
|
||||
struct stat statbuf = WINPR_C_ARRAY_INIT;
|
||||
BOOL result = 0;
|
||||
HANDLE hComm = nullptr;
|
||||
|
||||
if (stat("/dev/ttyS0", &statbuf) < 0)
|
||||
{
|
||||
(void)fprintf(stderr, "/dev/ttyS0 not available, making the test to succeed though\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
result = DefineCommDevice("COM1", "/dev/ttyS0");
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "DefineCommDevice failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (hComm == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void)fprintf(stderr, "CreateFileA failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_generic failure (SerialDriverUnknown)\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerialSys);
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_generic failure (SerialDriverSerialSys)\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!test_SerialSys(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerialSys failure\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerCxSys);
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_generic failure (SerialDriverSerCxSys)\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!test_SerCxSys(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCxSys failure\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerCx2Sys);
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_generic failure (SerialDriverSerCx2Sys)\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!test_SerCx2Sys(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCx2Sys failure\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!CloseHandle(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "CloseHandle failure, GetLastError()=%08x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
141
third_party/FreeRDP/winpr/libwinpr/comm/test/TestTimeouts.c
vendored
Normal file
141
third_party/FreeRDP/winpr/libwinpr/comm/test/TestTimeouts.c
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Serial Communication API
|
||||
*
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <termios.h>
|
||||
#endif
|
||||
|
||||
#include <winpr/comm.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include "../comm.h"
|
||||
|
||||
static BOOL test_generic(HANDLE hComm)
|
||||
{
|
||||
COMMTIMEOUTS timeouts = WINPR_C_ARRAY_INIT;
|
||||
COMMTIMEOUTS timeouts2 = WINPR_C_ARRAY_INIT;
|
||||
|
||||
timeouts.ReadIntervalTimeout = 1;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 2;
|
||||
timeouts.ReadTotalTimeoutConstant = 3;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 4;
|
||||
timeouts.WriteTotalTimeoutConstant = 5;
|
||||
|
||||
if (!SetCommTimeouts(hComm, &timeouts))
|
||||
{
|
||||
(void)fprintf(stderr, "SetCommTimeouts failure, GetLastError: 0x%08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetCommTimeouts(hComm, &timeouts2))
|
||||
{
|
||||
(void)fprintf(stderr, "GetCommTimeouts failure, GetLastError: 0x%08x\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (memcmp(&timeouts, &timeouts2, sizeof(COMMTIMEOUTS)) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "TestTimeouts failure, didn't get back the same timeouts.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* not supported combination */
|
||||
timeouts.ReadIntervalTimeout = MAXULONG;
|
||||
timeouts.ReadTotalTimeoutConstant = MAXULONG;
|
||||
if (SetCommTimeouts(hComm, &timeouts))
|
||||
{
|
||||
(void)fprintf(
|
||||
stderr,
|
||||
"SetCommTimeouts succeeded with ReadIntervalTimeout and ReadTotalTimeoutConstant "
|
||||
"set to MAXULONG. GetLastError: 0x%08x\n",
|
||||
GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GetLastError() != ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
(void)fprintf(
|
||||
stderr,
|
||||
"SetCommTimeouts failure, expected GetLastError to return ERROR_INVALID_PARAMETER "
|
||||
"and got: 0x%08x\n",
|
||||
GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TestTimeouts(int argc, char* argv[])
|
||||
{
|
||||
struct stat statbuf;
|
||||
BOOL result = 0;
|
||||
HANDLE hComm = nullptr;
|
||||
|
||||
if (stat("/dev/ttyS0", &statbuf) < 0)
|
||||
{
|
||||
(void)fprintf(stderr, "/dev/ttyS0 not available, making the test to succeed though\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
result = DefineCommDevice("COM1", "/dev/ttyS0");
|
||||
if (!result)
|
||||
{
|
||||
(void)fprintf(stderr, "DefineCommDevice failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (hComm == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void)fprintf(stderr, "CreateFileA failure: 0x%x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerialSys);
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerialSys failure\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerCxSys);
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCxSys failure\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(hComm, SerialDriverSerCx2Sys);
|
||||
if (!test_generic(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "test_SerCx2Sys failure\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!CloseHandle(hComm))
|
||||
{
|
||||
(void)fprintf(stderr, "CloseHandle failure, GetLastError()=%08x\n", GetLastError());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
22
third_party/FreeRDP/winpr/libwinpr/credentials/CMakeLists.txt
vendored
Normal file
22
third_party/FreeRDP/winpr/libwinpr/credentials/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-credentials cmake build script
|
||||
#
|
||||
# Copyright 2012 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.
|
||||
|
||||
winpr_module_add(credentials.c)
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
9
third_party/FreeRDP/winpr/libwinpr/credentials/ModuleOptions.cmake
vendored
Normal file
9
third_party/FreeRDP/winpr/libwinpr/credentials/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
set(MINWIN_LAYER "1")
|
||||
set(MINWIN_GROUP "security")
|
||||
set(MINWIN_MAJOR_VERSION "1")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "credentials")
|
||||
set(MINWIN_LONG_NAME "Credentials Management Functions")
|
||||
set(MODULE_LIBRARY_NAME
|
||||
"api-ms-win-${MINWIN_GROUP}-${MINWIN_SHORT_NAME}-l${MINWIN_LAYER}-${MINWIN_MAJOR_VERSION}-${MINWIN_MINOR_VERSION}"
|
||||
)
|
||||
303
third_party/FreeRDP/winpr/libwinpr/credentials/credentials.c
vendored
Normal file
303
third_party/FreeRDP/winpr/libwinpr/credentials/credentials.c
vendored
Normal file
@@ -0,0 +1,303 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Credentials Management
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2025 David Fort <contact@hardening-consulting.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cred.h>
|
||||
#include <winpr/error.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include "../log.h"
|
||||
|
||||
#define TAG WINPR_TAG("Cred")
|
||||
|
||||
/*
|
||||
* Low-Level Credentials Management Functions:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731(v=vs.85).aspx#low_level_credentials_management_functions
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
static BYTE char_decode(char c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return (BYTE)(c - 'A');
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return (BYTE)(c - 'a' + 26);
|
||||
if (c >= '0' && c <= '9')
|
||||
return (BYTE)(c - '0' + 52);
|
||||
if (c == '#')
|
||||
return 62;
|
||||
if (c == '-')
|
||||
return 63;
|
||||
return 64;
|
||||
}
|
||||
|
||||
static BOOL cred_decode(const char* cred, size_t len, BYTE* buf)
|
||||
{
|
||||
size_t i = 0;
|
||||
const char* p = cred;
|
||||
|
||||
while (len >= 4)
|
||||
{
|
||||
BYTE c0 = char_decode(p[0]);
|
||||
if (c0 > 63)
|
||||
return FALSE;
|
||||
|
||||
BYTE c1 = char_decode(p[1]);
|
||||
if (c1 > 63)
|
||||
return FALSE;
|
||||
|
||||
BYTE c2 = char_decode(p[2]);
|
||||
if (c2 > 63)
|
||||
return FALSE;
|
||||
|
||||
BYTE c3 = char_decode(p[3]);
|
||||
if (c3 > 63)
|
||||
return FALSE;
|
||||
|
||||
buf[i + 0] = (BYTE)((c1 << 6) | c0);
|
||||
buf[i + 1] = (BYTE)((c2 << 4) | (c1 >> 2));
|
||||
buf[i + 2] = (BYTE)((c3 << 2) | (c2 >> 4));
|
||||
len -= 4;
|
||||
i += 3;
|
||||
p += 4;
|
||||
}
|
||||
|
||||
if (len == 3)
|
||||
{
|
||||
BYTE c0 = char_decode(p[0]);
|
||||
if (c0 > 63)
|
||||
return FALSE;
|
||||
|
||||
BYTE c1 = char_decode(p[1]);
|
||||
if (c1 > 63)
|
||||
return FALSE;
|
||||
|
||||
BYTE c2 = char_decode(p[2]);
|
||||
if (c2 > 63)
|
||||
return FALSE;
|
||||
|
||||
buf[i + 0] = (BYTE)((c1 << 6) | c0);
|
||||
buf[i + 1] = (BYTE)((c2 << 4) | (c1 >> 2));
|
||||
}
|
||||
else if (len == 2)
|
||||
{
|
||||
BYTE c0 = char_decode(p[0]);
|
||||
if (c0 > 63)
|
||||
return FALSE;
|
||||
|
||||
BYTE c1 = char_decode(p[1]);
|
||||
if (c1 > 63)
|
||||
return FALSE;
|
||||
|
||||
buf[i + 0] = (BYTE)((c1 << 6) | c0);
|
||||
}
|
||||
else if (len == 1)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid string length");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static size_t cred_encode(const BYTE* bin, size_t len, char* cred, size_t credlen)
|
||||
{
|
||||
static const char encodingChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789"
|
||||
"#-";
|
||||
size_t n = 0;
|
||||
size_t offset = 0;
|
||||
while (offset < len)
|
||||
{
|
||||
if (n >= credlen)
|
||||
break;
|
||||
|
||||
cred[n++] = encodingChars[bin[offset] & 0x3f];
|
||||
BYTE x = (bin[offset] & 0xc0) >> 6;
|
||||
offset++;
|
||||
|
||||
if (offset >= len)
|
||||
{
|
||||
cred[n++] = encodingChars[x];
|
||||
break;
|
||||
}
|
||||
|
||||
if (n >= credlen)
|
||||
break;
|
||||
cred[n++] = encodingChars[((bin[offset] & 0xf) << 2) | x];
|
||||
x = (bin[offset] & 0xf0) >> 4;
|
||||
offset++;
|
||||
|
||||
if (offset >= len)
|
||||
{
|
||||
cred[n++] = encodingChars[x];
|
||||
break;
|
||||
}
|
||||
|
||||
if (n >= credlen)
|
||||
break;
|
||||
cred[n++] = encodingChars[((bin[offset] & 0x3) << 4) | x];
|
||||
|
||||
if (n >= credlen)
|
||||
break;
|
||||
cred[n++] = encodingChars[(bin[offset] & 0xfc) >> 2];
|
||||
offset++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
BOOL CredMarshalCredentialW(CRED_MARSHAL_TYPE CredType, PVOID Credential,
|
||||
LPWSTR* MarshaledCredential)
|
||||
{
|
||||
char* b = nullptr;
|
||||
if (!CredMarshalCredentialA(CredType, Credential, &b) || !b)
|
||||
return FALSE;
|
||||
|
||||
*MarshaledCredential = ConvertUtf8ToWCharAlloc(b, nullptr);
|
||||
free(b);
|
||||
return (*MarshaledCredential != nullptr);
|
||||
}
|
||||
|
||||
BOOL CredMarshalCredentialA(CRED_MARSHAL_TYPE CredType, PVOID Credential,
|
||||
LPSTR* MarshaledCredential)
|
||||
{
|
||||
CERT_CREDENTIAL_INFO* cert = Credential;
|
||||
|
||||
if (!cert || ((CredType == CertCredential) && (cert->cbSize < sizeof(CERT_CREDENTIAL_INFO))) ||
|
||||
!MarshaledCredential)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (CredType)
|
||||
{
|
||||
case CertCredential:
|
||||
{
|
||||
char buffer[3ULL + (sizeof(cert->rgbHashOfCert) * 4 / 3) + 1ULL /* rounding error */] =
|
||||
WINPR_C_ARRAY_INIT;
|
||||
|
||||
const char c = WINPR_ASSERTING_INT_CAST(char, 'A' + CredType);
|
||||
(void)_snprintf(buffer, sizeof(buffer), "@@%c", c);
|
||||
size_t len = cred_encode(cert->rgbHashOfCert, sizeof(cert->rgbHashOfCert), &buffer[3],
|
||||
sizeof(buffer) - 3);
|
||||
*MarshaledCredential = strndup(buffer, len + 3);
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
WLog_ERR(TAG, "unhandled type 0x%x", CredType);
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CredUnmarshalCredentialW(LPCWSTR cred, PCRED_MARSHAL_TYPE CredType, PVOID* Credential)
|
||||
{
|
||||
char* str = nullptr;
|
||||
if (cred)
|
||||
str = ConvertWCharToUtf8Alloc(cred, nullptr);
|
||||
const BOOL rc = CredUnmarshalCredentialA(str, CredType, Credential);
|
||||
free(str);
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL CredUnmarshalCredentialA(LPCSTR cred, PCRED_MARSHAL_TYPE CredType, PVOID* Credential)
|
||||
{
|
||||
if (!cred)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const size_t len = strlen(cred);
|
||||
if ((len < 3) || !CredType || !Credential || (cred[0] != '@') || (cred[1] != '@'))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BYTE b = char_decode(cred[2]);
|
||||
if (!b || (b > BinaryBlobForSystem))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*CredType = (CRED_MARSHAL_TYPE)b;
|
||||
|
||||
switch (*CredType)
|
||||
{
|
||||
case CertCredential:
|
||||
{
|
||||
BYTE hash[CERT_HASH_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if ((len != 30) || !cred_decode(&cred[3], len - 3, hash))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CERT_CREDENTIAL_INFO* cert = calloc(1, sizeof(CERT_CREDENTIAL_INFO));
|
||||
if (!cert)
|
||||
return FALSE;
|
||||
|
||||
cert->cbSize = sizeof(CERT_CREDENTIAL_INFO);
|
||||
memcpy(cert->rgbHashOfCert, hash, sizeof(cert->rgbHashOfCert));
|
||||
*Credential = cert;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WLog_ERR(TAG, "unhandled credType 0x%x", *CredType);
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CredIsMarshaledCredentialW(LPCWSTR MarshaledCredential)
|
||||
{
|
||||
CRED_MARSHAL_TYPE t = BinaryBlobForSystem;
|
||||
void* out = nullptr;
|
||||
|
||||
BOOL ret = CredUnmarshalCredentialW(MarshaledCredential, &t, &out);
|
||||
if (out)
|
||||
CredFree(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL CredIsMarshaledCredentialA(LPCSTR MarshaledCredential)
|
||||
{
|
||||
CRED_MARSHAL_TYPE t = BinaryBlobForSystem;
|
||||
void* out = nullptr;
|
||||
BOOL ret = CredUnmarshalCredentialA(MarshaledCredential, &t, &out);
|
||||
if (out)
|
||||
CredFree(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
VOID CredFree(PVOID Buffer)
|
||||
{
|
||||
free(Buffer);
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
23
third_party/FreeRDP/winpr/libwinpr/credentials/test/CMakeLists.txt
vendored
Normal file
23
third_party/FreeRDP/winpr/libwinpr/credentials/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
set(MODULE_NAME "TestCredentials")
|
||||
set(MODULE_PREFIX "TEST_CREDENTIALS")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS TestMarshalUnmarshal.c)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
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()
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr ${OPENSSL_LIBRARIES})
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
|
||||
95
third_party/FreeRDP/winpr/libwinpr/credentials/test/TestMarshalUnmarshal.c
vendored
Normal file
95
third_party/FreeRDP/winpr/libwinpr/credentials/test/TestMarshalUnmarshal.c
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Buffer Manipulation
|
||||
*
|
||||
* Copyright 2025 David Fort <contact@hardening-consulting.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <winpr/cred.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LPCSTR marshalled;
|
||||
BYTE source[CERT_HASH_LENGTH];
|
||||
} TestItem;
|
||||
|
||||
static const TestItem testValues[] = {
|
||||
{ "@@BQ9eNR0KWVU-CT8sPCp8z37POZHJ",
|
||||
{ 0x50, 0xef, 0x35, 0x11, 0xad, 0x58, 0x15, 0xf5, 0x0b, 0x13,
|
||||
0xcf, 0x3e, 0x42, 0xca, 0xcf, 0xf7, 0xfe, 0x38, 0xd9, 0x91 } },
|
||||
{ "@@BKay-HwJsFZzclXAWZ#nO6Eluc7P",
|
||||
{ 0x8a, 0x26, 0xff, 0x07, 0x9c, 0xb0, 0x45, 0x36, 0x73, 0xe5,
|
||||
0x05, 0x58, 0x99, 0x7f, 0x3a, 0x3a, 0x51, 0xba, 0xdc, 0xfe }
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
static int TestUnmarshal(WINPR_ATTR_UNUSED int argc, WINPR_ATTR_UNUSED char** argv)
|
||||
{
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(testValues); i++)
|
||||
{
|
||||
CRED_MARSHAL_TYPE t = BinaryBlobForSystem;
|
||||
CERT_CREDENTIAL_INFO* certInfo = nullptr;
|
||||
const TestItem* const val = &testValues[i];
|
||||
|
||||
if (!CredUnmarshalCredentialA(val->marshalled, &t, (void**)&certInfo) || !certInfo ||
|
||||
(t != CertCredential))
|
||||
return -1;
|
||||
|
||||
const BOOL ok =
|
||||
memcmp(val->source, certInfo->rgbHashOfCert, sizeof(certInfo->rgbHashOfCert)) == 0;
|
||||
|
||||
free(certInfo);
|
||||
|
||||
if (!ok)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int TestMarshal(WINPR_ATTR_UNUSED int argc, WINPR_ATTR_UNUSED char** argv)
|
||||
{
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(testValues); i++)
|
||||
{
|
||||
CERT_CREDENTIAL_INFO certInfo = { sizeof(certInfo), { 0 } };
|
||||
const TestItem* const val = &testValues[i];
|
||||
|
||||
memcpy(certInfo.rgbHashOfCert, val->source, sizeof(certInfo.rgbHashOfCert));
|
||||
LPSTR out = nullptr;
|
||||
|
||||
if (!CredMarshalCredentialA(CertCredential, &certInfo, &out) || !out)
|
||||
return -1;
|
||||
|
||||
BOOL ok = (strcmp(val->marshalled, out) == 0);
|
||||
|
||||
free(out);
|
||||
|
||||
if (!ok)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TestMarshalUnmarshal(int argc, char** argv)
|
||||
{
|
||||
int ret = TestUnmarshal(argc, argv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = TestMarshal(argc, argv);
|
||||
return ret;
|
||||
}
|
||||
52
third_party/FreeRDP/winpr/libwinpr/crt/CMakeLists.txt
vendored
Normal file
52
third_party/FreeRDP/winpr/libwinpr/crt/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-crt cmake build script
|
||||
#
|
||||
# Copyright 2012 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.
|
||||
|
||||
set(CRT_FILES
|
||||
alignment.c
|
||||
conversion.c
|
||||
buffer.c
|
||||
memory.c
|
||||
unicode.c
|
||||
string.c
|
||||
assert.c
|
||||
)
|
||||
|
||||
if(WITH_UNICODE_BUILTIN)
|
||||
list(APPEND CRT_FILES unicode_builtin.c)
|
||||
else()
|
||||
if(ANDROID)
|
||||
list(APPEND CRT_FILES unicode_android.c)
|
||||
elseif(NOT APPLE AND NOT WIN32)
|
||||
find_package(ICU REQUIRED i18n uc io data)
|
||||
winpr_pc_add_requires_private("icu-uc")
|
||||
winpr_pc_add_requires_private("icu-io")
|
||||
winpr_pc_add_requires_private("icu-i18n")
|
||||
list(APPEND CRT_FILES unicode_icu.c)
|
||||
winpr_system_include_directory_add(${ICU_INCLUDE_DIRS})
|
||||
winpr_library_add_private(${ICU_LIBRARIES})
|
||||
elseif(APPLE)
|
||||
list(APPEND CRT_FILES unicode_apple.m)
|
||||
find_library(FOUNDATION_FRAMEWORK Foundation REQUIRED)
|
||||
winpr_library_add_private(${FOUNDATION_FRAMEWORK})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
winpr_module_add(${CRT_FILES})
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
7
third_party/FreeRDP/winpr/libwinpr/crt/ModuleOptions.cmake
vendored
Normal file
7
third_party/FreeRDP/winpr/libwinpr/crt/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
set(MINWIN_LAYER "0")
|
||||
set(MINWIN_GROUP "none")
|
||||
set(MINWIN_MAJOR_VERSION "0")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "crt")
|
||||
set(MINWIN_LONG_NAME "Microsoft C Run-Time")
|
||||
set(MODULE_LIBRARY_NAME "${MINWIN_SHORT_NAME}")
|
||||
261
third_party/FreeRDP/winpr/libwinpr/crt/alignment.c
vendored
Normal file
261
third_party/FreeRDP/winpr/libwinpr/crt/alignment.c
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Data Alignment
|
||||
*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
/* Data Alignment: http://msdn.microsoft.com/en-us/library/fs9stz4e/ */
|
||||
|
||||
#if !defined(_WIN32) || (defined(__MINGW32__) && !defined(_UCRT))
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define WINPR_ALIGNED_MEM_SIGNATURE 0x0BA0BAB
|
||||
|
||||
#define WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(_memptr) \
|
||||
(WINPR_ALIGNED_MEM*)(((size_t)(((BYTE*)(_memptr)) - sizeof(WINPR_ALIGNED_MEM))))
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("crt")
|
||||
|
||||
struct winpr_aligned_mem
|
||||
{
|
||||
UINT32 sig;
|
||||
size_t size;
|
||||
void* base_addr;
|
||||
};
|
||||
typedef struct winpr_aligned_mem WINPR_ALIGNED_MEM;
|
||||
|
||||
void* winpr_aligned_malloc(size_t size, size_t alignment)
|
||||
{
|
||||
return winpr_aligned_offset_malloc(size, alignment, 0);
|
||||
}
|
||||
|
||||
void* winpr_aligned_calloc(size_t count, size_t size, size_t alignment)
|
||||
{
|
||||
return winpr_aligned_recalloc(nullptr, count, size, alignment);
|
||||
}
|
||||
|
||||
void* winpr_aligned_realloc(void* memblock, size_t size, size_t alignment)
|
||||
{
|
||||
return winpr_aligned_offset_realloc(memblock, size, alignment, 0);
|
||||
}
|
||||
|
||||
void* winpr_aligned_recalloc(void* memblock, size_t num, size_t size, size_t alignment)
|
||||
{
|
||||
return winpr_aligned_offset_recalloc(memblock, num, size, alignment, 0);
|
||||
}
|
||||
|
||||
void* winpr_aligned_offset_malloc(size_t size, size_t alignment, size_t offset)
|
||||
{
|
||||
size_t header = 0;
|
||||
size_t alignsize = 0;
|
||||
uintptr_t basesize = 0;
|
||||
void* base = nullptr;
|
||||
void* memblock = nullptr;
|
||||
WINPR_ALIGNED_MEM* pMem = nullptr;
|
||||
|
||||
/* alignment must be a power of 2 */
|
||||
if (alignment % 2 == 1)
|
||||
return nullptr;
|
||||
|
||||
/* offset must be less than size */
|
||||
if (offset >= size)
|
||||
return nullptr;
|
||||
|
||||
/* minimum alignment is pointer size */
|
||||
if (alignment < sizeof(void*))
|
||||
alignment = sizeof(void*);
|
||||
|
||||
if (alignment > SIZE_MAX - sizeof(WINPR_ALIGNED_MEM))
|
||||
return nullptr;
|
||||
|
||||
header = sizeof(WINPR_ALIGNED_MEM) + alignment;
|
||||
|
||||
if (size > SIZE_MAX - header)
|
||||
return nullptr;
|
||||
|
||||
alignsize = size + header;
|
||||
/* malloc size + alignment to make sure we can align afterwards */
|
||||
#if defined(_ISOC11_SOURCE)
|
||||
base = aligned_alloc(alignment, alignsize);
|
||||
#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600)
|
||||
if (posix_memalign(&base, alignment, alignsize) != 0)
|
||||
return nullptr;
|
||||
#else
|
||||
base = malloc(alignsize);
|
||||
#endif
|
||||
if (!base)
|
||||
return nullptr;
|
||||
|
||||
basesize = (uintptr_t)base;
|
||||
|
||||
if ((offset > UINTPTR_MAX) || (header > UINTPTR_MAX - offset) ||
|
||||
(basesize > UINTPTR_MAX - header - offset))
|
||||
{
|
||||
free(base);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memblock = (void*)(((basesize + header + offset) & ~(alignment - 1)) - offset);
|
||||
pMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(memblock);
|
||||
pMem->sig = WINPR_ALIGNED_MEM_SIGNATURE;
|
||||
pMem->base_addr = base;
|
||||
pMem->size = size;
|
||||
return memblock;
|
||||
}
|
||||
|
||||
void* winpr_aligned_offset_realloc(void* memblock, size_t size, size_t alignment, size_t offset)
|
||||
{
|
||||
size_t copySize = 0;
|
||||
void* newMemblock = nullptr;
|
||||
WINPR_ALIGNED_MEM* pMem = nullptr;
|
||||
WINPR_ALIGNED_MEM* pNewMem = nullptr;
|
||||
|
||||
if (!memblock)
|
||||
return winpr_aligned_offset_malloc(size, alignment, offset);
|
||||
|
||||
pMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(memblock);
|
||||
|
||||
if (pMem->sig != WINPR_ALIGNED_MEM_SIGNATURE)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"_aligned_offset_realloc: memory block was not allocated by _aligned_malloc!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
winpr_aligned_free(memblock);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
newMemblock = winpr_aligned_offset_malloc(size, alignment, offset);
|
||||
|
||||
if (!newMemblock)
|
||||
return nullptr;
|
||||
|
||||
pNewMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(newMemblock);
|
||||
copySize = (pNewMem->size < pMem->size) ? pNewMem->size : pMem->size;
|
||||
CopyMemory(newMemblock, memblock, copySize);
|
||||
winpr_aligned_free(memblock);
|
||||
return newMemblock;
|
||||
}
|
||||
|
||||
static inline size_t cMIN(size_t a, size_t b)
|
||||
{
|
||||
if (a > b)
|
||||
return b;
|
||||
return a;
|
||||
}
|
||||
|
||||
void* winpr_aligned_offset_recalloc(void* memblock, size_t num, size_t size, size_t alignment,
|
||||
size_t offset)
|
||||
{
|
||||
char* newMemblock = nullptr;
|
||||
WINPR_ALIGNED_MEM* pMem = nullptr;
|
||||
WINPR_ALIGNED_MEM* pNewMem = nullptr;
|
||||
|
||||
if (!memblock)
|
||||
{
|
||||
newMemblock = winpr_aligned_offset_malloc(size * num, alignment, offset);
|
||||
|
||||
if (newMemblock)
|
||||
{
|
||||
pNewMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(newMemblock);
|
||||
ZeroMemory(newMemblock, pNewMem->size);
|
||||
}
|
||||
|
||||
return newMemblock;
|
||||
}
|
||||
|
||||
pMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(memblock);
|
||||
|
||||
if (pMem->sig != WINPR_ALIGNED_MEM_SIGNATURE)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"_aligned_offset_recalloc: memory block was not allocated by _aligned_malloc!");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((num == 0) || (size == 0))
|
||||
goto fail;
|
||||
|
||||
if (pMem->size > (1ull * num * size) + alignment)
|
||||
return memblock;
|
||||
|
||||
newMemblock = winpr_aligned_offset_malloc(size * num, alignment, offset);
|
||||
|
||||
if (!newMemblock)
|
||||
goto fail;
|
||||
|
||||
pNewMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(newMemblock);
|
||||
{
|
||||
const size_t csize = cMIN(pMem->size, pNewMem->size);
|
||||
memcpy(newMemblock, memblock, csize);
|
||||
ZeroMemory(newMemblock + csize, pNewMem->size - csize);
|
||||
}
|
||||
fail:
|
||||
winpr_aligned_free(memblock);
|
||||
return newMemblock;
|
||||
}
|
||||
|
||||
size_t winpr_aligned_msize(void* memblock, WINPR_ATTR_UNUSED size_t alignment,
|
||||
WINPR_ATTR_UNUSED size_t offset)
|
||||
{
|
||||
WINPR_ALIGNED_MEM* pMem = nullptr;
|
||||
|
||||
if (!memblock)
|
||||
return 0;
|
||||
|
||||
pMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(memblock);
|
||||
|
||||
if (pMem->sig != WINPR_ALIGNED_MEM_SIGNATURE)
|
||||
{
|
||||
WLog_ERR(TAG, "_aligned_msize: memory block was not allocated by _aligned_malloc!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pMem->size;
|
||||
}
|
||||
|
||||
void winpr_aligned_free(void* memblock)
|
||||
{
|
||||
WINPR_ALIGNED_MEM* pMem = nullptr;
|
||||
|
||||
if (!memblock)
|
||||
return;
|
||||
|
||||
pMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(memblock);
|
||||
|
||||
if (pMem->sig != WINPR_ALIGNED_MEM_SIGNATURE)
|
||||
{
|
||||
WLog_ERR(TAG, "_aligned_free: memory block was not allocated by _aligned_malloc!");
|
||||
return;
|
||||
}
|
||||
|
||||
free(pMem->base_addr);
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
31
third_party/FreeRDP/winpr/libwinpr/crt/assert.c
vendored
Normal file
31
third_party/FreeRDP/winpr/libwinpr/crt/assert.c
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Runtime ASSERT macros
|
||||
*
|
||||
* Copyright 2021 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2021 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/debug.h>
|
||||
|
||||
void winpr_int_assert(const char* condstr, const char* file, const char* fkt, size_t line)
|
||||
{
|
||||
wLog* _log_cached_ptr = WLog_Get("com.freerdp.winpr.assert");
|
||||
WLog_Print(_log_cached_ptr, WLOG_FATAL, "%s [%s:%s:%" PRIuz "]", condstr, file, fkt, line);
|
||||
winpr_log_backtrace_ex(_log_cached_ptr, WLOG_FATAL, 20);
|
||||
abort();
|
||||
}
|
||||
50
third_party/FreeRDP/winpr/libwinpr/crt/buffer.c
vendored
Normal file
50
third_party/FreeRDP/winpr/libwinpr/crt/buffer.c
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Buffer Manipulation
|
||||
*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
/* Buffer Manipulation: http://msdn.microsoft.com/en-us/library/b3893xdy/ */
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <string.h>
|
||||
|
||||
errno_t memmove_s(void* dest, size_t numberOfElements, const void* src, size_t count)
|
||||
{
|
||||
if (count > numberOfElements)
|
||||
return -1;
|
||||
|
||||
memmove(dest, src, count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
errno_t wmemmove_s(WCHAR* dest, size_t numberOfElements, const WCHAR* src, size_t count)
|
||||
{
|
||||
if (count * sizeof(WCHAR) > numberOfElements)
|
||||
return -1;
|
||||
|
||||
memmove(dest, src, count * 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
726
third_party/FreeRDP/winpr/libwinpr/crt/casing.h
vendored
Normal file
726
third_party/FreeRDP/winpr/libwinpr/crt/casing.h
vendored
Normal file
@@ -0,0 +1,726 @@
|
||||
/**
|
||||
* Unicode case mappings
|
||||
*
|
||||
* This code is generated by wine's make_unicode script
|
||||
* which downloads data from unicode.org and produces
|
||||
* readily usable conversion tables.
|
||||
*
|
||||
* After asking permission from Alexandre Julliard in May 2011,
|
||||
* it was clarified that no copyright was claimed by the wine
|
||||
* project on the script's generated output.
|
||||
*/
|
||||
|
||||
#define WINPR_TOLOWERW(_wch) \
|
||||
(_wch + winpr_casemap_lower[winpr_casemap_lower[_wch >> 8] + (_wch & 0xFF)])
|
||||
|
||||
#define WINPR_TOUPPERW(_wch) \
|
||||
(_wch + winpr_casemap_upper[winpr_casemap_upper[_wch >> 8] + (_wch & 0xFF)])
|
||||
|
||||
static const WCHAR winpr_casemap_lower[3807] = {
|
||||
/* index */
|
||||
0x01bf, 0x02bf, 0x03bf, 0x044f, 0x054f, 0x064f, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x06af, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x07af, 0x08ae, 0x0100, 0x09ab, 0x0100, 0x0100,
|
||||
0x0a2f, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0b2f, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0c22, 0x0d00,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0ddf,
|
||||
/* defaults */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x0041 .. 0x00ff */
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x0100 .. 0x01ff */
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0xff39, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0xff87, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x00d2, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x00ce, 0x0001, 0x0000, 0x00cd, 0x00cd, 0x0001, 0x0000, 0x0000, 0x004f, 0x00ca,
|
||||
0x00cb, 0x0001, 0x0000, 0x00cd, 0x00cf, 0x0000, 0x00d3, 0x00d1, 0x0001, 0x0000, 0x0000, 0x0000,
|
||||
0x00d3, 0x00d5, 0x0000, 0x00d6, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x00da, 0x0001,
|
||||
0x0000, 0x00da, 0x0000, 0x0000, 0x0001, 0x0000, 0x00da, 0x0001, 0x0000, 0x00d9, 0x00d9, 0x0001,
|
||||
0x0000, 0x0001, 0x0000, 0x00db, 0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0001, 0x0000, 0x0002, 0x0001, 0x0000, 0x0002, 0x0001,
|
||||
0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0000, 0x0002, 0x0001, 0x0000, 0x0001, 0x0000, 0xff9f, 0xffc8, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000,
|
||||
/* 0x0200 .. 0x02ff */
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0xff7e, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2a2b, 0x0001,
|
||||
0x0000, 0xff5d, 0x2a28, 0x0000, 0x0000, 0x0001, 0x0000, 0xff3d, 0x0045, 0x0047, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x0370 .. 0x03ff */
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0026, 0x0000,
|
||||
0x0025, 0x0025, 0x0025, 0x0000, 0x0040, 0x0000, 0x003f, 0x003f, 0x0000, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0xffc4, 0x0000, 0x0000, 0x0001, 0x0000, 0xfff9, 0x0001, 0x0000, 0x0000, 0xff7e, 0xff7e, 0xff7e,
|
||||
/* 0x0400 .. 0x04ff */
|
||||
0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050,
|
||||
0x0050, 0x0050, 0x0050, 0x0050, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x000f, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000,
|
||||
/* 0x0500 .. 0x05ff */
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
|
||||
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
|
||||
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
|
||||
0x0030, 0x0030, 0x0030, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x10a0 .. 0x10ff */
|
||||
0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60,
|
||||
0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60,
|
||||
0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60,
|
||||
0x1c60, 0x1c60, 0x0000, 0x1c60, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1c60, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x1e00 .. 0x1eff */
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0xe241, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000,
|
||||
/* 0x1f01 .. 0x1fff */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8,
|
||||
0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8,
|
||||
0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8,
|
||||
0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8,
|
||||
0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, 0x0000, 0xfff8, 0x0000, 0xfff8, 0x0000, 0xfff8, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8,
|
||||
0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8,
|
||||
0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8,
|
||||
0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0xfff8, 0xfff8, 0xffb6, 0xffb6, 0xfff7, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffaa, 0xffaa, 0xffaa, 0xffaa, 0xfff7,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8,
|
||||
0xfff8, 0xff9c, 0xff9c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0xfff8, 0xfff8, 0xff90, 0xff90, 0xfff9, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xff80, 0xff80, 0xff82, 0xff82, 0xfff7,
|
||||
0x0000, 0x0000, 0x0000,
|
||||
/* 0x2103 .. 0x21ff */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe2a3,
|
||||
0x0000, 0x0000, 0x0000, 0xdf41, 0xdfba, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x001c,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0010, 0x0010, 0x0010,
|
||||
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
|
||||
0x0010, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000,
|
||||
/* 0x247c .. 0x24ff */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x001a, 0x001a,
|
||||
0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a,
|
||||
0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x2c00 .. 0x2cff */
|
||||
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
|
||||
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
|
||||
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
|
||||
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0001, 0x0000, 0xd609, 0xf11a, 0xd619, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0xd5e4, 0xd603, 0xd5e1, 0xd5e2, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd5c1, 0xd5c1, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0xa60d .. 0xa6ff */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
|
||||
0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000,
|
||||
/* 0xa722 .. 0xa7ff */
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x75fc, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x5ad8,
|
||||
0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
|
||||
0x0001, 0x0000, 0x0001, 0x0000, 0x5abc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0xff21 .. 0xffff */
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
};
|
||||
static const WCHAR winpr_casemap_upper[3994] = {
|
||||
/* index */
|
||||
0x019f, 0x029f, 0x039f, 0x045a, 0x0556, 0x0656, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x06dd, 0x07dc, 0x08dc, 0x0100, 0x09d0, 0x0100, 0x0100,
|
||||
0x0a55, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0b3f, 0x0c3f, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0cfe, 0x0ddb,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
|
||||
0x0100, 0x0100, 0x0100, 0x0e9a,
|
||||
/* defaults */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x0061 .. 0x00ff */
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x02e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0x0000, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0x0079,
|
||||
/* 0x0100 .. 0x01ff */
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xff18, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0xfed4, 0x00c3, 0x0000, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0061, 0x0000, 0x0000, 0x0000, 0xffff, 0x00a3, 0x0000,
|
||||
0x0000, 0x0000, 0x0082, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000,
|
||||
0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0038,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xfffe, 0x0000, 0xffff, 0xfffe, 0x0000, 0xffff,
|
||||
0xfffe, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0xffb1, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0x0000, 0xffff, 0xfffe, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff,
|
||||
/* 0x0200 .. 0x02ff */
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0xffff, 0x0000, 0x0000, 0x2a3f, 0x2a3f, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x2a1f, 0x2a1c, 0x2a1e, 0xff2e,
|
||||
0xff32, 0x0000, 0xff33, 0xff33, 0x0000, 0xff36, 0x0000, 0xff35, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0xff33, 0x0000, 0x0000, 0xff31, 0x0000, 0xa528, 0xa544, 0x0000, 0xff2f, 0xff2d, 0x0000, 0x29f7,
|
||||
0x0000, 0x0000, 0x0000, 0xff2d, 0x0000, 0x29fd, 0xff2b, 0x0000, 0x0000, 0xff2a, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x29e7, 0x0000, 0x0000, 0xff26, 0x0000, 0x0000, 0xff26,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0xff26, 0xffbb, 0xff27, 0xff27, 0xffb9, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0xff25, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x0345 .. 0x03ff */
|
||||
0x0054, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0082, 0x0082, 0x0082, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffda, 0xffdb, 0xffdb, 0xffdb, 0x0000,
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe1, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffc0, 0xffc1, 0xffc1, 0x0000, 0xffc2, 0xffc7, 0x0000, 0x0000, 0x0000,
|
||||
0xffd1, 0xffca, 0xfff8, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0xffaa, 0xffb0, 0x0007, 0x0000, 0x0000, 0xffa0, 0x0000, 0x0000, 0xffff,
|
||||
0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x0404 .. 0x04ff */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0,
|
||||
0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0xfff1,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
/* 0x0500 .. 0x05ff */
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
|
||||
0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
|
||||
0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
|
||||
0xffd0, 0xffd0, 0xffd0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x1d79 .. 0x1dff */
|
||||
0x8a04, 0x0000, 0x0000, 0x0000, 0x0ee6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000,
|
||||
/* 0x1e01 .. 0x1eff */
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffc5, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff,
|
||||
/* 0x1f00 .. 0x1fff */
|
||||
0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008,
|
||||
0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, 0x0008,
|
||||
0x0000, 0x0008, 0x0000, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x004a, 0x004a, 0x0056, 0x0056, 0x0056, 0x0056, 0x0064, 0x0064,
|
||||
0x0080, 0x0080, 0x0070, 0x0070, 0x007e, 0x007e, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008,
|
||||
0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0000, 0x0009,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3db, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0000, 0x0000,
|
||||
0x0000, 0x0007, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x210c .. 0x21ff */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffe4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0,
|
||||
0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x247b .. 0x24ff */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6,
|
||||
0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6,
|
||||
0xffe6, 0xffe6, 0xffe6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000,
|
||||
/* 0x2c16 .. 0x2cff */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
|
||||
0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
|
||||
0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
|
||||
0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
|
||||
0xffd0, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0xd5d5, 0xd5d8, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000,
|
||||
0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
|
||||
0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0x2d00 .. 0x2dff */
|
||||
0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0,
|
||||
0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0,
|
||||
0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0,
|
||||
0xe3a0, 0xe3a0, 0x0000, 0xe3a0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3a0, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0xa641 .. 0xa6ff */
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0xa723 .. 0xa7ff */
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
|
||||
0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* 0xff41 .. 0xffff */
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0,
|
||||
0xffe0, 0xffe0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
};
|
||||
44
third_party/FreeRDP/winpr/libwinpr/crt/conversion.c
vendored
Normal file
44
third_party/FreeRDP/winpr/libwinpr/crt/conversion.c
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Data Conversion
|
||||
*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/string.h>
|
||||
|
||||
/* Data Conversion: http://msdn.microsoft.com/en-us/library/0heszx3w/ */
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
errno_t _itoa_s(int value, char* buffer, size_t sizeInCharacters, WINPR_ATTR_UNUSED int radix)
|
||||
{
|
||||
int length = sprintf_s(nullptr, 0, "%d", value);
|
||||
|
||||
if (length < 0)
|
||||
return -1;
|
||||
|
||||
if (sizeInCharacters < (size_t)length)
|
||||
return -1;
|
||||
|
||||
(void)sprintf_s(buffer, WINPR_ASSERTING_INT_CAST(size_t, length + 1), "%d", value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
42
third_party/FreeRDP/winpr/libwinpr/crt/memory.c
vendored
Normal file
42
third_party/FreeRDP/winpr/libwinpr/crt/memory.c
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Memory Allocation
|
||||
*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
/* Memory Allocation: http://msdn.microsoft.com/en-us/library/hk1k7x6x.aspx */
|
||||
/* Memory Management Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366781/ */
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
PVOID SecureZeroMemory(PVOID ptr, size_t cnt)
|
||||
{
|
||||
volatile BYTE* p = ptr;
|
||||
|
||||
while (cnt--)
|
||||
{
|
||||
*p = 0;
|
||||
p++;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
843
third_party/FreeRDP/winpr/libwinpr/crt/string.c
vendored
Normal file
843
third_party/FreeRDP/winpr/libwinpr/crt/string.c
vendored
Normal file
@@ -0,0 +1,843 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* String Manipulation (CRT)
|
||||
*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/endian.h>
|
||||
|
||||
#if defined(WITH_URIPARSER)
|
||||
#include <uriparser/Uri.h>
|
||||
#endif
|
||||
|
||||
/* String Manipulation (CRT): http://msdn.microsoft.com/en-us/library/f0151s4x.aspx */
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("crt")
|
||||
|
||||
#if defined(WITH_URIPARSER)
|
||||
char* winpr_str_url_decode(const char* str, size_t len)
|
||||
{
|
||||
char* dst = strndup(str, len);
|
||||
if (!dst)
|
||||
return nullptr;
|
||||
|
||||
if (!uriUnescapeInPlaceExA(dst, URI_FALSE, URI_BR_DONT_TOUCH))
|
||||
{
|
||||
free(dst);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
char* winpr_str_url_encode(const char* str, size_t len)
|
||||
{
|
||||
char* dst = calloc(len + 1, sizeof(char) * 3);
|
||||
if (!dst)
|
||||
return nullptr;
|
||||
|
||||
if (!uriEscapeA(str, dst, URI_FALSE, URI_FALSE))
|
||||
{
|
||||
free(dst);
|
||||
return nullptr;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
#else
|
||||
static const char rfc3986[] = {
|
||||
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, 0x2d, 0x2e, 0x00,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f,
|
||||
0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x7e, 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, 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, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static char hex2bin(char what)
|
||||
{
|
||||
if (what >= 'a')
|
||||
what -= 'a' - 'A';
|
||||
if (what >= 'A')
|
||||
what -= ('A' - 10);
|
||||
else
|
||||
what -= '0';
|
||||
return what;
|
||||
}
|
||||
|
||||
static char unescape(const char* what, size_t* px)
|
||||
{
|
||||
if ((*what == '%') && (isxdigit(what[1]) && isxdigit(what[2])))
|
||||
{
|
||||
*px += 2;
|
||||
return 16 * hex2bin(what[1]) + hex2bin(what[2]);
|
||||
}
|
||||
|
||||
return *what;
|
||||
}
|
||||
|
||||
char* winpr_str_url_decode(const char* str, size_t len)
|
||||
{
|
||||
char* dst = calloc(len + 1, sizeof(char));
|
||||
if (!dst)
|
||||
return nullptr;
|
||||
|
||||
size_t pos = 0;
|
||||
for (size_t x = 0; x < strnlen(str, len); x++)
|
||||
{
|
||||
const char* cur = &str[x];
|
||||
dst[pos++] = unescape(cur, &x);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static char* escape(char* dst, char what)
|
||||
{
|
||||
if (rfc3986[what & 0xff])
|
||||
{
|
||||
*dst = what;
|
||||
return dst + 1;
|
||||
}
|
||||
|
||||
sprintf(dst, "%%%02" PRIX8, (BYTE)(what & 0xff));
|
||||
return dst + 3;
|
||||
}
|
||||
|
||||
char* winpr_str_url_encode(const char* str, size_t len)
|
||||
{
|
||||
char* dst = calloc(len + 1, sizeof(char) * 3);
|
||||
if (!dst)
|
||||
return nullptr;
|
||||
|
||||
char* ptr = dst;
|
||||
for (size_t x = 0; x < strnlen(str, len); x++)
|
||||
{
|
||||
const char cur = str[x];
|
||||
ptr = escape(ptr, cur);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL winpr_str_append(const char* what, char* buffer, size_t size, const char* separator)
|
||||
{
|
||||
const size_t used = strnlen(buffer, size);
|
||||
const size_t add = strnlen(what, size);
|
||||
const size_t sep_len = separator ? strnlen(separator, size) : 0;
|
||||
const size_t sep = (used > 0) ? sep_len : 0;
|
||||
|
||||
if (used + add + sep >= size)
|
||||
return FALSE;
|
||||
|
||||
if ((used > 0) && (sep_len > 0))
|
||||
strncat(buffer, separator, sep_len);
|
||||
|
||||
strncat(buffer, what, add);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
WINPR_ATTR_FORMAT_ARG(3, 4)
|
||||
int winpr_asprintf(char** s, size_t* slen, WINPR_FORMAT_ARG const char* templ, ...)
|
||||
{
|
||||
va_list ap = WINPR_C_ARRAY_INIT;
|
||||
|
||||
va_start(ap, templ);
|
||||
int rc = winpr_vasprintf(s, slen, templ, ap);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
WINPR_ATTR_FORMAT_ARG(3, 0)
|
||||
int winpr_vasprintf(char** s, size_t* slen, WINPR_FORMAT_ARG const char* templ, va_list oap)
|
||||
{
|
||||
va_list ap = WINPR_C_ARRAY_INIT;
|
||||
|
||||
*s = nullptr;
|
||||
*slen = 0;
|
||||
|
||||
va_copy(ap, oap);
|
||||
const int length = vsnprintf(nullptr, 0, templ, ap);
|
||||
va_end(ap);
|
||||
if (length < 0)
|
||||
return length;
|
||||
|
||||
char* str = calloc((size_t)length + 1UL, sizeof(char));
|
||||
if (!str)
|
||||
return -1;
|
||||
|
||||
va_copy(ap, oap);
|
||||
const int plen = vsnprintf(str, (size_t)length + 1UL, templ, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (length != plen)
|
||||
{
|
||||
free(str);
|
||||
return -1;
|
||||
}
|
||||
*s = str;
|
||||
*slen = (size_t)length;
|
||||
return length;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
char* _strdup(const char* strSource)
|
||||
{
|
||||
if (strSource == nullptr)
|
||||
return nullptr;
|
||||
|
||||
char* strDestination = strdup(strSource);
|
||||
|
||||
if (strDestination == nullptr)
|
||||
WLog_ERR(TAG, "strdup");
|
||||
|
||||
return strDestination;
|
||||
}
|
||||
|
||||
WCHAR* _wcsdup(const WCHAR* strSource)
|
||||
{
|
||||
if (!strSource)
|
||||
return nullptr;
|
||||
|
||||
size_t len = _wcslen(strSource);
|
||||
WCHAR* strDestination = calloc(len + 1, sizeof(WCHAR));
|
||||
|
||||
if (strDestination != nullptr)
|
||||
memcpy(strDestination, strSource, len * sizeof(WCHAR));
|
||||
|
||||
if (strDestination == nullptr)
|
||||
WLog_ERR(TAG, "wcsdup");
|
||||
|
||||
return strDestination;
|
||||
}
|
||||
|
||||
WCHAR* _wcsncat(WCHAR* dst, const WCHAR* src, size_t sz)
|
||||
{
|
||||
WINPR_ASSERT(dst);
|
||||
WINPR_ASSERT(src || (sz == 0));
|
||||
|
||||
const size_t dlen = _wcslen(dst);
|
||||
const size_t slen = _wcsnlen(src, sz);
|
||||
for (size_t x = 0; x < slen; x++)
|
||||
dst[dlen + x] = src[x];
|
||||
dst[dlen + slen] = '\0';
|
||||
return dst;
|
||||
}
|
||||
|
||||
int _stricmp(const char* string1, const char* string2)
|
||||
{
|
||||
return strcasecmp(string1, string2);
|
||||
}
|
||||
|
||||
int _strnicmp(const char* string1, const char* string2, size_t count)
|
||||
{
|
||||
return strncasecmp(string1, string2, count);
|
||||
}
|
||||
|
||||
/* _wcscmp -> wcscmp */
|
||||
|
||||
int _wcscmp(const WCHAR* string1, const WCHAR* string2)
|
||||
{
|
||||
WINPR_ASSERT(string1);
|
||||
WINPR_ASSERT(string2);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
const WCHAR w1 = *string1++;
|
||||
const WCHAR w2 = *string2++;
|
||||
|
||||
if (w1 != w2)
|
||||
return (int)w1 - w2;
|
||||
else if ((w1 == '\0') || (w2 == '\0'))
|
||||
return (int)w1 - w2;
|
||||
}
|
||||
}
|
||||
|
||||
int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count)
|
||||
{
|
||||
WINPR_ASSERT(string1);
|
||||
WINPR_ASSERT(string2);
|
||||
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
const WCHAR a = string1[x];
|
||||
const WCHAR b = string2[x];
|
||||
|
||||
if (a != b)
|
||||
return (int)a - b;
|
||||
else if ((a == '\0') || (b == '\0'))
|
||||
return (int)a - b;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* _wcslen -> wcslen */
|
||||
|
||||
size_t _wcslen(const WCHAR* str)
|
||||
{
|
||||
const WCHAR* p = str;
|
||||
|
||||
WINPR_ASSERT(p);
|
||||
|
||||
while (*p)
|
||||
p++;
|
||||
|
||||
return (size_t)(p - str);
|
||||
}
|
||||
|
||||
/* _wcsnlen -> wcsnlen */
|
||||
|
||||
size_t _wcsnlen(const WCHAR* str, size_t max)
|
||||
{
|
||||
WINPR_ASSERT(str);
|
||||
|
||||
size_t x = 0;
|
||||
for (; x < max; x++)
|
||||
{
|
||||
if (str[x] == 0)
|
||||
return x;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/* _wcsstr -> wcsstr */
|
||||
|
||||
WCHAR* _wcsstr(const WCHAR* str, const WCHAR* strSearch)
|
||||
{
|
||||
WINPR_ASSERT(str);
|
||||
WINPR_ASSERT(strSearch);
|
||||
|
||||
if (strSearch[0] == '\0')
|
||||
return WINPR_CAST_CONST_PTR_AWAY(str, WCHAR*);
|
||||
|
||||
const size_t searchLen = _wcslen(strSearch);
|
||||
while (*str)
|
||||
{
|
||||
if (_wcsncmp(str, strSearch, searchLen) == 0)
|
||||
return WINPR_CAST_CONST_PTR_AWAY(str, WCHAR*);
|
||||
str++;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* _wcschr -> wcschr */
|
||||
|
||||
WCHAR* _wcschr(const WCHAR* str, WCHAR c)
|
||||
{
|
||||
union
|
||||
{
|
||||
const WCHAR* cc;
|
||||
WCHAR* c;
|
||||
} cnv;
|
||||
const WCHAR* p = str;
|
||||
|
||||
while (*p && (*p != c))
|
||||
p++;
|
||||
|
||||
cnv.cc = (*p == c) ? p : nullptr;
|
||||
return cnv.c;
|
||||
}
|
||||
|
||||
/* _wcsrchr -> wcsrchr */
|
||||
|
||||
WCHAR* _wcsrchr(const WCHAR* str, WCHAR c)
|
||||
{
|
||||
union
|
||||
{
|
||||
const WCHAR* cc;
|
||||
WCHAR* c;
|
||||
} cnv;
|
||||
const WCHAR* p = nullptr;
|
||||
|
||||
if (!str)
|
||||
return nullptr;
|
||||
|
||||
for (; *str != '\0'; str++)
|
||||
{
|
||||
const WCHAR ch = *str;
|
||||
if (ch == c)
|
||||
p = str;
|
||||
}
|
||||
|
||||
cnv.cc = p;
|
||||
return cnv.c;
|
||||
}
|
||||
|
||||
char* strtok_s(char* strToken, const char* strDelimit, char** context)
|
||||
{
|
||||
return strtok_r(strToken, strDelimit, context);
|
||||
}
|
||||
|
||||
WCHAR* wcstok_s(WCHAR* strToken, const WCHAR* strDelimit, WCHAR** context)
|
||||
{
|
||||
WCHAR* nextToken = nullptr;
|
||||
WCHAR value = 0;
|
||||
|
||||
if (!strToken)
|
||||
strToken = *context;
|
||||
|
||||
value = *strToken;
|
||||
|
||||
while (*strToken && _wcschr(strDelimit, value))
|
||||
{
|
||||
strToken++;
|
||||
value = *strToken;
|
||||
}
|
||||
|
||||
if (!*strToken)
|
||||
return nullptr;
|
||||
|
||||
nextToken = strToken++;
|
||||
value = *strToken;
|
||||
|
||||
while (*strToken && !(_wcschr(strDelimit, value)))
|
||||
{
|
||||
strToken++;
|
||||
value = *strToken;
|
||||
}
|
||||
|
||||
if (*strToken)
|
||||
*strToken++ = 0;
|
||||
|
||||
*context = strToken;
|
||||
return nextToken;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) || defined(_UWP)
|
||||
|
||||
/* Windows API Sets - api-ms-win-core-string-l2-1-0.dll
|
||||
* http://msdn.microsoft.com/en-us/library/hh802935/
|
||||
*/
|
||||
|
||||
#include "casing.h"
|
||||
|
||||
LPSTR CharUpperA(LPSTR lpsz)
|
||||
{
|
||||
size_t length = 0;
|
||||
|
||||
if (!lpsz)
|
||||
return nullptr;
|
||||
|
||||
length = strlen(lpsz);
|
||||
|
||||
if (length < 1)
|
||||
return (LPSTR) nullptr;
|
||||
|
||||
if (length == 1)
|
||||
{
|
||||
char c = *lpsz;
|
||||
|
||||
if ((c >= 'a') && (c <= 'z'))
|
||||
c = (char)(c - 'a' + 'A');
|
||||
|
||||
*lpsz = c;
|
||||
return lpsz;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
if ((lpsz[i] >= 'a') && (lpsz[i] <= 'z'))
|
||||
lpsz[i] = (char)(lpsz[i] - 'a' + 'A');
|
||||
}
|
||||
|
||||
return lpsz;
|
||||
}
|
||||
|
||||
LPWSTR CharUpperW(LPWSTR lpsz)
|
||||
{
|
||||
size_t length = 0;
|
||||
|
||||
if (!lpsz)
|
||||
return nullptr;
|
||||
|
||||
length = _wcslen(lpsz);
|
||||
|
||||
if (length < 1)
|
||||
return (LPWSTR) nullptr;
|
||||
|
||||
if (length == 1)
|
||||
{
|
||||
WCHAR c = *lpsz;
|
||||
|
||||
if ((c >= L'a') && (c <= L'z'))
|
||||
c = c - L'a' + L'A';
|
||||
|
||||
*lpsz = c;
|
||||
return lpsz;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
if ((lpsz[i] >= L'a') && (lpsz[i] <= L'z'))
|
||||
lpsz[i] = lpsz[i] - L'a' + L'A';
|
||||
}
|
||||
|
||||
return lpsz;
|
||||
}
|
||||
|
||||
DWORD CharUpperBuffA(LPSTR lpsz, DWORD cchLength)
|
||||
{
|
||||
if (cchLength < 1)
|
||||
return 0;
|
||||
|
||||
for (DWORD i = 0; i < cchLength; i++)
|
||||
{
|
||||
if ((lpsz[i] >= 'a') && (lpsz[i] <= 'z'))
|
||||
lpsz[i] = (char)(lpsz[i] - 'a' + 'A');
|
||||
}
|
||||
|
||||
return cchLength;
|
||||
}
|
||||
|
||||
DWORD CharUpperBuffW(LPWSTR lpsz, DWORD cchLength)
|
||||
{
|
||||
for (DWORD i = 0; i < cchLength; i++)
|
||||
{
|
||||
WCHAR value = winpr_Data_Get_UINT16(&lpsz[i]);
|
||||
value = WINPR_TOUPPERW(value);
|
||||
winpr_Data_Write_UINT16(&lpsz[i], value);
|
||||
}
|
||||
|
||||
return cchLength;
|
||||
}
|
||||
|
||||
LPSTR CharLowerA(LPSTR lpsz)
|
||||
{
|
||||
size_t length = 0;
|
||||
|
||||
if (!lpsz)
|
||||
return (LPSTR) nullptr;
|
||||
|
||||
length = strlen(lpsz);
|
||||
|
||||
if (length < 1)
|
||||
return (LPSTR) nullptr;
|
||||
|
||||
if (length == 1)
|
||||
{
|
||||
char c = *lpsz;
|
||||
|
||||
if ((c >= 'A') && (c <= 'Z'))
|
||||
c = (char)(c - 'A' + 'a');
|
||||
|
||||
*lpsz = c;
|
||||
return lpsz;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
if ((lpsz[i] >= 'A') && (lpsz[i] <= 'Z'))
|
||||
lpsz[i] = (char)(lpsz[i] - 'A' + 'a');
|
||||
}
|
||||
|
||||
return lpsz;
|
||||
}
|
||||
|
||||
LPWSTR CharLowerW(LPWSTR lpsz)
|
||||
{
|
||||
const size_t len = _wcsnlen(lpsz, UINT32_MAX + 1);
|
||||
if (len > UINT32_MAX)
|
||||
return nullptr;
|
||||
CharLowerBuffW(lpsz, (UINT32)len);
|
||||
return lpsz;
|
||||
}
|
||||
|
||||
DWORD CharLowerBuffA(LPSTR lpsz, DWORD cchLength)
|
||||
{
|
||||
if (cchLength < 1)
|
||||
return 0;
|
||||
|
||||
for (DWORD i = 0; i < cchLength; i++)
|
||||
{
|
||||
if ((lpsz[i] >= 'A') && (lpsz[i] <= 'Z'))
|
||||
lpsz[i] = (char)(lpsz[i] - 'A' + 'a');
|
||||
}
|
||||
|
||||
return cchLength;
|
||||
}
|
||||
|
||||
DWORD CharLowerBuffW(LPWSTR lpsz, DWORD cchLength)
|
||||
{
|
||||
for (DWORD i = 0; i < cchLength; i++)
|
||||
{
|
||||
WCHAR value = winpr_Data_Get_UINT16(&lpsz[i]);
|
||||
value = WINPR_TOLOWERW(value);
|
||||
winpr_Data_Write_UINT16(&lpsz[i], value);
|
||||
}
|
||||
|
||||
return cchLength;
|
||||
}
|
||||
|
||||
BOOL IsCharAlphaA(CHAR ch)
|
||||
{
|
||||
if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL IsCharAlphaW(WCHAR ch)
|
||||
{
|
||||
if (((ch >= L'a') && (ch <= L'z')) || ((ch >= L'A') && (ch <= L'Z')))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL IsCharAlphaNumericA(CHAR ch)
|
||||
{
|
||||
if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
|
||||
((ch >= '0') && (ch <= '9')))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL IsCharAlphaNumericW(WCHAR ch)
|
||||
{
|
||||
if (((ch >= L'a') && (ch <= L'z')) || ((ch >= L'A') && (ch <= L'Z')) ||
|
||||
((ch >= L'0') && (ch <= L'9')))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL IsCharUpperA(CHAR ch)
|
||||
{
|
||||
if ((ch >= 'A') && (ch <= 'Z'))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL IsCharUpperW(WCHAR ch)
|
||||
{
|
||||
if ((ch >= L'A') && (ch <= L'Z'))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL IsCharLowerA(CHAR ch)
|
||||
{
|
||||
if ((ch >= 'a') && (ch <= 'z'))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL IsCharLowerW(WCHAR ch)
|
||||
{
|
||||
if ((ch >= L'a') && (ch <= L'z'))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
size_t ConvertLineEndingToLF(char* str, size_t size)
|
||||
{
|
||||
size_t skip = 0;
|
||||
|
||||
WINPR_ASSERT(str || (size == 0));
|
||||
for (size_t x = 0; x < size; x++)
|
||||
{
|
||||
char c = str[x];
|
||||
switch (c)
|
||||
{
|
||||
case '\r':
|
||||
str[x - skip] = '\n';
|
||||
if ((x + 1 < size) && (str[x + 1] == '\n'))
|
||||
skip++;
|
||||
break;
|
||||
default:
|
||||
str[x - skip] = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return size - skip;
|
||||
}
|
||||
|
||||
char* ConvertLineEndingToCRLF(const char* str, size_t* size)
|
||||
{
|
||||
WINPR_ASSERT(size);
|
||||
const size_t s = *size;
|
||||
WINPR_ASSERT(str || (s == 0));
|
||||
|
||||
*size = 0;
|
||||
if (s == 0)
|
||||
return nullptr;
|
||||
|
||||
size_t linebreaks = 0;
|
||||
for (size_t x = 0; x < s - 1; x++)
|
||||
{
|
||||
char c = str[x];
|
||||
switch (c)
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
linebreaks++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
char* cnv = calloc(s + linebreaks * 2ull + 1ull, sizeof(char));
|
||||
if (!cnv)
|
||||
return nullptr;
|
||||
|
||||
size_t pos = 0;
|
||||
for (size_t x = 0; x < s; x++)
|
||||
{
|
||||
const char c = str[x];
|
||||
switch (c)
|
||||
{
|
||||
case '\r':
|
||||
cnv[pos++] = '\r';
|
||||
cnv[pos++] = '\n';
|
||||
break;
|
||||
case '\n':
|
||||
/* Do not duplicate existing \r\n sequences */
|
||||
if ((x > 0) && (str[x - 1] != '\r'))
|
||||
{
|
||||
cnv[pos++] = '\r';
|
||||
cnv[pos++] = '\n';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cnv[pos++] = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*size = pos;
|
||||
return cnv;
|
||||
}
|
||||
|
||||
char* StrSep(char** stringp, const char* delim)
|
||||
{
|
||||
char* start = *stringp;
|
||||
char* p = nullptr;
|
||||
p = (start != nullptr) ? strpbrk(start, delim) : nullptr;
|
||||
|
||||
if (!p)
|
||||
*stringp = nullptr;
|
||||
else
|
||||
{
|
||||
*p = '\0';
|
||||
*stringp = p + 1;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
INT64 GetLine(char** lineptr, size_t* size, FILE* stream)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
char c;
|
||||
char* n;
|
||||
size_t step = 32;
|
||||
size_t used = 0;
|
||||
|
||||
if (!lineptr || !size)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (used + 2 >= *size)
|
||||
{
|
||||
*size += step;
|
||||
n = realloc(*lineptr, *size);
|
||||
|
||||
if (!n)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*lineptr = n;
|
||||
}
|
||||
|
||||
c = fgetc(stream);
|
||||
|
||||
if (c != EOF)
|
||||
(*lineptr)[used++] = c;
|
||||
} while ((c != '\n') && (c != '\r') && (c != EOF));
|
||||
|
||||
(*lineptr)[used] = '\0';
|
||||
return used;
|
||||
#elif !defined(ANDROID) && !defined(IOS)
|
||||
return getline(lineptr, size, stream);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(WINPR_HAVE_STRNDUP)
|
||||
char* strndup(const char* src, size_t n)
|
||||
{
|
||||
char* dst = calloc(n + 1, sizeof(char));
|
||||
if (dst)
|
||||
strncpy(dst, src, n);
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
const WCHAR* InitializeConstWCharFromUtf8(const char* str, WCHAR* buffer, size_t len)
|
||||
{
|
||||
WINPR_ASSERT(str);
|
||||
WINPR_ASSERT(buffer || (len == 0));
|
||||
(void)ConvertUtf8ToWChar(str, buffer, len);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
WCHAR* wcsndup(const WCHAR* s, size_t n)
|
||||
{
|
||||
if (!s)
|
||||
return nullptr;
|
||||
|
||||
WCHAR* copy = calloc(n + 1, sizeof(WCHAR));
|
||||
if (!copy)
|
||||
return nullptr;
|
||||
memcpy(copy, s, n * sizeof(WCHAR));
|
||||
return copy;
|
||||
}
|
||||
23
third_party/FreeRDP/winpr/libwinpr/crt/test/CMakeLists.txt
vendored
Normal file
23
third_party/FreeRDP/winpr/libwinpr/crt/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
set(MODULE_NAME "TestCrt")
|
||||
set(MODULE_PREFIX "TEST_CRT")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS TestTypes.c TestFormatSpecifiers.c TestAlignment.c TestString.c TestUnicodeConversion.c)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
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 "WinPR/Test")
|
||||
87
third_party/FreeRDP/winpr/libwinpr/crt/test/TestAlignment.c
vendored
Normal file
87
third_party/FreeRDP/winpr/libwinpr/crt/test/TestAlignment.c
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
int TestAlignment(int argc, char* argv[])
|
||||
{
|
||||
void* ptr = nullptr;
|
||||
size_t alignment = 0;
|
||||
size_t offset = 0;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
/* Alignment should be 2^N where N is a positive integer */
|
||||
|
||||
alignment = 16;
|
||||
offset = 8;
|
||||
|
||||
/* _aligned_malloc */
|
||||
|
||||
ptr = winpr_aligned_malloc(100, alignment);
|
||||
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
printf("Error allocating aligned memory.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((size_t)ptr % alignment) != 0)
|
||||
{
|
||||
printf("This pointer, %p, is not aligned on %" PRIuz "\n", ptr, alignment);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* _aligned_realloc */
|
||||
|
||||
ptr = winpr_aligned_realloc(ptr, 200, alignment);
|
||||
|
||||
if (((size_t)ptr % alignment) != 0)
|
||||
{
|
||||
printf("This pointer, %p, is not aligned on %" PRIuz "\n", ptr, alignment);
|
||||
return -1;
|
||||
}
|
||||
|
||||
winpr_aligned_free(ptr);
|
||||
|
||||
/* _aligned_offset_malloc */
|
||||
|
||||
ptr = winpr_aligned_offset_malloc(200, alignment, offset);
|
||||
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
printf("Error reallocating aligned offset memory.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((((size_t)ptr) + offset) % alignment) != 0)
|
||||
{
|
||||
printf("This pointer, %p, does not satisfy offset %" PRIuz " and alignment %" PRIuz "\n",
|
||||
ptr, offset, alignment);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* _aligned_offset_realloc */
|
||||
|
||||
ptr = winpr_aligned_offset_realloc(ptr, 200, alignment, offset);
|
||||
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
printf("Error reallocating aligned offset memory.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((((size_t)ptr) + offset) % alignment) != 0)
|
||||
{
|
||||
printf("This pointer, %p, does not satisfy offset %" PRIuz " and alignment %" PRIuz "\n",
|
||||
ptr, offset, alignment);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* _aligned_free works for both _aligned_malloc and _aligned_offset_malloc. free() should not be
|
||||
* used. */
|
||||
winpr_aligned_free(ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
169
third_party/FreeRDP/winpr/libwinpr/crt/test/TestFormatSpecifiers.c
vendored
Normal file
169
third_party/FreeRDP/winpr/libwinpr/crt/test/TestFormatSpecifiers.c
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
#include <stdio.h>
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/string.h>
|
||||
|
||||
int TestFormatSpecifiers(int argc, char* argv[])
|
||||
{
|
||||
unsigned errors = 0;
|
||||
|
||||
char fmt[4096];
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
/* size_t */
|
||||
{
|
||||
size_t arg = 0xabcd;
|
||||
const char* chk = "uz:43981 oz:125715 xz:abcd Xz:ABCD";
|
||||
|
||||
(void)sprintf_s(fmt, sizeof(fmt), "uz:%" PRIuz " oz:%" PRIoz " xz:%" PRIxz " Xz:%" PRIXz "",
|
||||
arg, arg, arg, arg);
|
||||
|
||||
if (strcmp(fmt, chk) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s failed size_t test: got [%s] instead of [%s]\n", __func__,
|
||||
fmt, chk);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
/* INT8 */
|
||||
{
|
||||
INT8 arg = -16;
|
||||
const char* chk = "d8:-16 x8:f0 X8:F0";
|
||||
|
||||
(void)sprintf_s(fmt, sizeof(fmt), "d8:%" PRId8 " x8:%" PRIx8 " X8:%" PRIX8 "", arg,
|
||||
(UINT8)arg, (UINT8)arg);
|
||||
|
||||
if (strcmp(fmt, chk) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s failed INT8 test: got [%s] instead of [%s]\n", __func__, fmt,
|
||||
chk);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
/* UINT8 */
|
||||
{
|
||||
UINT8 arg = 0xFE;
|
||||
const char* chk = "u8:254 o8:376 x8:fe X8:FE";
|
||||
|
||||
(void)sprintf_s(fmt, sizeof(fmt), "u8:%" PRIu8 " o8:%" PRIo8 " x8:%" PRIx8 " X8:%" PRIX8 "",
|
||||
arg, arg, arg, arg);
|
||||
|
||||
if (strcmp(fmt, chk) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s failed UINT8 test: got [%s] instead of [%s]\n", __func__, fmt,
|
||||
chk);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
/* INT16 */
|
||||
{
|
||||
INT16 arg = -16;
|
||||
const char* chk = "d16:-16 x16:fff0 X16:FFF0";
|
||||
|
||||
(void)sprintf_s(fmt, sizeof(fmt), "d16:%" PRId16 " x16:%" PRIx16 " X16:%" PRIX16 "", arg,
|
||||
(UINT16)arg, (UINT16)arg);
|
||||
|
||||
if (strcmp(fmt, chk) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s failed INT16 test: got [%s] instead of [%s]\n", __func__, fmt,
|
||||
chk);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
/* UINT16 */
|
||||
{
|
||||
UINT16 arg = 0xFFFE;
|
||||
const char* chk = "u16:65534 o16:177776 x16:fffe X16:FFFE";
|
||||
|
||||
(void)sprintf_s(fmt, sizeof(fmt),
|
||||
"u16:%" PRIu16 " o16:%" PRIo16 " x16:%" PRIx16 " X16:%" PRIX16 "", arg, arg,
|
||||
arg, arg);
|
||||
|
||||
if (strcmp(fmt, chk) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s failed UINT16 test: got [%s] instead of [%s]\n", __func__,
|
||||
fmt, chk);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
/* INT32 */
|
||||
{
|
||||
INT32 arg = -16;
|
||||
const char* chk = "d32:-16 x32:fffffff0 X32:FFFFFFF0";
|
||||
|
||||
(void)sprintf_s(fmt, sizeof(fmt), "d32:%" PRId32 " x32:%" PRIx32 " X32:%" PRIX32 "", arg,
|
||||
(UINT32)arg, (UINT32)arg);
|
||||
|
||||
if (strcmp(fmt, chk) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s failed INT32 test: got [%s] instead of [%s]\n", __func__, fmt,
|
||||
chk);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
/* UINT32 */
|
||||
{
|
||||
UINT32 arg = 0xFFFFFFFE;
|
||||
const char* chk = "u32:4294967294 o32:37777777776 x32:fffffffe X32:FFFFFFFE";
|
||||
|
||||
(void)sprintf_s(fmt, sizeof(fmt),
|
||||
"u32:%" PRIu32 " o32:%" PRIo32 " x32:%" PRIx32 " X32:%" PRIX32 "", arg, arg,
|
||||
arg, arg);
|
||||
|
||||
if (strcmp(fmt, chk) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s failed UINT16 test: got [%s] instead of [%s]\n", __func__,
|
||||
fmt, chk);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
/* INT64 */
|
||||
{
|
||||
INT64 arg = -16;
|
||||
const char* chk = "d64:-16 x64:fffffffffffffff0 X64:FFFFFFFFFFFFFFF0";
|
||||
|
||||
(void)sprintf_s(fmt, sizeof(fmt), "d64:%" PRId64 " x64:%" PRIx64 " X64:%" PRIX64 "", arg,
|
||||
(UINT64)arg, (UINT64)arg);
|
||||
|
||||
if (strcmp(fmt, chk) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s failed INT64 test: got [%s] instead of [%s]\n", __func__, fmt,
|
||||
chk);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
/* UINT64 */
|
||||
{
|
||||
UINT64 arg = 0xFFFFFFFFFFFFFFFE;
|
||||
const char* chk = "u64:18446744073709551614 o64:1777777777777777777776 "
|
||||
"x64:fffffffffffffffe X64:FFFFFFFFFFFFFFFE";
|
||||
|
||||
(void)sprintf_s(fmt, sizeof(fmt),
|
||||
"u64:%" PRIu64 " o64:%" PRIo64 " x64:%016" PRIx64 " X64:%016" PRIX64 "",
|
||||
arg, arg, arg, arg);
|
||||
|
||||
if (strcmp(fmt, chk) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s failed UINT64 test: got [%s] instead of [%s]\n", __func__,
|
||||
fmt, chk);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors)
|
||||
{
|
||||
(void)fprintf(stderr, "%s produced %u errors\n", __func__, errors);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
222
third_party/FreeRDP/winpr/libwinpr/crt/test/TestString.c
vendored
Normal file
222
third_party/FreeRDP/winpr/libwinpr/crt/test/TestString.c
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
static const CHAR testStringA[] = { 'T', 'h', 'e', ' ', 'q', 'u', 'i', 'c', 'k', ' ', 'b',
|
||||
'r', 'o', 'w', 'n', ' ', 'f', 'o', 'x', ' ', 'j', 'u',
|
||||
'm', 'p', 's', ' ', 'o', 'v', 'e', 'r', ' ', 't', 'h',
|
||||
'e', ' ', 'l', 'a', 'z', 'y', ' ', 'd', 'o', 'g', '\0' };
|
||||
|
||||
#define testStringA_Length ((sizeof(testStringA) / sizeof(CHAR)) - 1)
|
||||
|
||||
static const CHAR testToken1A[] = { 'q', 'u', 'i', 'c', 'k', '\0' };
|
||||
static const CHAR testToken2A[] = { 'b', 'r', 'o', 'w', 'n', '\0' };
|
||||
static const CHAR testToken3A[] = { 'f', 'o', 'x', '\0' };
|
||||
|
||||
#define testToken1A_Length ((sizeof(testToken1A) / sizeof(CHAR)) - 1)
|
||||
#define testToken2A_Length ((sizeof(testToken2A) / sizeof(CHAR)) - 1)
|
||||
#define testToken3A_Length ((sizeof(testToken3A) / sizeof(CHAR)) - 1)
|
||||
|
||||
static const CHAR testTokensA[] = { 'q', 'u', 'i', 'c', 'k', '\r', '\n', 'b', 'r', 'o',
|
||||
'w', 'n', '\r', '\n', 'f', 'o', 'x', '\r', '\n', '\0' };
|
||||
|
||||
#define testTokensA_Length ((sizeof(testTokensA) / sizeof(CHAR)) - 1)
|
||||
|
||||
static const CHAR testDelimiterA[] = { '\r', '\n', '\0' };
|
||||
|
||||
#define testDelimiterA_Length ((sizeof(testDelimiter) / sizeof(CHAR)) - 1)
|
||||
|
||||
struct url_test_pair
|
||||
{
|
||||
const char* what;
|
||||
const char* escaped;
|
||||
};
|
||||
|
||||
static const struct url_test_pair url_tests[] = {
|
||||
{ "xxx%bar ga<ka>ee#%%#%{h}g{f{e%d|c\\b^a~p[q]r`s;t/u?v:w@x=y&z$xxx",
|
||||
"xxx%25bar%20ga%3Cka%3Eee%23%25%25%23%25%7Bh%7Dg%7Bf%7Be%25d%7Cc%5Cb%5Ea~p%5Bq%5Dr%60s%3Bt%"
|
||||
"2Fu%3Fv%3Aw%40x%3Dy%26z%24xxx" },
|
||||
{ "äöúëü", "%C3%A4%C3%B6%C3%BA%C3%AB%C3%BC" },
|
||||
{ "🎅🏄🤘😈", "%F0%9F%8E%85%F0%9F%8F%84%F0%9F%A4%98%F0%9F%98%88" },
|
||||
{ "foo$.%.^.&.\\.txt+", "foo%24.%25.%5E.%26.%5C.txt%2B" }
|
||||
};
|
||||
|
||||
static BOOL test_url_escape(void)
|
||||
{
|
||||
for (size_t x = 0; x < ARRAYSIZE(url_tests); x++)
|
||||
{
|
||||
const struct url_test_pair* cur = &url_tests[x];
|
||||
|
||||
char* escaped = winpr_str_url_encode(cur->what, strlen(cur->what) + 1);
|
||||
char* what = winpr_str_url_decode(cur->escaped, strlen(cur->escaped) + 1);
|
||||
|
||||
const size_t elen = strlen(escaped);
|
||||
const size_t wlen = strlen(what);
|
||||
const size_t pelen = strlen(cur->escaped);
|
||||
const size_t pwlen = strlen(cur->what);
|
||||
BOOL rc = TRUE;
|
||||
if (!escaped || (elen != pelen) || (strcmp(escaped, cur->escaped) != 0))
|
||||
{
|
||||
printf("expected: [%" PRIuz "] %s\n", pelen, cur->escaped);
|
||||
printf("got : [%" PRIuz "] %s\n", elen, escaped);
|
||||
rc = FALSE;
|
||||
}
|
||||
else if (!what || (wlen != pwlen) || (strcmp(what, cur->what) != 0))
|
||||
{
|
||||
printf("expected: [%" PRIuz "] %s\n", pwlen, cur->what);
|
||||
printf("got : [%" PRIuz "] %s\n", wlen, what);
|
||||
rc = FALSE;
|
||||
}
|
||||
|
||||
free(escaped);
|
||||
free(what);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL test_winpr_asprintf(void)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const char test[] = "test string case";
|
||||
const size_t len = strnlen(test, sizeof(test));
|
||||
|
||||
char* str = nullptr;
|
||||
size_t slen = 0;
|
||||
const int res = winpr_asprintf(&str, &slen, "%s", test);
|
||||
if (!str)
|
||||
goto fail;
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
if ((size_t)res != len)
|
||||
goto fail;
|
||||
if (len != slen)
|
||||
goto fail;
|
||||
if (strnlen(str, slen + 10) != slen)
|
||||
goto fail;
|
||||
rc = TRUE;
|
||||
fail:
|
||||
free(str);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestString(int argc, char* argv[])
|
||||
{
|
||||
const WCHAR* p = nullptr;
|
||||
size_t pos = 0;
|
||||
size_t length = 0;
|
||||
WCHAR* context = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (!test_winpr_asprintf())
|
||||
return -1;
|
||||
|
||||
if (!test_url_escape())
|
||||
return -1;
|
||||
|
||||
/* _wcslen */
|
||||
WCHAR testStringW[ARRAYSIZE(testStringA)] = WINPR_C_ARRAY_INIT;
|
||||
(void)ConvertUtf8NToWChar(testStringA, ARRAYSIZE(testStringA), testStringW,
|
||||
ARRAYSIZE(testStringW));
|
||||
const size_t testStringW_Length = testStringA_Length;
|
||||
length = _wcslen(testStringW);
|
||||
|
||||
if (length != testStringW_Length)
|
||||
{
|
||||
printf("_wcslen error: length mismatch: Actual: %" PRIuz ", Expected: %" PRIuz "\n", length,
|
||||
testStringW_Length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* _wcschr */
|
||||
union
|
||||
{
|
||||
char c[2];
|
||||
WCHAR w;
|
||||
} search;
|
||||
search.c[0] = 'r';
|
||||
search.c[1] = '\0';
|
||||
|
||||
p = _wcschr(testStringW, search.w);
|
||||
pos = (p - testStringW);
|
||||
|
||||
if (pos != 11)
|
||||
{
|
||||
printf("_wcschr error: position mismatch: Actual: %" PRIuz ", Expected: 11\n", pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = _wcschr(&testStringW[pos + 1], search.w);
|
||||
pos = (p - testStringW);
|
||||
|
||||
if (pos != 29)
|
||||
{
|
||||
printf("_wcschr error: position mismatch: Actual: %" PRIuz ", Expected: 29\n", pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = _wcschr(&testStringW[pos + 1], search.w);
|
||||
|
||||
if (p != nullptr)
|
||||
{
|
||||
printf("_wcschr error: return value mismatch: Actual: %p, Expected: nullptr\n",
|
||||
(const void*)p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* wcstok_s */
|
||||
WCHAR testDelimiterW[ARRAYSIZE(testDelimiterA)] = WINPR_C_ARRAY_INIT;
|
||||
WCHAR testTokensW[ARRAYSIZE(testTokensA)] = WINPR_C_ARRAY_INIT;
|
||||
(void)ConvertUtf8NToWChar(testTokensA, ARRAYSIZE(testTokensA), testTokensW,
|
||||
ARRAYSIZE(testTokensW));
|
||||
(void)ConvertUtf8NToWChar(testDelimiterA, ARRAYSIZE(testDelimiterA), testDelimiterW,
|
||||
ARRAYSIZE(testDelimiterW));
|
||||
p = wcstok_s(testTokensW, testDelimiterW, &context);
|
||||
|
||||
WCHAR testToken1W[ARRAYSIZE(testToken1A)] = WINPR_C_ARRAY_INIT;
|
||||
(void)ConvertUtf8NToWChar(testToken1A, ARRAYSIZE(testToken1A), testToken1W,
|
||||
ARRAYSIZE(testToken1W));
|
||||
if (memcmp(p, testToken1W, sizeof(testToken1W)) != 0)
|
||||
{
|
||||
printf("wcstok_s error: token #1 mismatch\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = wcstok_s(nullptr, testDelimiterW, &context);
|
||||
|
||||
WCHAR testToken2W[ARRAYSIZE(testToken2A)] = WINPR_C_ARRAY_INIT;
|
||||
(void)ConvertUtf8NToWChar(testToken2A, ARRAYSIZE(testToken2A), testToken2W,
|
||||
ARRAYSIZE(testToken2W));
|
||||
if (memcmp(p, testToken2W, sizeof(testToken2W)) != 0)
|
||||
{
|
||||
printf("wcstok_s error: token #2 mismatch\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = wcstok_s(nullptr, testDelimiterW, &context);
|
||||
|
||||
WCHAR testToken3W[ARRAYSIZE(testToken3A)] = WINPR_C_ARRAY_INIT;
|
||||
(void)ConvertUtf8NToWChar(testToken3A, ARRAYSIZE(testToken3A), testToken3W,
|
||||
ARRAYSIZE(testToken3W));
|
||||
if (memcmp(p, testToken3W, sizeof(testToken3W)) != 0)
|
||||
{
|
||||
printf("wcstok_s error: token #3 mismatch\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = wcstok_s(nullptr, testDelimiterW, &context);
|
||||
|
||||
if (p != nullptr)
|
||||
{
|
||||
printf("wcstok_s error: return value is not nullptr\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
115
third_party/FreeRDP/winpr/libwinpr/crt/test/TestTypes.c
vendored
Normal file
115
third_party/FreeRDP/winpr/libwinpr/crt/test/TestTypes.c
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#define EXPECTED_SIZEOF_BYTE 1
|
||||
#define EXPECTED_SIZEOF_BOOLEAN 1
|
||||
#define EXPECTED_SIZEOF_CHAR 1
|
||||
#define EXPECTED_SIZEOF_UCHAR 1
|
||||
#define EXPECTED_SIZEOF_INT8 1
|
||||
#define EXPECTED_SIZEOF_UINT8 1
|
||||
#define EXPECTED_SIZEOF_INT16 2
|
||||
#define EXPECTED_SIZEOF_UINT16 2
|
||||
#define EXPECTED_SIZEOF_WORD 2
|
||||
#define EXPECTED_SIZEOF_WCHAR 2
|
||||
#define EXPECTED_SIZEOF_SHORT 2
|
||||
#define EXPECTED_SIZEOF_USHORT 2
|
||||
#define EXPECTED_SIZEOF_BOOL 4
|
||||
#define EXPECTED_SIZEOF_INT 4
|
||||
#define EXPECTED_SIZEOF_UINT 4
|
||||
#define EXPECTED_SIZEOF_INT32 4
|
||||
#define EXPECTED_SIZEOF_UINT32 4
|
||||
#define EXPECTED_SIZEOF_DWORD 4
|
||||
#define EXPECTED_SIZEOF_DWORD32 4
|
||||
#define EXPECTED_SIZEOF_LONG 4
|
||||
#define EXPECTED_SIZEOF_LONG32 4
|
||||
#define EXPECTED_SIZEOF_INT64 8
|
||||
#define EXPECTED_SIZEOF_UINT64 8
|
||||
#define EXPECTED_SIZEOF_DWORD64 8
|
||||
#define EXPECTED_SIZEOF_DWORDLONG 8
|
||||
#define EXPECTED_SIZEOF_LONG64 8
|
||||
#define EXPECTED_SIZEOF_ULONGLONG 8
|
||||
#define EXPECTED_SIZEOF_LUID 8
|
||||
#define EXPECTED_SIZEOF_FILETIME 8
|
||||
#define EXPECTED_SIZEOF_LARGE_INTEGER 8
|
||||
#define EXPECTED_SIZEOF_ULARGE_INTEGER 8
|
||||
#define EXPECTED_SIZEOF_GUID 16
|
||||
#define EXPECTED_SIZEOF_SYSTEMTIME 16
|
||||
#define EXPECTED_SIZEOF_size_t sizeof(void*)
|
||||
#define EXPECTED_SIZEOF_INT_PTR sizeof(void*)
|
||||
#define EXPECTED_SIZEOF_UINT_PTR sizeof(void*)
|
||||
#define EXPECTED_SIZEOF_DWORD_PTR sizeof(void*)
|
||||
#define EXPECTED_SIZEOF_LONG_PTR sizeof(void*)
|
||||
#define EXPECTED_SIZEOF_ULONG_PTR sizeof(void*)
|
||||
|
||||
#define TEST_SIZEOF_TYPE(_name) \
|
||||
if (sizeof(_name) != EXPECTED_SIZEOF_##_name) \
|
||||
{ \
|
||||
(void)fprintf(stderr, "sizeof(%s) mismatch: Actual: %" PRIuz ", Expected: %" PRIuz "\n", \
|
||||
#_name, sizeof(_name), (size_t)EXPECTED_SIZEOF_##_name); \
|
||||
status = -1; \
|
||||
}
|
||||
|
||||
int TestTypes(int argc, char* argv[])
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
TEST_SIZEOF_TYPE(INT8)
|
||||
TEST_SIZEOF_TYPE(UINT8)
|
||||
|
||||
TEST_SIZEOF_TYPE(BYTE)
|
||||
TEST_SIZEOF_TYPE(BOOLEAN)
|
||||
TEST_SIZEOF_TYPE(CHAR)
|
||||
TEST_SIZEOF_TYPE(UCHAR)
|
||||
|
||||
TEST_SIZEOF_TYPE(INT16)
|
||||
TEST_SIZEOF_TYPE(UINT16)
|
||||
|
||||
TEST_SIZEOF_TYPE(WORD)
|
||||
TEST_SIZEOF_TYPE(WCHAR)
|
||||
TEST_SIZEOF_TYPE(SHORT)
|
||||
TEST_SIZEOF_TYPE(USHORT)
|
||||
|
||||
/* fails on OS X */
|
||||
// TEST_SIZEOF_TYPE(BOOL)
|
||||
|
||||
TEST_SIZEOF_TYPE(INT)
|
||||
TEST_SIZEOF_TYPE(UINT)
|
||||
TEST_SIZEOF_TYPE(DWORD)
|
||||
TEST_SIZEOF_TYPE(DWORD32)
|
||||
TEST_SIZEOF_TYPE(LONG)
|
||||
TEST_SIZEOF_TYPE(LONG32)
|
||||
|
||||
TEST_SIZEOF_TYPE(INT32)
|
||||
TEST_SIZEOF_TYPE(UINT32)
|
||||
|
||||
TEST_SIZEOF_TYPE(INT64)
|
||||
TEST_SIZEOF_TYPE(UINT64)
|
||||
|
||||
TEST_SIZEOF_TYPE(DWORD64)
|
||||
TEST_SIZEOF_TYPE(DWORDLONG)
|
||||
|
||||
TEST_SIZEOF_TYPE(LONG64)
|
||||
TEST_SIZEOF_TYPE(ULONGLONG)
|
||||
|
||||
TEST_SIZEOF_TYPE(LUID)
|
||||
TEST_SIZEOF_TYPE(FILETIME)
|
||||
TEST_SIZEOF_TYPE(LARGE_INTEGER)
|
||||
TEST_SIZEOF_TYPE(ULARGE_INTEGER)
|
||||
|
||||
TEST_SIZEOF_TYPE(GUID)
|
||||
TEST_SIZEOF_TYPE(SYSTEMTIME)
|
||||
|
||||
TEST_SIZEOF_TYPE(size_t)
|
||||
TEST_SIZEOF_TYPE(INT_PTR)
|
||||
TEST_SIZEOF_TYPE(UINT_PTR)
|
||||
TEST_SIZEOF_TYPE(DWORD_PTR)
|
||||
TEST_SIZEOF_TYPE(LONG_PTR)
|
||||
TEST_SIZEOF_TYPE(ULONG_PTR)
|
||||
|
||||
return status;
|
||||
}
|
||||
1305
third_party/FreeRDP/winpr/libwinpr/crt/test/TestUnicodeConversion.c
vendored
Normal file
1305
third_party/FreeRDP/winpr/libwinpr/crt/test/TestUnicodeConversion.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
652
third_party/FreeRDP/winpr/libwinpr/crt/unicode.c
vendored
Normal file
652
third_party/FreeRDP/winpr/libwinpr/crt/unicode.c
vendored
Normal file
@@ -0,0 +1,652 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Unicode Conversion (CRT)
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2022 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/error.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "unicode.h"
|
||||
|
||||
/**
|
||||
* Notes on cross-platform Unicode portability:
|
||||
*
|
||||
* Unicode has many possible Unicode Transformation Format (UTF) encodings,
|
||||
* where some of the most commonly used are UTF-8, UTF-16 and sometimes UTF-32.
|
||||
*
|
||||
* The number in the UTF encoding name (8, 16, 32) refers to the number of bits
|
||||
* per code unit. A code unit is the minimal bit combination that can represent
|
||||
* a unit of encoded text in the given encoding. For instance, UTF-8 encodes
|
||||
* the English alphabet using 8 bits (or one byte) each, just like in ASCII.
|
||||
*
|
||||
* However, the total number of code points (values in the Unicode codespace)
|
||||
* only fits completely within 32 bits. This means that for UTF-8 and UTF-16,
|
||||
* more than one code unit may be required to fully encode a specific value.
|
||||
* UTF-8 and UTF-16 are variable-width encodings, while UTF-32 is fixed-width.
|
||||
*
|
||||
* UTF-8 has the advantage of being backwards compatible with ASCII, and is
|
||||
* one of the most commonly used Unicode encoding.
|
||||
*
|
||||
* UTF-16 is used everywhere in the Windows API. The strategy employed by
|
||||
* Microsoft to provide backwards compatibility in their API was to create
|
||||
* an ANSI and a Unicode version of the same function, ending with A (ANSI)
|
||||
* and W (Wide character, or UTF-16 Unicode). In headers, the original
|
||||
* function name is replaced by a macro that defines to either the ANSI
|
||||
* or Unicode version based on the definition of the _UNICODE macro.
|
||||
*
|
||||
* UTF-32 has the advantage of being fixed width, but wastes a lot of space
|
||||
* for English text (4x more than UTF-8, 2x more than UTF-16).
|
||||
*
|
||||
* In C, wide character strings are often defined with the wchar_t type.
|
||||
* Many functions are provided to deal with those wide character strings,
|
||||
* such as wcslen (strlen equivalent) or wprintf (printf equivalent).
|
||||
*
|
||||
* This may lead to some confusion, since many of these functions exist
|
||||
* on both Windows and Linux, but they are *not* the same!
|
||||
*
|
||||
* This sample hello world is a good example:
|
||||
*
|
||||
* #include <wchar.h>
|
||||
*
|
||||
* wchar_t hello[] = L"Hello, World!\n";
|
||||
*
|
||||
* int main(int argc, char** argv)
|
||||
* {
|
||||
* wprintf(hello);
|
||||
* wprintf(L"sizeof(wchar_t): %d\n", sizeof(wchar_t));
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* There is a reason why the sample prints the size of the wchar_t type:
|
||||
* On Windows, wchar_t is two bytes (UTF-16), while on most other systems
|
||||
* it is 4 bytes (UTF-32). This means that if you write code on Windows,
|
||||
* use L"" to define a string which is meant to be UTF-16 and not UTF-32,
|
||||
* you will have a little surprise when trying to port your code to Linux.
|
||||
*
|
||||
* Since the Windows API uses UTF-16, not UTF-32, WinPR defines the WCHAR
|
||||
* type to always be 2-bytes long and uses it instead of wchar_t. Do not
|
||||
* ever use wchar_t with WinPR unless you know what you are doing.
|
||||
*
|
||||
* As for L"", it is unfortunately unusable in a portable way, unless a
|
||||
* special option is passed to GCC to define wchar_t as being two bytes.
|
||||
* For string constants that must be UTF-16, it is a pain, but they can
|
||||
* be defined in a portable way like this:
|
||||
*
|
||||
* WCHAR hello[] = { 'H','e','l','l','o','\0' };
|
||||
*
|
||||
* Such strings cannot be passed to native functions like wcslen(), which
|
||||
* may expect a different wchar_t size. For this reason, WinPR provides
|
||||
* _wcslen, which expects UTF-16 WCHAR strings on all platforms.
|
||||
*
|
||||
*/
|
||||
|
||||
/** \deprecated We no longer export this function, see ConvertUtf8ToWChar family of functions for a
|
||||
* replacement
|
||||
*
|
||||
* Conversion to Unicode (UTF-16)
|
||||
* MultiByteToWideChar: http://msdn.microsoft.com/en-us/library/windows/desktop/dd319072/
|
||||
*
|
||||
* cbMultiByte is an input size in bytes (BYTE)
|
||||
* cchWideChar is an output size in wide characters (WCHAR)
|
||||
*
|
||||
* Null-terminated UTF-8 strings:
|
||||
*
|
||||
* cchWideChar *cannot* be assumed to be cbMultiByte since UTF-8 is variable-width!
|
||||
*
|
||||
* Instead, obtain the required cchWideChar output size like this:
|
||||
* cchWideChar = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) lpMultiByteStr, -1, nullptr, 0);
|
||||
*
|
||||
* A value of -1 for cbMultiByte indicates that the input string is null-terminated,
|
||||
* and the null terminator *will* be processed. The size returned by MultiByteToWideChar
|
||||
* will therefore include the null terminator. Equivalent behavior can be obtained by
|
||||
* computing the length in bytes of the input buffer, including the null terminator:
|
||||
*
|
||||
* cbMultiByte = strlen((char*) lpMultiByteStr) + 1;
|
||||
*
|
||||
* An output buffer of the proper size can then be allocated:
|
||||
*
|
||||
* lpWideCharStr = (LPWSTR) malloc(cchWideChar * sizeof(WCHAR));
|
||||
*
|
||||
* Since cchWideChar is an output size in wide characters, the actual buffer size is:
|
||||
* (cchWideChar * sizeof(WCHAR)) or (cchWideChar * 2)
|
||||
*
|
||||
* Finally, perform the conversion:
|
||||
*
|
||||
* cchWideChar = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) lpMultiByteStr, -1, lpWideCharStr,
|
||||
* cchWideChar);
|
||||
*
|
||||
* The value returned by MultiByteToWideChar corresponds to the number of wide characters written
|
||||
* to the output buffer, and should match the value obtained on the first call to
|
||||
* MultiByteToWideChar.
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(WITH_WINPR_DEPRECATED)
|
||||
static
|
||||
#endif
|
||||
int
|
||||
MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
|
||||
LPWSTR lpWideCharStr, int cchWideChar)
|
||||
{
|
||||
return int_MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr,
|
||||
cchWideChar);
|
||||
}
|
||||
|
||||
/** \deprecated We no longer export this function, see ConvertWCharToUtf8 family of functions for a
|
||||
* replacement
|
||||
*
|
||||
* Conversion from Unicode (UTF-16)
|
||||
* WideCharToMultiByte: http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130/
|
||||
*
|
||||
* cchWideChar is an input size in wide characters (WCHAR)
|
||||
* cbMultiByte is an output size in bytes (BYTE)
|
||||
*
|
||||
* Null-terminated UTF-16 strings:
|
||||
*
|
||||
* cbMultiByte *cannot* be assumed to be cchWideChar since UTF-8 is variable-width!
|
||||
*
|
||||
* Instead, obtain the required cbMultiByte output size like this:
|
||||
* cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) lpWideCharStr, -1, nullptr, 0, nullptr,
|
||||
* nullptr);
|
||||
*
|
||||
* A value of -1 for cbMultiByte indicates that the input string is null-terminated,
|
||||
* and the null terminator *will* be processed. The size returned by WideCharToMultiByte
|
||||
* will therefore include the null terminator. Equivalent behavior can be obtained by
|
||||
* computing the length in bytes of the input buffer, including the null terminator:
|
||||
*
|
||||
* cchWideChar = _wcslen((WCHAR*) lpWideCharStr) + 1;
|
||||
*
|
||||
* An output buffer of the proper size can then be allocated:
|
||||
* lpMultiByteStr = (LPSTR) malloc(cbMultiByte);
|
||||
*
|
||||
* Since cbMultiByte is an output size in bytes, it is the same as the buffer size
|
||||
*
|
||||
* Finally, perform the conversion:
|
||||
*
|
||||
* cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) lpWideCharStr, -1, lpMultiByteStr,
|
||||
* cbMultiByte, nullptr, nullptr);
|
||||
*
|
||||
* The value returned by WideCharToMultiByte corresponds to the number of bytes written
|
||||
* to the output buffer, and should match the value obtained on the first call to
|
||||
* WideCharToMultiByte.
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(WITH_WINPR_DEPRECATED)
|
||||
static
|
||||
#endif
|
||||
int
|
||||
WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
|
||||
LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
|
||||
LPBOOL lpUsedDefaultChar)
|
||||
{
|
||||
return int_WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr,
|
||||
cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ConvertToUnicode is a convenience wrapper for MultiByteToWideChar:
|
||||
*
|
||||
* If the lpWideCharStr parameter for the converted string points to nullptr
|
||||
* or if the cchWideChar parameter is set to 0 this function will automatically
|
||||
* allocate the required memory which is guaranteed to be null-terminated
|
||||
* after the conversion, even if the source c string isn't.
|
||||
*
|
||||
* If the cbMultiByte parameter is set to -1 the passed lpMultiByteStr must
|
||||
* be null-terminated and the required length for the converted string will be
|
||||
* calculated accordingly.
|
||||
*/
|
||||
#if defined(WITH_WINPR_DEPRECATED)
|
||||
int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
|
||||
LPWSTR* lpWideCharStr, int cchWideChar)
|
||||
{
|
||||
int status = 0;
|
||||
BOOL allocate = FALSE;
|
||||
|
||||
if (!lpMultiByteStr)
|
||||
return 0;
|
||||
|
||||
if (!lpWideCharStr)
|
||||
return 0;
|
||||
|
||||
if (cbMultiByte == -1)
|
||||
{
|
||||
size_t len = strnlen(lpMultiByteStr, INT_MAX);
|
||||
if (len >= INT_MAX)
|
||||
return 0;
|
||||
cbMultiByte = (int)(len + 1);
|
||||
}
|
||||
|
||||
if (cchWideChar == 0)
|
||||
{
|
||||
cchWideChar =
|
||||
MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, nullptr, 0);
|
||||
allocate = TRUE;
|
||||
}
|
||||
else if (!(*lpWideCharStr))
|
||||
allocate = TRUE;
|
||||
|
||||
if (cchWideChar < 1)
|
||||
return 0;
|
||||
|
||||
if (allocate)
|
||||
{
|
||||
*lpWideCharStr = (LPWSTR)calloc((size_t)cchWideChar + 1ull, sizeof(WCHAR));
|
||||
|
||||
if (!(*lpWideCharStr))
|
||||
{
|
||||
// SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
status = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, *lpWideCharStr,
|
||||
cchWideChar);
|
||||
|
||||
if (status != cchWideChar)
|
||||
{
|
||||
if (allocate)
|
||||
{
|
||||
free(*lpWideCharStr);
|
||||
*lpWideCharStr = nullptr;
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ConvertFromUnicode is a convenience wrapper for WideCharToMultiByte:
|
||||
*
|
||||
* If the lpMultiByteStr parameter for the converted string points to nullptr
|
||||
* or if the cbMultiByte parameter is set to 0 this function will automatically
|
||||
* allocate the required memory which is guaranteed to be null-terminated
|
||||
* after the conversion, even if the source unicode string isn't.
|
||||
*
|
||||
* If the cchWideChar parameter is set to -1 the passed lpWideCharStr must
|
||||
* be null-terminated and the required length for the converted string will be
|
||||
* calculated accordingly.
|
||||
*/
|
||||
#if defined(WITH_WINPR_DEPRECATED)
|
||||
int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
|
||||
LPSTR* lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
|
||||
LPBOOL lpUsedDefaultChar)
|
||||
{
|
||||
int status = 0;
|
||||
BOOL allocate = FALSE;
|
||||
|
||||
if (!lpWideCharStr)
|
||||
return 0;
|
||||
|
||||
if (!lpMultiByteStr)
|
||||
return 0;
|
||||
|
||||
if (cchWideChar == -1)
|
||||
cchWideChar = (int)(_wcslen(lpWideCharStr) + 1);
|
||||
|
||||
if (cbMultiByte == 0)
|
||||
{
|
||||
cbMultiByte = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, nullptr, 0,
|
||||
nullptr, nullptr);
|
||||
allocate = TRUE;
|
||||
}
|
||||
else if (!(*lpMultiByteStr))
|
||||
allocate = TRUE;
|
||||
|
||||
if (cbMultiByte < 1)
|
||||
return 0;
|
||||
|
||||
if (allocate)
|
||||
{
|
||||
*lpMultiByteStr = (LPSTR)calloc(1, (size_t)cbMultiByte + 1ull);
|
||||
|
||||
if (!(*lpMultiByteStr))
|
||||
{
|
||||
// SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
status = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, *lpMultiByteStr,
|
||||
cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
|
||||
|
||||
if ((status != cbMultiByte) && allocate)
|
||||
{
|
||||
status = 0;
|
||||
}
|
||||
|
||||
if ((status <= 0) && allocate)
|
||||
{
|
||||
free(*lpMultiByteStr);
|
||||
*lpMultiByteStr = nullptr;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Swap Unicode byte order (UTF16LE <-> UTF16BE)
|
||||
*/
|
||||
|
||||
const WCHAR* ByteSwapUnicode(WCHAR* wstr, size_t length)
|
||||
{
|
||||
WINPR_ASSERT(wstr || (length == 0));
|
||||
|
||||
for (size_t x = 0; x < length; x++)
|
||||
wstr[x] = _byteswap_ushort(wstr[x]);
|
||||
return wstr;
|
||||
}
|
||||
|
||||
SSIZE_T ConvertWCharToUtf8(const WCHAR* wstr, char* str, size_t len)
|
||||
{
|
||||
if (!wstr)
|
||||
{
|
||||
if (str && len)
|
||||
str[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t wlen = _wcslen(wstr);
|
||||
return ConvertWCharNToUtf8(wstr, wlen + 1, str, len);
|
||||
}
|
||||
|
||||
SSIZE_T ConvertWCharNToUtf8(const WCHAR* wstr, size_t wlen, char* str, size_t len)
|
||||
{
|
||||
BOOL isNullTerminated = FALSE;
|
||||
if (wlen == 0)
|
||||
return 0;
|
||||
|
||||
WINPR_ASSERT(wstr);
|
||||
size_t iwlen = _wcsnlen(wstr, wlen);
|
||||
|
||||
if ((len > INT32_MAX) || (wlen > INT32_MAX))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iwlen < wlen)
|
||||
{
|
||||
isNullTerminated = TRUE;
|
||||
iwlen++;
|
||||
}
|
||||
const int rc =
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr, (int)iwlen, str, (int)len, nullptr, nullptr);
|
||||
if ((rc <= 0) || ((len > 0) && ((size_t)rc > len)))
|
||||
return -1;
|
||||
else if (!isNullTerminated)
|
||||
{
|
||||
if (str && ((size_t)rc < len))
|
||||
str[rc] = '\0';
|
||||
return rc;
|
||||
}
|
||||
else if ((size_t)rc == len)
|
||||
{
|
||||
if (str && (str[rc - 1] != '\0'))
|
||||
return rc;
|
||||
}
|
||||
return rc - 1;
|
||||
}
|
||||
|
||||
SSIZE_T ConvertMszWCharNToUtf8(const WCHAR* wstr, size_t wlen, char* str, size_t len)
|
||||
{
|
||||
if (wlen == 0)
|
||||
return 0;
|
||||
|
||||
WINPR_ASSERT(wstr);
|
||||
|
||||
if ((len > INT32_MAX) || (wlen > INT32_MAX))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int iwlen = (int)len;
|
||||
const int rc = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)wlen, str, iwlen, nullptr, nullptr);
|
||||
if ((rc <= 0) || ((len > 0) && (rc > iwlen)))
|
||||
return -1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
SSIZE_T ConvertUtf8ToWChar(const char* str, WCHAR* wstr, size_t wlen)
|
||||
{
|
||||
if (!str)
|
||||
{
|
||||
if (wstr && wlen)
|
||||
wstr[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t len = strlen(str);
|
||||
return ConvertUtf8NToWChar(str, len + 1, wstr, wlen);
|
||||
}
|
||||
|
||||
SSIZE_T ConvertUtf8NToWChar(const char* str, size_t len, WCHAR* wstr, size_t wlen)
|
||||
{
|
||||
size_t ilen = strnlen(str, len);
|
||||
BOOL isNullTerminated = FALSE;
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
WINPR_ASSERT(str);
|
||||
|
||||
if ((len > INT32_MAX) || (wlen > INT32_MAX))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return -1;
|
||||
}
|
||||
if (ilen < len)
|
||||
{
|
||||
isNullTerminated = TRUE;
|
||||
ilen++;
|
||||
}
|
||||
|
||||
const int iwlen = (int)wlen;
|
||||
const int rc = MultiByteToWideChar(CP_UTF8, 0, str, (int)ilen, wstr, iwlen);
|
||||
if ((rc <= 0) || ((wlen > 0) && (rc > iwlen)))
|
||||
return -1;
|
||||
if (!isNullTerminated)
|
||||
{
|
||||
if (wstr && (rc < iwlen))
|
||||
wstr[rc] = '\0';
|
||||
return rc;
|
||||
}
|
||||
else if (rc == iwlen)
|
||||
{
|
||||
if (wstr && (wstr[rc - 1] != '\0'))
|
||||
return rc;
|
||||
}
|
||||
return rc - 1;
|
||||
}
|
||||
|
||||
SSIZE_T ConvertMszUtf8NToWChar(const char* str, size_t len, WCHAR* wstr, size_t wlen)
|
||||
{
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
WINPR_ASSERT(str);
|
||||
|
||||
if ((len > INT32_MAX) || (wlen > INT32_MAX))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int iwlen = (int)wlen;
|
||||
const int rc = MultiByteToWideChar(CP_UTF8, 0, str, (int)len, wstr, iwlen);
|
||||
if ((rc <= 0) || ((wlen > 0) && (rc > iwlen)))
|
||||
return -1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
char* ConvertWCharToUtf8Alloc(const WCHAR* wstr, size_t* pUtfCharLength)
|
||||
{
|
||||
char* tmp = nullptr;
|
||||
const SSIZE_T rc = ConvertWCharToUtf8(wstr, nullptr, 0);
|
||||
if (pUtfCharLength)
|
||||
*pUtfCharLength = 0;
|
||||
if (rc < 0)
|
||||
return nullptr;
|
||||
tmp = calloc((size_t)rc + 1ull, sizeof(char));
|
||||
if (!tmp)
|
||||
return nullptr;
|
||||
const SSIZE_T rc2 = ConvertWCharToUtf8(wstr, tmp, (size_t)rc + 1ull);
|
||||
if (rc2 < 0)
|
||||
{
|
||||
free(tmp);
|
||||
return nullptr;
|
||||
}
|
||||
WINPR_ASSERT(rc == rc2);
|
||||
if (pUtfCharLength)
|
||||
*pUtfCharLength = (size_t)rc2;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
char* ConvertWCharNToUtf8Alloc(const WCHAR* wstr, size_t wlen, size_t* pUtfCharLength)
|
||||
{
|
||||
char* tmp = nullptr;
|
||||
const SSIZE_T rc = ConvertWCharNToUtf8(wstr, wlen, nullptr, 0);
|
||||
|
||||
if (pUtfCharLength)
|
||||
*pUtfCharLength = 0;
|
||||
if (rc < 0)
|
||||
return nullptr;
|
||||
tmp = calloc((size_t)rc + 1ull, sizeof(char));
|
||||
if (!tmp)
|
||||
return nullptr;
|
||||
const SSIZE_T rc2 = ConvertWCharNToUtf8(wstr, wlen, tmp, (size_t)rc + 1ull);
|
||||
if (rc2 < 0)
|
||||
{
|
||||
free(tmp);
|
||||
return nullptr;
|
||||
}
|
||||
WINPR_ASSERT(rc == rc2);
|
||||
if (pUtfCharLength)
|
||||
*pUtfCharLength = (size_t)rc2;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
char* ConvertMszWCharNToUtf8Alloc(const WCHAR* wstr, size_t wlen, size_t* pUtfCharLength)
|
||||
{
|
||||
char* tmp = nullptr;
|
||||
const SSIZE_T rc = ConvertMszWCharNToUtf8(wstr, wlen, nullptr, 0);
|
||||
|
||||
if (pUtfCharLength)
|
||||
*pUtfCharLength = 0;
|
||||
if (rc < 0)
|
||||
return nullptr;
|
||||
tmp = calloc((size_t)rc + 1ull, sizeof(char));
|
||||
if (!tmp)
|
||||
return nullptr;
|
||||
const SSIZE_T rc2 = ConvertMszWCharNToUtf8(wstr, wlen, tmp, (size_t)rc + 1ull);
|
||||
if (rc2 < 0)
|
||||
{
|
||||
free(tmp);
|
||||
return nullptr;
|
||||
}
|
||||
WINPR_ASSERT(rc == rc2);
|
||||
if (pUtfCharLength)
|
||||
*pUtfCharLength = (size_t)rc2;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
WCHAR* ConvertUtf8ToWCharAlloc(const char* str, size_t* pSize)
|
||||
{
|
||||
WCHAR* tmp = nullptr;
|
||||
const SSIZE_T rc = ConvertUtf8ToWChar(str, nullptr, 0);
|
||||
if (pSize)
|
||||
*pSize = 0;
|
||||
if (rc < 0)
|
||||
return nullptr;
|
||||
tmp = calloc((size_t)rc + 1ull, sizeof(WCHAR));
|
||||
if (!tmp)
|
||||
return nullptr;
|
||||
const SSIZE_T rc2 = ConvertUtf8ToWChar(str, tmp, (size_t)rc + 1ull);
|
||||
if (rc2 < 0)
|
||||
{
|
||||
free(tmp);
|
||||
return nullptr;
|
||||
}
|
||||
WINPR_ASSERT(rc == rc2);
|
||||
if (pSize)
|
||||
*pSize = (size_t)rc2;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
WCHAR* ConvertUtf8NToWCharAlloc(const char* str, size_t len, size_t* pSize)
|
||||
{
|
||||
WCHAR* tmp = nullptr;
|
||||
const SSIZE_T rc = ConvertUtf8NToWChar(str, len, nullptr, 0);
|
||||
if (pSize)
|
||||
*pSize = 0;
|
||||
if (rc < 0)
|
||||
return nullptr;
|
||||
tmp = calloc((size_t)rc + 1ull, sizeof(WCHAR));
|
||||
if (!tmp)
|
||||
return nullptr;
|
||||
const SSIZE_T rc2 = ConvertUtf8NToWChar(str, len, tmp, (size_t)rc + 1ull);
|
||||
if (rc2 < 0)
|
||||
{
|
||||
free(tmp);
|
||||
return nullptr;
|
||||
}
|
||||
WINPR_ASSERT(rc == rc2);
|
||||
if (pSize)
|
||||
*pSize = (size_t)rc2;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
WCHAR* ConvertMszUtf8NToWCharAlloc(const char* str, size_t len, size_t* pSize)
|
||||
{
|
||||
WCHAR* tmp = nullptr;
|
||||
const SSIZE_T rc = ConvertMszUtf8NToWChar(str, len, nullptr, 0);
|
||||
if (pSize)
|
||||
*pSize = 0;
|
||||
if (rc < 0)
|
||||
return nullptr;
|
||||
tmp = calloc((size_t)rc + 1ull, sizeof(WCHAR));
|
||||
if (!tmp)
|
||||
return nullptr;
|
||||
const SSIZE_T rc2 = ConvertMszUtf8NToWChar(str, len, tmp, (size_t)rc + 1ull);
|
||||
if (rc2 < 0)
|
||||
{
|
||||
free(tmp);
|
||||
return nullptr;
|
||||
}
|
||||
WINPR_ASSERT(rc == rc2);
|
||||
if (pSize)
|
||||
*pSize = (size_t)rc2;
|
||||
return tmp;
|
||||
}
|
||||
32
third_party/FreeRDP/winpr/libwinpr/crt/unicode.h
vendored
Normal file
32
third_party/FreeRDP/winpr/libwinpr/crt/unicode.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Unicode Conversion (CRT)
|
||||
*
|
||||
* Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2022 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 WINPR_CRT_UNICODE_INTERNAL
|
||||
#define WINPR_CRT_UNICODE_INTERNAL
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
|
||||
LPWSTR lpWideCharStr, int cchWideChar);
|
||||
|
||||
int int_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
|
||||
LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
|
||||
LPBOOL lpUsedDefaultChar);
|
||||
#endif
|
||||
184
third_party/FreeRDP/winpr/libwinpr/crt/unicode_android.c
vendored
Normal file
184
third_party/FreeRDP/winpr/libwinpr/crt/unicode_android.c
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Unicode Conversion (CRT)
|
||||
*
|
||||
* Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2022 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/string.h>
|
||||
|
||||
#include "../utils/android.h"
|
||||
#include "unicode.h"
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (a) < (b) ? (a) : (b)
|
||||
#endif
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("unicode")
|
||||
|
||||
static int convert_int(JNIEnv* env, const void* data, size_t size, void* buffer, size_t buffersize,
|
||||
BOOL toUTF16)
|
||||
{
|
||||
WINPR_ASSERT(env);
|
||||
WINPR_ASSERT(data || (size == 0));
|
||||
WINPR_ASSERT(buffer || (buffersize == 0));
|
||||
|
||||
jstring utf8 = (*env)->NewStringUTF(env, "UTF-8");
|
||||
jstring utf16 = (*env)->NewStringUTF(env, "UTF-16LE");
|
||||
jclass stringClass = (*env)->FindClass(env, "java/lang/String");
|
||||
|
||||
if (!utf8 || !utf16 || !stringClass)
|
||||
{
|
||||
WLog_ERR(TAG, "utf8-%p, utf16=%p, stringClass=%p", utf8, utf16, stringClass);
|
||||
return -1;
|
||||
}
|
||||
|
||||
jmethodID constructorID =
|
||||
(*env)->GetMethodID(env, stringClass, "<init>", "([BLjava/lang/String;)V");
|
||||
jmethodID getBytesID =
|
||||
(*env)->GetMethodID(env, stringClass, "getBytes", "(Ljava/lang/String;)[B");
|
||||
if (!constructorID || !getBytesID)
|
||||
{
|
||||
WLog_ERR(TAG, "constructorID=%p, getBytesID=%p", constructorID, getBytesID);
|
||||
return -2;
|
||||
}
|
||||
|
||||
jbyteArray ret = (*env)->NewByteArray(env, size);
|
||||
if (!ret)
|
||||
{
|
||||
WLog_ERR(TAG, "NewByteArray(%" PRIuz ") failed", size);
|
||||
return -3;
|
||||
}
|
||||
|
||||
(*env)->SetByteArrayRegion(env, ret, 0, size, data);
|
||||
|
||||
jobject obj = (*env)->NewObject(env, stringClass, constructorID, ret, toUTF16 ? utf8 : utf16);
|
||||
if (!obj)
|
||||
{
|
||||
WLog_ERR(TAG, "NewObject(String, byteArray, UTF-%d) failed", toUTF16 ? 16 : 8);
|
||||
return -4;
|
||||
}
|
||||
|
||||
jbyteArray res = (*env)->CallObjectMethod(env, obj, getBytesID, toUTF16 ? utf16 : utf8);
|
||||
if (!res)
|
||||
{
|
||||
WLog_ERR(TAG, "CallObjectMethod(String, getBytes, UTF-%d) failed", toUTF16 ? 16 : 8);
|
||||
return -4;
|
||||
}
|
||||
|
||||
jsize rlen = (*env)->GetArrayLength(env, res);
|
||||
if (buffersize > 0)
|
||||
{
|
||||
if (rlen > buffersize)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
rlen = MIN(rlen, buffersize);
|
||||
(*env)->GetByteArrayRegion(env, res, 0, rlen, buffer);
|
||||
}
|
||||
|
||||
if (toUTF16)
|
||||
rlen /= sizeof(WCHAR);
|
||||
|
||||
return rlen;
|
||||
}
|
||||
|
||||
static int convert(const void* data, size_t size, void* buffer, size_t buffersize, BOOL toUTF16)
|
||||
{
|
||||
int rc;
|
||||
JNIEnv* env = nullptr;
|
||||
jboolean attached = winpr_jni_attach_thread(&env);
|
||||
rc = convert_int(env, data, size, buffer, buffersize, toUTF16);
|
||||
if (attached)
|
||||
winpr_jni_detach_thread();
|
||||
return rc;
|
||||
}
|
||||
|
||||
int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
|
||||
LPWSTR lpWideCharStr, int cchWideChar)
|
||||
{
|
||||
size_t cbCharLen = (size_t)cbMultiByte;
|
||||
|
||||
WINPR_UNUSED(dwFlags);
|
||||
|
||||
/* If cbMultiByte is 0, the function fails */
|
||||
if ((cbMultiByte == 0) || (cbMultiByte < -1))
|
||||
return 0;
|
||||
|
||||
if (cchWideChar < 0)
|
||||
return -1;
|
||||
|
||||
if (cbMultiByte < 0)
|
||||
{
|
||||
const size_t len = strlen(lpMultiByteStr);
|
||||
if (len >= INT32_MAX)
|
||||
return 0;
|
||||
cbCharLen = (int)len + 1;
|
||||
}
|
||||
else
|
||||
cbCharLen = cbMultiByte;
|
||||
|
||||
WINPR_ASSERT(lpMultiByteStr);
|
||||
switch (CodePage)
|
||||
{
|
||||
case CP_ACP:
|
||||
case CP_UTF8:
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Unsupported encoding %u", CodePage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return convert(lpMultiByteStr, cbCharLen, lpWideCharStr, cchWideChar * sizeof(WCHAR), TRUE);
|
||||
}
|
||||
|
||||
int int_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
|
||||
LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
|
||||
LPBOOL lpUsedDefaultChar)
|
||||
{
|
||||
size_t cbCharLen = (size_t)cchWideChar;
|
||||
|
||||
WINPR_UNUSED(dwFlags);
|
||||
/* If cchWideChar is 0, the function fails */
|
||||
if ((cchWideChar == 0) || (cchWideChar < -1))
|
||||
return 0;
|
||||
|
||||
if (cbMultiByte < 0)
|
||||
return -1;
|
||||
|
||||
WINPR_ASSERT(lpWideCharStr);
|
||||
/* If cchWideChar is -1, the string is null-terminated */
|
||||
if (cchWideChar == -1)
|
||||
{
|
||||
const size_t len = _wcslen(lpWideCharStr);
|
||||
if (len >= INT32_MAX)
|
||||
return 0;
|
||||
cbCharLen = (int)len + 1;
|
||||
}
|
||||
else
|
||||
cbCharLen = cchWideChar;
|
||||
|
||||
/*
|
||||
* if cbMultiByte is 0, the function returns the required buffer size
|
||||
* in bytes for lpMultiByteStr and makes no use of the output parameter itself.
|
||||
*/
|
||||
return convert(lpWideCharStr, cbCharLen * sizeof(WCHAR), lpMultiByteStr, cbMultiByte, FALSE);
|
||||
}
|
||||
149
third_party/FreeRDP/winpr/libwinpr/crt/unicode_apple.m
vendored
Normal file
149
third_party/FreeRDP/winpr/libwinpr/crt/unicode_apple.m
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Unicode Conversion (CRT)
|
||||
*
|
||||
* Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2022 Thincast Technologies GmbH
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/error.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include "unicode.h"
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (a) < (b) ? (a) : (b)
|
||||
#endif
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("unicode")
|
||||
|
||||
int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
|
||||
LPWSTR lpWideCharStr, int cchWideChar)
|
||||
{
|
||||
const BOOL isNullTerminated = cbMultiByte < 0;
|
||||
|
||||
/* If cbMultiByte is 0, the function fails */
|
||||
if ((cbMultiByte == 0) || (cbMultiByte < -1))
|
||||
return 0;
|
||||
|
||||
/* If cbMultiByte is -1, the string is null-terminated */
|
||||
if (isNullTerminated)
|
||||
{
|
||||
size_t len = strnlen(lpMultiByteStr, INT32_MAX);
|
||||
if (len >= INT32_MAX)
|
||||
return 0;
|
||||
cbMultiByte = (int)len + 1;
|
||||
}
|
||||
|
||||
NSString *utf = [[NSString alloc] initWithBytes:lpMultiByteStr
|
||||
length:cbMultiByte
|
||||
encoding:NSUTF8StringEncoding];
|
||||
if (!utf)
|
||||
{
|
||||
WLog_WARN(TAG, "[NSString alloc] NSUTF8StringEncoding failed [%d] '%s'", cbMultiByte,
|
||||
lpMultiByteStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const WCHAR *utf16 =
|
||||
(const WCHAR *)[utf cStringUsingEncoding:NSUTF16LittleEndianStringEncoding];
|
||||
const size_t utf16ByteLen = [utf lengthOfBytesUsingEncoding:NSUTF16LittleEndianStringEncoding];
|
||||
const size_t utf16CharLen = utf16ByteLen / sizeof(WCHAR);
|
||||
if (!utf16)
|
||||
{
|
||||
WLog_WARN(TAG, "[utf cStringUsingEncoding:NSUTF16LittleEndianStringEncoding] failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cchWideChar == 0)
|
||||
return utf16CharLen;
|
||||
else if (cchWideChar < utf16CharLen)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t mlen = MIN((size_t)utf16CharLen, cchWideChar);
|
||||
const size_t len = _wcsnlen(utf16, mlen);
|
||||
memcpy(lpWideCharStr, utf16, len * sizeof(WCHAR));
|
||||
if ((len < (size_t)cchWideChar) &&
|
||||
((len == 0) || ((len > 0) && (lpWideCharStr[len - 1] != '\0'))))
|
||||
lpWideCharStr[len] = '\0';
|
||||
return utf16CharLen;
|
||||
}
|
||||
}
|
||||
|
||||
int int_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
|
||||
LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
|
||||
LPBOOL lpUsedDefaultChar)
|
||||
{
|
||||
const BOOL isNullTerminated = cchWideChar < 0;
|
||||
|
||||
/* If cchWideChar is 0, the function fails */
|
||||
if ((cchWideChar == 0) || (cchWideChar < -1))
|
||||
return 0;
|
||||
|
||||
/* If cchWideChar is -1, the string is null-terminated */
|
||||
if (isNullTerminated)
|
||||
{
|
||||
size_t len = _wcslen(lpWideCharStr);
|
||||
if (len >= INT32_MAX)
|
||||
return 0;
|
||||
cchWideChar = (int)len + 1;
|
||||
}
|
||||
|
||||
NSString *utf = [[NSString alloc] initWithCharacters:lpWideCharStr length:cchWideChar];
|
||||
if (!utf)
|
||||
{
|
||||
WLog_WARN(TAG, "[NSString alloc] initWithCharacters failed [%d] 'XXX'", cchWideChar);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *utf8 = [utf cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
const size_t utf8Len = [utf lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
if (!utf8)
|
||||
{
|
||||
WLog_WARN(TAG, "[utf cStringUsingEncoding:NSUTF8StringEncoding] failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cbMultiByte == 0)
|
||||
return utf8Len;
|
||||
else if (cbMultiByte < utf8Len)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t mlen = MIN((size_t)cbMultiByte, utf8Len);
|
||||
const size_t len = strnlen(utf8, mlen);
|
||||
memcpy(lpMultiByteStr, utf8, len * sizeof(char));
|
||||
if ((len < (size_t)cbMultiByte) && (len > 0) && (lpMultiByteStr[len - 1] != '\0'))
|
||||
lpMultiByteStr[len] = '\0';
|
||||
return utf8Len;
|
||||
}
|
||||
}
|
||||
729
third_party/FreeRDP/winpr/libwinpr/crt/unicode_builtin.c
vendored
Normal file
729
third_party/FreeRDP/winpr/libwinpr/crt/unicode_builtin.c
vendored
Normal file
@@ -0,0 +1,729 @@
|
||||
/*
|
||||
* Copyright 2001-2004 Unicode, Inc.
|
||||
*
|
||||
* Disclaimer
|
||||
*
|
||||
* This source code is provided as is by Unicode, Inc. No claims are
|
||||
* made as to fitness for any particular purpose. No warranties of any
|
||||
* kind are expressed or implied. The recipient agrees to determine
|
||||
* applicability of information provided. If this file has been
|
||||
* purchased on magnetic or optical media from Unicode, Inc., the
|
||||
* sole remedy for any claim will be exchange of defective media
|
||||
* within 90 days of receipt.
|
||||
*
|
||||
* Limitations on Rights to Redistribute This Code
|
||||
*
|
||||
* Unicode, Inc. hereby grants the right to freely use the information
|
||||
* supplied in this file in the creation of products supporting the
|
||||
* Unicode Standard, and to make copies of this file in any form
|
||||
* for internal or external distribution as long as this notice
|
||||
* remains attached.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Conversions between UTF32, UTF-16, and UTF-8. Source code file.
|
||||
Author: Mark E. Davis, 1994.
|
||||
Rev History: Rick McGowan, fixes & updates May 2001.
|
||||
Sept 2001: fixed const & error conditions per
|
||||
mods suggested by S. Parent & A. Lillich.
|
||||
June 2002: Tim Dodd added detection and handling of incomplete
|
||||
source sequences, enhanced error detection, added casts
|
||||
to eliminate compiler warnings.
|
||||
July 2003: slight mods to back out aggressive FFFE detection.
|
||||
Jan 2004: updated switches in from-UTF8 conversions.
|
||||
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
|
||||
|
||||
See the header file "utf.h" for complete documentation.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
|
||||
#include "unicode.h"
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("unicode")
|
||||
|
||||
/*
|
||||
* Character Types:
|
||||
*
|
||||
* UTF8: uint8_t 8 bits
|
||||
* UTF16: uint16_t 16 bits
|
||||
* UTF32: uint32_t 32 bits
|
||||
*/
|
||||
|
||||
/* Some fundamental constants */
|
||||
#define UNI_REPLACEMENT_CHAR (uint32_t)0x0000FFFD
|
||||
#define UNI_MAX_BMP (uint32_t)0x0000FFFF
|
||||
#define UNI_MAX_UTF16 (uint32_t)0x0010FFFF
|
||||
#define UNI_MAX_UTF32 (uint32_t)0x7FFFFFFF
|
||||
#define UNI_MAX_LEGAL_UTF32 (uint32_t)0x0010FFFF
|
||||
|
||||
typedef enum
|
||||
{
|
||||
conversionOK, /* conversion successful */
|
||||
sourceExhausted, /* partial character in source, but hit end */
|
||||
targetExhausted, /* insuff. room in target for conversion */
|
||||
sourceIllegal /* source sequence is illegal/malformed */
|
||||
} ConversionResult;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
strictConversion = 0,
|
||||
lenientConversion
|
||||
} ConversionFlags;
|
||||
|
||||
static const int halfShift = 10; /* used for shifting by 10 bits */
|
||||
|
||||
static const uint32_t halfBase = 0x0010000UL;
|
||||
static const uint32_t halfMask = 0x3FFUL;
|
||||
|
||||
#define UNI_SUR_HIGH_START (uint32_t)0xD800
|
||||
#define UNI_SUR_HIGH_END (uint32_t)0xDBFF
|
||||
#define UNI_SUR_LOW_START (uint32_t)0xDC00
|
||||
#define UNI_SUR_LOW_END (uint32_t)0xDFFF
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Index into the table below with the first byte of a UTF-8 sequence to
|
||||
* get the number of trailing bytes that are supposed to follow it.
|
||||
* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
|
||||
* left as-is for anyone who may want to do such conversion, which was
|
||||
* allowed in earlier algorithms.
|
||||
*/
|
||||
static const char trailingBytesForUTF8[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
|
||||
};
|
||||
|
||||
/*
|
||||
* Magic values subtracted from a buffer value during UTF8 conversion.
|
||||
* This table contains as many values as there might be trailing bytes
|
||||
* in a UTF-8 sequence.
|
||||
*/
|
||||
static const uint32_t offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
|
||||
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
|
||||
|
||||
/*
|
||||
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
|
||||
* into the first byte, depending on how many bytes follow. There are
|
||||
* as many entries in this table as there are UTF-8 sequence types.
|
||||
* (I.e., one byte sequence, two byte... etc.). Remember that sequence
|
||||
* for *legal* UTF-8 will be 4 or fewer bytes total.
|
||||
*/
|
||||
static const uint8_t firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||
|
||||
/* We always need UTF-16LE, even on big endian systems! */
|
||||
static WCHAR setWcharFrom(WCHAR w)
|
||||
{
|
||||
#if defined(__BIG_ENDIAN__)
|
||||
union
|
||||
{
|
||||
WCHAR w;
|
||||
char c[2];
|
||||
} cnv;
|
||||
|
||||
cnv.w = w;
|
||||
const char c = cnv.c[0];
|
||||
cnv.c[0] = cnv.c[1];
|
||||
cnv.c[1] = c;
|
||||
return cnv.w;
|
||||
#else
|
||||
return w;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* The interface converts a whole buffer to avoid function-call overhead.
|
||||
* Constants have been gathered. Loops & conditionals have been removed as
|
||||
* much as possible for efficiency, in favor of drop-through switches.
|
||||
* (See "Note A" at the bottom of the file for equivalent code.)
|
||||
* If your compiler supports it, the "isLegalUTF8" call can be turned
|
||||
* into an inline function.
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static ConversionResult winpr_ConvertUTF16toUTF8_Internal(const uint16_t** sourceStart,
|
||||
const uint16_t* sourceEnd,
|
||||
uint8_t** targetStart,
|
||||
const uint8_t* targetEnd,
|
||||
ConversionFlags flags)
|
||||
{
|
||||
bool computeLength = (!targetEnd) ? true : false;
|
||||
const uint16_t* source = *sourceStart;
|
||||
uint8_t* target = *targetStart;
|
||||
ConversionResult result = conversionOK;
|
||||
|
||||
while (source < sourceEnd)
|
||||
{
|
||||
uint32_t ch = 0;
|
||||
unsigned short bytesToWrite = 0;
|
||||
const uint32_t byteMask = 0xBF;
|
||||
const uint32_t byteMark = 0x80;
|
||||
const uint16_t* oldSource =
|
||||
source; /* In case we have to back up because of target overflow. */
|
||||
|
||||
ch = setWcharFrom(*source++);
|
||||
|
||||
/* If we have a surrogate pair, convert to UTF32 first. */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END)
|
||||
{
|
||||
/* If the 16 bits following the high surrogate are in the source buffer... */
|
||||
if (source < sourceEnd)
|
||||
{
|
||||
uint32_t ch2 = setWcharFrom(*source);
|
||||
|
||||
/* If it's a low surrogate, convert to UTF32. */
|
||||
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END)
|
||||
{
|
||||
ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) +
|
||||
halfBase;
|
||||
++source;
|
||||
}
|
||||
else if (flags == strictConversion)
|
||||
{
|
||||
/* it's an unpaired high surrogate */
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We don't have the 16 bits following the high surrogate. */
|
||||
--source; /* return to the high surrogate */
|
||||
result = sourceExhausted;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (flags == strictConversion)
|
||||
{
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)
|
||||
{
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Figure out how many bytes the result will require */
|
||||
if (ch < (uint32_t)0x80)
|
||||
{
|
||||
bytesToWrite = 1;
|
||||
}
|
||||
else if (ch < (uint32_t)0x800)
|
||||
{
|
||||
bytesToWrite = 2;
|
||||
}
|
||||
else if (ch < (uint32_t)0x10000)
|
||||
{
|
||||
bytesToWrite = 3;
|
||||
}
|
||||
else if (ch < (uint32_t)0x110000)
|
||||
{
|
||||
bytesToWrite = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesToWrite = 3;
|
||||
ch = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
|
||||
target += bytesToWrite;
|
||||
|
||||
if ((target > targetEnd) && (!computeLength))
|
||||
{
|
||||
source = oldSource; /* Back up source pointer! */
|
||||
target -= bytesToWrite;
|
||||
result = targetExhausted;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!computeLength)
|
||||
{
|
||||
switch (bytesToWrite)
|
||||
{
|
||||
/* note: everything falls through. */
|
||||
case 4:
|
||||
*--target = (uint8_t)((ch | byteMark) & byteMask);
|
||||
ch >>= 6;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
case 3:
|
||||
*--target = (uint8_t)((ch | byteMark) & byteMask);
|
||||
ch >>= 6;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 2:
|
||||
*--target = (uint8_t)((ch | byteMark) & byteMask);
|
||||
ch >>= 6;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 1:
|
||||
*--target = (uint8_t)(ch | firstByteMark[bytesToWrite]);
|
||||
break;
|
||||
default:
|
||||
return sourceIllegal;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (bytesToWrite)
|
||||
{
|
||||
/* note: everything falls through. */
|
||||
case 4:
|
||||
--target;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 3:
|
||||
--target;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 2:
|
||||
--target;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 1:
|
||||
--target;
|
||||
break;
|
||||
default:
|
||||
return sourceIllegal;
|
||||
}
|
||||
}
|
||||
|
||||
target += bytesToWrite;
|
||||
}
|
||||
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
|
||||
* This must be called with the length pre-determined by the first byte.
|
||||
* If not calling this from ConvertUTF8to*, then the length can be set by:
|
||||
* length = trailingBytesForUTF8[*source]+1;
|
||||
* and the sequence is illegal right away if there aren't that many bytes
|
||||
* available.
|
||||
* If presented with a length > 4, this returns false. The Unicode
|
||||
* definition of UTF-8 goes up to 4-byte sequences.
|
||||
*/
|
||||
|
||||
static bool isLegalUTF8(const uint8_t* source, int length)
|
||||
{
|
||||
uint8_t a = 0;
|
||||
const uint8_t* srcptr = source + length;
|
||||
|
||||
switch (length)
|
||||
{
|
||||
default:
|
||||
return false;
|
||||
|
||||
/* Everything else falls through when "true"... */
|
||||
case 4:
|
||||
if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
|
||||
return false;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 3:
|
||||
if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
|
||||
return false;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 2:
|
||||
if ((a = (*--srcptr)) > 0xBF)
|
||||
return false;
|
||||
|
||||
switch (*source)
|
||||
{
|
||||
/* no fall-through in this inner switch */
|
||||
case 0xE0:
|
||||
if (a < 0xA0)
|
||||
return false;
|
||||
|
||||
break;
|
||||
|
||||
case 0xED:
|
||||
if (a > 0x9F)
|
||||
return false;
|
||||
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
if (a < 0x90)
|
||||
return false;
|
||||
|
||||
break;
|
||||
|
||||
case 0xF4:
|
||||
if (a > 0x8F)
|
||||
return false;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (a < 0x80)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 1:
|
||||
if (*source >= 0x80 && *source < 0xC2)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*source > 0xF4)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static ConversionResult winpr_ConvertUTF8toUTF16_Internal(const uint8_t** sourceStart,
|
||||
const uint8_t* sourceEnd,
|
||||
uint16_t** targetStart,
|
||||
const uint16_t* targetEnd,
|
||||
ConversionFlags flags)
|
||||
{
|
||||
bool computeLength = (!targetEnd) ? true : false;
|
||||
ConversionResult result = conversionOK;
|
||||
const uint8_t* source = *sourceStart;
|
||||
uint16_t* target = *targetStart;
|
||||
|
||||
while (source < sourceEnd)
|
||||
{
|
||||
uint32_t ch = 0;
|
||||
unsigned short extraBytesToRead =
|
||||
WINPR_ASSERTING_INT_CAST(unsigned short, trailingBytesForUTF8[*source]);
|
||||
|
||||
if ((source + extraBytesToRead) >= sourceEnd)
|
||||
{
|
||||
result = sourceExhausted;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Do this check whether lenient or strict */
|
||||
if (!isLegalUTF8(source, extraBytesToRead + 1))
|
||||
{
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The cases all fall through. See "Note A" below.
|
||||
*/
|
||||
switch (extraBytesToRead)
|
||||
{
|
||||
case 5:
|
||||
ch += *source++;
|
||||
ch <<= 6; /* remember, illegal UTF-8 */
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 4:
|
||||
ch += *source++;
|
||||
ch <<= 6; /* remember, illegal UTF-8 */
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 3:
|
||||
ch += *source++;
|
||||
ch <<= 6;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 2:
|
||||
ch += *source++;
|
||||
ch <<= 6;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 1:
|
||||
ch += *source++;
|
||||
ch <<= 6;
|
||||
/* fallthrough */
|
||||
WINPR_FALLTHROUGH
|
||||
|
||||
case 0:
|
||||
ch += *source++;
|
||||
break;
|
||||
default:
|
||||
return sourceIllegal;
|
||||
}
|
||||
|
||||
ch -= offsetsFromUTF8[extraBytesToRead];
|
||||
|
||||
if ((target >= targetEnd) && (!computeLength))
|
||||
{
|
||||
source -= (extraBytesToRead + 1); /* Back up source pointer! */
|
||||
result = targetExhausted;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch <= UNI_MAX_BMP)
|
||||
{
|
||||
/* Target is a character <= 0xFFFF */
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
|
||||
{
|
||||
if (flags == strictConversion)
|
||||
{
|
||||
source -= (extraBytesToRead + 1); /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!computeLength)
|
||||
*target++ = setWcharFrom(UNI_REPLACEMENT_CHAR);
|
||||
else
|
||||
target++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!computeLength)
|
||||
*target++ = setWcharFrom((WCHAR)ch); /* normal case */
|
||||
else
|
||||
target++;
|
||||
}
|
||||
}
|
||||
else if (ch > UNI_MAX_UTF16)
|
||||
{
|
||||
if (flags == strictConversion)
|
||||
{
|
||||
result = sourceIllegal;
|
||||
source -= (extraBytesToRead + 1); /* return to the start */
|
||||
break; /* Bail out; shouldn't continue */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!computeLength)
|
||||
*target++ = setWcharFrom(UNI_REPLACEMENT_CHAR);
|
||||
else
|
||||
target++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* target is a character in range 0xFFFF - 0x10FFFF. */
|
||||
if ((target + 1 >= targetEnd) && (!computeLength))
|
||||
{
|
||||
source -= (extraBytesToRead + 1); /* Back up source pointer! */
|
||||
result = targetExhausted;
|
||||
break;
|
||||
}
|
||||
|
||||
ch -= halfBase;
|
||||
|
||||
if (!computeLength)
|
||||
{
|
||||
*target++ = setWcharFrom((WCHAR)((ch >> halfShift) + UNI_SUR_HIGH_START));
|
||||
*target++ = setWcharFrom((WCHAR)((ch & halfMask) + UNI_SUR_LOW_START));
|
||||
}
|
||||
else
|
||||
{
|
||||
target++;
|
||||
target++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* WinPR built-in Unicode API
|
||||
*/
|
||||
|
||||
static int winpr_ConvertUTF8toUTF16(const uint8_t* src, int cchSrc, uint16_t* dst, int cchDst)
|
||||
{
|
||||
size_t length = 0;
|
||||
uint16_t* dstBeg = nullptr;
|
||||
uint16_t* dstEnd = nullptr;
|
||||
const uint8_t* srcBeg = nullptr;
|
||||
const uint8_t* srcEnd = nullptr;
|
||||
ConversionResult result = sourceIllegal;
|
||||
|
||||
if (cchSrc == -1)
|
||||
cchSrc = (int)strnlen((const char*)src, INT32_MAX - 1) + 1;
|
||||
|
||||
srcBeg = src;
|
||||
srcEnd = &src[cchSrc];
|
||||
|
||||
if (cchDst == 0)
|
||||
{
|
||||
result =
|
||||
winpr_ConvertUTF8toUTF16_Internal(&srcBeg, srcEnd, &dstBeg, dstEnd, strictConversion);
|
||||
|
||||
length = dstBeg - (uint16_t*)nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
dstBeg = dst;
|
||||
dstEnd = &dst[cchDst];
|
||||
|
||||
result =
|
||||
winpr_ConvertUTF8toUTF16_Internal(&srcBeg, srcEnd, &dstBeg, dstEnd, strictConversion);
|
||||
|
||||
length = dstBeg - dst;
|
||||
}
|
||||
|
||||
if (result == targetExhausted)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (result == conversionOK) ? WINPR_ASSERTING_INT_CAST(int, length) : 0;
|
||||
}
|
||||
|
||||
static int winpr_ConvertUTF16toUTF8(const uint16_t* src, int cchSrc, uint8_t* dst, int cchDst)
|
||||
{
|
||||
size_t length = 0;
|
||||
uint8_t* dstBeg = nullptr;
|
||||
uint8_t* dstEnd = nullptr;
|
||||
const uint16_t* srcBeg = nullptr;
|
||||
const uint16_t* srcEnd = nullptr;
|
||||
ConversionResult result = sourceIllegal;
|
||||
|
||||
if (cchSrc == -1)
|
||||
cchSrc = (int)_wcsnlen((const WCHAR*)src, INT32_MAX - 1) + 1;
|
||||
|
||||
srcBeg = src;
|
||||
srcEnd = &src[cchSrc];
|
||||
|
||||
if (cchDst == 0)
|
||||
{
|
||||
result =
|
||||
winpr_ConvertUTF16toUTF8_Internal(&srcBeg, srcEnd, &dstBeg, dstEnd, strictConversion);
|
||||
|
||||
length = dstBeg - ((uint8_t*)nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
dstBeg = dst;
|
||||
dstEnd = &dst[cchDst];
|
||||
|
||||
result =
|
||||
winpr_ConvertUTF16toUTF8_Internal(&srcBeg, srcEnd, &dstBeg, dstEnd, strictConversion);
|
||||
|
||||
length = dstBeg - dst;
|
||||
}
|
||||
|
||||
if (result == targetExhausted)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (result == conversionOK) ? WINPR_ASSERTING_INT_CAST(int, length) : 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
|
||||
LPWSTR lpWideCharStr, int cchWideChar)
|
||||
{
|
||||
size_t cbCharLen = (size_t)cbMultiByte;
|
||||
|
||||
WINPR_UNUSED(dwFlags);
|
||||
|
||||
/* If cbMultiByte is 0, the function fails */
|
||||
if ((cbMultiByte == 0) || (cbMultiByte < -1))
|
||||
return 0;
|
||||
|
||||
if (cchWideChar < 0)
|
||||
return -1;
|
||||
|
||||
if (cbMultiByte < 0)
|
||||
{
|
||||
const size_t len = strlen(lpMultiByteStr);
|
||||
if (len >= INT32_MAX)
|
||||
return 0;
|
||||
cbCharLen = (int)len + 1;
|
||||
}
|
||||
else
|
||||
cbCharLen = cbMultiByte;
|
||||
|
||||
WINPR_ASSERT(lpMultiByteStr);
|
||||
switch (CodePage)
|
||||
{
|
||||
case CP_ACP:
|
||||
case CP_UTF8:
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Unsupported encoding %u", CodePage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return winpr_ConvertUTF8toUTF16((const uint8_t*)lpMultiByteStr,
|
||||
WINPR_ASSERTING_INT_CAST(int, cbCharLen),
|
||||
(uint16_t*)lpWideCharStr, cchWideChar);
|
||||
}
|
||||
|
||||
int int_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
|
||||
LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
|
||||
LPBOOL lpUsedDefaultChar)
|
||||
{
|
||||
size_t cbCharLen = (size_t)cchWideChar;
|
||||
|
||||
WINPR_UNUSED(dwFlags);
|
||||
/* If cchWideChar is 0, the function fails */
|
||||
if ((cchWideChar == 0) || (cchWideChar < -1))
|
||||
return 0;
|
||||
|
||||
if (cbMultiByte < 0)
|
||||
return -1;
|
||||
|
||||
WINPR_ASSERT(lpWideCharStr);
|
||||
/* If cchWideChar is -1, the string is null-terminated */
|
||||
if (cchWideChar == -1)
|
||||
{
|
||||
const size_t len = _wcslen(lpWideCharStr);
|
||||
if (len >= INT32_MAX)
|
||||
return 0;
|
||||
cbCharLen = (int)len + 1;
|
||||
}
|
||||
else
|
||||
cbCharLen = cchWideChar;
|
||||
|
||||
/*
|
||||
* if cbMultiByte is 0, the function returns the required buffer size
|
||||
* in bytes for lpMultiByteStr and makes no use of the output parameter itself.
|
||||
*/
|
||||
|
||||
return winpr_ConvertUTF16toUTF8((const uint16_t*)lpWideCharStr,
|
||||
WINPR_ASSERTING_INT_CAST(int, cbCharLen),
|
||||
(uint8_t*)lpMultiByteStr, cbMultiByte);
|
||||
}
|
||||
234
third_party/FreeRDP/winpr/libwinpr/crt/unicode_icu.c
vendored
Normal file
234
third_party/FreeRDP/winpr/libwinpr/crt/unicode_icu.c
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Unicode Conversion (CRT)
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2022 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/error.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <unicode/ucnv.h>
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
#include "unicode.h"
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("unicode")
|
||||
|
||||
#define UCNV_CONVERT 1
|
||||
|
||||
int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
|
||||
LPWSTR lpWideCharStr, int cchWideChar)
|
||||
{
|
||||
const BOOL isNullTerminated = cbMultiByte < 0;
|
||||
|
||||
WINPR_UNUSED(dwFlags);
|
||||
|
||||
/* If cbMultiByte is 0, the function fails */
|
||||
|
||||
if ((cbMultiByte == 0) || (cbMultiByte < -1))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
if (isNullTerminated)
|
||||
len = strlen(lpMultiByteStr) + 1;
|
||||
else
|
||||
len = WINPR_ASSERTING_INT_CAST(size_t, cbMultiByte);
|
||||
|
||||
if (len >= INT_MAX)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
cbMultiByte = WINPR_ASSERTING_INT_CAST(int, len);
|
||||
|
||||
/*
|
||||
* if cchWideChar is 0, the function returns the required buffer size
|
||||
* in characters for lpWideCharStr and makes no use of the output parameter itself.
|
||||
*/
|
||||
{
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
int32_t targetLength = -1;
|
||||
|
||||
switch (CodePage)
|
||||
{
|
||||
case CP_ACP:
|
||||
case CP_UTF8:
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Unsupported encoding %u", CodePage);
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int32_t targetCapacity = cchWideChar;
|
||||
#if defined(UCNV_CONVERT)
|
||||
char* targetStart = (char*)lpWideCharStr;
|
||||
targetLength =
|
||||
ucnv_convert("UTF-16LE", "UTF-8", targetStart, targetCapacity * (int32_t)sizeof(WCHAR),
|
||||
lpMultiByteStr, cbMultiByte, &error);
|
||||
if (targetLength > 0)
|
||||
targetLength /= sizeof(WCHAR);
|
||||
#else
|
||||
WCHAR* targetStart = lpWideCharStr;
|
||||
u_strFromUTF8(targetStart, targetCapacity, &targetLength, lpMultiByteStr, cbMultiByte,
|
||||
&error);
|
||||
#endif
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case U_BUFFER_OVERFLOW_ERROR:
|
||||
if (targetCapacity > 0)
|
||||
{
|
||||
cchWideChar = 0;
|
||||
WLog_ERR(TAG, "insufficient buffer supplied, got %d, required %d",
|
||||
targetCapacity, targetLength);
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
else
|
||||
cchWideChar = targetLength;
|
||||
break;
|
||||
case U_STRING_NOT_TERMINATED_WARNING:
|
||||
cchWideChar = targetLength;
|
||||
break;
|
||||
case U_ZERO_ERROR:
|
||||
cchWideChar = targetLength;
|
||||
break;
|
||||
default:
|
||||
WLog_WARN(TAG, "unexpected ICU error code %s [0x%08" PRIx32 "]", u_errorName(error),
|
||||
WINPR_CXX_COMPAT_CAST(unsigned, error));
|
||||
if (U_FAILURE(error))
|
||||
{
|
||||
WLog_ERR(TAG, "unexpected ICU error code %s [0x%08" PRIx32 "] is fatal",
|
||||
u_errorName(error), WINPR_CXX_COMPAT_CAST(unsigned, error));
|
||||
cchWideChar = 0;
|
||||
SetLastError(ERROR_NO_UNICODE_TRANSLATION);
|
||||
}
|
||||
else
|
||||
cchWideChar = targetLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cchWideChar;
|
||||
}
|
||||
|
||||
int int_WideCharToMultiByte(UINT CodePage, WINPR_ATTR_UNUSED DWORD dwFlags, LPCWSTR lpWideCharStr,
|
||||
int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte,
|
||||
WINPR_ATTR_UNUSED LPCSTR lpDefaultChar,
|
||||
WINPR_ATTR_UNUSED LPBOOL lpUsedDefaultChar)
|
||||
{
|
||||
/* If cchWideChar is 0, the function fails */
|
||||
|
||||
if ((cchWideChar == 0) || (cchWideChar < -1))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If cchWideChar is -1, the string is null-terminated */
|
||||
|
||||
size_t len = 0;
|
||||
if (cchWideChar == -1)
|
||||
len = _wcslen(lpWideCharStr) + 1;
|
||||
else
|
||||
len = WINPR_ASSERTING_INT_CAST(size_t, cchWideChar);
|
||||
|
||||
if (len >= INT32_MAX)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
cchWideChar = WINPR_ASSERTING_INT_CAST(int, len);
|
||||
|
||||
/*
|
||||
* if cbMultiByte is 0, the function returns the required buffer size
|
||||
* in bytes for lpMultiByteStr and makes no use of the output parameter itself.
|
||||
*/
|
||||
{
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
int32_t targetLength = -1;
|
||||
|
||||
switch (CodePage)
|
||||
{
|
||||
case CP_ACP:
|
||||
case CP_UTF8:
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Unsupported encoding %u", CodePage);
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* targetStart = lpMultiByteStr;
|
||||
const int32_t targetCapacity = cbMultiByte;
|
||||
#if defined(UCNV_CONVERT)
|
||||
const char* str = (const char*)lpWideCharStr;
|
||||
targetLength = ucnv_convert("UTF-8", "UTF-16LE", targetStart, targetCapacity, str,
|
||||
cchWideChar * (int32_t)sizeof(WCHAR), &error);
|
||||
#else
|
||||
u_strToUTF8(targetStart, targetCapacity, &targetLength, lpWideCharStr, cchWideChar, &error);
|
||||
#endif
|
||||
switch (error)
|
||||
{
|
||||
case U_BUFFER_OVERFLOW_ERROR:
|
||||
if (targetCapacity > 0)
|
||||
{
|
||||
WLog_ERR(TAG, "insufficient buffer supplied, got %d, required %d",
|
||||
targetCapacity, targetLength);
|
||||
cbMultiByte = 0;
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
else
|
||||
cbMultiByte = targetLength;
|
||||
break;
|
||||
case U_STRING_NOT_TERMINATED_WARNING:
|
||||
cbMultiByte = targetLength;
|
||||
break;
|
||||
case U_ZERO_ERROR:
|
||||
cbMultiByte = targetLength;
|
||||
break;
|
||||
default:
|
||||
WLog_WARN(TAG, "unexpected ICU error code %s [0x%08" PRIx32 "]", u_errorName(error),
|
||||
WINPR_CXX_COMPAT_CAST(unsigned, error));
|
||||
if (U_FAILURE(error))
|
||||
{
|
||||
WLog_ERR(TAG, "unexpected ICU error code %s [0x%08" PRIx32 "] is fatal",
|
||||
u_errorName(error), WINPR_CXX_COMPAT_CAST(unsigned, error));
|
||||
cbMultiByte = 0;
|
||||
SetLastError(ERROR_NO_UNICODE_TRANSLATION);
|
||||
}
|
||||
else
|
||||
cbMultiByte = targetLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cbMultiByte;
|
||||
}
|
||||
50
third_party/FreeRDP/winpr/libwinpr/crypto/CMakeLists.txt
vendored
Normal file
50
third_party/FreeRDP/winpr/libwinpr/crypto/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-crypto cmake build script
|
||||
#
|
||||
# Copyright 2012 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.
|
||||
|
||||
set(SRCS hash.c rand.c cipher.c cert.c crypto.c crypto.h)
|
||||
if(WITH_INTERNAL_RC4)
|
||||
list(APPEND SRCS rc4.c rc4.h)
|
||||
endif()
|
||||
|
||||
if(WITH_INTERNAL_MD4)
|
||||
list(APPEND SRCS md4.c md4.h)
|
||||
endif()
|
||||
|
||||
if(WITH_INTERNAL_MD5)
|
||||
list(APPEND SRCS md5.c md5.h)
|
||||
list(APPEND SRCS hmac_md5.c hmac_md5.h)
|
||||
endif()
|
||||
|
||||
winpr_module_add(${SRCS})
|
||||
|
||||
if(OPENSSL_FOUND)
|
||||
winpr_system_include_directory_add(${OPENSSL_INCLUDE_DIR})
|
||||
winpr_library_add_private(${OPENSSL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(MBEDTLS_FOUND)
|
||||
winpr_system_include_directory_add(${MBEDTLS_INCLUDE_DIR})
|
||||
winpr_library_add_private(${MBEDTLS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
winpr_library_add_public(crypt32)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
7
third_party/FreeRDP/winpr/libwinpr/crypto/ModuleOptions.cmake
vendored
Normal file
7
third_party/FreeRDP/winpr/libwinpr/crypto/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
set(MINWIN_LAYER "1")
|
||||
set(MINWIN_GROUP "core")
|
||||
set(MINWIN_MAJOR_VERSION "1")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "crypto")
|
||||
set(MINWIN_LONG_NAME "Cryptography API (CryptoAPI)")
|
||||
set(MODULE_LIBRARY_NAME "crypt32")
|
||||
239
third_party/FreeRDP/winpr/libwinpr/crypto/cert.c
vendored
Normal file
239
third_party/FreeRDP/winpr/libwinpr/crypto/cert.c
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Cryptography API (CryptoAPI)
|
||||
*
|
||||
* Copyright 2012-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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
/**
|
||||
* CertOpenStore
|
||||
* CertCloseStore
|
||||
* CertControlStore
|
||||
* CertDuplicateStore
|
||||
* CertSaveStore
|
||||
* CertRegisterPhysicalStore
|
||||
* CertRegisterSystemStore
|
||||
* CertAddStoreToCollection
|
||||
* CertRemoveStoreFromCollection
|
||||
* CertOpenSystemStoreA
|
||||
* CertOpenSystemStoreW
|
||||
* CertEnumPhysicalStore
|
||||
* CertEnumSystemStore
|
||||
* CertEnumSystemStoreLocation
|
||||
* CertSetStoreProperty
|
||||
* CertUnregisterPhysicalStore
|
||||
* CertUnregisterSystemStore
|
||||
*
|
||||
* CertAddCertificateContextToStore
|
||||
* CertAddCertificateLinkToStore
|
||||
* CertAddCRLContextToStore
|
||||
* CertAddCRLLinkToStore
|
||||
* CertAddCTLContextToStore
|
||||
* CertAddCTLLinkToStore
|
||||
* CertAddEncodedCertificateToStore
|
||||
* CertAddEncodedCertificateToSystemStoreA
|
||||
* CertAddEncodedCertificateToSystemStoreW
|
||||
* CertAddEncodedCRLToStore
|
||||
* CertAddEncodedCTLToStore
|
||||
* CertAddSerializedElementToStore
|
||||
* CertDeleteCertificateFromStore
|
||||
* CertDeleteCRLFromStore
|
||||
* CertDeleteCTLFromStore
|
||||
* CertGetCRLFromStore
|
||||
* CertEnumCertificatesInStore
|
||||
* CertEnumCRLsInStore
|
||||
* CertEnumCTLsInStore
|
||||
* CertFindCertificateInStore
|
||||
* CertFindChainInStore
|
||||
* CertFindCRLInStore
|
||||
* CertFindCTLInStore
|
||||
* CertGetIssuerCertificateFromStore
|
||||
* CertGetStoreProperty
|
||||
* CertGetSubjectCertificateFromStore
|
||||
* CertSerializeCertificateStoreElement
|
||||
* CertSerializeCRLStoreElement
|
||||
* CertSerializeCTLStoreElement
|
||||
*
|
||||
* CertAddEnhancedKeyUsageIdentifier
|
||||
* CertAddRefServerOcspResponse
|
||||
* CertAddRefServerOcspResponseContext
|
||||
* CertAlgIdToOID
|
||||
* CertCloseServerOcspResponse
|
||||
* CertCompareCertificate
|
||||
* CertCompareCertificateName
|
||||
* CertCompareIntegerBlob
|
||||
* CertComparePublicKeyInfo
|
||||
* CertCreateCertificateChainEngine
|
||||
* CertCreateCertificateContext
|
||||
* CertCreateContext
|
||||
* CertCreateCRLContext
|
||||
* CertCreateCTLContext
|
||||
* CertCreateCTLEntryFromCertificateContextProperties
|
||||
* CertCreateSelfSignCertificate
|
||||
* CertDuplicateCertificateChain
|
||||
* CertDuplicateCertificateContext
|
||||
* CertDuplicateCRLContext
|
||||
* CertDuplicateCTLContext
|
||||
* CertEnumCertificateContextProperties
|
||||
* CertEnumCRLContextProperties
|
||||
* CertEnumCTLContextProperties
|
||||
* CertEnumSubjectInSortedCTL
|
||||
* CertFindAttribute
|
||||
* CertFindCertificateInCRL
|
||||
* CertFindExtension
|
||||
* CertFindRDNAttr
|
||||
* CertFindSubjectInCTL
|
||||
* CertFindSubjectInSortedCTL
|
||||
* CertFreeCertificateChain
|
||||
* CertFreeCertificateChainEngine
|
||||
* CertFreeCertificateChainList
|
||||
* CertFreeCertificateContext
|
||||
* CertFreeCRLContext
|
||||
* CertFreeCTLContext
|
||||
* CertFreeServerOcspResponseContext
|
||||
* CertGetCertificateChain
|
||||
* CertGetCertificateContextProperty
|
||||
* CertGetCRLContextProperty
|
||||
* CertGetCTLContextProperty
|
||||
* CertGetEnhancedKeyUsage
|
||||
* CertGetIntendedKeyUsage
|
||||
* CertGetNameStringA
|
||||
* CertGetNameStringW
|
||||
* CertGetPublicKeyLength
|
||||
* CertGetServerOcspResponseContext
|
||||
* CertGetValidUsages
|
||||
* CertIsRDNAttrsInCertificateName
|
||||
* CertIsStrongHashToSign
|
||||
* CertIsValidCRLForCertificate
|
||||
* CertNameToStrA
|
||||
* CertNameToStrW
|
||||
* CertOIDToAlgId
|
||||
* CertOpenServerOcspResponse
|
||||
* CertRDNValueToStrA
|
||||
* CertRDNValueToStrW
|
||||
* CertRemoveEnhancedKeyUsageIdentifier
|
||||
* CertResyncCertificateChainEngine
|
||||
* CertRetrieveLogoOrBiometricInfo
|
||||
* CertSelectCertificateChains
|
||||
* CertSetCertificateContextPropertiesFromCTLEntry
|
||||
* CertSetCertificateContextProperty
|
||||
* CertSetCRLContextProperty
|
||||
* CertSetCTLContextProperty
|
||||
* CertSetEnhancedKeyUsage
|
||||
* CertStrToNameA
|
||||
* CertStrToNameW
|
||||
* CertVerifyCertificateChainPolicy
|
||||
* CertVerifyCRLRevocation
|
||||
* CertVerifyCRLTimeValidity
|
||||
* CertVerifyCTLUsage
|
||||
* CertVerifyRevocation
|
||||
* CertVerifySubjectCertificateContext
|
||||
* CertVerifyTimeValidity
|
||||
* CertVerifyValidityNesting
|
||||
*/
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/wincrypt.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "crypto.h"
|
||||
|
||||
HCERTSTORE CertOpenStore(LPCSTR lpszStoreProvider, DWORD dwMsgAndCertEncodingType,
|
||||
WINPR_ATTR_UNUSED HCRYPTPROV_LEGACY hCryptProv,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED const void* pvPara)
|
||||
{
|
||||
WINPR_CERTSTORE* certstore = nullptr;
|
||||
|
||||
certstore = (WINPR_CERTSTORE*)calloc(1, sizeof(WINPR_CERTSTORE));
|
||||
|
||||
if (certstore)
|
||||
{
|
||||
certstore->lpszStoreProvider = lpszStoreProvider;
|
||||
certstore->dwMsgAndCertEncodingType = dwMsgAndCertEncodingType;
|
||||
}
|
||||
|
||||
return (HCERTSTORE)certstore;
|
||||
}
|
||||
|
||||
HCERTSTORE CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
|
||||
WINPR_ATTR_UNUSED LPCWSTR szSubsystemProtocol)
|
||||
{
|
||||
HCERTSTORE hCertStore = nullptr;
|
||||
|
||||
hCertStore = CertOpenStore(CERT_STORE_PROV_FILE, X509_ASN_ENCODING, hProv, 0, nullptr);
|
||||
|
||||
return hCertStore;
|
||||
}
|
||||
|
||||
HCERTSTORE CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
|
||||
WINPR_ATTR_UNUSED LPCSTR szSubsystemProtocol)
|
||||
{
|
||||
return CertOpenSystemStoreW(hProv, nullptr);
|
||||
}
|
||||
|
||||
BOOL CertCloseStore(HCERTSTORE hCertStore, WINPR_ATTR_UNUSED DWORD dwFlags)
|
||||
{
|
||||
WINPR_CERTSTORE* certstore = nullptr;
|
||||
|
||||
certstore = (WINPR_CERTSTORE*)hCertStore;
|
||||
|
||||
free(certstore);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PCCERT_CONTEXT CertFindCertificateInStore(WINPR_ATTR_UNUSED HCERTSTORE hCertStore,
|
||||
WINPR_ATTR_UNUSED DWORD dwCertEncodingType,
|
||||
WINPR_ATTR_UNUSED DWORD dwFindFlags,
|
||||
WINPR_ATTR_UNUSED DWORD dwFindType,
|
||||
WINPR_ATTR_UNUSED const void* pvFindPara,
|
||||
WINPR_ATTR_UNUSED PCCERT_CONTEXT pPrevCertContext)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return (PCCERT_CONTEXT)1;
|
||||
}
|
||||
|
||||
PCCERT_CONTEXT CertEnumCertificatesInStore(WINPR_ATTR_UNUSED HCERTSTORE hCertStore,
|
||||
WINPR_ATTR_UNUSED PCCERT_CONTEXT pPrevCertContext)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return (PCCERT_CONTEXT) nullptr;
|
||||
}
|
||||
|
||||
DWORD CertGetNameStringW(WINPR_ATTR_UNUSED PCCERT_CONTEXT pCertContext,
|
||||
WINPR_ATTR_UNUSED DWORD dwType, WINPR_ATTR_UNUSED DWORD dwFlags,
|
||||
WINPR_ATTR_UNUSED void* pvTypePara, WINPR_ATTR_UNUSED LPWSTR pszNameString,
|
||||
WINPR_ATTR_UNUSED DWORD cchNameString)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD CertGetNameStringA(WINPR_ATTR_UNUSED PCCERT_CONTEXT pCertContext,
|
||||
WINPR_ATTR_UNUSED DWORD dwType, WINPR_ATTR_UNUSED DWORD dwFlags,
|
||||
WINPR_ATTR_UNUSED void* pvTypePara, WINPR_ATTR_UNUSED LPSTR pszNameString,
|
||||
WINPR_ATTR_UNUSED DWORD cchNameString)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
881
third_party/FreeRDP/winpr/libwinpr/crypto/cipher.c
vendored
Normal file
881
third_party/FreeRDP/winpr/libwinpr/crypto/cipher.c
vendored
Normal file
@@ -0,0 +1,881 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
*
|
||||
* Copyright 2015 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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("crypto.cipher")
|
||||
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
#include "rc4.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rc4.h>
|
||||
#include <openssl/des.h>
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/des.h>
|
||||
#include <mbedtls/cipher.h>
|
||||
#if MBEDTLS_VERSION_MAJOR < 3
|
||||
#define mbedtls_cipher_info_get_iv_size(_info) (_info->iv_size)
|
||||
#define mbedtls_cipher_info_get_key_bitlen(_info) (_info->key_bitlen)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct winpr_cipher_ctx_private_st
|
||||
{
|
||||
WINPR_CIPHER_TYPE cipher;
|
||||
WINPR_CRYPTO_OPERATION op;
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
EVP_CIPHER_CTX* ectx;
|
||||
#endif
|
||||
#ifdef WITH_MBEDTLS
|
||||
mbedtls_cipher_context_t* mctx;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* RC4
|
||||
*/
|
||||
|
||||
struct winpr_rc4_ctx_private_st
|
||||
{
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
winpr_int_RC4_CTX* ictx;
|
||||
#else
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_CIPHER_CTX* ctx;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
static WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOOL override_fips)
|
||||
{
|
||||
if (!key || (keylen == 0))
|
||||
return nullptr;
|
||||
|
||||
WINPR_RC4_CTX* ctx = (WINPR_RC4_CTX*)calloc(1, sizeof(WINPR_RC4_CTX));
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
WINPR_UNUSED(override_fips);
|
||||
ctx->ictx = winpr_int_rc4_new(key, keylen);
|
||||
if (!ctx->ictx)
|
||||
goto fail;
|
||||
#elif defined(WITH_OPENSSL)
|
||||
const EVP_CIPHER* evp = nullptr;
|
||||
|
||||
if (keylen > INT_MAX)
|
||||
goto fail;
|
||||
|
||||
ctx->ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx->ctx)
|
||||
goto fail;
|
||||
|
||||
evp = EVP_rc4();
|
||||
|
||||
if (!evp)
|
||||
goto fail;
|
||||
|
||||
EVP_CIPHER_CTX_reset(ctx->ctx);
|
||||
if (EVP_EncryptInit_ex(ctx->ctx, evp, nullptr, nullptr, nullptr) != 1)
|
||||
goto fail;
|
||||
|
||||
/* EVP_CIPH_FLAG_NON_FIPS_ALLOW does not exist before openssl 1.0.1 */
|
||||
#if !(OPENSSL_VERSION_NUMBER < 0x10001000L)
|
||||
|
||||
if (override_fips == TRUE)
|
||||
EVP_CIPHER_CTX_set_flags(ctx->ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW);
|
||||
|
||||
#endif
|
||||
EVP_CIPHER_CTX_set_key_length(ctx->ctx, (int)keylen);
|
||||
if (EVP_EncryptInit_ex(ctx->ctx, nullptr, nullptr, key, nullptr) != 1)
|
||||
goto fail;
|
||||
#endif
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
|
||||
winpr_RC4_Free(ctx);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WINPR_RC4_CTX* winpr_RC4_New_Allow_FIPS(const void* key, size_t keylen)
|
||||
{
|
||||
return winpr_RC4_New_Internal(key, keylen, TRUE);
|
||||
}
|
||||
|
||||
WINPR_RC4_CTX* winpr_RC4_New(const void* key, size_t keylen)
|
||||
{
|
||||
return winpr_RC4_New_Internal(key, keylen, FALSE);
|
||||
}
|
||||
|
||||
BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const void* input, void* output)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
return winpr_int_rc4_update(ctx->ictx, length, input, output);
|
||||
#elif defined(WITH_OPENSSL)
|
||||
WINPR_ASSERT(ctx->ctx);
|
||||
int outputLength = 0;
|
||||
if (length > INT_MAX)
|
||||
return FALSE;
|
||||
|
||||
WINPR_ASSERT(ctx);
|
||||
if (EVP_CipherUpdate(ctx->ctx, output, &outputLength, input, (int)length) != 1)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void winpr_RC4_Free(WINPR_RC4_CTX* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
winpr_int_rc4_free(ctx->ictx);
|
||||
#elif defined(WITH_OPENSSL)
|
||||
EVP_CIPHER_CTX_free(ctx->ctx);
|
||||
#endif
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic Cipher API
|
||||
*/
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
extern const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
extern mbedtls_md_type_t winpr_mbedtls_get_md_type(int md);
|
||||
#endif
|
||||
|
||||
struct cipher_map
|
||||
{
|
||||
WINPR_CIPHER_TYPE md;
|
||||
const char* name;
|
||||
};
|
||||
static const struct cipher_map s_cipher_map[] = {
|
||||
{ WINPR_CIPHER_NONE, "none" },
|
||||
{ WINPR_CIPHER_NULL, "null" },
|
||||
{ WINPR_CIPHER_AES_128_ECB, "aes-128-ecb" },
|
||||
{ WINPR_CIPHER_AES_192_ECB, "aes-192-ecb" },
|
||||
{ WINPR_CIPHER_AES_256_ECB, "aes-256-ecb" },
|
||||
{ WINPR_CIPHER_AES_128_CBC, "aes-128-cbc" },
|
||||
{ WINPR_CIPHER_AES_192_CBC, "aes-192-cbc" },
|
||||
{ WINPR_CIPHER_AES_256_CBC, "aes-256-cbc" },
|
||||
{ WINPR_CIPHER_AES_128_CFB128, "aes-128-cfb128" },
|
||||
{ WINPR_CIPHER_AES_192_CFB128, "aes-192-cfb128" },
|
||||
{ WINPR_CIPHER_AES_256_CFB128, "aes-256-cfb128" },
|
||||
{ WINPR_CIPHER_AES_128_CTR, "aes-128-ctr" },
|
||||
{ WINPR_CIPHER_AES_192_CTR, "aes-192-ctr" },
|
||||
{ WINPR_CIPHER_AES_256_CTR, "aes-256-ctr" },
|
||||
{ WINPR_CIPHER_AES_128_GCM, "aes-128-gcm" },
|
||||
{ WINPR_CIPHER_AES_192_GCM, "aes-192-gcm" },
|
||||
{ WINPR_CIPHER_AES_256_GCM, "aes-256-gcm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_ECB, "camellia-128-ecb" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_ECB, "camellia-192-ecb" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_ECB, "camellia-256-ecb" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_CBC, "camellia-128-cbc" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_CBC, "camellia-192-cbc" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_CBC, "camellia-256-cbc" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_CFB128, "camellia-128-cfb128" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_CFB128, "camellia-192-cfb128" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_CFB128, "camellia-256-cfb128" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_CTR, "camellia-128-ctr" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_CTR, "camellia-192-ctr" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_CTR, "camellia-256-ctr" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_GCM, "camellia-128-gcm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_GCM, "camellia-192-gcm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_GCM, "camellia-256-gcm" },
|
||||
{ WINPR_CIPHER_DES_ECB, "des-ecb" },
|
||||
{ WINPR_CIPHER_DES_CBC, "des-cbc" },
|
||||
{ WINPR_CIPHER_DES_EDE_ECB, "des-ede-ecb" },
|
||||
{ WINPR_CIPHER_DES_EDE_CBC, "des-ede-cbc" },
|
||||
{ WINPR_CIPHER_DES_EDE3_ECB, "des-ede3-ecb" },
|
||||
{ WINPR_CIPHER_DES_EDE3_CBC, "des-ede3-cbc" },
|
||||
{ WINPR_CIPHER_BLOWFISH_ECB, "blowfish-ecb" },
|
||||
{ WINPR_CIPHER_BLOWFISH_CBC, "blowfish-cbc" },
|
||||
{ WINPR_CIPHER_BLOWFISH_CFB64, "blowfish-cfb64" },
|
||||
{ WINPR_CIPHER_BLOWFISH_CTR, "blowfish-ctr" },
|
||||
{ WINPR_CIPHER_ARC4_128, "rc4" },
|
||||
{ WINPR_CIPHER_AES_128_CCM, "aes-128-ccm" },
|
||||
{ WINPR_CIPHER_AES_192_CCM, "aes-192-ccm" },
|
||||
{ WINPR_CIPHER_AES_256_CCM, "aes-256-ccm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_CCM, "camellia-128-ccm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_CCM, "camellia-192-ccm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_CCM, "camellia-256-ccm" },
|
||||
};
|
||||
|
||||
static int cipher_compare(const void* a, const void* b)
|
||||
{
|
||||
const WINPR_CIPHER_TYPE* cipher = a;
|
||||
const struct cipher_map* map = b;
|
||||
if (*cipher == map->md)
|
||||
return 0;
|
||||
return *cipher > map->md ? 1 : -1;
|
||||
}
|
||||
|
||||
const char* winpr_cipher_type_to_string(WINPR_CIPHER_TYPE md)
|
||||
{
|
||||
WINPR_CIPHER_TYPE lc = md;
|
||||
const struct cipher_map* ret = bsearch(&lc, s_cipher_map, ARRAYSIZE(s_cipher_map),
|
||||
sizeof(struct cipher_map), cipher_compare);
|
||||
if (!ret)
|
||||
return "unknown";
|
||||
return ret->name;
|
||||
}
|
||||
|
||||
static int cipher_string_compare(const void* a, const void* b)
|
||||
{
|
||||
const char* cipher = a;
|
||||
const struct cipher_map* map = b;
|
||||
return strcmp(cipher, map->name);
|
||||
}
|
||||
|
||||
WINPR_CIPHER_TYPE winpr_cipher_type_from_string(const char* name)
|
||||
{
|
||||
const struct cipher_map* ret = bsearch(name, s_cipher_map, ARRAYSIZE(s_cipher_map),
|
||||
sizeof(struct cipher_map), cipher_string_compare);
|
||||
if (!ret)
|
||||
return WINPR_CIPHER_NONE;
|
||||
return ret->md;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
static const EVP_CIPHER* winpr_openssl_get_evp_cipher(WINPR_CIPHER_TYPE cipher)
|
||||
{
|
||||
const EVP_CIPHER* evp = nullptr;
|
||||
|
||||
switch (cipher)
|
||||
{
|
||||
case WINPR_CIPHER_NULL:
|
||||
evp = EVP_enc_null();
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_ECB:
|
||||
evp = EVP_get_cipherbyname("aes-128-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_ECB:
|
||||
evp = EVP_get_cipherbyname("aes-192-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_ECB:
|
||||
evp = EVP_get_cipherbyname("aes-256-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CBC:
|
||||
evp = EVP_get_cipherbyname("aes-128-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CBC:
|
||||
evp = EVP_get_cipherbyname("aes-192-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CBC:
|
||||
evp = EVP_get_cipherbyname("aes-256-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CFB128:
|
||||
evp = EVP_get_cipherbyname("aes-128-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CFB128:
|
||||
evp = EVP_get_cipherbyname("aes-192-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CFB128:
|
||||
evp = EVP_get_cipherbyname("aes-256-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CTR:
|
||||
evp = EVP_get_cipherbyname("aes-128-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CTR:
|
||||
evp = EVP_get_cipherbyname("aes-192-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CTR:
|
||||
evp = EVP_get_cipherbyname("aes-256-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_GCM:
|
||||
evp = EVP_get_cipherbyname("aes-128-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_GCM:
|
||||
evp = EVP_get_cipherbyname("aes-192-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_GCM:
|
||||
evp = EVP_get_cipherbyname("aes-256-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CCM:
|
||||
evp = EVP_get_cipherbyname("aes-128-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CCM:
|
||||
evp = EVP_get_cipherbyname("aes-192-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CCM:
|
||||
evp = EVP_get_cipherbyname("aes-256-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_ECB:
|
||||
evp = EVP_get_cipherbyname("camellia-128-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_ECB:
|
||||
evp = EVP_get_cipherbyname("camellia-192-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_ECB:
|
||||
evp = EVP_get_cipherbyname("camellia-256-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_CBC:
|
||||
evp = EVP_get_cipherbyname("camellia-128-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_CBC:
|
||||
evp = EVP_get_cipherbyname("camellia-192-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_CBC:
|
||||
evp = EVP_get_cipherbyname("camellia-256-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_CFB128:
|
||||
evp = EVP_get_cipherbyname("camellia-128-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_CFB128:
|
||||
evp = EVP_get_cipherbyname("camellia-192-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_CFB128:
|
||||
evp = EVP_get_cipherbyname("camellia-256-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_CTR:
|
||||
evp = EVP_get_cipherbyname("camellia-128-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_CTR:
|
||||
evp = EVP_get_cipherbyname("camellia-192-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_CTR:
|
||||
evp = EVP_get_cipherbyname("camellia-256-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_GCM:
|
||||
evp = EVP_get_cipherbyname("camellia-128-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_GCM:
|
||||
evp = EVP_get_cipherbyname("camellia-192-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_GCM:
|
||||
evp = EVP_get_cipherbyname("camellia-256-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_CCM:
|
||||
evp = EVP_get_cipherbyname("camellia-128-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_CCM:
|
||||
evp = EVP_get_cipherbyname("camellia-192-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_CCM:
|
||||
evp = EVP_get_cipherbyname("camellia-256-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_ECB:
|
||||
evp = EVP_get_cipherbyname("des-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_CBC:
|
||||
evp = EVP_get_cipherbyname("des-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_EDE_ECB:
|
||||
evp = EVP_get_cipherbyname("des-ede-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_EDE_CBC:
|
||||
evp = EVP_get_cipherbyname("des-ede-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_EDE3_ECB:
|
||||
evp = EVP_get_cipherbyname("des-ede3-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_EDE3_CBC:
|
||||
evp = EVP_get_cipherbyname("des-ede3-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_ARC4_128:
|
||||
evp = EVP_get_cipherbyname("rc4");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_BLOWFISH_ECB:
|
||||
evp = EVP_get_cipherbyname("blowfish-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_BLOWFISH_CBC:
|
||||
evp = EVP_get_cipherbyname("blowfish-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_BLOWFISH_CFB64:
|
||||
evp = EVP_get_cipherbyname("blowfish-cfb64");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_BLOWFISH_CTR:
|
||||
evp = EVP_get_cipherbyname("blowfish-ctr");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return evp;
|
||||
}
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher)
|
||||
{
|
||||
mbedtls_cipher_type_t type = MBEDTLS_CIPHER_NONE;
|
||||
|
||||
switch (cipher)
|
||||
{
|
||||
case WINPR_CIPHER_NONE:
|
||||
type = MBEDTLS_CIPHER_NONE;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_NULL:
|
||||
type = MBEDTLS_CIPHER_NULL;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_ECB:
|
||||
type = MBEDTLS_CIPHER_AES_128_ECB;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_ECB:
|
||||
type = MBEDTLS_CIPHER_AES_192_ECB;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_ECB:
|
||||
type = MBEDTLS_CIPHER_AES_256_ECB;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CBC:
|
||||
type = MBEDTLS_CIPHER_AES_128_CBC;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CBC:
|
||||
type = MBEDTLS_CIPHER_AES_192_CBC;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CBC:
|
||||
type = MBEDTLS_CIPHER_AES_256_CBC;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CFB128:
|
||||
type = MBEDTLS_CIPHER_AES_128_CFB128;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CFB128:
|
||||
type = MBEDTLS_CIPHER_AES_192_CFB128;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CFB128:
|
||||
type = MBEDTLS_CIPHER_AES_256_CFB128;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CTR:
|
||||
type = MBEDTLS_CIPHER_AES_128_CTR;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CTR:
|
||||
type = MBEDTLS_CIPHER_AES_192_CTR;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CTR:
|
||||
type = MBEDTLS_CIPHER_AES_256_CTR;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_GCM:
|
||||
type = MBEDTLS_CIPHER_AES_128_GCM;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_GCM:
|
||||
type = MBEDTLS_CIPHER_AES_192_GCM;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_GCM:
|
||||
type = MBEDTLS_CIPHER_AES_256_GCM;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CCM:
|
||||
type = MBEDTLS_CIPHER_AES_128_CCM;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CCM:
|
||||
type = MBEDTLS_CIPHER_AES_192_CCM;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CCM:
|
||||
type = MBEDTLS_CIPHER_AES_256_CCM;
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
WINPR_CIPHER_CTX* winpr_Cipher_New(WINPR_CIPHER_TYPE cipher, WINPR_CRYPTO_OPERATION op,
|
||||
const void* key, const void* iv)
|
||||
{
|
||||
return winpr_Cipher_NewEx(cipher, op, key, 0, iv, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
WINPR_API WINPR_CIPHER_CTX* winpr_Cipher_NewEx(WINPR_CIPHER_TYPE cipher, WINPR_CRYPTO_OPERATION op,
|
||||
const void* key, WINPR_ATTR_UNUSED size_t keylen,
|
||||
const void* iv, WINPR_ATTR_UNUSED size_t ivlen)
|
||||
{
|
||||
if (cipher == WINPR_CIPHER_ARC4_128)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"WINPR_CIPHER_ARC4_128 (RC4) cipher not supported, use winpr_RC4_new instead");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WINPR_CIPHER_CTX* ctx = calloc(1, sizeof(WINPR_CIPHER_CTX));
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
|
||||
ctx->cipher = cipher;
|
||||
ctx->op = op;
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
const EVP_CIPHER* evp = winpr_openssl_get_evp_cipher(cipher);
|
||||
if (!evp)
|
||||
goto fail;
|
||||
|
||||
ctx->ectx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx->ectx)
|
||||
goto fail;
|
||||
|
||||
{
|
||||
const int operation = (op == WINPR_ENCRYPT) ? 1 : 0;
|
||||
if (EVP_CipherInit_ex(ctx->ectx, evp, nullptr, key, iv, operation) != 1)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_set_padding(ctx->ectx, 0);
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_cipher_type_t cipher_type = winpr_mbedtls_get_cipher_type(cipher);
|
||||
const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(cipher_type);
|
||||
|
||||
if (!cipher_info)
|
||||
goto fail;
|
||||
|
||||
ctx->mctx = calloc(1, sizeof(mbedtls_cipher_context_t));
|
||||
if (!ctx->mctx)
|
||||
goto fail;
|
||||
|
||||
const mbedtls_operation_t operation = (op == WINPR_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT;
|
||||
mbedtls_cipher_init(ctx->mctx);
|
||||
|
||||
if (mbedtls_cipher_setup(ctx->mctx, cipher_info) != 0)
|
||||
goto fail;
|
||||
|
||||
const int key_bitlen = mbedtls_cipher_get_key_bitlen(ctx->mctx);
|
||||
|
||||
if (mbedtls_cipher_setkey(ctx->mctx, key, key_bitlen, operation) != 0)
|
||||
goto fail;
|
||||
|
||||
if (mbedtls_cipher_set_padding_mode(ctx->mctx, MBEDTLS_PADDING_NONE) != 0)
|
||||
goto fail;
|
||||
|
||||
#endif
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
winpr_Cipher_Free(ctx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL winpr_Cipher_SetPadding(WINPR_CIPHER_CTX* ctx, BOOL enabled)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
if (!ctx->ectx)
|
||||
return FALSE;
|
||||
EVP_CIPHER_CTX_set_padding(ctx->ectx, enabled);
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_cipher_padding_t option = enabled ? MBEDTLS_PADDING_PKCS7 : MBEDTLS_PADDING_NONE;
|
||||
if (mbedtls_cipher_set_padding_mode((mbedtls_cipher_context_t*)ctx, option) != 0)
|
||||
return FALSE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const void* input, size_t ilen, void* output,
|
||||
size_t* olen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
WINPR_ASSERT(olen);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
int outl = (int)*olen;
|
||||
|
||||
if (ilen > INT_MAX)
|
||||
{
|
||||
WLog_ERR(TAG, "input length %" PRIuz " > %d, abort", ilen, INT_MAX);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(ctx->ectx);
|
||||
if (EVP_CipherUpdate(ctx->ectx, output, &outl, input, (int)ilen) == 1)
|
||||
{
|
||||
*olen = (size_t)outl;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
WINPR_ASSERT(ctx->mctx);
|
||||
if (mbedtls_cipher_update(ctx->mctx, input, ilen, output, olen) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
|
||||
WLog_ERR(TAG, "Failed to update the data");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, void* output, size_t* olen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
int outl = (int)*olen;
|
||||
|
||||
WINPR_ASSERT(ctx->ectx);
|
||||
if (EVP_CipherFinal_ex(ctx->ectx, output, &outl) == 1)
|
||||
{
|
||||
*olen = (size_t)outl;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
|
||||
WINPR_ASSERT(ctx->mctx);
|
||||
if (mbedtls_cipher_finish(ctx->mctx, output, olen) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
if (ctx->ectx)
|
||||
EVP_CIPHER_CTX_free(ctx->ectx);
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
if (ctx->mctx)
|
||||
{
|
||||
mbedtls_cipher_free(ctx->mctx);
|
||||
free(ctx->mctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Key Generation
|
||||
*/
|
||||
|
||||
int winpr_Cipher_BytesToKey(int cipher, WINPR_MD_TYPE md, const void* salt, const void* data,
|
||||
size_t datal, size_t count, void* key, void* iv)
|
||||
{
|
||||
/**
|
||||
* Key and IV generation compatible with OpenSSL EVP_BytesToKey():
|
||||
* https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html
|
||||
*/
|
||||
#if defined(WITH_OPENSSL)
|
||||
const EVP_MD* evp_md = nullptr;
|
||||
const EVP_CIPHER* evp_cipher = nullptr;
|
||||
evp_md = winpr_openssl_get_evp_md(md);
|
||||
evp_cipher = winpr_openssl_get_evp_cipher(WINPR_ASSERTING_INT_CAST(WINPR_CIPHER_TYPE, cipher));
|
||||
WINPR_ASSERT(datal <= INT_MAX);
|
||||
WINPR_ASSERT(count <= INT_MAX);
|
||||
return EVP_BytesToKey(evp_cipher, evp_md, salt, data, (int)datal, (int)count, key, iv);
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
int rv = 0;
|
||||
BYTE md_buf[64];
|
||||
int niv, nkey, addmd = 0;
|
||||
unsigned int mds = 0;
|
||||
mbedtls_md_context_t ctx;
|
||||
const mbedtls_md_info_t* md_info;
|
||||
mbedtls_cipher_type_t cipher_type;
|
||||
const mbedtls_cipher_info_t* cipher_info;
|
||||
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
|
||||
md_info = mbedtls_md_info_from_type(md_type);
|
||||
cipher_type = winpr_mbedtls_get_cipher_type(cipher);
|
||||
cipher_info = mbedtls_cipher_info_from_type(cipher_type);
|
||||
nkey = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
|
||||
niv = mbedtls_cipher_info_get_iv_size(cipher_info);
|
||||
|
||||
if ((nkey > 64) || (niv > 64))
|
||||
return 0;
|
||||
|
||||
if (!data)
|
||||
return nkey;
|
||||
|
||||
mbedtls_md_init(&ctx);
|
||||
|
||||
if (mbedtls_md_setup(&ctx, md_info, 0) != 0)
|
||||
goto err;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (mbedtls_md_starts(&ctx) != 0)
|
||||
goto err;
|
||||
|
||||
if (addmd++)
|
||||
{
|
||||
if (mbedtls_md_update(&ctx, md_buf, mds) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mbedtls_md_update(&ctx, data, datal) != 0)
|
||||
goto err;
|
||||
|
||||
if (salt)
|
||||
{
|
||||
if (mbedtls_md_update(&ctx, salt, 8) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mbedtls_md_finish(&ctx, md_buf) != 0)
|
||||
goto err;
|
||||
|
||||
mds = mbedtls_md_get_size(md_info);
|
||||
|
||||
for (unsigned int i = 1; i < (unsigned int)count; i++)
|
||||
{
|
||||
if (mbedtls_md_starts(&ctx) != 0)
|
||||
goto err;
|
||||
|
||||
if (mbedtls_md_update(&ctx, md_buf, mds) != 0)
|
||||
goto err;
|
||||
|
||||
if (mbedtls_md_finish(&ctx, md_buf) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
unsigned int i = 0;
|
||||
|
||||
if (nkey)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (nkey == 0)
|
||||
break;
|
||||
|
||||
if (i == mds)
|
||||
break;
|
||||
|
||||
if (key)
|
||||
*(BYTE*)(key++) = md_buf[i];
|
||||
|
||||
nkey--;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (niv && (i != mds))
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (niv == 0)
|
||||
break;
|
||||
|
||||
if (i == mds)
|
||||
break;
|
||||
|
||||
if (iv)
|
||||
*(BYTE*)(iv++) = md_buf[i];
|
||||
|
||||
niv--;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((nkey == 0) && (niv == 0))
|
||||
break;
|
||||
}
|
||||
|
||||
rv = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
|
||||
err:
|
||||
mbedtls_md_free(&ctx);
|
||||
SecureZeroMemory(md_buf, 64);
|
||||
return rv;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
324
third_party/FreeRDP/winpr/libwinpr/crypto/crypto.c
vendored
Normal file
324
third_party/FreeRDP/winpr/libwinpr/crypto/crypto.c
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Cryptography API (CryptoAPI)
|
||||
*
|
||||
* Copyright 2012-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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
/**
|
||||
* CryptAcquireCertificatePrivateKey
|
||||
* CryptBinaryToStringA
|
||||
* CryptBinaryToStringW
|
||||
* CryptCloseAsyncHandle
|
||||
* CryptCreateAsyncHandle
|
||||
* CryptCreateKeyIdentifierFromCSP
|
||||
* CryptDecodeMessage
|
||||
* CryptDecodeObject
|
||||
* CryptDecodeObjectEx
|
||||
* CryptDecryptAndVerifyMessageSignature
|
||||
* CryptDecryptMessage
|
||||
* CryptEncodeObject
|
||||
* CryptEncodeObjectEx
|
||||
* CryptEncryptMessage
|
||||
* CryptEnumKeyIdentifierProperties
|
||||
* CryptEnumOIDFunction
|
||||
* CryptEnumOIDInfo
|
||||
* CryptExportPKCS8
|
||||
* CryptExportPublicKeyInfo
|
||||
* CryptExportPublicKeyInfoEx
|
||||
* CryptExportPublicKeyInfoFromBCryptKeyHandle
|
||||
* CryptFindCertificateKeyProvInfo
|
||||
* CryptFindLocalizedName
|
||||
* CryptFindOIDInfo
|
||||
* CryptFormatObject
|
||||
* CryptFreeOIDFunctionAddress
|
||||
* CryptGetAsyncParam
|
||||
* CryptGetDefaultOIDDllList
|
||||
* CryptGetDefaultOIDFunctionAddress
|
||||
* CryptGetKeyIdentifierProperty
|
||||
* CryptGetMessageCertificates
|
||||
* CryptGetMessageSignerCount
|
||||
* CryptGetOIDFunctionAddress
|
||||
* CryptGetOIDFunctionValue
|
||||
* CryptHashCertificate
|
||||
* CryptHashCertificate2
|
||||
* CryptHashMessage
|
||||
* CryptHashPublicKeyInfo
|
||||
* CryptHashToBeSigned
|
||||
* CryptImportPKCS8
|
||||
* CryptImportPublicKeyInfo
|
||||
* CryptImportPublicKeyInfoEx
|
||||
* CryptImportPublicKeyInfoEx2
|
||||
* CryptInitOIDFunctionSet
|
||||
* CryptInstallDefaultContext
|
||||
* CryptInstallOIDFunctionAddress
|
||||
* CryptLoadSip
|
||||
* CryptMemAlloc
|
||||
* CryptMemFree
|
||||
* CryptMemRealloc
|
||||
* CryptMsgCalculateEncodedLength
|
||||
* CryptMsgClose
|
||||
* CryptMsgControl
|
||||
* CryptMsgCountersign
|
||||
* CryptMsgCountersignEncoded
|
||||
* CryptMsgDuplicate
|
||||
* CryptMsgEncodeAndSignCTL
|
||||
* CryptMsgGetAndVerifySigner
|
||||
* CryptMsgGetParam
|
||||
* CryptMsgOpenToDecode
|
||||
* CryptMsgOpenToEncode
|
||||
* CryptMsgSignCTL
|
||||
* CryptMsgUpdate
|
||||
* CryptMsgVerifyCountersignatureEncoded
|
||||
* CryptMsgVerifyCountersignatureEncodedEx
|
||||
* CryptQueryObject
|
||||
* CryptRegisterDefaultOIDFunction
|
||||
* CryptRegisterOIDFunction
|
||||
* CryptRegisterOIDInfo
|
||||
* CryptRetrieveTimeStamp
|
||||
* CryptSetAsyncParam
|
||||
* CryptSetKeyIdentifierProperty
|
||||
* CryptSetOIDFunctionValue
|
||||
* CryptSignAndEncodeCertificate
|
||||
* CryptSignAndEncryptMessage
|
||||
* CryptSignCertificate
|
||||
* CryptSignMessage
|
||||
* CryptSignMessageWithKey
|
||||
* CryptSIPAddProvider
|
||||
* CryptSIPCreateIndirectData
|
||||
* CryptSIPGetCaps
|
||||
* CryptSIPGetSignedDataMsg
|
||||
* CryptSIPLoad
|
||||
* CryptSIPPutSignedDataMsg
|
||||
* CryptSIPRemoveProvider
|
||||
* CryptSIPRemoveSignedDataMsg
|
||||
* CryptSIPRetrieveSubjectGuid
|
||||
* CryptSIPRetrieveSubjectGuidForCatalogFile
|
||||
* CryptSIPVerifyIndirectData
|
||||
* CryptUninstallDefaultContext
|
||||
* CryptUnregisterDefaultOIDFunction
|
||||
* CryptUnregisterOIDFunction
|
||||
* CryptUnregisterOIDInfo
|
||||
* CryptUpdateProtectedState
|
||||
* CryptVerifyCertificateSignature
|
||||
* CryptVerifyCertificateSignatureEx
|
||||
* CryptVerifyDetachedMessageHash
|
||||
* CryptVerifyDetachedMessageSignature
|
||||
* CryptVerifyMessageHash
|
||||
* CryptVerifyMessageSignature
|
||||
* CryptVerifyMessageSignatureWithKey
|
||||
* CryptVerifyTimeStampSignature
|
||||
* DbgInitOSS
|
||||
* DbgPrintf
|
||||
* PFXExportCertStore
|
||||
* PFXExportCertStore2
|
||||
* PFXExportCertStoreEx
|
||||
* PFXImportCertStore
|
||||
* PFXIsPFXBlob
|
||||
* PFXVerifyPassword
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "crypto.h"
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
static wListDictionary* g_ProtectedMemoryBlocks = nullptr;
|
||||
|
||||
BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags)
|
||||
{
|
||||
BYTE* pCipherText = nullptr;
|
||||
size_t cbOut = 0;
|
||||
size_t cbFinal = 0;
|
||||
WINPR_CIPHER_CTX* enc = nullptr;
|
||||
BYTE randomKey[256] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock = nullptr;
|
||||
|
||||
if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS)
|
||||
return FALSE;
|
||||
|
||||
if (winpr_RAND(randomKey, sizeof(randomKey)) < 0)
|
||||
return FALSE;
|
||||
|
||||
if (!g_ProtectedMemoryBlocks)
|
||||
{
|
||||
g_ProtectedMemoryBlocks = ListDictionary_New(TRUE);
|
||||
|
||||
if (!g_ProtectedMemoryBlocks)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pMemBlock = (WINPR_PROTECTED_MEMORY_BLOCK*)calloc(1, sizeof(WINPR_PROTECTED_MEMORY_BLOCK));
|
||||
|
||||
if (!pMemBlock)
|
||||
return FALSE;
|
||||
|
||||
pMemBlock->pData = pData;
|
||||
pMemBlock->cbData = cbData;
|
||||
pMemBlock->dwFlags = dwFlags;
|
||||
|
||||
if (winpr_RAND(pMemBlock->salt, 8) < 0)
|
||||
goto out;
|
||||
|
||||
if (winpr_Cipher_BytesToKey(WINPR_CIPHER_AES_256_CBC, WINPR_MD_SHA1, pMemBlock->salt, randomKey,
|
||||
sizeof(randomKey), 4, pMemBlock->key, pMemBlock->iv) <= 0)
|
||||
goto out;
|
||||
|
||||
SecureZeroMemory(randomKey, sizeof(randomKey));
|
||||
|
||||
cbOut = pMemBlock->cbData + 16 - 1;
|
||||
pCipherText = (BYTE*)calloc(1, cbOut);
|
||||
|
||||
if (!pCipherText)
|
||||
goto out;
|
||||
|
||||
if ((enc = winpr_Cipher_NewEx(WINPR_CIPHER_AES_256_CBC, WINPR_ENCRYPT, pMemBlock->key,
|
||||
sizeof(pMemBlock->key), pMemBlock->iv, sizeof(pMemBlock->iv))) ==
|
||||
nullptr)
|
||||
goto out;
|
||||
if (!winpr_Cipher_Update(enc, pMemBlock->pData, pMemBlock->cbData, pCipherText, &cbOut))
|
||||
goto out;
|
||||
if (!winpr_Cipher_Final(enc, pCipherText + cbOut, &cbFinal))
|
||||
goto out;
|
||||
winpr_Cipher_Free(enc);
|
||||
|
||||
CopyMemory(pMemBlock->pData, pCipherText, pMemBlock->cbData);
|
||||
free(pCipherText);
|
||||
|
||||
return ListDictionary_Add(g_ProtectedMemoryBlocks, pData, pMemBlock);
|
||||
out:
|
||||
free(pMemBlock);
|
||||
free(pCipherText);
|
||||
winpr_Cipher_Free(enc);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CryptUnprotectMemory(LPVOID pData, WINPR_ATTR_UNUSED DWORD cbData, DWORD dwFlags)
|
||||
{
|
||||
BYTE* pPlainText = nullptr;
|
||||
size_t cbOut = 0;
|
||||
size_t cbFinal = 0;
|
||||
WINPR_CIPHER_CTX* dec = nullptr;
|
||||
WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock = nullptr;
|
||||
|
||||
if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS)
|
||||
return FALSE;
|
||||
|
||||
if (!g_ProtectedMemoryBlocks)
|
||||
return FALSE;
|
||||
|
||||
pMemBlock =
|
||||
(WINPR_PROTECTED_MEMORY_BLOCK*)ListDictionary_GetItemValue(g_ProtectedMemoryBlocks, pData);
|
||||
|
||||
if (!pMemBlock)
|
||||
goto out;
|
||||
|
||||
cbOut = pMemBlock->cbData + 16 - 1;
|
||||
|
||||
pPlainText = (BYTE*)malloc(cbOut);
|
||||
|
||||
if (!pPlainText)
|
||||
goto out;
|
||||
|
||||
if ((dec = winpr_Cipher_NewEx(WINPR_CIPHER_AES_256_CBC, WINPR_DECRYPT, pMemBlock->key,
|
||||
sizeof(pMemBlock->key), pMemBlock->iv, sizeof(pMemBlock->iv))) ==
|
||||
nullptr)
|
||||
goto out;
|
||||
if (!winpr_Cipher_Update(dec, pMemBlock->pData, pMemBlock->cbData, pPlainText, &cbOut))
|
||||
goto out;
|
||||
if (!winpr_Cipher_Final(dec, pPlainText + cbOut, &cbFinal))
|
||||
goto out;
|
||||
winpr_Cipher_Free(dec);
|
||||
|
||||
CopyMemory(pMemBlock->pData, pPlainText, pMemBlock->cbData);
|
||||
SecureZeroMemory(pPlainText, pMemBlock->cbData);
|
||||
free(pPlainText);
|
||||
|
||||
ListDictionary_Remove(g_ProtectedMemoryBlocks, pData);
|
||||
|
||||
free(pMemBlock);
|
||||
|
||||
return TRUE;
|
||||
|
||||
out:
|
||||
free(pPlainText);
|
||||
free(pMemBlock);
|
||||
winpr_Cipher_Free(dec);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CryptProtectData(WINPR_ATTR_UNUSED DATA_BLOB* pDataIn, WINPR_ATTR_UNUSED LPCWSTR szDataDescr,
|
||||
WINPR_ATTR_UNUSED DATA_BLOB* pOptionalEntropy,
|
||||
WINPR_ATTR_UNUSED PVOID pvReserved,
|
||||
WINPR_ATTR_UNUSED CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED DATA_BLOB* pDataOut)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptUnprotectData(WINPR_ATTR_UNUSED DATA_BLOB* pDataIn,
|
||||
WINPR_ATTR_UNUSED LPWSTR* ppszDataDescr,
|
||||
WINPR_ATTR_UNUSED DATA_BLOB* pOptionalEntropy,
|
||||
WINPR_ATTR_UNUSED PVOID pvReserved,
|
||||
WINPR_ATTR_UNUSED CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED DATA_BLOB* pDataOut)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptStringToBinaryW(WINPR_ATTR_UNUSED LPCWSTR pszString, WINPR_ATTR_UNUSED DWORD cchString,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED BYTE* pbBinary,
|
||||
WINPR_ATTR_UNUSED DWORD* pcbBinary, WINPR_ATTR_UNUSED DWORD* pdwSkip,
|
||||
WINPR_ATTR_UNUSED DWORD* pdwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptStringToBinaryA(WINPR_ATTR_UNUSED LPCSTR pszString, WINPR_ATTR_UNUSED DWORD cchString,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED BYTE* pbBinary,
|
||||
WINPR_ATTR_UNUSED DWORD* pcbBinary, WINPR_ATTR_UNUSED DWORD* pdwSkip,
|
||||
WINPR_ATTR_UNUSED DWORD* pdwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptBinaryToStringW(WINPR_ATTR_UNUSED CONST BYTE* pbBinary, WINPR_ATTR_UNUSED DWORD cbBinary,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED LPWSTR pszString,
|
||||
WINPR_ATTR_UNUSED DWORD* pcchString)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptBinaryToStringA(WINPR_ATTR_UNUSED CONST BYTE* pbBinary, WINPR_ATTR_UNUSED DWORD cbBinary,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED LPSTR pszString,
|
||||
WINPR_ATTR_UNUSED DWORD* pcchString)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
43
third_party/FreeRDP/winpr/libwinpr/crypto/crypto.h
vendored
Normal file
43
third_party/FreeRDP/winpr/libwinpr/crypto/crypto.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Cryptography API (CryptoAPI)
|
||||
*
|
||||
* Copyright 2012-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 WINPR_CRYPTO_PRIVATE_H
|
||||
#define WINPR_CRYPTO_PRIVATE_H
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE* pData;
|
||||
DWORD cbData;
|
||||
DWORD dwFlags;
|
||||
BYTE key[32];
|
||||
BYTE iv[32];
|
||||
BYTE salt[8];
|
||||
} WINPR_PROTECTED_MEMORY_BLOCK;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LPCSTR lpszStoreProvider;
|
||||
DWORD dwMsgAndCertEncodingType;
|
||||
} WINPR_CERTSTORE;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_CRYPTO_PRIVATE_H */
|
||||
776
third_party/FreeRDP/winpr/libwinpr/crypto/hash.c
vendored
Normal file
776
third_party/FreeRDP/winpr/libwinpr/crypto/hash.c
vendored
Normal file
@@ -0,0 +1,776 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
*
|
||||
* Copyright 2015 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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/md4.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/core_names.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
#ifdef MBEDTLS_MD5_C
|
||||
#include <mbedtls/md5.h>
|
||||
#endif
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <mbedtls/md.h>
|
||||
#if MBEDTLS_VERSION_MAJOR < 3
|
||||
#define mbedtls_md_info_from_ctx(_ctx) (_ctx->md_info)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(WITH_INTERNAL_MD4)
|
||||
#include "md4.h"
|
||||
#endif
|
||||
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
#include "md5.h"
|
||||
#include "hmac_md5.h"
|
||||
#endif
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("crypto.hash")
|
||||
|
||||
/**
|
||||
* HMAC
|
||||
*/
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
extern const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md)
|
||||
{
|
||||
const char* name = winpr_md_type_to_string(md);
|
||||
if (!name)
|
||||
return nullptr;
|
||||
return EVP_get_digestbyname(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
mbedtls_md_type_t winpr_mbedtls_get_md_type(int md)
|
||||
{
|
||||
mbedtls_md_type_t type = MBEDTLS_MD_NONE;
|
||||
|
||||
switch (md)
|
||||
{
|
||||
case WINPR_MD_MD5:
|
||||
type = MBEDTLS_MD_MD5;
|
||||
break;
|
||||
|
||||
case WINPR_MD_SHA1:
|
||||
type = MBEDTLS_MD_SHA1;
|
||||
break;
|
||||
|
||||
case WINPR_MD_SHA224:
|
||||
type = MBEDTLS_MD_SHA224;
|
||||
break;
|
||||
|
||||
case WINPR_MD_SHA256:
|
||||
type = MBEDTLS_MD_SHA256;
|
||||
break;
|
||||
|
||||
case WINPR_MD_SHA384:
|
||||
type = MBEDTLS_MD_SHA384;
|
||||
break;
|
||||
|
||||
case WINPR_MD_SHA512:
|
||||
type = MBEDTLS_MD_SHA512;
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct hash_map
|
||||
{
|
||||
const char* name;
|
||||
WINPR_MD_TYPE md;
|
||||
};
|
||||
static const struct hash_map hashes[] = {
|
||||
{ "md2", WINPR_MD_MD2 }, { "md4", WINPR_MD_MD4 },
|
||||
{ "md5", WINPR_MD_MD5 }, { "sha1", WINPR_MD_SHA1 },
|
||||
{ "sha224", WINPR_MD_SHA224 }, { "sha256", WINPR_MD_SHA256 },
|
||||
{ "sha384", WINPR_MD_SHA384 }, { "sha512", WINPR_MD_SHA512 },
|
||||
{ "sha3_224", WINPR_MD_SHA3_224 }, { "sha3_256", WINPR_MD_SHA3_256 },
|
||||
{ "sha3_384", WINPR_MD_SHA3_384 }, { "sha3_512", WINPR_MD_SHA3_512 },
|
||||
{ "shake128", WINPR_MD_SHAKE128 }, { "shake256", WINPR_MD_SHAKE256 },
|
||||
{ nullptr, WINPR_MD_NONE }
|
||||
};
|
||||
|
||||
WINPR_MD_TYPE winpr_md_type_from_string(const char* name)
|
||||
{
|
||||
const struct hash_map* cur = hashes;
|
||||
while (cur->name)
|
||||
{
|
||||
if (_stricmp(cur->name, name) == 0)
|
||||
return cur->md;
|
||||
cur++;
|
||||
}
|
||||
return WINPR_MD_NONE;
|
||||
}
|
||||
|
||||
const char* winpr_md_type_to_string(WINPR_MD_TYPE md)
|
||||
{
|
||||
const struct hash_map* cur = hashes;
|
||||
while (cur->name)
|
||||
{
|
||||
if (cur->md == md)
|
||||
return cur->name;
|
||||
cur++;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
struct winpr_hmac_ctx_private_st
|
||||
{
|
||||
WINPR_MD_TYPE md;
|
||||
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
WINPR_HMAC_MD5_CTX hmac_md5;
|
||||
#endif
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MAC_CTX* xhmac;
|
||||
#else
|
||||
HMAC_CTX* hmac;
|
||||
#endif
|
||||
#endif
|
||||
#if defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t hmac;
|
||||
#endif
|
||||
};
|
||||
|
||||
WINPR_HMAC_CTX* winpr_HMAC_New(void)
|
||||
{
|
||||
WINPR_HMAC_CTX* ctx = (WINPR_HMAC_CTX*)calloc(1, sizeof(WINPR_HMAC_CTX));
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
|
||||
if (!(ctx->hmac = (HMAC_CTX*)calloc(1, sizeof(HMAC_CTX))))
|
||||
goto fail;
|
||||
|
||||
HMAC_CTX_init(ctx->hmac);
|
||||
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
if (!(ctx->hmac = HMAC_CTX_new()))
|
||||
goto fail;
|
||||
#else
|
||||
EVP_MAC* emac = EVP_MAC_fetch(nullptr, "HMAC", nullptr);
|
||||
if (!emac)
|
||||
goto fail;
|
||||
ctx->xhmac = EVP_MAC_CTX_new(emac);
|
||||
EVP_MAC_free(emac);
|
||||
if (!ctx->xhmac)
|
||||
goto fail;
|
||||
#endif
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_init(&ctx->hmac);
|
||||
#endif
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
winpr_HMAC_Free(ctx);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const void* key, size_t keylen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
ctx->md = md;
|
||||
switch (ctx->md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
hmac_md5_init(&ctx->hmac_md5, key, keylen);
|
||||
return TRUE;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
char* hash = WINPR_CAST_CONST_PTR_AWAY(winpr_md_type_to_string(md), char*);
|
||||
|
||||
if (!ctx->xhmac)
|
||||
return FALSE;
|
||||
|
||||
const char* param_name = OSSL_MAC_PARAM_DIGEST;
|
||||
const OSSL_PARAM param[] = { OSSL_PARAM_construct_utf8_string(param_name, hash, 0),
|
||||
OSSL_PARAM_construct_end() };
|
||||
|
||||
return EVP_MAC_init(ctx->xhmac, key, keylen, param) == 1;
|
||||
#else
|
||||
HMAC_CTX* hmac = ctx->hmac;
|
||||
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
|
||||
|
||||
if (!evp || !hmac)
|
||||
return FALSE;
|
||||
|
||||
if (keylen > INT_MAX)
|
||||
return FALSE;
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
HMAC_Init_ex(hmac, key, (int)keylen, evp, nullptr); /* no return value on OpenSSL 0.9.x */
|
||||
return TRUE;
|
||||
#else
|
||||
|
||||
if (HMAC_Init_ex(hmac, key, (int)keylen, evp, nullptr) == 1)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* hmac = &ctx->hmac;
|
||||
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
|
||||
const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
|
||||
|
||||
if (!md_info || !hmac)
|
||||
return FALSE;
|
||||
|
||||
if (mbedtls_md_info_from_ctx(hmac) != md_info)
|
||||
{
|
||||
mbedtls_md_free(hmac); /* can be called at any time after mbedtls_md_init */
|
||||
|
||||
if (mbedtls_md_setup(hmac, md_info, 1) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (mbedtls_md_hmac_starts(hmac, key, keylen) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const void* input, size_t ilen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
switch (ctx->md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
hmac_md5_update(&ctx->hmac_md5, input, ilen);
|
||||
return TRUE;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
return EVP_MAC_update(ctx->xhmac, input, ilen) == 1;
|
||||
#else
|
||||
HMAC_CTX* hmac = ctx->hmac;
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
HMAC_Update(hmac, input, ilen); /* no return value on OpenSSL 0.9.x */
|
||||
return TRUE;
|
||||
#else
|
||||
|
||||
if (HMAC_Update(hmac, input, ilen) == 1)
|
||||
return TRUE;
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* mdctx = &ctx->hmac;
|
||||
|
||||
if (mbedtls_md_hmac_update(mdctx, input, ilen) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, void* output, size_t olen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
switch (ctx->md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
if (olen < WINPR_MD5_DIGEST_LENGTH)
|
||||
return FALSE;
|
||||
hmac_md5_finalize(&ctx->hmac_md5, output);
|
||||
return TRUE;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
const int rc = EVP_MAC_final(ctx->xhmac, output, nullptr, olen);
|
||||
return (rc == 1);
|
||||
#else
|
||||
HMAC_CTX* hmac = ctx->hmac;
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
HMAC_Final(hmac, output, nullptr); /* no return value on OpenSSL 0.9.x */
|
||||
return TRUE;
|
||||
#else
|
||||
|
||||
if (HMAC_Final(hmac, output, nullptr) == 1)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* mdctx = &ctx->hmac;
|
||||
|
||||
if (mbedtls_md_hmac_finish(mdctx, output) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MAC_CTX_free(ctx->xhmac);
|
||||
#else
|
||||
HMAC_CTX* hmac = ctx->hmac;
|
||||
|
||||
if (hmac)
|
||||
{
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
HMAC_CTX_cleanup(hmac);
|
||||
free(hmac);
|
||||
#else
|
||||
HMAC_CTX_free(hmac);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* hmac = &ctx->hmac;
|
||||
|
||||
if (hmac)
|
||||
mbedtls_md_free(hmac);
|
||||
|
||||
#endif
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
BOOL winpr_HMAC(WINPR_MD_TYPE md, const void* key, size_t keylen, const void* input, size_t ilen,
|
||||
void* output, size_t olen)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
WINPR_HMAC_CTX* ctx = winpr_HMAC_New();
|
||||
|
||||
if (!ctx)
|
||||
return FALSE;
|
||||
|
||||
if (!winpr_HMAC_Init(ctx, md, key, keylen))
|
||||
goto out;
|
||||
|
||||
if (!winpr_HMAC_Update(ctx, input, ilen))
|
||||
goto out;
|
||||
|
||||
if (!winpr_HMAC_Final(ctx, output, olen))
|
||||
goto out;
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_HMAC_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic Digest API
|
||||
*/
|
||||
|
||||
struct winpr_digest_ctx_private_st
|
||||
{
|
||||
WINPR_MD_TYPE md;
|
||||
|
||||
#if defined(WITH_INTERNAL_MD4)
|
||||
WINPR_MD4_CTX md4;
|
||||
#endif
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
WINPR_MD5_CTX md5;
|
||||
#endif
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_MD_CTX* mdctx;
|
||||
#endif
|
||||
#if defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* mdctx;
|
||||
#endif
|
||||
};
|
||||
|
||||
WINPR_DIGEST_CTX* winpr_Digest_New(void)
|
||||
{
|
||||
WINPR_DIGEST_CTX* ctx = calloc(1, sizeof(WINPR_DIGEST_CTX));
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
ctx->mdctx = EVP_MD_CTX_create();
|
||||
#else
|
||||
ctx->mdctx = EVP_MD_CTX_new();
|
||||
#endif
|
||||
if (!ctx->mdctx)
|
||||
goto fail;
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
ctx->mdctx = (mbedtls_md_context_t*)calloc(1, sizeof(mbedtls_md_context_t));
|
||||
|
||||
if (!ctx->mdctx)
|
||||
goto fail;
|
||||
|
||||
mbedtls_md_init(ctx->mdctx);
|
||||
#endif
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
winpr_Digest_Free(ctx);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, const EVP_MD* evp)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
EVP_MD_CTX* mdctx = ctx->mdctx;
|
||||
|
||||
if (!mdctx || !evp)
|
||||
return FALSE;
|
||||
|
||||
if (EVP_DigestInit_ex(mdctx, evp, nullptr) != 1)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to initialize digest %s", winpr_md_type_to_string(ctx->md));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
mbedtls_md_context_t* mdctx = ctx->mdctx;
|
||||
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
|
||||
const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
|
||||
|
||||
if (!md_info)
|
||||
return FALSE;
|
||||
|
||||
if (mbedtls_md_info_from_ctx(mdctx) != md_info)
|
||||
{
|
||||
mbedtls_md_free(mdctx); /* can be called at any time after mbedtls_md_init */
|
||||
|
||||
if (mbedtls_md_setup(mdctx, md_info, 0) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (mbedtls_md_starts(mdctx) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
ctx->md = md;
|
||||
switch (md)
|
||||
{
|
||||
case WINPR_MD_MD5:
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
winpr_MD5_Init(&ctx->md5);
|
||||
return TRUE;
|
||||
#elif defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#if !defined(WITH_INTERNAL_MD5)
|
||||
if (md == WINPR_MD_MD5)
|
||||
{
|
||||
EVP_MD* md5 = EVP_MD_fetch(nullptr, "MD5", "fips=no");
|
||||
BOOL rc = winpr_Digest_Init_Internal(ctx, md5);
|
||||
EVP_MD_free(md5);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
|
||||
EVP_MD_CTX_set_flags(ctx->mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
||||
return winpr_Digest_Init_Internal(ctx, evp);
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
return winpr_Digest_Init_Internal(ctx, md);
|
||||
#endif
|
||||
}
|
||||
default:
|
||||
WLog_ERR(TAG, "Invalid FIPS digest %s requested", winpr_md_type_to_string(md));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
ctx->md = md;
|
||||
switch (md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD4)
|
||||
case WINPR_MD_MD4:
|
||||
winpr_MD4_Init(&ctx->md4);
|
||||
return TRUE;
|
||||
#endif
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
winpr_MD5_Init(&ctx->md5);
|
||||
return TRUE;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
|
||||
return winpr_Digest_Init_Internal(ctx, evp);
|
||||
#else
|
||||
return winpr_Digest_Init_Internal(ctx, md);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
switch (ctx->md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD4)
|
||||
case WINPR_MD_MD4:
|
||||
winpr_MD4_Update(&ctx->md4, input, ilen);
|
||||
return TRUE;
|
||||
#endif
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
winpr_MD5_Update(&ctx->md5, input, ilen);
|
||||
return TRUE;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_MD_CTX* mdctx = ctx->mdctx;
|
||||
|
||||
return EVP_DigestUpdate(mdctx, input, ilen) == 1;
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* mdctx = ctx->mdctx;
|
||||
|
||||
if (mbedtls_md_update(mdctx, input, ilen) != 0)
|
||||
return FALSE;
|
||||
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, void* output, WINPR_ATTR_UNUSED size_t olen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
switch (ctx->md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD4)
|
||||
case WINPR_MD_MD4:
|
||||
if (olen < WINPR_MD4_DIGEST_LENGTH)
|
||||
return FALSE;
|
||||
winpr_MD4_Final(output, &ctx->md4);
|
||||
return TRUE;
|
||||
#endif
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
if (olen < WINPR_MD5_DIGEST_LENGTH)
|
||||
return FALSE;
|
||||
winpr_MD5_Final(output, &ctx->md5);
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_MD_CTX* mdctx = ctx->mdctx;
|
||||
|
||||
return EVP_DigestFinal_ex(mdctx, output, nullptr) == 1;
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* mdctx = ctx->mdctx;
|
||||
|
||||
if (mbedtls_md_finish(mdctx, output) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL winpr_DigestSign_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md, void* key)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
|
||||
if (!evp)
|
||||
return FALSE;
|
||||
|
||||
const int rdsi = EVP_DigestSignInit(ctx->mdctx, nullptr, evp, nullptr, key);
|
||||
return (rdsi > 0);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL winpr_DigestSign_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_MD_CTX* mdctx = ctx->mdctx;
|
||||
|
||||
return (EVP_DigestSignUpdate(mdctx, input, ilen) == 1);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL winpr_DigestSign_Final(WINPR_DIGEST_CTX* ctx, void* output, size_t* piolen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_MD_CTX* mdctx = ctx->mdctx;
|
||||
|
||||
return EVP_DigestSignFinal(mdctx, output, piolen) == 1;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
#if defined(WITH_OPENSSL)
|
||||
if (ctx->mdctx)
|
||||
{
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
EVP_MD_CTX_destroy(ctx->mdctx);
|
||||
#else
|
||||
EVP_MD_CTX_free(ctx->mdctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
if (ctx->mdctx)
|
||||
{
|
||||
mbedtls_md_free(ctx->mdctx);
|
||||
free(ctx->mdctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
BOOL winpr_Digest_Allow_FIPS(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output,
|
||||
size_t olen)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
|
||||
|
||||
if (!ctx)
|
||||
return FALSE;
|
||||
|
||||
if (!winpr_Digest_Init_Allow_FIPS(ctx, md))
|
||||
goto out;
|
||||
|
||||
if (!winpr_Digest_Update(ctx, input, ilen))
|
||||
goto out;
|
||||
|
||||
if (!winpr_Digest_Final(ctx, output, olen))
|
||||
goto out;
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_Digest_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL winpr_Digest(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output, size_t olen)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
|
||||
|
||||
if (!ctx)
|
||||
return FALSE;
|
||||
|
||||
if (!winpr_Digest_Init(ctx, md))
|
||||
goto out;
|
||||
|
||||
if (!winpr_Digest_Update(ctx, input, ilen))
|
||||
goto out;
|
||||
|
||||
if (!winpr_Digest_Final(ctx, output, olen))
|
||||
goto out;
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_Digest_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
56
third_party/FreeRDP/winpr/libwinpr/crypto/hmac_md5.c
vendored
Normal file
56
third_party/FreeRDP/winpr/libwinpr/crypto/hmac_md5.c
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hmac_md5.h"
|
||||
#include "md5.h"
|
||||
|
||||
void hmac_md5_init(WINPR_HMAC_MD5_CTX* ctx, const unsigned char* key, size_t key_len)
|
||||
{
|
||||
const WINPR_HMAC_MD5_CTX empty = WINPR_C_ARRAY_INIT;
|
||||
unsigned char k_ipad[KEY_IOPAD_SIZE] = WINPR_C_ARRAY_INIT;
|
||||
unsigned char k_opad[KEY_IOPAD_SIZE] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
assert(ctx);
|
||||
*ctx = empty;
|
||||
|
||||
if (key_len <= KEY_IOPAD_SIZE)
|
||||
{
|
||||
memcpy(k_ipad, key, key_len);
|
||||
memcpy(k_opad, key, key_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
WINPR_MD5_CTX lctx = WINPR_C_ARRAY_INIT;
|
||||
|
||||
winpr_MD5_Init(&lctx);
|
||||
winpr_MD5_Update(&lctx, key, key_len);
|
||||
winpr_MD5_Final(k_ipad, &lctx);
|
||||
memcpy(k_opad, k_ipad, KEY_IOPAD_SIZE);
|
||||
}
|
||||
for (size_t i = 0; i < KEY_IOPAD_SIZE; i++)
|
||||
{
|
||||
k_ipad[i] ^= 0x36;
|
||||
k_opad[i] ^= 0x5c;
|
||||
}
|
||||
|
||||
winpr_MD5_Init(&ctx->icontext);
|
||||
winpr_MD5_Update(&ctx->icontext, k_ipad, KEY_IOPAD_SIZE);
|
||||
|
||||
winpr_MD5_Init(&ctx->ocontext);
|
||||
winpr_MD5_Update(&ctx->ocontext, k_opad, KEY_IOPAD_SIZE);
|
||||
}
|
||||
|
||||
void hmac_md5_update(WINPR_HMAC_MD5_CTX* ctx, const unsigned char* text, size_t text_len)
|
||||
{
|
||||
assert(ctx);
|
||||
winpr_MD5_Update(&ctx->icontext, text, text_len);
|
||||
}
|
||||
|
||||
void hmac_md5_finalize(WINPR_HMAC_MD5_CTX* ctx, unsigned char* hmac)
|
||||
{
|
||||
assert(ctx);
|
||||
winpr_MD5_Final(hmac, &ctx->icontext);
|
||||
|
||||
winpr_MD5_Update(&ctx->ocontext, hmac, 16);
|
||||
winpr_MD5_Final(hmac, &ctx->ocontext);
|
||||
}
|
||||
19
third_party/FreeRDP/winpr/libwinpr/crypto/hmac_md5.h
vendored
Normal file
19
third_party/FreeRDP/winpr/libwinpr/crypto/hmac_md5.h
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef WINPR_HMAC_MD5
|
||||
#define WINPR_HMAC_MD5
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
#define KEY_IOPAD_SIZE 64
|
||||
typedef struct
|
||||
{
|
||||
WINPR_MD5_CTX icontext;
|
||||
WINPR_MD5_CTX ocontext;
|
||||
} WINPR_HMAC_MD5_CTX;
|
||||
|
||||
void hmac_md5_init(WINPR_HMAC_MD5_CTX* ctx, const unsigned char* key, size_t key_len);
|
||||
void hmac_md5_update(WINPR_HMAC_MD5_CTX* ctx, const unsigned char* text, size_t text_len);
|
||||
void hmac_md5_finalize(WINPR_HMAC_MD5_CTX* ctx, unsigned char* hmac);
|
||||
|
||||
#endif
|
||||
271
third_party/FreeRDP/winpr/libwinpr/crypto/md4.c
vendored
Normal file
271
third_party/FreeRDP/winpr/libwinpr/crypto/md4.c
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD4 Message-Digest Algorithm (RFC 1320).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* (This is a heavily cut-down "BSD license".)
|
||||
*
|
||||
* This differs from Colin Plumb's older public domain implementation in that
|
||||
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||
* unsigned integer data type will do), there's no compile-time endianness
|
||||
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||
* the properties of the two independent implementations.
|
||||
*
|
||||
* The primary goals of this implementation are portability and ease of use.
|
||||
* It is meant to be fast, but not as fast as possible. Some known
|
||||
* optimizations are not included to reduce source code size and avoid
|
||||
* compile-time configuration.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "md4.h"
|
||||
|
||||
/*
|
||||
* The basic MD4 functions.
|
||||
*
|
||||
* F and G are optimized compared to their RFC 1320 definitions, with the
|
||||
* optimization for F borrowed from Colin Plumb's MD5 implementation.
|
||||
*/
|
||||
static inline winpr_MD4_u32plus F(winpr_MD4_u32plus x, winpr_MD4_u32plus y, winpr_MD4_u32plus z)
|
||||
{
|
||||
return ((z) ^ ((x) & ((y) ^ (z))));
|
||||
}
|
||||
static inline winpr_MD4_u32plus G(winpr_MD4_u32plus x, winpr_MD4_u32plus y, winpr_MD4_u32plus z)
|
||||
{
|
||||
return (((x) & ((y) | (z))) | ((y) & (z)));
|
||||
}
|
||||
static inline winpr_MD4_u32plus H(winpr_MD4_u32plus x, winpr_MD4_u32plus y, winpr_MD4_u32plus z)
|
||||
{
|
||||
return ((x) ^ (y) ^ (z));
|
||||
}
|
||||
|
||||
/*
|
||||
* The MD4 transformation for all three rounds.
|
||||
*/
|
||||
#define STEP(f, a, b, c, d, x, s) \
|
||||
(a) += f((b), (c), (d)) + (x); \
|
||||
(a) = (((a) << (s)) | (((a)&0xffffffff) >> (32 - (s))));
|
||||
|
||||
/*
|
||||
* SET reads 4 input bytes in little-endian byte order and stores them in a
|
||||
* properly aligned word in host byte order.
|
||||
*
|
||||
* The check for little-endian architectures that tolerate unaligned memory
|
||||
* accesses is just an optimization. Nothing will break if it fails to detect
|
||||
* a suitable architecture.
|
||||
*
|
||||
* Unfortunately, this optimization may be a C strict aliasing rules violation
|
||||
* if the caller's data buffer has effective type that cannot be aliased by
|
||||
* winpr_MD4_u32plus. In practice, this problem may occur if these MD4 routines are
|
||||
* inlined into a calling function, or with future and dangerously advanced
|
||||
* link-time optimizations. For the time being, keeping these MD4 routines in
|
||||
* their own translation unit avoids the problem.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) (*(const winpr_MD4_u32plus*)&ptr[4ULL * (n)])
|
||||
#define GET(n) SET(n)
|
||||
#else
|
||||
#define SET(n) \
|
||||
(ctx->block[(n)] = (winpr_MD4_u32plus)ptr[4ULL * (n)] | \
|
||||
((winpr_MD4_u32plus)ptr[4ULL * (n) + 1] << 8) | \
|
||||
((winpr_MD4_u32plus)ptr[4ULL * (n) + 2] << 16) | \
|
||||
((winpr_MD4_u32plus)ptr[4ULL * (n) + 3] << 24))
|
||||
#define GET(n) (ctx->block[(n)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This processes one or more 64-byte data blocks, but does NOT update the bit
|
||||
* counters. There are no alignment requirements.
|
||||
*/
|
||||
static const void* body(WINPR_MD4_CTX* ctx, const void* data, size_t size)
|
||||
{
|
||||
const winpr_MD4_u32plus ac1 = 0x5a827999;
|
||||
const winpr_MD4_u32plus ac2 = 0x6ed9eba1;
|
||||
|
||||
const unsigned char* ptr = (const unsigned char*)data;
|
||||
|
||||
winpr_MD4_u32plus a = ctx->a;
|
||||
winpr_MD4_u32plus b = ctx->b;
|
||||
winpr_MD4_u32plus c = ctx->c;
|
||||
winpr_MD4_u32plus d = ctx->d;
|
||||
|
||||
do
|
||||
{
|
||||
const winpr_MD4_u32plus saved_a = a;
|
||||
const winpr_MD4_u32plus saved_b = b;
|
||||
const winpr_MD4_u32plus saved_c = c;
|
||||
const winpr_MD4_u32plus saved_d = d;
|
||||
|
||||
/* Round 1 */
|
||||
STEP(F, a, b, c, d, SET(0), 3)
|
||||
STEP(F, d, a, b, c, SET(1), 7)
|
||||
STEP(F, c, d, a, b, SET(2), 11)
|
||||
STEP(F, b, c, d, a, SET(3), 19)
|
||||
STEP(F, a, b, c, d, SET(4), 3)
|
||||
STEP(F, d, a, b, c, SET(5), 7)
|
||||
STEP(F, c, d, a, b, SET(6), 11)
|
||||
STEP(F, b, c, d, a, SET(7), 19)
|
||||
STEP(F, a, b, c, d, SET(8), 3)
|
||||
STEP(F, d, a, b, c, SET(9), 7)
|
||||
STEP(F, c, d, a, b, SET(10), 11)
|
||||
STEP(F, b, c, d, a, SET(11), 19)
|
||||
STEP(F, a, b, c, d, SET(12), 3)
|
||||
STEP(F, d, a, b, c, SET(13), 7)
|
||||
STEP(F, c, d, a, b, SET(14), 11)
|
||||
STEP(F, b, c, d, a, SET(15), 19)
|
||||
|
||||
/* Round 2 */
|
||||
STEP(G, a, b, c, d, GET(0) + ac1, 3)
|
||||
STEP(G, d, a, b, c, GET(4) + ac1, 5)
|
||||
STEP(G, c, d, a, b, GET(8) + ac1, 9)
|
||||
STEP(G, b, c, d, a, GET(12) + ac1, 13)
|
||||
STEP(G, a, b, c, d, GET(1) + ac1, 3)
|
||||
STEP(G, d, a, b, c, GET(5) + ac1, 5)
|
||||
STEP(G, c, d, a, b, GET(9) + ac1, 9)
|
||||
STEP(G, b, c, d, a, GET(13) + ac1, 13)
|
||||
STEP(G, a, b, c, d, GET(2) + ac1, 3)
|
||||
STEP(G, d, a, b, c, GET(6) + ac1, 5)
|
||||
STEP(G, c, d, a, b, GET(10) + ac1, 9)
|
||||
STEP(G, b, c, d, a, GET(14) + ac1, 13)
|
||||
STEP(G, a, b, c, d, GET(3) + ac1, 3)
|
||||
STEP(G, d, a, b, c, GET(7) + ac1, 5)
|
||||
STEP(G, c, d, a, b, GET(11) + ac1, 9)
|
||||
STEP(G, b, c, d, a, GET(15) + ac1, 13)
|
||||
|
||||
/* Round 3 */
|
||||
STEP(H, a, b, c, d, GET(0) + ac2, 3)
|
||||
STEP(H, d, a, b, c, GET(8) + ac2, 9)
|
||||
STEP(H, c, d, a, b, GET(4) + ac2, 11)
|
||||
STEP(H, b, c, d, a, GET(12) + ac2, 15)
|
||||
STEP(H, a, b, c, d, GET(2) + ac2, 3)
|
||||
STEP(H, d, a, b, c, GET(10) + ac2, 9)
|
||||
STEP(H, c, d, a, b, GET(6) + ac2, 11)
|
||||
STEP(H, b, c, d, a, GET(14) + ac2, 15)
|
||||
STEP(H, a, b, c, d, GET(1) + ac2, 3)
|
||||
STEP(H, d, a, b, c, GET(9) + ac2, 9)
|
||||
STEP(H, c, d, a, b, GET(5) + ac2, 11)
|
||||
STEP(H, b, c, d, a, GET(13) + ac2, 15)
|
||||
STEP(H, a, b, c, d, GET(3) + ac2, 3)
|
||||
STEP(H, d, a, b, c, GET(11) + ac2, 9)
|
||||
STEP(H, c, d, a, b, GET(7) + ac2, 11)
|
||||
STEP(H, b, c, d, a, GET(15) + ac2, 15)
|
||||
|
||||
a += saved_a;
|
||||
b += saved_b;
|
||||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
ctx->c = c;
|
||||
ctx->d = d;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void winpr_MD4_Init(WINPR_MD4_CTX* ctx)
|
||||
{
|
||||
ctx->a = 0x67452301;
|
||||
ctx->b = 0xefcdab89;
|
||||
ctx->c = 0x98badcfe;
|
||||
ctx->d = 0x10325476;
|
||||
|
||||
ctx->lo = 0;
|
||||
ctx->hi = 0;
|
||||
}
|
||||
|
||||
void winpr_MD4_Update(WINPR_MD4_CTX* ctx, const void* data, size_t size)
|
||||
{
|
||||
winpr_MD4_u32plus saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
size_t used = saved_lo & 0x3f;
|
||||
|
||||
if (used)
|
||||
{
|
||||
size_t available = 64 - used;
|
||||
|
||||
if (size < available)
|
||||
{
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[used], data, available);
|
||||
data = (const unsigned char*)data + available;
|
||||
size -= available;
|
||||
body(ctx, ctx->buffer, 64);
|
||||
}
|
||||
|
||||
if (size >= 64)
|
||||
{
|
||||
data = body(ctx, data, size & ~(size_t)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer, data, size);
|
||||
}
|
||||
|
||||
static inline void mdOUT(unsigned char* dst, winpr_MD4_u32plus src)
|
||||
{
|
||||
(dst)[0] = (unsigned char)(src);
|
||||
(dst)[1] = (unsigned char)((src) >> 8);
|
||||
(dst)[2] = (unsigned char)((src) >> 16);
|
||||
(dst)[3] = (unsigned char)((src) >> 24);
|
||||
}
|
||||
|
||||
void winpr_MD4_Final(unsigned char* result, WINPR_MD4_CTX* ctx)
|
||||
{
|
||||
size_t used = ctx->lo & 0x3f;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
size_t available = 64 - used;
|
||||
|
||||
if (available < 8)
|
||||
{
|
||||
memset(&ctx->buffer[used], 0, available);
|
||||
body(ctx, ctx->buffer, 64);
|
||||
used = 0;
|
||||
available = 64;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, available - 8);
|
||||
|
||||
ctx->lo <<= 3;
|
||||
mdOUT(&ctx->buffer[56], ctx->lo);
|
||||
mdOUT(&ctx->buffer[60], ctx->hi);
|
||||
|
||||
body(ctx, ctx->buffer, 64);
|
||||
|
||||
mdOUT(&result[0], ctx->a);
|
||||
mdOUT(&result[4], ctx->b);
|
||||
mdOUT(&result[8], ctx->c);
|
||||
mdOUT(&result[12], ctx->d);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
46
third_party/FreeRDP/winpr/libwinpr/crypto/md4.h
vendored
Normal file
46
third_party/FreeRDP/winpr/libwinpr/crypto/md4.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD4 Message-Digest Algorithm (RFC 1320).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See md4.c for more information.
|
||||
*/
|
||||
|
||||
#if !defined(WINPR_MD4_H)
|
||||
#define WINPR_MD4_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
/* Any 32-bit or wider unsigned integer data type will do */
|
||||
typedef UINT32 winpr_MD4_u32plus;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
winpr_MD4_u32plus lo, hi;
|
||||
winpr_MD4_u32plus a, b, c, d;
|
||||
unsigned char buffer[64];
|
||||
winpr_MD4_u32plus block[16];
|
||||
} WINPR_MD4_CTX;
|
||||
|
||||
extern void winpr_MD4_Init(WINPR_MD4_CTX* ctx);
|
||||
extern void winpr_MD4_Update(WINPR_MD4_CTX* ctx, const void* data, size_t size);
|
||||
extern void winpr_MD4_Final(unsigned char* result, WINPR_MD4_CTX* ctx);
|
||||
|
||||
#endif
|
||||
296
third_party/FreeRDP/winpr/libwinpr/crypto/md5.c
vendored
Normal file
296
third_party/FreeRDP/winpr/libwinpr/crypto/md5.c
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* (This is a heavily cut-down "BSD license".)
|
||||
*
|
||||
* This differs from Colin Plumb's older public domain implementation in that
|
||||
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||
* unsigned integer data type will do), there's no compile-time endianness
|
||||
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||
* the properties of the two independent implementations.
|
||||
*
|
||||
* The primary goals of this implementation are portability and ease of use.
|
||||
* It is meant to be fast, but not as fast as possible. Some known
|
||||
* optimizations are not included to reduce source code size and avoid
|
||||
* compile-time configuration.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
/*
|
||||
* The basic MD5 functions.
|
||||
*
|
||||
* F and G are optimized compared to their RFC 1321 definitions for
|
||||
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
|
||||
* implementation.
|
||||
*/
|
||||
static inline winpr_MD5_u32plus F(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
|
||||
{
|
||||
return ((z) ^ ((x) & ((y) ^ (z))));
|
||||
}
|
||||
static inline winpr_MD5_u32plus G(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
|
||||
{
|
||||
return ((y) ^ ((z) & ((x) ^ (y))));
|
||||
}
|
||||
static inline winpr_MD5_u32plus H(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
|
||||
{
|
||||
return (((x) ^ (y)) ^ (z));
|
||||
}
|
||||
static inline winpr_MD5_u32plus H2(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
|
||||
{
|
||||
return ((x) ^ ((y) ^ (z)));
|
||||
}
|
||||
static inline winpr_MD5_u32plus I(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
|
||||
{
|
||||
return ((y) ^ ((x) | ~(z)));
|
||||
}
|
||||
|
||||
/*
|
||||
* The MD5 transformation for all four rounds.
|
||||
*/
|
||||
#define STEP(f, a, b, c, d, x, t, s) \
|
||||
(a) += f((b), (c), (d)) + (x) + (t); \
|
||||
(a) = (((a) << (s)) | (((a)&0xffffffff) >> (32 - (s)))); \
|
||||
(a) += (b);
|
||||
|
||||
/*
|
||||
* SET reads 4 input bytes in little-endian byte order and stores them in a
|
||||
* properly aligned word in host byte order.
|
||||
*
|
||||
* The check for little-endian architectures that tolerate unaligned memory
|
||||
* accesses is just an optimization. Nothing will break if it fails to detect
|
||||
* a suitable architecture.
|
||||
*
|
||||
* Unfortunately, this optimization may be a C strict aliasing rules violation
|
||||
* if the caller's data buffer has effective type that cannot be aliased by
|
||||
* MD5_u32plus. In practice, this problem may occur if these MD5 routines are
|
||||
* inlined into a calling function, or with future and dangerously advanced
|
||||
* link-time optimizations. For the time being, keeping these MD5 routines in
|
||||
* their own translation unit avoids the problem.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) (*(const winpr_MD5_u32plus*)&ptr[4ULL * (n)])
|
||||
#define GET(n) SET(n)
|
||||
#else
|
||||
#define SET(n) \
|
||||
(ctx->block[(n)] = (winpr_MD5_u32plus)ptr[4ULL * (n)] | \
|
||||
((winpr_MD5_u32plus)ptr[4ULL * (n) + 1] << 8) | \
|
||||
((winpr_MD5_u32plus)ptr[4ULL * (n) + 2] << 16) | \
|
||||
((winpr_MD5_u32plus)ptr[4ULL * (n) + 3] << 24))
|
||||
#define GET(n) (ctx->block[(n)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This processes one or more 64-byte data blocks, but does NOT update the bit
|
||||
* counters. There are no alignment requirements.
|
||||
*/
|
||||
static const void* body(WINPR_MD5_CTX* ctx, const void* data, size_t size)
|
||||
{
|
||||
const unsigned char* ptr = (const unsigned char*)data;
|
||||
|
||||
winpr_MD5_u32plus a = ctx->a;
|
||||
winpr_MD5_u32plus b = ctx->b;
|
||||
winpr_MD5_u32plus c = ctx->c;
|
||||
winpr_MD5_u32plus d = ctx->d;
|
||||
|
||||
do
|
||||
{
|
||||
const winpr_MD5_u32plus saved_a = a;
|
||||
const winpr_MD5_u32plus saved_b = b;
|
||||
const winpr_MD5_u32plus saved_c = c;
|
||||
const winpr_MD5_u32plus saved_d = d;
|
||||
|
||||
/* Round 1 */
|
||||
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
|
||||
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
|
||||
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
|
||||
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
|
||||
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
|
||||
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
|
||||
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
|
||||
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
|
||||
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
|
||||
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
|
||||
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
|
||||
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
|
||||
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
|
||||
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
|
||||
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
|
||||
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
|
||||
|
||||
/* Round 2 */
|
||||
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
|
||||
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
|
||||
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
|
||||
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
|
||||
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
|
||||
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
|
||||
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
|
||||
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
|
||||
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
|
||||
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
|
||||
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
|
||||
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
|
||||
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
|
||||
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
|
||||
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
|
||||
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
|
||||
|
||||
/* Round 3 */
|
||||
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
|
||||
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
|
||||
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
|
||||
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
|
||||
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
|
||||
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
|
||||
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
|
||||
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
|
||||
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
|
||||
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
|
||||
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
|
||||
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
|
||||
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
|
||||
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
|
||||
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
|
||||
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
|
||||
|
||||
/* Round 4 */
|
||||
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
|
||||
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
|
||||
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
|
||||
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
|
||||
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
|
||||
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
|
||||
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
|
||||
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
|
||||
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
|
||||
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
|
||||
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
|
||||
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
|
||||
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
|
||||
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
|
||||
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
|
||||
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
|
||||
|
||||
a += saved_a;
|
||||
b += saved_b;
|
||||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
ctx->c = c;
|
||||
ctx->d = d;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void winpr_MD5_Init(WINPR_MD5_CTX* ctx)
|
||||
{
|
||||
ctx->a = 0x67452301;
|
||||
ctx->b = 0xefcdab89;
|
||||
ctx->c = 0x98badcfe;
|
||||
ctx->d = 0x10325476;
|
||||
|
||||
ctx->lo = 0;
|
||||
ctx->hi = 0;
|
||||
}
|
||||
|
||||
void winpr_MD5_Update(WINPR_MD5_CTX* ctx, const void* data, size_t size)
|
||||
{
|
||||
winpr_MD5_u32plus saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
size_t used = saved_lo & 0x3f;
|
||||
|
||||
if (used)
|
||||
{
|
||||
size_t available = 64 - used;
|
||||
|
||||
if (size < available)
|
||||
{
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[used], data, available);
|
||||
data = (const unsigned char*)data + available;
|
||||
size -= available;
|
||||
body(ctx, ctx->buffer, 64);
|
||||
}
|
||||
|
||||
if (size >= 64)
|
||||
{
|
||||
data = body(ctx, data, size & ~(size_t)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer, data, size);
|
||||
}
|
||||
|
||||
static inline void mdOUT(unsigned char* dst, winpr_MD5_u32plus src)
|
||||
{
|
||||
(dst)[0] = (unsigned char)(src);
|
||||
(dst)[1] = (unsigned char)((src) >> 8);
|
||||
(dst)[2] = (unsigned char)((src) >> 16);
|
||||
(dst)[3] = (unsigned char)((src) >> 24);
|
||||
}
|
||||
|
||||
void winpr_MD5_Final(unsigned char* result, WINPR_MD5_CTX* ctx)
|
||||
{
|
||||
size_t used = ctx->lo & 0x3f;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
size_t available = 64 - used;
|
||||
|
||||
if (available < 8)
|
||||
{
|
||||
memset(&ctx->buffer[used], 0, available);
|
||||
body(ctx, ctx->buffer, 64);
|
||||
used = 0;
|
||||
available = 64;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, available - 8);
|
||||
|
||||
ctx->lo <<= 3;
|
||||
mdOUT(&ctx->buffer[56], ctx->lo);
|
||||
mdOUT(&ctx->buffer[60], ctx->hi);
|
||||
|
||||
body(ctx, ctx->buffer, 64);
|
||||
|
||||
mdOUT(&result[0], ctx->a);
|
||||
mdOUT(&result[4], ctx->b);
|
||||
mdOUT(&result[8], ctx->c);
|
||||
mdOUT(&result[12], ctx->d);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
48
third_party/FreeRDP/winpr/libwinpr/crypto/md5.h
vendored
Normal file
48
third_party/FreeRDP/winpr/libwinpr/crypto/md5.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See md5.c for more information.
|
||||
*/
|
||||
|
||||
#if !defined(WINPR_MD5_H)
|
||||
#define WINPR_MD5_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
/* Any 32-bit or wider unsigned integer data type will do */
|
||||
typedef UINT32 winpr_MD5_u32plus;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
winpr_MD5_u32plus lo, hi;
|
||||
winpr_MD5_u32plus a, b, c, d;
|
||||
unsigned char buffer[64];
|
||||
winpr_MD5_u32plus block[16];
|
||||
} WINPR_MD5_CTX;
|
||||
|
||||
extern void winpr_MD5_Init(WINPR_MD5_CTX* ctx);
|
||||
extern void winpr_MD5_Update(WINPR_MD5_CTX* ctx, const void* data, size_t size);
|
||||
extern void winpr_MD5_Final(unsigned char* result, WINPR_MD5_CTX* ctx);
|
||||
|
||||
#endif
|
||||
83
third_party/FreeRDP/winpr/libwinpr/crypto/rand.c
vendored
Normal file
83
third_party/FreeRDP/winpr/libwinpr/crypto/rand.c
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
*
|
||||
* Copyright 2015 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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#ifdef MBEDTLS_HAVEGE_C
|
||||
#include <mbedtls/havege.h>
|
||||
#endif
|
||||
#include <mbedtls/hmac_drbg.h>
|
||||
#endif
|
||||
|
||||
int winpr_RAND(void* output, size_t len)
|
||||
{
|
||||
#if defined(WITH_OPENSSL)
|
||||
if (len > INT_MAX)
|
||||
return -1;
|
||||
if (RAND_bytes(output, (int)len) != 1)
|
||||
return -1;
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
#if defined(MBEDTLS_HAVEGE_C)
|
||||
mbedtls_havege_state hs;
|
||||
mbedtls_havege_init(&hs);
|
||||
|
||||
if (mbedtls_havege_random(&hs, output, len) != 0)
|
||||
return -1;
|
||||
|
||||
mbedtls_havege_free(&hs);
|
||||
#else
|
||||
int status;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_hmac_drbg_context hmac_drbg;
|
||||
const mbedtls_md_info_t* md_info;
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_hmac_drbg_init(&hmac_drbg);
|
||||
|
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
|
||||
if ((status = mbedtls_hmac_drbg_seed(&hmac_drbg, md_info, mbedtls_entropy_func, &entropy,
|
||||
nullptr, 0)) != 0)
|
||||
return -1;
|
||||
|
||||
status = mbedtls_hmac_drbg_random(&hmac_drbg, output, len);
|
||||
mbedtls_hmac_drbg_free(&hmac_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
|
||||
if (status != 0)
|
||||
return -1;
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int winpr_RAND_pseudo(void* output, size_t len)
|
||||
{
|
||||
return winpr_RAND(output, len);
|
||||
}
|
||||
89
third_party/FreeRDP/winpr/libwinpr/crypto/rc4.c
vendored
Normal file
89
third_party/FreeRDP/winpr/libwinpr/crypto/rc4.c
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* RC4 implementation for RDP
|
||||
*
|
||||
* Copyright 2023 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2023 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
|
||||
#include "rc4.h"
|
||||
|
||||
#define CTX_SIZE 256
|
||||
|
||||
struct winpr_int_rc4_ctx
|
||||
{
|
||||
size_t i;
|
||||
size_t j;
|
||||
BYTE s[CTX_SIZE];
|
||||
BYTE t[CTX_SIZE];
|
||||
};
|
||||
|
||||
static void swap(BYTE* p1, BYTE* p2)
|
||||
{
|
||||
BYTE t = *p1;
|
||||
*p1 = *p2;
|
||||
*p2 = t;
|
||||
}
|
||||
|
||||
winpr_int_RC4_CTX* winpr_int_rc4_new(const BYTE* key, size_t keylength)
|
||||
{
|
||||
winpr_int_RC4_CTX* ctx = calloc(1, sizeof(winpr_int_RC4_CTX));
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
|
||||
for (size_t i = 0; i < CTX_SIZE; i++)
|
||||
{
|
||||
ctx->s[i] = WINPR_ASSERTING_INT_CAST(BYTE, i);
|
||||
ctx->t[i] = key[i % keylength];
|
||||
}
|
||||
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < CTX_SIZE; i++)
|
||||
{
|
||||
j = (j + ctx->s[i] + ctx->t[i]) % CTX_SIZE;
|
||||
swap(&ctx->s[i], &ctx->s[j]);
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void winpr_int_rc4_free(winpr_int_RC4_CTX* ctx)
|
||||
{
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
BOOL winpr_int_rc4_update(winpr_int_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
size_t t1 = ctx->i;
|
||||
size_t t2 = ctx->j;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
t1 = (t1 + 1) % CTX_SIZE;
|
||||
t2 = (t2 + ctx->s[t1]) % CTX_SIZE;
|
||||
swap(&ctx->s[t1], &ctx->s[t2]);
|
||||
|
||||
const size_t idx = ((size_t)ctx->s[t1] + ctx->s[t2]) % CTX_SIZE;
|
||||
const BYTE val = ctx->s[idx];
|
||||
const BYTE out = *input++ ^ val;
|
||||
*output++ = out;
|
||||
}
|
||||
|
||||
ctx->i = t1;
|
||||
ctx->j = t2;
|
||||
return TRUE;
|
||||
}
|
||||
35
third_party/FreeRDP/winpr/libwinpr/crypto/rc4.h
vendored
Normal file
35
third_party/FreeRDP/winpr/libwinpr/crypto/rc4.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* RC4 implementation for RDP
|
||||
*
|
||||
* Copyright 2023 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2023 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 WINPR_RC4_H
|
||||
#define WINPR_RC4_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/winpr.h>
|
||||
|
||||
typedef struct winpr_int_rc4_ctx winpr_int_RC4_CTX;
|
||||
|
||||
void winpr_int_rc4_free(winpr_int_RC4_CTX* ctx);
|
||||
|
||||
WINPR_ATTR_MALLOC(winpr_int_rc4_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
winpr_int_RC4_CTX* winpr_int_rc4_new(const BYTE* key, size_t keylength);
|
||||
BOOL winpr_int_rc4_update(winpr_int_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output);
|
||||
|
||||
#endif
|
||||
29
third_party/FreeRDP/winpr/libwinpr/crypto/test/CMakeLists.txt
vendored
Normal file
29
third_party/FreeRDP/winpr/libwinpr/crypto/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
set(MODULE_NAME "TestCrypto")
|
||||
set(MODULE_PREFIX "TEST_CRYPTO")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS TestCryptoHash.c TestCryptoRand.c TestCryptoCipher.c TestCryptoProtectData.c
|
||||
TestCryptoProtectMemory.c TestCryptoCertEnumCertificatesInStore.c
|
||||
)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
if(WIN32)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32 crypt32 cryptui)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
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 "WinPR/Test")
|
||||
88
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoCertEnumCertificatesInStore.c
vendored
Normal file
88
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoCertEnumCertificatesInStore.c
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
//#define WITH_CRYPTUI 1
|
||||
#endif
|
||||
|
||||
#ifdef WITH_CRYPTUI
|
||||
#include <cryptuiapi.h>
|
||||
#endif
|
||||
|
||||
int TestCryptoCertEnumCertificatesInStore(int argc, char* argv[])
|
||||
{
|
||||
int index = 0;
|
||||
DWORD status = 0;
|
||||
LPTSTR pszNameString = nullptr;
|
||||
HCERTSTORE hCertStore = nullptr;
|
||||
PCCERT_CONTEXT pCertContext = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
/**
|
||||
* System Store Locations:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa388136/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Requires elevated rights:
|
||||
* hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
||||
* CERT_SYSTEM_STORE_LOCAL_MACHINE, _T("Remote Desktop"));
|
||||
*/
|
||||
|
||||
hCertStore = CertOpenSystemStore(0, _T("MY"));
|
||||
// hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
||||
// CERT_SYSTEM_STORE_CURRENT_USER, _T("MY"));
|
||||
|
||||
if (!hCertStore)
|
||||
{
|
||||
printf("Failed to open system store\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
|
||||
while ((pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)))
|
||||
{
|
||||
status =
|
||||
CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, nullptr, 0);
|
||||
if (status == 0)
|
||||
return -1;
|
||||
|
||||
pszNameString = (LPTSTR)calloc(status, sizeof(TCHAR));
|
||||
if (!pszNameString)
|
||||
{
|
||||
printf("Unable to allocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr,
|
||||
pszNameString, status);
|
||||
if (status == 0)
|
||||
{
|
||||
free(pszNameString);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_tprintf(_T("Certificate #%d: %s\n"), index++, pszNameString);
|
||||
|
||||
free(pszNameString);
|
||||
|
||||
#ifdef WITH_CRYPTUI
|
||||
CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pCertContext, nullptr, nullptr, 0,
|
||||
nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!CertCloseStore(hCertStore, 0))
|
||||
{
|
||||
printf("Failed to close system store\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
251
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoCipher.c
vendored
Normal file
251
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoCipher.c
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/ssl.h>
|
||||
|
||||
static BOOL test_crypto_cipher_aes_128_cbc(BOOL ex)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
BYTE key[16] = "0123456789abcdeF";
|
||||
BYTE iv[16] = "1234567887654321";
|
||||
BYTE ibuf[1024] = WINPR_C_ARRAY_INIT;
|
||||
BYTE obuf[1024] = WINPR_C_ARRAY_INIT;
|
||||
size_t ilen = 0;
|
||||
size_t olen = 0;
|
||||
size_t xlen = 0;
|
||||
const char plaintext[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua.";
|
||||
|
||||
/* encrypt */
|
||||
|
||||
WINPR_CIPHER_CTX* ctx = nullptr;
|
||||
if (ex)
|
||||
ctx = winpr_Cipher_NewEx(WINPR_CIPHER_AES_128_CBC, WINPR_ENCRYPT, key, sizeof(key), iv,
|
||||
sizeof(iv));
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
else
|
||||
ctx = winpr_Cipher_New(WINPR_CIPHER_AES_128_CBC, WINPR_ENCRYPT, key, iv);
|
||||
#endif
|
||||
if (!ctx)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_New (encrypt) failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ilen = strnlen(plaintext, sizeof(plaintext)) + 1;
|
||||
memcpy(ibuf, plaintext, ilen);
|
||||
|
||||
ilen = ((ilen + 15) / 16) * 16;
|
||||
olen = 0;
|
||||
xlen = 0;
|
||||
|
||||
if (!winpr_Cipher_Update(ctx, ibuf, ilen, obuf, &olen))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_New (encrypt) failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
xlen += olen;
|
||||
|
||||
if (!winpr_Cipher_Final(ctx, obuf + xlen, &olen))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_Final (encrypt) failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
xlen += olen;
|
||||
|
||||
if (xlen != ilen)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: error, xlen (%" PRIuz ") != ilen (%" PRIuz ") (encrypt)\n",
|
||||
__func__, xlen, ilen);
|
||||
goto out;
|
||||
}
|
||||
|
||||
winpr_Cipher_Free(ctx);
|
||||
ctx = nullptr;
|
||||
|
||||
/* decrypt */
|
||||
|
||||
if (ex)
|
||||
ctx = winpr_Cipher_NewEx(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, key, sizeof(key), iv,
|
||||
sizeof(iv));
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
else
|
||||
ctx = winpr_Cipher_New(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, key, iv);
|
||||
|
||||
#endif
|
||||
if (!ctx)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_New (decrypt) failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memset(ibuf, 0, sizeof(ibuf));
|
||||
memcpy(ibuf, obuf, xlen);
|
||||
memset(obuf, 0, sizeof(obuf));
|
||||
|
||||
ilen = xlen;
|
||||
olen = 0;
|
||||
xlen = 0;
|
||||
|
||||
if (!winpr_Cipher_Update(ctx, ibuf, ilen, obuf, &olen))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_New (decrypt) failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
xlen += olen;
|
||||
|
||||
if (!winpr_Cipher_Final(ctx, obuf + xlen, &olen))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_Final (decrypt) failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
xlen += olen;
|
||||
|
||||
if (xlen != ilen)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: error, xlen (%" PRIuz ") != ilen (%" PRIuz ") (decrypt)\n",
|
||||
__func__, xlen, ilen);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp((const char*)obuf, plaintext) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: error, decrypted data does not match plaintext\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
|
||||
out:
|
||||
winpr_Cipher_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char TEST_RC4_KEY[] = "Key";
|
||||
static const char TEST_RC4_PLAINTEXT[] = "Plaintext";
|
||||
static const char TEST_RC4_CIPHERTEXT[] = "\xBB\xF3\x16\xE8\xD9\x40\xAF\x0A\xD3";
|
||||
|
||||
static BOOL test_crypto_cipher_rc4(void)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
WINPR_RC4_CTX* ctx = nullptr;
|
||||
|
||||
const size_t len = strnlen(TEST_RC4_PLAINTEXT, sizeof(TEST_RC4_PLAINTEXT));
|
||||
BYTE* text = (BYTE*)calloc(1, len);
|
||||
if (!text)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: failed to allocate text buffer (len=%" PRIuz ")\n", __func__,
|
||||
len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((ctx = winpr_RC4_New(TEST_RC4_KEY, strnlen(TEST_RC4_KEY, sizeof(TEST_RC4_KEY)))) == nullptr)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_RC4_New failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
rc = winpr_RC4_Update(ctx, len, (const BYTE*)TEST_RC4_PLAINTEXT, text);
|
||||
winpr_RC4_Free(ctx);
|
||||
if (!rc)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_RC4_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(text, TEST_RC4_CIPHERTEXT, len) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(text, len, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_RC4_CIPHERTEXT, len, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "%s: unexpected RC4 ciphertext: Actual: %s Expected: %s\n", __func__,
|
||||
actual, expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
|
||||
out:
|
||||
free(text);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const BYTE* TEST_RAND_DATA =
|
||||
(BYTE*)"\x1F\xC2\xEE\x4C\xA3\x66\x80\xA2\xCE\xFE\x56\xB4\x9E\x08\x30\x96"
|
||||
"\x33\x6A\xA9\x6D\x36\xFD\x3C\xB7\x83\x04\x4E\x5E\xDC\x22\xCD\xF3"
|
||||
"\x48\xDF\x3A\x2A\x61\xF1\xA8\xFA\x1F\xC6\xC7\x1B\x81\xB4\xE1\x0E"
|
||||
"\xCB\xA2\xEF\xA1\x12\x4A\x83\xE5\x1D\x72\x1D\x2D\x26\xA8\x6B\xC0";
|
||||
|
||||
static const BYTE* TEST_CIPHER_KEY =
|
||||
(BYTE*)"\x9D\x7C\xC0\xA1\x94\x3B\x07\x67\x2F\xD3\x83\x10\x51\x83\x38\x0E"
|
||||
"\x1C\x74\x8C\x4E\x15\x79\xD6\xFF\xE2\xF0\x37\x7F\x8C\xD7\xD2\x13";
|
||||
|
||||
static const BYTE* TEST_CIPHER_IV =
|
||||
(BYTE*)"\xFE\xE3\x9F\xF0\xD1\x5E\x37\x0C\xAB\xAB\x9B\x04\xF3\xDB\x99\x15";
|
||||
|
||||
static BOOL test_crypto_cipher_key(void)
|
||||
{
|
||||
int status = 0;
|
||||
BYTE key[32] = WINPR_C_ARRAY_INIT;
|
||||
BYTE iv[16] = WINPR_C_ARRAY_INIT;
|
||||
BYTE salt[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
|
||||
|
||||
status = winpr_Cipher_BytesToKey(WINPR_CIPHER_AES_256_CBC, WINPR_MD_SHA1, salt, TEST_RAND_DATA,
|
||||
64, 4, key, iv);
|
||||
|
||||
if (status != 32 || memcmp(key, TEST_CIPHER_KEY, 32) != 0 ||
|
||||
memcmp(iv, TEST_CIPHER_IV, 16) != 0)
|
||||
{
|
||||
char* akstr = nullptr;
|
||||
char* ekstr = nullptr;
|
||||
char* aivstr = nullptr;
|
||||
char* eivstr = nullptr;
|
||||
|
||||
akstr = winpr_BinToHexString(key, 32, 0);
|
||||
ekstr = winpr_BinToHexString(TEST_CIPHER_KEY, 32, 0);
|
||||
|
||||
aivstr = winpr_BinToHexString(iv, 16, 0);
|
||||
eivstr = winpr_BinToHexString(TEST_CIPHER_IV, 16, 0);
|
||||
|
||||
(void)fprintf(stderr, "Unexpected EVP_BytesToKey Key: Actual: %s, Expected: %s\n", akstr,
|
||||
ekstr);
|
||||
(void)fprintf(stderr, "Unexpected EVP_BytesToKey IV : Actual: %s, Expected: %s\n", aivstr,
|
||||
eivstr);
|
||||
|
||||
free(akstr);
|
||||
free(ekstr);
|
||||
free(aivstr);
|
||||
free(eivstr);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TestCryptoCipher(int argc, char* argv[])
|
||||
{
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
|
||||
|
||||
if (!test_crypto_cipher_aes_128_cbc(TRUE))
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_cipher_aes_128_cbc(FALSE))
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_cipher_rc4())
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_cipher_key())
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
318
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoHash.c
vendored
Normal file
318
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoHash.c
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/ssl.h>
|
||||
|
||||
static const char TEST_MD5_DATA[] = "test";
|
||||
static const BYTE TEST_MD5_HASH[] =
|
||||
"\x09\x8f\x6b\xcd\x46\x21\xd3\x73\xca\xde\x4e\x83\x26\x27\xb4\xf6";
|
||||
|
||||
static BOOL test_crypto_hash_md5(void)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
BYTE hash[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_DIGEST_CTX* ctx = nullptr;
|
||||
|
||||
if (!(ctx = winpr_Digest_New()))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_New failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
if (!winpr_Digest_Init(ctx, WINPR_MD_MD5))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Init failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Update(ctx, (const BYTE*)TEST_MD5_DATA,
|
||||
strnlen(TEST_MD5_DATA, sizeof(TEST_MD5_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Final(ctx, hash, sizeof(hash)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Final failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (memcmp(hash, TEST_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(hash, WINPR_MD5_DIGEST_LENGTH, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_MD5_HASH, WINPR_MD5_DIGEST_LENGTH, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "unexpected MD5 hash: Actual: %s Expected: %s\n", actual, expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_Digest_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char TEST_MD4_DATA[] = "test";
|
||||
static const BYTE TEST_MD4_HASH[] =
|
||||
"\xdb\x34\x6d\x69\x1d\x7a\xcc\x4d\xc2\x62\x5d\xb1\x9f\x9e\x3f\x52";
|
||||
|
||||
static BOOL test_crypto_hash_md4(void)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
BYTE hash[WINPR_MD4_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_DIGEST_CTX* ctx = nullptr;
|
||||
|
||||
if (!(ctx = winpr_Digest_New()))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_New failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
if (!winpr_Digest_Init(ctx, WINPR_MD_MD4))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Init failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Update(ctx, (const BYTE*)TEST_MD4_DATA,
|
||||
strnlen(TEST_MD4_DATA, sizeof(TEST_MD4_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Final(ctx, hash, sizeof(hash)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Final failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (memcmp(hash, TEST_MD4_HASH, WINPR_MD4_DIGEST_LENGTH) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(hash, WINPR_MD4_DIGEST_LENGTH, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_MD4_HASH, WINPR_MD4_DIGEST_LENGTH, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "unexpected MD4 hash: Actual: %s Expected: %s\n", actual, expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_Digest_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char TEST_SHA1_DATA[] = "test";
|
||||
static const BYTE TEST_SHA1_HASH[] =
|
||||
"\xa9\x4a\x8f\xe5\xcc\xb1\x9b\xa6\x1c\x4c\x08\x73\xd3\x91\xe9\x87\x98\x2f\xbb\xd3";
|
||||
|
||||
static BOOL test_crypto_hash_sha1(void)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
BYTE hash[WINPR_SHA1_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_DIGEST_CTX* ctx = nullptr;
|
||||
|
||||
if (!(ctx = winpr_Digest_New()))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_New failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
if (!winpr_Digest_Init(ctx, WINPR_MD_SHA1))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Init failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Update(ctx, (const BYTE*)TEST_SHA1_DATA,
|
||||
strnlen(TEST_SHA1_DATA, sizeof(TEST_SHA1_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Final(ctx, hash, sizeof(hash)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Final failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(hash, TEST_SHA1_HASH, WINPR_MD5_DIGEST_LENGTH) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(hash, WINPR_SHA1_DIGEST_LENGTH, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "unexpected SHA1 hash: Actual: %s Expected: %s\n", actual, expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_Digest_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char TEST_HMAC_MD5_DATA[] = "Hi There";
|
||||
static const BYTE TEST_HMAC_MD5_KEY[] =
|
||||
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
|
||||
static const BYTE TEST_HMAC_MD5_HASH[] =
|
||||
"\xb5\x79\x91\xa2\x20\x3d\x49\x2d\x73\xfb\x71\x43\xdf\xc5\x08\x28";
|
||||
|
||||
static BOOL test_crypto_hash_hmac_md5(void)
|
||||
{
|
||||
BYTE hash[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_HMAC_CTX* ctx = nullptr;
|
||||
BOOL result = FALSE;
|
||||
|
||||
if (!(ctx = winpr_HMAC_New()))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_New failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!winpr_HMAC_Init(ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, WINPR_MD5_DIGEST_LENGTH))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Init failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Update(ctx, (const BYTE*)TEST_HMAC_MD5_DATA,
|
||||
strnlen(TEST_HMAC_MD5_DATA, sizeof(TEST_HMAC_MD5_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Update(ctx, (const BYTE*)TEST_HMAC_MD5_DATA,
|
||||
strnlen(TEST_HMAC_MD5_DATA, sizeof(TEST_HMAC_MD5_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Final(ctx, hash, sizeof(hash)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Final failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(hash, TEST_HMAC_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(hash, WINPR_MD5_DIGEST_LENGTH, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_HMAC_MD5_HASH, WINPR_MD5_DIGEST_LENGTH, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "unexpected HMAC-MD5 hash: Actual: %s Expected: %s\n", actual,
|
||||
expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_HMAC_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char TEST_HMAC_SHA1_DATA[] = "Hi There";
|
||||
static const BYTE TEST_HMAC_SHA1_KEY[] =
|
||||
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
|
||||
static const BYTE TEST_HMAC_SHA1_HASH[] =
|
||||
"\xab\x23\x08\x2d\xca\x0c\x75\xea\xca\x60\x09\xc0\xb8\x8c\x2d\xf4\xf4\xbf\x88\xee";
|
||||
|
||||
static BOOL test_crypto_hash_hmac_sha1(void)
|
||||
{
|
||||
BYTE hash[WINPR_SHA1_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_HMAC_CTX* ctx = nullptr;
|
||||
BOOL result = FALSE;
|
||||
|
||||
if (!(ctx = winpr_HMAC_New()))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_New failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!winpr_HMAC_Init(ctx, WINPR_MD_SHA1, TEST_HMAC_SHA1_KEY, WINPR_SHA1_DIGEST_LENGTH))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Init failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Update(ctx, (const BYTE*)TEST_HMAC_SHA1_DATA,
|
||||
strnlen(TEST_HMAC_SHA1_DATA, sizeof(TEST_HMAC_SHA1_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Update(ctx, (const BYTE*)TEST_HMAC_SHA1_DATA,
|
||||
strnlen(TEST_HMAC_SHA1_DATA, sizeof(TEST_HMAC_SHA1_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Final(ctx, hash, sizeof(hash)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Final failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(hash, TEST_HMAC_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(hash, WINPR_SHA1_DIGEST_LENGTH, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_HMAC_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "unexpected HMAC-SHA1 hash: Actual: %s Expected: %s\n", actual,
|
||||
expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_HMAC_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
int TestCryptoHash(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
|
||||
|
||||
if (!test_crypto_hash_md5())
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_hash_md4())
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_hash_sha1())
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_hash_hmac_md5())
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_hash_hmac_sha1())
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
10
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoProtectData.c
vendored
Normal file
10
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoProtectData.c
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
int TestCryptoProtectData(int argc, char* argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
55
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoProtectMemory.c
vendored
Normal file
55
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoProtectMemory.c
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/ssl.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
static const char* SECRET_PASSWORD_TEST = "MySecretPassword123!";
|
||||
|
||||
int TestCryptoProtectMemory(int argc, char* argv[])
|
||||
{
|
||||
UINT32 cbPlainText = 0;
|
||||
UINT32 cbCipherText = 0;
|
||||
const char* pPlainText = nullptr;
|
||||
BYTE* pCipherText = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
pPlainText = SECRET_PASSWORD_TEST;
|
||||
cbPlainText = strlen(pPlainText) + 1;
|
||||
cbCipherText = cbPlainText +
|
||||
(CRYPTPROTECTMEMORY_BLOCK_SIZE - (cbPlainText % CRYPTPROTECTMEMORY_BLOCK_SIZE));
|
||||
printf("cbPlainText: %" PRIu32 " cbCipherText: %" PRIu32 "\n", cbPlainText, cbCipherText);
|
||||
pCipherText = (BYTE*)malloc(cbCipherText);
|
||||
if (!pCipherText)
|
||||
{
|
||||
printf("Unable to allocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
CopyMemory(pCipherText, pPlainText, cbPlainText);
|
||||
ZeroMemory(&pCipherText[cbPlainText], (cbCipherText - cbPlainText));
|
||||
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
|
||||
|
||||
if (!CryptProtectMemory(pCipherText, cbCipherText, CRYPTPROTECTMEMORY_SAME_PROCESS))
|
||||
{
|
||||
printf("CryptProtectMemory failure\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("PlainText: %s (cbPlainText = %" PRIu32 ", cbCipherText = %" PRIu32 ")\n", pPlainText,
|
||||
cbPlainText, cbCipherText);
|
||||
winpr_HexDump("crypto.test", WLOG_DEBUG, pCipherText, cbCipherText);
|
||||
|
||||
if (!CryptUnprotectMemory(pCipherText, cbCipherText, CRYPTPROTECTMEMORY_SAME_PROCESS))
|
||||
{
|
||||
printf("CryptUnprotectMemory failure\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Decrypted CipherText: %s\n", pCipherText);
|
||||
SecureZeroMemory(pCipherText, cbCipherText);
|
||||
free(pCipherText);
|
||||
return 0;
|
||||
}
|
||||
27
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoRand.c
vendored
Normal file
27
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoRand.c
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
int TestCryptoRand(int argc, char* argv[])
|
||||
{
|
||||
char* str = nullptr;
|
||||
BYTE rnd[16] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (winpr_RAND(rnd, sizeof(rnd)) < 0)
|
||||
return -1;
|
||||
|
||||
str = winpr_BinToHexString(rnd, sizeof(rnd), FALSE);
|
||||
// (void)fprintf(stderr, "Rand: %s\n", str);
|
||||
free(str);
|
||||
|
||||
if (memcmp(rnd, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
26
third_party/FreeRDP/winpr/libwinpr/dsparse/CMakeLists.txt
vendored
Normal file
26
third_party/FreeRDP/winpr/libwinpr/dsparse/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-dsparse cmake build script
|
||||
#
|
||||
# Copyright 2012 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.
|
||||
|
||||
winpr_module_add(dsparse.c)
|
||||
|
||||
if(WIN32)
|
||||
winpr_library_add_public(ntdsapi)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
7
third_party/FreeRDP/winpr/libwinpr/dsparse/ModuleOptions.cmake
vendored
Normal file
7
third_party/FreeRDP/winpr/libwinpr/dsparse/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
set(MINWIN_LAYER "0")
|
||||
set(MINWIN_GROUP "none")
|
||||
set(MINWIN_MAJOR_VERSION "0")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "dsparse")
|
||||
set(MINWIN_LONG_NAME "Domain Controller and Replication Management Functions")
|
||||
set(MODULE_LIBRARY_NAME "${MINWIN_SHORT_NAME}")
|
||||
142
third_party/FreeRDP/winpr/libwinpr/dsparse/dsparse.c
vendored
Normal file
142
third_party/FreeRDP/winpr/libwinpr/dsparse/dsparse.c
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Active Directory Domain Services Parsing Functions
|
||||
*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/dsparse.h>
|
||||
#include <winpr/assert.h>
|
||||
|
||||
/**
|
||||
* dsparse.dll:
|
||||
*
|
||||
* DsCrackSpnA
|
||||
* DsCrackSpnW
|
||||
* DsCrackUnquotedMangledRdnA
|
||||
* DsCrackUnquotedMangledRdnW
|
||||
* DsGetRdnW
|
||||
* DsIsMangledDnA
|
||||
* DsIsMangledDnW
|
||||
* DsIsMangledRdnValueA
|
||||
* DsIsMangledRdnValueW
|
||||
* DsMakeSpnA
|
||||
* DsMakeSpnW
|
||||
* DsQuoteRdnValueA
|
||||
* DsQuoteRdnValueW
|
||||
* DsUnquoteRdnValueA
|
||||
* DsUnquoteRdnValueW
|
||||
*/
|
||||
|
||||
#if !defined(_WIN32) || defined(_UWP)
|
||||
|
||||
DWORD DsMakeSpnW(LPCWSTR ServiceClass, LPCWSTR ServiceName, LPCWSTR InstanceName,
|
||||
USHORT InstancePort, LPCWSTR Referrer, DWORD* pcSpnLength, LPWSTR pszSpn)
|
||||
{
|
||||
DWORD res = ERROR_OUTOFMEMORY;
|
||||
char* ServiceClassA = nullptr;
|
||||
char* ServiceNameA = nullptr;
|
||||
char* InstanceNameA = nullptr;
|
||||
char* ReferrerA = nullptr;
|
||||
char* pszSpnA = nullptr;
|
||||
size_t length = 0;
|
||||
|
||||
WINPR_ASSERT(ServiceClass);
|
||||
WINPR_ASSERT(ServiceName);
|
||||
WINPR_ASSERT(pcSpnLength);
|
||||
|
||||
length = *pcSpnLength;
|
||||
if ((length > 0) && pszSpn)
|
||||
pszSpnA = calloc(length + 1, sizeof(char));
|
||||
|
||||
if (ServiceClass)
|
||||
{
|
||||
ServiceClassA = ConvertWCharToUtf8Alloc(ServiceClass, nullptr);
|
||||
if (!ServiceClassA)
|
||||
goto fail;
|
||||
}
|
||||
if (ServiceName)
|
||||
{
|
||||
ServiceNameA = ConvertWCharToUtf8Alloc(ServiceName, nullptr);
|
||||
if (!ServiceNameA)
|
||||
goto fail;
|
||||
}
|
||||
if (InstanceName)
|
||||
{
|
||||
InstanceNameA = ConvertWCharToUtf8Alloc(InstanceName, nullptr);
|
||||
if (!InstanceNameA)
|
||||
goto fail;
|
||||
}
|
||||
if (Referrer)
|
||||
{
|
||||
ReferrerA = ConvertWCharToUtf8Alloc(Referrer, nullptr);
|
||||
if (!ReferrerA)
|
||||
goto fail;
|
||||
}
|
||||
res = DsMakeSpnA(ServiceClassA, ServiceNameA, InstanceNameA, InstancePort, ReferrerA,
|
||||
pcSpnLength, pszSpnA);
|
||||
|
||||
if (res == ERROR_SUCCESS)
|
||||
{
|
||||
if (ConvertUtf8NToWChar(pszSpnA, *pcSpnLength, pszSpn, length) < 0)
|
||||
res = ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(ServiceClassA);
|
||||
free(ServiceNameA);
|
||||
free(InstanceNameA);
|
||||
free(ReferrerA);
|
||||
free(pszSpnA);
|
||||
return res;
|
||||
}
|
||||
|
||||
DWORD DsMakeSpnA(LPCSTR ServiceClass, LPCSTR ServiceName, LPCSTR InstanceName, USHORT InstancePort,
|
||||
LPCSTR Referrer, DWORD* pcSpnLength, LPSTR pszSpn)
|
||||
{
|
||||
DWORD SpnLength = 0;
|
||||
DWORD ServiceClassLength = 0;
|
||||
DWORD ServiceNameLength = 0;
|
||||
|
||||
WINPR_ASSERT(ServiceClass);
|
||||
WINPR_ASSERT(ServiceName);
|
||||
WINPR_ASSERT(pcSpnLength);
|
||||
|
||||
WINPR_UNUSED(InstanceName);
|
||||
WINPR_UNUSED(InstancePort);
|
||||
WINPR_UNUSED(Referrer);
|
||||
|
||||
if ((*pcSpnLength != 0) && (pszSpn == nullptr))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
ServiceClassLength = (DWORD)strlen(ServiceClass);
|
||||
ServiceNameLength = (DWORD)strlen(ServiceName);
|
||||
|
||||
SpnLength = ServiceClassLength + 1 + ServiceNameLength + 1;
|
||||
|
||||
if ((*pcSpnLength == 0) || (*pcSpnLength < SpnLength))
|
||||
{
|
||||
*pcSpnLength = SpnLength;
|
||||
return ERROR_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
(void)sprintf_s(pszSpn, *pcSpnLength, "%s/%s", ServiceClass, ServiceName);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
23
third_party/FreeRDP/winpr/libwinpr/dsparse/test/CMakeLists.txt
vendored
Normal file
23
third_party/FreeRDP/winpr/libwinpr/dsparse/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
set(MODULE_NAME "TestDsParse")
|
||||
set(MODULE_PREFIX "TEST_DSPARSE")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS TestDsMakeSpn.c)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
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 "WinPR/Test")
|
||||
155
third_party/FreeRDP/winpr/libwinpr/dsparse/test/TestDsMakeSpn.c
vendored
Normal file
155
third_party/FreeRDP/winpr/libwinpr/dsparse/test/TestDsMakeSpn.c
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/dsparse.h>
|
||||
|
||||
static BOOL test_DsMakeSpnA(void)
|
||||
{
|
||||
LPCSTR testServiceClass = "HTTP";
|
||||
LPCSTR testServiceName = "LAB1-W2K8R2-GW.lab1.awake.local";
|
||||
LPCSTR testSpn = "HTTP/LAB1-W2K8R2-GW.lab1.awake.local";
|
||||
BOOL rc = FALSE;
|
||||
CHAR Spn[100] = WINPR_C_ARRAY_INIT;
|
||||
DWORD status = 0;
|
||||
DWORD SpnLength = -1;
|
||||
|
||||
status =
|
||||
DsMakeSpnA(testServiceClass, testServiceName, nullptr, 0, nullptr, &SpnLength, nullptr);
|
||||
|
||||
if (status != ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
printf("DsMakeSpnA: expected ERROR_INVALID_PARAMETER\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
SpnLength = 0;
|
||||
status =
|
||||
DsMakeSpnA(testServiceClass, testServiceName, nullptr, 0, nullptr, &SpnLength, nullptr);
|
||||
|
||||
if (status != ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
printf("DsMakeSpnA: expected ERROR_BUFFER_OVERFLOW\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (SpnLength != 37)
|
||||
{
|
||||
printf("DsMakeSpnA: SpnLength mismatch: Actual: %" PRIu32 ", Expected: 37\n", SpnLength);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = DsMakeSpnA(testServiceClass, testServiceName, nullptr, 0, nullptr, &SpnLength, Spn);
|
||||
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
printf("DsMakeSpnA: expected ERROR_SUCCESS\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (strcmp(Spn, testSpn) != 0)
|
||||
{
|
||||
printf("DsMakeSpnA: SPN mismatch: Actual: %s, Expected: %s\n", Spn, testSpn);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printf("DsMakeSpnA: %s\n", Spn);
|
||||
rc = TRUE;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL test_DsMakeSpnW(void)
|
||||
{
|
||||
const CHAR ctestServiceClass[] = { 'H', 'T', 'T', 'P', '\0' };
|
||||
const CHAR ctestServiceName[] = { 'L', 'A', 'B', '1', '-', 'W', '2', 'K', '8', 'R', '2',
|
||||
'-', 'G', 'W', '.', 'l', 'a', 'b', '1', '.', 'a', 'w',
|
||||
'a', 'k', 'e', '.', 'l', 'o', 'c', 'a', 'l', '\0' };
|
||||
const CHAR ctestSpn[] = { 'H', 'T', 'T', 'P', '/', 'L', 'A', 'B', '1', '-', 'W', '2', 'K',
|
||||
'8', 'R', '2', '-', 'G', 'W', '.', 'l', 'a', 'b', '1', '.', 'a',
|
||||
'w', 'a', 'k', 'e', '.', 'l', 'o', 'c', 'a', 'l', '\0' };
|
||||
WCHAR testServiceClass[ARRAYSIZE(ctestServiceClass)] = WINPR_C_ARRAY_INIT;
|
||||
WCHAR testServiceName[ARRAYSIZE(ctestServiceName)] = WINPR_C_ARRAY_INIT;
|
||||
WCHAR testSpn[ARRAYSIZE(ctestSpn)] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
BOOL rc = FALSE;
|
||||
WCHAR Spn[100] = WINPR_C_ARRAY_INIT;
|
||||
DWORD status = 0;
|
||||
DWORD SpnLength = -1;
|
||||
|
||||
(void)ConvertUtf8NToWChar(ctestServiceClass, ARRAYSIZE(ctestServiceClass), testServiceClass,
|
||||
ARRAYSIZE(testServiceClass));
|
||||
(void)ConvertUtf8NToWChar(ctestServiceName, ARRAYSIZE(ctestServiceName), testServiceName,
|
||||
ARRAYSIZE(testServiceName));
|
||||
(void)ConvertUtf8NToWChar(ctestSpn, ARRAYSIZE(ctestSpn), testSpn, ARRAYSIZE(testSpn));
|
||||
|
||||
status =
|
||||
DsMakeSpnW(testServiceClass, testServiceName, nullptr, 0, nullptr, &SpnLength, nullptr);
|
||||
|
||||
if (status != ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
printf("DsMakeSpnW: expected ERROR_INVALID_PARAMETER\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
SpnLength = 0;
|
||||
status =
|
||||
DsMakeSpnW(testServiceClass, testServiceName, nullptr, 0, nullptr, &SpnLength, nullptr);
|
||||
|
||||
if (status != ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
printf("DsMakeSpnW: expected ERROR_BUFFER_OVERFLOW\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (SpnLength != 37)
|
||||
{
|
||||
printf("DsMakeSpnW: SpnLength mismatch: Actual: %" PRIu32 ", Expected: 37\n", SpnLength);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = DsMakeSpnW(testServiceClass, testServiceName, nullptr, 0, nullptr, &SpnLength, Spn);
|
||||
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
printf("DsMakeSpnW: expected ERROR_SUCCESS\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (_wcscmp(Spn, testSpn) != 0)
|
||||
{
|
||||
char buffer1[8192] = WINPR_C_ARRAY_INIT;
|
||||
char buffer2[8192] = WINPR_C_ARRAY_INIT;
|
||||
char* SpnA = buffer1;
|
||||
char* testSpnA = buffer2;
|
||||
|
||||
(void)ConvertWCharToUtf8(Spn, SpnA, ARRAYSIZE(buffer1));
|
||||
(void)ConvertWCharToUtf8(testSpn, testSpnA, ARRAYSIZE(buffer2));
|
||||
printf("DsMakeSpnW: SPN mismatch: Actual: %s, Expected: %s\n", SpnA, testSpnA);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[8192] = WINPR_C_ARRAY_INIT;
|
||||
char* SpnA = buffer;
|
||||
|
||||
(void)ConvertWCharToUtf8(Spn, SpnA, ARRAYSIZE(buffer));
|
||||
printf("DsMakeSpnW: %s\n", SpnA);
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
int TestDsMakeSpn(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (!test_DsMakeSpnA())
|
||||
return -1;
|
||||
if (!test_DsMakeSpnW())
|
||||
return -2;
|
||||
return 0;
|
||||
}
|
||||
5
third_party/FreeRDP/winpr/libwinpr/dummy.c
vendored
Normal file
5
third_party/FreeRDP/winpr/libwinpr/dummy.c
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
int winpr_dummy()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
22
third_party/FreeRDP/winpr/libwinpr/environment/CMakeLists.txt
vendored
Normal file
22
third_party/FreeRDP/winpr/libwinpr/environment/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-environment cmake build script
|
||||
#
|
||||
# Copyright 2012 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.
|
||||
|
||||
winpr_module_add(environment.c)
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
9
third_party/FreeRDP/winpr/libwinpr/environment/ModuleOptions.cmake
vendored
Normal file
9
third_party/FreeRDP/winpr/libwinpr/environment/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
set(MINWIN_LAYER "1")
|
||||
set(MINWIN_GROUP "core")
|
||||
set(MINWIN_MAJOR_VERSION "2")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "processenvironment")
|
||||
set(MINWIN_LONG_NAME "Process Environment Functions")
|
||||
set(MODULE_LIBRARY_NAME
|
||||
"api-ms-win-${MINWIN_GROUP}-${MINWIN_SHORT_NAME}-l${MINWIN_LAYER}-${MINWIN_MAJOR_VERSION}-${MINWIN_MINOR_VERSION}"
|
||||
)
|
||||
760
third_party/FreeRDP/winpr/libwinpr/environment/environment.c
vendored
Normal file
760
third_party/FreeRDP/winpr/libwinpr/environment/environment.c
vendored
Normal file
@@ -0,0 +1,760 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Process Environment Functions
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2013 Thincast Technologies GmbH
|
||||
* Copyright 2013 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/platform.h>
|
||||
#include <winpr/error.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#include <winpr/environment.h>
|
||||
|
||||
#include "../log.h"
|
||||
|
||||
#define TAG WINPR_TAG("environment")
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WINPR_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(__IOS__)
|
||||
|
||||
#elif defined(__MACOSX__)
|
||||
#include <crt_externs.h>
|
||||
#define environ (*_NSGetEnviron())
|
||||
#endif
|
||||
|
||||
DWORD GetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer)
|
||||
{
|
||||
size_t length = 0;
|
||||
char* cwd = nullptr;
|
||||
char* ccwd = nullptr;
|
||||
|
||||
do
|
||||
{
|
||||
length += MAX_PATH;
|
||||
char* tmp = realloc(cwd, length);
|
||||
if (!tmp)
|
||||
{
|
||||
free(cwd);
|
||||
return 0;
|
||||
}
|
||||
cwd = tmp;
|
||||
|
||||
ccwd = getcwd(cwd, length);
|
||||
} while (!ccwd && (errno == ERANGE));
|
||||
|
||||
if (!ccwd)
|
||||
{
|
||||
free(cwd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = strnlen(cwd, length);
|
||||
|
||||
if ((nBufferLength == 0) && (lpBuffer == nullptr))
|
||||
{
|
||||
free(cwd);
|
||||
return (DWORD)length;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lpBuffer == nullptr)
|
||||
{
|
||||
free(cwd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((length + 1) > nBufferLength)
|
||||
{
|
||||
free(cwd);
|
||||
return (DWORD)(length + 1);
|
||||
}
|
||||
|
||||
memcpy(lpBuffer, cwd, length + 1);
|
||||
free(cwd);
|
||||
return (DWORD)length;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD GetCurrentDirectoryW(WINPR_ATTR_UNUSED DWORD nBufferLength, WINPR_ATTR_UNUSED LPWSTR lpBuffer)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL SetCurrentDirectoryA(WINPR_ATTR_UNUSED LPCSTR lpPathName)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetCurrentDirectoryW(WINPR_ATTR_UNUSED LPCWSTR lpPathName)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD SearchPathA(WINPR_ATTR_UNUSED LPCSTR lpPath, WINPR_ATTR_UNUSED LPCSTR lpFileName,
|
||||
WINPR_ATTR_UNUSED LPCSTR lpExtension, WINPR_ATTR_UNUSED DWORD nBufferLength,
|
||||
WINPR_ATTR_UNUSED LPSTR lpBuffer, WINPR_ATTR_UNUSED LPSTR* lpFilePart)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD SearchPathW(WINPR_ATTR_UNUSED LPCWSTR lpPath, WINPR_ATTR_UNUSED LPCWSTR lpFileName,
|
||||
WINPR_ATTR_UNUSED LPCWSTR lpExtension, WINPR_ATTR_UNUSED DWORD nBufferLength,
|
||||
WINPR_ATTR_UNUSED LPWSTR lpBuffer, WINPR_ATTR_UNUSED LPWSTR* lpFilePart)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPSTR GetCommandLineA(VOID)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LPWSTR GetCommandLineW(VOID)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL NeedCurrentDirectoryForExePathA(WINPR_ATTR_UNUSED LPCSTR ExeName)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL NeedCurrentDirectoryForExePathW(WINPR_ATTR_UNUSED LPCWSTR ExeName)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) || defined(_UWP)
|
||||
|
||||
DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
|
||||
{
|
||||
#if !defined(_UWP)
|
||||
size_t length = 0;
|
||||
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
char* env = getenv(lpName);
|
||||
|
||||
if (!env)
|
||||
{
|
||||
SetLastError(ERROR_ENVVAR_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = strlen(env);
|
||||
|
||||
if ((length + 1 > nSize) || (!lpBuffer))
|
||||
return (DWORD)length + 1;
|
||||
|
||||
CopyMemory(lpBuffer, env, length);
|
||||
lpBuffer[length] = '\0';
|
||||
|
||||
return (DWORD)length;
|
||||
#else
|
||||
SetLastError(ERROR_ENVVAR_NOT_FOUND);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
DWORD GetEnvironmentVariableW(WINPR_ATTR_UNUSED LPCWSTR lpName, WINPR_ATTR_UNUSED LPWSTR lpBuffer,
|
||||
WINPR_ATTR_UNUSED DWORD nSize)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
SetLastError(ERROR_ENVVAR_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL SetEnvironmentVariableA(LPCSTR lpName, LPCSTR lpValue)
|
||||
{
|
||||
#if !defined(_UWP)
|
||||
if (!lpName)
|
||||
return FALSE;
|
||||
|
||||
if (lpValue)
|
||||
{
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
if (0 != setenv(lpName, lpValue, 1))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
if (0 != unsetenv(lpName))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL SetEnvironmentVariableW(WINPR_ATTR_UNUSED LPCWSTR lpName, WINPR_ATTR_UNUSED LPCWSTR lpValue)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetEnvironmentStrings function:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms683187/
|
||||
*
|
||||
* The GetEnvironmentStrings function returns a pointer to a block of memory
|
||||
* that contains the environment variables of the calling process (both the
|
||||
* system and the user environment variables). Each environment block contains
|
||||
* the environment variables in the following format:
|
||||
*
|
||||
* Var1=Value1\0
|
||||
* Var2=Value2\0
|
||||
* Var3=Value3\0
|
||||
* ...
|
||||
* VarN=ValueN\0\0
|
||||
*/
|
||||
|
||||
extern char** environ;
|
||||
|
||||
LPCH GetEnvironmentStringsA(VOID)
|
||||
{
|
||||
#if !defined(_UWP)
|
||||
size_t offset = 0;
|
||||
char** envp = environ;
|
||||
const size_t blocksize = 128;
|
||||
size_t cchEnvironmentBlock = blocksize;
|
||||
LPCH lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock, sizeof(CHAR));
|
||||
|
||||
if (!lpszEnvironmentBlock)
|
||||
return nullptr;
|
||||
|
||||
while (*envp)
|
||||
{
|
||||
const size_t length = strlen(*envp);
|
||||
const size_t required = offset + length + 8ull;
|
||||
if (required > UINT32_MAX)
|
||||
{
|
||||
WLog_ERR(TAG, "Environment block too large: %" PRIuz, required);
|
||||
|
||||
free(lpszEnvironmentBlock);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (required > cchEnvironmentBlock)
|
||||
{
|
||||
size_t new_size = cchEnvironmentBlock;
|
||||
do
|
||||
{
|
||||
new_size += blocksize;
|
||||
} while (new_size <= required);
|
||||
LPCH new_blk = (LPCH)realloc(lpszEnvironmentBlock, new_size * sizeof(CHAR));
|
||||
if (!new_blk)
|
||||
{
|
||||
free(lpszEnvironmentBlock);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
lpszEnvironmentBlock = new_blk;
|
||||
cchEnvironmentBlock = new_size;
|
||||
}
|
||||
|
||||
char* p = &(lpszEnvironmentBlock[offset]);
|
||||
|
||||
CopyMemory(p, *envp, length * sizeof(CHAR));
|
||||
p[length] = '\0';
|
||||
|
||||
offset += (length + 1ull);
|
||||
envp++;
|
||||
}
|
||||
|
||||
lpszEnvironmentBlock[offset] = '\0';
|
||||
|
||||
return lpszEnvironmentBlock;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
LPWCH GetEnvironmentStringsW(VOID)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL SetEnvironmentStringsA(WINPR_ATTR_UNUSED LPCH NewEnvironment)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetEnvironmentStringsW(WINPR_ATTR_UNUSED LPWCH NewEnvironment)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD ExpandEnvironmentStringsA(WINPR_ATTR_UNUSED LPCSTR lpSrc, WINPR_ATTR_UNUSED LPSTR lpDst,
|
||||
WINPR_ATTR_UNUSED DWORD nSize)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD ExpandEnvironmentStringsW(WINPR_ATTR_UNUSED LPCWSTR lpSrc, WINPR_ATTR_UNUSED LPWSTR lpDst,
|
||||
WINPR_ATTR_UNUSED DWORD nSize)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL FreeEnvironmentStringsA(LPCH lpszEnvironmentBlock)
|
||||
{
|
||||
free(lpszEnvironmentBlock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL FreeEnvironmentStringsW(LPWCH lpszEnvironmentBlock)
|
||||
{
|
||||
free(lpszEnvironmentBlock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge)
|
||||
{
|
||||
const char* cp = nullptr;
|
||||
char* p = nullptr;
|
||||
size_t offset = 0;
|
||||
size_t length = 0;
|
||||
const char* envp = nullptr;
|
||||
DWORD cchEnvironmentBlock = 0;
|
||||
LPCH lpszEnvironmentBlock = nullptr;
|
||||
const char** mergeStrings = nullptr;
|
||||
size_t mergeStringLength = 0;
|
||||
size_t mergeArraySize = 128;
|
||||
size_t mergeLength = 0;
|
||||
size_t foundMerge = 0;
|
||||
char* foundEquals = nullptr;
|
||||
|
||||
mergeStrings = (LPCSTR*)calloc(mergeArraySize, sizeof(char*));
|
||||
|
||||
if (!mergeStrings)
|
||||
return nullptr;
|
||||
|
||||
mergeStringLength = 0;
|
||||
|
||||
cp = merge;
|
||||
|
||||
while (*cp && *(cp + 1))
|
||||
{
|
||||
length = strlen(cp);
|
||||
|
||||
if (mergeStringLength == mergeArraySize)
|
||||
{
|
||||
const char** new_str = nullptr;
|
||||
|
||||
mergeArraySize += 128;
|
||||
new_str = (const char**)realloc((void*)mergeStrings, mergeArraySize * sizeof(char*));
|
||||
|
||||
if (!new_str)
|
||||
{
|
||||
free((void*)mergeStrings);
|
||||
return nullptr;
|
||||
}
|
||||
mergeStrings = new_str;
|
||||
}
|
||||
|
||||
mergeStrings[mergeStringLength] = cp;
|
||||
cp += length + 1;
|
||||
mergeStringLength++;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
|
||||
cchEnvironmentBlock = 128;
|
||||
lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock, sizeof(CHAR));
|
||||
|
||||
if (!lpszEnvironmentBlock)
|
||||
{
|
||||
free((void*)mergeStrings);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
envp = original;
|
||||
|
||||
while ((original != nullptr) && (*envp && *(envp + 1)))
|
||||
{
|
||||
size_t old_offset = offset;
|
||||
length = strlen(envp);
|
||||
|
||||
while ((offset + length + 8) > cchEnvironmentBlock)
|
||||
{
|
||||
cchEnvironmentBlock *= 2;
|
||||
LPCH tmp = (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock * sizeof(CHAR));
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
free((void*)lpszEnvironmentBlock);
|
||||
free((void*)mergeStrings);
|
||||
return nullptr;
|
||||
}
|
||||
lpszEnvironmentBlock = tmp;
|
||||
}
|
||||
|
||||
p = &(lpszEnvironmentBlock[offset]);
|
||||
|
||||
// check if this value is in the mergeStrings
|
||||
foundMerge = 0;
|
||||
for (size_t run = 0; run < mergeStringLength; run++)
|
||||
{
|
||||
if (!mergeStrings[run])
|
||||
continue;
|
||||
|
||||
mergeLength = strlen(mergeStrings[run]);
|
||||
foundEquals = strstr(mergeStrings[run], "=");
|
||||
|
||||
if (!foundEquals)
|
||||
continue;
|
||||
|
||||
const intptr_t len = foundEquals - mergeStrings[run] + 1;
|
||||
if (strncmp(envp, mergeStrings[run], WINPR_ASSERTING_INT_CAST(size_t, len)) == 0)
|
||||
{
|
||||
// found variable in merge list ... use this ....
|
||||
if (*(foundEquals + 1) == '\0')
|
||||
{
|
||||
// check if the argument is set ... if not remove variable ...
|
||||
foundMerge = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((offset + mergeLength + 8) > cchEnvironmentBlock)
|
||||
{
|
||||
cchEnvironmentBlock *= 2;
|
||||
LPCH tmp =
|
||||
(LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock * sizeof(CHAR));
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
free((void*)lpszEnvironmentBlock);
|
||||
free((void*)mergeStrings);
|
||||
return nullptr;
|
||||
}
|
||||
lpszEnvironmentBlock = tmp;
|
||||
p = &(lpszEnvironmentBlock[old_offset]);
|
||||
}
|
||||
|
||||
foundMerge = 1;
|
||||
CopyMemory(p, mergeStrings[run], mergeLength);
|
||||
mergeStrings[run] = nullptr;
|
||||
p[mergeLength] = '\0';
|
||||
offset += (mergeLength + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundMerge == 0)
|
||||
{
|
||||
CopyMemory(p, envp, length * sizeof(CHAR));
|
||||
p[length] = '\0';
|
||||
offset += (length + 1);
|
||||
}
|
||||
|
||||
envp += (length + 1);
|
||||
}
|
||||
|
||||
// now merge the not already merged env
|
||||
for (size_t run = 0; run < mergeStringLength; run++)
|
||||
{
|
||||
if (!mergeStrings[run])
|
||||
continue;
|
||||
|
||||
mergeLength = strlen(mergeStrings[run]);
|
||||
|
||||
while ((offset + mergeLength + 8) > cchEnvironmentBlock)
|
||||
{
|
||||
cchEnvironmentBlock *= 2;
|
||||
LPCH tmp = (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock * sizeof(CHAR));
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
free((void*)lpszEnvironmentBlock);
|
||||
free((void*)mergeStrings);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
lpszEnvironmentBlock = tmp;
|
||||
}
|
||||
|
||||
p = &(lpszEnvironmentBlock[offset]);
|
||||
|
||||
CopyMemory(p, mergeStrings[run], mergeLength);
|
||||
mergeStrings[run] = nullptr;
|
||||
p[mergeLength] = '\0';
|
||||
offset += (mergeLength + 1);
|
||||
}
|
||||
|
||||
lpszEnvironmentBlock[offset] = '\0';
|
||||
|
||||
free((void*)mergeStrings);
|
||||
|
||||
return lpszEnvironmentBlock;
|
||||
}
|
||||
|
||||
DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
|
||||
{
|
||||
size_t vLength = 0;
|
||||
char* env = nullptr;
|
||||
char* foundEquals = nullptr;
|
||||
const char* penvb = envBlock;
|
||||
size_t nLength = 0;
|
||||
size_t fLength = 0;
|
||||
size_t lpNameLength = 0;
|
||||
|
||||
if (!lpName || nullptr == envBlock)
|
||||
return 0;
|
||||
|
||||
lpNameLength = strlen(lpName);
|
||||
|
||||
if (lpNameLength < 1)
|
||||
return 0;
|
||||
|
||||
while (*penvb && *(penvb + 1))
|
||||
{
|
||||
fLength = strlen(penvb);
|
||||
foundEquals = strstr(penvb, "=");
|
||||
|
||||
if (!foundEquals)
|
||||
{
|
||||
/* if no = sign is found the envBlock is broken */
|
||||
return 0;
|
||||
}
|
||||
|
||||
nLength = WINPR_ASSERTING_INT_CAST(size_t, (foundEquals - penvb));
|
||||
|
||||
if (nLength != lpNameLength)
|
||||
{
|
||||
penvb += (fLength + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(penvb, lpName, nLength) == 0)
|
||||
{
|
||||
env = foundEquals + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
penvb += (fLength + 1);
|
||||
}
|
||||
|
||||
if (!env)
|
||||
return 0;
|
||||
|
||||
vLength = strlen(env);
|
||||
if (vLength >= UINT32_MAX)
|
||||
return 0;
|
||||
|
||||
if ((vLength + 1 > nSize) || (!lpBuffer))
|
||||
return (DWORD)vLength + 1;
|
||||
|
||||
CopyMemory(lpBuffer, env, vLength + 1);
|
||||
|
||||
return (DWORD)vLength;
|
||||
}
|
||||
|
||||
BOOL SetEnvironmentVariableEBA(LPSTR* envBlock, LPCSTR lpName, LPCSTR lpValue)
|
||||
{
|
||||
size_t length = 0;
|
||||
char* envstr = nullptr;
|
||||
char* newEB = nullptr;
|
||||
|
||||
if (!lpName)
|
||||
return FALSE;
|
||||
|
||||
if (lpValue)
|
||||
{
|
||||
length = (strlen(lpName) + strlen(lpValue) + 2); /* +2 because of = and \0 */
|
||||
envstr = (char*)malloc(length + 1); /* +1 because of closing \0 */
|
||||
|
||||
if (!envstr)
|
||||
return FALSE;
|
||||
|
||||
(void)sprintf_s(envstr, length, "%s=%s", lpName, lpValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = strlen(lpName) + 2; /* +2 because of = and \0 */
|
||||
envstr = (char*)malloc(length + 1); /* +1 because of closing \0 */
|
||||
|
||||
if (!envstr)
|
||||
return FALSE;
|
||||
|
||||
(void)sprintf_s(envstr, length, "%s=", lpName);
|
||||
}
|
||||
|
||||
envstr[length] = '\0';
|
||||
|
||||
newEB = MergeEnvironmentStrings((LPCSTR)*envBlock, envstr);
|
||||
|
||||
free(envstr);
|
||||
free(*envBlock);
|
||||
|
||||
*envBlock = newEB;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock)
|
||||
{
|
||||
char* p = nullptr;
|
||||
SSIZE_T index = 0;
|
||||
size_t count = 0;
|
||||
size_t length = 0;
|
||||
char** envp = nullptr;
|
||||
|
||||
count = 0;
|
||||
if (!lpszEnvironmentBlock)
|
||||
return nullptr;
|
||||
|
||||
p = (char*)lpszEnvironmentBlock;
|
||||
|
||||
while (p[0] && p[1])
|
||||
{
|
||||
length = strlen(p);
|
||||
p += (length + 1);
|
||||
count++;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
p = (char*)lpszEnvironmentBlock;
|
||||
|
||||
envp = (char**)calloc(count + 1, sizeof(char*));
|
||||
if (!envp)
|
||||
return nullptr;
|
||||
envp[count] = nullptr;
|
||||
|
||||
while (p[0] && p[1])
|
||||
{
|
||||
length = strlen(p);
|
||||
envp[index] = _strdup(p);
|
||||
if (!envp[index])
|
||||
{
|
||||
for (index -= 1; index >= 0; --index)
|
||||
{
|
||||
free(envp[index]);
|
||||
}
|
||||
free((void*)envp);
|
||||
return nullptr;
|
||||
}
|
||||
p += (length + 1);
|
||||
index++;
|
||||
}
|
||||
|
||||
return envp;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// https://devblogs.microsoft.com/oldnewthing/20100203-00/?p=15083
|
||||
#define WINPR_MAX_ENVIRONMENT_LENGTH 2048
|
||||
|
||||
DWORD GetEnvironmentVariableX(const char* lpName, char* lpBuffer, DWORD nSize)
|
||||
{
|
||||
DWORD result = 0;
|
||||
DWORD nSizeW = 0;
|
||||
LPWSTR lpNameW = nullptr;
|
||||
LPWSTR lpBufferW = nullptr;
|
||||
LPSTR lpBufferA = lpBuffer;
|
||||
|
||||
lpNameW = ConvertUtf8ToWCharAlloc(lpName, nullptr);
|
||||
if (!lpNameW)
|
||||
goto cleanup;
|
||||
|
||||
if (!lpBuffer)
|
||||
{
|
||||
char lpBufferMaxA[WINPR_MAX_ENVIRONMENT_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WCHAR lpBufferMaxW[WINPR_MAX_ENVIRONMENT_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
LPSTR lpTmpBuffer = lpBufferMaxA;
|
||||
|
||||
nSizeW = ARRAYSIZE(lpBufferMaxW);
|
||||
|
||||
result = GetEnvironmentVariableW(lpNameW, lpBufferMaxW, nSizeW);
|
||||
|
||||
SSIZE_T rc =
|
||||
ConvertWCharNToUtf8(lpBufferMaxW, nSizeW, lpTmpBuffer, ARRAYSIZE(lpBufferMaxA));
|
||||
if ((rc < 0) || (rc >= UINT32_MAX))
|
||||
goto cleanup;
|
||||
|
||||
result = (DWORD)rc + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSizeW = nSize;
|
||||
lpBufferW = calloc(nSizeW + 1, sizeof(WCHAR));
|
||||
|
||||
if (!lpBufferW)
|
||||
goto cleanup;
|
||||
|
||||
result = GetEnvironmentVariableW(lpNameW, lpBufferW, nSizeW);
|
||||
|
||||
if (result == 0)
|
||||
goto cleanup;
|
||||
|
||||
SSIZE_T rc = ConvertWCharNToUtf8(lpBufferW, nSizeW, lpBufferA, nSize);
|
||||
if ((rc < 0) || (rc > UINT32_MAX))
|
||||
goto cleanup;
|
||||
|
||||
result = (DWORD)rc;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(lpBufferW);
|
||||
free(lpNameW);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
DWORD GetEnvironmentVariableX(const char* lpName, char* lpBuffer, DWORD nSize)
|
||||
{
|
||||
return GetEnvironmentVariableA(lpName, lpBuffer, nSize);
|
||||
}
|
||||
|
||||
#endif
|
||||
25
third_party/FreeRDP/winpr/libwinpr/environment/test/CMakeLists.txt
vendored
Normal file
25
third_party/FreeRDP/winpr/libwinpr/environment/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
set(MODULE_NAME "TestEnvironment")
|
||||
set(MODULE_PREFIX "TEST_ENVIRONMENT")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS TestEnvironmentGetEnvironmentStrings.c TestEnvironmentSetEnvironmentVariable.c
|
||||
TestEnvironmentMergeEnvironmentStrings.c TestEnvironmentGetSetEB.c
|
||||
)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
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 "WinPR/Test")
|
||||
41
third_party/FreeRDP/winpr/libwinpr/environment/test/TestEnvironmentGetEnvironmentStrings.c
vendored
Normal file
41
third_party/FreeRDP/winpr/libwinpr/environment/test/TestEnvironmentGetEnvironmentStrings.c
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/environment.h>
|
||||
|
||||
int TestEnvironmentGetEnvironmentStrings(int argc, char* argv[])
|
||||
{
|
||||
int r = -1;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
LPTCH lpszEnvironmentBlock = GetEnvironmentStrings();
|
||||
if (!lpszEnvironmentBlock)
|
||||
goto fail;
|
||||
|
||||
TCHAR* p = lpszEnvironmentBlock;
|
||||
while (p[0] && p[1])
|
||||
{
|
||||
const size_t max = _tcslen(p);
|
||||
const int rc = _sntprintf(nullptr, 0, _T("%s\n"), p);
|
||||
if (rc < 1)
|
||||
{
|
||||
_tprintf(_T("test failed: return %d\n"), rc);
|
||||
goto fail;
|
||||
}
|
||||
if (max != (size_t)(rc - 1))
|
||||
{
|
||||
_tprintf(_T("test failed: length %") _T(PRIuz) _T(" != %d [%s]\n"), max, rc - 1, p);
|
||||
goto fail;
|
||||
}
|
||||
p += (max + 1);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
fail:
|
||||
FreeEnvironmentStrings(lpszEnvironmentBlock);
|
||||
|
||||
return r;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user