diff --git a/.gitignore b/.gitignore index ff66464d9..56412d950 100755 --- a/.gitignore +++ b/.gitignore @@ -12,16 +12,25 @@ cmake_install.cmake CPackConfig.cmake CPackSourceConfig.cmake DartConfiguration.tcl +CMakeCPackOptions.cmake _CPack_Packages +LICENSE.txt external/* !external/README +*.a.objlist.cmake +*.a.objlist +*.a.objdir +*_dummy.c +*_dummy.c.base + # Packages *.zip *.exe *.sh *.deb *.rpm +*.dmg *.tar.Z *.tar.gz diff --git a/CMakeCPack.cmake b/CMakeCPack.cmake new file mode 100644 index 000000000..f33be3db1 --- /dev/null +++ b/CMakeCPack.cmake @@ -0,0 +1,96 @@ + +# Generate .txt license file for CPack (PackageMaker requires a file extension) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/LICENSE ${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt @ONLY) + +SET(CPACK_BINARY_ZIP "ON") + +# Workaround to remove c++ compiler macros and defines for Eclipse. +# If c++ macros/defines are set __cplusplus is also set which causes +# problems when compiling freerdp/jni. To prevent this problem we set the macros to "". + +if (ANDROID AND CMAKE_EXTRA_GENERATOR STREQUAL "Eclipse CDT4") + set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS "") + message(STATUS "Disabled CXX system defines for eclipse (workaround).") +endif() + +set(CPACK_SOURCE_IGNORE_FILES "/\\\\.git/;/\\\\.gitignore;/CMakeCache.txt") + +if(NOT WIN32) + if(APPLE AND (NOT IOS)) + + if(WITH_SERVER) + set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "mfreerdp-server") + endif() + endif() + + if(WITH_X11) + set(CPACK_PACKAGE_EXECUTABLES "xfreerdp") + + if(WITH_SERVER) + set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "xfreerdp-server") + endif() + endif() +endif() + +set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") +set(CPACK_TOPLEVEL_TAG "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") + +string(TOLOWER ${CMAKE_PROJECT_NAME} CMAKE_PROJECT_NAME_lower) +set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME_lower}-${FREERDP_VERSION_FULL}-${CPACK_SYSTEM_NAME}") +set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME_lower}-${FREERDP_VERSION_FULL}-${CPACK_SYSTEM_NAME}") + +set(CPACK_PACKAGE_NAME "FreeRDP") +set(CPACK_PACKAGE_VENDOR "FreeRDP") +set(CPACK_PACKAGE_VERSION ${FREERDP_VERSION_FULL}) +set(CPACK_PACKAGE_VERSION_MAJOR ${FREERDP_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${FREERDP_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${FREERDP_VERSION_REVISION}) +SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "FreeRDP: A Remote Desktop Protocol Implementation") + +set(CPACK_PACKAGE_CONTACT "Marc-Andre Moreau") +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "marcandre.moreau@gmail.com") +set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) + +set(CPACK_PACKAGE_INSTALL_DIRECTORY "FreeRDP") +set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt") + +set(CPACK_NSIS_MODIFY_PATH ON) +set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/resources\\\\FreeRDP_Install.bmp") +set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/resources\\\\FreeRDP_Icon_96px.ico") +set(CPACK_NSIS_MUI_UNICON "${CMAKE_SOURCE_DIR}/resource\\\\FreeRDP_Icon_96px.ico") + +set(CPACK_COMPONENTS_ALL client server libraries headers) + +if(MSVC) + if(MSVC_RUNTIME STREQUAL "dynamic") + set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE) + include(InstallRequiredSystemLibraries) + + install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} + DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT libraries) + endif() +endif() + +set(CPACK_COMPONENT_CLIENT_DISPLAY_NAME "Client") +set(CPACK_COMPONENT_CLIENT_GROUP "Applications") + +set(CPACK_COMPONENT_SERVER_DISPLAY_NAME "Server") +set(CPACK_COMPONENT_SERVER_GROUP "Applications") + +set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") +set(CPACK_COMPONENT_LIBRARIES_GROUP "Runtime") + +set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "Headers") +set(CPACK_COMPONENT_HEADERS_GROUP "Development") + +set(CPACK_COMPONENT_GROUP_RUNTIME_DESCRIPTION "Runtime") +set(CPACK_COMPONENT_GROUP_APPLICATIONS_DESCRIPTION "Applications") +set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION "Development") + +configure_file("${CMAKE_SOURCE_DIR}/CMakeCPackOptions.cmake.in" + "${CMAKE_BINARY_DIR}/CMakeCPackOptions.cmake" @ONLY) +set(CPACK_PROJECT_CONFIG_FILE "${CMAKE_BINARY_DIR}/CMakeCPackOptions.cmake") + +include(CPack) diff --git a/CMakeCPackOptions.cmake.in b/CMakeCPackOptions.cmake.in new file mode 100644 index 000000000..826eaa10d --- /dev/null +++ b/CMakeCPackOptions.cmake.in @@ -0,0 +1,10 @@ +# This file is configured at cmake time, and loaded at cpack time. +# To pass variables to cpack from cmake, they must be configured in this file. + +if("${CPACK_GENERATOR}" STREQUAL "PackageMaker") + if(CMAKE_PACKAGE_QTGUI) + set(CPACK_PACKAGE_DEFAULT_LOCATION "/Applications") + else() + set(CPACK_PACKAGE_DEFAULT_LOCATION "/usr") + endif() +endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index b85a9a130..f9ce8252f 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,14 @@ cmake_minimum_required(VERSION 2.8) project(FreeRDP C) +if(NOT DEFINED VENDOR) + set(VENDOR "FreeRDP" CACHE STRING "FreeRDP package vendor") +endif() + set(CMAKE_COLOR_MAKEFILE ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + # Include our extra modules set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/) @@ -159,6 +165,10 @@ if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") if(WITH_SSE2) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mssse3") endif() + CHECK_C_COMPILER_FLAG(-Wno-deprecated-declarations Wno-deprecated-declarations) + if(Wno-deprecated-declarations) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations") + endif() endif() if(MSVC) @@ -230,7 +240,9 @@ if(APPLE) set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_IOS_EXTERNAL_SSL_PATH}) set_property(GLOBAL PROPERTY XCODE_ATTRIBUTE_SKIP_INSTALL YES) else() - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) + if(NOT DEFINED CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET MATCHES "") + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6 CACHE STRING "OSX deployment target" FORCE) + endif() if(NOT DEFINED CMAKE_OSX_ARCHITECTURES) set(CMAKE_OSX_ARCHITECTURES i386 x86_64) @@ -242,9 +254,11 @@ if(APPLE) endif() endif() - if(WITH_CLANG) - set(CMAKE_C_COMPILER "clang") - endif() +# Temporarily disabled, causes the cmake script to be reexecuted, causing the compilation to fail. +# Workaround: specify the parameter in the command-line +# if(WITH_CLANG) +# set(CMAKE_C_COMPILER "clang") +# endif() if (WITH_VERBOSE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -v") @@ -273,6 +287,7 @@ if(NOT IOS AND NOT ANDROID) endif() if(UNIX OR CYGWIN) + check_include_files(sys/eventfd.h HAVE_AIO_H) check_include_files(sys/eventfd.h HAVE_EVENTFD_H) check_include_files(sys/timerfd.h HAVE_TIMERFD_H) set(X11_FEATURE_TYPE "RECOMMENDED") @@ -475,9 +490,7 @@ if(WITH_THIRD_PARTY) endif() endif() -if (NOT WITH_WAYK) - add_subdirectory(include) -endif() +add_subdirectory(include) add_subdirectory(libfreerdp) @@ -500,114 +513,16 @@ endif() # Packaging -SET(CPACK_BINARY_ZIP "ON") +set(CMAKE_CPACK_INCLUDE_FILE "CMakeCPack.cmake") -if(NOT WITH_WAYK) - -set(CPACK_SOURCE_IGNORE_FILES "/\\\\.git/;/\\\\.gitignore;/CMakeCache.txt") - -if(NOT WIN32) - if(APPLE AND (NOT IOS)) - #set(CPACK_PACKAGE_EXECUTABLES "mfreerdp") - - if(WITH_SERVER) - set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "mfreerdp-server") - endif() +if(NOT (VENDOR MATCHES "FreeRDP")) + if(DEFINED CLIENT_VENDOR_PATH) + if(EXISTS "${CMAKE_SOURCE_DIR}/${CLIENT_VENDOR_PATH}/CMakeCPack.cmake") + set(CMAKE_CPACK_INCLUDE_FILE "${CLIENT_VENDOR_PATH}/CMakeCPack.cmake") + endif() endif() - - if(WITH_X11) - set(CPACK_PACKAGE_EXECUTABLES "xfreerdp") - - if(WITH_SERVER) - set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "xfreerdp-server") - endif() - endif() - endif() -set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") -set(CPACK_TOPLEVEL_TAG "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") +#message("VENDOR: ${VENDOR} CLIENT_VENDOR_PATH: ${CLIENT_VENDOR_PATH} CMAKE_CPACK_INCLUDE_FILE: ${CMAKE_CPACK_INCLUDE_FILE}") -string(TOLOWER ${CMAKE_PROJECT_NAME} CMAKE_PROJECT_NAME_lower) -set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME_lower}-${FREERDP_VERSION_FULL}-${CPACK_SYSTEM_NAME}") -set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME_lower}-${FREERDP_VERSION_FULL}-${CPACK_SYSTEM_NAME}") - -set(CPACK_PACKAGE_NAME "FreeRDP") -set(CPACK_PACKAGE_VENDOR "FreeRDP") -set(CPACK_PACKAGE_VERSION ${FREERDP_VERSION_FULL}) -set(CPACK_PACKAGE_VERSION_MAJOR ${FREERDP_VERSION_MAJOR}) -set(CPACK_PACKAGE_VERSION_MINOR ${FREERDP_VERSION_MINOR}) -set(CPACK_PACKAGE_VERSION_PATCH ${FREERDP_VERSION_REVISION}) -SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "FreeRDP: A Remote Desktop Protocol Implementation") - -set(CPACK_PACKAGE_CONTACT "Marc-Andre Moreau") -set(CPACK_DEBIAN_PACKAGE_MAINTAINER "marcandre.moreau@gmail.com") -set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) - -set(CPACK_PACKAGE_INSTALL_DIRECTORY "FreeRDP") -set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/LICENSE") -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") - -set(CPACK_NSIS_MODIFY_PATH ON) -set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/resources\\\\FreeRDP_Install.bmp") -set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/resources\\\\FreeRDP_Icon_96px.ico") -set(CPACK_NSIS_MUI_UNICON "${CMAKE_SOURCE_DIR}/resource\\\\FreeRDP_Icon_96px.ico") - -set(CPACK_COMPONENTS_ALL client server libraries headers) - -if(MSVC) - if(MSVC_RUNTIME STREQUAL "dynamic") - set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE) - include(InstallRequiredSystemLibraries) - -if(NOT WITH_WAYK) - install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} - DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT libraries) -endif() - endif() - - set(EXTRA_DATA_DIR "extra/") - file(GLOB EXTRA_FILES "${CMAKE_SOURCE_DIR}/extra/*") - install(FILES ${EXTRA_FILES} - DESTINATION ${EXTRA_DATA_DIR} - COMPONENT extra) - - set(REV_DATA_DIR "REV/") - file(GLOB REV_FILES "${CMAKE_SOURCE_DIR}/REV/*") - install(FILES ${REV_FILES} - DESTINATION ${REV_DATA_DIR} - COMPONENT rev) - - set(CPACK_COMPONENTS_AL ${CPACK_COMPONENTS_ALL} extra rev) -endif() - - -set(CPACK_COMPONENT_CLIENT_DISPLAY_NAME "Client") -set(CPACK_COMPONENT_CLIENT_GROUP "Applications") - -set(CPACK_COMPONENT_SERVER_DISPLAY_NAME "Server") -set(CPACK_COMPONENT_SERVER_GROUP "Applications") - -set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") -set(CPACK_COMPONENT_LIBRARIES_GROUP "Runtime") - -set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "Headers") -set(CPACK_COMPONENT_HEADERS_GROUP "Development") - -set(CPACK_COMPONENT_GROUP_RUNTIME_DESCRIPTION "Runtime") -set(CPACK_COMPONENT_GROUP_APPLICATIONS_DESCRIPTION "Applications") -set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION "Development") - -# Workaround to remove c++ compiler macros and defines for Eclipse. -# If c++ macros/defines are set __cplusplus is also set which causes -# problems when compiling freerdp/jni. To prevent this problem -# we set the macros to "". -if (ANDROID AND CMAKE_EXTRA_GENERATOR STREQUAL "Eclipse CDT4") - set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS "") - message(STATUS "Disabled CXX system defines for eclipse (workaround).") -endif() - -include(CPack) - -endif() +include(${CMAKE_CPACK_INCLUDE_FILE}) diff --git a/channels/audin/client/alsa/CMakeLists.txt b/channels/audin/client/alsa/CMakeLists.txt index b39ec52b3..4a4ca6096 100644 --- a/channels/audin/client/alsa/CMakeLists.txt +++ b/channels/audin/client/alsa/CMakeLists.txt @@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp - MODULES freerdp-utils) + MODULES freerdp-codec freerdp-utils) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES}) diff --git a/channels/audin/client/pulse/CMakeLists.txt b/channels/audin/client/pulse/CMakeLists.txt index a183ced3c..6c1f59ded 100644 --- a/channels/audin/client/pulse/CMakeLists.txt +++ b/channels/audin/client/pulse/CMakeLists.txt @@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp - MODULES freerdp-utils) + MODULES freerdp-codec freerdp-utils) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY}) diff --git a/channels/audin/server/audin.c b/channels/audin/server/audin.c index b597150fa..defdf50e1 100644 --- a/channels/audin/server/audin.c +++ b/channels/audin/server/audin.c @@ -78,7 +78,7 @@ static void audin_server_send_version(audin_server* audin, wStream* s) { Stream_Write_UINT8(s, MSG_SNDIN_VERSION); Stream_Write_UINT32(s, 1); /* Version (4 bytes) */ - WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL); + WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); } static BOOL audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length) @@ -130,7 +130,7 @@ static void audin_server_send_formats(audin_server* audin, wStream* s) } } - WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL); + WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); } static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length) @@ -166,6 +166,7 @@ static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 le Stream_Read_UINT16(s, audin->context.client_formats[i].nBlockAlign); Stream_Read_UINT16(s, audin->context.client_formats[i].wBitsPerSample); Stream_Read_UINT16(s, audin->context.client_formats[i].cbSize); + if (audin->context.client_formats[i].cbSize > 0) { Stream_Seek(s, audin->context.client_formats[i].cbSize); @@ -201,7 +202,7 @@ static void audin_server_send_open(audin_server* audin, wStream* s) Stream_Write_UINT16(s, 16); /* wBitsPerSample */ Stream_Write_UINT16(s, 0); /* cbSize */ - WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL); + WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); } static BOOL audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length) @@ -283,10 +284,10 @@ static void* audin_server_thread_func(void* arg) void* buffer; BYTE MessageId; BOOL ready = FALSE; - UINT32 bytes_returned = 0; + DWORD BytesReturned = 0; audin_server* audin = (audin_server*) arg; - if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE) + if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualFileHandle, &buffer, &BytesReturned) == TRUE) { fd = *((void**) buffer); WTSFreeMemory(buffer); @@ -303,7 +304,7 @@ static void* audin_server_thread_func(void* arg) if (WaitForSingleObject(audin->stopEvent, 0) == WAIT_OBJECT_0) break; - if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &bytes_returned) == FALSE) + if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE) break; ready = *((BOOL*) buffer); @@ -330,46 +331,48 @@ static void* audin_server_thread_func(void* arg) Stream_SetPosition(s, 0); - if (WTSVirtualChannelRead(audin->audin_channel, 0, Stream_Buffer(s), - Stream_Capacity(s), &bytes_returned) == FALSE) + if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s), + Stream_Capacity(s), &BytesReturned) == FALSE) { - if (bytes_returned == 0) + if (BytesReturned == 0) break; - Stream_EnsureRemainingCapacity(s, (int) bytes_returned); + Stream_EnsureRemainingCapacity(s, BytesReturned); - if (WTSVirtualChannelRead(audin->audin_channel, 0, Stream_Buffer(s), - Stream_Capacity(s), &bytes_returned) == FALSE) + if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s), + Stream_Capacity(s), &BytesReturned) == FALSE) + { break; + } } - if (bytes_returned < 1) + if (BytesReturned < 1) continue; Stream_Read_UINT8(s, MessageId); - bytes_returned--; + BytesReturned--; switch (MessageId) { case MSG_SNDIN_VERSION: - if (audin_server_recv_version(audin, s, bytes_returned)) + if (audin_server_recv_version(audin, s, BytesReturned)) audin_server_send_formats(audin, s); break; case MSG_SNDIN_FORMATS: - if (audin_server_recv_formats(audin, s, bytes_returned)) + if (audin_server_recv_formats(audin, s, BytesReturned)) audin_server_send_open(audin, s); break; case MSG_SNDIN_OPEN_REPLY: - audin_server_recv_open_reply(audin, s, bytes_returned); + audin_server_recv_open_reply(audin, s, BytesReturned); break; case MSG_SNDIN_DATA_INCOMING: break; case MSG_SNDIN_DATA: - audin_server_recv_data(audin, s, bytes_returned); + audin_server_recv_data(audin, s, BytesReturned); break; case MSG_SNDIN_FORMATCHANGE: @@ -394,7 +397,7 @@ static BOOL audin_server_open(audin_server_context* context) if (!audin->thread) { - audin->audin_channel = WTSVirtualChannelOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC); + audin->audin_channel = WTSVirtualChannelManagerOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC); if (!audin->audin_channel) return FALSE; diff --git a/channels/cliprdr/CMakeLists.txt b/channels/cliprdr/CMakeLists.txt index b5f1cf4b3..c5cfd729e 100644 --- a/channels/cliprdr/CMakeLists.txt +++ b/channels/cliprdr/CMakeLists.txt @@ -21,3 +21,6 @@ if(WITH_CLIENT_CHANNELS) add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME}) endif() +if(WITH_SERVER_CHANNELS) + add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME}) +endif() diff --git a/channels/cliprdr/ChannelOptions.cmake b/channels/cliprdr/ChannelOptions.cmake index 9cafcd965..f175f3f6a 100644 --- a/channels/cliprdr/ChannelOptions.cmake +++ b/channels/cliprdr/ChannelOptions.cmake @@ -1,7 +1,7 @@ set(OPTION_DEFAULT OFF) set(OPTION_CLIENT_DEFAULT ON) -set(OPTION_SERVER_DEFAULT OFF) +set(OPTION_SERVER_DEFAULT ON) define_channel_options(NAME "cliprdr" TYPE "static" DESCRIPTION "Clipboard Virtual Channel Extension" diff --git a/channels/cliprdr/client/CMakeLists.txt b/channels/cliprdr/client/CMakeLists.txt index f1dd07440..00c5605a0 100644 --- a/channels/cliprdr/client/CMakeLists.txt +++ b/channels/cliprdr/client/CMakeLists.txt @@ -18,7 +18,6 @@ define_channel_client("cliprdr") set(${MODULE_PREFIX}_SRCS - cliprdr_constants.h cliprdr_format.c cliprdr_format.h cliprdr_main.c diff --git a/channels/cliprdr/client/cliprdr_constants.h b/channels/cliprdr/client/cliprdr_constants.h deleted file mode 100644 index e3e141986..000000000 --- a/channels/cliprdr/client/cliprdr_constants.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Clipboard Virtual Channel - * - * Copyright 2009-2011 Jay Sorg - * Copyright 2010-2011 Vic Lee - * - * 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 __CLIPRDR_CONSTANTS -#define __CLIPRDR_CONSTANTS - -/* CLIPRDR_HEADER.msgType */ -#define CB_MONITOR_READY 0x0001 -#define CB_FORMAT_LIST 0x0002 -#define CB_FORMAT_LIST_RESPONSE 0x0003 -#define CB_FORMAT_DATA_REQUEST 0x0004 -#define CB_FORMAT_DATA_RESPONSE 0x0005 -#define CB_TEMP_DIRECTORY 0x0006 -#define CB_CLIP_CAPS 0x0007 -#define CB_FILECONTENTS_REQUEST 0x0008 -#define CB_FILECONTENTS_RESPONSE 0x0009 -#define CB_LOCK_CLIPDATA 0x000A -#define CB_UNLOCK_CLIPDATA 0x000B - -/* CLIPRDR_HEADER.msgFlags */ -#define CB_RESPONSE_OK 0x0001 -#define CB_RESPONSE_FAIL 0x0002 -#define CB_ASCII_NAMES 0x0004 - -/* CLIPRDR_CAPS_SET.capabilitySetType */ -#define CB_CAPSTYPE_GENERAL 0x0001 - -/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */ -#define CB_CAPSTYPE_GENERAL_LEN 12 - -/* CLIPRDR_GENERAL_CAPABILITY.version */ -#define CB_CAPS_VERSION_1 0x00000001 -#define CB_CAPS_VERSION_2 0x00000002 - -/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */ -#define CB_USE_LONG_FORMAT_NAMES 0x00000002 -#define CB_STREAM_FILECLIP_ENABLED 0x00000004 -#define CB_FILECLIP_NO_FILE_PATHS 0x00000008 -#define CB_CAN_LOCK_CLIPDATA 0x00000010 - -#endif /* __CLIPRDR_CONSTANTS */ diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index 59a729262..b3c8fdcd7 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -34,7 +34,6 @@ #include #include -#include "cliprdr_constants.h" #include "cliprdr_main.h" #include "cliprdr_format.h" diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index f83abba7a..8475b5c74 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -27,13 +27,13 @@ #include #include +#include #include #include #include #include -#include "cliprdr_constants.h" #include "cliprdr_main.h" #include "cliprdr_format.h" @@ -77,6 +77,11 @@ void cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s) Stream_Write_UINT32(s, dataLen); Stream_SetPosition(s, pos); +#ifdef WITH_DEBUG_CLIPRDR + printf("Cliprdr Sending (%d bytes)\n", dataLen + 8); + winpr_HexDump(Stream_Buffer(s), dataLen + 8); +#endif + svc_plugin_send((rdpSvcPlugin*) cliprdr, s); } @@ -207,6 +212,10 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s) DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d", CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); +#ifdef WITH_DEBUG_CLIPRDR + winpr_HexDump(Stream_Buffer(s), dataLen + 8); +#endif + switch (msgType) { case CB_CLIP_CAPS: diff --git a/channels/cliprdr/client/cliprdr_main.h b/channels/cliprdr/client/cliprdr_main.h index b2b984d31..38d361031 100644 --- a/channels/cliprdr/client/cliprdr_main.h +++ b/channels/cliprdr/client/cliprdr_main.h @@ -25,14 +25,6 @@ #include -struct _CLIPRDR_FORMAT_NAME -{ - UINT32 id; - char* name; - int length; -}; -typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME; - struct cliprdr_plugin { rdpSvcPlugin plugin; diff --git a/channels/cliprdr/server/CMakeLists.txt b/channels/cliprdr/server/CMakeLists.txt new file mode 100644 index 000000000..3e2ef0b2d --- /dev/null +++ b/channels/cliprdr/server/CMakeLists.txt @@ -0,0 +1,35 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# +# 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. + +define_channel_server("cliprdr") + +set(${MODULE_PREFIX}_SRCS + cliprdr_main.c + cliprdr_main.h) + +add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry") + +set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE freerdp + MODULES freerdp-utils) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server") diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c new file mode 100644 index 000000000..3e81809f0 --- /dev/null +++ b/channels/cliprdr/server/cliprdr_main.c @@ -0,0 +1,536 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Clipboard Virtual Channel Extension + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "cliprdr_main.h" + +/** + * Initialization Sequence\n + * Client Server\n + * | |\n + * |<----------------------Server Clipboard Capabilities PDU-----------------|\n + * |<-----------------------------Monitor Ready PDU--------------------------|\n + * |-----------------------Client Clipboard Capabilities PDU---------------->|\n + * |---------------------------Temporary Directory PDU---------------------->|\n + * |-------------------------------Format List PDU-------------------------->|\n + * |<--------------------------Format List Response PDU----------------------|\n + * + */ + +/** + * Data Transfer Sequences\n + * Shared Local\n + * Clipboard Owner Clipboard Owner\n + * | |\n + * |-------------------------------------------------------------------------|\n _ + * |-------------------------------Format List PDU-------------------------->|\n | + * |<--------------------------Format List Response PDU----------------------|\n _| Copy Sequence + * |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n + * |-------------------------------------------------------------------------|\n + * |-------------------------------------------------------------------------|\n _ + * |<--------------------------Format Data Request PDU-----------------------|\n | Paste Sequence Palette, + * |---------------------------Format Data Response PDU--------------------->|\n _| Metafile, File List Data + * |-------------------------------------------------------------------------|\n + * |-------------------------------------------------------------------------|\n _ + * |<------------------------Format Contents Request PDU---------------------|\n | Paste Sequence + * |-------------------------Format Contents Response PDU------------------->|\n _| File Stream Data + * |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n + * |-------------------------------------------------------------------------|\n + * + */ + +static int cliprdr_server_send_capabilities(CliprdrServerContext* context) +{ + wStream* s; + BOOL status; + UINT32 generalFlags; + CLIPRDR_HEADER header; + + printf("CliprdrServerSendCapabilities\n"); + + header.msgType = CB_CLIP_CAPS; + header.msgFlags = 0; + header.dataLen = 16; + + generalFlags = 0; + + if (context->priv->UseLongFormatNames) + generalFlags |= CB_USE_LONG_FORMAT_NAMES; + + s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH); + + Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */ + Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */ + Stream_Write_UINT32(s, header.dataLen); /* dataLen (4 bytes) */ + + Stream_Write_UINT16(s, 1); /* cCapabilitiesSets (2 bytes) */ + Stream_Write_UINT16(s, 0); /* pad1 (2 bytes) */ + + Stream_Write_UINT16(s, CB_CAPSTYPE_GENERAL); /* capabilitySetType (2 bytes) */ + Stream_Write_UINT16(s, CB_CAPSTYPE_GENERAL_LEN); /* lengthCapability (2 bytes) */ + Stream_Write_UINT32(s, CB_CAPS_VERSION_2); /* version (4 bytes) */ + Stream_Write_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ + + Stream_SealLength(s); + + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL); + + Stream_Free(s, TRUE); + + return 0; +} + +static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context) +{ + wStream* s; + BOOL status; + CLIPRDR_HEADER header; + + printf("CliprdrServerSendMonitorReady\n"); + + header.msgType = CB_MONITOR_READY; + header.msgFlags = 0; + header.dataLen = 0; + + s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH); + + Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */ + Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */ + Stream_Write_UINT32(s, header.dataLen); /* dataLen (4 bytes) */ + + Stream_SealLength(s); + + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL); + + Stream_Free(s, TRUE); + + return 0; +} + +static int cliprdr_server_send_format_list_response(CliprdrServerContext* context) +{ + wStream* s; + BOOL status; + CLIPRDR_HEADER header; + + printf("CliprdrServerSendFormatListResponse\n"); + + header.msgType = CB_FORMAT_LIST_RESPONSE; + header.msgFlags = CB_RESPONSE_OK; + header.dataLen = 0; + + s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH); + + Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */ + Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */ + Stream_Write_UINT32(s, header.dataLen); /* dataLen (4 bytes) */ + + Stream_SealLength(s); + + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL); + + Stream_Free(s, TRUE); + + return 0; +} + +static int cliprdr_server_receive_capabilities(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) +{ + UINT32 version; + UINT32 generalFlags; + UINT16 cCapabilitiesSets; + UINT16 capabilitySetType; + UINT16 lengthCapability; + + Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ + Stream_Seek_UINT16(s); /* pad1 (2 bytes) */ + + Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ + Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */ + + Stream_Read_UINT32(s, version); /* version (4 bytes) */ + Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ + + if (generalFlags & CB_USE_LONG_FORMAT_NAMES) + context->priv->UseLongFormatNames = TRUE; + + if (generalFlags & CB_STREAM_FILECLIP_ENABLED) + context->priv->StreamFileClipEnabled = TRUE; + + if (generalFlags & CB_FILECLIP_NO_FILE_PATHS) + context->priv->FileClipNoFilePaths = TRUE; + + if (generalFlags & CB_CAN_LOCK_CLIPDATA) + context->priv->CanLockClipData = TRUE; + + return 0; +} + +static int cliprdr_server_receive_temporary_directory(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) +{ + WCHAR* wszTempDir; + + if (Stream_GetRemainingLength(s) < 520) + return -1; + + wszTempDir = (WCHAR*) Stream_Pointer(s); + + if (wszTempDir[260] != 0) + return -1; + + ConvertFromUnicode(CP_UTF8, 0, wszTempDir, -1, + &(context->priv->ClientTemporaryDirectory), 0, NULL, NULL); + + printf("ClientTemporaryDirectory: %s\n", context->priv->ClientTemporaryDirectory); + + return 0; +} + +int cliprdr_wcslen(const WCHAR* str, const WCHAR* end) +{ + WCHAR* p = (WCHAR*) str; + + if (!p) + return -1; + + while (*p) + { + if (p == end) + return -1; + + p++; + } + + return (p - str); +} + +static void cliprdr_free_format_list(UINT32 count, CLIPRDR_FORMAT_NAME* formatNames) +{ + int i; + + if (formatNames) + { + for (i = 0; i < count; i++) + { + free(formatNames[i].name); + } + + free(formatNames); + } +} + +static int cliprdr_server_receive_long_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) +{ + int i; + WCHAR* end; + int length; + int position; + + printf("%s\n", __FUNCTION__); + + position = Stream_GetPosition(s); + Stream_SetPosition(s, Stream_Length(s)); + end = (WCHAR*) Stream_Pointer(s); + Stream_SetPosition(s, position); + + cliprdr_free_format_list(context->priv->ClientFormatNameCount, context->priv->ClientFormatNames); + context->priv->ClientFormatNameCount = 0; + context->priv->ClientFormatNames = NULL; + + while (Stream_GetRemainingLength(s) >= 6) + { + Stream_Seek(s, 4); /* formatId (4 bytes) */ + + length = cliprdr_wcslen((WCHAR*) Stream_Pointer(s), end); + + if (length < 0) + return -1; + + Stream_Seek(s, (length + 1) * 2); /* wszFormatName */ + + context->priv->ClientFormatNameCount++; + } + + context->priv->ClientFormatNames = (CLIPRDR_FORMAT_NAME*) + malloc(sizeof(CLIPRDR_FORMAT_NAME) * context->priv->ClientFormatNameCount); + + Stream_SetPosition(s, position); + + for (i = 0; i < context->priv->ClientFormatNameCount; i++) + { + Stream_Read_UINT32(s, context->priv->ClientFormatNames[i].id); /* formatId (4 bytes) */ + + length = cliprdr_wcslen((WCHAR*) Stream_Pointer(s), end); + + context->priv->ClientFormatNames[i].name = NULL; + + if (length) + { + context->priv->ClientFormatNames[i].length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), + -1, &(context->priv->ClientFormatNames[i].name), 0, NULL, NULL) - 1; + } + else + { + context->priv->ClientFormatNames[i].length = 0; + } + + Stream_Seek(s, (length + 1) * 2); /* wszFormatName */ + } + + for (i = 0; i < context->priv->ClientFormatNameCount; i++) + { + printf("Format %d: Id: 0x%04X Name: %s Length: %d\n", i, + context->priv->ClientFormatNames[i].id, + context->priv->ClientFormatNames[i].name, + context->priv->ClientFormatNames[i].length); + } + + return 0; +} + +static int cliprdr_server_receive_short_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) +{ + printf("%s: unimplemented\n", __FUNCTION__); + return 0; +} + +static int cliprdr_server_receive_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) +{ + int status; + + if (context->priv->UseLongFormatNames) + { + status = cliprdr_server_receive_long_format_list(context, s, header); + } + else + { + status = cliprdr_server_receive_short_format_list(context, s, header); + } + + cliprdr_server_send_format_list_response(context); + + return status; +} + +static int cliprdr_server_receive_pdu(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) +{ + printf("CliprdrServerReceivePdu: msgType: %d msgFlags: 0x%08X dataLen: %d\n", + header->msgType, header->msgFlags, header->dataLen); + + switch (header->msgType) + { + case CB_CLIP_CAPS: + cliprdr_server_receive_capabilities(context, s, header); + break; + + case CB_TEMP_DIRECTORY: + cliprdr_server_receive_temporary_directory(context, s, header); + break; + + case CB_FORMAT_LIST: + cliprdr_server_receive_format_list(context, s, header); + break; + + case CB_FORMAT_LIST_RESPONSE: + break; + + case CB_LOCK_CLIPDATA: + break; + + case CB_UNLOCK_CLIPDATA: + break; + + case CB_FORMAT_DATA_REQUEST: + break; + + case CB_FORMAT_DATA_RESPONSE: + break; + + case CB_FILECONTENTS_REQUEST: + break; + + case CB_FILECONTENTS_RESPONSE: + break; + + default: + printf("Unexpected clipboard PDU type: %d\n", header->msgType); + break; + } + + return 0; +} + +static void* cliprdr_server_thread(void* arg) +{ + wStream* s; + DWORD status; + DWORD nCount; + void* buffer; + int position; + HANDLE events[8]; + HANDLE ChannelEvent; + DWORD BytesReturned; + CLIPRDR_HEADER header; + CliprdrServerContext* context; + + context = (CliprdrServerContext*) arg; + + buffer = NULL; + BytesReturned = 0; + ChannelEvent = NULL; + + s = Stream_New(NULL, 4096); + + if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) + { + if (BytesReturned == sizeof(HANDLE)) + CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); + + WTSFreeMemory(buffer); + } + + nCount = 0; + events[nCount++] = ChannelEvent; + events[nCount++] = context->priv->StopEvent; + + cliprdr_server_send_capabilities(context); + cliprdr_server_send_monitor_ready(context); + + while (1) + { + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + + if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) + { + break; + } + + if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, + (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) + { + if (BytesReturned) + Stream_Seek(s, BytesReturned); + } + else + { + Stream_EnsureRemainingCapacity(s, BytesReturned); + } + + if (Stream_GetPosition(s) >= CLIPRDR_HEADER_LENGTH) + { + position = Stream_GetPosition(s); + Stream_SetPosition(s, 0); + + Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */ + Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */ + Stream_Read_UINT32(s, header.dataLen); /* dataLen (4 bytes) */ + + Stream_SetPosition(s, position); + + if (Stream_GetPosition(s) >= (header.dataLen + CLIPRDR_HEADER_LENGTH)) + { + Stream_SealLength(s); + Stream_SetPosition(s, CLIPRDR_HEADER_LENGTH); + + cliprdr_server_receive_pdu(context, s, &header); + Stream_SetPosition(s, 0); + } + } + } + + Stream_Free(s, TRUE); + + return NULL; +} + +static int cliprdr_server_start(CliprdrServerContext* context) +{ + context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "cliprdr", 0); + + if (!context->priv->ChannelHandle) + return -1; + + context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + context->priv->Thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) cliprdr_server_thread, (void*) context, 0, NULL); + + return 0; +} + +static int cliprdr_server_stop(CliprdrServerContext* context) +{ + SetEvent(context->priv->StopEvent); + + WaitForSingleObject(context->priv->Thread, INFINITE); + CloseHandle(context->priv->Thread); + + return 0; +} + +CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm) +{ + CliprdrServerContext* context; + + context = (CliprdrServerContext*) malloc(sizeof(CliprdrServerContext)); + + if (context) + { + ZeroMemory(context, sizeof(CliprdrServerContext)); + + context->vcm = vcm; + + context->Start = cliprdr_server_start; + context->Stop = cliprdr_server_stop; + + context->priv = (CliprdrServerPrivate*) malloc(sizeof(CliprdrServerPrivate)); + + if (context->priv) + { + ZeroMemory(context->priv, sizeof(CliprdrServerPrivate)); + + context->priv->UseLongFormatNames = TRUE; + context->priv->StreamFileClipEnabled = TRUE; + context->priv->FileClipNoFilePaths = TRUE; + context->priv->CanLockClipData = TRUE; + } + } + + return context; +} + +void cliprdr_server_context_free(CliprdrServerContext* context) +{ + if (context) + { + if (context->priv) + { + free(context->priv); + } + + free(context); + } +} diff --git a/channels/cliprdr/server/cliprdr_main.h b/channels/cliprdr/server/cliprdr_main.h new file mode 100644 index 000000000..3e201eeb3 --- /dev/null +++ b/channels/cliprdr/server/cliprdr_main.h @@ -0,0 +1,56 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Clipboard Virtual Channel Extension + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H +#define FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H + +#include +#include +#include + +#include + +#define CLIPRDR_HEADER_LENGTH 8 + +struct _CLIPRDR_HEADER +{ + UINT16 msgType; + UINT16 msgFlags; + UINT32 dataLen; +}; +typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER; + +struct _cliprdr_server_private +{ + HANDLE Thread; + HANDLE StopEvent; + void* ChannelHandle; + + BOOL UseLongFormatNames; + BOOL StreamFileClipEnabled; + BOOL FileClipNoFilePaths; + BOOL CanLockClipData; + + UINT32 ClientFormatNameCount; + CLIPRDR_FORMAT_NAME* ClientFormatNames; + + char* ClientTemporaryDirectory; +}; + +#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H */ diff --git a/channels/drdynvc/CMakeLists.txt b/channels/drdynvc/CMakeLists.txt index 8fc41cb90..9a6ee1ff6 100644 --- a/channels/drdynvc/CMakeLists.txt +++ b/channels/drdynvc/CMakeLists.txt @@ -21,3 +21,6 @@ if(WITH_CLIENT_CHANNELS) add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME}) endif() +if(WITH_SERVER_CHANNELS) + add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME}) +endif() diff --git a/channels/drdynvc/ChannelOptions.cmake b/channels/drdynvc/ChannelOptions.cmake index 1b226e64d..76376b6bf 100644 --- a/channels/drdynvc/ChannelOptions.cmake +++ b/channels/drdynvc/ChannelOptions.cmake @@ -1,7 +1,7 @@ set(OPTION_DEFAULT OFF) set(OPTION_CLIENT_DEFAULT ON) -set(OPTION_SERVER_DEFAULT OFF) +set(OPTION_SERVER_DEFAULT ON) define_channel_options(NAME "drdynvc" TYPE "static" DESCRIPTION "Dynamic Virtual Channel Extension" diff --git a/channels/drdynvc/server/CMakeLists.txt b/channels/drdynvc/server/CMakeLists.txt new file mode 100644 index 000000000..8b7c27d25 --- /dev/null +++ b/channels/drdynvc/server/CMakeLists.txt @@ -0,0 +1,35 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# +# 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. + +define_channel_server("drdynvc") + +set(${MODULE_PREFIX}_SRCS + drdynvc_main.c + drdynvc_main.h) + +add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry") + +set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE freerdp + MODULES freerdp-utils) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server") diff --git a/channels/drdynvc/server/drdynvc_main.c b/channels/drdynvc/server/drdynvc_main.c new file mode 100644 index 000000000..07da57e0c --- /dev/null +++ b/channels/drdynvc/server/drdynvc_main.c @@ -0,0 +1,149 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Dynamic Virtual Channel Extension + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "drdynvc_main.h" + +static void* drdynvc_server_thread(void* arg) +{ + wStream* s; + DWORD status; + DWORD nCount; + void* buffer; + HANDLE events[8]; + HANDLE ChannelEvent; + DWORD BytesReturned; + DrdynvcServerContext* context; + + context = (DrdynvcServerContext*) arg; + + buffer = NULL; + BytesReturned = 0; + ChannelEvent = NULL; + + s = Stream_New(NULL, 4096); + + if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) + { + if (BytesReturned == sizeof(HANDLE)) + CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); + + WTSFreeMemory(buffer); + } + + nCount = 0; + events[nCount++] = ChannelEvent; + events[nCount++] = context->priv->StopEvent; + + while (1) + { + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + + if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) + { + break; + } + + if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, + (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) + { + if (BytesReturned) + Stream_Seek(s, BytesReturned); + } + else + { + Stream_EnsureRemainingCapacity(s, BytesReturned); + } + } + + Stream_Free(s, TRUE); + + return NULL; +} + +static int drdynvc_server_start(DrdynvcServerContext* context) +{ + context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdr", 0); + + if (!context->priv->ChannelHandle) + return -1; + + context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + context->priv->Thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL); + + return 0; +} + +static int drdynvc_server_stop(DrdynvcServerContext* context) +{ + SetEvent(context->priv->StopEvent); + + WaitForSingleObject(context->priv->Thread, INFINITE); + CloseHandle(context->priv->Thread); + + return 0; +} + +DrdynvcServerContext* drdynvc_server_context_new(WTSVirtualChannelManager* vcm) +{ + DrdynvcServerContext* context; + + context = (DrdynvcServerContext*) malloc(sizeof(DrdynvcServerContext)); + + if (context) + { + ZeroMemory(context, sizeof(DrdynvcServerContext)); + + context->vcm = vcm; + + context->Start = drdynvc_server_start; + context->Stop = drdynvc_server_stop; + + context->priv = (DrdynvcServerPrivate*) malloc(sizeof(DrdynvcServerPrivate)); + + if (context->priv) + { + ZeroMemory(context->priv, sizeof(DrdynvcServerPrivate)); + } + } + + return context; +} + +void drdynvc_server_context_free(DrdynvcServerContext* context) +{ + if (context) + { + if (context->priv) + { + free(context->priv); + } + + free(context); + } +} diff --git a/channels/drdynvc/server/drdynvc_main.h b/channels/drdynvc/server/drdynvc_main.h new file mode 100644 index 000000000..aa69b5706 --- /dev/null +++ b/channels/drdynvc/server/drdynvc_main.h @@ -0,0 +1,37 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Dynamic Virtual Channel Extension + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_SERVER_DRDYNVC_MAIN_H +#define FREERDP_CHANNEL_SERVER_DRDYNVC_MAIN_H + +#include +#include +#include + +#include +#include + +struct _drdynvc_server_private +{ + HANDLE Thread; + HANDLE StopEvent; + void* ChannelHandle; +}; + +#endif /* FREERDP_CHANNEL_SERVER_DRDYNVC_MAIN_H */ diff --git a/channels/rdpdr/CMakeLists.txt b/channels/rdpdr/CMakeLists.txt index fc4eb638a..e9b418159 100644 --- a/channels/rdpdr/CMakeLists.txt +++ b/channels/rdpdr/CMakeLists.txt @@ -20,3 +20,7 @@ define_channel("rdpdr") if(WITH_CLIENT_CHANNELS) add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME}) endif() + +if(WITH_SERVER_CHANNELS) + add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME}) +endif() diff --git a/channels/rdpdr/ChannelOptions.cmake b/channels/rdpdr/ChannelOptions.cmake index 3bc158571..9a966768c 100644 --- a/channels/rdpdr/ChannelOptions.cmake +++ b/channels/rdpdr/ChannelOptions.cmake @@ -1,7 +1,7 @@ set(OPTION_DEFAULT OFF) set(OPTION_CLIENT_DEFAULT ON) -set(OPTION_SERVER_DEFAULT OFF) +set(OPTION_SERVER_DEFAULT ON) define_channel_options(NAME "rdpdr" TYPE "static" DESCRIPTION "Device Redirection Virtual Channel Extension" diff --git a/channels/rdpdr/client/rdpdr_capabilities.c b/channels/rdpdr/client/rdpdr_capabilities.c index 025977c92..21f90699d 100644 --- a/channels/rdpdr/client/rdpdr_capabilities.c +++ b/channels/rdpdr/client/rdpdr_capabilities.c @@ -33,132 +33,132 @@ #include "rdpdr_capabilities.h" /* Output device redirection capability set header */ -static void rdpdr_write_capset_header(wStream* data_out, UINT16 capabilityType, UINT16 capabilityLength, UINT32 version) +static void rdpdr_write_capset_header(wStream* s, UINT16 capabilityType, UINT16 capabilityLength, UINT32 version) { - Stream_Write_UINT16(data_out, capabilityType); - Stream_Write_UINT16(data_out, capabilityLength); - Stream_Write_UINT32(data_out, version); + Stream_Write_UINT16(s, capabilityType); + Stream_Write_UINT16(s, capabilityLength); + Stream_Write_UINT32(s, version); } /* Output device direction general capability set */ -static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* data_out) +static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s) { - rdpdr_write_capset_header(data_out, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02); + rdpdr_write_capset_header(s, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02); - Stream_Write_UINT32(data_out, 0); /* osType, ignored on receipt */ - Stream_Write_UINT32(data_out, 0); /* osVersion, unused and must be set to zero */ - Stream_Write_UINT16(data_out, 1); /* protocolMajorVersion, must be set to 1 */ - Stream_Write_UINT16(data_out, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */ - Stream_Write_UINT32(data_out, 0x0000FFFF); /* ioCode1 */ - Stream_Write_UINT32(data_out, 0); /* ioCode2, must be set to zero, reserved for future use */ - Stream_Write_UINT32(data_out, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */ - Stream_Write_UINT32(data_out, ENABLE_ASYNCIO); /* extraFlags1 */ - Stream_Write_UINT32(data_out, 0); /* extraFlags2, must be set to zero, reserved for future use */ - Stream_Write_UINT32(data_out, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */ + Stream_Write_UINT32(s, 0); /* osType, ignored on receipt */ + Stream_Write_UINT32(s, 0); /* osVersion, unused and must be set to zero */ + Stream_Write_UINT16(s, 1); /* protocolMajorVersion, must be set to 1 */ + Stream_Write_UINT16(s, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */ + Stream_Write_UINT32(s, 0x0000FFFF); /* ioCode1 */ + Stream_Write_UINT32(s, 0); /* ioCode2, must be set to zero, reserved for future use */ + Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */ + Stream_Write_UINT32(s, ENABLE_ASYNCIO); /* extraFlags1 */ + Stream_Write_UINT32(s, 0); /* extraFlags2, must be set to zero, reserved for future use */ + Stream_Write_UINT32(s, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */ } /* Process device direction general capability set */ -static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* data_in) +static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; - Stream_Read_UINT16(data_in, capabilityLength); - Stream_Seek(data_in, capabilityLength - 4); + Stream_Read_UINT16(s, capabilityLength); + Stream_Seek(s, capabilityLength - 4); } /* Output printer direction capability set */ -static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* data_out) +static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* s) { - rdpdr_write_capset_header(data_out, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01); + rdpdr_write_capset_header(s, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01); } /* Process printer direction capability set */ -static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* data_in) +static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; - Stream_Read_UINT16(data_in, capabilityLength); - Stream_Seek(data_in, capabilityLength - 4); + Stream_Read_UINT16(s, capabilityLength); + Stream_Seek(s, capabilityLength - 4); } /* Output port redirection capability set */ -static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* data_out) +static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* s) { - rdpdr_write_capset_header(data_out, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01); + rdpdr_write_capset_header(s, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01); } /* Process port redirection capability set */ -static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* data_in) +static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; - Stream_Read_UINT16(data_in, capabilityLength); - Stream_Seek(data_in, capabilityLength - 4); + Stream_Read_UINT16(s, capabilityLength); + Stream_Seek(s, capabilityLength - 4); } /* Output drive redirection capability set */ -static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* data_out) +static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* s) { - rdpdr_write_capset_header(data_out, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02); + rdpdr_write_capset_header(s, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02); } /* Process drive redirection capability set */ -static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* data_in) +static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; - Stream_Read_UINT16(data_in, capabilityLength); - Stream_Seek(data_in, capabilityLength - 4); + Stream_Read_UINT16(s, capabilityLength); + Stream_Seek(s, capabilityLength - 4); } /* Output smart card redirection capability set */ -static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* data_out) +static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) { - rdpdr_write_capset_header(data_out, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01); + rdpdr_write_capset_header(s, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01); } /* Process smartcard redirection capability set */ -static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* data_in) +static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; - Stream_Read_UINT16(data_in, capabilityLength); - Stream_Seek(data_in, capabilityLength - 4); + Stream_Read_UINT16(s, capabilityLength); + Stream_Seek(s, capabilityLength - 4); } -void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* data_in) +void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s) { UINT16 i; UINT16 numCapabilities; UINT16 capabilityType; - Stream_Read_UINT16(data_in, numCapabilities); - Stream_Seek(data_in, 2); /* pad (2 bytes) */ + Stream_Read_UINT16(s, numCapabilities); + Stream_Seek(s, 2); /* pad (2 bytes) */ - for(i = 0; i < numCapabilities; i++) + for (i = 0; i < numCapabilities; i++) { - Stream_Read_UINT16(data_in, capabilityType); + Stream_Read_UINT16(s, capabilityType); switch (capabilityType) { case CAP_GENERAL_TYPE: - rdpdr_process_general_capset(rdpdr, data_in); + rdpdr_process_general_capset(rdpdr, s); break; case CAP_PRINTER_TYPE: - rdpdr_process_printer_capset(rdpdr, data_in); + rdpdr_process_printer_capset(rdpdr, s); break; case CAP_PORT_TYPE: - rdpdr_process_port_capset(rdpdr, data_in); + rdpdr_process_port_capset(rdpdr, s); break; case CAP_DRIVE_TYPE: - rdpdr_process_drive_capset(rdpdr, data_in); + rdpdr_process_drive_capset(rdpdr, s); break; case CAP_SMARTCARD_TYPE: - rdpdr_process_smartcard_capset(rdpdr, data_in); + rdpdr_process_smartcard_capset(rdpdr, s); break; default: @@ -170,21 +170,21 @@ void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* data_in) void rdpdr_send_capability_response(rdpdrPlugin* rdpdr) { - wStream* data_out; + wStream* s; - data_out = Stream_New(NULL, 256); + s = Stream_New(NULL, 256); - Stream_Write_UINT16(data_out, RDPDR_CTYP_CORE); - Stream_Write_UINT16(data_out, PAKID_CORE_CLIENT_CAPABILITY); + Stream_Write_UINT16(s, RDPDR_CTYP_CORE); + Stream_Write_UINT16(s, PAKID_CORE_CLIENT_CAPABILITY); - Stream_Write_UINT16(data_out, 5); /* numCapabilities */ - Stream_Write_UINT16(data_out, 0); /* pad */ + Stream_Write_UINT16(s, 5); /* numCapabilities */ + Stream_Write_UINT16(s, 0); /* pad */ - rdpdr_write_general_capset(rdpdr, data_out); - rdpdr_write_printer_capset(rdpdr, data_out); - rdpdr_write_port_capset(rdpdr, data_out); - rdpdr_write_drive_capset(rdpdr, data_out); - rdpdr_write_smartcard_capset(rdpdr, data_out); + rdpdr_write_general_capset(rdpdr, s); + rdpdr_write_printer_capset(rdpdr, s); + rdpdr_write_port_capset(rdpdr, s); + rdpdr_write_drive_capset(rdpdr, s); + rdpdr_write_smartcard_capset(rdpdr, s); - svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out); + svc_plugin_send((rdpSvcPlugin*)rdpdr, s); } diff --git a/channels/rdpdr/server/CMakeLists.txt b/channels/rdpdr/server/CMakeLists.txt new file mode 100644 index 000000000..a7dd06c03 --- /dev/null +++ b/channels/rdpdr/server/CMakeLists.txt @@ -0,0 +1,35 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# +# 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. + +define_channel_server("rdpdr") + +set(${MODULE_PREFIX}_SRCS + rdpdr_main.c + rdpdr_main.h) + +add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry") + +set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE freerdp + MODULES freerdp-utils) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server") diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c new file mode 100644 index 000000000..16c150eaa --- /dev/null +++ b/channels/rdpdr/server/rdpdr_main.c @@ -0,0 +1,699 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Device Redirection Virtual Channel Extension + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "rdpdr_main.h" + +static UINT32 g_ClientId = 0; + +static int rdpdr_server_send_announce_request(RdpdrServerContext* context) +{ + wStream* s; + BOOL status; + RDPDR_HEADER header; + + printf("RdpdrServerSendAnnounceRequest\n"); + + header.Component = RDPDR_CTYP_CORE; + header.PacketId = PAKID_CORE_SERVER_ANNOUNCE; + + s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8); + + Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ + Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ + + Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */ + Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */ + Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */ + + Stream_SealLength(s); + + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL); + + Stream_Free(s, TRUE); + + return 0; +} + +static int rdpdr_server_receive_announce_response(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header) +{ + UINT32 ClientId; + UINT16 VersionMajor; + UINT16 VersionMinor; + + Stream_Read_UINT16(s, VersionMajor); /* VersionMajor (2 bytes) */ + Stream_Read_UINT16(s, VersionMinor); /* VersionMinor (2 bytes) */ + Stream_Read_UINT32(s, ClientId); /* ClientId (4 bytes) */ + + printf("Client Announce Response: VersionMajor: 0x%04X VersionMinor: 0x%04X ClientId: 0x%04X\n", + VersionMajor, VersionMinor, ClientId); + + context->priv->ClientId = ClientId; + + return 0; +} + +static int rdpdr_server_receive_client_name_request(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header) +{ + UINT32 UnicodeFlag; + UINT32 ComputerNameLen; + + Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */ + Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */ + Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */ + + /** + * Caution: ComputerNameLen is given *bytes*, + * not in characters, including the NULL terminator! + */ + + if (context->priv->ClientComputerName) + { + free(context->priv->ClientComputerName); + context->priv->ClientComputerName = NULL; + } + + if (UnicodeFlag) + { + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), + -1, &(context->priv->ClientComputerName), 0, NULL, NULL); + } + else + { + context->priv->ClientComputerName = _strdup((char*) Stream_Pointer(s)); + } + + Stream_Seek(s, ComputerNameLen); + + printf("ClientComputerName: %s\n", context->priv->ClientComputerName); + + return 0; +} + +static int rdpdr_server_read_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header) +{ + Stream_Read_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */ + Stream_Read_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */ + Stream_Read_UINT32(s, header->Version); /* Version (4 bytes) */ + return 0; +} + +static int rdpdr_server_write_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header) +{ + Stream_Write_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */ + Stream_Write_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */ + Stream_Write_UINT32(s, header->Version); /* Version (4 bytes) */ + return 0; +} + +static int rdpdr_server_read_general_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header) +{ + UINT32 ioCode1; + UINT32 extraFlags1; + UINT32 extendedPdu; + UINT16 VersionMajor; + UINT16 VersionMinor; + UINT32 SpecialTypeDeviceCap; + + Stream_Seek_UINT32(s); /* osType (4 bytes), ignored on receipt */ + Stream_Seek_UINT32(s); /* osVersion (4 bytes), unused and must be set to zero */ + Stream_Read_UINT16(s, VersionMajor); /* protocolMajorVersion (2 bytes) */ + Stream_Read_UINT16(s, VersionMinor); /* protocolMinorVersion (2 bytes) */ + Stream_Read_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */ + Stream_Seek_UINT32(s); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */ + Stream_Read_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */ + Stream_Read_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */ + Stream_Seek_UINT32(s); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */ + Stream_Read_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */ + + context->priv->UserLoggedOnPdu = (extendedPdu & RDPDR_USER_LOGGEDON_PDU) ? TRUE : FALSE; + + return 0; +} + +static int rdpdr_server_write_general_capability_set(RdpdrServerContext* context, wStream* s) +{ + UINT32 ioCode1; + UINT32 extendedPdu; + UINT32 extraFlags1; + UINT32 SpecialTypeDeviceCap; + RDPDR_CAPABILITY_HEADER header; + + header.CapabilityType = CAP_GENERAL_TYPE; + header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH + 36; + header.Version = GENERAL_CAPABILITY_VERSION_02; + + ioCode1 = 0; + ioCode1 |= RDPDR_IRP_MJ_CREATE; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_CLEANUP; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_CLOSE; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_READ; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_WRITE; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY; /* optional */ + ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY; /* optional */ + + extendedPdu = 0; + extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU; /* always set */ + extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS; /* optional */ + + if (context->priv->UserLoggedOnPdu) + extendedPdu |= RDPDR_USER_LOGGEDON_PDU; /* optional */ + + extraFlags1 = 0; + extraFlags1 |= ENABLE_ASYNCIO; /* optional */ + + SpecialTypeDeviceCap = 0; + + Stream_EnsureRemainingCapacity(s, header.CapabilityLength); + rdpdr_server_write_capability_set_header(s, &header); + + Stream_Write_UINT32(s, 0); /* osType (4 bytes), ignored on receipt */ + Stream_Write_UINT32(s, 0); /* osVersion (4 bytes), unused and must be set to zero */ + Stream_Write_UINT16(s, context->priv->VersionMajor); /* protocolMajorVersion (2 bytes) */ + Stream_Write_UINT16(s, context->priv->VersionMinor); /* protocolMinorVersion (2 bytes) */ + Stream_Write_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */ + Stream_Write_UINT32(s, 0); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */ + Stream_Write_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */ + Stream_Write_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */ + Stream_Write_UINT32(s, 0); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */ + Stream_Write_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */ + + return 0; +} + +static int rdpdr_server_read_printer_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header) +{ + return 0; +} + +static int rdpdr_server_write_printer_capability_set(RdpdrServerContext* context, wStream* s) +{ + RDPDR_CAPABILITY_HEADER header; + + header.CapabilityType = CAP_PRINTER_TYPE; + header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH; + header.Version = PRINT_CAPABILITY_VERSION_01; + + Stream_EnsureRemainingCapacity(s, header.CapabilityLength); + rdpdr_server_write_capability_set_header(s, &header); + + return 0; +} + +static int rdpdr_server_read_port_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header) +{ + return 0; +} + +static int rdpdr_server_write_port_capability_set(RdpdrServerContext* context, wStream* s) +{ + RDPDR_CAPABILITY_HEADER header; + + header.CapabilityType = CAP_PORT_TYPE; + header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH; + header.Version = PORT_CAPABILITY_VERSION_01; + + Stream_EnsureRemainingCapacity(s, header.CapabilityLength); + rdpdr_server_write_capability_set_header(s, &header); + + return 0; +} + +static int rdpdr_server_read_drive_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header) +{ + return 0; +} + +static int rdpdr_server_write_drive_capability_set(RdpdrServerContext* context, wStream* s) +{ + RDPDR_CAPABILITY_HEADER header; + + header.CapabilityType = CAP_DRIVE_TYPE; + header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH; + header.Version = DRIVE_CAPABILITY_VERSION_02; + + Stream_EnsureRemainingCapacity(s, header.CapabilityLength); + rdpdr_server_write_capability_set_header(s, &header); + + return 0; +} + +static int rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header) +{ + return 0; +} + +static int rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context, wStream* s) +{ + RDPDR_CAPABILITY_HEADER header; + + header.CapabilityType = CAP_SMARTCARD_TYPE; + header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH; + header.Version = SMARTCARD_CAPABILITY_VERSION_01; + + Stream_EnsureRemainingCapacity(s, header.CapabilityLength); + rdpdr_server_write_capability_set_header(s, &header); + + return 0; +} + +static int rdpdr_server_send_core_capability_request(RdpdrServerContext* context) +{ + wStream* s; + BOOL status; + RDPDR_HEADER header; + UINT16 numCapabilities; + + printf("RdpdrServerSendCoreCapabilityRequest\n"); + + header.Component = RDPDR_CTYP_CORE; + header.PacketId = PAKID_CORE_SERVER_CAPABILITY; + + numCapabilities = 5; + + s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 512); + + Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ + Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ + + Stream_Write_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */ + Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */ + + rdpdr_server_write_general_capability_set(context, s); + rdpdr_server_write_printer_capability_set(context, s); + rdpdr_server_write_port_capability_set(context, s); + rdpdr_server_write_drive_capability_set(context, s); + rdpdr_server_write_smartcard_capability_set(context, s); + + Stream_SealLength(s); + + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL); + + Stream_Free(s, TRUE); + + return 0; +} + +static int rdpdr_server_receive_core_capability_response(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header) +{ + int i; + UINT16 numCapabilities; + RDPDR_CAPABILITY_HEADER capabilityHeader; + + Stream_Read_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */ + Stream_Seek_UINT16(s); /* Padding (2 bytes) */ + + for (i = 0; i < numCapabilities; i++) + { + rdpdr_server_read_capability_set_header(s, &capabilityHeader); + + switch (capabilityHeader.CapabilityType) + { + case CAP_GENERAL_TYPE: + rdpdr_server_read_general_capability_set(context, s, &capabilityHeader); + break; + + case CAP_PRINTER_TYPE: + rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader); + break; + + case CAP_PORT_TYPE: + rdpdr_server_read_port_capability_set(context, s, &capabilityHeader); + break; + + case CAP_DRIVE_TYPE: + rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader); + break; + + case CAP_SMARTCARD_TYPE: + rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader); + break; + + default: + printf("Unknown capabilityType %d\n", capabilityHeader.CapabilityType); + Stream_Seek(s, capabilityHeader.CapabilityLength - RDPDR_CAPABILITY_HEADER_LENGTH); + break; + } + } + + return 0; +} + +static int rdpdr_server_send_client_id_confirm(RdpdrServerContext* context) +{ + wStream* s; + BOOL status; + RDPDR_HEADER header; + + printf("RdpdrServerSendClientIdConfirm\n"); + + header.Component = RDPDR_CTYP_CORE; + header.PacketId = PAKID_CORE_CLIENTID_CONFIRM; + + s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8); + + Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ + Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ + + Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */ + Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */ + Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */ + + Stream_SealLength(s); + + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL); + + Stream_Free(s, TRUE); + + return 0; +} + +static int rdpdr_server_receive_device_list_announce_request(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header) +{ + int i; + UINT32 DeviceCount; + UINT32 DeviceType; + UINT32 DeviceId; + char PreferredDosName[9]; + UINT32 DeviceDataLength; + + PreferredDosName[8] = 0; + + Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */ + + printf("%s: DeviceCount: %d\n", __FUNCTION__, DeviceCount); + + for (i = 0; i < DeviceCount; i++) + { + Stream_Read_UINT32(s, DeviceType); /* DeviceType (4 bytes) */ + Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */ + Stream_Read(s, PreferredDosName, 8); /* PreferredDosName (8 bytes) */ + Stream_Read_UINT32(s, DeviceDataLength); /* DeviceDataLength (4 bytes) */ + + printf("Device %d Name: %s Id: 0x%04X DataLength: %d\n", + i, PreferredDosName, DeviceId, DeviceDataLength); + + switch (DeviceId) + { + case RDPDR_DTYP_FILESYSTEM: + break; + + case RDPDR_DTYP_PRINT: + break; + + case RDPDR_DTYP_SERIAL: + break; + + case RDPDR_DTYP_PARALLEL: + break; + + case RDPDR_DTYP_SMARTCARD: + break; + + default: + break; + } + + Stream_Seek(s, DeviceDataLength); + } + + return 0; +} + +static int rdpdr_server_send_user_logged_on(RdpdrServerContext* context) +{ + wStream* s; + BOOL status; + RDPDR_HEADER header; + + printf("%s\n", __FUNCTION__); + + header.Component = RDPDR_CTYP_CORE; + header.PacketId = PAKID_CORE_USER_LOGGEDON; + + s = Stream_New(NULL, RDPDR_HEADER_LENGTH); + + Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ + Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ + + Stream_SealLength(s); + + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL); + + Stream_Free(s, TRUE); + + return 0; +} + +static int rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header) +{ + printf("RdpdrServerReceivePdu: Component: 0x%04X PacketId: 0x%04X\n", + header->Component, header->PacketId); + + winpr_HexDump(Stream_Buffer(s), Stream_Length(s)); + + if (header->Component == RDPDR_CTYP_CORE) + { + switch (header->PacketId) + { + case PAKID_CORE_CLIENTID_CONFIRM: + rdpdr_server_receive_announce_response(context, s, header); + break; + + case PAKID_CORE_CLIENT_NAME: + rdpdr_server_receive_client_name_request(context, s, header); + rdpdr_server_send_core_capability_request(context); + break; + + case PAKID_CORE_CLIENT_CAPABILITY: + rdpdr_server_receive_core_capability_response(context, s, header); + rdpdr_server_send_client_id_confirm(context); + + if (context->priv->UserLoggedOnPdu) + rdpdr_server_send_user_logged_on(context); + break; + + case PAKID_CORE_DEVICELIST_ANNOUNCE: + rdpdr_server_receive_device_list_announce_request(context, s, header); + break; + + case PAKID_CORE_DEVICE_REPLY: + break; + + case PAKID_CORE_DEVICE_IOREQUEST: + break; + + case PAKID_CORE_DEVICE_IOCOMPLETION: + break; + + case PAKID_CORE_DEVICELIST_REMOVE: + break; + + default: + break; + } + } + else if (header->Component == RDPDR_CTYP_PRN) + { + switch (header->PacketId) + { + case PAKID_PRN_CACHE_DATA: + break; + + case PAKID_PRN_USING_XPS: + break; + + default: + break; + } + } + else + { + printf("Unknown RDPDR_HEADER.Component: 0x%04X\n", header->Component); + return -1; + } + + return 0; +} + +static void* rdpdr_server_thread(void* arg) +{ + wStream* s; + DWORD status; + DWORD nCount; + void* buffer; + int position; + HANDLE events[8]; + RDPDR_HEADER header; + HANDLE ChannelEvent; + DWORD BytesReturned; + RdpdrServerContext* context; + + context = (RdpdrServerContext*) arg; + + buffer = NULL; + BytesReturned = 0; + ChannelEvent = NULL; + + s = Stream_New(NULL, 4096); + + if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) + { + if (BytesReturned == sizeof(HANDLE)) + CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); + + WTSFreeMemory(buffer); + } + + nCount = 0; + events[nCount++] = ChannelEvent; + events[nCount++] = context->priv->StopEvent; + + rdpdr_server_send_announce_request(context); + + while (1) + { + BytesReturned = 0; + + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + + if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) + { + break; + } + + if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Pointer(s), + Stream_Capacity(s) - Stream_GetPosition(s), &BytesReturned)) + { + if (BytesReturned) + Stream_Seek(s, BytesReturned); + } + else + { + Stream_EnsureRemainingCapacity(s, BytesReturned); + } + + if (Stream_GetPosition(s) >= RDPDR_HEADER_LENGTH) + { + position = Stream_GetPosition(s); + Stream_SetPosition(s, 0); + + Stream_Read_UINT16(s, header.Component); /* Component (2 bytes) */ + Stream_Read_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ + + Stream_SetPosition(s, position); + + Stream_SealLength(s); + Stream_SetPosition(s, RDPDR_HEADER_LENGTH); + + rdpdr_server_receive_pdu(context, s, &header); + Stream_SetPosition(s, 0); + } + } + + Stream_Free(s, TRUE); + + return NULL; +} + +static int rdpdr_server_start(RdpdrServerContext* context) +{ + context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdr", 0); + + if (!context->priv->ChannelHandle) + return -1; + + context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + context->priv->Thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) rdpdr_server_thread, (void*) context, 0, NULL); + + return 0; +} + +static int rdpdr_server_stop(RdpdrServerContext* context) +{ + SetEvent(context->priv->StopEvent); + + WaitForSingleObject(context->priv->Thread, INFINITE); + CloseHandle(context->priv->Thread); + + return 0; +} + +RdpdrServerContext* rdpdr_server_context_new(WTSVirtualChannelManager* vcm) +{ + RdpdrServerContext* context; + + context = (RdpdrServerContext*) malloc(sizeof(RdpdrServerContext)); + + if (context) + { + ZeroMemory(context, sizeof(RdpdrServerContext)); + + context->vcm = vcm; + + context->Start = rdpdr_server_start; + context->Stop = rdpdr_server_stop; + + context->priv = (RdpdrServerPrivate*) malloc(sizeof(RdpdrServerPrivate)); + + if (context->priv) + { + ZeroMemory(context->priv, sizeof(RdpdrServerPrivate)); + + context->priv->VersionMajor = RDPDR_VERSION_MAJOR; + context->priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X; + context->priv->ClientId = g_ClientId++; + + context->priv->UserLoggedOnPdu = TRUE; + } + } + + return context; +} + +void rdpdr_server_context_free(RdpdrServerContext* context) +{ + if (context) + { + if (context->priv) + { + free(context->priv); + } + + free(context); + } +} diff --git a/channels/rdpdr/server/rdpdr_main.h b/channels/rdpdr/server/rdpdr_main.h new file mode 100644 index 000000000..9472f44da --- /dev/null +++ b/channels/rdpdr/server/rdpdr_main.h @@ -0,0 +1,70 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Device Redirection Virtual Channel Extension + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_SERVER_RDPDR_MAIN_H +#define FREERDP_CHANNEL_SERVER_RDPDR_MAIN_H + +#include +#include +#include + +#include +#include + +struct _rdpdr_server_private +{ + HANDLE Thread; + HANDLE StopEvent; + void* ChannelHandle; + + UINT32 ClientId; + UINT16 VersionMajor; + UINT16 VersionMinor; + char* ClientComputerName; + + BOOL UserLoggedOnPdu; +}; + +#define RDPDR_HEADER_LENGTH 4 + +struct _RDPDR_HEADER +{ + UINT16 Component; + UINT16 PacketId; +}; +typedef struct _RDPDR_HEADER RDPDR_HEADER; + +#define RDPDR_VERSION_MAJOR 0x0001 + +#define RDPDR_VERSION_MINOR_RDP50 0x0002 +#define RDPDR_VERSION_MINOR_RDP51 0x0005 +#define RDPDR_VERSION_MINOR_RDP52 0x000A +#define RDPDR_VERSION_MINOR_RDP6X 0x000C + +#define RDPDR_CAPABILITY_HEADER_LENGTH 8 + +struct _RDPDR_CAPABILITY_HEADER +{ + UINT16 CapabilityType; + UINT16 CapabilityLength; + UINT32 Version; +}; +typedef struct _RDPDR_CAPABILITY_HEADER RDPDR_CAPABILITY_HEADER; + +#endif /* FREERDP_CHANNEL_SERVER_RDPDR_MAIN_H */ diff --git a/channels/rdpsnd/client/CMakeLists.txt b/channels/rdpsnd/client/CMakeLists.txt index 63c439548..d741fa76d 100644 --- a/channels/rdpsnd/client/CMakeLists.txt +++ b/channels/rdpsnd/client/CMakeLists.txt @@ -28,7 +28,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp - MODULES freerdp-utils) + MODULES freerdp-codec freerdp-utils) set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} @@ -43,6 +43,10 @@ if(WITH_ALSA) add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "alsa" "") endif() +if(WITH_IOSAUDIO) + add_channel_client_subsystem($(MODULE_PREFIX) $(CHANNEL_NAME) "ios" "") +endif() + if(WITH_PULSE) add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "pulse" "") endif() diff --git a/channels/rdpsnd/client/alsa/CMakeLists.txt b/channels/rdpsnd/client/alsa/CMakeLists.txt index 2f5eb1df7..397634c80 100644 --- a/channels/rdpsnd/client/alsa/CMakeLists.txt +++ b/channels/rdpsnd/client/alsa/CMakeLists.txt @@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp - MODULES freerdp-utils) + MODULES freerdp-codec freerdp-utils) set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} diff --git a/channels/rdpsnd/client/ios/CMakeLists.txt b/channels/rdpsnd/client/ios/CMakeLists.txt new file mode 100644 index 000000000..2db67b285 --- /dev/null +++ b/channels/rdpsnd/client/ios/CMakeLists.txt @@ -0,0 +1,52 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Laxmikant Rashinkar +# Copyright 2012 Marc-Andre Moreau +# Copyright 2013 Corey Clayton +# +# 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. + +define_channel_client_subsystem("rdpsnd" "ios" "") + +FIND_LIBRARY(CORE_AUDIO CoreAudio) +FIND_LIBRARY(AUDIO_TOOL AudioToolbox) +FIND_LIBRARY(CORE_FOUNDATION CoreFoundation) + +set(${MODULE_PREFIX}_SRCS + rdpsnd_ios.c + TPCircularBuffer.c) + +include_directories(..) + +add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "") + +set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE freerdp + MODULES freerdp-utils) + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} + ${AUDIO_TOOL} + ${CORE_AUDIO} + ${CORE_FOUNDATION}) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +if(NOT STATIC_CHANNELS) + install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH}) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/ios") diff --git a/channels/rdpsnd/client/ios/TPCircularBuffer.c b/channels/rdpsnd/client/ios/TPCircularBuffer.c new file mode 100644 index 000000000..d9e049ad2 --- /dev/null +++ b/channels/rdpsnd/client/ios/TPCircularBuffer.c @@ -0,0 +1,136 @@ +// +// TPCircularBuffer.c +// Circular/Ring buffer implementation +// +// https://github.com/michaeltyson/TPCircularBuffer +// +// Created by Michael Tyson on 10/12/2011. +// +// Copyright (C) 2012-2013 A Tasty Pixel +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// + +#include "TPCircularBuffer.h" +#include +#include + +#define reportResult(result,operation) (_reportResult((result),(operation),strrchr(__FILE__, '/')+1,__LINE__)) +static inline bool _reportResult(kern_return_t result, const char *operation, const char* file, int line) { + if ( result != ERR_SUCCESS ) { + printf("%s:%d: %s: %s\n", file, line, operation, mach_error_string(result)); + return false; + } + return true; +} + +bool TPCircularBufferInit(TPCircularBuffer *buffer, int length) { + + // Keep trying until we get our buffer, needed to handle race conditions + int retries = 3; + while ( true ) { + + buffer->length = round_page(length); // We need whole page sizes + + // Temporarily allocate twice the length, so we have the contiguous address space to + // support a second instance of the buffer directly after + vm_address_t bufferAddress; + kern_return_t result = vm_allocate(mach_task_self(), + &bufferAddress, + buffer->length * 2, + VM_FLAGS_ANYWHERE); // allocate anywhere it'll fit + if ( result != ERR_SUCCESS ) { + if ( retries-- == 0 ) { + reportResult(result, "Buffer allocation"); + return false; + } + // Try again if we fail + continue; + } + + // Now replace the second half of the allocation with a virtual copy of the first half. Deallocate the second half... + result = vm_deallocate(mach_task_self(), + bufferAddress + buffer->length, + buffer->length); + if ( result != ERR_SUCCESS ) { + if ( retries-- == 0 ) { + reportResult(result, "Buffer deallocation"); + return false; + } + // If this fails somehow, deallocate the whole region and try again + vm_deallocate(mach_task_self(), bufferAddress, buffer->length); + continue; + } + + // Re-map the buffer to the address space immediately after the buffer + vm_address_t virtualAddress = bufferAddress + buffer->length; + vm_prot_t cur_prot, max_prot; + result = vm_remap(mach_task_self(), + &virtualAddress, // mirror target + buffer->length, // size of mirror + 0, // auto alignment + 0, // force remapping to virtualAddress + mach_task_self(), // same task + bufferAddress, // mirror source + 0, // MAP READ-WRITE, NOT COPY + &cur_prot, // unused protection struct + &max_prot, // unused protection struct + VM_INHERIT_DEFAULT); + if ( result != ERR_SUCCESS ) { + if ( retries-- == 0 ) { + reportResult(result, "Remap buffer memory"); + return false; + } + // If this remap failed, we hit a race condition, so deallocate and try again + vm_deallocate(mach_task_self(), bufferAddress, buffer->length); + continue; + } + + if ( virtualAddress != bufferAddress+buffer->length ) { + // If the memory is not contiguous, clean up both allocated buffers and try again + if ( retries-- == 0 ) { + printf("Couldn't map buffer memory to end of buffer\n"); + return false; + } + + vm_deallocate(mach_task_self(), virtualAddress, buffer->length); + vm_deallocate(mach_task_self(), bufferAddress, buffer->length); + continue; + } + + buffer->buffer = (void*)bufferAddress; + buffer->fillCount = 0; + buffer->head = buffer->tail = 0; + + return true; + } + return false; +} + +void TPCircularBufferCleanup(TPCircularBuffer *buffer) { + vm_deallocate(mach_task_self(), (vm_address_t)buffer->buffer, buffer->length * 2); + memset(buffer, 0, sizeof(TPCircularBuffer)); +} + +void TPCircularBufferClear(TPCircularBuffer *buffer) { + int32_t fillCount; + if ( TPCircularBufferTail(buffer, &fillCount) ) { + TPCircularBufferConsume(buffer, fillCount); + } +} diff --git a/channels/rdpsnd/client/ios/TPCircularBuffer.h b/channels/rdpsnd/client/ios/TPCircularBuffer.h new file mode 100644 index 000000000..cd2a4d837 --- /dev/null +++ b/channels/rdpsnd/client/ios/TPCircularBuffer.h @@ -0,0 +1,195 @@ +// +// TPCircularBuffer.h +// Circular/Ring buffer implementation +// +// https://github.com/michaeltyson/TPCircularBuffer +// +// Created by Michael Tyson on 10/12/2011. +// +// +// This implementation makes use of a virtual memory mapping technique that inserts a virtual copy +// of the buffer memory directly after the buffer's end, negating the need for any buffer wrap-around +// logic. Clients can simply use the returned memory address as if it were contiguous space. +// +// The implementation is thread-safe in the case of a single producer and single consumer. +// +// Virtual memory technique originally proposed by Philip Howard (http://vrb.slashusr.org/), and +// adapted to Darwin by Kurt Revis (http://www.snoize.com, +// http://www.snoize.com/Code/PlayBufferedSoundFile.tar.gz) +// +// +// Copyright (C) 2012-2013 A Tasty Pixel +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef TPCircularBuffer_h +#define TPCircularBuffer_h + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + void *buffer; + int32_t length; + int32_t tail; + int32_t head; + volatile int32_t fillCount; +} TPCircularBuffer; + +/*! + * Initialise buffer + * + * Note that the length is advisory only: Because of the way the + * memory mirroring technique works, the true buffer length will + * be multiples of the device page size (e.g. 4096 bytes) + * + * @param buffer Circular buffer + * @param length Length of buffer + */ +bool TPCircularBufferInit(TPCircularBuffer *buffer, int32_t length); + +/*! + * Cleanup buffer + * + * Releases buffer resources. + */ +void TPCircularBufferCleanup(TPCircularBuffer *buffer); + +/*! + * Clear buffer + * + * Resets buffer to original, empty state. + * + * This is safe for use by consumer while producer is accessing + * buffer. + */ +void TPCircularBufferClear(TPCircularBuffer *buffer); + +// Reading (consuming) + +/*! + * Access end of buffer + * + * This gives you a pointer to the end of the buffer, ready + * for reading, and the number of available bytes to read. + * + * @param buffer Circular buffer + * @param availableBytes On output, the number of bytes ready for reading + * @return Pointer to the first bytes ready for reading, or NULL if buffer is empty + */ +static __inline__ __attribute__((always_inline)) void* TPCircularBufferTail(TPCircularBuffer *buffer, int32_t* availableBytes) { + *availableBytes = buffer->fillCount; + if ( *availableBytes == 0 ) return NULL; + return (void*)((char*)buffer->buffer + buffer->tail); +} + +/*! + * Consume bytes in buffer + * + * This frees up the just-read bytes, ready for writing again. + * + * @param buffer Circular buffer + * @param amount Number of bytes to consume + */ +static __inline__ __attribute__((always_inline)) void TPCircularBufferConsume(TPCircularBuffer *buffer, int32_t amount) { + buffer->tail = (buffer->tail + amount) % buffer->length; + OSAtomicAdd32Barrier(-amount, &buffer->fillCount); + assert(buffer->fillCount >= 0); +} + +/*! + * Version of TPCircularBufferConsume without the memory barrier, for more optimal use in single-threaded contexts + */ +static __inline__ __attribute__((always_inline)) void TPCircularBufferConsumeNoBarrier(TPCircularBuffer *buffer, int32_t amount) { + buffer->tail = (buffer->tail + amount) % buffer->length; + buffer->fillCount -= amount; + assert(buffer->fillCount >= 0); +} + +/*! + * Access front of buffer + * + * This gives you a pointer to the front of the buffer, ready + * for writing, and the number of available bytes to write. + * + * @param buffer Circular buffer + * @param availableBytes On output, the number of bytes ready for writing + * @return Pointer to the first bytes ready for writing, or NULL if buffer is full + */ +static __inline__ __attribute__((always_inline)) void* TPCircularBufferHead(TPCircularBuffer *buffer, int32_t* availableBytes) { + *availableBytes = (buffer->length - buffer->fillCount); + if ( *availableBytes == 0 ) return NULL; + return (void*)((char*)buffer->buffer + buffer->head); +} + +// Writing (producing) + +/*! + * Produce bytes in buffer + * + * This marks the given section of the buffer ready for reading. + * + * @param buffer Circular buffer + * @param amount Number of bytes to produce + */ +static __inline__ __attribute__((always_inline)) void TPCircularBufferProduce(TPCircularBuffer *buffer, int amount) { + buffer->head = (buffer->head + amount) % buffer->length; + OSAtomicAdd32Barrier(amount, &buffer->fillCount); + assert(buffer->fillCount <= buffer->length); +} + +/*! + * Version of TPCircularBufferProduce without the memory barrier, for more optimal use in single-threaded contexts + */ +static __inline__ __attribute__((always_inline)) void TPCircularBufferProduceNoBarrier(TPCircularBuffer *buffer, int amount) { + buffer->head = (buffer->head + amount) % buffer->length; + buffer->fillCount += amount; + assert(buffer->fillCount <= buffer->length); +} + +/*! + * Helper routine to copy bytes to buffer + * + * This copies the given bytes to the buffer, and marks them ready for writing. + * + * @param buffer Circular buffer + * @param src Source buffer + * @param len Number of bytes in source buffer + * @return true if bytes copied, false if there was insufficient space + */ +static __inline__ __attribute__((always_inline)) bool TPCircularBufferProduceBytes(TPCircularBuffer *buffer, const void* src, int32_t len) { + int32_t space; + void *ptr = TPCircularBufferHead(buffer, &space); + if ( space < len ) return false; + memcpy(ptr, src, len); + TPCircularBufferProduce(buffer, len); + return true; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/channels/rdpsnd/client/ios/rdpsnd_ios.c b/channels/rdpsnd/client/ios/rdpsnd_ios.c new file mode 100644 index 000000000..60da43cc1 --- /dev/null +++ b/channels/rdpsnd/client/ios/rdpsnd_ios.c @@ -0,0 +1,299 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Audio Output Virtual Channel + * + * Copyright 2013 Dell Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include + +#import + +#include "rdpsnd_main.h" +#include "TPCircularBuffer.h" + +#define INPUT_BUFFER_SIZE 32768 +#define CIRCULAR_BUFFER_SIZE (INPUT_BUFFER_SIZE * 4) + +typedef struct rdpsnd_ios_plugin +{ + rdpsndDevicePlugin device; + AudioComponentInstance audio_unit; + TPCircularBuffer buffer; + BOOL is_opened; + BOOL is_playing; +} rdpsndIOSPlugin; + +#define THIS(__ptr) ((rdpsndIOSPlugin*)__ptr) + +static OSStatus rdpsnd_ios_render_cb( + void *inRefCon, + AudioUnitRenderActionFlags __unused *ioActionFlags, + const AudioTimeStamp __unused *inTimeStamp, + UInt32 inBusNumber, + UInt32 __unused inNumberFrames, + AudioBufferList *ioData +) +{ + unsigned int i; + + if (inBusNumber != 0) + { + return noErr; + } + + rdpsndIOSPlugin *p = THIS(inRefCon); + + for (i = 0; i < ioData->mNumberBuffers; i++) + { + AudioBuffer* target_buffer = &ioData->mBuffers[i]; + + int32_t available_bytes = 0; + const void *buffer = TPCircularBufferTail(&p->buffer, &available_bytes); + if (buffer != NULL && available_bytes > 0) + { + const int bytes_to_copy = MIN((int32_t)target_buffer->mDataByteSize, available_bytes); + + memcpy(target_buffer->mData, buffer, bytes_to_copy); + target_buffer->mDataByteSize = bytes_to_copy; + + TPCircularBufferConsume(&p->buffer, bytes_to_copy); + } + else + { + target_buffer->mDataByteSize = 0; + AudioOutputUnitStop(p->audio_unit); + p->is_playing = 0; + } + } + + return noErr; +} + +static BOOL rdpsnd_ios_format_supported(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* format) +{ + if (format->wFormatTag == WAVE_FORMAT_PCM) + { + return 1; + } + return 0; +} + +static void rdpsnd_ios_set_format(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* __unused format, int __unused latency) +{ +} + +static void rdpsnd_ios_set_volume(rdpsndDevicePlugin* __unused device, UINT32 __unused value) +{ +} + +static void rdpsnd_ios_start(rdpsndDevicePlugin* device) +{ + rdpsndIOSPlugin *p = THIS(device); + + /* If this device is not playing... */ + if (!p->is_playing) + { + /* Start the device. */ + int32_t available_bytes = 0; + TPCircularBufferTail(&p->buffer, &available_bytes); + if (available_bytes > 0) + { + p->is_playing = 1; + AudioOutputUnitStart(p->audio_unit); + } + } +} + +static void rdpsnd_ios_stop(rdpsndDevicePlugin* __unused device) +{ + rdpsndIOSPlugin *p = THIS(device); + + /* If the device is playing... */ + if (p->is_playing) + { + /* Stop the device. */ + AudioOutputUnitStop(p->audio_unit); + p->is_playing = 0; + + /* Free all buffers. */ + TPCircularBufferClear(&p->buffer); + } +} + +static void rdpsnd_ios_play(rdpsndDevicePlugin* device, BYTE* data, int size) +{ + rdpsndIOSPlugin *p = THIS(device); + + const BOOL ok = TPCircularBufferProduceBytes(&p->buffer, data, size); + if (!ok) + { + return; + } + + rdpsnd_ios_start(device); +} + +static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int __unused latency) +{ + rdpsndIOSPlugin *p = THIS(device); + + if (p->is_opened) + { + return; + } + + /* Find the output audio unit. */ + AudioComponentDescription desc; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_RemoteIO; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + AudioComponent audioComponent = AudioComponentFindNext(NULL, &desc); + if (audioComponent == NULL) return; + + /* Open the audio unit. */ + OSStatus status = AudioComponentInstanceNew(audioComponent, &p->audio_unit); + if (status != 0) return; + + /* Set the format for the AudioUnit. */ + AudioStreamBasicDescription audioFormat = {0}; + audioFormat.mSampleRate = format->nSamplesPerSec; + audioFormat.mFormatID = kAudioFormatLinearPCM; + audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; + audioFormat.mFramesPerPacket = 1; /* imminent property of the Linear PCM */ + audioFormat.mChannelsPerFrame = format->nChannels; + audioFormat.mBitsPerChannel = format->wBitsPerSample; + audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8; + audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket; + + status = AudioUnitSetProperty( + p->audio_unit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &audioFormat, + sizeof(audioFormat)); + if (status != 0) + { + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + /* Set up the AudioUnit callback. */ + AURenderCallbackStruct callbackStruct = {0}; + callbackStruct.inputProc = rdpsnd_ios_render_cb; + callbackStruct.inputProcRefCon = p; + status = AudioUnitSetProperty( + p->audio_unit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &callbackStruct, + sizeof(callbackStruct)); + if (status != 0) + { + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + /* Initialize the AudioUnit. */ + status = AudioUnitInitialize(p->audio_unit); + if (status != 0) + { + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + /* Allocate the circular buffer. */ + const BOOL ok = TPCircularBufferInit(&p->buffer, CIRCULAR_BUFFER_SIZE); + if (!ok) + { + AudioUnitUninitialize(p->audio_unit); + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + p->is_opened = 1; +} + +static void rdpsnd_ios_close(rdpsndDevicePlugin* device) +{ + rdpsndIOSPlugin *p = THIS(device); + + /* Make sure the device is stopped. */ + rdpsnd_ios_stop(device); + + /* If the device is open... */ + if (p->is_opened) + { + /* Close the device. */ + AudioUnitUninitialize(p->audio_unit); + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + p->is_opened = 0; + + /* Destroy the circular buffer. */ + TPCircularBufferCleanup(&p->buffer); + } +} + +static void rdpsnd_ios_free(rdpsndDevicePlugin* device) +{ + rdpsndIOSPlugin *p = THIS(device); + + /* Ensure the device is closed. */ + rdpsnd_ios_close(device); + + /* Free memory associated with the device. */ + free(p); +} + +#ifdef STATIC_CHANNELS +#define freerdp_rdpsnd_client_subsystem_entry ios_freerdp_rdpsnd_client_subsystem_entry +#endif + +int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) +{ + rdpsndIOSPlugin *p = (rdpsndIOSPlugin*)malloc(sizeof(rdpsndIOSPlugin)); + memset(p, 0, sizeof(rdpsndIOSPlugin)); + + p->device.Open = rdpsnd_ios_open; + p->device.FormatSupported = rdpsnd_ios_format_supported; + p->device.SetFormat = rdpsnd_ios_set_format; + p->device.SetVolume = rdpsnd_ios_set_volume; + p->device.Play = rdpsnd_ios_play; + p->device.Start = rdpsnd_ios_start; + p->device.Close = rdpsnd_ios_close; + p->device.Free = rdpsnd_ios_free; + + pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p); + + return 0; +} \ No newline at end of file diff --git a/channels/rdpsnd/client/pulse/CMakeLists.txt b/channels/rdpsnd/client/pulse/CMakeLists.txt index ab695b2c3..3d4a34b76 100644 --- a/channels/rdpsnd/client/pulse/CMakeLists.txt +++ b/channels/rdpsnd/client/pulse/CMakeLists.txt @@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp - MODULES freerdp-utils) + MODULES freerdp-codec freerdp-utils) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY}) diff --git a/channels/rdpsnd/server/CMakeLists.txt b/channels/rdpsnd/server/CMakeLists.txt index b6d0c0901..c98816d68 100644 --- a/channels/rdpsnd/server/CMakeLists.txt +++ b/channels/rdpsnd/server/CMakeLists.txt @@ -18,7 +18,8 @@ define_channel_server("rdpsnd") set(${MODULE_PREFIX}_SRCS - rdpsnd.c) + rdpsnd_main.c + rdpsnd_main.h) add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry") diff --git a/channels/rdpsnd/server/rdpsnd_main.c b/channels/rdpsnd/server/rdpsnd_main.c new file mode 100644 index 000000000..4bc7107d5 --- /dev/null +++ b/channels/rdpsnd/server/rdpsnd_main.c @@ -0,0 +1,572 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Server Audio Virtual Channel + * + * Copyright 2012 Vic Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include + +#include "rdpsnd_main.h" + +static BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s) +{ + int pos; + UINT16 i; + BOOL status; + + Stream_Write_UINT8(s, SNDC_FORMATS); + Stream_Write_UINT8(s, 0); + Stream_Seek_UINT16(s); + + Stream_Write_UINT32(s, 0); /* dwFlags */ + Stream_Write_UINT32(s, 0); /* dwVolume */ + Stream_Write_UINT32(s, 0); /* dwPitch */ + Stream_Write_UINT16(s, 0); /* wDGramPort */ + Stream_Write_UINT16(s, context->num_server_formats); /* wNumberOfFormats */ + Stream_Write_UINT8(s, context->block_no); /* cLastBlockConfirmed */ + Stream_Write_UINT16(s, 0x06); /* wVersion */ + Stream_Write_UINT8(s, 0); /* bPad */ + + for (i = 0; i < context->num_server_formats; i++) + { + Stream_Write_UINT16(s, context->server_formats[i].wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */ + Stream_Write_UINT16(s, context->server_formats[i].nChannels); /* nChannels */ + Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec); /* nSamplesPerSec */ + + Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec * + context->server_formats[i].nChannels * + context->server_formats[i].wBitsPerSample / 8); /* nAvgBytesPerSec */ + + Stream_Write_UINT16(s, context->server_formats[i].nBlockAlign); /* nBlockAlign */ + Stream_Write_UINT16(s, context->server_formats[i].wBitsPerSample); /* wBitsPerSample */ + Stream_Write_UINT16(s, context->server_formats[i].cbSize); /* cbSize */ + + if (context->server_formats[i].cbSize > 0) + { + Stream_Write(s, context->server_formats[i].data, context->server_formats[i].cbSize); + } + } + + pos = Stream_GetPosition(s); + Stream_SetPosition(s, 2); + Stream_Write_UINT16(s, pos - 4); + Stream_SetPosition(s, pos); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); + Stream_SetPosition(s, 0); + + return status; +} + +static void rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s) +{ + UINT16 timestamp = 0; + BYTE confirmBlockNum = 0; + Stream_Read_UINT16(s, timestamp); + Stream_Read_UINT8(s, confirmBlockNum); + Stream_Seek_UINT8(s); +} + +static void rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStream* s) +{ + UINT16 quality; + + Stream_Read_UINT16(s, quality); + Stream_Seek_UINT16(s); // reserved + + fprintf(stderr, "Client requested sound quality: %#0X\n", quality); +} + +static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s) +{ + int i, num_known_format = 0; + UINT32 flags, vol, pitch; + UINT16 udpPort, version; + BYTE lastblock; + + Stream_Read_UINT32(s, flags); /* dwFlags */ + Stream_Read_UINT32(s, vol); /* dwVolume */ + Stream_Read_UINT32(s, pitch); /* dwPitch */ + Stream_Read_UINT16(s, udpPort); /* wDGramPort */ + Stream_Read_UINT16(s, context->num_client_formats); /* wNumberOfFormats */ + Stream_Read_UINT8(s, lastblock); /* cLastBlockConfirmed */ + Stream_Read_UINT16(s, version); /* wVersion */ + Stream_Seek_UINT8(s); /* bPad */ + + if (context->num_client_formats > 0) + { + context->client_formats = (AUDIO_FORMAT*) malloc(context->num_client_formats * sizeof(AUDIO_FORMAT)); + ZeroMemory(context->client_formats, sizeof(AUDIO_FORMAT)); + + for (i = 0; i < context->num_client_formats; i++) + { + Stream_Read_UINT16(s, context->client_formats[i].wFormatTag); + Stream_Read_UINT16(s, context->client_formats[i].nChannels); + Stream_Read_UINT32(s, context->client_formats[i].nSamplesPerSec); + Stream_Read_UINT32(s, context->client_formats[i].nAvgBytesPerSec); + Stream_Read_UINT16(s, context->client_formats[i].nBlockAlign); + Stream_Read_UINT16(s, context->client_formats[i].wBitsPerSample); + Stream_Read_UINT16(s, context->client_formats[i].cbSize); + + if (context->client_formats[i].cbSize > 0) + { + Stream_Seek(s, context->client_formats[i].cbSize); + } + + if (context->client_formats[i].wFormatTag != 0) + { + //lets call this a known format + //TODO: actually look through our own list of known formats + num_known_format++; + } + } + } + + if (num_known_format == 0) + { + fprintf(stderr, "Client doesn't support any known formats!\n"); + return FALSE; + } + + return TRUE; +} + +static void* rdpsnd_server_thread(void* arg) +{ + wStream* s; + DWORD status; + DWORD nCount; + void* buffer; + BYTE msgType; + UINT16 BodySize; + HANDLE events[8]; + HANDLE ChannelEvent; + DWORD BytesReturned; + RdpsndServerContext* context; + + context = (RdpsndServerContext*) arg; + + buffer = NULL; + BytesReturned = 0; + ChannelEvent = NULL; + + s = Stream_New(NULL, 4096); + + if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) + { + if (BytesReturned == sizeof(HANDLE)) + CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); + + WTSFreeMemory(buffer); + } + + nCount = 0; + events[nCount++] = ChannelEvent; + events[nCount++] = context->priv->StopEvent; + + s = Stream_New(NULL, 4096); + rdpsnd_server_send_formats(context, s); + + while (1) + { + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + + if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) + { + break; + } + + Stream_SetPosition(s, 0); + + if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, + (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) + { + if (BytesReturned) + Stream_Seek(s, BytesReturned); + } + else + { + if (!BytesReturned) + break; + + Stream_EnsureRemainingCapacity(s, BytesReturned); + + if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, + (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) + { + break; + } + } + + Stream_Read_UINT8(s, msgType); + Stream_Seek_UINT8(s); /* bPad */ + Stream_Read_UINT16(s, BodySize); + + switch (msgType) + { + case SNDC_WAVECONFIRM: + rdpsnd_server_recv_waveconfirm(context, s); + break; + + case SNDC_QUALITYMODE: + rdpsnd_server_recv_quality_mode(context, s); + break; + + case SNDC_FORMATS: + if (rdpsnd_server_recv_formats(context, s)) + { + IFCALL(context->Activated, context); + } + break; + + default: + fprintf(stderr, "UNKOWN MESSAGE TYPE!! (%#0X)\n\n", msgType); + break; + } + } + + Stream_Free(s, TRUE); + + return NULL; +} + +static BOOL rdpsnd_server_initialize(RdpsndServerContext* context) +{ + context->Start(context); + return TRUE; +} + +static void rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index) +{ + int bs; + int out_buffer_size; + AUDIO_FORMAT *format; + + if (client_format_index < 0 || client_format_index >= context->num_client_formats) + { + fprintf(stderr, "rdpsnd_server_select_format: index %d is not correct.\n", client_format_index); + return; + } + + context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8; + context->priv->src_bytes_per_frame = context->priv->src_bytes_per_sample * context->src_format.nChannels; + + context->selected_client_format = client_format_index; + format = &context->client_formats[client_format_index]; + + if (format->nSamplesPerSec == 0) + { + fprintf(stderr, "Invalid Client Sound Format!!\n\n"); + return; + } + + if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM) + { + bs = (format->nBlockAlign - 4 * format->nChannels) * 4; + context->priv->out_frames = (format->nBlockAlign * 4 * format->nChannels * 2 / bs + 1) * bs / (format->nChannels * 2); + } + else if (format->wFormatTag == WAVE_FORMAT_ADPCM) + { + bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2; + context->priv->out_frames = bs * 4; + } + else + { + context->priv->out_frames = 0x4000 / context->priv->src_bytes_per_frame; + } + + if (format->nSamplesPerSec != context->src_format.nSamplesPerSec) + { + context->priv->out_frames = (context->priv->out_frames * context->src_format.nSamplesPerSec + format->nSamplesPerSec - 100) / format->nSamplesPerSec; + } + context->priv->out_pending_frames = 0; + + out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame; + + if (context->priv->out_buffer_size < out_buffer_size) + { + context->priv->out_buffer = (BYTE*) realloc(context->priv->out_buffer, out_buffer_size); + context->priv->out_buffer_size = out_buffer_size; + } + + freerdp_dsp_context_reset_adpcm(context->priv->dsp_context); +} + +static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context) +{ + int size; + BYTE* src; + int frames; + int fill_size; + BOOL status; + AUDIO_FORMAT* format; + int tbytes_per_frame; + wStream* s = context->priv->rdpsnd_pdu; + + format = &context->client_formats[context->selected_client_format]; + tbytes_per_frame = format->nChannels * context->priv->src_bytes_per_sample; + + if ((format->nSamplesPerSec == context->src_format.nSamplesPerSec) && + (format->nChannels == context->src_format.nChannels)) + { + src = context->priv->out_buffer; + frames = context->priv->out_pending_frames; + } + else + { + context->priv->dsp_context->resample(context->priv->dsp_context, context->priv->out_buffer, + context->priv->src_bytes_per_sample, context->src_format.nChannels, + context->src_format.nSamplesPerSec, context->priv->out_pending_frames, + format->nChannels, format->nSamplesPerSec); + frames = context->priv->dsp_context->resampled_frames; + src = context->priv->dsp_context->resampled_buffer; + } + size = frames * tbytes_per_frame; + + if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM) + { + context->priv->dsp_context->encode_ima_adpcm(context->priv->dsp_context, + src, size, format->nChannels, format->nBlockAlign); + src = context->priv->dsp_context->adpcm_buffer; + size = context->priv->dsp_context->adpcm_size; + } + else if (format->wFormatTag == WAVE_FORMAT_ADPCM) + { + context->priv->dsp_context->encode_ms_adpcm(context->priv->dsp_context, + src, size, format->nChannels, format->nBlockAlign); + src = context->priv->dsp_context->adpcm_buffer; + size = context->priv->dsp_context->adpcm_size; + } + + context->block_no = (context->block_no + 1) % 256; + + /* Fill to nBlockAlign for the last audio packet */ + + fill_size = 0; + + if ((format->wFormatTag == WAVE_FORMAT_DVI_ADPCM || format->wFormatTag == WAVE_FORMAT_ADPCM) && + (context->priv->out_pending_frames < context->priv->out_frames) && ((size % format->nBlockAlign) != 0)) + { + fill_size = format->nBlockAlign - (size % format->nBlockAlign); + } + + /* WaveInfo PDU */ + Stream_SetPosition(s, 0); + Stream_Write_UINT8(s, SNDC_WAVE); /* msgType */ + Stream_Write_UINT8(s, 0); /* bPad */ + Stream_Write_UINT16(s, size + fill_size + 8); /* BodySize */ + + Stream_Write_UINT16(s, 0); /* wTimeStamp */ + Stream_Write_UINT16(s, context->selected_client_format); /* wFormatNo */ + Stream_Write_UINT8(s, context->block_no); /* cBlockNo */ + Stream_Seek(s, 3); /* bPad */ + Stream_Write(s, src, 4); + + WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); + Stream_SetPosition(s, 0); + + /* Wave PDU */ + Stream_EnsureRemainingCapacity(s, size + fill_size); + Stream_Write_UINT32(s, 0); /* bPad */ + Stream_Write(s, src + 4, size - 4); + + if (fill_size > 0) + Stream_Zero(s, fill_size); + + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); + Stream_SetPosition(s, 0); + + context->priv->out_pending_frames = 0; + + return status; +} + +static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes) +{ + int cframes; + int cframesize; + + if (context->selected_client_format < 0) + return FALSE; + + while (nframes > 0) + { + cframes = MIN(nframes, context->priv->out_frames - context->priv->out_pending_frames); + cframesize = cframes * context->priv->src_bytes_per_frame; + + CopyMemory(context->priv->out_buffer + + (context->priv->out_pending_frames * context->priv->src_bytes_per_frame), buf, cframesize); + buf = (BYTE*) buf + cframesize; + nframes -= cframes; + context->priv->out_pending_frames += cframes; + + if (context->priv->out_pending_frames >= context->priv->out_frames) + { + if (!rdpsnd_server_send_audio_pdu(context)) + return FALSE; + } + } + + return TRUE; +} + +static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right) +{ + int pos; + BOOL status; + wStream* s = context->priv->rdpsnd_pdu; + + Stream_Write_UINT8(s, SNDC_SETVOLUME); + Stream_Write_UINT8(s, 0); + Stream_Seek_UINT16(s); + + Stream_Write_UINT16(s, left); + Stream_Write_UINT16(s, right); + + pos = Stream_GetPosition(s); + Stream_SetPosition(s, 2); + Stream_Write_UINT16(s, pos - 4); + Stream_SetPosition(s, pos); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); + Stream_SetPosition(s, 0); + + return status; +} + +static BOOL rdpsnd_server_close(RdpsndServerContext* context) +{ + int pos; + BOOL status; + wStream* s = context->priv->rdpsnd_pdu; + + if (context->selected_client_format < 0) + return FALSE; + + if (context->priv->out_pending_frames > 0) + { + if (!rdpsnd_server_send_audio_pdu(context)) + return FALSE; + } + + context->selected_client_format = -1; + + Stream_Write_UINT8(s, SNDC_CLOSE); + Stream_Write_UINT8(s, 0); + Stream_Seek_UINT16(s); + + pos = Stream_GetPosition(s); + Stream_SetPosition(s, 2); + Stream_Write_UINT16(s, pos - 4); + Stream_SetPosition(s, pos); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); + Stream_SetPosition(s, 0); + + return status; +} + +static int rdpsnd_server_start(RdpsndServerContext* context) +{ + context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpsnd", 0); + + if (!context->priv->ChannelHandle) + return -1; + + context->priv->rdpsnd_pdu = Stream_New(NULL, 4096); + + context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + context->priv->Thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL); + + return 0; +} + +static int rdpsnd_server_stop(RdpsndServerContext* context) +{ + SetEvent(context->priv->StopEvent); + + WaitForSingleObject(context->priv->Thread, INFINITE); + CloseHandle(context->priv->Thread); + + return 0; +} + +RdpsndServerContext* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm) +{ + RdpsndServerContext* context; + + context = (RdpsndServerContext*) malloc(sizeof(RdpsndServerContext)); + + if (context) + { + ZeroMemory(context, sizeof(RdpsndServerContext)); + + context->vcm = vcm; + + context->Start = rdpsnd_server_start; + context->Stop = rdpsnd_server_stop; + + context->selected_client_format = -1; + context->Initialize = rdpsnd_server_initialize; + context->SelectFormat = rdpsnd_server_select_format; + context->SendSamples = rdpsnd_server_send_samples; + context->SetVolume = rdpsnd_server_set_volume; + context->Close = rdpsnd_server_close; + + context->priv = (RdpsndServerPrivate*) malloc(sizeof(RdpsndServerPrivate)); + + if (context->priv) + { + ZeroMemory(context->priv, sizeof(RdpsndServerPrivate)); + + context->priv->dsp_context = freerdp_dsp_context_new(); + } + } + + return context; +} + +void rdpsnd_server_context_free(RdpsndServerContext* context) +{ + SetEvent(context->priv->StopEvent); + WaitForSingleObject(context->priv->Thread, INFINITE); + + if (context->priv->ChannelHandle) + WTSVirtualChannelClose(context->priv->ChannelHandle); + + if (context->priv->rdpsnd_pdu) + Stream_Free(context->priv->rdpsnd_pdu, TRUE); + + if (context->priv->out_buffer) + free(context->priv->out_buffer); + + if (context->priv->dsp_context) + freerdp_dsp_context_free(context->priv->dsp_context); + + if (context->client_formats) + free(context->client_formats); + + free(context); +} diff --git a/channels/rdpsnd/server/rdpsnd_main.h b/channels/rdpsnd/server/rdpsnd_main.h new file mode 100644 index 000000000..6322cee4a --- /dev/null +++ b/channels/rdpsnd/server/rdpsnd_main.h @@ -0,0 +1,48 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Server Audio Virtual Channel + * + * Copyright 2012 Vic Lee + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H +#define FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H + +#include +#include +#include + +#include +#include +#include + +struct _rdpsnd_server_private +{ + HANDLE Thread; + HANDLE StopEvent; + void* ChannelHandle; + + wStream* rdpsnd_pdu; + BYTE* out_buffer; + int out_buffer_size; + int out_frames; + int out_pending_frames; + UINT32 src_bytes_per_sample; + UINT32 src_bytes_per_frame; + FREERDP_DSP_CONTEXT* dsp_context; +}; + +#endif /* FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H */ diff --git a/channels/server/channels.c b/channels/server/channels.c index eeae1dc22..35da5afb2 100644 --- a/channels/server/channels.c +++ b/channels/server/channels.c @@ -42,6 +42,9 @@ #include #include +#include +#include +#include void freerdp_channels_dummy() { @@ -50,6 +53,15 @@ void freerdp_channels_dummy() rdpsnd_server_context_new(NULL); rdpsnd_server_context_free(NULL); + + cliprdr_server_context_new(NULL); + cliprdr_server_context_free(NULL); + + rdpdr_server_context_new(NULL); + rdpdr_server_context_free(NULL); + + drdynvc_server_context_new(NULL); + drdynvc_server_context_free(NULL); } /** @@ -420,7 +432,7 @@ WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client) vcm = (WTSVirtualChannelManager*) malloc(sizeof(WTSVirtualChannelManager)); - if (vcm != NULL) + if (vcm) { ZeroMemory(vcm, sizeof(WTSVirtualChannelManager)); @@ -470,8 +482,7 @@ void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm) } } -void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, - void** fds, int* fds_count) +void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count) { void* fd; @@ -507,13 +518,13 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm) /* Initialize drdynvc channel once and only once. */ vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED; - channel = WTSVirtualChannelOpenEx(vcm, "drdynvc", 0); + channel = WTSVirtualChannelManagerOpenEx(vcm, "drdynvc", 0); if (channel) { vcm->drdynvc_channel = channel; dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */ - WTSVirtualChannelWrite(channel, (BYTE*) &dynvc_caps, sizeof(dynvc_caps), NULL); + WTSVirtualChannelWrite(channel, (PCHAR) &dynvc_caps, sizeof(dynvc_caps), NULL); } } @@ -539,10 +550,12 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm) return result; } -void* WTSVirtualChannelOpenEx( - /* __in */ WTSVirtualChannelManager* vcm, - /* __in */ const char* pVirtualName, - /* __in */ UINT32 flags) +HANDLE WTSVirtualChannelManagerGetEventHandle(WTSVirtualChannelManager* vcm) +{ + return vcm->send_event; +} + +HANDLE WTSVirtualChannelManagerOpenEx(WTSVirtualChannelManager* vcm, LPSTR pVirtualName, DWORD flags) { int i; int len; @@ -592,7 +605,7 @@ void* WTSVirtualChannelOpenEx( s = Stream_New(NULL, 64); wts_write_drdynvc_create_request(s, channel->channel_id, pVirtualName); - WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL); + WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); Stream_Free(s, TRUE); DEBUG_DVC("ChannelId %d.%s (total %d)", channel->channel_id, pVirtualName, list_size(vcm->dvc_channel_list)); @@ -646,11 +659,7 @@ void* WTSVirtualChannelOpenEx( return channel; } -BOOL WTSVirtualChannelQuery( - /* __in */ void* hChannelHandle, - /* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass, - /* __out */ void** ppBuffer, - /* __out */ UINT32* pBytesReturned) +BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned) { void* pfd; BOOL bval; @@ -659,6 +668,7 @@ BOOL WTSVirtualChannelQuery( BOOL result = FALSE; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; ZeroMemory(fds, sizeof(fds)); + switch (WtsVirtualClass) { case WTSVirtualFileHandle: @@ -677,6 +687,13 @@ BOOL WTSVirtualChannelQuery( result = TRUE; break; + case WTSVirtualEventHandle: + *ppBuffer = malloc(sizeof(HANDLE)); + CopyMemory(*ppBuffer, &(channel->receive_event), sizeof(HANDLE)); + *pBytesReturned = sizeof(void*); + result = TRUE; + break; + case WTSVirtualChannelReady: if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) { @@ -715,25 +732,19 @@ BOOL WTSVirtualChannelQuery( return result; } -void WTSFreeMemory( - /* __in */ void* pMemory) +VOID WTSFreeMemory(PVOID pMemory) { free(pMemory); } -BOOL WTSVirtualChannelRead( - /* __in */ void* hChannelHandle, - /* __in */ UINT32 TimeOut, - /* __out */ BYTE* Buffer, - /* __in */ UINT32 BufferSize, - /* __out */ UINT32* pBytesRead) +BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead) { wts_data_item* item; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; item = (wts_data_item*) list_peek(channel->receive_queue); - if (item == NULL) + if (!item) { ResetEvent(channel->receive_event); *pBytesRead = 0; @@ -755,16 +766,12 @@ BOOL WTSVirtualChannelRead( ReleaseMutex(channel->mutex); CopyMemory(Buffer, item->buffer, item->length); - wts_data_item_free(item) ; + wts_data_item_free(item); return TRUE; } -BOOL WTSVirtualChannelWrite( - /* __in */ void* hChannelHandle, - /* __in */ BYTE* Buffer, - /* __in */ UINT32 Length, - /* __out */ UINT32* pBytesWritten) +BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten) { rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; wts_data_item* item; @@ -774,7 +781,7 @@ BOOL WTSVirtualChannelWrite( int first; UINT32 written; - if (channel == NULL) + if (!channel) return FALSE; if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) @@ -841,8 +848,7 @@ BOOL WTSVirtualChannelWrite( return TRUE; } -BOOL WTSVirtualChannelClose( - /* __in */ void* hChannelHandle) +BOOL WTSVirtualChannelClose(HANDLE hChannelHandle) { wStream* s; wts_data_item* item; @@ -868,7 +874,7 @@ BOOL WTSVirtualChannelClose( { s = Stream_New(NULL, 8); wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channel_id); - WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL); + WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL); Stream_Free(s, TRUE); } } diff --git a/channels/tsmf/client/alsa/CMakeLists.txt b/channels/tsmf/client/alsa/CMakeLists.txt index 2ad1dcb71..bf2528206 100644 --- a/channels/tsmf/client/alsa/CMakeLists.txt +++ b/channels/tsmf/client/alsa/CMakeLists.txt @@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp - MODULES freerdp-utils) + MODULES freerdp-codec freerdp-utils) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES}) diff --git a/channels/tsmf/client/pulse/CMakeLists.txt b/channels/tsmf/client/pulse/CMakeLists.txt index 613485b80..c201b5253 100644 --- a/channels/tsmf/client/pulse/CMakeLists.txt +++ b/channels/tsmf/client/pulse/CMakeLists.txt @@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp - MODULES freerdp-utils) + MODULES freerdp-codec freerdp-utils) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY}) diff --git a/client/.gitignore b/client/.gitignore index 86106bc3c..8a070de0c 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1,4 +1,10 @@ -WaykClient - - -DotNetClient \ No newline at end of file +/* +!/Android +!/common +!/DirectFB +!/iOS +!/Mac +!/Sample +!/Windows +!/X11 +!/CMakeLists.txt diff --git a/client/Android/ModuleOptions.cmake b/client/Android/ModuleOptions.cmake new file mode 100644 index 000000000..38f85b400 --- /dev/null +++ b/client/Android/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_CLIENT_NAME "afreerdp") +set(FREERDP_CLIENT_PLATFORM "Android") +set(FREERDP_CLIENT_VENDOR "FreeRDP") diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index e78c37517..0c4c35aa2 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -51,10 +51,29 @@ if(ANDROID) add_subdirectory(Android) endif() -if(WITH_WAYK) - add_subdirectory(WaykClient) -endif() +# Pick up other clients + +set(FILENAME "ModuleOptions.cmake") +file(GLOB FILEPATHS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/${FILENAME}") + +foreach(FILEPATH ${FILEPATHS}) + if(${FILEPATH} MATCHES "^([^/]*)//${FILENAME}") + string(REGEX REPLACE "^([^/]*)//${FILENAME}" "\\1" FREERDP_CLIENT ${FILEPATH}) + set(FREERDP_CLIENT_ENABLED 0) + include(${FILEPATH}) + if(FREERDP_CLIENT_ENABLED) + if(NOT (${FREERDP_CLIENT_VENDOR} MATCHES "FreeRDP")) + list(APPEND FREERDP_EXTRA_CLIENTS ${FREERDP_CLIENT}) + if(${FREERDP_CLIENT_VENDOR} MATCHES "${VENDOR}") + set(CLIENT_VENDOR_PATH "client/${FREERDP_CLIENT}" PARENT_SCOPE) + endif() + endif() + endif() + endif() +endforeach() + +foreach(FREERDP_CLIENT ${FREERDP_EXTRA_CLIENTS}) + add_subdirectory(${FREERDP_CLIENT}) +endforeach() + -if (WITH_DOTNET) - add_subdirectory(DotNetClient) -endif() diff --git a/client/DirectFB/ModuleOptions.cmake b/client/DirectFB/ModuleOptions.cmake new file mode 100644 index 000000000..2ef9266f0 --- /dev/null +++ b/client/DirectFB/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_CLIENT_NAME "dfreerdp") +set(FREERDP_CLIENT_PLATFORM "DirectFB") +set(FREERDP_CLIENT_VENDOR "FreeRDP") diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt index 2344f46a1..75b62161a 100755 --- a/client/Mac/CMakeLists.txt +++ b/client/Mac/CMakeLists.txt @@ -85,7 +85,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHI MODULE winpr MODULES winpr-input winpr-crt winpr-utils) -set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "") target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) # Set a list of the dependent targets used by the application. There should be a way to get this list automatically diff --git a/client/Mac/ModuleOptions.cmake b/client/Mac/ModuleOptions.cmake new file mode 100644 index 000000000..3902d2b71 --- /dev/null +++ b/client/Mac/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_CLIENT_NAME "mfreerdp") +set(FREERDP_CLIENT_PLATFORM "MacOSX") +set(FREERDP_CLIENT_VENDOR "FreeRDP") diff --git a/client/Sample/ModuleOptions.cmake b/client/Sample/ModuleOptions.cmake new file mode 100644 index 000000000..d4d5a9e44 --- /dev/null +++ b/client/Sample/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_CLIENT_NAME "sfreerdp") +set(FREERDP_CLIENT_PLATFORM "Sample") +set(FREERDP_CLIENT_VENDOR "FreeRDP") diff --git a/client/Windows/CMakeLists.txt b/client/Windows/CMakeLists.txt index f32422cd3..0f2b26d65 100644 --- a/client/Windows/CMakeLists.txt +++ b/client/Windows/CMakeLists.txt @@ -63,10 +63,8 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) if(WITH_CLIENT_INTERFACE) - if (NOT WITH_WAYK) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) add_subdirectory(cli) - endif() else() install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client) endif() diff --git a/client/Windows/ModuleOptions.cmake b/client/Windows/ModuleOptions.cmake new file mode 100644 index 000000000..a0fcaec59 --- /dev/null +++ b/client/Windows/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_CLIENT_NAME "wfreerdp") +set(FREERDP_CLIENT_PLATFORM "Windows") +set(FREERDP_CLIENT_VENDOR "FreeRDP") diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index b69c29794..b4969a933 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -371,7 +371,7 @@ BOOL wf_post_connect(freerdp* instance) if (settings->RemoteFxCodec) { wfc->tile = wf_image_new(wfc, 64, 64, 32, NULL); - wfc->rfx_context = rfx_context_new(); + wfc->rfx_context = rfx_context_new(FALSE); } if (settings->NSCodec) diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index 907200733..3a8749c56 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -92,8 +92,6 @@ if(WITH_MANPAGES) MODULE freerdp MODULES freerdp-core freerdp-utils) - message(WARNING "GAD_LIBS: ${GAD_LIBS}") - target_link_libraries(generate_argument_docbook ${GAD_LIBS}) add_custom_command(OUTPUT xfreerdp.1 diff --git a/client/X11/ModuleOptions.cmake b/client/X11/ModuleOptions.cmake new file mode 100644 index 000000000..4fef68a2f --- /dev/null +++ b/client/X11/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_CLIENT_NAME "xfreerdp") +set(FREERDP_CLIENT_PLATFORM "X11") +set(FREERDP_CLIENT_VENDOR "FreeRDP") diff --git a/client/X11/generate_argument_docbook.c b/client/X11/generate_argument_docbook.c index 09ac6a36b..75bef5f04 100644 --- a/client/X11/generate_argument_docbook.c +++ b/client/X11/generate_argument_docbook.c @@ -155,12 +155,12 @@ int main(int argc, char *argv[]) const COMMAND_LINE_ARGUMENT_A *arg = &args[x]; fprintf(fp, "\t\t\t\n"); - if( COMMAND_LINE_VALUE_REQUIRED == arg->Flags ) - fprintf(fp, "\t\t\t\t %s\n", tr_esc_str(arg->Name), tr_esc_str(arg->Format) ); + if ( COMMAND_LINE_VALUE_REQUIRED == arg->Flags) + fprintf(fp, "\t\t\t\t %s\n", tr_esc_str((LPSTR) arg->Name), tr_esc_str(arg->Format) ); else - fprintf(fp, "\t\t\t\t\n", tr_esc_str(arg->Name) ); + fprintf(fp, "\t\t\t\t\n", tr_esc_str((LPSTR) arg->Name)); fprintf(fp, "\t\t\t\t\n"); - fprintf(fp, "\t\t\t\t\t%s\n", tr_esc_str(arg->Text)); + fprintf(fp, "\t\t\t\t\t%s\n", tr_esc_str((LPSTR) arg->Text)); fprintf(fp, "\t\t\t\t\n"); fprintf(fp, "\t\t\t\n"); diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index a3f266209..8a29b2d5c 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -908,7 +908,7 @@ BOOL xf_post_connect(freerdp* instance) if (instance->settings->RemoteFxCodec) { - rfx_context = (void*) rfx_context_new(); + rfx_context = (void*) rfx_context_new(FALSE); xfc->rfx_context = rfx_context; } diff --git a/client/X11/xf_monitor.h b/client/X11/xf_monitor.h index 9e29eec85..316c5ad0d 100644 --- a/client/X11/xf_monitor.h +++ b/client/X11/xf_monitor.h @@ -20,6 +20,7 @@ #ifndef __XF_MONITOR_H #define __XF_MONITOR_H +#include #include #include @@ -43,8 +44,8 @@ typedef struct _VIRTUAL_SCREEN VIRTUAL_SCREEN; #include "xf_client.h" #include "xfreerdp.h" -int xf_list_monitors(xfContext* xfc); -BOOL xf_detect_monitors(xfContext* xfc, rdpSettings* settings); -void xf_monitors_free(xfContext *xfc, rdpSettings *settings); +FREERDP_API int xf_list_monitors(xfContext* xfc); +FREERDP_API BOOL xf_detect_monitors(xfContext* xfc, rdpSettings* settings); +FREERDP_API void xf_monitors_free(xfContext *xfc, rdpSettings *settings); #endif /* __XF_MONITOR_H */ diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index a7aaa70a2..9cb78b946 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -22,6 +22,8 @@ typedef struct xf_context xfContext; +#include + #include "xf_window.h" #include "xf_monitor.h" #include "xf_channels.h" @@ -215,7 +217,7 @@ void xf_unlock_x11(xfContext* xfc, BOOL display); void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale); void xf_transform_window(xfContext* xfc); -DWORD xf_exit_code_from_disconnect_reason(DWORD reason); +FREERDP_API DWORD xf_exit_code_from_disconnect_reason(DWORD reason); #endif /* __XFREERDP_H */ diff --git a/client/common/CMakeLists.txt b/client/common/CMakeLists.txt index 2b9841e5f..a5cfd6ef6 100644 --- a/client/common/CMakeLists.txt +++ b/client/common/CMakeLists.txt @@ -52,11 +52,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHI target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) -set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "") - -if (NOT WITH_WAYK) - install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) -endif() +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Common") diff --git a/client/common/compatibility.h b/client/common/compatibility.h index 5d2077d27..358587c93 100644 --- a/client/common/compatibility.h +++ b/client/common/compatibility.h @@ -23,8 +23,8 @@ #include #include -int freerdp_detect_old_command_line_syntax(int argc, char** argv, int* count); -int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSettings* settings); +FREERDP_API int freerdp_detect_old_command_line_syntax(int argc, char** argv, int* count); +FREERDP_API int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSettings* settings); #endif /* FREERDP_CLIENT_COMPATIBILITY */ diff --git a/client/iOS/ModuleOptions.cmake b/client/iOS/ModuleOptions.cmake new file mode 100644 index 000000000..3c4b366bb --- /dev/null +++ b/client/iOS/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_CLIENT_NAME "ifreerdp") +set(FREERDP_CLIENT_PLATFORM "iOS") +set(FREERDP_CLIENT_VENDOR "FreeRDP") diff --git a/cmake/ComplexLibrary.cmake b/cmake/ComplexLibrary.cmake index 1b04f3f20..993fd2c52 100644 --- a/cmake/ComplexLibrary.cmake +++ b/cmake/ComplexLibrary.cmake @@ -1,4 +1,6 @@ + +include(EchoTarget) include(CMakeParseArguments) macro(set_complex_link_libraries) @@ -46,3 +48,32 @@ macro(add_complex_library) endif() endmacro(add_complex_library) + +if(${CMAKE_VERSION} VERSION_GREATER 2.8.8) + set(CMAKE_OBJECT_TARGET_SUPPORT 1) +endif() + +function(create_object_cotarget target) + + set(cotarget "${target}-objects") + + get_target_property(${target}_TYPE ${target} TYPE) + + if(NOT ((${target}_TYPE MATCHES "SHARED_LIBRARY") OR (${target}_TYPE MATCHES "SHARED_LIBRARY"))) + return() + endif() + + get_target_property(${target}_SOURCES ${target} SOURCES) + get_target_property(${target}_LINK_LIBRARIES ${target} LINK_LIBRARIES) + get_target_property(${target}_INCLUDE_DIRECTORIES ${target} INCLUDE_DIRECTORIES) + + add_library(${cotarget} "OBJECT" ${${target}_SOURCES}) + + set_target_properties(${cotarget} PROPERTIES LINK_LIBRARIES "${${target}_LINK_LIBRARIES}") + set_target_properties(${cotarget} PROPERTIES INCLUDE_DIRECTORIES "${${target}_INCLUDE_DIRECTORIES}") + + echo_target(${target}) + echo_target(${cotarget}) + +endfunction() + diff --git a/cmake/EchoTarget.cmake b/cmake/EchoTarget.cmake new file mode 100644 index 000000000..12759256b --- /dev/null +++ b/cmake/EchoTarget.cmake @@ -0,0 +1,178 @@ +function(echo_target_property tgt prop) + # v for value, d for defined, s for set + get_property(v TARGET ${tgt} PROPERTY ${prop}) + get_property(d TARGET ${tgt} PROPERTY ${prop} DEFINED) + get_property(s TARGET ${tgt} PROPERTY ${prop} SET) + + # only produce output for values that are set + if(s) + message("tgt='${tgt}' prop='${prop}'") + message(" value='${v}'") + message(" defined='${d}'") + message(" set='${s}'") + message("") + endif() +endfunction() + +function(echo_target tgt) + if(NOT TARGET ${tgt}) + message("There is no target named '${tgt}'") + return() + endif() + + set(props + DEBUG_OUTPUT_NAME + RELEASE_OUTPUT_NAME + DEBUG_POSTFIX + RELEASE_POSTFIX + ARCHIVE_OUTPUT_DIRECTORY + ARCHIVE_OUTPUT_DIRECTORY_DEBUG + ARCHIVE_OUTPUT_DIRECTORY_RELEASE + ARCHIVE_OUTPUT_NAME + ARCHIVE_OUTPUT_NAME_DEBUG + ARCHIVE_OUTPUT_NAME_RELEASE + AUTOMOC + AUTOMOC_MOC_OPTIONS + BUILD_WITH_INSTALL_RPATH + BUNDLE + BUNDLE_EXTENSION + COMPILE_DEFINITIONS + COMPILE_DEFINITIONS_DEBUG + COMPILE_DEFINITIONS_RELEASE + COMPILE_FLAGS + DEBUG_POSTFIX + DEFINE_SYMBOL + ENABLE_EXPORTS + EXCLUDE_FROM_ALL + EchoString + FOLDER + FRAMEWORK + Fortran_FORMAT + Fortran_MODULE_DIRECTORY + GENERATOR_FILE_NAME + GNUtoMS + HAS_CXX + IMPLICIT_DEPENDS_INCLUDE_TRANSFORM + IMPORTED + IMPORTED_CONFIGURATIONS + IMPORTED_IMPLIB + IMPORTED_IMPLIB_RELEASE + IMPORTED_IMPLIB_RELEASE + IMPORTED_LINK_DEPENDENT_LIBRARIES + IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG + IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE + IMPORTED_LINK_INTERFACE_LANGUAGES + IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE + IMPORTED_LINK_INTERFACE_LIBRARIES + IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG + IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE + IMPORTED_LINK_INTERFACE_MULTIPLICITY + IMPORTED_LINK_INTERFACE_MULTIPLICITY_DEBUG + IMPORTED_LINK_INTERFACE_MULTIPLICITY_RELEASE + IMPORTED_LOCATION + IMPORTED_LOCATION_DEBUG + IMPORTED_LOCATION_RELEASE + IMPORTED_NO_SONAME + IMPORTED_NO_SONAME_DEBUG + IMPORTED_NO_SONAME_RELEASE + IMPORTED_SONAME + IMPORTED_SONAME_DEBUG + IMPORTED_SONAME_RELEASE + IMPORT_PREFIX + IMPORT_SUFFIX + INCLUDE_DIRECTORIES + INSTALL_NAME_DIR + INSTALL_RPATH + INSTALL_RPATH_USE_LINK_PATH + INTERPROCEDURAL_OPTIMIZATION + INTERPROCEDURAL_OPTIMIZATION_DEBUG + INTERPROCEDURAL_OPTIMIZATION_RELEASE + LABELS + LIBRARY_OUTPUT_DIRECTORY + LIBRARY_OUTPUT_DIRECTORY_DEBUG + LIBRARY_OUTPUT_DIRECTORY_RELEASE + LIBRARY_OUTPUT_NAME + LIBRARY_OUTPUT_NAME_DEBUG + LIBRARY_OUTPUT_NAME_RELEASE + LINKER_LANGUAGE + LINK_DEPENDS + LINK_LIBRARIES + LINK_FLAGS + LINK_FLAGS_DEBUG + LINK_FLAGS_RELEASE + LINK_INTERFACE_LIBRARIES + LINK_INTERFACE_LIBRARIES_DEBUG + LINK_INTERFACE_LIBRARIES_RELEASE + LINK_INTERFACE_MULTIPLICITY + LINK_INTERFACE_MULTIPLICITY_DEBUG + LINK_INTERFACE_MULTIPLICITY_RELEASE + LINK_SEARCH_END_STATIC + LINK_SEARCH_START_STATIC + LOCATION + LOCATION_DEBUG + LOCATION_RELEASE + MACOSX_BUNDLE + MACOSX_BUNDLE_INFO_PLIST + MACOSX_FRAMEWORK_INFO_PLIST + MAP_IMPORTED_CONFIG_DEBUG + MAP_IMPORTED_CONFIG_RELEASE + OSX_ARCHITECTURES + OSX_ARCHITECTURES_DEBUG + OSX_ARCHITECTURES_RELEASE + OUTPUT_NAME + OUTPUT_NAME_DEBUG + OUTPUT_NAME_RELEASE + POST_INSTALL_SCRIPT + PREFIX + PRE_INSTALL_SCRIPT + PRIVATE_HEADER + PROJECT_LABEL + PUBLIC_HEADER + RESOURCE + RULE_LAUNCH_COMPILE + RULE_LAUNCH_CUSTOM + RULE_LAUNCH_LINK + RUNTIME_OUTPUT_DIRECTORY + RUNTIME_OUTPUT_DIRECTORY_DEBUG + RUNTIME_OUTPUT_DIRECTORY_RELEASE + RUNTIME_OUTPUT_NAME + RUNTIME_OUTPUT_NAME_DEBUG + RUNTIME_OUTPUT_NAME_RELEASE + SKIP_BUILD_RPATH + SOURCES + SOVERSION + STATIC_LIBRARY_FLAGS + STATIC_LIBRARY_FLAGS_DEBUG + STATIC_LIBRARY_FLAGS_RELEASE + SUFFIX + TYPE + VERSION + VS_DOTNET_REFERENCES + VS_GLOBAL_KEYWORD + VS_GLOBAL_PROJECT_TYPES + VS_KEYWORD + VS_SCC_AUXPATH + VS_SCC_LOCALPATH + VS_SCC_PROJECTNAME + VS_SCC_PROVIDER + VS_WINRT_EXTENSIONS + VS_WINRT_REFERENCES + WIN32_EXECUTABLE + ) + + message("======================== ${tgt} ========================") + foreach(p ${props}) + echo_target_property("${tgt}" "${p}") + endforeach() + message("") + +endfunction() + +function(echo_targets) + set(tgts ${ARGV}) + foreach(t ${tgts}) + echo_target("${t}") + endforeach() +endfunction() + diff --git a/cmake/MergeStaticLibs.cmake b/cmake/MergeStaticLibs.cmake index a0673fa7e..4fa5dad9c 100644 --- a/cmake/MergeStaticLibs.cmake +++ b/cmake/MergeStaticLibs.cmake @@ -12,16 +12,19 @@ # You should have received a copy of the FMILIB_License.txt file # along with this program. If not, contact Modelon AB . -# Merge_static_libs(outlib lib1 lib2 ... libn) merges a number of static +# Merge_static_libs(output_library lib1 lib2 ... libn) merges a number of static # libs into a single static library -function(merge_static_libs outlib) +function(merge_static_libs output_library) + set(output_target "${output_library}") + string(REGEX REPLACE "-" "_" output_library ${output_library}) set(libs ${ARGV}) list(REMOVE_AT libs 0) -# Create a dummy file that the target will depend on - set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${outlib}_dummy.c) + + # Create a dummy file that the target will depend on + set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${output_library}_dummy.c) file(WRITE ${dummyfile} "const char * dummy = \"${dummyfile}\";") - add_library(${outlib} STATIC ${dummyfile}) + add_library(${output_target} STATIC ${dummyfile}) if("${CMAKE_CFG_INTDIR}" STREQUAL ".") set(multiconfig FALSE) @@ -29,7 +32,7 @@ function(merge_static_libs outlib) set(multiconfig TRUE) endif() -# First get the file names of the libraries to be merged + # First get the file names of the libraries to be merged foreach(lib ${libs}) get_target_property(libtype ${lib} TYPE) if(NOT libtype STREQUAL "STATIC_LIBRARY") @@ -45,8 +48,8 @@ function(merge_static_libs outlib) list(APPEND libfiles "${libfile}") endif(multiconfig) endforeach() - #message(STATUS "will be merging ${libfiles}") -# Just to be sure: cleanup from duplicates + + # Just to be sure: cleanup from duplicates if(multiconfig) foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES}) list(REMOVE_DUPLICATES libfiles_${CONFIG_TYPE}) @@ -55,7 +58,7 @@ function(merge_static_libs outlib) endif() list(REMOVE_DUPLICATES libfiles) -# Now the easy part for MSVC and for MAC + # Now the easy part for MSVC and for MAC if(MSVC) # lib.exe does the merging of libraries just need to conver the list into string foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES}) @@ -64,7 +67,7 @@ function(merge_static_libs outlib) set(flags "${flags} ${lib}") endforeach() string(TOUPPER "STATIC_LIBRARY_FLAGS_${CONFIG_TYPE}" PROPNAME) - set_target_properties(${outlib} PROPERTIES ${PROPNAME} "${flags}") + set_target_properties(${output_target} PROPERTIES ${PROPNAME} "${flags}") endforeach() elseif(APPLE) @@ -72,8 +75,8 @@ function(merge_static_libs outlib) if(multiconfig) message(FATAL_ERROR "Multiple configurations are not supported") endif() - get_target_property(outfile ${outlib} LOCATION) - add_custom_command(TARGET ${outlib} POST_BUILD + get_target_property(outfile ${output_target} LOCATION) + add_custom_command(TARGET ${output_target} POST_BUILD COMMAND rm ${outfile} COMMAND /usr/bin/libtool -static -o ${outfile} ${libfiles} @@ -83,48 +86,66 @@ function(merge_static_libs outlib) if(multiconfig) message(FATAL_ERROR "Multiple configurations are not supported") endif() - get_target_property(outfile ${outlib} LOCATION) - message(STATUS "outfile location is ${outfile}") + get_target_property(outfile ${output_target} LOCATION) + message(STATUS "output file location is ${outfile}") foreach(lib ${libfiles}) -# objlistfile will contain the list of object files for the library + # objlistfile will contain the list of object files for the library set(objlistfile ${lib}.objlist) set(objdir ${lib}.objdir) set(objlistcmake ${objlistfile}.cmake) -# we only need to extract files once + get_filename_component(libname ${lib} NAME_WE) + if(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/cmake.check_cache IS_NEWER_THAN ${objlistcmake}) -#--------------------------------- - FILE(WRITE ${objlistcmake} -"# Extract object files from the library -message(STATUS \"Extracting object files from ${lib}\") -EXECUTE_PROCESS(COMMAND ${CMAKE_AR} -x ${lib} - WORKING_DIRECTORY ${objdir}) -# save the list of object files -EXECUTE_PROCESS(COMMAND ls . - OUTPUT_FILE ${objlistfile} - WORKING_DIRECTORY ${objdir})") -#--------------------------------- + + file(WRITE ${objlistcmake} " + # delete previous object files + message(STATUS \"Removing previous object files from ${lib}\") + EXECUTE_PROCESS(COMMAND ls . + WORKING_DIRECTORY ${objdir} + COMMAND xargs -I {} rm {} + WORKING_DIRECTORY ${objdir}) + # Extract object files from the library + message(STATUS \"Extracting object files from ${lib}\") + EXECUTE_PROCESS(COMMAND ${CMAKE_AR} -x ${lib} + WORKING_DIRECTORY ${objdir}) + # Prefixing object files to avoid conflicts + message(STATUS \"Prefixing object files to avoid conflicts\") + EXECUTE_PROCESS(COMMAND ls . + WORKING_DIRECTORY ${objdir} + COMMAND xargs -I {} mv {} ${libname}_{} + WORKING_DIRECTORY ${objdir}) + # save the list of object files + EXECUTE_PROCESS(COMMAND ls . + OUTPUT_FILE ${objlistfile} + WORKING_DIRECTORY ${objdir}) + ") + file(MAKE_DIRECTORY ${objdir}) + add_custom_command( OUTPUT ${objlistfile} COMMAND ${CMAKE_COMMAND} -P ${objlistcmake} DEPENDS ${lib}) + endif() + list(APPEND extrafiles "${objlistfile}") # relative path is needed by ar under MSYS file(RELATIVE_PATH objlistfilerpath ${objdir} ${objlistfile}) - add_custom_command(TARGET ${outlib} POST_BUILD + add_custom_command(TARGET ${output_target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Running: ${CMAKE_AR} ru ${outfile} @${objlistfilerpath}" COMMAND ${CMAKE_AR} ru "${outfile}" @"${objlistfilerpath}" - WORKING_DIRECTORY ${objdir}) + #COMMAND ld -r -static -o "${outfile}" --whole-archive @"${objlistfilerpath}" + WORKING_DIRECTORY ${objdir}) endforeach() - add_custom_command(TARGET ${outlib} POST_BUILD + add_custom_command(TARGET ${output_target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Running: ${CMAKE_RANLIB} ${outfile}" COMMAND ${CMAKE_RANLIB} ${outfile}) endif() - file(WRITE ${dummyfile}.base "const char* ${outlib}_sublibs=\"${libs}\";") + file(WRITE ${dummyfile}.base "const char* ${output_library}_sublibs=\"${libs}\";") add_custom_command( - OUTPUT ${dummyfile} - COMMAND ${CMAKE_COMMAND} -E copy ${dummyfile}.base ${dummyfile} + OUTPUT ${dummyfile} + COMMAND ${CMAKE_COMMAND} -E copy ${dummyfile}.base ${dummyfile} DEPENDS ${libs} ${extrafiles}) endfunction() diff --git a/config.h.in b/config.h.in index 83b0abecb..bbbe36102 100755 --- a/config.h.in +++ b/config.h.in @@ -32,6 +32,7 @@ #cmakedefine HAVE_EVENTFD_H #cmakedefine HAVE_TIMERFD_H #cmakedefine HAVE_TM_GMTOFF +#cmakedefine HAVE_AIO_H /* Options */ diff --git a/include/freerdp/channels/rdpdr.h b/include/freerdp/channels/rdpdr.h index 88b1bbe79..9a3077a30 100644 --- a/include/freerdp/channels/rdpdr.h +++ b/include/freerdp/channels/rdpdr.h @@ -21,6 +21,7 @@ #ifndef FREERDP_CHANNEL_RDPDR_H #define FREERDP_CHANNEL_RDPDR_H +#include #include #include #include @@ -113,43 +114,14 @@ enum FILE_CREATE_DISPOSITION }; /* DR_CREATE_REQ.CreateOptions [MS-SMB2] */ -enum FILE_CREATE_OPTION -{ - FILE_DIRECTORY_FILE = 0x00000001, - FILE_NON_DIRECTORY_FILE = 0x00000040, - FILE_COMPLETE_IF_OPLOCKED = 0x00000100, - FILE_DELETE_ON_CLOSE = 0x00001000, - FILE_OPEN_REPARSE_POINT = 0x00200000, - FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000 -}; /* DR_CREATE_REQ.DesiredAccess [MS-SMB2] */ -#ifndef _WIN32 - -#if 0 -#define FILE_READ_DATA 0x00000001 -#define FILE_WRITE_DATA 0x00000002 -#define FILE_APPEND_DATA 0x00000004 -#define FILE_READ_EA 0x00000008 -#define FILE_WRITE_EA 0x00000010 -#define FILE_EXECUTE 0x00000020 -#define FILE_READ_ATTRIBUTES 0x00000080 -#define FILE_WRITE_ATTRIBUTES 0x00000100 -#endif - -#include - -#endif - /* DR_CREATE_RSP.Information */ /* DR_DRIVE_CREATE_RSP.DeviceCreateResponse */ -enum FILE_RESPONSE -{ - FILE_SUPERSEDED = 0x00000000, - FILE_OPENED = 0x00000001, - FILE_OVERWRITTEN = 0x00000003 -}; + +#define FILE_OPENED 0x00000001 +#define FILE_OVERWRITTEN 0x00000003 /* DR_CORE_CLIENT_ANNOUNCE_RSP.VersionMinor */ enum RDPDR_MINOR_RDP_VERSION @@ -211,73 +183,6 @@ enum RDP_LOWIO_OP RDP_LOWIO_OP_UNLOCK_MULTIPLE = 0x00000005 }; -/* NTSTATUS values */ -/* http://msdn.microsoft.com/en-us/library/cc704588.aspx */ -enum NTSTATUS -{ - STATUS_SUCCESS = 0x00000000, -#ifndef _WIN32 - STATUS_TIMEOUT = 0x00000102, - STATUS_PENDING = 0x00000103, -#endif - STATUS_REPARSE = 0x00000104, - STATUS_MORE_ENTRIES = 0x00000105, - STATUS_NOT_ALL_ASSIGNED = 0x00000106, - STATUS_OPLOCK_BREAK_IN_PROGRESS = 0x00000108, - STATUS_VOLUME_MOUNTED = 0x00000109, - STATUS_NOTIFY_CLEANUP = 0x0000010B, - STATUS_NOTIFY_ENUM_DIR = 0x0000010C, - STATUS_NO_QUOTAS_FOR_ACCOUNT = 0x0000010D, - STATUS_FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A, - STATUS_FILE_LOCKED_WITH_WRITERS = 0x0000012B, - STATUS_WAIT_FOR_OPLOCK = 0x00000367, - STATUS_OBJECT_NAME_EXISTS = 0x40000000, - STATUS_BAD_CURRENT_DIRECTORY = 0x40000007, - STATUS_NO_MORE_FILES = 0x80000006, - STATUS_DEVICE_PAPER_EMPTY = 0x8000000E, - STATUS_DEVICE_POWERED_OFF = 0x8000000F, - STATUS_DEVICE_OFF_LINE = 0x80000010, - STATUS_DEVICE_BUSY = 0x80000011, - STATUS_NO_MORE_ENTRIES = 0x8000001A, - STATUS_UNSUCCESSFUL = 0xC0000001, - STATUS_NOT_IMPLEMENTED = 0xC0000002, - STATUS_INVALID_INFO_CLASS = 0xC0000003, -#ifndef _WIN32 - STATUS_INVALID_HANDLE = 0xC0000008, - STATUS_INVALID_PARAMETER = 0xC000000D, -#endif - STATUS_NO_SUCH_DEVICE = 0xC000000E, - STATUS_NO_SUCH_FILE = 0xC000000F, - STATUS_INVALID_DEVICE_REQUEST = 0xC0000010, - STATUS_END_OF_FILE = 0xC0000011, - STATUS_NO_MEDIA_IN_DEVICE = 0xC0000013, - STATUS_UNRECOGNIZED_MEDIA = 0xC0000014, - STATUS_ACCESS_DENIED = 0xc0000022, - STATUS_OBJECT_NAME_INVALID = 0xC0000033, - STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034, - STATUS_OBJECT_NAME_COLLISION = 0xc0000035, - STATUS_PORT_DISCONNECTED = 0xC0000037, - STATUS_OBJECT_PATH_INVALID = 0xC0000039, - STATUS_OBJECT_PATH_NOT_FOUND = 0xC000003A, - STATUS_INVALID_PORT_HANDLE = 0xC0000042, - STATUS_DELETE_PENDING = 0xC0000056, - STATUS_DISK_FULL = 0xC000007F, - STATUS_DEVICE_NOT_READY = 0xC00000A3, - STATUS_IO_TIMEOUT = 0xC00000B5, - STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA, - STATUS_NOT_SUPPORTED = 0xC00000BB, - STATUS_PRINT_QUEUE_FULL = 0xC00000C6, - STATUS_PRINT_CANCELLED = 0xC00000C8, - STATUS_DIRECTORY_NOT_EMPTY = 0xC0000101, - STATUS_FILE_CORRUPT_ERROR = 0xC0000102, - STATUS_NOT_A_DIRECTORY = 0xC0000103, - STATUS_NAME_TOO_LONG = 0xC0000106, - STATUS_CANCELLED = 0xC0000120, - STATUS_CANNOT_DELETE = 0xC0000121, - STATUS_FILE_DELETED = 0xC0000123, - STATUS_FILE_CLOSED = 0xC0000128 -}; - enum RDPDR_PRINTER_ANNOUNCE_FLAG { RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII = 0x00000001, diff --git a/include/freerdp/channels/wtsvc.h b/include/freerdp/channels/wtsvc.h index 227c75fa4..3a01c525b 100644 --- a/include/freerdp/channels/wtsvc.h +++ b/include/freerdp/channels/wtsvc.h @@ -35,17 +35,27 @@ #include #include -typedef struct WTSVirtualChannelManager WTSVirtualChannelManager; - -#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001 +#include +#include +//#include typedef enum _WTS_VIRTUAL_CLASS { WTSVirtualClientData, WTSVirtualFileHandle, - WTSVirtualChannelReady + WTSVirtualEventHandle, /* Extended */ + WTSVirtualChannelReady /* Extended */ } WTS_VIRTUAL_CLASS; +#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW 0x00000000 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED 0x00000002 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH 0x00000004 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL 0x00000006 +#define WTS_CHANNEL_OPTION_DYNAMIC_NO_COMPRESS 0x00000008 + +typedef struct WTSVirtualChannelManager WTSVirtualChannelManager; + #ifdef __cplusplus extern "C" { #endif @@ -55,9 +65,10 @@ extern "C" { */ FREERDP_API WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client); FREERDP_API void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm); -FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, - void** fds, int* fds_count); + +FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count); FREERDP_API BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm); +FREERDP_API HANDLE WTSVirtualChannelManagerGetEventHandle(WTSVirtualChannelManager* vcm); /** * Opens a static or dynamic virtual channel and return the handle. If the @@ -69,10 +80,10 @@ FREERDP_API BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelMa * Static virtual channels must be opened from the main thread. Dynamic virtual channels * can be opened from any thread. */ -FREERDP_API void* WTSVirtualChannelOpenEx( - /* __in */ WTSVirtualChannelManager* vcm, - /* __in */ const char* pVirtualName, - /* __in */ UINT32 flags); + +// WINPR_API HANDLE WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags); + +WINPR_API HANDLE WTSVirtualChannelManagerOpenEx(WTSVirtualChannelManager* vcm, LPSTR pVirtualName, DWORD flags); /** * Returns information about a specified virtual channel. @@ -80,17 +91,14 @@ FREERDP_API void* WTSVirtualChannelOpenEx( * Servers use this function to gain access to a virtual channel file handle * that can be used for asynchronous I/O. */ -FREERDP_API BOOL WTSVirtualChannelQuery( - /* __in */ void* hChannelHandle, - /* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass, - /* __out */ void** ppBuffer, - /* __out */ UINT32* pBytesReturned); + +WINPR_API BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned); /** * Frees memory allocated by WTSVirtualChannelQuery */ -FREERDP_API void WTSFreeMemory( - /* __in */ void* pMemory); + +WINPR_API VOID WTSFreeMemory(PVOID pMemory); /** * Reads data from the server end of a virtual channel. @@ -109,27 +117,20 @@ FREERDP_API void WTSFreeMemory( * The caller should use the file handle returned by WTSVirtualChannelQuery to * determine whether a packet has arrived. */ -FREERDP_API BOOL WTSVirtualChannelRead( - /* __in */ void* hChannelHandle, - /* __in */ UINT32 TimeOut, - /* __out */ BYTE* Buffer, - /* __in */ UINT32 BufferSize, - /* __out */ UINT32* pBytesRead); + +WINPR_API BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead); /** * Writes data to the server end of a virtual channel. */ -FREERDP_API BOOL WTSVirtualChannelWrite( - /* __in */ void* hChannelHandle, - /* __in */ BYTE* Buffer, - /* __in */ UINT32 Length, - /* __out */ UINT32* pBytesWritten); + +WINPR_API BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten); /** * Closes an open virtual channel handle. */ -FREERDP_API BOOL WTSVirtualChannelClose( - /* __in */ void* hChannelHandle); + +WINPR_API BOOL WTSVirtualChannelClose(HANDLE hChannelHandle); #ifdef __cplusplus } diff --git a/include/freerdp/client/cliprdr.h b/include/freerdp/client/cliprdr.h index ea0d1cf7a..6cf137eab 100644 --- a/include/freerdp/client/cliprdr.h +++ b/include/freerdp/client/cliprdr.h @@ -20,6 +20,8 @@ #ifndef FREERDP_CHANNEL_CLIENT_CLIPRDR_H #define FREERDP_CHANNEL_CLIENT_CLIPRDR_H +#include + /** * Client Interface */ @@ -52,6 +54,48 @@ struct _cliprdr_client_context #define CB_FORMAT_JPEG 0xD012 #define CB_FORMAT_GIF 0xD013 +/* CLIPRDR_HEADER.msgType */ +#define CB_MONITOR_READY 0x0001 +#define CB_FORMAT_LIST 0x0002 +#define CB_FORMAT_LIST_RESPONSE 0x0003 +#define CB_FORMAT_DATA_REQUEST 0x0004 +#define CB_FORMAT_DATA_RESPONSE 0x0005 +#define CB_TEMP_DIRECTORY 0x0006 +#define CB_CLIP_CAPS 0x0007 +#define CB_FILECONTENTS_REQUEST 0x0008 +#define CB_FILECONTENTS_RESPONSE 0x0009 +#define CB_LOCK_CLIPDATA 0x000A +#define CB_UNLOCK_CLIPDATA 0x000B + +/* CLIPRDR_HEADER.msgFlags */ +#define CB_RESPONSE_OK 0x0001 +#define CB_RESPONSE_FAIL 0x0002 +#define CB_ASCII_NAMES 0x0004 + +/* CLIPRDR_CAPS_SET.capabilitySetType */ +#define CB_CAPSTYPE_GENERAL 0x0001 + +/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */ +#define CB_CAPSTYPE_GENERAL_LEN 12 + +/* CLIPRDR_GENERAL_CAPABILITY.version */ +#define CB_CAPS_VERSION_1 0x00000001 +#define CB_CAPS_VERSION_2 0x00000002 + +/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */ +#define CB_USE_LONG_FORMAT_NAMES 0x00000002 +#define CB_STREAM_FILECLIP_ENABLED 0x00000004 +#define CB_FILECLIP_NO_FILE_PATHS 0x00000008 +#define CB_CAN_LOCK_CLIPDATA 0x00000010 + +struct _CLIPRDR_FORMAT_NAME +{ + UINT32 id; + char* name; + int length; +}; +typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME; + /** * Clipboard Events */ diff --git a/include/freerdp/codec/nsc.h b/include/freerdp/codec/nsc.h index 9601fb8c2..a5832352e 100644 --- a/include/freerdp/codec/nsc.h +++ b/include/freerdp/codec/nsc.h @@ -50,6 +50,7 @@ struct _NSC_MESSAGE UINT32 height; BYTE* data; int scanline; + BYTE* PlaneBuffer; UINT32 MaxPlaneSize; BYTE* PlaneBuffers[5]; UINT32 OrgByteCount[4]; diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 57f4fed44..60ada8b79 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -56,7 +56,6 @@ struct _RFX_TILE BYTE* data; int scanline; BOOL allocated; - BYTE quantIdxY; BYTE quantIdxCb; BYTE quantIdxCr; @@ -68,6 +67,7 @@ struct _RFX_TILE BYTE* YData; BYTE* CbData; BYTE* CrData; + BYTE* YCbCrData; }; typedef struct _RFX_TILE RFX_TILE; @@ -118,6 +118,7 @@ struct _RFX_CONTEXT { RFX_STATE state; + BOOL encoder; UINT16 flags; UINT16 properties; UINT16 width; @@ -153,7 +154,7 @@ struct _RFX_CONTEXT }; typedef struct _RFX_CONTEXT RFX_CONTEXT; -FREERDP_API RFX_CONTEXT* rfx_context_new(void); +FREERDP_API RFX_CONTEXT* rfx_context_new(BOOL encoder); FREERDP_API void rfx_context_free(RFX_CONTEXT* context); FREERDP_API void rfx_context_set_pixel_format(RFX_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format); FREERDP_API void rfx_context_reset(RFX_CONTEXT* context); diff --git a/include/freerdp/server/cliprdr.h b/include/freerdp/server/cliprdr.h new file mode 100644 index 000000000..946eb7652 --- /dev/null +++ b/include/freerdp/server/cliprdr.h @@ -0,0 +1,51 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Clipboard Virtual Channel Server Interface + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_SERVER_CLIPRDR_H +#define FREERDP_CHANNEL_SERVER_CLIPRDR_H + +#include +#include +#include +#include + +/** + * Server Interface + */ + +typedef struct _cliprdr_server_context CliprdrServerContext; +typedef struct _cliprdr_server_private CliprdrServerPrivate; + +typedef int (*psCliprdrStart)(CliprdrServerContext* context); +typedef int (*psCliprdrStop)(CliprdrServerContext* context); + +struct _cliprdr_server_context +{ + WTSVirtualChannelManager* vcm; + + psCliprdrStart Start; + psCliprdrStop Stop; + + CliprdrServerPrivate* priv; +}; + +FREERDP_API CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm); +FREERDP_API void cliprdr_server_context_free(CliprdrServerContext* context); + +#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_H */ diff --git a/include/freerdp/server/drdynvc.h b/include/freerdp/server/drdynvc.h new file mode 100644 index 000000000..31eb4ece6 --- /dev/null +++ b/include/freerdp/server/drdynvc.h @@ -0,0 +1,50 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Dynamic Virtual Channel Extension + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_SERVER_DRDYNVC_H +#define FREERDP_CHANNEL_SERVER_DRDYNVC_H + +#include +#include +#include + +/** + * Server Interface + */ + +typedef struct _drdynvc_client_context DrdynvcServerContext; +typedef struct _drdynvc_server_private DrdynvcServerPrivate; + +typedef int (*psDrdynvcStart)(DrdynvcServerContext* context); +typedef int (*psDrdynvcStop)(DrdynvcServerContext* context); + +struct _drdynvc_client_context +{ + WTSVirtualChannelManager* vcm; + + psDrdynvcStart Start; + psDrdynvcStop Stop; + + DrdynvcServerPrivate* priv; +}; + +FREERDP_API DrdynvcServerContext* drdynvc_server_context_new(WTSVirtualChannelManager* vcm); +FREERDP_API void drdynvc_server_context_free(DrdynvcServerContext* context); + +#endif /* FREERDP_CHANNEL_SERVER_DRDYNVC_H */ diff --git a/include/freerdp/server/rdpdr.h b/include/freerdp/server/rdpdr.h new file mode 100644 index 000000000..d24be3fcd --- /dev/null +++ b/include/freerdp/server/rdpdr.h @@ -0,0 +1,51 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Device Redirection Virtual Channel Server Interface + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_SERVER_RDPDR_H +#define FREERDP_CHANNEL_SERVER_RDPDR_H + +#include +#include +#include +#include + +/** + * Server Interface + */ + +typedef struct _rdpdr_server_context RdpdrServerContext; +typedef struct _rdpdr_server_private RdpdrServerPrivate; + +typedef int (*psRdpdrStart)(RdpdrServerContext* context); +typedef int (*psRdpdrStop)(RdpdrServerContext* context); + +struct _rdpdr_server_context +{ + WTSVirtualChannelManager* vcm; + + psRdpdrStart Start; + psRdpdrStop Stop; + + RdpdrServerPrivate* priv; +}; + +FREERDP_API RdpdrServerContext* rdpdr_server_context_new(WTSVirtualChannelManager* vcm); +FREERDP_API void rdpdr_server_context_free(RdpdrServerContext* context); + +#endif /* FREERDP_CHANNEL_SERVER_RDPDR_H */ diff --git a/include/freerdp/server/rdpsnd.h b/include/freerdp/server/rdpsnd.h index 8b0c163c2..5b65cd8ff 100644 --- a/include/freerdp/server/rdpsnd.h +++ b/include/freerdp/server/rdpsnd.h @@ -23,20 +23,30 @@ #include #include +typedef struct _rdpsnd_server_context RdpsndServerContext; typedef struct _rdpsnd_server_context rdpsnd_server_context; +typedef struct _rdpsnd_server_private RdpsndServerPrivate; -typedef BOOL (*psRdpsndServerInitialize)(rdpsnd_server_context* context); -typedef void (*psRdpsndServerSelectFormat)(rdpsnd_server_context* context, int client_format_index); -typedef BOOL (*psRdpsndServerSendSamples)(rdpsnd_server_context* context, const void* buf, int nframes); -typedef BOOL (*psRdpsndServerSetVolume)(rdpsnd_server_context* context, int left, int right); -typedef BOOL (*psRdpsndServerClose)(rdpsnd_server_context* context); +typedef int (*psRdpsndStart)(RdpsndServerContext* context); +typedef int (*psRdpsndStop)(RdpsndServerContext* context); -typedef void (*psRdpsndServerActivated)(rdpsnd_server_context* context); +typedef BOOL (*psRdpsndServerInitialize)(RdpsndServerContext* context); +typedef void (*psRdpsndServerSelectFormat)(RdpsndServerContext* context, int client_format_index); +typedef BOOL (*psRdpsndServerSendSamples)(RdpsndServerContext* context, const void* buf, int nframes); +typedef BOOL (*psRdpsndServerSetVolume)(RdpsndServerContext* context, int left, int right); +typedef BOOL (*psRdpsndServerClose)(RdpsndServerContext* context); + +typedef void (*psRdpsndServerActivated)(RdpsndServerContext* context); struct _rdpsnd_server_context { WTSVirtualChannelManager* vcm; + psRdpsndStart Start; + psRdpsndStop Stop; + + RdpsndServerPrivate* priv; + /* Server self-defined pointer. */ void* data; @@ -95,8 +105,8 @@ struct _rdpsnd_server_context extern "C" { #endif -FREERDP_API rdpsnd_server_context* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm); -FREERDP_API void rdpsnd_server_context_free(rdpsnd_server_context* context); +FREERDP_API RdpsndServerContext* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm); +FREERDP_API void rdpsnd_server_context_free(RdpsndServerContext* context); #ifdef __cplusplus } diff --git a/libfreerdp/CMakeLists.txt b/libfreerdp/CMakeLists.txt index bbc714b15..3a167bcf5 100644 --- a/libfreerdp/CMakeLists.txt +++ b/libfreerdp/CMakeLists.txt @@ -59,11 +59,7 @@ if(MONOLITHIC_BUILD) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) - if(NOT WITH_WAYK) - install(TARGETS ${MODULE_NAME} - DESTINATION ${CMAKE_INSTALL_LIBDIR} - COMPONENT libraries) - endif() + install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp") endif() diff --git a/libfreerdp/codec/nsc_encode.c b/libfreerdp/codec/nsc_encode.c index 627d032f4..9f0dc4c04 100644 --- a/libfreerdp/codec/nsc_encode.c +++ b/libfreerdp/codec/nsc_encode.c @@ -390,6 +390,7 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y, UINT32 MaxPlaneSize; UINT32 MaxMessageSize; NSC_MESSAGE* messages; + UINT32 PaddedMaxPlaneSize; k = 0; MaxRegionWidth = 64 * 4; @@ -430,11 +431,15 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y, for (i = 0; i < *numMessages; i++) { - messages[i].PlaneBuffers[0] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize); - messages[i].PlaneBuffers[1] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize); - messages[i].PlaneBuffers[2] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize); - messages[i].PlaneBuffers[3] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize); - messages[i].PlaneBuffers[4] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize); + PaddedMaxPlaneSize = messages[i].MaxPlaneSize + 32; + + messages[i].PlaneBuffer = (BYTE*) BufferPool_Take(context->priv->PlanePool, PaddedMaxPlaneSize * 5); + + messages[i].PlaneBuffers[0] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 0) + 16]); + messages[i].PlaneBuffers[1] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 1) + 16]); + messages[i].PlaneBuffers[2] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 2) + 16]); + messages[i].PlaneBuffers[3] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 3) + 16]); + messages[i].PlaneBuffers[4] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 4) + 16]); } for (i = 0; i < *numMessages; i++) @@ -504,11 +509,7 @@ int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message) int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message) { - BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[0]); - BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[1]); - BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[2]); - BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[3]); - BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[4]); + BufferPool_Return(context->priv->PlanePool, message->PlaneBuffer); return 0; } diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index decf2f07d..3c1545f98 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -154,7 +154,7 @@ void rfx_tile_init(RFX_TILE* tile) } } -RFX_TILE* rfx_tile_new() +RFX_TILE* rfx_decoder_tile_new() { RFX_TILE* tile = NULL; @@ -171,7 +171,7 @@ RFX_TILE* rfx_tile_new() return tile; } -void rfx_tile_free(RFX_TILE* tile) +void rfx_decoder_tile_free(RFX_TILE* tile) { if (tile) { @@ -181,7 +181,29 @@ void rfx_tile_free(RFX_TILE* tile) } } -RFX_CONTEXT* rfx_context_new(void) +RFX_TILE* rfx_encoder_tile_new() +{ + RFX_TILE* tile = NULL; + + tile = (RFX_TILE*) malloc(sizeof(RFX_TILE)); + + if (tile) + { + ZeroMemory(tile, sizeof(RFX_TILE)); + } + + return tile; +} + +void rfx_encoder_tile_free(RFX_TILE* tile) +{ + if (tile) + { + free(tile); + } +} + +RFX_CONTEXT* rfx_context_new(BOOL encoder) { HKEY hKey; LONG status; @@ -194,13 +216,24 @@ RFX_CONTEXT* rfx_context_new(void) context = (RFX_CONTEXT*) malloc(sizeof(RFX_CONTEXT)); ZeroMemory(context, sizeof(RFX_CONTEXT)); + context->encoder = encoder; + context->priv = (RFX_CONTEXT_PRIV*) malloc(sizeof(RFX_CONTEXT_PRIV)); ZeroMemory(context->priv, sizeof(RFX_CONTEXT_PRIV)); context->priv->TilePool = ObjectPool_New(TRUE); - ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_tile_new; ObjectPool_Object(context->priv->TilePool)->fnObjectInit = (OBJECT_INIT_FN) rfx_tile_init; - ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_tile_free; + + if (context->encoder) + { + ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_encoder_tile_new; + ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_encoder_tile_free; + } + else + { + ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_decoder_tile_new; + ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_decoder_tile_free; + } /* * align buffers to 16 byte boundary (needed for SSE/NEON instructions) @@ -212,9 +245,11 @@ RFX_CONTEXT* rfx_context_new(void) * in order to allow optimized functions (SEE, NEON) to read from positions * that are actually in front/beyond the buffer. Offset calculations are * performed at the BufferPool_Take function calls in rfx_encode/decode.c. + * + * We then multiply by 3 to use a single, partioned buffer for all 3 channels. */ - context->priv->BufferPool = BufferPool_New(TRUE, 8192 + 32, 16); + context->priv->BufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16); #ifdef _WIN32 { @@ -937,14 +972,11 @@ void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message) { tile = message->tiles[i]; - if (tile->YData) - BufferPool_Return(context->priv->BufferPool, tile->YData); - - if (tile->CbData) - BufferPool_Return(context->priv->BufferPool, tile->CbData); - - if (tile->CrData) - BufferPool_Return(context->priv->BufferPool, tile->CrData); + if (tile->YCbCrData) + { + BufferPool_Return(context->priv->BufferPool, tile->YCbCrData); + tile->YCbCrData = NULL; + } ObjectPool_Return(context->priv->TilePool, (void*) tile); } @@ -1105,7 +1137,7 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, { context->numQuant = 1; context->quants = (UINT32*) malloc(sizeof(rfx_default_quantization_values)); - memcpy(context->quants, rfx_default_quantization_values, sizeof(rfx_default_quantization_values)); + CopyMemory(context->quants, &rfx_default_quantization_values, sizeof(rfx_default_quantization_values)); context->quantIdxY = 0; context->quantIdxCb = 0; context->quantIdxCr = 0; @@ -1186,9 +1218,12 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, tile->YLen = 0; tile->CbLen = 0; tile->CrLen = 0; - tile->YData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); - tile->CbData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); - tile->CrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); + + tile->YCbCrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); + + tile->YData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 0) + 16]); + tile->CbData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 1) + 16]); + tile->CrData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 2) + 16]); if (context->priv->UseThreads) { @@ -1294,9 +1329,6 @@ RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, in RFX_MESSAGE* message; RFX_MESSAGE* messages; - printf("rfx_encode_messages: numRects: %d maxDataSize: %d x: %d y: %d w: %d/%d h: %d/%d\n", numRects, maxDataSize, - rects[0].x, rects[0].y, rects[0].width, width, rects[0].height, height); - message = rfx_encode_message(context, rects, numRects, data, width, height, scanline); messages = rfx_split_message(context, message, numMessages, maxDataSize); rfx_message_free(context, message); diff --git a/libfreerdp/codec/rfx_decode.c b/libfreerdp/codec/rfx_decode.c index 2a642f9da..d91cfc52f 100644 --- a/libfreerdp/codec/rfx_decode.c +++ b/libfreerdp/codec/rfx_decode.c @@ -128,6 +128,7 @@ static void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantizatio /* stride is bytes between rows in the output buffer. */ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int stride) { + BYTE* pBuffer; INT16* pSrcDst[3]; UINT32 *y_quants, *cb_quants, *cr_quants; static const prim_size_t roi_64x64 = { 64, 64 }; @@ -139,9 +140,10 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int cb_quants = context->quants + (tile->quantIdxCb * 10); cr_quants = context->quants + (tile->quantIdxCr * 10); - pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */ - pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */ - pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */ + pBuffer = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); + pSrcDst[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* y_r_buffer */ + pSrcDst[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* cb_g_buffer */ + pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* cr_b_buffer */ rfx_decode_component(context, y_quants, tile->YData, tile->YLen, pSrcDst[0]); /* YData */ @@ -161,9 +163,7 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int PROFILER_EXIT(context->priv->prof_rfx_decode_rgb); - BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16); - BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16); - BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16); + BufferPool_Return(context->priv->BufferPool, pBuffer); return TRUE; } diff --git a/libfreerdp/codec/rfx_encode.c b/libfreerdp/codec/rfx_encode.c index f484e58fd..ab106e291 100644 --- a/libfreerdp/codec/rfx_encode.c +++ b/libfreerdp/codec/rfx_encode.c @@ -219,6 +219,7 @@ static void rfx_encode_component(RFX_CONTEXT* context, const UINT32* quantizatio void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile) { + BYTE* pBuffer; INT16* pSrcDst[3]; int YLen, CbLen, CrLen; UINT32 *YQuant, *CbQuant, *CrQuant; @@ -230,9 +231,10 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile) CbQuant = context->quants + (tile->quantIdxCb * 10); CrQuant = context->quants + (tile->quantIdxCr * 10); - pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */ - pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */ - pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */ + pBuffer = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); + pSrcDst[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* y_r_buffer */ + pSrcDst[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* cb_g_buffer */ + pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* cr_b_buffer */ PROFILER_ENTER(context->priv->prof_rfx_encode_rgb); @@ -265,7 +267,5 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile) PROFILER_EXIT(context->priv->prof_rfx_encode_rgb); - BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16); - BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16); - BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16); + BufferPool_Return(context->priv->BufferPool, pBuffer); } diff --git a/libfreerdp/core/CMakeLists.txt b/libfreerdp/core/CMakeLists.txt index 9cf9ed8c2..b04b1f79a 100644 --- a/libfreerdp/core/CMakeLists.txt +++ b/libfreerdp/core/CMakeLists.txt @@ -136,7 +136,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE winpr - MODULES winpr-registry winpr-utils winpr-interlocked winpr-dsparse winpr-sspi winpr-rpc winpr-crt) + MODULES winpr-registry winpr-utils winpr-interlocked winpr-dsparse winpr-sspi winpr-rpc winpr-handle winpr-crt) if(MONOLITHIC_BUILD) set(FREERDP_LIBS ${FREERDP_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index e8a04af9b..0d8606bc5 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -120,6 +120,7 @@ BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings) if (Stream_GetRemainingLength(s) < 4) return FALSE; + Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily */ Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress */ @@ -149,6 +150,7 @@ BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings) if (Stream_GetRemainingLength(s) < 10) return FALSE; + Stream_Seek_UINT32(s); /* clientSessionId, should be set to 0 */ Stream_Read_UINT32(s, settings->PerformanceFlags); /* performanceFlags */ diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index 88d039eb8..04de4d81e 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -191,11 +191,15 @@ BOOL license_send(rdpLicense* license, wStream* s, BYTE type) sec_flags = SEC_LICENSE_PKT; wMsgSize = length - LICENSE_PACKET_HEADER_MAX_LENGTH + 4; + flags = PREAMBLE_VERSION_3_0; + /** * Using EXTENDED_ERROR_MSG_SUPPORTED here would cause mstsc to crash when * running in server mode! This flag seems to be incorrectly documented. */ - flags = PREAMBLE_VERSION_3_0 | EXTENDED_ERROR_MSG_SUPPORTED; + + if (!license->rdp->settings->ServerMode) + flags |= EXTENDED_ERROR_MSG_SUPPORTED; rdp_write_header(license->rdp, s, length, MCS_GLOBAL_CHANNEL_ID); rdp_write_security_header(s, sec_flags); diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 5b38c905e..64a54ff4b 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -30,6 +30,10 @@ #include "peer.h" +#ifdef WITH_DEBUG_RDP +extern const char* DATA_PDU_TYPE_STRINGS[80]; +#endif + static BOOL freerdp_peer_initialize(freerdp_peer* client) { client->context->rdp->settings->ServerMode = TRUE; @@ -85,6 +89,11 @@ static BOOL peer_recv_data_pdu(freerdp_peer* client, wStream* s) if (!rdp_read_share_data_header(s, &length, &type, &share_id, &compressed_type, &compressed_len)) return FALSE; +#ifdef WITH_DEBUG_RDP + printf("recv %s Data PDU (0x%02X), length: %d\n", + type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length); +#endif + switch (type) { case DATA_PDU_TYPE_SYNCHRONIZE: diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 4b66e6555..80089e2fb 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -31,7 +31,7 @@ #include #ifdef WITH_DEBUG_RDP -static const char* const DATA_PDU_TYPE_STRINGS[] = +const char* DATA_PDU_TYPE_STRINGS[80] = { "?", "?", /* 0x00 - 0x01 */ "Update", /* 0x02 */ @@ -65,7 +65,7 @@ static const char* const DATA_PDU_TYPE_STRINGS[] = "?", "?", "?", /* 0x33 - 0x35 */ "Status Info", /* 0x36 */ "Monitor Layout" /* 0x37 */ - "?", "?", "?", /* 0x38 - 0x40 */ + "FrameAcknowledge", "?", "?", /* 0x38 - 0x40 */ "?", "?", "?", "?", "?", "?" /* 0x41 - 0x46 */ }; #endif @@ -133,20 +133,21 @@ void rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, UINT Stream_Write_UINT16(s, channel_id); /* pduSource */ } -BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32* share_id, - BYTE *compressed_type, UINT16 *compressed_len) +BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32* shareId, + BYTE *compressedType, UINT16 *compressedLen) { if (Stream_GetRemainingLength(s) < 12) return FALSE; /* Share Data Header */ - Stream_Read_UINT32(s, *share_id); /* shareId (4 bytes) */ + Stream_Read_UINT32(s, *shareId); /* shareId (4 bytes) */ Stream_Seek_UINT8(s); /* pad1 (1 byte) */ Stream_Seek_UINT8(s); /* streamId (1 byte) */ Stream_Read_UINT16(s, *length); /* uncompressedLength (2 bytes) */ Stream_Read_UINT8(s, *type); /* pduType2, Data PDU Type (1 byte) */ - Stream_Read_UINT8(s, *compressed_type); /* compressedType (1 byte) */ - Stream_Read_UINT16(s, *compressed_len); /* compressedLength (2 bytes) */ + Stream_Read_UINT8(s, *compressedType); /* compressedType (1 byte) */ + Stream_Read_UINT16(s, *compressedLen); /* compressedLength (2 bytes) */ + return TRUE; } @@ -567,9 +568,8 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s) } #ifdef WITH_DEBUG_RDP - /* if (type != DATA_PDU_TYPE_UPDATE) */ - DEBUG_RDP("recv %s Data PDU (0x%02X), length:%d", - type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length); + printf("recv %s Data PDU (0x%02X), length: %d\n", + type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length); #endif switch (type) diff --git a/libfreerdp/dummy.c b/libfreerdp/dummy.c index b959f9be3..fb941c948 100644 --- a/libfreerdp/dummy.c +++ b/libfreerdp/dummy.c @@ -1,5 +1,5 @@ -int dummy() +int freerdp_dummy() { return 0; } diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 95443ab57..f72f6b2e0 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -917,10 +917,20 @@ void gdi_register_update_callbacks(rdpUpdate* update) void gdi_init_primary(rdpGdi* gdi) { - gdi->primary = gdi_bitmap_new_ex(gdi, gdi->width, gdi->height, gdi->dstBpp, gdi->primary_buffer); + gdi->primary = (gdiBitmap*) malloc(sizeof(gdiBitmap)); + gdi->primary->hdc = gdi_CreateCompatibleDC(gdi->hdc); + + if (!gdi->primary_buffer) + gdi->primary->bitmap = gdi_CreateCompatibleBitmap(gdi->hdc, gdi->width, gdi->height); + else + gdi->primary->bitmap = gdi_CreateBitmap(gdi->width, gdi->height, gdi->dstBpp, gdi->primary_buffer); + + gdi_SelectObject(gdi->primary->hdc, (HGDIOBJECT) gdi->primary->bitmap); + gdi->primary->org_bitmap = NULL; + gdi->primary_buffer = gdi->primary->bitmap->data; - if (gdi->drawing == NULL) + if (!gdi->drawing) gdi->drawing = gdi->primary; gdi->primary->hdc->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND)); @@ -1042,7 +1052,7 @@ int gdi_init(freerdp* instance, UINT32 flags, BYTE* buffer) gdi_register_graphics(instance->context->graphics); - gdi->rfx_context = rfx_context_new(); + gdi->rfx_context = rfx_context_new(FALSE); gdi->nsc_context = nsc_context_new(); return 0; diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index 4cb3d6d7a..cb0f5fb57 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -134,6 +134,7 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3 } plugin->data_in = NULL; + Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) data_in, NULL); diff --git a/server/.gitignore b/server/.gitignore index e8786806f..b5581fbbc 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -1,3 +1,7 @@ -WaykServer -xrdp-ng - +/* +!/common +!/Mac +!/Sample +!/Windows +!/X11 +!/CmakeLists.txt diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index fed64d78c..a7c3ec233 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -35,13 +35,28 @@ else() add_subdirectory(Windows) endif() -if(WITH_WAYK) - if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/WaykServer") - add_subdirectory(WaykServer) - endif() -endif() - if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/xrdp-ng") add_subdirectory("xrdp-ng") endif() +# Pick up other clients + +set(FILENAME "ModuleOptions.cmake") +file(GLOB FILEPATHS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/${FILENAME}") + +foreach(FILEPATH ${FILEPATHS}) + if(${FILEPATH} MATCHES "^([^/]*)//${FILENAME}") + string(REGEX REPLACE "^([^/]*)//${FILENAME}" "\\1" FREERDP_SERVER ${FILEPATH}) + set(FREERDP_SERVER_ENABLED 0) + include(${FILEPATH}) + if(FREERDP_SERVER_ENABLED) + if(NOT (${FREERDP_SERVER_VENDOR} MATCHES "FreeRDP")) + list(APPEND FREERDP_EXTRA_SERVERS ${FREERDP_SERVER}) + endif() + endif() + endif() +endforeach() + +foreach(FREERDP_SERVER ${FREERDP_EXTRA_SERVERS}) + add_subdirectory(${FREERDP_SERVER}) +endforeach() diff --git a/server/Mac/ModuleOptions.cmake b/server/Mac/ModuleOptions.cmake new file mode 100644 index 000000000..bfd36cbbf --- /dev/null +++ b/server/Mac/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_SERVER_NAME "mfreerdp-server") +set(FREERDP_SERVER_PLATFORM "X11") +set(FREERDP_SERVER_VENDOR "FreeRDP") diff --git a/server/Mac/mf_interface.h b/server/Mac/mf_interface.h index cf383ad89..a59951f4f 100644 --- a/server/Mac/mf_interface.h +++ b/server/Mac/mf_interface.h @@ -66,7 +66,7 @@ struct mf_peer_context //#endif //#ifdef CHANNEL_RDPSND_SERVER - rdpsnd_server_context* rdpsnd; + RdpsndServerContext* rdpsnd; //#endif }; diff --git a/server/Mac/mf_peer.c b/server/Mac/mf_peer.c index 074ece076..0d059cf49 100644 --- a/server/Mac/mf_peer.c +++ b/server/Mac/mf_peer.c @@ -175,7 +175,7 @@ void mf_peer_rfx_update(freerdp_peer* client) int mf_peer_context_new(freerdp_peer* client, mfPeerContext* context) { context->info = mf_info_get_instance(); - context->rfx_context = rfx_context_new(); + context->rfx_context = rfx_context_new(TRUE); context->rfx_context->mode = RLGR3; context->rfx_context->width = client->settings->DesktopWidth; context->rfx_context->height = client->settings->DesktopHeight; diff --git a/server/Mac/mf_rdpsnd.c b/server/Mac/mf_rdpsnd.c index 2e273ded3..0f66f7e3c 100644 --- a/server/Mac/mf_rdpsnd.c +++ b/server/Mac/mf_rdpsnd.c @@ -34,7 +34,7 @@ static const AUDIO_FORMAT supported_audio_formats[] = { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, NULL } }; -static void mf_peer_rdpsnd_activated(rdpsnd_server_context* context) +static void mf_peer_rdpsnd_activated(RdpsndServerContext* context) { OSStatus status; int i, j; diff --git a/server/Mac/mf_rdpsnd.h b/server/Mac/mf_rdpsnd.h index e635be7d7..2c3c6de2d 100644 --- a/server/Mac/mf_rdpsnd.h +++ b/server/Mac/mf_rdpsnd.h @@ -53,7 +53,7 @@ struct _AQRecorderState UInt32 bufferByteSize; SInt64 currentPacket; bool isRunning; - rdpsnd_server_context* snd_context; + RdpsndServerContext* snd_context; }; diff --git a/server/Sample/ModuleOptions.cmake b/server/Sample/ModuleOptions.cmake new file mode 100644 index 000000000..5621f6d78 --- /dev/null +++ b/server/Sample/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_SERVER_NAME "sfreerdp-server") +set(FREERDP_SERVER_PLATFORM "Sample") +set(FREERDP_SERVER_VENDOR "FreeRDP") diff --git a/server/Sample/sf_rdpsnd.c b/server/Sample/sf_rdpsnd.c index 568db3bb5..9a1b70bcb 100644 --- a/server/Sample/sf_rdpsnd.c +++ b/server/Sample/sf_rdpsnd.c @@ -31,7 +31,7 @@ static const AUDIO_FORMAT test_audio_formats[] = { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL } }; -static void sf_peer_rdpsnd_activated(rdpsnd_server_context* context) +static void sf_peer_rdpsnd_activated(RdpsndServerContext* context) { printf("RDPSND Activated\n"); } diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c index b38fe468d..c98d4e05e 100644 --- a/server/Sample/sfreerdp.c +++ b/server/Sample/sfreerdp.c @@ -49,7 +49,7 @@ static BOOL test_dump_rfx_realtime = TRUE; void test_peer_context_new(freerdp_peer* client, testPeerContext* context) { - context->rfx_context = rfx_context_new(); + context->rfx_context = rfx_context_new(TRUE); context->rfx_context->mode = RLGR3; context->rfx_context->width = SAMPLE_SERVER_DEFAULT_WIDTH; context->rfx_context->height = SAMPLE_SERVER_DEFAULT_HEIGHT; @@ -398,10 +398,10 @@ static void* tf_debug_channel_thread_func(void* arg) void* fd; wStream* s; void* buffer; - UINT32 bytes_returned = 0; + DWORD BytesReturned = 0; testPeerContext* context = (testPeerContext*) arg; - if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE) + if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &BytesReturned) == TRUE) { fd = *((void**) buffer); WTSFreeMemory(buffer); @@ -411,7 +411,7 @@ static void* tf_debug_channel_thread_func(void* arg) s = Stream_New(NULL, 4096); - WTSVirtualChannelWrite(context->debug_channel, (BYTE*) "test1", 5, NULL); + WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test1", 5, NULL); while (1) { @@ -422,25 +422,25 @@ static void* tf_debug_channel_thread_func(void* arg) Stream_SetPosition(s, 0); - if (WTSVirtualChannelRead(context->debug_channel, 0, Stream_Buffer(s), - Stream_Capacity(s), &bytes_returned) == FALSE) + if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR) Stream_Buffer(s), + Stream_Capacity(s), &BytesReturned) == FALSE) { - if (bytes_returned == 0) + if (BytesReturned == 0) break; - Stream_EnsureRemainingCapacity(s, bytes_returned); + Stream_EnsureRemainingCapacity(s, BytesReturned); - if (WTSVirtualChannelRead(context->debug_channel, 0, Stream_Buffer(s), - Stream_Capacity(s), &bytes_returned) == FALSE) + if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR) Stream_Buffer(s), + Stream_Capacity(s), &BytesReturned) == FALSE) { /* should not happen */ break; } } - Stream_SetPosition(s, bytes_returned); + Stream_SetPosition(s, BytesReturned); - printf("got %d bytes\n", bytes_returned); + printf("got %d bytes\n", BytesReturned); } Stream_Free(s, TRUE); @@ -498,7 +498,7 @@ BOOL tf_peer_post_connect(freerdp_peer* client) { if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpdbg", 6) == 0) { - context->debug_channel = WTSVirtualChannelOpenEx(context->vcm, "rdpdbg", 0); + context->debug_channel = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdbg", 0); if (context->debug_channel != NULL) { @@ -580,7 +580,7 @@ void tf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { if (context->debug_channel) { - WTSVirtualChannelWrite(context->debug_channel, (BYTE*) "test2", 5, NULL); + WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test2", 5, NULL); } } else if ((flags & 0x4000) && code == 0x2D) /* 'x' key */ diff --git a/server/Sample/sfreerdp.h b/server/Sample/sfreerdp.h index b5a05a4cb..b54af158d 100644 --- a/server/Sample/sfreerdp.h +++ b/server/Sample/sfreerdp.h @@ -54,7 +54,7 @@ struct test_peer_context audin_server_context* audin; BOOL audin_open; UINT32 frame_id; - rdpsnd_server_context* rdpsnd; + RdpsndServerContext* rdpsnd; }; typedef struct test_peer_context testPeerContext; diff --git a/server/Windows/ModuleOptions.cmake b/server/Windows/ModuleOptions.cmake new file mode 100644 index 000000000..69d759661 --- /dev/null +++ b/server/Windows/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_SERVER_NAME "wfreerdp-server") +set(FREERDP_SERVER_PLATFORM "Windows") +set(FREERDP_SERVER_VENDOR "FreeRDP") diff --git a/server/Windows/wf_directsound.c b/server/Windows/wf_directsound.c index cc0518073..f0ee7cb82 100644 --- a/server/Windows/wf_directsound.c +++ b/server/Windows/wf_directsound.c @@ -26,7 +26,7 @@ int wf_rdpsnd_set_latest_peer(wfPeerContext* peer) return 0; } -int wf_directsound_activate(rdpsnd_server_context* context) +int wf_directsound_activate(RdpsndServerContext* context) { HRESULT hr; wfInfo* wfi; diff --git a/server/Windows/wf_directsound.h b/server/Windows/wf_directsound.h index f88e7dfb0..9e51b27d2 100644 --- a/server/Windows/wf_directsound.h +++ b/server/Windows/wf_directsound.h @@ -6,7 +6,7 @@ int wf_rdpsnd_set_latest_peer(wfPeerContext* peer); -int wf_directsound_activate(rdpsnd_server_context* context); +int wf_directsound_activate(RdpsndServerContext* context); DWORD WINAPI wf_rdpsnd_directsound_thread(LPVOID lpParam); diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index 6352c5e2d..4108448b9 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -100,7 +100,7 @@ struct wf_peer_context HANDLE socketSemaphore; WTSVirtualChannelManager* vcm; - rdpsnd_server_context* rdpsnd; + RdpsndServerContext* rdpsnd; }; struct wf_server diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index 6b6847b7d..0a4362d43 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -46,7 +46,7 @@ static const AUDIO_FORMAT supported_audio_formats[] = { WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL } }; -static void wf_peer_rdpsnd_activated(rdpsnd_server_context* context) +static void wf_peer_rdpsnd_activated(RdpsndServerContext* context) { wfInfo* wfi; int i, j; diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c index e6daf5c57..0332316be 100644 --- a/server/Windows/wf_update.c +++ b/server/Windows/wf_update.c @@ -198,7 +198,7 @@ void wf_update_encoder_reset(wfInfo* wfi) } else { - wfi->rfx_context = rfx_context_new(); + wfi->rfx_context = rfx_context_new(TRUE); wfi->rfx_context->mode = RLGR3; wfi->rfx_context->width = wfi->servscreen_width; wfi->rfx_context->height = wfi->servscreen_height; diff --git a/server/Windows/wf_wasapi.c b/server/Windows/wf_wasapi.c index c24d495ea..7530ca76e 100644 --- a/server/Windows/wf_wasapi.c +++ b/server/Windows/wf_wasapi.c @@ -34,7 +34,7 @@ int wf_rdpsnd_set_latest_peer(wfPeerContext* peer) } -int wf_wasapi_activate(rdpsnd_server_context* context) +int wf_wasapi_activate(RdpsndServerContext* context) { wchar_t * pattern = L"Stereo Mix"; diff --git a/server/Windows/wf_wasapi.h b/server/Windows/wf_wasapi.h index 78cd0cbf6..7461f2a0d 100644 --- a/server/Windows/wf_wasapi.h +++ b/server/Windows/wf_wasapi.h @@ -6,7 +6,7 @@ int wf_rdpsnd_set_latest_peer(wfPeerContext* peer); -int wf_wasapi_activate(rdpsnd_server_context* context); +int wf_wasapi_activate(RdpsndServerContext* context); int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr); diff --git a/server/X11/ModuleOptions.cmake b/server/X11/ModuleOptions.cmake new file mode 100644 index 000000000..fcba05934 --- /dev/null +++ b/server/X11/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_SERVER_NAME "xfreerdp-server") +set(FREERDP_SERVER_PLATFORM "X11") +set(FREERDP_SERVER_VENDOR "FreeRDP") diff --git a/server/X11/xf_peer.c b/server/X11/xf_peer.c index de6397398..056253b01 100644 --- a/server/X11/xf_peer.c +++ b/server/X11/xf_peer.c @@ -307,7 +307,7 @@ xfInfo* xf_info_init() void xf_peer_context_new(freerdp_peer* client, xfPeerContext* context) { context->info = xf_info_init(); - context->rfx_context = rfx_context_new(); + context->rfx_context = rfx_context_new(TRUE); context->rfx_context->mode = RLGR3; context->rfx_context->width = context->info->width; context->rfx_context->height = context->info->height; diff --git a/server/common/CMakeLists.txt b/server/common/CMakeLists.txt index f33fb1b15..d0fc89f59 100644 --- a/server/common/CMakeLists.txt +++ b/server/common/CMakeLists.txt @@ -38,7 +38,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${FREERDP_CHANNELS_SERVER_LIBS}) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) -set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "") install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index 81904788c..b4aaf45d2 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -72,9 +72,7 @@ endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/winpr/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/winpr/config.h) -if(NOT WITH_WAYK) - add_subdirectory(include) -endif() +add_subdirectory(include) add_subdirectory(libwinpr) diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index f06d30458..7934034ce 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -321,11 +321,15 @@ typedef struct _wBufferPoolItem wBufferPoolItem; struct _wBufferPool { - int defaultSize; + int fixedSize; DWORD alignment; BOOL synchronized; CRITICAL_SECTION lock; + int size; + int capacity; + void** array; + int aSize; int aCapacity; wBufferPoolItem* aArray; diff --git a/winpr/include/winpr/credui.h b/winpr/include/winpr/credui.h index 3fac9f77b..b4277906e 100644 --- a/winpr/include/winpr/credui.h +++ b/winpr/include/winpr/credui.h @@ -67,9 +67,6 @@ #define CREDUIWIN_SECURE_PROMPT 0x00001000 #define CREDUIWIN_PACK_32_WOW 0x10000000 -typedef HANDLE HWND; -typedef HANDLE HBITMAP; - typedef struct _CREDUI_INFOA { DWORD cbSize; diff --git a/winpr/include/winpr/file.h b/winpr/include/winpr/file.h index eac472bf2..12208dae4 100644 --- a/winpr/include/winpr/file.h +++ b/winpr/include/winpr/file.h @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -37,30 +38,6 @@ #define INVALID_SET_FILE_POINTER ((DWORD) - 1) #define INVALID_FILE_ATTRIBUTES ((DWORD) - 1) -#define FILE_READ_DATA 0x0001 -#define FILE_LIST_DIRECTORY 0x0001 -#define FILE_WRITE_DATA 0x0002 -#define FILE_ADD_FILE 0x0002 -#define FILE_APPEND_DATA 0x0004 -#define FILE_ADD_SUBDIRECTORY 0x0004 -#define FILE_CREATE_PIPE_INSTANCE 0x0004 -#define FILE_READ_EA 0x0008 -#define FILE_WRITE_EA 0x0010 -#define FILE_EXECUTE 0x0020 -#define FILE_TRAVERSE 0x0020 -#define FILE_DELETE_CHILD 0x0040 -#define FILE_READ_ATTRIBUTES 0x0080 -#define FILE_WRITE_ATTRIBUTES 0x0100 - -#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF) -#define FILE_GENERIC_READ (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE) -#define FILE_GENERIC_WRITE (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE) -#define FILE_GENERIC_EXECUTE (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE) - -#define FILE_SHARE_READ 0x00000001 -#define FILE_SHARE_WRITE 0x00000002 -#define FILE_SHARE_DELETE 0x00000004 - #define FILE_ATTRIBUTE_READONLY 0x00000001 #define FILE_ATTRIBUTE_HIDDEN 0x00000002 #define FILE_ATTRIBUTE_SYSTEM 0x00000004 diff --git a/winpr/include/winpr/io.h b/winpr/include/winpr/io.h index c182ea4ef..52d94ed17 100644 --- a/winpr/include/winpr/io.h +++ b/winpr/include/winpr/io.h @@ -25,24 +25,7 @@ #ifndef _WIN32 -#define GENERIC_READ 0x80000000 -#define GENERIC_WRITE 0x40000000 -#define GENERIC_EXECUTE 0x20000000 -#define GENERIC_ALL 0x10000000 - -#define DELETE 0x00010000 -#define READ_CONTROL 0x00020000 -#define WRITE_DAC 0x00040000 -#define WRITE_OWNER 0x00080000 -#define SYNCHRONIZE 0x00100000 -#define STANDARD_RIGHTS_REQUIRED 0x000F0000 -#define STANDARD_RIGHTS_READ 0x00020000 -#define STANDARD_RIGHTS_WRITE 0x00020000 -#define STANDARD_RIGHTS_EXECUTE 0x00020000 -#define STANDARD_RIGHTS_ALL 0x001F0000 -#define SPECIFIC_RIGHTS_ALL 0x0000FFFF -#define ACCESS_SYSTEM_SECURITY 0x01000000 -#define MAXIMUM_ALLOWED 0x02000000 +#include typedef struct _OVERLAPPED { diff --git a/winpr/include/winpr/nt.h b/winpr/include/winpr/nt.h new file mode 100644 index 000000000..dccf6e69b --- /dev/null +++ b/winpr/include/winpr/nt.h @@ -0,0 +1,1405 @@ +/** + * WinPR: Windows Portable Runtime + * Windows Native System Services + * + * Copyright 2013 Marc-Andre Moreau + * + * 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_NT_H +#define WINPR_NT_H + +#include +#include + +#ifndef _WIN32 + +#define FACILITY_DEBUGGER 0x1 +#define FACILITY_RPC_RUNTIME 0x2 +#define FACILITY_RPC_STUBS 0x3 +#define FACILITY_IO_ERROR_CODE 0x4 +#define FACILITY_TERMINAL_SERVER 0xA +#define FACILITY_USB_ERROR_CODE 0x10 +#define FACILITY_HID_ERROR_CODE 0x11 +#define FACILITY_FIREWIRE_ERROR_CODE 0x12 +#define FACILITY_CLUSTER_ERROR_CODE 0x13 +#define FACILITY_ACPI_ERROR_CODE 0x14 +#define FACILITY_SXS_ERROR_CODE 0x15 + +#define DBG_EXCEPTION_HANDLED ((NTSTATUS)0x00010001) +#define DBG_CONTINUE ((NTSTATUS)0x00010002) +#define DBG_REPLY_LATER ((NTSTATUS)0x40010001) +#define DBG_UNABLE_TO_PROVIDE_HANDLE ((NTSTATUS)0x40010002) +#define DBG_TERMINATE_THREAD ((NTSTATUS)0x40010003) +#define DBG_TERMINATE_PROCESS ((NTSTATUS)0x40010004) +#define DBG_CONTROL_C ((NTSTATUS)0x40010005) +#define DBG_PRINTEXCEPTION_C ((NTSTATUS)0x40010006) +#define DBG_RIPEXCEPTION ((NTSTATUS)0x40010007) +#define DBG_CONTROL_BREAK ((NTSTATUS)0x40010008) +#define DBG_COMMAND_EXCEPTION ((NTSTATUS)0x40010009) +#define DBG_EXCEPTION_NOT_HANDLED ((NTSTATUS)0x80010001) +#define DBG_NO_STATE_CHANGE ((NTSTATUS)0xC0010001) +#define DBG_APP_NOT_IDLE ((NTSTATUS)0xC0010002) + +/** + * NTSTATUS codes + */ + +#if!defined(STATUS_SUCCESS) +#define STATUS_SUCCESS ((NTSTATUS)0x00000000) +#endif + +#define STATUS_SEVERITY_SUCCESS 0x0 +#define STATUS_SEVERITY_INFORMATIONAL 0x1 +#define STATUS_SEVERITY_WARNING 0x2 +#define STATUS_SEVERITY_ERROR 0x3 + +#define STATUS_WAIT_1 ((NTSTATUS)0x00000001) +#define STATUS_WAIT_2 ((NTSTATUS)0x00000002) +#define STATUS_WAIT_3 ((NTSTATUS)0x00000003) +#define STATUS_WAIT_63 ((NTSTATUS)0x0000003f) +#define STATUS_ABANDONED ((NTSTATUS)0x00000080) +#define STATUS_ABANDONED_WAIT_63 ((NTSTATUS)0x000000BF) +#define STATUS_USER_APC ((NTSTATUS)0x000000C0) +#define STATUS_KERNEL_APC ((NTSTATUS)0x00000100) +#define STATUS_ALERTED ((NTSTATUS)0x00000101) +#define STATUS_TIMEOUT ((NTSTATUS)0x00000102) +#define STATUS_PENDING ((NTSTATUS)0x00000103) +#define STATUS_REPARSE ((NTSTATUS)0x00000104) +#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105) +#define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS)0x00000106) +#define STATUS_SOME_NOT_MAPPED ((NTSTATUS)0x00000107) +#define STATUS_OPLOCK_BREAK_IN_PROGRESS ((NTSTATUS)0x00000108) +#define STATUS_VOLUME_MOUNTED ((NTSTATUS)0x00000109) +#define STATUS_RXACT_COMMITTED ((NTSTATUS)0x0000010A) +#define STATUS_NOTIFY_CLEANUP ((NTSTATUS)0x0000010B) +#define STATUS_NOTIFY_ENUM_DIR ((NTSTATUS)0x0000010C) +#define STATUS_NO_QUOTAS_FOR_ACCOUNT ((NTSTATUS)0x0000010D) +#define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED ((NTSTATUS)0x0000010E) +#define STATUS_PAGE_FAULT_TRANSITION ((NTSTATUS)0x00000110) +#define STATUS_PAGE_FAULT_DEMAND_ZERO ((NTSTATUS)0x00000111) +#define STATUS_PAGE_FAULT_COPY_ON_WRITE ((NTSTATUS)0x00000112) +#define STATUS_PAGE_FAULT_GUARD_PAGE ((NTSTATUS)0x00000113) +#define STATUS_PAGE_FAULT_PAGING_FILE ((NTSTATUS)0x00000114) +#define STATUS_CACHE_PAGE_LOCKED ((NTSTATUS)0x00000115) +#define STATUS_CRASH_DUMP ((NTSTATUS)0x00000116) +#define STATUS_BUFFER_ALL_ZEROS ((NTSTATUS)0x00000117) +#define STATUS_REPARSE_OBJECT ((NTSTATUS)0x00000118) +#define STATUS_RESOURCE_REQUIREMENTS_CHANGED ((NTSTATUS)0x00000119) +#define STATUS_TRANSLATION_COMPLETE ((NTSTATUS)0x00000120) +#define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY ((NTSTATUS)0x00000121) +#define STATUS_NOTHING_TO_TERMINATE ((NTSTATUS)0x00000122) +#define STATUS_PROCESS_NOT_IN_JOB ((NTSTATUS)0x00000123) +#define STATUS_PROCESS_IN_JOB ((NTSTATUS)0x00000124) +#define STATUS_VOLSNAP_HIBERNATE_READY ((NTSTATUS)0x00000125) +#define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY ((NTSTATUS)0x00000126) + +#define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS)0x40000000) +#define STATUS_THREAD_WAS_SUSPENDED ((NTSTATUS)0x40000001) +#define STATUS_WORKING_SET_LIMIT_RANGE ((NTSTATUS)0x40000002) +#define STATUS_IMAGE_NOT_AT_BASE ((NTSTATUS)0x40000003) +#define STATUS_RXACT_STATE_CREATED ((NTSTATUS)0x40000004) +#define STATUS_SEGMENT_NOTIFICATION ((NTSTATUS)0x40000005) +#define STATUS_LOCAL_USER_SESSION_KEY ((NTSTATUS)0x40000006) +#define STATUS_BAD_CURRENT_DIRECTORY ((NTSTATUS)0x40000007) +#define STATUS_SERIAL_MORE_WRITES ((NTSTATUS)0x40000008) +#define STATUS_REGISTRY_RECOVERED ((NTSTATUS)0x40000009) +#define STATUS_FT_READ_RECOVERY_FROM_BACKUP ((NTSTATUS)0x4000000A) +#define STATUS_FT_WRITE_RECOVERY ((NTSTATUS)0x4000000B) +#define STATUS_SERIAL_COUNTER_TIMEOUT ((NTSTATUS)0x4000000C) +#define STATUS_NULL_LM_PASSWORD ((NTSTATUS)0x4000000D) +#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH ((NTSTATUS)0x4000000E) +#define STATUS_RECEIVE_PARTIAL ((NTSTATUS)0x4000000F) +#define STATUS_RECEIVE_EXPEDITED ((NTSTATUS)0x40000010) +#define STATUS_RECEIVE_PARTIAL_EXPEDITED ((NTSTATUS)0x40000011) +#define STATUS_EVENT_DONE ((NTSTATUS)0x40000012) +#define STATUS_EVENT_PENDING ((NTSTATUS)0x40000013) +#define STATUS_CHECKING_FILE_SYSTEM ((NTSTATUS)0x40000014) +#define STATUS_FATAL_APP_EXIT ((NTSTATUS)0x40000015) +#define STATUS_PREDEFINED_HANDLE ((NTSTATUS)0x40000016) +#define STATUS_WAS_UNLOCKED ((NTSTATUS)0x40000017) +#define STATUS_SERVICE_NOTIFICATION ((NTSTATUS)0x40000018) +#define STATUS_WAS_LOCKED ((NTSTATUS)0x40000019) +#define STATUS_LOG_HARD_ERROR ((NTSTATUS)0x4000001A) +#define STATUS_ALREADY_WIN32 ((NTSTATUS)0x4000001B) +#define STATUS_WX86_UNSIMULATE ((NTSTATUS)0x4000001C) +#define STATUS_WX86_CONTINUE ((NTSTATUS)0x4000001D) +#define STATUS_WX86_SINGLE_STEP ((NTSTATUS)0x4000001E) +#define STATUS_WX86_BREAKPOINT ((NTSTATUS)0x4000001F) +#define STATUS_WX86_EXCEPTION_CONTINUE ((NTSTATUS)0x40000020) +#define STATUS_WX86_EXCEPTION_LASTCHANCE ((NTSTATUS)0x40000021) +#define STATUS_WX86_EXCEPTION_CHAIN ((NTSTATUS)0x40000022) +#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE ((NTSTATUS)0x40000023) +#define STATUS_NO_YIELD_PERFORMED ((NTSTATUS)0x40000024) +#define STATUS_TIMER_RESUME_IGNORED ((NTSTATUS)0x40000025) +#define STATUS_ARBITRATION_UNHANDLED ((NTSTATUS)0x40000026) +#define STATUS_CARDBUS_NOT_SUPPORTED ((NTSTATUS)0x40000027) +#define STATUS_WX86_CREATEWX86TIB ((NTSTATUS)0x40000028) +#define STATUS_MP_PROCESSOR_MISMATCH ((NTSTATUS)0x40000029) +#define STATUS_HIBERNATED ((NTSTATUS)0x4000002A) +#define STATUS_RESUME_HIBERNATION ((NTSTATUS)0x4000002B) +#define STATUS_FIRMWARE_UPDATED ((NTSTATUS)0x4000002C) +#define STATUS_WAKE_SYSTEM ((NTSTATUS)0x40000294) +#define STATUS_DS_SHUTTING_DOWN ((NTSTATUS)0x40000370) + +#define RPC_NT_UUID_LOCAL_ONLY ((NTSTATUS)0x40020056) +#define RPC_NT_SEND_INCOMPLETE ((NTSTATUS)0x400200AF) + +#define STATUS_CTX_CDM_CONNECT ((NTSTATUS)0x400A0004) +#define STATUS_CTX_CDM_DISCONNECT ((NTSTATUS)0x400A0005) + +#define STATUS_SXS_RELEASE_ACTIVATION_CONTEXT ((NTSTATUS)0x4015000D) + +#define STATUS_GUARD_PAGE_VIOLATION ((NTSTATUS)0x80000001) +#define STATUS_DATATYPE_MISALIGNMENT ((NTSTATUS)0x80000002) +#define STATUS_BREAKPOINT ((NTSTATUS)0x80000003) +#define STATUS_SINGLE_STEP ((NTSTATUS)0x80000004) +#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005) +#define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006) +#define STATUS_WAKE_SYSTEM_DEBUGGER ((NTSTATUS)0x80000007) + +#define STATUS_HANDLES_CLOSED ((NTSTATUS)0x8000000A) +#define STATUS_NO_INHERITANCE ((NTSTATUS)0x8000000B) +#define STATUS_GUID_SUBSTITUTION_MADE ((NTSTATUS)0x8000000C) +#define STATUS_PARTIAL_COPY ((NTSTATUS)0x8000000D) +#define STATUS_DEVICE_PAPER_EMPTY ((NTSTATUS)0x8000000E) +#define STATUS_DEVICE_POWERED_OFF ((NTSTATUS)0x8000000F) +#define STATUS_DEVICE_OFF_LINE ((NTSTATUS)0x80000010) +#define STATUS_DEVICE_BUSY ((NTSTATUS)0x80000011) +#define STATUS_NO_MORE_EAS ((NTSTATUS)0x80000012) +#define STATUS_INVALID_EA_NAME ((NTSTATUS)0x80000013) +#define STATUS_EA_LIST_INCONSISTENT ((NTSTATUS)0x80000014) +#define STATUS_INVALID_EA_FLAG ((NTSTATUS)0x80000015) +#define STATUS_VERIFY_REQUIRED ((NTSTATUS)0x80000016) +#define STATUS_EXTRANEOUS_INFORMATION ((NTSTATUS)0x80000017) +#define STATUS_RXACT_COMMIT_NECESSARY ((NTSTATUS)0x80000018) +#define STATUS_NO_MORE_ENTRIES ((NTSTATUS)0x8000001A) +#define STATUS_FILEMARK_DETECTED ((NTSTATUS)0x8000001B) +#define STATUS_MEDIA_CHANGED ((NTSTATUS)0x8000001C) +#define STATUS_BUS_RESET ((NTSTATUS)0x8000001D) +#define STATUS_END_OF_MEDIA ((NTSTATUS)0x8000001E) +#define STATUS_BEGINNING_OF_MEDIA ((NTSTATUS)0x8000001F) +#define STATUS_MEDIA_CHECK ((NTSTATUS)0x80000020) +#define STATUS_SETMARK_DETECTED ((NTSTATUS)0x80000021) +#define STATUS_NO_DATA_DETECTED ((NTSTATUS)0x80000022) +#define STATUS_REDIRECTOR_HAS_OPEN_HANDLES ((NTSTATUS)0x80000023) +#define STATUS_SERVER_HAS_OPEN_HANDLES ((NTSTATUS)0x80000024) +#define STATUS_ALREADY_DISCONNECTED ((NTSTATUS)0x80000025) +#define STATUS_LONGJUMP ((NTSTATUS)0x80000026) +#define STATUS_CLEANER_CARTRIDGE_INSTALLED ((NTSTATUS)0x80000027) +#define STATUS_PLUGPLAY_QUERY_VETOED ((NTSTATUS)0x80000028) +#define STATUS_UNWIND_CONSOLIDATE ((NTSTATUS)0x80000029) +#define STATUS_REGISTRY_HIVE_RECOVERED ((NTSTATUS)0x8000002A) +#define STATUS_DLL_MIGHT_BE_INSECURE ((NTSTATUS)0x8000002B) +#define STATUS_DLL_MIGHT_BE_INCOMPATIBLE ((NTSTATUS)0x8000002C) + +#define STATUS_DEVICE_REQUIRES_CLEANING ((NTSTATUS)0x80000288) +#define STATUS_DEVICE_DOOR_OPEN ((NTSTATUS)0x80000289) + +#define STATUS_CLUSTER_NODE_ALREADY_UP ((NTSTATUS)0x80130001) +#define STATUS_CLUSTER_NODE_ALREADY_DOWN ((NTSTATUS)0x80130002) +#define STATUS_CLUSTER_NETWORK_ALREADY_ONLINE ((NTSTATUS)0x80130003) +#define STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE ((NTSTATUS)0x80130004) +#define STATUS_CLUSTER_NODE_ALREADY_MEMBER ((NTSTATUS)0x80130005) + +#define STATUS_WAIT_0 ((NTSTATUS)0x00000000) +#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001) +#define STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002) +#define STATUS_INVALID_INFO_CLASS ((NTSTATUS)0xC0000003) +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004) +#define STATUS_ACCESS_VIOLATION ((NTSTATUS)0xC0000005) +#define STATUS_IN_PAGE_ERROR ((NTSTATUS)0xC0000006) +#define STATUS_PAGEFILE_QUOTA ((NTSTATUS)0xC0000007) +#define STATUS_INVALID_HANDLE ((NTSTATUS)0xC0000008) +#define STATUS_BAD_INITIAL_STACK ((NTSTATUS)0xC0000009) +#define STATUS_BAD_INITIAL_PC ((NTSTATUS)0xC000000A) +#define STATUS_INVALID_CID ((NTSTATUS)0xC000000B) +#define STATUS_TIMER_NOT_CANCELED ((NTSTATUS)0xC000000C) +#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000D) +#define STATUS_NO_SUCH_DEVICE ((NTSTATUS)0xC000000E) +#define STATUS_NO_SUCH_FILE ((NTSTATUS)0xC000000F) +#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS)0xC0000010) +#define STATUS_END_OF_FILE ((NTSTATUS)0xC0000011) +#define STATUS_WRONG_VOLUME ((NTSTATUS)0xC0000012) +#define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS)0xC0000013) +#define STATUS_UNRECOGNIZED_MEDIA ((NTSTATUS)0xC0000014) +#define STATUS_NONEXISTENT_SECTOR ((NTSTATUS)0xC0000015) +#define STATUS_MORE_PROCESSING_REQUIRED ((NTSTATUS)0xC0000016) +#define STATUS_NO_MEMORY ((NTSTATUS)0xC0000017) +#define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS)0xC0000018) +#define STATUS_NOT_MAPPED_VIEW ((NTSTATUS)0xC0000019) +#define STATUS_UNABLE_TO_FREE_VM ((NTSTATUS)0xC000001A) +#define STATUS_UNABLE_TO_DELETE_SECTION ((NTSTATUS)0xC000001B) +#define STATUS_INVALID_SYSTEM_SERVICE ((NTSTATUS)0xC000001C) +#define STATUS_ILLEGAL_INSTRUCTION ((NTSTATUS)0xC000001D) +#define STATUS_INVALID_LOCK_SEQUENCE ((NTSTATUS)0xC000001E) +#define STATUS_INVALID_VIEW_SIZE ((NTSTATUS)0xC000001F) +#define STATUS_INVALID_FILE_FOR_SECTION ((NTSTATUS)0xC0000020) +#define STATUS_ALREADY_COMMITTED ((NTSTATUS)0xC0000021) +#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022) +#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023) +#define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS)0xC0000024) +#define STATUS_NONCONTINUABLE_EXCEPTION ((NTSTATUS)0xC0000025) +#define STATUS_INVALID_DISPOSITION ((NTSTATUS)0xC0000026) +#define STATUS_UNWIND ((NTSTATUS)0xC0000027) +#define STATUS_BAD_STACK ((NTSTATUS)0xC0000028) +#define STATUS_INVALID_UNWIND_TARGET ((NTSTATUS)0xC0000029) +#define STATUS_NOT_LOCKED ((NTSTATUS)0xC000002A) +#define STATUS_PARITY_ERROR ((NTSTATUS)0xC000002B) +#define STATUS_UNABLE_TO_DECOMMIT_VM ((NTSTATUS)0xC000002C) +#define STATUS_NOT_COMMITTED ((NTSTATUS)0xC000002D) +#define STATUS_INVALID_PORT_ATTRIBUTES ((NTSTATUS)0xC000002E) +#define STATUS_PORT_MESSAGE_TOO_LONG ((NTSTATUS)0xC000002F) +#define STATUS_INVALID_PARAMETER_MIX ((NTSTATUS)0xC0000030) +#define STATUS_INVALID_QUOTA_LOWER ((NTSTATUS)0xC0000031) +#define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS)0xC0000032) +#define STATUS_OBJECT_NAME_INVALID ((NTSTATUS)0xC0000033) +#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034) +#define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS)0xC0000035) +#define STATUS_PORT_DISCONNECTED ((NTSTATUS)0xC0000037) +#define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS)0xC0000038) +#define STATUS_OBJECT_PATH_INVALID ((NTSTATUS)0xC0000039) +#define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS)0xC000003A) +#define STATUS_OBJECT_PATH_SYNTAX_BAD ((NTSTATUS)0xC000003B) +#define STATUS_DATA_OVERRUN ((NTSTATUS)0xC000003C) +#define STATUS_DATA_LATE_ERROR ((NTSTATUS)0xC000003D) +#define STATUS_DATA_ERROR ((NTSTATUS)0xC000003E) +#define STATUS_CRC_ERROR ((NTSTATUS)0xC000003F) +#define STATUS_SECTION_TOO_BIG ((NTSTATUS)0xC0000040) +#define STATUS_PORT_CONNECTION_REFUSED ((NTSTATUS)0xC0000041) +#define STATUS_INVALID_PORT_HANDLE ((NTSTATUS)0xC0000042) +#define STATUS_SHARING_VIOLATION ((NTSTATUS)0xC0000043) +#define STATUS_QUOTA_EXCEEDED ((NTSTATUS)0xC0000044) +#define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS)0xC0000045) +#define STATUS_MUTANT_NOT_OWNED ((NTSTATUS)0xC0000046) +#define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((NTSTATUS)0xC0000047) +#define STATUS_PORT_ALREADY_SET ((NTSTATUS)0xC0000048) +#define STATUS_SECTION_NOT_IMAGE ((NTSTATUS)0xC0000049) +#define STATUS_SUSPEND_COUNT_EXCEEDED ((NTSTATUS)0xC000004A) +#define STATUS_THREAD_IS_TERMINATING ((NTSTATUS)0xC000004B) +#define STATUS_BAD_WORKING_SET_LIMIT ((NTSTATUS)0xC000004C) +#define STATUS_INCOMPATIBLE_FILE_MAP ((NTSTATUS)0xC000004D) +#define STATUS_SECTION_PROTECTION ((NTSTATUS)0xC000004E) +#define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS)0xC000004F) +#define STATUS_EA_TOO_LARGE ((NTSTATUS)0xC0000050) +#define STATUS_NONEXISTENT_EA_ENTRY ((NTSTATUS)0xC0000051) +#define STATUS_NO_EAS_ON_FILE ((NTSTATUS)0xC0000052) +#define STATUS_EA_CORRUPT_ERROR ((NTSTATUS)0xC0000053) +#define STATUS_FILE_LOCK_CONFLICT ((NTSTATUS)0xC0000054) +#define STATUS_LOCK_NOT_GRANTED ((NTSTATUS)0xC0000055) +#define STATUS_DELETE_PENDING ((NTSTATUS)0xC0000056) +#define STATUS_CTL_FILE_NOT_SUPPORTED ((NTSTATUS)0xC0000057) +#define STATUS_UNKNOWN_REVISION ((NTSTATUS)0xC0000058) +#define STATUS_REVISION_MISMATCH ((NTSTATUS)0xC0000059) +#define STATUS_INVALID_OWNER ((NTSTATUS)0xC000005A) +#define STATUS_INVALID_PRIMARY_GROUP ((NTSTATUS)0xC000005B) +#define STATUS_NO_IMPERSONATION_TOKEN ((NTSTATUS)0xC000005C) +#define STATUS_CANT_DISABLE_MANDATORY ((NTSTATUS)0xC000005D) +#define STATUS_NO_LOGON_SERVERS ((NTSTATUS)0xC000005E) +#define STATUS_NO_SUCH_LOGON_SESSION ((NTSTATUS)0xC000005F) +#define STATUS_NO_SUCH_PRIVILEGE ((NTSTATUS)0xC0000060) +#define STATUS_PRIVILEGE_NOT_HELD ((NTSTATUS)0xC0000061) +#define STATUS_INVALID_ACCOUNT_NAME ((NTSTATUS)0xC0000062) +#define STATUS_USER_EXISTS ((NTSTATUS)0xC0000063) +#define STATUS_NO_SUCH_USER ((NTSTATUS)0xC0000064) +#define STATUS_GROUP_EXISTS ((NTSTATUS)0xC0000065) +#define STATUS_NO_SUCH_GROUP ((NTSTATUS)0xC0000066) +#define STATUS_MEMBER_IN_GROUP ((NTSTATUS)0xC0000067) +#define STATUS_MEMBER_NOT_IN_GROUP ((NTSTATUS)0xC0000068) +#define STATUS_LAST_ADMIN ((NTSTATUS)0xC0000069) +#define STATUS_WRONG_PASSWORD ((NTSTATUS)0xC000006A) +#define STATUS_ILL_FORMED_PASSWORD ((NTSTATUS)0xC000006B) +#define STATUS_PASSWORD_RESTRICTION ((NTSTATUS)0xC000006C) +#define STATUS_LOGON_FAILURE ((NTSTATUS)0xC000006D) +#define STATUS_ACCOUNT_RESTRICTION ((NTSTATUS)0xC000006E) +#define STATUS_INVALID_LOGON_HOURS ((NTSTATUS)0xC000006F) +#define STATUS_INVALID_WORKSTATION ((NTSTATUS)0xC0000070) +#define STATUS_PASSWORD_EXPIRED ((NTSTATUS)0xC0000071) +#define STATUS_ACCOUNT_DISABLED ((NTSTATUS)0xC0000072) +#define STATUS_NONE_MAPPED ((NTSTATUS)0xC0000073) +#define STATUS_TOO_MANY_LUIDS_REQUESTED ((NTSTATUS)0xC0000074) +#define STATUS_LUIDS_EXHAUSTED ((NTSTATUS)0xC0000075) +#define STATUS_INVALID_SUB_AUTHORITY ((NTSTATUS)0xC0000076) +#define STATUS_INVALID_ACL ((NTSTATUS)0xC0000077) +#define STATUS_INVALID_SID ((NTSTATUS)0xC0000078) +#define STATUS_INVALID_SECURITY_DESCR ((NTSTATUS)0xC0000079) +#define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS)0xC000007A) +#define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS)0xC000007B) +#define STATUS_NO_TOKEN ((NTSTATUS)0xC000007C) +#define STATUS_BAD_INHERITANCE_ACL ((NTSTATUS)0xC000007D) +#define STATUS_RANGE_NOT_LOCKED ((NTSTATUS)0xC000007E) +#define STATUS_DISK_FULL ((NTSTATUS)0xC000007F) +#define STATUS_SERVER_DISABLED ((NTSTATUS)0xC0000080) +#define STATUS_SERVER_NOT_DISABLED ((NTSTATUS)0xC0000081) +#define STATUS_TOO_MANY_GUIDS_REQUESTED ((NTSTATUS)0xC0000082) +#define STATUS_GUIDS_EXHAUSTED ((NTSTATUS)0xC0000083) +#define STATUS_INVALID_ID_AUTHORITY ((NTSTATUS)0xC0000084) +#define STATUS_AGENTS_EXHAUSTED ((NTSTATUS)0xC0000085) +#define STATUS_INVALID_VOLUME_LABEL ((NTSTATUS)0xC0000086) +#define STATUS_SECTION_NOT_EXTENDED ((NTSTATUS)0xC0000087) +#define STATUS_NOT_MAPPED_DATA ((NTSTATUS)0xC0000088) +#define STATUS_RESOURCE_DATA_NOT_FOUND ((NTSTATUS)0xC0000089) +#define STATUS_RESOURCE_TYPE_NOT_FOUND ((NTSTATUS)0xC000008A) +#define STATUS_RESOURCE_NAME_NOT_FOUND ((NTSTATUS)0xC000008B) +#define STATUS_ARRAY_BOUNDS_EXCEEDED ((NTSTATUS)0xC000008C) +#define STATUS_FLOAT_DENORMAL_OPERAND ((NTSTATUS)0xC000008D) +#define STATUS_FLOAT_DIVIDE_BY_ZERO ((NTSTATUS)0xC000008E) +#define STATUS_FLOAT_INEXACT_RESULT ((NTSTATUS)0xC000008F) +#define STATUS_FLOAT_INVALID_OPERATION ((NTSTATUS)0xC0000090) +#define STATUS_FLOAT_OVERFLOW ((NTSTATUS)0xC0000091) +#define STATUS_FLOAT_STACK_CHECK ((NTSTATUS)0xC0000092) +#define STATUS_FLOAT_UNDERFLOW ((NTSTATUS)0xC0000093) +#define STATUS_INTEGER_DIVIDE_BY_ZERO ((NTSTATUS)0xC0000094) +#define STATUS_INTEGER_OVERFLOW ((NTSTATUS)0xC0000095) +#define STATUS_PRIVILEGED_INSTRUCTION ((NTSTATUS)0xC0000096) +#define STATUS_TOO_MANY_PAGING_FILES ((NTSTATUS)0xC0000097) +#define STATUS_FILE_INVALID ((NTSTATUS)0xC0000098) +#define STATUS_ALLOTTED_SPACE_EXCEEDED ((NTSTATUS)0xC0000099) +#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009A) +#define STATUS_DFS_EXIT_PATH_FOUND ((NTSTATUS)0xC000009B) +#define STATUS_DEVICE_DATA_ERROR ((NTSTATUS)0xC000009C) +#define STATUS_DEVICE_NOT_CONNECTED ((NTSTATUS)0xC000009D) +#define STATUS_DEVICE_POWER_FAILURE ((NTSTATUS)0xC000009E) +#define STATUS_FREE_VM_NOT_AT_BASE ((NTSTATUS)0xC000009F) +#define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS)0xC00000A0) +#define STATUS_WORKING_SET_QUOTA ((NTSTATUS)0xC00000A1) +#define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS)0xC00000A2) +#define STATUS_DEVICE_NOT_READY ((NTSTATUS)0xC00000A3) +#define STATUS_INVALID_GROUP_ATTRIBUTES ((NTSTATUS)0xC00000A4) +#define STATUS_BAD_IMPERSONATION_LEVEL ((NTSTATUS)0xC00000A5) +#define STATUS_CANT_OPEN_ANONYMOUS ((NTSTATUS)0xC00000A6) +#define STATUS_BAD_VALIDATION_CLASS ((NTSTATUS)0xC00000A7) +#define STATUS_BAD_TOKEN_TYPE ((NTSTATUS)0xC00000A8) +#define STATUS_BAD_MASTER_BOOT_RECORD ((NTSTATUS)0xC00000A9) +#define STATUS_INSTRUCTION_MISALIGNMENT ((NTSTATUS)0xC00000AA) +#define STATUS_INSTANCE_NOT_AVAILABLE ((NTSTATUS)0xC00000AB) +#define STATUS_PIPE_NOT_AVAILABLE ((NTSTATUS)0xC00000AC) +#define STATUS_INVALID_PIPE_STATE ((NTSTATUS)0xC00000AD) +#define STATUS_PIPE_BUSY ((NTSTATUS)0xC00000AE) +#define STATUS_ILLEGAL_FUNCTION ((NTSTATUS)0xC00000AF) +#define STATUS_PIPE_DISCONNECTED ((NTSTATUS)0xC00000B0) +#define STATUS_PIPE_CLOSING ((NTSTATUS)0xC00000B1) +#define STATUS_PIPE_CONNECTED ((NTSTATUS)0xC00000B2) +#define STATUS_PIPE_LISTENING ((NTSTATUS)0xC00000B3) +#define STATUS_INVALID_READ_MODE ((NTSTATUS)0xC00000B4) +#define STATUS_IO_TIMEOUT ((NTSTATUS)0xC00000B5) +#define STATUS_FILE_FORCED_CLOSED ((NTSTATUS)0xC00000B6) +#define STATUS_PROFILING_NOT_STARTED ((NTSTATUS)0xC00000B7) +#define STATUS_PROFILING_NOT_STOPPED ((NTSTATUS)0xC00000B8) +#define STATUS_COULD_NOT_INTERPRET ((NTSTATUS)0xC00000B9) +#define STATUS_FILE_IS_A_DIRECTORY ((NTSTATUS)0xC00000BA) +#define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BB) +#define STATUS_REMOTE_NOT_LISTENING ((NTSTATUS)0xC00000BC) +#define STATUS_DUPLICATE_NAME ((NTSTATUS)0xC00000BD) +#define STATUS_BAD_NETWORK_PATH ((NTSTATUS)0xC00000BE) +#define STATUS_NETWORK_BUSY ((NTSTATUS)0xC00000BF) +#define STATUS_DEVICE_DOES_NOT_EXIST ((NTSTATUS)0xC00000C0) +#define STATUS_TOO_MANY_COMMANDS ((NTSTATUS)0xC00000C1) +#define STATUS_ADAPTER_HARDWARE_ERROR ((NTSTATUS)0xC00000C2) +#define STATUS_INVALID_NETWORK_RESPONSE ((NTSTATUS)0xC00000C3) +#define STATUS_UNEXPECTED_NETWORK_ERROR ((NTSTATUS)0xC00000C4) +#define STATUS_BAD_REMOTE_ADAPTER ((NTSTATUS)0xC00000C5) +#define STATUS_PRINT_QUEUE_FULL ((NTSTATUS)0xC00000C6) +#define STATUS_NO_SPOOL_SPACE ((NTSTATUS)0xC00000C7) +#define STATUS_PRINT_CANCELLED ((NTSTATUS)0xC00000C8) +#define STATUS_NETWORK_NAME_DELETED ((NTSTATUS)0xC00000C9) +#define STATUS_NETWORK_ACCESS_DENIED ((NTSTATUS)0xC00000CA) +#define STATUS_BAD_DEVICE_TYPE ((NTSTATUS)0xC00000CB) +#define STATUS_BAD_NETWORK_NAME ((NTSTATUS)0xC00000CC) +#define STATUS_TOO_MANY_NAMES ((NTSTATUS)0xC00000CD) +#define STATUS_TOO_MANY_SESSIONS ((NTSTATUS)0xC00000CE) +#define STATUS_SHARING_PAUSED ((NTSTATUS)0xC00000CF) +#define STATUS_REQUEST_NOT_ACCEPTED ((NTSTATUS)0xC00000D0) +#define STATUS_REDIRECTOR_PAUSED ((NTSTATUS)0xC00000D1) +#define STATUS_NET_WRITE_FAULT ((NTSTATUS)0xC00000D2) +#define STATUS_PROFILING_AT_LIMIT ((NTSTATUS)0xC00000D3) +#define STATUS_NOT_SAME_DEVICE ((NTSTATUS)0xC00000D4) +#define STATUS_FILE_RENAMED ((NTSTATUS)0xC00000D5) +#define STATUS_VIRTUAL_CIRCUIT_CLOSED ((NTSTATUS)0xC00000D6) +#define STATUS_NO_SECURITY_ON_OBJECT ((NTSTATUS)0xC00000D7) +#define STATUS_CANT_WAIT ((NTSTATUS)0xC00000D8) +#define STATUS_PIPE_EMPTY ((NTSTATUS)0xC00000D9) +#define STATUS_CANT_ACCESS_DOMAIN_INFO ((NTSTATUS)0xC00000DA) +#define STATUS_CANT_TERMINATE_SELF ((NTSTATUS)0xC00000DB) +#define STATUS_INVALID_SERVER_STATE ((NTSTATUS)0xC00000DC) +#define STATUS_INVALID_DOMAIN_STATE ((NTSTATUS)0xC00000DD) +#define STATUS_INVALID_DOMAIN_ROLE ((NTSTATUS)0xC00000DE) +#define STATUS_NO_SUCH_DOMAIN ((NTSTATUS)0xC00000DF) +#define STATUS_DOMAIN_EXISTS ((NTSTATUS)0xC00000E0) +#define STATUS_DOMAIN_LIMIT_EXCEEDED ((NTSTATUS)0xC00000E1) +#define STATUS_OPLOCK_NOT_GRANTED ((NTSTATUS)0xC00000E2) +#define STATUS_INVALID_OPLOCK_PROTOCOL ((NTSTATUS)0xC00000E3) +#define STATUS_INTERNAL_DB_CORRUPTION ((NTSTATUS)0xC00000E4) +#define STATUS_INTERNAL_ERROR ((NTSTATUS)0xC00000E5) +#define STATUS_GENERIC_NOT_MAPPED ((NTSTATUS)0xC00000E6) +#define STATUS_BAD_DESCRIPTOR_FORMAT ((NTSTATUS)0xC00000E7) +#define STATUS_INVALID_USER_BUFFER ((NTSTATUS)0xC00000E8) +#define STATUS_UNEXPECTED_IO_ERROR ((NTSTATUS)0xC00000E9) +#define STATUS_UNEXPECTED_MM_CREATE_ERR ((NTSTATUS)0xC00000EA) +#define STATUS_UNEXPECTED_MM_MAP_ERROR ((NTSTATUS)0xC00000EB) +#define STATUS_UNEXPECTED_MM_EXTEND_ERR ((NTSTATUS)0xC00000EC) +#define STATUS_NOT_LOGON_PROCESS ((NTSTATUS)0xC00000ED) +#define STATUS_LOGON_SESSION_EXISTS ((NTSTATUS)0xC00000EE) +#define STATUS_INVALID_PARAMETER_1 ((NTSTATUS)0xC00000EF) +#define STATUS_INVALID_PARAMETER_2 ((NTSTATUS)0xC00000F0) +#define STATUS_INVALID_PARAMETER_3 ((NTSTATUS)0xC00000F1) +#define STATUS_INVALID_PARAMETER_4 ((NTSTATUS)0xC00000F2) +#define STATUS_INVALID_PARAMETER_5 ((NTSTATUS)0xC00000F3) +#define STATUS_INVALID_PARAMETER_6 ((NTSTATUS)0xC00000F4) +#define STATUS_INVALID_PARAMETER_7 ((NTSTATUS)0xC00000F5) +#define STATUS_INVALID_PARAMETER_8 ((NTSTATUS)0xC00000F6) +#define STATUS_INVALID_PARAMETER_9 ((NTSTATUS)0xC00000F7) +#define STATUS_INVALID_PARAMETER_10 ((NTSTATUS)0xC00000F8) +#define STATUS_INVALID_PARAMETER_11 ((NTSTATUS)0xC00000F9) +#define STATUS_INVALID_PARAMETER_12 ((NTSTATUS)0xC00000FA) +#define STATUS_REDIRECTOR_NOT_STARTED ((NTSTATUS)0xC00000FB) +#define STATUS_REDIRECTOR_STARTED ((NTSTATUS)0xC00000FC) +#define STATUS_STACK_OVERFLOW ((NTSTATUS)0xC00000FD) +#define STATUS_NO_SUCH_PACKAGE ((NTSTATUS)0xC00000FE) +#define STATUS_BAD_FUNCTION_TABLE ((NTSTATUS)0xC00000FF) +#define STATUS_VARIABLE_NOT_FOUND ((NTSTATUS)0xC0000100) +#define STATUS_DIRECTORY_NOT_EMPTY ((NTSTATUS)0xC0000101) +#define STATUS_FILE_CORRUPT_ERROR ((NTSTATUS)0xC0000102) +#define STATUS_NOT_A_DIRECTORY ((NTSTATUS)0xC0000103) +#define STATUS_BAD_LOGON_SESSION_STATE ((NTSTATUS)0xC0000104) +#define STATUS_LOGON_SESSION_COLLISION ((NTSTATUS)0xC0000105) +#define STATUS_NAME_TOO_LONG ((NTSTATUS)0xC0000106) +#define STATUS_FILES_OPEN ((NTSTATUS)0xC0000107) +#define STATUS_CONNECTION_IN_USE ((NTSTATUS)0xC0000108) +#define STATUS_MESSAGE_NOT_FOUND ((NTSTATUS)0xC0000109) +#define STATUS_PROCESS_IS_TERMINATING ((NTSTATUS)0xC000010A) +#define STATUS_INVALID_LOGON_TYPE ((NTSTATUS)0xC000010B) +#define STATUS_NO_GUID_TRANSLATION ((NTSTATUS)0xC000010C) +#define STATUS_CANNOT_IMPERSONATE ((NTSTATUS)0xC000010D) +#define STATUS_IMAGE_ALREADY_LOADED ((NTSTATUS)0xC000010E) +#define STATUS_ABIOS_NOT_PRESENT ((NTSTATUS)0xC000010F) +#define STATUS_ABIOS_LID_NOT_EXIST ((NTSTATUS)0xC0000110) +#define STATUS_ABIOS_LID_ALREADY_OWNED ((NTSTATUS)0xC0000111) +#define STATUS_ABIOS_NOT_LID_OWNER ((NTSTATUS)0xC0000112) +#define STATUS_ABIOS_INVALID_COMMAND ((NTSTATUS)0xC0000113) +#define STATUS_ABIOS_INVALID_LID ((NTSTATUS)0xC0000114) +#define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE ((NTSTATUS)0xC0000115) +#define STATUS_ABIOS_INVALID_SELECTOR ((NTSTATUS)0xC0000116) +#define STATUS_NO_LDT ((NTSTATUS)0xC0000117) +#define STATUS_INVALID_LDT_SIZE ((NTSTATUS)0xC0000118) +#define STATUS_INVALID_LDT_OFFSET ((NTSTATUS)0xC0000119) +#define STATUS_INVALID_LDT_DESCRIPTOR ((NTSTATUS)0xC000011A) +#define STATUS_INVALID_IMAGE_NE_FORMAT ((NTSTATUS)0xC000011B) +#define STATUS_RXACT_INVALID_STATE ((NTSTATUS)0xC000011C) +#define STATUS_RXACT_COMMIT_FAILURE ((NTSTATUS)0xC000011D) +#define STATUS_MAPPED_FILE_SIZE_ZERO ((NTSTATUS)0xC000011E) +#define STATUS_TOO_MANY_OPENED_FILES ((NTSTATUS)0xC000011F) +#define STATUS_CANCELLED ((NTSTATUS)0xC0000120) +#define STATUS_CANNOT_DELETE ((NTSTATUS)0xC0000121) +#define STATUS_INVALID_COMPUTER_NAME ((NTSTATUS)0xC0000122) +#define STATUS_FILE_DELETED ((NTSTATUS)0xC0000123) +#define STATUS_SPECIAL_ACCOUNT ((NTSTATUS)0xC0000124) +#define STATUS_SPECIAL_GROUP ((NTSTATUS)0xC0000125) +#define STATUS_SPECIAL_USER ((NTSTATUS)0xC0000126) +#define STATUS_MEMBERS_PRIMARY_GROUP ((NTSTATUS)0xC0000127) +#define STATUS_FILE_CLOSED ((NTSTATUS)0xC0000128) +#define STATUS_TOO_MANY_THREADS ((NTSTATUS)0xC0000129) +#define STATUS_THREAD_NOT_IN_PROCESS ((NTSTATUS)0xC000012A) +#define STATUS_TOKEN_ALREADY_IN_USE ((NTSTATUS)0xC000012B) +#define STATUS_PAGEFILE_QUOTA_EXCEEDED ((NTSTATUS)0xC000012C) +#define STATUS_COMMITMENT_LIMIT ((NTSTATUS)0xC000012D) +#define STATUS_INVALID_IMAGE_LE_FORMAT ((NTSTATUS)0xC000012E) +#define STATUS_INVALID_IMAGE_NOT_MZ ((NTSTATUS)0xC000012F) +#define STATUS_INVALID_IMAGE_PROTECT ((NTSTATUS)0xC0000130) +#define STATUS_INVALID_IMAGE_WIN_16 ((NTSTATUS)0xC0000131) +#define STATUS_LOGON_SERVER_CONFLICT ((NTSTATUS)0xC0000132) +#define STATUS_TIME_DIFFERENCE_AT_DC ((NTSTATUS)0xC0000133) +#define STATUS_SYNCHRONIZATION_REQUIRED ((NTSTATUS)0xC0000134) +#define STATUS_DLL_NOT_FOUND ((NTSTATUS)0xC0000135) +#define STATUS_OPEN_FAILED ((NTSTATUS)0xC0000136) +#define STATUS_IO_PRIVILEGE_FAILED ((NTSTATUS)0xC0000137) +#define STATUS_ORDINAL_NOT_FOUND ((NTSTATUS)0xC0000138) +#define STATUS_ENTRYPOINT_NOT_FOUND ((NTSTATUS)0xC0000139) +#define STATUS_CONTROL_C_EXIT ((NTSTATUS)0xC000013A) +#define STATUS_LOCAL_DISCONNECT ((NTSTATUS)0xC000013B) +#define STATUS_REMOTE_DISCONNECT ((NTSTATUS)0xC000013C) +#define STATUS_REMOTE_RESOURCES ((NTSTATUS)0xC000013D) +#define STATUS_LINK_FAILED ((NTSTATUS)0xC000013E) +#define STATUS_LINK_TIMEOUT ((NTSTATUS)0xC000013F) +#define STATUS_INVALID_CONNECTION ((NTSTATUS)0xC0000140) +#define STATUS_INVALID_ADDRESS ((NTSTATUS)0xC0000141) +#define STATUS_DLL_INIT_FAILED ((NTSTATUS)0xC0000142) +#define STATUS_MISSING_SYSTEMFILE ((NTSTATUS)0xC0000143) +#define STATUS_UNHANDLED_EXCEPTION ((NTSTATUS)0xC0000144) +#define STATUS_APP_INIT_FAILURE ((NTSTATUS)0xC0000145) +#define STATUS_PAGEFILE_CREATE_FAILED ((NTSTATUS)0xC0000146) +#define STATUS_NO_PAGEFILE ((NTSTATUS)0xC0000147) +#define STATUS_INVALID_LEVEL ((NTSTATUS)0xC0000148) +#define STATUS_WRONG_PASSWORD_CORE ((NTSTATUS)0xC0000149) +#define STATUS_ILLEGAL_FLOAT_CONTEXT ((NTSTATUS)0xC000014A) +#define STATUS_PIPE_BROKEN ((NTSTATUS)0xC000014B) +#define STATUS_REGISTRY_CORRUPT ((NTSTATUS)0xC000014C) +#define STATUS_REGISTRY_IO_FAILED ((NTSTATUS)0xC000014D) +#define STATUS_NO_EVENT_PAIR ((NTSTATUS)0xC000014E) +#define STATUS_UNRECOGNIZED_VOLUME ((NTSTATUS)0xC000014F) +#define STATUS_SERIAL_NO_DEVICE_INITED ((NTSTATUS)0xC0000150) +#define STATUS_NO_SUCH_ALIAS ((NTSTATUS)0xC0000151) +#define STATUS_MEMBER_NOT_IN_ALIAS ((NTSTATUS)0xC0000152) +#define STATUS_MEMBER_IN_ALIAS ((NTSTATUS)0xC0000153) +#define STATUS_ALIAS_EXISTS ((NTSTATUS)0xC0000154) +#define STATUS_LOGON_NOT_GRANTED ((NTSTATUS)0xC0000155) +#define STATUS_TOO_MANY_SECRETS ((NTSTATUS)0xC0000156) +#define STATUS_SECRET_TOO_LONG ((NTSTATUS)0xC0000157) +#define STATUS_INTERNAL_DB_ERROR ((NTSTATUS)0xC0000158) +#define STATUS_FULLSCREEN_MODE ((NTSTATUS)0xC0000159) +#define STATUS_TOO_MANY_CONTEXT_IDS ((NTSTATUS)0xC000015A) +#define STATUS_LOGON_TYPE_NOT_GRANTED ((NTSTATUS)0xC000015B) +#define STATUS_NOT_REGISTRY_FILE ((NTSTATUS)0xC000015C) +#define STATUS_NT_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS)0xC000015D) +#define STATUS_DOMAIN_CTRLR_CONFIG_ERROR ((NTSTATUS)0xC000015E) +#define STATUS_FT_MISSING_MEMBER ((NTSTATUS)0xC000015F) +#define STATUS_ILL_FORMED_SERVICE_ENTRY ((NTSTATUS)0xC0000160) +#define STATUS_ILLEGAL_CHARACTER ((NTSTATUS)0xC0000161) +#define STATUS_UNMAPPABLE_CHARACTER ((NTSTATUS)0xC0000162) +#define STATUS_UNDEFINED_CHARACTER ((NTSTATUS)0xC0000163) +#define STATUS_FLOPPY_VOLUME ((NTSTATUS)0xC0000164) +#define STATUS_FLOPPY_ID_MARK_NOT_FOUND ((NTSTATUS)0xC0000165) +#define STATUS_FLOPPY_WRONG_CYLINDER ((NTSTATUS)0xC0000166) +#define STATUS_FLOPPY_UNKNOWN_ERROR ((NTSTATUS)0xC0000167) +#define STATUS_FLOPPY_BAD_REGISTERS ((NTSTATUS)0xC0000168) +#define STATUS_DISK_RECALIBRATE_FAILED ((NTSTATUS)0xC0000169) +#define STATUS_DISK_OPERATION_FAILED ((NTSTATUS)0xC000016A) +#define STATUS_DISK_RESET_FAILED ((NTSTATUS)0xC000016B) +#define STATUS_SHARED_IRQ_BUSY ((NTSTATUS)0xC000016C) +#define STATUS_FT_ORPHANING ((NTSTATUS)0xC000016D) +#define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT ((NTSTATUS)0xC000016E) + +#define STATUS_PARTITION_FAILURE ((NTSTATUS)0xC0000172) +#define STATUS_INVALID_BLOCK_LENGTH ((NTSTATUS)0xC0000173) +#define STATUS_DEVICE_NOT_PARTITIONED ((NTSTATUS)0xC0000174) +#define STATUS_UNABLE_TO_LOCK_MEDIA ((NTSTATUS)0xC0000175) +#define STATUS_UNABLE_TO_UNLOAD_MEDIA ((NTSTATUS)0xC0000176) +#define STATUS_EOM_OVERFLOW ((NTSTATUS)0xC0000177) +#define STATUS_NO_MEDIA ((NTSTATUS)0xC0000178) +#define STATUS_NO_SUCH_MEMBER ((NTSTATUS)0xC000017A) +#define STATUS_INVALID_MEMBER ((NTSTATUS)0xC000017B) +#define STATUS_KEY_DELETED ((NTSTATUS)0xC000017C) +#define STATUS_NO_LOG_SPACE ((NTSTATUS)0xC000017D) +#define STATUS_TOO_MANY_SIDS ((NTSTATUS)0xC000017E) +#define STATUS_LM_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS)0xC000017F) +#define STATUS_KEY_HAS_CHILDREN ((NTSTATUS)0xC0000180) +#define STATUS_CHILD_MUST_BE_VOLATILE ((NTSTATUS)0xC0000181) +#define STATUS_DEVICE_CONFIGURATION_ERROR ((NTSTATUS)0xC0000182) +#define STATUS_DRIVER_INTERNAL_ERROR ((NTSTATUS)0xC0000183) +#define STATUS_INVALID_DEVICE_STATE ((NTSTATUS)0xC0000184) +#define STATUS_IO_DEVICE_ERROR ((NTSTATUS)0xC0000185) +#define STATUS_DEVICE_PROTOCOL_ERROR ((NTSTATUS)0xC0000186) +#define STATUS_BACKUP_CONTROLLER ((NTSTATUS)0xC0000187) +#define STATUS_LOG_FILE_FULL ((NTSTATUS)0xC0000188) +#define STATUS_TOO_LATE ((NTSTATUS)0xC0000189) +#define STATUS_NO_TRUST_LSA_SECRET ((NTSTATUS)0xC000018A) +#define STATUS_NO_TRUST_SAM_ACCOUNT ((NTSTATUS)0xC000018B) +#define STATUS_TRUSTED_DOMAIN_FAILURE ((NTSTATUS)0xC000018C) +#define STATUS_TRUSTED_RELATIONSHIP_FAILURE ((NTSTATUS)0xC000018D) +#define STATUS_EVENTLOG_FILE_CORRUPT ((NTSTATUS)0xC000018E) +#define STATUS_EVENTLOG_CANT_START ((NTSTATUS)0xC000018F) +#define STATUS_TRUST_FAILURE ((NTSTATUS)0xC0000190) +#define STATUS_MUTANT_LIMIT_EXCEEDED ((NTSTATUS)0xC0000191) +#define STATUS_NETLOGON_NOT_STARTED ((NTSTATUS)0xC0000192) +#define STATUS_ACCOUNT_EXPIRED ((NTSTATUS)0xC0000193) +#define STATUS_POSSIBLE_DEADLOCK ((NTSTATUS)0xC0000194) +#define STATUS_NETWORK_CREDENTIAL_CONFLICT ((NTSTATUS)0xC0000195) +#define STATUS_REMOTE_SESSION_LIMIT ((NTSTATUS)0xC0000196) +#define STATUS_EVENTLOG_FILE_CHANGED ((NTSTATUS)0xC0000197) +#define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT ((NTSTATUS)0xC0000198) +#define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT ((NTSTATUS)0xC0000199) +#define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT ((NTSTATUS)0xC000019A) +#define STATUS_DOMAIN_TRUST_INCONSISTENT ((NTSTATUS)0xC000019B) +#define STATUS_FS_DRIVER_REQUIRED ((NTSTATUS)0xC000019C) +#define STATUS_NO_USER_SESSION_KEY ((NTSTATUS)0xC0000202) +#define STATUS_USER_SESSION_DELETED ((NTSTATUS)0xC0000203) +#define STATUS_RESOURCE_LANG_NOT_FOUND ((NTSTATUS)0xC0000204) +#define STATUS_INSUFF_SERVER_RESOURCES ((NTSTATUS)0xC0000205) +#define STATUS_INVALID_BUFFER_SIZE ((NTSTATUS)0xC0000206) +#define STATUS_INVALID_ADDRESS_COMPONENT ((NTSTATUS)0xC0000207) +#define STATUS_INVALID_ADDRESS_WILDCARD ((NTSTATUS)0xC0000208) +#define STATUS_TOO_MANY_ADDRESSES ((NTSTATUS)0xC0000209) +#define STATUS_ADDRESS_ALREADY_EXISTS ((NTSTATUS)0xC000020A) +#define STATUS_ADDRESS_CLOSED ((NTSTATUS)0xC000020B) +#define STATUS_CONNECTION_DISCONNECTED ((NTSTATUS)0xC000020C) +#define STATUS_CONNECTION_RESET ((NTSTATUS)0xC000020D) +#define STATUS_TOO_MANY_NODES ((NTSTATUS)0xC000020E) +#define STATUS_TRANSACTION_ABORTED ((NTSTATUS)0xC000020F) +#define STATUS_TRANSACTION_TIMED_OUT ((NTSTATUS)0xC0000210) +#define STATUS_TRANSACTION_NO_RELEASE ((NTSTATUS)0xC0000211) +#define STATUS_TRANSACTION_NO_MATCH ((NTSTATUS)0xC0000212) +#define STATUS_TRANSACTION_RESPONDED ((NTSTATUS)0xC0000213) +#define STATUS_TRANSACTION_INVALID_ID ((NTSTATUS)0xC0000214) +#define STATUS_TRANSACTION_INVALID_TYPE ((NTSTATUS)0xC0000215) +#define STATUS_NOT_SERVER_SESSION ((NTSTATUS)0xC0000216) +#define STATUS_NOT_CLIENT_SESSION ((NTSTATUS)0xC0000217) +#define STATUS_CANNOT_LOAD_REGISTRY_FILE ((NTSTATUS)0xC0000218) +#define STATUS_DEBUG_ATTACH_FAILED ((NTSTATUS)0xC0000219) +#define STATUS_SYSTEM_PROCESS_TERMINATED ((NTSTATUS)0xC000021A) +#define STATUS_DATA_NOT_ACCEPTED ((NTSTATUS)0xC000021B) +#define STATUS_NO_BROWSER_SERVERS_FOUND ((NTSTATUS)0xC000021C) +#define STATUS_VDM_HARD_ERROR ((NTSTATUS)0xC000021D) +#define STATUS_DRIVER_CANCEL_TIMEOUT ((NTSTATUS)0xC000021E) +#define STATUS_REPLY_MESSAGE_MISMATCH ((NTSTATUS)0xC000021F) +#define STATUS_MAPPED_ALIGNMENT ((NTSTATUS)0xC0000220) +#define STATUS_IMAGE_CHECKSUM_MISMATCH ((NTSTATUS)0xC0000221) +#define STATUS_LOST_WRITEBEHIND_DATA ((NTSTATUS)0xC0000222) +#define STATUS_CLIENT_SERVER_PARAMETERS_INVALID ((NTSTATUS)0xC0000223) +#define STATUS_PASSWORD_MUST_CHANGE ((NTSTATUS)0xC0000224) +#define STATUS_NOT_FOUND ((NTSTATUS)0xC0000225) +#define STATUS_NOT_TINY_STREAM ((NTSTATUS)0xC0000226) +#define STATUS_RECOVERY_FAILURE ((NTSTATUS)0xC0000227) +#define STATUS_STACK_OVERFLOW_READ ((NTSTATUS)0xC0000228) +#define STATUS_FAIL_CHECK ((NTSTATUS)0xC0000229) +#define STATUS_DUPLICATE_OBJECTID ((NTSTATUS)0xC000022A) +#define STATUS_OBJECTID_EXISTS ((NTSTATUS)0xC000022B) +#define STATUS_CONVERT_TO_LARGE ((NTSTATUS)0xC000022C) +#define STATUS_RETRY ((NTSTATUS)0xC000022D) +#define STATUS_FOUND_OUT_OF_SCOPE ((NTSTATUS)0xC000022E) +#define STATUS_ALLOCATE_BUCKET ((NTSTATUS)0xC000022F) +#define STATUS_PROPSET_NOT_FOUND ((NTSTATUS)0xC0000230) +#define STATUS_MARSHALL_OVERFLOW ((NTSTATUS)0xC0000231) +#define STATUS_INVALID_VARIANT ((NTSTATUS)0xC0000232) +#define STATUS_DOMAIN_CONTROLLER_NOT_FOUND ((NTSTATUS)0xC0000233) +#define STATUS_ACCOUNT_LOCKED_OUT ((NTSTATUS)0xC0000234) +#define STATUS_HANDLE_NOT_CLOSABLE ((NTSTATUS)0xC0000235) +#define STATUS_CONNECTION_REFUSED ((NTSTATUS)0xC0000236) +#define STATUS_GRACEFUL_DISCONNECT ((NTSTATUS)0xC0000237) +#define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS)0xC0000238) +#define STATUS_ADDRESS_NOT_ASSOCIATED ((NTSTATUS)0xC0000239) +#define STATUS_CONNECTION_INVALID ((NTSTATUS)0xC000023A) +#define STATUS_CONNECTION_ACTIVE ((NTSTATUS)0xC000023B) +#define STATUS_NETWORK_UNREACHABLE ((NTSTATUS)0xC000023C) +#define STATUS_HOST_UNREACHABLE ((NTSTATUS)0xC000023D) +#define STATUS_PROTOCOL_UNREACHABLE ((NTSTATUS)0xC000023E) +#define STATUS_PORT_UNREACHABLE ((NTSTATUS)0xC000023F) +#define STATUS_REQUEST_ABORTED ((NTSTATUS)0xC0000240) +#define STATUS_CONNECTION_ABORTED ((NTSTATUS)0xC0000241) +#define STATUS_BAD_COMPRESSION_BUFFER ((NTSTATUS)0xC0000242) +#define STATUS_USER_MAPPED_FILE ((NTSTATUS)0xC0000243) +#define STATUS_AUDIT_FAILED ((NTSTATUS)0xC0000244) +#define STATUS_TIMER_RESOLUTION_NOT_SET ((NTSTATUS)0xC0000245) +#define STATUS_CONNECTION_COUNT_LIMIT ((NTSTATUS)0xC0000246) +#define STATUS_LOGIN_TIME_RESTRICTION ((NTSTATUS)0xC0000247) +#define STATUS_LOGIN_WKSTA_RESTRICTION ((NTSTATUS)0xC0000248) +#define STATUS_IMAGE_MP_UP_MISMATCH ((NTSTATUS)0xC0000249) +#define STATUS_INSUFFICIENT_LOGON_INFO ((NTSTATUS)0xC0000250) +#define STATUS_BAD_DLL_ENTRYPOINT ((NTSTATUS)0xC0000251) +#define STATUS_BAD_SERVICE_ENTRYPOINT ((NTSTATUS)0xC0000252) +#define STATUS_LPC_REPLY_LOST ((NTSTATUS)0xC0000253) +#define STATUS_IP_ADDRESS_CONFLICT1 ((NTSTATUS)0xC0000254) +#define STATUS_IP_ADDRESS_CONFLICT2 ((NTSTATUS)0xC0000255) +#define STATUS_REGISTRY_QUOTA_LIMIT ((NTSTATUS)0xC0000256) +#define STATUS_PATH_NOT_COVERED ((NTSTATUS)0xC0000257) +#define STATUS_NO_CALLBACK_ACTIVE ((NTSTATUS)0xC0000258) +#define STATUS_LICENSE_QUOTA_EXCEEDED ((NTSTATUS)0xC0000259) +#define STATUS_PWD_TOO_SHORT ((NTSTATUS)0xC000025A) +#define STATUS_PWD_TOO_RECENT ((NTSTATUS)0xC000025B) +#define STATUS_PWD_HISTORY_CONFLICT ((NTSTATUS)0xC000025C) +#define STATUS_PLUGPLAY_NO_DEVICE ((NTSTATUS)0xC000025E) +#define STATUS_UNSUPPORTED_COMPRESSION ((NTSTATUS)0xC000025F) +#define STATUS_INVALID_HW_PROFILE ((NTSTATUS)0xC0000260) +#define STATUS_INVALID_PLUGPLAY_DEVICE_PATH ((NTSTATUS)0xC0000261) +#define STATUS_DRIVER_ORDINAL_NOT_FOUND ((NTSTATUS)0xC0000262) +#define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND ((NTSTATUS)0xC0000263) +#define STATUS_RESOURCE_NOT_OWNED ((NTSTATUS)0xC0000264) +#define STATUS_TOO_MANY_LINKS ((NTSTATUS)0xC0000265) +#define STATUS_QUOTA_LIST_INCONSISTENT ((NTSTATUS)0xC0000266) +#define STATUS_FILE_IS_OFFLINE ((NTSTATUS)0xC0000267) +#define STATUS_EVALUATION_EXPIRATION ((NTSTATUS)0xC0000268) +#define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS)0xC0000269) +#define STATUS_LICENSE_VIOLATION ((NTSTATUS)0xC000026A) +#define STATUS_DLL_INIT_FAILED_LOGOFF ((NTSTATUS)0xC000026B) +#define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS)0xC000026C) +#define STATUS_DFS_UNAVAILABLE ((NTSTATUS)0xC000026D) +#define STATUS_VOLUME_DISMOUNTED ((NTSTATUS)0xC000026E) +#define STATUS_WX86_INTERNAL_ERROR ((NTSTATUS)0xC000026F) +#define STATUS_WX86_FLOAT_STACK_CHECK ((NTSTATUS)0xC0000270) +#define STATUS_VALIDATE_CONTINUE ((NTSTATUS)0xC0000271) +#define STATUS_NO_MATCH ((NTSTATUS)0xC0000272) +#define STATUS_NO_MORE_MATCHES ((NTSTATUS)0xC0000273) +#define STATUS_NOT_A_REPARSE_POINT ((NTSTATUS)0xC0000275) +#define STATUS_IO_REPARSE_TAG_INVALID ((NTSTATUS)0xC0000276) +#define STATUS_IO_REPARSE_TAG_MISMATCH ((NTSTATUS)0xC0000277) +#define STATUS_IO_REPARSE_DATA_INVALID ((NTSTATUS)0xC0000278) +#define STATUS_IO_REPARSE_TAG_NOT_HANDLED ((NTSTATUS)0xC0000279) +#define STATUS_REPARSE_POINT_NOT_RESOLVED ((NTSTATUS)0xC0000280) +#define STATUS_DIRECTORY_IS_A_REPARSE_POINT ((NTSTATUS)0xC0000281) +#define STATUS_RANGE_LIST_CONFLICT ((NTSTATUS)0xC0000282) +#define STATUS_SOURCE_ELEMENT_EMPTY ((NTSTATUS)0xC0000283) +#define STATUS_DESTINATION_ELEMENT_FULL ((NTSTATUS)0xC0000284) +#define STATUS_ILLEGAL_ELEMENT_ADDRESS ((NTSTATUS)0xC0000285) +#define STATUS_MAGAZINE_NOT_PRESENT ((NTSTATUS)0xC0000286) +#define STATUS_REINITIALIZATION_NEEDED ((NTSTATUS)0xC0000287) +#define STATUS_ENCRYPTION_FAILED ((NTSTATUS)0xC000028A) +#define STATUS_DECRYPTION_FAILED ((NTSTATUS)0xC000028B) +#define STATUS_RANGE_NOT_FOUND ((NTSTATUS)0xC000028C) +#define STATUS_NO_RECOVERY_POLICY ((NTSTATUS)0xC000028D) +#define STATUS_NO_EFS ((NTSTATUS)0xC000028E) +#define STATUS_WRONG_EFS ((NTSTATUS)0xC000028F) +#define STATUS_NO_USER_KEYS ((NTSTATUS)0xC0000290) +#define STATUS_FILE_NOT_ENCRYPTED ((NTSTATUS)0xC0000291) +#define STATUS_NOT_EXPORT_FORMAT ((NTSTATUS)0xC0000292) +#define STATUS_FILE_ENCRYPTED ((NTSTATUS)0xC0000293) +#define STATUS_WMI_GUID_NOT_FOUND ((NTSTATUS)0xC0000295) +#define STATUS_WMI_INSTANCE_NOT_FOUND ((NTSTATUS)0xC0000296) +#define STATUS_WMI_ITEMID_NOT_FOUND ((NTSTATUS)0xC0000297) +#define STATUS_WMI_TRY_AGAIN ((NTSTATUS)0xC0000298) +#define STATUS_SHARED_POLICY ((NTSTATUS)0xC0000299) +#define STATUS_POLICY_OBJECT_NOT_FOUND ((NTSTATUS)0xC000029A) +#define STATUS_POLICY_ONLY_IN_DS ((NTSTATUS)0xC000029B) +#define STATUS_VOLUME_NOT_UPGRADED ((NTSTATUS)0xC000029C) +#define STATUS_REMOTE_STORAGE_NOT_ACTIVE ((NTSTATUS)0xC000029D) +#define STATUS_REMOTE_STORAGE_MEDIA_ERROR ((NTSTATUS)0xC000029E) +#define STATUS_NO_TRACKING_SERVICE ((NTSTATUS)0xC000029F) +#define STATUS_SERVER_SID_MISMATCH ((NTSTATUS)0xC00002A0) +#define STATUS_DS_NO_ATTRIBUTE_OR_VALUE ((NTSTATUS)0xC00002A1) +#define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX ((NTSTATUS)0xC00002A2) +#define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED ((NTSTATUS)0xC00002A3) +#define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS ((NTSTATUS)0xC00002A4) +#define STATUS_DS_BUSY ((NTSTATUS)0xC00002A5) +#define STATUS_DS_UNAVAILABLE ((NTSTATUS)0xC00002A6) +#define STATUS_DS_NO_RIDS_ALLOCATED ((NTSTATUS)0xC00002A7) +#define STATUS_DS_NO_MORE_RIDS ((NTSTATUS)0xC00002A8) +#define STATUS_DS_INCORRECT_ROLE_OWNER ((NTSTATUS)0xC00002A9) +#define STATUS_DS_RIDMGR_INIT_ERROR ((NTSTATUS)0xC00002AA) +#define STATUS_DS_OBJ_CLASS_VIOLATION ((NTSTATUS)0xC00002AB) +#define STATUS_DS_CANT_ON_NON_LEAF ((NTSTATUS)0xC00002AC) +#define STATUS_DS_CANT_ON_RDN ((NTSTATUS)0xC00002AD) +#define STATUS_DS_CANT_MOD_OBJ_CLASS ((NTSTATUS)0xC00002AE) +#define STATUS_DS_CROSS_DOM_MOVE_FAILED ((NTSTATUS)0xC00002AF) +#define STATUS_DS_GC_NOT_AVAILABLE ((NTSTATUS)0xC00002B0) +#define STATUS_DIRECTORY_SERVICE_REQUIRED ((NTSTATUS)0xC00002B1) +#define STATUS_REPARSE_ATTRIBUTE_CONFLICT ((NTSTATUS)0xC00002B2) +#define STATUS_CANT_ENABLE_DENY_ONLY ((NTSTATUS)0xC00002B3) +#define STATUS_FLOAT_MULTIPLE_FAULTS ((NTSTATUS)0xC00002B4) +#define STATUS_FLOAT_MULTIPLE_TRAPS ((NTSTATUS)0xC00002B5) +#define STATUS_DEVICE_REMOVED ((NTSTATUS)0xC00002B6) +#define STATUS_JOURNAL_DELETE_IN_PROGRESS ((NTSTATUS)0xC00002B7) +#define STATUS_JOURNAL_NOT_ACTIVE ((NTSTATUS)0xC00002B8) +#define STATUS_NOINTERFACE ((NTSTATUS)0xC00002B9) +#define STATUS_DS_ADMIN_LIMIT_EXCEEDED ((NTSTATUS)0xC00002C1) +#define STATUS_DRIVER_FAILED_SLEEP ((NTSTATUS)0xC00002C2) +#define STATUS_MUTUAL_AUTHENTICATION_FAILED ((NTSTATUS)0xC00002C3) +#define STATUS_CORRUPT_SYSTEM_FILE ((NTSTATUS)0xC00002C4) +#define STATUS_DATATYPE_MISALIGNMENT_ERROR ((NTSTATUS)0xC00002C5) +#define STATUS_WMI_READ_ONLY ((NTSTATUS)0xC00002C6) +#define STATUS_WMI_SET_FAILURE ((NTSTATUS)0xC00002C7) +#define STATUS_COMMITMENT_MINIMUM ((NTSTATUS)0xC00002C8) +#define STATUS_REG_NAT_CONSUMPTION ((NTSTATUS)0xC00002C9) +#define STATUS_TRANSPORT_FULL ((NTSTATUS)0xC00002CA) +#define STATUS_DS_SAM_INIT_FAILURE ((NTSTATUS)0xC00002CB) +#define STATUS_ONLY_IF_CONNECTED ((NTSTATUS)0xC00002CC) +#define STATUS_DS_SENSITIVE_GROUP_VIOLATION ((NTSTATUS)0xC00002CD) +#define STATUS_PNP_RESTART_ENUMERATION ((NTSTATUS)0xC00002CE) +#define STATUS_JOURNAL_ENTRY_DELETED ((NTSTATUS)0xC00002CF) +#define STATUS_DS_CANT_MOD_PRIMARYGROUPID ((NTSTATUS)0xC00002D0) +#define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE ((NTSTATUS)0xC00002D1) +#define STATUS_PNP_REBOOT_REQUIRED ((NTSTATUS)0xC00002D2) +#define STATUS_POWER_STATE_INVALID ((NTSTATUS)0xC00002D3) +#define STATUS_DS_INVALID_GROUP_TYPE ((NTSTATUS)0xC00002D4) +#define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN ((NTSTATUS)0xC00002D5) +#define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN ((NTSTATUS)0xC00002D6) +#define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS)0xC00002D7) +#define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS)0xC00002D8) +#define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS)0xC00002D9) +#define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER ((NTSTATUS)0xC00002DA) +#define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER ((NTSTATUS)0xC00002DB) +#define STATUS_DS_HAVE_PRIMARY_MEMBERS ((NTSTATUS)0xC00002DC) +#define STATUS_WMI_NOT_SUPPORTED ((NTSTATUS)0xC00002DD) +#define STATUS_INSUFFICIENT_POWER ((NTSTATUS)0xC00002DE) +#define STATUS_SAM_NEED_BOOTKEY_PASSWORD ((NTSTATUS)0xC00002DF) +#define STATUS_SAM_NEED_BOOTKEY_FLOPPY ((NTSTATUS)0xC00002E0) +#define STATUS_DS_CANT_START ((NTSTATUS)0xC00002E1) +#define STATUS_DS_INIT_FAILURE ((NTSTATUS)0xC00002E2) +#define STATUS_SAM_INIT_FAILURE ((NTSTATUS)0xC00002E3) +#define STATUS_DS_GC_REQUIRED ((NTSTATUS)0xC00002E4) +#define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY ((NTSTATUS)0xC00002E5) +#define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS ((NTSTATUS)0xC00002E6) +#define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED ((NTSTATUS)0xC00002E7) +#define STATUS_MULTIPLE_FAULT_VIOLATION ((NTSTATUS)0xC00002E8) +#define STATUS_CURRENT_DOMAIN_NOT_ALLOWED ((NTSTATUS)0xC00002E9) +#define STATUS_CANNOT_MAKE ((NTSTATUS)0xC00002EA) +#define STATUS_SYSTEM_SHUTDOWN ((NTSTATUS)0xC00002EB) +#define STATUS_DS_INIT_FAILURE_CONSOLE ((NTSTATUS)0xC00002EC) +#define STATUS_DS_SAM_INIT_FAILURE_CONSOLE ((NTSTATUS)0xC00002ED) +#define STATUS_UNFINISHED_CONTEXT_DELETED ((NTSTATUS)0xC00002EE) +#define STATUS_NO_TGT_REPLY ((NTSTATUS)0xC00002EF) +#define STATUS_OBJECTID_NOT_FOUND ((NTSTATUS)0xC00002F0) +#define STATUS_NO_IP_ADDRESSES ((NTSTATUS)0xC00002F1) +#define STATUS_WRONG_CREDENTIAL_HANDLE ((NTSTATUS)0xC00002F2) +#define STATUS_CRYPTO_SYSTEM_INVALID ((NTSTATUS)0xC00002F3) +#define STATUS_MAX_REFERRALS_EXCEEDED ((NTSTATUS)0xC00002F4) +#define STATUS_MUST_BE_KDC ((NTSTATUS)0xC00002F5) +#define STATUS_STRONG_CRYPTO_NOT_SUPPORTED ((NTSTATUS)0xC00002F6) +#define STATUS_TOO_MANY_PRINCIPALS ((NTSTATUS)0xC00002F7) +#define STATUS_NO_PA_DATA ((NTSTATUS)0xC00002F8) +#define STATUS_PKINIT_NAME_MISMATCH ((NTSTATUS)0xC00002F9) +#define STATUS_SMARTCARD_LOGON_REQUIRED ((NTSTATUS)0xC00002FA) +#define STATUS_KDC_INVALID_REQUEST ((NTSTATUS)0xC00002FB) +#define STATUS_KDC_UNABLE_TO_REFER ((NTSTATUS)0xC00002FC) +#define STATUS_KDC_UNKNOWN_ETYPE ((NTSTATUS)0xC00002FD) +#define STATUS_SHUTDOWN_IN_PROGRESS ((NTSTATUS)0xC00002FE) +#define STATUS_SERVER_SHUTDOWN_IN_PROGRESS ((NTSTATUS)0xC00002FF) +#define STATUS_NOT_SUPPORTED_ON_SBS ((NTSTATUS)0xC0000300) +#define STATUS_WMI_GUID_DISCONNECTED ((NTSTATUS)0xC0000301) +#define STATUS_WMI_ALREADY_DISABLED ((NTSTATUS)0xC0000302) +#define STATUS_WMI_ALREADY_ENABLED ((NTSTATUS)0xC0000303) +#define STATUS_MFT_TOO_FRAGMENTED ((NTSTATUS)0xC0000304) +#define STATUS_COPY_PROTECTION_FAILURE ((NTSTATUS)0xC0000305) +#define STATUS_CSS_AUTHENTICATION_FAILURE ((NTSTATUS)0xC0000306) +#define STATUS_CSS_KEY_NOT_PRESENT ((NTSTATUS)0xC0000307) +#define STATUS_CSS_KEY_NOT_ESTABLISHED ((NTSTATUS)0xC0000308) +#define STATUS_CSS_SCRAMBLED_SECTOR ((NTSTATUS)0xC0000309) +#define STATUS_CSS_REGION_MISMATCH ((NTSTATUS)0xC000030A) +#define STATUS_CSS_RESETS_EXHAUSTED ((NTSTATUS)0xC000030B) +#define STATUS_PKINIT_FAILURE ((NTSTATUS)0xC0000320) +#define STATUS_SMARTCARD_SUBSYSTEM_FAILURE ((NTSTATUS)0xC0000321) +#define STATUS_NO_KERB_KEY ((NTSTATUS)0xC0000322) +#define STATUS_HOST_DOWN ((NTSTATUS)0xC0000350) +#define STATUS_UNSUPPORTED_PREAUTH ((NTSTATUS)0xC0000351) +#define STATUS_EFS_ALG_BLOB_TOO_BIG ((NTSTATUS)0xC0000352) +#define STATUS_PORT_NOT_SET ((NTSTATUS)0xC0000353) +#define STATUS_DEBUGGER_INACTIVE ((NTSTATUS)0xC0000354) +#define STATUS_DS_VERSION_CHECK_FAILURE ((NTSTATUS)0xC0000355) +#define STATUS_AUDITING_DISABLED ((NTSTATUS)0xC0000356) +#define STATUS_PRENT4_MACHINE_ACCOUNT ((NTSTATUS)0xC0000357) +#define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS)0xC0000358) +#define STATUS_INVALID_IMAGE_WIN_32 ((NTSTATUS)0xC0000359) +#define STATUS_INVALID_IMAGE_WIN_64 ((NTSTATUS)0xC000035A) +#define STATUS_BAD_BINDINGS ((NTSTATUS)0xC000035B) +#define STATUS_NETWORK_SESSION_EXPIRED ((NTSTATUS)0xC000035C) +#define STATUS_APPHELP_BLOCK ((NTSTATUS)0xC000035D) +#define STATUS_ALL_SIDS_FILTERED ((NTSTATUS)0xC000035E) +#define STATUS_NOT_SAFE_MODE_DRIVER ((NTSTATUS)0xC000035F) +#define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT ((NTSTATUS)0xC0000361) +#define STATUS_ACCESS_DISABLED_BY_POLICY_PATH ((NTSTATUS)0xC0000362) +#define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER ((NTSTATUS)0xC0000363) +#define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ((NTSTATUS)0xC0000364) +#define STATUS_FAILED_DRIVER_ENTRY ((NTSTATUS)0xC0000365) +#define STATUS_DEVICE_ENUMERATION_ERROR ((NTSTATUS)0xC0000366) +#define STATUS_WAIT_FOR_OPLOCK ((NTSTATUS)0x00000367) +#define STATUS_MOUNT_POINT_NOT_RESOLVED ((NTSTATUS)0xC0000368) +#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER ((NTSTATUS)0xC0000369) +#define STATUS_MCA_OCCURED ((NTSTATUS)0xC000036A) +#define STATUS_DRIVER_BLOCKED_CRITICAL ((NTSTATUS)0xC000036B) +#define STATUS_DRIVER_BLOCKED ((NTSTATUS)0xC000036C) +#define STATUS_DRIVER_DATABASE_ERROR ((NTSTATUS)0xC000036D) +#define STATUS_SYSTEM_HIVE_TOO_LARGE ((NTSTATUS)0xC000036E) +#define STATUS_INVALID_IMPORT_OF_NON_DLL ((NTSTATUS)0xC000036F) +#define STATUS_SMARTCARD_WRONG_PIN ((NTSTATUS)0xC0000380) +#define STATUS_SMARTCARD_CARD_BLOCKED ((NTSTATUS)0xC0000381) +#define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED ((NTSTATUS)0xC0000382) +#define STATUS_SMARTCARD_NO_CARD ((NTSTATUS)0xC0000383) +#define STATUS_SMARTCARD_NO_KEY_CONTAINER ((NTSTATUS)0xC0000384) +#define STATUS_SMARTCARD_NO_CERTIFICATE ((NTSTATUS)0xC0000385) +#define STATUS_SMARTCARD_NO_KEYSET ((NTSTATUS)0xC0000386) +#define STATUS_SMARTCARD_IO_ERROR ((NTSTATUS)0xC0000387) +#define STATUS_DOWNGRADE_DETECTED ((NTSTATUS)0xC0000388) +#define STATUS_SMARTCARD_CERT_REVOKED ((NTSTATUS)0xC0000389) +#define STATUS_ISSUING_CA_UNTRUSTED ((NTSTATUS)0xC000038A) +#define STATUS_REVOCATION_OFFLINE_C ((NTSTATUS)0xC000038B) +#define STATUS_PKINIT_CLIENT_FAILURE ((NTSTATUS)0xC000038C) +#define STATUS_SMARTCARD_CERT_EXPIRED ((NTSTATUS)0xC000038D) +#define STATUS_DRIVER_FAILED_PRIOR_UNLOAD ((NTSTATUS)0xC000038E) +#define STATUS_SMARTCARD_SILENT_CONTEXT ((NTSTATUS)0xC000038F) +#define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS)0xC0000401) +#define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS)0xC0000402) +#define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED ((NTSTATUS)0xC0000403) +#define STATUS_DS_NAME_NOT_UNIQUE ((NTSTATUS)0xC0000404) +#define STATUS_DS_DUPLICATE_ID_FOUND ((NTSTATUS)0xC0000405) +#define STATUS_DS_GROUP_CONVERSION_ERROR ((NTSTATUS)0xC0000406) +#define STATUS_VOLSNAP_PREPARE_HIBERNATE ((NTSTATUS)0xC0000407) +#define STATUS_USER2USER_REQUIRED ((NTSTATUS)0xC0000408) +#define STATUS_STACK_BUFFER_OVERRUN ((NTSTATUS)0xC0000409) +#define STATUS_NO_S4U_PROT_SUPPORT ((NTSTATUS)0xC000040A) +#define STATUS_CROSSREALM_DELEGATION_FAILURE ((NTSTATUS)0xC000040B) +#define STATUS_REVOCATION_OFFLINE_KDC ((NTSTATUS)0xC000040C) +#define STATUS_ISSUING_CA_UNTRUSTED_KDC ((NTSTATUS)0xC000040D) +#define STATUS_KDC_CERT_EXPIRED ((NTSTATUS)0xC000040E) +#define STATUS_KDC_CERT_REVOKED ((NTSTATUS)0xC000040F) +#define STATUS_PARAMETER_QUOTA_EXCEEDED ((NTSTATUS)0xC0000410) +#define STATUS_HIBERNATION_FAILURE ((NTSTATUS)0xC0000411) +#define STATUS_DELAY_LOAD_FAILED ((NTSTATUS)0xC0000412) +#define STATUS_AUTHENTICATION_FIREWALL_FAILED ((NTSTATUS)0xC0000413) +#define STATUS_VDM_DISALLOWED ((NTSTATUS)0xC0000414) +#define STATUS_HUNG_DISPLAY_DRIVER_THREAD ((NTSTATUS)0xC0000415) +#define STATUS_INVALID_CRUNTIME_PARAMETER ((NTSTATUS)0xC0000417) +#define STATUS_ASSERTION_FAILURE ((NTSTATUS)0xC0000420L) +#define STATUS_CALLBACK_POP_STACK ((NTSTATUS)0xC0000423) +#define STATUS_WOW_ASSERTION ((NTSTATUS)0xC0009898) + +#define RPC_NT_INVALID_STRING_BINDING ((NTSTATUS)0xC0020001) +#define RPC_NT_WRONG_KIND_OF_BINDING ((NTSTATUS)0xC0020002) +#define RPC_NT_INVALID_BINDING ((NTSTATUS)0xC0020003) +#define RPC_NT_PROTSEQ_NOT_SUPPORTED ((NTSTATUS)0xC0020004) +#define RPC_NT_INVALID_RPC_PROTSEQ ((NTSTATUS)0xC0020005) +#define RPC_NT_INVALID_STRING_UUID ((NTSTATUS)0xC0020006) +#define RPC_NT_INVALID_ENDPOINT_FORMAT ((NTSTATUS)0xC0020007) +#define RPC_NT_INVALID_NET_ADDR ((NTSTATUS)0xC0020008) +#define RPC_NT_NO_ENDPOINT_FOUND ((NTSTATUS)0xC0020009) +#define RPC_NT_INVALID_TIMEOUT ((NTSTATUS)0xC002000A) +#define RPC_NT_OBJECT_NOT_FOUND ((NTSTATUS)0xC002000B) +#define RPC_NT_ALREADY_REGISTERED ((NTSTATUS)0xC002000C) +#define RPC_NT_TYPE_ALREADY_REGISTERED ((NTSTATUS)0xC002000D) +#define RPC_NT_ALREADY_LISTENING ((NTSTATUS)0xC002000E) +#define RPC_NT_NO_PROTSEQS_REGISTERED ((NTSTATUS)0xC002000F) +#define RPC_NT_NOT_LISTENING ((NTSTATUS)0xC0020010) +#define RPC_NT_UNKNOWN_MGR_TYPE ((NTSTATUS)0xC0020011) +#define RPC_NT_UNKNOWN_IF ((NTSTATUS)0xC0020012) +#define RPC_NT_NO_BINDINGS ((NTSTATUS)0xC0020013) +#define RPC_NT_NO_PROTSEQS ((NTSTATUS)0xC0020014) +#define RPC_NT_CANT_CREATE_ENDPOINT ((NTSTATUS)0xC0020015) +#define RPC_NT_OUT_OF_RESOURCES ((NTSTATUS)0xC0020016) +#define RPC_NT_SERVER_UNAVAILABLE ((NTSTATUS)0xC0020017) +#define RPC_NT_SERVER_TOO_BUSY ((NTSTATUS)0xC0020018) +#define RPC_NT_INVALID_NETWORK_OPTIONS ((NTSTATUS)0xC0020019) +#define RPC_NT_NO_CALL_ACTIVE ((NTSTATUS)0xC002001A) +#define RPC_NT_CALL_FAILED ((NTSTATUS)0xC002001B) +#define RPC_NT_CALL_FAILED_DNE ((NTSTATUS)0xC002001C) +#define RPC_NT_PROTOCOL_ERROR ((NTSTATUS)0xC002001D) +#define RPC_NT_UNSUPPORTED_TRANS_SYN ((NTSTATUS)0xC002001F) +#define RPC_NT_UNSUPPORTED_TYPE ((NTSTATUS)0xC0020021) +#define RPC_NT_INVALID_TAG ((NTSTATUS)0xC0020022) +#define RPC_NT_INVALID_BOUND ((NTSTATUS)0xC0020023) +#define RPC_NT_NO_ENTRY_NAME ((NTSTATUS)0xC0020024) +#define RPC_NT_INVALID_NAME_SYNTAX ((NTSTATUS)0xC0020025) +#define RPC_NT_UNSUPPORTED_NAME_SYNTAX ((NTSTATUS)0xC0020026) +#define RPC_NT_UUID_NO_ADDRESS ((NTSTATUS)0xC0020028) +#define RPC_NT_DUPLICATE_ENDPOINT ((NTSTATUS)0xC0020029) +#define RPC_NT_UNKNOWN_AUTHN_TYPE ((NTSTATUS)0xC002002A) +#define RPC_NT_MAX_CALLS_TOO_SMALL ((NTSTATUS)0xC002002B) +#define RPC_NT_STRING_TOO_LONG ((NTSTATUS)0xC002002C) +#define RPC_NT_PROTSEQ_NOT_FOUND ((NTSTATUS)0xC002002D) +#define RPC_NT_PROCNUM_OUT_OF_RANGE ((NTSTATUS)0xC002002E) +#define RPC_NT_BINDING_HAS_NO_AUTH ((NTSTATUS)0xC002002F) +#define RPC_NT_UNKNOWN_AUTHN_SERVICE ((NTSTATUS)0xC0020030) +#define RPC_NT_UNKNOWN_AUTHN_LEVEL ((NTSTATUS)0xC0020031) +#define RPC_NT_INVALID_AUTH_IDENTITY ((NTSTATUS)0xC0020032) +#define RPC_NT_UNKNOWN_AUTHZ_SERVICE ((NTSTATUS)0xC0020033) +#define EPT_NT_INVALID_ENTRY ((NTSTATUS)0xC0020034) +#define EPT_NT_CANT_PERFORM_OP ((NTSTATUS)0xC0020035) +#define EPT_NT_NOT_REGISTERED ((NTSTATUS)0xC0020036) +#define RPC_NT_NOTHING_TO_EXPORT ((NTSTATUS)0xC0020037) +#define RPC_NT_INCOMPLETE_NAME ((NTSTATUS)0xC0020038) +#define RPC_NT_INVALID_VERS_OPTION ((NTSTATUS)0xC0020039) +#define RPC_NT_NO_MORE_MEMBERS ((NTSTATUS)0xC002003A) +#define RPC_NT_NOT_ALL_OBJS_UNEXPORTED ((NTSTATUS)0xC002003B) +#define RPC_NT_INTERFACE_NOT_FOUND ((NTSTATUS)0xC002003C) +#define RPC_NT_ENTRY_ALREADY_EXISTS ((NTSTATUS)0xC002003D) +#define RPC_NT_ENTRY_NOT_FOUND ((NTSTATUS)0xC002003E) +#define RPC_NT_NAME_SERVICE_UNAVAILABLE ((NTSTATUS)0xC002003F) +#define RPC_NT_INVALID_NAF_ID ((NTSTATUS)0xC0020040) +#define RPC_NT_CANNOT_SUPPORT ((NTSTATUS)0xC0020041) +#define RPC_NT_NO_CONTEXT_AVAILABLE ((NTSTATUS)0xC0020042) +#define RPC_NT_INTERNAL_ERROR ((NTSTATUS)0xC0020043) +#define RPC_NT_ZERO_DIVIDE ((NTSTATUS)0xC0020044) +#define RPC_NT_ADDRESS_ERROR ((NTSTATUS)0xC0020045) +#define RPC_NT_FP_DIV_ZERO ((NTSTATUS)0xC0020046) +#define RPC_NT_FP_UNDERFLOW ((NTSTATUS)0xC0020047) +#define RPC_NT_FP_OVERFLOW ((NTSTATUS)0xC0020048) +#define RPC_NT_CALL_IN_PROGRESS ((NTSTATUS)0xC0020049) +#define RPC_NT_NO_MORE_BINDINGS ((NTSTATUS)0xC002004A) +#define RPC_NT_GROUP_MEMBER_NOT_FOUND ((NTSTATUS)0xC002004B) +#define EPT_NT_CANT_CREATE ((NTSTATUS)0xC002004C) +#define RPC_NT_INVALID_OBJECT ((NTSTATUS)0xC002004D) +#define RPC_NT_NO_INTERFACES ((NTSTATUS)0xC002004F) +#define RPC_NT_CALL_CANCELLED ((NTSTATUS)0xC0020050) +#define RPC_NT_BINDING_INCOMPLETE ((NTSTATUS)0xC0020051) +#define RPC_NT_COMM_FAILURE ((NTSTATUS)0xC0020052) +#define RPC_NT_UNSUPPORTED_AUTHN_LEVEL ((NTSTATUS)0xC0020053) +#define RPC_NT_NO_PRINC_NAME ((NTSTATUS)0xC0020054) +#define RPC_NT_NOT_RPC_ERROR ((NTSTATUS)0xC0020055) +#define RPC_NT_SEC_PKG_ERROR ((NTSTATUS)0xC0020057) +#define RPC_NT_NOT_CANCELLED ((NTSTATUS)0xC0020058) +#define RPC_NT_INVALID_ASYNC_HANDLE ((NTSTATUS)0xC0020062) +#define RPC_NT_INVALID_ASYNC_CALL ((NTSTATUS)0xC0020063) + +#define RPC_NT_NO_MORE_ENTRIES ((NTSTATUS)0xC0030001) +#define RPC_NT_SS_CHAR_TRANS_OPEN_FAIL ((NTSTATUS)0xC0030002) +#define RPC_NT_SS_CHAR_TRANS_SHORT_FILE ((NTSTATUS)0xC0030003) +#define RPC_NT_SS_IN_NULL_CONTEXT ((NTSTATUS)0xC0030004) +#define RPC_NT_SS_CONTEXT_MISMATCH ((NTSTATUS)0xC0030005) +#define RPC_NT_SS_CONTEXT_DAMAGED ((NTSTATUS)0xC0030006) +#define RPC_NT_SS_HANDLES_MISMATCH ((NTSTATUS)0xC0030007) +#define RPC_NT_SS_CANNOT_GET_CALL_HANDLE ((NTSTATUS)0xC0030008) +#define RPC_NT_NULL_REF_POINTER ((NTSTATUS)0xC0030009) +#define RPC_NT_ENUM_VALUE_OUT_OF_RANGE ((NTSTATUS)0xC003000A) +#define RPC_NT_BYTE_COUNT_TOO_SMALL ((NTSTATUS)0xC003000B) +#define RPC_NT_BAD_STUB_DATA ((NTSTATUS)0xC003000C) +#define RPC_NT_INVALID_ES_ACTION ((NTSTATUS)0xC0030059) +#define RPC_NT_WRONG_ES_VERSION ((NTSTATUS)0xC003005A) +#define RPC_NT_WRONG_STUB_VERSION ((NTSTATUS)0xC003005B) +#define RPC_NT_INVALID_PIPE_OBJECT ((NTSTATUS)0xC003005C) +#define RPC_NT_INVALID_PIPE_OPERATION ((NTSTATUS)0xC003005D) +#define RPC_NT_WRONG_PIPE_VERSION ((NTSTATUS)0xC003005E) +#define RPC_NT_PIPE_CLOSED ((NTSTATUS)0xC003005F) +#define RPC_NT_PIPE_DISCIPLINE_ERROR ((NTSTATUS)0xC0030060) +#define RPC_NT_PIPE_EMPTY ((NTSTATUS)0xC0030061) + +#define STATUS_PNP_BAD_MPS_TABLE ((NTSTATUS)0xC0040035) +#define STATUS_PNP_TRANSLATION_FAILED ((NTSTATUS)0xC0040036) +#define STATUS_PNP_IRQ_TRANSLATION_FAILED ((NTSTATUS)0xC0040037) +#define STATUS_PNP_INVALID_ID ((NTSTATUS)0xC0040038) + +#define STATUS_ACPI_INVALID_OPCODE ((NTSTATUS)0xC0140001L) +#define STATUS_ACPI_STACK_OVERFLOW ((NTSTATUS)0xC0140002L) +#define STATUS_ACPI_ASSERT_FAILED ((NTSTATUS)0xC0140003L) +#define STATUS_ACPI_INVALID_INDEX ((NTSTATUS)0xC0140004L) +#define STATUS_ACPI_INVALID_ARGUMENT ((NTSTATUS)0xC0140005L) +#define STATUS_ACPI_FATAL ((NTSTATUS)0xC0140006L) +#define STATUS_ACPI_INVALID_SUPERNAME ((NTSTATUS)0xC0140007L) +#define STATUS_ACPI_INVALID_ARGTYPE ((NTSTATUS)0xC0140008L) +#define STATUS_ACPI_INVALID_OBJTYPE ((NTSTATUS)0xC0140009L) +#define STATUS_ACPI_INVALID_TARGETTYPE ((NTSTATUS)0xC014000AL) +#define STATUS_ACPI_INCORRECT_ARGUMENT_COUNT ((NTSTATUS)0xC014000BL) +#define STATUS_ACPI_ADDRESS_NOT_MAPPED ((NTSTATUS)0xC014000CL) +#define STATUS_ACPI_INVALID_EVENTTYPE ((NTSTATUS)0xC014000DL) +#define STATUS_ACPI_HANDLER_COLLISION ((NTSTATUS)0xC014000EL) +#define STATUS_ACPI_INVALID_DATA ((NTSTATUS)0xC014000FL) +#define STATUS_ACPI_INVALID_REGION ((NTSTATUS)0xC0140010L) +#define STATUS_ACPI_INVALID_ACCESS_SIZE ((NTSTATUS)0xC0140011L) +#define STATUS_ACPI_ACQUIRE_GLOBAL_LOCK ((NTSTATUS)0xC0140012L) +#define STATUS_ACPI_ALREADY_INITIALIZED ((NTSTATUS)0xC0140013L) +#define STATUS_ACPI_NOT_INITIALIZED ((NTSTATUS)0xC0140014L) +#define STATUS_ACPI_INVALID_MUTEX_LEVEL ((NTSTATUS)0xC0140015L) +#define STATUS_ACPI_MUTEX_NOT_OWNED ((NTSTATUS)0xC0140016L) +#define STATUS_ACPI_MUTEX_NOT_OWNER ((NTSTATUS)0xC0140017L) +#define STATUS_ACPI_RS_ACCESS ((NTSTATUS)0xC0140018L) +#define STATUS_ACPI_INVALID_TABLE ((NTSTATUS)0xC0140019L) +#define STATUS_ACPI_REG_HANDLER_FAILED ((NTSTATUS)0xC0140020L) +#define STATUS_ACPI_POWER_REQUEST_FAILED ((NTSTATUS)0xC0140021L) + +#define STATUS_CTX_WINSTATION_NAME_INVALID ((NTSTATUS)0xC00A0001) +#define STATUS_CTX_INVALID_PD ((NTSTATUS)0xC00A0002) +#define STATUS_CTX_PD_NOT_FOUND ((NTSTATUS)0xC00A0003) +#define STATUS_CTX_CLOSE_PENDING ((NTSTATUS)0xC00A0006) +#define STATUS_CTX_NO_OUTBUF ((NTSTATUS)0xC00A0007) +#define STATUS_CTX_MODEM_INF_NOT_FOUND ((NTSTATUS)0xC00A0008) +#define STATUS_CTX_INVALID_MODEMNAME ((NTSTATUS)0xC00A0009) +#define STATUS_CTX_RESPONSE_ERROR ((NTSTATUS)0xC00A000A) +#define STATUS_CTX_MODEM_RESPONSE_TIMEOUT ((NTSTATUS)0xC00A000B) +#define STATUS_CTX_MODEM_RESPONSE_NO_CARRIER ((NTSTATUS)0xC00A000C) +#define STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE ((NTSTATUS)0xC00A000D) +#define STATUS_CTX_MODEM_RESPONSE_BUSY ((NTSTATUS)0xC00A000E) +#define STATUS_CTX_MODEM_RESPONSE_VOICE ((NTSTATUS)0xC00A000F) +#define STATUS_CTX_TD_ERROR ((NTSTATUS)0xC00A0010) +#define STATUS_CTX_LICENSE_CLIENT_INVALID ((NTSTATUS)0xC00A0012) +#define STATUS_CTX_LICENSE_NOT_AVAILABLE ((NTSTATUS)0xC00A0013) +#define STATUS_CTX_LICENSE_EXPIRED ((NTSTATUS)0xC00A0014) +#define STATUS_CTX_WINSTATION_NOT_FOUND ((NTSTATUS)0xC00A0015) +#define STATUS_CTX_WINSTATION_NAME_COLLISION ((NTSTATUS)0xC00A0016) +#define STATUS_CTX_WINSTATION_BUSY ((NTSTATUS)0xC00A0017) +#define STATUS_CTX_BAD_VIDEO_MODE ((NTSTATUS)0xC00A0018) +#define STATUS_CTX_GRAPHICS_INVALID ((NTSTATUS)0xC00A0022) +#define STATUS_CTX_NOT_CONSOLE ((NTSTATUS)0xC00A0024) +#define STATUS_CTX_CLIENT_QUERY_TIMEOUT ((NTSTATUS)0xC00A0026) +#define STATUS_CTX_CONSOLE_DISCONNECT ((NTSTATUS)0xC00A0027) +#define STATUS_CTX_CONSOLE_CONNECT ((NTSTATUS)0xC00A0028) +#define STATUS_CTX_SHADOW_DENIED ((NTSTATUS)0xC00A002A) +#define STATUS_CTX_WINSTATION_ACCESS_DENIED ((NTSTATUS)0xC00A002B) +#define STATUS_CTX_INVALID_WD ((NTSTATUS)0xC00A002E) +#define STATUS_CTX_WD_NOT_FOUND ((NTSTATUS)0xC00A002F) +#define STATUS_CTX_SHADOW_INVALID ((NTSTATUS)0xC00A0030) +#define STATUS_CTX_SHADOW_DISABLED ((NTSTATUS)0xC00A0031) +#define STATUS_RDP_PROTOCOL_ERROR ((NTSTATUS)0xC00A0032) +#define STATUS_CTX_CLIENT_LICENSE_NOT_SET ((NTSTATUS)0xC00A0033) +#define STATUS_CTX_CLIENT_LICENSE_IN_USE ((NTSTATUS)0xC00A0034) +#define STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE ((NTSTATUS)0xC00A0035) +#define STATUS_CTX_SHADOW_NOT_RUNNING ((NTSTATUS)0xC00A0036) + +#define STATUS_CLUSTER_INVALID_NODE ((NTSTATUS)0xC0130001) +#define STATUS_CLUSTER_NODE_EXISTS ((NTSTATUS)0xC0130002) +#define STATUS_CLUSTER_JOIN_IN_PROGRESS ((NTSTATUS)0xC0130003) +#define STATUS_CLUSTER_NODE_NOT_FOUND ((NTSTATUS)0xC0130004) +#define STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND ((NTSTATUS)0xC0130005) +#define STATUS_CLUSTER_NETWORK_EXISTS ((NTSTATUS)0xC0130006) +#define STATUS_CLUSTER_NETWORK_NOT_FOUND ((NTSTATUS)0xC0130007) +#define STATUS_CLUSTER_NETINTERFACE_EXISTS ((NTSTATUS)0xC0130008) +#define STATUS_CLUSTER_NETINTERFACE_NOT_FOUND ((NTSTATUS)0xC0130009) +#define STATUS_CLUSTER_INVALID_REQUEST ((NTSTATUS)0xC013000A) +#define STATUS_CLUSTER_INVALID_NETWORK_PROVIDER ((NTSTATUS)0xC013000B) +#define STATUS_CLUSTER_NODE_DOWN ((NTSTATUS)0xC013000C) +#define STATUS_CLUSTER_NODE_UNREACHABLE ((NTSTATUS)0xC013000D) +#define STATUS_CLUSTER_NODE_NOT_MEMBER ((NTSTATUS)0xC013000E) +#define STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS ((NTSTATUS)0xC013000F) +#define STATUS_CLUSTER_INVALID_NETWORK ((NTSTATUS)0xC0130010) +#define STATUS_CLUSTER_NO_NET_ADAPTERS ((NTSTATUS)0xC0130011) +#define STATUS_CLUSTER_NODE_UP ((NTSTATUS)0xC0130012) +#define STATUS_CLUSTER_NODE_PAUSED ((NTSTATUS)0xC0130013) +#define STATUS_CLUSTER_NODE_NOT_PAUSED ((NTSTATUS)0xC0130014) +#define STATUS_CLUSTER_NO_SECURITY_CONTEXT ((NTSTATUS)0xC0130015) +#define STATUS_CLUSTER_NETWORK_NOT_INTERNAL ((NTSTATUS)0xC0130016) +#define STATUS_CLUSTER_POISONED ((NTSTATUS)0xC0130017) + +#define STATUS_SXS_SECTION_NOT_FOUND ((NTSTATUS)0xC0150001) +#define STATUS_SXS_CANT_GEN_ACTCTX ((NTSTATUS)0xC0150002) +#define STATUS_SXS_INVALID_ACTCTXDATA_FORMAT ((NTSTATUS)0xC0150003) +#define STATUS_SXS_ASSEMBLY_NOT_FOUND ((NTSTATUS)0xC0150004) +#define STATUS_SXS_MANIFEST_FORMAT_ERROR ((NTSTATUS)0xC0150005) +#define STATUS_SXS_MANIFEST_PARSE_ERROR ((NTSTATUS)0xC0150006) +#define STATUS_SXS_ACTIVATION_CONTEXT_DISABLED ((NTSTATUS)0xC0150007) +#define STATUS_SXS_KEY_NOT_FOUND ((NTSTATUS)0xC0150008) +#define STATUS_SXS_VERSION_CONFLICT ((NTSTATUS)0xC0150009) +#define STATUS_SXS_WRONG_SECTION_TYPE ((NTSTATUS)0xC015000A) +#define STATUS_SXS_THREAD_QUERIES_DISABLED ((NTSTATUS)0xC015000B) +#define STATUS_SXS_ASSEMBLY_MISSING ((NTSTATUS)0xC015000C) +#define STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET ((NTSTATUS)0xC015000E) +#define STATUS_SXS_EARLY_DEACTIVATION ((NTSTATUS)0xC015000F) +#define STATUS_SXS_INVALID_DEACTIVATION ((NTSTATUS)0xC0150010) +#define STATUS_SXS_MULTIPLE_DEACTIVATION ((NTSTATUS)0xC0150011) +#define STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY ((NTSTATUS)0xC0150012) +#define STATUS_SXS_PROCESS_TERMINATION_REQUESTED ((NTSTATUS)0xC0150013) +#define STATUS_SXS_CORRUPT_ACTIVATION_STACK ((NTSTATUS)0xC0150014) +#define STATUS_SXS_CORRUPTION ((NTSTATUS)0xC0150015) +#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE ((NTSTATUS)0xC0150016) +#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME ((NTSTATUS)0xC0150017) +#define STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE ((NTSTATUS)0xC0150018) +#define STATUS_SXS_IDENTITY_PARSE_ERROR ((NTSTATUS)0xC0150019) +#define STATUS_SXS_COMPONENT_STORE_CORRUPT ((NTSTATUS)0xC015001A) +#define STATUS_SXS_FILE_HASH_MISMATCH ((NTSTATUS)0xC015001B) +#define STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT ((NTSTATUS)0xC015001C) +#define STATUS_SXS_IDENTITIES_DIFFERENT ((NTSTATUS)0xC015001D) +#define STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT ((NTSTATUS)0xC015001E) +#define STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY ((NTSTATUS)0xC015001F) +#define STATUS_ADVANCED_INSTALLER_FAILED ((NTSTATUS)0xC0150020) +#define STATUS_XML_ENCODING_MISMATCH ((NTSTATUS)0xC0150021) +#define STATUS_SXS_MANIFEST_TOO_BIG ((NTSTATUS)0xC0150022) +#define STATUS_SXS_SETTING_NOT_REGISTERED ((NTSTATUS)0xC0150023) +#define STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE ((NTSTATUS)0xC0150024) +#define STATUS_SXS_PRIMITIVE_INSTALLER_FAILED ((NTSTATUS)0xC0150025) +#define STATUS_GENERIC_COMMAND_FAILED ((NTSTATUS)0xC0150026) +#define STATUS_SXS_FILE_HASH_MISSING ((NTSTATUS)0xC0150027) + +typedef struct _PEB PEB; +typedef struct _PEB* PPEB; + +typedef struct _TEB TEB; +typedef struct _TEB* PTEB; + +/** + * Process Environment Block + */ + +struct _THREAD_BLOCK_ID +{ + DWORD ThreadId; + TEB* ThreadEnvironmentBlock; +}; +typedef struct _THREAD_BLOCK_ID THREAD_BLOCK_ID; + +struct _PEB +{ + DWORD ThreadCount; + DWORD ThreadArraySize; + THREAD_BLOCK_ID* Threads; +}; + +/* + * Thread Environment Block + */ + +struct _TEB +{ + PEB* ProcessEnvironmentBlock; + + DWORD LastErrorValue; + PVOID TlsSlots[64]; +}; + +#define GENERIC_READ 0x80000000 +#define GENERIC_WRITE 0x40000000 +#define GENERIC_EXECUTE 0x20000000 +#define GENERIC_ALL 0x10000000 + +#define DELETE 0x00010000 +#define READ_CONTROL 0x00020000 +#define WRITE_DAC 0x00040000 +#define WRITE_OWNER 0x00080000 +#define SYNCHRONIZE 0x00100000 +#define STANDARD_RIGHTS_REQUIRED 0x000F0000 +#define STANDARD_RIGHTS_READ 0x00020000 +#define STANDARD_RIGHTS_WRITE 0x00020000 +#define STANDARD_RIGHTS_EXECUTE 0x00020000 +#define STANDARD_RIGHTS_ALL 0x001F0000 +#define SPECIFIC_RIGHTS_ALL 0x0000FFFF +#define ACCESS_SYSTEM_SECURITY 0x01000000 +#define MAXIMUM_ALLOWED 0x02000000 + +#define FILE_READ_DATA 0x0001 +#define FILE_LIST_DIRECTORY 0x0001 +#define FILE_WRITE_DATA 0x0002 +#define FILE_ADD_FILE 0x0002 +#define FILE_APPEND_DATA 0x0004 +#define FILE_ADD_SUBDIRECTORY 0x0004 +#define FILE_CREATE_PIPE_INSTANCE 0x0004 +#define FILE_READ_EA 0x0008 +#define FILE_WRITE_EA 0x0010 +#define FILE_EXECUTE 0x0020 +#define FILE_TRAVERSE 0x0020 +#define FILE_DELETE_CHILD 0x0040 +#define FILE_READ_ATTRIBUTES 0x0080 +#define FILE_WRITE_ATTRIBUTES 0x0100 + +#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF) +#define FILE_GENERIC_READ (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE) +#define FILE_GENERIC_WRITE (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE) +#define FILE_GENERIC_EXECUTE (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE) + +#define FILE_SHARE_READ 0x00000001 +#define FILE_SHARE_WRITE 0x00000002 +#define FILE_SHARE_DELETE 0x00000004 + +#define FILE_DIRECTORY_FILE 0x00000001 +#define FILE_WRITE_THROUGH 0x00000002 +#define FILE_SEQUENTIAL_ONLY 0x00000004 +#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 +#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#define FILE_NON_DIRECTORY_FILE 0x00000040 +#define FILE_CREATE_TREE_CONNECTION 0x00000080 +#define FILE_COMPLETE_IF_OPLOCKED 0x00000100 +#define FILE_NO_EA_KNOWLEDGE 0x00000200 +#define FILE_OPEN_REMOTE_INSTANCE 0x00000400 +#define FILE_RANDOM_ACCESS 0x00000800 +#define FILE_DELETE_ON_CLOSE 0x00001000 +#define FILE_OPEN_BY_FILE_ID 0x00002000 +#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 +#define FILE_NO_COMPRESSION 0x00008000 +#define FILE_OPEN_REQUIRING_OPLOCK 0x00010000 +#define FILE_RESERVE_OPFILTER 0x00100000 +#define FILE_OPEN_REPARSE_POINT 0x00200000 +#define FILE_OPEN_NO_RECALL 0x00400000 +#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000 + +#define FILE_VALID_OPTION_FLAGS 0x00FFFFFF +#define FILE_VALID_PIPE_OPTION_FLAGS 0x00000032 +#define FILE_VALID_MAILSLOT_OPTION_FLAGS 0x00000032 +#define FILE_VALID_SET_FLAGS 0x00000036 + +#define FILE_SUPERSEDED 0x00000000 +#define FILE_OPENED 0x00000001 +#define FILE_CREATED 0x00000002 +#define FILE_OVERWRITTEN 0x00000003 +#define FILE_EXISTS 0x00000004 +#define FILE_DOES_NOT_EXIST 0x00000005 + +typedef DWORD ACCESS_MASK; +typedef ACCESS_MASK* PACCESS_MASK; + +typedef CONST char *PCSZ; + +typedef struct _STRING +{ + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +} STRING; +typedef STRING *PSTRING; + +typedef STRING ANSI_STRING; +typedef PSTRING PANSI_STRING; +typedef PSTRING PCANSI_STRING; + +typedef STRING OEM_STRING; +typedef PSTRING POEM_STRING; +typedef CONST STRING* PCOEM_STRING; + +typedef struct _LSA_UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING; + +#define OBJ_INHERIT 0x00000002L +#define OBJ_PERMANENT 0x00000010L +#define OBJ_EXCLUSIVE 0x00000020L +#define OBJ_CASE_INSENSITIVE 0x00000040L +#define OBJ_OPENIF 0x00000080L +#define OBJ_OPENLINK 0x00000100L +#define OBJ_KERNEL_HANDLE 0x00000200L +#define OBJ_FORCE_ACCESS_CHECK 0x00000400L +#define OBJ_VALID_ATTRIBUTES 0x000007F2L + +typedef struct _OBJECT_ATTRIBUTES +{ + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; + +typedef struct _IO_STATUS_BLOCK +{ + union + { + NTSTATUS status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +typedef VOID (*PIO_APC_ROUTINE)(PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG Reserved); + +#ifdef __cplusplus +extern "C" { +#endif + +WINPR_API PTEB NtCurrentTeb(void); + +WINPR_API VOID RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString); + +WINPR_API VOID RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString); + +WINPR_API NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PCANSI_STRING SourceString, BOOLEAN AllocateDestinationString); + +WINPR_API VOID RtlFreeUnicodeString(PUNICODE_STRING UnicodeString); + +WINPR_API ULONG RtlNtStatusToDosError(NTSTATUS status); + +WINPR_API VOID InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes, + PUNICODE_STRING ObjectName, ULONG Attributes, HANDLE RootDirectory, + PSECURITY_DESCRIPTOR SecurityDescriptor); + +WINPR_API NTSTATUS NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, + PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, + ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength); + +WINPR_API NTSTATUS NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, + ULONG ShareAccess, ULONG OpenOptions); + +WINPR_API NTSTATUS NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event, + PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, + ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, + PVOID OutputBuffer, ULONG OutputBufferLength); + +WINPR_API NTSTATUS NtClose(HANDLE Handle); + +WINPR_API NTSTATUS NtWaitForSingleObject(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /* WINPR_NT_H */ + diff --git a/winpr/include/winpr/print.h b/winpr/include/winpr/print.h index d5e9cc724..b85f176f9 100644 --- a/winpr/include/winpr/print.h +++ b/winpr/include/winpr/print.h @@ -20,6 +20,10 @@ #ifndef WINPR_UTILS_PRINT_H #define WINPR_UTILS_PRINT_H +#include +#include +#include + #include #include @@ -32,6 +36,8 @@ extern "C" { WINPR_API void winpr_HexDump(BYTE* data, int length); WINPR_API int wprintfx(const char *fmt, ...); +WINPR_API int wvprintfx(const char *fmt, va_list args); +WINPR_API int wvsnprintfx(char *buffer, size_t bufferSize, const char* fmt, va_list args); #ifdef __cplusplus } diff --git a/winpr/include/winpr/registry.h b/winpr/include/winpr/registry.h index 53175ce28..e6f9757f4 100644 --- a/winpr/include/winpr/registry.h +++ b/winpr/include/winpr/registry.h @@ -35,6 +35,7 @@ extern "C" { #include #include +#include #include #include @@ -106,9 +107,6 @@ extern "C" { typedef HANDLE HKEY; typedef HANDLE* PHKEY; -typedef DWORD ACCESS_MASK; -typedef ACCESS_MASK* PACCESS_MASK; - typedef ACCESS_MASK REGSAM; #define HKEY_CLASSES_ROOT ((HKEY) (LONG_PTR) (LONG) 0x80000000) diff --git a/winpr/include/winpr/security.h b/winpr/include/winpr/security.h index 59f02d953..13a49cb28 100644 --- a/winpr/include/winpr/security.h +++ b/winpr/include/winpr/security.h @@ -30,12 +30,7 @@ #ifndef _WIN32 -typedef struct _LSA_UNICODE_STRING -{ - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING; +#include #define SECURITY_MANDATORY_UNTRUSTED_RID 0x0000 #define SECURITY_MANDATORY_LOW_RID 0x1000 diff --git a/winpr/include/winpr/wlog.h b/winpr/include/winpr/wlog.h new file mode 100644 index 000000000..394e1a9c6 --- /dev/null +++ b/winpr/include/winpr/wlog.h @@ -0,0 +1,166 @@ +/** + * WinPR: Windows Portable Runtime + * WinPR Logger + * + * Copyright 2013 Marc-Andre Moreau + * + * 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_LOG_H +#define WINPR_LOG_H + +#include + +#include +#include + +typedef struct _wLog wLog; +typedef struct _wLogMessage wLogMessage; +typedef struct _wLogLayout wLogLayout; +typedef struct _wLogAppender wLogAppender; + +/** + * Log Levels + */ + +#define WLOG_TRACE 0 +#define WLOG_DEBUG 1 +#define WLOG_INFO 2 +#define WLOG_WARN 3 +#define WLOG_ERROR 4 +#define WLOG_FATAL 5 +#define WLOG_OFF 6 + +/** + * Log Message + */ + +#define WLOG_MESSAGE_STRING 0 + +struct _wLogMessage +{ + DWORD Type; + + DWORD Level; + + LPSTR PrefixString; + + LPSTR FormatString; + LPSTR TextString; + + DWORD LineNumber; /* __LINE__ */ + LPCSTR FileName; /* __FILE__ */ + LPCSTR FunctionName; /* __FUNCTION__ */ +}; + +/** + * Log Layout + */ + +struct _wLogLayout +{ + DWORD Type; + + LPSTR FormatString; +}; + +/** + * Log Appenders + */ + +#define WLOG_APPENDER_CONSOLE 0 +#define WLOG_APPENDER_FILE 1 + +typedef int (*WLOG_APPENDER_OPEN_FN)(wLog* log, wLogAppender* appender); +typedef int (*WLOG_APPENDER_CLOSE_FN)(wLog* log, wLogAppender* appender); +typedef int (*WLOG_APPENDER_WRITE_MESSAGE_FN)(wLog* log, wLogAppender* appender, wLogMessage* message); + +#define WLOG_APPENDER_COMMON() \ + DWORD Type; \ + wLogLayout* Layout; \ + WLOG_APPENDER_OPEN_FN Open; \ + WLOG_APPENDER_CLOSE_FN Close; \ + WLOG_APPENDER_WRITE_MESSAGE_FN WriteMessage + +struct _wLogAppender +{ + WLOG_APPENDER_COMMON(); +}; + +#define WLOG_CONSOLE_STDOUT 1 +#define WLOG_CONSOLE_STDERR 2 + +struct _wLogConsoleAppender +{ + WLOG_APPENDER_COMMON(); + + int outputStream; +}; +typedef struct _wLogConsoleAppender wLogConsoleAppender; + +struct _wLogFileAppender +{ + WLOG_APPENDER_COMMON(); + + char* FileName; + FILE* FileDescriptor; +}; +typedef struct _wLogFileAppender wLogFileAppender; + +/** + * Logger + */ + +struct _wLog +{ + LPSTR Name; + DWORD Level; + + wLogAppender* Appender; +}; + +WINPR_API void WLog_PrintMessage(wLog* log, wLogMessage* message, ...); + +#define WLog_Print(_log, _log_level, _fmt, ...) \ + if (_log_level <= _log->Level) { \ + wLogMessage _log_message; \ + _log_message.Type = WLOG_MESSAGE_STRING; \ + _log_message.Level = _log_level; \ + _log_message.FormatString = _fmt; \ + _log_message.LineNumber = __LINE__; \ + _log_message.FileName = __FILE__; \ + _log_message.FunctionName = __FUNCTION__; \ + WLog_PrintMessage(_log, &(_log_message), ## __VA_ARGS__ ); \ + } + +WINPR_API DWORD WLog_GetLogLevel(wLog* log); +WINPR_API void WLog_SetLogLevel(wLog* log, DWORD logLevel); + +WINPR_API wLogAppender* WLog_GetLogAppender(wLog* log); +WINPR_API void WLog_SetLogAppenderType(wLog* log, DWORD logAppenderType); + +WINPR_API int WLog_OpenAppender(wLog* log); +WINPR_API int WLog_CloseAppender(wLog* log); + +WINPR_API void WLog_ConsoleAppender_SetOutputStream(wLog* log, wLogConsoleAppender* appender, int outputStream); + +WINPR_API void WLog_FileAppender_SetOutputFileName(wLog* log, wLogFileAppender* appender, const char* filename); + +WINPR_API wLogLayout* WLog_GetLogLayout(wLog* log); +WINPR_API void WLog_Layout_SetPrefixFormat(wLog* log, wLogLayout* layout, const char* format); + +WINPR_API wLog* WLog_New(LPCSTR name); +WINPR_API void WLog_Free(wLog* log); + +#endif /* WINPR_WLOG_H */ diff --git a/winpr/include/winpr/wtsapi.h b/winpr/include/winpr/wtsapi.h new file mode 100644 index 000000000..42f2b0101 --- /dev/null +++ b/winpr/include/winpr/wtsapi.h @@ -0,0 +1,1094 @@ +/** + * WinPR: Windows Portable Runtime + * Windows Terminal Services API + * + * Copyright 2013 Marc-Andre Moreau + * + * 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_WTSAPI_H +#define WINPR_WTSAPI_H + +#include +#include + +#include + +#ifndef _WIN32 + +/** + * Virtual Channel Protocol (Common) + */ + +#define CHANNEL_CHUNK_LENGTH 1600 + +#define CHANNEL_PDU_LENGTH (CHANNEL_CHUNK_LENGTH + sizeof(CHANNEL_PDU_HEADER)) + +#define CHANNEL_FLAG_FIRST 0x01 +#define CHANNEL_FLAG_LAST 0x02 +#define CHANNEL_FLAG_ONLY (CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST) +#define CHANNEL_FLAG_MIDDLE 0 +#define CHANNEL_FLAG_FAIL 0x100 + +#define CHANNEL_FLAG_SHOW_PROTOCOL 0x10 +#define CHANNEL_FLAG_SUSPEND 0x20 +#define CHANNEL_FLAG_RESUME 0x40 +#define CHANNEL_FLAG_SHADOW_PERSISTENT 0x80 + +#define CHANNEL_OPTION_INITIALIZED 0x80000000 + +#define CHANNEL_OPTION_ENCRYPT_RDP 0x40000000 +#define CHANNEL_OPTION_ENCRYPT_SC 0x20000000 +#define CHANNEL_OPTION_ENCRYPT_CS 0x10000000 +#define CHANNEL_OPTION_PRI_HIGH 0x08000000 +#define CHANNEL_OPTION_PRI_MED 0x04000000 +#define CHANNEL_OPTION_PRI_LOW 0x02000000 +#define CHANNEL_OPTION_COMPRESS_RDP 0x00800000 +#define CHANNEL_OPTION_COMPRESS 0x00400000 +#define CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000 +#define CHANNEL_OPTION_REMOTE_CONTROL_PERSISTENT 0x00100000 + +#define CHANNEL_MAX_COUNT 30 +#define CHANNEL_NAME_LEN 7 + +typedef struct tagCHANNEL_DEF +{ + char name[CHANNEL_NAME_LEN + 1]; + ULONG options; +} CHANNEL_DEF; +typedef CHANNEL_DEF *PCHANNEL_DEF; +typedef PCHANNEL_DEF *PPCHANNEL_DEF; + +typedef struct tagCHANNEL_PDU_HEADER +{ + UINT32 length; + UINT32 flags; +} CHANNEL_PDU_HEADER, *PCHANNEL_PDU_HEADER; + +/** + * Virtual Channel Client API + */ + +#ifdef _WIN32 +#define VCAPITYPE __stdcall +#define VCEXPORT +#else +#define VCAPITYPE CALLBACK +#define VCEXPORT __export +#endif + +typedef VOID VCAPITYPE CHANNEL_INIT_EVENT_FN(LPVOID pInitHandle, + UINT event, LPVOID pData, UINT dataLength); + +typedef CHANNEL_INIT_EVENT_FN *PCHANNEL_INIT_EVENT_FN; + +typedef VOID VCAPITYPE CHANNEL_INIT_EVENT_EX_FN(LPVOID lpUserParam, + LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength); + +typedef CHANNEL_INIT_EVENT_EX_FN *PCHANNEL_INIT_EVENT_EX_FN; + +#define CHANNEL_EVENT_INITIALIZED 0 +#define CHANNEL_EVENT_CONNECTED 1 +#define CHANNEL_EVENT_V1_CONNECTED 2 +#define CHANNEL_EVENT_DISCONNECTED 3 +#define CHANNEL_EVENT_TERMINATED 4 +#define CHANNEL_EVENT_REMOTE_CONTROL_START 5 +#define CHANNEL_EVENT_REMOTE_CONTROL_STOP 6 +#define CHANNEL_EVENT_DATA_RECEIVED 10 +#define CHANNEL_EVENT_WRITE_COMPLETE 11 +#define CHANNEL_EVENT_WRITE_CANCELLED 12 + +typedef VOID VCAPITYPE CHANNEL_OPEN_EVENT_FN(DWORD openHandle, UINT event, + LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags); + +typedef CHANNEL_OPEN_EVENT_FN *PCHANNEL_OPEN_EVENT_FN; + +typedef VOID VCAPITYPE CHANNEL_OPEN_EVENT_EX_FN(LPVOID lpUserParam, DWORD openHandle, UINT event, + LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags); + +typedef CHANNEL_OPEN_EVENT_EX_FN *PCHANNEL_OPEN_EVENT_EX_FN; + +#define CHANNEL_RC_OK 0 +#define CHANNEL_RC_ALREADY_INITIALIZED 1 +#define CHANNEL_RC_NOT_INITIALIZED 2 +#define CHANNEL_RC_ALREADY_CONNECTED 3 +#define CHANNEL_RC_NOT_CONNECTED 4 +#define CHANNEL_RC_TOO_MANY_CHANNELS 5 +#define CHANNEL_RC_BAD_CHANNEL 6 +#define CHANNEL_RC_BAD_CHANNEL_HANDLE 7 +#define CHANNEL_RC_NO_BUFFER 8 +#define CHANNEL_RC_BAD_INIT_HANDLE 9 +#define CHANNEL_RC_NOT_OPEN 10 +#define CHANNEL_RC_BAD_PROC 11 +#define CHANNEL_RC_NO_MEMORY 12 +#define CHANNEL_RC_UNKNOWN_CHANNEL_NAME 13 +#define CHANNEL_RC_ALREADY_OPEN 14 +#define CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY 15 +#define CHANNEL_RC_NULL_DATA 16 +#define CHANNEL_RC_ZERO_LENGTH 17 +#define CHANNEL_RC_INVALID_INSTANCE 18 +#define CHANNEL_RC_UNSUPPORTED_VERSION 19 +#define CHANNEL_RC_INITIALIZATION_ERROR 20 + +#define VIRTUAL_CHANNEL_VERSION_WIN2000 1 + +typedef UINT VCAPITYPE VIRTUALCHANNELINIT(LPVOID* ppInitHandle, PCHANNEL_DEF pChannel, + INT channelCount, ULONG versionRequested, PCHANNEL_INIT_EVENT_FN pChannelInitEventProc); + +typedef VIRTUALCHANNELINIT *PVIRTUALCHANNELINIT; + +typedef UINT VCAPITYPE VIRTUALCHANNELINITEX(LPVOID lpUserParam, LPVOID pInitHandle, PCHANNEL_DEF pChannel, + INT channelCount, ULONG versionRequested, PCHANNEL_INIT_EVENT_EX_FN pChannelInitEventProcEx); + +typedef VIRTUALCHANNELINITEX *PVIRTUALCHANNELINITEX; + +typedef UINT VCAPITYPE VIRTUALCHANNELOPEN(LPVOID pInitHandle, LPDWORD pOpenHandle, + PCHAR pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc); + +typedef VIRTUALCHANNELOPEN *PVIRTUALCHANNELOPEN; + +typedef UINT VCAPITYPE VIRTUALCHANNELOPENEX(LPVOID pInitHandle, LPDWORD pOpenHandle, + PCHAR pChannelName, PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx); + +typedef VIRTUALCHANNELOPENEX *PVIRTUALCHANNELOPENEX; + +typedef UINT VCAPITYPE VIRTUALCHANNELCLOSE(DWORD openHandle); + +typedef VIRTUALCHANNELCLOSE *PVIRTUALCHANNELCLOSE; + +typedef UINT VCAPITYPE VIRTUALCHANNELCLOSEEX(LPVOID pInitHandle, DWORD openHandle); + +typedef VIRTUALCHANNELCLOSEEX *PVIRTUALCHANNELCLOSEEX; + +typedef UINT VCAPITYPE VIRTUALCHANNELWRITE(DWORD openHandle, + LPVOID pData, ULONG dataLength, LPVOID pUserData); + +typedef VIRTUALCHANNELWRITE *PVIRTUALCHANNELWRITE; + +typedef UINT VCAPITYPE VIRTUALCHANNELWRITEEX(LPVOID pInitHandle, DWORD openHandle, + LPVOID pData, ULONG dataLength, LPVOID pUserData); + +typedef VIRTUALCHANNELWRITEEX *PVIRTUALCHANNELWRITEEX; + +typedef struct tagCHANNEL_ENTRY_POINTS +{ + DWORD cbSize; + DWORD protocolVersion; + PVIRTUALCHANNELINIT pVirtualChannelInit; + PVIRTUALCHANNELOPEN pVirtualChannelOpen; + PVIRTUALCHANNELCLOSE pVirtualChannelClose; + PVIRTUALCHANNELWRITE pVirtualChannelWrite; +} CHANNEL_ENTRY_POINTS, *PCHANNEL_ENTRY_POINTS; + +typedef struct tagCHANNEL_ENTRY_POINTS_EX +{ + DWORD cbSize; + DWORD protocolVersion; + PVIRTUALCHANNELINITEX pVirtualChannelInitEx; + PVIRTUALCHANNELOPENEX pVirtualChannelOpenEx; + PVIRTUALCHANNELCLOSEEX pVirtualChannelCloseEx; + PVIRTUALCHANNELWRITEEX pVirtualChannelWriteEx; +} CHANNEL_ENTRY_POINTS_EX, *PCHANNEL_ENTRY_POINTS_EX; + +typedef BOOL VCAPITYPE VIRTUALCHANNELENTRY(PCHANNEL_ENTRY_POINTS pEntryPoints); + +typedef VIRTUALCHANNELENTRY *PVIRTUALCHANNELENTRY; + +typedef BOOL VCAPITYPE VIRTUALCHANNELENTRYEX(PCHANNEL_ENTRY_POINTS_EX pEntryPointsEx, PVOID pInitHandle); + +typedef VIRTUALCHANNELENTRYEX *PVIRTUALCHANNELENTRYEX; + +typedef HRESULT (VCAPITYPE *PFNVCAPIGETINSTANCE)(REFIID refiid, PULONG pNumObjs, PVOID* ppObjArray); + +/** + * Windows Terminal Services API (WtsApi) + */ + +#define WTS_CURRENT_SERVER ((HANDLE)NULL) +#define WTS_CURRENT_SERVER_HANDLE ((HANDLE)NULL) +#define WTS_CURRENT_SERVER_NAME (NULL) + +#define WTS_CURRENT_SESSION ((DWORD)-1) + +#define WTS_ANY_SESSION ((DWORD)-2) + +#define IDTIMEOUT 32000 +#define IDASYNC 32001 + +#define USERNAME_LENGTH 20 +#define CLIENTNAME_LENGTH 20 +#define CLIENTADDRESS_LENGTH 30 + +#define WTS_WSD_LOGOFF 0x00000001 +#define WTS_WSD_SHUTDOWN 0x00000002 +#define WTS_WSD_REBOOT 0x00000004 +#define WTS_WSD_POWEROFF 0x00000008 +#define WTS_WSD_FASTREBOOT 0x00000010 + +#define MAX_ELAPSED_TIME_LENGTH 15 +#define MAX_DATE_TIME_LENGTH 56 +#define WINSTATIONNAME_LENGTH 32 +#define DOMAIN_LENGTH 17 + +#define WTS_DRIVE_LENGTH 3 +#define WTS_LISTENER_NAME_LENGTH 32 +#define WTS_COMMENT_LENGTH 60 + +#define WTS_LISTENER_CREATE 0x00000001 +#define WTS_LISTENER_UPDATE 0x00000010 + +#define WTS_SECURITY_QUERY_INFORMATION 0x00000001 +#define WTS_SECURITY_SET_INFORMATION 0x00000002 +#define WTS_SECURITY_RESET 0x00000004 +#define WTS_SECURITY_VIRTUAL_CHANNELS 0x00000008 +#define WTS_SECURITY_REMOTE_CONTROL 0x00000010 +#define WTS_SECURITY_LOGON 0x00000020 +#define WTS_SECURITY_LOGOFF 0x00000040 +#define WTS_SECURITY_MESSAGE 0x00000080 +#define WTS_SECURITY_CONNECT 0x00000100 +#define WTS_SECURITY_DISCONNECT 0x00000200 + +#define WTS_SECURITY_GUEST_ACCESS (WTS_SECURITY_LOGON) + +#define WTS_SECURITY_CURRENT_GUEST_ACCESS (WTS_SECURITY_VIRTUAL_CHANNELS | WTS_SECURITY_LOGOFF) + +#define WTS_SECURITY_USER_ACCESS (WTS_SECURITY_CURRENT_GUEST_ACCESS | WTS_SECURITY_QUERY_INFORMATION | WTS_SECURITY_CONNECT) + +#define WTS_SECURITY_CURRENT_USER_ACCESS (WTS_SECURITY_SET_INFORMATION | WTS_SECURITY_RESET \ + WTS_SECURITY_VIRTUAL_CHANNELS | WTS_SECURITY_LOGOFF \ + WTS_SECURITY_DISCONNECT) + +#define WTS_SECURITY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | WTS_SECURITY_QUERY_INFORMATION | \ + WTS_SECURITY_SET_INFORMATION | WTS_SECURITY_RESET | \ + WTS_SECURITY_VIRTUAL_CHANNELS | WTS_SECURITY_REMOTE_CONTROL | \ + WTS_SECURITY_LOGON | WTS_SECURITY_MESSAGE | \ + WTS_SECURITY_CONNECT | WTS_SECURITY_DISCONNECT) + +typedef enum _WTS_CONNECTSTATE_CLASS +{ + WTSActive, + WTSConnected, + WTSConnectQuery, + WTSShadow, + WTSDisconnected, + WTSIdle, + WTSListen, + WTSReset, + WTSDown, + WTSInit, +} WTS_CONNECTSTATE_CLASS; + +typedef struct _WTS_SERVER_INFOW +{ + LPWSTR pServerName; +} WTS_SERVER_INFOW, *PWTS_SERVER_INFOW; + +typedef struct _WTS_SERVER_INFOA +{ + LPSTR pServerName; +} WTS_SERVER_INFOA, *PWTS_SERVER_INFOA; + +typedef struct _WTS_SESSION_INFOW +{ + DWORD SessionId; + LPWSTR pWinStationName; + WTS_CONNECTSTATE_CLASS State; +} WTS_SESSION_INFOW, *PWTS_SESSION_INFOW; + +typedef struct _WTS_SESSION_INFOA +{ + DWORD SessionId; + LPSTR pWinStationName; + WTS_CONNECTSTATE_CLASS State; +} WTS_SESSION_INFOA, *PWTS_SESSION_INFOA; + +typedef struct _WTS_SESSION_INFO_1W +{ + DWORD ExecEnvId; + WTS_CONNECTSTATE_CLASS State; + DWORD SessionId; + LPWSTR pSessionName; + LPWSTR pHostName; + LPWSTR pUserName; + LPWSTR pDomainName; + LPWSTR pFarmName; +} WTS_SESSION_INFO_1W, *PWTS_SESSION_INFO_1W; + +typedef struct _WTS_SESSION_INFO_1A +{ + DWORD ExecEnvId; + WTS_CONNECTSTATE_CLASS State; + DWORD SessionId; + LPSTR pSessionName; + LPSTR pHostName; + LPSTR pUserName; + LPSTR pDomainName; + LPSTR pFarmName; +} WTS_SESSION_INFO_1A, *PWTS_SESSION_INFO_1A; + +typedef struct _WTS_PROCESS_INFOW +{ + DWORD SessionId; + DWORD ProcessId; + LPWSTR pProcessName; + PSID pUserSid; +} WTS_PROCESS_INFOW, *PWTS_PROCESS_INFOW; + +typedef struct _WTS_PROCESS_INFOA +{ + DWORD SessionId; + DWORD ProcessId; + LPSTR pProcessName; + PSID pUserSid; +} WTS_PROCESS_INFOA, *PWTS_PROCESS_INFOA; + +#define WTS_PROTOCOL_TYPE_CONSOLE 0 +#define WTS_PROTOCOL_TYPE_ICA 1 +#define WTS_PROTOCOL_TYPE_RDP 2 + +typedef enum _WTS_INFO_CLASS +{ + WTSInitialProgram, + WTSApplicationName, + WTSWorkingDirectory, + WTSOEMId, + WTSSessionId, + WTSUserName, + WTSWinStationName, + WTSDomainName, + WTSConnectState, + WTSClientBuildNumber, + WTSClientName, + WTSClientDirectory, + WTSClientProductId, + WTSClientHardwareId, + WTSClientAddress, + WTSClientDisplay, + WTSClientProtocolType, + WTSIdleTime, + WTSLogonTime, + WTSIncomingBytes, + WTSOutgoingBytes, + WTSIncomingFrames, + WTSOutgoingFrames, + WTSClientInfo, + WTSSessionInfo, + WTSSessionInfoEx, + WTSConfigInfo, + WTSValidationInfo, + WTSSessionAddressV4, + WTSIsRemoteSession +} WTS_INFO_CLASS; + +typedef struct _WTSCONFIGINFOW +{ + ULONG version; + ULONG fConnectClientDrivesAtLogon; + ULONG fConnectPrinterAtLogon; + ULONG fDisablePrinterRedirection; + ULONG fDisableDefaultMainClientPrinter; + ULONG ShadowSettings; + WCHAR LogonUserName[USERNAME_LENGTH + 1]; + WCHAR LogonDomain[DOMAIN_LENGTH + 1]; + WCHAR WorkDirectory[MAX_PATH + 1]; + WCHAR InitialProgram[MAX_PATH + 1]; + WCHAR ApplicationName[MAX_PATH + 1]; +} WTSCONFIGINFOW, *PWTSCONFIGINFOW; + +typedef struct _WTSCONFIGINFOA +{ + ULONG version; + ULONG fConnectClientDrivesAtLogon; + ULONG fConnectPrinterAtLogon; + ULONG fDisablePrinterRedirection; + ULONG fDisableDefaultMainClientPrinter; + ULONG ShadowSettings; + CHAR LogonUserName[USERNAME_LENGTH + 1]; + CHAR LogonDomain[DOMAIN_LENGTH + 1]; + CHAR WorkDirectory[MAX_PATH + 1]; + CHAR InitialProgram[MAX_PATH + 1]; + CHAR ApplicationName[MAX_PATH + 1]; +} WTSCONFIGINFOA, *PWTSCONFIGINFOA; + +typedef struct _WTSINFOW +{ + WTS_CONNECTSTATE_CLASS State; + DWORD SessionId; + DWORD IncomingBytes; + DWORD OutgoingBytes; + DWORD IncomingFrames; + DWORD OutgoingFrames; + DWORD IncomingCompressedBytes; + DWORD OutgoingCompressedBytes; + WCHAR WinStationName[WINSTATIONNAME_LENGTH]; + WCHAR Domain[DOMAIN_LENGTH]; + WCHAR UserName[USERNAME_LENGTH+1]; + LARGE_INTEGER ConnectTime; + LARGE_INTEGER DisconnectTime; + LARGE_INTEGER LastInputTime; + LARGE_INTEGER LogonTime; + LARGE_INTEGER CurrentTime; +} WTSINFOW, *PWTSINFOW; + +typedef struct _WTSINFOA +{ + WTS_CONNECTSTATE_CLASS State; + DWORD SessionId; + DWORD IncomingBytes; + DWORD OutgoingBytes; + DWORD IncomingFrames; + DWORD OutgoingFrames; + DWORD IncomingCompressedBytes; + DWORD OutgoingCompressedBy; + CHAR WinStationName[WINSTATIONNAME_LENGTH]; + CHAR Domain[DOMAIN_LENGTH]; + CHAR UserName[USERNAME_LENGTH+1]; + LARGE_INTEGER ConnectTime; + LARGE_INTEGER DisconnectTime; + LARGE_INTEGER LastInputTime; + LARGE_INTEGER LogonTime; + LARGE_INTEGER CurrentTime; +} WTSINFOA, *PWTSINFOA; + +#define WTS_SESSIONSTATE_UNKNOWN 0xFFFFFFFF +#define WTS_SESSIONSTATE_LOCK 0x00000000 +#define WTS_SESSIONSTATE_UNLOCK 0x00000001 + +typedef struct _WTSINFOEX_LEVEL1_W +{ + ULONG SessionId; + WTS_CONNECTSTATE_CLASS SessionState; + LONG SessionFlags; + WCHAR WinStationName[WINSTATIONNAME_LENGTH + 1]; + WCHAR UserName[USERNAME_LENGTH + 1]; + WCHAR DomainName[DOMAIN_LENGTH + 1]; + LARGE_INTEGER LogonTime; + LARGE_INTEGER ConnectTime; + LARGE_INTEGER DisconnectTime; + LARGE_INTEGER LastInputTime; + LARGE_INTEGER CurrentTime; + DWORD IncomingBytes; + DWORD OutgoingBytes; + DWORD IncomingFrames; + DWORD OutgoingFrames; + DWORD IncomingCompressedBytes; + DWORD OutgoingCompressedBytes; +} WTSINFOEX_LEVEL1_W, *PWTSINFOEX_LEVEL1_W; + +typedef struct _WTSINFOEX_LEVEL1_A +{ + ULONG SessionId; + WTS_CONNECTSTATE_CLASS SessionState; + LONG SessionFlags; + CHAR WinStationName[WINSTATIONNAME_LENGTH + 1]; + CHAR UserName[USERNAME_LENGTH + 1]; + CHAR DomainName[DOMAIN_LENGTH + 1]; + LARGE_INTEGER LogonTime; + LARGE_INTEGER ConnectTime; + LARGE_INTEGER DisconnectTime; + LARGE_INTEGER LastInputTime; + LARGE_INTEGER CurrentTime; + DWORD IncomingBytes; + DWORD OutgoingBytes; + DWORD IncomingFrames; + DWORD OutgoingFrames; + DWORD IncomingCompressedBytes; + DWORD OutgoingCompressedBytes; +} WTSINFOEX_LEVEL1_A, *PWTSINFOEX_LEVEL1_A; + +typedef union _WTSINFOEX_LEVEL_W +{ + WTSINFOEX_LEVEL1_W WTSInfoExLevel1; +} WTSINFOEX_LEVEL_W, *PWTSINFOEX_LEVEL_W; + +typedef union _WTSINFOEX_LEVEL_A +{ + WTSINFOEX_LEVEL1_A WTSInfoExLevel1; +} WTSINFOEX_LEVEL_A, *PWTSINFOEX_LEVEL_A; + +typedef struct _WTSINFOEXW +{ + DWORD Level; + WTSINFOEX_LEVEL_W Data; +} WTSINFOEXW, *PWTSINFOEXW; + +typedef struct _WTSINFOEXA +{ + DWORD Level; + WTSINFOEX_LEVEL_A Data; +} WTSINFOEXA, *PWTSINFOEXA; + +typedef struct _WTSCLIENTW +{ + WCHAR ClientName[CLIENTNAME_LENGTH + 1]; + WCHAR Domain[DOMAIN_LENGTH + 1]; + WCHAR UserName[USERNAME_LENGTH + 1]; + WCHAR WorkDirectory[MAX_PATH + 1]; + WCHAR InitialProgram[MAX_PATH + 1]; + BYTE EncryptionLevel; + ULONG ClientAddressFamily; + USHORT ClientAddress[CLIENTADDRESS_LENGTH + 1]; + USHORT HRes; + USHORT VRes; + USHORT ColorDepth; + WCHAR ClientDirectory[MAX_PATH + 1]; + ULONG ClientBuildNumber; + ULONG ClientHardwareId; + USHORT ClientProductId; + USHORT OutBufCountHost; + USHORT OutBufCountClient; + USHORT OutBufLength; + WCHAR DeviceId[MAX_PATH + 1]; +} WTSCLIENTW, *PWTSCLIENTW; + +typedef struct _WTSCLIENTA +{ + CHAR ClientName[CLIENTNAME_LENGTH + 1]; + CHAR Domain[DOMAIN_LENGTH + 1]; + CHAR UserName[USERNAME_LENGTH + 1]; + CHAR WorkDirectory[MAX_PATH + 1]; + CHAR InitialProgram[MAX_PATH + 1]; + BYTE EncryptionLevel; + ULONG ClientAddressFamily; + USHORT ClientAddress[CLIENTADDRESS_LENGTH + 1]; + USHORT HRes; + USHORT VRes; + USHORT ColorDepth; + CHAR ClientDirectory[MAX_PATH + 1]; + ULONG ClientBuildNumber; + ULONG ClientHardwareId; + USHORT ClientProductId; + USHORT OutBufCountHost; + USHORT OutBufCountClient; + USHORT OutBufLength; + CHAR DeviceId[MAX_PATH + 1]; +} WTSCLIENTA, *PWTSCLIENTA; + +#define PRODUCTINFO_COMPANYNAME_LENGTH 256 +#define PRODUCTINFO_PRODUCTID_LENGTH 4 + +typedef struct _WTS_PRODUCT_INFOA +{ + CHAR CompanyName[PRODUCTINFO_COMPANYNAME_LENGTH]; + CHAR ProductID[PRODUCTINFO_PRODUCTID_LENGTH]; +} PRODUCT_INFOA; + +typedef struct _WTS_PRODUCT_INFOW +{ + WCHAR CompanyName[PRODUCTINFO_COMPANYNAME_LENGTH]; + WCHAR ProductID[PRODUCTINFO_PRODUCTID_LENGTH]; +} PRODUCT_INFOW; + +#define VALIDATIONINFORMATION_LICENSE_LENGTH 16384 +#define VALIDATIONINFORMATION_HARDWAREID_LENGTH 20 + +typedef struct _WTS_VALIDATION_INFORMATIONA +{ + PRODUCT_INFOA ProductInfo; + BYTE License[VALIDATIONINFORMATION_LICENSE_LENGTH]; + DWORD LicenseLength; + BYTE HardwareID[VALIDATIONINFORMATION_HARDWAREID_LENGTH]; + DWORD HardwareIDLength; +} WTS_VALIDATION_INFORMATIONA, *PWTS_VALIDATION_INFORMATIONA; + +typedef struct _WTS_VALIDATION_INFORMATIONW +{ + PRODUCT_INFOW ProductInfo; + BYTE License[VALIDATIONINFORMATION_LICENSE_LENGTH]; + DWORD LicenseLength; + BYTE HardwareID[VALIDATIONINFORMATION_HARDWAREID_LENGTH]; + DWORD HardwareIDLength; +} WTS_VALIDATION_INFORMATIONW, *PWTS_VALIDATION_INFORMATIONW; + +typedef struct _WTS_CLIENT_ADDRESS +{ + DWORD AddressFamily; + BYTE Address[20]; +} WTS_CLIENT_ADDRESS, *PWTS_CLIENT_ADDRESS; + +typedef struct _WTS_CLIENT_DISPLAY +{ + DWORD HorizontalResolution; + DWORD VerticalResolution; + DWORD ColorDepth; +} WTS_CLIENT_DISPLAY, *PWTS_CLIENT_DISPLAY; + +typedef enum _WTS_CONFIG_CLASS +{ + WTSUserConfigInitialProgram, + WTSUserConfigWorkingDirectory, + WTSUserConfigfInheritInitialProgram, + WTSUserConfigfAllowLogonTerminalServer, + WTSUserConfigTimeoutSettingsConnections, + WTSUserConfigTimeoutSettingsDisconnections, + WTSUserConfigTimeoutSettingsIdle, + WTSUserConfigfDeviceClientDrives, + WTSUserConfigfDeviceClientPrinters, + WTSUserConfigfDeviceClientDefaultPrinter, + WTSUserConfigBrokenTimeoutSettings, + WTSUserConfigReconnectSettings, + WTSUserConfigModemCallbackSettings, + WTSUserConfigModemCallbackPhoneNumber, + WTSUserConfigShadowingSettings, + WTSUserConfigTerminalServerProfilePath, + WTSUserConfigTerminalServerHomeDir, + WTSUserConfigTerminalServerHomeDirDrive, + WTSUserConfigfTerminalServerRemoteHomeDir, + WTSUserConfigUser, +} WTS_CONFIG_CLASS; + +typedef enum _WTS_CONFIG_SOURCE +{ + WTSUserConfigSourceSAM +} WTS_CONFIG_SOURCE; + +typedef struct _WTSUSERCONFIGA +{ + DWORD Source; + DWORD InheritInitialProgram; + DWORD AllowLogonTerminalServer; + DWORD TimeoutSettingsConnections; + DWORD TimeoutSettingsDisconnections; + DWORD TimeoutSettingsIdle; + DWORD DeviceClientDrives; + DWORD DeviceClientPrinters; + DWORD ClientDefaultPrinter; + DWORD BrokenTimeoutSettings; + DWORD ReconnectSettings; + DWORD ShadowingSettings; + DWORD TerminalServerRemoteHomeDir; + CHAR InitialProgram[MAX_PATH + 1]; + CHAR WorkDirectory[MAX_PATH + 1]; + CHAR TerminalServerProfilePath[MAX_PATH + 1]; + CHAR TerminalServerHomeDir[MAX_PATH + 1]; + CHAR TerminalServerHomeDirDrive[WTS_DRIVE_LENGTH + 1]; +} WTSUSERCONFIGA, *PWTSUSERCONFIGA; + +typedef struct _WTSUSERCONFIGW +{ + DWORD Source; + DWORD InheritInitialProgram; + DWORD AllowLogonTerminalServer; + DWORD TimeoutSettingsConnections; + DWORD TimeoutSettingsDisconnections; + DWORD TimeoutSettingsIdle; + DWORD DeviceClientDrives; + DWORD DeviceClientPrinters; + DWORD ClientDefaultPrinter; + DWORD BrokenTimeoutSettings; + DWORD ReconnectSettings; + DWORD ShadowingSettings; + DWORD TerminalServerRemoteHomeDir; + WCHAR InitialProgram[MAX_PATH + 1]; + WCHAR WorkDirectory[MAX_PATH + 1]; + WCHAR TerminalServerProfilePath[MAX_PATH + 1]; + WCHAR TerminalServerHomeDir[MAX_PATH + 1]; + WCHAR TerminalServerHomeDirDrive[WTS_DRIVE_LENGTH + 1]; +} WTSUSERCONFIGW, *PWTSUSERCONFIGW; + +#define WTS_EVENT_NONE 0x00000000 +#define WTS_EVENT_CREATE 0x00000001 +#define WTS_EVENT_DELETE 0x00000002 +#define WTS_EVENT_RENAME 0x00000004 +#define WTS_EVENT_CONNECT 0x00000008 +#define WTS_EVENT_DISCONNECT 0x00000010 +#define WTS_EVENT_LOGON 0x00000020 +#define WTS_EVENT_LOGOFF 0x00000040 +#define WTS_EVENT_STATECHANGE 0x00000080 +#define WTS_EVENT_LICENSE 0x00000100 +#define WTS_EVENT_ALL 0x7fffffff +#define WTS_EVENT_FLUSH 0x80000000 + +#define REMOTECONTROL_KBDSHIFT_HOTKEY 0x1 +#define REMOTECONTROL_KBDCTRL_HOTKEY 0x2 +#define REMOTECONTROL_KBDALT_HOTKEY 0x4 + +typedef enum _WTS_VIRTUAL_CLASS +{ + WTSVirtualClientData, + WTSVirtualFileHandle, + WTSVirtualEventHandle, /* Extended */ + WTSVirtualChannelReady /* Extended */ +} WTS_VIRTUAL_CLASS; + +typedef struct _WTS_SESSION_ADDRESS +{ + DWORD AddressFamily; + BYTE Address[20]; +} WTS_SESSION_ADDRESS, *PWTS_SESSION_ADDRESS; + +#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW 0x00000000 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED 0x00000002 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH 0x00000004 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL 0x00000006 +#define WTS_CHANNEL_OPTION_DYNAMIC_NO_COMPRESS 0x00000008 + +#define NOTIFY_FOR_ALL_SESSIONS 1 +#define NOTIFY_FOR_THIS_SESSION 0 + +#define WTS_PROCESS_INFO_LEVEL_0 0 +#define WTS_PROCESS_INFO_LEVEL_1 1 + +typedef struct _WTS_PROCESS_INFO_EXW +{ + DWORD SessionId; + DWORD ProcessId; + LPWSTR pProcessName; + PSID pUserSid; + DWORD NumberOfThreads; + DWORD HandleCount; + DWORD PagefileUsage; + DWORD PeakPagefileUsage; + DWORD WorkingSetSize; + DWORD PeakWorkingSetSize; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; +} WTS_PROCESS_INFO_EXW, *PWTS_PROCESS_INFO_EXW; + +typedef struct _WTS_PROCESS_INFO_EXA +{ + DWORD SessionId; + DWORD ProcessId; + LPSTR pProcessName; + PSID pUserSid; + DWORD NumberOfThreads; + DWORD HandleCount; + DWORD PagefileUsage; + DWORD PeakPagefileUsage; + DWORD WorkingSetSize; + DWORD PeakWorkingSetSize; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; +} WTS_PROCESS_INFO_EXA, *PWTS_PROCESS_INFO_EXA; + +typedef enum _WTS_TYPE_CLASS +{ + WTSTypeProcessInfoLevel0, + WTSTypeProcessInfoLevel1, + WTSTypeSessionInfoLevel1, +} WTS_TYPE_CLASS; + +typedef WCHAR WTSLISTENERNAMEW[WTS_LISTENER_NAME_LENGTH + 1]; +typedef WTSLISTENERNAMEW *PWTSLISTENERNAMEW; +typedef CHAR WTSLISTENERNAMEA[WTS_LISTENER_NAME_LENGTH + 1]; +typedef WTSLISTENERNAMEA *PWTSLISTENERNAMEA; + +typedef struct _WTSLISTENERCONFIGW +{ + ULONG version; + ULONG fEnableListener; + ULONG MaxConnectionCount; + ULONG fPromptForPassword; + ULONG fInheritColorDepth; + ULONG ColorDepth; + ULONG fInheritBrokenTimeoutSettings; + ULONG BrokenTimeoutSettings; + ULONG fDisablePrinterRedirection; + ULONG fDisableDriveRedirection; + ULONG fDisableComPortRedirection; + ULONG fDisableLPTPortRedirection; + ULONG fDisableClipboardRedirection; + ULONG fDisableAudioRedirection; + ULONG fDisablePNPRedirection; + ULONG fDisableDefaultMainClientPrinter; + ULONG LanAdapter; + ULONG PortNumber; + ULONG fInheritShadowSettings; + ULONG ShadowSettings; + ULONG TimeoutSettingsConnection; + ULONG TimeoutSettingsDisconnection; + ULONG TimeoutSettingsIdle; + ULONG SecurityLayer; + ULONG MinEncryptionLevel; + ULONG UserAuthentication; + WCHAR Comment[WTS_COMMENT_LENGTH + 1]; + WCHAR LogonUserName[USERNAME_LENGTH + 1]; + WCHAR LogonDomain[DOMAIN_LENGTH + 1]; + WCHAR WorkDirectory[MAX_PATH + 1]; + WCHAR InitialProgram[MAX_PATH + 1]; +} WTSLISTENERCONFIGW, *PWTSLISTENERCONFIGW; + +typedef struct _WTSLISTENERCONFIGA +{ + ULONG version; + ULONG fEnableListener; + ULONG MaxConnectionCount; + ULONG fPromptForPassword; + ULONG fInheritColorDepth; + ULONG ColorDepth; + ULONG fInheritBrokenTimeoutSettings; + ULONG BrokenTimeoutSettings; + ULONG fDisablePrinterRedirection; + ULONG fDisableDriveRedirection; + ULONG fDisableComPortRedirection; + ULONG fDisableLPTPortRedirection; + ULONG fDisableClipboardRedirection; + ULONG fDisableAudioRedirection; + ULONG fDisablePNPRedirection; + ULONG fDisableDefaultMainClientPrinter; + ULONG LanAdapter; + ULONG PortNumber; + ULONG fInheritShadowSettings; + ULONG ShadowSettings; + ULONG TimeoutSettingsConnection; + ULONG TimeoutSettingsDisconnection; + ULONG TimeoutSettingsIdle; + ULONG SecurityLayer; + ULONG MinEncryptionLevel; + ULONG UserAuthentication; + CHAR Comment[WTS_COMMENT_LENGTH + 1]; + CHAR LogonUserName[USERNAME_LENGTH + 1]; + CHAR LogonDomain[DOMAIN_LENGTH + 1]; + CHAR WorkDirectory[MAX_PATH + 1]; + CHAR InitialProgram[MAX_PATH + 1]; +} WTSLISTENERCONFIGA, *PWTSLISTENERCONFIGA; + +#ifdef UNICODE +#define WTS_SERVER_INFO WTS_SERVER_INFOW +#define PWTS_SERVER_INFO PWTS_SERVER_INFOW +#define WTS_SESSION_INFO WTS_SESSION_INFOW +#define PWTS_SESSION_INFO PWTS_SESSION_INFOW +#define WTS_SESSION_INFO_1 WTS_SESSION_INFO_1W +#define PWTS_SESSION_INFO_1 PWTS_SESSION_INFO_1W +#define WTS_PROCESS_INFO WTS_PROCESS_INFOW +#define PWTS_PROCESS_INFO PWTS_PROCESS_INFOW +#define WTSCONFIGINFO WTSCONFIGINFOW +#define PWTSCONFIGINFO PWTSCONFIGINFOW +#define WTSINFO WTSINFOW +#define PWTSINFO PWTSINFOW +#define WTSINFOEX WTSINFOEXW +#define PWTSINFOEX PWTSINFOEXW +#define WTSINFOEX_LEVEL WTSINFOEX_LEVEL_W +#define PWTSINFOEX_LEVEL PWTSINFOEX_LEVEL_W +#define WTSINFOEX_LEVEL1 WTSINFOEX_LEVEL1_W +#define PWTSINFOEX_LEVEL1 PWTSINFOEX_LEVEL1_W +#define WTSCLIENT WTSCLIENTW +#define PWTSCLIENT PWTSCLIENTW +#define PRODUCT_INFO PRODUCT_INFOW +#define WTS_VALIDATION_INFORMATION WTS_VALIDATION_INFORMATIONW +#define PWTS_VALIDATION_INFORMATION PWTS_VALIDATION_INFORMATIONW +#define WTSUSERCONFIG WTSUSERCONFIGW +#define PWTSUSERCONFIG PWTSUSERCONFIGW +#define WTS_PROCESS_INFO_EX WTS_PROCESS_INFO_EXW +#define PWTS_PROCESS_INFO_EX PWTS_PROCESS_INFO_EXW +#define WTSLISTENERNAME WTSLISTENERNAMEW +#define PWTSLISTENERNAME PWTSLISTENERNAMEW +#define WTSLISTENERCONFIG WTSLISTENERCONFIGW +#define PWTSLISTENERCONFIG PWTSLISTENERCONFIGW +#else +#define WTS_SERVER_INFO WTS_SERVER_INFOA +#define PWTS_SERVER_INFO PWTS_SERVER_INFOA +#define WTS_SESSION_INFO WTS_SESSION_INFOA +#define PWTS_SESSION_INFO PWTS_SESSION_INFOA +#define WTS_SESSION_INFO_1 WTS_SESSION_INFO_1A +#define PWTS_SESSION_INFO_1 PWTS_SESSION_INFO_1A +#define WTS_PROCESS_INFO WTS_PROCESS_INFOA +#define PWTS_PROCESS_INFO PWTS_PROCESS_INFOA +#define WTSCONFIGINFO WTSCONFIGINFOA +#define PWTSCONFIGINFO PWTSCONFIGINFOA +#define WTSINFO WTSINFOA +#define PWTSINFO PWTSINFOA +#define WTSINFOEX WTSINFOEXA +#define PWTSINFOEX PWTSINFOEXA +#define WTSINFOEX_LEVEL WTSINFOEX_LEVEL_A +#define PWTSINFOEX_LEVEL PWTSINFOEX_LEVEL_A +#define WTSINFOEX_LEVEL1 WTSINFOEX_LEVEL1_A +#define PWTSINFOEX_LEVEL1 PWTSINFOEX_LEVEL1_A +#define WTSCLIENT WTSCLIENTA +#define PWTSCLIENT PWTSCLIENTA +#define PRODUCT_INFO PRODUCT_INFOA +#define WTS_VALIDATION_INFORMATION WTS_VALIDATION_INFORMATIONA +#define PWTS_VALIDATION_INFORMATION PWTS_VALIDATION_INFORMATIONA +#define WTSUSERCONFIG WTSUSERCONFIGA +#define PWTSUSERCONFIG PWTSUSERCONFIGA +#define WTS_PROCESS_INFO_EX WTS_PROCESS_INFO_EXA +#define PWTS_PROCESS_INFO_EX PWTS_PROCESS_INFO_EXA +#define WTSLISTENERNAME WTSLISTENERNAMEA +#define PWTSLISTENERNAME PWTSLISTENERNAMEA +#define WTSLISTENERCONFIG WTSLISTENERCONFIGA +#define PWTSLISTENERCONFIG PWTSLISTENERCONFIGA +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +WINPR_API BOOL WTSStopRemoteControlSession(ULONG LogonId); + +WINPR_API BOOL WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers); +WINPR_API BOOL WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers); + +WINPR_API BOOL WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait); +WINPR_API BOOL WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait); + +WINPR_API BOOL WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount); +WINPR_API BOOL WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount); + +WINPR_API HANDLE WTSOpenServerW(LPWSTR pServerName); +WINPR_API HANDLE WTSOpenServerA(LPSTR pServerName); + +WINPR_API HANDLE WTSOpenServerExW(LPWSTR pServerName); +WINPR_API HANDLE WTSOpenServerExA(LPSTR pServerName); + +WINPR_API VOID WTSCloseServer(HANDLE hServer); + +WINPR_API BOOL WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount); +WINPR_API BOOL WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount); + +WINPR_API BOOL WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount); +WINPR_API BOOL WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount); + +WINPR_API BOOL WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount); +WINPR_API BOOL WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount); + +WINPR_API BOOL WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode); + +WINPR_API BOOL WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned); +WINPR_API BOOL WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer, DWORD* pBytesReturned); + +WINPR_API BOOL WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned); +WINPR_API BOOL WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer, DWORD* pBytesReturned); + +WINPR_API BOOL WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength); +WINPR_API BOOL WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer, DWORD DataLength); + +WINPR_API BOOL WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength, + LPWSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait); +WINPR_API BOOL WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle, DWORD TitleLength, + LPSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait); + +WINPR_API BOOL WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait); + +WINPR_API BOOL WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait); + +WINPR_API BOOL WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag); + +WINPR_API BOOL WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags); + +WINPR_API HANDLE WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName); + +WINPR_API HANDLE WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags); + +WINPR_API BOOL WTSVirtualChannelClose(HANDLE hChannelHandle); + +WINPR_API BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead); + +WINPR_API BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten); + +WINPR_API BOOL WTSVirtualChannelPurgeInput(HANDLE hChannelHandle); + +WINPR_API BOOL WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle); + +WINPR_API BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned); + +WINPR_API VOID WTSFreeMemory(PVOID pMemory); + +WINPR_API BOOL WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags); + +WINPR_API BOOL WTSUnRegisterSessionNotification(HWND hWnd); + +WINPR_API BOOL WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags); + +WINPR_API BOOL WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd); + +WINPR_API BOOL WTSQueryUserToken(ULONG SessionId, PHANDLE phToken); + +WINPR_API BOOL WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries); +WINPR_API BOOL WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries); + +WINPR_API BOOL WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPWSTR* ppProcessInfo, DWORD* pCount); +WINPR_API BOOL WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPSTR* ppProcessInfo, DWORD* pCount); + +WINPR_API BOOL WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEW pListeners, DWORD* pCount); +WINPR_API BOOL WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEA pListeners, DWORD* pCount); + +WINPR_API BOOL WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer); +WINPR_API BOOL WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer); + +WINPR_API BOOL WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer, DWORD flag); +WINPR_API BOOL WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag); + +WINPR_API BOOL WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor); +WINPR_API BOOL WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor); + +WINPR_API BOOL WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded); +WINPR_API BOOL WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded); + +WINPR_API BOOL WTSEnableChildSessions(BOOL bEnable); + +WINPR_API BOOL WTSIsChildSessionsEnabled(PBOOL pbEnabled); + +WINPR_API BOOL WTSGetChildSessionId(PULONG pSessionId); + +#ifdef __cplusplus +} +#endif + +#ifdef UNICODE +#define WTSStartRemoteControlSession WTSStartRemoteControlSessionW +#define WTSConnectSession WTSConnectSessionW +#define WTSEnumerateServers WTSEnumerateServersW +#define WTSOpenServer WTSOpenServerW +#define WTSOpenServerEx WTSOpenServerExW +#define WTSEnumerateSessions WTSEnumerateSessionsW +#define WTSEnumerateSessionsEx WTSEnumerateSessionsExW +#define WTSEnumerateProcesses WTSEnumerateProcessesW +#define WTSQuerySessionInformation WTSQuerySessionInformationW +#define WTSQueryUserConfig WTSQueryUserConfigW +#define WTSSetUserConfig WTSSetUserConfigW +#define WTSSendMessage WTSSendMessageW +#define WTSFreeMemoryEx WTSFreeMemoryExW +#define WTSEnumerateProcessesEx WTSEnumerateProcessesExW +#define WTSEnumerateListeners WTSEnumerateListenersW +#define WTSQueryListenerConfig WTSQueryListenerConfigW +#define WTSCreateListener WTSCreateListenerW +#define WTSSetListenerSecurity WTSSetListenerSecurityW +#define WTSGetListenerSecurity WTSGetListenerSecurityW +#else +#define WTSStartRemoteControlSession WTSStartRemoteControlSessionA +#define WTSConnectSession WTSConnectSessionA +#define WTSEnumerateServers WTSEnumerateServersA +#define WTSOpenServer WTSOpenServerA +#define WTSOpenServerEx WTSOpenServerExA +#define WTSEnumerateSessions WTSEnumerateSessionsA +#define WTSEnumerateSessionsEx WTSEnumerateSessionsExA +#define WTSEnumerateProcesses WTSEnumerateProcessesA +#define WTSQuerySessionInformation WTSQuerySessionInformationA +#define WTSQueryUserConfig WTSQueryUserConfigA +#define WTSSetUserConfig WTSSetUserConfigA +#define WTSSendMessage WTSSendMessageA +#define WTSFreeMemoryEx WTSFreeMemoryExA +#define WTSEnumerateProcessesEx WTSEnumerateProcessesExA +#define WTSEnumerateListeners WTSEnumerateListenersA +#define WTSQueryListenerConfig WTSQueryListenerConfigA +#define WTSCreateListener WTSCreateListenerA +#define WTSSetListenerSecurity WTSSetListenerSecurityA +#define WTSGetListenerSecurity WTSGetListenerSecurityA +#endif + +#endif + +#endif /* WINPR_WTSAPI_H */ + diff --git a/winpr/include/winpr/wtypes.h b/winpr/include/winpr/wtypes.h index c05e1b86c..d3639d771 100644 --- a/winpr/include/winpr/wtypes.h +++ b/winpr/include/winpr/wtypes.h @@ -83,6 +83,8 @@ typedef short SHORT; typedef void* HANDLE, *PHANDLE, *LPHANDLE; typedef HANDLE HINSTANCE; typedef HANDLE HMODULE; +typedef HANDLE HWND; +typedef HANDLE HBITMAP; typedef DWORD HCALL; typedef int INT, *LPINT; @@ -113,7 +115,6 @@ typedef WCHAR* LPWSTR, *PWSTR, *LPWCH; typedef const WCHAR *LPCWSTR,*PCWSTR; typedef unsigned __int64 QWORD; -typedef UCHAR* STRING; typedef unsigned int UINT; typedef unsigned char UINT8; @@ -158,6 +159,9 @@ typedef struct _LUID LONG HighPart; } LUID, *PLUID; +typedef GUID IID; +typedef IID* REFIID; + #ifdef UNICODE #define _T(x) L ## x #else diff --git a/winpr/libwinpr/CMakeLists.txt b/winpr/libwinpr/CMakeLists.txt index c5c2c6ece..a0d0f612c 100644 --- a/winpr/libwinpr/CMakeLists.txt +++ b/winpr/libwinpr/CMakeLists.txt @@ -55,9 +55,7 @@ if(MONOLITHIC_BUILD) target_link_libraries(${MODULE_NAME} ${WINPR_LIBS}) -if(NOT WITH_WAYK) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) -endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/libwinpr") endif() diff --git a/winpr/libwinpr/com/CMakeLists.txt b/winpr/libwinpr/com/CMakeLists.txt new file mode 100644 index 000000000..826c678f3 --- /dev/null +++ b/winpr/libwinpr/com/CMakeLists.txt @@ -0,0 +1,49 @@ +# WinPR: Windows Portable Runtime +# libwinpr-com cmake build script +# +# Copyright 2013 Marc-Andre Moreau +# +# 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-com") +set(MODULE_PREFIX "WINPR_COM") + +set(${MODULE_PREFIX}_SRCS + com.c) + +if(MSVC AND (NOT MONOLITHIC_BUILD)) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) +endif() + +add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" + MONOLITHIC ${MONOLITHIC_BUILD} + SOURCES ${${MODULE_PREFIX}_SRCS}) + +set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib") + +if(WIN32) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} credui) +endif() + +if(MONOLITHIC_BUILD) + set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) +else() + target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR") + +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/winpr/libwinpr/com/ModuleOptions.cmake b/winpr/libwinpr/com/ModuleOptions.cmake new file mode 100644 index 000000000..37c3b962a --- /dev/null +++ b/winpr/libwinpr/com/ModuleOptions.cmake @@ -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 "com") +set(MINWIN_LONG_NAME "Component Object Model (COM)") +set(MODULE_LIBRARY_NAME "api-ms-win-${MINWIN_GROUP}-${MINWIN_SHORT_NAME}-l${MINWIN_LAYER}-${MINWIN_MAJOR_VERSION}-${MINWIN_MINOR_VERSION}") + diff --git a/winpr/libwinpr/com/com.c b/winpr/libwinpr/com/com.c new file mode 100644 index 000000000..97332a070 --- /dev/null +++ b/winpr/libwinpr/com/com.c @@ -0,0 +1,115 @@ +/** + * WinPR: Windows Portable Runtime + * Component Object Model (COM) + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/** + * api-ms-win-core-com-l1-1-0.dll: + * + * CLSIDFromProgID + * CLSIDFromString + * CoAddRefServerProcess + * CoAllowUnmarshalerCLSID + * CoCancelCall + * CoCopyProxy + * CoCreateFreeThreadedMarshaler + * CoCreateGuid + * CoCreateInstance + * CoCreateInstanceEx + * CoCreateInstanceFromApp + * CoDecodeProxy + * CoDecrementMTAUsage + * CoDisableCallCancellation + * CoDisconnectContext + * CoDisconnectObject + * CoEnableCallCancellation + * CoFreeUnusedLibraries + * CoFreeUnusedLibrariesEx + * CoGetApartmentType + * CoGetCallContext + * CoGetCallerTID + * CoGetCancelObject + * CoGetClassObject + * CoGetContextToken + * CoGetCurrentLogicalThreadId + * CoGetCurrentProcess + * CoGetDefaultContext + * CoGetInterfaceAndReleaseStream + * CoGetMalloc + * CoGetMarshalSizeMax + * CoGetObjectContext + * CoGetPSClsid + * CoGetStandardMarshal + * CoGetStdMarshalEx + * CoGetTreatAsClass + * CoImpersonateClient + * CoIncrementMTAUsage + * CoInitializeEx + * CoInitializeSecurity + * CoInvalidateRemoteMachineBindings + * CoIsHandlerConnected + * CoLockObjectExternal + * CoMarshalHresult + * CoMarshalInterface + * CoMarshalInterThreadInterfaceInStream + * CoQueryAuthenticationServices + * CoQueryClientBlanket + * CoQueryProxyBlanket + * CoRegisterClassObject + * CoRegisterPSClsid + * CoRegisterSurrogate + * CoReleaseMarshalData + * CoReleaseServerProcess + * CoResumeClassObjects + * CoRevertToSelf + * CoRevokeClassObject + * CoSetCancelObject + * CoSetProxyBlanket + * CoSuspendClassObjects + * CoSwitchCallContext + * CoTaskMemAlloc + * CoTaskMemFree + * CoTaskMemRealloc + * CoTestCancel + * CoUninitialize + * CoUnmarshalHresult + * CoUnmarshalInterface + * CoWaitForMultipleHandles + * CoWaitForMultipleObjects + * CreateStreamOnHGlobal + * FreePropVariantArray + * GetHGlobalFromStream + * IIDFromString + * ProgIDFromCLSID + * PropVariantClear + * PropVariantCopy + * StringFromCLSID + * StringFromGUID2 + * StringFromIID + */ + +#ifndef _WIN32 + + + +#endif diff --git a/winpr/libwinpr/com/module.def b/winpr/libwinpr/com/module.def new file mode 100644 index 000000000..4467b6c7b --- /dev/null +++ b/winpr/libwinpr/com/module.def @@ -0,0 +1,2 @@ +LIBRARY "libwinpr-com" +EXPORTS diff --git a/winpr/libwinpr/com/test/.gitignore b/winpr/libwinpr/com/test/.gitignore new file mode 100644 index 000000000..4a027eed9 --- /dev/null +++ b/winpr/libwinpr/com/test/.gitignore @@ -0,0 +1,3 @@ +TestCom +TestCom.c + diff --git a/winpr/libwinpr/com/test/CMakeLists.txt b/winpr/libwinpr/com/test/CMakeLists.txt new file mode 100644 index 000000000..94e42c352 --- /dev/null +++ b/winpr/libwinpr/com/test/CMakeLists.txt @@ -0,0 +1,31 @@ + +set(MODULE_NAME "TestCom") +set(MODULE_PREFIX "TEST_COM") + +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) + +set(${MODULE_PREFIX}_TESTS + TestComReference.c) + +create_test_sourcelist(${MODULE_PREFIX}_SRCS + ${${MODULE_PREFIX}_DRIVER} + ${${MODULE_PREFIX}_TESTS}) + +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE winpr + MODULES winpr-crt winpr-com) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}") + +foreach(test ${${MODULE_PREFIX}_TESTS}) + get_filename_component(TestName ${test} NAME_WE) + add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName}) +endforeach() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test") + diff --git a/winpr/libwinpr/com/test/TestComReference.c b/winpr/libwinpr/com/test/TestComReference.c new file mode 100644 index 000000000..4b26f3da3 --- /dev/null +++ b/winpr/libwinpr/com/test/TestComReference.c @@ -0,0 +1,8 @@ + +#include + +int TestComReference(int argc, char* argv[]) +{ + return 0; +} + diff --git a/winpr/libwinpr/dummy.c b/winpr/libwinpr/dummy.c index b959f9be3..bd2de4583 100644 --- a/winpr/libwinpr/dummy.c +++ b/winpr/libwinpr/dummy.c @@ -1,5 +1,5 @@ -int dummy() +int winpr_dummy() { return 0; } diff --git a/winpr/libwinpr/error/CMakeLists.txt b/winpr/libwinpr/error/CMakeLists.txt index db6780490..eb78993c6 100644 --- a/winpr/libwinpr/error/CMakeLists.txt +++ b/winpr/libwinpr/error/CMakeLists.txt @@ -31,10 +31,20 @@ add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib") +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL + MODULE winpr + MODULES winpr-nt) + if(MONOLITHIC_BUILD) else() + target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR") + +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/winpr/libwinpr/error/error.c b/winpr/libwinpr/error/error.c index ff11daa6b..96c35cd6c 100644 --- a/winpr/libwinpr/error/error.c +++ b/winpr/libwinpr/error/error.c @@ -23,25 +23,12 @@ #include -/** - * api-ms-win-core-errorhandling-l1-1-1.dll: - * - * GetErrorMode - * SetErrorMode - * GetLastError - * SetLastError - * RestoreLastError - * RaiseException - * UnhandledExceptionFilter - * SetUnhandledExceptionFilter - * AddVectoredExceptionHandler - * RemoveVectoredExceptionHandler - * AddVectoredContinueHandler - * RemoveVectoredContinueHandler - */ - #ifndef _WIN32 +#include + +#include + UINT GetErrorMode(void) { return 0; @@ -54,12 +41,12 @@ UINT SetErrorMode(UINT uMode) DWORD GetLastError(VOID) { - return 0; + return NtCurrentTeb()->LastErrorValue; } VOID SetLastError(DWORD dwErrCode) { - + NtCurrentTeb()->LastErrorValue = dwErrCode; } VOID RestoreLastError(DWORD dwErrCode) diff --git a/winpr/libwinpr/error/test/.gitignore b/winpr/libwinpr/error/test/.gitignore new file mode 100644 index 000000000..8f1dcb16a --- /dev/null +++ b/winpr/libwinpr/error/test/.gitignore @@ -0,0 +1,3 @@ +TestError +TestError.c + diff --git a/winpr/libwinpr/error/test/CMakeLists.txt b/winpr/libwinpr/error/test/CMakeLists.txt new file mode 100644 index 000000000..ecec7093f --- /dev/null +++ b/winpr/libwinpr/error/test/CMakeLists.txt @@ -0,0 +1,31 @@ + +set(MODULE_NAME "TestError") +set(MODULE_PREFIX "TEST_ERROR") + +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) + +set(${MODULE_PREFIX}_TESTS + TestErrorSetLastError.c) + +create_test_sourcelist(${MODULE_PREFIX}_SRCS + ${${MODULE_PREFIX}_DRIVER} + ${${MODULE_PREFIX}_TESTS}) + +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE winpr + MODULES winpr-crt winpr-synch winpr-thread winpr-error) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}") + +foreach(test ${${MODULE_PREFIX}_TESTS}) + get_filename_component(TestName ${test} NAME_WE) + add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName}) +endforeach() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test") + diff --git a/winpr/libwinpr/error/test/TestErrorSetLastError.c b/winpr/libwinpr/error/test/TestErrorSetLastError.c new file mode 100644 index 000000000..073417adc --- /dev/null +++ b/winpr/libwinpr/error/test/TestErrorSetLastError.c @@ -0,0 +1,89 @@ + +#include +#include +#include + +#include + +static int status = 0; + +static DWORD errors[4] = +{ + ERROR_INVALID_DATA, + ERROR_BROKEN_PIPE, + ERROR_INVALID_NAME, + ERROR_BAD_ARGUMENTS +}; + +static void* test_error_thread(void* arg) +{ + int id; + DWORD error; + + id = (int) (size_t) arg; + + error = errors[id]; + + SetLastError(error); + + Sleep(10); + + error = GetLastError(); + + if (error != errors[id]) + { + printf("GetLastError() failure (thread %d): Expected: 0x%04X, Actual: 0x%04X\n", + id, errors[id], error); + + if (!status) + status = -1; + + return NULL; + } + + return NULL; +} + +int TestErrorSetLastError(int argc, char* argv[]) +{ + DWORD error; + HANDLE threads[4]; + + SetLastError(ERROR_ACCESS_DENIED); + + error = GetLastError(); + + if (error != ERROR_ACCESS_DENIED) + { + printf("GetLastError() failure: Expected: 0x%04X, Actual: 0x%04X\n", + ERROR_ACCESS_DENIED, error); + return -1; + } + + threads[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_error_thread, (void*) (size_t) 0, 0, NULL); + threads[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_error_thread, (void*) (size_t) 1, 0, NULL); + threads[2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_error_thread, (void*) (size_t) 2, 0, NULL); + threads[3] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_error_thread, (void*) (size_t) 3, 0, NULL); + + WaitForSingleObject(threads[0], INFINITE); + WaitForSingleObject(threads[1], INFINITE); + WaitForSingleObject(threads[2], INFINITE); + WaitForSingleObject(threads[3], INFINITE); + + CloseHandle(threads[0]); + CloseHandle(threads[1]); + CloseHandle(threads[2]); + CloseHandle(threads[3]); + + error = GetLastError(); + + if (error != ERROR_ACCESS_DENIED) + { + printf("GetLastError() failure: Expected: 0x%04X, Actual: 0x%04X\n", + ERROR_ACCESS_DENIED, error); + return -1; + } + + return status; +} + diff --git a/winpr/libwinpr/file/CMakeLists.txt b/winpr/libwinpr/file/CMakeLists.txt index 7ab377c6d..9014f4cda 100644 --- a/winpr/libwinpr/file/CMakeLists.txt +++ b/winpr/libwinpr/file/CMakeLists.txt @@ -31,7 +31,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SO set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL MODULE winpr - MODULES winpr-crt winpr-handle winpr-path) + MODULES winpr-crt winpr-handle winpr-path winpr-synch) if(MONOLITHIC_BUILD) diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index b296d34ee..feb673c77 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -23,7 +23,9 @@ #include #include +#include #include +#include #include @@ -124,6 +126,21 @@ * http://download.microsoft.com/download/4/3/8/43889780-8d45-4b2e-9d3a-c696a890309f/File%20System%20Behavior%20Overview.pdf */ +/** + * Asynchronous I/O - The GNU C Library: + * http://www.gnu.org/software/libc/manual/html_node/Asynchronous-I_002fO.html + */ + +/** + * aio.h - asynchronous input and output: + * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/aio.h.html + */ + +/** + * Asynchronous I/O User Guide: + * http://code.google.com/p/kernel/wiki/AIOUserGuide + */ + #ifndef _WIN32 #ifdef HAVE_UNISTD_H @@ -142,6 +159,14 @@ #include #include +#ifdef HAVE_AIO_H +#undef HAVE_AIO_H /* disable for now, incomplete */ +#endif + +#ifdef HAVE_AIO_H +#include +#endif + #ifdef ANDROID #include #else @@ -184,6 +209,7 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, pNamedPipe->nOutBufferSize = 0; pNamedPipe->nInBufferSize = 0; pNamedPipe->nDefaultTimeOut = 0; + pNamedPipe->dwFlagsAndAttributes = dwFlagsAndAttributes; pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName); pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName); @@ -259,20 +285,66 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, pipe = (WINPR_NAMED_PIPE*) Object; - status = nNumberOfBytesToRead; - - if (pipe->clientfd != -1) - status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead); - else - return FALSE; - - if (status < 0) + if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)) { - *lpNumberOfBytesRead = 0; - return FALSE; - } + status = nNumberOfBytesToRead; - *lpNumberOfBytesRead = status; + if (pipe->clientfd == -1) + return FALSE; + + status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead); + + if (status < 0) + { + *lpNumberOfBytesRead = 0; + return FALSE; + } + + *lpNumberOfBytesRead = status; + } + else + { + /* Overlapped I/O */ + + if (!lpOverlapped) + return FALSE; + + if (pipe->clientfd == -1) + return FALSE; + + pipe->lpOverlapped = lpOverlapped; + +#ifdef HAVE_AIO_H + { + struct aiocb cb; + + ZeroMemory(&cb, sizeof(struct aiocb)); + cb.aio_nbytes = nNumberOfBytesToRead; + cb.aio_fildes = pipe->clientfd; + cb.aio_offset = lpOverlapped->Offset; + cb.aio_buf = lpBuffer; + + status = aio_read(&cb); + + printf("aio_read status: %d\n", status); + + if (status < 0) + { + return FALSE; + } + } +#else + + /* synchronous behavior */ + + lpOverlapped->Internal = 0; + lpOverlapped->InternalHigh = (ULONG_PTR) nNumberOfBytesToRead; + lpOverlapped->Pointer = (PVOID) lpBuffer; + + SetEvent(lpOverlapped->hEvent); + +#endif + } return TRUE; } @@ -321,20 +393,66 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, pipe = (WINPR_NAMED_PIPE*) Object; - status = nNumberOfBytesToWrite; - - if (pipe->clientfd != -1) - status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite); - else - return FALSE; - - if (status < 0) + if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)) { - *lpNumberOfBytesWritten = 0; - return FALSE; - } + status = nNumberOfBytesToWrite; - *lpNumberOfBytesWritten = status; + if (pipe->clientfd == -1) + return FALSE; + + status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite); + + if (status < 0) + { + *lpNumberOfBytesWritten = 0; + return FALSE; + } + + *lpNumberOfBytesWritten = status; + } + else + { + /* Overlapped I/O */ + + if (!lpOverlapped) + return FALSE; + + if (pipe->clientfd == -1) + return FALSE; + + pipe->lpOverlapped = lpOverlapped; + +#ifdef HAVE_AIO_H + { + struct aiocb cb; + + ZeroMemory(&cb, sizeof(struct aiocb)); + cb.aio_nbytes = nNumberOfBytesToWrite; + cb.aio_fildes = pipe->clientfd; + cb.aio_offset = lpOverlapped->Offset; + cb.aio_buf = lpBuffer; + + status = aio_write(&cb); + + printf("aio_write status: %d\n", status); + + if (status < 0) + { + return FALSE; + } + } +#else + + /* synchronous behavior */ + + lpOverlapped->Internal = 1; + lpOverlapped->InternalHigh = (ULONG_PTR) nNumberOfBytesToWrite; + lpOverlapped->Pointer = (PVOID) lpBuffer; + + SetEvent(lpOverlapped->hEvent); + +#endif + } return TRUE; } diff --git a/winpr/libwinpr/io/io.c b/winpr/libwinpr/io/io.c index b319e6c77..bf6adaa9c 100644 --- a/winpr/libwinpr/io/io.c +++ b/winpr/libwinpr/io/io.c @@ -23,25 +23,69 @@ #include -/** - * api-ms-win-core-io-l1-1-1.dll: - * - * GetOverlappedResult - * GetOverlappedResultEx - * DeviceIoControl - * CreateIoCompletionPort - * GetQueuedCompletionStatus - * GetQueuedCompletionStatusEx - * PostQueuedCompletionStatus - * CancelIo - * CancelIoEx - * CancelSynchronousIo - */ - #ifndef _WIN32 +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "../handle/handle.h" + +#include "../pipe/pipe.h" + BOOL GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait) { + ULONG Type; + PVOID Object; + + if (!winpr_Handle_GetInfo(hFile, &Type, &Object)) + return FALSE; + + else if (Type == HANDLE_TYPE_NAMED_PIPE) + { + int status; + DWORD request; + PVOID lpBuffer; + DWORD nNumberOfBytes; + WINPR_NAMED_PIPE* pipe; + + pipe = (WINPR_NAMED_PIPE*) Object; + + if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)) + return FALSE; + + if (pipe->clientfd == -1) + return FALSE; + + lpBuffer = lpOverlapped->Pointer; + request = (DWORD) lpOverlapped->Internal; + nNumberOfBytes = (DWORD) lpOverlapped->InternalHigh; + + if (request == 0) + { + status = read(pipe->clientfd, lpBuffer, nNumberOfBytes); + } + else + { + status = write(pipe->clientfd, lpBuffer, nNumberOfBytes); + } + + if (status < 0) + { + *lpNumberOfBytesTransferred = 0; + return FALSE; + } + + *lpNumberOfBytesTransferred = status; + } + return TRUE; } diff --git a/winpr/libwinpr/nt/CMakeLists.txt b/winpr/libwinpr/nt/CMakeLists.txt new file mode 100644 index 000000000..451a7696b --- /dev/null +++ b/winpr/libwinpr/nt/CMakeLists.txt @@ -0,0 +1,58 @@ +# WinPR: Windows Portable Runtime +# libwinpr-nt cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# +# 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-nt") +set(MODULE_PREFIX "WINPR_NT") + +set(${MODULE_PREFIX}_SRCS + nt.c) + +if(MSVC AND (NOT MONOLITHIC_BUILD)) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) +endif() + +add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" + MONOLITHIC ${MONOLITHIC_BUILD} + SOURCES ${${MODULE_PREFIX}_SRCS}) + +set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib") + +set(${MODULE_PREFIX}_LIBS + ${CMAKE_THREAD_LIBS_INIT} + ${CMAKE_DL_LIBS}) + +if(${CMAKE_SYSTEM_NAME} MATCHES SunOS) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} rt) +endif() + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL + MODULE winpr + MODULES winpr-crt) + +if(MONOLITHIC_BUILD) + set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) +else() + target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR") + +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/winpr/libwinpr/nt/ModuleOptions.cmake b/winpr/libwinpr/nt/ModuleOptions.cmake new file mode 100644 index 000000000..750a8f556 --- /dev/null +++ b/winpr/libwinpr/nt/ModuleOptions.cmake @@ -0,0 +1,8 @@ + +set(MINWIN_LAYER "0") +set(MINWIN_GROUP "none") +set(MINWIN_MAJOR_VERSION "0") +set(MINWIN_MINOR_VERSION "0") +set(MINWIN_SHORT_NAME "nt") +set(MINWIN_LONG_NAME "Windows Native System Services") +set(MODULE_LIBRARY_NAME "${MINWIN_SHORT_NAME}") diff --git a/winpr/libwinpr/nt/module.def b/winpr/libwinpr/nt/module.def new file mode 100644 index 000000000..b45c622b5 --- /dev/null +++ b/winpr/libwinpr/nt/module.def @@ -0,0 +1,3 @@ +LIBRARY "libwinpr-nt" +EXPORTS + diff --git a/winpr/libwinpr/nt/nt.c b/winpr/libwinpr/nt/nt.c new file mode 100644 index 000000000..5ce1afc58 --- /dev/null +++ b/winpr/libwinpr/nt/nt.c @@ -0,0 +1,387 @@ +/** + * WinPR: Windows Portable Runtime + * Windows Native System Services + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/** + * NtXxx Routines: + * http://msdn.microsoft.com/en-us/library/windows/hardware/ff557720/ + */ + +#ifndef _WIN32 + +#include + +#include + +/** + * The current implementation of NtCurrentTeb() is not the most efficient + * but it's a starting point. Beware of potential performance bottlenecks + * caused by multithreaded usage of SetLastError/GetLastError. + */ + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +static PPEB g_ProcessEnvironmentBlock = NULL; + +static void NtThreadEnvironmentBlockFree(PTEB teb); +static void NtProcessEnvironmentBlockFree(PPEB peb); + +static PTEB NtThreadEnvironmentBlockNew() +{ + PTEB teb = NULL; + pthread_key_t key; + + teb = (PTEB) malloc(sizeof(TEB)); + + if (teb) + { + ZeroMemory(teb, sizeof(TEB)); + + /** + * We are not really using the key, but it provides an automatic way + * of calling NtThreadEnvironmentBlockFree on thread termination for + * the current Thread Environment Block. + */ + + pthread_key_create(&key, (void (*)(void*)) NtThreadEnvironmentBlockFree); + pthread_setspecific(key, (void*) teb); + } + + return teb; +} + +static void NtThreadEnvironmentBlockFree(PTEB teb) +{ + DWORD index; + PPEB peb = NULL; + + peb = teb->ProcessEnvironmentBlock; + + pthread_mutex_lock(&mutex); + + for (index = 0; index < peb->ThreadArraySize; index++) + { + if (peb->Threads[index].ThreadEnvironmentBlock == teb) + { + peb->Threads[index].ThreadId = 0; + peb->Threads[index].ThreadEnvironmentBlock = NULL; + peb->ThreadCount--; + break; + } + } + + if (!peb->ThreadCount) + { + NtProcessEnvironmentBlockFree(peb); + } + + pthread_mutex_unlock(&mutex); + + free(teb); +} + +static PPEB NtProcessEnvironmentBlockNew() +{ + PPEB peb = NULL; + + peb = (PPEB) malloc(sizeof(PEB)); + + if (peb) + { + ZeroMemory(peb, sizeof(PEB)); + + peb->ThreadCount = 0; + peb->ThreadArraySize = 64; + peb->Threads = (THREAD_BLOCK_ID*) malloc(sizeof(THREAD_BLOCK_ID) * peb->ThreadArraySize); + + if (peb->Threads) + { + ZeroMemory(peb->Threads, sizeof(THREAD_BLOCK_ID) * peb->ThreadArraySize); + } + } + + return peb; +} + +static void NtProcessEnvironmentBlockFree(PPEB peb) +{ + if (peb) + { + free(peb->Threads); + free(peb); + } + + g_ProcessEnvironmentBlock = NULL; +} + +PPEB NtCurrentPeb(void) +{ + PPEB peb = NULL; + + pthread_mutex_lock(&mutex); + + if (!g_ProcessEnvironmentBlock) + g_ProcessEnvironmentBlock = NtProcessEnvironmentBlockNew(); + + peb = g_ProcessEnvironmentBlock; + + pthread_mutex_unlock(&mutex); + + return peb; +} + +PTEB NtCurrentTeb(void) +{ + DWORD index; + int freeIndex; + DWORD ThreadId; + PPEB peb = NULL; + PTEB teb = NULL; + + peb = NtCurrentPeb(); + + ThreadId = (DWORD) pthread_self(); + + freeIndex = -1; + + pthread_mutex_lock(&mutex); + + for (index = 0; index < peb->ThreadArraySize; index++) + { + if (!peb->Threads[index].ThreadId) + { + if (freeIndex < 0) + freeIndex = (int) index; + } + + if (peb->Threads[index].ThreadId == ThreadId) + { + teb = peb->Threads[index].ThreadEnvironmentBlock; + break; + } + } + + if (!teb) + { + if (freeIndex >= 0) + { + teb = NtThreadEnvironmentBlockNew(); + peb->Threads[freeIndex].ThreadEnvironmentBlock = teb; + peb->Threads[freeIndex].ThreadId = ThreadId; + peb->ThreadCount++; + + teb->ProcessEnvironmentBlock = peb; + teb->LastErrorValue = 0; + } + } + + pthread_mutex_unlock(&mutex); + + return teb; +} + +/** + * RtlInitAnsiString routine: + * http://msdn.microsoft.com/en-us/library/windows/hardware/ff561918/ + */ + +VOID RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString) +{ + DestinationString->Buffer = (PCHAR) SourceString; + + if (!SourceString) + { + DestinationString->Length = 0; + DestinationString->MaximumLength = 0; + } + else + { + USHORT length = (USHORT) strlen(SourceString); + DestinationString->Length = length; + DestinationString->MaximumLength = length + 1; + } +} + +/** + * RtlInitUnicodeString routine: + * http://msdn.microsoft.com/en-us/library/windows/hardware/ff561934/ + */ + +VOID RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString) +{ + DestinationString->Buffer = (PWSTR) SourceString; + + if (!SourceString) + { + DestinationString->Length = 0; + DestinationString->MaximumLength = 0; + } + else + { + USHORT length = (USHORT) _wcslen(SourceString); + DestinationString->Length = length * 2; + DestinationString->MaximumLength = (length + 1) * 2; + } +} + +/** + * RtlAnsiStringToUnicodeString function: + * http://msdn.microsoft.com/en-us/library/ms648413/ + */ + +NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PCANSI_STRING SourceString, BOOLEAN AllocateDestinationString) +{ + int index; + + if (!SourceString) + { + RtlInitUnicodeString(DestinationString, NULL); + return 0; + } + + if (AllocateDestinationString) + { + DestinationString->Length = SourceString->Length * 2; + DestinationString->MaximumLength = SourceString->MaximumLength * 2; + + DestinationString->Buffer = (PWSTR) malloc(DestinationString->MaximumLength); + + for (index = 0; index < SourceString->MaximumLength; index++) + { + DestinationString->Buffer[index] = (WCHAR) SourceString->Buffer[index]; + } + } + else + { + + } + + return 0; +} + +/** + * RtlFreeUnicodeString function: + * http://msdn.microsoft.com/en-us/library/ms648418/ + */ + +VOID RtlFreeUnicodeString(PUNICODE_STRING UnicodeString) +{ + if (UnicodeString) + { + if (UnicodeString->Buffer) + free(UnicodeString->Buffer); + + UnicodeString->Length = 0; + UnicodeString->MaximumLength = 0; + } +} + +/** + * RtlNtStatusToDosError function: + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms680600/ + */ + +ULONG RtlNtStatusToDosError(NTSTATUS status) +{ + return status; +} + +/** + * InitializeObjectAttributes macro + * http://msdn.microsoft.com/en-us/library/windows/hardware/ff547804/ + */ + +VOID InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes, + PUNICODE_STRING ObjectName, ULONG Attributes, HANDLE RootDirectory, + PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + InitializedAttributes->Length = sizeof(OBJECT_ATTRIBUTES); + InitializedAttributes->ObjectName = ObjectName; + InitializedAttributes->Attributes = Attributes; + InitializedAttributes->RootDirectory = RootDirectory; + InitializedAttributes->SecurityDescriptor = SecurityDescriptor; + InitializedAttributes->SecurityQualityOfService = NULL; +} + +/** + * NtCreateFile function: + * http://msdn.microsoft.com/en-us/library/bb432380/ + */ + +NTSTATUS NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, + PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, + ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength) +{ + return 0; +} + +/** + * NtOpenFile function: + * http://msdn.microsoft.com/en-us/library/bb432381/ + */ + +NTSTATUS NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, + ULONG ShareAccess, ULONG OpenOptions) +{ + return 0; +} + +/** + * NtDeviceIoControlFile function: + * http://msdn.microsoft.com/en-us/library/ms648411/ + */ + +NTSTATUS NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event, + PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, + ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, + PVOID OutputBuffer, ULONG OutputBufferLength) +{ + return 0; +} + +/** + * NtClose function: + * http://msdn.microsoft.com/en-us/library/ms648410/ + */ + +NTSTATUS NtClose(HANDLE Handle) +{ + return 0; +} + +/** + * NtWaitForSingleObject function: + * http://msdn.microsoft.com/en-us/library/ms648412/ + */ + +NTSTATUS NtWaitForSingleObject(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout) +{ + return 0; +} + +#endif + diff --git a/winpr/libwinpr/nt/test/.gitignore b/winpr/libwinpr/nt/test/.gitignore new file mode 100644 index 000000000..1302271b9 --- /dev/null +++ b/winpr/libwinpr/nt/test/.gitignore @@ -0,0 +1,3 @@ +TestNt +TestNt.c + diff --git a/winpr/libwinpr/nt/test/CMakeLists.txt b/winpr/libwinpr/nt/test/CMakeLists.txt new file mode 100644 index 000000000..b3fcb8bab --- /dev/null +++ b/winpr/libwinpr/nt/test/CMakeLists.txt @@ -0,0 +1,32 @@ + +set(MODULE_NAME "TestNt") +set(MODULE_PREFIX "TEST_NT") + +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) + +set(${MODULE_PREFIX}_TESTS + TestNtCreateFile.c + TestNtCurrentTeb.c) + +create_test_sourcelist(${MODULE_PREFIX}_SRCS + ${${MODULE_PREFIX}_DRIVER} + ${${MODULE_PREFIX}_TESTS}) + +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE winpr + MODULES winpr-crt winpr-nt) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}") + +foreach(test ${${MODULE_PREFIX}_TESTS}) + get_filename_component(TestName ${test} NAME_WE) + add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName}) +endforeach() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test") + diff --git a/winpr/libwinpr/nt/test/TestNtCreateFile.c b/winpr/libwinpr/nt/test/TestNtCreateFile.c new file mode 100644 index 000000000..4dcb876ae --- /dev/null +++ b/winpr/libwinpr/nt/test/TestNtCreateFile.c @@ -0,0 +1,30 @@ + +#include + +#include + +int TestNtCreateFile(int argc, char* argv[]) +{ + HANDLE handle; + NTSTATUS ntstatus; + ULONG CreateOptions; + ANSI_STRING aString; + UNICODE_STRING uString; + ACCESS_MASK DesiredAccess = 0; + OBJECT_ATTRIBUTES attributes; + IO_STATUS_BLOCK ioStatusBlock; + + RtlInitAnsiString(&aString, "\\Device\\FreeRDP\\TEST"); + RtlAnsiStringToUnicodeString(&uString, &aString, TRUE); + + InitializeObjectAttributes(&attributes, NULL, 0, NULL, NULL); + + DesiredAccess = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE; + CreateOptions = FILE_DIRECTORY_FILE | FILE_WRITE_THROUGH; + + ntstatus = NtCreateFile(&handle, DesiredAccess, &attributes, &ioStatusBlock, 0, 0, 0, CreateOptions, 0, 0, 0); + + RtlFreeUnicodeString(&uString); + + return 0; +} diff --git a/winpr/libwinpr/nt/test/TestNtCurrentTeb.c b/winpr/libwinpr/nt/test/TestNtCurrentTeb.c new file mode 100644 index 000000000..43f46a77f --- /dev/null +++ b/winpr/libwinpr/nt/test/TestNtCurrentTeb.c @@ -0,0 +1,20 @@ + +#include + +#include + +int TestNtCurrentTeb(int argc, char* argv[]) +{ + PTEB teb; + + teb = NtCurrentTeb(); + + if (!teb) + { + printf("NtCurrentTeb() returned NULL\n"); + return -1; + } + + return 0; +} + diff --git a/winpr/libwinpr/path/CMakeLists.txt b/winpr/libwinpr/path/CMakeLists.txt index 59eaf6875..ecd9b0bca 100644 --- a/winpr/libwinpr/path/CMakeLists.txt +++ b/winpr/libwinpr/path/CMakeLists.txt @@ -28,10 +28,15 @@ add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib") +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL + MODULE winpr + MODULES winpr-crt winpr-heap winpr-environment) + if(MONOLITHIC_BUILD) - + else() - target_link_libraries(${MODULE_NAME} winpr-crt winpr-heap winpr-environment) + target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() diff --git a/winpr/libwinpr/pipe/CMakeLists.txt b/winpr/libwinpr/pipe/CMakeLists.txt index d30b31cbb..330e188d6 100644 --- a/winpr/libwinpr/pipe/CMakeLists.txt +++ b/winpr/libwinpr/pipe/CMakeLists.txt @@ -35,7 +35,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SO set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL MODULE winpr - MODULES winpr-crt winpr-handle winpr-file) + MODULES winpr-crt winpr-synch winpr-handle winpr-file) if(MONOLITHIC_BUILD) diff --git a/winpr/libwinpr/pipe/pipe.c b/winpr/libwinpr/pipe/pipe.c index ec65eee03..144979e86 100644 --- a/winpr/libwinpr/pipe/pipe.c +++ b/winpr/libwinpr/pipe/pipe.c @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -114,6 +115,7 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD pNamedPipe->nOutBufferSize = nOutBufferSize; pNamedPipe->nInBufferSize = nInBufferSize; pNamedPipe->nDefaultTimeOut = nDefaultTimeOut; + pNamedPipe->dwFlagsAndAttributes = dwOpenMode; pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpName); pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpName); @@ -183,6 +185,14 @@ BOOL ConnectNamedPipe(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped) pNamedPipe->clientfd = status; + if (pNamedPipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED) + { + if (!lpOverlapped) + return FALSE; + + SetEvent(lpOverlapped->hEvent); + } + return TRUE; } diff --git a/winpr/libwinpr/pipe/pipe.h b/winpr/libwinpr/pipe/pipe.h index 2c326a771..efc79989a 100644 --- a/winpr/libwinpr/pipe/pipe.h +++ b/winpr/libwinpr/pipe/pipe.h @@ -51,6 +51,8 @@ struct winpr_named_pipe DWORD nOutBufferSize; DWORD nInBufferSize; DWORD nDefaultTimeOut; + DWORD dwFlagsAndAttributes; + LPOVERLAPPED lpOverlapped; }; typedef struct winpr_named_pipe WINPR_NAMED_PIPE; diff --git a/winpr/libwinpr/synch/CMakeLists.txt b/winpr/libwinpr/synch/CMakeLists.txt index fbc607292..3beea6d5a 100644 --- a/winpr/libwinpr/synch/CMakeLists.txt +++ b/winpr/libwinpr/synch/CMakeLists.txt @@ -55,7 +55,7 @@ set(${MODULE_PREFIX}_LIBS ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) -if(${CMAKE_SYSTEM_NAME} MATCHES SunOS) +if((NOT WIN32) AND (NOT APPLE) AND (NOT ANDROID)) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} rt) endif() diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c index bfb221315..8fab17203 100644 --- a/winpr/libwinpr/synch/wait.c +++ b/winpr/libwinpr/synch/wait.c @@ -45,6 +45,8 @@ #include "../handle/handle.h" +#include "../pipe/pipe.h" + static void ts_add_ms(struct timespec *ts, DWORD dwMilliseconds) { ts->tv_sec += dwMilliseconds / 1000L; @@ -241,6 +243,31 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) return WAIT_FAILED; #endif } + else if (Type == HANDLE_TYPE_NAMED_PIPE) + { + int status; + fd_set rfds; + struct timeval timeout; + WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object; + + FD_ZERO(&rfds); + FD_SET(pipe->clientfd, &rfds); + ZeroMemory(&timeout, sizeof(timeout)); + + if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) + { + timeout.tv_usec = dwMilliseconds * 1000; + } + + status = select(pipe->clientfd + 1, &rfds, NULL, NULL, + (dwMilliseconds == INFINITE) ? NULL : &timeout); + + if (status < 0) + return WAIT_FAILED; + + if (status != 1) + return WAIT_TIMEOUT; + } else { fprintf(stderr, "WaitForSingleObject: unknown handle type %lu\n", Type); @@ -302,6 +329,11 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl WINPR_TIMER* timer = (WINPR_TIMER*) Object; fd = timer->fd; } + else if (Type == HANDLE_TYPE_NAMED_PIPE) + { + WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object; + fd = pipe->clientfd; + } else { return WAIT_FAILED; @@ -347,6 +379,11 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl WINPR_TIMER* timer = (WINPR_TIMER*) Object; fd = timer->fd; } + else if (Type == HANDLE_TYPE_NAMED_PIPE) + { + WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object; + fd = pipe->clientfd; + } if (FD_ISSET(fd, &fds)) { diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index d7db7b6d6..1154dc3f0 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -51,7 +51,8 @@ set(${MODULE_PREFIX}_SRCS ntlm.c print.c stream.c - cmdline.c) + cmdline.c + wlog.c) set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${${MODULE_PREFIX}_COLLECTIONS_SRCS} diff --git a/winpr/libwinpr/utils/collections/BufferPool.c b/winpr/libwinpr/utils/collections/BufferPool.c index e5b39114f..7dfae8e32 100644 --- a/winpr/libwinpr/utils/collections/BufferPool.c +++ b/winpr/libwinpr/utils/collections/BufferPool.c @@ -85,7 +85,16 @@ int BufferPool_GetPoolSize(wBufferPool* pool) if (pool->synchronized) EnterCriticalSection(&pool->lock); - size = pool->uSize; + if (pool->fixedSize) + { + /* fixed size buffers */ + size = pool->size; + } + else + { + /* variable size buffers */ + size = pool->uSize; + } if (pool->synchronized) LeaveCriticalSection(&pool->lock); @@ -106,13 +115,24 @@ int BufferPool_GetBufferSize(wBufferPool* pool, void* buffer) if (pool->synchronized) EnterCriticalSection(&pool->lock); - for (index = 0; index < pool->uSize; index++) + if (pool->fixedSize) { - if (pool->uArray[index].buffer == buffer) + /* fixed size buffers */ + size = pool->fixedSize; + found = TRUE; + } + else + { + /* variable size buffers */ + + for (index = 0; index < pool->uSize; index++) { - size = pool->uArray[index].size; - found = TRUE; - break; + if (pool->uArray[index].buffer == buffer) + { + size = pool->uArray[index].size; + found = TRUE; + break; + } } } @@ -138,65 +158,90 @@ void* BufferPool_Take(wBufferPool* pool, int size) if (pool->synchronized) EnterCriticalSection(&pool->lock); - maxSize = 0; - maxIndex = 0; - - if (size < 1) - size = pool->defaultSize; - - for (index = 0; index < pool->aSize; index++) + if (pool->fixedSize) { - if (pool->aArray[index].size > maxSize) + /* fixed size buffers */ + + if (pool->size > 0) + buffer = pool->array[--(pool->size)]; + + if (!buffer) { - maxIndex = index; - maxSize = pool->aArray[index].size; + if (pool->alignment) + buffer = _aligned_malloc(pool->fixedSize, pool->alignment); + else + buffer = malloc(pool->fixedSize); } - - if (pool->aArray[index].size >= size) - { - foundIndex = index; - found = TRUE; - break; - } - } - - if (!found && maxSize) - { - foundIndex = maxIndex; - found = TRUE; - } - - if (!found) - { - if (pool->alignment) - buffer = _aligned_malloc(size, pool->alignment); - else - buffer = malloc(size); } else { - buffer = pool->aArray[index].buffer; + /* variable size buffers */ - if (maxSize < size) + maxSize = 0; + maxIndex = 0; + + if (size < 1) + size = pool->fixedSize; + + for (index = 0; index < pool->aSize; index++) { - if (pool->alignment) - buffer = _aligned_realloc(buffer, size, pool->alignment); - else - buffer = realloc(buffer, size); + if (pool->aArray[index].size > maxSize) + { + maxIndex = index; + maxSize = pool->aArray[index].size; + } + + if (pool->aArray[index].size >= size) + { + foundIndex = index; + found = TRUE; + break; + } } - BufferPool_ShiftAvailable(pool, foundIndex, -1); - } + if (!found && maxSize) + { + foundIndex = maxIndex; + found = TRUE; + } - if (pool->uSize + 1 > pool->uCapacity) - { - pool->uCapacity *= 2; - pool->uArray = (wBufferPoolItem*) realloc(pool->uArray, sizeof(wBufferPoolItem) * pool->uCapacity); - } + if (!found) + { + if (pool->alignment) + buffer = _aligned_malloc(size, pool->alignment); + else + buffer = malloc(size); + } + else + { + buffer = pool->aArray[foundIndex].buffer; - pool->uArray[pool->uSize].buffer = buffer; - pool->uArray[pool->uSize].size = size; - (pool->uSize)++; + if (maxSize < size) + { + if (pool->alignment) + { + _aligned_free(buffer); + buffer = _aligned_malloc(size, pool->alignment); + } + else + { + buffer = realloc(buffer, size); + } + } + + BufferPool_ShiftAvailable(pool, foundIndex, -1); + } + + if (pool->uSize + 1 > pool->uCapacity) + { + pool->uCapacity *= 2; + pool->uArray = (wBufferPoolItem*) realloc(pool->uArray, sizeof(wBufferPoolItem) * pool->uCapacity); + } + + pool->uArray[pool->uSize].buffer = buffer; + pool->uArray[pool->uSize].size = size; + (pool->uSize)++; + } if (pool->synchronized) LeaveCriticalSection(&pool->lock); @@ -217,32 +262,49 @@ void BufferPool_Return(wBufferPool* pool, void* buffer) if (pool->synchronized) EnterCriticalSection(&pool->lock); - for (index = 0; index < pool->uSize; index++) + if (pool->fixedSize) { - if (pool->uArray[index].buffer == buffer) - { - found = TRUE; - break; - } - } + /* fixed size buffers */ - if (found) - { - size = pool->uArray[index].size; - BufferPool_ShiftUsed(pool, index, -1); - } - - if (size) - { - if ((pool->aSize + 1) >= pool->aCapacity) + if ((pool->size + 1) >= pool->capacity) { - pool->aCapacity *= 2; - pool->aArray = (wBufferPoolItem*) realloc(pool->aArray, sizeof(wBufferPoolItem) * pool->aCapacity); + pool->capacity *= 2; + pool->array = (void**) realloc(pool->array, sizeof(void*) * pool->capacity); } - pool->aArray[pool->aSize].buffer = buffer; - pool->aArray[pool->aSize].size = size; - (pool->aSize)++; + pool->array[(pool->size)++] = buffer; + } + else + { + /* variable size buffers */ + + for (index = 0; index < pool->uSize; index++) + { + if (pool->uArray[index].buffer == buffer) + { + found = TRUE; + break; + } + } + + if (found) + { + size = pool->uArray[index].size; + BufferPool_ShiftUsed(pool, index, -1); + } + + if (size) + { + if ((pool->aSize + 1) >= pool->aCapacity) + { + pool->aCapacity *= 2; + pool->aArray = (wBufferPoolItem*) realloc(pool->aArray, sizeof(wBufferPoolItem) * pool->aCapacity); + } + + pool->aArray[pool->aSize].buffer = buffer; + pool->aArray[pool->aSize].size = size; + (pool->aSize)++; + } } if (pool->synchronized) @@ -258,24 +320,43 @@ void BufferPool_Clear(wBufferPool* pool) if (pool->synchronized) EnterCriticalSection(&pool->lock); - while (pool->aSize > 0) + if (pool->fixedSize) { - (pool->aSize)--; + /* fixed size buffers */ - if (pool->alignment) - _aligned_free(pool->aArray[pool->aSize].buffer); - else - free(pool->aArray[pool->aSize].buffer); + while (pool->size > 0) + { + (pool->size)--; + + if (pool->alignment) + _aligned_free(pool->array[pool->size]); + else + free(pool->array[pool->size]); + } } - - while (pool->uSize > 0) + else { - (pool->uSize)--; + /* variable size buffers */ - if (pool->alignment) - _aligned_free(pool->uArray[pool->uSize].buffer); - else - free(pool->uArray[pool->uSize].buffer); + while (pool->aSize > 0) + { + (pool->aSize)--; + + if (pool->alignment) + _aligned_free(pool->aArray[pool->aSize].buffer); + else + free(pool->aArray[pool->aSize].buffer); + } + + while (pool->uSize > 0) + { + (pool->uSize)--; + + if (pool->alignment) + _aligned_free(pool->uArray[pool->uSize].buffer); + else + free(pool->uArray[pool->uSize].buffer); + } } if (pool->synchronized) @@ -286,7 +367,7 @@ void BufferPool_Clear(wBufferPool* pool) * Construction, Destruction */ -wBufferPool* BufferPool_New(BOOL synchronized, int defaultSize, DWORD alignment) +wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment) { wBufferPool* pool = NULL; @@ -294,10 +375,10 @@ wBufferPool* BufferPool_New(BOOL synchronized, int defaultSize, DWORD alignment) if (pool) { - pool->defaultSize = defaultSize; + pool->fixedSize = fixedSize; - if (pool->defaultSize < 0) - pool->defaultSize = 0; + if (pool->fixedSize < 0) + pool->fixedSize = 0; pool->alignment = alignment; pool->synchronized = synchronized; @@ -305,13 +386,26 @@ wBufferPool* BufferPool_New(BOOL synchronized, int defaultSize, DWORD alignment) if (pool->synchronized) InitializeCriticalSectionAndSpinCount(&pool->lock, 4000); - pool->aSize = 0; - pool->aCapacity = 32; - pool->aArray = (wBufferPoolItem*) malloc(sizeof(wBufferPoolItem) * pool->aCapacity); + if (pool->fixedSize) + { + /* fixed size buffers */ - pool->uSize = 0; - pool->uCapacity = 32; - pool->uArray = (wBufferPoolItem*) malloc(sizeof(wBufferPoolItem) * pool->uCapacity); + pool->size = 0; + pool->capacity = 32; + pool->array = (void**) malloc(sizeof(void*) * pool->capacity); + } + else + { + /* variable size buffers */ + + pool->aSize = 0; + pool->aCapacity = 32; + pool->aArray = (wBufferPoolItem*) malloc(sizeof(wBufferPoolItem) * pool->aCapacity); + + pool->uSize = 0; + pool->uCapacity = 32; + pool->uArray = (wBufferPoolItem*) malloc(sizeof(wBufferPoolItem) * pool->uCapacity); + } } return pool; @@ -326,8 +420,19 @@ void BufferPool_Free(wBufferPool* pool) if (pool->synchronized) DeleteCriticalSection(&pool->lock); - free(pool->aArray); - free(pool->uArray); + if (pool->fixedSize) + { + /* fixed size buffers */ + + free(pool->array); + } + else + { + /* variable size buffers */ + + free(pool->aArray); + free(pool->uArray); + } free(pool); } diff --git a/winpr/libwinpr/utils/print.c b/winpr/libwinpr/utils/print.c index ed9f55af8..8d98b100f 100644 --- a/winpr/libwinpr/utils/print.c +++ b/winpr/libwinpr/utils/print.c @@ -76,3 +76,8 @@ int wprintfx(const char *fmt, ...) return status; } + +int wvsnprintfx(char *buffer, size_t bufferSize, const char* fmt, va_list args) +{ + return trio_vsnprintf(buffer, bufferSize, fmt, args); +} diff --git a/winpr/libwinpr/utils/test/CMakeLists.txt b/winpr/libwinpr/utils/test/CMakeLists.txt index 31d1de762..841e1dea2 100644 --- a/winpr/libwinpr/utils/test/CMakeLists.txt +++ b/winpr/libwinpr/utils/test/CMakeLists.txt @@ -12,6 +12,7 @@ set(${MODULE_PREFIX}_TESTS TestLinkedList.c TestListDictionary.c TestCmdLine.c + TestWLog.c TestBufferPool.c TestStreamPool.c TestMessageQueue.c diff --git a/winpr/libwinpr/utils/test/TestBufferPool.c b/winpr/libwinpr/utils/test/TestBufferPool.c index 710bc61dd..7e6f0b97a 100644 --- a/winpr/libwinpr/utils/test/TestBufferPool.c +++ b/winpr/libwinpr/utils/test/TestBufferPool.c @@ -5,28 +5,18 @@ int TestBufferPool(int argc, char* argv[]) { - int PoolSize; + DWORD PoolSize; int BufferSize; - int DefaultSize; wBufferPool* pool; BYTE* Buffers[10]; + DWORD DefaultSize = 1234; - DefaultSize = 1234; + pool = BufferPool_New(TRUE, -1, 16); - pool = BufferPool_New(TRUE, DefaultSize, 16); - - Buffers[0] = BufferPool_Take(pool, -1); - Buffers[1] = BufferPool_Take(pool, 0); + Buffers[0] = BufferPool_Take(pool, DefaultSize); + Buffers[1] = BufferPool_Take(pool, DefaultSize); Buffers[2] = BufferPool_Take(pool, 2048); - PoolSize = BufferPool_GetPoolSize(pool); - - if (PoolSize != 3) - { - printf("BufferPool_GetPoolSize failure: Actual: %d Expected: %d\n", PoolSize, 3); - return -1; - } - BufferSize = BufferPool_GetBufferSize(pool, Buffers[0]); if (BufferSize != DefaultSize) @@ -63,14 +53,6 @@ int TestBufferPool(int argc, char* argv[]) BufferPool_Clear(pool); - PoolSize = BufferPool_GetPoolSize(pool); - - if (PoolSize != 0) - { - printf("BufferPool_GetPoolSize failure: Actual: %d Expected: %d\n", PoolSize, 0); - return -1; - } - BufferPool_Free(pool); return 0; diff --git a/winpr/libwinpr/utils/test/TestWLog.c b/winpr/libwinpr/utils/test/TestWLog.c new file mode 100644 index 000000000..7f430517c --- /dev/null +++ b/winpr/libwinpr/utils/test/TestWLog.c @@ -0,0 +1,55 @@ + +#include +#include +#include + +int TestWLog(int argc, char* argv[]) +{ + wLog* log; + wLogLayout* layout; + wLogAppender* appender; + + log = WLog_New("CONSOLE_LOG_TEST"); + + WLog_SetLogLevel(log, WLOG_INFO); + + WLog_SetLogAppenderType(log, WLOG_APPENDER_CONSOLE); + appender = WLog_GetLogAppender(log); + + layout = WLog_GetLogLayout(log); + WLog_Layout_SetPrefixFormat(log, layout, "[%lv:%mn] [%fl|%fn|%ln] - "); + + WLog_ConsoleAppender_SetOutputStream(log, (wLogConsoleAppender*) appender, WLOG_CONSOLE_STDERR); + WLog_OpenAppender(log); + + WLog_Print(log, WLOG_INFO, "this is a test"); + WLog_Print(log, WLOG_WARN, "this is a %dnd %s", 2, "test"); + WLog_Print(log, WLOG_ERROR, "this is an error"); + WLog_Print(log, WLOG_TRACE, "this is a trace output"); + + WLog_CloseAppender(log); + WLog_Free(log); + + log = WLog_New("FILE_LOG_TEST"); + + WLog_SetLogLevel(log, WLOG_WARN); + + WLog_SetLogAppenderType(log, WLOG_APPENDER_FILE); + appender = WLog_GetLogAppender(log); + + layout = WLog_GetLogLayout(log); + WLog_Layout_SetPrefixFormat(log, layout, "[%lv:%mn] [%fl|%fn|%ln] - "); + + WLog_FileAppender_SetOutputFileName(log, (wLogFileAppender*) appender, "/tmp/wlog_test.log"); + WLog_OpenAppender(log); + + WLog_Print(log, WLOG_INFO, "this is a test"); + WLog_Print(log, WLOG_WARN, "this is a %dnd %s", 2, "test"); + WLog_Print(log, WLOG_ERROR, "this is an error"); + WLog_Print(log, WLOG_TRACE, "this is a trace output"); + + WLog_CloseAppender(log); + WLog_Free(log); + + return 0; +} diff --git a/winpr/libwinpr/utils/wlog.c b/winpr/libwinpr/utils/wlog.c new file mode 100644 index 000000000..aced199d8 --- /dev/null +++ b/winpr/libwinpr/utils/wlog.c @@ -0,0 +1,615 @@ +/** + * WinPR: Windows Portable Runtime + * WinPR Logger + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include + +#include + +/** + * References for general logging concepts: + * + * Short introduction to log4j: + * http://logging.apache.org/log4j/1.2/manual.html + * + * logging - Logging facility for Python: + * http://docs.python.org/2/library/logging.html + */ + +#define WLOG_MAX_PREFIX_SIZE 512 +#define WLOG_MAX_STRING_SIZE 8192 + +const char* WLOG_LEVELS[7] = +{ + "TRACE", + "DEBUG", + "INFO", + "WARN", + "ERROR", + "FATAL", + "OFF" +}; + +int WLog_Write(wLog* log, wLogMessage* message) +{ + if (!log->Appender) + return -1; + + if (!log->Appender->WriteMessage) + return -1; + + return log->Appender->WriteMessage(log, log->Appender, message); +} + +void WLog_PrintMessageVA(wLog* log, wLogMessage* message, va_list args) +{ + if (!strchr(message->FormatString, '%')) + { + message->TextString = (LPSTR) message->FormatString; + WLog_Write(log, message); + } + else + { + char formattedLogMessage[8192]; + wvsnprintfx(formattedLogMessage, WLOG_MAX_STRING_SIZE - 1, message->FormatString, args); + + message->TextString = formattedLogMessage; + WLog_Write(log, message); + } +} + +void WLog_PrintMessage(wLog* log, wLogMessage* message, ...) +{ + va_list args; + va_start(args, message); + WLog_PrintMessageVA(log, message, args); + va_end(args); +} + +DWORD WLog_GetLogLevel(wLog* log) +{ + return log->Level; +} + +void WLog_SetLogLevel(wLog* log, DWORD logLevel) +{ + if (logLevel > WLOG_OFF) + logLevel = WLOG_OFF; + + log->Level = logLevel; +} + +/** + * Log Layout + */ + +void WLog_PrintMessagePrefixVA(wLog* log, wLogMessage* message, const char* format, va_list args) +{ + if (!strchr(format, '%')) + { + message->PrefixString = (LPSTR) format; + } + else + { + wvsnprintfx(message->PrefixString, WLOG_MAX_PREFIX_SIZE - 1, format, args); + } +} + +void WLog_PrintMessagePrefix(wLog* log, wLogMessage* message, const char* format, ...) +{ + va_list args; + va_start(args, format); + WLog_PrintMessagePrefixVA(log, message, format, args); + va_end(args); +} + +void WLog_Layout_GetMessagePrefix(wLog* log, wLogLayout* layout, wLogMessage* message) +{ + char* p; + int index; + int argc = 0; + void* args[32]; + char format[128]; + + index = 0; + p = (char*) layout->FormatString; + + while (*p) + { + if (*p == '%') + { + p++; + + if (*p) + { + if ((*p == 'l') && (*(p + 1) == 'v')) /* log level */ + { + args[argc++] = (void*) WLOG_LEVELS[message->Level]; + format[index++] = '%'; + format[index++] = 's'; + p++; + } + else if ((*p == 'm') && (*(p + 1) == 'n')) /* module name */ + { + args[argc++] = (void*) log->Name; + format[index++] = '%'; + format[index++] = 's'; + p++; + } + else if ((*p == 'f') && (*(p + 1) == 'l')) /* file */ + { + char* file; + + file = strrchr(message->FileName, '/'); + + if (!file) + file = strrchr(message->FileName, '\\'); + + if (file) + file++; + else + file = (char*) message->FileName; + + args[argc++] = (void*) file; + format[index++] = '%'; + format[index++] = 's'; + p++; + } + else if ((*p == 'f') && (*(p + 1) == 'n')) /* function */ + { + args[argc++] = (void*) message->FunctionName; + format[index++] = '%'; + format[index++] = 's'; + p++; + } + else if ((*p == 'l') && (*(p + 1) == 'n')) /* line number */ + { + args[argc++] = (void*) message->LineNumber; + format[index++] = '%'; + format[index++] = 'd'; + p++; + } + } + } + else + { + format[index++] = *p; + } + + p++; + } + + format[index++] = '\0'; + + switch (argc) + { + case 0: + WLog_PrintMessagePrefix(log, message, format); + break; + + case 1: + WLog_PrintMessagePrefix(log, message, format, args[0]); + break; + + case 2: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1]); + break; + + case 3: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2]); + break; + + case 4: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3]); + break; + + case 5: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4]); + break; + + case 6: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5]); + break; + + case 7: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5], args[6]); + break; + + case 8: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7]); + break; + + case 9: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7], args[8]); + break; + + case 10: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7], args[8], args[9]); + break; + + case 11: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7], args[8], args[9], args[10]); + break; + + case 12: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7], args[8], args[9], args[10], + args[11]); + break; + + case 13: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7], args[8], args[9], args[10], + args[11], args[12]); + break; + + case 14: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7], args[8], args[9], args[10], + args[11], args[12], args[13]); + break; + + case 15: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7], args[8], args[9], args[10], + args[11], args[12], args[13], args[14]); + break; + + case 16: + WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7], args[8], args[9], args[10], + args[11], args[12], args[13], args[14], args[15]); + break; + } +} + +wLogLayout* WLog_GetLogLayout(wLog* log) +{ + return log->Appender->Layout; +} + +void WLog_Layout_SetPrefixFormat(wLog* log, wLogLayout* layout, const char* format) +{ + if (layout->FormatString) + free(layout->FormatString); + + layout->FormatString = _strdup(format); +} + +wLogLayout* WLog_Layout_New(wLog* log) +{ + wLogLayout* layout; + + layout = (wLogLayout*) malloc(sizeof(wLogLayout)); + + if (layout) + { + ZeroMemory(layout, sizeof(wLogLayout)); + + layout->FormatString = _strdup("[%lv][%mn] - "); + } + + return layout; +} + +void WLog_Layout_Free(wLog* log, wLogLayout* layout) +{ + if (layout) + { + if (layout->FormatString) + free(layout->FormatString); + + free(layout); + } +} + +/** + * Console Appender + */ + +void WLog_ConsoleAppender_SetOutputStream(wLog* log, wLogConsoleAppender* appender, int outputStream) +{ + if (!appender) + return; + + if (outputStream < 0) + outputStream = WLOG_CONSOLE_STDOUT; + + if (outputStream == WLOG_CONSOLE_STDOUT) + appender->outputStream = WLOG_CONSOLE_STDOUT; + else if (outputStream == WLOG_CONSOLE_STDERR) + appender->outputStream = WLOG_CONSOLE_STDERR; + else + appender->outputStream = WLOG_CONSOLE_STDOUT; +} + +int WLog_ConsoleAppender_Open(wLog* log, wLogConsoleAppender* appender) +{ + return 0; +} + +int WLog_ConsoleAppender_Close(wLog* log, wLogConsoleAppender* appender) +{ + return 0; +} + +int WLog_ConsoleAppender_WriteMessage(wLog* log, wLogConsoleAppender* appender, wLogMessage* message) +{ + FILE* fp; + char prefix[WLOG_MAX_PREFIX_SIZE]; + + if (message->Level > log->Level) + return 0; + + fp = (appender->outputStream == WLOG_CONSOLE_STDERR) ? stderr : stdout; + + message->PrefixString = prefix; + WLog_Layout_GetMessagePrefix(log, appender->Layout, message); + + fprintf(fp, "%s%s\n", message->PrefixString, message->TextString); + + return 1; +} + +wLogConsoleAppender* WLog_ConsoleAppender_New(wLog* log) +{ + wLogConsoleAppender* ConsoleAppender; + + ConsoleAppender = (wLogConsoleAppender*) malloc(sizeof(wLogConsoleAppender)); + + if (ConsoleAppender) + { + ZeroMemory(ConsoleAppender, sizeof(wLogConsoleAppender)); + + ConsoleAppender->Open = (WLOG_APPENDER_OPEN_FN) WLog_ConsoleAppender_Open; + ConsoleAppender->Close = (WLOG_APPENDER_OPEN_FN) WLog_ConsoleAppender_Close; + ConsoleAppender->WriteMessage = (WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_ConsoleAppender_WriteMessage; + + ConsoleAppender->outputStream = WLOG_CONSOLE_STDOUT; + } + + return ConsoleAppender; +} + +void WLog_ConsoleAppender_Free(wLog* log, wLogConsoleAppender* appender) +{ + if (appender) + { + free(appender); + } +} + +/** + * File Appender + */ + +void WLog_FileAppender_SetOutputFileName(wLog* log, wLogFileAppender* appender, const char* filename) +{ + if (!appender) + return; + + if (!filename) + return; + + appender->FileName = _strdup(filename); +} + +int WLog_FileAppender_Open(wLog* log, wLogFileAppender* appender) +{ + if (!appender->FileName) + return -1; + + appender->FileDescriptor = fopen(appender->FileName, "a+"); + + if (!appender->FileDescriptor) + return -1; + + return 0; +} + +int WLog_FileAppender_Close(wLog* log, wLogFileAppender* appender) +{ + if (!appender->FileDescriptor) + return 0; + + fclose(appender->FileDescriptor); + + appender->FileDescriptor = NULL; + + return 0; +} + +int WLog_FileAppender_WriteMessage(wLog* log, wLogFileAppender* appender, wLogMessage* message) +{ + FILE* fp; + char prefix[WLOG_MAX_PREFIX_SIZE]; + + if (message->Level > log->Level) + return 0; + + fp = appender->FileDescriptor; + + if (!fp) + return -1; + + message->PrefixString = prefix; + WLog_Layout_GetMessagePrefix(log, appender->Layout, message); + + fprintf(fp, "%s%s\n", message->PrefixString, message->TextString); + + return 1; +} + +wLogFileAppender* WLog_FileAppender_New(wLog* log) +{ + wLogFileAppender* FileAppender; + + FileAppender = (wLogFileAppender*) malloc(sizeof(wLogFileAppender)); + + if (FileAppender) + { + ZeroMemory(FileAppender, sizeof(wLogFileAppender)); + + FileAppender->Open = (WLOG_APPENDER_OPEN_FN) WLog_FileAppender_Open; + FileAppender->Close = (WLOG_APPENDER_OPEN_FN) WLog_FileAppender_Close; + FileAppender->WriteMessage = (WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_FileAppender_WriteMessage; + } + + return FileAppender; +} + +void WLog_FileAppender_Free(wLog* log, wLogFileAppender* appender) +{ + if (appender) + { + if (appender->FileName) + free(appender->FileName); + + free(appender); + } +} + +wLogAppender* WLog_Appender_New(wLog* log, DWORD logAppenderType) +{ + wLogAppender* appender = NULL; + + if (logAppenderType == WLOG_APPENDER_CONSOLE) + { + appender = (wLogAppender*) WLog_ConsoleAppender_New(log); + } + else if (logAppenderType == WLOG_APPENDER_FILE) + { + appender = (wLogAppender*) WLog_FileAppender_New(log); + } + + if (!appender) + appender = (wLogAppender*) WLog_ConsoleAppender_New(log); + + appender->Layout = WLog_Layout_New(log); + + return appender; +} + +void WLog_Appender_Free(wLog* log, wLogAppender* appender) +{ + if (appender) + { + if (appender->Layout) + { + WLog_Layout_Free(log, appender->Layout); + appender->Layout = NULL; + } + + if (appender->Type == WLOG_APPENDER_CONSOLE) + { + WLog_ConsoleAppender_Free(log, (wLogConsoleAppender*) appender); + } + else if (appender->Type == WLOG_APPENDER_FILE) + { + WLog_FileAppender_Free(log, (wLogFileAppender*) appender); + } + } +} + +wLogAppender* WLog_GetLogAppender(wLog* log) +{ + return log->Appender; +} + +void WLog_SetLogAppenderType(wLog* log, DWORD logAppenderType) +{ + if (log->Appender) + { + WLog_Appender_Free(log, log->Appender); + log->Appender = NULL; + } + + log->Appender = WLog_Appender_New(log, logAppenderType); +} + +int WLog_OpenAppender(wLog* log) +{ + if (!log->Appender) + return -1; + + if (!log->Appender->Open) + return 0; + + return log->Appender->Open(log, log->Appender); +} + +int WLog_CloseAppender(wLog* log) +{ + if (!log->Appender) + return -1; + + if (!log->Appender->Close) + return 0; + + return log->Appender->Close(log, log->Appender); +} + +wLog* WLog_New(LPCSTR name) +{ + wLog* log; + + log = (wLog*) malloc(sizeof(wLog)); + + if (log) + { + ZeroMemory(log, sizeof(wLog)); + + log->Name = _strdup(name); + log->Level = WLOG_TRACE; + + WLog_SetLogAppenderType(log, WLOG_APPENDER_CONSOLE); + } + + return log; +} + +void WLog_Free(wLog* log) +{ + if (log) + { + if (log->Appender) + { + WLog_Appender_Free(log, log->Appender); + log->Appender = NULL; + } + + free(log->Name); + free(log); + } +} diff --git a/winpr/libwinpr/wtsapi/CMakeLists.txt b/winpr/libwinpr/wtsapi/CMakeLists.txt new file mode 100644 index 000000000..07a933c70 --- /dev/null +++ b/winpr/libwinpr/wtsapi/CMakeLists.txt @@ -0,0 +1,52 @@ +# WinPR: Windows Portable Runtime +# libwinpr-wtsapi cmake build script +# +# Copyright 2013 Marc-Andre Moreau +# +# 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-wtsapi") +set(MODULE_PREFIX "WINPR_WTSAPI") + +set(${MODULE_PREFIX}_SRCS + wtsapi.c + wtsrpc_c.c + wtsrpc_c.h) + +if(MSVC AND (NOT MONOLITHIC_BUILD)) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) +endif() + +add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" + MONOLITHIC ${MONOLITHIC_BUILD} + SOURCES ${${MODULE_PREFIX}_SRCS}) + +set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib") + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL + MODULE winpr + MODULES winpr-nt winpr-io winpr-synch winpr-file winpr-error) + +if(MONOLITHIC_BUILD) + set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) +else() + target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR") + +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/winpr/libwinpr/wtsapi/ModuleOptions.cmake b/winpr/libwinpr/wtsapi/ModuleOptions.cmake new file mode 100644 index 000000000..0575367f2 --- /dev/null +++ b/winpr/libwinpr/wtsapi/ModuleOptions.cmake @@ -0,0 +1,9 @@ + +set(MINWIN_LAYER "0") +set(MINWIN_GROUP "none") +set(MINWIN_MAJOR_VERSION "0") +set(MINWIN_MINOR_VERSION "0") +set(MINWIN_SHORT_NAME "wtsapi") +set(MINWIN_LONG_NAME "Windows Terminal Services API") +set(MODULE_LIBRARY_NAME "api-ms-win-${MINWIN_GROUP}-${MINWIN_SHORT_NAME}-l${MINWIN_LAYER}-${MINWIN_MAJOR_VERSION}-${MINWIN_MINOR_VERSION}") + diff --git a/winpr/libwinpr/wtsapi/module.def b/winpr/libwinpr/wtsapi/module.def new file mode 100644 index 000000000..b5adf3c6e --- /dev/null +++ b/winpr/libwinpr/wtsapi/module.def @@ -0,0 +1,2 @@ +LIBRARY "libwinpr-wtsapi" +EXPORTS diff --git a/winpr/libwinpr/wtsapi/test/.gitignore b/winpr/libwinpr/wtsapi/test/.gitignore new file mode 100644 index 000000000..8ac76a2e4 --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/.gitignore @@ -0,0 +1,3 @@ +TestWtsApi +TestWtsApi.c + diff --git a/winpr/libwinpr/wtsapi/test/CMakeLists.txt b/winpr/libwinpr/wtsapi/test/CMakeLists.txt new file mode 100644 index 000000000..fa473d9c2 --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/CMakeLists.txt @@ -0,0 +1,31 @@ + +set(MODULE_NAME "TestWtsApi") +set(MODULE_PREFIX "TEST_WTSAPI") + +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) + +set(${MODULE_PREFIX}_TESTS + TestWtsApiEnumerate.c) + +create_test_sourcelist(${MODULE_PREFIX}_SRCS + ${${MODULE_PREFIX}_DRIVER} + ${${MODULE_PREFIX}_TESTS}) + +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE winpr + MODULES winpr-crt winpr-wtsapi) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}") + +foreach(test ${${MODULE_PREFIX}_TESTS}) + get_filename_component(TestName ${test} NAME_WE) + add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName}) +endforeach() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test") + diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerate.c b/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerate.c new file mode 100644 index 000000000..2f46520b5 --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiEnumerate.c @@ -0,0 +1,8 @@ + +#include + +int TestWtsApiEnumerate(int argc, char* argv[]) +{ + return 0; +} + diff --git a/winpr/libwinpr/wtsapi/wtsapi.c b/winpr/libwinpr/wtsapi/wtsapi.c new file mode 100644 index 000000000..a76361e3e --- /dev/null +++ b/winpr/libwinpr/wtsapi/wtsapi.c @@ -0,0 +1,524 @@ +/** + * WinPR: Windows Portable Runtime + * Windows Terminal Services API + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +/** + * Remote Desktop Services API Functions: + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464/ + */ + +#ifndef _WIN32 + +#include "wtsrpc_c.h" + +BOOL WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) +{ + return RpcStartRemoteControlSession(NULL, pTargetServerName, TargetLogonId, HotkeyVk, HotkeyModifiers); +} + +BOOL WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) +{ + return TRUE; +} + +BOOL WTSStopRemoteControlSession(ULONG LogonId) +{ + return RpcStopRemoteControlSession(NULL, LogonId); +} + +BOOL WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait) +{ + return RpcConnectSession(NULL, LogonId, TargetLogonId, pPassword, bWait); +} + +BOOL WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait) +{ + return TRUE; +} + +BOOL WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount) +{ + return RpcEnumerateServers(NULL, pDomainName, Reserved, Version, ppServerInfo, pCount); +} + +BOOL WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount) +{ + return TRUE; +} + +HANDLE WTSOpenServerW(LPWSTR pServerName) +{ + return RpcOpenServer(NULL, pServerName); +} + +HANDLE WTSOpenServerA(LPSTR pServerName) +{ + return NULL; +} + +HANDLE WTSOpenServerExW(LPWSTR pServerName) +{ + return RpcOpenServerEx(NULL, pServerName); +} + +HANDLE WTSOpenServerExA(LPSTR pServerName) +{ + return NULL; +} + +VOID WTSCloseServer(HANDLE hServer) +{ + RpcCloseServer(NULL, hServer); +} + +BOOL WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount) +{ + return RpcEnumerateSessions(NULL, hServer, Reserved, Version, ppSessionInfo, pCount); +} + +BOOL WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount) +{ + return TRUE; +} + +BOOL WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount) +{ + return RpcEnumerateSessionsEx(NULL, hServer, pLevel, Filter, ppSessionInfo, pCount); +} + +BOOL WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount) +{ + return TRUE; +} + +BOOL WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount) +{ + return RpcEnumerateProcesses(NULL, hServer, Reserved, Version, ppProcessInfo, pCount); +} + +BOOL WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount) +{ + return TRUE; +} + +BOOL WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode) +{ + return RpcTerminateProcess(NULL, hServer, ProcessId, ExitCode); +} + +BOOL WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) +{ + return RpcQuerySessionInformation(NULL, hServer, SessionId, WTSInfoClass, ppBuffer, pBytesReturned); +} + +BOOL WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer, DWORD* pBytesReturned) +{ + return TRUE; +} + +BOOL WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) +{ + return RpcQueryUserConfig(NULL, pServerName, pUserName, WTSConfigClass, ppBuffer, pBytesReturned); +} + +BOOL WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer, DWORD* pBytesReturned) +{ + return TRUE; +} + +BOOL WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength) +{ + return RpcSetUserConfig(NULL, pServerName, pUserName, WTSConfigClass, pBuffer, DataLength); +} + +BOOL WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer, DWORD DataLength) +{ + return TRUE; +} + +BOOL WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength, + LPWSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait) +{ + return RpcSendMessage(NULL, hServer, SessionId, pTitle, TitleLength, + pMessage, MessageLength, Style, Timeout, pResponse, bWait); +} + +BOOL WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle, DWORD TitleLength, + LPSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait) +{ + return TRUE; +} + +BOOL WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait) +{ + return RpcDisconnectSession(NULL, hServer, SessionId, bWait); +} + +BOOL WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait) +{ + return RpcLogoffSession(NULL, hServer, SessionId, bWait); +} + +BOOL WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag) +{ + return RpcShutdownSystem(NULL, hServer, ShutdownFlag); +} + +BOOL WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags) +{ + return TRUE; +} + +HANDLE WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName) +{ + HANDLE handle = NULL; + + if (hServer != WTS_CURRENT_SERVER_HANDLE) + { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + return handle; +} + +HANDLE WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags) +{ + HANDLE handle = NULL; + + if (!flags) + handle = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE, SessionId, pVirtualName); + + return handle; +} + +BOOL WTSVirtualChannelClose(HANDLE hChannelHandle) +{ + if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* TODO: properly close handle */ + + return TRUE; +} + +BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead) +{ + OVERLAPPED overlapped; + + if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + overlapped.hEvent = 0; + overlapped.Offset = 0; + overlapped.OffsetHigh = 0; + + if (ReadFile(hChannelHandle, Buffer, BufferSize, pBytesRead, &overlapped)) + return TRUE; + + if (GetLastError() != ERROR_IO_PENDING) + return FALSE; + + if (!TimeOut) + { + CancelIo(hChannelHandle); + *pBytesRead = 0; + return TRUE; + } + + if (WaitForSingleObject(hChannelHandle, TimeOut) == WAIT_TIMEOUT) + { + CancelIo(hChannelHandle); + SetLastError(ERROR_IO_INCOMPLETE); + return FALSE; + } + + return GetOverlappedResult(hChannelHandle, &overlapped, pBytesRead, 0); +} + +BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten) +{ + OVERLAPPED overlapped; + + if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + overlapped.hEvent = 0; + overlapped.Offset = 0; + overlapped.OffsetHigh = 0; + + if (WriteFile(hChannelHandle, Buffer, Length, pBytesWritten, &overlapped)) + return TRUE; + + if (GetLastError() == ERROR_IO_PENDING) + return GetOverlappedResult(hChannelHandle, &overlapped, pBytesWritten, 1); + + return FALSE; +} + +BOOL VirtualChannelIoctl(HANDLE hChannelHandle, ULONG IoControlCode) +{ + DWORD error; + NTSTATUS ntstatus; + IO_STATUS_BLOCK ioStatusBlock; + + if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + ntstatus = NtDeviceIoControlFile(hChannelHandle, 0, 0, 0, &ioStatusBlock, IoControlCode, 0, 0, 0, 0); + + if (ntstatus == STATUS_PENDING) + { + ntstatus = NtWaitForSingleObject(hChannelHandle, 0, 0); + + if (ntstatus >= 0) + ntstatus = ioStatusBlock.status; + } + + if (ntstatus == STATUS_BUFFER_OVERFLOW) + { + ntstatus = STATUS_BUFFER_TOO_SMALL; + error = RtlNtStatusToDosError(ntstatus); + SetLastError(error); + return FALSE; + } + + if (ntstatus < 0) + { + error = RtlNtStatusToDosError(ntstatus); + SetLastError(error); + return FALSE; + } + + return TRUE; +} + +#define FILE_DEVICE_TERMSRV 0x00000038 + +BOOL WTSVirtualChannelPurgeInput(HANDLE hChannelHandle) +{ + return VirtualChannelIoctl(hChannelHandle, (FILE_DEVICE_TERMSRV << 16) | 0x0107); +} + +BOOL WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle) +{ + return VirtualChannelIoctl(hChannelHandle, (FILE_DEVICE_TERMSRV << 16) | 0x010B); +} + +BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned) +{ + if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (WtsVirtualClass == WTSVirtualFileHandle) + { + *ppBuffer = malloc(sizeof(void*)); + CopyMemory(*ppBuffer, &hChannelHandle, sizeof(void*)); + *pBytesReturned = sizeof(void*); + return TRUE; + } + + return FALSE; +} + +VOID WTSFreeMemory(PVOID pMemory) +{ + free(pMemory); +} + +BOOL WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries) +{ + BOOL status = TRUE; + + switch (WTSTypeClass) + { + case WTSTypeProcessInfoLevel0: + break; + + case WTSTypeProcessInfoLevel1: + break; + + case WTSTypeSessionInfoLevel1: + break; + + default: + status = FALSE; + break; + } + + return status; +} + +BOOL WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries) +{ + BOOL status = TRUE; + + switch (WTSTypeClass) + { + case WTSTypeProcessInfoLevel0: + break; + + case WTSTypeProcessInfoLevel1: + break; + + case WTSTypeSessionInfoLevel1: + break; + + default: + status = FALSE; + break; + } + + return status; +} + +BOOL WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags) +{ + return RpcRegisterSessionNotification(NULL, hWnd, dwFlags); +} + +BOOL WTSUnRegisterSessionNotification(HWND hWnd) +{ + return RpcUnRegisterSessionNotification(NULL, hWnd); +} + +BOOL WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags) +{ + return RpcRegisterSessionNotificationEx(NULL, hServer, hWnd, dwFlags); +} + +BOOL WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd) +{ + return RpcUnRegisterSessionNotificationEx(NULL, hServer, hWnd); +} + +BOOL WTSQueryUserToken(ULONG SessionId, PHANDLE phToken) +{ + return TRUE; +} + +BOOL WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPWSTR* ppProcessInfo, DWORD* pCount) +{ + return TRUE; +} + +BOOL WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPSTR* ppProcessInfo, DWORD* pCount) +{ + return TRUE; +} + +BOOL WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEW pListeners, DWORD* pCount) +{ + return TRUE; +} + +BOOL WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEA pListeners, DWORD* pCount) +{ + return TRUE; +} + +BOOL WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer) +{ + return TRUE; +} + +BOOL WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer) +{ + return TRUE; +} + +BOOL WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer, DWORD flag) +{ + return TRUE; +} + +BOOL WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag) +{ + return TRUE; +} + +BOOL WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor) +{ + return TRUE; +} + +BOOL WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor) +{ + return TRUE; +} + +BOOL WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded) +{ + return TRUE; +} + +BOOL WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, + LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded) +{ + return TRUE; +} + +BOOL WTSEnableChildSessions(BOOL bEnable) +{ + return RpcEnableChildSessions(NULL, bEnable); +} + +BOOL WTSIsChildSessionsEnabled(PBOOL pbEnabled) +{ + return RpcIsChildSessionsEnabled(NULL, pbEnabled); +} + +BOOL WTSGetChildSessionId(PULONG pSessionId) +{ + return RpcGetChildSessionId(NULL, pSessionId); +} + +#endif diff --git a/winpr/libwinpr/wtsapi/wtsrpc_c.c b/winpr/libwinpr/wtsapi/wtsrpc_c.c new file mode 100644 index 000000000..18b4a05a9 --- /dev/null +++ b/winpr/libwinpr/wtsapi/wtsrpc_c.c @@ -0,0 +1,170 @@ +/** + * WinPR: Windows Portable Runtime + * Windows Terminal Services API + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#ifndef _WIN32 + +#include "wtsrpc_c.h" + +/** + * RPC Client Stubs + */ + +BOOL RpcStartRemoteControlSession(void* context, LPWSTR pTargetServerName, + ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) +{ + return TRUE; +} + +BOOL RpcStopRemoteControlSession(void* context, ULONG LogonId) +{ + return TRUE; +} + +BOOL RpcConnectSession(void* context, ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait) +{ + return TRUE; +} + +BOOL RpcEnumerateServers(void* context, LPWSTR pDomainName, DWORD Reserved, + DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount) +{ + return TRUE; +} + +HANDLE RpcOpenServer(void* context, LPWSTR pServerName) +{ + return NULL; +} + +HANDLE RpcOpenServerEx(void* context, LPWSTR pServerName) +{ + return NULL; +} + +VOID RpcCloseServer(void* context, HANDLE hServer) +{ + +} + +BOOL RpcEnumerateSessions(void* context, HANDLE hServer, DWORD Reserved, + DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount) +{ + return TRUE; +} + +BOOL RpcEnumerateSessionsEx(void* context, HANDLE hServer, DWORD* pLevel, + DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount) +{ + return TRUE; +} + +BOOL RpcEnumerateProcesses(void* context, HANDLE hServer, DWORD Reserved, + DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount) +{ + return TRUE; +} + +BOOL RpcTerminateProcess(void* context, HANDLE hServer, DWORD ProcessId, DWORD ExitCode) +{ + return TRUE; +} + +BOOL RpcQuerySessionInformation(void* context, HANDLE hServer, DWORD SessionId, + WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) +{ + return TRUE; +} + +BOOL RpcQueryUserConfig(void* context, LPWSTR pServerName, LPWSTR pUserName, + WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) +{ + return TRUE; +} + +BOOL RpcSetUserConfig(void* context, LPWSTR pServerName, LPWSTR pUserName, + WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength) +{ + return TRUE; +} + +BOOL RpcSendMessage(void* context, HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength, + LPWSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait) +{ + return TRUE; +} + +BOOL RpcDisconnectSession(void* context, HANDLE hServer, DWORD SessionId, BOOL bWait) +{ + return TRUE; +} + +BOOL RpcLogoffSession(void* context, HANDLE hServer, DWORD SessionId, BOOL bWait) +{ + return TRUE; +} + +BOOL RpcShutdownSystem(void* context, HANDLE hServer, DWORD ShutdownFlag) +{ + return TRUE; +} + +BOOL RpcRegisterSessionNotification(void* context, HWND hWnd, DWORD dwFlags) +{ + return TRUE; +} + +BOOL RpcUnRegisterSessionNotification(void* context, HWND hWnd) +{ + return TRUE; +} + +BOOL RpcRegisterSessionNotificationEx(void* context, HANDLE hServer, HWND hWnd, DWORD dwFlags) +{ + return TRUE; +} + +BOOL RpcUnRegisterSessionNotificationEx(void* context, HANDLE hServer, HWND hWnd) +{ + return TRUE; +} + +BOOL RpcEnableChildSessions(void* context, BOOL bEnable) +{ + return TRUE; +} + +BOOL RpcIsChildSessionsEnabled(void* context, PBOOL pbEnabled) +{ + return TRUE; +} + +BOOL RpcGetChildSessionId(void* context, PULONG pSessionId) +{ + return TRUE; +} + +#endif diff --git a/winpr/libwinpr/wtsapi/wtsrpc_c.h b/winpr/libwinpr/wtsapi/wtsrpc_c.h new file mode 100644 index 000000000..8377f786f --- /dev/null +++ b/winpr/libwinpr/wtsapi/wtsrpc_c.h @@ -0,0 +1,76 @@ +/** + * WinPR: Windows Portable Runtime + * Windows Terminal Services API + * + * Copyright 2013 Marc-Andre Moreau + * + * 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_WTSAPI_RPC_CLIENT_STUBS_H +#define WINPR_WTSAPI_RPC_CLIENT_STUBS_H + +/** + * RPC Client Stubs + */ + +BOOL RpcStartRemoteControlSession(void* context, LPWSTR pTargetServerName, + ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers); +BOOL RpcStopRemoteControlSession(void* context, ULONG LogonId); + +BOOL RpcConnectSession(void* context, ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait); + +BOOL RpcEnumerateServers(void* context, LPWSTR pDomainName, DWORD Reserved, + DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount); + +HANDLE RpcOpenServer(void* context, LPWSTR pServerName); +HANDLE RpcOpenServerEx(void* context, LPWSTR pServerName); +VOID RpcCloseServer(void* context, HANDLE hServer); + +BOOL RpcEnumerateSessions(void* context, HANDLE hServer, DWORD Reserved, + DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount); +BOOL RpcEnumerateSessionsEx(void* context, HANDLE hServer, DWORD* pLevel, + DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount); + +BOOL RpcEnumerateProcesses(void* context, HANDLE hServer, DWORD Reserved, + DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount); +BOOL RpcTerminateProcess(void* context, HANDLE hServer, DWORD ProcessId, DWORD ExitCode); + +BOOL RpcQuerySessionInformation(void* context, HANDLE hServer, DWORD SessionId, + WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned); + +BOOL RpcQueryUserConfig(void* context, LPWSTR pServerName, LPWSTR pUserName, + WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned); +BOOL RpcSetUserConfig(void* context, LPWSTR pServerName, LPWSTR pUserName, + WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength); + +BOOL RpcSendMessage(void* context, HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength, + LPWSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait); + +BOOL RpcDisconnectSession(void* context, HANDLE hServer, DWORD SessionId, BOOL bWait); + +BOOL RpcLogoffSession(void* context, HANDLE hServer, DWORD SessionId, BOOL bWait); + +BOOL RpcShutdownSystem(void* context, HANDLE hServer, DWORD ShutdownFlag); + +BOOL RpcRegisterSessionNotification(void* context, HWND hWnd, DWORD dwFlags); +BOOL RpcUnRegisterSessionNotification(void* context, HWND hWnd); + +BOOL RpcRegisterSessionNotificationEx(void* context, HANDLE hServer, HWND hWnd, DWORD dwFlags); +BOOL RpcUnRegisterSessionNotificationEx(void* context, HANDLE hServer, HWND hWnd); + +BOOL RpcEnableChildSessions(void* context, BOOL bEnable); +BOOL RpcIsChildSessionsEnabled(void* context, PBOOL pbEnabled); +BOOL RpcGetChildSessionId(void* context, PULONG pSessionId); + +#endif /* WINPR_WTSAPI_RPC_CLIENT_STUBS_H */ diff --git a/winpr/tools/makecert/CMakeLists.txt b/winpr/tools/makecert/CMakeLists.txt index 22b0fb9e5..4089fd914 100644 --- a/winpr/tools/makecert/CMakeLists.txt +++ b/winpr/tools/makecert/CMakeLists.txt @@ -43,10 +43,9 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) -if(NOT WITH_WAYK) - install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) - add_subdirectory(cli) -endif() +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) + +add_subdirectory(cli) set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Tools")